syswin32.pp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993-98 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. {$S-}
  14. unit syswin32;
  15. {$I os.inc}
  16. interface
  17. { include system-independent routine headers }
  18. {$I systemh.inc}
  19. { include heap support headers }
  20. {$I heaph.inc}
  21. {ifdef debug removed (PM)}
  22. {$ifdef i386}
  23. {$define Set_i386_Exception_handler}
  24. {$endif i386}
  25. {endif debug}
  26. const
  27. { Default filehandles }
  28. UnusedHandle : longint = -1;
  29. StdInputHandle : longint = 0;
  30. StdOutputHandle : longint = 0;
  31. StdErrorHandle : longint = 0;
  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. IsLibrary,IsMultiThreaded,IsConsole : boolean;
  64. DLLreason,DLLparam:longint;
  65. implementation
  66. { include system independent routines }
  67. {$I system.inc}
  68. { some declarations for Win32 API calls }
  69. {$I win32.inc}
  70. CONST
  71. { These constants are used for conversion of error codes }
  72. { from win32 i/o errors to tp i/o errors }
  73. { errors 1 to 18 are the same as in Turbo Pascal }
  74. { DO NOT MODIFY UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING! }
  75. { The media is write protected. }
  76. ERROR_WRITE_PROTECT = 19;
  77. { The system cannot find the device specified. }
  78. ERROR_BAD_UNIT = 20;
  79. { The device is not ready. }
  80. ERROR_NOT_READY = 21;
  81. { The device does not recognize the command. }
  82. ERROR_BAD_COMMAND = 22;
  83. { Data error (cyclic redundancy check) }
  84. ERROR_CRC = 23;
  85. { The program issued a command but the }
  86. { command length is incorrect. }
  87. ERROR_BAD_LENGTH = 24;
  88. { The drive cannot locate a specific }
  89. { area or track on the disk. }
  90. ERROR_SEEK = 25;
  91. { The specified disk or diskette cannot be accessed. }
  92. ERROR_NOT_DOS_DISK = 26;
  93. { The drive cannot find the sector requested. }
  94. ERROR_SECTOR_NOT_FOUND = 27;
  95. { The printer is out of paper. }
  96. ERROR_OUT_OF_PAPER = 28;
  97. { The system cannot write to the specified device. }
  98. ERROR_WRITE_FAULT = 29;
  99. { The system cannot read from the specified device. }
  100. ERROR_READ_FAULT = 30;
  101. { A device attached to the system is not functioning.}
  102. ERROR_GEN_FAILURE = 31;
  103. { The process cannot access the file because }
  104. { it is being used by another process. }
  105. ERROR_SHARING_VIOLATION = 32;
  106. var
  107. errno : longint;
  108. { misc. functions }
  109. function GetLastError : DWORD;
  110. external 'kernel32' name 'GetLastError';
  111. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  112. external 'user32' name 'MessageBoxA';
  113. { time and date functions }
  114. function GetTickCount : longint;
  115. external 'kernel32' name 'GetTickCount';
  116. { process functions }
  117. procedure ExitProcess(uExitCode : UINT);
  118. external 'kernel32' name 'ExitProcess';
  119. Procedure Errno2InOutRes;
  120. Begin
  121. { DO NOT MODIFY UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING }
  122. if (errno >= ERROR_WRITE_PROTECT) and (errno <= ERROR_GEN_FAILURE) THEN
  123. BEGIN
  124. { This is the offset to the Win32 to add to directly map }
  125. { to the DOS/TP compatible error codes when in this range }
  126. InOutRes := word(errno)+131;
  127. END
  128. else
  129. { This case is special }
  130. if errno=ERROR_SHARING_VIOLATION THEN
  131. BEGIN
  132. InOutRes :=5;
  133. END
  134. else
  135. { other error codes can directly be mapped }
  136. InOutRes := Word(errno);
  137. errno:=0;
  138. end;
  139. {$ifdef dummy}
  140. procedure int_stackcheck(stack_size:longint);[public,alias: 'STACKCHECK'];
  141. {
  142. called when trying to get local stack if the compiler directive $S
  143. is set this function must preserve esi !!!! because esi is set by
  144. the calling proc for methods it must preserve all registers !!
  145. With a 2048 byte safe area used to write to StdIo without crossing
  146. the stack boundary
  147. }
  148. begin
  149. asm
  150. pushl %eax
  151. pushl %ebx
  152. movl stack_size,%ebx
  153. addl $2048,%ebx
  154. movl %esp,%eax
  155. subl %ebx,%eax
  156. movl stacklimit,%ebx
  157. cmpl %eax,%ebx
  158. jae __short_on_stack
  159. popl %ebx
  160. popl %eax
  161. leave
  162. ret $4
  163. __short_on_stack:
  164. { can be usefull for error recovery !! }
  165. popl %ebx
  166. popl %eax
  167. end['EAX','EBX'];
  168. HandleError(202);
  169. end;
  170. {$endif dummy}
  171. procedure halt(errnum : byte);
  172. begin
  173. do_exit;
  174. ExitProcess(errnum);
  175. end;
  176. function paramcount : longint;
  177. begin
  178. paramcount := argc - 1;
  179. end;
  180. function paramstr(l : longint) : string;
  181. begin
  182. if (l>=0) and (l+1<=argc) then
  183. paramstr:=strpas(argv[l])
  184. else
  185. paramstr:='';
  186. end;
  187. procedure randomize;
  188. begin
  189. randseed:=GetTickCount;
  190. end;
  191. {*****************************************************************************
  192. Heap Management
  193. *****************************************************************************}
  194. { memory functions }
  195. function GlobalAlloc(mode,size:longint):longint;
  196. external 'kernel32' name 'GlobalAlloc';
  197. function GlobalLock(handle:longint):pointer;
  198. external 'kernel32' name 'GlobalLock';
  199. {$ifdef SYSTEMDEBUG}
  200. function GlobalSize(h:longint):longint;
  201. external 'kernel32' name 'GlobalSize';
  202. {$endif}
  203. {$ASMMODE DIRECT}
  204. function getheapstart:pointer;assembler;
  205. asm
  206. leal HEAP,%eax
  207. end ['EAX'];
  208. function getheapsize:longint;assembler;
  209. asm
  210. movl HEAPSIZE,%eax
  211. end ['EAX'];
  212. {$ASMMODE ATT}
  213. function Sbrk(size : longint):longint;
  214. var
  215. h,l : longint;
  216. begin
  217. h:=GlobalAlloc(258,size);
  218. l:=longint(GlobalLock(h));
  219. if l=0 then
  220. l:=-1;
  221. {$ifdef SYSTEMDEBUG}
  222. Writeln('new heap part at $',hexstr(l,8), ' size = ',GlobalSize(h));
  223. {$endif}
  224. sbrk:=l;
  225. end;
  226. { include standard heap management }
  227. {$I heap.inc}
  228. {*****************************************************************************
  229. Low Level File Routines
  230. *****************************************************************************}
  231. function WriteFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
  232. overlap:pointer):longint;
  233. external 'kernel32' name 'WriteFile';
  234. function ReadFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
  235. overlap:pointer):longint;
  236. external 'kernel32' name 'ReadFile';
  237. function CloseHandle(h : longint) : longint;
  238. external 'kernel32' name 'CloseHandle';
  239. function DeleteFile(p : pchar) : longint;
  240. external 'kernel32' name 'DeleteFileA';
  241. function MoveFile(old,_new : pchar) : longint;
  242. external 'kernel32' name 'MoveFileA';
  243. function SetFilePointer(l1,l2 : longint;l3 : pointer;l4 : longint) : longint;
  244. external 'kernel32' name 'SetFilePointer';
  245. function GetFileSize(h:longint;p:pointer) : longint;
  246. external 'kernel32' name 'GetFileSize';
  247. function CreateFile(name : pointer;access,sharing : longint;
  248. security : pointer;how,attr,template : longint) : longint;
  249. external 'kernel32' name 'CreateFileA';
  250. function SetEndOfFile(h : longint) : longbool;
  251. external 'kernel32' name 'SetEndOfFile';
  252. function GetFileType(Handle:DWORD):DWord;
  253. external 'kernel32' name 'GetFileType';
  254. procedure AllowSlash(p:pchar);
  255. var
  256. i : longint;
  257. begin
  258. { allow slash as backslash }
  259. for i:=0 to strlen(p) do
  260. if p[i]='/' then p[i]:='\';
  261. end;
  262. procedure do_close(h : longint);
  263. begin
  264. closehandle(h);
  265. end;
  266. procedure do_erase(p : pchar);
  267. begin
  268. AllowSlash(p);
  269. if DeleteFile(p)=0 then
  270. Begin
  271. errno:=GetLastError;
  272. Errno2InoutRes;
  273. end;
  274. end;
  275. procedure do_rename(p1,p2 : pchar);
  276. begin
  277. AllowSlash(p1);
  278. AllowSlash(p2);
  279. if MoveFile(p1,p2)=0 then
  280. Begin
  281. errno:=GetLastError;
  282. Errno2InoutRes;
  283. end;
  284. end;
  285. function do_write(h,addr,len : longint) : longint;
  286. var
  287. size:longint;
  288. begin
  289. if writefile(h,pointer(addr),len,size,nil)=0 then
  290. Begin
  291. errno:=GetLastError;
  292. Errno2InoutRes;
  293. end;
  294. do_write:=size;
  295. end;
  296. function do_read(h,addr,len : longint) : longint;
  297. var
  298. result:longint;
  299. begin
  300. if readfile(h,pointer(addr),len,result,nil)=0 then
  301. Begin
  302. errno:=GetLastError;
  303. Errno2InoutRes;
  304. end;
  305. do_read:=result;
  306. end;
  307. function do_filepos(handle : longint) : longint;
  308. var
  309. l:longint;
  310. begin
  311. l:=SetFilePointer(handle,0,nil,FILE_CURRENT);
  312. if l=-1 then
  313. begin
  314. l:=0;
  315. errno:=GetLastError;
  316. Errno2InoutRes;
  317. end;
  318. do_filepos:=l;
  319. end;
  320. procedure do_seek(handle,pos : longint);
  321. begin
  322. if SetFilePointer(handle,pos,nil,FILE_BEGIN)=-1 then
  323. Begin
  324. errno:=GetLastError;
  325. Errno2InoutRes;
  326. end;
  327. end;
  328. function do_seekend(handle:longint):longint;
  329. begin
  330. do_seekend:=SetFilePointer(handle,0,nil,FILE_END);
  331. if do_seekend=-1 then
  332. begin
  333. errno:=GetLastError;
  334. Errno2InoutRes;
  335. end;
  336. end;
  337. function do_filesize(handle : longint) : longint;
  338. var
  339. aktfilepos : longint;
  340. begin
  341. aktfilepos:=do_filepos(handle);
  342. do_filesize:=do_seekend(handle);
  343. do_seek(handle,aktfilepos);
  344. end;
  345. procedure do_truncate (handle,pos:longint);
  346. begin
  347. do_seek(handle,pos);
  348. if not(SetEndOfFile(handle)) then
  349. begin
  350. errno:=GetLastError;
  351. Errno2InoutRes;
  352. end;
  353. end;
  354. procedure do_open(var f;p : pchar;flags:longint);
  355. {
  356. filerec and textrec have both handle and mode as the first items so
  357. they could use the same routine for opening/creating.
  358. when (flags and $10) the file will be append
  359. when (flags and $100) the file will be truncate/rewritten
  360. when (flags and $1000) there is no check for close (needed for textfiles)
  361. }
  362. var
  363. oflags,cd : longint;
  364. begin
  365. AllowSlash(p);
  366. { close first if opened }
  367. if ((flags and $1000)=0) then
  368. begin
  369. case filerec(f).mode of
  370. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  371. fmclosed : ;
  372. else
  373. begin
  374. {not assigned}
  375. inoutres:=102;
  376. exit;
  377. end;
  378. end;
  379. end;
  380. { reset file handle }
  381. filerec(f).handle:=UnusedHandle;
  382. { convert filemode to filerec modes }
  383. case (flags and 3) of
  384. 0 : begin
  385. filerec(f).mode:=fminput;
  386. oflags:=GENERIC_READ;
  387. end;
  388. 1 : begin
  389. filerec(f).mode:=fmoutput;
  390. oflags:=GENERIC_WRITE;
  391. end;
  392. 2 : begin
  393. filerec(f).mode:=fminout;
  394. oflags:=GENERIC_WRITE or GENERIC_READ;
  395. end;
  396. end;
  397. { standard is opening and existing file }
  398. cd:=OPEN_EXISTING;
  399. { create it ? }
  400. if (flags and $100)<>0 then
  401. cd:=CREATE_ALWAYS
  402. { or append ? }
  403. else
  404. if (flags and $10)<>0 then
  405. cd:=OPEN_ALWAYS;
  406. { empty name is special }
  407. if p[0]=#0 then
  408. begin
  409. case filerec(f).mode of
  410. fminput : filerec(f).handle:=StdInputHandle;
  411. fmappend,
  412. fmoutput : begin
  413. filerec(f).handle:=StdOutputHandle;
  414. filerec(f).mode:=fmoutput; {fool fmappend}
  415. end;
  416. end;
  417. exit;
  418. end;
  419. filerec(f).handle:=CreateFile(p,oflags,0,nil,cd,FILE_ATTRIBUTE_NORMAL,0);
  420. { append mode }
  421. if (flags and $10)<>0 then
  422. begin
  423. do_seekend(filerec(f).handle);
  424. filerec(f).mode:=fmoutput; {fool fmappend}
  425. end;
  426. { get errors }
  427. if (filerec(f).handle=0) or (filerec(f).handle=-1) then
  428. { handle -1 is returned sometimes !! (PM) }
  429. begin
  430. errno:=GetLastError;
  431. Errno2InoutRes;
  432. end;
  433. end;
  434. function do_isdevice(handle:longint):boolean;
  435. begin
  436. do_isdevice:=(getfiletype(handle)=2);
  437. end;
  438. {*****************************************************************************
  439. UnTyped File Handling
  440. *****************************************************************************}
  441. {$i file.inc}
  442. {*****************************************************************************
  443. Typed File Handling
  444. *****************************************************************************}
  445. {$i typefile.inc}
  446. {*****************************************************************************
  447. Text File Handling
  448. *****************************************************************************}
  449. {$DEFINE EOF_CTRLZ}
  450. {$i text.inc}
  451. {*****************************************************************************
  452. Directory Handling
  453. *****************************************************************************}
  454. function CreateDirectory(name : pointer;sec : pointer) : longint;
  455. external 'kernel32' name 'CreateDirectoryA';
  456. function RemoveDirectory(name:pointer):longint;
  457. external 'kernel32' name 'RemoveDirectoryA';
  458. function SetCurrentDirectory(name : pointer) : longint;
  459. external 'kernel32' name 'SetCurrentDirectoryA';
  460. function GetCurrentDirectory(bufsize : longint;name : pchar) : longint;
  461. external 'kernel32' name 'GetCurrentDirectoryA';
  462. type
  463. TDirFnType=function(name:pointer):word;
  464. procedure dirfn(afunc : TDirFnType;const s:string);
  465. var
  466. buffer : array[0..255] of char;
  467. begin
  468. move(s[1],buffer,length(s));
  469. buffer[length(s)]:=#0;
  470. AllowSlash(pchar(@buffer));
  471. if aFunc(@buffer)=0 then
  472. begin
  473. errno:=GetLastError;
  474. Errno2InoutRes;
  475. end;
  476. end;
  477. function CreateDirectoryTrunc(name:pointer):word;
  478. begin
  479. CreateDirectoryTrunc:=CreateDirectory(name,nil);
  480. end;
  481. procedure mkdir(const s:string);[IOCHECK];
  482. begin
  483. If InOutRes <> 0 then exit;
  484. dirfn(TDirFnType(@CreateDirectoryTrunc),s);
  485. end;
  486. procedure rmdir(const s:string);[IOCHECK];
  487. begin
  488. If InOutRes <> 0 then exit;
  489. dirfn(TDirFnType(@RemoveDirectory),s);
  490. end;
  491. procedure chdir(const s:string);[IOCHECK];
  492. begin
  493. If InOutRes <> 0 then exit;
  494. dirfn(TDirFnType(@SetCurrentDirectory),s);
  495. end;
  496. procedure getdir(drivenr:byte;var dir:shortstring);
  497. const
  498. Drive:array[0..3]of char=(#0,':',#0,#0);
  499. var
  500. defaultdrive:boolean;
  501. DirBuf,SaveBuf:array[0..259] of Char;
  502. begin
  503. defaultdrive:=drivenr=0;
  504. if not defaultdrive then
  505. begin
  506. byte(Drive[0]):=Drivenr+64;
  507. GetCurrentDirectory(SizeOf(SaveBuf),SaveBuf);
  508. SetCurrentDirectory(@Drive);
  509. end;
  510. GetCurrentDirectory(SizeOf(DirBuf),DirBuf);
  511. if not defaultdrive then
  512. SetCurrentDirectory(@SaveBuf);
  513. dir:=strpas(DirBuf);
  514. end;
  515. {*****************************************************************************
  516. SystemUnit Initialization
  517. *****************************************************************************}
  518. { Startup }
  519. procedure GetStartupInfo(p : pointer);
  520. external 'kernel32' name 'GetStartupInfoA';
  521. function GetStdHandle(nStdHandle:DWORD):THANDLE;
  522. external 'kernel32' name 'GetStdHandle';
  523. { command line/enviroment functions }
  524. function GetCommandLine : pchar;
  525. external 'kernel32' name 'GetCommandLineA';
  526. { module functions }
  527. function GetModuleFileName(l1:longint;p:pointer;l2:longint):longint;
  528. external 'kernel32' name 'GetModuleFileNameA';
  529. function GetModuleHandle(p : pointer) : longint;
  530. external 'kernel32' name 'GetModuleHandleA';
  531. var
  532. ModuleName : array[0..255] of char;
  533. function GetCommandFile:pchar;
  534. begin
  535. GetModuleFileName(0,@ModuleName,255);
  536. GetCommandFile:=@ModuleName;
  537. end;
  538. procedure setup_arguments;
  539. var
  540. arglen,
  541. count : longint;
  542. argstart,
  543. cmdline : pchar;
  544. quote : set of char;
  545. argsbuf : array[0..127] of pchar;
  546. begin
  547. { create commandline, it starts with the executed filename which is argv[0] }
  548. cmdline:=GetCommandLine;
  549. count:=0;
  550. repeat
  551. { skip leading spaces }
  552. while cmdline^ in [' ',#9,#13] do
  553. inc(longint(cmdline));
  554. case cmdline^ of
  555. #0 : break;
  556. '"' : begin
  557. quote:=['"'];
  558. inc(longint(cmdline));
  559. end;
  560. '''' : begin
  561. quote:=[''''];
  562. inc(longint(cmdline));
  563. end;
  564. else
  565. quote:=[' ',#9,#13];
  566. end;
  567. { scan until the end of the argument }
  568. argstart:=cmdline;
  569. while (cmdline^<>#0) and not(cmdline^ in quote) do
  570. inc(longint(cmdline));
  571. { reserve some memory }
  572. arglen:=cmdline-argstart;
  573. getmem(argsbuf[count],arglen+1);
  574. move(argstart^,argsbuf[count]^,arglen);
  575. argsbuf[count][arglen]:=#0;
  576. { skip quote }
  577. if cmdline^ in quote then
  578. inc(longint(cmdline));
  579. inc(count);
  580. until false;
  581. { create argc }
  582. argc:=count;
  583. { create an nil entry }
  584. argsbuf[count]:=nil;
  585. inc(count);
  586. { create the argv }
  587. getmem(argv,count shl 2);
  588. move(argsbuf,argv^,count shl 2);
  589. end;
  590. {$ifdef dummy}
  591. Function SetUpStack : longint;
  592. { This routine does the following : }
  593. { returns the value of the initial SP - __stklen }
  594. begin
  595. asm
  596. pushl %ebx
  597. pushl %eax
  598. movl __stklen,%ebx
  599. movl %esp,%eax
  600. subl %ebx,%eax
  601. movl %eax,__RESULT
  602. popl %eax
  603. popl %ebx
  604. end;
  605. end;
  606. {$endif}
  607. procedure install_exception_handlers;forward;
  608. {$ASMMODE DIRECT}
  609. var
  610. { value of the stack segment
  611. to check if the call stack can be written on exceptions }
  612. _SS : longint;
  613. procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
  614. begin
  615. IsLibrary:=false;
  616. { install the handlers for exe only ?
  617. or should we install them for DLL also ? (PM) }
  618. install_exception_handlers;
  619. asm
  620. pushl %ebp
  621. xorl %ebp,%ebp
  622. movw %ss,%bp
  623. movl %ebp,__SS
  624. xorl %ebp,%ebp
  625. call PASCALMAIN
  626. popl %ebp
  627. end;
  628. { if we pass here there was no error ! }
  629. ExitProcess(0);
  630. end;
  631. procedure Dll_entry;[public, alias : '_FPC_DLL_Entry'];
  632. begin
  633. IsLibrary:=true;
  634. case DLLreason of
  635. 1,2 : asm
  636. xorl %edi,%edi
  637. movw %ss,%di
  638. movl %edi,__SS
  639. call PASCALMAIN
  640. end;
  641. else
  642. asm
  643. call FPC_DO_EXIT
  644. end;
  645. end;
  646. end;
  647. {$ifdef Set_i386_Exception_handler}
  648. const
  649. EXCEPTION_MAXIMUM_PARAMETERS = 15;
  650. EXCEPTION_ACCESS_VIOLATION = $c0000005;
  651. EXCEPTION_BREAKPOINT = $80000003;
  652. EXCEPTION_DATATYPE_MISALIGNMENT = $80000002;
  653. EXCEPTION_SINGLE_STEP = $80000004;
  654. EXCEPTION_ARRAY_BOUNDS_EXCEEDED = $c000008c;
  655. EXCEPTION_FLT_DENORMAL_OPERAND = $c000008d;
  656. EXCEPTION_FLT_DIVIDE_BY_ZERO = $c000008e;
  657. EXCEPTION_FLT_INEXACT_RESULT = $c000008f;
  658. EXCEPTION_FLT_INVALID_OPERATION = $c0000090;
  659. EXCEPTION_FLT_OVERFLOW = $c0000091;
  660. EXCEPTION_FLT_STACK_CHECK = $c0000092;
  661. EXCEPTION_FLT_UNDERFLOW = $c0000093;
  662. EXCEPTION_INT_DIVIDE_BY_ZERO = $c0000094;
  663. EXCEPTION_INT_OVERFLOW = $c0000095;
  664. EXCEPTION_INVALID_HANDLE = $c0000008;
  665. EXCEPTION_PRIV_INSTRUCTION = $c0000096;
  666. EXCEPTION_NONCONTINUABLE_EXCEPTION = $c0000025;
  667. EXCEPTION_NONCONTINUABLE = $1;
  668. EXCEPTION_STACK_OVERFLOW = $c00000fd;
  669. EXCEPTION_INVALID_DISPOSITION = $c0000026;
  670. ExceptionContinueExecution = 0;
  671. ExceptionContinueSearch = 1;
  672. type
  673. FLOATING_SAVE_AREA = record
  674. ControlWord : DWORD;
  675. StatusWord : DWORD;
  676. TagWord : DWORD;
  677. ErrorOffset : DWORD;
  678. ErrorSelector : DWORD;
  679. DataOffset : DWORD;
  680. DataSelector : DWORD;
  681. RegisterArea : array[0..79] of BYTE;
  682. Cr0NpxState : DWORD;
  683. end;
  684. _FLOATING_SAVE_AREA = FLOATING_SAVE_AREA;
  685. TFLOATINGSAVEAREA = FLOATING_SAVE_AREA;
  686. PFLOATINGSAVEAREA = ^FLOATING_SAVE_AREA;
  687. CONTEXT = record
  688. ContextFlags : DWORD;
  689. Dr0 : DWORD;
  690. Dr1 : DWORD;
  691. Dr2 : DWORD;
  692. Dr3 : DWORD;
  693. Dr6 : DWORD;
  694. Dr7 : DWORD;
  695. FloatSave : FLOATING_SAVE_AREA;
  696. SegGs : DWORD;
  697. SegFs : DWORD;
  698. SegEs : DWORD;
  699. SegDs : DWORD;
  700. Edi : DWORD;
  701. Esi : DWORD;
  702. Ebx : DWORD;
  703. Edx : DWORD;
  704. Ecx : DWORD;
  705. Eax : DWORD;
  706. Ebp : DWORD;
  707. Eip : DWORD;
  708. SegCs : DWORD;
  709. EFlags : DWORD;
  710. Esp : DWORD;
  711. SegSs : DWORD;
  712. end;
  713. LPCONTEXT = ^CONTEXT;
  714. _CONTEXT = CONTEXT;
  715. TCONTEXT = CONTEXT;
  716. PCONTEXT = ^CONTEXT;
  717. type pexception_record = ^exception_record;
  718. EXCEPTION_RECORD = record
  719. ExceptionCode : longint;
  720. ExceptionFlags : longint;
  721. ExceptionRecord : pexception_record;
  722. ExceptionAddress : pointer;
  723. NumberParameters : longint;
  724. ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of pointer;
  725. end;
  726. PEXCEPTION_POINTERS = ^EXCEPTION_POINTERS;
  727. EXCEPTION_POINTERS = record
  728. ExceptionRecord : PEXCEPTION_RECORD ;
  729. ContextRecord : PCONTEXT ;
  730. end;
  731. { type of functions that should be used for exception handling }
  732. LPTOP_LEVEL_EXCEPTION_FILTER = function(excep :PEXCEPTION_POINTERS) : longint;
  733. function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : LPTOP_LEVEL_EXCEPTION_FILTER)
  734. : LPTOP_LEVEL_EXCEPTION_FILTER;
  735. external 'kernel32' name 'SetUnhandledExceptionFilter';
  736. function syswin32_i386_exception_handler(excep :PEXCEPTION_POINTERS) : longint;
  737. var frame : longint;
  738. begin
  739. { default : unhandled !}
  740. if excep^.ContextRecord^.SegSs=_SS then
  741. frame:=excep^.ContextRecord^.Ebp
  742. else
  743. frame:=0;
  744. syswin32_i386_exception_handler:=ExceptionContinueSearch;
  745. case excep^.ExceptionRecord^.ExceptionCode of
  746. EXCEPTION_ACCESS_VIOLATION :
  747. HandleErrorFrame(216,frame);
  748. { EXCEPTION_BREAKPOINT = $80000003;
  749. EXCEPTION_DATATYPE_MISALIGNMENT = $80000002;
  750. EXCEPTION_SINGLE_STEP = $80000004; }
  751. EXCEPTION_ARRAY_BOUNDS_EXCEEDED :
  752. HandleErrorFrame(201,frame);
  753. { EXCEPTION_FLT_DENORMAL_OPERAND = $c000008d; }
  754. EXCEPTION_FLT_DIVIDE_BY_ZERO :
  755. HandleErrorFrame(200,frame);
  756. {EXCEPTION_FLT_INEXACT_RESULT = $c000008f;
  757. EXCEPTION_FLT_INVALID_OPERATION = $c0000090;}
  758. EXCEPTION_FLT_OVERFLOW :
  759. HandleErrorFrame(205,frame);
  760. EXCEPTION_FLT_STACK_CHECK :
  761. HandleErrorFrame(207,frame);
  762. { EXCEPTION_FLT_UNDERFLOW :
  763. HandleErrorFrame(206,frame); should be accepted as zero !! }
  764. EXCEPTION_INT_DIVIDE_BY_ZERO :
  765. HandleErrorFrame(200,frame);
  766. EXCEPTION_INT_OVERFLOW :
  767. HandleErrorFrame(215,frame);
  768. {EXCEPTION_INVALID_HANDLE = $c0000008;
  769. EXCEPTION_PRIV_INSTRUCTION = $c0000096;
  770. EXCEPTION_NONCONTINUABLE_EXCEPTION = $c0000025;
  771. EXCEPTION_NONCONTINUABLE = $1;}
  772. EXCEPTION_STACK_OVERFLOW :
  773. HandleErrorFrame(202,frame);
  774. {EXCEPTION_INVALID_DISPOSITION = $c0000026;}
  775. end;
  776. end;
  777. var
  778. old_exception : LPTOP_LEVEL_EXCEPTION_FILTER;
  779. procedure install_exception_handlers;
  780. begin
  781. old_exception:=SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
  782. end;
  783. {$else not i386 (Processor specific !!)}
  784. procedure install_exception_handlers;
  785. begin
  786. end;
  787. {$endif Set_i386_Exception_handler}
  788. const
  789. Exe_entry_code : pointer = @Exe_entry;
  790. Dll_entry_code : pointer = @Dll_entry;
  791. {$ASMMODE ATT}
  792. begin
  793. { get some helpful informations }
  794. GetStartupInfo(@startupinfo);
  795. { some misc Win32 stuff }
  796. hprevinst:=0;
  797. if not IsLibrary then
  798. HInstance:=getmodulehandle(GetCommandFile);
  799. MainInstance:=HInstance;
  800. { No idea how to know this issue !! }
  801. IsMultithreaded:=false;
  802. cmdshow:=startupinfo.wshowwindow;
  803. { to test stack depth }
  804. loweststack:=maxlongint;
  805. { real test stack depth }
  806. { stacklimit := setupstack; }
  807. { Setup heap }
  808. InitHeap;
  809. { Setup stdin, stdout and stderr }
  810. StdInputHandle:=longint(GetStdHandle(STD_INPUT_HANDLE));
  811. StdOutputHandle:=longint(GetStdHandle(STD_OUTPUT_HANDLE));
  812. StdErrorHandle:=longint(GetStdHandle(STD_ERROR_HANDLE));
  813. OpenStdIO(Input,fmInput,StdInputHandle);
  814. OpenStdIO(Output,fmOutput,StdOutputHandle);
  815. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  816. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  817. { Arguments }
  818. setup_arguments;
  819. { Reset IO Error }
  820. InOutRes:=0;
  821. { Reset internal error variable }
  822. errno := 0;
  823. end.
  824. {
  825. $Log$
  826. Revision 1.31 1998-12-28 15:50:51 peter
  827. + stdout, which is needed when you write something in the system unit
  828. to the screen. Like the runtime error
  829. Revision 1.30 1998/12/21 14:28:23 pierre
  830. * HandleError -> HandleErrorFrame to avoid problem in
  831. assembler code in i386.inc
  832. (call to overloaded function in assembler block !)
  833. Revision 1.29 1998/12/15 22:43:14 peter
  834. * removed temp symbols
  835. Revision 1.28 1998/12/09 17:57:33 pierre
  836. + exception handling by default
  837. Revision 1.27 1998/12/01 14:00:08 pierre
  838. + added conversion from exceptions into run time error
  839. (only if syswin32 compiled with -ddebug for now !)
  840. * added HandleErrorFrame(errno,frame)
  841. where you specify the frame
  842. needed for win32 exception handling
  843. Revision 1.26 1998/11/30 13:13:41 pierre
  844. * needs asw to link correctly wprt0 or wdllprt0 file
  845. Revision 1.25 1998/11/30 09:16:58 pierre
  846. + added the changes from Pavel Ozerski after several modifications
  847. to be able to create DLLs
  848. Revision 1.24 1998/11/16 15:48:54 peter
  849. * fixed longbool returns for api calls
  850. Revision 1.23 1998/11/16 14:14:58 pierre
  851. * changed getdir(byte,string) to getdir(byte,shortstring)
  852. Revision 1.22 1998/10/27 15:07:16 florian
  853. + Is* flags added
  854. + IsLibrary works also
  855. Revision 1.21 1998/10/15 16:26:19 peter
  856. + fpuinit
  857. + end of backtrace indicator
  858. Revision 1.20 1998/09/14 10:48:33 peter
  859. * FPC_ names
  860. * Heap manager is now system independent
  861. Revision 1.19 1998/09/02 09:03:46 pierre
  862. * do_open sometimes returns -1 as handle on fail
  863. was not checked correctly
  864. Revision 1.16 1998/08/24 14:45:22 pierre
  865. * sbrk was wrong
  866. heap growing now works for win32
  867. Revision 1.15 1998/08/21 10:10:16 peter
  868. * winheap turned off by default
  869. Revision 1.14 1998/07/30 13:27:19 michael
  870. + Added support for errorproc. Changed runerror to HandleError
  871. Revision 1.13 1998/07/13 21:19:15 florian
  872. * some problems with ansi string support fixed
  873. Revision 1.12 1998/07/07 12:37:28 carl
  874. * correct mapping of error codes for TP compatibility
  875. + implemented stack checking in ifdef dummy
  876. Revision 1.11 1998/07/02 12:33:18 carl
  877. * IOCheck/InOutRes check for mkdir,rmdir and chdir like in TP
  878. Revision 1.10 1998/07/01 15:30:02 peter
  879. * better readln/writeln
  880. Revision 1.9 1998/06/10 10:39:17 peter
  881. * working w32 rtl
  882. Revision 1.8 1998/06/08 23:07:47 peter
  883. * dos interface is now 100% compatible
  884. * fixed call PASCALMAIN which must be direct asm
  885. Revision 1.7 1998/05/06 12:36:51 michael
  886. + Removed log from before restored version.
  887. Revision 1.6 1998/04/27 18:29:09 florian
  888. + do_open implemented, the file-I/O should be now complete
  889. Revision 1.5 1998/04/27 13:58:21 florian
  890. + paramstr/paramcount implemented
  891. Revision 1.4 1998/04/26 22:37:22 florian
  892. * some small extensions
  893. Revision 1.3 1998/04/26 21:49:57 florian
  894. + more stuff added (??dir procedures etc.)
  895. }