system.pp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597
  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. unit {$ifdef VER1_0}SysWin32{$else}System{$endif};
  14. interface
  15. {$ifdef SYSTEMDEBUG}
  16. {$define SYSTEMEXCEPTIONDEBUG}
  17. {$endif SYSTEMDEBUG}
  18. {$ifdef i386}
  19. {$define Set_i386_Exception_handler}
  20. {$endif i386}
  21. { include system-independent routine headers }
  22. {$I systemh.inc}
  23. type
  24. { the fields of this record are os dependent }
  25. { and they shouldn't be used in a program }
  26. { only the type TCriticalSection is important }
  27. TCriticalSection = packed record
  28. DebugInfo : pointer;
  29. LockCount : longint;
  30. RecursionCount : longint;
  31. OwningThread : DWord;
  32. LockSemaphore : DWord;
  33. Reserved : DWord;
  34. end;
  35. { include threading stuff }
  36. {$i threadh.inc}
  37. { include heap support headers }
  38. {$I heaph.inc}
  39. const
  40. { Default filehandles }
  41. UnusedHandle : longint = -1;
  42. StdInputHandle : longint = 0;
  43. StdOutputHandle : longint = 0;
  44. StdErrorHandle : longint = 0;
  45. FileNameCaseSensitive : boolean = true;
  46. sLineBreak : string[2] = #13#10;
  47. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  48. { Thread count for DLL }
  49. Thread_count : longint = 0;
  50. type
  51. TStartupInfo=packed record
  52. cb : longint;
  53. lpReserved : Pointer;
  54. lpDesktop : Pointer;
  55. lpTitle : Pointer;
  56. dwX : longint;
  57. dwY : longint;
  58. dwXSize : longint;
  59. dwYSize : longint;
  60. dwXCountChars : longint;
  61. dwYCountChars : longint;
  62. dwFillAttribute : longint;
  63. dwFlags : longint;
  64. wShowWindow : Word;
  65. cbReserved2 : Word;
  66. lpReserved2 : Pointer;
  67. hStdInput : longint;
  68. hStdOutput : longint;
  69. hStdError : longint;
  70. end;
  71. var
  72. { C compatible arguments }
  73. argc : longint;
  74. argv : ppchar;
  75. { Win32 Info }
  76. startupinfo : tstartupinfo;
  77. hprevinst,
  78. HInstance,
  79. MainInstance,
  80. cmdshow : longint;
  81. DLLreason,DLLparam:longint;
  82. Win32StackTop : Dword;
  83. type
  84. TDLL_Process_Entry_Hook = function (dllparam : longint) : longbool;
  85. TDLL_Entry_Hook = procedure (dllparam : longint);
  86. const
  87. Dll_Process_Attach_Hook : TDLL_Process_Entry_Hook = nil;
  88. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  89. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  90. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  91. implementation
  92. { include system independent routines }
  93. {$I system.inc}
  94. { some declarations for Win32 API calls }
  95. {$I win32.inc}
  96. CONST
  97. { These constants are used for conversion of error codes }
  98. { from win32 i/o errors to tp i/o errors }
  99. { errors 1 to 18 are the same as in Turbo Pascal }
  100. { DO NOT MODIFY UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING! }
  101. { The media is write protected. }
  102. ERROR_WRITE_PROTECT = 19;
  103. { The system cannot find the device specified. }
  104. ERROR_BAD_UNIT = 20;
  105. { The device is not ready. }
  106. ERROR_NOT_READY = 21;
  107. { The device does not recognize the command. }
  108. ERROR_BAD_COMMAND = 22;
  109. { Data error (cyclic redundancy check) }
  110. ERROR_CRC = 23;
  111. { The program issued a command but the }
  112. { command length is incorrect. }
  113. ERROR_BAD_LENGTH = 24;
  114. { The drive cannot locate a specific }
  115. { area or track on the disk. }
  116. ERROR_SEEK = 25;
  117. { The specified disk or diskette cannot be accessed. }
  118. ERROR_NOT_DOS_DISK = 26;
  119. { The drive cannot find the sector requested. }
  120. ERROR_SECTOR_NOT_FOUND = 27;
  121. { The printer is out of paper. }
  122. ERROR_OUT_OF_PAPER = 28;
  123. { The system cannot write to the specified device. }
  124. ERROR_WRITE_FAULT = 29;
  125. { The system cannot read from the specified device. }
  126. ERROR_READ_FAULT = 30;
  127. { A device attached to the system is not functioning.}
  128. ERROR_GEN_FAILURE = 31;
  129. { The process cannot access the file because }
  130. { it is being used by another process. }
  131. ERROR_SHARING_VIOLATION = 32;
  132. var
  133. errno : longint;
  134. {$ASMMODE ATT}
  135. { misc. functions }
  136. function GetLastError : DWORD;
  137. external 'kernel32' name 'GetLastError';
  138. { time and date functions }
  139. function GetTickCount : longint;
  140. external 'kernel32' name 'GetTickCount';
  141. { process functions }
  142. procedure ExitProcess(uExitCode : UINT);
  143. external 'kernel32' name 'ExitProcess';
  144. Procedure Errno2InOutRes;
  145. Begin
  146. { DO NOT MODIFY UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING }
  147. if (errno >= ERROR_WRITE_PROTECT) and (errno <= ERROR_GEN_FAILURE) THEN
  148. BEGIN
  149. { This is the offset to the Win32 to add to directly map }
  150. { to the DOS/TP compatible error codes when in this range }
  151. InOutRes := word(errno)+131;
  152. END
  153. else
  154. { This case is special }
  155. if errno=ERROR_SHARING_VIOLATION THEN
  156. BEGIN
  157. InOutRes :=5;
  158. END
  159. else
  160. { other error codes can directly be mapped }
  161. InOutRes := Word(errno);
  162. errno:=0;
  163. end;
  164. {$ifdef dummy}
  165. procedure int_stackcheck(stack_size:longint);[public,alias: 'STACKCHECK'];
  166. {
  167. called when trying to get local stack if the compiler directive $S
  168. is set this function must preserve esi !!!! because esi is set by
  169. the calling proc for methods it must preserve all registers !!
  170. With a 2048 byte safe area used to write to StdIo without crossing
  171. the stack boundary
  172. }
  173. begin
  174. asm
  175. pushl %eax
  176. pushl %ebx
  177. movl stack_size,%ebx
  178. addl $2048,%ebx
  179. movl %esp,%eax
  180. subl %ebx,%eax
  181. movl stacklimit,%ebx
  182. cmpl %eax,%ebx
  183. jae .L__short_on_stack
  184. popl %ebx
  185. popl %eax
  186. leave
  187. ret $4
  188. .L__short_on_stack:
  189. { can be usefull for error recovery !! }
  190. popl %ebx
  191. popl %eax
  192. end['EAX','EBX'];
  193. HandleError(202);
  194. end;
  195. {$endif dummy}
  196. function paramcount : longint;
  197. begin
  198. paramcount := argc - 1;
  199. end;
  200. { module functions }
  201. function GetModuleFileName(l1:longint;p:pointer;l2:longint):longint;
  202. external 'kernel32' name 'GetModuleFileNameA';
  203. function GetModuleHandle(p : pointer) : longint;
  204. external 'kernel32' name 'GetModuleHandleA';
  205. function GetCommandFile:pchar;forward;
  206. function paramstr(l : longint) : string;
  207. begin
  208. if (l>=0) and (l<argc) then
  209. paramstr:=strpas(argv[l])
  210. else
  211. paramstr:='';
  212. end;
  213. procedure randomize;
  214. begin
  215. randseed:=GetTickCount;
  216. end;
  217. {*****************************************************************************
  218. Heap Management
  219. *****************************************************************************}
  220. { memory functions }
  221. function GetProcessHeap : DWord;
  222. external 'kernel32' name 'GetProcessHeap';
  223. function HeapAlloc(hHeap : DWord; dwFlags : DWord; dwBytes : DWord) : Longint;
  224. external 'kernel32' name 'HeapAlloc';
  225. {$IFDEF SYSTEMDEBUG}
  226. function HeapSize(hHeap : DWord; dwFlags : DWord; ptr : Pointer) : DWord;
  227. external 'kernel32' name 'HeapSize';
  228. {$ENDIF}
  229. var
  230. heap : longint;external name 'HEAP';
  231. intern_heapsize : longint;external name 'HEAPSIZE';
  232. function getheapstart:pointer;assembler;
  233. asm
  234. leal HEAP,%eax
  235. end ['EAX'];
  236. function getheapsize:longint;assembler;
  237. asm
  238. movl intern_HEAPSIZE,%eax
  239. end ['EAX'];
  240. function Sbrk(size : longint):longint;
  241. var
  242. l : longint;
  243. begin
  244. l := HeapAlloc(GetProcessHeap(), 0, size);
  245. if (l = 0) then
  246. l := -1;
  247. {$ifdef DUMPGROW}
  248. Writeln('new heap part at $',hexstr(l,8), ' size = ',HeapSize(GetProcessHeap()));
  249. {$endif}
  250. sbrk:=l;
  251. end;
  252. { include standard heap management }
  253. {$I heap.inc}
  254. {*****************************************************************************
  255. Low Level File Routines
  256. *****************************************************************************}
  257. function WriteFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
  258. overlap:pointer):longint;
  259. external 'kernel32' name 'WriteFile';
  260. function ReadFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
  261. overlap:pointer):longint;
  262. external 'kernel32' name 'ReadFile';
  263. function CloseHandle(h : longint) : longint;
  264. external 'kernel32' name 'CloseHandle';
  265. function DeleteFile(p : pchar) : longint;
  266. external 'kernel32' name 'DeleteFileA';
  267. function MoveFile(old,_new : pchar) : longint;
  268. external 'kernel32' name 'MoveFileA';
  269. function SetFilePointer(l1,l2 : longint;l3 : pointer;l4 : longint) : longint;
  270. external 'kernel32' name 'SetFilePointer';
  271. function GetFileSize(h:longint;p:pointer) : longint;
  272. external 'kernel32' name 'GetFileSize';
  273. function CreateFile(name : pointer;access,sharing : longint;
  274. security : pointer;how,attr,template : longint) : longint;
  275. external 'kernel32' name 'CreateFileA';
  276. function SetEndOfFile(h : longint) : longbool;
  277. external 'kernel32' name 'SetEndOfFile';
  278. function GetFileType(Handle:DWORD):DWord;
  279. external 'kernel32' name 'GetFileType';
  280. procedure AllowSlash(p:pchar);
  281. var
  282. i : longint;
  283. begin
  284. { allow slash as backslash }
  285. for i:=0 to strlen(p) do
  286. if p[i]='/' then p[i]:='\';
  287. end;
  288. function do_isdevice(handle:longint):boolean;
  289. begin
  290. do_isdevice:=(getfiletype(handle)=2);
  291. end;
  292. procedure do_close(h : longint);
  293. begin
  294. if do_isdevice(h) then
  295. exit;
  296. CloseHandle(h);
  297. end;
  298. procedure do_erase(p : pchar);
  299. begin
  300. AllowSlash(p);
  301. if DeleteFile(p)=0 then
  302. Begin
  303. errno:=GetLastError;
  304. Errno2InoutRes;
  305. end;
  306. end;
  307. procedure do_rename(p1,p2 : pchar);
  308. begin
  309. AllowSlash(p1);
  310. AllowSlash(p2);
  311. if MoveFile(p1,p2)=0 then
  312. Begin
  313. errno:=GetLastError;
  314. Errno2InoutRes;
  315. end;
  316. end;
  317. function do_write(h,addr,len : longint) : longint;
  318. var
  319. size:longint;
  320. begin
  321. if writefile(h,pointer(addr),len,size,nil)=0 then
  322. Begin
  323. errno:=GetLastError;
  324. Errno2InoutRes;
  325. end;
  326. do_write:=size;
  327. end;
  328. function do_read(h,addr,len : longint) : longint;
  329. var
  330. _result:longint;
  331. begin
  332. if readfile(h,pointer(addr),len,_result,nil)=0 then
  333. Begin
  334. errno:=GetLastError;
  335. Errno2InoutRes;
  336. end;
  337. do_read:=_result;
  338. end;
  339. function do_filepos(handle : longint) : longint;
  340. var
  341. l:longint;
  342. begin
  343. l:=SetFilePointer(handle,0,nil,FILE_CURRENT);
  344. if l=-1 then
  345. begin
  346. l:=0;
  347. errno:=GetLastError;
  348. Errno2InoutRes;
  349. end;
  350. do_filepos:=l;
  351. end;
  352. procedure do_seek(handle,pos : longint);
  353. begin
  354. if SetFilePointer(handle,pos,nil,FILE_BEGIN)=-1 then
  355. Begin
  356. errno:=GetLastError;
  357. Errno2InoutRes;
  358. end;
  359. end;
  360. function do_seekend(handle:longint):longint;
  361. begin
  362. do_seekend:=SetFilePointer(handle,0,nil,FILE_END);
  363. if do_seekend=-1 then
  364. begin
  365. errno:=GetLastError;
  366. Errno2InoutRes;
  367. end;
  368. end;
  369. function do_filesize(handle : longint) : longint;
  370. var
  371. aktfilepos : longint;
  372. begin
  373. aktfilepos:=do_filepos(handle);
  374. do_filesize:=do_seekend(handle);
  375. do_seek(handle,aktfilepos);
  376. end;
  377. procedure do_truncate (handle,pos:longint);
  378. begin
  379. do_seek(handle,pos);
  380. if not(SetEndOfFile(handle)) then
  381. begin
  382. errno:=GetLastError;
  383. Errno2InoutRes;
  384. end;
  385. end;
  386. procedure do_open(var f;p : pchar;flags:longint);
  387. {
  388. filerec and textrec have both handle and mode as the first items so
  389. they could use the same routine for opening/creating.
  390. when (flags and $100) the file will be append
  391. when (flags and $1000) the file will be truncate/rewritten
  392. when (flags and $10000) there is no check for close (needed for textfiles)
  393. }
  394. Const
  395. file_Share_Read = $00000001;
  396. file_Share_Write = $00000002;
  397. Var
  398. shflags,
  399. oflags,cd : longint;
  400. begin
  401. AllowSlash(p);
  402. { close first if opened }
  403. if ((flags and $10000)=0) then
  404. begin
  405. case filerec(f).mode of
  406. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  407. fmclosed : ;
  408. else
  409. begin
  410. {not assigned}
  411. inoutres:=102;
  412. exit;
  413. end;
  414. end;
  415. end;
  416. { reset file handle }
  417. filerec(f).handle:=UnusedHandle;
  418. { convert filesharing }
  419. shflags:=0;
  420. if ((filemode and fmshareExclusive) = fmshareExclusive) then
  421. { no sharing }
  422. else
  423. if (filemode = fmShareCompat) or ((filemode and fmshareDenyWrite) = fmshareDenyWrite) then
  424. shflags := file_Share_Read
  425. else
  426. if ((filemode and fmshareDenyRead) = fmshareDenyRead) then
  427. shflags := file_Share_Write
  428. else
  429. if ((filemode and fmshareDenyNone) = fmshareDenyNone) then
  430. shflags := file_Share_Read + file_Share_Write;
  431. { convert filemode to filerec modes }
  432. case (flags and 3) of
  433. 0 : begin
  434. filerec(f).mode:=fminput;
  435. oflags:=GENERIC_READ;
  436. end;
  437. 1 : begin
  438. filerec(f).mode:=fmoutput;
  439. oflags:=GENERIC_WRITE;
  440. end;
  441. 2 : begin
  442. filerec(f).mode:=fminout;
  443. oflags:=GENERIC_WRITE or GENERIC_READ;
  444. end;
  445. end;
  446. { standard is opening and existing file }
  447. cd:=OPEN_EXISTING;
  448. { create it ? }
  449. if (flags and $1000)<>0 then
  450. cd:=CREATE_ALWAYS
  451. { or append ? }
  452. else
  453. if (flags and $100)<>0 then
  454. cd:=OPEN_ALWAYS;
  455. { empty name is special }
  456. if p[0]=#0 then
  457. begin
  458. case FileRec(f).mode of
  459. fminput :
  460. FileRec(f).Handle:=StdInputHandle;
  461. fminout, { this is set by rewrite }
  462. fmoutput :
  463. FileRec(f).Handle:=StdOutputHandle;
  464. fmappend :
  465. begin
  466. FileRec(f).Handle:=StdOutputHandle;
  467. FileRec(f).mode:=fmoutput; {fool fmappend}
  468. end;
  469. end;
  470. exit;
  471. end;
  472. filerec(f).handle:=CreateFile(p,oflags,shflags,nil,cd,FILE_ATTRIBUTE_NORMAL,0);
  473. { append mode }
  474. if (flags and $100)<>0 then
  475. begin
  476. do_seekend(filerec(f).handle);
  477. filerec(f).mode:=fmoutput; {fool fmappend}
  478. end;
  479. { get errors }
  480. { handle -1 is returned sometimes !! (PM) }
  481. if (filerec(f).handle=0) or (filerec(f).handle=-1) then
  482. begin
  483. errno:=GetLastError;
  484. Errno2InoutRes;
  485. end;
  486. end;
  487. {*****************************************************************************
  488. UnTyped File Handling
  489. *****************************************************************************}
  490. {$i file.inc}
  491. {*****************************************************************************
  492. Typed File Handling
  493. *****************************************************************************}
  494. {$i typefile.inc}
  495. {*****************************************************************************
  496. Text File Handling
  497. *****************************************************************************}
  498. {$DEFINE EOF_CTRLZ}
  499. {$i text.inc}
  500. {*****************************************************************************
  501. Directory Handling
  502. *****************************************************************************}
  503. function CreateDirectory(name : pointer;sec : pointer) : longint;
  504. external 'kernel32' name 'CreateDirectoryA';
  505. function RemoveDirectory(name:pointer):longint;
  506. external 'kernel32' name 'RemoveDirectoryA';
  507. function SetCurrentDirectory(name : pointer) : longint;
  508. external 'kernel32' name 'SetCurrentDirectoryA';
  509. function GetCurrentDirectory(bufsize : longint;name : pchar) : longint;
  510. external 'kernel32' name 'GetCurrentDirectoryA';
  511. type
  512. TDirFnType=function(name:pointer):word;
  513. procedure dirfn(afunc : TDirFnType;const s:string);
  514. var
  515. buffer : array[0..255] of char;
  516. begin
  517. move(s[1],buffer,length(s));
  518. buffer[length(s)]:=#0;
  519. AllowSlash(pchar(@buffer));
  520. if aFunc(@buffer)=0 then
  521. begin
  522. errno:=GetLastError;
  523. Errno2InoutRes;
  524. end;
  525. end;
  526. function CreateDirectoryTrunc(name:pointer):word;
  527. begin
  528. CreateDirectoryTrunc:=CreateDirectory(name,nil);
  529. end;
  530. procedure mkdir(const s:string);[IOCHECK];
  531. begin
  532. If (s='') or (InOutRes <> 0) then
  533. exit;
  534. dirfn(TDirFnType(@CreateDirectoryTrunc),s);
  535. end;
  536. procedure rmdir(const s:string);[IOCHECK];
  537. begin
  538. If (s='') or (InOutRes <> 0) then
  539. exit;
  540. dirfn(TDirFnType(@RemoveDirectory),s);
  541. end;
  542. procedure chdir(const s:string);[IOCHECK];
  543. begin
  544. If (s='') or (InOutRes <> 0) then
  545. exit;
  546. dirfn(TDirFnType(@SetCurrentDirectory),s);
  547. end;
  548. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  549. const
  550. Drive:array[0..3]of char=(#0,':',#0,#0);
  551. var
  552. defaultdrive:boolean;
  553. DirBuf,SaveBuf:array[0..259] of Char;
  554. begin
  555. defaultdrive:=drivenr=0;
  556. if not defaultdrive then
  557. begin
  558. byte(Drive[0]):=Drivenr+64;
  559. GetCurrentDirectory(SizeOf(SaveBuf),SaveBuf);
  560. if SetCurrentDirectory(@Drive) <> 0 then
  561. begin
  562. errno := word (GetLastError);
  563. Errno2InoutRes;
  564. end;
  565. end;
  566. GetCurrentDirectory(SizeOf(DirBuf),DirBuf);
  567. if not defaultdrive then
  568. SetCurrentDirectory(@SaveBuf);
  569. dir:=strpas(DirBuf);
  570. if not FileNameCaseSensitive then
  571. dir:=upcase(dir);
  572. end;
  573. {*****************************************************************************
  574. Thread Handling
  575. *****************************************************************************}
  576. const
  577. fpucw : word = $1332;
  578. procedure InitFPU;assembler;
  579. asm
  580. fninit
  581. fldcw fpucw
  582. end;
  583. { include threading stuff, this is os independend part }
  584. {$I thread.inc}
  585. {*****************************************************************************
  586. SystemUnit Initialization
  587. *****************************************************************************}
  588. { Startup }
  589. procedure GetStartupInfo(p : pointer);
  590. external 'kernel32' name 'GetStartupInfoA';
  591. function GetStdHandle(nStdHandle:DWORD):THANDLE;
  592. external 'kernel32' name 'GetStdHandle';
  593. { command line/enviroment functions }
  594. function GetCommandLine : pchar;
  595. external 'kernel32' name 'GetCommandLineA';
  596. var
  597. ModuleName : array[0..255] of char;
  598. function GetCommandFile:pchar;
  599. begin
  600. GetModuleFileName(0,@ModuleName,255);
  601. GetCommandFile:=@ModuleName;
  602. end;
  603. procedure setup_arguments;
  604. var
  605. arglen,
  606. count : longint;
  607. argstart,
  608. pc,arg : pchar;
  609. quote : char;
  610. argvlen : longint;
  611. procedure allocarg(idx,len:longint);
  612. begin
  613. if idx>=argvlen then
  614. begin
  615. argvlen:=(idx+8) and (not 7);
  616. sysreallocmem(argv,argvlen*sizeof(pointer));
  617. end;
  618. { use realloc to reuse already existing memory }
  619. if len<>0 then
  620. sysreallocmem(argv[idx],len+1);
  621. end;
  622. begin
  623. { create commandline, it starts with the executed filename which is argv[0] }
  624. { Win32 passes the command NOT via the args, but via getmodulefilename}
  625. count:=0;
  626. argv:=nil;
  627. argvlen:=0;
  628. pc:=getcommandfile;
  629. Arglen:=0;
  630. repeat
  631. Inc(Arglen);
  632. until (pc[Arglen]=#0);
  633. allocarg(count,arglen);
  634. move(pc^,argv[count]^,arglen);
  635. { Setup cmdline variable }
  636. cmdline:=GetCommandLine;
  637. { process arguments }
  638. pc:=cmdline;
  639. {$IfDef SYSTEM_DEBUG_STARTUP}
  640. Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
  641. {$EndIf }
  642. while pc^<>#0 do
  643. begin
  644. { skip leading spaces }
  645. while pc^ in [#1..#32] do
  646. inc(pc);
  647. { calc argument length }
  648. quote:=' ';
  649. argstart:=pc;
  650. arglen:=0;
  651. while (pc^<>#0) do
  652. begin
  653. case pc^ of
  654. #1..#32 :
  655. begin
  656. if quote<>' ' then
  657. inc(arglen)
  658. else
  659. break;
  660. end;
  661. '"' :
  662. begin
  663. if quote<>'''' then
  664. begin
  665. if pchar(pc+1)^<>'"' then
  666. begin
  667. if quote='"' then
  668. quote:=' '
  669. else
  670. quote:='"';
  671. end
  672. else
  673. inc(pc);
  674. end
  675. else
  676. inc(arglen);
  677. end;
  678. '''' :
  679. begin
  680. if quote<>'"' then
  681. begin
  682. if pchar(pc+1)^<>'''' then
  683. begin
  684. if quote='''' then
  685. quote:=' '
  686. else
  687. quote:='''';
  688. end
  689. else
  690. inc(pc);
  691. end
  692. else
  693. inc(arglen);
  694. end;
  695. else
  696. inc(arglen);
  697. end;
  698. inc(pc);
  699. end;
  700. { copy argument }
  701. { Don't copy the first one, it is already there.}
  702. If Count<>0 then
  703. begin
  704. allocarg(count,arglen);
  705. quote:=' ';
  706. pc:=argstart;
  707. arg:=argv[count];
  708. while (pc^<>#0) do
  709. begin
  710. case pc^ of
  711. #1..#32 :
  712. begin
  713. if quote<>' ' then
  714. begin
  715. arg^:=pc^;
  716. inc(arg);
  717. end
  718. else
  719. break;
  720. end;
  721. '"' :
  722. begin
  723. if quote<>'''' then
  724. begin
  725. if pchar(pc+1)^<>'"' then
  726. begin
  727. if quote='"' then
  728. quote:=' '
  729. else
  730. quote:='"';
  731. end
  732. else
  733. inc(pc);
  734. end
  735. else
  736. begin
  737. arg^:=pc^;
  738. inc(arg);
  739. end;
  740. end;
  741. '''' :
  742. begin
  743. if quote<>'"' then
  744. begin
  745. if pchar(pc+1)^<>'''' then
  746. begin
  747. if quote='''' then
  748. quote:=' '
  749. else
  750. quote:='''';
  751. end
  752. else
  753. inc(pc);
  754. end
  755. else
  756. begin
  757. arg^:=pc^;
  758. inc(arg);
  759. end;
  760. end;
  761. else
  762. begin
  763. arg^:=pc^;
  764. inc(arg);
  765. end;
  766. end;
  767. inc(pc);
  768. end;
  769. arg^:=#0;
  770. end;
  771. {$IfDef SYSTEM_DEBUG_STARTUP}
  772. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  773. {$EndIf SYSTEM_DEBUG_STARTUP}
  774. inc(count);
  775. end;
  776. { get argc and create an nil entry }
  777. argc:=count;
  778. allocarg(argc,0);
  779. { free unused memory }
  780. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  781. end;
  782. {*****************************************************************************
  783. System Dependent Exit code
  784. *****************************************************************************}
  785. procedure install_exception_handlers;forward;
  786. procedure remove_exception_handlers;forward;
  787. procedure PascalMain;external name 'PASCALMAIN';
  788. procedure fpc_do_exit;external name 'FPC_DO_EXIT';
  789. Procedure ExitDLL(Exitcode : longint); forward;
  790. Procedure system_exit;
  791. begin
  792. { don't call ExitProcess inside
  793. the DLL exit code !!
  794. This crashes Win95 at least PM }
  795. if IsLibrary then
  796. ExitDLL(ExitCode);
  797. if not IsConsole then
  798. begin
  799. Close(stderr);
  800. Close(stdout);
  801. { what about Input and Output ?? PM }
  802. end;
  803. remove_exception_handlers;
  804. ExitProcess(ExitCode);
  805. end;
  806. {$ifdef dummy}
  807. Function SetUpStack : longint;
  808. { This routine does the following : }
  809. { returns the value of the initial SP - __stklen }
  810. begin
  811. asm
  812. pushl %ebx
  813. pushl %eax
  814. movl __stklen,%ebx
  815. movl %esp,%eax
  816. subl %ebx,%eax
  817. movl %eax,__RESULT
  818. popl %eax
  819. popl %ebx
  820. end;
  821. end;
  822. {$endif}
  823. var
  824. { value of the stack segment
  825. to check if the call stack can be written on exceptions }
  826. _SS : longint;
  827. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  828. begin
  829. IsLibrary:=false;
  830. { install the handlers for exe only ?
  831. or should we install them for DLL also ? (PM) }
  832. install_exception_handlers;
  833. { This strange construction is needed to solve the _SS problem
  834. with a smartlinked syswin32 (PFV) }
  835. asm
  836. pushl %ebp
  837. xorl %ebp,%ebp
  838. movl %esp,%eax
  839. movl %eax,Win32StackTop
  840. movw %ss,%bp
  841. movl %ebp,_SS
  842. call InitFPU
  843. xorl %ebp,%ebp
  844. call PASCALMAIN
  845. popl %ebp
  846. end;
  847. { if we pass here there was no error ! }
  848. system_exit;
  849. end;
  850. Const
  851. { DllEntryPoint }
  852. DLL_PROCESS_ATTACH = 1;
  853. DLL_THREAD_ATTACH = 2;
  854. DLL_PROCESS_DETACH = 0;
  855. DLL_THREAD_DETACH = 3;
  856. Var
  857. DLLBuf : Jmp_buf;
  858. Const
  859. DLLExitOK : boolean = true;
  860. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  861. var
  862. res : longbool;
  863. begin
  864. IsLibrary:=true;
  865. Dll_entry:=false;
  866. case DLLreason of
  867. DLL_PROCESS_ATTACH :
  868. begin
  869. If SetJmp(DLLBuf) = 0 then
  870. begin
  871. if assigned(Dll_Process_Attach_Hook) then
  872. begin
  873. res:=Dll_Process_Attach_Hook(DllParam);
  874. if not res then
  875. exit(false);
  876. end;
  877. PASCALMAIN;
  878. Dll_entry:=true;
  879. end
  880. else
  881. Dll_entry:=DLLExitOK;
  882. end;
  883. DLL_THREAD_ATTACH :
  884. begin
  885. inc(Thread_count);
  886. {$ifdef MT}
  887. AllocateThreadVars;
  888. {$endif MT}
  889. if assigned(Dll_Thread_Attach_Hook) then
  890. Dll_Thread_Attach_Hook(DllParam);
  891. Dll_entry:=true; { return value is ignored }
  892. end;
  893. DLL_THREAD_DETACH :
  894. begin
  895. dec(Thread_count);
  896. if assigned(Dll_Thread_Detach_Hook) then
  897. Dll_Thread_Detach_Hook(DllParam);
  898. {$ifdef MT}
  899. ReleaseThreadVars;
  900. {$endif MT}
  901. Dll_entry:=true; { return value is ignored }
  902. end;
  903. DLL_PROCESS_DETACH :
  904. begin
  905. Dll_entry:=true; { return value is ignored }
  906. If SetJmp(DLLBuf) = 0 then
  907. begin
  908. FPC_DO_EXIT;
  909. end;
  910. if assigned(Dll_Process_Detach_Hook) then
  911. Dll_Process_Detach_Hook(DllParam);
  912. end;
  913. end;
  914. end;
  915. Procedure ExitDLL(Exitcode : longint);
  916. begin
  917. DLLExitOK:=ExitCode=0;
  918. LongJmp(DLLBuf,1);
  919. end;
  920. //
  921. // Hardware exception handling
  922. //
  923. {$ifdef Set_i386_Exception_handler}
  924. (*
  925. Error code definitions for the Win32 API functions
  926. Values are 32 bit values layed out as follows:
  927. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  928. 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
  929. +---+-+-+-----------------------+-------------------------------+
  930. |Sev|C|R| Facility | Code |
  931. +---+-+-+-----------------------+-------------------------------+
  932. where
  933. Sev - is the severity code
  934. 00 - Success
  935. 01 - Informational
  936. 10 - Warning
  937. 11 - Error
  938. C - is the Customer code flag
  939. R - is a reserved bit
  940. Facility - is the facility code
  941. Code - is the facility's status code
  942. *)
  943. const
  944. SEVERITY_SUCCESS = $00000000;
  945. SEVERITY_INFORMATIONAL = $40000000;
  946. SEVERITY_WARNING = $80000000;
  947. SEVERITY_ERROR = $C0000000;
  948. const
  949. STATUS_SEGMENT_NOTIFICATION = $40000005;
  950. DBG_TERMINATE_THREAD = $40010003;
  951. DBG_TERMINATE_PROCESS = $40010004;
  952. DBG_CONTROL_C = $40010005;
  953. DBG_CONTROL_BREAK = $40010008;
  954. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  955. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  956. STATUS_BREAKPOINT = $80000003;
  957. STATUS_SINGLE_STEP = $80000004;
  958. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  959. STATUS_ACCESS_VIOLATION = $C0000005;
  960. STATUS_IN_PAGE_ERROR = $C0000006;
  961. STATUS_INVALID_HANDLE = $C0000008;
  962. STATUS_NO_MEMORY = $C0000017;
  963. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  964. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  965. STATUS_INVALID_DISPOSITION = $C0000026;
  966. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  967. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  968. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  969. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  970. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  971. STATUS_FLOAT_OVERFLOW = $C0000091;
  972. STATUS_FLOAT_STACK_CHECK = $C0000092;
  973. STATUS_FLOAT_UNDERFLOW = $C0000093;
  974. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  975. STATUS_INTEGER_OVERFLOW = $C0000095;
  976. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  977. STATUS_STACK_OVERFLOW = $C00000FD;
  978. STATUS_CONTROL_C_EXIT = $C000013A;
  979. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  980. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  981. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  982. EXCEPTION_EXECUTE_HANDLER = 1;
  983. EXCEPTION_CONTINUE_EXECUTION = -1;
  984. EXCEPTION_CONTINUE_SEARCH = 0;
  985. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  986. CONTEXT_X86 = $00010000;
  987. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  988. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  989. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  990. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  991. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  992. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  993. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  994. MAXIMUM_SUPPORTED_EXTENSION = 512;
  995. type
  996. PFloatingSaveArea = ^TFloatingSaveArea;
  997. TFloatingSaveArea = packed record
  998. ControlWord : Cardinal;
  999. StatusWord : Cardinal;
  1000. TagWord : Cardinal;
  1001. ErrorOffset : Cardinal;
  1002. ErrorSelector : Cardinal;
  1003. DataOffset : Cardinal;
  1004. DataSelector : Cardinal;
  1005. RegisterArea : array[0..79] of Byte;
  1006. Cr0NpxState : Cardinal;
  1007. end;
  1008. PContext = ^TContext;
  1009. TContext = packed record
  1010. //
  1011. // The flags values within this flag control the contents of
  1012. // a CONTEXT record.
  1013. //
  1014. ContextFlags : Cardinal;
  1015. //
  1016. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  1017. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  1018. // included in CONTEXT_FULL.
  1019. //
  1020. Dr0, Dr1, Dr2,
  1021. Dr3, Dr6, Dr7 : Cardinal;
  1022. //
  1023. // This section is specified/returned if the
  1024. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  1025. //
  1026. FloatSave : TFloatingSaveArea;
  1027. //
  1028. // This section is specified/returned if the
  1029. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  1030. //
  1031. SegGs, SegFs,
  1032. SegEs, SegDs : Cardinal;
  1033. //
  1034. // This section is specified/returned if the
  1035. // ContextFlags word contains the flag CONTEXT_INTEGER.
  1036. //
  1037. Edi, Esi, Ebx,
  1038. Edx, Ecx, Eax : Cardinal;
  1039. //
  1040. // This section is specified/returned if the
  1041. // ContextFlags word contains the flag CONTEXT_CONTROL.
  1042. //
  1043. Ebp : Cardinal;
  1044. Eip : Cardinal;
  1045. SegCs : Cardinal;
  1046. EFlags, Esp, SegSs : Cardinal;
  1047. //
  1048. // This section is specified/returned if the ContextFlags word
  1049. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  1050. // The format and contexts are processor specific
  1051. //
  1052. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  1053. end;
  1054. type
  1055. PExceptionRecord = ^TExceptionRecord;
  1056. TExceptionRecord = packed record
  1057. ExceptionCode : Longint;
  1058. ExceptionFlags : Longint;
  1059. ExceptionRecord : PExceptionRecord;
  1060. ExceptionAddress : Pointer;
  1061. NumberParameters : Longint;
  1062. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  1063. end;
  1064. PExceptionPointers = ^TExceptionPointers;
  1065. TExceptionPointers = packed record
  1066. ExceptionRecord : PExceptionRecord;
  1067. ContextRecord : PContext;
  1068. end;
  1069. { type of functions that should be used for exception handling }
  1070. TTopLevelExceptionFilter = function (excep : PExceptionPointers) : Longint;stdcall;
  1071. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : TTopLevelExceptionFilter) : TTopLevelExceptionFilter;
  1072. external 'kernel32' name 'SetUnhandledExceptionFilter';
  1073. const
  1074. MaxExceptionLevel = 16;
  1075. exceptLevel : Byte = 0;
  1076. var
  1077. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  1078. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1079. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  1080. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1081. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  1082. begin
  1083. if IsConsole then begin
  1084. write(stderr,'HandleErrorAddrFrame(error=',error);
  1085. write(stderr,',addr=',hexstr(addr,8));
  1086. writeln(stderr,',frame=',hexstr(frame,8),')');
  1087. end;
  1088. HandleErrorAddrFrame(error,addr,frame);
  1089. end;
  1090. {$endif SYSTEMEXCEPTIONDEBUG}
  1091. procedure JumpToHandleErrorFrame;
  1092. var
  1093. eip, ebp, error : Longint;
  1094. begin
  1095. // save ebp
  1096. asm
  1097. movl (%ebp),%eax
  1098. movl %eax,ebp
  1099. end;
  1100. if (exceptLevel > 0) then
  1101. dec(exceptLevel);
  1102. eip:=exceptEip[exceptLevel];
  1103. error:=exceptError[exceptLevel];
  1104. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1105. if IsConsole then
  1106. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  1107. end;
  1108. {$endif SYSTEMEXCEPTIONDEBUG}
  1109. if resetFPU[exceptLevel] then asm
  1110. fninit
  1111. fldcw fpucw
  1112. end;
  1113. { build a fake stack }
  1114. asm
  1115. movl ebp,%eax
  1116. pushl %eax
  1117. movl eip,%eax
  1118. pushl %eax
  1119. movl error,%eax
  1120. pushl %eax
  1121. movl eip,%eax
  1122. pushl %eax
  1123. movl ebp,%ebp // Change frame pointer
  1124. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1125. jmpl DebugHandleErrorAddrFrame
  1126. {$else not SYSTEMEXCEPTIONDEBUG}
  1127. jmpl HandleErrorAddrFrame
  1128. {$endif SYSTEMEXCEPTIONDEBUG}
  1129. end;
  1130. end;
  1131. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  1132. var
  1133. frame,
  1134. res : longint;
  1135. function SysHandleErrorFrame(error, frame : Longint; must_reset_fpu : Boolean) : Longint;
  1136. begin
  1137. if (frame = 0) then
  1138. SysHandleErrorFrame:=EXCEPTION_CONTINUE_SEARCH
  1139. else begin
  1140. if (exceptLevel >= MaxExceptionLevel) then exit;
  1141. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  1142. exceptError[exceptLevel] := error;
  1143. resetFPU[exceptLevel] := must_reset_fpu;
  1144. inc(exceptLevel);
  1145. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  1146. excep^.ExceptionRecord^.ExceptionCode := 0;
  1147. SysHandleErrorFrame := EXCEPTION_CONTINUE_EXECUTION;
  1148. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1149. if IsConsole then begin
  1150. writeln(stderr,'Exception Continue Exception set at ',
  1151. hexstr(exceptEip[exceptLevel],8));
  1152. writeln(stderr,'Eip changed to ',
  1153. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1154. end;
  1155. {$endif SYSTEMEXCEPTIONDEBUG}
  1156. end;
  1157. end;
  1158. begin
  1159. if excep^.ContextRecord^.SegSs=_SS then
  1160. frame := excep^.ContextRecord^.Ebp
  1161. else
  1162. frame := 0;
  1163. res := EXCEPTION_CONTINUE_SEARCH;
  1164. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1165. if IsConsole then Writeln(stderr,'Exception ',
  1166. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  1167. {$endif SYSTEMEXCEPTIONDEBUG}
  1168. case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
  1169. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1170. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1171. res := SysHandleErrorFrame(200, frame, true);
  1172. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1173. res := SysHandleErrorFrame(201, frame, false);
  1174. STATUS_STACK_OVERFLOW :
  1175. res := SysHandleErrorFrame(202, frame, false);
  1176. STATUS_FLOAT_OVERFLOW :
  1177. res := SysHandleErrorFrame(205, frame, true);
  1178. STATUS_FLOAT_UNDERFLOW :
  1179. res := SysHandleErrorFrame(206, frame, true);
  1180. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  1181. STATUS_FLOAT_INVALID_OPERATION,
  1182. STATUS_FLOAT_STACK_CHECK :
  1183. res := SysHandleErrorFrame(207, frame, true);
  1184. STATUS_INTEGER_OVERFLOW :
  1185. res := SysHandleErrorFrame(215, frame, false);
  1186. STATUS_ACCESS_VIOLATION,
  1187. STATUS_FLOAT_DENORMAL_OPERAND :
  1188. res := SysHandleErrorFrame(216, frame, true);
  1189. else begin
  1190. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1191. res := SysHandleErrorFrame(217, frame, true);
  1192. end;
  1193. end;
  1194. syswin32_i386_exception_handler := res;
  1195. end;
  1196. procedure install_exception_handlers;
  1197. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1198. var
  1199. oldexceptaddr,
  1200. newexceptaddr : Longint;
  1201. {$endif SYSTEMEXCEPTIONDEBUG}
  1202. begin
  1203. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1204. asm
  1205. movl $0,%eax
  1206. movl %fs:(%eax),%eax
  1207. movl %eax,oldexceptaddr
  1208. end;
  1209. {$endif SYSTEMEXCEPTIONDEBUG}
  1210. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  1211. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1212. asm
  1213. movl $0,%eax
  1214. movl %fs:(%eax),%eax
  1215. movl %eax,newexceptaddr
  1216. end;
  1217. if IsConsole then
  1218. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  1219. ' new exception ',hexstr(newexceptaddr,8));
  1220. {$endif SYSTEMEXCEPTIONDEBUG}
  1221. end;
  1222. procedure remove_exception_handlers;
  1223. begin
  1224. SetUnhandledExceptionFilter(nil);
  1225. end;
  1226. {$else not i386 (Processor specific !!)}
  1227. procedure install_exception_handlers;
  1228. begin
  1229. end;
  1230. procedure remove_exception_handlers;
  1231. begin
  1232. end;
  1233. {$endif Set_i386_Exception_handler}
  1234. {****************************************************************************
  1235. Error Message writing using messageboxes
  1236. ****************************************************************************}
  1237. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  1238. external 'user32' name 'MessageBoxA';
  1239. const
  1240. ErrorBufferLength = 1024;
  1241. var
  1242. ErrorBuf : array[0..ErrorBufferLength] of char;
  1243. ErrorLen : longint;
  1244. Function ErrorWrite(Var F: TextRec): Integer;
  1245. {
  1246. An error message should always end with #13#10#13#10
  1247. }
  1248. var
  1249. p : pchar;
  1250. i : longint;
  1251. Begin
  1252. if F.BufPos>0 then
  1253. begin
  1254. if F.BufPos+ErrorLen>ErrorBufferLength then
  1255. i:=ErrorBufferLength-ErrorLen
  1256. else
  1257. i:=F.BufPos;
  1258. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1259. inc(ErrorLen,i);
  1260. ErrorBuf[ErrorLen]:=#0;
  1261. end;
  1262. if ErrorLen>3 then
  1263. begin
  1264. p:=@ErrorBuf[ErrorLen];
  1265. for i:=1 to 4 do
  1266. begin
  1267. dec(p);
  1268. if not(p^ in [#10,#13]) then
  1269. break;
  1270. end;
  1271. end;
  1272. if ErrorLen=ErrorBufferLength then
  1273. i:=4;
  1274. if (i=4) then
  1275. begin
  1276. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1277. ErrorLen:=0;
  1278. end;
  1279. F.BufPos:=0;
  1280. ErrorWrite:=0;
  1281. End;
  1282. Function ErrorClose(Var F: TextRec): Integer;
  1283. begin
  1284. if ErrorLen>0 then
  1285. begin
  1286. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1287. ErrorLen:=0;
  1288. end;
  1289. ErrorLen:=0;
  1290. ErrorClose:=0;
  1291. end;
  1292. Function ErrorOpen(Var F: TextRec): Integer;
  1293. Begin
  1294. TextRec(F).InOutFunc:=@ErrorWrite;
  1295. TextRec(F).FlushFunc:=@ErrorWrite;
  1296. TextRec(F).CloseFunc:=@ErrorClose;
  1297. ErrorOpen:=0;
  1298. End;
  1299. procedure AssignError(Var T: Text);
  1300. begin
  1301. Assign(T,'');
  1302. TextRec(T).OpenFunc:=@ErrorOpen;
  1303. Rewrite(T);
  1304. end;
  1305. const
  1306. Exe_entry_code : pointer = @Exe_entry;
  1307. Dll_entry_code : pointer = @Dll_entry;
  1308. begin
  1309. { get some helpful informations }
  1310. GetStartupInfo(@startupinfo);
  1311. { some misc Win32 stuff }
  1312. hprevinst:=0;
  1313. if not IsLibrary then
  1314. HInstance:=getmodulehandle(GetCommandFile);
  1315. MainInstance:=HInstance;
  1316. { No idea how to know this issue !! }
  1317. IsMultithreaded:=false;
  1318. cmdshow:=startupinfo.wshowwindow;
  1319. { to test stack depth }
  1320. loweststack:=maxlongint;
  1321. { real test stack depth }
  1322. { stacklimit := setupstack; }
  1323. {$ifdef MT}
  1324. { allocate one threadvar entry from windows, we use this entry }
  1325. { for a pointer to our threadvars }
  1326. dataindex:=TlsAlloc;
  1327. { the exceptions use threadvars so do this _before_ initexceptions }
  1328. AllocateThreadVars;
  1329. {$endif MT}
  1330. { Setup heap }
  1331. InitHeap;
  1332. InitExceptions;
  1333. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1334. displayed in and messagebox }
  1335. StdInputHandle:=longint(GetStdHandle(STD_INPUT_HANDLE));
  1336. StdOutputHandle:=longint(GetStdHandle(STD_OUTPUT_HANDLE));
  1337. StdErrorHandle:=longint(GetStdHandle(STD_ERROR_HANDLE));
  1338. if not IsConsole then
  1339. begin
  1340. AssignError(stderr);
  1341. AssignError(stdout);
  1342. Assign(Output,'');
  1343. Assign(Input,'');
  1344. end
  1345. else
  1346. begin
  1347. OpenStdIO(Input,fmInput,StdInputHandle);
  1348. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1349. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1350. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1351. end;
  1352. { Arguments }
  1353. setup_arguments;
  1354. { Reset IO Error }
  1355. InOutRes:=0;
  1356. { Reset internal error variable }
  1357. errno:=0;
  1358. end.
  1359. {
  1360. $Log$
  1361. Revision 1.10 2001-06-01 22:23:21 peter
  1362. * same argument parsing -"abc" becomes -abc. This is compatible with
  1363. delphi and with unix shells (merged)
  1364. Revision 1.9 2001/03/21 23:29:40 florian
  1365. + sLineBreak and misc. stuff for Kylix compatiblity
  1366. Revision 1.8 2001/03/21 21:08:20 hajny
  1367. * GetDir fixed
  1368. Revision 1.7 2001/03/16 20:09:58 hajny
  1369. * universal FExpand
  1370. Revision 1.6 2001/02/20 21:31:12 peter
  1371. * chdir,mkdir,rmdir with empty string fixed
  1372. Revision 1.5 2001/01/26 16:38:03 florian
  1373. *** empty log message ***
  1374. Revision 1.4 2001/01/24 21:47:38 florian
  1375. + more MT stuff added
  1376. Revision 1.3 2001/01/05 15:44:35 florian
  1377. * some stuff for MT
  1378. Revision 1.2 2000/12/18 17:28:58 jonas
  1379. * fixed range check errors
  1380. Revision 1.1 2000/10/15 08:19:49 peter
  1381. * system unit rename for 1.1 branch
  1382. Revision 1.6 2000/10/13 12:01:52 peter
  1383. * fixed exception callback
  1384. Revision 1.5 2000/10/11 16:05:55 peter
  1385. * stdcall for callbacks (merged)
  1386. Revision 1.4 2000/09/11 20:19:28 florian
  1387. * complete exception handling provided by Thomas Schatzl
  1388. Revision 1.3 2000/09/04 19:36:59 peter
  1389. * new heapalloc calls, patch from Thomas Schatzl
  1390. Revision 1.2 2000/07/13 11:33:58 michael
  1391. + removed logs
  1392. }