system.pp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667
  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 WinAPIHeapSize(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 = ',WinAPIHeapSize(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. var
  833. { value of the stack segment
  834. to check if the call stack can be written on exceptions }
  835. _SS : longint;
  836. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  837. begin
  838. IsLibrary:=false;
  839. { install the handlers for exe only ?
  840. or should we install them for DLL also ? (PM) }
  841. install_exception_handlers;
  842. { This strange construction is needed to solve the _SS problem
  843. with a smartlinked syswin32 (PFV) }
  844. asm
  845. { allocate space for an excption frame }
  846. pushl $0
  847. pushl %fs:(0)
  848. { movl %esp,%fs:(0)
  849. but don't insert it as it doesn't
  850. point to anything yet
  851. this will be used in signals unit }
  852. movl %esp,%eax
  853. movl %eax,System_exception_frame
  854. pushl %ebp
  855. xorl %ebp,%ebp
  856. movl %esp,%eax
  857. movl %eax,Win32StackTop
  858. movw %ss,%bp
  859. movl %ebp,_SS
  860. call InitFPU
  861. xorl %ebp,%ebp
  862. call PASCALMAIN
  863. popl %ebp
  864. end;
  865. { if we pass here there was no error ! }
  866. system_exit;
  867. end;
  868. Const
  869. { DllEntryPoint }
  870. DLL_PROCESS_ATTACH = 1;
  871. DLL_THREAD_ATTACH = 2;
  872. DLL_PROCESS_DETACH = 0;
  873. DLL_THREAD_DETACH = 3;
  874. Var
  875. DLLBuf : Jmp_buf;
  876. Const
  877. DLLExitOK : boolean = true;
  878. function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
  879. var
  880. res : longbool;
  881. begin
  882. IsLibrary:=true;
  883. Dll_entry:=false;
  884. case DLLreason of
  885. DLL_PROCESS_ATTACH :
  886. begin
  887. If SetJmp(DLLBuf) = 0 then
  888. begin
  889. if assigned(Dll_Process_Attach_Hook) then
  890. begin
  891. res:=Dll_Process_Attach_Hook(DllParam);
  892. if not res then
  893. exit(false);
  894. end;
  895. PASCALMAIN;
  896. Dll_entry:=true;
  897. end
  898. else
  899. Dll_entry:=DLLExitOK;
  900. end;
  901. DLL_THREAD_ATTACH :
  902. begin
  903. inc(Thread_count);
  904. {$ifdef MT}
  905. AllocateThreadVars;
  906. {$endif MT}
  907. if assigned(Dll_Thread_Attach_Hook) then
  908. Dll_Thread_Attach_Hook(DllParam);
  909. Dll_entry:=true; { return value is ignored }
  910. end;
  911. DLL_THREAD_DETACH :
  912. begin
  913. dec(Thread_count);
  914. if assigned(Dll_Thread_Detach_Hook) then
  915. Dll_Thread_Detach_Hook(DllParam);
  916. {$ifdef MT}
  917. ReleaseThreadVars;
  918. {$endif MT}
  919. Dll_entry:=true; { return value is ignored }
  920. end;
  921. DLL_PROCESS_DETACH :
  922. begin
  923. Dll_entry:=true; { return value is ignored }
  924. If SetJmp(DLLBuf) = 0 then
  925. begin
  926. FPC_DO_EXIT;
  927. end;
  928. if assigned(Dll_Process_Detach_Hook) then
  929. Dll_Process_Detach_Hook(DllParam);
  930. end;
  931. end;
  932. end;
  933. Procedure ExitDLL(Exitcode : longint);
  934. begin
  935. DLLExitOK:=ExitCode=0;
  936. LongJmp(DLLBuf,1);
  937. end;
  938. //
  939. // Hardware exception handling
  940. //
  941. {$ifdef Set_i386_Exception_handler}
  942. (*
  943. Error code definitions for the Win32 API functions
  944. Values are 32 bit values layed out as follows:
  945. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  946. 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
  947. +---+-+-+-----------------------+-------------------------------+
  948. |Sev|C|R| Facility | Code |
  949. +---+-+-+-----------------------+-------------------------------+
  950. where
  951. Sev - is the severity code
  952. 00 - Success
  953. 01 - Informational
  954. 10 - Warning
  955. 11 - Error
  956. C - is the Customer code flag
  957. R - is a reserved bit
  958. Facility - is the facility code
  959. Code - is the facility's status code
  960. *)
  961. const
  962. SEVERITY_SUCCESS = $00000000;
  963. SEVERITY_INFORMATIONAL = $40000000;
  964. SEVERITY_WARNING = $80000000;
  965. SEVERITY_ERROR = $C0000000;
  966. const
  967. STATUS_SEGMENT_NOTIFICATION = $40000005;
  968. DBG_TERMINATE_THREAD = $40010003;
  969. DBG_TERMINATE_PROCESS = $40010004;
  970. DBG_CONTROL_C = $40010005;
  971. DBG_CONTROL_BREAK = $40010008;
  972. STATUS_GUARD_PAGE_VIOLATION = $80000001;
  973. STATUS_DATATYPE_MISALIGNMENT = $80000002;
  974. STATUS_BREAKPOINT = $80000003;
  975. STATUS_SINGLE_STEP = $80000004;
  976. DBG_EXCEPTION_NOT_HANDLED = $80010001;
  977. STATUS_ACCESS_VIOLATION = $C0000005;
  978. STATUS_IN_PAGE_ERROR = $C0000006;
  979. STATUS_INVALID_HANDLE = $C0000008;
  980. STATUS_NO_MEMORY = $C0000017;
  981. STATUS_ILLEGAL_INSTRUCTION = $C000001D;
  982. STATUS_NONCONTINUABLE_EXCEPTION = $C0000025;
  983. STATUS_INVALID_DISPOSITION = $C0000026;
  984. STATUS_ARRAY_BOUNDS_EXCEEDED = $C000008C;
  985. STATUS_FLOAT_DENORMAL_OPERAND = $C000008D;
  986. STATUS_FLOAT_DIVIDE_BY_ZERO = $C000008E;
  987. STATUS_FLOAT_INEXACT_RESULT = $C000008F;
  988. STATUS_FLOAT_INVALID_OPERATION = $C0000090;
  989. STATUS_FLOAT_OVERFLOW = $C0000091;
  990. STATUS_FLOAT_STACK_CHECK = $C0000092;
  991. STATUS_FLOAT_UNDERFLOW = $C0000093;
  992. STATUS_INTEGER_DIVIDE_BY_ZERO = $C0000094;
  993. STATUS_INTEGER_OVERFLOW = $C0000095;
  994. STATUS_PRIVILEGED_INSTRUCTION = $C0000096;
  995. STATUS_STACK_OVERFLOW = $C00000FD;
  996. STATUS_CONTROL_C_EXIT = $C000013A;
  997. STATUS_FLOAT_MULTIPLE_FAULTS = $C00002B4;
  998. STATUS_FLOAT_MULTIPLE_TRAPS = $C00002B5;
  999. STATUS_REG_NAT_CONSUMPTION = $C00002C9;
  1000. EXCEPTION_EXECUTE_HANDLER = 1;
  1001. EXCEPTION_CONTINUE_EXECUTION = -1;
  1002. EXCEPTION_CONTINUE_SEARCH = 0;
  1003. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  1004. CONTEXT_X86 = $00010000;
  1005. CONTEXT_CONTROL = CONTEXT_X86 or $00000001;
  1006. CONTEXT_INTEGER = CONTEXT_X86 or $00000002;
  1007. CONTEXT_SEGMENTS = CONTEXT_X86 or $00000004;
  1008. CONTEXT_FLOATING_POINT = CONTEXT_X86 or $00000008;
  1009. CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 or $00000010;
  1010. CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 or $00000020;
  1011. CONTEXT_FULL = CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_SEGMENTS;
  1012. MAXIMUM_SUPPORTED_EXTENSION = 512;
  1013. type
  1014. PFloatingSaveArea = ^TFloatingSaveArea;
  1015. TFloatingSaveArea = packed record
  1016. ControlWord : Cardinal;
  1017. StatusWord : Cardinal;
  1018. TagWord : Cardinal;
  1019. ErrorOffset : Cardinal;
  1020. ErrorSelector : Cardinal;
  1021. DataOffset : Cardinal;
  1022. DataSelector : Cardinal;
  1023. RegisterArea : array[0..79] of Byte;
  1024. Cr0NpxState : Cardinal;
  1025. end;
  1026. PContext = ^TContext;
  1027. TContext = packed record
  1028. //
  1029. // The flags values within this flag control the contents of
  1030. // a CONTEXT record.
  1031. //
  1032. ContextFlags : Cardinal;
  1033. //
  1034. // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
  1035. // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
  1036. // included in CONTEXT_FULL.
  1037. //
  1038. Dr0, Dr1, Dr2,
  1039. Dr3, Dr6, Dr7 : Cardinal;
  1040. //
  1041. // This section is specified/returned if the
  1042. // ContextFlags word contains the flag CONTEXT_FLOATING_POINT.
  1043. //
  1044. FloatSave : TFloatingSaveArea;
  1045. //
  1046. // This section is specified/returned if the
  1047. // ContextFlags word contains the flag CONTEXT_SEGMENTS.
  1048. //
  1049. SegGs, SegFs,
  1050. SegEs, SegDs : Cardinal;
  1051. //
  1052. // This section is specified/returned if the
  1053. // ContextFlags word contains the flag CONTEXT_INTEGER.
  1054. //
  1055. Edi, Esi, Ebx,
  1056. Edx, Ecx, Eax : Cardinal;
  1057. //
  1058. // This section is specified/returned if the
  1059. // ContextFlags word contains the flag CONTEXT_CONTROL.
  1060. //
  1061. Ebp : Cardinal;
  1062. Eip : Cardinal;
  1063. SegCs : Cardinal;
  1064. EFlags, Esp, SegSs : Cardinal;
  1065. //
  1066. // This section is specified/returned if the ContextFlags word
  1067. // contains the flag CONTEXT_EXTENDED_REGISTERS.
  1068. // The format and contexts are processor specific
  1069. //
  1070. ExtendedRegisters : array[0..MAXIMUM_SUPPORTED_EXTENSION-1] of Byte;
  1071. end;
  1072. type
  1073. PExceptionRecord = ^TExceptionRecord;
  1074. TExceptionRecord = packed record
  1075. ExceptionCode : Longint;
  1076. ExceptionFlags : Longint;
  1077. ExceptionRecord : PExceptionRecord;
  1078. ExceptionAddress : Pointer;
  1079. NumberParameters : Longint;
  1080. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of Pointer;
  1081. end;
  1082. PExceptionPointers = ^TExceptionPointers;
  1083. TExceptionPointers = packed record
  1084. ExceptionRecord : PExceptionRecord;
  1085. ContextRecord : PContext;
  1086. end;
  1087. { type of functions that should be used for exception handling }
  1088. TTopLevelExceptionFilter = function (excep : PExceptionPointers) : Longint;stdcall;
  1089. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : TTopLevelExceptionFilter) : TTopLevelExceptionFilter;
  1090. external 'kernel32' name 'SetUnhandledExceptionFilter';
  1091. const
  1092. MaxExceptionLevel = 16;
  1093. exceptLevel : Byte = 0;
  1094. var
  1095. exceptEip : array[0..MaxExceptionLevel-1] of Longint;
  1096. exceptError : array[0..MaxExceptionLevel-1] of Byte;
  1097. resetFPU : array[0..MaxExceptionLevel-1] of Boolean;
  1098. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1099. procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
  1100. begin
  1101. if IsConsole then begin
  1102. write(stderr,'HandleErrorAddrFrame(error=',error);
  1103. write(stderr,',addr=',hexstr(addr,8));
  1104. writeln(stderr,',frame=',hexstr(frame,8),')');
  1105. end;
  1106. HandleErrorAddrFrame(error,addr,frame);
  1107. end;
  1108. {$endif SYSTEMEXCEPTIONDEBUG}
  1109. procedure JumpToHandleErrorFrame;
  1110. var
  1111. eip, ebp, error : Longint;
  1112. begin
  1113. // save ebp
  1114. asm
  1115. movl (%ebp),%eax
  1116. movl %eax,ebp
  1117. end;
  1118. if (exceptLevel > 0) then
  1119. dec(exceptLevel);
  1120. eip:=exceptEip[exceptLevel];
  1121. error:=exceptError[exceptLevel];
  1122. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1123. if IsConsole then
  1124. writeln(stderr,'In JumpToHandleErrorFrame error=',error);
  1125. {$endif SYSTEMEXCEPTIONDEBUG}
  1126. if resetFPU[exceptLevel] then asm
  1127. fninit
  1128. fldcw fpucw
  1129. end;
  1130. { build a fake stack }
  1131. asm
  1132. movl ebp,%eax
  1133. pushl %eax
  1134. movl eip,%eax
  1135. pushl %eax
  1136. movl error,%eax
  1137. pushl %eax
  1138. movl eip,%eax
  1139. pushl %eax
  1140. movl ebp,%ebp // Change frame pointer
  1141. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1142. jmpl DebugHandleErrorAddrFrame
  1143. {$else not SYSTEMEXCEPTIONDEBUG}
  1144. jmpl HandleErrorAddrFrame
  1145. {$endif SYSTEMEXCEPTIONDEBUG}
  1146. end;
  1147. end;
  1148. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  1149. var
  1150. frame,
  1151. res : longint;
  1152. function SysHandleErrorFrame(error, frame : Longint; must_reset_fpu : Boolean) : Longint;
  1153. begin
  1154. if (frame = 0) then
  1155. SysHandleErrorFrame:=EXCEPTION_CONTINUE_SEARCH
  1156. else begin
  1157. if (exceptLevel >= MaxExceptionLevel) then exit;
  1158. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  1159. exceptError[exceptLevel] := error;
  1160. resetFPU[exceptLevel] := must_reset_fpu;
  1161. inc(exceptLevel);
  1162. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  1163. excep^.ExceptionRecord^.ExceptionCode := 0;
  1164. SysHandleErrorFrame := EXCEPTION_CONTINUE_EXECUTION;
  1165. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1166. if IsConsole then begin
  1167. writeln(stderr,'Exception Continue Exception set at ',
  1168. hexstr(exceptEip[exceptLevel],8));
  1169. writeln(stderr,'Eip changed to ',
  1170. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1171. end;
  1172. {$endif SYSTEMEXCEPTIONDEBUG}
  1173. end;
  1174. end;
  1175. begin
  1176. if excep^.ContextRecord^.SegSs=_SS then
  1177. frame := excep^.ContextRecord^.Ebp
  1178. else
  1179. frame := 0;
  1180. res := EXCEPTION_CONTINUE_SEARCH;
  1181. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1182. if IsConsole then Writeln(stderr,'Exception ',
  1183. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  1184. {$endif SYSTEMEXCEPTIONDEBUG}
  1185. case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
  1186. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1187. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1188. res := SysHandleErrorFrame(200, frame, true);
  1189. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1190. res := SysHandleErrorFrame(201, frame, false);
  1191. STATUS_STACK_OVERFLOW :
  1192. res := SysHandleErrorFrame(202, frame, false);
  1193. STATUS_FLOAT_OVERFLOW :
  1194. res := SysHandleErrorFrame(205, frame, true);
  1195. STATUS_FLOAT_UNDERFLOW :
  1196. res := SysHandleErrorFrame(206, frame, true);
  1197. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  1198. STATUS_FLOAT_INVALID_OPERATION,
  1199. STATUS_FLOAT_STACK_CHECK :
  1200. res := SysHandleErrorFrame(207, frame, true);
  1201. STATUS_INTEGER_OVERFLOW :
  1202. res := SysHandleErrorFrame(215, frame, false);
  1203. STATUS_ACCESS_VIOLATION,
  1204. STATUS_FLOAT_DENORMAL_OPERAND :
  1205. res := SysHandleErrorFrame(216, frame, true);
  1206. else begin
  1207. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1208. res := SysHandleErrorFrame(217, frame, true);
  1209. end;
  1210. end;
  1211. syswin32_i386_exception_handler := res;
  1212. end;
  1213. procedure install_exception_handlers;
  1214. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1215. var
  1216. oldexceptaddr,
  1217. newexceptaddr : Longint;
  1218. {$endif SYSTEMEXCEPTIONDEBUG}
  1219. begin
  1220. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1221. asm
  1222. movl $0,%eax
  1223. movl %fs:(%eax),%eax
  1224. movl %eax,oldexceptaddr
  1225. end;
  1226. {$endif SYSTEMEXCEPTIONDEBUG}
  1227. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  1228. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1229. asm
  1230. movl $0,%eax
  1231. movl %fs:(%eax),%eax
  1232. movl %eax,newexceptaddr
  1233. end;
  1234. if IsConsole then
  1235. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  1236. ' new exception ',hexstr(newexceptaddr,8));
  1237. {$endif SYSTEMEXCEPTIONDEBUG}
  1238. end;
  1239. procedure remove_exception_handlers;
  1240. begin
  1241. SetUnhandledExceptionFilter(nil);
  1242. end;
  1243. {$else not i386 (Processor specific !!)}
  1244. procedure install_exception_handlers;
  1245. begin
  1246. end;
  1247. procedure remove_exception_handlers;
  1248. begin
  1249. end;
  1250. {$endif Set_i386_Exception_handler}
  1251. {****************************************************************************
  1252. Error Message writing using messageboxes
  1253. ****************************************************************************}
  1254. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  1255. external 'user32' name 'MessageBoxA';
  1256. const
  1257. ErrorBufferLength = 1024;
  1258. var
  1259. ErrorBuf : array[0..ErrorBufferLength] of char;
  1260. ErrorLen : longint;
  1261. Function ErrorWrite(Var F: TextRec): Integer;
  1262. {
  1263. An error message should always end with #13#10#13#10
  1264. }
  1265. var
  1266. p : pchar;
  1267. i : longint;
  1268. Begin
  1269. if F.BufPos>0 then
  1270. begin
  1271. if F.BufPos+ErrorLen>ErrorBufferLength then
  1272. i:=ErrorBufferLength-ErrorLen
  1273. else
  1274. i:=F.BufPos;
  1275. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1276. inc(ErrorLen,i);
  1277. ErrorBuf[ErrorLen]:=#0;
  1278. end;
  1279. if ErrorLen>3 then
  1280. begin
  1281. p:=@ErrorBuf[ErrorLen];
  1282. for i:=1 to 4 do
  1283. begin
  1284. dec(p);
  1285. if not(p^ in [#10,#13]) then
  1286. break;
  1287. end;
  1288. end;
  1289. if ErrorLen=ErrorBufferLength then
  1290. i:=4;
  1291. if (i=4) then
  1292. begin
  1293. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1294. ErrorLen:=0;
  1295. end;
  1296. F.BufPos:=0;
  1297. ErrorWrite:=0;
  1298. End;
  1299. Function ErrorClose(Var F: TextRec): Integer;
  1300. begin
  1301. if ErrorLen>0 then
  1302. begin
  1303. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1304. ErrorLen:=0;
  1305. end;
  1306. ErrorLen:=0;
  1307. ErrorClose:=0;
  1308. end;
  1309. Function ErrorOpen(Var F: TextRec): Integer;
  1310. Begin
  1311. TextRec(F).InOutFunc:=@ErrorWrite;
  1312. TextRec(F).FlushFunc:=@ErrorWrite;
  1313. TextRec(F).CloseFunc:=@ErrorClose;
  1314. ErrorOpen:=0;
  1315. End;
  1316. procedure AssignError(Var T: Text);
  1317. begin
  1318. Assign(T,'');
  1319. TextRec(T).OpenFunc:=@ErrorOpen;
  1320. Rewrite(T);
  1321. end;
  1322. const
  1323. Exe_entry_code : pointer = @Exe_entry;
  1324. Dll_entry_code : pointer = @Dll_entry;
  1325. begin
  1326. StackBottom := Sptr - StackLength;
  1327. { get some helpful informations }
  1328. GetStartupInfo(@startupinfo);
  1329. { some misc Win32 stuff }
  1330. hprevinst:=0;
  1331. if not IsLibrary then
  1332. HInstance:=getmodulehandle(GetCommandFile);
  1333. MainInstance:=HInstance;
  1334. cmdshow:=startupinfo.wshowwindow;
  1335. { real test stack depth }
  1336. { stacklimit := setupstack; }
  1337. {$ifdef MT}
  1338. { allocate one threadvar entry from windows, we use this entry }
  1339. { for a pointer to our threadvars }
  1340. dataindex:=TlsAlloc;
  1341. { the exceptions use threadvars so do this _before_ initexceptions }
  1342. AllocateThreadVars;
  1343. {$endif MT}
  1344. { Setup heap }
  1345. InitHeap;
  1346. InitExceptions;
  1347. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1348. displayed in and messagebox }
  1349. StdInputHandle:=longint(GetStdHandle(STD_INPUT_HANDLE));
  1350. StdOutputHandle:=longint(GetStdHandle(STD_OUTPUT_HANDLE));
  1351. StdErrorHandle:=longint(GetStdHandle(STD_ERROR_HANDLE));
  1352. if not IsConsole then
  1353. begin
  1354. AssignError(stderr);
  1355. AssignError(stdout);
  1356. Assign(Output,'');
  1357. Assign(Input,'');
  1358. end
  1359. else
  1360. begin
  1361. OpenStdIO(Input,fmInput,StdInputHandle);
  1362. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1363. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1364. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1365. end;
  1366. { Arguments }
  1367. setup_arguments;
  1368. { Reset IO Error }
  1369. InOutRes:=0;
  1370. { Reset internal error variable }
  1371. errno:=0;
  1372. {$ifdef HASVARIANT}
  1373. initvariantmanager;
  1374. {$endif HASVARIANT}
  1375. end.
  1376. {
  1377. $Log$
  1378. Revision 1.27 2002-06-04 09:25:14 pierre
  1379. * Rename HeapSize to WinAPIHeapSize to avoid conflict with general function
  1380. Revision 1.26 2002/04/12 17:45:13 carl
  1381. + generic stack checking
  1382. Revision 1.25 2002/03/11 19:10:33 peter
  1383. * Regenerated with updated fpcmake
  1384. Revision 1.24 2002/01/30 14:57:11 pierre
  1385. * fix compilation failure
  1386. Revision 1.23 2002/01/25 16:23:03 peter
  1387. * merged filesearch() fix
  1388. Revision 1.22 2001/12/02 17:21:25 peter
  1389. * merged fixes from 1.0
  1390. Revision 1.21 2001/11/08 16:16:54 florian
  1391. + beginning of variant dispatching
  1392. Revision 1.20 2001/11/07 13:05:16 michael
  1393. + Fixed Append() bug. Appending non-existing file now gives an error
  1394. Revision 1.19 2001/10/23 21:51:03 peter
  1395. * criticalsection renamed to rtlcriticalsection for kylix compatibility
  1396. Revision 1.18 2001/10/09 02:37:29 carl
  1397. * bugfix #1639 (IsMultiThread varialbe setting)
  1398. Revision 1.17 2001/08/19 21:02:02 florian
  1399. * fixed and added a lot of stuff to get the Jedi DX8 headers
  1400. compiled
  1401. Revision 1.16 2001/07/30 20:53:50 peter
  1402. * fixed getdir() that was broken when a directory on a different drive
  1403. was asked
  1404. Revision 1.15 2001/06/30 18:55:48 hajny
  1405. * GetDir fix for inaccessible drives
  1406. Revision 1.14 2001/06/18 14:26:16 jonas
  1407. * move platform independent constant declarations after inclusion of
  1408. systemh.inc
  1409. Revision 1.13 2001/06/13 22:20:11 hajny
  1410. + platform specific information
  1411. Revision 1.12 2001/06/10 17:56:57 hajny
  1412. * errno changed to a threadvar if MT enabled
  1413. Revision 1.11 2001/06/07 21:16:30 peter
  1414. * fixed empty arguments
  1415. Revision 1.10 2001/06/01 22:23:21 peter
  1416. * same argument parsing -"abc" becomes -abc. This is compatible with
  1417. delphi and with unix shells (merged)
  1418. Revision 1.9 2001/03/21 23:29:40 florian
  1419. + sLineBreak and misc. stuff for Kylix compatiblity
  1420. Revision 1.8 2001/03/21 21:08:20 hajny
  1421. * GetDir fixed
  1422. Revision 1.7 2001/03/16 20:09:58 hajny
  1423. * universal FExpand
  1424. Revision 1.6 2001/02/20 21:31:12 peter
  1425. * chdir,mkdir,rmdir with empty string fixed
  1426. Revision 1.5 2001/01/26 16:38:03 florian
  1427. *** empty log message ***
  1428. Revision 1.4 2001/01/24 21:47:38 florian
  1429. + more MT stuff added
  1430. Revision 1.3 2001/01/05 15:44:35 florian
  1431. * some stuff for MT
  1432. Revision 1.2 2000/12/18 17:28:58 jonas
  1433. * fixed range check errors
  1434. Revision 1.1 2000/10/15 08:19:49 peter
  1435. * system unit rename for 1.1 branch
  1436. Revision 1.6 2000/10/13 12:01:52 peter
  1437. * fixed exception callback
  1438. Revision 1.5 2000/10/11 16:05:55 peter
  1439. * stdcall for callbacks (merged)
  1440. Revision 1.4 2000/09/11 20:19:28 florian
  1441. * complete exception handling provided by Thomas Schatzl
  1442. Revision 1.3 2000/09/04 19:36:59 peter
  1443. * new heapalloc calls, patch from Thomas Schatzl
  1444. Revision 1.2 2000/07/13 11:33:58 michael
  1445. + removed logs
  1446. }