system.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  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. member of the Free Pascal development team.
  5. FPC Pascal system unit for the Win32 API.
  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 FPC_HAS_INDIRECT_MAIN_INFORMATION}
  18. {$ifdef cpui386}
  19. {$define Set_i386_Exception_handler}
  20. {$endif cpui386}
  21. {$define DISABLE_NO_THREAD_MANAGER}
  22. {$define HAS_WIDESTRINGMANAGER}
  23. { include system-independent routine headers }
  24. {$I systemh.inc}
  25. const
  26. LineEnding = #13#10;
  27. LFNSupport = true;
  28. DirectorySeparator = '\';
  29. DriveSeparator = ':';
  30. ExtensionSeparator = '.';
  31. PathSeparator = ';';
  32. AllowDirectorySeparators : set of char = ['\','/'];
  33. AllowDriveSeparators : set of char = [':'];
  34. { FileNameCaseSensitive is defined separately below!!! }
  35. maxExitCode = 65535;
  36. MaxPathLen = 260;
  37. AllFilesMask = '*';
  38. type
  39. PEXCEPTION_FRAME = ^TEXCEPTION_FRAME;
  40. TEXCEPTION_FRAME = record
  41. next : PEXCEPTION_FRAME;
  42. handler : pointer;
  43. end;
  44. const
  45. { Default filehandles }
  46. UnusedHandle : THandle = THandle(-1);
  47. StdInputHandle : THandle = 0;
  48. StdOutputHandle : THandle = 0;
  49. StdErrorHandle : THandle = 0;
  50. FileNameCaseSensitive : boolean = true;
  51. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  52. sLineBreak = LineEnding;
  53. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  54. System_exception_frame : PEXCEPTION_FRAME =nil;
  55. type
  56. TStartupInfo=packed record
  57. cb : longint;
  58. lpReserved : Pointer;
  59. lpDesktop : Pointer;
  60. lpTitle : Pointer;
  61. dwX : longint;
  62. dwY : longint;
  63. dwXSize : longint;
  64. dwYSize : longint;
  65. dwXCountChars : longint;
  66. dwYCountChars : longint;
  67. dwFillAttribute : longint;
  68. dwFlags : longint;
  69. wShowWindow : Word;
  70. cbReserved2 : Word;
  71. lpReserved2 : Pointer;
  72. hStdInput : longint;
  73. hStdOutput : longint;
  74. hStdError : longint;
  75. end;
  76. var
  77. { C compatible arguments }
  78. argc : longint; public name 'operatingsystem_parameter_argc';
  79. argv : ppchar; public name 'operatingsystem_parameter_argv';
  80. { Win32 Info }
  81. startupinfo : tstartupinfo;
  82. MainInstance,
  83. cmdshow : longint;
  84. DLLreason : longint; public name 'operatingsystem_dllreason';
  85. DLLparam : longint; public name 'operatingsystem_dllparam';
  86. StartupConsoleMode : DWORD;
  87. const
  88. hprevinst: longint=0;
  89. type
  90. TDLL_Entry_Hook = procedure (dllparam : longint);
  91. const
  92. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  93. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  94. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  95. Const
  96. { it can be discussed whether fmShareDenyNone means read and write or read, write and delete, see
  97. also http://bugs.freepascal.org/view.php?id=8898, this allows users to configure the used
  98. value
  99. }
  100. fmShareDenyNoneFlags : DWord = 3;
  101. implementation
  102. var
  103. SysInstance : Longint;public name '_FPC_SysInstance';
  104. InitFinalTable : record end; external name 'INITFINAL';
  105. ThreadvarTablesTable : record end; external name 'FPC_THREADVARTABLES';
  106. procedure PascalMain;stdcall;external name 'PASCALMAIN';
  107. procedure asm_exit;stdcall;external name 'asm_exit';
  108. const
  109. EntryInformation : TEntryInformation = (
  110. InitFinalTable : @InitFinalTable;
  111. ThreadvarTablesTable : @ThreadvarTablesTable;
  112. asm_exit : @asm_exit;
  113. PascalMain : @PascalMain;
  114. valgrind_used : false;
  115. );
  116. { include system independent routines }
  117. {$I system.inc}
  118. {*****************************************************************************
  119. System Dependent Exit code
  120. *****************************************************************************}
  121. procedure install_exception_handlers;forward;
  122. procedure remove_exception_handlers;forward;
  123. procedure fpc_do_exit;stdcall;external name 'FPC_DO_EXIT';
  124. Procedure ExitDLL(Exitcode : longint); forward;
  125. Procedure system_exit;
  126. begin
  127. { don't call ExitProcess inside
  128. the DLL exit code !!
  129. This crashes Win95 at least PM }
  130. if IsLibrary then
  131. ExitDLL(ExitCode);
  132. if not IsConsole then
  133. begin
  134. Close(stderr);
  135. Close(stdout);
  136. Close(erroutput);
  137. Close(Input);
  138. Close(Output);
  139. { what about Input and Output ?? PM }
  140. { now handled, FPK }
  141. end;
  142. remove_exception_handlers;
  143. { do cleanup required by the startup code }
  144. EntryInformation.asm_exit();
  145. { call exitprocess, with cleanup as required }
  146. ExitProcess(exitcode);
  147. end;
  148. var
  149. { value of the stack segment
  150. to check if the call stack can be written on exceptions }
  151. _SS : Cardinal;
  152. procedure Exe_entry(const info : TEntryInformation);[public,alias:'_FPC_EXE_Entry'];
  153. var
  154. ST : pointer;
  155. begin
  156. EntryInformation:=info;
  157. IsLibrary:=false;
  158. { install the handlers for exe only ?
  159. or should we install them for DLL also ? (PM) }
  160. install_exception_handlers;
  161. { This strange construction is needed to solve the _SS problem
  162. with a smartlinked syswin32 (PFV) }
  163. asm
  164. { allocate space for an exception frame }
  165. pushl $0
  166. pushl %fs:(0)
  167. { movl %esp,%fs:(0)
  168. but don't insert it as it doesn't
  169. point to anything yet
  170. this will be used in signals unit }
  171. movl %esp,%eax
  172. movl %eax,System_exception_frame
  173. pushl %ebp
  174. movl %esp,%eax
  175. movl %eax,st
  176. end;
  177. StackTop:=st;
  178. asm
  179. xorl %eax,%eax
  180. movw %ss,%ax
  181. movl %eax,_SS
  182. xorl %ebp,%ebp
  183. end;
  184. EntryInformation.PascalMain();
  185. asm
  186. popl %ebp
  187. end;
  188. { if we pass here there was no error ! }
  189. system_exit;
  190. end;
  191. function is_prefetch(p : pointer) : boolean;
  192. var
  193. a : array[0..15] of byte;
  194. doagain : boolean;
  195. instrlo,instrhi,opcode : byte;
  196. i : longint;
  197. begin
  198. result:=false;
  199. { read memory savely without causing another exeception }
  200. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  201. exit;
  202. i:=0;
  203. doagain:=true;
  204. while doagain and (i<15) do
  205. begin
  206. opcode:=a[i];
  207. instrlo:=opcode and $f;
  208. instrhi:=opcode and $f0;
  209. case instrhi of
  210. { prefix? }
  211. $20,$30:
  212. doagain:=(instrlo and 7)=6;
  213. $60:
  214. doagain:=(instrlo and $c)=4;
  215. $f0:
  216. doagain:=instrlo in [0,2,3];
  217. $0:
  218. begin
  219. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  220. exit;
  221. end;
  222. else
  223. doagain:=false;
  224. end;
  225. inc(i);
  226. end;
  227. end;
  228. {******************************************************************************}
  229. { include code common with win64 }
  230. {$I syswin.inc}
  231. {******************************************************************************}
  232. //
  233. // Hardware exception handling
  234. //
  235. {$ifdef Set_i386_Exception_handler}
  236. type
  237. PFloatingSaveArea = ^TFloatingSaveArea;
  238. TFloatingSaveArea = packed record
  239. ControlWord : Cardinal;
  240. StatusWord : Cardinal;
  241. TagWord : Cardinal;
  242. ErrorOffset : Cardinal;
  243. ErrorSelector : Cardinal;
  244. DataOffset : Cardinal;
  245. DataSelector : Cardinal;
  246. RegisterArea : array[0..79] of Byte;
  247. Cr0NpxState : Cardinal;
  248. end;
  249. PContext = ^TContext;
  250. TContext = packed record
  251. //
  252. // The flags values within this flag control the contents of
  253. // a CONTEXT record.
  254. //
  255. ContextFlags : Cardinal;
  256. //
  257. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  258. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  259. // included in CONTEXT_FULL.
  260. //
  261. Dr0, Dr1, Dr2,
  262. Dr3, Dr6, Dr7 : Cardinal;
  263. //
  264. // This section is specified/returned if the
  265. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  266. //
  267. FloatSave : TFloatingSaveArea;
  268. //
  269. // This section is specified/returned if the
  270. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  271. //
  272. SegGs, SegFs,
  273. SegEs, SegDs : Cardinal;
  274. //
  275. // This section is specified/returned if the
  276. // ContextFlags word contains the flag CONTEXT_INTEGER.
  277. //
  278. Edi, Esi, Ebx,
  279. Edx, Ecx, Eax : Cardinal;
  280. //
  281. // This section is specified/returned if the
  282. // ContextFlags word contains the flag CONTEXT_CONTROL.
  283. //
  284. Ebp : Cardinal;
  285. Eip : Cardinal;
  286. SegCs : Cardinal;
  287. EFlags, Esp, SegSs : Cardinal;
  288. //
  289. // This section is specified/returned if the ContextFlags word
  290. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  291. // The format and contexts are processor specific
  292. //
  293. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  294. end;
  295. PExceptionPointers = ^TExceptionPointers;
  296. TExceptionPointers = packed record
  297. ExceptionRecord : PExceptionRecord;
  298. ContextRecord : PContext;
  299. end;
  300. { type of functions that should be used for exception handling }
  301. TTopLevelExceptionFilter = function (excep : PExceptionPointers) : Longint;stdcall;
  302. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : TTopLevelExceptionFilter) : TTopLevelExceptionFilter;
  303. stdcall;external 'kernel32' name 'SetUnhandledExceptionFilter';
  304. const
  305. MaxExceptionLevel = 16;
  306. exceptLevel : Byte = 0;
  307. var
  308. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  309. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  310. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  311. {$ifdef SYSTEMEXCEPTIONDEBUG}
  312. procedure DebugHandleErrorAddrFrame(error : longint; addr, frame : pointer);
  313. begin
  314. if IsConsole then
  315. begin
  316. write(stderr,'HandleErrorAddrFrame(error=',error);
  317. write(stderr,',addr=',hexstr(ptruint(addr),8));
  318. writeln(stderr,',frame=',hexstr(ptruint(frame),8),')');
  319. end;
  320. HandleErrorAddrFrame(error,addr,frame);
  321. end;
  322. {$endif SYSTEMEXCEPTIONDEBUG}
  323. procedure JumpToHandleErrorFrame;
  324. var
  325. eip, ebp, error : Longint;
  326. begin
  327. // save ebp
  328. asm
  329. movl (%ebp),%eax
  330. movl %eax,ebp
  331. end;
  332. if (exceptLevel > 0) then
  333. dec(exceptLevel);
  334. eip:=exceptEip[exceptLevel];
  335. error:=exceptError[exceptLevel];
  336. {$ifdef SYSTEMEXCEPTIONDEBUG}
  337. if IsConsole then
  338. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  339. {$endif SYSTEMEXCEPTIONDEBUG}
  340. if resetFPU[exceptLevel] then
  341. SysResetFPU;
  342. { build a fake stack }
  343. asm
  344. movl ebp,%ecx
  345. movl eip,%edx
  346. movl error,%eax
  347. pushl eip
  348. movl ebp,%ebp // Change frame pointer
  349. {$ifdef SYSTEMEXCEPTIONDEBUG}
  350. jmpl DebugHandleErrorAddrFrame
  351. {$else not SYSTEMEXCEPTIONDEBUG}
  352. jmpl HandleErrorAddrFrame
  353. {$endif SYSTEMEXCEPTIONDEBUG}
  354. end;
  355. end;
  356. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  357. var
  358. res: longint;
  359. err: byte;
  360. must_reset_fpu: boolean;
  361. begin
  362. res := EXCEPTION_CONTINUE_SEARCH;
  363. if excep^.ContextRecord^.SegSs=_SS then begin
  364. err := 0;
  365. must_reset_fpu := true;
  366. {$ifdef SYSTEMEXCEPTIONDEBUG}
  367. if IsConsole then Writeln(stderr,'Exception ',
  368. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  369. {$endif SYSTEMEXCEPTIONDEBUG}
  370. case excep^.ExceptionRecord^.ExceptionCode of
  371. STATUS_INTEGER_DIVIDE_BY_ZERO,
  372. STATUS_FLOAT_DIVIDE_BY_ZERO :
  373. err := 200;
  374. STATUS_ARRAY_BOUNDS_EXCEEDED :
  375. begin
  376. err := 201;
  377. must_reset_fpu := false;
  378. end;
  379. STATUS_STACK_OVERFLOW :
  380. begin
  381. err := 202;
  382. must_reset_fpu := false;
  383. end;
  384. STATUS_FLOAT_OVERFLOW :
  385. err := 205;
  386. STATUS_FLOAT_DENORMAL_OPERAND,
  387. STATUS_FLOAT_UNDERFLOW :
  388. err := 206;
  389. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  390. STATUS_FLOAT_INEXACT_RESULT,
  391. STATUS_FLOAT_INVALID_OPERATION,
  392. STATUS_FLOAT_STACK_CHECK :
  393. err := 207;
  394. STATUS_INTEGER_OVERFLOW :
  395. begin
  396. err := 215;
  397. must_reset_fpu := false;
  398. end;
  399. STATUS_ILLEGAL_INSTRUCTION:
  400. { if we're testing sse support, simply set the flag and continue }
  401. if sse_check then
  402. begin
  403. os_supports_sse:=false;
  404. { skip the offending movaps %xmm7, %xmm6 instruction }
  405. inc(excep^.ContextRecord^.Eip,3);
  406. excep^.ExceptionRecord^.ExceptionCode := 0;
  407. res:=EXCEPTION_CONTINUE_EXECUTION;
  408. end
  409. else
  410. err := 216;
  411. STATUS_ACCESS_VIOLATION:
  412. { Athlon prefetch bug? }
  413. if is_prefetch(pointer(excep^.ContextRecord^.Eip)) then
  414. begin
  415. { if yes, then retry }
  416. excep^.ExceptionRecord^.ExceptionCode := 0;
  417. res:=EXCEPTION_CONTINUE_EXECUTION;
  418. end
  419. else
  420. err := 216;
  421. STATUS_CONTROL_C_EXIT:
  422. err := 217;
  423. STATUS_PRIVILEGED_INSTRUCTION:
  424. begin
  425. err := 218;
  426. must_reset_fpu := false;
  427. end;
  428. else
  429. begin
  430. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  431. err := 217
  432. else
  433. err := 255;
  434. end;
  435. end;
  436. if (err <> 0) and (exceptLevel < MaxExceptionLevel) then begin
  437. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  438. exceptError[exceptLevel] := err;
  439. resetFPU[exceptLevel] := must_reset_fpu;
  440. inc(exceptLevel);
  441. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  442. excep^.ExceptionRecord^.ExceptionCode := 0;
  443. res := EXCEPTION_CONTINUE_EXECUTION;
  444. {$ifdef SYSTEMEXCEPTIONDEBUG}
  445. if IsConsole then begin
  446. writeln(stderr,'Exception Continue Exception set at ',
  447. hexstr(exceptEip[exceptLevel],8));
  448. writeln(stderr,'Eip changed to ',
  449. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', err);
  450. end;
  451. {$endif SYSTEMEXCEPTIONDEBUG}
  452. end;
  453. end;
  454. syswin32_i386_exception_handler := res;
  455. end;
  456. procedure install_exception_handlers;
  457. {$ifdef SYSTEMEXCEPTIONDEBUG}
  458. var
  459. oldexceptaddr,
  460. newexceptaddr : Longint;
  461. {$endif SYSTEMEXCEPTIONDEBUG}
  462. begin
  463. {$ifdef SYSTEMEXCEPTIONDEBUG}
  464. asm
  465. movl $0,%eax
  466. movl %fs:(%eax),%eax
  467. movl %eax,oldexceptaddr
  468. end;
  469. {$endif SYSTEMEXCEPTIONDEBUG}
  470. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  471. {$ifdef SYSTEMEXCEPTIONDEBUG}
  472. asm
  473. movl $0,%eax
  474. movl %fs:(%eax),%eax
  475. movl %eax,newexceptaddr
  476. end;
  477. if IsConsole then
  478. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  479. ' new exception ',hexstr(newexceptaddr,8));
  480. {$endif SYSTEMEXCEPTIONDEBUG}
  481. end;
  482. procedure remove_exception_handlers;
  483. begin
  484. SetUnhandledExceptionFilter(nil);
  485. end;
  486. {$else not cpui386 (Processor specific !!)}
  487. procedure install_exception_handlers;
  488. begin
  489. end;
  490. procedure remove_exception_handlers;
  491. begin
  492. end;
  493. {$endif Set_i386_Exception_handler}
  494. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  495. type
  496. tdosheader = packed record
  497. e_magic : word;
  498. e_cblp : word;
  499. e_cp : word;
  500. e_crlc : word;
  501. e_cparhdr : word;
  502. e_minalloc : word;
  503. e_maxalloc : word;
  504. e_ss : word;
  505. e_sp : word;
  506. e_csum : word;
  507. e_ip : word;
  508. e_cs : word;
  509. e_lfarlc : word;
  510. e_ovno : word;
  511. e_res : array[0..3] of word;
  512. e_oemid : word;
  513. e_oeminfo : word;
  514. e_res2 : array[0..9] of word;
  515. e_lfanew : longint;
  516. end;
  517. tpeheader = packed record
  518. PEMagic : longint;
  519. Machine : word;
  520. NumberOfSections : word;
  521. TimeDateStamp : longint;
  522. PointerToSymbolTable : longint;
  523. NumberOfSymbols : longint;
  524. SizeOfOptionalHeader : word;
  525. Characteristics : word;
  526. Magic : word;
  527. MajorLinkerVersion : byte;
  528. MinorLinkerVersion : byte;
  529. SizeOfCode : longint;
  530. SizeOfInitializedData : longint;
  531. SizeOfUninitializedData : longint;
  532. AddressOfEntryPoint : longint;
  533. BaseOfCode : longint;
  534. BaseOfData : longint;
  535. ImageBase : longint;
  536. SectionAlignment : longint;
  537. FileAlignment : longint;
  538. MajorOperatingSystemVersion : word;
  539. MinorOperatingSystemVersion : word;
  540. MajorImageVersion : word;
  541. MinorImageVersion : word;
  542. MajorSubsystemVersion : word;
  543. MinorSubsystemVersion : word;
  544. Reserved1 : longint;
  545. SizeOfImage : longint;
  546. SizeOfHeaders : longint;
  547. CheckSum : longint;
  548. Subsystem : word;
  549. DllCharacteristics : word;
  550. SizeOfStackReserve : longint;
  551. SizeOfStackCommit : longint;
  552. SizeOfHeapReserve : longint;
  553. SizeOfHeapCommit : longint;
  554. LoaderFlags : longint;
  555. NumberOfRvaAndSizes : longint;
  556. DataDirectory : array[1..$80] of byte;
  557. end;
  558. begin
  559. if (SysInstance=0) and not IsLibrary then
  560. SysInstance:=getmodulehandle(nil);
  561. if (SysInstance=0) then
  562. result:=stklen
  563. else
  564. result:=tpeheader((pointer(SysInstance)+(tdosheader(pointer(SysInstance)^).e_lfanew))^).SizeOfStackReserve;
  565. end;
  566. begin
  567. { get some helpful informations }
  568. GetStartupInfo(@startupinfo);
  569. { some misc Win32 stuff }
  570. if not IsLibrary then
  571. SysInstance:=getmodulehandle(nil);
  572. MainInstance:=SysInstance;
  573. { pass dummy value }
  574. StackLength := CheckInitialStkLen($1000000);
  575. StackBottom := StackTop - StackLength;
  576. cmdshow:=startupinfo.wshowwindow;
  577. { Setup heap and threading, these may be already initialized from TLS callback }
  578. if not Assigned(CurrentTM.BeginThread) then
  579. begin
  580. InitHeap;
  581. InitSystemThreads;
  582. end;
  583. SysInitExceptions;
  584. { setup fastmove stuff }
  585. fpc_cpucodeinit;
  586. initwidestringmanager;
  587. initunicodestringmanager;
  588. InitWin32Widestrings;
  589. SysInitStdIO;
  590. { Arguments }
  591. setup_arguments;
  592. { Reset IO Error }
  593. InOutRes:=0;
  594. ProcessID := GetCurrentProcessID;
  595. { Reset internal error variable }
  596. errno:=0;
  597. initvariantmanager;
  598. DispCallByIDProc:=@DoDispCallByIDError;
  599. end.