system.pp 45 KB

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