syswin32.pp 28 KB

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