system.pp 46 KB

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