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