dos.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  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. CommandLine : array[0..511] of char;
  233. AppParam : array[0..255] of char;
  234. pathlocal : string;
  235. begin
  236. DosError:=0;
  237. FillChar(SI, SizeOf(SI), 0);
  238. SI.cb:=SizeOf(SI);
  239. SI.wShowWindow:=1;
  240. { always surround the name of the application by quotes
  241. so that long filenames will always be accepted. But don't
  242. do it if there are already double quotes, since Win32 does not
  243. like double quotes which are duplicated!
  244. }
  245. if pos('"',path) = 0 then
  246. pathlocal:='"'+path+'"'
  247. else
  248. pathlocal := path;
  249. Move(Pathlocal[1],CommandLine,length(Pathlocal));
  250. AppParam[0]:=' ';
  251. AppParam[1]:=' ';
  252. Move(ComLine[1],AppParam[2],length(Comline));
  253. AppParam[Length(ComLine)+2]:=#0;
  254. { concatenate both pathnames }
  255. Move(Appparam[0],CommandLine[length(Pathlocal)],strlen(Appparam)+1);
  256. if not CreateProcess(nil, PChar(@CommandLine),
  257. Nil, Nil, ExecInheritsHandles,$20, Nil, Nil, SI, PI) then
  258. begin
  259. DosError:=Last2DosError(GetLastError);
  260. exit;
  261. end;
  262. if WaitForSingleObject(PI.hProcess,dword($ffffffff))<>$ffffffff then
  263. GetExitCodeProcess(PI.hProcess,l)
  264. else
  265. l:=-1;
  266. CloseHandle(PI.hProcess);
  267. CloseHandle(PI.hThread);
  268. LastDosExitCode:=l;
  269. end;
  270. {******************************************************************************
  271. --- Disk ---
  272. ******************************************************************************}
  273. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  274. freeclusters,totalclusters:DWORD):longbool;
  275. stdcall; external 'kernel32' name 'GetDiskFreeSpaceA';
  276. type
  277. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,
  278. total,free):longbool;stdcall;
  279. var
  280. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  281. function diskfree(drive : byte) : int64;
  282. var
  283. disk : array[1..4] of char;
  284. secs,bytes,
  285. free,total : DWORD;
  286. qwtotal,qwfree,qwcaller : int64;
  287. begin
  288. if drive=0 then
  289. begin
  290. disk[1]:='\';
  291. disk[2]:=#0;
  292. end
  293. else
  294. begin
  295. disk[1]:=chr(drive+64);
  296. disk[2]:=':';
  297. disk[3]:='\';
  298. disk[4]:=#0;
  299. end;
  300. if assigned(GetDiskFreeSpaceEx) then
  301. begin
  302. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  303. diskfree:=qwfree
  304. else
  305. diskfree:=-1;
  306. end
  307. else
  308. begin
  309. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  310. diskfree:=int64(free)*secs*bytes
  311. else
  312. diskfree:=-1;
  313. end;
  314. end;
  315. function disksize(drive : byte) : int64;
  316. var
  317. disk : array[1..4] of char;
  318. secs,bytes,
  319. free,total : DWORD;
  320. qwtotal,qwfree,qwcaller : int64;
  321. begin
  322. if drive=0 then
  323. begin
  324. disk[1]:='\';
  325. disk[2]:=#0;
  326. end
  327. else
  328. begin
  329. disk[1]:=chr(drive+64);
  330. disk[2]:=':';
  331. disk[3]:='\';
  332. disk[4]:=#0;
  333. end;
  334. if assigned(GetDiskFreeSpaceEx) then
  335. begin
  336. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  337. disksize:=qwtotal
  338. else
  339. disksize:=-1;
  340. end
  341. else
  342. begin
  343. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  344. disksize:=int64(total)*secs*bytes
  345. else
  346. disksize:=-1;
  347. end;
  348. end;
  349. {******************************************************************************
  350. --- Findfirst FindNext ---
  351. ******************************************************************************}
  352. { Needed kernel calls }
  353. function FindFirstFile (lpFileName: PChar; var lpFindFileData: TWinFindData): THandle;
  354. stdcall; external 'kernel32' name 'FindFirstFileA';
  355. function FindNextFile (hFindFile: THandle; var lpFindFileData: TWinFindData): LongBool;
  356. stdcall; external 'kernel32' name 'FindNextFileA';
  357. function FindCloseFile (hFindFile: THandle): LongBool;
  358. stdcall; external 'kernel32' name 'FindClose';
  359. Procedure StringToPchar (Var S : String);
  360. Var L : Longint;
  361. begin
  362. L:=ord(S[0]);
  363. Move (S[1],S[0],L);
  364. S[L]:=#0;
  365. end;
  366. Procedure PCharToString (Var S : String);
  367. Var L : Longint;
  368. begin
  369. L:=strlen(pchar(@S[0]));
  370. Move (S[0],S[1],L);
  371. S[0]:=char(l);
  372. end;
  373. procedure FindMatch(var f:searchrec);
  374. begin
  375. { Find file with correct attribute }
  376. While (F.WinFindData.dwFileAttributes and DWORD(F.ExcludeAttr))<>0 do
  377. begin
  378. if not FindNextFile (F.FindHandle,F.WinFindData) then
  379. begin
  380. DosError:=Last2DosError(GetLastError);
  381. if DosError=2 then
  382. DosError:=18;
  383. exit;
  384. end;
  385. end;
  386. { Convert some attributes back }
  387. f.size:=F.WinFindData.NFileSizeLow;
  388. f.attr:=WinToDosAttr(F.WinFindData.dwFileAttributes);
  389. WinToDosTime(F.WinFindData.ftLastWriteTime,f.Time);
  390. f.Name:=StrPas(@F.WinFindData.cFileName);
  391. end;
  392. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  393. begin
  394. fillchar(f,sizeof(f),0);
  395. { no error }
  396. doserror:=0;
  397. F.Name:=Path;
  398. F.Attr:=attr;
  399. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  400. StringToPchar(f.name);
  401. { FindFirstFile is a Win32 Call }
  402. F.WinFindData.dwFileAttributes:=DosToWinAttr(f.attr);
  403. F.FindHandle:=FindFirstFile (pchar(@f.Name),F.WinFindData);
  404. If F.FindHandle=Invalid_Handle_value then
  405. begin
  406. DosError:=Last2DosError(GetLastError);
  407. if DosError=2 then
  408. DosError:=18;
  409. exit;
  410. end;
  411. { Find file with correct attribute }
  412. FindMatch(f);
  413. end;
  414. procedure findnext(var f : searchRec);
  415. begin
  416. { no error }
  417. doserror:=0;
  418. if not FindNextFile (F.FindHandle,F.WinFindData) then
  419. begin
  420. DosError:=Last2DosError(GetLastError);
  421. if DosError=2 then
  422. DosError:=18;
  423. exit;
  424. end;
  425. { Find file with correct attribute }
  426. FindMatch(f);
  427. end;
  428. Procedure FindClose(Var f: SearchRec);
  429. begin
  430. If F.FindHandle<>Invalid_Handle_value then
  431. FindCloseFile(F.FindHandle);
  432. end;
  433. {******************************************************************************
  434. --- File ---
  435. ******************************************************************************}
  436. function GetWinFileTime(h : longint;creation,lastaccess,lastwrite : PWinFileTime) : longbool;
  437. stdcall; external 'kernel32' name 'GetFileTime';
  438. function SetWinFileTime(h : longint;creation,lastaccess,lastwrite : PWinFileTime) : longbool;
  439. stdcall; external 'kernel32' name 'SetFileTime';
  440. function SetFileAttributes(lpFileName : pchar;dwFileAttributes : longint) : longbool;
  441. stdcall; external 'kernel32' name 'SetFileAttributesA';
  442. function GetFileAttributes(lpFileName : pchar) : longint;
  443. stdcall; external 'kernel32' name 'GetFileAttributesA';
  444. { <immobilizer> }
  445. function GetFullPathName(lpFileName: PChar; nBufferLength: Longint; lpBuffer: PChar; var lpFilePart : PChar):DWORD;
  446. stdcall; external 'kernel32' name 'GetFullPathNameA';
  447. function GetShortPathName(lpszLongPath:pchar; lpszShortPath:pchar; cchBuffer:DWORD):DWORD;
  448. stdcall; external 'kernel32' name 'GetShortPathNameA';
  449. Function FSearch(path: pathstr; dirlist: string): pathstr;
  450. var
  451. p1 : longint;
  452. s : searchrec;
  453. newdir : pathstr;
  454. begin
  455. { check if the file specified exists }
  456. findfirst(path,anyfile and not(directory),s);
  457. if doserror=0 then
  458. begin
  459. findclose(s);
  460. fsearch:=path;
  461. exit;
  462. end;
  463. { No wildcards allowed in these things }
  464. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  465. fsearch:=''
  466. else
  467. begin
  468. { allow slash as backslash }
  469. DoDirSeparators(dirlist);
  470. repeat
  471. p1:=pos(';',dirlist);
  472. if p1<>0 then
  473. begin
  474. newdir:=copy(dirlist,1,p1-1);
  475. delete(dirlist,1,p1);
  476. end
  477. else
  478. begin
  479. newdir:=dirlist;
  480. dirlist:='';
  481. end;
  482. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  483. newdir:=newdir+'\';
  484. findfirst(newdir+path,anyfile and not(directory),s);
  485. if doserror=0 then
  486. newdir:=newdir+path
  487. else
  488. newdir:='';
  489. until (dirlist='') or (newdir<>'');
  490. fsearch:=newdir;
  491. end;
  492. findclose(s);
  493. end;
  494. procedure getftime(var f;var time : longint);
  495. var
  496. ft : TWinFileTime;
  497. begin
  498. doserror:=0;
  499. if GetWinFileTime(filerec(f).Handle,nil,nil,@ft) and
  500. WinToDosTime(ft,time) then
  501. exit
  502. else
  503. begin
  504. DosError:=Last2DosError(GetLastError);
  505. time:=0;
  506. end;
  507. end;
  508. procedure setftime(var f;time : longint);
  509. var
  510. ft : TWinFileTime;
  511. begin
  512. doserror:=0;
  513. if DosToWinTime(time,ft) and
  514. SetWinFileTime(filerec(f).Handle,nil,nil,@ft) then
  515. exit
  516. else
  517. DosError:=Last2DosError(GetLastError);
  518. end;
  519. procedure getfattr(var f;var attr : word);
  520. var
  521. l : longint;
  522. s : RawByteString;
  523. begin
  524. doserror:=0;
  525. s:=ToSingleByteFileSystemEncodedFileName(filerec(f).name);
  526. l:=GetFileAttributes(pchar(s));
  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. var s : RawByteString;
  537. begin
  538. { Fail for setting VolumeId }
  539. if (attr and VolumeID)<>0 then
  540. doserror:=5
  541. else
  542. begin
  543. s:=ToSingleByteFileSystemEncodedFileName(filerec(f).name);
  544. if SetFileAttributes(pchar(s),attr) then
  545. doserror:=0
  546. else
  547. doserror:=getlasterror;
  548. end;
  549. end;
  550. { change to short filename if successful win32 call PM }
  551. function GetShortName(var p : String) : boolean;
  552. var
  553. buffer : array[0..255] of char;
  554. ret : longint;
  555. begin
  556. {we can't mess with p, because we have to return it if call is
  557. unsuccesfully.}
  558. if Length(p)>0 then {copy p to array of char}
  559. move(p[1],buffer[0],length(p));
  560. buffer[length(p)]:=chr(0);
  561. {Should return value load loaddoserror?}
  562. ret:=GetShortPathName(@buffer,@buffer,255);
  563. if (Ret > 0) and (Ret <= 255) then
  564. begin
  565. Move (Buffer, P [1], Ret);
  566. byte (P [0]) := Ret;
  567. GetShortName := true;
  568. end
  569. else
  570. GetShortName := false;
  571. end;
  572. { change to long filename if successful DOS call PM }
  573. function GetLongName(var p : String) : boolean;
  574. var
  575. SR: SearchRec;
  576. FullFN, FinalFN, TestFN: string;
  577. Found: boolean;
  578. SPos: byte;
  579. begin
  580. if Length (P) = 0 then
  581. GetLongName := false
  582. else
  583. begin
  584. FullFN := FExpand (P); (* Needed to be done at the beginning to get proper case for all parts *)
  585. SPos := 1;
  586. if (Length (FullFN) > 2) then
  587. if (FullFN [2] = DriveSeparator) then
  588. SPos := 4
  589. else
  590. if (FullFN [1] = DirectorySeparator) and (FullFN [2] = DirectorySeparator) then
  591. begin
  592. SPos := 3;
  593. while (Length (FullFN) > SPos) and (FullFN [SPos] <> DirectorySeparator) do
  594. Inc (SPos);
  595. if SPos >= Length (FullFN) then
  596. SPos := 1
  597. else
  598. begin
  599. Inc (SPos);
  600. while (Length (FullFN) >= SPos) and (FullFN [SPos] <> DirectorySeparator) do
  601. Inc (SPos);
  602. if SPos <= Length (FullFN) then
  603. Inc (SPos);
  604. end;
  605. end;
  606. FinalFN := Copy (FullFN, 1, Pred (SPos));
  607. Delete (FullFN, 1, Pred (SPos));
  608. Found := true;
  609. while (FullFN <> '') and Found do
  610. begin
  611. SPos := Pos (DirectorySeparator, FullFN);
  612. TestFN := Copy (FullFN, 1, Pred (SPos));
  613. Delete (FullFN, 1, Pred (SPos));
  614. FindFirst (FinalFN + TestFN, AnyFile, SR);
  615. if DosError <> 0 then
  616. Found := false
  617. else
  618. begin
  619. FinalFN := FinalFN + SR.Name;
  620. if (FullFN <> '') and (FullFN [1] = DirectorySeparator) then
  621. begin
  622. FinalFN := FinalFN + DirectorySeparator;
  623. Delete (FullFN, 1, 1);
  624. end;
  625. end;
  626. FindClose (SR);
  627. end;
  628. if Found then
  629. begin
  630. GetLongName := true;
  631. P := FinalFN;
  632. end
  633. else
  634. GetLongName := false
  635. end;
  636. end;
  637. {******************************************************************************
  638. --- Environment ---
  639. ******************************************************************************}
  640. {
  641. The environment is a block of zero terminated strings
  642. terminated by a #0
  643. }
  644. function GetEnvironmentStrings : pchar;
  645. stdcall; external 'kernel32' name 'GetEnvironmentStringsA';
  646. function FreeEnvironmentStrings(p : pchar) : longbool;
  647. stdcall; external 'kernel32' name 'FreeEnvironmentStringsA';
  648. {$push}
  649. { GetEnvironmentStrings cannot be checked by CheckPointer function }
  650. {$checkpointer off}
  651. function envcount : longint;
  652. var
  653. hp,p : pchar;
  654. count : longint;
  655. begin
  656. p:=GetEnvironmentStrings;
  657. hp:=p;
  658. count:=0;
  659. while hp^<>#0 do
  660. begin
  661. { next string entry}
  662. hp:=hp+strlen(hp)+1;
  663. inc(count);
  664. end;
  665. FreeEnvironmentStrings(p);
  666. envcount:=count;
  667. end;
  668. Function EnvStr (Index: longint): string;
  669. var
  670. hp,p : pchar;
  671. count,i : longint;
  672. begin
  673. { envcount takes some time in win32 }
  674. count:=envcount;
  675. { range checking }
  676. if (index<=0) or (index>count) then
  677. begin
  678. envstr:='';
  679. exit;
  680. end;
  681. p:=GetEnvironmentStrings;
  682. hp:=p;
  683. { retrive the string with the given index }
  684. for i:=2 to index do
  685. hp:=hp+strlen(hp)+1;
  686. envstr:=strpas(hp);
  687. FreeEnvironmentStrings(p);
  688. end;
  689. Function GetEnv(envvar: string): string;
  690. var
  691. s : string;
  692. i : longint;
  693. hp,p : pchar;
  694. begin
  695. getenv:='';
  696. p:=GetEnvironmentStrings;
  697. hp:=p;
  698. while hp^<>#0 do
  699. begin
  700. s:=strpas(hp);
  701. i:=pos('=',s);
  702. if upcase(copy(s,1,i-1))=upcase(envvar) then
  703. begin
  704. { getenv:=copy(s,i+1,length(s)-i);
  705. this limits the size to 255-(i+1) }
  706. getenv:=strpas(hp+i);
  707. break;
  708. end;
  709. { next string entry}
  710. hp:=hp+strlen(hp)+1;
  711. end;
  712. FreeEnvironmentStrings(p);
  713. end;
  714. {$pop}
  715. function GetModuleHandle(p : PChar) : PtrUInt;
  716. stdcall; external 'kernel32' name 'GetModuleHandleA';
  717. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  718. stdcall; external 'kernel32' name 'GetVersionExA';
  719. function GetProcAddress(hModule : THandle;lpProcName : pchar) : pointer;
  720. stdcall; external 'kernel32' name 'GetProcAddress';
  721. begin
  722. GetDiskFreeSpaceEx:=nil;
  723. kernel32dll:=GetModuleHandle('kernel32');
  724. if kernel32dll<>0 then
  725. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  726. end.