system.pp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635
  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) : longbool;
  516. external 'kernel32' name 'CreateDirectoryA';
  517. function RemoveDirectory(name:pointer):longbool;
  518. external 'kernel32' name 'RemoveDirectoryA';
  519. function SetCurrentDirectory(name : pointer) : longbool;
  520. external 'kernel32' name 'SetCurrentDirectoryA';
  521. function GetCurrentDirectory(bufsize : longint;name : pchar) : longbool;
  522. external 'kernel32' name 'GetCurrentDirectoryA';
  523. type
  524. TDirFnType=function(name:pointer):longbool;
  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 not aFunc(@buffer) then
  533. begin
  534. errno:=GetLastError;
  535. Errno2InoutRes;
  536. end;
  537. end;
  538. function CreateDirectoryTrunc(name:pointer):longbool;
  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 not SetCurrentDirectory(@Drive) then
  573. begin
  574. errno := word (GetLastError);
  575. Errno2InoutRes;
  576. Dir := char (DriveNr + 64) + ':\';
  577. SetCurrentDirectory(@SaveBuf);
  578. Exit;
  579. end;
  580. end;
  581. GetCurrentDirectory(SizeOf(DirBuf),DirBuf);
  582. if not defaultdrive then
  583. SetCurrentDirectory(@SaveBuf);
  584. dir:=strpas(DirBuf);
  585. if not FileNameCaseSensitive then
  586. dir:=upcase(dir);
  587. end;
  588. {*****************************************************************************
  589. Thread Handling
  590. *****************************************************************************}
  591. const
  592. fpucw : word = $1332;
  593. procedure InitFPU;assembler;
  594. asm
  595. fninit
  596. fldcw fpucw
  597. end;
  598. { include threading stuff, this is os independend part }
  599. {$I thread.inc}
  600. {*****************************************************************************
  601. SystemUnit Initialization
  602. *****************************************************************************}
  603. { Startup }
  604. procedure GetStartupInfo(p : pointer);
  605. external 'kernel32' name 'GetStartupInfoA';
  606. function GetStdHandle(nStdHandle:DWORD):THANDLE;
  607. external 'kernel32' name 'GetStdHandle';
  608. { command line/enviroment functions }
  609. function GetCommandLine : pchar;
  610. external 'kernel32' name 'GetCommandLineA';
  611. var
  612. ModuleName : array[0..255] of char;
  613. function GetCommandFile:pchar;
  614. begin
  615. GetModuleFileName(0,@ModuleName,255);
  616. GetCommandFile:=@ModuleName;
  617. end;
  618. procedure setup_arguments;
  619. var
  620. arglen,
  621. count : longint;
  622. argstart,
  623. pc,arg : pchar;
  624. quote : char;
  625. argvlen : longint;
  626. procedure allocarg(idx,len:longint);
  627. begin
  628. if idx>=argvlen then
  629. begin
  630. argvlen:=(idx+8) and (not 7);
  631. sysreallocmem(argv,argvlen*sizeof(pointer));
  632. end;
  633. { use realloc to reuse already existing memory }
  634. if len<>0 then
  635. sysreallocmem(argv[idx],len+1);
  636. end;
  637. begin
  638. { create commandline, it starts with the executed filename which is argv[0] }
  639. { Win32 passes the command NOT via the args, but via getmodulefilename}
  640. count:=0;
  641. argv:=nil;
  642. argvlen:=0;
  643. pc:=getcommandfile;
  644. Arglen:=0;
  645. repeat
  646. Inc(Arglen);
  647. until (pc[Arglen]=#0);
  648. allocarg(count,arglen);
  649. move(pc^,argv[count]^,arglen);
  650. { Setup cmdline variable }
  651. cmdline:=GetCommandLine;
  652. { process arguments }
  653. pc:=cmdline;
  654. {$IfDef SYSTEM_DEBUG_STARTUP}
  655. Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
  656. {$EndIf }
  657. while pc^<>#0 do
  658. begin
  659. { skip leading spaces }
  660. while pc^ in [#1..#32] do
  661. inc(pc);
  662. if pc^=#0 then
  663. break;
  664. { calc argument length }
  665. quote:=' ';
  666. argstart:=pc;
  667. arglen:=0;
  668. while (pc^<>#0) do
  669. begin
  670. case pc^ of
  671. #1..#32 :
  672. begin
  673. if quote<>' ' then
  674. inc(arglen)
  675. else
  676. break;
  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. '''' :
  696. begin
  697. if quote<>'"' then
  698. begin
  699. if pchar(pc+1)^<>'''' then
  700. begin
  701. if quote='''' then
  702. quote:=' '
  703. else
  704. quote:='''';
  705. end
  706. else
  707. inc(pc);
  708. end
  709. else
  710. inc(arglen);
  711. end;
  712. else
  713. inc(arglen);
  714. end;
  715. inc(pc);
  716. end;
  717. { copy argument }
  718. { Don't copy the first one, it is already there.}
  719. If Count<>0 then
  720. begin
  721. allocarg(count,arglen);
  722. quote:=' ';
  723. pc:=argstart;
  724. arg:=argv[count];
  725. while (pc^<>#0) do
  726. begin
  727. case pc^ of
  728. #1..#32 :
  729. begin
  730. if quote<>' ' then
  731. begin
  732. arg^:=pc^;
  733. inc(arg);
  734. end
  735. else
  736. break;
  737. end;
  738. '"' :
  739. begin
  740. if quote<>'''' then
  741. begin
  742. if pchar(pc+1)^<>'"' then
  743. begin
  744. if quote='"' then
  745. quote:=' '
  746. else
  747. quote:='"';
  748. end
  749. else
  750. inc(pc);
  751. end
  752. else
  753. begin
  754. arg^:=pc^;
  755. inc(arg);
  756. end;
  757. end;
  758. '''' :
  759. begin
  760. if quote<>'"' then
  761. begin
  762. if pchar(pc+1)^<>'''' then
  763. begin
  764. if quote='''' then
  765. quote:=' '
  766. else
  767. quote:='''';
  768. end
  769. else
  770. inc(pc);
  771. end
  772. else
  773. begin
  774. arg^:=pc^;
  775. inc(arg);
  776. end;
  777. end;
  778. else
  779. begin
  780. arg^:=pc^;
  781. inc(arg);
  782. end;
  783. end;
  784. inc(pc);
  785. end;
  786. arg^:=#0;
  787. end;
  788. {$IfDef SYSTEM_DEBUG_STARTUP}
  789. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  790. {$EndIf SYSTEM_DEBUG_STARTUP}
  791. inc(count);
  792. end;
  793. { get argc and create an nil entry }
  794. argc:=count;
  795. allocarg(argc,0);
  796. { free unused memory }
  797. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  798. end;
  799. {*****************************************************************************
  800. System Dependent Exit code
  801. *****************************************************************************}
  802. procedure install_exception_handlers;forward;
  803. procedure remove_exception_handlers;forward;
  804. procedure PascalMain;external name 'PASCALMAIN';
  805. procedure fpc_do_exit;external name 'FPC_DO_EXIT';
  806. Procedure ExitDLL(Exitcode : longint); forward;
  807. Procedure system_exit;
  808. begin
  809. { don't call ExitProcess inside
  810. the DLL exit code !!
  811. This crashes Win95 at least PM }
  812. if IsLibrary then
  813. ExitDLL(ExitCode);
  814. if not IsConsole then
  815. begin
  816. Close(stderr);
  817. Close(stdout);
  818. { what about Input and Output ?? PM }
  819. end;
  820. remove_exception_handlers;
  821. ExitProcess(ExitCode);
  822. end;
  823. {$ifdef dummy}
  824. Function SetUpStack : longint;
  825. { This routine does the following : }
  826. { returns the value of the initial SP - __stklen }
  827. begin
  828. asm
  829. pushl %ebx
  830. pushl %eax
  831. movl __stklen,%ebx
  832. movl %esp,%eax
  833. subl %ebx,%eax
  834. movl %eax,__RESULT
  835. popl %eax
  836. popl %ebx
  837. end;
  838. end;
  839. {$endif}
  840. var
  841. { value of the stack segment
  842. to check if the call stack can be written on exceptions }
  843. _SS : longint;
  844. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  845. begin
  846. IsLibrary:=false;
  847. { install the handlers for exe only ?
  848. or should we install them for DLL also ? (PM) }
  849. install_exception_handlers;
  850. { This strange construction is needed to solve the _SS problem
  851. with a smartlinked syswin32 (PFV) }
  852. asm
  853. pushl %ebp
  854. xorl %ebp,%ebp
  855. movl %esp,%eax
  856. movl %eax,Win32StackTop
  857. movw %ss,%bp
  858. movl %ebp,_SS
  859. call InitFPU
  860. xorl %ebp,%ebp
  861. call PASCALMAIN
  862. popl %ebp
  863. end;
  864. { if we pass here there was no error ! }
  865. system_exit;
  866. end;
  867. Const
  868. { DllEntryPoint }
  869. DLL_PROCESS_ATTACH = 1;
  870. DLL_THREAD_ATTACH = 2;
  871. DLL_PROCESS_DETACH = 0;
  872. DLL_THREAD_DETACH = 3;
  873. Var
  874. DLLBuf : Jmp_buf;
  875. Const
  876. DLLExitOK : boolean = true;
  877. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  878. var
  879. res : longbool;
  880. begin
  881. IsLibrary:=true;
  882. Dll_entry:=false;
  883. case DLLreason of
  884. DLL_PROCESS_ATTACH :
  885. begin
  886. If SetJmp(DLLBuf) = 0 then
  887. begin
  888. if assigned(Dll_Process_Attach_Hook) then
  889. begin
  890. res:=Dll_Process_Attach_Hook(DllParam);
  891. if not res then
  892. exit(false);
  893. end;
  894. PASCALMAIN;
  895. Dll_entry:=true;
  896. end
  897. else
  898. Dll_entry:=DLLExitOK;
  899. end;
  900. DLL_THREAD_ATTACH :
  901. begin
  902. inc(Thread_count);
  903. {$ifdef MT}
  904. AllocateThreadVars;
  905. {$endif MT}
  906. if assigned(Dll_Thread_Attach_Hook) then
  907. Dll_Thread_Attach_Hook(DllParam);
  908. Dll_entry:=true; { return value is ignored }
  909. end;
  910. DLL_THREAD_DETACH :
  911. begin
  912. dec(Thread_count);
  913. if assigned(Dll_Thread_Detach_Hook) then
  914. Dll_Thread_Detach_Hook(DllParam);
  915. {$ifdef MT}
  916. ReleaseThreadVars;
  917. {$endif MT}
  918. Dll_entry:=true; { return value is ignored }
  919. end;
  920. DLL_PROCESS_DETACH :
  921. begin
  922. Dll_entry:=true; { return value is ignored }
  923. If SetJmp(DLLBuf) = 0 then
  924. begin
  925. FPC_DO_EXIT;
  926. end;
  927. if assigned(Dll_Process_Detach_Hook) then
  928. Dll_Process_Detach_Hook(DllParam);
  929. end;
  930. end;
  931. end;
  932. Procedure ExitDLL(Exitcode : longint);
  933. begin
  934. DLLExitOK:=ExitCode=0;
  935. LongJmp(DLLBuf,1);
  936. end;
  937. //
  938. // Hardware exception handling
  939. //
  940. {$ifdef Set_i386_Exception_handler}
  941. (*
  942. Error code definitions for the Win32 API functions
  943. Values are 32 bit values layed out as follows:
  944. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  945. 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
  946. +---+-+-+-----------------------+-------------------------------+
  947. |Sev|C|R| Facility | Code |
  948. +---+-+-+-----------------------+-------------------------------+
  949. where
  950. Sev - is the severity code
  951. 00 - Success
  952. 01 - Informational
  953. 10 - Warning
  954. 11 - Error
  955. C - is the Customer code flag
  956. R - is a reserved bit
  957. Facility - is the facility code
  958. Code - is the facility's status code
  959. *)
  960. const
  961. SEVERITY_SUCCESS = $00000000;
  962. SEVERITY_INFORMATIONAL = $40000000;
  963. SEVERITY_WARNING = $80000000;
  964. SEVERITY_ERROR = $C0000000;
  965. const
  966. STATUS_SEGMENT_NOTIFICATION = $40000005;
  967. DBG_TERMINATE_THREAD = $40010003;
  968. DBG_TERMINATE_PROCESS = $40010004;
  969. DBG_CONTROL_C = $40010005;
  970. DBG_CONTROL_BREAK = $40010008;
  971. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  972. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  973. STATUS_BREAKPOINT = $80000003;
  974. STATUS_SINGLE_STEP = $80000004;
  975. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  976. STATUS_ACCESS_VIOLATION = $C0000005;
  977. STATUS_IN_PAGE_ERROR = $C0000006;
  978. STATUS_INVALID_HANDLE = $C0000008;
  979. STATUS_NO_MEMORY = $C0000017;
  980. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  981. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  982. STATUS_INVALID_DISPOSITION = $C0000026;
  983. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  984. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  985. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  986. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  987. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  988. STATUS_FLOAT_OVERFLOW = $C0000091;
  989. STATUS_FLOAT_STACK_CHECK = $C0000092;
  990. STATUS_FLOAT_UNDERFLOW = $C0000093;
  991. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  992. STATUS_INTEGER_OVERFLOW = $C0000095;
  993. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  994. STATUS_STACK_OVERFLOW = $C00000FD;
  995. STATUS_CONTROL_C_EXIT = $C000013A;
  996. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  997. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  998. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  999. EXCEPTION_EXECUTE_HANDLER = 1;
  1000. EXCEPTION_CONTINUE_EXECUTION = -1;
  1001. EXCEPTION_CONTINUE_SEARCH = 0;
  1002. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  1003. CONTEXT_X86 = $00010000;
  1004. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  1005. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  1006. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  1007. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  1008. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  1009. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  1010. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  1011. MAXIMUM_SUPPORTED_EXTENSION = 512;
  1012. type
  1013. PFloatingSaveArea = ^TFloatingSaveArea;
  1014. TFloatingSaveArea = packed record
  1015. ControlWord : Cardinal;
  1016. StatusWord : Cardinal;
  1017. TagWord : Cardinal;
  1018. ErrorOffset : Cardinal;
  1019. ErrorSelector : Cardinal;
  1020. DataOffset : Cardinal;
  1021. DataSelector : Cardinal;
  1022. RegisterArea : array[0..79] of Byte;
  1023. Cr0NpxState : Cardinal;
  1024. end;
  1025. PContext = ^TContext;
  1026. TContext = packed record
  1027. //
  1028. // The flags values within this flag control the contents of
  1029. // a CONTEXT record.
  1030. //
  1031. ContextFlags : Cardinal;
  1032. //
  1033. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  1034. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  1035. // included in CONTEXT_FULL.
  1036. //
  1037. Dr0, Dr1, Dr2,
  1038. Dr3, Dr6, Dr7 : Cardinal;
  1039. //
  1040. // This section is specified/returned if the
  1041. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  1042. //
  1043. FloatSave : TFloatingSaveArea;
  1044. //
  1045. // This section is specified/returned if the
  1046. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  1047. //
  1048. SegGs, SegFs,
  1049. SegEs, SegDs : Cardinal;
  1050. //
  1051. // This section is specified/returned if the
  1052. // ContextFlags word contains the flag CONTEXT_INTEGER.
  1053. //
  1054. Edi, Esi, Ebx,
  1055. Edx, Ecx, Eax : Cardinal;
  1056. //
  1057. // This section is specified/returned if the
  1058. // ContextFlags word contains the flag CONTEXT_CONTROL.
  1059. //
  1060. Ebp : Cardinal;
  1061. Eip : Cardinal;
  1062. SegCs : Cardinal;
  1063. EFlags, Esp, SegSs : Cardinal;
  1064. //
  1065. // This section is specified/returned if the ContextFlags word
  1066. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  1067. // The format and contexts are processor specific
  1068. //
  1069. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  1070. end;
  1071. type
  1072. PExceptionRecord = ^TExceptionRecord;
  1073. TExceptionRecord = packed record
  1074. ExceptionCode : Longint;
  1075. ExceptionFlags : Longint;
  1076. ExceptionRecord : PExceptionRecord;
  1077. ExceptionAddress : Pointer;
  1078. NumberParameters : Longint;
  1079. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  1080. end;
  1081. PExceptionPointers = ^TExceptionPointers;
  1082. TExceptionPointers = packed record
  1083. ExceptionRecord : PExceptionRecord;
  1084. ContextRecord : PContext;
  1085. end;
  1086. { type of functions that should be used for exception handling }
  1087. TTopLevelExceptionFilter = function (excep : PExceptionPointers) : Longint;stdcall;
  1088. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : TTopLevelExceptionFilter) : TTopLevelExceptionFilter;
  1089. external 'kernel32' name 'SetUnhandledExceptionFilter';
  1090. const
  1091. MaxExceptionLevel = 16;
  1092. exceptLevel : Byte = 0;
  1093. var
  1094. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  1095. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1096. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  1097. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1098. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  1099. begin
  1100. if IsConsole then begin
  1101. write(stderr,'HandleErrorAddrFrame(error=',error);
  1102. write(stderr,',addr=',hexstr(addr,8));
  1103. writeln(stderr,',frame=',hexstr(frame,8),')');
  1104. end;
  1105. HandleErrorAddrFrame(error,addr,frame);
  1106. end;
  1107. {$endif SYSTEMEXCEPTIONDEBUG}
  1108. procedure JumpToHandleErrorFrame;
  1109. var
  1110. eip, ebp, error : Longint;
  1111. begin
  1112. // save ebp
  1113. asm
  1114. movl (%ebp),%eax
  1115. movl %eax,ebp
  1116. end;
  1117. if (exceptLevel > 0) then
  1118. dec(exceptLevel);
  1119. eip:=exceptEip[exceptLevel];
  1120. error:=exceptError[exceptLevel];
  1121. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1122. if IsConsole then
  1123. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  1124. end;
  1125. {$endif SYSTEMEXCEPTIONDEBUG}
  1126. if resetFPU[exceptLevel] then asm
  1127. fninit
  1128. fldcw fpucw
  1129. end;
  1130. { build a fake stack }
  1131. asm
  1132. movl ebp,%eax
  1133. pushl %eax
  1134. movl eip,%eax
  1135. pushl %eax
  1136. movl error,%eax
  1137. pushl %eax
  1138. movl eip,%eax
  1139. pushl %eax
  1140. movl ebp,%ebp // Change frame pointer
  1141. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1142. jmpl DebugHandleErrorAddrFrame
  1143. {$else not SYSTEMEXCEPTIONDEBUG}
  1144. jmpl HandleErrorAddrFrame
  1145. {$endif SYSTEMEXCEPTIONDEBUG}
  1146. end;
  1147. end;
  1148. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  1149. var
  1150. frame,
  1151. res : longint;
  1152. function SysHandleErrorFrame(error, frame : Longint; must_reset_fpu : Boolean) : Longint;
  1153. begin
  1154. if (frame = 0) then
  1155. SysHandleErrorFrame:=EXCEPTION_CONTINUE_SEARCH
  1156. else begin
  1157. if (exceptLevel >= MaxExceptionLevel) then exit;
  1158. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  1159. exceptError[exceptLevel] := error;
  1160. resetFPU[exceptLevel] := must_reset_fpu;
  1161. inc(exceptLevel);
  1162. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  1163. excep^.ExceptionRecord^.ExceptionCode := 0;
  1164. SysHandleErrorFrame := EXCEPTION_CONTINUE_EXECUTION;
  1165. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1166. if IsConsole then begin
  1167. writeln(stderr,'Exception Continue Exception set at ',
  1168. hexstr(exceptEip[exceptLevel],8));
  1169. writeln(stderr,'Eip changed to ',
  1170. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1171. end;
  1172. {$endif SYSTEMEXCEPTIONDEBUG}
  1173. end;
  1174. end;
  1175. begin
  1176. if excep^.ContextRecord^.SegSs=_SS then
  1177. frame := excep^.ContextRecord^.Ebp
  1178. else
  1179. frame := 0;
  1180. res := EXCEPTION_CONTINUE_SEARCH;
  1181. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1182. if IsConsole then Writeln(stderr,'Exception ',
  1183. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  1184. {$endif SYSTEMEXCEPTIONDEBUG}
  1185. case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
  1186. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1187. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1188. res := SysHandleErrorFrame(200, frame, true);
  1189. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1190. res := SysHandleErrorFrame(201, frame, false);
  1191. STATUS_STACK_OVERFLOW :
  1192. res := SysHandleErrorFrame(202, frame, false);
  1193. STATUS_FLOAT_OVERFLOW :
  1194. res := SysHandleErrorFrame(205, frame, true);
  1195. STATUS_FLOAT_UNDERFLOW :
  1196. res := SysHandleErrorFrame(206, frame, true);
  1197. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  1198. STATUS_FLOAT_INVALID_OPERATION,
  1199. STATUS_FLOAT_STACK_CHECK :
  1200. res := SysHandleErrorFrame(207, frame, true);
  1201. STATUS_INTEGER_OVERFLOW :
  1202. res := SysHandleErrorFrame(215, frame, false);
  1203. STATUS_ACCESS_VIOLATION,
  1204. STATUS_FLOAT_DENORMAL_OPERAND :
  1205. res := SysHandleErrorFrame(216, frame, true);
  1206. else begin
  1207. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1208. res := SysHandleErrorFrame(217, frame, true);
  1209. end;
  1210. end;
  1211. syswin32_i386_exception_handler := res;
  1212. end;
  1213. procedure install_exception_handlers;
  1214. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1215. var
  1216. oldexceptaddr,
  1217. newexceptaddr : Longint;
  1218. {$endif SYSTEMEXCEPTIONDEBUG}
  1219. begin
  1220. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1221. asm
  1222. movl $0,%eax
  1223. movl %fs:(%eax),%eax
  1224. movl %eax,oldexceptaddr
  1225. end;
  1226. {$endif SYSTEMEXCEPTIONDEBUG}
  1227. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  1228. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1229. asm
  1230. movl $0,%eax
  1231. movl %fs:(%eax),%eax
  1232. movl %eax,newexceptaddr
  1233. end;
  1234. if IsConsole then
  1235. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  1236. ' new exception ',hexstr(newexceptaddr,8));
  1237. {$endif SYSTEMEXCEPTIONDEBUG}
  1238. end;
  1239. procedure remove_exception_handlers;
  1240. begin
  1241. SetUnhandledExceptionFilter(nil);
  1242. end;
  1243. {$else not i386 (Processor specific !!)}
  1244. procedure install_exception_handlers;
  1245. begin
  1246. end;
  1247. procedure remove_exception_handlers;
  1248. begin
  1249. end;
  1250. {$endif Set_i386_Exception_handler}
  1251. {****************************************************************************
  1252. Error Message writing using messageboxes
  1253. ****************************************************************************}
  1254. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  1255. external 'user32' name 'MessageBoxA';
  1256. const
  1257. ErrorBufferLength = 1024;
  1258. var
  1259. ErrorBuf : array[0..ErrorBufferLength] of char;
  1260. ErrorLen : longint;
  1261. Function ErrorWrite(Var F: TextRec): Integer;
  1262. {
  1263. An error message should always end with #13#10#13#10
  1264. }
  1265. var
  1266. p : pchar;
  1267. i : longint;
  1268. Begin
  1269. if F.BufPos>0 then
  1270. begin
  1271. if F.BufPos+ErrorLen>ErrorBufferLength then
  1272. i:=ErrorBufferLength-ErrorLen
  1273. else
  1274. i:=F.BufPos;
  1275. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1276. inc(ErrorLen,i);
  1277. ErrorBuf[ErrorLen]:=#0;
  1278. end;
  1279. if ErrorLen>3 then
  1280. begin
  1281. p:=@ErrorBuf[ErrorLen];
  1282. for i:=1 to 4 do
  1283. begin
  1284. dec(p);
  1285. if not(p^ in [#10,#13]) then
  1286. break;
  1287. end;
  1288. end;
  1289. if ErrorLen=ErrorBufferLength then
  1290. i:=4;
  1291. if (i=4) then
  1292. begin
  1293. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1294. ErrorLen:=0;
  1295. end;
  1296. F.BufPos:=0;
  1297. ErrorWrite:=0;
  1298. End;
  1299. Function ErrorClose(Var F: TextRec): Integer;
  1300. begin
  1301. if ErrorLen>0 then
  1302. begin
  1303. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1304. ErrorLen:=0;
  1305. end;
  1306. ErrorLen:=0;
  1307. ErrorClose:=0;
  1308. end;
  1309. Function ErrorOpen(Var F: TextRec): Integer;
  1310. Begin
  1311. TextRec(F).InOutFunc:=@ErrorWrite;
  1312. TextRec(F).FlushFunc:=@ErrorWrite;
  1313. TextRec(F).CloseFunc:=@ErrorClose;
  1314. ErrorOpen:=0;
  1315. End;
  1316. procedure AssignError(Var T: Text);
  1317. begin
  1318. Assign(T,'');
  1319. TextRec(T).OpenFunc:=@ErrorOpen;
  1320. Rewrite(T);
  1321. end;
  1322. const
  1323. Exe_entry_code : pointer = @Exe_entry;
  1324. Dll_entry_code : pointer = @Dll_entry;
  1325. begin
  1326. { get some helpful informations }
  1327. GetStartupInfo(@startupinfo);
  1328. { some misc Win32 stuff }
  1329. hprevinst:=0;
  1330. if not IsLibrary then
  1331. HInstance:=getmodulehandle(GetCommandFile);
  1332. MainInstance:=HInstance;
  1333. { No idea how to know this issue !! }
  1334. IsMultithreaded:=false;
  1335. cmdshow:=startupinfo.wshowwindow;
  1336. { to test stack depth }
  1337. loweststack:=maxlongint;
  1338. { real test stack depth }
  1339. { stacklimit := setupstack; }
  1340. {$ifdef MT}
  1341. { allocate one threadvar entry from windows, we use this entry }
  1342. { for a pointer to our threadvars }
  1343. dataindex:=TlsAlloc;
  1344. { the exceptions use threadvars so do this _before_ initexceptions }
  1345. AllocateThreadVars;
  1346. {$endif MT}
  1347. { Setup heap }
  1348. InitHeap;
  1349. InitExceptions;
  1350. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1351. displayed in and messagebox }
  1352. StdInputHandle:=longint(GetStdHandle(STD_INPUT_HANDLE));
  1353. StdOutputHandle:=longint(GetStdHandle(STD_OUTPUT_HANDLE));
  1354. StdErrorHandle:=longint(GetStdHandle(STD_ERROR_HANDLE));
  1355. if not IsConsole then
  1356. begin
  1357. AssignError(stderr);
  1358. AssignError(stdout);
  1359. Assign(Output,'');
  1360. Assign(Input,'');
  1361. end
  1362. else
  1363. begin
  1364. OpenStdIO(Input,fmInput,StdInputHandle);
  1365. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1366. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1367. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1368. end;
  1369. { Arguments }
  1370. setup_arguments;
  1371. { Reset IO Error }
  1372. InOutRes:=0;
  1373. { Reset internal error variable }
  1374. errno:=0;
  1375. end.
  1376. {
  1377. $Log$
  1378. Revision 1.16 2001-07-30 20:53:50 peter
  1379. * fixed getdir() that was broken when a directory on a different drive
  1380. was asked
  1381. Revision 1.15 2001/06/30 18:55:48 hajny
  1382. * GetDir fix for inaccessible drives
  1383. Revision 1.14 2001/06/18 14:26:16 jonas
  1384. * move platform independent constant declarations after inclusion of
  1385. systemh.inc
  1386. Revision 1.13 2001/06/13 22:20:11 hajny
  1387. + platform specific information
  1388. Revision 1.12 2001/06/10 17:56:57 hajny
  1389. * errno changed to a threadvar if MT enabled
  1390. Revision 1.11 2001/06/07 21:16:30 peter
  1391. * fixed empty arguments
  1392. Revision 1.10 2001/06/01 22:23:21 peter
  1393. * same argument parsing -"abc" becomes -abc. This is compatible with
  1394. delphi and with unix shells (merged)
  1395. Revision 1.9 2001/03/21 23:29:40 florian
  1396. + sLineBreak and misc. stuff for Kylix compatiblity
  1397. Revision 1.8 2001/03/21 21:08:20 hajny
  1398. * GetDir fixed
  1399. Revision 1.7 2001/03/16 20:09:58 hajny
  1400. * universal FExpand
  1401. Revision 1.6 2001/02/20 21:31:12 peter
  1402. * chdir,mkdir,rmdir with empty string fixed
  1403. Revision 1.5 2001/01/26 16:38:03 florian
  1404. *** empty log message ***
  1405. Revision 1.4 2001/01/24 21:47:38 florian
  1406. + more MT stuff added
  1407. Revision 1.3 2001/01/05 15:44:35 florian
  1408. * some stuff for MT
  1409. Revision 1.2 2000/12/18 17:28:58 jonas
  1410. * fixed range check errors
  1411. Revision 1.1 2000/10/15 08:19:49 peter
  1412. * system unit rename for 1.1 branch
  1413. Revision 1.6 2000/10/13 12:01:52 peter
  1414. * fixed exception callback
  1415. Revision 1.5 2000/10/11 16:05:55 peter
  1416. * stdcall for callbacks (merged)
  1417. Revision 1.4 2000/09/11 20:19:28 florian
  1418. * complete exception handling provided by Thomas Schatzl
  1419. Revision 1.3 2000/09/04 19:36:59 peter
  1420. * new heapalloc calls, patch from Thomas Schatzl
  1421. Revision 1.2 2000/07/13 11:33:58 michael
  1422. + removed logs
  1423. }