syswin32.pp 30 KB

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