dos.pp 22 KB

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