system.pp 32 KB

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