syswin32.pp 31 KB

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