syswin32.pp 14 KB

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