syswin32.pp 30 KB

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