system.pp 42 KB

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