dos.pp 26 KB

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