system.pp 44 KB

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