dos.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  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. 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. DoDirSeparators(dirlist);
  471. repeat
  472. p1:=pos(';',dirlist);
  473. if p1<>0 then
  474. begin
  475. newdir:=copy(dirlist,1,p1-1);
  476. delete(dirlist,1,p1);
  477. end
  478. else
  479. begin
  480. newdir:=dirlist;
  481. dirlist:='';
  482. end;
  483. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  484. newdir:=newdir+'\';
  485. findfirst(newdir+path,anyfile and not(directory),s);
  486. if doserror=0 then
  487. newdir:=newdir+path
  488. else
  489. newdir:='';
  490. until (dirlist='') or (newdir<>'');
  491. fsearch:=newdir;
  492. end;
  493. findclose(s);
  494. end;
  495. procedure getftime(var f;var time : longint);
  496. var
  497. ft : TWinFileTime;
  498. begin
  499. doserror:=0;
  500. if GetWinFileTime(filerec(f).Handle,nil,nil,@ft) and
  501. WinToDosTime(ft,time) then
  502. exit
  503. else
  504. begin
  505. DosError:=Last2DosError(GetLastError);
  506. time:=0;
  507. end;
  508. end;
  509. procedure setftime(var f;time : longint);
  510. var
  511. ft : TWinFileTime;
  512. begin
  513. doserror:=0;
  514. if DosToWinTime(time,ft) and
  515. SetWinFileTime(filerec(f).Handle,nil,nil,@ft) then
  516. exit
  517. else
  518. DosError:=Last2DosError(GetLastError);
  519. end;
  520. procedure getfattr(var f;var attr : word);
  521. var
  522. l : longint;
  523. begin
  524. doserror:=0;
  525. l:=GetFileAttributes(filerec(f).name);
  526. if l=longint($ffffffff) then
  527. begin
  528. doserror:=getlasterror;
  529. attr:=0;
  530. end
  531. else
  532. attr:=l and $ffff;
  533. end;
  534. procedure setfattr(var f;attr : word);
  535. begin
  536. { Fail for setting VolumeId }
  537. if (attr and VolumeID)<>0 then
  538. doserror:=5
  539. else
  540. if SetFileAttributes(filerec(f).name,attr) then
  541. doserror:=0
  542. else
  543. doserror:=getlasterror;
  544. end;
  545. { change to short filename if successful win32 call PM }
  546. function GetShortName(var p : String) : boolean;
  547. var
  548. buffer : array[0..255] of char;
  549. ret : longint;
  550. begin
  551. {we can't mess with p, because we have to return it if call is
  552. unsuccesfully.}
  553. if Length(p)>0 then {copy p to array of char}
  554. move(p[1],buffer[0],length(p));
  555. buffer[length(p)]:=chr(0);
  556. {Should return value load loaddoserror?}
  557. ret:=GetShortPathName(@buffer,@buffer,255);
  558. if (Ret > 0) and (Ret <= 255) then
  559. begin
  560. Move (Buffer, P [1], Ret);
  561. byte (P [0]) := Ret;
  562. GetShortName := true;
  563. end
  564. else
  565. GetShortName := false;
  566. end;
  567. { change to long filename if successful DOS call PM }
  568. function GetLongName(var p : String) : boolean;
  569. var
  570. SR: SearchRec;
  571. FullFN, FinalFN, TestFN: string;
  572. Found: boolean;
  573. SPos: byte;
  574. begin
  575. if Length (P) = 0 then
  576. GetLongName := false
  577. else
  578. begin
  579. FullFN := FExpand (P); (* Needed to be done at the beginning to get proper case for all parts *)
  580. SPos := 1;
  581. if (Length (FullFN) > 2) then
  582. if (FullFN [2] = DriveSeparator) then
  583. SPos := 4
  584. else
  585. if (FullFN [1] = DirectorySeparator) and (FullFN [2] = DirectorySeparator) then
  586. begin
  587. SPos := 3;
  588. while (Length (FullFN) > SPos) and (FullFN [SPos] <> DirectorySeparator) do
  589. Inc (SPos);
  590. if SPos >= Length (FullFN) then
  591. SPos := 1
  592. else
  593. begin
  594. Inc (SPos);
  595. while (Length (FullFN) >= SPos) and (FullFN [SPos] <> DirectorySeparator) do
  596. Inc (SPos);
  597. if SPos <= Length (FullFN) then
  598. Inc (SPos);
  599. end;
  600. end;
  601. FinalFN := Copy (FullFN, 1, Pred (SPos));
  602. Delete (FullFN, 1, Pred (SPos));
  603. Found := true;
  604. while (FullFN <> '') and Found do
  605. begin
  606. SPos := Pos (DirectorySeparator, FullFN);
  607. TestFN := Copy (FullFN, 1, Pred (SPos));
  608. Delete (FullFN, 1, Pred (SPos));
  609. FindFirst (FinalFN + TestFN, AnyFile, SR);
  610. if DosError <> 0 then
  611. Found := false
  612. else
  613. begin
  614. FinalFN := FinalFN + SR.Name;
  615. if (FullFN <> '') and (FullFN [1] = DirectorySeparator) then
  616. begin
  617. FinalFN := FinalFN + DirectorySeparator;
  618. Delete (FullFN, 1, 1);
  619. end;
  620. end;
  621. FindClose (SR);
  622. end;
  623. if Found then
  624. begin
  625. GetLongName := true;
  626. P := FinalFN;
  627. end
  628. else
  629. GetLongName := false
  630. end;
  631. end;
  632. {******************************************************************************
  633. --- Environment ---
  634. ******************************************************************************}
  635. {
  636. The environment is a block of zero terminated strings
  637. terminated by a #0
  638. }
  639. function GetEnvironmentStrings : pchar;
  640. stdcall; external 'kernel32' name 'GetEnvironmentStringsA';
  641. function FreeEnvironmentStrings(p : pchar) : longbool;
  642. stdcall; external 'kernel32' name 'FreeEnvironmentStringsA';
  643. function envcount : longint;
  644. var
  645. hp,p : pchar;
  646. count : longint;
  647. begin
  648. p:=GetEnvironmentStrings;
  649. hp:=p;
  650. count:=0;
  651. while hp^<>#0 do
  652. begin
  653. { next string entry}
  654. hp:=hp+strlen(hp)+1;
  655. inc(count);
  656. end;
  657. FreeEnvironmentStrings(p);
  658. envcount:=count;
  659. end;
  660. Function EnvStr (Index: longint): string;
  661. var
  662. hp,p : pchar;
  663. count,i : longint;
  664. begin
  665. { envcount takes some time in win32 }
  666. count:=envcount;
  667. { range checking }
  668. if (index<=0) or (index>count) then
  669. begin
  670. envstr:='';
  671. exit;
  672. end;
  673. p:=GetEnvironmentStrings;
  674. hp:=p;
  675. { retrive the string with the given index }
  676. for i:=2 to index do
  677. hp:=hp+strlen(hp)+1;
  678. envstr:=strpas(hp);
  679. FreeEnvironmentStrings(p);
  680. end;
  681. Function GetEnv(envvar: string): string;
  682. var
  683. s : string;
  684. i : longint;
  685. hp,p : pchar;
  686. begin
  687. getenv:='';
  688. p:=GetEnvironmentStrings;
  689. hp:=p;
  690. while hp^<>#0 do
  691. begin
  692. s:=strpas(hp);
  693. i:=pos('=',s);
  694. if upcase(copy(s,1,i-1))=upcase(envvar) then
  695. begin
  696. { getenv:=copy(s,i+1,length(s)-i);
  697. this limits the size to 255-(i+1) }
  698. getenv:=strpas(hp+i);
  699. break;
  700. end;
  701. { next string entry}
  702. hp:=hp+strlen(hp)+1;
  703. end;
  704. FreeEnvironmentStrings(p);
  705. end;
  706. function FreeLibrary(hLibModule : THandle) : longbool;
  707. stdcall; external 'kernel32' name 'FreeLibrary';
  708. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  709. stdcall; external 'kernel32' name 'GetVersionExA';
  710. function LoadLibrary(lpLibFileName : pchar):THandle;
  711. stdcall; external 'kernel32' name 'LoadLibraryA';
  712. function GetProcAddress(hModule : THandle;lpProcName : pchar) : pointer;
  713. stdcall; external 'kernel32' name 'GetProcAddress';
  714. var
  715. oldexitproc : pointer;
  716. procedure dosexitproc;
  717. begin
  718. exitproc:=oldexitproc;
  719. if kernel32dll<>0 then
  720. FreeLibrary(kernel32dll);
  721. end;
  722. begin
  723. oldexitproc:=exitproc;
  724. exitproc:=@dosexitproc;
  725. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  726. GetVersionEx(versioninfo);
  727. kernel32dll:=0;
  728. GetDiskFreeSpaceEx:=nil;
  729. {$ifndef win64}
  730. if ((versioninfo.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS) and
  731. (versioninfo.dwBuildNUmber>=1000)) or
  732. (versioninfo.dwPlatformId=VER_PLATFORM_WIN32_NT) then
  733. {$endif win64}
  734. begin
  735. kernel32dll:=LoadLibrary('kernel32');
  736. if kernel32dll<>0 then
  737. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  738. end;
  739. end.