dos.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  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. unit dos;
  12. interface
  13. Const
  14. Max_Path = 260;
  15. Type
  16. PWinFileTime = ^TWinFileTime;
  17. TWinFileTime = record
  18. dwLowDateTime,
  19. dwHighDateTime : DWORD;
  20. end;
  21. PWinFindData = ^TWinFindData;
  22. TWinFindData = record
  23. dwFileAttributes: DWORD;
  24. ftCreationTime: TWinFileTime;
  25. ftLastAccessTime: TWinFileTime;
  26. ftLastWriteTime: TWinFileTime;
  27. nFileSizeHigh: DWORD;
  28. nFileSizeLow: DWORD;
  29. dwReserved0: DWORD;
  30. dwReserved1: DWORD;
  31. cFileName: array[0..MAX_PATH-1] of Char;
  32. cAlternateFileName: array[0..15] of Char;
  33. // The structure should be 320 bytes long...
  34. pad : system.integer;
  35. end;
  36. Searchrec = Record
  37. FindHandle : THandle;
  38. WinFindData : TWinFindData;
  39. ExcludeAttr : longint;
  40. time : longint;
  41. size : longint;
  42. attr : longint;
  43. name : string;
  44. end;
  45. {$i dosh.inc}
  46. Const
  47. { allow EXEC to inherited handles from calling process,
  48. needed for FPREDIR in ide/text
  49. now set to true by default because
  50. other OS also pass open handles to childs
  51. finally reset to false after Florian's response PM }
  52. ExecInheritsHandles : Longbool = false;
  53. implementation
  54. uses
  55. strings;
  56. {$DEFINE HAS_GETMSCOUNT}
  57. {$DEFINE HAS_GETSHORTNAME}
  58. {$DEFINE HAS_GETLONGNAME}
  59. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  60. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  61. {$I dos.inc}
  62. const
  63. INVALID_HANDLE_VALUE = THandle(-1);
  64. VER_PLATFORM_WIN32s = 0;
  65. VER_PLATFORM_WIN32_WINDOWS = 1;
  66. VER_PLATFORM_WIN32_NT = 2;
  67. type
  68. OSVERSIONINFO = record
  69. dwOSVersionInfoSize : DWORD;
  70. dwMajorVersion : DWORD;
  71. dwMinorVersion : DWORD;
  72. dwBuildNumber : DWORD;
  73. dwPlatformId : DWORD;
  74. szCSDVersion : array[0..127] of char;
  75. end;
  76. var
  77. versioninfo : OSVERSIONINFO;
  78. kernel32dll : THandle;
  79. {******************************************************************************
  80. --- Conversion ---
  81. ******************************************************************************}
  82. function GetLastError : DWORD;
  83. stdcall; external 'kernel32' name 'GetLastError';
  84. function FileTimeToDosDateTime(const ft :TWinFileTime;var data,time : word) : longbool;
  85. stdcall; external 'kernel32' name 'FileTimeToDosDateTime';
  86. function DosDateTimeToFileTime(date,time : word;var ft :TWinFileTime) : longbool;
  87. stdcall; external 'kernel32' name 'DosDateTimeToFileTime';
  88. function FileTimeToLocalFileTime(const ft : TWinFileTime;var lft : TWinFileTime) : longbool;
  89. stdcall; external 'kernel32' name 'FileTimeToLocalFileTime';
  90. function LocalFileTimeToFileTime(const lft : TWinFileTime;var ft : TWinFileTime) : longbool;
  91. stdcall; external 'kernel32' name 'LocalFileTimeToFileTime';
  92. function GetTickCount : longint;
  93. stdcall;external 'kernel32' name 'GetTickCount';
  94. function GetMsCount: int64;
  95. begin
  96. GetMsCount := cardinal (GetTickCount);
  97. end;
  98. type
  99. Longrec=packed record
  100. lo,hi : word;
  101. end;
  102. function Last2DosError(d:dword):integer;
  103. begin
  104. case d of
  105. 87 : { Parameter invalid -> Data invalid }
  106. Last2DosError:=13;
  107. else
  108. Last2DosError:=d;
  109. end;
  110. end;
  111. Function DosToWinAttr (Const Attr : Longint) : longint;
  112. begin
  113. DosToWinAttr:=Attr;
  114. end;
  115. Function WinToDosAttr (Const Attr : Longint) : longint;
  116. begin
  117. WinToDosAttr:=Attr;
  118. end;
  119. Function DosToWinTime (DTime:longint;Var Wtime : TWinFileTime):longbool;
  120. var
  121. lft : TWinFileTime;
  122. begin
  123. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,lft) and
  124. LocalFileTimeToFileTime(lft,Wtime);
  125. end;
  126. Function WinToDosTime (Const Wtime : TWinFileTime;var DTime:longint):longbool;
  127. var
  128. lft : TWinFileTime;
  129. begin
  130. WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
  131. FileTimeToDosDateTime(lft,longrec(dtime).hi,longrec(dtime).lo);
  132. end;
  133. {******************************************************************************
  134. --- Info / Date / Time ---
  135. ******************************************************************************}
  136. type
  137. TSystemTime = record
  138. wYear,
  139. wMonth,
  140. wDayOfWeek,
  141. wDay,
  142. wHour,
  143. wMinute,
  144. wSecond,
  145. wMilliseconds: Word;
  146. end;
  147. function GetVersion : longint;
  148. stdcall; external 'kernel32' name 'GetVersion';
  149. procedure GetLocalTime(var t : TSystemTime);
  150. stdcall; external 'kernel32' name 'GetLocalTime';
  151. function SetLocalTime(const t : TSystemTime) : longbool;
  152. stdcall; external 'kernel32' name 'SetLocalTime';
  153. function dosversion : word;
  154. begin
  155. dosversion:=GetVersion and $ffff;
  156. end;
  157. procedure getdate(var year,month,mday,wday : word);
  158. var
  159. t : TSystemTime;
  160. begin
  161. GetLocalTime(t);
  162. year:=t.wYear;
  163. month:=t.wMonth;
  164. mday:=t.wDay;
  165. wday:=t.wDayOfWeek;
  166. end;
  167. procedure setdate(year,month,day : word);
  168. var
  169. t : TSystemTime;
  170. begin
  171. { we need the time set privilege }
  172. { so this function crash currently }
  173. {!!!!!}
  174. GetLocalTime(t);
  175. t.wYear:=year;
  176. t.wMonth:=month;
  177. t.wDay:=day;
  178. { only a quite good solution, we can loose some ms }
  179. SetLocalTime(t);
  180. end;
  181. procedure gettime(var hour,minute,second,sec100 : word);
  182. var
  183. t : TSystemTime;
  184. begin
  185. GetLocalTime(t);
  186. hour:=t.wHour;
  187. minute:=t.wMinute;
  188. second:=t.wSecond;
  189. sec100:=t.wMilliSeconds div 10;
  190. end;
  191. procedure settime(hour,minute,second,sec100 : word);
  192. var
  193. t : TSystemTime;
  194. begin
  195. { we need the time set privilege }
  196. { so this function crash currently }
  197. {!!!!!}
  198. GetLocalTime(t);
  199. t.wHour:=hour;
  200. t.wMinute:=minute;
  201. t.wSecond:=second;
  202. t.wMilliSeconds:=sec100*10;
  203. SetLocalTime(t);
  204. end;
  205. {******************************************************************************
  206. --- Exec ---
  207. ******************************************************************************}
  208. type
  209. PProcessInformation = ^TProcessInformation;
  210. TProcessInformation = record
  211. hProcess: THandle;
  212. hThread: THandle;
  213. dwProcessId: DWORD;
  214. dwThreadId: DWORD;
  215. end;
  216. function CreateProcess(lpApplicationName: PChar; lpCommandLine: PChar;
  217. lpProcessAttributes, lpThreadAttributes: Pointer;
  218. bInheritHandles: Longbool; dwCreationFlags: DWORD; lpEnvironment: Pointer;
  219. lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
  220. var lpProcessInformation: TProcessInformation): longbool;
  221. stdcall; external 'kernel32' name 'CreateProcessA';
  222. function getExitCodeProcess(h:THandle;var code:longint):longbool;
  223. stdcall; external 'kernel32' name 'GetExitCodeProcess';
  224. function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD;
  225. stdcall; external 'kernel32' name 'WaitForSingleObject';
  226. function CloseHandle(h : THandle) : longint;
  227. stdcall; external 'kernel32' name 'CloseHandle';
  228. procedure exec(const path : pathstr;const comline : comstr);
  229. var
  230. SI: TStartupInfo;
  231. PI: TProcessInformation;
  232. l : Longint;
  233. CommandLine : array[0..511] of char;
  234. AppParam : array[0..255] of char;
  235. pathlocal : string;
  236. begin
  237. DosError:=0;
  238. FillChar(SI, SizeOf(SI), 0);
  239. SI.cb:=SizeOf(SI);
  240. SI.wShowWindow:=1;
  241. { always surround the name of the application by quotes
  242. so that long filenames will always be accepted. But don't
  243. do it if there are already double quotes, since Win32 does not
  244. like double quotes which are duplicated!
  245. }
  246. if pos('"',path) = 0 then
  247. pathlocal:='"'+path+'"'
  248. else
  249. pathlocal := path;
  250. Move(Pathlocal[1],CommandLine,length(Pathlocal));
  251. AppParam[0]:=' ';
  252. AppParam[1]:=' ';
  253. Move(ComLine[1],AppParam[2],length(Comline));
  254. AppParam[Length(ComLine)+2]:=#0;
  255. { concatenate both pathnames }
  256. Move(Appparam[0],CommandLine[length(Pathlocal)],strlen(Appparam)+1);
  257. if not CreateProcess(nil, PChar(@CommandLine),
  258. Nil, Nil, ExecInheritsHandles,$20, Nil, Nil, SI, PI) then
  259. begin
  260. DosError:=Last2DosError(GetLastError);
  261. exit;
  262. end;
  263. if WaitForSingleObject(PI.hProcess,dword($ffffffff))<>$ffffffff then
  264. GetExitCodeProcess(PI.hProcess,l)
  265. else
  266. l:=-1;
  267. CloseHandle(PI.hProcess);
  268. CloseHandle(PI.hThread);
  269. LastDosExitCode:=l;
  270. end;
  271. {******************************************************************************
  272. --- Disk ---
  273. ******************************************************************************}
  274. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  275. freeclusters,totalclusters:DWORD):longbool;
  276. stdcall; external 'kernel32' name 'GetDiskFreeSpaceA';
  277. type
  278. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,
  279. total,free):longbool;stdcall;
  280. var
  281. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  282. function diskfree(drive : byte) : int64;
  283. var
  284. disk : array[1..4] of char;
  285. secs,bytes,
  286. free,total : DWORD;
  287. qwtotal,qwfree,qwcaller : int64;
  288. begin
  289. if drive=0 then
  290. begin
  291. disk[1]:='\';
  292. disk[2]:=#0;
  293. end
  294. else
  295. begin
  296. disk[1]:=chr(drive+64);
  297. disk[2]:=':';
  298. disk[3]:='\';
  299. disk[4]:=#0;
  300. end;
  301. if assigned(GetDiskFreeSpaceEx) then
  302. begin
  303. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  304. diskfree:=qwfree
  305. else
  306. diskfree:=-1;
  307. end
  308. else
  309. begin
  310. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  311. diskfree:=int64(free)*secs*bytes
  312. else
  313. diskfree:=-1;
  314. end;
  315. end;
  316. function disksize(drive : byte) : int64;
  317. var
  318. disk : array[1..4] of char;
  319. secs,bytes,
  320. free,total : DWORD;
  321. qwtotal,qwfree,qwcaller : int64;
  322. begin
  323. if drive=0 then
  324. begin
  325. disk[1]:='\';
  326. disk[2]:=#0;
  327. end
  328. else
  329. begin
  330. disk[1]:=chr(drive+64);
  331. disk[2]:=':';
  332. disk[3]:='\';
  333. disk[4]:=#0;
  334. end;
  335. if assigned(GetDiskFreeSpaceEx) then
  336. begin
  337. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  338. disksize:=qwtotal
  339. else
  340. disksize:=-1;
  341. end
  342. else
  343. begin
  344. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  345. disksize:=int64(total)*secs*bytes
  346. else
  347. disksize:=-1;
  348. end;
  349. end;
  350. {******************************************************************************
  351. --- Findfirst FindNext ---
  352. ******************************************************************************}
  353. { Needed kernel calls }
  354. function FindFirstFile (lpFileName: PChar; var lpFindFileData: TWinFindData): THandle;
  355. stdcall; external 'kernel32' name 'FindFirstFileA';
  356. function FindNextFile (hFindFile: THandle; var lpFindFileData: TWinFindData): LongBool;
  357. stdcall; external 'kernel32' name 'FindNextFileA';
  358. function FindCloseFile (hFindFile: THandle): LongBool;
  359. stdcall; external 'kernel32' name 'FindClose';
  360. Procedure StringToPchar (Var S : String);
  361. Var L : Longint;
  362. begin
  363. L:=ord(S[0]);
  364. Move (S[1],S[0],L);
  365. S[L]:=#0;
  366. end;
  367. Procedure PCharToString (Var S : String);
  368. Var L : Longint;
  369. begin
  370. L:=strlen(pchar(@S[0]));
  371. Move (S[0],S[1],L);
  372. S[0]:=char(l);
  373. end;
  374. procedure FindMatch(var f:searchrec);
  375. begin
  376. { Find file with correct attribute }
  377. While (F.WinFindData.dwFileAttributes and DWORD(F.ExcludeAttr))<>0 do
  378. begin
  379. if not FindNextFile (F.FindHandle,F.WinFindData) then
  380. begin
  381. DosError:=Last2DosError(GetLastError);
  382. if DosError=2 then
  383. DosError:=18;
  384. exit;
  385. end;
  386. end;
  387. { Convert some attributes back }
  388. f.size:=F.WinFindData.NFileSizeLow;
  389. f.attr:=WinToDosAttr(F.WinFindData.dwFileAttributes);
  390. WinToDosTime(F.WinFindData.ftLastWriteTime,f.Time);
  391. f.Name:=StrPas(@F.WinFindData.cFileName);
  392. end;
  393. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  394. begin
  395. fillchar(f,sizeof(f),0);
  396. { no error }
  397. doserror:=0;
  398. F.Name:=Path;
  399. F.Attr:=attr;
  400. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  401. StringToPchar(f.name);
  402. { FindFirstFile is a Win32 Call }
  403. F.WinFindData.dwFileAttributes:=DosToWinAttr(f.attr);
  404. F.FindHandle:=FindFirstFile (pchar(@f.Name),F.WinFindData);
  405. If F.FindHandle=Invalid_Handle_value then
  406. begin
  407. DosError:=Last2DosError(GetLastError);
  408. if DosError=2 then
  409. DosError:=18;
  410. exit;
  411. end;
  412. { Find file with correct attribute }
  413. FindMatch(f);
  414. end;
  415. procedure findnext(var f : searchRec);
  416. begin
  417. { no error }
  418. doserror:=0;
  419. if not FindNextFile (F.FindHandle,F.WinFindData) then
  420. begin
  421. DosError:=Last2DosError(GetLastError);
  422. if DosError=2 then
  423. DosError:=18;
  424. exit;
  425. end;
  426. { Find file with correct attribute }
  427. FindMatch(f);
  428. end;
  429. Procedure FindClose(Var f: SearchRec);
  430. begin
  431. If F.FindHandle<>Invalid_Handle_value then
  432. FindCloseFile(F.FindHandle);
  433. end;
  434. {******************************************************************************
  435. --- File ---
  436. ******************************************************************************}
  437. function GetWinFileTime(h : longint;creation,lastaccess,lastwrite : PWinFileTime) : longbool;
  438. stdcall; external 'kernel32' name 'GetFileTime';
  439. function SetWinFileTime(h : longint;creation,lastaccess,lastwrite : PWinFileTime) : longbool;
  440. stdcall; external 'kernel32' name 'SetFileTime';
  441. function SetFileAttributes(lpFileName : pchar;dwFileAttributes : longint) : longbool;
  442. stdcall; external 'kernel32' name 'SetFileAttributesA';
  443. function GetFileAttributes(lpFileName : pchar) : longint;
  444. stdcall; external 'kernel32' name 'GetFileAttributesA';
  445. { <immobilizer> }
  446. function GetFullPathName(lpFileName: PChar; nBufferLength: Longint; lpBuffer: PChar; var lpFilePart : PChar):DWORD;
  447. stdcall; external 'kernel32' name 'GetFullPathNameA';
  448. function GetShortPathName(lpszLongPath:pchar; lpszShortPath:pchar; cchBuffer:DWORD):DWORD;
  449. stdcall; external 'kernel32' name 'GetShortPathNameA';
  450. Function FSearch(path: pathstr; dirlist: string): pathstr;
  451. var
  452. i,p1 : longint;
  453. s : searchrec;
  454. newdir : pathstr;
  455. begin
  456. { check if the file specified exists }
  457. findfirst(path,anyfile and not(directory),s);
  458. if doserror=0 then
  459. begin
  460. findclose(s);
  461. fsearch:=path;
  462. exit;
  463. end;
  464. { No wildcards allowed in these things }
  465. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  466. fsearch:=''
  467. else
  468. begin
  469. { allow slash as backslash }
  470. for i:=1 to length(dirlist) do
  471. if dirlist[i]='/' then dirlist[i]:='\';
  472. repeat
  473. p1:=pos(';',dirlist);
  474. if p1<>0 then
  475. begin
  476. newdir:=copy(dirlist,1,p1-1);
  477. delete(dirlist,1,p1);
  478. end
  479. else
  480. begin
  481. newdir:=dirlist;
  482. dirlist:='';
  483. end;
  484. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  485. newdir:=newdir+'\';
  486. findfirst(newdir+path,anyfile and not(directory),s);
  487. if doserror=0 then
  488. newdir:=newdir+path
  489. else
  490. newdir:='';
  491. until (dirlist='') or (newdir<>'');
  492. fsearch:=newdir;
  493. end;
  494. findclose(s);
  495. end;
  496. procedure getftime(var f;var time : longint);
  497. var
  498. ft : TWinFileTime;
  499. begin
  500. doserror:=0;
  501. if GetWinFileTime(filerec(f).Handle,nil,nil,@ft) and
  502. WinToDosTime(ft,time) then
  503. exit
  504. else
  505. begin
  506. DosError:=Last2DosError(GetLastError);
  507. time:=0;
  508. end;
  509. end;
  510. procedure setftime(var f;time : longint);
  511. var
  512. ft : TWinFileTime;
  513. begin
  514. doserror:=0;
  515. if DosToWinTime(time,ft) and
  516. SetWinFileTime(filerec(f).Handle,nil,nil,@ft) then
  517. exit
  518. else
  519. DosError:=Last2DosError(GetLastError);
  520. end;
  521. procedure getfattr(var f;var attr : word);
  522. var
  523. l : longint;
  524. begin
  525. doserror:=0;
  526. l:=GetFileAttributes(filerec(f).name);
  527. if l=longint($ffffffff) then
  528. begin
  529. doserror:=getlasterror;
  530. attr:=0;
  531. end
  532. else
  533. attr:=l and $ffff;
  534. end;
  535. procedure setfattr(var f;attr : word);
  536. begin
  537. { Fail for setting VolumeId }
  538. if (attr and VolumeID)<>0 then
  539. doserror:=5
  540. else
  541. if SetFileAttributes(filerec(f).name,attr) then
  542. doserror:=0
  543. else
  544. doserror:=getlasterror;
  545. end;
  546. { change to short filename if successful win32 call PM }
  547. function GetShortName(var p : String) : boolean;
  548. var
  549. buffer : array[0..255] of char;
  550. ret : longint;
  551. begin
  552. {we can't mess with p, because we have to return it if call is
  553. unsuccesfully.}
  554. if Length(p)>0 then {copy p to array of char}
  555. move(p[1],buffer[0],length(p));
  556. buffer[length(p)]:=chr(0);
  557. {Should return value load loaddoserror?}
  558. ret:=GetShortPathName(@buffer,@buffer,255);
  559. if (Ret > 0) and (Ret <= 255) then
  560. begin
  561. Move (Buffer, P [1], Ret);
  562. byte (P [0]) := Ret;
  563. GetShortName := true;
  564. end
  565. else
  566. GetShortName := false;
  567. end;
  568. { change to long filename if successful DOS call PM }
  569. function GetLongName(var p : String) : boolean;
  570. var
  571. SR: SearchRec;
  572. FullFN, FinalFN, TestFN: string;
  573. Found: boolean;
  574. SPos: byte;
  575. begin
  576. if Length (P) = 0 then
  577. GetLongName := false
  578. else
  579. begin
  580. FullFN := FExpand (P); (* Needed to be done at the beginning to get proper case for all parts *)
  581. SPos := 1;
  582. if (Length (FullFN) > 2) then
  583. if (FullFN [2] = DriveSeparator) then
  584. SPos := 4
  585. else
  586. if (FullFN [1] = DirectorySeparator) and (FullFN [2] = DirectorySeparator) then
  587. begin
  588. SPos := 3;
  589. while (Length (FullFN) > SPos) and (FullFN [SPos] <> DirectorySeparator) do
  590. Inc (SPos);
  591. if SPos >= Length (FullFN) then
  592. SPos := 1
  593. else
  594. begin
  595. Inc (SPos);
  596. while (Length (FullFN) >= SPos) and (FullFN [SPos] <> DirectorySeparator) do
  597. Inc (SPos);
  598. if SPos <= Length (FullFN) then
  599. Inc (SPos);
  600. end;
  601. end;
  602. FinalFN := Copy (FullFN, 1, Pred (SPos));
  603. Delete (FullFN, 1, Pred (SPos));
  604. Found := true;
  605. while (FullFN <> '') and Found do
  606. begin
  607. SPos := Pos (DirectorySeparator, FullFN);
  608. TestFN := Copy (FullFN, 1, Pred (SPos));
  609. Delete (FullFN, 1, Pred (SPos));
  610. FindFirst (FinalFN + TestFN, AnyFile, SR);
  611. if DosError <> 0 then
  612. Found := false
  613. else
  614. begin
  615. FinalFN := FinalFN + SR.Name;
  616. if (FullFN <> '') and (FullFN [1] = DirectorySeparator) then
  617. begin
  618. FinalFN := FinalFN + DirectorySeparator;
  619. Delete (FullFN, 1, 1);
  620. end;
  621. end;
  622. FindClose (SR);
  623. end;
  624. if Found then
  625. begin
  626. GetLongName := true;
  627. P := FinalFN;
  628. end
  629. else
  630. GetLongName := false
  631. end;
  632. end;
  633. {******************************************************************************
  634. --- Environment ---
  635. ******************************************************************************}
  636. {
  637. The environment is a block of zero terminated strings
  638. terminated by a #0
  639. }
  640. function GetEnvironmentStrings : pchar;
  641. stdcall; external 'kernel32' name 'GetEnvironmentStringsA';
  642. function FreeEnvironmentStrings(p : pchar) : longbool;
  643. stdcall; external 'kernel32' name 'FreeEnvironmentStringsA';
  644. function envcount : longint;
  645. var
  646. hp,p : pchar;
  647. count : longint;
  648. begin
  649. p:=GetEnvironmentStrings;
  650. hp:=p;
  651. count:=0;
  652. while hp^<>#0 do
  653. begin
  654. { next string entry}
  655. hp:=hp+strlen(hp)+1;
  656. inc(count);
  657. end;
  658. FreeEnvironmentStrings(p);
  659. envcount:=count;
  660. end;
  661. Function EnvStr (Index: longint): string;
  662. var
  663. hp,p : pchar;
  664. count,i : longint;
  665. begin
  666. { envcount takes some time in win32 }
  667. count:=envcount;
  668. { range checking }
  669. if (index<=0) or (index>count) then
  670. begin
  671. envstr:='';
  672. exit;
  673. end;
  674. p:=GetEnvironmentStrings;
  675. hp:=p;
  676. { retrive the string with the given index }
  677. for i:=2 to index do
  678. hp:=hp+strlen(hp)+1;
  679. envstr:=strpas(hp);
  680. FreeEnvironmentStrings(p);
  681. end;
  682. Function GetEnv(envvar: string): string;
  683. var
  684. s : string;
  685. i : longint;
  686. hp,p : pchar;
  687. begin
  688. getenv:='';
  689. p:=GetEnvironmentStrings;
  690. hp:=p;
  691. while hp^<>#0 do
  692. begin
  693. s:=strpas(hp);
  694. i:=pos('=',s);
  695. if upcase(copy(s,1,i-1))=upcase(envvar) then
  696. begin
  697. { getenv:=copy(s,i+1,length(s)-i);
  698. this limits the size to 255-(i+1) }
  699. getenv:=strpas(hp+i);
  700. break;
  701. end;
  702. { next string entry}
  703. hp:=hp+strlen(hp)+1;
  704. end;
  705. FreeEnvironmentStrings(p);
  706. end;
  707. function FreeLibrary(hLibModule : THandle) : longbool;
  708. stdcall; external 'kernel32' name 'FreeLibrary';
  709. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  710. stdcall; external 'kernel32' name 'GetVersionExA';
  711. function LoadLibrary(lpLibFileName : pchar):THandle;
  712. stdcall; external 'kernel32' name 'LoadLibraryA';
  713. function GetProcAddress(hModule : THandle;lpProcName : pchar) : pointer;
  714. stdcall; external 'kernel32' name 'GetProcAddress';
  715. var
  716. oldexitproc : pointer;
  717. procedure dosexitproc;
  718. begin
  719. exitproc:=oldexitproc;
  720. if kernel32dll<>0 then
  721. FreeLibrary(kernel32dll);
  722. end;
  723. begin
  724. oldexitproc:=exitproc;
  725. exitproc:=@dosexitproc;
  726. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  727. GetVersionEx(versioninfo);
  728. kernel32dll:=0;
  729. GetDiskFreeSpaceEx:=nil;
  730. {$ifndef win64}
  731. if ((versioninfo.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS) and
  732. (versioninfo.dwBuildNUmber>=1000)) or
  733. (versioninfo.dwPlatformId=VER_PLATFORM_WIN32_NT) then
  734. {$endif win64}
  735. begin
  736. kernel32dll:=LoadLibrary('kernel32');
  737. if kernel32dll<>0 then
  738. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  739. end;
  740. end.