dos.pp 25 KB

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