system.pp 45 KB

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