system.pp 25 KB

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