system.pp 50 KB

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