2
0

system.pp 45 KB

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