system.pp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546
  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. { always allocate, even if length is zero, since }
  596. { the arg. is still present! }
  597. sysreallocmem(argv[idx],len+1);
  598. end;
  599. begin
  600. { create commandline, it starts with the executed filename which is argv[0] }
  601. { Win32 passes the command NOT via the args, but via getmodulefilename}
  602. count:=0;
  603. argv:=nil;
  604. argvlen:=0;
  605. pc:=getcommandfile;
  606. Arglen:=0;
  607. repeat
  608. Inc(Arglen);
  609. until (pc[Arglen]=#0);
  610. allocarg(count,arglen);
  611. move(pc^,argv[count]^,arglen);
  612. { Setup cmdline variable }
  613. cmdline:=GetCommandLine;
  614. { process arguments }
  615. pc:=cmdline;
  616. {$IfDef SYSTEM_DEBUG_STARTUP}
  617. Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
  618. {$EndIf }
  619. while pc^<>#0 do
  620. begin
  621. { skip leading spaces }
  622. while pc^ in [#1..#32] do
  623. inc(pc);
  624. if pc^=#0 then
  625. break;
  626. { calc argument length }
  627. quote:=' ';
  628. argstart:=pc;
  629. arglen:=0;
  630. while (pc^<>#0) do
  631. begin
  632. case pc^ of
  633. #1..#32 :
  634. begin
  635. if quote<>' ' then
  636. inc(arglen)
  637. else
  638. break;
  639. end;
  640. '"' :
  641. begin
  642. if quote<>'''' then
  643. begin
  644. if pchar(pc+1)^<>'"' then
  645. begin
  646. if quote='"' then
  647. quote:=' '
  648. else
  649. quote:='"';
  650. end
  651. else
  652. inc(pc);
  653. end
  654. else
  655. inc(arglen);
  656. end;
  657. '''' :
  658. begin
  659. if quote<>'"' then
  660. begin
  661. if pchar(pc+1)^<>'''' then
  662. begin
  663. if quote='''' then
  664. quote:=' '
  665. else
  666. quote:='''';
  667. end
  668. else
  669. inc(pc);
  670. end
  671. else
  672. inc(arglen);
  673. end;
  674. else
  675. inc(arglen);
  676. end;
  677. inc(pc);
  678. end;
  679. { copy argument }
  680. { Don't copy the first one, it is already there.}
  681. If Count<>0 then
  682. begin
  683. allocarg(count,arglen);
  684. quote:=' ';
  685. pc:=argstart;
  686. arg:=argv[count];
  687. while (pc^<>#0) do
  688. begin
  689. case pc^ of
  690. #1..#32 :
  691. begin
  692. if quote<>' ' then
  693. begin
  694. arg^:=pc^;
  695. inc(arg);
  696. end
  697. else
  698. break;
  699. end;
  700. '"' :
  701. begin
  702. if quote<>'''' then
  703. begin
  704. if pchar(pc+1)^<>'"' then
  705. begin
  706. if quote='"' then
  707. quote:=' '
  708. else
  709. quote:='"';
  710. end
  711. else
  712. inc(pc);
  713. end
  714. else
  715. begin
  716. arg^:=pc^;
  717. inc(arg);
  718. end;
  719. end;
  720. '''' :
  721. begin
  722. if quote<>'"' then
  723. begin
  724. if pchar(pc+1)^<>'''' then
  725. begin
  726. if quote='''' then
  727. quote:=' '
  728. else
  729. quote:='''';
  730. end
  731. else
  732. inc(pc);
  733. end
  734. else
  735. begin
  736. arg^:=pc^;
  737. inc(arg);
  738. end;
  739. end;
  740. else
  741. begin
  742. arg^:=pc^;
  743. inc(arg);
  744. end;
  745. end;
  746. inc(pc);
  747. end;
  748. arg^:=#0;
  749. end;
  750. {$IfDef SYSTEM_DEBUG_STARTUP}
  751. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  752. {$EndIf SYSTEM_DEBUG_STARTUP}
  753. inc(count);
  754. end;
  755. { get argc and create an nil entry }
  756. argc:=count;
  757. allocarg(argc,0);
  758. { free unused memory }
  759. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  760. end;
  761. {*****************************************************************************
  762. System Dependent Exit code
  763. *****************************************************************************}
  764. procedure install_exception_handlers;forward;
  765. procedure remove_exception_handlers;forward;
  766. procedure PascalMain;external name 'PASCALMAIN';
  767. procedure fpc_do_exit;external name 'FPC_DO_EXIT';
  768. Procedure ExitDLL(Exitcode : longint); forward;
  769. Procedure system_exit;
  770. begin
  771. { don't call ExitProcess inside
  772. the DLL exit code !!
  773. This crashes Win95 at least PM }
  774. if IsLibrary then
  775. ExitDLL(ExitCode);
  776. if not IsConsole then
  777. begin
  778. Close(stderr);
  779. Close(stdout);
  780. { what about Input and Output ?? PM }
  781. end;
  782. remove_exception_handlers;
  783. ExitProcess(ExitCode);
  784. end;
  785. var
  786. { value of the stack segment
  787. to check if the call stack can be written on exceptions }
  788. _SS : longint;
  789. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  790. begin
  791. IsLibrary:=false;
  792. { install the handlers for exe only ?
  793. or should we install them for DLL also ? (PM) }
  794. install_exception_handlers;
  795. { This strange construction is needed to solve the _SS problem
  796. with a smartlinked syswin32 (PFV) }
  797. asm
  798. { allocate space for an exception frame }
  799. pushl $0
  800. pushl %fs:(0)
  801. { movl %esp,%fs:(0)
  802. but don't insert it as it doesn't
  803. point to anything yet
  804. this will be used in signals unit }
  805. movl %esp,%eax
  806. movl %eax,System_exception_frame
  807. pushl %ebp
  808. xorl %ebp,%ebp
  809. movl %esp,%eax
  810. movl %eax,Win32StackTop
  811. movw %ss,%bp
  812. movl %ebp,_SS
  813. call SysResetFPU
  814. xorl %ebp,%ebp
  815. call PASCALMAIN
  816. popl %ebp
  817. end;
  818. { if we pass here there was no error ! }
  819. system_exit;
  820. end;
  821. Const
  822. { DllEntryPoint }
  823. DLL_PROCESS_ATTACH = 1;
  824. DLL_THREAD_ATTACH = 2;
  825. DLL_PROCESS_DETACH = 0;
  826. DLL_THREAD_DETACH = 3;
  827. Var
  828. DLLBuf : Jmp_buf;
  829. Const
  830. DLLExitOK : boolean = true;
  831. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  832. var
  833. res : longbool;
  834. begin
  835. IsLibrary:=true;
  836. Dll_entry:=false;
  837. case DLLreason of
  838. DLL_PROCESS_ATTACH :
  839. begin
  840. If SetJmp(DLLBuf) = 0 then
  841. begin
  842. if assigned(Dll_Process_Attach_Hook) then
  843. begin
  844. res:=Dll_Process_Attach_Hook(DllParam);
  845. if not res then
  846. exit(false);
  847. end;
  848. PASCALMAIN;
  849. Dll_entry:=true;
  850. end
  851. else
  852. Dll_entry:=DLLExitOK;
  853. end;
  854. DLL_THREAD_ATTACH :
  855. begin
  856. inc(Thread_count);
  857. {$warning Allocate Threadvars !}
  858. if assigned(Dll_Thread_Attach_Hook) then
  859. Dll_Thread_Attach_Hook(DllParam);
  860. Dll_entry:=true; { return value is ignored }
  861. end;
  862. DLL_THREAD_DETACH :
  863. begin
  864. dec(Thread_count);
  865. if assigned(Dll_Thread_Detach_Hook) then
  866. Dll_Thread_Detach_Hook(DllParam);
  867. {$warning Release Threadvars !}
  868. Dll_entry:=true; { return value is ignored }
  869. end;
  870. DLL_PROCESS_DETACH :
  871. begin
  872. Dll_entry:=true; { return value is ignored }
  873. If SetJmp(DLLBuf) = 0 then
  874. begin
  875. FPC_DO_EXIT;
  876. end;
  877. if assigned(Dll_Process_Detach_Hook) then
  878. Dll_Process_Detach_Hook(DllParam);
  879. end;
  880. end;
  881. end;
  882. Procedure ExitDLL(Exitcode : longint);
  883. begin
  884. DLLExitOK:=ExitCode=0;
  885. LongJmp(DLLBuf,1);
  886. end;
  887. //
  888. // Hardware exception handling
  889. //
  890. {$ifdef Set_i386_Exception_handler}
  891. {
  892. Error code definitions for the Win32 API functions
  893. Values are 32 bit values layed out as follows:
  894. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  895. 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
  896. +---+-+-+-----------------------+-------------------------------+
  897. |Sev|C|R| Facility | Code |
  898. +---+-+-+-----------------------+-------------------------------+
  899. where
  900. Sev - is the severity code
  901. 00 - Success
  902. 01 - Informational
  903. 10 - Warning
  904. 11 - Error
  905. C - is the Customer code flag
  906. R - is a reserved bit
  907. Facility - is the facility code
  908. Code - is the facility's status code
  909. }
  910. const
  911. SEVERITY_SUCCESS = $00000000;
  912. SEVERITY_INFORMATIONAL = $40000000;
  913. SEVERITY_WARNING = $80000000;
  914. SEVERITY_ERROR = $C0000000;
  915. const
  916. STATUS_SEGMENT_NOTIFICATION = $40000005;
  917. DBG_TERMINATE_THREAD = $40010003;
  918. DBG_TERMINATE_PROCESS = $40010004;
  919. DBG_CONTROL_C = $40010005;
  920. DBG_CONTROL_BREAK = $40010008;
  921. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  922. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  923. STATUS_BREAKPOINT = $80000003;
  924. STATUS_SINGLE_STEP = $80000004;
  925. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  926. STATUS_ACCESS_VIOLATION = $C0000005;
  927. STATUS_IN_PAGE_ERROR = $C0000006;
  928. STATUS_INVALID_HANDLE = $C0000008;
  929. STATUS_NO_MEMORY = $C0000017;
  930. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  931. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  932. STATUS_INVALID_DISPOSITION = $C0000026;
  933. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  934. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  935. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  936. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  937. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  938. STATUS_FLOAT_OVERFLOW = $C0000091;
  939. STATUS_FLOAT_STACK_CHECK = $C0000092;
  940. STATUS_FLOAT_UNDERFLOW = $C0000093;
  941. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  942. STATUS_INTEGER_OVERFLOW = $C0000095;
  943. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  944. STATUS_STACK_OVERFLOW = $C00000FD;
  945. STATUS_CONTROL_C_EXIT = $C000013A;
  946. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  947. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  948. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  949. EXCEPTION_EXECUTE_HANDLER = 1;
  950. EXCEPTION_CONTINUE_EXECUTION = -1;
  951. EXCEPTION_CONTINUE_SEARCH = 0;
  952. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  953. CONTEXT_X86 = $00010000;
  954. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  955. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  956. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  957. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  958. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  959. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  960. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  961. MAXIMUM_SUPPORTED_EXTENSION = 512;
  962. type
  963. PFloatingSaveArea = ^TFloatingSaveArea;
  964. TFloatingSaveArea = packed record
  965. ControlWord : Cardinal;
  966. StatusWord : Cardinal;
  967. TagWord : Cardinal;
  968. ErrorOffset : Cardinal;
  969. ErrorSelector : Cardinal;
  970. DataOffset : Cardinal;
  971. DataSelector : Cardinal;
  972. RegisterArea : array[0..79] of Byte;
  973. Cr0NpxState : Cardinal;
  974. end;
  975. PContext = ^TContext;
  976. TContext = packed record
  977. //
  978. // The flags values within this flag control the contents of
  979. // a CONTEXT record.
  980. //
  981. ContextFlags : Cardinal;
  982. //
  983. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  984. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  985. // included in CONTEXT_FULL.
  986. //
  987. Dr0, Dr1, Dr2,
  988. Dr3, Dr6, Dr7 : Cardinal;
  989. //
  990. // This section is specified/returned if the
  991. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  992. //
  993. FloatSave : TFloatingSaveArea;
  994. //
  995. // This section is specified/returned if the
  996. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  997. //
  998. SegGs, SegFs,
  999. SegEs, SegDs : Cardinal;
  1000. //
  1001. // This section is specified/returned if the
  1002. // ContextFlags word contains the flag CONTEXT_INTEGER.
  1003. //
  1004. Edi, Esi, Ebx,
  1005. Edx, Ecx, Eax : Cardinal;
  1006. //
  1007. // This section is specified/returned if the
  1008. // ContextFlags word contains the flag CONTEXT_CONTROL.
  1009. //
  1010. Ebp : Cardinal;
  1011. Eip : Cardinal;
  1012. SegCs : Cardinal;
  1013. EFlags, Esp, SegSs : Cardinal;
  1014. //
  1015. // This section is specified/returned if the ContextFlags word
  1016. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  1017. // The format and contexts are processor specific
  1018. //
  1019. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  1020. end;
  1021. type
  1022. PExceptionRecord = ^TExceptionRecord;
  1023. TExceptionRecord = packed record
  1024. ExceptionCode : Longint;
  1025. ExceptionFlags : Longint;
  1026. ExceptionRecord : PExceptionRecord;
  1027. ExceptionAddress : Pointer;
  1028. NumberParameters : Longint;
  1029. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  1030. end;
  1031. PExceptionPointers = ^TExceptionPointers;
  1032. TExceptionPointers = packed record
  1033. ExceptionRecord : PExceptionRecord;
  1034. ContextRecord : PContext;
  1035. end;
  1036. { type of functions that should be used for exception handling }
  1037. TTopLevelExceptionFilter = function (excep : PExceptionPointers) : Longint;stdcall;
  1038. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : TTopLevelExceptionFilter) : TTopLevelExceptionFilter;
  1039. external 'kernel32' name 'SetUnhandledExceptionFilter';
  1040. const
  1041. MaxExceptionLevel = 16;
  1042. exceptLevel : Byte = 0;
  1043. var
  1044. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  1045. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1046. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  1047. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1048. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  1049. begin
  1050. if IsConsole then begin
  1051. write(stderr,'HandleErrorAddrFrame(error=',error);
  1052. write(stderr,',addr=',hexstr(addr,8));
  1053. writeln(stderr,',frame=',hexstr(frame,8),')');
  1054. end;
  1055. HandleErrorAddrFrame(error,addr,frame);
  1056. end;
  1057. {$endif SYSTEMEXCEPTIONDEBUG}
  1058. procedure JumpToHandleErrorFrame;
  1059. var
  1060. eip, ebp, error : Longint;
  1061. begin
  1062. // save ebp
  1063. asm
  1064. movl (%ebp),%eax
  1065. movl %eax,ebp
  1066. end;
  1067. if (exceptLevel > 0) then
  1068. dec(exceptLevel);
  1069. eip:=exceptEip[exceptLevel];
  1070. error:=exceptError[exceptLevel];
  1071. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1072. if IsConsole then
  1073. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  1074. {$endif SYSTEMEXCEPTIONDEBUG}
  1075. if resetFPU[exceptLevel] then asm
  1076. fninit
  1077. fldcw fpucw
  1078. end;
  1079. { build a fake stack }
  1080. asm
  1081. movl ebp,%eax
  1082. pushl %eax
  1083. movl eip,%eax
  1084. pushl %eax
  1085. movl error,%eax
  1086. pushl %eax
  1087. movl eip,%eax
  1088. pushl %eax
  1089. movl ebp,%ebp // Change frame pointer
  1090. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1091. jmpl DebugHandleErrorAddrFrame
  1092. {$else not SYSTEMEXCEPTIONDEBUG}
  1093. jmpl HandleErrorAddrFrame
  1094. {$endif SYSTEMEXCEPTIONDEBUG}
  1095. end;
  1096. end;
  1097. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  1098. var
  1099. frame,
  1100. res : longint;
  1101. function SysHandleErrorFrame(error, frame : Longint; must_reset_fpu : Boolean) : Longint;
  1102. begin
  1103. if (frame = 0) then
  1104. SysHandleErrorFrame:=EXCEPTION_CONTINUE_SEARCH
  1105. else begin
  1106. if (exceptLevel >= MaxExceptionLevel) then exit;
  1107. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  1108. exceptError[exceptLevel] := error;
  1109. resetFPU[exceptLevel] := must_reset_fpu;
  1110. inc(exceptLevel);
  1111. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  1112. excep^.ExceptionRecord^.ExceptionCode := 0;
  1113. SysHandleErrorFrame := EXCEPTION_CONTINUE_EXECUTION;
  1114. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1115. if IsConsole then begin
  1116. writeln(stderr,'Exception Continue Exception set at ',
  1117. hexstr(exceptEip[exceptLevel],8));
  1118. writeln(stderr,'Eip changed to ',
  1119. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1120. end;
  1121. {$endif SYSTEMEXCEPTIONDEBUG}
  1122. end;
  1123. end;
  1124. begin
  1125. if excep^.ContextRecord^.SegSs=_SS then
  1126. frame := excep^.ContextRecord^.Ebp
  1127. else
  1128. frame := 0;
  1129. res := EXCEPTION_CONTINUE_SEARCH;
  1130. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1131. if IsConsole then Writeln(stderr,'Exception ',
  1132. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  1133. {$endif SYSTEMEXCEPTIONDEBUG}
  1134. case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
  1135. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1136. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1137. res := SysHandleErrorFrame(200, frame, true);
  1138. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1139. res := SysHandleErrorFrame(201, frame, false);
  1140. STATUS_STACK_OVERFLOW :
  1141. res := SysHandleErrorFrame(202, frame, false);
  1142. STATUS_FLOAT_OVERFLOW :
  1143. res := SysHandleErrorFrame(205, frame, true);
  1144. STATUS_FLOAT_UNDERFLOW :
  1145. res := SysHandleErrorFrame(206, frame, true);
  1146. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  1147. STATUS_FLOAT_INVALID_OPERATION,
  1148. STATUS_FLOAT_STACK_CHECK :
  1149. res := SysHandleErrorFrame(207, frame, true);
  1150. STATUS_INTEGER_OVERFLOW :
  1151. res := SysHandleErrorFrame(215, frame, false);
  1152. STATUS_ACCESS_VIOLATION,
  1153. STATUS_FLOAT_DENORMAL_OPERAND :
  1154. res := SysHandleErrorFrame(216, frame, true);
  1155. else begin
  1156. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1157. res := SysHandleErrorFrame(217, frame, true);
  1158. end;
  1159. end;
  1160. syswin32_i386_exception_handler := res;
  1161. end;
  1162. procedure install_exception_handlers;
  1163. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1164. var
  1165. oldexceptaddr,
  1166. newexceptaddr : Longint;
  1167. {$endif SYSTEMEXCEPTIONDEBUG}
  1168. begin
  1169. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1170. asm
  1171. movl $0,%eax
  1172. movl %fs:(%eax),%eax
  1173. movl %eax,oldexceptaddr
  1174. end;
  1175. {$endif SYSTEMEXCEPTIONDEBUG}
  1176. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  1177. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1178. asm
  1179. movl $0,%eax
  1180. movl %fs:(%eax),%eax
  1181. movl %eax,newexceptaddr
  1182. end;
  1183. if IsConsole then
  1184. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  1185. ' new exception ',hexstr(newexceptaddr,8));
  1186. {$endif SYSTEMEXCEPTIONDEBUG}
  1187. end;
  1188. procedure remove_exception_handlers;
  1189. begin
  1190. SetUnhandledExceptionFilter(nil);
  1191. end;
  1192. {$else not i386 (Processor specific !!)}
  1193. procedure install_exception_handlers;
  1194. begin
  1195. end;
  1196. procedure remove_exception_handlers;
  1197. begin
  1198. end;
  1199. {$endif Set_i386_Exception_handler}
  1200. {****************************************************************************
  1201. Error Message writing using messageboxes
  1202. ****************************************************************************}
  1203. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  1204. external 'user32' name 'MessageBoxA';
  1205. const
  1206. ErrorBufferLength = 1024;
  1207. var
  1208. ErrorBuf : array[0..ErrorBufferLength] of char;
  1209. ErrorLen : longint;
  1210. Function ErrorWrite(Var F: TextRec): Integer;
  1211. {
  1212. An error message should always end with #13#10#13#10
  1213. }
  1214. var
  1215. p : pchar;
  1216. i : longint;
  1217. Begin
  1218. if F.BufPos>0 then
  1219. begin
  1220. if F.BufPos+ErrorLen>ErrorBufferLength then
  1221. i:=ErrorBufferLength-ErrorLen
  1222. else
  1223. i:=F.BufPos;
  1224. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1225. inc(ErrorLen,i);
  1226. ErrorBuf[ErrorLen]:=#0;
  1227. end;
  1228. if ErrorLen>3 then
  1229. begin
  1230. p:=@ErrorBuf[ErrorLen];
  1231. for i:=1 to 4 do
  1232. begin
  1233. dec(p);
  1234. if not(p^ in [#10,#13]) then
  1235. break;
  1236. end;
  1237. end;
  1238. if ErrorLen=ErrorBufferLength then
  1239. i:=4;
  1240. if (i=4) then
  1241. begin
  1242. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1243. ErrorLen:=0;
  1244. end;
  1245. F.BufPos:=0;
  1246. ErrorWrite:=0;
  1247. End;
  1248. Function ErrorClose(Var F: TextRec): Integer;
  1249. begin
  1250. if ErrorLen>0 then
  1251. begin
  1252. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1253. ErrorLen:=0;
  1254. end;
  1255. ErrorLen:=0;
  1256. ErrorClose:=0;
  1257. end;
  1258. Function ErrorOpen(Var F: TextRec): Integer;
  1259. Begin
  1260. TextRec(F).InOutFunc:=@ErrorWrite;
  1261. TextRec(F).FlushFunc:=@ErrorWrite;
  1262. TextRec(F).CloseFunc:=@ErrorClose;
  1263. ErrorOpen:=0;
  1264. End;
  1265. procedure AssignError(Var T: Text);
  1266. begin
  1267. Assign(T,'');
  1268. TextRec(T).OpenFunc:=@ErrorOpen;
  1269. Rewrite(T);
  1270. end;
  1271. procedure SysInitStdIO;
  1272. begin
  1273. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1274. displayed in and messagebox }
  1275. StdInputHandle:=longint(GetStdHandle(cardinal(STD_INPUT_HANDLE)));
  1276. StdOutputHandle:=longint(GetStdHandle(cardinal(STD_OUTPUT_HANDLE)));
  1277. StdErrorHandle:=longint(GetStdHandle(cardinal(STD_ERROR_HANDLE)));
  1278. if not IsConsole then
  1279. begin
  1280. AssignError(stderr);
  1281. AssignError(stdout);
  1282. Assign(Output,'');
  1283. Assign(Input,'');
  1284. end
  1285. else
  1286. begin
  1287. OpenStdIO(Input,fmInput,StdInputHandle);
  1288. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1289. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1290. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1291. end;
  1292. end;
  1293. const
  1294. Exe_entry_code : pointer = @Exe_entry;
  1295. Dll_entry_code : pointer = @Dll_entry;
  1296. begin
  1297. StackLength := InitialStkLen;
  1298. StackBottom := Sptr - StackLength;
  1299. { get some helpful informations }
  1300. GetStartupInfo(@startupinfo);
  1301. { some misc Win32 stuff }
  1302. hprevinst:=0;
  1303. if not IsLibrary then
  1304. HInstance:=getmodulehandle(GetCommandFile);
  1305. MainInstance:=HInstance;
  1306. cmdshow:=startupinfo.wshowwindow;
  1307. { Setup heap }
  1308. InitHeap;
  1309. SysInitExceptions;
  1310. SysInitStdIO;
  1311. { Arguments }
  1312. setup_arguments;
  1313. { Reset IO Error }
  1314. InOutRes:=0;
  1315. { Reset internal error variable }
  1316. errno:=0;
  1317. {$ifdef HASVARIANT}
  1318. initvariantmanager;
  1319. {$endif HASVARIANT}
  1320. end.
  1321. {
  1322. $Log$
  1323. Revision 1.36 2002-10-31 15:17:58 carl
  1324. * always allocate argument even if its empty (bugfix web bug 2202)
  1325. Revision 1.35 2002/10/14 20:40:22 florian
  1326. * InitFPU renamed to SysResetFPU
  1327. Revision 1.34 2002/10/14 19:39:17 peter
  1328. * threads unit added for thread support
  1329. Revision 1.33 2002/10/13 09:28:45 florian
  1330. + call to initvariantmanager inserted
  1331. Revision 1.32 2002/09/07 21:28:10 carl
  1332. - removed os_types
  1333. * fix range check errors
  1334. Revision 1.31 2002/09/07 16:01:29 peter
  1335. * old logs removed and tabs fixed
  1336. Revision 1.30 2002/08/26 13:49:18 pierre
  1337. * fix bug report 2086
  1338. Revision 1.29 2002/07/28 20:43:49 florian
  1339. * several fixes for linux/powerpc
  1340. * several fixes to MT
  1341. Revision 1.28 2002/07/01 16:29:05 peter
  1342. * sLineBreak changed to normal constant like Kylix
  1343. Revision 1.27 2002/06/04 09:25:14 pierre
  1344. * Rename HeapSize to WinAPIHeapSize to avoid conflict with general function
  1345. Revision 1.26 2002/04/12 17:45:13 carl
  1346. + generic stack checking
  1347. Revision 1.25 2002/03/11 19:10:33 peter
  1348. * Regenerated with updated fpcmake
  1349. Revision 1.24 2002/01/30 14:57:11 pierre
  1350. * fix compilation failure
  1351. Revision 1.23 2002/01/25 16:23:03 peter
  1352. * merged filesearch() fix
  1353. }