system.pp 48 KB

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