dos.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2004 by the Free Pascal development team.
  4. Dos unit for BP7 compatible RTL
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$IFNDEF FPC_DOTTEDUNITS}
  12. unit dos;
  13. {$ENDIF FPC_DOTTEDUNITS}
  14. {$mode fpc}
  15. interface
  16. {$IFDEF FPC_DOTTEDUNITS}
  17. uses WinApi.Windows;
  18. {$ELSE FPC_DOTTEDUNITS}
  19. uses windows;
  20. {$ENDIF FPC_DOTTEDUNITS}
  21. Const
  22. Max_Path = MaxPathLen;
  23. Type
  24. Searchrec = Packed Record
  25. FindHandle : THandle;
  26. W32FindData : TWin32FindData;
  27. ExcludeAttr : longint;
  28. time : longint;
  29. size : longint;
  30. attr : longint;
  31. name : string;
  32. end;
  33. {$i dosh.inc}
  34. Function WinToDosTime (Const Wtime : TFileTime; var DTime:longint):longbool;
  35. Function DosToWinTime (DTime:longint; var Wtime : TFileTime):longbool;
  36. implementation
  37. {$DEFINE HAS_GETMSCOUNT}
  38. {$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS}
  39. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  40. {$I dos.inc}
  41. {******************************************************************************
  42. --- Conversion ---
  43. ******************************************************************************}
  44. function GetMsCount: int64;
  45. begin
  46. GetMsCount := cardinal (GetTickCount);
  47. end;
  48. function Last2DosError(d:dword):integer;
  49. begin
  50. case d of
  51. 87 : { Parameter invalid -> Data invalid }
  52. Last2DosError:=13;
  53. else
  54. Last2DosError:=integer(d);
  55. end;
  56. end;
  57. Function DosToWinAttr (Const Attr : Longint) : longint;
  58. begin
  59. DosToWinAttr:=Attr;
  60. end;
  61. Function WinToDosAttr (Const Attr : Longint) : longint;
  62. begin
  63. WinToDosAttr:=Attr;
  64. end;
  65. type
  66. Longrec=packed record
  67. lo,hi : word;
  68. end;
  69. Function DosToWinTime (DTime:longint; var Wtime : TFileTime):longbool;
  70. var
  71. FatDate, FatTime: WORD;
  72. lft: TFileTime;
  73. st: SYSTEMTIME;
  74. begin
  75. FatDate:=Longrec(Dtime).Hi;
  76. FatTime:=Longrec(Dtime).Lo;
  77. with st do
  78. begin
  79. wDay:=FatDate and $1F;
  80. wMonth:=(FatDate shr 5) and $F;
  81. wYear:=(FatDate shr 9) + 1980;
  82. wSecond:=(FatTime and $1F)*2;
  83. wMinute:=(FatTime shr 5) and $1F;
  84. wHour:=FatTime shr 11;
  85. wMilliseconds:=0;
  86. wDayOfWeek:=0;
  87. end;
  88. DosToWinTime:=SystemTimeToFileTime(@st, @lft) and LocalFileTimeToFileTime(@lft, @Wtime);
  89. end;
  90. Function WinToDosTime (Const Wtime : TFileTime; var DTime:longint):longbool;
  91. var
  92. FatDate, FatTime: WORD;
  93. lft: TFileTime;
  94. st: SYSTEMTIME;
  95. res: longbool;
  96. begin
  97. res:=FileTimeToLocalFileTime(@WTime, @lft) and FileTimeToSystemTime(@lft, @st);
  98. if res then
  99. begin
  100. FatDate:=st.wDay or (st.wMonth shl 5) or (word(st.wYear - 1980) shl 9);
  101. FatTime:=word(st.wSecond div 2) or (st.wMinute shl 5) or (st.wHour shl 11);
  102. Longrec(Dtime).Hi:=FatDate;
  103. Longrec(Dtime).Lo:=FatTime;
  104. end;
  105. WinToDosTime:=res;
  106. end;
  107. {******************************************************************************
  108. --- Info / Date / Time ---
  109. ******************************************************************************}
  110. function dosversion : word;
  111. var
  112. versioninfo : OSVERSIONINFO;
  113. begin
  114. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  115. GetVersionEx(versioninfo);
  116. dosversion:=versioninfo.dwMajorVersion and $FF or versioninfo.dwMinorVersion and $FF shl 8;
  117. end;
  118. procedure getdate(var year,month,mday,wday : word);
  119. var
  120. t : TSystemTime;
  121. begin
  122. GetLocalTime(t);
  123. year:=t.wYear;
  124. month:=t.wMonth;
  125. mday:=t.wDay;
  126. wday:=t.wDayOfWeek;
  127. end;
  128. procedure setdate(year,month,day : word);
  129. var
  130. t : TSystemTime;
  131. begin
  132. GetLocalTime(t);
  133. t.wYear:=year;
  134. t.wMonth:=month;
  135. t.wDay:=day;
  136. { only a quite good solution, we can loose some ms }
  137. SetLocalTime(t);
  138. end;
  139. procedure gettime(var hour,minute,second,sec100 : word);
  140. var
  141. t : TSystemTime;
  142. begin
  143. GetLocalTime(t);
  144. hour:=t.wHour;
  145. minute:=t.wMinute;
  146. second:=t.wSecond;
  147. sec100:=t.wMilliSeconds div 10;
  148. end;
  149. procedure settime(hour,minute,second,sec100 : word);
  150. var
  151. t : TSystemTime;
  152. begin
  153. GetLocalTime(t);
  154. t.wHour:=hour;
  155. t.wMinute:=minute;
  156. t.wSecond:=second;
  157. t.wMilliSeconds:=sec100*10;
  158. SetLocalTime(t);
  159. end;
  160. {******************************************************************************
  161. --- Exec ---
  162. ******************************************************************************}
  163. procedure exec(const path : pathstr;const comline : comstr);
  164. var
  165. PI: TProcessInformation;
  166. Proc : THandle;
  167. l : LongInt;
  168. PathW : array[0..FileNameLen] of WideChar;
  169. CmdLineW : array[0..FileNameLen] of WideChar;
  170. begin
  171. DosError := 0;
  172. AnsiToWideBuf(@path[1], Length(path), PathW, SizeOf(PathW));
  173. AnsiToWideBuf(@comline[1], Length(comline), CmdLineW, SizeOf(CmdLineW));
  174. if not CreateProcess(PathW, CmdLineW,
  175. nil, nil, FALSE, 0, nil, nil, nil, PI) then
  176. begin
  177. DosError:=Last2DosError(GetLastError);
  178. exit;
  179. end;
  180. Proc:=PI.hProcess;
  181. CloseHandle(PI.hThread);
  182. if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
  183. GetExitCodeProcess(Proc, @l)
  184. else
  185. l:=-1;
  186. CloseHandle(Proc);
  187. LastDosExitCode:=l;
  188. end;
  189. {******************************************************************************
  190. --- Disk ---
  191. ******************************************************************************}
  192. var
  193. DriveNames: array[1..24] of PWideChar;
  194. function GetDriveName(drive: byte): PWideChar;
  195. const
  196. dev_attr = FILE_ATTRIBUTE_TEMPORARY or FILE_ATTRIBUTE_DIRECTORY;
  197. var
  198. h: THandle;
  199. fd: TWin32FindData;
  200. i, len: LongInt;
  201. begin
  202. GetDriveName:=nil;
  203. // Current drive is C: drive always
  204. if drive = 0 then
  205. drive:=2;
  206. if (drive < 3) or (drive > 26) then
  207. exit;
  208. if DriveNames[1] = nil then
  209. begin
  210. // Drive C: is filesystem root always
  211. GetMem(DriveNames[1], 2*SizeOf(WideChar));
  212. DriveNames[1][0]:='\';
  213. DriveNames[1][1]:=#0;
  214. // Other drives are found dinamically
  215. h:=FindFirstFile('\*', @fd);
  216. if h <> 0 then
  217. begin
  218. i:=2;
  219. repeat
  220. if fd.dwFileAttributes and dev_attr = dev_attr then begin
  221. len:=0;
  222. while fd.cFileName[len] <> #0 do
  223. Inc(len);
  224. len:=(len + 2)*SizeOf(WideChar);
  225. GetMem(DriveNames[i], len);
  226. DriveNames[i]^:='\';
  227. Move(fd.cFileName, DriveNames[i][1], len - SizeOf(WideChar));
  228. Inc(i);
  229. end;
  230. until (i > 24) or not FindNextFile(h, fd);
  231. {$ifdef FPC_DOTTEDUNITS}WinApi.{$endif}Windows.FindClose(h);
  232. end;
  233. end;
  234. GetDriveName:=DriveNames[drive - 2];
  235. end;
  236. function diskfree(drive : byte) : int64;
  237. var
  238. disk: PWideChar;
  239. qwtotal,qwfree,qwcaller : int64;
  240. begin
  241. disk:=GetDriveName(drive);
  242. if (disk <> nil) and GetDiskFreeSpaceEx(disk, @qwcaller, @qwtotal, @qwfree) then
  243. diskfree:=qwfree
  244. else
  245. diskfree:=-1;
  246. end;
  247. function disksize(drive : byte) : int64;
  248. var
  249. disk : PWideChar;
  250. qwtotal,qwfree,qwcaller : int64;
  251. begin
  252. disk:=GetDriveName(drive);
  253. if (disk <> nil) and GetDiskFreeSpaceEx(disk, @qwcaller, @qwtotal, @qwfree) then
  254. disksize:=qwtotal
  255. else
  256. disksize:=-1;
  257. end;
  258. {******************************************************************************
  259. --- Findfirst FindNext ---
  260. ******************************************************************************}
  261. Procedure StringToPchar (Var S : ShortString);
  262. Var L : Longint;
  263. begin
  264. L:=ord(S[0]);
  265. Move (S[1],S[0],L);
  266. S[L]:=#0;
  267. end;
  268. Procedure PCharToString (Var S : ShortString);
  269. Var L : Longint;
  270. begin
  271. L:=strlen(PAnsiChar(@S[0]));
  272. Move (S[0],S[1],L);
  273. S[0]:=AnsiChar(l);
  274. end;
  275. procedure FindMatch(var f:searchrec);
  276. var
  277. buf: array[0..MaxPathLen] of AnsiChar;
  278. begin
  279. { Find file with correct attribute }
  280. While (F.W32FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  281. begin
  282. if not FindNextFile (F.FindHandle, F.W32FindData) then
  283. begin
  284. DosError:=Last2DosError(GetLastError);
  285. if DosError=2 then
  286. DosError:=18;
  287. exit;
  288. end;
  289. end;
  290. { Convert some attributes back }
  291. f.size:=F.W32FindData.NFileSizeLow;
  292. f.attr:=WinToDosAttr(F.W32FindData.dwFileAttributes);
  293. WinToDosTime(F.W32FindData.ftLastWriteTime,f.Time);
  294. WideToAnsiBuf(@F.W32FindData.cFileName, -1, buf, SizeOf(buf));
  295. f.Name:=StrPas(@buf);
  296. end;
  297. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  298. var
  299. buf: array[0..MaxPathLen] of WideChar;
  300. begin
  301. if path = ''then
  302. begin
  303. DosError:=3;
  304. exit;
  305. end;
  306. fillchar(f,sizeof(f),0);
  307. { no error }
  308. doserror:=0;
  309. F.Name:=Path;
  310. F.Attr:=attr;
  311. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  312. StringToPchar(f.name);
  313. { FindFirstFile is a WinCE Call }
  314. F.W32FindData.dwFileAttributes:=DosToWinAttr(f.attr);
  315. AnsiToWideBuf(@f.Name, -1, buf, SizeOf(buf));
  316. F.FindHandle:=FindFirstFile (buf, F.W32FindData);
  317. If F.FindHandle = Invalid_Handle_value then
  318. begin
  319. DosError:=Last2DosError(GetLastError);
  320. if DosError=2 then
  321. DosError:=18;
  322. exit;
  323. end;
  324. { Find file with correct attribute }
  325. FindMatch(f);
  326. end;
  327. procedure findnext(var f : searchRec);
  328. begin
  329. { no error }
  330. doserror:=0;
  331. if not FindNextFile (F.FindHandle, F.W32FindData) then
  332. begin
  333. DosError:=Last2DosError(GetLastError);
  334. if DosError=2 then
  335. DosError:=18;
  336. exit;
  337. end;
  338. { Find file with correct attribute }
  339. FindMatch(f);
  340. end;
  341. Procedure FindClose(Var f: SearchRec);
  342. begin
  343. If F.FindHandle <> Invalid_Handle_value then
  344. {$ifdef FPC_DOTTEDUNITS}WinApi.{$endif}Windows.FindClose(F.FindHandle);
  345. end;
  346. {******************************************************************************
  347. --- File ---
  348. ******************************************************************************}
  349. Function FSearch(path: pathstr; dirlist: shortstring): pathstr;
  350. var
  351. p1 : longint;
  352. s : searchrec;
  353. newdir : pathstr;
  354. begin
  355. { No wildcards allowed in these things }
  356. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  357. begin
  358. fsearch:='';
  359. exit;
  360. end;
  361. { check if the file specified exists }
  362. findfirst(path,anyfile and not(directory),s);
  363. if doserror=0 then
  364. begin
  365. findclose(s);
  366. fsearch:=path;
  367. exit;
  368. end;
  369. findclose(s);
  370. { allow slash as backslash }
  371. DoDirSeparators(dirlist);
  372. repeat
  373. p1:=pos(';',dirlist);
  374. if p1<>0 then
  375. begin
  376. newdir:=copy(dirlist,1,p1-1);
  377. delete(dirlist,1,p1);
  378. end
  379. else
  380. begin
  381. newdir:=dirlist;
  382. dirlist:='';
  383. end;
  384. if (newdir<>'') and (not (newdir[length(newdir)] in [DirectorySeparator,DriveSeparator])) then
  385. newdir:=newdir+DirectorySeparator;
  386. findfirst(newdir+path,anyfile and not(directory),s);
  387. if doserror=0 then
  388. newdir:=newdir+path
  389. else
  390. newdir:='';
  391. findclose(s);
  392. until (dirlist='') or (newdir<>'');
  393. fsearch:=newdir;
  394. end;
  395. { </immobilizer> }
  396. procedure getftime(var f;var time : longint);
  397. var
  398. ft : TFileTime;
  399. begin
  400. doserror:=0;
  401. if GetFileTime(filerec(f).Handle,nil,nil,@ft) and
  402. WinToDosTime(ft,time) then
  403. exit
  404. else
  405. begin
  406. DosError:=Last2DosError(GetLastError);
  407. time:=0;
  408. end;
  409. end;
  410. procedure setftime(var f;time : longint);
  411. var
  412. ft : TFileTime;
  413. begin
  414. doserror:=0;
  415. if DosToWinTime(time,ft) and
  416. SetFileTime(filerec(f).Handle,nil,nil,@ft) then
  417. exit
  418. else
  419. DosError:=Last2DosError(GetLastError);
  420. end;
  421. procedure getfattr(var f;var attr : word);
  422. var
  423. l : cardinal;
  424. {$ifdef FPC_ANSI_TEXTFILEREC}
  425. u: unicodestring;
  426. {$endif FPC_ANSI_TEXTFILEREC}
  427. begin
  428. if filerec(f).name[0] = #0 then
  429. begin
  430. doserror:=3;
  431. attr:=0;
  432. end
  433. else
  434. begin
  435. doserror:=0;
  436. {$ifdef FPC_ANSI_TEXTFILEREC}
  437. widestringmanager.Ansi2UnicodeMoveProc(filerec(f).name,DefaultFileSystemCodePage,u,length(filerec(f).name));
  438. l:=GetFileAttributes(pwidechar(u));
  439. {$else}
  440. l:=GetFileAttributes(filerec(f).name);
  441. {$endif}
  442. if l = $ffffffff then
  443. begin
  444. doserror:=Last2DosError(GetLastError);
  445. attr:=0;
  446. end
  447. else
  448. attr:=l and $ffff;
  449. end;
  450. end;
  451. procedure setfattr(var f;attr : word);
  452. var
  453. buf: array[0..MaxPathLen] of WideChar;
  454. begin
  455. { Fail for setting VolumeId }
  456. if (attr and VolumeID)<>0 then
  457. doserror:=5
  458. else
  459. begin
  460. AnsiToWideBuf(@filerec(f).name, -1, buf, SizeOf(buf));
  461. if SetFileAttributes(buf,attr) then
  462. doserror:=0
  463. else
  464. doserror:=Last2DosError(GetLastError);
  465. end;
  466. end;
  467. {******************************************************************************
  468. --- Environment ---
  469. ******************************************************************************}
  470. // WinCE does not have environment. It can be emulated via registry or file. (YS)
  471. function envcount : longint;
  472. begin
  473. envcount:=0;
  474. end;
  475. Function EnvStr (Index: longint): string;
  476. begin
  477. EnvStr:='';
  478. end;
  479. Function GetEnv(envvar: string): string;
  480. begin
  481. GetEnv:='';
  482. end;
  483. var
  484. oldexitproc : pointer;
  485. procedure dosexitproc;
  486. var
  487. i: LongInt;
  488. begin
  489. exitproc:=oldexitproc;
  490. if DriveNames[1] <> nil then
  491. for i:=1 to 24 do
  492. if DriveNames[i] <> nil then
  493. FreeMem(DriveNames[i])
  494. else
  495. break;
  496. end;
  497. begin
  498. oldexitproc:=exitproc;
  499. exitproc:=@dosexitproc;
  500. end.