dos.pp 28 KB

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