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