system.pp 46 KB

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