system.pp 44 KB

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