syswin32.pp 28 KB

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