system.pp 44 KB

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