dos.pp 23 KB

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