system.pp 50 KB

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