system.pp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655
  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. { include threading stuff }
  44. {$i threadh.inc}
  45. { include heap support headers }
  46. {$I heaph.inc}
  47. const
  48. { Default filehandles }
  49. UnusedHandle : longint = -1;
  50. StdInputHandle : longint = 0;
  51. StdOutputHandle : longint = 0;
  52. StdErrorHandle : longint = 0;
  53. FileNameCaseSensitive : boolean = true;
  54. sLineBreak : string = LineEnding;
  55. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  56. { Thread count for DLL }
  57. Thread_count : longint = 0;
  58. type
  59. TStartupInfo=packed record
  60. cb : longint;
  61. lpReserved : Pointer;
  62. lpDesktop : Pointer;
  63. lpTitle : Pointer;
  64. dwX : longint;
  65. dwY : longint;
  66. dwXSize : longint;
  67. dwYSize : longint;
  68. dwXCountChars : longint;
  69. dwYCountChars : longint;
  70. dwFillAttribute : longint;
  71. dwFlags : longint;
  72. wShowWindow : Word;
  73. cbReserved2 : Word;
  74. lpReserved2 : Pointer;
  75. hStdInput : longint;
  76. hStdOutput : longint;
  77. hStdError : longint;
  78. end;
  79. var
  80. { C compatible arguments }
  81. argc : longint;
  82. argv : ppchar;
  83. { Win32 Info }
  84. startupinfo : tstartupinfo;
  85. hprevinst,
  86. HInstance,
  87. MainInstance,
  88. cmdshow : longint;
  89. DLLreason,DLLparam:longint;
  90. Win32StackTop : Dword;
  91. type
  92. TDLL_Process_Entry_Hook = function (dllparam : longint) : longbool;
  93. TDLL_Entry_Hook = procedure (dllparam : longint);
  94. const
  95. Dll_Process_Attach_Hook : TDLL_Process_Entry_Hook = nil;
  96. Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
  97. Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
  98. Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
  99. implementation
  100. { include system independent routines }
  101. {$I system.inc}
  102. { some declarations for Win32 API calls }
  103. {$I win32.inc}
  104. CONST
  105. { These constants are used for conversion of error codes }
  106. { from win32 i/o errors to tp i/o errors }
  107. { errors 1 to 18 are the same as in Turbo Pascal }
  108. { DO NOT MODIFY UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING! }
  109. { The media is write protected. }
  110. ERROR_WRITE_PROTECT = 19;
  111. { The system cannot find the device specified. }
  112. ERROR_BAD_UNIT = 20;
  113. { The device is not ready. }
  114. ERROR_NOT_READY = 21;
  115. { The device does not recognize the command. }
  116. ERROR_BAD_COMMAND = 22;
  117. { Data error (cyclic redundancy check) }
  118. ERROR_CRC = 23;
  119. { The program issued a command but the }
  120. { command length is incorrect. }
  121. ERROR_BAD_LENGTH = 24;
  122. { The drive cannot locate a specific }
  123. { area or track on the disk. }
  124. ERROR_SEEK = 25;
  125. { The specified disk or diskette cannot be accessed. }
  126. ERROR_NOT_DOS_DISK = 26;
  127. { The drive cannot find the sector requested. }
  128. ERROR_SECTOR_NOT_FOUND = 27;
  129. { The printer is out of paper. }
  130. ERROR_OUT_OF_PAPER = 28;
  131. { The system cannot write to the specified device. }
  132. ERROR_WRITE_FAULT = 29;
  133. { The system cannot read from the specified device. }
  134. ERROR_READ_FAULT = 30;
  135. { A device attached to the system is not functioning.}
  136. ERROR_GEN_FAILURE = 31;
  137. { The process cannot access the file because }
  138. { it is being used by another process. }
  139. ERROR_SHARING_VIOLATION = 32;
  140. {$IFDEF MT}
  141. threadvar
  142. {$ELSE MT}
  143. var
  144. {$ENDIF MT}
  145. errno : longint;
  146. {$ASMMODE ATT}
  147. { misc. functions }
  148. function GetLastError : DWORD;
  149. external 'kernel32' name 'GetLastError';
  150. { time and date functions }
  151. function GetTickCount : longint;
  152. external 'kernel32' name 'GetTickCount';
  153. { process functions }
  154. procedure ExitProcess(uExitCode : UINT);
  155. external 'kernel32' name 'ExitProcess';
  156. Procedure Errno2InOutRes;
  157. Begin
  158. { DO NOT MODIFY UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING }
  159. if (errno >= ERROR_WRITE_PROTECT) and (errno <= ERROR_GEN_FAILURE) THEN
  160. BEGIN
  161. { This is the offset to the Win32 to add to directly map }
  162. { to the DOS/TP compatible error codes when in this range }
  163. InOutRes := word(errno)+131;
  164. END
  165. else
  166. { This case is special }
  167. if errno=ERROR_SHARING_VIOLATION THEN
  168. BEGIN
  169. InOutRes :=5;
  170. END
  171. else
  172. { other error codes can directly be mapped }
  173. InOutRes := Word(errno);
  174. errno:=0;
  175. end;
  176. {$ifdef dummy}
  177. procedure int_stackcheck(stack_size:longint);[public,alias: 'STACKCHECK'];
  178. {
  179. called when trying to get local stack if the compiler directive $S
  180. is set this function must preserve esi !!!! because esi is set by
  181. the calling proc for methods it must preserve all registers !!
  182. With a 2048 byte safe area used to write to StdIo without crossing
  183. the stack boundary
  184. }
  185. begin
  186. asm
  187. pushl %eax
  188. pushl %ebx
  189. movl stack_size,%ebx
  190. addl $2048,%ebx
  191. movl %esp,%eax
  192. subl %ebx,%eax
  193. movl stacklimit,%ebx
  194. cmpl %eax,%ebx
  195. jae .L__short_on_stack
  196. popl %ebx
  197. popl %eax
  198. leave
  199. ret $4
  200. .L__short_on_stack:
  201. { can be usefull for error recovery !! }
  202. popl %ebx
  203. popl %eax
  204. end['EAX','EBX'];
  205. HandleError(202);
  206. end;
  207. {$endif dummy}
  208. function paramcount : longint;
  209. begin
  210. paramcount := argc - 1;
  211. end;
  212. { module functions }
  213. function GetModuleFileName(l1:longint;p:pointer;l2:longint):longint;
  214. external 'kernel32' name 'GetModuleFileNameA';
  215. function GetModuleHandle(p : pointer) : longint;
  216. external 'kernel32' name 'GetModuleHandleA';
  217. function GetCommandFile:pchar;forward;
  218. function paramstr(l : longint) : string;
  219. begin
  220. if (l>=0) and (l<argc) then
  221. paramstr:=strpas(argv[l])
  222. else
  223. paramstr:='';
  224. end;
  225. procedure randomize;
  226. begin
  227. randseed:=GetTickCount;
  228. end;
  229. {*****************************************************************************
  230. Heap Management
  231. *****************************************************************************}
  232. { memory functions }
  233. function GetProcessHeap : DWord;
  234. external 'kernel32' name 'GetProcessHeap';
  235. function HeapAlloc(hHeap : DWord; dwFlags : DWord; dwBytes : DWord) : Longint;
  236. external 'kernel32' name 'HeapAlloc';
  237. {$IFDEF SYSTEMDEBUG}
  238. function HeapSize(hHeap : DWord; dwFlags : DWord; ptr : Pointer) : DWord;
  239. external 'kernel32' name 'HeapSize';
  240. {$ENDIF}
  241. var
  242. heap : longint;external name 'HEAP';
  243. intern_heapsize : longint;external name 'HEAPSIZE';
  244. function getheapstart:pointer;assembler;
  245. asm
  246. leal HEAP,%eax
  247. end ['EAX'];
  248. function getheapsize:longint;assembler;
  249. asm
  250. movl intern_HEAPSIZE,%eax
  251. end ['EAX'];
  252. function Sbrk(size : longint):longint;
  253. var
  254. l : longint;
  255. begin
  256. l := HeapAlloc(GetProcessHeap(), 0, size);
  257. if (l = 0) then
  258. l := -1;
  259. {$ifdef DUMPGROW}
  260. Writeln('new heap part at $',hexstr(l,8), ' size = ',HeapSize(GetProcessHeap()));
  261. {$endif}
  262. sbrk:=l;
  263. end;
  264. { include standard heap management }
  265. {$I heap.inc}
  266. {*****************************************************************************
  267. Low Level File Routines
  268. *****************************************************************************}
  269. function WriteFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
  270. overlap:pointer):longint;
  271. external 'kernel32' name 'WriteFile';
  272. function ReadFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
  273. overlap:pointer):longint;
  274. external 'kernel32' name 'ReadFile';
  275. function CloseHandle(h : longint) : longint;
  276. external 'kernel32' name 'CloseHandle';
  277. function DeleteFile(p : pchar) : longint;
  278. external 'kernel32' name 'DeleteFileA';
  279. function MoveFile(old,_new : pchar) : longint;
  280. external 'kernel32' name 'MoveFileA';
  281. function SetFilePointer(l1,l2 : longint;l3 : pointer;l4 : longint) : longint;
  282. external 'kernel32' name 'SetFilePointer';
  283. function GetFileSize(h:longint;p:pointer) : longint;
  284. external 'kernel32' name 'GetFileSize';
  285. function CreateFile(name : pointer;access,sharing : longint;
  286. security : PSecurityAttributes;how,attr,template : longint) : longint;
  287. external 'kernel32' name 'CreateFileA';
  288. function SetEndOfFile(h : longint) : longbool;
  289. external 'kernel32' name 'SetEndOfFile';
  290. function GetFileType(Handle:DWORD):DWord;
  291. external 'kernel32' name 'GetFileType';
  292. procedure AllowSlash(p:pchar);
  293. var
  294. i : longint;
  295. begin
  296. { allow slash as backslash }
  297. for i:=0 to strlen(p) do
  298. if p[i]='/' then p[i]:='\';
  299. end;
  300. function do_isdevice(handle:longint):boolean;
  301. begin
  302. do_isdevice:=(getfiletype(handle)=2);
  303. end;
  304. procedure do_close(h : longint);
  305. begin
  306. if do_isdevice(h) then
  307. exit;
  308. CloseHandle(h);
  309. end;
  310. procedure do_erase(p : pchar);
  311. begin
  312. AllowSlash(p);
  313. if DeleteFile(p)=0 then
  314. Begin
  315. errno:=GetLastError;
  316. Errno2InoutRes;
  317. end;
  318. end;
  319. procedure do_rename(p1,p2 : pchar);
  320. begin
  321. AllowSlash(p1);
  322. AllowSlash(p2);
  323. if MoveFile(p1,p2)=0 then
  324. Begin
  325. errno:=GetLastError;
  326. Errno2InoutRes;
  327. end;
  328. end;
  329. function do_write(h,addr,len : longint) : longint;
  330. var
  331. size:longint;
  332. begin
  333. if writefile(h,pointer(addr),len,size,nil)=0 then
  334. Begin
  335. errno:=GetLastError;
  336. Errno2InoutRes;
  337. end;
  338. do_write:=size;
  339. end;
  340. function do_read(h,addr,len : longint) : longint;
  341. var
  342. _result:longint;
  343. begin
  344. if readfile(h,pointer(addr),len,_result,nil)=0 then
  345. Begin
  346. errno:=GetLastError;
  347. Errno2InoutRes;
  348. end;
  349. do_read:=_result;
  350. end;
  351. function do_filepos(handle : longint) : longint;
  352. var
  353. l:longint;
  354. begin
  355. l:=SetFilePointer(handle,0,nil,FILE_CURRENT);
  356. if l=-1 then
  357. begin
  358. l:=0;
  359. errno:=GetLastError;
  360. Errno2InoutRes;
  361. end;
  362. do_filepos:=l;
  363. end;
  364. procedure do_seek(handle,pos : longint);
  365. begin
  366. if SetFilePointer(handle,pos,nil,FILE_BEGIN)=-1 then
  367. Begin
  368. errno:=GetLastError;
  369. Errno2InoutRes;
  370. end;
  371. end;
  372. function do_seekend(handle:longint):longint;
  373. begin
  374. do_seekend:=SetFilePointer(handle,0,nil,FILE_END);
  375. if do_seekend=-1 then
  376. begin
  377. errno:=GetLastError;
  378. Errno2InoutRes;
  379. end;
  380. end;
  381. function do_filesize(handle : longint) : longint;
  382. var
  383. aktfilepos : longint;
  384. begin
  385. aktfilepos:=do_filepos(handle);
  386. do_filesize:=do_seekend(handle);
  387. do_seek(handle,aktfilepos);
  388. end;
  389. procedure do_truncate (handle,pos:longint);
  390. begin
  391. do_seek(handle,pos);
  392. if not(SetEndOfFile(handle)) then
  393. begin
  394. errno:=GetLastError;
  395. Errno2InoutRes;
  396. end;
  397. end;
  398. procedure do_open(var f;p : pchar;flags:longint);
  399. {
  400. filerec and textrec have both handle and mode as the first items so
  401. they could use the same routine for opening/creating.
  402. when (flags and $100) the file will be append
  403. when (flags and $1000) the file will be truncate/rewritten
  404. when (flags and $10000) there is no check for close (needed for textfiles)
  405. }
  406. Const
  407. file_Share_Read = $00000001;
  408. file_Share_Write = $00000002;
  409. Var
  410. shflags,
  411. oflags,cd : longint;
  412. security : TSecurityAttributes;
  413. begin
  414. AllowSlash(p);
  415. { close first if opened }
  416. if ((flags and $10000)=0) then
  417. begin
  418. case filerec(f).mode of
  419. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  420. fmclosed : ;
  421. else
  422. begin
  423. {not assigned}
  424. inoutres:=102;
  425. exit;
  426. end;
  427. end;
  428. end;
  429. { reset file handle }
  430. filerec(f).handle:=UnusedHandle;
  431. { convert filesharing }
  432. shflags:=0;
  433. if ((filemode and fmshareExclusive) = fmshareExclusive) then
  434. { no sharing }
  435. else
  436. if (filemode = fmShareCompat) or ((filemode and fmshareDenyWrite) = fmshareDenyWrite) then
  437. shflags := file_Share_Read
  438. else
  439. if ((filemode and fmshareDenyRead) = fmshareDenyRead) then
  440. shflags := file_Share_Write
  441. else
  442. if ((filemode and fmshareDenyNone) = fmshareDenyNone) then
  443. shflags := file_Share_Read + file_Share_Write;
  444. { convert filemode to filerec modes }
  445. case (flags and 3) of
  446. 0 : begin
  447. filerec(f).mode:=fminput;
  448. oflags:=GENERIC_READ;
  449. end;
  450. 1 : begin
  451. filerec(f).mode:=fmoutput;
  452. oflags:=GENERIC_WRITE;
  453. end;
  454. 2 : begin
  455. filerec(f).mode:=fminout;
  456. oflags:=GENERIC_WRITE or GENERIC_READ;
  457. end;
  458. end;
  459. { create it ? }
  460. if (flags and $1000)<>0 then
  461. cd:=CREATE_ALWAYS
  462. { or Append/Open ? }
  463. else
  464. cd:=OPEN_EXISTING;
  465. { empty name is special }
  466. if p[0]=#0 then
  467. begin
  468. case FileRec(f).mode of
  469. fminput :
  470. FileRec(f).Handle:=StdInputHandle;
  471. fminout, { this is set by rewrite }
  472. fmoutput :
  473. FileRec(f).Handle:=StdOutputHandle;
  474. fmappend :
  475. begin
  476. FileRec(f).Handle:=StdOutputHandle;
  477. FileRec(f).mode:=fmoutput; {fool fmappend}
  478. end;
  479. end;
  480. exit;
  481. end;
  482. security.nLength := Sizeof(TSecurityAttributes);
  483. security.bInheritHandle:=true;
  484. security.lpSecurityDescriptor:=nil;
  485. filerec(f).handle:=CreateFile(p,oflags,shflags,@security,cd,FILE_ATTRIBUTE_NORMAL,0);
  486. { append mode }
  487. if (flags and $100)<>0 then
  488. begin
  489. do_seekend(filerec(f).handle);
  490. filerec(f).mode:=fmoutput; {fool fmappend}
  491. end;
  492. { get errors }
  493. { handle -1 is returned sometimes !! (PM) }
  494. if (filerec(f).handle=0) or (filerec(f).handle=-1) then
  495. begin
  496. errno:=GetLastError;
  497. Errno2InoutRes;
  498. end;
  499. end;
  500. {*****************************************************************************
  501. UnTyped File Handling
  502. *****************************************************************************}
  503. {$i file.inc}
  504. {*****************************************************************************
  505. Typed File Handling
  506. *****************************************************************************}
  507. {$i typefile.inc}
  508. {*****************************************************************************
  509. Text File Handling
  510. *****************************************************************************}
  511. {$DEFINE EOF_CTRLZ}
  512. {$i text.inc}
  513. {*****************************************************************************
  514. Directory Handling
  515. *****************************************************************************}
  516. function CreateDirectory(name : pointer;sec : pointer) : longbool;
  517. external 'kernel32' name 'CreateDirectoryA';
  518. function RemoveDirectory(name:pointer):longbool;
  519. external 'kernel32' name 'RemoveDirectoryA';
  520. function SetCurrentDirectory(name : pointer) : longbool;
  521. external 'kernel32' name 'SetCurrentDirectoryA';
  522. function GetCurrentDirectory(bufsize : longint;name : pchar) : longbool;
  523. external 'kernel32' name 'GetCurrentDirectoryA';
  524. type
  525. TDirFnType=function(name:pointer):longbool;
  526. procedure dirfn(afunc : TDirFnType;const s:string);
  527. var
  528. buffer : array[0..255] of char;
  529. begin
  530. move(s[1],buffer,length(s));
  531. buffer[length(s)]:=#0;
  532. AllowSlash(pchar(@buffer));
  533. if not aFunc(@buffer) then
  534. begin
  535. errno:=GetLastError;
  536. Errno2InoutRes;
  537. end;
  538. end;
  539. function CreateDirectoryTrunc(name:pointer):longbool;
  540. begin
  541. CreateDirectoryTrunc:=CreateDirectory(name,nil);
  542. end;
  543. procedure mkdir(const s:string);[IOCHECK];
  544. begin
  545. If (s='') or (InOutRes <> 0) then
  546. exit;
  547. dirfn(TDirFnType(@CreateDirectoryTrunc),s);
  548. end;
  549. procedure rmdir(const s:string);[IOCHECK];
  550. begin
  551. If (s='') or (InOutRes <> 0) then
  552. exit;
  553. dirfn(TDirFnType(@RemoveDirectory),s);
  554. end;
  555. procedure chdir(const s:string);[IOCHECK];
  556. begin
  557. If (s='') or (InOutRes <> 0) then
  558. exit;
  559. dirfn(TDirFnType(@SetCurrentDirectory),s);
  560. end;
  561. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  562. const
  563. Drive:array[0..3]of char=(#0,':',#0,#0);
  564. var
  565. defaultdrive:boolean;
  566. DirBuf,SaveBuf:array[0..259] of Char;
  567. begin
  568. defaultdrive:=drivenr=0;
  569. if not defaultdrive then
  570. begin
  571. byte(Drive[0]):=Drivenr+64;
  572. GetCurrentDirectory(SizeOf(SaveBuf),SaveBuf);
  573. if not SetCurrentDirectory(@Drive) then
  574. begin
  575. errno := word (GetLastError);
  576. Errno2InoutRes;
  577. Dir := char (DriveNr + 64) + ':\';
  578. SetCurrentDirectory(@SaveBuf);
  579. Exit;
  580. end;
  581. end;
  582. GetCurrentDirectory(SizeOf(DirBuf),DirBuf);
  583. if not defaultdrive then
  584. SetCurrentDirectory(@SaveBuf);
  585. dir:=strpas(DirBuf);
  586. if not FileNameCaseSensitive then
  587. dir:=upcase(dir);
  588. end;
  589. {*****************************************************************************
  590. Thread Handling
  591. *****************************************************************************}
  592. const
  593. fpucw : word = $1332;
  594. procedure InitFPU;assembler;
  595. asm
  596. fninit
  597. fldcw fpucw
  598. end;
  599. { include threading stuff, this is os independend part }
  600. {$I thread.inc}
  601. {*****************************************************************************
  602. SystemUnit Initialization
  603. *****************************************************************************}
  604. { Startup }
  605. procedure GetStartupInfo(p : pointer);
  606. external 'kernel32' name 'GetStartupInfoA';
  607. function GetStdHandle(nStdHandle:DWORD):THANDLE;
  608. external 'kernel32' name 'GetStdHandle';
  609. { command line/enviroment functions }
  610. function GetCommandLine : pchar;
  611. external 'kernel32' name 'GetCommandLineA';
  612. var
  613. ModuleName : array[0..255] of char;
  614. function GetCommandFile:pchar;
  615. begin
  616. GetModuleFileName(0,@ModuleName,255);
  617. GetCommandFile:=@ModuleName;
  618. end;
  619. procedure setup_arguments;
  620. var
  621. arglen,
  622. count : longint;
  623. argstart,
  624. pc,arg : pchar;
  625. quote : char;
  626. argvlen : longint;
  627. procedure allocarg(idx,len:longint);
  628. begin
  629. if idx>=argvlen then
  630. begin
  631. argvlen:=(idx+8) and (not 7);
  632. sysreallocmem(argv,argvlen*sizeof(pointer));
  633. end;
  634. { use realloc to reuse already existing memory }
  635. if len<>0 then
  636. sysreallocmem(argv[idx],len+1);
  637. end;
  638. begin
  639. { create commandline, it starts with the executed filename which is argv[0] }
  640. { Win32 passes the command NOT via the args, but via getmodulefilename}
  641. count:=0;
  642. argv:=nil;
  643. argvlen:=0;
  644. pc:=getcommandfile;
  645. Arglen:=0;
  646. repeat
  647. Inc(Arglen);
  648. until (pc[Arglen]=#0);
  649. allocarg(count,arglen);
  650. move(pc^,argv[count]^,arglen);
  651. { Setup cmdline variable }
  652. cmdline:=GetCommandLine;
  653. { process arguments }
  654. pc:=cmdline;
  655. {$IfDef SYSTEM_DEBUG_STARTUP}
  656. Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
  657. {$EndIf }
  658. while pc^<>#0 do
  659. begin
  660. { skip leading spaces }
  661. while pc^ in [#1..#32] do
  662. inc(pc);
  663. if pc^=#0 then
  664. break;
  665. { calc argument length }
  666. quote:=' ';
  667. argstart:=pc;
  668. arglen:=0;
  669. while (pc^<>#0) do
  670. begin
  671. case pc^ of
  672. #1..#32 :
  673. begin
  674. if quote<>' ' then
  675. inc(arglen)
  676. else
  677. break;
  678. end;
  679. '"' :
  680. begin
  681. if quote<>'''' then
  682. begin
  683. if pchar(pc+1)^<>'"' then
  684. begin
  685. if quote='"' then
  686. quote:=' '
  687. else
  688. quote:='"';
  689. end
  690. else
  691. inc(pc);
  692. end
  693. else
  694. inc(arglen);
  695. end;
  696. '''' :
  697. begin
  698. if quote<>'"' then
  699. begin
  700. if pchar(pc+1)^<>'''' then
  701. begin
  702. if quote='''' then
  703. quote:=' '
  704. else
  705. quote:='''';
  706. end
  707. else
  708. inc(pc);
  709. end
  710. else
  711. inc(arglen);
  712. end;
  713. else
  714. inc(arglen);
  715. end;
  716. inc(pc);
  717. end;
  718. { copy argument }
  719. { Don't copy the first one, it is already there.}
  720. If Count<>0 then
  721. begin
  722. allocarg(count,arglen);
  723. quote:=' ';
  724. pc:=argstart;
  725. arg:=argv[count];
  726. while (pc^<>#0) do
  727. begin
  728. case pc^ of
  729. #1..#32 :
  730. begin
  731. if quote<>' ' then
  732. begin
  733. arg^:=pc^;
  734. inc(arg);
  735. end
  736. else
  737. break;
  738. end;
  739. '"' :
  740. begin
  741. if quote<>'''' then
  742. begin
  743. if pchar(pc+1)^<>'"' then
  744. begin
  745. if quote='"' then
  746. quote:=' '
  747. else
  748. quote:='"';
  749. end
  750. else
  751. inc(pc);
  752. end
  753. else
  754. begin
  755. arg^:=pc^;
  756. inc(arg);
  757. end;
  758. end;
  759. '''' :
  760. begin
  761. if quote<>'"' then
  762. begin
  763. if pchar(pc+1)^<>'''' then
  764. begin
  765. if quote='''' then
  766. quote:=' '
  767. else
  768. quote:='''';
  769. end
  770. else
  771. inc(pc);
  772. end
  773. else
  774. begin
  775. arg^:=pc^;
  776. inc(arg);
  777. end;
  778. end;
  779. else
  780. begin
  781. arg^:=pc^;
  782. inc(arg);
  783. end;
  784. end;
  785. inc(pc);
  786. end;
  787. arg^:=#0;
  788. end;
  789. {$IfDef SYSTEM_DEBUG_STARTUP}
  790. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  791. {$EndIf SYSTEM_DEBUG_STARTUP}
  792. inc(count);
  793. end;
  794. { get argc and create an nil entry }
  795. argc:=count;
  796. allocarg(argc,0);
  797. { free unused memory }
  798. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  799. end;
  800. {*****************************************************************************
  801. System Dependent Exit code
  802. *****************************************************************************}
  803. procedure install_exception_handlers;forward;
  804. procedure remove_exception_handlers;forward;
  805. procedure PascalMain;external name 'PASCALMAIN';
  806. procedure fpc_do_exit;external name 'FPC_DO_EXIT';
  807. Procedure ExitDLL(Exitcode : longint); forward;
  808. Procedure system_exit;
  809. begin
  810. { don't call ExitProcess inside
  811. the DLL exit code !!
  812. This crashes Win95 at least PM }
  813. if IsLibrary then
  814. ExitDLL(ExitCode);
  815. if not IsConsole then
  816. begin
  817. Close(stderr);
  818. Close(stdout);
  819. { what about Input and Output ?? PM }
  820. end;
  821. remove_exception_handlers;
  822. ExitProcess(ExitCode);
  823. end;
  824. {$ifdef dummy}
  825. Function SetUpStack : longint;
  826. { This routine does the following : }
  827. { returns the value of the initial SP - __stklen }
  828. begin
  829. asm
  830. pushl %ebx
  831. pushl %eax
  832. movl __stklen,%ebx
  833. movl %esp,%eax
  834. subl %ebx,%eax
  835. movl %eax,__RESULT
  836. popl %eax
  837. popl %ebx
  838. end;
  839. end;
  840. {$endif}
  841. var
  842. { value of the stack segment
  843. to check if the call stack can be written on exceptions }
  844. _SS : longint;
  845. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  846. begin
  847. IsLibrary:=false;
  848. { install the handlers for exe only ?
  849. or should we install them for DLL also ? (PM) }
  850. install_exception_handlers;
  851. { This strange construction is needed to solve the _SS problem
  852. with a smartlinked syswin32 (PFV) }
  853. asm
  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. end;
  1126. {$endif SYSTEMEXCEPTIONDEBUG}
  1127. if resetFPU[exceptLevel] then asm
  1128. fninit
  1129. fldcw fpucw
  1130. end;
  1131. { build a fake stack }
  1132. asm
  1133. movl ebp,%eax
  1134. pushl %eax
  1135. movl eip,%eax
  1136. pushl %eax
  1137. movl error,%eax
  1138. pushl %eax
  1139. movl eip,%eax
  1140. pushl %eax
  1141. movl ebp,%ebp // Change frame pointer
  1142. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1143. jmpl DebugHandleErrorAddrFrame
  1144. {$else not SYSTEMEXCEPTIONDEBUG}
  1145. jmpl HandleErrorAddrFrame
  1146. {$endif SYSTEMEXCEPTIONDEBUG}
  1147. end;
  1148. end;
  1149. function syswin32_i386_exception_handler(excep : PExceptionPointers) : Longint;stdcall;
  1150. var
  1151. frame,
  1152. res : longint;
  1153. function SysHandleErrorFrame(error, frame : Longint; must_reset_fpu : Boolean) : Longint;
  1154. begin
  1155. if (frame = 0) then
  1156. SysHandleErrorFrame:=EXCEPTION_CONTINUE_SEARCH
  1157. else begin
  1158. if (exceptLevel >= MaxExceptionLevel) then exit;
  1159. exceptEip[exceptLevel] := excep^.ContextRecord^.Eip;
  1160. exceptError[exceptLevel] := error;
  1161. resetFPU[exceptLevel] := must_reset_fpu;
  1162. inc(exceptLevel);
  1163. excep^.ContextRecord^.Eip := Longint(@JumpToHandleErrorFrame);
  1164. excep^.ExceptionRecord^.ExceptionCode := 0;
  1165. SysHandleErrorFrame := EXCEPTION_CONTINUE_EXECUTION;
  1166. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1167. if IsConsole then begin
  1168. writeln(stderr,'Exception Continue Exception set at ',
  1169. hexstr(exceptEip[exceptLevel],8));
  1170. writeln(stderr,'Eip changed to ',
  1171. hexstr(longint(@JumpToHandleErrorFrame),8), ' error=', error);
  1172. end;
  1173. {$endif SYSTEMEXCEPTIONDEBUG}
  1174. end;
  1175. end;
  1176. begin
  1177. if excep^.ContextRecord^.SegSs=_SS then
  1178. frame := excep^.ContextRecord^.Ebp
  1179. else
  1180. frame := 0;
  1181. res := EXCEPTION_CONTINUE_SEARCH;
  1182. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1183. if IsConsole then Writeln(stderr,'Exception ',
  1184. hexstr(excep^.ExceptionRecord^.ExceptionCode, 8));
  1185. {$endif SYSTEMEXCEPTIONDEBUG}
  1186. case cardinal(excep^.ExceptionRecord^.ExceptionCode) of
  1187. STATUS_INTEGER_DIVIDE_BY_ZERO,
  1188. STATUS_FLOAT_DIVIDE_BY_ZERO :
  1189. res := SysHandleErrorFrame(200, frame, true);
  1190. STATUS_ARRAY_BOUNDS_EXCEEDED :
  1191. res := SysHandleErrorFrame(201, frame, false);
  1192. STATUS_STACK_OVERFLOW :
  1193. res := SysHandleErrorFrame(202, frame, false);
  1194. STATUS_FLOAT_OVERFLOW :
  1195. res := SysHandleErrorFrame(205, frame, true);
  1196. STATUS_FLOAT_UNDERFLOW :
  1197. res := SysHandleErrorFrame(206, frame, true);
  1198. {excep^.ContextRecord^.FloatSave.StatusWord := excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
  1199. STATUS_FLOAT_INVALID_OPERATION,
  1200. STATUS_FLOAT_STACK_CHECK :
  1201. res := SysHandleErrorFrame(207, frame, true);
  1202. STATUS_INTEGER_OVERFLOW :
  1203. res := SysHandleErrorFrame(215, frame, false);
  1204. STATUS_ACCESS_VIOLATION,
  1205. STATUS_FLOAT_DENORMAL_OPERAND :
  1206. res := SysHandleErrorFrame(216, frame, true);
  1207. else begin
  1208. if ((excep^.ExceptionRecord^.ExceptionCode and SEVERITY_ERROR) = SEVERITY_ERROR) then
  1209. res := SysHandleErrorFrame(217, frame, true);
  1210. end;
  1211. end;
  1212. syswin32_i386_exception_handler := res;
  1213. end;
  1214. procedure install_exception_handlers;
  1215. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1216. var
  1217. oldexceptaddr,
  1218. newexceptaddr : Longint;
  1219. {$endif SYSTEMEXCEPTIONDEBUG}
  1220. begin
  1221. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1222. asm
  1223. movl $0,%eax
  1224. movl %fs:(%eax),%eax
  1225. movl %eax,oldexceptaddr
  1226. end;
  1227. {$endif SYSTEMEXCEPTIONDEBUG}
  1228. SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  1229. {$ifdef SYSTEMEXCEPTIONDEBUG}
  1230. asm
  1231. movl $0,%eax
  1232. movl %fs:(%eax),%eax
  1233. movl %eax,newexceptaddr
  1234. end;
  1235. if IsConsole then
  1236. writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
  1237. ' new exception ',hexstr(newexceptaddr,8));
  1238. {$endif SYSTEMEXCEPTIONDEBUG}
  1239. end;
  1240. procedure remove_exception_handlers;
  1241. begin
  1242. SetUnhandledExceptionFilter(nil);
  1243. end;
  1244. {$else not i386 (Processor specific !!)}
  1245. procedure install_exception_handlers;
  1246. begin
  1247. end;
  1248. procedure remove_exception_handlers;
  1249. begin
  1250. end;
  1251. {$endif Set_i386_Exception_handler}
  1252. {****************************************************************************
  1253. Error Message writing using messageboxes
  1254. ****************************************************************************}
  1255. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  1256. external 'user32' name 'MessageBoxA';
  1257. const
  1258. ErrorBufferLength = 1024;
  1259. var
  1260. ErrorBuf : array[0..ErrorBufferLength] of char;
  1261. ErrorLen : longint;
  1262. Function ErrorWrite(Var F: TextRec): Integer;
  1263. {
  1264. An error message should always end with #13#10#13#10
  1265. }
  1266. var
  1267. p : pchar;
  1268. i : longint;
  1269. Begin
  1270. if F.BufPos>0 then
  1271. begin
  1272. if F.BufPos+ErrorLen>ErrorBufferLength then
  1273. i:=ErrorBufferLength-ErrorLen
  1274. else
  1275. i:=F.BufPos;
  1276. Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
  1277. inc(ErrorLen,i);
  1278. ErrorBuf[ErrorLen]:=#0;
  1279. end;
  1280. if ErrorLen>3 then
  1281. begin
  1282. p:=@ErrorBuf[ErrorLen];
  1283. for i:=1 to 4 do
  1284. begin
  1285. dec(p);
  1286. if not(p^ in [#10,#13]) then
  1287. break;
  1288. end;
  1289. end;
  1290. if ErrorLen=ErrorBufferLength then
  1291. i:=4;
  1292. if (i=4) then
  1293. begin
  1294. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1295. ErrorLen:=0;
  1296. end;
  1297. F.BufPos:=0;
  1298. ErrorWrite:=0;
  1299. End;
  1300. Function ErrorClose(Var F: TextRec): Integer;
  1301. begin
  1302. if ErrorLen>0 then
  1303. begin
  1304. MessageBox(0,@ErrorBuf,pchar('Error'),0);
  1305. ErrorLen:=0;
  1306. end;
  1307. ErrorLen:=0;
  1308. ErrorClose:=0;
  1309. end;
  1310. Function ErrorOpen(Var F: TextRec): Integer;
  1311. Begin
  1312. TextRec(F).InOutFunc:=@ErrorWrite;
  1313. TextRec(F).FlushFunc:=@ErrorWrite;
  1314. TextRec(F).CloseFunc:=@ErrorClose;
  1315. ErrorOpen:=0;
  1316. End;
  1317. procedure AssignError(Var T: Text);
  1318. begin
  1319. Assign(T,'');
  1320. TextRec(T).OpenFunc:=@ErrorOpen;
  1321. Rewrite(T);
  1322. end;
  1323. const
  1324. Exe_entry_code : pointer = @Exe_entry;
  1325. Dll_entry_code : pointer = @Dll_entry;
  1326. begin
  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. { to test stack depth }
  1336. loweststack:=maxlongint;
  1337. { real test stack depth }
  1338. { stacklimit := setupstack; }
  1339. {$ifdef MT}
  1340. { allocate one threadvar entry from windows, we use this entry }
  1341. { for a pointer to our threadvars }
  1342. dataindex:=TlsAlloc;
  1343. { the exceptions use threadvars so do this _before_ initexceptions }
  1344. AllocateThreadVars;
  1345. {$endif MT}
  1346. { Setup heap }
  1347. InitHeap;
  1348. InitExceptions;
  1349. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1350. displayed in and messagebox }
  1351. StdInputHandle:=longint(GetStdHandle(STD_INPUT_HANDLE));
  1352. StdOutputHandle:=longint(GetStdHandle(STD_OUTPUT_HANDLE));
  1353. StdErrorHandle:=longint(GetStdHandle(STD_ERROR_HANDLE));
  1354. if not IsConsole then
  1355. begin
  1356. AssignError(stderr);
  1357. AssignError(stdout);
  1358. Assign(Output,'');
  1359. Assign(Input,'');
  1360. end
  1361. else
  1362. begin
  1363. OpenStdIO(Input,fmInput,StdInputHandle);
  1364. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1365. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1366. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1367. end;
  1368. { Arguments }
  1369. setup_arguments;
  1370. { Reset IO Error }
  1371. InOutRes:=0;
  1372. { Reset internal error variable }
  1373. errno:=0;
  1374. {$ifdef HASVARIANT}
  1375. initvariantmanager;
  1376. {$endif HASVARIANT}
  1377. end.
  1378. {
  1379. $Log$
  1380. Revision 1.22 2001-12-02 17:21:25 peter
  1381. * merged fixes from 1.0
  1382. Revision 1.21 2001/11/08 16:16:54 florian
  1383. + beginning of variant dispatching
  1384. Revision 1.20 2001/11/07 13:05:16 michael
  1385. + Fixed Append() bug. Appending non-existing file now gives an error
  1386. Revision 1.19 2001/10/23 21:51:03 peter
  1387. * criticalsection renamed to rtlcriticalsection for kylix compatibility
  1388. Revision 1.18 2001/10/09 02:37:29 carl
  1389. * bugfix #1639 (IsMultiThread varialbe setting)
  1390. Revision 1.17 2001/08/19 21:02:02 florian
  1391. * fixed and added a lot of stuff to get the Jedi DX8 headers
  1392. compiled
  1393. Revision 1.16 2001/07/30 20:53:50 peter
  1394. * fixed getdir() that was broken when a directory on a different drive
  1395. was asked
  1396. Revision 1.15 2001/06/30 18:55:48 hajny
  1397. * GetDir fix for inaccessible drives
  1398. Revision 1.14 2001/06/18 14:26:16 jonas
  1399. * move platform independent constant declarations after inclusion of
  1400. systemh.inc
  1401. Revision 1.13 2001/06/13 22:20:11 hajny
  1402. + platform specific information
  1403. Revision 1.12 2001/06/10 17:56:57 hajny
  1404. * errno changed to a threadvar if MT enabled
  1405. Revision 1.11 2001/06/07 21:16:30 peter
  1406. * fixed empty arguments
  1407. Revision 1.10 2001/06/01 22:23:21 peter
  1408. * same argument parsing -"abc" becomes -abc. This is compatible with
  1409. delphi and with unix shells (merged)
  1410. Revision 1.9 2001/03/21 23:29:40 florian
  1411. + sLineBreak and misc. stuff for Kylix compatiblity
  1412. Revision 1.8 2001/03/21 21:08:20 hajny
  1413. * GetDir fixed
  1414. Revision 1.7 2001/03/16 20:09:58 hajny
  1415. * universal FExpand
  1416. Revision 1.6 2001/02/20 21:31:12 peter
  1417. * chdir,mkdir,rmdir with empty string fixed
  1418. Revision 1.5 2001/01/26 16:38:03 florian
  1419. *** empty log message ***
  1420. Revision 1.4 2001/01/24 21:47:38 florian
  1421. + more MT stuff added
  1422. Revision 1.3 2001/01/05 15:44:35 florian
  1423. * some stuff for MT
  1424. Revision 1.2 2000/12/18 17:28:58 jonas
  1425. * fixed range check errors
  1426. Revision 1.1 2000/10/15 08:19:49 peter
  1427. * system unit rename for 1.1 branch
  1428. Revision 1.6 2000/10/13 12:01:52 peter
  1429. * fixed exception callback
  1430. Revision 1.5 2000/10/11 16:05:55 peter
  1431. * stdcall for callbacks (merged)
  1432. Revision 1.4 2000/09/11 20:19:28 florian
  1433. * complete exception handling provided by Thomas Schatzl
  1434. Revision 1.3 2000/09/04 19:36:59 peter
  1435. * new heapalloc calls, patch from Thomas Schatzl
  1436. Revision 1.2 2000/07/13 11:33:58 michael
  1437. + removed logs
  1438. }