dos.pp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  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. F.W32FindData.dwFileAttributes:=DosToWinAttr(f.attr);
  514. While (F.W32FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  515. begin
  516. if not FindNextFile (F.FindHandle,F.W32FindData) then
  517. begin
  518. DosError:=Last2DosError(GetLastError);
  519. if DosError=2 then
  520. DosError:=18;
  521. exit;
  522. end;
  523. end;
  524. { Convert some attributes back }
  525. f.size:=F.W32FindData.NFileSizeLow;
  526. f.attr:=WinToDosAttr(F.W32FindData.dwFileAttributes);
  527. WinToDosTime(F.W32FindData.ftLastWriteTime,f.Time);
  528. f.Name:=StrPas(@F.W32FindData.cFileName);
  529. end;
  530. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  531. begin
  532. { no error }
  533. doserror:=0;
  534. F.Name:=Path;
  535. F.Attr:=attr;
  536. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  537. StringToPchar(f.name);
  538. { FindFirstFile is a Win32 Call }
  539. F.W32FindData.dwFileAttributes:=DosToWinAttr(f.attr);
  540. F.FindHandle:=FindFirstFile (pchar(@f.Name),F.W32FindData);
  541. f.attr:=WinToDosAttr(F.W32FindData.dwFileAttributes);
  542. If longint(F.FindHandle)=Invalid_Handle_value then
  543. begin
  544. DosError:=Last2DosError(GetLastError);
  545. if DosError=2 then
  546. DosError:=18;
  547. exit;
  548. end;
  549. { Find file with correct attribute }
  550. FindMatch(f);
  551. end;
  552. procedure findnext(var f : searchRec);
  553. begin
  554. { no error }
  555. doserror:=0;
  556. if not FindNextFile (F.FindHandle,F.W32FindData) then
  557. begin
  558. DosError:=Last2DosError(GetLastError);
  559. if DosError=2 then
  560. DosError:=18;
  561. exit;
  562. end;
  563. { Find file with correct attribute }
  564. FindMatch(f);
  565. end;
  566. procedure swapvectors;
  567. begin
  568. end;
  569. Procedure FindClose(Var f: SearchRec);
  570. begin
  571. If longint(F.FindHandle)<>Invalid_Handle_value then
  572. FindCloseFile(F.FindHandle);
  573. end;
  574. {******************************************************************************
  575. --- File ---
  576. ******************************************************************************}
  577. function GeTWin32FileTime(h : longint;creation,lastaccess,lastwrite : PWin32FileTime) : longbool;
  578. stdcall; external 'kernel32' name 'GetFileTime';
  579. function SeTWin32FileTime(h : longint;creation,lastaccess,lastwrite : PWin32FileTime) : longbool;
  580. stdcall; external 'kernel32' name 'SetFileTime';
  581. function SetFileAttributes(lpFileName : pchar;dwFileAttributes : longint) : longbool;
  582. stdcall; external 'kernel32' name 'SetFileAttributesA';
  583. function GetFileAttributes(lpFileName : pchar) : longint;
  584. stdcall; external 'kernel32' name 'GetFileAttributesA';
  585. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  586. var
  587. dotpos,p1,i : longint;
  588. begin
  589. { allow slash as backslash }
  590. for i:=1 to length(path) do
  591. if path[i]='/' then path[i]:='\';
  592. { get drive name }
  593. p1:=pos(':',path);
  594. if p1>0 then
  595. begin
  596. dir:=path[1]+':';
  597. delete(path,1,p1);
  598. end
  599. else
  600. dir:='';
  601. { split the path and the name, there are no more path informtions }
  602. { if path contains no backslashes }
  603. while true do
  604. begin
  605. p1:=pos('\',path);
  606. if p1=0 then
  607. break;
  608. dir:=dir+copy(path,1,p1);
  609. delete(path,1,p1);
  610. end;
  611. { try to find out a extension }
  612. Ext:='';
  613. i:=Length(Path);
  614. DotPos:=256;
  615. While (i>0) Do
  616. Begin
  617. If (Path[i]='.') Then
  618. begin
  619. DotPos:=i;
  620. break;
  621. end;
  622. Dec(i);
  623. end;
  624. Ext:=Copy(Path,DotPos,255);
  625. Name:=Copy(Path,1,DotPos - 1);
  626. end;
  627. { <immobilizer> }
  628. function GetFullPathName(lpFileName: PChar; nBufferLength: Longint; lpBuffer: PChar; var lpFilePart : PChar):DWORD;
  629. stdcall; external 'kernel32' name 'GetFullPathNameA';
  630. function GetShortPathName(lpszLongPath:pchar; lpszShortPath:pchar; cchBuffer:DWORD):DWORD;
  631. stdcall; external 'kernel32' name 'GetShortPathNameA';
  632. (*
  633. function FExpand (const Path: PathStr): PathStr;
  634. - declared in fexpand.inc
  635. *)
  636. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  637. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  638. {$I fexpand.inc}
  639. {$UNDEF FPC_FEXPAND_DRIVES}
  640. {$UNDEF FPC_FEXPAND_UNC}
  641. Function FSearch(path: pathstr; dirlist: string): pathstr;
  642. var
  643. i,p1 : longint;
  644. s : searchrec;
  645. newdir : pathstr;
  646. begin
  647. { check if the file specified exists }
  648. findfirst(path,anyfile and not(directory),s);
  649. if doserror=0 then
  650. begin
  651. findclose(s);
  652. fsearch:=path;
  653. exit;
  654. end;
  655. { No wildcards allowed in these things }
  656. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  657. fsearch:=''
  658. else
  659. begin
  660. { allow slash as backslash }
  661. for i:=1 to length(dirlist) do
  662. if dirlist[i]='/' then dirlist[i]:='\';
  663. repeat
  664. p1:=pos(';',dirlist);
  665. if p1<>0 then
  666. begin
  667. newdir:=copy(dirlist,1,p1-1);
  668. delete(dirlist,1,p1);
  669. end
  670. else
  671. begin
  672. newdir:=dirlist;
  673. dirlist:='';
  674. end;
  675. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  676. newdir:=newdir+'\';
  677. findfirst(newdir+path,anyfile and not(directory),s);
  678. if doserror=0 then
  679. newdir:=newdir+path
  680. else
  681. newdir:='';
  682. until (dirlist='') or (newdir<>'');
  683. fsearch:=newdir;
  684. end;
  685. findclose(s);
  686. end;
  687. { </immobilizer> }
  688. procedure getftime(var f;var time : longint);
  689. var
  690. ft : TWin32FileTime;
  691. begin
  692. doserror:=0;
  693. if GeTWin32FileTime(filerec(f).Handle,nil,nil,@ft) and
  694. WinToDosTime(ft,time) then
  695. exit
  696. else
  697. begin
  698. DosError:=Last2DosError(GetLastError);
  699. time:=0;
  700. end;
  701. end;
  702. procedure setftime(var f;time : longint);
  703. var
  704. ft : TWin32FileTime;
  705. begin
  706. doserror:=0;
  707. if DosToWinTime(time,ft) and
  708. SeTWin32FileTime(filerec(f).Handle,nil,nil,@ft) then
  709. exit
  710. else
  711. DosError:=Last2DosError(GetLastError);
  712. end;
  713. procedure getfattr(var f;var attr : word);
  714. var
  715. l : longint;
  716. begin
  717. doserror:=0;
  718. l:=GetFileAttributes(filerec(f).name);
  719. if l=longint($ffffffff) then
  720. begin
  721. doserror:=getlasterror;
  722. attr:=0;
  723. end
  724. else
  725. attr:=l and $ffff;
  726. end;
  727. procedure setfattr(var f;attr : word);
  728. begin
  729. { Fail for setting VolumeId }
  730. if (attr and VolumeID)<>0 then
  731. doserror:=5
  732. else
  733. if SetFileAttributes(filerec(f).name,attr) then
  734. doserror:=0
  735. else
  736. doserror:=getlasterror;
  737. end;
  738. { change to short filename if successful win32 call PM }
  739. function GetShortName(var p : String) : boolean;
  740. var
  741. buffer : array[0..255] of char;
  742. ret : longint;
  743. begin
  744. {we can't mess with p, because we have to return it if call is
  745. unsuccesfully.}
  746. if Length(p)>0 then {copy p to array of char}
  747. move(p[1],buffer[0],length(p));
  748. buffer[length(p)]:=chr(0);
  749. {Should return value load loaddoserror?}
  750. ret:=GetShortPathName(@buffer,@buffer,255);
  751. if ret=0 then
  752. p:=strpas(buffer);
  753. GetShortName:=ret<>0;
  754. end;
  755. { change to long filename if successful DOS call PM }
  756. function GetLongName(var p : String) : boolean;
  757. var
  758. lfn,sfn : array[0..255] of char;
  759. filename : pchar;
  760. ret : longint;
  761. begin
  762. {contrary to shortname, SDK does not mention input buffer can be equal
  763. to output.}
  764. if Length(p)>0 then {copy p to array of char}
  765. move(p[1],sfn[0],length(p));
  766. sfn[length(p)]:=chr(0);
  767. fillchar(lfn,sizeof(lfn),#0);
  768. filename:=nil;
  769. {Should return value load loaddoserror?}
  770. ret:=GetFullPathName(@sfn,255,@lfn,filename);
  771. if ret=0 then
  772. p:=strpas(lfn); {lfn here returns full path, filename only fn}
  773. GetLongName:=ret<>0;
  774. end;
  775. {******************************************************************************
  776. --- Environment ---
  777. ******************************************************************************}
  778. {
  779. The environment is a block of zero terminated strings
  780. terminated by a #0
  781. }
  782. function GetEnvironmentStrings : pchar;
  783. stdcall; external 'kernel32' name 'GetEnvironmentStringsA';
  784. function FreeEnvironmentStrings(p : pchar) : longbool;
  785. stdcall; external 'kernel32' name 'FreeEnvironmentStringsA';
  786. function envcount : longint;
  787. var
  788. hp,p : pchar;
  789. count : longint;
  790. begin
  791. p:=GetEnvironmentStrings;
  792. hp:=p;
  793. count:=0;
  794. while hp^<>#0 do
  795. begin
  796. { next string entry}
  797. hp:=hp+strlen(hp)+1;
  798. inc(count);
  799. end;
  800. FreeEnvironmentStrings(p);
  801. envcount:=count;
  802. end;
  803. Function EnvStr(index: integer): string;
  804. var
  805. hp,p : pchar;
  806. count,i : longint;
  807. begin
  808. { envcount takes some time in win32 }
  809. count:=envcount;
  810. { range checking }
  811. if (index<=0) or (index>count) then
  812. begin
  813. envstr:='';
  814. exit;
  815. end;
  816. p:=GetEnvironmentStrings;
  817. hp:=p;
  818. { retrive the string with the given index }
  819. for i:=2 to index do
  820. hp:=hp+strlen(hp)+1;
  821. envstr:=strpas(hp);
  822. FreeEnvironmentStrings(p);
  823. end;
  824. Function GetEnv(envvar: string): string;
  825. var
  826. s : string;
  827. i : longint;
  828. hp,p : pchar;
  829. begin
  830. getenv:='';
  831. p:=GetEnvironmentStrings;
  832. hp:=p;
  833. while hp^<>#0 do
  834. begin
  835. s:=strpas(hp);
  836. i:=pos('=',s);
  837. if upcase(copy(s,1,i-1))=upcase(envvar) then
  838. begin
  839. getenv:=copy(s,i+1,length(s)-i);
  840. break;
  841. end;
  842. { next string entry}
  843. hp:=hp+strlen(hp)+1;
  844. end;
  845. FreeEnvironmentStrings(p);
  846. end;
  847. {******************************************************************************
  848. --- Not Supported ---
  849. ******************************************************************************}
  850. Procedure keep(exitcode : word);
  851. Begin
  852. End;
  853. Procedure getintvec(intno : byte;var vector : pointer);
  854. Begin
  855. End;
  856. Procedure setintvec(intno : byte;vector : pointer);
  857. Begin
  858. End;
  859. function FreeLibrary(hLibModule : TWin32Handle) : longbool;
  860. stdcall; external 'kernel32' name 'FreeLibrary';
  861. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  862. stdcall; external 'kernel32' name 'GetVersionExA';
  863. function LoadLibrary(lpLibFileName : pchar):TWin32Handle;
  864. stdcall; external 'kernel32' name 'LoadLibraryA';
  865. function GetProcAddress(hModule : TWin32Handle;lpProcName : pchar) : pointer;
  866. stdcall; external 'kernel32' name 'GetProcAddress';
  867. var
  868. oldexitproc : pointer;
  869. procedure dosexitproc;
  870. begin
  871. exitproc:=oldexitproc;
  872. if kernel32dll<>0 then
  873. FreeLibrary(kernel32dll);
  874. end;
  875. begin
  876. oldexitproc:=exitproc;
  877. exitproc:=@dosexitproc;
  878. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  879. GetVersionEx(versioninfo);
  880. kernel32dll:=0;
  881. GetDiskFreeSpaceEx:=nil;
  882. if ((versioninfo.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS) and
  883. (versioninfo.dwBuildNUmber>=1000)) or
  884. (versioninfo.dwPlatformId=VER_PLATFORM_WIN32_NT) then
  885. begin
  886. kernel32dll:=LoadLibrary('kernel32');
  887. if kernel32dll<>0 then
  888. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  889. end;
  890. end.
  891. {
  892. $Log$
  893. Revision 1.22 2004-01-06 00:58:35 florian
  894. * fixed fsearch
  895. Revision 1.21 2003/10/27 15:27:47 peter
  896. * fixed setfattr with volumeid
  897. Revision 1.20 2003/09/17 15:06:36 peter
  898. * stdcall patch
  899. Revision 1.19 2003/06/10 11:16:15 jonas
  900. * fix from Peter
  901. Revision 1.18 2002/12/24 15:35:15 peter
  902. * error code fixes
  903. Revision 1.17 2002/12/15 20:23:53 peter
  904. * map error 87 to 13 to be compatible with dos
  905. Revision 1.16 2002/12/04 21:35:50 carl
  906. * bugfixes for dos.exec() : it would not be able to execute 16-bit apps
  907. * doserror was not reset to zero in dos.exec
  908. Revision 1.15 2002/12/03 20:39:14 carl
  909. * fix for dos.exec with non-microsoft shells
  910. Revision 1.14 2002/09/07 16:01:28 peter
  911. * old logs removed and tabs fixed
  912. Revision 1.13 2002/07/06 11:48:09 carl
  913. + fsearch bugfix for Win9X systems
  914. Revision 1.12 2002/05/16 19:32:57 carl
  915. * fix range check error
  916. }