system.pp 46 KB

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