dos.pp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by the Free Pascal development team.
  5. Dos unit for BP7 compatible RTL
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit dos;
  13. interface
  14. { Include Win32 Consts,Types }
  15. {$I win32.inc}
  16. Const
  17. Max_Path = 255;
  18. {Bitmasks for CPU Flags}
  19. fcarry = $0001;
  20. fparity = $0004;
  21. fauxiliary = $0010;
  22. fzero = $0040;
  23. fsign = $0080;
  24. foverflow = $0800;
  25. {Bitmasks for file attribute}
  26. readonly = $01;
  27. hidden = $02;
  28. sysfile = $04;
  29. volumeid = $08;
  30. directory = $10;
  31. archive = $20;
  32. anyfile = $3F;
  33. {File Status}
  34. fmclosed = $D7B0;
  35. fminput = $D7B1;
  36. fmoutput = $D7B2;
  37. fminout = $D7B3;
  38. Type
  39. { Needed for Win95 LFN Support }
  40. ComStr = String[255];
  41. PathStr = String[255];
  42. DirStr = String[255];
  43. NameStr = String[255];
  44. ExtStr = String[255];
  45. {
  46. filerec.inc contains the definition of the filerec.
  47. textrec.inc contains the definition of the textrec.
  48. It is in a separate file to make it available in other units without
  49. having to use the DOS unit for it.
  50. }
  51. {$i filerec.inc}
  52. {$i textrec.inc}
  53. DateTime = packed record
  54. Year,
  55. Month,
  56. Day,
  57. Hour,
  58. Min,
  59. Sec : word;
  60. End;
  61. PWin32FindData = ^TWin32FindData;
  62. TWin32FindData = packed record
  63. dwFileAttributes: Cardinal;
  64. ftCreationTime: TFileTime;
  65. ftLastAccessTime: TFileTime;
  66. ftLastWriteTime: TFileTime;
  67. nFileSizeHigh: Cardinal;
  68. nFileSizeLow: Cardinal;
  69. dwReserved0: Cardinal;
  70. dwReserved1: Cardinal;
  71. cFileName: array[0..MAX_PATH - 1] of Char;
  72. cAlternateFileName: array[0..13] of Char;
  73. end;
  74. Searchrec = Packed Record
  75. FindHandle : THandle;
  76. W32FindData : TWin32FindData;
  77. ExcludeAttr : longint;
  78. time : longint;
  79. size : longint;
  80. attr : longint;
  81. name : string;
  82. end;
  83. registers = packed record
  84. case i : integer of
  85. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  86. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  87. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  88. end;
  89. Var
  90. DosError : integer;
  91. {Interrupt}
  92. Procedure Intr(intno: byte; var regs: registers);
  93. Procedure MSDos(var regs: registers);
  94. {Info/Date/Time}
  95. Function DosVersion: Word;
  96. Procedure GetDate(var year, month, mday, wday: word);
  97. Procedure GetTime(var hour, minute, second, sec100: word);
  98. procedure SetDate(year,month,day: word);
  99. Procedure SetTime(hour,minute,second,sec100: word);
  100. Procedure UnpackTime(p: longint; var t: datetime);
  101. Procedure PackTime(var t: datetime; var p: longint);
  102. {Exec}
  103. Procedure Exec(const path: pathstr; const comline: comstr);
  104. Function DosExitCode: word;
  105. {Disk}
  106. Function DiskFree(drive: byte) : longint;
  107. Function DiskSize(drive: byte) : longint;
  108. Procedure FindFirst(const path: pathstr; attr: word; var f: searchRec);
  109. Procedure FindNext(var f: searchRec);
  110. Procedure FindClose(Var f: SearchRec);
  111. {File}
  112. Procedure GetFAttr(var f; var attr: word);
  113. Procedure GetFTime(var f; var time: longint);
  114. Function FSearch(path: pathstr; dirlist: string): pathstr;
  115. Function FExpand(const path: pathstr): pathstr;
  116. Procedure FSplit(path: pathstr; var dir: dirstr; var name: namestr; var ext: extstr);
  117. {Environment}
  118. Function EnvCount: longint;
  119. Function EnvStr(index: integer): string;
  120. Function GetEnv(envvar: string): string;
  121. {Misc}
  122. Procedure SetFAttr(var f; attr: word);
  123. Procedure SetFTime(var f; time: longint);
  124. Procedure GetCBreak(var breakvalue: boolean);
  125. Procedure SetCBreak(breakvalue: boolean);
  126. Procedure GetVerify(var verify: boolean);
  127. Procedure SetVerify(verify: boolean);
  128. {Do Nothing Functions}
  129. Procedure SwapVectors;
  130. Procedure GetIntVec(intno: byte; var vector: pointer);
  131. Procedure SetIntVec(intno: byte; vector: pointer);
  132. Procedure Keep(exitcode: word);
  133. implementation
  134. uses strings;
  135. {******************************************************************************
  136. --- Conversion ---
  137. ******************************************************************************}
  138. function GetLastError : DWORD;
  139. external 'kernel32' name 'GetLastError';
  140. function FileTimeToDosDateTime(const ft :TFileTime;var data,time : word) : longbool;
  141. external 'kernel32' name 'FileTimeToDosDateTime';
  142. function DosDateTimeToFileTime(date,time : word;var ft :TFileTime) : longbool;
  143. external 'kernel32' name 'DosDateTimeToFileTime';
  144. function FileTimeToLocalFileTime(const ft : TFileTime;var lft : TFileTime) : longbool;
  145. external 'kernel32' name 'FileTimeToLocalFileTime';
  146. function LocalFileTimeToFileTime(const lft : TFileTime;var ft : TFileTime) : longbool;
  147. external 'kernel32' name 'LocalFileTimeToFileTime';
  148. type
  149. Longrec=packed record
  150. lo,hi : word;
  151. end;
  152. function Last2DosError(d:dword):integer;
  153. begin
  154. Last2DosError:=d;
  155. end;
  156. Function DosToWinAttr (Const Attr : Longint) : longint;
  157. begin
  158. DosToWinAttr:=Attr;
  159. end;
  160. Function WinToDosAttr (Const Attr : Longint) : longint;
  161. begin
  162. WinToDosAttr:=Attr;
  163. end;
  164. Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
  165. var
  166. lft : TFileTime;
  167. begin
  168. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,lft) and
  169. LocalFileTimeToFileTime(lft,Wtime);
  170. end;
  171. Function WinToDosTime (Const Wtime : TFileTime;var DTime:longint):longbool;
  172. var
  173. lft : TFileTime;
  174. begin
  175. WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
  176. FileTimeToDosDateTime(lft,longrec(dtime).hi,longrec(dtime).lo);
  177. end;
  178. {******************************************************************************
  179. --- Dos Interrupt ---
  180. ******************************************************************************}
  181. procedure intr(intno : byte;var regs : registers);
  182. begin
  183. { !!!!!!!! }
  184. end;
  185. procedure msdos(var regs : registers);
  186. begin
  187. { !!!!!!!! }
  188. end;
  189. {******************************************************************************
  190. --- Info / Date / Time ---
  191. ******************************************************************************}
  192. function GetVersion : longint;
  193. external 'kernel32' name 'GetVersion';
  194. procedure GetLocalTime(var t : TSystemTime);
  195. external 'kernel32' name 'GetLocalTime';
  196. function SetLocalTime(const t : TSystemTime) : longbool;
  197. external 'kernel32' name 'SetLocalTime';
  198. function dosversion : word;
  199. begin
  200. dosversion:=GetVersion;
  201. end;
  202. procedure getdate(var year,month,mday,wday : word);
  203. var
  204. t : TSystemTime;
  205. begin
  206. GetLocalTime(t);
  207. year:=t.wYear;
  208. month:=t.wMonth;
  209. mday:=t.wDay;
  210. wday:=t.wDayOfWeek;
  211. end;
  212. procedure setdate(year,month,day : word);
  213. var
  214. t : TSystemTime;
  215. begin
  216. { we need the time set privilege }
  217. { so this function crash currently }
  218. {!!!!!}
  219. GetLocalTime(t);
  220. t.wYear:=year;
  221. t.wMonth:=month;
  222. t.wDay:=day;
  223. { only a quite good solution, we can loose some ms }
  224. SetLocalTime(t);
  225. end;
  226. procedure gettime(var hour,minute,second,sec100 : word);
  227. var
  228. t : TSystemTime;
  229. begin
  230. GetLocalTime(t);
  231. hour:=t.wHour;
  232. minute:=t.wMinute;
  233. second:=t.wSecond;
  234. sec100:=t.wMilliSeconds div 10;
  235. end;
  236. procedure settime(hour,minute,second,sec100 : word);
  237. var
  238. t : TSystemTime;
  239. begin
  240. { we need the time set privilege }
  241. { so this function crash currently }
  242. {!!!!!}
  243. GetLocalTime(t);
  244. t.wHour:=hour;
  245. t.wMinute:=minute;
  246. t.wSecond:=second;
  247. t.wMilliSeconds:=sec100*10;
  248. SetLocalTime(t);
  249. end;
  250. Procedure packtime(var t : datetime;var p : longint);
  251. Begin
  252. p:=(t.sec shr 1)+(t.min shl 5)+(t.hour shl 11)+(t.day shl 16)+(t.month shl 21)+((t.year-1980) shl 25);
  253. End;
  254. Procedure unpacktime(p : longint;var t : datetime);
  255. Begin
  256. with t do
  257. begin
  258. sec:=(p and 31) shl 1;
  259. min:=(p shr 5) and 63;
  260. hour:=(p shr 11) and 31;
  261. day:=(p shr 16) and 31;
  262. month:=(p shr 21) and 15;
  263. year:=(p shr 25)+1980;
  264. end;
  265. End;
  266. {******************************************************************************
  267. --- Exec ---
  268. ******************************************************************************}
  269. function CreateProcess(lpApplicationName: PChar; lpCommandLine: PChar;
  270. lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
  271. bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
  272. lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
  273. var lpProcessInformation: TProcessInformation): longbool;
  274. external 'kernel32' name 'CreateProcessA';
  275. function getExitCodeProcess(h:THandle;var code:longint):longbool;
  276. external 'kernel32' name 'GetExitCodeProcess';
  277. function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD;
  278. external 'kernel32' name 'WaitForSingleObject';
  279. function CloseHandle(h : THandle) : longint;
  280. external 'kernel32' name 'CloseHandle';
  281. var
  282. lastdosexitcode : word;
  283. procedure exec(const path : pathstr;const comline : comstr);
  284. var
  285. SI: TStartupInfo;
  286. PI: TProcessInformation;
  287. Proc : THandle;
  288. l : Longint;
  289. AppPath,
  290. AppParam : array[0..255] of char;
  291. begin
  292. FillChar(SI, SizeOf(SI), 0);
  293. SI.cb:=SizeOf(SI);
  294. SI.wShowWindow:=1;
  295. Move(Path[1],AppPath,length(Path));
  296. AppPath[Length(Path)]:=#0;
  297. AppParam[0]:='-';
  298. AppParam[1]:=' ';
  299. Move(ComLine[1],AppParam[2],length(Comline));
  300. AppParam[Length(ComLine)+2]:=#0;
  301. if not CreateProcess(PChar(@AppPath), PChar(@AppParam), Nil, Nil, False,$20, Nil, Nil, SI, PI) then
  302. begin
  303. DosError:=Last2DosError(GetLastError);
  304. exit;
  305. end;
  306. Proc:=PI.hProcess;
  307. CloseHandle(PI.hThread);
  308. if WaitForSingleObject(Proc, Infinite) <> $ffffffff then
  309. GetExitCodeProcess(Proc,l)
  310. else
  311. l:=-1;
  312. CloseHandle(Proc);
  313. LastDosExitCode:=l;
  314. end;
  315. function dosexitcode : word;
  316. begin
  317. dosexitcode:=lastdosexitcode;
  318. end;
  319. procedure getcbreak(var breakvalue : boolean);
  320. begin
  321. { !! No Win32 Function !! }
  322. end;
  323. procedure setcbreak(breakvalue : boolean);
  324. begin
  325. { !! No Win32 Function !! }
  326. end;
  327. procedure getverify(var verify : boolean);
  328. begin
  329. { !! No Win32 Function !! }
  330. end;
  331. procedure setverify(verify : boolean);
  332. begin
  333. { !! No Win32 Function !! }
  334. end;
  335. {******************************************************************************
  336. --- Disk ---
  337. ******************************************************************************}
  338. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  339. freeclusters,totalclusters:longint):longbool;
  340. external 'kernel32' name 'GetDiskFreeSpaceA';
  341. function diskfree(drive : byte) : longint;
  342. var
  343. disk : array[1..4] of char;
  344. secs,bytes,
  345. free,total : longint;
  346. begin
  347. if drive=0 then
  348. begin
  349. disk[1]:='\';
  350. disk[2]:=#0;
  351. end
  352. else
  353. begin
  354. disk[1]:=chr(drive+64);
  355. disk[2]:=':';
  356. disk[3]:='\';
  357. disk[4]:=#0;
  358. end;
  359. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  360. diskfree:=free*secs*bytes
  361. else
  362. diskfree:=-1;
  363. end;
  364. function disksize(drive : byte) : longint;
  365. var
  366. disk : array[1..4] of char;
  367. secs,bytes,
  368. free,total : longint;
  369. begin
  370. if drive=0 then
  371. begin
  372. disk[1]:='\';
  373. disk[2]:=#0;
  374. end
  375. else
  376. begin
  377. disk[1]:=chr(drive+64);
  378. disk[2]:=':';
  379. disk[3]:='\';
  380. disk[4]:=#0;
  381. end;
  382. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  383. disksize:=total*secs*bytes
  384. else
  385. disksize:=-1;
  386. end;
  387. {******************************************************************************
  388. --- Findfirst FindNext ---
  389. ******************************************************************************}
  390. { Needed kernel calls }
  391. function FindFirstFile (lpFileName: PChar; var lpFindFileData: TWIN32FindData): THandle;
  392. external 'kernel32' name 'FindFirstFileA';
  393. function FindNextFile (hFindFile: THandle; var lpFindFileData: TWIN32FindData): LongBool;
  394. external 'kernel32' name 'FindNextFileA';
  395. function FindCloseFile (hFindFile: THandle): LongBool;
  396. external 'kernel32' name 'FindClose';
  397. Procedure StringToPchar (Var S : String);
  398. Var L : Longint;
  399. begin
  400. L:=ord(S[0]);
  401. Move (S[1],S[0],L);
  402. S[L]:=#0;
  403. end;
  404. procedure FindMatch(var f:searchrec);
  405. begin
  406. { Find file with correct attribute }
  407. While (F.W32FindData.dwFileAttributes and F.ExcludeAttr)<>0 do
  408. begin
  409. if not FindNextFile (F.FindHandle,F.W32FindData) then
  410. begin
  411. DosError:=Last2DosError(GetLastError);
  412. exit;
  413. end;
  414. end;
  415. { Convert some attributes back }
  416. f.size:=F.W32FindData.NFileSizeLow;
  417. f.attr:=WinToDosAttr(F.W32FindData.dwFileAttributes);
  418. WinToDosTime(F.W32FindData.ftLastWriteTime,f.Time);
  419. f.Name:=StrPas(@F.W32FindData.cFileName);
  420. end;
  421. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  422. begin
  423. { no error }
  424. doserror:=0;
  425. F.Name:=Path;
  426. F.Attr:=attr;
  427. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  428. StringToPchar(f.name);
  429. { FindFirstFile is a Win32 Call }
  430. F.FindHandle:=FindFirstFile (pchar(@f.Name),F.W32FindData);
  431. If longint(F.FindHandle)=Invalid_Handle_value then
  432. begin
  433. DosError:=Last2DosError(GetLastError);
  434. exit;
  435. end;
  436. { Find file with correct attribute }
  437. FindMatch(f);
  438. end;
  439. procedure findnext(var f : searchRec);
  440. begin
  441. { no error }
  442. doserror:=0;
  443. if not FindNextFile (F.FindHandle,F.W32FindData) then
  444. begin
  445. DosError:=Last2DosError(GetLastError);
  446. exit;
  447. end;
  448. { Find file with correct attribute }
  449. FindMatch(f);
  450. end;
  451. procedure swapvectors;
  452. begin
  453. end;
  454. Procedure FindClose(Var f: SearchRec);
  455. begin
  456. If longint(F.FindHandle)<>Invalid_Handle_value then
  457. FindCloseFile(F.FindHandle);
  458. end;
  459. {******************************************************************************
  460. --- File ---
  461. ******************************************************************************}
  462. function GetFileTime(h : longint;creation,lastaccess,lastwrite : PFileTime) : longbool;
  463. external 'kernel32' name 'GetFileTime';
  464. function SetFileTime(h : longint;creation,lastaccess,lastwrite : PFileTime) : longbool;
  465. external 'kernel32' name 'SetFileTime';
  466. function SetFileAttributes(lpFileName : pchar;dwFileAttributes : longint) : longbool;
  467. external 'kernel32' name 'SetFileAttributesA';
  468. function GetFileAttributes(lpFileName : pchar) : longint;
  469. external 'kernel32' name 'GetFileAttributesA';
  470. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  471. var
  472. dotpos,p1,i : longint;
  473. begin
  474. { allow slash as backslash }
  475. for i:=1 to length(path) do
  476. if path[i]='/' then path[i]:='\';
  477. { get drive name }
  478. p1:=pos(':',path);
  479. if p1>0 then
  480. begin
  481. dir:=path[1]+':';
  482. delete(path,1,p1);
  483. end
  484. else
  485. dir:='';
  486. { split the path and the name, there are no more path informtions }
  487. { if path contains no backslashes }
  488. while true do
  489. begin
  490. p1:=pos('\',path);
  491. if p1=0 then
  492. break;
  493. dir:=dir+copy(path,1,p1);
  494. delete(path,1,p1);
  495. end;
  496. { try to find out a extension }
  497. Ext:='';
  498. i:=Length(Path);
  499. DotPos:=256;
  500. While (i>0) Do
  501. Begin
  502. If (Path[i]='.') Then
  503. begin
  504. DotPos:=i;
  505. break;
  506. end;
  507. Dec(i);
  508. end;
  509. Ext:=Copy(Path,DotPos,255);
  510. Name:=Copy(Path,1,DotPos - 1);
  511. end;
  512. function fexpand(const path : pathstr) : pathstr;
  513. var
  514. s,pa : string[79];
  515. i,j : longint;
  516. begin
  517. getdir(0,s);
  518. i:=ioresult;
  519. if FileNameCaseSensitive then
  520. pa:=path
  521. else
  522. pa:=upcase(path);
  523. { allow slash as backslash }
  524. for i:=1 to length(pa) do
  525. if pa[i]='/' then
  526. pa[i]:='\';
  527. if (length(pa)>1) and (pa[2]=':') and (pa[1] in ['A'..'Z','a'..'z']) then
  528. begin
  529. { Always uppercase driveletter }
  530. if (pa[1] in ['a'..'z']) then
  531. pa[1]:=Chr(Ord(Pa[1])-32);
  532. { we must get the right directory }
  533. getdir(ord(pa[1])-ord('A')+1,s);
  534. if (ord(pa[0])>2) and (pa[3]<>'\') then
  535. if pa[1]=s[1] then
  536. pa:=s+'\'+copy (pa,3,length(pa))
  537. else
  538. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  539. end
  540. else
  541. if pa[1]='\' then
  542. pa:=s[1]+':'+pa
  543. else if s[0]=#3 then
  544. pa:=s+pa
  545. else
  546. pa:=s+'\'+pa;
  547. { Turbo Pascal gives current dir on drive if only drive given as parameter! }
  548. if length(pa) = 2 then
  549. begin
  550. getdir(byte(pa[1])-64,s);
  551. i:=ioresult;
  552. pa := s;
  553. end;
  554. {First remove all references to '\.\'}
  555. while pos ('\.\',pa)<>0 do
  556. delete (pa,pos('\.\',pa),2);
  557. {Now remove also all references to '\..\' + of course previous dirs..}
  558. repeat
  559. i:=pos('\..\',pa);
  560. if i<>0 then
  561. begin
  562. j:=i-1;
  563. while (j>1) and (pa[j]<>'\') do
  564. dec (j);
  565. if pa[j+1] = ':' then j := 3;
  566. delete (pa,j,i-j+3);
  567. end;
  568. until i=0;
  569. { Turbo Pascal gets rid of a \.. at the end of the path }
  570. { Now remove also any reference to '\..' at end of line
  571. + of course previous dir.. }
  572. i:=pos('\..',pa);
  573. if i<>0 then
  574. begin
  575. if i = length(pa) - 2 then
  576. begin
  577. j:=i-1;
  578. while (j>1) and (pa[j]<>'\') do
  579. dec (j);
  580. delete (pa,j,i-j+3);
  581. end;
  582. pa := pa + '\';
  583. end;
  584. { Remove End . and \}
  585. if (length(pa)>0) and (pa[length(pa)]='.') then
  586. dec(byte(pa[0]));
  587. { if only the drive + a '\' is left then the '\' should be left to prevtn the program
  588. accessing the current directory on the drive rather than the root!}
  589. { if the last char of path = '\' then leave it in as this is what TP does! }
  590. if ((length(pa)>3) and (pa[length(pa)]='\')) and (path[length(path)] <> '\') then
  591. dec(byte(pa[0]));
  592. { if only a drive is given in path then there should be a '\' at the
  593. end of the string given back }
  594. if length(path) = 2 then pa := pa + '\';
  595. fexpand:=pa;
  596. end;
  597. Function FSearch(path: pathstr; dirlist: string): pathstr;
  598. var
  599. i,p1 : longint;
  600. s : searchrec;
  601. newdir : pathstr;
  602. begin
  603. { No wildcards allowed in these things }
  604. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  605. fsearch:=''
  606. else
  607. begin
  608. { allow slash as backslash }
  609. for i:=1 to length(dirlist) do
  610. if dirlist[i]='/' then dirlist[i]:='\';
  611. repeat
  612. p1:=pos(';',dirlist);
  613. if p1=0 then
  614. begin
  615. newdir:=copy(dirlist,1,p1-1);
  616. delete(dirlist,1,p1);
  617. end
  618. else
  619. begin
  620. newdir:=dirlist;
  621. dirlist:='';
  622. end;
  623. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  624. newdir:=newdir+'\';
  625. findfirst(newdir+path,anyfile,s);
  626. if doserror=0 then
  627. newdir:=newdir+path
  628. else
  629. newdir:='';
  630. until (dirlist='') or (newdir<>'');
  631. fsearch:=newdir;
  632. end;
  633. end;
  634. procedure getftime(var f;var time : longint);
  635. var
  636. ft : TFileTime;
  637. begin
  638. if GetFileTime(filerec(f).Handle,nil,nil,@ft) and
  639. WinToDosTime(ft,time) then
  640. exit
  641. else
  642. time:=0;
  643. end;
  644. procedure setftime(var f;time : longint);
  645. var
  646. ft : TFileTime;
  647. begin
  648. if DosToWinTime(time,ft) then
  649. SetFileTime(filerec(f).Handle,nil,nil,@ft);
  650. end;
  651. procedure getfattr(var f;var attr : word);
  652. var
  653. l : longint;
  654. begin
  655. l:=GetFileAttributes(filerec(f).name);
  656. if l=$ffffffff then
  657. doserror:=getlasterror;
  658. attr:=l;
  659. end;
  660. procedure setfattr(var f;attr : word);
  661. begin
  662. doserror:=0;
  663. if not(SetFileAttributes(filerec(f).name,attr)) then
  664. doserror:=getlasterror;
  665. end;
  666. {******************************************************************************
  667. --- Environment ---
  668. ******************************************************************************}
  669. {
  670. The environment is a block of zero terminated strings
  671. terminated by a #0
  672. }
  673. function GetEnvironmentStrings : pchar;
  674. external 'kernel32' name 'GetEnvironmentStringsA';
  675. function FreeEnvironmentStrings(p : pchar) : longbool;
  676. external 'kernel32' name 'FreeEnvironmentStringsA';
  677. function envcount : longint;
  678. var
  679. hp,p : pchar;
  680. count : longint;
  681. begin
  682. p:=GetEnvironmentStrings;
  683. hp:=p;
  684. count:=0;
  685. while hp^<>#0 do
  686. begin
  687. { next string entry}
  688. hp:=hp+strlen(hp)+1;
  689. inc(count);
  690. end;
  691. FreeEnvironmentStrings(p);
  692. envcount:=count;
  693. end;
  694. Function EnvStr(index: integer): string;
  695. var
  696. hp,p : pchar;
  697. count,i : longint;
  698. begin
  699. { envcount takes some time in win32 }
  700. count:=envcount;
  701. { range checking }
  702. if (index<=0) or (index>count) then
  703. begin
  704. envstr:='';
  705. exit;
  706. end;
  707. p:=GetEnvironmentStrings;
  708. hp:=p;
  709. { retrive the string with the given index }
  710. for i:=2 to index do
  711. hp:=hp+strlen(hp)+1;
  712. envstr:=strpas(hp);
  713. FreeEnvironmentStrings(p);
  714. end;
  715. Function GetEnv(envvar: string): string;
  716. var
  717. s : string;
  718. i : longint;
  719. hp,p : pchar;
  720. begin
  721. getenv:='';
  722. p:=GetEnvironmentStrings;
  723. hp:=p;
  724. while hp^<>#0 do
  725. begin
  726. s:=strpas(hp);
  727. i:=pos('=',s);
  728. if upcase(copy(s,1,i-1))=upcase(envvar) then
  729. begin
  730. getenv:=copy(s,i+1,length(s)-i);
  731. break;
  732. end;
  733. { next string entry}
  734. hp:=hp+strlen(hp)+1;
  735. end;
  736. FreeEnvironmentStrings(p);
  737. end;
  738. {******************************************************************************
  739. --- Not Supported ---
  740. ******************************************************************************}
  741. Procedure keep(exitcode : word);
  742. Begin
  743. End;
  744. Procedure getintvec(intno : byte;var vector : pointer);
  745. Begin
  746. End;
  747. Procedure setintvec(intno : byte;vector : pointer);
  748. Begin
  749. End;
  750. end.
  751. {
  752. $Log$
  753. Revision 1.17 1999-05-16 17:08:59 peter
  754. * fixed driveletter checking
  755. Revision 1.16 1999/05/08 19:47:27 peter
  756. * check ioresult after getdir calls
  757. Revision 1.15 1999/04/28 11:42:52 peter
  758. + FileNameCaseSensetive boolean
  759. Revision 1.14 1999/04/08 12:23:07 peter
  760. * removed os.inc
  761. Revision 1.13 1998/11/16 15:48:53 peter
  762. * fixed longbool returns for api calls
  763. Revision 1.12 1998/10/27 10:55:55 michael
  764. * environment vars are case insensitive under WinNT/DOS
  765. Revision 1.11 1998/10/22 15:32:38 pierre
  766. * fsplit adapted to long filenames
  767. Revision 1.10 1998/10/16 14:20:06 peter
  768. * removed writelns
  769. Revision 1.9 1998/10/16 08:55:26 peter
  770. * findfirst is now more delphi alike
  771. Revision 1.8 1998/08/16 09:12:11 michael
  772. Corrected fexpand behaviour.
  773. Revision 1.7 1998/06/10 10:39:13 peter
  774. * working w32 rtl
  775. Revision 1.6 1998/06/08 23:07:45 peter
  776. * dos interface is now 100% compatible
  777. * fixed call PASCALMAIN which must be direct asm
  778. Revision 1.5 1998/05/06 12:36:50 michael
  779. + Removed log from before restored version.
  780. Revision 1.4 1998/04/27 14:01:38 florian
  781. * was uncompilable
  782. Revision 1.3 1998/04/26 22:37:02 florian
  783. + getftime, unpacktime, packtime
  784. Revision 1.2 1998/04/26 21:49:09 florian
  785. + first compiling and working version
  786. }