system.pp 46 KB

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