system.pp 40 KB

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