system.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2006 by Florian Klaempfl and Pavel Ozerski
  4. member of the Free Pascal development team.
  5. FPC Pascal system unit for the Win64 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. {$define FPC_IS_SYSTEM}
  15. { $define SYSTEMEXCEPTIONDEBUG}
  16. {$ifdef SYSTEMDEBUG}
  17. {$define SYSTEMEXCEPTIONDEBUG}
  18. {$endif SYSTEMDEBUG}
  19. {$define DISABLE_NO_THREAD_MANAGER}
  20. {$define HAS_WIDESTRINGMANAGER}
  21. {$define DISABLE_NO_DYNLIBS_MANAGER}
  22. {$define FPC_SYSTEM_HAS_SYSDLH}
  23. {$define FPC_HAS_SETCTRLBREAKHANDLER}
  24. {$if defined(FPC_USE_WIN64_SEH) or defined(CPUAARCH64)}
  25. {$define SYSTEM_USE_WIN_SEH}
  26. {$endif}
  27. {$ifdef SYSTEM_USE_WIN_SEH}
  28. {$define FPC_SYSTEM_HAS_RAISEEXCEPTION}
  29. {$define FPC_SYSTEM_HAS_RERAISE}
  30. {$define FPC_SYSTEM_HAS_CAPTUREBACKTRACE}
  31. {$endif SYSTEM_USE_WIN_SEH}
  32. { include system-independent routine headers }
  33. {$I systemh.inc}
  34. { include common windows headers }
  35. {$I syswinh.inc}
  36. var
  37. MainInstance : qword;
  38. implementation
  39. {$ifdef CPUX86_64}
  40. {$asmmode att}
  41. {$endif CPUX86_64}
  42. var
  43. {$ifdef VER3_0}
  44. SysInstance : qword;
  45. FPCSysInstance: PQWord = @SysInstance; public name '_FPC_SysInstance';
  46. {$else VER3_0}
  47. FPCSysInstance : PQWord;public name '_FPC_SysInstance';
  48. {$endif VER3_0}
  49. {$define FPC_SYSTEM_HAS_OSSETUPENTRYINFORMATION}
  50. procedure OsSetupEntryInformation(constref info: TEntryInformation); forward;
  51. {$ifdef FPC_USE_WIN64_SEH}
  52. function main_wrapper(arg: Pointer; proc: Pointer): ptrint; assembler; nostackframe;
  53. asm
  54. subq $40, %rsp
  55. .seh_stackalloc 40
  56. .seh_endprologue
  57. call %rdx { "arg" is passed in %rcx }
  58. nop { this nop is critical for exception handling }
  59. addq $40, %rsp
  60. .seh_handler __FPC_default_handler,@except,@unwind
  61. end;
  62. {$endif FPC_USE_WIN64_SEH}
  63. {$ifdef CPUAARCH64)}
  64. function main_wrapper(arg: Pointer; proc: Pointer): ptrint; assembler; nostackframe;
  65. asm
  66. stp fp,lr,[sp, #-16]!
  67. .seh_savefplr_x -16
  68. .seh_endprologue
  69. blr x1 { "arg" is passed in x0 }
  70. nop { this nop is critical for exception handling }
  71. ldp fp,lr,[sp], #16
  72. .seh_handler __FPC_default_handler,@except,@unwind
  73. end;
  74. {$endif}
  75. {$if defined(CPUX86_64)}
  76. {$define FPC_SYSTEM_HAS_STACKTOP}
  77. function StackTop: pointer; assembler;nostackframe;
  78. asm
  79. movq %gs:(8),%rax
  80. end;
  81. {$endif}
  82. { include system independent routines }
  83. {$I system.inc}
  84. {*****************************************************************************
  85. System Dependent Exit code
  86. *****************************************************************************}
  87. {$ifndef SYSTEM_USE_WIN_SEH}
  88. procedure install_exception_handlers;forward;
  89. {$endif SYSTEM_USE_WIN_SEH}
  90. {$ifdef VER3_0}
  91. procedure PascalMain;external name 'PASCALMAIN';
  92. {$endif VER3_0}
  93. { include code common with win32 }
  94. {$I syswin.inc}
  95. {$ifdef VER3_0}
  96. { TLS directory code }
  97. {$I systlsdir.inc}
  98. {$endif VER3_0}
  99. procedure OsSetupEntryInformation(constref info: TEntryInformation);
  100. begin
  101. TlsKey := info.OS.TlsKeyAddr;
  102. FPCSysInstance := info.OS.SysInstance;
  103. WStrInitTablesTable := info.OS.WideInitTables;
  104. end;
  105. Procedure system_exit;
  106. begin
  107. { see comments in win32/system.pp about this logic }
  108. if IsLibrary then
  109. begin
  110. if DllInitState in [DLL_PROCESS_ATTACH,DLL_PROCESS_DETACH] then
  111. LongJmp(DLLBuf,1)
  112. else
  113. MainThreadIDWin32:=0;
  114. end;
  115. if not IsConsole then
  116. begin
  117. Close(stderr);
  118. Close(stdout);
  119. Close(erroutput);
  120. Close(Input);
  121. Close(Output);
  122. { what about Input and Output ?? PM }
  123. { now handled, FPK }
  124. end;
  125. { call exitprocess, with cleanup as required }
  126. ExitProcess(exitcode);
  127. end;
  128. var
  129. { old compilers emitted a reference to _fltused if a module contains
  130. floating type code so the linker could leave away floating point
  131. libraries or not. VC does this as well so we need to define this
  132. symbol as well (FK)
  133. }
  134. _fltused : int64;cvar;public;
  135. { value of the stack segment
  136. to check if the call stack can be written on exceptions }
  137. _SS : Cardinal;
  138. {$ifdef VER3_0}
  139. procedure Exe_entry;[public,alias:'_FPC_EXE_Entry'];
  140. {$else VER3_0}
  141. procedure Exe_entry(constref info: TEntryInformation);[public,alias:'_FPC_EXE_Entry'];
  142. {$endif VER3_0}
  143. begin
  144. {$ifndef VER3_0}
  145. SetupEntryInformation(info);
  146. {$endif VER3_0}
  147. IsLibrary:=false;
  148. { install the handlers for exe only ?
  149. or should we install them for DLL also ? (PM) }
  150. {$ifndef SYSTEM_USE_WIN_SEH}
  151. install_exception_handlers;
  152. {$endif SYSTEM_USE_WIN_SEH}
  153. ExitCode:=0;
  154. {$if defined(CPUX86_64)}
  155. asm
  156. xorq %rax,%rax
  157. movw %ss,%ax
  158. movl %eax,_SS(%rip)
  159. movq %rbp,%rsi
  160. xorq %rbp,%rbp
  161. {$ifdef VER3_0}
  162. {$ifdef FPC_USE_WIN64_SEH}
  163. xor %rcx,%rcx
  164. lea PASCALMAIN(%rip),%rdx
  165. call main_wrapper
  166. {$else FPC_USE_WIN64_SEH}
  167. call PASCALMAIN
  168. {$endif FPC_USE_WIN64_SEH}
  169. {$else VER3_0}
  170. {$ifdef FPC_USE_WIN64_SEH}
  171. xor %rcx,%rcx
  172. lea EntryInformation(%rip),%rdx
  173. movq TEntryInformation.PascalMain(%rdx),%rdx
  174. call main_wrapper
  175. {$else FPC_USE_WIN64_SEH}
  176. lea EntryInformation(%rip),%rdx
  177. call TEntryInformation.PascalMain(%rdx)
  178. {$endif FPC_USE_WIN64_SEH}
  179. {$endif VER3_0}
  180. movq %rsi,%rbp
  181. end ['RSI','RBP']; { <-- specifying RSI allows compiler to save/restore it properly }
  182. {$elseif defined(CPUAARCH64)}
  183. asm
  184. mov x0,#0
  185. adrp x1,EntryInformation@PAGE
  186. add x1,x1,EntryInformation@PAGEOFF
  187. ldr x1,[x1,TEntryInformation.PascalMain]
  188. adrp x8,main_wrapper@PAGE
  189. add x8,x8,main_wrapper@PAGEOFF
  190. blr x8
  191. end ['X8'];
  192. {$else}
  193. info.PascalMain();
  194. {$endif}
  195. { if we pass here there was no error ! }
  196. system_exit;
  197. end;
  198. {$ifdef VER3_0}
  199. procedure _FPC_DLLMainCRTStartup(_hinstance : qword;_dllreason : dword;_dllparam:Pointer);stdcall;public name '_DLLMainCRTStartup';
  200. begin
  201. IsConsole:=true;
  202. sysinstance:=_hinstance;
  203. dllreason:=_dllreason;
  204. dllparam:=PtrInt(_dllparam);
  205. DLL_Entry;
  206. end;
  207. procedure _FPC_DLLWinMainCRTStartup(_hinstance : qword;_dllreason : dword;_dllparam:Pointer);stdcall;public name '_DLLWinMainCRTStartup';
  208. begin
  209. IsConsole:=false;
  210. sysinstance:=_hinstance;
  211. dllreason:=_dllreason;
  212. dllparam:=PtrInt(_dllparam);
  213. DLL_Entry;
  214. end;
  215. {$endif VER3_0}
  216. {$ifdef CPUX86_64}
  217. function is_prefetch(p : pointer) : boolean;
  218. var
  219. a : array[0..15] of byte;
  220. doagain : boolean;
  221. instrlo,instrhi,opcode : byte;
  222. i : longint;
  223. begin
  224. result:=false;
  225. { read memory savely without causing another exeception }
  226. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  227. exit;
  228. i:=0;
  229. doagain:=true;
  230. while doagain and (i<15) do
  231. begin
  232. opcode:=a[i];
  233. instrlo:=opcode and $f;
  234. instrhi:=opcode and $f0;
  235. case instrhi of
  236. { prefix? }
  237. $20,$30:
  238. doagain:=(instrlo and 7)=6;
  239. $60:
  240. doagain:=(instrlo and $c)=4;
  241. $f0:
  242. doagain:=instrlo in [0,2,3];
  243. $0:
  244. begin
  245. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  246. exit;
  247. end;
  248. else
  249. doagain:=false;
  250. end;
  251. inc(i);
  252. end;
  253. end;
  254. {$endif}
  255. //
  256. // Hardware exception handling
  257. //
  258. {$I seh64.inc}
  259. type
  260. TVectoredExceptionHandler = function (excep : PExceptionPointers) : Longint;
  261. function AddVectoredExceptionHandler(FirstHandler : DWORD;VectoredHandler : TVectoredExceptionHandler) : longint;
  262. external 'kernel32' name 'AddVectoredExceptionHandler';
  263. {$ifndef SYSTEM_USE_WIN_SEH}
  264. const
  265. MaxExceptionLevel = 16;
  266. exceptLevel : Byte = 0;
  267. var
  268. exceptRip : array[0..MaxExceptionLevel-1] of Int64;
  269. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  270. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  271. {$ifdef SYSTEMEXCEPTIONDEBUG}
  272. procedure DebugHandleErrorAddrFrame(error : longint; addr, frame : pointer);
  273. begin
  274. if IsConsole then
  275. begin
  276. write(stderr,'HandleErrorAddrFrame(error=',error);
  277. write(stderr,',addr=',hexstr(int64(addr),16));
  278. writeln(stderr,',frame=',hexstr(int64(frame),16),')');
  279. end;
  280. HandleErrorAddrFrame(error,addr,frame);
  281. end;
  282. {$endif SYSTEMEXCEPTIONDEBUG}
  283. procedure JumpToHandleErrorFrame;
  284. var
  285. rip, rbp : int64;
  286. error : longint;
  287. begin
  288. // save ebp
  289. {$ifdef CPUX86_64}
  290. asm
  291. movq (%rbp),%rax
  292. movq %rax,rbp
  293. end;
  294. {$endif}
  295. if exceptLevel>0 then
  296. dec(exceptLevel);
  297. rip:=exceptRip[exceptLevel];
  298. error:=exceptError[exceptLevel];
  299. {$ifdef SYSTEMEXCEPTIONDEBUG}
  300. if IsConsole then
  301. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  302. {$endif SYSTEMEXCEPTIONDEBUG}
  303. if resetFPU[exceptLevel] then
  304. SysResetFPU;
  305. { build a fake stack }
  306. {$ifdef CPUX86_64}
  307. asm
  308. movq rbp,%r8
  309. movq rip,%rdx
  310. movl error,%ecx
  311. pushq rip
  312. movq rbp,%rbp // Change frame pointer
  313. {$ifdef SYSTEMEXCEPTIONDEBUG}
  314. jmpl DebugHandleErrorAddrFrame
  315. {$else not SYSTEMEXCEPTIONDEBUG}
  316. jmpl HandleErrorAddrFrame
  317. {$endif SYSTEMEXCEPTIONDEBUG}
  318. end;
  319. {$endif}
  320. end;
  321. function syswin64_x86_64_exception_handler(excep : PExceptionPointers) : Longint;public;
  322. var
  323. res: longint;
  324. err: byte;
  325. must_reset_fpu: boolean;
  326. begin
  327. res:=EXCEPTION_CONTINUE_SEARCH;
  328. {$ifdef SYSTEMEXCEPTIONDEBUG}
  329. if IsConsole then
  330. Writeln(stderr,'syswin64_x86_64_exception_handler called');
  331. {$endif SYSTEMEXCEPTIONDEBUG}
  332. if excep^.ContextRecord^.SegSs=_SS then
  333. begin
  334. err := 0;
  335. must_reset_fpu := true;
  336. {$ifdef SYSTEMEXCEPTIONDEBUG}
  337. if IsConsole then Writeln(stderr,'Exception ',
  338. hexstr(excep^.ExceptionRecord^.ExceptionCode,8));
  339. {$endif SYSTEMEXCEPTIONDEBUG}
  340. case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
  341. STATUS_INTEGER_DIVIDE_BY_ZERO,
  342. STATUS_FLOAT_DIVIDE_BY_ZERO :
  343. err := 208;
  344. STATUS_ARRAY_BOUNDS_EXCEEDED :
  345. begin
  346. err := 201;
  347. must_reset_fpu := false;
  348. end;
  349. STATUS_STACK_OVERFLOW :
  350. begin
  351. err := 202;
  352. must_reset_fpu := false;
  353. end;
  354. STATUS_FLOAT_OVERFLOW :
  355. err := 205;
  356. STATUS_FLOAT_DENORMAL_OPERAND,
  357. STATUS_FLOAT_UNDERFLOW :
  358. err := 206;
  359. { excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  360. STATUS_FLOAT_INEXACT_RESULT,
  361. STATUS_FLOAT_INVALID_OPERATION,
  362. STATUS_FLOAT_STACK_CHECK :
  363. err := 207;
  364. STATUS_INTEGER_OVERFLOW :
  365. begin
  366. err := 215;
  367. must_reset_fpu := false;
  368. end;
  369. STATUS_ILLEGAL_INSTRUCTION:
  370. err := 216;
  371. STATUS_ACCESS_VIOLATION:
  372. { Athlon prefetch bug? }
  373. if is_prefetch(pointer(excep^.ContextRecord^.rip)) then
  374. begin
  375. { if yes, then retry }
  376. excep^.ExceptionRecord^.ExceptionCode := 0;
  377. res:=EXCEPTION_CONTINUE_EXECUTION;
  378. end
  379. else
  380. err := 216;
  381. STATUS_CONTROL_C_EXIT:
  382. err := 217;
  383. STATUS_PRIVILEGED_INSTRUCTION:
  384. begin
  385. err := 218;
  386. must_reset_fpu := false;
  387. end;
  388. else
  389. begin
  390. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  391. err := 217
  392. else
  393. { pass through exceptions which aren't an error. The problem is that vectored handlers
  394. always are called before structured ones so we see also internal exceptions of libraries.
  395. I wonder if there is a better solution (FK)
  396. }
  397. res:=EXCEPTION_CONTINUE_SEARCH;
  398. end;
  399. end;
  400. if (err <> 0) and (exceptLevel < MaxExceptionLevel) then
  401. begin
  402. exceptRip[exceptLevel] := excep^.ContextRecord^.Rip;
  403. exceptError[exceptLevel] := err;
  404. resetFPU[exceptLevel] := must_reset_fpu;
  405. inc(exceptLevel);
  406. excep^.ContextRecord^.Rip := Int64(@JumpToHandleErrorFrame);
  407. excep^.ExceptionRecord^.ExceptionCode := 0;
  408. res := EXCEPTION_CONTINUE_EXECUTION;
  409. {$ifdef SYSTEMEXCEPTIONDEBUG}
  410. if IsConsole then begin
  411. writeln(stderr,'Exception Continue Exception set at ',
  412. hexstr(exceptRip[exceptLevel-1],16));
  413. writeln(stderr,'Rip changed to ',
  414. hexstr(int64(@JumpToHandleErrorFrame),16), ' error=', err);
  415. end;
  416. {$endif SYSTEMEXCEPTIONDEBUG}
  417. end;
  418. end;
  419. syswin64_x86_64_exception_handler := res;
  420. end;
  421. procedure install_exception_handlers;
  422. begin
  423. AddVectoredExceptionHandler(1,@syswin64_x86_64_exception_handler);
  424. end;
  425. {$endif ndef SYSTEM_USE_WIN_SEH}
  426. {$ifdef VER3_0}
  427. procedure LinkIn(p1,p2,p3: Pointer); inline;
  428. begin
  429. end;
  430. procedure _FPC_mainCRTStartup;stdcall;public name '_mainCRTStartup';
  431. begin
  432. IsConsole:=true;
  433. GetConsoleMode(GetStdHandle((Std_Input_Handle)),@StartupConsoleMode);
  434. {$ifdef FPC_USE_TLS_DIRECTORY}
  435. LinkIn(@_tls_used,@FreePascal_TLS_callback,@FreePascal_end_of_TLS_callback);
  436. {$endif FPC_USE_TLS_DIRECTORY}
  437. Exe_entry;
  438. end;
  439. procedure _FPC_WinMainCRTStartup;stdcall;public name '_WinMainCRTStartup';
  440. begin
  441. IsConsole:=false;
  442. {$ifdef FPC_USE_TLS_DIRECTORY}
  443. LinkIn(@_tls_used,@FreePascal_TLS_callback,@FreePascal_end_of_TLS_callback);
  444. {$endif FPC_USE_TLS_DIRECTORY}
  445. Exe_entry;
  446. end;
  447. {$endif VER3_0}
  448. {$ifdef FPC_SECTION_THREADVARS}
  449. function fpc_tls_add(addr: pointer): pointer; assembler; nostackframe;
  450. [public,alias: 'FPC_TLS_ADD']; compilerproc;
  451. asm
  452. sub $56,%rsp { 32 spill area + 16 local vars + 8 misalignment }
  453. .seh_stackalloc 56
  454. .seh_endprologue
  455. lea tls_data_start(%rip),%rax
  456. sub %rax,%rcx
  457. cmpb $0,IsLibrary(%rip)
  458. mov _tls_index(%rip),%eax
  459. jnz .L1
  460. mov %gs:(88),%rdx
  461. add (%rdx,%rax,8),%rcx
  462. mov %rcx,%rax
  463. jmp .L3
  464. .L1:
  465. mov %rcx,32(%rsp)
  466. call GetLastError
  467. mov %rax,40(%rsp) { save LastError }
  468. mov _tls_index(%rip),%ecx
  469. call TlsGetValue
  470. test %rax,%rax
  471. jnz .L2
  472. { This can happen when a thread existed before DLL was loaded,
  473. or if DisableThreadLibraryCalls was called. }
  474. call SysAllocateThreadVars
  475. mov $0x1000000,%rcx
  476. call InitThread
  477. mov _tls_index(%rip),%ecx
  478. call TlsGetValue
  479. .L2:
  480. add %rax,32(%rsp)
  481. mov 40(%rsp),%rcx
  482. call SetLastError
  483. mov 32(%rsp),%rax
  484. .L3:
  485. add $56,%rsp
  486. end;
  487. {$endif FPC_SECTION_THREADVARS}
  488. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  489. type
  490. tdosheader = packed record
  491. e_magic : word;
  492. e_cblp : word;
  493. e_cp : word;
  494. e_crlc : word;
  495. e_cparhdr : word;
  496. e_minalloc : word;
  497. e_maxalloc : word;
  498. e_ss : word;
  499. e_sp : word;
  500. e_csum : word;
  501. e_ip : word;
  502. e_cs : word;
  503. e_lfarlc : word;
  504. e_ovno : word;
  505. e_res : array[0..3] of word;
  506. e_oemid : word;
  507. e_oeminfo : word;
  508. e_res2 : array[0..9] of word;
  509. e_lfanew : longint;
  510. end;
  511. tpeheader = packed record
  512. PEMagic : longint;
  513. Machine : word;
  514. NumberOfSections : word;
  515. TimeDateStamp : longint;
  516. PointerToSymbolTable : longint;
  517. NumberOfSymbols : longint;
  518. SizeOfOptionalHeader : word;
  519. Characteristics : word;
  520. Magic : word;
  521. MajorLinkerVersion : byte;
  522. MinorLinkerVersion : byte;
  523. SizeOfCode : longint;
  524. SizeOfInitializedData : longint;
  525. SizeOfUninitializedData : longint;
  526. AddressOfEntryPoint : longint;
  527. BaseOfCode : longint;
  528. {$ifdef win32}
  529. BaseOfData : longint;
  530. {$endif win32}
  531. ImageBase : PtrInt;
  532. SectionAlignment : longint;
  533. FileAlignment : longint;
  534. MajorOperatingSystemVersion : word;
  535. MinorOperatingSystemVersion : word;
  536. MajorImageVersion : word;
  537. MinorImageVersion : word;
  538. MajorSubsystemVersion : word;
  539. MinorSubsystemVersion : word;
  540. Reserved1 : longint;
  541. SizeOfImage : longint;
  542. SizeOfHeaders : longint;
  543. CheckSum : longint;
  544. Subsystem : word;
  545. DllCharacteristics : word;
  546. SizeOfStackReserve : PtrInt;
  547. SizeOfStackCommit : PtrInt;
  548. SizeOfHeapReserve : PtrInt;
  549. SizeOfHeapCommit : PtrInt;
  550. LoaderFlags : longint;
  551. NumberOfRvaAndSizes : longint;
  552. DataDirectory : array[1..$80] of byte;
  553. end;
  554. begin
  555. result:=tpeheader((pointer(getmodulehandle(nil))+(tdosheader(pointer(getmodulehandle(nil))^).e_lfanew))^).SizeOfStackReserve;
  556. end;
  557. initialization
  558. { pass dummy value }
  559. StackLength := CheckInitialStkLen($1000000);
  560. StackBottom := StackTop - StackLength;
  561. { get some helpful informations }
  562. GetStartupInfo(@startupinfo);
  563. { some misc Win32 stuff }
  564. if not IsLibrary then
  565. FPCSysInstance^:=getmodulehandle(nil);
  566. MainInstance:=FPCSysInstance^;
  567. cmdshow:=startupinfo.wshowwindow;
  568. { Setup heap and threading, these may be already initialized from TLS callback }
  569. if not Assigned(CurrentTM.BeginThread) then
  570. begin
  571. InitHeap;
  572. InitSystemThreads;
  573. end;
  574. SysInitExceptions;
  575. initunicodestringmanager;
  576. InitWin32Widestrings;
  577. SysInitStdIO;
  578. { Arguments }
  579. setup_arguments;
  580. InitSystemDynLibs;
  581. { Reset IO Error }
  582. InOutRes:=0;
  583. ProcessID := GetCurrentProcessID;
  584. DispCallByIDProc:=@DoDispCallByIDError;
  585. finalization
  586. WinFinalizeSystem;
  587. end.