system.pp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  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. hprevinst,
  83. MainInstance,
  84. cmdshow : longint;
  85. DLLreason : dword; public name 'operatingsystem_dllreason';
  86. DLLparam : PtrInt; public name 'operatingsystem_dllparam';
  87. StartupConsoleMode : DWORD;
  88. type
  89. TDLL_Entry_Hook = procedure (dllparam : PtrInt);
  90. const
  91. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  92. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  93. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  94. Const
  95. { it can be discussed whether fmShareDenyNone means read and write or read, write and delete, see
  96. also http://bugs.freepascal.org/view.php?id=8898, this allows users to configure the used
  97. value
  98. }
  99. fmShareDenyNoneFlags : DWord = 3;
  100. implementation
  101. var
  102. EntryInformation : TEntryInformation;
  103. SysInstance : Longint;public name '_FPC_SysInstance';
  104. { used by wstrings.inc because wstrings.inc is included before sysos.inc
  105. this is put here (FK) }
  106. function SysAllocStringLen(psz:pointer;len:dword):pointer;stdcall;
  107. external 'oleaut32.dll' name 'SysAllocStringLen';
  108. procedure SysFreeString(bstr:pointer);stdcall;
  109. external 'oleaut32.dll' name 'SysFreeString';
  110. function SysReAllocStringLen(var bstr:pointer;psz: pointer;
  111. len:dword): Integer; stdcall;external 'oleaut32.dll' name 'SysReAllocStringLen';
  112. { include system independent routines }
  113. {$I system.inc}
  114. {*****************************************************************************
  115. Parameter Handling
  116. *****************************************************************************}
  117. procedure setup_arguments;
  118. var
  119. arglen,
  120. count : longint;
  121. argstart,
  122. pc,arg : pchar;
  123. quote : Boolean;
  124. argvlen : longint;
  125. buf: array[0..259] of char; // need MAX_PATH bytes, not 256!
  126. procedure allocarg(idx,len:longint);
  127. var
  128. oldargvlen : longint;
  129. begin
  130. if idx>=argvlen then
  131. begin
  132. oldargvlen:=argvlen;
  133. argvlen:=(idx+8) and (not 7);
  134. sysreallocmem(argv,argvlen*sizeof(pointer));
  135. fillchar(argv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
  136. end;
  137. { use realloc to reuse already existing memory }
  138. { always allocate, even if length is zero, since }
  139. { the arg. is still present! }
  140. sysreallocmem(argv[idx],len+1);
  141. end;
  142. begin
  143. { create commandline, it starts with the executed filename which is argv[0] }
  144. { Win32 passes the command NOT via the args, but via getmodulefilename}
  145. count:=0;
  146. argv:=nil;
  147. argvlen:=0;
  148. ArgLen := GetModuleFileName(0, @buf[0], sizeof(buf));
  149. buf[ArgLen] := #0; // be safe
  150. allocarg(0,arglen);
  151. move(buf,argv[0]^,arglen+1);
  152. { Setup cmdline variable }
  153. cmdline:=GetCommandLine;
  154. { process arguments }
  155. pc:=cmdline;
  156. {$IfDef SYSTEM_DEBUG_STARTUP}
  157. Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
  158. {$EndIf }
  159. while pc^<>#0 do
  160. begin
  161. { skip leading spaces }
  162. while pc^ in [#1..#32] do
  163. inc(pc);
  164. if pc^=#0 then
  165. break;
  166. { calc argument length }
  167. quote:=False;
  168. argstart:=pc;
  169. arglen:=0;
  170. while (pc^<>#0) do
  171. begin
  172. case pc^ of
  173. #1..#32 :
  174. begin
  175. if quote then
  176. inc(arglen)
  177. else
  178. break;
  179. end;
  180. '"' :
  181. if pc[1]<>'"' then
  182. quote := not quote
  183. else
  184. inc(pc);
  185. else
  186. inc(arglen);
  187. end;
  188. inc(pc);
  189. end;
  190. { copy argument }
  191. { Don't copy the first one, it is already there.}
  192. If Count<>0 then
  193. begin
  194. allocarg(count,arglen);
  195. quote:=False;
  196. pc:=argstart;
  197. arg:=argv[count];
  198. while (pc^<>#0) do
  199. begin
  200. case pc^ of
  201. #1..#32 :
  202. begin
  203. if quote then
  204. begin
  205. arg^:=pc^;
  206. inc(arg);
  207. end
  208. else
  209. break;
  210. end;
  211. '"' :
  212. if pc[1]<>'"' then
  213. quote := not quote
  214. else
  215. inc(pc);
  216. else
  217. begin
  218. arg^:=pc^;
  219. inc(arg);
  220. end;
  221. end;
  222. inc(pc);
  223. end;
  224. arg^:=#0;
  225. end;
  226. {$IfDef SYSTEM_DEBUG_STARTUP}
  227. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  228. {$EndIf SYSTEM_DEBUG_STARTUP}
  229. inc(count);
  230. end;
  231. { get argc }
  232. argc:=count;
  233. { free unused memory, leaving a nil entry at the end }
  234. sysreallocmem(argv,(count+1)*sizeof(pointer));
  235. argv[count] := nil;
  236. end;
  237. function paramcount : longint;
  238. begin
  239. paramcount := argc - 1;
  240. end;
  241. function paramstr(l : longint) : string;
  242. begin
  243. if (l>=0) and (l<argc) then
  244. paramstr:=strpas(argv[l])
  245. else
  246. paramstr:='';
  247. end;
  248. procedure randomize;
  249. begin
  250. randseed:=GetTickCount;
  251. end;
  252. {*****************************************************************************
  253. System Dependent Exit code
  254. *****************************************************************************}
  255. procedure install_exception_handlers;forward;
  256. procedure remove_exception_handlers;forward;
  257. procedure fpc_do_exit;stdcall;external name 'FPC_DO_EXIT';
  258. Procedure ExitDLL(Exitcode : longint); forward;
  259. procedure asm_exit;stdcall;external name 'asm_exit';
  260. Procedure system_exit;
  261. begin
  262. { don't call ExitProcess inside
  263. the DLL exit code !!
  264. This crashes Win95 at least PM }
  265. if IsLibrary then
  266. ExitDLL(ExitCode);
  267. if not IsConsole then
  268. begin
  269. Close(stderr);
  270. Close(stdout);
  271. Close(erroutput);
  272. Close(Input);
  273. Close(Output);
  274. { what about Input and Output ?? PM }
  275. { now handled, FPK }
  276. end;
  277. remove_exception_handlers;
  278. { do cleanup required by the startup code }
  279. EntryInformation.asm_exit();
  280. { call exitprocess, with cleanup as required }
  281. ExitProcess(exitcode);
  282. end;
  283. var
  284. { value of the stack segment
  285. to check if the call stack can be written on exceptions }
  286. _SS : Cardinal;
  287. procedure Exe_entry(const info : TEntryInformation);[public,alias:'_FPC_EXE_Entry'];
  288. var
  289. ST : pointer;
  290. begin
  291. EntryInformation:=info;
  292. IsLibrary:=false;
  293. { install the handlers for exe only ?
  294. or should we install them for DLL also ? (PM) }
  295. install_exception_handlers;
  296. { This strange construction is needed to solve the _SS problem
  297. with a smartlinked syswin32 (PFV) }
  298. asm
  299. { allocate space for an exception frame }
  300. pushl $0
  301. pushl %fs:(0)
  302. { movl %esp,%fs:(0)
  303. but don't insert it as it doesn't
  304. point to anything yet
  305. this will be used in signals unit }
  306. movl %esp,%eax
  307. movl %eax,System_exception_frame
  308. pushl %ebp
  309. movl %esp,%eax
  310. movl %eax,st
  311. end;
  312. StackTop:=st;
  313. asm
  314. xorl %eax,%eax
  315. movw %ss,%ax
  316. movl %eax,_SS
  317. xorl %ebp,%ebp
  318. end;
  319. EntryInformation.PascalMain();
  320. asm
  321. popl %ebp
  322. end;
  323. { if we pass here there was no error ! }
  324. system_exit;
  325. end;
  326. function GetCurrentProcess : dword;
  327. stdcall;external 'kernel32' name 'GetCurrentProcess';
  328. function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
  329. stdcall;external 'kernel32' name 'ReadProcessMemory';
  330. function is_prefetch(p : pointer) : boolean;
  331. var
  332. a : array[0..15] of byte;
  333. doagain : boolean;
  334. instrlo,instrhi,opcode : byte;
  335. i : longint;
  336. begin
  337. result:=false;
  338. { read memory savely without causing another exeception }
  339. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  340. exit;
  341. i:=0;
  342. doagain:=true;
  343. while doagain and (i<15) do
  344. begin
  345. opcode:=a[i];
  346. instrlo:=opcode and $f;
  347. instrhi:=opcode and $f0;
  348. case instrhi of
  349. { prefix? }
  350. $20,$30:
  351. doagain:=(instrlo and 7)=6;
  352. $60:
  353. doagain:=(instrlo and $c)=4;
  354. $f0:
  355. doagain:=instrlo in [0,2,3];
  356. $0:
  357. begin
  358. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  359. exit;
  360. end;
  361. else
  362. doagain:=false;
  363. end;
  364. inc(i);
  365. end;
  366. end;
  367. {******************************************************************************}
  368. { include code common with win64 }
  369. {$I syswin.inc}
  370. {******************************************************************************}
  371. //
  372. // Hardware exception handling
  373. //
  374. {$ifdef Set_i386_Exception_handler}
  375. type
  376. PFloatingSaveArea = ^TFloatingSaveArea;
  377. TFloatingSaveArea = packed record
  378. ControlWord : Cardinal;
  379. StatusWord : Cardinal;
  380. TagWord : Cardinal;
  381. ErrorOffset : Cardinal;
  382. ErrorSelector : Cardinal;
  383. DataOffset : Cardinal;
  384. DataSelector : Cardinal;
  385. RegisterArea : array[0..79] of Byte;
  386. Cr0NpxState : Cardinal;
  387. end;
  388. PContext = ^TContext;
  389. TContext = packed record
  390. //
  391. // The flags values within this flag control the contents of
  392. // a CONTEXT record.
  393. //
  394. ContextFlags : Cardinal;
  395. //
  396. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  397. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  398. // included in CONTEXT_FULL.
  399. //
  400. Dr0, Dr1, Dr2,
  401. Dr3, Dr6, Dr7 : Cardinal;
  402. //
  403. // This section is specified/returned if the
  404. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  405. //
  406. FloatSave : TFloatingSaveArea;
  407. //
  408. // This section is specified/returned if the
  409. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  410. //
  411. SegGs, SegFs,
  412. SegEs, SegDs : Cardinal;
  413. //
  414. // This section is specified/returned if the
  415. // ContextFlags word contains the flag CONTEXT_INTEGER.
  416. //
  417. Edi, Esi, Ebx,
  418. Edx, Ecx, Eax : Cardinal;
  419. //
  420. // This section is specified/returned if the
  421. // ContextFlags word contains the flag CONTEXT_CONTROL.
  422. //
  423. Ebp : Cardinal;
  424. Eip : Cardinal;
  425. SegCs : Cardinal;
  426. EFlags, Esp, SegSs : Cardinal;
  427. //
  428. // This section is specified/returned if the ContextFlags word
  429. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  430. // The format and contexts are processor specific
  431. //
  432. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  433. end;
  434. type
  435. PExceptionRecord = ^TExceptionRecord;
  436. TExceptionRecord = packed record
  437. ExceptionCode : cardinal;
  438. ExceptionFlags : Longint;
  439. ExceptionRecord : PExceptionRecord;
  440. ExceptionAddress : Pointer;
  441. NumberParameters : Longint;
  442. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  443. end;
  444. PExceptionPointers = ^TExceptionPointers;
  445. TExceptionPointers = packed record
  446. ExceptionRecord : PExceptionRecord;
  447. ContextRecord : PContext;
  448. end;
  449. { type of functions that should be used for exception handling }
  450. TTopLevelExceptionFilter = function (excep : PExceptionPointers) : Longint;stdcall;
  451. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : TTopLevelExceptionFilter) : TTopLevelExceptionFilter;
  452. stdcall;external 'kernel32' name 'SetUnhandledExceptionFilter';
  453. const
  454. MaxExceptionLevel = 16;
  455. exceptLevel : Byte = 0;
  456. var
  457. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  458. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  459. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  460. {$ifdef SYSTEMEXCEPTIONDEBUG}
  461. procedure DebugHandleErrorAddrFrame(error : longint; addr, frame : pointer);
  462. begin
  463. if IsConsole then
  464. begin
  465. write(stderr,'HandleErrorAddrFrame(error=',error);
  466. write(stderr,',addr=',hexstr(ptruint(addr),8));
  467. writeln(stderr,',frame=',hexstr(ptruint(frame),8),')');
  468. end;
  469. HandleErrorAddrFrame(error,addr,frame);
  470. end;
  471. {$endif SYSTEMEXCEPTIONDEBUG}
  472. procedure JumpToHandleErrorFrame;
  473. var
  474. eip, ebp, error : Longint;
  475. begin
  476. // save ebp
  477. asm
  478. movl (%ebp),%eax
  479. movl %eax,ebp
  480. end;
  481. if (exceptLevel > 0) then
  482. dec(exceptLevel);
  483. eip:=exceptEip[exceptLevel];
  484. error:=exceptError[exceptLevel];
  485. {$ifdef SYSTEMEXCEPTIONDEBUG}
  486. if IsConsole then
  487. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  488. {$endif SYSTEMEXCEPTIONDEBUG}
  489. if resetFPU[exceptLevel] then
  490. SysResetFPU;
  491. { build a fake stack }
  492. asm
  493. movl ebp,%ecx
  494. movl eip,%edx
  495. movl error,%eax
  496. pushl eip
  497. movl ebp,%ebp // Change frame pointer
  498. {$ifdef SYSTEMEXCEPTIONDEBUG}
  499. jmpl DebugHandleErrorAddrFrame
  500. {$else not SYSTEMEXCEPTIONDEBUG}
  501. jmpl HandleErrorAddrFrame
  502. {$endif SYSTEMEXCEPTIONDEBUG}
  503. end;
  504. end;
  505. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  506. var
  507. res: longint;
  508. err: byte;
  509. must_reset_fpu: boolean;
  510. begin
  511. res := EXCEPTION_CONTINUE_SEARCH;
  512. if excep^.ContextRecord^.SegSs=_SS then begin
  513. err := 0;
  514. must_reset_fpu := true;
  515. {$ifdef SYSTEMEXCEPTIONDEBUG}
  516. if IsConsole then Writeln(stderr,'Exception ',
  517. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  518. {$endif SYSTEMEXCEPTIONDEBUG}
  519. case excep^.ExceptionRecord^.ExceptionCode of
  520. STATUS_INTEGER_DIVIDE_BY_ZERO,
  521. STATUS_FLOAT_DIVIDE_BY_ZERO :
  522. err := 200;
  523. STATUS_ARRAY_BOUNDS_EXCEEDED :
  524. begin
  525. err := 201;
  526. must_reset_fpu := false;
  527. end;
  528. STATUS_STACK_OVERFLOW :
  529. begin
  530. err := 202;
  531. must_reset_fpu := false;
  532. end;
  533. STATUS_FLOAT_OVERFLOW :
  534. err := 205;
  535. STATUS_FLOAT_DENORMAL_OPERAND,
  536. STATUS_FLOAT_UNDERFLOW :
  537. err := 206;
  538. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  539. STATUS_FLOAT_INEXACT_RESULT,
  540. STATUS_FLOAT_INVALID_OPERATION,
  541. STATUS_FLOAT_STACK_CHECK :
  542. err := 207;
  543. STATUS_INTEGER_OVERFLOW :
  544. begin
  545. err := 215;
  546. must_reset_fpu := false;
  547. end;
  548. STATUS_ILLEGAL_INSTRUCTION:
  549. { if we're testing sse support, simply set the flag and continue }
  550. if sse_check then
  551. begin
  552. os_supports_sse:=false;
  553. { skip the offending movaps %xmm7, %xmm6 instruction }
  554. inc(excep^.ContextRecord^.Eip,3);
  555. excep^.ExceptionRecord^.ExceptionCode := 0;
  556. res:=EXCEPTION_CONTINUE_EXECUTION;
  557. end
  558. else
  559. err := 216;
  560. STATUS_ACCESS_VIOLATION:
  561. { Athlon prefetch bug? }
  562. if is_prefetch(pointer(excep^.ContextRecord^.Eip)) then
  563. begin
  564. { if yes, then retry }
  565. excep^.ExceptionRecord^.ExceptionCode := 0;
  566. res:=EXCEPTION_CONTINUE_EXECUTION;
  567. end
  568. else
  569. err := 216;
  570. STATUS_CONTROL_C_EXIT:
  571. err := 217;
  572. STATUS_PRIVILEGED_INSTRUCTION:
  573. begin
  574. err := 218;
  575. must_reset_fpu := false;
  576. end;
  577. else
  578. begin
  579. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  580. err := 217
  581. else
  582. err := 255;
  583. end;
  584. end;
  585. if (err <> 0) and (exceptLevel < MaxExceptionLevel) then begin
  586. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  587. exceptError[exceptLevel] := err;
  588. resetFPU[exceptLevel] := must_reset_fpu;
  589. inc(exceptLevel);
  590. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  591. excep^.ExceptionRecord^.ExceptionCode := 0;
  592. res := EXCEPTION_CONTINUE_EXECUTION;
  593. {$ifdef SYSTEMEXCEPTIONDEBUG}
  594. if IsConsole then begin
  595. writeln(stderr,'Exception Continue Exception set at ',
  596. hexstr(exceptEip[exceptLevel],8));
  597. writeln(stderr,'Eip changed to ',
  598. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', err);
  599. end;
  600. {$endif SYSTEMEXCEPTIONDEBUG}
  601. end;
  602. end;
  603. syswin32_i386_exception_handler := res;
  604. end;
  605. procedure install_exception_handlers;
  606. {$ifdef SYSTEMEXCEPTIONDEBUG}
  607. var
  608. oldexceptaddr,
  609. newexceptaddr : Longint;
  610. {$endif SYSTEMEXCEPTIONDEBUG}
  611. begin
  612. {$ifdef SYSTEMEXCEPTIONDEBUG}
  613. asm
  614. movl $0,%eax
  615. movl %fs:(%eax),%eax
  616. movl %eax,oldexceptaddr
  617. end;
  618. {$endif SYSTEMEXCEPTIONDEBUG}
  619. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  620. {$ifdef SYSTEMEXCEPTIONDEBUG}
  621. asm
  622. movl $0,%eax
  623. movl %fs:(%eax),%eax
  624. movl %eax,newexceptaddr
  625. end;
  626. if IsConsole then
  627. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  628. ' new exception ',hexstr(newexceptaddr,8));
  629. {$endif SYSTEMEXCEPTIONDEBUG}
  630. end;
  631. procedure remove_exception_handlers;
  632. begin
  633. SetUnhandledExceptionFilter(nil);
  634. end;
  635. {$else not cpui386 (Processor specific !!)}
  636. procedure install_exception_handlers;
  637. begin
  638. end;
  639. procedure remove_exception_handlers;
  640. begin
  641. end;
  642. {$endif Set_i386_Exception_handler}
  643. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  644. type
  645. tdosheader = packed record
  646. e_magic : word;
  647. e_cblp : word;
  648. e_cp : word;
  649. e_crlc : word;
  650. e_cparhdr : word;
  651. e_minalloc : word;
  652. e_maxalloc : word;
  653. e_ss : word;
  654. e_sp : word;
  655. e_csum : word;
  656. e_ip : word;
  657. e_cs : word;
  658. e_lfarlc : word;
  659. e_ovno : word;
  660. e_res : array[0..3] of word;
  661. e_oemid : word;
  662. e_oeminfo : word;
  663. e_res2 : array[0..9] of word;
  664. e_lfanew : longint;
  665. end;
  666. tpeheader = packed record
  667. PEMagic : longint;
  668. Machine : word;
  669. NumberOfSections : word;
  670. TimeDateStamp : longint;
  671. PointerToSymbolTable : longint;
  672. NumberOfSymbols : longint;
  673. SizeOfOptionalHeader : word;
  674. Characteristics : word;
  675. Magic : word;
  676. MajorLinkerVersion : byte;
  677. MinorLinkerVersion : byte;
  678. SizeOfCode : longint;
  679. SizeOfInitializedData : longint;
  680. SizeOfUninitializedData : longint;
  681. AddressOfEntryPoint : longint;
  682. BaseOfCode : longint;
  683. BaseOfData : longint;
  684. ImageBase : longint;
  685. SectionAlignment : longint;
  686. FileAlignment : longint;
  687. MajorOperatingSystemVersion : word;
  688. MinorOperatingSystemVersion : word;
  689. MajorImageVersion : word;
  690. MinorImageVersion : word;
  691. MajorSubsystemVersion : word;
  692. MinorSubsystemVersion : word;
  693. Reserved1 : longint;
  694. SizeOfImage : longint;
  695. SizeOfHeaders : longint;
  696. CheckSum : longint;
  697. Subsystem : word;
  698. DllCharacteristics : word;
  699. SizeOfStackReserve : longint;
  700. SizeOfStackCommit : longint;
  701. SizeOfHeapReserve : longint;
  702. SizeOfHeapCommit : longint;
  703. LoaderFlags : longint;
  704. NumberOfRvaAndSizes : longint;
  705. DataDirectory : array[1..$80] of byte;
  706. end;
  707. begin
  708. result:=tpeheader((pointer(SysInstance)+(tdosheader(pointer(SysInstance)^).e_lfanew))^).SizeOfStackReserve;
  709. end;
  710. begin
  711. { get some helpful informations }
  712. GetStartupInfo(@startupinfo);
  713. SysResetFPU;
  714. if not(IsLibrary) then
  715. SysInitFPU;
  716. { some misc Win32 stuff }
  717. hprevinst:=0;
  718. if not IsLibrary then
  719. SysInstance:=getmodulehandle(nil);
  720. MainInstance:=SysInstance;
  721. { pass dummy value }
  722. StackLength := CheckInitialStkLen($1000000);
  723. StackBottom := StackTop - StackLength;
  724. cmdshow:=startupinfo.wshowwindow;
  725. { Setup heap }
  726. InitHeap;
  727. SysInitExceptions;
  728. { setup fastmove stuff }
  729. fpc_cpucodeinit;
  730. SysInitStdIO;
  731. { Arguments }
  732. setup_arguments;
  733. { Reset IO Error }
  734. InOutRes:=0;
  735. ProcessID := GetCurrentProcessID;
  736. { threading }
  737. InitSystemThreads;
  738. { Reset internal error variable }
  739. errno:=0;
  740. initvariantmanager;
  741. initwidestringmanager;
  742. {$ifndef VER2_2}
  743. initunicodestringmanager;
  744. {$endif VER2_2}
  745. InitWin32Widestrings;
  746. DispCallByIDProc:=@DoDispCallByIDError;
  747. end.