system.pp 44 KB

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