system.pp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  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 : longint; public name 'operatingsystem_dllreason';
  86. DLLparam : longint; public name 'operatingsystem_dllparam';
  87. StartupConsoleMode : DWORD;
  88. type
  89. TDLL_Entry_Hook = procedure (dllparam : longint);
  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. {$ifndef FPC_HAS_INDIRECT_MAIN_INFORMATION}
  258. procedure PascalMain;stdcall;external name 'PASCALMAIN';
  259. {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
  260. procedure fpc_do_exit;stdcall;external name 'FPC_DO_EXIT';
  261. Procedure ExitDLL(Exitcode : longint); forward;
  262. procedure asm_exit;stdcall;external name 'asm_exit';
  263. Procedure system_exit;
  264. begin
  265. { don't call ExitProcess inside
  266. the DLL exit code !!
  267. This crashes Win95 at least PM }
  268. if IsLibrary then
  269. ExitDLL(ExitCode);
  270. if not IsConsole then
  271. begin
  272. Close(stderr);
  273. Close(stdout);
  274. Close(erroutput);
  275. Close(Input);
  276. Close(Output);
  277. { what about Input and Output ?? PM }
  278. { now handled, FPK }
  279. end;
  280. remove_exception_handlers;
  281. { in 2.0 asm_exit does an exitprocess }
  282. {$ifndef ver2_0}
  283. { do cleanup required by the startup code }
  284. {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
  285. EntryInformation.asm_exit();
  286. {$else FPC_HAS_INDIRECT_MAIN_INFORMATION}
  287. asm_exit;
  288. {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
  289. {$endif ver2_0}
  290. { call exitprocess, with cleanup as required }
  291. ExitProcess(exitcode);
  292. end;
  293. var
  294. { value of the stack segment
  295. to check if the call stack can be written on exceptions }
  296. _SS : Cardinal;
  297. procedure Exe_entry(const info : TEntryInformation);[public,alias:'_FPC_EXE_Entry'];
  298. var
  299. ST : pointer;
  300. begin
  301. EntryInformation:=info;
  302. IsLibrary:=false;
  303. { install the handlers for exe only ?
  304. or should we install them for DLL also ? (PM) }
  305. install_exception_handlers;
  306. { This strange construction is needed to solve the _SS problem
  307. with a smartlinked syswin32 (PFV) }
  308. asm
  309. { allocate space for an exception frame }
  310. pushl $0
  311. pushl %fs:(0)
  312. { movl %esp,%fs:(0)
  313. but don't insert it as it doesn't
  314. point to anything yet
  315. this will be used in signals unit }
  316. movl %esp,%eax
  317. movl %eax,System_exception_frame
  318. pushl %ebp
  319. movl %esp,%eax
  320. movl %eax,st
  321. end;
  322. StackTop:=st;
  323. asm
  324. xorl %eax,%eax
  325. movw %ss,%ax
  326. movl %eax,_SS
  327. xorl %ebp,%ebp
  328. end;
  329. {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
  330. EntryInformation.PascalMain();
  331. {$else FPC_HAS_INDIRECT_MAIN_INFORMATION}
  332. PascalMain;
  333. {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
  334. asm
  335. popl %ebp
  336. end;
  337. { if we pass here there was no error ! }
  338. system_exit;
  339. end;
  340. function GetCurrentProcess : dword;
  341. stdcall;external 'kernel32' name 'GetCurrentProcess';
  342. function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
  343. stdcall;external 'kernel32' name 'ReadProcessMemory';
  344. function is_prefetch(p : pointer) : boolean;
  345. var
  346. a : array[0..15] of byte;
  347. doagain : boolean;
  348. instrlo,instrhi,opcode : byte;
  349. i : longint;
  350. begin
  351. result:=false;
  352. { read memory savely without causing another exeception }
  353. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  354. exit;
  355. i:=0;
  356. doagain:=true;
  357. while doagain and (i<15) do
  358. begin
  359. opcode:=a[i];
  360. instrlo:=opcode and $f;
  361. instrhi:=opcode and $f0;
  362. case instrhi of
  363. { prefix? }
  364. $20,$30:
  365. doagain:=(instrlo and 7)=6;
  366. $60:
  367. doagain:=(instrlo and $c)=4;
  368. $f0:
  369. doagain:=instrlo in [0,2,3];
  370. $0:
  371. begin
  372. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  373. exit;
  374. end;
  375. else
  376. doagain:=false;
  377. end;
  378. inc(i);
  379. end;
  380. end;
  381. {******************************************************************************}
  382. { include code common with win64 }
  383. {$I syswin.inc}
  384. {******************************************************************************}
  385. //
  386. // Hardware exception handling
  387. //
  388. {$ifdef Set_i386_Exception_handler}
  389. type
  390. PFloatingSaveArea = ^TFloatingSaveArea;
  391. TFloatingSaveArea = packed record
  392. ControlWord : Cardinal;
  393. StatusWord : Cardinal;
  394. TagWord : Cardinal;
  395. ErrorOffset : Cardinal;
  396. ErrorSelector : Cardinal;
  397. DataOffset : Cardinal;
  398. DataSelector : Cardinal;
  399. RegisterArea : array[0..79] of Byte;
  400. Cr0NpxState : Cardinal;
  401. end;
  402. PContext = ^TContext;
  403. TContext = packed record
  404. //
  405. // The flags values within this flag control the contents of
  406. // a CONTEXT record.
  407. //
  408. ContextFlags : Cardinal;
  409. //
  410. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  411. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  412. // included in CONTEXT_FULL.
  413. //
  414. Dr0, Dr1, Dr2,
  415. Dr3, Dr6, Dr7 : Cardinal;
  416. //
  417. // This section is specified/returned if the
  418. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  419. //
  420. FloatSave : TFloatingSaveArea;
  421. //
  422. // This section is specified/returned if the
  423. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  424. //
  425. SegGs, SegFs,
  426. SegEs, SegDs : Cardinal;
  427. //
  428. // This section is specified/returned if the
  429. // ContextFlags word contains the flag CONTEXT_INTEGER.
  430. //
  431. Edi, Esi, Ebx,
  432. Edx, Ecx, Eax : Cardinal;
  433. //
  434. // This section is specified/returned if the
  435. // ContextFlags word contains the flag CONTEXT_CONTROL.
  436. //
  437. Ebp : Cardinal;
  438. Eip : Cardinal;
  439. SegCs : Cardinal;
  440. EFlags, Esp, SegSs : Cardinal;
  441. //
  442. // This section is specified/returned if the ContextFlags word
  443. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  444. // The format and contexts are processor specific
  445. //
  446. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  447. end;
  448. type
  449. PExceptionRecord = ^TExceptionRecord;
  450. TExceptionRecord = packed record
  451. ExceptionCode : cardinal;
  452. ExceptionFlags : Longint;
  453. ExceptionRecord : PExceptionRecord;
  454. ExceptionAddress : Pointer;
  455. NumberParameters : Longint;
  456. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  457. end;
  458. PExceptionPointers = ^TExceptionPointers;
  459. TExceptionPointers = packed record
  460. ExceptionRecord : PExceptionRecord;
  461. ContextRecord : PContext;
  462. end;
  463. { type of functions that should be used for exception handling }
  464. TTopLevelExceptionFilter = function (excep : PExceptionPointers) : Longint;stdcall;
  465. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : TTopLevelExceptionFilter) : TTopLevelExceptionFilter;
  466. stdcall;external 'kernel32' name 'SetUnhandledExceptionFilter';
  467. const
  468. MaxExceptionLevel = 16;
  469. exceptLevel : Byte = 0;
  470. var
  471. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  472. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  473. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  474. {$ifdef SYSTEMEXCEPTIONDEBUG}
  475. procedure DebugHandleErrorAddrFrame(error : longint; addr, frame : pointer);
  476. begin
  477. if IsConsole then
  478. begin
  479. write(stderr,'HandleErrorAddrFrame(error=',error);
  480. write(stderr,',addr=',hexstr(ptruint(addr),8));
  481. writeln(stderr,',frame=',hexstr(ptruint(frame),8),')');
  482. end;
  483. HandleErrorAddrFrame(error,addr,frame);
  484. end;
  485. {$endif SYSTEMEXCEPTIONDEBUG}
  486. procedure JumpToHandleErrorFrame;
  487. var
  488. eip, ebp, error : Longint;
  489. begin
  490. // save ebp
  491. asm
  492. movl (%ebp),%eax
  493. movl %eax,ebp
  494. end;
  495. if (exceptLevel > 0) then
  496. dec(exceptLevel);
  497. eip:=exceptEip[exceptLevel];
  498. error:=exceptError[exceptLevel];
  499. {$ifdef SYSTEMEXCEPTIONDEBUG}
  500. if IsConsole then
  501. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  502. {$endif SYSTEMEXCEPTIONDEBUG}
  503. if resetFPU[exceptLevel] then
  504. SysResetFPU;
  505. { build a fake stack }
  506. asm
  507. {$ifdef REGCALL}
  508. movl ebp,%ecx
  509. movl eip,%edx
  510. movl error,%eax
  511. pushl eip
  512. movl ebp,%ebp // Change frame pointer
  513. {$else}
  514. movl ebp,%eax
  515. pushl %eax
  516. movl eip,%eax
  517. pushl %eax
  518. movl error,%eax
  519. pushl %eax
  520. movl eip,%eax
  521. pushl %eax
  522. movl ebp,%ebp // Change frame pointer
  523. {$endif}
  524. {$ifdef SYSTEMEXCEPTIONDEBUG}
  525. jmpl DebugHandleErrorAddrFrame
  526. {$else not SYSTEMEXCEPTIONDEBUG}
  527. jmpl HandleErrorAddrFrame
  528. {$endif SYSTEMEXCEPTIONDEBUG}
  529. end;
  530. end;
  531. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  532. var
  533. res: longint;
  534. err: byte;
  535. must_reset_fpu: boolean;
  536. begin
  537. res := EXCEPTION_CONTINUE_SEARCH;
  538. if excep^.ContextRecord^.SegSs=_SS then begin
  539. err := 0;
  540. must_reset_fpu := true;
  541. {$ifdef SYSTEMEXCEPTIONDEBUG}
  542. if IsConsole then Writeln(stderr,'Exception ',
  543. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  544. {$endif SYSTEMEXCEPTIONDEBUG}
  545. case excep^.ExceptionRecord^.ExceptionCode of
  546. STATUS_INTEGER_DIVIDE_BY_ZERO,
  547. STATUS_FLOAT_DIVIDE_BY_ZERO :
  548. err := 200;
  549. STATUS_ARRAY_BOUNDS_EXCEEDED :
  550. begin
  551. err := 201;
  552. must_reset_fpu := false;
  553. end;
  554. STATUS_STACK_OVERFLOW :
  555. begin
  556. err := 202;
  557. must_reset_fpu := false;
  558. end;
  559. STATUS_FLOAT_OVERFLOW :
  560. err := 205;
  561. STATUS_FLOAT_DENORMAL_OPERAND,
  562. STATUS_FLOAT_UNDERFLOW :
  563. err := 206;
  564. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  565. STATUS_FLOAT_INEXACT_RESULT,
  566. STATUS_FLOAT_INVALID_OPERATION,
  567. STATUS_FLOAT_STACK_CHECK :
  568. err := 207;
  569. STATUS_INTEGER_OVERFLOW :
  570. begin
  571. err := 215;
  572. must_reset_fpu := false;
  573. end;
  574. STATUS_ILLEGAL_INSTRUCTION:
  575. { if we're testing sse support, simply set the flag and continue }
  576. if sse_check then
  577. begin
  578. os_supports_sse:=false;
  579. { skip the offending movaps %xmm7, %xmm6 instruction }
  580. inc(excep^.ContextRecord^.Eip,3);
  581. excep^.ExceptionRecord^.ExceptionCode := 0;
  582. res:=EXCEPTION_CONTINUE_EXECUTION;
  583. end
  584. else
  585. err := 216;
  586. STATUS_ACCESS_VIOLATION:
  587. { Athlon prefetch bug? }
  588. if is_prefetch(pointer(excep^.ContextRecord^.Eip)) then
  589. begin
  590. { if yes, then retry }
  591. excep^.ExceptionRecord^.ExceptionCode := 0;
  592. res:=EXCEPTION_CONTINUE_EXECUTION;
  593. end
  594. else
  595. err := 216;
  596. STATUS_CONTROL_C_EXIT:
  597. err := 217;
  598. STATUS_PRIVILEGED_INSTRUCTION:
  599. begin
  600. err := 218;
  601. must_reset_fpu := false;
  602. end;
  603. else
  604. begin
  605. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  606. err := 217
  607. else
  608. err := 255;
  609. end;
  610. end;
  611. if (err <> 0) and (exceptLevel < MaxExceptionLevel) then begin
  612. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  613. exceptError[exceptLevel] := err;
  614. resetFPU[exceptLevel] := must_reset_fpu;
  615. inc(exceptLevel);
  616. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  617. excep^.ExceptionRecord^.ExceptionCode := 0;
  618. res := EXCEPTION_CONTINUE_EXECUTION;
  619. {$ifdef SYSTEMEXCEPTIONDEBUG}
  620. if IsConsole then begin
  621. writeln(stderr,'Exception Continue Exception set at ',
  622. hexstr(exceptEip[exceptLevel],8));
  623. writeln(stderr,'Eip changed to ',
  624. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', err);
  625. end;
  626. {$endif SYSTEMEXCEPTIONDEBUG}
  627. end;
  628. end;
  629. syswin32_i386_exception_handler := res;
  630. end;
  631. procedure install_exception_handlers;
  632. {$ifdef SYSTEMEXCEPTIONDEBUG}
  633. var
  634. oldexceptaddr,
  635. newexceptaddr : Longint;
  636. {$endif SYSTEMEXCEPTIONDEBUG}
  637. begin
  638. {$ifdef SYSTEMEXCEPTIONDEBUG}
  639. asm
  640. movl $0,%eax
  641. movl %fs:(%eax),%eax
  642. movl %eax,oldexceptaddr
  643. end;
  644. {$endif SYSTEMEXCEPTIONDEBUG}
  645. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  646. {$ifdef SYSTEMEXCEPTIONDEBUG}
  647. asm
  648. movl $0,%eax
  649. movl %fs:(%eax),%eax
  650. movl %eax,newexceptaddr
  651. end;
  652. if IsConsole then
  653. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  654. ' new exception ',hexstr(newexceptaddr,8));
  655. {$endif SYSTEMEXCEPTIONDEBUG}
  656. end;
  657. procedure remove_exception_handlers;
  658. begin
  659. SetUnhandledExceptionFilter(nil);
  660. end;
  661. {$else not cpui386 (Processor specific !!)}
  662. procedure install_exception_handlers;
  663. begin
  664. end;
  665. procedure remove_exception_handlers;
  666. begin
  667. end;
  668. {$endif Set_i386_Exception_handler}
  669. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  670. type
  671. tdosheader = packed record
  672. e_magic : word;
  673. e_cblp : word;
  674. e_cp : word;
  675. e_crlc : word;
  676. e_cparhdr : word;
  677. e_minalloc : word;
  678. e_maxalloc : word;
  679. e_ss : word;
  680. e_sp : word;
  681. e_csum : word;
  682. e_ip : word;
  683. e_cs : word;
  684. e_lfarlc : word;
  685. e_ovno : word;
  686. e_res : array[0..3] of word;
  687. e_oemid : word;
  688. e_oeminfo : word;
  689. e_res2 : array[0..9] of word;
  690. e_lfanew : longint;
  691. end;
  692. tpeheader = packed record
  693. PEMagic : longint;
  694. Machine : word;
  695. NumberOfSections : word;
  696. TimeDateStamp : longint;
  697. PointerToSymbolTable : longint;
  698. NumberOfSymbols : longint;
  699. SizeOfOptionalHeader : word;
  700. Characteristics : word;
  701. Magic : word;
  702. MajorLinkerVersion : byte;
  703. MinorLinkerVersion : byte;
  704. SizeOfCode : longint;
  705. SizeOfInitializedData : longint;
  706. SizeOfUninitializedData : longint;
  707. AddressOfEntryPoint : longint;
  708. BaseOfCode : longint;
  709. BaseOfData : longint;
  710. ImageBase : longint;
  711. SectionAlignment : longint;
  712. FileAlignment : longint;
  713. MajorOperatingSystemVersion : word;
  714. MinorOperatingSystemVersion : word;
  715. MajorImageVersion : word;
  716. MinorImageVersion : word;
  717. MajorSubsystemVersion : word;
  718. MinorSubsystemVersion : word;
  719. Reserved1 : longint;
  720. SizeOfImage : longint;
  721. SizeOfHeaders : longint;
  722. CheckSum : longint;
  723. Subsystem : word;
  724. DllCharacteristics : word;
  725. SizeOfStackReserve : longint;
  726. SizeOfStackCommit : longint;
  727. SizeOfHeapReserve : longint;
  728. SizeOfHeapCommit : longint;
  729. LoaderFlags : longint;
  730. NumberOfRvaAndSizes : longint;
  731. DataDirectory : array[1..$80] of byte;
  732. end;
  733. begin
  734. result:=tpeheader((pointer(SysInstance)+(tdosheader(pointer(SysInstance)^).e_lfanew))^).SizeOfStackReserve;
  735. end;
  736. begin
  737. { get some helpful informations }
  738. GetStartupInfo(@startupinfo);
  739. SysResetFPU;
  740. if not(IsLibrary) then
  741. SysInitFPU;
  742. { some misc Win32 stuff }
  743. hprevinst:=0;
  744. if not IsLibrary then
  745. SysInstance:=getmodulehandle(nil);
  746. MainInstance:=SysInstance;
  747. { pass dummy value }
  748. StackLength := CheckInitialStkLen($1000000);
  749. StackBottom := StackTop - StackLength;
  750. cmdshow:=startupinfo.wshowwindow;
  751. { Setup heap }
  752. InitHeap;
  753. SysInitExceptions;
  754. { setup fastmove stuff }
  755. fpc_cpucodeinit;
  756. SysInitStdIO;
  757. { Arguments }
  758. setup_arguments;
  759. { Reset IO Error }
  760. InOutRes:=0;
  761. ProcessID := GetCurrentProcessID;
  762. { threading }
  763. InitSystemThreads;
  764. { Reset internal error variable }
  765. errno:=0;
  766. initvariantmanager;
  767. initwidestringmanager;
  768. {$ifndef VER2_2}
  769. initunicodestringmanager;
  770. {$endif VER2_2}
  771. InitWin32Widestrings;
  772. DispCallByIDProc:=@DoDispCallByIDError;
  773. end.