syswin32.pp 38 KB

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