system.pp 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2005 by Florian Klaempfl and Pavel Ozerski
  4. and Yury Sidorov member of the Free Pascal development team.
  5. FPC Pascal system unit for the WinCE.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit System;
  13. interface
  14. {$ifdef SYSTEMDEBUG}
  15. {$define SYSTEMEXCEPTIONDEBUG}
  16. {$endif SYSTEMDEBUG}
  17. {$define WINCE_EXCEPTION_HANDLING}
  18. {$define DISABLE_NO_THREAD_MANAGER}
  19. {$define HAS_CMDLINE}
  20. {$define HAS_MT_MEMORYMANAGER} // comment this line to switch from wincemm to fpcmm
  21. {$define HAS_WIDESTRINGMANAGER}
  22. { include system-independent routine headers }
  23. {$I systemh.inc}
  24. const
  25. LineEnding = #13#10;
  26. LFNSupport = true;
  27. DirectorySeparator = '\';
  28. DriveSeparator = ':';
  29. ExtensionSeparator = '.';
  30. PathSeparator = ';';
  31. AllowDirectorySeparators : set of char = ['\','/'];
  32. AllowDriveSeparators : set of char = [':'];
  33. { FileNameCaseSensitive is defined separately below!!! }
  34. maxExitCode = 65535;
  35. MaxPathLen = 260;
  36. AllFilesMask = '*';
  37. const
  38. { Default filehandles }
  39. UnusedHandle : THandle = THandle(-1);
  40. StdInputHandle : THandle = 0;
  41. StdOutputHandle : THandle = 0;
  42. StdErrorHandle : THandle = 0;
  43. FileNameCaseSensitive : boolean = true;
  44. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  45. sLineBreak = LineEnding;
  46. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  47. { Thread count for DLL }
  48. Thread_count : longint = 0;
  49. var
  50. { WinCE Info }
  51. hprevinst,
  52. MainInstance,
  53. DLLreason,DLLparam:DWord;
  54. type
  55. TDLL_Process_Entry_Hook = function (dllparam : longint) : longbool;
  56. TDLL_Entry_Hook = procedure (dllparam : longint);
  57. const
  58. Dll_Process_Attach_Hook : TDLL_Process_Entry_Hook = nil;
  59. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  60. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  61. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  62. { ANSI <-> Wide }
  63. function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
  64. function WideToAnsiBuf(WideBuf: PWideChar; WideCharsLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
  65. function PCharToPWideChar(str: PChar; strlen: longint = -1; outlen: PLongInt = nil): PWideChar;
  66. function StringToPWideChar(const s: AnsiString; outlen: PLongInt = nil): PWideChar;
  67. { Wrappers for some WinAPI calls }
  68. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle;
  69. function ResetEvent(h: THandle): LONGBOOL;
  70. function SetEvent(h: THandle): LONGBOOL;
  71. function GetCurrentProcessId:DWORD;
  72. function Win32GetCurrentThreadId:DWORD;
  73. function TlsAlloc : DWord;
  74. function TlsFree(dwTlsIndex : DWord) : LongBool;
  75. function GetFileAttributes(p : pchar) : dword;
  76. function DeleteFile(p : pchar) : longint;
  77. function MoveFile(old,_new : pchar) : longint;
  78. function CreateFile(lpFileName:pchar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  79. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  80. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  81. function CreateDirectory(name : pointer;sec : pointer) : longbool;
  82. function RemoveDirectory(name:pointer):longbool;
  83. {$ifdef CPUARM}
  84. { the external directive isn't really necessary here because it is overriden by external (FK) }
  85. function addd(d1,d2 : double) : double; compilerproc;
  86. cdecl;external 'coredll' name '__addd';
  87. function subd(d1,d2 : double) : double; compilerproc;
  88. cdecl;external 'coredll' name '__subd';
  89. function muld(d1,d2 : double) : double; compilerproc;
  90. cdecl;external 'coredll' name '__muld';
  91. function divd(d1,d2 : double) : double; compilerproc;
  92. cdecl;external 'coredll' name '__divd';
  93. function eqd(d1,d2 : double) : boolean; compilerproc;
  94. cdecl;external 'coredll' name '__eqd';
  95. function ned(d1,d2 : double) : boolean; compilerproc;
  96. cdecl;external 'coredll' name '__ned';
  97. function ltd(d1,d2 : double) : boolean; compilerproc;
  98. cdecl;external 'coredll' name '__ltd';
  99. function gtd(d1,d2 : double) : boolean; compilerproc;
  100. cdecl;external 'coredll' name '__gtd';
  101. function ged(d1,d2 : double) : boolean; compilerproc;
  102. cdecl;external 'coredll' name '__ged';
  103. function led(d1,d2 : double) : boolean; compilerproc;
  104. cdecl;external 'coredll' name '__led';
  105. { ***************** single ******************** }
  106. function eqs(d1,d2 : single) : boolean; compilerproc;
  107. cdecl;external 'coredll' name '__eqs';
  108. function nes(d1,d2 : single) : boolean; compilerproc;
  109. cdecl;external 'coredll' name '__nes';
  110. function lts(d1,d2 : single) : boolean; compilerproc;
  111. cdecl;external 'coredll' name '__lts';
  112. function gts(d1,d2 : single) : boolean; compilerproc;
  113. cdecl;external 'coredll' name '__gts';
  114. function ges(d1,d2 : single) : boolean; compilerproc;
  115. cdecl;external 'coredll' name '__ges';
  116. function les(d1,d2 : single) : boolean; compilerproc;
  117. cdecl;external 'coredll' name '__les';
  118. function dtos(d : double) : single; compilerproc;
  119. cdecl;external 'coredll' name '__dtos';
  120. function stod(d : single) : double; compilerproc;
  121. cdecl;external 'coredll' name '__stod';
  122. function negs(d : single) : single; compilerproc;
  123. cdecl;external 'coredll' name '__negs';
  124. function negd(d : double) : double; compilerproc;
  125. cdecl;external 'coredll' name '__negd';
  126. function utod(i : dword) : double; compilerproc;
  127. cdecl;external 'coredll' name '__utod';
  128. function itod(i : longint) : double; compilerproc;
  129. cdecl;external 'coredll' name '__itod';
  130. function ui64tod(i : qword) : double; compilerproc;
  131. cdecl;external 'coredll' name '__u64tod';
  132. function i64tod(i : int64) : double; compilerproc;
  133. cdecl;external 'coredll' name '__i64tod';
  134. function utos(i : dword) : single; compilerproc;
  135. cdecl;external 'coredll' name '__utos';
  136. function itos(i : longint) : single; compilerproc;
  137. cdecl;external 'coredll' name '__itos';
  138. function ui64tos(i : qword) : single; compilerproc;
  139. cdecl;external 'coredll' name '__u64tos';
  140. function i64tos(i : int64) : single; compilerproc;
  141. cdecl;external 'coredll' name '__i64tos';
  142. function adds(s1,s2 : single) : single; compilerproc;
  143. function subs(s1,s2 : single) : single; compilerproc;
  144. function muls(s1,s2 : single) : single; compilerproc;
  145. function divs(s1,s2 : single) : single; compilerproc;
  146. {$endif CPUARM}
  147. function CmdLine: PChar;
  148. { C compatible arguments }
  149. function argc: longint;
  150. function argv: ppchar;
  151. implementation
  152. var
  153. SysInstance : Longint;
  154. {$define HAS_RESOURCES}
  155. {$i winres.inc}
  156. function MessageBox(w1:longint;l1,l2:PWideChar;w2:longint):longint;
  157. cdecl; external 'coredll' name 'MessageBoxW';
  158. {*****************************************************************************}
  159. {$define FPC_SYSTEM_HAS_MOVE}
  160. procedure memmove(dest, src: pointer; count: longint);
  161. cdecl; external 'coredll' name 'memmove';
  162. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE']; {$ifdef SYSTEMINLINE}inline;{$endif}
  163. begin
  164. if count > 0 then
  165. memmove(@dest, @source, count);
  166. end;
  167. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  168. function memcmp(buf1, buf2: pointer; count: longint): longint;
  169. cdecl; external 'coredll' name 'memcmp';
  170. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt; {$ifdef SYSTEMINLINE}inline;{$endif}
  171. begin
  172. CompareByte := memcmp(@buf1, @buf2, len);
  173. end;
  174. {$ifdef CPUARM}
  175. {$define FPC_SYSTEM_HAS_INT}
  176. function floor(d : double) : double;
  177. cdecl;external 'coredll' name 'floor';
  178. function ceil(d : double) : double;
  179. cdecl;external 'coredll' name 'ceil';
  180. function fpc_int_real(d: ValReal): ValReal;compilerproc;
  181. begin
  182. if d > 0 then
  183. fpc_int_real:=floor(d)
  184. else
  185. fpc_int_real:=ceil(d);
  186. end;
  187. {$define FPC_SYSTEM_HAS_TRUNC}
  188. function __dtoi64(d: double) : int64; cdecl; external 'coredll';
  189. function fpc_trunc_real(d : ValReal) : int64; assembler; nostackframe; compilerproc;
  190. asm
  191. b __dtoi64
  192. end;
  193. {$define FPC_SYSTEM_HAS_ABS}
  194. function fabs(d: double): double; cdecl; external 'coredll';
  195. function fpc_abs_real(d : ValReal) : ValReal; assembler; nostackframe; compilerproc;
  196. asm
  197. b fabs
  198. end;
  199. {$define FPC_SYSTEM_HAS_SQRT}
  200. function coresqrt(d: double): double; cdecl; external 'coredll' name 'sqrt';
  201. function fpc_sqrt_real(d : ValReal) : ValReal; assembler; nostackframe; compilerproc;
  202. asm
  203. b coresqrt
  204. end;
  205. function adds(s1,s2 : single) : single;
  206. begin
  207. adds := addd(s1, s2);
  208. end;
  209. function subs(s1,s2 : single) : single;
  210. begin
  211. subs := subd(s1, s2);
  212. end;
  213. function muls(s1,s2 : single) : single;
  214. begin
  215. muls := muld(s1, s2);
  216. end;
  217. function divs(s1,s2 : single) : single;
  218. begin
  219. divs := divd(s1, s2);
  220. end;
  221. {$endif CPUARM}
  222. {*****************************************************************************}
  223. { include system independent routines }
  224. {$I system.inc}
  225. {*****************************************************************************
  226. ANSI <-> Wide
  227. *****************************************************************************}
  228. const
  229. { MultiByteToWideChar }
  230. MB_PRECOMPOSED = 1;
  231. MB_COMPOSITE = 2;
  232. MB_ERR_INVALID_CHARS = 8;
  233. MB_USEGLYPHCHARS = 4;
  234. CP_ACP = 0;
  235. CP_OEMCP = 1;
  236. function MultiByteToWideChar(CodePage:UINT; dwFlags:DWORD; lpMultiByteStr:PChar; cchMultiByte:longint; lpWideCharStr:PWideChar;cchWideChar:longint):longint;
  237. cdecl; external 'coredll' name 'MultiByteToWideChar';
  238. function WideCharToMultiByte(CodePage:UINT; dwFlags:DWORD; lpWideCharStr:PWideChar; cchWideChar:longint; lpMultiByteStr:PChar;cchMultiByte:longint; lpDefaultChar:PChar; lpUsedDefaultChar:pointer):longint;
  239. cdecl; external 'coredll' name 'WideCharToMultiByte';
  240. { Returns number of characters stored to WideBuf, including null-terminator. }
  241. function AnsiToWideBuf(AnsiBuf: PChar; AnsiBufLen: longint; WideBuf: PWideChar; WideBufLen: longint): longint;
  242. begin
  243. Result := MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, AnsiBuf, AnsiBufLen, WideBuf, WideBufLen div SizeOf(WideChar));
  244. if ((AnsiBufLen <> -1) or (Result = 0)) and (WideBuf <> nil) then
  245. begin
  246. if (Result + 1)*SizeOf(WideChar) > WideBufLen then
  247. begin
  248. Result := 0;
  249. if WideBufLen < SizeOf(WideChar) then
  250. exit;
  251. end;
  252. WideBuf[Result] := #0;
  253. end;
  254. if (AnsiBufLen <> -1) and ((Result <> 0) or (AnsiBufLen = 0)) then
  255. Inc(Result);
  256. end;
  257. { Returns number of characters stored to AnsiBuf, including null-terminator. }
  258. function WideToAnsiBuf(WideBuf: PWideChar; WideCharsLen: longint; AnsiBuf: PChar; AnsiBufLen: longint): longint;
  259. begin
  260. Result := WideCharToMultiByte(CP_ACP, 0, WideBuf, WideCharsLen, AnsiBuf, AnsiBufLen, nil, nil);
  261. if ((WideCharsLen <> -1) or (Result = 0)) and (AnsiBuf <> nil) then
  262. begin
  263. if Result + 1 > AnsiBufLen then
  264. begin
  265. Result := 0;
  266. if AnsiBufLen < 1 then
  267. exit;
  268. end;
  269. AnsiBuf[Result] := #0;
  270. end;
  271. if (WideCharsLen <> -1) and ((Result <> 0) or (WideCharsLen = 0)) then
  272. Inc(Result);
  273. end;
  274. { Returns dynamic memory block, which contains wide string. This memory should be freed using FreeMem. }
  275. { outlen will contain number of wide characters stored to result buffer, including null-terminator. }
  276. function PCharToPWideChar(str: PChar; strlen: longint = -1; outlen: PLongInt = nil): PWideChar;
  277. var
  278. len: longint;
  279. begin
  280. while True do begin
  281. if strlen <> -1 then
  282. len:=strlen + 1
  283. else
  284. len:=AnsiToWideBuf(str, -1, nil, 0);
  285. if len > 0 then
  286. begin
  287. len:=len*SizeOf(WideChar);
  288. GetMem(Result, len);
  289. len:=AnsiToWideBuf(str, strlen, Result, len);
  290. if (len = 0) and (strlen <> -1) then
  291. begin
  292. FreeMem(Result);
  293. strlen:=-1;
  294. continue;
  295. end;
  296. end
  297. else begin
  298. GetMem(Result, SizeOf(WideChar));
  299. len:=1;
  300. Result^:=#0;
  301. end;
  302. break;
  303. end;
  304. if outlen <> nil then
  305. outlen^:=len;
  306. end;
  307. { Returns dynamic memory block, which contains wide string. This memory should be freed using FreeMem. }
  308. { outlen will contain number of wide characters stored to result buffer, including null-terminator. }
  309. function StringToPWideChar(const s: AnsiString; outlen: PLongInt = nil): PWideChar;
  310. var
  311. len, wlen: longint;
  312. begin
  313. len:=Length(s);
  314. wlen:=(len + 1)*SizeOf(WideChar);
  315. GetMem(Result, wlen);
  316. wlen:=AnsiToWideBuf(PChar(s), len, Result, wlen)*SizeOf(WideChar);
  317. if wlen = 0 then
  318. begin
  319. wlen:=AnsiToWideBuf(PChar(s), len, nil, 0)*SizeOf(WideChar);
  320. if wlen > 0 then
  321. begin
  322. ReAllocMem(Result, wlen);
  323. wlen:=AnsiToWideBuf(PChar(s), len, Result, wlen)*SizeOf(WideChar);
  324. end
  325. else
  326. begin
  327. Result^:=#0;
  328. wlen:=SizeOf(WideChar);
  329. end;
  330. end;
  331. if outlen <> nil then
  332. outlen^:=wlen div SizeOf(WideChar);
  333. end;
  334. {*****************************************************************************
  335. WinAPI wrappers implementation
  336. *****************************************************************************}
  337. function GetFileAttributesW(p : pwidechar) : dword;
  338. cdecl; external KernelDLL name 'GetFileAttributesW';
  339. function DeleteFileW(p : pwidechar) : longint;
  340. cdecl; external KernelDLL name 'DeleteFileW';
  341. function MoveFileW(old,_new : pwidechar) : longint;
  342. cdecl; external KernelDLL name 'MoveFileW';
  343. function CreateFileW(lpFileName:pwidechar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  344. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  345. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  346. cdecl; external KernelDLL name 'CreateFileW';
  347. function CreateDirectoryW(name : pwidechar;sec : pointer) : longbool;
  348. cdecl; external KernelDLL name 'CreateDirectoryW';
  349. function RemoveDirectoryW(name:pwidechar):longbool;
  350. cdecl; external KernelDLL name 'RemoveDirectoryW';
  351. function GetFileAttributes(p : pchar) : dword;
  352. var
  353. buf: array[0..MaxPathLen] of WideChar;
  354. begin
  355. AnsiToWideBuf(p, -1, buf, SizeOf(buf));
  356. GetFileAttributes := GetFileAttributesW(buf);
  357. end;
  358. function DeleteFile(p : pchar) : longint;
  359. var
  360. buf: array[0..MaxPathLen] of WideChar;
  361. begin
  362. AnsiToWideBuf(p, -1, buf, SizeOf(buf));
  363. DeleteFile := DeleteFileW(buf);
  364. end;
  365. function MoveFile(old,_new : pchar) : longint;
  366. var
  367. buf_old, buf_new: array[0..MaxPathLen] of WideChar;
  368. begin
  369. AnsiToWideBuf(old, -1, buf_old, SizeOf(buf_old));
  370. AnsiToWideBuf(_new, -1, buf_new, SizeOf(buf_new));
  371. MoveFile := MoveFileW(buf_old, buf_new);
  372. end;
  373. function CreateFile(lpFileName:pchar; dwDesiredAccess:DWORD; dwShareMode:DWORD;
  374. lpSecurityAttributes:pointer; dwCreationDisposition:DWORD;
  375. dwFlagsAndAttributes:DWORD; hTemplateFile:DWORD):longint;
  376. var
  377. buf: array[0..MaxPathLen] of WideChar;
  378. begin
  379. AnsiToWideBuf(lpFileName, -1, buf, SizeOf(buf));
  380. CreateFile := CreateFileW(buf, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  381. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  382. end;
  383. function CreateDirectory(name : pointer;sec : pointer) : longbool;
  384. var
  385. buf: array[0..MaxPathLen] of WideChar;
  386. begin
  387. AnsiToWideBuf(name, -1, buf, SizeOf(buf));
  388. CreateDirectory := CreateDirectoryW(buf, sec);
  389. end;
  390. function RemoveDirectory(name:pointer):longbool;
  391. var
  392. buf: array[0..MaxPathLen] of WideChar;
  393. begin
  394. AnsiToWideBuf(name, -1, buf, SizeOf(buf));
  395. RemoveDirectory := RemoveDirectoryW(buf);
  396. end;
  397. const
  398. {$ifdef CPUARM}
  399. UserKData = $FFFFC800;
  400. {$else CPUARM}
  401. UserKData = $00005800;
  402. {$endif CPUARM}
  403. SYSHANDLE_OFFSET = $004;
  404. SYS_HANDLE_BASE = 64;
  405. SH_CURTHREAD = 1;
  406. SH_CURPROC = 2;
  407. type
  408. PHandle = ^THandle;
  409. const
  410. EVENT_PULSE = 1;
  411. EVENT_RESET = 2;
  412. EVENT_SET = 3;
  413. function CreateEventW(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:PWideChar): THandle;
  414. cdecl; external KernelDLL name 'CreateEventW';
  415. function CreateEvent(lpEventAttributes:pointer;bManualReset:longbool;bInitialState:longbool;lpName:pchar): THandle;
  416. var
  417. buf: array[0..MaxPathLen] of WideChar;
  418. begin
  419. AnsiToWideBuf(lpName, -1, buf, SizeOf(buf));
  420. CreateEvent := CreateEventW(lpEventAttributes, bManualReset, bInitialState, buf);
  421. end;
  422. function EventModify(h: THandle; func: DWORD): LONGBOOL;
  423. cdecl; external KernelDLL name 'EventModify';
  424. function TlsCall(p1, p2: DWORD): DWORD;
  425. cdecl; external KernelDLL name 'TlsCall';
  426. function ResetEvent(h: THandle): LONGBOOL;
  427. begin
  428. ResetEvent := EventModify(h,EVENT_RESET);
  429. end;
  430. function SetEvent(h: THandle): LONGBOOL;
  431. begin
  432. SetEvent := EventModify(h,EVENT_SET);
  433. end;
  434. function GetCurrentProcessId:DWORD;
  435. var
  436. p: PHandle;
  437. begin
  438. p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURPROC*SizeOf(THandle));
  439. GetCurrentProcessId := p^;
  440. end;
  441. function Win32GetCurrentThreadId:DWORD;
  442. var
  443. p: PHandle;
  444. begin
  445. p:=PHandle(UserKData+SYSHANDLE_OFFSET + SH_CURTHREAD*SizeOf(THandle));
  446. Win32GetCurrentThreadId := p^;
  447. end;
  448. const
  449. TLS_FUNCALLOC = 0;
  450. TLS_FUNCFREE = 1;
  451. function TlsAlloc : DWord;
  452. begin
  453. TlsAlloc := TlsCall(TLS_FUNCALLOC, 0);
  454. end;
  455. function TlsFree(dwTlsIndex : DWord) : LongBool;
  456. begin
  457. TlsFree := LongBool(TlsCall(TLS_FUNCFREE, dwTlsIndex));
  458. end;
  459. {*****************************************************************************
  460. Parameter Handling
  461. *****************************************************************************}
  462. function GetCommandLine : pwidechar;
  463. cdecl; external KernelDLL name 'GetCommandLineW';
  464. var
  465. ModuleName : array[0..255] of char;
  466. function GetCommandFile:pchar;
  467. var
  468. buf: array[0..MaxPathLen] of WideChar;
  469. begin
  470. if ModuleName[0] = #0 then begin
  471. GetModuleFileName(0, @buf, SizeOf(buf));
  472. WideToAnsiBuf(buf, -1, @ModuleName, SizeOf(ModuleName));
  473. end;
  474. GetCommandFile:=@ModuleName;
  475. end;
  476. var
  477. Fargc: longint;
  478. Fargv: ppchar;
  479. FCmdLine: PChar;
  480. procedure setup_arguments;
  481. var
  482. arglen,
  483. count : longint;
  484. argstart,
  485. pc,arg : pchar;
  486. quote : char;
  487. argvlen : longint;
  488. procedure allocarg(idx,len:longint);
  489. var
  490. oldargvlen : longint;
  491. begin
  492. if idx>=argvlen then
  493. begin
  494. oldargvlen:=argvlen;
  495. argvlen:=(idx+8) and (not 7);
  496. sysreallocmem(Fargv,argvlen*sizeof(pointer));
  497. fillchar(Fargv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
  498. end;
  499. { use realloc to reuse already existing memory }
  500. { always allocate, even if length is zero, since }
  501. { the arg. is still present! }
  502. sysreallocmem(Fargv[idx],len+1);
  503. end;
  504. begin
  505. { create commandline, it starts with the executed filename which is argv[0] }
  506. { WinCE passes the command NOT via the args, but via getmodulefilename}
  507. if FCmdLine <> nil then exit;
  508. argvlen:=0;
  509. pc:=getcommandfile;
  510. Arglen:=0;
  511. while pc[Arglen] <> #0 do
  512. Inc(Arglen);
  513. allocarg(0,arglen);
  514. move(pc^,Fargv[0]^,arglen+1);
  515. { Setup FCmdLine variable }
  516. arg:=PChar(GetCommandLine);
  517. count:=WideToAnsiBuf(PWideChar(arg), -1, nil, 0);
  518. FCmdLine:=SysGetMem(arglen + count + 3);
  519. FCmdLine^:='"';
  520. move(pc^, (FCmdLine + 1)^, arglen);
  521. (FCmdLine + arglen + 1)^:='"';
  522. (FCmdLine + arglen + 2)^:=' ';
  523. WideToAnsiBuf(PWideChar(arg), -1, FCmdLine + arglen + 3, count);
  524. { process arguments }
  525. count:=0;
  526. pc:=FCmdLine;
  527. {$IfDef SYSTEM_DEBUG_STARTUP}
  528. Writeln(stderr,'WinCE GetCommandLine is #',pc,'#');
  529. {$EndIf }
  530. while pc^<>#0 do
  531. begin
  532. { skip leading spaces }
  533. while pc^ in [#1..#32] do
  534. inc(pc);
  535. if pc^=#0 then
  536. break;
  537. { calc argument length }
  538. quote:=' ';
  539. argstart:=pc;
  540. arglen:=0;
  541. while (pc^<>#0) do
  542. begin
  543. case pc^ of
  544. #1..#32 :
  545. begin
  546. if quote<>' ' then
  547. inc(arglen)
  548. else
  549. break;
  550. end;
  551. '"' :
  552. begin
  553. if quote<>'''' then
  554. begin
  555. if pchar(pc+1)^<>'"' then
  556. begin
  557. if quote='"' then
  558. quote:=' '
  559. else
  560. quote:='"';
  561. end
  562. else
  563. inc(pc);
  564. end
  565. else
  566. inc(arglen);
  567. end;
  568. '''' :
  569. begin
  570. if quote<>'"' then
  571. begin
  572. if pchar(pc+1)^<>'''' then
  573. begin
  574. if quote='''' then
  575. quote:=' '
  576. else
  577. quote:='''';
  578. end
  579. else
  580. inc(pc);
  581. end
  582. else
  583. inc(arglen);
  584. end;
  585. else
  586. inc(arglen);
  587. end;
  588. inc(pc);
  589. end;
  590. { copy argument }
  591. { Don't copy the first one, it is already there.}
  592. If Count<>0 then
  593. begin
  594. allocarg(count,arglen);
  595. quote:=' ';
  596. pc:=argstart;
  597. arg:=Fargv[count];
  598. while (pc^<>#0) do
  599. begin
  600. case pc^ of
  601. #1..#32 :
  602. begin
  603. if quote<>' ' then
  604. begin
  605. arg^:=pc^;
  606. inc(arg);
  607. end
  608. else
  609. break;
  610. end;
  611. '"' :
  612. begin
  613. if quote<>'''' then
  614. begin
  615. if pchar(pc+1)^<>'"' then
  616. begin
  617. if quote='"' then
  618. quote:=' '
  619. else
  620. quote:='"';
  621. end
  622. else
  623. inc(pc);
  624. end
  625. else
  626. begin
  627. arg^:=pc^;
  628. inc(arg);
  629. end;
  630. end;
  631. '''' :
  632. begin
  633. if quote<>'"' then
  634. begin
  635. if pchar(pc+1)^<>'''' then
  636. begin
  637. if quote='''' then
  638. quote:=' '
  639. else
  640. quote:='''';
  641. end
  642. else
  643. inc(pc);
  644. end
  645. else
  646. begin
  647. arg^:=pc^;
  648. inc(arg);
  649. end;
  650. end;
  651. else
  652. begin
  653. arg^:=pc^;
  654. inc(arg);
  655. end;
  656. end;
  657. inc(pc);
  658. end;
  659. arg^:=#0;
  660. end;
  661. {$IfDef SYSTEM_DEBUG_STARTUP}
  662. Writeln(stderr,'dos arg ',count,' #',arglen,'#',Fargv[count],'#');
  663. {$EndIf SYSTEM_DEBUG_STARTUP}
  664. inc(count);
  665. end;
  666. { get argc and create an nil entry }
  667. Fargc:=count;
  668. allocarg(argc,0);
  669. { free unused memory }
  670. sysreallocmem(Fargv,(argc+1)*sizeof(pointer));
  671. end;
  672. function CmdLine: PChar;
  673. begin
  674. setup_arguments;
  675. Result:=FCmdLine;
  676. end;
  677. function argc: longint;
  678. begin
  679. setup_arguments;
  680. Result:=Fargc;
  681. end;
  682. function argv: ppchar;
  683. begin
  684. setup_arguments;
  685. Result:=Fargv;
  686. end;
  687. function paramcount : longint;
  688. begin
  689. paramcount := argc - 1;
  690. end;
  691. function paramstr(l : longint) : string;
  692. begin
  693. setup_arguments;
  694. if (l>=0) and (l<Fargc) then
  695. paramstr:=strpas(Fargv[l])
  696. else
  697. paramstr:='';
  698. end;
  699. procedure randomize;
  700. begin
  701. randseed:=GetTickCount;
  702. end;
  703. {*****************************************************************************
  704. System Dependent Exit code
  705. *****************************************************************************}
  706. procedure PascalMain;external name 'PASCALMAIN';
  707. procedure ExitThread(Exitcode : longint); cdecl; external 'coredll';
  708. Procedure system_exit;
  709. begin
  710. if IsLibrary then
  711. exit;
  712. if not IsConsole then
  713. begin
  714. Close(stderr);
  715. Close(stdout);
  716. Close(erroutput);
  717. Close(Input);
  718. Close(Output);
  719. end;
  720. ExitThread(exitcode);
  721. end;
  722. {$ifdef cpu386}
  723. var
  724. { value of the stack segment
  725. to check if the call stack can be written on exceptions }
  726. _SS : Cardinal;
  727. {$endif cpu386}
  728. Const
  729. { DllEntryPoint }
  730. DLL_PROCESS_ATTACH = 1;
  731. DLL_THREAD_ATTACH = 2;
  732. DLL_PROCESS_DETACH = 0;
  733. DLL_THREAD_DETACH = 3;
  734. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  735. var
  736. res : longbool;
  737. begin
  738. IsLibrary:=true;
  739. Dll_entry:=false;
  740. case DLLreason of
  741. DLL_PROCESS_ATTACH :
  742. begin
  743. if assigned(Dll_Process_Attach_Hook) then
  744. begin
  745. res:=Dll_Process_Attach_Hook(DllParam);
  746. if not res then
  747. exit(false);
  748. end;
  749. PASCALMAIN;
  750. Dll_entry:=true;
  751. end;
  752. DLL_THREAD_ATTACH :
  753. begin
  754. inclocked(Thread_count);
  755. { Allocate Threadvars ?!}
  756. if assigned(Dll_Thread_Attach_Hook) then
  757. Dll_Thread_Attach_Hook(DllParam);
  758. end;
  759. DLL_THREAD_DETACH :
  760. begin
  761. declocked(Thread_count);
  762. if assigned(Dll_Thread_Detach_Hook) then
  763. Dll_Thread_Detach_Hook(DllParam);
  764. { Release Threadvars ?!}
  765. end;
  766. DLL_PROCESS_DETACH :
  767. begin
  768. Lib_Exit;
  769. if assigned(Dll_Process_Detach_Hook) then
  770. Dll_Process_Detach_Hook(DllParam);
  771. end;
  772. end;
  773. end;
  774. {$ifdef WINCE_EXCEPTION_HANDLING}
  775. //
  776. // Hardware exception handling
  777. //
  778. {
  779. Error code definitions for the WinCE API functions
  780. Values are 32 bit values layed out as follows:
  781. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  782. 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  783. +---+-+-+-----------------------+-------------------------------+
  784. |Sev|C|R| Facility | Code |
  785. +---+-+-+-----------------------+-------------------------------+
  786. where
  787. Sev - is the severity code
  788. 00 - Success
  789. 01 - Informational
  790. 10 - Warning
  791. 11 - Error
  792. C - is the Customer code flag
  793. R - is a reserved bit
  794. Facility - is the facility code
  795. Code - is the facility's status code
  796. }
  797. const
  798. SEVERITY_SUCCESS = $00000000;
  799. SEVERITY_INFORMATIONAL = $40000000;
  800. SEVERITY_WARNING = $80000000;
  801. SEVERITY_ERROR = $C0000000;
  802. const
  803. STATUS_SEGMENT_NOTIFICATION = $40000005;
  804. DBG_TERMINATE_THREAD = $40010003;
  805. DBG_TERMINATE_PROCESS = $40010004;
  806. DBG_CONTROL_C = $40010005;
  807. DBG_CONTROL_BREAK = $40010008;
  808. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  809. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  810. STATUS_BREAKPOINT = $80000003;
  811. STATUS_SINGLE_STEP = $80000004;
  812. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  813. STATUS_ACCESS_VIOLATION = $C0000005;
  814. STATUS_IN_PAGE_ERROR = $C0000006;
  815. STATUS_INVALID_HANDLE = $C0000008;
  816. STATUS_NO_MEMORY = $C0000017;
  817. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  818. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  819. STATUS_INVALID_DISPOSITION = $C0000026;
  820. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  821. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  822. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  823. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  824. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  825. STATUS_FLOAT_OVERFLOW = $C0000091;
  826. STATUS_FLOAT_STACK_CHECK = $C0000092;
  827. STATUS_FLOAT_UNDERFLOW = $C0000093;
  828. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  829. STATUS_INTEGER_OVERFLOW = $C0000095;
  830. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  831. STATUS_STACK_OVERFLOW = $C00000FD;
  832. STATUS_CONTROL_C_EXIT = $C000013A;
  833. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  834. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  835. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  836. const
  837. ExceptionContinueExecution = 0;
  838. ExceptionContinueSearch = 1;
  839. ExceptionNestedException = 2;
  840. ExceptionCollidedUnwind = 3;
  841. ExceptionExecuteHandler = 4;
  842. MaxExceptionLevel = 16;
  843. exceptLevel : Byte = 0;
  844. {$ifdef CPUARM}
  845. const
  846. CONTEXT_ARM = $0000040;
  847. CONTEXT_CONTROL = CONTEXT_ARM or $00000001;
  848. CONTEXT_INTEGER = CONTEXT_ARM or $00000002;
  849. CONTEXT_SEGMENTS = CONTEXT_ARM or $00000004;
  850. CONTEXT_FLOATING_POINT = CONTEXT_ARM or $00000008;
  851. CONTEXT_DEBUG_REGISTERS = CONTEXT_ARM or $00000010;
  852. CONTEXT_EXTENDED_REGISTERS = CONTEXT_ARM or $00000020;
  853. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  854. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  855. NUM_VFP_REGS = 32;
  856. NUM_EXTRA_CONTROL_REGS = 8;
  857. type
  858. PContext = ^TContext;
  859. TContext = record
  860. ContextFlags : LongWord;
  861. // This section is specified/returned if the ContextFlags word contains
  862. // the flag CONTEXT_INTEGER.
  863. R0 : LongWord;
  864. R1 : LongWord;
  865. R2 : LongWord;
  866. R3 : LongWord;
  867. R4 : LongWord;
  868. R5 : LongWord;
  869. R6 : LongWord;
  870. R7 : LongWord;
  871. R8 : LongWord;
  872. R9 : LongWord;
  873. R10 : LongWord;
  874. R11 : LongWord;
  875. R12 : LongWord;
  876. // This section is specified/returned if the ContextFlags word contains
  877. // the flag CONTEXT_CONTROL.
  878. Sp : LongWord;
  879. Lr : LongWord;
  880. Pc : LongWord;
  881. Psr : LongWord;
  882. Fpscr : LongWord;
  883. FpExc : LongWord;
  884. // Floating point registers
  885. S : array[0..(NUM_VFP_REGS + 1)-1] of LongWord;
  886. FpExtra : array[0..(NUM_EXTRA_CONTROL_REGS)-1] of LongWord;
  887. end;
  888. {$endif CPUARM}
  889. {$ifdef CPUI386}
  890. const
  891. CONTEXT_X86 = $00010000;
  892. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  893. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  894. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  895. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  896. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  897. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  898. MAXIMUM_SUPPORTED_EXTENSION = 512;
  899. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  900. type
  901. PFloatingSaveArea = ^TFloatingSaveArea;
  902. TFloatingSaveArea = packed record
  903. ControlWord : Cardinal;
  904. StatusWord : Cardinal;
  905. TagWord : Cardinal;
  906. ErrorOffset : Cardinal;
  907. ErrorSelector : Cardinal;
  908. DataOffset : Cardinal;
  909. DataSelector : Cardinal;
  910. RegisterArea : array[0..79] of Byte;
  911. Cr0NpxState : Cardinal;
  912. end;
  913. PContext = ^TContext;
  914. TContext = packed record
  915. //
  916. // The flags values within this flag control the contents of
  917. // a CONTEXT record.
  918. //
  919. ContextFlags : Cardinal;
  920. //
  921. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  922. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  923. // included in CONTEXT_FULL.
  924. //
  925. Dr0, Dr1, Dr2,
  926. Dr3, Dr6, Dr7 : Cardinal;
  927. //
  928. // This section is specified/returned if the
  929. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  930. //
  931. FloatSave : TFloatingSaveArea;
  932. //
  933. // This section is specified/returned if the
  934. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  935. //
  936. SegGs, SegFs,
  937. SegEs, SegDs : Cardinal;
  938. //
  939. // This section is specified/returned if the
  940. // ContextFlags word contains the flag CONTEXT_INTEGER.
  941. //
  942. Edi, Esi, Ebx,
  943. Edx, Ecx, Eax : Cardinal;
  944. //
  945. // This section is specified/returned if the
  946. // ContextFlags word contains the flag CONTEXT_CONTROL.
  947. //
  948. Ebp : Cardinal;
  949. Eip : Cardinal;
  950. SegCs : Cardinal;
  951. EFlags, Esp, SegSs : Cardinal;
  952. //
  953. // This section is specified/returned if the ContextFlags word
  954. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  955. // The format and contexts are processor specific
  956. //
  957. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  958. end;
  959. {$endif CPUI386}
  960. type
  961. PExceptionRecord = ^TExceptionRecord;
  962. TExceptionRecord = packed record
  963. ExceptionCode : Longint;
  964. ExceptionFlags : Longint;
  965. ExceptionRecord : PExceptionRecord;
  966. ExceptionAddress : Pointer;
  967. NumberParameters : Longint;
  968. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  969. end;
  970. PExceptionPointers = ^TExceptionPointers;
  971. TExceptionPointers = packed record
  972. ExceptionRecord : PExceptionRecord;
  973. ContextRecord : PContext;
  974. end;
  975. {$ifdef CPUI386}
  976. {**************************** i386 Exception handling *****************************************}
  977. function GetCurrentProcess:DWORD;
  978. begin
  979. GetCurrentProcess := SH_CURPROC+SYS_HANDLE_BASE;
  980. end;
  981. function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
  982. cdecl; external 'coredll' name 'ReadProcessMemory';
  983. function is_prefetch(p : pointer) : boolean;
  984. var
  985. a : array[0..15] of byte;
  986. doagain : boolean;
  987. instrlo,instrhi,opcode : byte;
  988. i : longint;
  989. begin
  990. result:=false;
  991. { read memory savely without causing another exeception }
  992. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  993. exit;
  994. i:=0;
  995. doagain:=true;
  996. while doagain and (i<15) do
  997. begin
  998. opcode:=a[i];
  999. instrlo:=opcode and $f;
  1000. instrhi:=opcode and $f0;
  1001. case instrhi of
  1002. { prefix? }
  1003. $20,$30:
  1004. doagain:=(instrlo and 7)=6;
  1005. $60:
  1006. doagain:=(instrlo and $c)=4;
  1007. $f0:
  1008. doagain:=instrlo in [0,2,3];
  1009. $0:
  1010. begin
  1011. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  1012. exit;
  1013. end;
  1014. else
  1015. doagain:=false;
  1016. end;
  1017. inc(i);
  1018. end;
  1019. end;
  1020. var
  1021. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  1022. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1023. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  1024. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1025. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  1026. begin
  1027. if IsConsole then
  1028. begin
  1029. write(stderr,'HandleErrorAddrFrame(error=',error);
  1030. write(stderr,',addr=',hexstr(addr,8));
  1031. writeln(stderr,',frame=',hexstr(frame,8),')');
  1032. end;
  1033. HandleErrorAddrFrame(error,addr,frame);
  1034. end;
  1035. {$endif SYSTEMEXCEPTIONDEBUG}
  1036. procedure JumpToHandleErrorFrame;
  1037. var
  1038. eip, ebp, error : Longint;
  1039. begin
  1040. // save ebp
  1041. asm
  1042. movl (%ebp),%eax
  1043. movl %eax,ebp
  1044. end;
  1045. if (exceptLevel > 0) then
  1046. dec(exceptLevel);
  1047. eip:=exceptEip[exceptLevel];
  1048. error:=exceptError[exceptLevel];
  1049. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1050. if IsConsole then
  1051. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  1052. {$endif SYSTEMEXCEPTIONDEBUG}
  1053. if resetFPU[exceptLevel] then
  1054. SysResetFPU;
  1055. { build a fake stack }
  1056. asm
  1057. {$ifdef REGCALL}
  1058. movl ebp,%ecx
  1059. movl eip,%edx
  1060. movl error,%eax
  1061. pushl eip
  1062. movl ebp,%ebp // Change frame pointer
  1063. {$else}
  1064. movl ebp,%eax
  1065. pushl %eax
  1066. movl eip,%eax
  1067. pushl %eax
  1068. movl error,%eax
  1069. pushl %eax
  1070. movl eip,%eax
  1071. pushl %eax
  1072. movl ebp,%ebp // Change frame pointer
  1073. {$endif}
  1074. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1075. jmpl DebugHandleErrorAddrFrame
  1076. {$else not SYSTEMEXCEPTIONDEBUG}
  1077. jmpl HandleErrorAddrFrame
  1078. {$endif SYSTEMEXCEPTIONDEBUG}
  1079. end;
  1080. end;
  1081. function i386_exception_handler(ExceptionRecord: PExceptionRecord;
  1082. EstablisherFrame: pointer; ContextRecord: PContext;
  1083. DispatcherContext: pointer): longint; cdecl;
  1084. var
  1085. res: longint;
  1086. must_reset_fpu: boolean;
  1087. begin
  1088. res := ExceptionContinueSearch;
  1089. if ContextRecord^.SegSs=_SS then begin
  1090. must_reset_fpu := true;
  1091. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1092. if IsConsole then Writeln(stderr,'Exception ',
  1093. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  1094. {$endif SYSTEMEXCEPTIONDEBUG}
  1095. case cardinal(ExceptionRecord^.ExceptionCode) of
  1096. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1097. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1098. res := 200;
  1099. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1100. begin
  1101. res := 201;
  1102. must_reset_fpu := false;
  1103. end;
  1104. STATUS_STACK_OVERFLOW :
  1105. begin
  1106. res := 202;
  1107. must_reset_fpu := false;
  1108. end;
  1109. STATUS_FLOAT_OVERFLOW :
  1110. res := 205;
  1111. STATUS_FLOAT_DENORMAL_OPERAND,
  1112. STATUS_FLOAT_UNDERFLOW :
  1113. res := 206;
  1114. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  1115. STATUS_FLOAT_INEXACT_RESULT,
  1116. STATUS_FLOAT_INVALID_OPERATION,
  1117. STATUS_FLOAT_STACK_CHECK :
  1118. res := 207;
  1119. STATUS_INTEGER_OVERFLOW :
  1120. begin
  1121. res := 215;
  1122. must_reset_fpu := false;
  1123. end;
  1124. STATUS_ILLEGAL_INSTRUCTION:
  1125. res := 216;
  1126. STATUS_ACCESS_VIOLATION:
  1127. { Athlon prefetch bug? }
  1128. if is_prefetch(pointer(ContextRecord^.Eip)) then
  1129. begin
  1130. { if yes, then retry }
  1131. ExceptionRecord^.ExceptionCode := 0;
  1132. res:=ExceptionContinueExecution;
  1133. end
  1134. else
  1135. res := 216;
  1136. STATUS_CONTROL_C_EXIT:
  1137. res := 217;
  1138. STATUS_PRIVILEGED_INSTRUCTION:
  1139. begin
  1140. res := 218;
  1141. must_reset_fpu := false;
  1142. end;
  1143. else
  1144. begin
  1145. if ((ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1146. res := 217
  1147. else
  1148. res := 255;
  1149. end;
  1150. end;
  1151. if (res >= 200) and (exceptLevel < MaxExceptionLevel) then begin
  1152. exceptEip[exceptLevel] := ContextRecord^.Eip;
  1153. exceptError[exceptLevel] := res;
  1154. resetFPU[exceptLevel] := must_reset_fpu;
  1155. inc(exceptLevel);
  1156. ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  1157. ExceptionRecord^.ExceptionCode := 0;
  1158. res := ExceptionContinueExecution;
  1159. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1160. if IsConsole then begin
  1161. writeln(stderr,'Exception Continue Exception set at ',
  1162. hexstr(exceptEip[exceptLevel],8));
  1163. writeln(stderr,'Eip changed to ',
  1164. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1165. end;
  1166. {$endif SYSTEMEXCEPTIONDEBUG}
  1167. end;
  1168. end;
  1169. i386_exception_handler := res;
  1170. end;
  1171. {$endif CPUI386}
  1172. {$ifdef CPUARM}
  1173. {**************************** ARM Exception handling *****************************************}
  1174. var
  1175. exceptPC : array[0..MaxExceptionLevel-1] of Longint;
  1176. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1177. procedure JumpToHandleErrorFrame;
  1178. var
  1179. _pc, _fp, _error : Longint;
  1180. begin
  1181. // get original fp
  1182. asm
  1183. ldr r0,[r11,#-12]
  1184. str r0,_fp
  1185. end;
  1186. if (exceptLevel > 0) then
  1187. dec(exceptLevel);
  1188. _pc:=exceptPC[exceptLevel];
  1189. _error:=exceptError[exceptLevel];
  1190. asm
  1191. ldr r0,_error
  1192. ldr r1,_pc
  1193. ldr r2,_fp
  1194. mov r11,r2 // Change frame pointer
  1195. b HandleErrorAddrFrame
  1196. end;
  1197. end;
  1198. function ARM_ExceptionHandler(ExceptionRecord: PExceptionRecord;
  1199. EstablisherFrame: pointer; ContextRecord: PContext;
  1200. DispatcherContext: pointer): longint; [public, alias : '_ARM_ExceptionHandler'];
  1201. var
  1202. res: longint;
  1203. begin
  1204. res := ExceptionContinueSearch;
  1205. case cardinal(ExceptionRecord^.ExceptionCode) of
  1206. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1207. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1208. res := 200;
  1209. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1210. res := 201;
  1211. STATUS_STACK_OVERFLOW :
  1212. res := 202;
  1213. STATUS_FLOAT_OVERFLOW :
  1214. res := 205;
  1215. STATUS_FLOAT_DENORMAL_OPERAND,
  1216. STATUS_FLOAT_UNDERFLOW :
  1217. res := 206;
  1218. STATUS_FLOAT_INEXACT_RESULT,
  1219. STATUS_FLOAT_INVALID_OPERATION,
  1220. STATUS_FLOAT_STACK_CHECK :
  1221. res := 207;
  1222. STATUS_INTEGER_OVERFLOW :
  1223. res := 215;
  1224. STATUS_ILLEGAL_INSTRUCTION:
  1225. res := 216;
  1226. STATUS_ACCESS_VIOLATION:
  1227. res := 216;
  1228. STATUS_DATATYPE_MISALIGNMENT:
  1229. res := 214;
  1230. STATUS_CONTROL_C_EXIT:
  1231. res := 217;
  1232. STATUS_PRIVILEGED_INSTRUCTION:
  1233. res := 218;
  1234. else
  1235. begin
  1236. if ((cardinal(ExceptionRecord^.ExceptionCode) and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1237. res := 217
  1238. else
  1239. res := 255;
  1240. end;
  1241. end;
  1242. if (res <> ExceptionContinueSearch) and (exceptLevel < MaxExceptionLevel) then begin
  1243. exceptPC[exceptLevel] := ContextRecord^.PC;
  1244. exceptError[exceptLevel] := res;
  1245. inc(exceptLevel);
  1246. ContextRecord^.PC := Longint(@JumpToHandleErrorFrame);
  1247. ExceptionRecord^.ExceptionCode := 0;
  1248. res := ExceptionContinueExecution;
  1249. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1250. if IsConsole then begin
  1251. writeln(stderr,'Exception Continue Exception set at ',
  1252. hexstr(exceptEip[exceptLevel],8));
  1253. writeln(stderr,'Eip changed to ',
  1254. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1255. end;
  1256. {$endif SYSTEMEXCEPTIONDEBUG}
  1257. end;
  1258. ARM_ExceptionHandler := res;
  1259. end;
  1260. {$endif CPUARM}
  1261. {$endif WINCE_EXCEPTION_HANDLING}
  1262. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  1263. var
  1264. st: pointer;
  1265. begin
  1266. IsLibrary:=false;
  1267. {$ifdef CPUARM}
  1268. asm
  1269. str sp,st
  1270. end;
  1271. StackTop:=st;
  1272. asm
  1273. mov fp,#0
  1274. bl PASCALMAIN;
  1275. end;
  1276. {$endif CPUARM}
  1277. {$ifdef CPUI386}
  1278. asm
  1279. {$ifdef WINCE_EXCEPTION_HANDLING}
  1280. pushl i386_exception_handler
  1281. pushl %fs:(0)
  1282. mov %esp,%fs:(0)
  1283. {$endif WINCE_EXCEPTION_HANDLING}
  1284. pushl %ebp
  1285. movl %esp,%eax
  1286. movl %eax,st
  1287. end;
  1288. StackTop:=st;
  1289. asm
  1290. xorl %eax,%eax
  1291. movw %ss,%ax
  1292. movl %eax,_SS
  1293. xorl %ebp,%ebp
  1294. call PASCALMAIN
  1295. popl %ebp
  1296. {$ifdef WINCE_EXCEPTION_HANDLING}
  1297. popl %fs:(0)
  1298. addl $4, %esp
  1299. {$endif WINCE_EXCEPTION_HANDLING}
  1300. end;
  1301. {$endif CPUI386}
  1302. end;
  1303. procedure _FPC_mainCRTStartup;public name '_mainCRTStartup';
  1304. begin
  1305. IsConsole:=True;
  1306. Exe_entry;
  1307. end;
  1308. procedure _FPC_WinMainCRTStartup;public name '_WinMainCRTStartup';
  1309. begin
  1310. IsConsole:=False;
  1311. Exe_entry;
  1312. end;
  1313. procedure _FPC_DLLMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);public name '_DLLMainCRTStartup';
  1314. begin
  1315. IsConsole:=true;
  1316. sysinstance:=_hinstance;
  1317. dllreason:=_dllreason;
  1318. dllparam:=_dllparam;
  1319. DLL_Entry;
  1320. end;
  1321. procedure _FPC_DLLWinMainCRTStartup(_hinstance,_dllreason,_dllparam:longint);public name '_DLLWinMainCRTStartup';
  1322. begin
  1323. IsConsole:=false;
  1324. sysinstance:=_hinstance;
  1325. dllreason:=_dllreason;
  1326. dllparam:=_dllparam;
  1327. DLL_Entry;
  1328. end;
  1329. {****************************************************************************
  1330. OS dependend widestrings
  1331. ****************************************************************************}
  1332. function CharUpperBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; cdecl; external KernelDLL name 'CharUpperBuffW';
  1333. function CharLowerBuff(lpsz:LPWSTR; cchLength:DWORD):DWORD; cdecl; external KernelDLL name 'CharLowerBuffW';
  1334. procedure WinCEWide2AnsiMove(source:pwidechar;var dest:ansistring;len:SizeInt);
  1335. var
  1336. i: integer;
  1337. begin
  1338. if len = 0 then
  1339. dest:=''
  1340. else
  1341. begin
  1342. for i:=1 to 2 do begin
  1343. setlength(dest, len);
  1344. len:=WideCharToMultiByte(CP_ACP, 0, source, len, @dest[1], len, nil, nil);
  1345. if len > 0 then
  1346. break;
  1347. len:=WideCharToMultiByte(CP_ACP, 0, source, len, nil, 0, nil, nil);
  1348. end;
  1349. setlength(dest, len);
  1350. end;
  1351. end;
  1352. procedure WinCEAnsi2WideMove(source:pchar;var dest:widestring;len:SizeInt);
  1353. var
  1354. i: integer;
  1355. begin
  1356. if len = 0 then
  1357. dest:=''
  1358. else
  1359. begin
  1360. for i:=1 to 2 do begin
  1361. setlength(dest, len);
  1362. len:=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, source, len, @dest[1], len);
  1363. if len > 0 then
  1364. break;
  1365. len:=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, source, len, nil, 0);
  1366. end;
  1367. setlength(dest, len);
  1368. end;
  1369. end;
  1370. function WinCEWideUpper(const s : WideString) : WideString;
  1371. begin
  1372. result:=s;
  1373. UniqueString(result);
  1374. if length(result)>0 then
  1375. CharUpperBuff(LPWSTR(result),length(result));
  1376. end;
  1377. function WinCEWideLower(const s : WideString) : WideString;
  1378. begin
  1379. result:=s;
  1380. UniqueString(result);
  1381. if length(result)>0 then
  1382. CharLowerBuff(LPWSTR(result),length(result));
  1383. end;
  1384. { there is a similiar procedure in sysutils which inits the fields which
  1385. are only relevant for the sysutils units }
  1386. procedure InitWinCEWidestrings;
  1387. begin
  1388. widestringmanager.Wide2AnsiMoveProc:=@WinCEWide2AnsiMove;
  1389. widestringmanager.Ansi2WideMoveProc:=@WinCEAnsi2WideMove;
  1390. widestringmanager.UpperWideStringProc:=@WinCEWideUpper;
  1391. widestringmanager.LowerWideStringProc:=@WinCEWideLower;
  1392. end;
  1393. {$IFDEF HAS_MT_MEMORYMANAGER}
  1394. {****************************************************************************
  1395. Memory manager
  1396. ****************************************************************************}
  1397. function malloc(Size : ptrint) : Pointer; cdecl; external 'coredll';
  1398. procedure free(P : pointer); cdecl; external 'coredll';
  1399. function realloc(P : Pointer; Size : ptrint) : pointer; cdecl; external 'coredll';
  1400. function _msize(P : pointer): ptrint; cdecl; external 'coredll';
  1401. function SysGetMem (Size : ptrint) : Pointer;
  1402. begin
  1403. Result:=malloc(Size);
  1404. end;
  1405. Function SysFreeMem (P : pointer) : ptrint;
  1406. begin
  1407. free(P);
  1408. Result:=0;
  1409. end;
  1410. Function SysFreeMemSize(p:pointer;Size:ptrint):ptrint;
  1411. begin
  1412. Result:=0;
  1413. if (size > 0) and (p <> nil) then
  1414. Result:=SysFreeMem(P);
  1415. end;
  1416. Function SysAllocMem(Size : ptrint) : Pointer;
  1417. begin
  1418. Result:=SysGetMem(Size);
  1419. if Result <> nil then
  1420. FillChar(Result^, Size, 0);
  1421. end;
  1422. Function SysReAllocMem (var p:pointer;Size:ptrint):Pointer;
  1423. begin
  1424. Result:=realloc(p, Size);
  1425. p:=Result;
  1426. end;
  1427. function SysTryResizeMem(var p:pointer;size : ptrint):boolean;
  1428. var
  1429. res: pointer;
  1430. begin
  1431. res:=realloc(p, Size);
  1432. Result:=(res <> nil) or (Size = 0);
  1433. if Result then
  1434. p:=res;
  1435. end;
  1436. function SysMemSize(P : pointer): ptrint;
  1437. begin
  1438. Result:=_msize(P);
  1439. end;
  1440. function SysGetHeapStatus:THeapStatus;
  1441. begin
  1442. fillchar(Result,sizeof(Result),0);
  1443. end;
  1444. function SysGetFPCHeapStatus:TFPCHeapStatus;
  1445. begin
  1446. fillchar(Result,sizeof(Result),0);
  1447. end;
  1448. {$ENDIF HAS_MT_MEMORYMANAGER}
  1449. {****************************************************************************
  1450. Error Message writing using messageboxes
  1451. ****************************************************************************}
  1452. const
  1453. ErrorBufferLength = 1024;
  1454. var
  1455. ErrorBuf : array[0..ErrorBufferLength] of char;
  1456. ErrorBufW : array[0..ErrorBufferLength] of widechar;
  1457. ErrorLen : longint;
  1458. Function ErrorWrite(Var F: TextRec): Integer;
  1459. {
  1460. An error message should always end with #13#10#13#10
  1461. }
  1462. var
  1463. p : pchar;
  1464. i : longint;
  1465. Begin
  1466. if F.BufPos>0 then
  1467. begin
  1468. if F.BufPos+ErrorLen>ErrorBufferLength then
  1469. i:=ErrorBufferLength-ErrorLen
  1470. else
  1471. i:=F.BufPos;
  1472. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1473. inc(ErrorLen,i);
  1474. ErrorBuf[ErrorLen]:=#0;
  1475. end;
  1476. if ErrorLen>3 then
  1477. begin
  1478. p:=@ErrorBuf[ErrorLen];
  1479. for i:=1 to 4 do
  1480. begin
  1481. dec(p);
  1482. if not(p^ in [#10,#13]) then
  1483. break;
  1484. end;
  1485. end;
  1486. if ErrorLen=ErrorBufferLength then
  1487. i:=4;
  1488. if (i=4) then
  1489. begin
  1490. AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
  1491. MessageBox(0,@ErrorBufW,'Error',0);
  1492. ErrorLen:=0;
  1493. end;
  1494. F.BufPos:=0;
  1495. ErrorWrite:=0;
  1496. End;
  1497. Function ErrorClose(Var F: TextRec): Integer;
  1498. begin
  1499. if ErrorLen>0 then
  1500. begin
  1501. AnsiToWideBuf(@ErrorBuf, -1, @ErrorBufW, SizeOf(ErrorBufW));
  1502. MessageBox(0,@ErrorBufW,'Error',0);
  1503. ErrorLen:=0;
  1504. end;
  1505. ErrorLen:=0;
  1506. ErrorClose:=0;
  1507. end;
  1508. Function ErrorOpen(Var F: TextRec): Integer;
  1509. Begin
  1510. TextRec(F).InOutFunc:=@ErrorWrite;
  1511. TextRec(F).FlushFunc:=@ErrorWrite;
  1512. TextRec(F).CloseFunc:=@ErrorClose;
  1513. ErrorOpen:=0;
  1514. End;
  1515. procedure AssignError(Var T: Text);
  1516. begin
  1517. Assign(T,'');
  1518. TextRec(T).OpenFunc:=@ErrorOpen;
  1519. Rewrite(T);
  1520. end;
  1521. function _getstdfilex(fd: integer): pointer; cdecl; external 'coredll';
  1522. function _fileno(fd: pointer): THandle; cdecl; external 'coredll';
  1523. procedure SysInitStdIO;
  1524. begin
  1525. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1526. displayed in and messagebox }
  1527. if not IsConsole then begin
  1528. AssignError(stderr);
  1529. AssignError(stdout);
  1530. Assign(Output,'');
  1531. Assign(Input,'');
  1532. Assign(ErrOutput,'');
  1533. end
  1534. else begin
  1535. StdInputHandle:=_fileno(_getstdfilex(0));
  1536. StdOutputHandle:=_fileno(_getstdfilex(1));
  1537. StdErrorHandle:=_fileno(_getstdfilex(2));
  1538. OpenStdIO(Input,fmInput,StdInputHandle);
  1539. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1540. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  1541. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1542. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1543. end;
  1544. end;
  1545. (* ProcessID cached to avoid repeated calls to GetCurrentProcess. *)
  1546. var
  1547. ProcessID: SizeUInt;
  1548. function GetProcessID: SizeUInt;
  1549. begin
  1550. GetProcessID := ProcessID;
  1551. end;
  1552. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  1553. begin
  1554. result := stklen;
  1555. end;
  1556. procedure SysCleanup;
  1557. var
  1558. i: integer;
  1559. begin
  1560. if FCmdLine = nil then
  1561. exit;
  1562. SysFreeMem(FCmdLine);
  1563. for i:=0 to Fargc do
  1564. sysfreemem(Fargv[i]);
  1565. sysfreemem(Fargv);
  1566. end;
  1567. initialization
  1568. SysResetFPU;
  1569. if not(IsLibrary) then
  1570. SysInitFPU;
  1571. StackLength := CheckInitialStkLen(InitialStkLen);
  1572. StackBottom := StackTop - StackLength;
  1573. { some misc stuff }
  1574. hprevinst:=0;
  1575. if not IsLibrary then
  1576. SysInstance:=GetModuleHandle(nil);
  1577. MainInstance:=SysInstance;
  1578. {$IFNDEF HAS_MT_MEMORYMANAGER}
  1579. { Setup Heap }
  1580. InitHeap;
  1581. {$ENDIF HAS_MT_MEMORYMANAGER}
  1582. SysInitExceptions;
  1583. if not IsLibrary then
  1584. begin
  1585. SysInitStdIO;
  1586. end;
  1587. { Reset IO Error }
  1588. InOutRes:=0;
  1589. ProcessID := GetCurrentProcessID;
  1590. { threading }
  1591. InitSystemThreads;
  1592. { Reset internal error variable }
  1593. errno:=0;
  1594. initvariantmanager;
  1595. initwidestringmanager;
  1596. InitWinCEWidestrings;
  1597. DispCallByIDProc:=@DoDispCallByIDError;
  1598. finalization
  1599. SysCleanup;
  1600. end.