system.pp 43 KB

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