dos.pp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team.
  5. Dos unit for BP7 compatible RTL
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit dos;
  13. interface
  14. { Include Win32 Consts,Types }
  15. {$I win32.inc}
  16. Const
  17. Max_Path = 260;
  18. {Bitmasks for CPU Flags}
  19. fcarry = $0001;
  20. fparity = $0004;
  21. fauxiliary = $0010;
  22. fzero = $0040;
  23. fsign = $0080;
  24. foverflow = $0800;
  25. {Bitmasks for file attribute}
  26. readonly = $01;
  27. hidden = $02;
  28. sysfile = $04;
  29. volumeid = $08;
  30. directory = $10;
  31. archive = $20;
  32. anyfile = $3F;
  33. {File Status}
  34. fmclosed = $D7B0;
  35. fminput = $D7B1;
  36. fmoutput = $D7B2;
  37. fminout = $D7B3;
  38. Type
  39. { Needed for Win95 LFN Support }
  40. ComStr = String[255];
  41. PathStr = String[255];
  42. DirStr = String[255];
  43. NameStr = String[255];
  44. ExtStr = String[255];
  45. {
  46. filerec.inc contains the definition of the filerec.
  47. textrec.inc contains the definition of the textrec.
  48. It is in a separate file to make it available in other units without
  49. having to use the DOS unit for it.
  50. }
  51. {$i filerec.inc}
  52. {$i textrec.inc}
  53. DateTime = packed record
  54. Year,
  55. Month,
  56. Day,
  57. Hour,
  58. Min,
  59. Sec : word;
  60. End;
  61. PWin32FindData = ^TWin32FindData;
  62. TWin32FindData = record
  63. dwFileAttributes: Cardinal;
  64. ftCreationTime: TFileTime;
  65. ftLastAccessTime: TFileTime;
  66. ftLastWriteTime: TFileTime;
  67. nFileSizeHigh: Cardinal;
  68. nFileSizeLow: Cardinal;
  69. dwReserved0: Cardinal;
  70. dwReserved1: Cardinal;
  71. cFileName: array[0..MAX_PATH - 1] of Char;
  72. cAlternateFileName: array[0..13] of Char;
  73. // The structure should be 320 bytes long...
  74. pad : system.integer;
  75. end;
  76. Searchrec = Packed Record
  77. FindHandle : THandle;
  78. W32FindData : TWin32FindData;
  79. ExcludeAttr : longint;
  80. time : longint;
  81. size : longint;
  82. attr : longint;
  83. name : string;
  84. end;
  85. registers = packed record
  86. case i : integer of
  87. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  88. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  89. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  90. end;
  91. Var
  92. DosError : integer;
  93. {Interrupt}
  94. Procedure Intr(intno: byte; var regs: registers);
  95. Procedure MSDos(var regs: registers);
  96. {Info/Date/Time}
  97. Function DosVersion: Word;
  98. Procedure GetDate(var year, month, mday, wday: word);
  99. Procedure GetTime(var hour, minute, second, sec100: word);
  100. procedure SetDate(year,month,day: word);
  101. Procedure SetTime(hour,minute,second,sec100: word);
  102. Procedure UnpackTime(p: longint; var t: datetime);
  103. Procedure PackTime(var t: datetime; var p: longint);
  104. {Exec}
  105. Procedure Exec(const path: pathstr; const comline: comstr);
  106. Function DosExitCode: word;
  107. {Disk}
  108. Function DiskFree(drive: byte) : int64;
  109. Function DiskSize(drive: byte) : int64;
  110. Procedure FindFirst(const path: pathstr; attr: word; var f: searchRec);
  111. Procedure FindNext(var f: searchRec);
  112. Procedure FindClose(Var f: SearchRec);
  113. {File}
  114. Procedure GetFAttr(var f; var attr: word);
  115. Procedure GetFTime(var f; var time: longint);
  116. Function FSearch(path: pathstr; dirlist: string): pathstr;
  117. Function FExpand(const path: pathstr): pathstr;
  118. Procedure FSplit(path: pathstr; var dir: dirstr; var name: namestr; var ext: extstr);
  119. function GetShortName(var p : String) : boolean;
  120. function GetLongName(var p : String) : boolean;
  121. {Environment}
  122. Function EnvCount: longint;
  123. Function EnvStr(index: integer): string;
  124. Function GetEnv(envvar: string): string;
  125. {Misc}
  126. Procedure SetFAttr(var f; attr: word);
  127. Procedure SetFTime(var f; time: longint);
  128. Procedure GetCBreak(var breakvalue: boolean);
  129. Procedure SetCBreak(breakvalue: boolean);
  130. Procedure GetVerify(var verify: boolean);
  131. Procedure SetVerify(verify: boolean);
  132. {Do Nothing Functions}
  133. Procedure SwapVectors;
  134. Procedure GetIntVec(intno: byte; var vector: pointer);
  135. Procedure SetIntVec(intno: byte; vector: pointer);
  136. Procedure Keep(exitcode: word);
  137. Const
  138. { allow EXEC to inherited handles from calling process,
  139. needed for FPREDIR in ide/text
  140. now set to true by default because
  141. other OS also pass open handles to childs
  142. finally reset to false after Florian's response PM }
  143. ExecInheritsHandles : BOOL = false;
  144. implementation
  145. uses strings;
  146. type
  147. OSVERSIONINFO = record
  148. dwOSVersionInfoSize : DWORD;
  149. dwMajorVersion : DWORD;
  150. dwMinorVersion : DWORD;
  151. dwBuildNumber : DWORD;
  152. dwPlatformId : DWORD;
  153. szCSDVersion : array[0..127] of char;
  154. end;
  155. LPOSVERSIONINFO = ^OSVERSIONINFO;
  156. var
  157. versioninfo : OSVERSIONINFO;
  158. kernel32dll : THandle;
  159. {******************************************************************************
  160. --- Conversion ---
  161. ******************************************************************************}
  162. function GetLastError : DWORD;
  163. external 'kernel32' name 'GetLastError';
  164. function FileTimeToDosDateTime(const ft :TFileTime;var data,time : word) : longbool;
  165. external 'kernel32' name 'FileTimeToDosDateTime';
  166. function DosDateTimeToFileTime(date,time : word;var ft :TFileTime) : longbool;
  167. external 'kernel32' name 'DosDateTimeToFileTime';
  168. function FileTimeToLocalFileTime(const ft : TFileTime;var lft : TFileTime) : longbool;
  169. external 'kernel32' name 'FileTimeToLocalFileTime';
  170. function LocalFileTimeToFileTime(const lft : TFileTime;var ft : TFileTime) : longbool;
  171. external 'kernel32' name 'LocalFileTimeToFileTime';
  172. type
  173. Longrec=packed record
  174. lo,hi : word;
  175. end;
  176. function Last2DosError(d:dword):integer;
  177. begin
  178. Last2DosError:=d;
  179. end;
  180. Function DosToWinAttr (Const Attr : Longint) : longint;
  181. begin
  182. DosToWinAttr:=Attr;
  183. end;
  184. Function WinToDosAttr (Const Attr : Longint) : longint;
  185. begin
  186. WinToDosAttr:=Attr;
  187. end;
  188. Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
  189. var
  190. lft : TFileTime;
  191. begin
  192. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,lft) and
  193. LocalFileTimeToFileTime(lft,Wtime);
  194. end;
  195. Function WinToDosTime (Const Wtime : TFileTime;var DTime:longint):longbool;
  196. var
  197. lft : TFileTime;
  198. begin
  199. WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
  200. FileTimeToDosDateTime(lft,longrec(dtime).hi,longrec(dtime).lo);
  201. end;
  202. {******************************************************************************
  203. --- Dos Interrupt ---
  204. ******************************************************************************}
  205. procedure intr(intno : byte;var regs : registers);
  206. begin
  207. { !!!!!!!! }
  208. end;
  209. procedure msdos(var regs : registers);
  210. begin
  211. { !!!!!!!! }
  212. end;
  213. {******************************************************************************
  214. --- Info / Date / Time ---
  215. ******************************************************************************}
  216. function GetVersion : longint;
  217. external 'kernel32' name 'GetVersion';
  218. procedure GetLocalTime(var t : TSystemTime);
  219. external 'kernel32' name 'GetLocalTime';
  220. function SetLocalTime(const t : TSystemTime) : longbool;
  221. external 'kernel32' name 'SetLocalTime';
  222. function dosversion : word;
  223. begin
  224. dosversion:=GetVersion and $ffff;
  225. end;
  226. procedure getdate(var year,month,mday,wday : word);
  227. var
  228. t : TSystemTime;
  229. begin
  230. GetLocalTime(t);
  231. year:=t.wYear;
  232. month:=t.wMonth;
  233. mday:=t.wDay;
  234. wday:=t.wDayOfWeek;
  235. end;
  236. procedure setdate(year,month,day : word);
  237. var
  238. t : TSystemTime;
  239. begin
  240. { we need the time set privilege }
  241. { so this function crash currently }
  242. {!!!!!}
  243. GetLocalTime(t);
  244. t.wYear:=year;
  245. t.wMonth:=month;
  246. t.wDay:=day;
  247. { only a quite good solution, we can loose some ms }
  248. SetLocalTime(t);
  249. end;
  250. procedure gettime(var hour,minute,second,sec100 : word);
  251. var
  252. t : TSystemTime;
  253. begin
  254. GetLocalTime(t);
  255. hour:=t.wHour;
  256. minute:=t.wMinute;
  257. second:=t.wSecond;
  258. sec100:=t.wMilliSeconds div 10;
  259. end;
  260. procedure settime(hour,minute,second,sec100 : word);
  261. var
  262. t : TSystemTime;
  263. begin
  264. { we need the time set privilege }
  265. { so this function crash currently }
  266. {!!!!!}
  267. GetLocalTime(t);
  268. t.wHour:=hour;
  269. t.wMinute:=minute;
  270. t.wSecond:=second;
  271. t.wMilliSeconds:=sec100*10;
  272. SetLocalTime(t);
  273. end;
  274. Procedure packtime(var t : datetime;var p : longint);
  275. Begin
  276. p:=(t.sec shr 1)+(t.min shl 5)+(t.hour shl 11)+(t.day shl 16)+(t.month shl 21)+((t.year-1980) shl 25);
  277. End;
  278. Procedure unpacktime(p : longint;var t : datetime);
  279. Begin
  280. with t do
  281. begin
  282. sec:=(p and 31) shl 1;
  283. min:=(p shr 5) and 63;
  284. hour:=(p shr 11) and 31;
  285. day:=(p shr 16) and 31;
  286. month:=(p shr 21) and 15;
  287. year:=(p shr 25)+1980;
  288. end;
  289. End;
  290. {******************************************************************************
  291. --- Exec ---
  292. ******************************************************************************}
  293. function CreateProcess(lpApplicationName: PChar; lpCommandLine: PChar;
  294. lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
  295. bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
  296. lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
  297. var lpProcessInformation: TProcessInformation): longbool;
  298. external 'kernel32' name 'CreateProcessA';
  299. function getExitCodeProcess(h:THandle;var code:longint):longbool;
  300. external 'kernel32' name 'GetExitCodeProcess';
  301. function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD;
  302. external 'kernel32' name 'WaitForSingleObject';
  303. function CloseHandle(h : THandle) : longint;
  304. external 'kernel32' name 'CloseHandle';
  305. var
  306. lastdosexitcode : longint;
  307. procedure exec(const path : pathstr;const comline : comstr);
  308. var
  309. SI: TStartupInfo;
  310. PI: TProcessInformation;
  311. Proc : THandle;
  312. l : Longint;
  313. AppPath,
  314. AppParam : array[0..255] of char;
  315. begin
  316. FillChar(SI, SizeOf(SI), 0);
  317. SI.cb:=SizeOf(SI);
  318. SI.wShowWindow:=1;
  319. Move(Path[1],AppPath,length(Path));
  320. AppPath[Length(Path)]:=#0;
  321. AppParam[0]:='-';
  322. AppParam[1]:=' ';
  323. Move(ComLine[1],AppParam[2],length(Comline));
  324. AppParam[Length(ComLine)+2]:=#0;
  325. if not CreateProcess(PChar(@AppPath), PChar(@AppParam),
  326. Nil, Nil, ExecInheritsHandles,$20, Nil, Nil, SI, PI) then
  327. begin
  328. DosError:=Last2DosError(GetLastError);
  329. exit;
  330. end;
  331. Proc:=PI.hProcess;
  332. CloseHandle(PI.hThread);
  333. if WaitForSingleObject(Proc, Infinite) <> $ffffffff then
  334. GetExitCodeProcess(Proc,l)
  335. else
  336. l:=-1;
  337. CloseHandle(Proc);
  338. LastDosExitCode:=l;
  339. end;
  340. function dosexitcode : word;
  341. begin
  342. dosexitcode:=lastdosexitcode and $ffff;
  343. end;
  344. procedure getcbreak(var breakvalue : boolean);
  345. begin
  346. { !! No Win32 Function !! }
  347. breakvalue := true;
  348. end;
  349. procedure setcbreak(breakvalue : boolean);
  350. begin
  351. { !! No Win32 Function !! }
  352. end;
  353. procedure getverify(var verify : boolean);
  354. begin
  355. { !! No Win32 Function !! }
  356. verify := true;
  357. end;
  358. procedure setverify(verify : boolean);
  359. begin
  360. { !! No Win32 Function !! }
  361. end;
  362. {******************************************************************************
  363. --- Disk ---
  364. ******************************************************************************}
  365. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  366. freeclusters,totalclusters:longint):longbool;
  367. external 'kernel32' name 'GetDiskFreeSpaceA';
  368. type
  369. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,
  370. total,free):longbool;stdcall;
  371. var
  372. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  373. function diskfree(drive : byte) : int64;
  374. var
  375. disk : array[1..4] of char;
  376. secs,bytes,
  377. free,total : longint;
  378. qwtotal,qwfree,qwcaller : int64;
  379. begin
  380. if drive=0 then
  381. begin
  382. disk[1]:='\';
  383. disk[2]:=#0;
  384. end
  385. else
  386. begin
  387. disk[1]:=chr(drive+64);
  388. disk[2]:=':';
  389. disk[3]:='\';
  390. disk[4]:=#0;
  391. end;
  392. if assigned(GetDiskFreeSpaceEx) then
  393. begin
  394. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  395. diskfree:=qwfree
  396. else
  397. diskfree:=-1;
  398. end
  399. else
  400. begin
  401. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  402. diskfree:=int64(free)*secs*bytes
  403. else
  404. diskfree:=-1;
  405. end;
  406. end;
  407. function disksize(drive : byte) : int64;
  408. var
  409. disk : array[1..4] of char;
  410. secs,bytes,
  411. free,total : longint;
  412. qwtotal,qwfree,qwcaller : int64;
  413. begin
  414. if drive=0 then
  415. begin
  416. disk[1]:='\';
  417. disk[2]:=#0;
  418. end
  419. else
  420. begin
  421. disk[1]:=chr(drive+64);
  422. disk[2]:=':';
  423. disk[3]:='\';
  424. disk[4]:=#0;
  425. end;
  426. if assigned(GetDiskFreeSpaceEx) then
  427. begin
  428. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  429. disksize:=qwtotal
  430. else
  431. disksize:=-1;
  432. end
  433. else
  434. begin
  435. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  436. disksize:=int64(total)*secs*bytes
  437. else
  438. disksize:=-1;
  439. end;
  440. end;
  441. {******************************************************************************
  442. --- Findfirst FindNext ---
  443. ******************************************************************************}
  444. { Needed kernel calls }
  445. function FindFirstFile (lpFileName: PChar; var lpFindFileData: TWIN32FindData): THandle;
  446. external 'kernel32' name 'FindFirstFileA';
  447. function FindNextFile (hFindFile: THandle; var lpFindFileData: TWIN32FindData): LongBool;
  448. external 'kernel32' name 'FindNextFileA';
  449. function FindCloseFile (hFindFile: THandle): LongBool;
  450. external 'kernel32' name 'FindClose';
  451. Procedure StringToPchar (Var S : String);
  452. Var L : Longint;
  453. begin
  454. L:=ord(S[0]);
  455. Move (S[1],S[0],L);
  456. S[L]:=#0;
  457. end;
  458. Procedure PCharToString (Var S : String);
  459. Var L : Longint;
  460. begin
  461. L:=strlen(pchar(@S[0]));
  462. Move (S[0],S[1],L);
  463. S[0]:=char(l);
  464. end;
  465. procedure FindMatch(var f:searchrec);
  466. begin
  467. { Find file with correct attribute }
  468. While (F.W32FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  469. begin
  470. if not FindNextFile (F.FindHandle,F.W32FindData) then
  471. begin
  472. DosError:=Last2DosError(GetLastError);
  473. exit;
  474. end;
  475. end;
  476. { Convert some attributes back }
  477. f.size:=F.W32FindData.NFileSizeLow;
  478. f.attr:=WinToDosAttr(F.W32FindData.dwFileAttributes);
  479. WinToDosTime(F.W32FindData.ftLastWriteTime,f.Time);
  480. f.Name:=StrPas(@F.W32FindData.cFileName);
  481. end;
  482. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  483. begin
  484. { no error }
  485. doserror:=0;
  486. F.Name:=Path;
  487. F.Attr:=attr;
  488. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  489. StringToPchar(f.name);
  490. { FindFirstFile is a Win32 Call }
  491. F.FindHandle:=FindFirstFile (pchar(@f.Name),F.W32FindData);
  492. If longint(F.FindHandle)=Invalid_Handle_value then
  493. begin
  494. DosError:=Last2DosError(GetLastError);
  495. exit;
  496. end;
  497. { Find file with correct attribute }
  498. FindMatch(f);
  499. end;
  500. procedure findnext(var f : searchRec);
  501. begin
  502. { no error }
  503. doserror:=0;
  504. if not FindNextFile (F.FindHandle,F.W32FindData) then
  505. begin
  506. DosError:=Last2DosError(GetLastError);
  507. exit;
  508. end;
  509. { Find file with correct attribute }
  510. FindMatch(f);
  511. end;
  512. procedure swapvectors;
  513. begin
  514. end;
  515. Procedure FindClose(Var f: SearchRec);
  516. begin
  517. If longint(F.FindHandle)<>Invalid_Handle_value then
  518. FindCloseFile(F.FindHandle);
  519. end;
  520. {******************************************************************************
  521. --- File ---
  522. ******************************************************************************}
  523. function GetFileTime(h : longint;creation,lastaccess,lastwrite : PFileTime) : longbool;
  524. external 'kernel32' name 'GetFileTime';
  525. function SetFileTime(h : longint;creation,lastaccess,lastwrite : PFileTime) : longbool;
  526. external 'kernel32' name 'SetFileTime';
  527. function SetFileAttributes(lpFileName : pchar;dwFileAttributes : longint) : longbool;
  528. external 'kernel32' name 'SetFileAttributesA';
  529. function GetFileAttributes(lpFileName : pchar) : longint;
  530. external 'kernel32' name 'GetFileAttributesA';
  531. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  532. var
  533. dotpos,p1,i : longint;
  534. begin
  535. { allow slash as backslash }
  536. for i:=1 to length(path) do
  537. if path[i]='/' then path[i]:='\';
  538. { get drive name }
  539. p1:=pos(':',path);
  540. if p1>0 then
  541. begin
  542. dir:=path[1]+':';
  543. delete(path,1,p1);
  544. end
  545. else
  546. dir:='';
  547. { split the path and the name, there are no more path informtions }
  548. { if path contains no backslashes }
  549. while true do
  550. begin
  551. p1:=pos('\',path);
  552. if p1=0 then
  553. break;
  554. dir:=dir+copy(path,1,p1);
  555. delete(path,1,p1);
  556. end;
  557. { try to find out a extension }
  558. Ext:='';
  559. i:=Length(Path);
  560. DotPos:=256;
  561. While (i>0) Do
  562. Begin
  563. If (Path[i]='.') Then
  564. begin
  565. DotPos:=i;
  566. break;
  567. end;
  568. Dec(i);
  569. end;
  570. Ext:=Copy(Path,DotPos,255);
  571. Name:=Copy(Path,1,DotPos - 1);
  572. end;
  573. { <immobilizer> }
  574. function GetFullPathName(lpFileName: PChar; nBufferLength: Longint; lpBuffer: PChar; var lpFilePart : PChar):DWORD;
  575. external 'kernel32' name 'GetFullPathNameA';
  576. function GetShortPathName(lpszLongPath:pchar; lpszShortPath:pchar; cchBuffer:DWORD):DWORD;
  577. external 'kernel32' name 'GetShortPathNameA';
  578. (*
  579. function FExpand (const Path: PathStr): PathStr;
  580. - declared in fexpand.inc
  581. *)
  582. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  583. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  584. {$I fexpand.inc}
  585. {$UNDEF FPC_FEXPAND_DRIVES}
  586. {$UNDEF FPC_FEXPAND_UNC}
  587. function SearchPath(lpPath : PChar; lpFileName : PChar; lpExtension : PChar; nBufferLength : Longint; lpBuffer : PChar;
  588. var lpFilePart : PChar) : Longint; external 'kernel32' name 'SearchPathA';
  589. Function FSearch(path: pathstr; dirlist: string): pathstr;
  590. var temp : PChar;
  591. value : Array [0..255] of char;
  592. i : Longint;
  593. dir,dir2 : dirstr;
  594. lastchar : char;
  595. name : namestr;
  596. ext : extstr;
  597. s : SearchRec;
  598. found : boolean;
  599. begin
  600. { check if the file specified exists }
  601. findfirst(path,anyfile,s);
  602. found:=(doserror=0);
  603. findclose(s);
  604. if found then
  605. begin
  606. fsearch:=path;
  607. exit;
  608. end;
  609. { search the path }
  610. fsearch:='';
  611. for i:=1 to length(path) do
  612. if path[i]='/' then
  613. path[i]:='\';
  614. fsplit(path,dir,name,ext);
  615. for i:=1 to length(dirlist) do
  616. if dirlist[i]='/' then
  617. dirlist[i]:='\';
  618. { allow slash as backslash }
  619. StringToPchar(name);
  620. StringToPchar(ext);
  621. StringToPchar(dir);
  622. if SearchPath(@dir, @name, @ext, 255, @value, temp)>0 then
  623. begin
  624. fsearch := strpas(value);
  625. exit;
  626. end;
  627. PCharToString(dir);
  628. repeat
  629. i:=pos(';',dirlist);
  630. while i=1 do
  631. begin
  632. delete(dirlist,1,1);
  633. i:=pos(';',dirlist);
  634. end;
  635. if i=0 then
  636. begin
  637. dir2:=dirlist;
  638. dirlist:='';
  639. end
  640. else
  641. begin
  642. dir2:=Copy(dirlist,1,i-1);
  643. dirlist:=Copy(dirlist,i+1,255);
  644. end;
  645. { don't add anything if dir2 is empty string }
  646. if dir2<>'' then
  647. lastchar:=dir2[length(dir2)]
  648. else
  649. lastchar:='\';
  650. if (lastchar<>'\') and (lastchar<>':') then
  651. dir2:=dir2+'\'+dir
  652. else
  653. dir2:=dir2+dir;
  654. StringToPchar(dir2);
  655. if SearchPath(@dir2, @name, @ext, 255, @value, temp)>0 then
  656. begin
  657. fsearch := strpas(value);
  658. exit;
  659. end;
  660. until dirlist='';
  661. end;
  662. { </immobilizer> }
  663. procedure getftime(var f;var time : longint);
  664. var
  665. ft : TFileTime;
  666. begin
  667. if GetFileTime(filerec(f).Handle,nil,nil,@ft) and
  668. WinToDosTime(ft,time) then
  669. exit
  670. else
  671. time:=0;
  672. end;
  673. procedure setftime(var f;time : longint);
  674. var
  675. ft : TFileTime;
  676. begin
  677. if DosToWinTime(time,ft) then
  678. SetFileTime(filerec(f).Handle,nil,nil,@ft);
  679. end;
  680. procedure getfattr(var f;var attr : word);
  681. var
  682. l : longint;
  683. begin
  684. doserror:=0;
  685. l:=GetFileAttributes(filerec(f).name);
  686. if l=longint($ffffffff) then
  687. begin
  688. doserror:=getlasterror;
  689. attr:=0;
  690. end
  691. else
  692. attr:=l and $ffff;
  693. end;
  694. procedure setfattr(var f;attr : word);
  695. begin
  696. doserror:=0;
  697. if not(SetFileAttributes(filerec(f).name,attr)) then
  698. doserror:=getlasterror;
  699. end;
  700. { change to short filename if successful win32 call PM }
  701. function GetShortName(var p : String) : boolean;
  702. var
  703. buffer : array[0..255] of char;
  704. ret : longint;
  705. begin
  706. {we can't mess with p, because we have to return it if call is
  707. unsuccesfully.}
  708. if Length(p)>0 then {copy p to array of char}
  709. move(p[1],buffer[0],length(p));
  710. buffer[length(p)]:=chr(0);
  711. {Should return value load loaddoserror?}
  712. ret:=GetShortPathName(@buffer,@buffer,255);
  713. if ret=0 then
  714. p:=strpas(buffer);
  715. GetShortName:=ret<>0;
  716. end;
  717. { change to long filename if successful DOS call PM }
  718. function GetLongName(var p : String) : boolean;
  719. var
  720. lfn,sfn : array[0..255] of char;
  721. filename : pchar;
  722. ret : longint;
  723. begin
  724. {contrary to shortname, SDK does not mention input buffer can be equal
  725. to output.}
  726. if Length(p)>0 then {copy p to array of char}
  727. move(p[1],sfn[0],length(p));
  728. sfn[length(p)]:=chr(0);
  729. fillchar(lfn,sizeof(lfn),#0);
  730. filename:=nil;
  731. {Should return value load loaddoserror?}
  732. ret:=GetFullPathName(@sfn,255,@lfn,filename);
  733. if ret=0 then
  734. p:=strpas(lfn); {lfn here returns full path, filename only fn}
  735. GetLongName:=ret<>0;
  736. end;
  737. {******************************************************************************
  738. --- Environment ---
  739. ******************************************************************************}
  740. {
  741. The environment is a block of zero terminated strings
  742. terminated by a #0
  743. }
  744. function GetEnvironmentStrings : pchar;
  745. external 'kernel32' name 'GetEnvironmentStringsA';
  746. function FreeEnvironmentStrings(p : pchar) : longbool;
  747. external 'kernel32' name 'FreeEnvironmentStringsA';
  748. function envcount : longint;
  749. var
  750. hp,p : pchar;
  751. count : longint;
  752. begin
  753. p:=GetEnvironmentStrings;
  754. hp:=p;
  755. count:=0;
  756. while hp^<>#0 do
  757. begin
  758. { next string entry}
  759. hp:=hp+strlen(hp)+1;
  760. inc(count);
  761. end;
  762. FreeEnvironmentStrings(p);
  763. envcount:=count;
  764. end;
  765. Function EnvStr(index: integer): string;
  766. var
  767. hp,p : pchar;
  768. count,i : longint;
  769. begin
  770. { envcount takes some time in win32 }
  771. count:=envcount;
  772. { range checking }
  773. if (index<=0) or (index>count) then
  774. begin
  775. envstr:='';
  776. exit;
  777. end;
  778. p:=GetEnvironmentStrings;
  779. hp:=p;
  780. { retrive the string with the given index }
  781. for i:=2 to index do
  782. hp:=hp+strlen(hp)+1;
  783. envstr:=strpas(hp);
  784. FreeEnvironmentStrings(p);
  785. end;
  786. Function GetEnv(envvar: string): string;
  787. var
  788. s : string;
  789. i : longint;
  790. hp,p : pchar;
  791. begin
  792. getenv:='';
  793. p:=GetEnvironmentStrings;
  794. hp:=p;
  795. while hp^<>#0 do
  796. begin
  797. s:=strpas(hp);
  798. i:=pos('=',s);
  799. if upcase(copy(s,1,i-1))=upcase(envvar) then
  800. begin
  801. getenv:=copy(s,i+1,length(s)-i);
  802. break;
  803. end;
  804. { next string entry}
  805. hp:=hp+strlen(hp)+1;
  806. end;
  807. FreeEnvironmentStrings(p);
  808. end;
  809. {******************************************************************************
  810. --- Not Supported ---
  811. ******************************************************************************}
  812. Procedure keep(exitcode : word);
  813. Begin
  814. End;
  815. Procedure getintvec(intno : byte;var vector : pointer);
  816. Begin
  817. End;
  818. Procedure setintvec(intno : byte;vector : pointer);
  819. Begin
  820. End;
  821. function FreeLibrary(hLibModule : THANDLE) : longbool;
  822. external 'kernel32' name 'FreeLibrary';
  823. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  824. external 'kernel32' name 'GetVersionExA';
  825. function LoadLibrary(lpLibFileName : pchar):THandle;
  826. external 'kernel32' name 'LoadLibraryA';
  827. function GetProcAddress(hModule : THandle;lpProcName : pchar) : pointer;
  828. external 'kernel32' name 'GetProcAddress';
  829. var
  830. oldexitproc : pointer;
  831. procedure dosexitproc;
  832. begin
  833. exitproc:=oldexitproc;
  834. if kernel32dll<>0 then
  835. FreeLibrary(kernel32dll);
  836. end;
  837. begin
  838. oldexitproc:=exitproc;
  839. exitproc:=@dosexitproc;
  840. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  841. GetVersionEx(versioninfo);
  842. kernel32dll:=0;
  843. GetDiskFreeSpaceEx:=nil;
  844. if ((versioninfo.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS) and
  845. (versioninfo.dwBuildNUmber>=1000)) or
  846. (versioninfo.dwPlatformId=VER_PLATFORM_WIN32_NT) then
  847. begin
  848. kernel32dll:=LoadLibrary('kernel32');
  849. if kernel32dll<>0 then
  850. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  851. end;
  852. end.
  853. {
  854. $Log$
  855. Revision 1.11 2001-11-23 01:35:09 carl
  856. * Range check error fix
  857. Revision 1.10 2001/11/23 00:36:26 carl
  858. * updated behavior of some routines to conform to docs
  859. Revision 1.9 2001/06/13 22:21:53 hajny
  860. + platform specific information
  861. Revision 1.8 2001/03/16 20:09:58 hajny
  862. * universal FExpand
  863. Revision 1.7 2000/12/18 17:28:58 jonas
  864. * fixed range check errors
  865. Revision 1.6 2000/09/06 20:47:34 peter
  866. * removed previous fsplit() patch as it's not the correct behaviour for
  867. LFNs. The code showing the bug could easily be adapted (merged)
  868. Revision 1.5 2000/09/04 20:17:54 peter
  869. * fixed previous commit (merged)
  870. Revision 1.4 2000/09/04 19:38:13 peter
  871. * fsplit with .. fix from Thomas (merged)
  872. Revision 1.3 2000/08/24 19:02:36 peter
  873. * fsearch checks if file exists first (merged)
  874. Revision 1.2 2000/07/13 11:33:57 michael
  875. + removed logs
  876. }