system.pp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl and Pavel Ozerski
  5. member of the Free Pascal development team.
  6. FPC Pascal system unit for the Win32 API.
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {$ifndef VER1_0}
  14. { $define MT}
  15. {$endif VER1_0}
  16. unit {$ifdef VER1_0}SysWin32{$else}System{$endif};
  17. interface
  18. {$ifdef SYSTEMDEBUG}
  19. {$define SYSTEMEXCEPTIONDEBUG}
  20. {$endif SYSTEMDEBUG}
  21. {$ifdef cpui386}
  22. {$define Set_i386_Exception_handler}
  23. {$endif cpui386}
  24. { Ctrl-Z means EOF }
  25. {$DEFINE EOF_CTRLZ}
  26. { include system-independent routine headers }
  27. {$I systemh.inc}
  28. const
  29. LineEnding = #13#10;
  30. LFNSupport = true;
  31. DirectorySeparator = '\';
  32. DriveSeparator = ':';
  33. PathSeparator = ';';
  34. { FileNameCaseSensitive is defined separately below!!! }
  35. maxExitCode = 65535;
  36. type
  37. PEXCEPTION_FRAME = ^TEXCEPTION_FRAME;
  38. TEXCEPTION_FRAME = record
  39. next : PEXCEPTION_FRAME;
  40. handler : pointer;
  41. end;
  42. const
  43. { Default filehandles }
  44. UnusedHandle : THandle = -1;
  45. StdInputHandle : THandle = 0;
  46. StdOutputHandle : THandle = 0;
  47. StdErrorHandle : THandle = 0;
  48. FileNameCaseSensitive : boolean = true;
  49. sLineBreak = LineEnding;
  50. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  51. { Thread count for DLL }
  52. Thread_count : longint = 0;
  53. System_exception_frame : PEXCEPTION_FRAME =nil;
  54. type
  55. TStartupInfo=packed record
  56. cb : longint;
  57. lpReserved : Pointer;
  58. lpDesktop : Pointer;
  59. lpTitle : Pointer;
  60. dwX : longint;
  61. dwY : longint;
  62. dwXSize : longint;
  63. dwYSize : longint;
  64. dwXCountChars : longint;
  65. dwYCountChars : longint;
  66. dwFillAttribute : longint;
  67. dwFlags : longint;
  68. wShowWindow : Word;
  69. cbReserved2 : Word;
  70. lpReserved2 : Pointer;
  71. hStdInput : longint;
  72. hStdOutput : longint;
  73. hStdError : longint;
  74. end;
  75. var
  76. { C compatible arguments }
  77. argc : longint;
  78. argv : ppchar;
  79. { Win32 Info }
  80. startupinfo : tstartupinfo;
  81. hprevinst,
  82. HInstance,
  83. MainInstance,
  84. cmdshow : longint;
  85. DLLreason,DLLparam:longint;
  86. Win32StackTop : Dword;
  87. type
  88. TDLL_Process_Entry_Hook = function (dllparam : longint) : longbool;
  89. TDLL_Entry_Hook = procedure (dllparam : longint);
  90. const
  91. Dll_Process_Attach_Hook : TDLL_Process_Entry_Hook = nil;
  92. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  93. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  94. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  95. type
  96. HMODULE = THandle;
  97. implementation
  98. { include system independent routines }
  99. {$I system.inc}
  100. {*****************************************************************************
  101. Parameter Handling
  102. *****************************************************************************}
  103. var
  104. ModuleName : array[0..255] of char;
  105. function GetCommandFile:pchar;
  106. begin
  107. GetModuleFileName(0,@ModuleName,255);
  108. GetCommandFile:=@ModuleName;
  109. end;
  110. procedure setup_arguments;
  111. var
  112. arglen,
  113. count : longint;
  114. argstart,
  115. pc,arg : pchar;
  116. quote : char;
  117. argvlen : longint;
  118. procedure allocarg(idx,len:longint);
  119. begin
  120. if idx>=argvlen then
  121. begin
  122. argvlen:=(idx+8) and (not 7);
  123. sysreallocmem(argv,argvlen*sizeof(pointer));
  124. end;
  125. { use realloc to reuse already existing memory }
  126. { always allocate, even if length is zero, since }
  127. { the arg. is still present! }
  128. sysreallocmem(argv[idx],len+1);
  129. end;
  130. begin
  131. { create commandline, it starts with the executed filename which is argv[0] }
  132. { Win32 passes the command NOT via the args, but via getmodulefilename}
  133. count:=0;
  134. argv:=nil;
  135. argvlen:=0;
  136. pc:=getcommandfile;
  137. Arglen:=0;
  138. repeat
  139. Inc(Arglen);
  140. until (pc[Arglen]=#0);
  141. allocarg(count,arglen);
  142. move(pc^,argv[count]^,arglen);
  143. { Setup cmdline variable }
  144. cmdline:=GetCommandLine;
  145. { process arguments }
  146. pc:=cmdline;
  147. {$IfDef SYSTEM_DEBUG_STARTUP}
  148. Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
  149. {$EndIf }
  150. while pc^<>#0 do
  151. begin
  152. { skip leading spaces }
  153. while pc^ in [#1..#32] do
  154. inc(pc);
  155. if pc^=#0 then
  156. break;
  157. { calc argument length }
  158. quote:=' ';
  159. argstart:=pc;
  160. arglen:=0;
  161. while (pc^<>#0) do
  162. begin
  163. case pc^ of
  164. #1..#32 :
  165. begin
  166. if quote<>' ' then
  167. inc(arglen)
  168. else
  169. break;
  170. end;
  171. '"' :
  172. begin
  173. if quote<>'''' then
  174. begin
  175. if pchar(pc+1)^<>'"' then
  176. begin
  177. if quote='"' then
  178. quote:=' '
  179. else
  180. quote:='"';
  181. end
  182. else
  183. inc(pc);
  184. end
  185. else
  186. inc(arglen);
  187. end;
  188. '''' :
  189. begin
  190. if quote<>'"' then
  191. begin
  192. if pchar(pc+1)^<>'''' then
  193. begin
  194. if quote='''' then
  195. quote:=' '
  196. else
  197. quote:='''';
  198. end
  199. else
  200. inc(pc);
  201. end
  202. else
  203. inc(arglen);
  204. end;
  205. else
  206. inc(arglen);
  207. end;
  208. inc(pc);
  209. end;
  210. { copy argument }
  211. { Don't copy the first one, it is already there.}
  212. If Count<>0 then
  213. begin
  214. allocarg(count,arglen);
  215. quote:=' ';
  216. pc:=argstart;
  217. arg:=argv[count];
  218. while (pc^<>#0) do
  219. begin
  220. case pc^ of
  221. #1..#32 :
  222. begin
  223. if quote<>' ' then
  224. begin
  225. arg^:=pc^;
  226. inc(arg);
  227. end
  228. else
  229. break;
  230. end;
  231. '"' :
  232. begin
  233. if quote<>'''' then
  234. begin
  235. if pchar(pc+1)^<>'"' then
  236. begin
  237. if quote='"' then
  238. quote:=' '
  239. else
  240. quote:='"';
  241. end
  242. else
  243. inc(pc);
  244. end
  245. else
  246. begin
  247. arg^:=pc^;
  248. inc(arg);
  249. end;
  250. end;
  251. '''' :
  252. begin
  253. if quote<>'"' then
  254. begin
  255. if pchar(pc+1)^<>'''' then
  256. begin
  257. if quote='''' then
  258. quote:=' '
  259. else
  260. quote:='''';
  261. end
  262. else
  263. inc(pc);
  264. end
  265. else
  266. begin
  267. arg^:=pc^;
  268. inc(arg);
  269. end;
  270. end;
  271. else
  272. begin
  273. arg^:=pc^;
  274. inc(arg);
  275. end;
  276. end;
  277. inc(pc);
  278. end;
  279. arg^:=#0;
  280. end;
  281. {$IfDef SYSTEM_DEBUG_STARTUP}
  282. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  283. {$EndIf SYSTEM_DEBUG_STARTUP}
  284. inc(count);
  285. end;
  286. { get argc and create an nil entry }
  287. argc:=count;
  288. allocarg(argc,0);
  289. { free unused memory }
  290. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  291. end;
  292. function paramcount : longint;
  293. begin
  294. paramcount := argc - 1;
  295. end;
  296. function paramstr(l : longint) : string;
  297. begin
  298. if (l>=0) and (l<argc) then
  299. paramstr:=strpas(argv[l])
  300. else
  301. paramstr:='';
  302. end;
  303. procedure randomize;
  304. begin
  305. randseed:=GetTickCount;
  306. end;
  307. {*****************************************************************************
  308. System Dependent Exit code
  309. *****************************************************************************}
  310. procedure install_exception_handlers;forward;
  311. procedure remove_exception_handlers;forward;
  312. procedure PascalMain;stdcall;external name 'PASCALMAIN';
  313. procedure fpc_do_exit;stdcall;external name 'FPC_DO_EXIT';
  314. Procedure ExitDLL(Exitcode : longint); forward;
  315. procedure asm_exit(Exitcode : longint);external name 'asm_exit';
  316. Procedure system_exit;
  317. begin
  318. { don't call ExitProcess inside
  319. the DLL exit code !!
  320. This crashes Win95 at least PM }
  321. if IsLibrary then
  322. ExitDLL(ExitCode);
  323. if not IsConsole then
  324. begin
  325. Close(stderr);
  326. Close(stdout);
  327. { what about Input and Output ?? PM }
  328. end;
  329. remove_exception_handlers;
  330. { call exitprocess, with cleanup as required }
  331. asm_exit(exitcode);
  332. end;
  333. var
  334. { value of the stack segment
  335. to check if the call stack can be written on exceptions }
  336. _SS : Cardinal;
  337. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  338. begin
  339. IsLibrary:=false;
  340. { install the handlers for exe only ?
  341. or should we install them for DLL also ? (PM) }
  342. install_exception_handlers;
  343. { This strange construction is needed to solve the _SS problem
  344. with a smartlinked syswin32 (PFV) }
  345. asm
  346. { allocate space for an exception frame }
  347. pushl $0
  348. pushl %fs:(0)
  349. { movl %esp,%fs:(0)
  350. but don't insert it as it doesn't
  351. point to anything yet
  352. this will be used in signals unit }
  353. movl %esp,%eax
  354. movl %eax,System_exception_frame
  355. pushl %ebp
  356. xorl %ebp,%ebp
  357. movl %esp,%eax
  358. movl %eax,Win32StackTop
  359. movw %ss,%bp
  360. movl %ebp,_SS
  361. call SysResetFPU
  362. xorl %ebp,%ebp
  363. call PASCALMAIN
  364. popl %ebp
  365. end;
  366. { if we pass here there was no error ! }
  367. system_exit;
  368. end;
  369. Const
  370. { DllEntryPoint }
  371. DLL_PROCESS_ATTACH = 1;
  372. DLL_THREAD_ATTACH = 2;
  373. DLL_PROCESS_DETACH = 0;
  374. DLL_THREAD_DETACH = 3;
  375. Var
  376. DLLBuf : Jmp_buf;
  377. Const
  378. DLLExitOK : boolean = true;
  379. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  380. var
  381. res : longbool;
  382. begin
  383. IsLibrary:=true;
  384. Dll_entry:=false;
  385. case DLLreason of
  386. DLL_PROCESS_ATTACH :
  387. begin
  388. If SetJmp(DLLBuf) = 0 then
  389. begin
  390. if assigned(Dll_Process_Attach_Hook) then
  391. begin
  392. res:=Dll_Process_Attach_Hook(DllParam);
  393. if not res then
  394. exit(false);
  395. end;
  396. PASCALMAIN;
  397. Dll_entry:=true;
  398. end
  399. else
  400. Dll_entry:=DLLExitOK;
  401. end;
  402. DLL_THREAD_ATTACH :
  403. begin
  404. inc(Thread_count);
  405. {$warning Allocate Threadvars !}
  406. if assigned(Dll_Thread_Attach_Hook) then
  407. Dll_Thread_Attach_Hook(DllParam);
  408. Dll_entry:=true; { return value is ignored }
  409. end;
  410. DLL_THREAD_DETACH :
  411. begin
  412. dec(Thread_count);
  413. if assigned(Dll_Thread_Detach_Hook) then
  414. Dll_Thread_Detach_Hook(DllParam);
  415. {$warning Release Threadvars !}
  416. Dll_entry:=true; { return value is ignored }
  417. end;
  418. DLL_PROCESS_DETACH :
  419. begin
  420. Dll_entry:=true; { return value is ignored }
  421. If SetJmp(DLLBuf) = 0 then
  422. begin
  423. FPC_DO_EXIT;
  424. end;
  425. if assigned(Dll_Process_Detach_Hook) then
  426. Dll_Process_Detach_Hook(DllParam);
  427. end;
  428. end;
  429. end;
  430. Procedure ExitDLL(Exitcode : longint);
  431. begin
  432. DLLExitOK:=ExitCode=0;
  433. LongJmp(DLLBuf,1);
  434. end;
  435. function GetCurrentProcess : dword;
  436. stdcall;external 'kernel32' name 'GetCurrentProcess';
  437. function ReadProcessMemory(process : dword;address : pointer;dest : pointer;size : dword;bytesread : pdword) : longbool;
  438. stdcall;external 'kernel32' name 'ReadProcessMemory';
  439. function is_prefetch(p : pointer) : boolean;
  440. var
  441. a : array[0..15] of byte;
  442. doagain : boolean;
  443. instrlo,instrhi,opcode : byte;
  444. i : longint;
  445. begin
  446. result:=false;
  447. { read memory savely without causing another exeception }
  448. if not(ReadProcessMemory(GetCurrentProcess,p,@a,sizeof(a),nil)) then
  449. exit;
  450. i:=0;
  451. doagain:=true;
  452. while doagain and (i<15) do
  453. begin
  454. opcode:=a[i];
  455. instrlo:=opcode and $f;
  456. instrhi:=opcode and $f0;
  457. case instrhi of
  458. { prefix? }
  459. $20,$30:
  460. doagain:=(instrlo and 7)=6;
  461. $60:
  462. doagain:=(instrlo and $c)=4;
  463. $f0:
  464. doagain:=instrlo in [0,2,3];
  465. $0:
  466. begin
  467. result:=(instrlo=$f) and (a[i+1] in [$d,$18]);
  468. exit;
  469. end;
  470. else
  471. doagain:=false;
  472. end;
  473. inc(i);
  474. end;
  475. end;
  476. //
  477. // Hardware exception handling
  478. //
  479. {$ifdef Set_i386_Exception_handler}
  480. {
  481. Error code definitions for the Win32 API functions
  482. Values are 32 bit values layed out as follows:
  483. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  484. 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
  485. +---+-+-+-----------------------+-------------------------------+
  486. |Sev|C|R| Facility | Code |
  487. +---+-+-+-----------------------+-------------------------------+
  488. where
  489. Sev - is the severity code
  490. 00 - Success
  491. 01 - Informational
  492. 10 - Warning
  493. 11 - Error
  494. C - is the Customer code flag
  495. R - is a reserved bit
  496. Facility - is the facility code
  497. Code - is the facility's status code
  498. }
  499. const
  500. SEVERITY_SUCCESS = $00000000;
  501. SEVERITY_INFORMATIONAL = $40000000;
  502. SEVERITY_WARNING = $80000000;
  503. SEVERITY_ERROR = $C0000000;
  504. const
  505. STATUS_SEGMENT_NOTIFICATION = $40000005;
  506. DBG_TERMINATE_THREAD = $40010003;
  507. DBG_TERMINATE_PROCESS = $40010004;
  508. DBG_CONTROL_C = $40010005;
  509. DBG_CONTROL_BREAK = $40010008;
  510. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  511. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  512. STATUS_BREAKPOINT = $80000003;
  513. STATUS_SINGLE_STEP = $80000004;
  514. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  515. STATUS_ACCESS_VIOLATION = $C0000005;
  516. STATUS_IN_PAGE_ERROR = $C0000006;
  517. STATUS_INVALID_HANDLE = $C0000008;
  518. STATUS_NO_MEMORY = $C0000017;
  519. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  520. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  521. STATUS_INVALID_DISPOSITION = $C0000026;
  522. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  523. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  524. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  525. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  526. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  527. STATUS_FLOAT_OVERFLOW = $C0000091;
  528. STATUS_FLOAT_STACK_CHECK = $C0000092;
  529. STATUS_FLOAT_UNDERFLOW = $C0000093;
  530. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  531. STATUS_INTEGER_OVERFLOW = $C0000095;
  532. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  533. STATUS_STACK_OVERFLOW = $C00000FD;
  534. STATUS_CONTROL_C_EXIT = $C000013A;
  535. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  536. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  537. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  538. EXCEPTION_EXECUTE_HANDLER = 1;
  539. EXCEPTION_CONTINUE_EXECUTION = -1;
  540. EXCEPTION_CONTINUE_SEARCH = 0;
  541. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  542. CONTEXT_X86 = $00010000;
  543. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  544. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  545. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  546. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  547. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  548. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  549. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  550. MAXIMUM_SUPPORTED_EXTENSION = 512;
  551. type
  552. PFloatingSaveArea = ^TFloatingSaveArea;
  553. TFloatingSaveArea = packed record
  554. ControlWord : Cardinal;
  555. StatusWord : Cardinal;
  556. TagWord : Cardinal;
  557. ErrorOffset : Cardinal;
  558. ErrorSelector : Cardinal;
  559. DataOffset : Cardinal;
  560. DataSelector : Cardinal;
  561. RegisterArea : array[0..79] of Byte;
  562. Cr0NpxState : Cardinal;
  563. end;
  564. PContext = ^TContext;
  565. TContext = packed record
  566. //
  567. // The flags values within this flag control the contents of
  568. // a CONTEXT record.
  569. //
  570. ContextFlags : Cardinal;
  571. //
  572. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  573. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  574. // included in CONTEXT_FULL.
  575. //
  576. Dr0, Dr1, Dr2,
  577. Dr3, Dr6, Dr7 : Cardinal;
  578. //
  579. // This section is specified/returned if the
  580. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  581. //
  582. FloatSave : TFloatingSaveArea;
  583. //
  584. // This section is specified/returned if the
  585. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  586. //
  587. SegGs, SegFs,
  588. SegEs, SegDs : Cardinal;
  589. //
  590. // This section is specified/returned if the
  591. // ContextFlags word contains the flag CONTEXT_INTEGER.
  592. //
  593. Edi, Esi, Ebx,
  594. Edx, Ecx, Eax : Cardinal;
  595. //
  596. // This section is specified/returned if the
  597. // ContextFlags word contains the flag CONTEXT_CONTROL.
  598. //
  599. Ebp : Cardinal;
  600. Eip : Cardinal;
  601. SegCs : Cardinal;
  602. EFlags, Esp, SegSs : Cardinal;
  603. //
  604. // This section is specified/returned if the ContextFlags word
  605. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  606. // The format and contexts are processor specific
  607. //
  608. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  609. end;
  610. type
  611. PExceptionRecord = ^TExceptionRecord;
  612. TExceptionRecord = packed record
  613. ExceptionCode : Longint;
  614. ExceptionFlags : Longint;
  615. ExceptionRecord : PExceptionRecord;
  616. ExceptionAddress : Pointer;
  617. NumberParameters : Longint;
  618. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  619. end;
  620. PExceptionPointers = ^TExceptionPointers;
  621. TExceptionPointers = packed record
  622. ExceptionRecord : PExceptionRecord;
  623. ContextRecord : PContext;
  624. end;
  625. { type of functions that should be used for exception handling }
  626. TTopLevelExceptionFilter = function (excep : PExceptionPointers) : Longint;stdcall;
  627. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : TTopLevelExceptionFilter) : TTopLevelExceptionFilter;
  628. stdcall;external 'kernel32' name 'SetUnhandledExceptionFilter';
  629. const
  630. MaxExceptionLevel = 16;
  631. exceptLevel : Byte = 0;
  632. var
  633. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  634. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  635. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  636. {$ifdef SYSTEMEXCEPTIONDEBUG}
  637. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  638. begin
  639. if IsConsole then begin
  640. write(stderr,'HandleErrorAddrFrame(error=',error);
  641. write(stderr,',addr=',hexstr(addr,8));
  642. writeln(stderr,',frame=',hexstr(frame,8),')');
  643. end;
  644. HandleErrorAddrFrame(error,addr,frame);
  645. end;
  646. {$endif SYSTEMEXCEPTIONDEBUG}
  647. procedure JumpToHandleErrorFrame;
  648. var
  649. eip, ebp, error : Longint;
  650. begin
  651. // save ebp
  652. asm
  653. movl (%ebp),%eax
  654. movl %eax,ebp
  655. end;
  656. if (exceptLevel > 0) then
  657. dec(exceptLevel);
  658. eip:=exceptEip[exceptLevel];
  659. error:=exceptError[exceptLevel];
  660. {$ifdef SYSTEMEXCEPTIONDEBUG}
  661. if IsConsole then
  662. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  663. {$endif SYSTEMEXCEPTIONDEBUG}
  664. if resetFPU[exceptLevel] then asm
  665. fninit
  666. fldcw fpucw
  667. end;
  668. { build a fake stack }
  669. asm
  670. {$ifdef REGCALL}
  671. movl ebp,%ecx
  672. movl eip,%edx
  673. movl error,%eax
  674. pushl eip
  675. movl ebp,%ebp // Change frame pointer
  676. {$else}
  677. movl ebp,%eax
  678. pushl %eax
  679. movl eip,%eax
  680. pushl %eax
  681. movl error,%eax
  682. pushl %eax
  683. movl eip,%eax
  684. pushl %eax
  685. movl ebp,%ebp // Change frame pointer
  686. {$endif}
  687. {$ifdef SYSTEMEXCEPTIONDEBUG}
  688. jmpl DebugHandleErrorAddrFrame
  689. {$else not SYSTEMEXCEPTIONDEBUG}
  690. jmpl HandleErrorAddrFrame
  691. {$endif SYSTEMEXCEPTIONDEBUG}
  692. end;
  693. end;
  694. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  695. var
  696. frame,
  697. res : longint;
  698. function SysHandleErrorFrame(error, frame : Longint; must_reset_fpu : Boolean) : Longint;
  699. begin
  700. if (frame = 0) then
  701. SysHandleErrorFrame:=EXCEPTION_CONTINUE_SEARCH
  702. else begin
  703. if (exceptLevel >= MaxExceptionLevel) then exit;
  704. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  705. exceptError[exceptLevel] := error;
  706. resetFPU[exceptLevel] := must_reset_fpu;
  707. inc(exceptLevel);
  708. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  709. excep^.ExceptionRecord^.ExceptionCode := 0;
  710. SysHandleErrorFrame := EXCEPTION_CONTINUE_EXECUTION;
  711. {$ifdef SYSTEMEXCEPTIONDEBUG}
  712. if IsConsole then begin
  713. writeln(stderr,'Exception Continue Exception set at ',
  714. hexstr(exceptEip[exceptLevel],8));
  715. writeln(stderr,'Eip changed to ',
  716. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  717. end;
  718. {$endif SYSTEMEXCEPTIONDEBUG}
  719. end;
  720. end;
  721. begin
  722. if excep^.ContextRecord^.SegSs=_SS then
  723. frame := excep^.ContextRecord^.Ebp
  724. else
  725. frame := 0;
  726. res := EXCEPTION_CONTINUE_SEARCH;
  727. {$ifdef SYSTEMEXCEPTIONDEBUG}
  728. if IsConsole then Writeln(stderr,'Exception ',
  729. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  730. {$endif SYSTEMEXCEPTIONDEBUG}
  731. case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
  732. STATUS_INTEGER_DIVIDE_BY_ZERO,
  733. STATUS_FLOAT_DIVIDE_BY_ZERO :
  734. res := SysHandleErrorFrame(200, frame, true);
  735. STATUS_ARRAY_BOUNDS_EXCEEDED :
  736. res := SysHandleErrorFrame(201, frame, false);
  737. STATUS_STACK_OVERFLOW :
  738. res := SysHandleErrorFrame(202, frame, false);
  739. STATUS_FLOAT_OVERFLOW :
  740. res := SysHandleErrorFrame(205, frame, true);
  741. STATUS_FLOAT_DENORMAL_OPERAND,
  742. STATUS_FLOAT_UNDERFLOW :
  743. res := SysHandleErrorFrame(206, frame, true);
  744. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  745. STATUS_FLOAT_INEXACT_RESULT,
  746. STATUS_FLOAT_INVALID_OPERATION,
  747. STATUS_FLOAT_STACK_CHECK :
  748. res := SysHandleErrorFrame(207, frame, true);
  749. STATUS_INTEGER_OVERFLOW :
  750. res := SysHandleErrorFrame(215, frame, false);
  751. STATUS_ILLEGAL_INSTRUCTION:
  752. res := SysHandleErrorFrame(216, frame, true);
  753. STATUS_ACCESS_VIOLATION:
  754. { Athlon prefetch bug? }
  755. if is_prefetch(pointer(excep^.ContextRecord^.Eip)) then
  756. begin
  757. { if yes, then retry }
  758. excep^.ExceptionRecord^.ExceptionCode := 0;
  759. res:=EXCEPTION_CONTINUE_EXECUTION;
  760. end
  761. else
  762. res := SysHandleErrorFrame(216, frame, true);
  763. STATUS_CONTROL_C_EXIT:
  764. res := SysHandleErrorFrame(217, frame, true);
  765. STATUS_PRIVILEGED_INSTRUCTION:
  766. res := SysHandleErrorFrame(218, frame, false);
  767. else
  768. begin
  769. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  770. res := SysHandleErrorFrame(217, frame, true)
  771. else
  772. res := SysHandleErrorFrame(255, frame, true);
  773. end;
  774. end;
  775. syswin32_i386_exception_handler := res;
  776. end;
  777. procedure install_exception_handlers;
  778. {$ifdef SYSTEMEXCEPTIONDEBUG}
  779. var
  780. oldexceptaddr,
  781. newexceptaddr : Longint;
  782. {$endif SYSTEMEXCEPTIONDEBUG}
  783. begin
  784. {$ifdef SYSTEMEXCEPTIONDEBUG}
  785. asm
  786. movl $0,%eax
  787. movl %fs:(%eax),%eax
  788. movl %eax,oldexceptaddr
  789. end;
  790. {$endif SYSTEMEXCEPTIONDEBUG}
  791. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  792. {$ifdef SYSTEMEXCEPTIONDEBUG}
  793. asm
  794. movl $0,%eax
  795. movl %fs:(%eax),%eax
  796. movl %eax,newexceptaddr
  797. end;
  798. if IsConsole then
  799. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  800. ' new exception ',hexstr(newexceptaddr,8));
  801. {$endif SYSTEMEXCEPTIONDEBUG}
  802. end;
  803. procedure remove_exception_handlers;
  804. begin
  805. SetUnhandledExceptionFilter(nil);
  806. end;
  807. {$else not cpui386 (Processor specific !!)}
  808. procedure install_exception_handlers;
  809. begin
  810. end;
  811. procedure remove_exception_handlers;
  812. begin
  813. end;
  814. {$endif Set_i386_Exception_handler}
  815. {****************************************************************************
  816. Error Message writing using messageboxes
  817. ****************************************************************************}
  818. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  819. stdcall;external 'user32' name 'MessageBoxA';
  820. const
  821. ErrorBufferLength = 1024;
  822. var
  823. ErrorBuf : array[0..ErrorBufferLength] of char;
  824. ErrorLen : longint;
  825. Function ErrorWrite(Var F: TextRec): Integer;
  826. {
  827. An error message should always end with #13#10#13#10
  828. }
  829. var
  830. p : pchar;
  831. i : longint;
  832. Begin
  833. if F.BufPos>0 then
  834. begin
  835. if F.BufPos+ErrorLen>ErrorBufferLength then
  836. i:=ErrorBufferLength-ErrorLen
  837. else
  838. i:=F.BufPos;
  839. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  840. inc(ErrorLen,i);
  841. ErrorBuf[ErrorLen]:=#0;
  842. end;
  843. if ErrorLen>3 then
  844. begin
  845. p:=@ErrorBuf[ErrorLen];
  846. for i:=1 to 4 do
  847. begin
  848. dec(p);
  849. if not(p^ in [#10,#13]) then
  850. break;
  851. end;
  852. end;
  853. if ErrorLen=ErrorBufferLength then
  854. i:=4;
  855. if (i=4) then
  856. begin
  857. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  858. ErrorLen:=0;
  859. end;
  860. F.BufPos:=0;
  861. ErrorWrite:=0;
  862. End;
  863. Function ErrorClose(Var F: TextRec): Integer;
  864. begin
  865. if ErrorLen>0 then
  866. begin
  867. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  868. ErrorLen:=0;
  869. end;
  870. ErrorLen:=0;
  871. ErrorClose:=0;
  872. end;
  873. Function ErrorOpen(Var F: TextRec): Integer;
  874. Begin
  875. TextRec(F).InOutFunc:=@ErrorWrite;
  876. TextRec(F).FlushFunc:=@ErrorWrite;
  877. TextRec(F).CloseFunc:=@ErrorClose;
  878. ErrorOpen:=0;
  879. End;
  880. procedure AssignError(Var T: Text);
  881. begin
  882. Assign(T,'');
  883. TextRec(T).OpenFunc:=@ErrorOpen;
  884. Rewrite(T);
  885. end;
  886. procedure SysInitStdIO;
  887. begin
  888. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  889. displayed in and messagebox }
  890. StdInputHandle:=longint(GetStdHandle(cardinal(STD_INPUT_HANDLE)));
  891. StdOutputHandle:=longint(GetStdHandle(cardinal(STD_OUTPUT_HANDLE)));
  892. StdErrorHandle:=longint(GetStdHandle(cardinal(STD_ERROR_HANDLE)));
  893. if not IsConsole then
  894. begin
  895. AssignError(stderr);
  896. AssignError(stdout);
  897. Assign(Output,'');
  898. Assign(Input,'');
  899. Assign(ErrOutput,'');
  900. end
  901. else
  902. begin
  903. OpenStdIO(Input,fmInput,StdInputHandle);
  904. OpenStdIO(Output,fmOutput,StdOutputHandle);
  905. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  906. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  907. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  908. end;
  909. end;
  910. (* ProcessID cached to avoid repeated calls to GetCurrentProcess. *)
  911. var
  912. ProcessID: SizeUInt;
  913. function GetProcessID: SizeUInt;
  914. begin
  915. GetProcessID := ProcessID;
  916. end;
  917. const
  918. Exe_entry_code : pointer = @Exe_entry;
  919. Dll_entry_code : pointer = @Dll_entry;
  920. begin
  921. StackLength := InitialStkLen;
  922. StackBottom := Sptr - StackLength;
  923. { get some helpful informations }
  924. GetStartupInfo(@startupinfo);
  925. { some misc Win32 stuff }
  926. hprevinst:=0;
  927. if not IsLibrary then
  928. HInstance:=getmodulehandle(GetCommandFile);
  929. MainInstance:=HInstance;
  930. cmdshow:=startupinfo.wshowwindow;
  931. { Setup heap }
  932. InitHeap;
  933. SysInitExceptions;
  934. SysInitStdIO;
  935. { Arguments }
  936. setup_arguments;
  937. { Reset IO Error }
  938. InOutRes:=0;
  939. ProcessID := GetCurrentProcessID;
  940. { threading }
  941. InitSystemThreads;
  942. { Reset internal error variable }
  943. errno:=0;
  944. {$ifdef HASVARIANT}
  945. initvariantmanager;
  946. {$endif HASVARIANT}
  947. {$ifdef HASWIDESTRING}
  948. initwidestringmanager;
  949. {$endif HASWIDESTRING}
  950. end.
  951. {
  952. $Log$
  953. Revision 1.67 2005-02-06 13:06:20 peter
  954. * moved file and dir functions to sysfile/sysdir
  955. * win32 thread in systemunit
  956. Revision 1.66 2005/02/01 20:22:50 florian
  957. * improved widestring infrastructure manager
  958. Revision 1.65 2004/12/12 11:53:47 florian
  959. * remove inline assembler for calling asm_exit
  960. Revision 1.64 2004/12/05 14:36:38 hajny
  961. + GetProcessID added
  962. Revision 1.63 2004/11/04 09:32:31 peter
  963. ErrOutput added
  964. Revision 1.62 2004/10/25 15:38:59 peter
  965. * compiler defined HEAP and HEAPSIZE removed
  966. Revision 1.61 2004/09/03 19:27:25 olle
  967. + added maxExitCode to all System.pp
  968. * constrained error code to be below maxExitCode in RunError et. al.
  969. Revision 1.60 2004/06/27 11:57:18 florian
  970. * finally (hopefully) fixed sysalloc trouble
  971. Revision 1.59 2004/06/26 15:05:14 florian
  972. * fixed argument copying
  973. Revision 1.58 2004/06/20 09:24:40 peter
  974. fixed go32v2 compile
  975. Revision 1.57 2004/06/17 16:16:14 peter
  976. * New heapmanager that releases memory back to the OS, donated
  977. by Micha Nelissen
  978. Revision 1.56 2004/05/16 18:51:20 peter
  979. * use thandle in do_*
  980. Revision 1.55 2004/04/22 21:10:56 peter
  981. * do_read/do_write addr argument changed to pointer
  982. Revision 1.54 2004/02/15 21:37:18 hajny
  983. * ProcessID initialization added
  984. Revision 1.53 2004/02/02 17:01:47 florian
  985. * workaround for AMD prefetch bug
  986. Revision 1.52 2004/01/20 23:12:49 hajny
  987. * ExecuteProcess fixes, ProcessID and ThreadID added
  988. Revision 1.51 2003/12/17 21:56:33 peter
  989. * win32 regcall patches
  990. Revision 1.50 2003/12/04 20:52:41 peter
  991. * stdcall for CreateFile
  992. Revision 1.49 2003/11/24 23:08:37 michael
  993. + Redefined Fileopen so it corresponds to ascdef.inc definition
  994. Revision 1.48 2003/11/03 09:42:28 marco
  995. * Peter's Cardinal<->Longint fixes patch
  996. Revision 1.47 2003/10/17 22:15:10 olle
  997. * changed i386 to cpui386
  998. Revision 1.46 2003/10/16 15:43:13 peter
  999. * THandle is platform dependent
  1000. Revision 1.45 2003/10/06 23:52:53 florian
  1001. * some data types cleaned up
  1002. Revision 1.44 2003/09/27 11:52:36 peter
  1003. * sbrk returns pointer
  1004. Revision 1.43 2003/09/26 07:30:34 michael
  1005. + Win32 Do_open crahs on append
  1006. Revision 1.42 2003/09/17 15:06:36 peter
  1007. * stdcall patch
  1008. Revision 1.41 2003/09/12 12:33:43 olle
  1009. * nice-ified
  1010. Revision 1.40 2003/01/01 20:56:57 florian
  1011. + added invalid instruction exception
  1012. Revision 1.39 2002/12/24 15:35:15 peter
  1013. * error code fixes
  1014. Revision 1.38 2002/12/07 13:58:45 carl
  1015. * fix warnings
  1016. Revision 1.37 2002/11/30 18:17:35 carl
  1017. + profiling support
  1018. Revision 1.36 2002/10/31 15:17:58 carl
  1019. * always allocate argument even if its empty (bugfix web bug 2202)
  1020. Revision 1.35 2002/10/14 20:40:22 florian
  1021. * InitFPU renamed to SysResetFPU
  1022. Revision 1.34 2002/10/14 19:39:17 peter
  1023. * threads unit added for thread support
  1024. Revision 1.33 2002/10/13 09:28:45 florian
  1025. + call to initvariantmanager inserted
  1026. Revision 1.32 2002/09/07 21:28:10 carl
  1027. - removed os_types
  1028. * fix range check errors
  1029. Revision 1.31 2002/09/07 16:01:29 peter
  1030. * old logs removed and tabs fixed
  1031. Revision 1.30 2002/08/26 13:49:18 pierre
  1032. * fix bug report 2086
  1033. Revision 1.29 2002/07/28 20:43:49 florian
  1034. * several fixes for linux/powerpc
  1035. * several fixes to MT
  1036. Revision 1.28 2002/07/01 16:29:05 peter
  1037. * sLineBreak changed to normal constant like Kylix
  1038. Revision 1.27 2002/06/04 09:25:14 pierre
  1039. * Rename HeapSize to WinAPIHeapSize to avoid conflict with general function
  1040. Revision 1.26 2002/04/12 17:45:13 carl
  1041. + generic stack checking
  1042. Revision 1.25 2002/03/11 19:10:33 peter
  1043. * Regenerated with updated fpcmake
  1044. Revision 1.24 2002/01/30 14:57:11 pierre
  1045. * fix compilation failure
  1046. Revision 1.23 2002/01/25 16:23:03 peter
  1047. * merged filesearch() fix
  1048. }