syswin32.pp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993-98 by Florian Klaempfl and Pavel Ozerski
  5. member of the Free Pascal development team.
  6. FPC Pascal system unit for the Win32 API.
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {$S-}
  14. unit syswin32;
  15. {$I os.inc}
  16. interface
  17. { include system-independent routine headers }
  18. {$I systemh.inc}
  19. const
  20. { Default filehandles }
  21. UnusedHandle : longint = -1;
  22. StdInputHandle : longint = 0;
  23. StdOutputHandle : longint = 0;
  24. StdErrorHandle : longint = 0;
  25. type
  26. TStartupInfo=packed record
  27. cb : longint;
  28. lpReserved : Pointer;
  29. lpDesktop : Pointer;
  30. lpTitle : Pointer;
  31. dwX : longint;
  32. dwY : longint;
  33. dwXSize : longint;
  34. dwYSize : longint;
  35. dwXCountChars : longint;
  36. dwYCountChars : longint;
  37. dwFillAttribute : longint;
  38. dwFlags : longint;
  39. wShowWindow : Word;
  40. cbReserved2 : Word;
  41. lpReserved2 : Pointer;
  42. hStdInput : longint;
  43. hStdOutput : longint;
  44. hStdError : longint;
  45. end;
  46. var
  47. startupinfo : tstartupinfo;
  48. hprevinst,
  49. hinstance,
  50. cmdshow : longint;
  51. heaperror : pointer;
  52. implementation
  53. { include system independent routines }
  54. {$I system.inc}
  55. { some declarations for Win32 API calls }
  56. {$I win32.inc}
  57. type
  58. plongint = ^longint;
  59. { misc. functions }
  60. function GetLastError : DWORD;
  61. external 'kernel32' name 'GetLastError';
  62. function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
  63. external 'user32' name 'MessageBoxA';
  64. { command line/enviroment functions }
  65. function GetCommandLine : LPTSTR;
  66. external 'kernel32' name 'GetCommandLineA';
  67. { time and date functions }
  68. function GetTickCount : longint;
  69. external 'kernel32' name 'GetTickCount';
  70. { process functions }
  71. procedure ExitProcess(uExitCode : UINT);
  72. external 'kernel32' name 'ExitProcess';
  73. {$ifdef dummy}
  74. procedure int_stackcheck(stack_size:longint);[public,alias: 'STACKCHECK'];
  75. {
  76. called when trying to get local stack if the compiler directive $S
  77. is set this function must preserve esi !!!! because esi is set by
  78. the calling proc for methods it must preserve all registers !!
  79. }
  80. begin
  81. asm
  82. pushl %eax
  83. pushl %ebx
  84. movl stack_size,%ebx
  85. movl %esp,%eax
  86. subl %ebx,%eax
  87. {$ifdef SYSTEMDEBUG}
  88. movl U_SYSTEM_LOWESTSTACK,%ebx
  89. cmpl %eax,%ebx
  90. jb _is_not_lowest
  91. movl %eax,U_SYSTEM_LOWESTSTACK
  92. _is_not_lowest:
  93. {$endif SYSTEMDEBUG}
  94. movl __stkbottom,%ebx
  95. cmpl %eax,%ebx
  96. jae __short_on_stack
  97. popl %ebx
  98. popl %eax
  99. leave
  100. ret $4
  101. __short_on_stack:
  102. { can be usefull for error recovery !! }
  103. popl %ebx
  104. popl %eax
  105. end['EAX','EBX'];
  106. RunError(202);
  107. end;
  108. {$endif dummy}
  109. procedure halt(errnum : byte);
  110. begin
  111. do_exit;
  112. flush(stderr);
  113. ExitProcess(errnum);
  114. end;
  115. function paramcount : longint;
  116. var
  117. count : longint;
  118. cmdline : pchar;
  119. quote : set of char;
  120. begin
  121. cmdline:=GetCommandLine;
  122. count:=0;
  123. while true do
  124. begin
  125. { skip leading spaces }
  126. while cmdline^ in [' ',#9] do
  127. cmdline:=cmdline+1;
  128. if cmdline^='"' then
  129. begin
  130. quote:=['"'];
  131. cmdline:=cmdline+1;
  132. end
  133. else
  134. quote:=[' ',#9];
  135. if cmdline^=#0 then
  136. break;
  137. inc(count);
  138. while (cmdline^<>#0) and not(cmdline^ in quote) do
  139. cmdline:=cmdline+1;
  140. { skip quote }
  141. if cmdline^ in quote then
  142. cmdline:=cmdline+1;
  143. end;
  144. paramcount:=count-1;
  145. end;
  146. function paramstr(l : longint) : string;
  147. var
  148. s : string;
  149. count : longint;
  150. cmdline : pchar;
  151. quote : set of char;
  152. begin
  153. s:='';
  154. if (l>=0) and (l<=paramcount) then
  155. begin
  156. cmdline:=GetCommandLine;
  157. count:=0;
  158. while true do
  159. begin
  160. { skip leading spaces }
  161. while cmdline^ in [' ',#9] do
  162. cmdline:=cmdline+1;
  163. if cmdline^='"' then
  164. begin
  165. quote:=['"'];
  166. cmdline:=cmdline+1;
  167. end
  168. else
  169. quote:=[' ',#9];
  170. if cmdline^=#0 then
  171. break;
  172. if count=l then
  173. begin
  174. while (cmdline^<>#0) and not(cmdline^ in quote) do
  175. begin
  176. s:=s+cmdline^;
  177. cmdline:=cmdline+1;
  178. end;
  179. break;
  180. end
  181. else
  182. begin
  183. while (cmdline^<>#0) and not(cmdline^ in quote) do
  184. cmdline:=cmdline+1;
  185. end;
  186. { skip quote }
  187. if cmdline^ in quote then
  188. cmdline:=cmdline+1;
  189. inc(count);
  190. end;
  191. end;
  192. paramstr:=s;
  193. end;
  194. procedure randomize;
  195. begin
  196. randseed:=GetTickCount;
  197. end;
  198. {*****************************************************************************
  199. Heap Management
  200. *****************************************************************************}
  201. { Include Windows Heap manager }
  202. {$I winheap.inc}
  203. {*****************************************************************************
  204. Low Level File Routines
  205. *****************************************************************************}
  206. function WriteFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
  207. overlap:pointer):longint;
  208. external 'kernel32' name 'WriteFile';
  209. function ReadFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
  210. overlap:pointer):longint;
  211. external 'kernel32' name 'ReadFile';
  212. function CloseHandle(h : longint) : longint;
  213. external 'kernel32' name 'CloseHandle';
  214. function DeleteFile(p : pchar) : longint;
  215. external 'kernel32' name 'DeleteFileA';
  216. function MoveFile(old,_new : pchar) : longint;
  217. external 'kernel32' name 'MoveFileA';
  218. function SetFilePointer(l1,l2 : longint;l3 : pointer;l4 : longint) : longint;
  219. external 'kernel32' name 'SetFilePointer';
  220. function GetFileSize(h:longint;p:pointer) : longint;
  221. external 'kernel32' name 'GetFileSize';
  222. function CreateFile(name : pointer;access,sharing : longint;
  223. security : pointer;how,attr,template : longint) : longint;
  224. external 'kernel32' name 'CreateFileA';
  225. function SetEndOfFile(h : longint) : boolean;
  226. external 'kernel32' name 'SetEndOfFile';
  227. procedure AllowSlash(p:pchar);
  228. var
  229. i : longint;
  230. begin
  231. { allow slash as backslash }
  232. for i:=0 to strlen(p) do
  233. if p[i]='/' then p[i]:='\';
  234. end;
  235. procedure do_close(h : longint);
  236. begin
  237. closehandle(h);
  238. end;
  239. procedure do_erase(p : pchar);
  240. begin
  241. AllowSlash(p);
  242. if DeleteFile(p)=0 then
  243. inoutres:=GetLastError;
  244. end;
  245. procedure do_rename(p1,p2 : pchar);
  246. begin
  247. AllowSlash(p1);
  248. AllowSlash(p2);
  249. if MoveFile(p1,p2)=0 then
  250. inoutres:=GetLastError;
  251. end;
  252. function do_write(h,addr,len : longint) : longint;
  253. var
  254. size:longint;
  255. begin
  256. if writefile(h,pointer(addr),len,size,nil)=0 then
  257. inoutres:=GetLastError;
  258. do_write:=size;
  259. end;
  260. function do_read(h,addr,len : longint) : longint;
  261. var
  262. result:longint;
  263. begin
  264. if readfile(h,pointer(addr),len,result,nil)=0 then
  265. inoutres:=GetLastError;
  266. do_read:=result;
  267. end;
  268. function do_filepos(handle : longint) : longint;
  269. var
  270. l:longint;
  271. begin
  272. l:=SetFilePointer(handle,0,nil,FILE_CURRENT);
  273. if l=-1 then
  274. begin
  275. l:=0;
  276. inoutres:=GetLastError;
  277. end;
  278. do_filepos:=l;
  279. end;
  280. procedure do_seek(handle,pos : longint);
  281. begin
  282. if SetFilePointer(handle,pos,nil,FILE_BEGIN)=-1 then
  283. inoutres:=GetLastError;
  284. end;
  285. function do_seekend(handle:longint):longint;
  286. begin
  287. do_seekend:=SetFilePointer(handle,0,nil,FILE_END);
  288. if do_seekend=-1 then
  289. begin
  290. inoutres:=GetLastError;
  291. do_seekend:=0;
  292. end;
  293. end;
  294. function do_filesize(handle : longint) : longint;
  295. var
  296. aktfilepos : longint;
  297. begin
  298. aktfilepos:=do_filepos(handle);
  299. do_filesize:=do_seekend(handle);
  300. do_seek(handle,aktfilepos);
  301. end;
  302. procedure do_truncate (handle,pos:longint);
  303. begin
  304. do_seek(handle,pos);
  305. if not(SetEndOfFile(handle)) then
  306. inoutres:=GetLastError;
  307. end;
  308. procedure do_open(var f;p : pchar;flags:longint);
  309. {
  310. filerec and textrec have both handle and mode as the first items so
  311. they could use the same routine for opening/creating.
  312. when (flags and $10) the file will be append
  313. when (flags and $100) the file will be truncate/rewritten
  314. when (flags and $1000) there is no check for close (needed for textfiles)
  315. }
  316. var
  317. oflags,cd : longint;
  318. begin
  319. AllowSlash(p);
  320. { close first if opened }
  321. if ((flags and $1000)=0) then
  322. begin
  323. case filerec(f).mode of
  324. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  325. fmclosed : ;
  326. else
  327. begin
  328. {not assigned}
  329. inoutres:=102;
  330. exit;
  331. end;
  332. end;
  333. end;
  334. { reset file handle }
  335. filerec(f).handle:=UnusedHandle;
  336. { convert filemode to filerec modes }
  337. case (flags and 3) of
  338. 0 : begin
  339. filerec(f).mode:=fminput;
  340. oflags:=GENERIC_READ;
  341. end;
  342. 1 : begin
  343. filerec(f).mode:=fmoutput;
  344. oflags:=GENERIC_WRITE;
  345. end;
  346. 2 : begin
  347. filerec(f).mode:=fminout;
  348. oflags:=GENERIC_WRITE or GENERIC_READ;
  349. end;
  350. end;
  351. { standard is opening and existing file }
  352. cd:=OPEN_EXISTING;
  353. { create it ? }
  354. if (flags and $100)<>0 then
  355. cd:=CREATE_ALWAYS
  356. { or append ? }
  357. else
  358. if (flags and $10)<>0 then
  359. cd:=OPEN_ALWAYS;
  360. { empty name is special }
  361. if p[0]=#0 then
  362. begin
  363. case filerec(f).mode of
  364. fminput : filerec(f).handle:=StdInputHandle;
  365. fmappend,
  366. fmoutput : begin
  367. filerec(f).handle:=StdOutputHandle;
  368. filerec(f).mode:=fmoutput; {fool fmappend}
  369. end;
  370. end;
  371. exit;
  372. end;
  373. filerec(f).handle:=CreateFile(p,oflags,0,nil,cd,FILE_ATTRIBUTE_NORMAL,0);
  374. { append mode }
  375. if (flags and $10)<>0 then
  376. begin
  377. do_seekend(filerec(f).handle);
  378. filerec(f).mode:=fmoutput; {fool fmappend}
  379. end;
  380. { get errors }
  381. if filerec(f).handle=0 then
  382. inoutres:=GetLastError;
  383. end;
  384. {*****************************************************************************
  385. UnTyped File Handling
  386. *****************************************************************************}
  387. {$i file.inc}
  388. {*****************************************************************************
  389. Typed File Handling
  390. *****************************************************************************}
  391. {$i typefile.inc}
  392. {*****************************************************************************
  393. Text File Handling
  394. *****************************************************************************}
  395. {$DEFINE EOF_CTRLZ}
  396. {$i text.inc}
  397. {*****************************************************************************
  398. Directory Handling
  399. *****************************************************************************}
  400. function CreateDirectory(name : pointer;sec : pointer) : longint;
  401. external 'kernel32' name 'CreateDirectoryA';
  402. function RemoveDirectory(name:pointer):longint;
  403. external 'kernel32' name 'RemoveDirectoryA';
  404. function SetCurrentDirectory(name : pointer) : longint;
  405. external 'kernel32' name 'SetCurrentDirectoryA';
  406. function GetCurrentDirectory(bufsize : longint;name : pchar) : longint;
  407. external 'kernel32' name 'GetCurrentDirectoryA';
  408. type
  409. TDirFnType=function(name:pointer):word;
  410. procedure dirfn(afunc : TDirFnType;const s:string);
  411. var
  412. buffer : array[0..255] of char;
  413. begin
  414. move(s[1],buffer,length(s));
  415. buffer[length(s)]:=#0;
  416. AllowSlash(pchar(@buffer));
  417. if aFunc(@buffer)=0 then
  418. inoutres:=GetLastError;
  419. end;
  420. function CreateDirectoryTrunc(name:pointer):word;
  421. begin
  422. CreateDirectoryTrunc:=CreateDirectory(name,nil);
  423. end;
  424. procedure mkdir(const s:string);[IOCHECK];
  425. begin
  426. dirfn(TDirFnType(@CreateDirectoryTrunc),s);
  427. end;
  428. procedure rmdir(const s:string);[IOCHECK];
  429. begin
  430. dirfn(TDirFnType(@RemoveDirectory),s);
  431. end;
  432. procedure chdir(const s:string);[IOCHECK];
  433. begin
  434. dirfn(TDirFnType(@SetCurrentDirectory),s);
  435. end;
  436. procedure getdir(drivenr:byte;var dir:string);
  437. const
  438. Drive:array[0..3]of char=(#0,':',#0,#0);
  439. var
  440. defaultdrive:boolean;
  441. DirBuf,SaveBuf:array[0..259] of Char;
  442. begin
  443. defaultdrive:=drivenr=0;
  444. if not defaultdrive then
  445. begin
  446. byte(Drive[0]):=Drivenr+64;
  447. GetCurrentDirectory(SizeOf(SaveBuf),SaveBuf);
  448. SetCurrentDirectory(@Drive);
  449. end;
  450. GetCurrentDirectory(SizeOf(DirBuf),DirBuf);
  451. if not defaultdrive then
  452. SetCurrentDirectory(@SaveBuf);
  453. dir:=strpas(DirBuf);
  454. end;
  455. {*****************************************************************************
  456. SystemUnit Initialization
  457. *****************************************************************************}
  458. { Startup }
  459. procedure GetStartupInfo(p : pointer);
  460. external 'kernel32' name 'GetStartupInfoA';
  461. function GetStdHandle(nStdHandle:DWORD):THANDLE;
  462. external 'kernel32' name 'GetStdHandle';
  463. { module functions }
  464. function GetModuleFileName(l1:longint;p:pointer;l2:longint):longint;
  465. external 'kernel32' name 'GetModuleFileNameA';
  466. function GetModuleHandle(p : pointer) : longint;
  467. external 'kernel32' name 'GetModuleHandleA';
  468. {$ASMMODE DIRECT}
  469. procedure Entry;[public,alias: '_mainCRTStartup'];
  470. begin
  471. { call to the pascal main }
  472. asm
  473. call PASCALMAIN
  474. end;
  475. { that's all folks }
  476. ExitProcess(0);
  477. end;
  478. {$ASMMODE ATT}
  479. procedure OpenStdIO(var f:text;mode:word;hdl:longint);
  480. begin
  481. Assign(f,'');
  482. TextRec(f).Handle:=hdl;
  483. TextRec(f).Mode:=mode;
  484. TextRec(f).InOutFunc:=@FileInOutFunc;
  485. TextRec(f).FlushFunc:=@FileInOutFunc;
  486. TextRec(f).Closefunc:=@fileclosefunc;
  487. end;
  488. var
  489. s : string;
  490. begin
  491. { get some helpful informations }
  492. GetStartupInfo(@startupinfo);
  493. { Initialize ExitProc }
  494. ExitProc:=Nil;
  495. { to test stack depth }
  496. loweststack:=maxlongint;
  497. { Setup heap }
  498. {!!! InitHeap; }
  499. { Setup stdin, stdout and stderr }
  500. StdInputHandle:=longint(GetStdHandle(STD_INPUT_HANDLE));
  501. StdOutputHandle:=longint(GetStdHandle(STD_OUTPUT_HANDLE));
  502. StdErrorHandle:=longint(GetStdHandle(STD_ERROR_HANDLE));
  503. OpenStdIO(Input,fmInput,StdInputHandle);
  504. OpenStdIO(Output,fmOutput,StdOutputHandle);
  505. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  506. { Reset IO Error }
  507. InOutRes:=0;
  508. { some misc Win32 stuff }
  509. hprevinst:=0;
  510. getmodulefilename(0,@s,256);
  511. hinstance:=getmodulehandle(@s);
  512. cmdshow:=startupinfo.wshowwindow;
  513. end.
  514. {
  515. $Log$
  516. Revision 1.9 1998-06-10 10:39:17 peter
  517. * working w32 rtl
  518. Revision 1.8 1998/06/08 23:07:47 peter
  519. * dos interface is now 100% compatible
  520. * fixed call PASCALMAIN which must be direct asm
  521. Revision 1.7 1998/05/06 12:36:51 michael
  522. + Removed log from before restored version.
  523. Revision 1.6 1998/04/27 18:29:09 florian
  524. + do_open implemented, the file-I/O should be now complete
  525. Revision 1.5 1998/04/27 13:58:21 florian
  526. + paramstr/paramcount implemented
  527. Revision 1.4 1998/04/26 22:37:22 florian
  528. * some small extensions
  529. Revision 1.3 1998/04/26 21:49:57 florian
  530. + more stuff added (??dir procedures etc.)
  531. }