system.pp 39 KB

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