dos.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  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 AnsiChar;
  32. cAlternateFileName: array[0..15] of AnsiChar;
  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 AnsiChar;
  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: PAnsiChar; lpCommandLine: PAnsiChar;
  216. lpProcessAttributes, lpThreadAttributes: Pointer;
  217. bInheritHandles: Longbool; dwCreationFlags: DWORD; lpEnvironment: Pointer;
  218. lpCurrentDirectory: PAnsiChar; 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 AnsiChar;
  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, PAnsiChar(@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:PAnsiChar;var sector_cluster,bytes_sector,
  290. freeclusters,totalclusters:DWORD):longbool;
  291. stdcall; external 'kernel32' name 'GetDiskFreeSpaceA';
  292. type
  293. TGetDiskFreeSpaceEx = function(drive:PAnsiChar;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 AnsiChar;
  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 AnsiChar;
  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: PAnsiChar; 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 : ShortString);
  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 : ShortString);
  383. Var L : Longint;
  384. begin
  385. L:=strlen(PAnsiChar(@S[0]));
  386. Move (S[0],S[1],L);
  387. S[0]:=AnsiChar(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. var
  410. S : ShortString;
  411. begin
  412. fillchar(f,sizeof(f),0);
  413. { no error }
  414. doserror:=0;
  415. F.Name:=Path;
  416. F.Attr:=attr;
  417. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  418. S:=f.name;
  419. StringToPchar(S);
  420. { FindFirstFile is a Win32 Call }
  421. F.WinFindData.dwFileAttributes:=DosToWinAttr(f.attr);
  422. F.FindHandle:=FindFirstFile (PAnsiChar(@S),F.WinFindData);
  423. If F.FindHandle=Invalid_Handle_value then
  424. begin
  425. DosError:=Last2DosError(GetLastError);
  426. if DosError=2 then
  427. DosError:=18;
  428. exit;
  429. end;
  430. { Find file with correct attribute }
  431. FindMatch(f);
  432. end;
  433. procedure findnext(var f : searchRec);
  434. begin
  435. { no error }
  436. doserror:=0;
  437. if not FindNextFile (F.FindHandle,F.WinFindData) then
  438. begin
  439. DosError:=Last2DosError(GetLastError);
  440. if DosError=2 then
  441. DosError:=18;
  442. exit;
  443. end;
  444. { Find file with correct attribute }
  445. FindMatch(f);
  446. end;
  447. Procedure FindClose(Var f: SearchRec);
  448. begin
  449. If F.FindHandle<>Invalid_Handle_value then
  450. FindCloseFile(F.FindHandle);
  451. end;
  452. {******************************************************************************
  453. --- File ---
  454. ******************************************************************************}
  455. function GetWinFileTime(h : longint;creation,lastaccess,lastwrite : PWinFileTime) : longbool;
  456. stdcall; external 'kernel32' name 'GetFileTime';
  457. function SetWinFileTime(h : longint;creation,lastaccess,lastwrite : PWinFileTime) : longbool;
  458. stdcall; external 'kernel32' name 'SetFileTime';
  459. function SetFileAttributes(lpFileName : PAnsiChar;dwFileAttributes : longint) : longbool;
  460. stdcall; external 'kernel32' name 'SetFileAttributesA';
  461. function GetFileAttributes(lpFileName : PAnsiChar) : longint;
  462. stdcall; external 'kernel32' name 'GetFileAttributesA';
  463. { <immobilizer> }
  464. function GetFullPathName(lpFileName: PAnsiChar; nBufferLength: Longint; lpBuffer: PAnsiChar; var lpFilePart : PAnsiChar):DWORD;
  465. stdcall; external 'kernel32' name 'GetFullPathNameA';
  466. function GetShortPathName(lpszLongPath:PAnsiChar; lpszShortPath:PAnsiChar; cchBuffer:DWORD):DWORD;
  467. stdcall; external 'kernel32' name 'GetShortPathNameA';
  468. Function FSearch(path: pathstr; dirlist: shortstring): pathstr;
  469. var
  470. p1 : longint;
  471. s : searchrec;
  472. newdir : pathstr;
  473. begin
  474. { No wildcards allowed in these things }
  475. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  476. begin
  477. fsearch:='';
  478. exit;
  479. end;
  480. { check if the file specified exists }
  481. findfirst(path,anyfile and not(directory),s);
  482. if doserror=0 then
  483. begin
  484. findclose(s);
  485. fsearch:=path;
  486. exit;
  487. end;
  488. findclose(s);
  489. { allow slash as backslash }
  490. DoDirSeparators(dirlist);
  491. repeat
  492. p1:=pos(';',dirlist);
  493. if p1<>0 then
  494. begin
  495. newdir:=copy(dirlist,1,p1-1);
  496. delete(dirlist,1,p1);
  497. end
  498. else
  499. begin
  500. newdir:=dirlist;
  501. dirlist:='';
  502. end;
  503. if (newdir<>'') and (not (newdir[length(newdir)] in [DirectorySeparator,DriveSeparator])) then
  504. newdir:=newdir+DirectorySeparator;
  505. findfirst(newdir+path,anyfile and not(directory),s);
  506. if doserror=0 then
  507. newdir:=newdir+path
  508. else
  509. newdir:='';
  510. findclose(s);
  511. until (dirlist='') or (newdir<>'');
  512. fsearch:=newdir;
  513. end;
  514. procedure getftime(var f;var time : longint);
  515. var
  516. ft : TWinFileTime;
  517. begin
  518. doserror:=0;
  519. if GetWinFileTime(filerec(f).Handle,nil,nil,@ft) and
  520. WinToDosTime(ft,time) then
  521. exit
  522. else
  523. begin
  524. DosError:=Last2DosError(GetLastError);
  525. time:=0;
  526. end;
  527. end;
  528. procedure setftime(var f;time : longint);
  529. var
  530. ft : TWinFileTime;
  531. begin
  532. doserror:=0;
  533. if DosToWinTime(time,ft) and
  534. SetWinFileTime(filerec(f).Handle,nil,nil,@ft) then
  535. exit
  536. else
  537. DosError:=Last2DosError(GetLastError);
  538. end;
  539. procedure getfattr(var f;var attr : word);
  540. var
  541. l : longint;
  542. s : RawByteString;
  543. begin
  544. doserror:=0;
  545. s:=ToSingleByteFileSystemEncodedFileName(filerec(f).name);
  546. l:=GetFileAttributes(PAnsiChar(s));
  547. if l=longint($ffffffff) then
  548. begin
  549. doserror:=getlasterror;
  550. attr:=0;
  551. end
  552. else
  553. attr:=l and $ffff;
  554. end;
  555. procedure setfattr(var f;attr : word);
  556. var s : RawByteString;
  557. begin
  558. { Fail for setting VolumeId }
  559. if (attr and VolumeID)<>0 then
  560. doserror:=5
  561. else
  562. begin
  563. s:=ToSingleByteFileSystemEncodedFileName(filerec(f).name);
  564. if SetFileAttributes(PAnsiChar(s),attr) then
  565. doserror:=0
  566. else
  567. doserror:=getlasterror;
  568. end;
  569. end;
  570. { change to short filename if successful win32 call PM }
  571. function GetShortName(var p : shortString) : boolean;
  572. var
  573. buffer : array[0..255] of AnsiChar;
  574. ret : longint;
  575. begin
  576. {we can't mess with p, because we have to return it if call is
  577. unsuccesfully.}
  578. if Length(p)>0 then {copy p to array of AnsiChar}
  579. move(p[1],buffer[0],length(p));
  580. buffer[length(p)]:=chr(0);
  581. {Should return value load loaddoserror?}
  582. ret:=GetShortPathName(@buffer,@buffer,255);
  583. if (Ret > 0) and (Ret <= 255) then
  584. begin
  585. Move (Buffer, P [1], Ret);
  586. byte (P [0]) := Ret;
  587. GetShortName := true;
  588. end
  589. else
  590. GetShortName := false;
  591. end;
  592. { change to long filename if successful DOS call PM }
  593. function GetLongName(var p : shortString) : boolean;
  594. var
  595. SR: SearchRec;
  596. FullFN, FinalFN, TestFN: shortstring;
  597. Found: boolean;
  598. SPos: byte;
  599. begin
  600. if Length (P) = 0 then
  601. GetLongName := false
  602. else
  603. begin
  604. FullFN := FExpand (P); (* Needed to be done at the beginning to get proper case for all parts *)
  605. SPos := 1;
  606. if (Length (FullFN) > 2) then
  607. if (FullFN [2] = DriveSeparator) then
  608. SPos := 4
  609. else
  610. if (FullFN [1] = DirectorySeparator) and (FullFN [2] = DirectorySeparator) then
  611. begin
  612. SPos := 3;
  613. while (Length (FullFN) > SPos) and (FullFN [SPos] <> DirectorySeparator) do
  614. Inc (SPos);
  615. if SPos >= Length (FullFN) then
  616. SPos := 1
  617. else
  618. begin
  619. Inc (SPos);
  620. while (Length (FullFN) >= SPos) and (FullFN [SPos] <> DirectorySeparator) do
  621. Inc (SPos);
  622. if SPos <= Length (FullFN) then
  623. Inc (SPos);
  624. end;
  625. end;
  626. FinalFN := Copy (FullFN, 1, Pred (SPos));
  627. Delete (FullFN, 1, Pred (SPos));
  628. Found := true;
  629. while (FullFN <> '') and Found do
  630. begin
  631. SPos := Pos (DirectorySeparator, FullFN);
  632. TestFN := Copy (FullFN, 1, Pred (SPos));
  633. Delete (FullFN, 1, Pred (SPos));
  634. FindFirst (FinalFN + TestFN, AnyFile, SR);
  635. if DosError <> 0 then
  636. Found := false
  637. else
  638. begin
  639. FinalFN := FinalFN + SR.Name;
  640. if (FullFN <> '') and (FullFN [1] = DirectorySeparator) then
  641. begin
  642. FinalFN := FinalFN + DirectorySeparator;
  643. Delete (FullFN, 1, 1);
  644. end;
  645. end;
  646. FindClose (SR);
  647. end;
  648. if Found then
  649. begin
  650. GetLongName := true;
  651. P := FinalFN;
  652. end
  653. else
  654. GetLongName := false
  655. end;
  656. end;
  657. {******************************************************************************
  658. --- Environment ---
  659. ******************************************************************************}
  660. {
  661. The environment is a block of zero terminated strings
  662. terminated by a #0
  663. }
  664. function GetEnvironmentStrings : PAnsiChar;
  665. stdcall; external 'kernel32' name 'GetEnvironmentStringsA';
  666. function FreeEnvironmentStrings(p : PAnsiChar) : longbool;
  667. stdcall; external 'kernel32' name 'FreeEnvironmentStringsA';
  668. {$push}
  669. { GetEnvironmentStrings cannot be checked by CheckPointer function }
  670. {$checkpointer off}
  671. function envcount : longint;
  672. var
  673. hp,p : PAnsiChar;
  674. count : longint;
  675. begin
  676. p:=GetEnvironmentStrings;
  677. hp:=p;
  678. count:=0;
  679. while hp^<>#0 do
  680. begin
  681. { next string entry}
  682. hp:=hp+strlen(hp)+1;
  683. inc(count);
  684. end;
  685. FreeEnvironmentStrings(p);
  686. envcount:=count;
  687. end;
  688. Function EnvStr (Index: longint): shortstring;
  689. var
  690. hp,p : PAnsiChar;
  691. count,i : longint;
  692. begin
  693. { envcount takes some time in win32 }
  694. count:=envcount;
  695. { range checking }
  696. if (index<=0) or (index>count) then
  697. begin
  698. envstr:='';
  699. exit;
  700. end;
  701. p:=GetEnvironmentStrings;
  702. hp:=p;
  703. { retrive the string with the given index }
  704. for i:=2 to index do
  705. hp:=hp+strlen(hp)+1;
  706. envstr:=strpas(hp);
  707. FreeEnvironmentStrings(p);
  708. end;
  709. Function GetEnv(envvar: shortstring): shortstring;
  710. var
  711. s : shortstring;
  712. i : longint;
  713. hp,p : PAnsiChar;
  714. begin
  715. getenv:='';
  716. p:=GetEnvironmentStrings;
  717. hp:=p;
  718. while hp^<>#0 do
  719. begin
  720. s:=strpas(hp);
  721. i:=pos('=',s);
  722. if upcase(copy(s,1,i-1))=upcase(envvar) then
  723. begin
  724. { getenv:=copy(s,i+1,length(s)-i);
  725. this limits the size to 255-(i+1) }
  726. getenv:=strpas(hp+i);
  727. break;
  728. end;
  729. { next string entry}
  730. hp:=hp+strlen(hp)+1;
  731. end;
  732. FreeEnvironmentStrings(p);
  733. end;
  734. {$pop}
  735. function GetModuleHandle(p : PAnsiChar) : PtrUInt;
  736. stdcall; external 'kernel32' name 'GetModuleHandleA';
  737. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  738. stdcall; external 'kernel32' name 'GetVersionExA';
  739. function GetProcAddress(hModule : THandle;lpProcName : PAnsiChar) : pointer;
  740. stdcall; external 'kernel32' name 'GetProcAddress';
  741. begin
  742. GetDiskFreeSpaceEx:=nil;
  743. kernel32dll:=GetModuleHandle('kernel32');
  744. if kernel32dll<>0 then
  745. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  746. end.