dos.pp 20 KB

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