dos.pp 23 KB

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