system.pp 49 KB

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