syswin32.pp 30 KB

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