dos.pp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  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. CommandLine : array[0..511] of char;
  314. AppParam : array[0..255] of char;
  315. SpacePos : integer;
  316. pathlocal : string;
  317. begin
  318. DosError := 0;
  319. FillChar(SI, SizeOf(SI), 0);
  320. SI.cb:=SizeOf(SI);
  321. SI.wShowWindow:=1;
  322. { always surroound the name of the application by quotes
  323. so that long filenames will always be accepted. But don't
  324. do it if there are already double quotes, since Win32 does not
  325. like double quotes which are duplicated!
  326. }
  327. if pos('"',path) = 0 then
  328. pathlocal:='"'+path+'"'
  329. else
  330. pathlocal := path;
  331. Move(Pathlocal[1],CommandLine,length(Pathlocal));
  332. AppParam[0]:=' ';
  333. AppParam[1]:=' ';
  334. Move(ComLine[1],AppParam[2],length(Comline));
  335. AppParam[Length(ComLine)+2]:=#0;
  336. { concatenate both pathnames }
  337. Move(Appparam[0],CommandLine[length(Pathlocal)],strlen(Appparam)+1);
  338. if not CreateProcess(nil, PChar(@CommandLine),
  339. Nil, Nil, ExecInheritsHandles,$20, Nil, Nil, SI, PI) then
  340. begin
  341. DosError:=Last2DosError(GetLastError);
  342. exit;
  343. end;
  344. Proc:=PI.hProcess;
  345. CloseHandle(PI.hThread);
  346. if WaitForSingleObject(Proc, dword(Infinite)) <> $ffffffff then
  347. GetExitCodeProcess(Proc,l)
  348. else
  349. l:=-1;
  350. CloseHandle(Proc);
  351. LastDosExitCode:=l;
  352. end;
  353. function dosexitcode : word;
  354. begin
  355. dosexitcode:=lastdosexitcode and $ffff;
  356. end;
  357. procedure getcbreak(var breakvalue : boolean);
  358. begin
  359. { !! No Win32 Function !! }
  360. breakvalue := true;
  361. end;
  362. procedure setcbreak(breakvalue : boolean);
  363. begin
  364. { !! No Win32 Function !! }
  365. end;
  366. procedure getverify(var verify : boolean);
  367. begin
  368. { !! No Win32 Function !! }
  369. verify := true;
  370. end;
  371. procedure setverify(verify : boolean);
  372. begin
  373. { !! No Win32 Function !! }
  374. end;
  375. {******************************************************************************
  376. --- Disk ---
  377. ******************************************************************************}
  378. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  379. freeclusters,totalclusters:longint):longbool;
  380. external 'kernel32' name 'GetDiskFreeSpaceA';
  381. type
  382. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,
  383. total,free):longbool;stdcall;
  384. var
  385. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  386. function diskfree(drive : byte) : int64;
  387. var
  388. disk : array[1..4] of char;
  389. secs,bytes,
  390. free,total : longint;
  391. qwtotal,qwfree,qwcaller : int64;
  392. begin
  393. if drive=0 then
  394. begin
  395. disk[1]:='\';
  396. disk[2]:=#0;
  397. end
  398. else
  399. begin
  400. disk[1]:=chr(drive+64);
  401. disk[2]:=':';
  402. disk[3]:='\';
  403. disk[4]:=#0;
  404. end;
  405. if assigned(GetDiskFreeSpaceEx) then
  406. begin
  407. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  408. diskfree:=qwfree
  409. else
  410. diskfree:=-1;
  411. end
  412. else
  413. begin
  414. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  415. diskfree:=int64(free)*secs*bytes
  416. else
  417. diskfree:=-1;
  418. end;
  419. end;
  420. function disksize(drive : byte) : int64;
  421. var
  422. disk : array[1..4] of char;
  423. secs,bytes,
  424. free,total : longint;
  425. qwtotal,qwfree,qwcaller : int64;
  426. begin
  427. if drive=0 then
  428. begin
  429. disk[1]:='\';
  430. disk[2]:=#0;
  431. end
  432. else
  433. begin
  434. disk[1]:=chr(drive+64);
  435. disk[2]:=':';
  436. disk[3]:='\';
  437. disk[4]:=#0;
  438. end;
  439. if assigned(GetDiskFreeSpaceEx) then
  440. begin
  441. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  442. disksize:=qwtotal
  443. else
  444. disksize:=-1;
  445. end
  446. else
  447. begin
  448. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  449. disksize:=int64(total)*secs*bytes
  450. else
  451. disksize:=-1;
  452. end;
  453. end;
  454. {******************************************************************************
  455. --- Findfirst FindNext ---
  456. ******************************************************************************}
  457. { Needed kernel calls }
  458. function FindFirstFile (lpFileName: PChar; var lpFindFileData: TWIN32FindData): THandle;
  459. external 'kernel32' name 'FindFirstFileA';
  460. function FindNextFile (hFindFile: THandle; var lpFindFileData: TWIN32FindData): LongBool;
  461. external 'kernel32' name 'FindNextFileA';
  462. function FindCloseFile (hFindFile: THandle): LongBool;
  463. external 'kernel32' name 'FindClose';
  464. Procedure StringToPchar (Var S : String);
  465. Var L : Longint;
  466. begin
  467. L:=ord(S[0]);
  468. Move (S[1],S[0],L);
  469. S[L]:=#0;
  470. end;
  471. Procedure PCharToString (Var S : String);
  472. Var L : Longint;
  473. begin
  474. L:=strlen(pchar(@S[0]));
  475. Move (S[0],S[1],L);
  476. S[0]:=char(l);
  477. end;
  478. procedure FindMatch(var f:searchrec);
  479. begin
  480. { Find file with correct attribute }
  481. While (F.W32FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  482. begin
  483. if not FindNextFile (F.FindHandle,F.W32FindData) then
  484. begin
  485. DosError:=Last2DosError(GetLastError);
  486. exit;
  487. end;
  488. end;
  489. { Convert some attributes back }
  490. f.size:=F.W32FindData.NFileSizeLow;
  491. f.attr:=WinToDosAttr(F.W32FindData.dwFileAttributes);
  492. WinToDosTime(F.W32FindData.ftLastWriteTime,f.Time);
  493. f.Name:=StrPas(@F.W32FindData.cFileName);
  494. end;
  495. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  496. begin
  497. { no error }
  498. doserror:=0;
  499. F.Name:=Path;
  500. F.Attr:=attr;
  501. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  502. StringToPchar(f.name);
  503. { FindFirstFile is a Win32 Call }
  504. F.FindHandle:=FindFirstFile (pchar(@f.Name),F.W32FindData);
  505. If longint(F.FindHandle)=Invalid_Handle_value then
  506. begin
  507. DosError:=Last2DosError(GetLastError);
  508. exit;
  509. end;
  510. { Find file with correct attribute }
  511. FindMatch(f);
  512. end;
  513. procedure findnext(var f : searchRec);
  514. begin
  515. { no error }
  516. doserror:=0;
  517. if not FindNextFile (F.FindHandle,F.W32FindData) then
  518. begin
  519. DosError:=Last2DosError(GetLastError);
  520. exit;
  521. end;
  522. { Find file with correct attribute }
  523. FindMatch(f);
  524. end;
  525. procedure swapvectors;
  526. begin
  527. end;
  528. Procedure FindClose(Var f: SearchRec);
  529. begin
  530. If longint(F.FindHandle)<>Invalid_Handle_value then
  531. FindCloseFile(F.FindHandle);
  532. end;
  533. {******************************************************************************
  534. --- File ---
  535. ******************************************************************************}
  536. function GetFileTime(h : longint;creation,lastaccess,lastwrite : PFileTime) : longbool;
  537. external 'kernel32' name 'GetFileTime';
  538. function SetFileTime(h : longint;creation,lastaccess,lastwrite : PFileTime) : longbool;
  539. external 'kernel32' name 'SetFileTime';
  540. function SetFileAttributes(lpFileName : pchar;dwFileAttributes : longint) : longbool;
  541. external 'kernel32' name 'SetFileAttributesA';
  542. function GetFileAttributes(lpFileName : pchar) : longint;
  543. external 'kernel32' name 'GetFileAttributesA';
  544. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  545. var
  546. dotpos,p1,i : longint;
  547. begin
  548. { allow slash as backslash }
  549. for i:=1 to length(path) do
  550. if path[i]='/' then path[i]:='\';
  551. { get drive name }
  552. p1:=pos(':',path);
  553. if p1>0 then
  554. begin
  555. dir:=path[1]+':';
  556. delete(path,1,p1);
  557. end
  558. else
  559. dir:='';
  560. { split the path and the name, there are no more path informtions }
  561. { if path contains no backslashes }
  562. while true do
  563. begin
  564. p1:=pos('\',path);
  565. if p1=0 then
  566. break;
  567. dir:=dir+copy(path,1,p1);
  568. delete(path,1,p1);
  569. end;
  570. { try to find out a extension }
  571. Ext:='';
  572. i:=Length(Path);
  573. DotPos:=256;
  574. While (i>0) Do
  575. Begin
  576. If (Path[i]='.') Then
  577. begin
  578. DotPos:=i;
  579. break;
  580. end;
  581. Dec(i);
  582. end;
  583. Ext:=Copy(Path,DotPos,255);
  584. Name:=Copy(Path,1,DotPos - 1);
  585. end;
  586. { <immobilizer> }
  587. function GetFullPathName(lpFileName: PChar; nBufferLength: Longint; lpBuffer: PChar; var lpFilePart : PChar):DWORD;
  588. external 'kernel32' name 'GetFullPathNameA';
  589. function GetShortPathName(lpszLongPath:pchar; lpszShortPath:pchar; cchBuffer:DWORD):DWORD;
  590. external 'kernel32' name 'GetShortPathNameA';
  591. (*
  592. function FExpand (const Path: PathStr): PathStr;
  593. - declared in fexpand.inc
  594. *)
  595. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  596. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  597. {$I fexpand.inc}
  598. {$UNDEF FPC_FEXPAND_DRIVES}
  599. {$UNDEF FPC_FEXPAND_UNC}
  600. function SearchPath(lpPath : PChar; lpFileName : PChar; lpExtension : PChar; nBufferLength : Longint; lpBuffer : PChar;
  601. var lpFilePart : PChar) : Longint; external 'kernel32' name 'SearchPathA';
  602. Function FSearch(path: pathstr; dirlist: string): pathstr;
  603. var temp : PChar;
  604. value : Array [0..255] of char;
  605. i : Longint;
  606. dir,dir2 : dirstr;
  607. lastchar : char;
  608. name : namestr;
  609. ext : extstr;
  610. s : SearchRec;
  611. found : boolean;
  612. begin
  613. { check if the file specified exists }
  614. findfirst(path,anyfile,s);
  615. found:=(doserror=0);
  616. findclose(s);
  617. if found then
  618. begin
  619. fsearch:=path;
  620. exit;
  621. end;
  622. { search the path }
  623. fsearch:='';
  624. for i:=1 to length(path) do
  625. if path[i]='/' then
  626. path[i]:='\';
  627. fsplit(path,dir,name,ext);
  628. for i:=1 to length(dirlist) do
  629. if dirlist[i]='/' then
  630. dirlist[i]:='\';
  631. { bugfix here : Win98SE returns a path, when the name is NULL! }
  632. { so if the name of the file to search is '' then simply exit }
  633. { immediately (WinNT behavior is correct). }
  634. if name='' then
  635. exit;
  636. { allow slash as backslash }
  637. StringToPchar(name);
  638. StringToPchar(ext);
  639. StringToPchar(dir);
  640. if SearchPath(@dir, @name, @ext, 255, @value, temp)>0 then
  641. begin
  642. fsearch := strpas(value);
  643. exit;
  644. end;
  645. PCharToString(dir);
  646. repeat
  647. i:=pos(';',dirlist);
  648. while i=1 do
  649. begin
  650. delete(dirlist,1,1);
  651. i:=pos(';',dirlist);
  652. end;
  653. if i=0 then
  654. begin
  655. dir2:=dirlist;
  656. dirlist:='';
  657. end
  658. else
  659. begin
  660. dir2:=Copy(dirlist,1,i-1);
  661. dirlist:=Copy(dirlist,i+1,255);
  662. end;
  663. { don't add anything if dir2 is empty string }
  664. if dir2<>'' then
  665. lastchar:=dir2[length(dir2)]
  666. else
  667. lastchar:='\';
  668. if (lastchar<>'\') and (lastchar<>':') then
  669. dir2:=dir2+'\'+dir
  670. else
  671. dir2:=dir2+dir;
  672. StringToPchar(dir2);
  673. if SearchPath(@dir2, @name, @ext, 255, @value, temp)>0 then
  674. begin
  675. fsearch := strpas(value);
  676. exit;
  677. end;
  678. until dirlist='';
  679. end;
  680. { </immobilizer> }
  681. procedure getftime(var f;var time : longint);
  682. var
  683. ft : TFileTime;
  684. begin
  685. if GetFileTime(filerec(f).Handle,nil,nil,@ft) and
  686. WinToDosTime(ft,time) then
  687. exit
  688. else
  689. time:=0;
  690. end;
  691. procedure setftime(var f;time : longint);
  692. var
  693. ft : TFileTime;
  694. begin
  695. if DosToWinTime(time,ft) then
  696. SetFileTime(filerec(f).Handle,nil,nil,@ft);
  697. end;
  698. procedure getfattr(var f;var attr : word);
  699. var
  700. l : longint;
  701. begin
  702. doserror:=0;
  703. l:=GetFileAttributes(filerec(f).name);
  704. if l=longint($ffffffff) then
  705. begin
  706. doserror:=getlasterror;
  707. attr:=0;
  708. end
  709. else
  710. attr:=l and $ffff;
  711. end;
  712. procedure setfattr(var f;attr : word);
  713. begin
  714. doserror:=0;
  715. if not(SetFileAttributes(filerec(f).name,attr)) then
  716. doserror:=getlasterror;
  717. end;
  718. { change to short filename if successful win32 call PM }
  719. function GetShortName(var p : String) : boolean;
  720. var
  721. buffer : array[0..255] of char;
  722. ret : longint;
  723. begin
  724. {we can't mess with p, because we have to return it if call is
  725. unsuccesfully.}
  726. if Length(p)>0 then {copy p to array of char}
  727. move(p[1],buffer[0],length(p));
  728. buffer[length(p)]:=chr(0);
  729. {Should return value load loaddoserror?}
  730. ret:=GetShortPathName(@buffer,@buffer,255);
  731. if ret=0 then
  732. p:=strpas(buffer);
  733. GetShortName:=ret<>0;
  734. end;
  735. { change to long filename if successful DOS call PM }
  736. function GetLongName(var p : String) : boolean;
  737. var
  738. lfn,sfn : array[0..255] of char;
  739. filename : pchar;
  740. ret : longint;
  741. begin
  742. {contrary to shortname, SDK does not mention input buffer can be equal
  743. to output.}
  744. if Length(p)>0 then {copy p to array of char}
  745. move(p[1],sfn[0],length(p));
  746. sfn[length(p)]:=chr(0);
  747. fillchar(lfn,sizeof(lfn),#0);
  748. filename:=nil;
  749. {Should return value load loaddoserror?}
  750. ret:=GetFullPathName(@sfn,255,@lfn,filename);
  751. if ret=0 then
  752. p:=strpas(lfn); {lfn here returns full path, filename only fn}
  753. GetLongName:=ret<>0;
  754. end;
  755. {******************************************************************************
  756. --- Environment ---
  757. ******************************************************************************}
  758. {
  759. The environment is a block of zero terminated strings
  760. terminated by a #0
  761. }
  762. function GetEnvironmentStrings : pchar;
  763. external 'kernel32' name 'GetEnvironmentStringsA';
  764. function FreeEnvironmentStrings(p : pchar) : longbool;
  765. external 'kernel32' name 'FreeEnvironmentStringsA';
  766. function envcount : longint;
  767. var
  768. hp,p : pchar;
  769. count : longint;
  770. begin
  771. p:=GetEnvironmentStrings;
  772. hp:=p;
  773. count:=0;
  774. while hp^<>#0 do
  775. begin
  776. { next string entry}
  777. hp:=hp+strlen(hp)+1;
  778. inc(count);
  779. end;
  780. FreeEnvironmentStrings(p);
  781. envcount:=count;
  782. end;
  783. Function EnvStr(index: integer): string;
  784. var
  785. hp,p : pchar;
  786. count,i : longint;
  787. begin
  788. { envcount takes some time in win32 }
  789. count:=envcount;
  790. { range checking }
  791. if (index<=0) or (index>count) then
  792. begin
  793. envstr:='';
  794. exit;
  795. end;
  796. p:=GetEnvironmentStrings;
  797. hp:=p;
  798. { retrive the string with the given index }
  799. for i:=2 to index do
  800. hp:=hp+strlen(hp)+1;
  801. envstr:=strpas(hp);
  802. FreeEnvironmentStrings(p);
  803. end;
  804. Function GetEnv(envvar: string): string;
  805. var
  806. s : string;
  807. i : longint;
  808. hp,p : pchar;
  809. begin
  810. getenv:='';
  811. p:=GetEnvironmentStrings;
  812. hp:=p;
  813. while hp^<>#0 do
  814. begin
  815. s:=strpas(hp);
  816. i:=pos('=',s);
  817. if upcase(copy(s,1,i-1))=upcase(envvar) then
  818. begin
  819. getenv:=copy(s,i+1,length(s)-i);
  820. break;
  821. end;
  822. { next string entry}
  823. hp:=hp+strlen(hp)+1;
  824. end;
  825. FreeEnvironmentStrings(p);
  826. end;
  827. {******************************************************************************
  828. --- Not Supported ---
  829. ******************************************************************************}
  830. Procedure keep(exitcode : word);
  831. Begin
  832. End;
  833. Procedure getintvec(intno : byte;var vector : pointer);
  834. Begin
  835. End;
  836. Procedure setintvec(intno : byte;vector : pointer);
  837. Begin
  838. End;
  839. function FreeLibrary(hLibModule : THANDLE) : longbool;
  840. external 'kernel32' name 'FreeLibrary';
  841. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  842. external 'kernel32' name 'GetVersionExA';
  843. function LoadLibrary(lpLibFileName : pchar):THandle;
  844. external 'kernel32' name 'LoadLibraryA';
  845. function GetProcAddress(hModule : THandle;lpProcName : pchar) : pointer;
  846. external 'kernel32' name 'GetProcAddress';
  847. var
  848. oldexitproc : pointer;
  849. procedure dosexitproc;
  850. begin
  851. exitproc:=oldexitproc;
  852. if kernel32dll<>0 then
  853. FreeLibrary(kernel32dll);
  854. end;
  855. begin
  856. oldexitproc:=exitproc;
  857. exitproc:=@dosexitproc;
  858. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  859. GetVersionEx(versioninfo);
  860. kernel32dll:=0;
  861. GetDiskFreeSpaceEx:=nil;
  862. if ((versioninfo.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS) and
  863. (versioninfo.dwBuildNUmber>=1000)) or
  864. (versioninfo.dwPlatformId=VER_PLATFORM_WIN32_NT) then
  865. begin
  866. kernel32dll:=LoadLibrary('kernel32');
  867. if kernel32dll<>0 then
  868. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  869. end;
  870. end.
  871. {
  872. $Log$
  873. Revision 1.16 2002-12-04 21:35:50 carl
  874. * bugfixes for dos.exec() : it would not be able to execute 16-bit apps
  875. * doserror was not reset to zero in dos.exec
  876. Revision 1.15 2002/12/03 20:39:14 carl
  877. * fix for dos.exec with non-microsoft shells
  878. Revision 1.14 2002/09/07 16:01:28 peter
  879. * old logs removed and tabs fixed
  880. Revision 1.13 2002/07/06 11:48:09 carl
  881. + fsearch bugfix for Win9X systems
  882. Revision 1.12 2002/05/16 19:32:57 carl
  883. * fix range check error
  884. }