dos.pp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team.
  4. Dos unit for BP7 compatible RTL
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$inline on}
  12. {$IFNDEF FPC_DOTTEDUNITS}
  13. unit dos;
  14. {$ENDIF FPC_DOTTEDUNITS}
  15. interface
  16. {$IFDEF FPC_DOTTEDUNITS}
  17. Uses
  18. WatcomApi.WatCom;
  19. {$ELSE FPC_DOTTEDUNITS}
  20. Uses
  21. Watcom;
  22. {$ENDIF FPC_DOTTEDUNITS}
  23. Type
  24. searchrec = packed record
  25. fill : array[1..21] of byte;
  26. attr : byte;
  27. time : longint;
  28. { reserved : word; not in DJGPP V2 }
  29. size : longint;
  30. name : string[255]; { LFN Name, DJGPP uses only [12] but more can't hurt (PFV) }
  31. end;
  32. {$DEFINE HAS_REGISTERS}
  33. Registers = Watcom.Registers;
  34. {$i dosh.inc}
  35. implementation
  36. {$IFDEF FPC_DOTTEDUNITS}
  37. uses
  38. System.Strings;
  39. {$ELSE FPC_DOTTEDUNITS}
  40. uses
  41. strings;
  42. {$ENDIF FPC_DOTTEDUNITS}
  43. {$DEFINE HAS_GETMSCOUNT}
  44. {$DEFINE HAS_INTR}
  45. {$DEFINE HAS_GETCBREAK}
  46. {$DEFINE HAS_SETCBREAK}
  47. {$DEFINE HAS_GETVERIFY}
  48. {$DEFINE HAS_SETVERIFY}
  49. {$DEFINE HAS_GETSHORTNAME}
  50. {$DEFINE HAS_GETLONGNAME}
  51. {$DEFINE HAS_GETMSCOUNT}
  52. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  53. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  54. {$I dos.inc}
  55. {******************************************************************************
  56. --- Dos Interrupt ---
  57. ******************************************************************************}
  58. var
  59. dosregs : registers;
  60. procedure LoadDosError;
  61. var
  62. r : registers;
  63. SimpleDosError : word;
  64. begin
  65. if (dosregs.flags and fcarry) <> 0 then
  66. begin
  67. { I got a extended error = 0
  68. while CarryFlag was set from Exec function }
  69. SimpleDosError:=dosregs.ax;
  70. r.eax:=$5900;
  71. r.ebx:=$0;
  72. realintr($21,r);
  73. { conversion from word to integer !!
  74. gave a Bound check error if ax is $FFFF !! PM }
  75. doserror:=integer(r.ax);
  76. case doserror of
  77. 0 : DosError:=integer(SimpleDosError);
  78. 19 : DosError:=150;
  79. 21 : DosError:=152;
  80. end;
  81. end
  82. else
  83. doserror:=0;
  84. end;
  85. procedure intr(intno : byte;var regs : registers);
  86. begin
  87. realintr(intno,regs);
  88. end;
  89. {******************************************************************************
  90. --- Info / Date / Time ---
  91. ******************************************************************************}
  92. function dosversion : word;
  93. begin
  94. dosregs.ax:=$3000;
  95. msdos(dosregs);
  96. dosversion:=dosregs.ax;
  97. end;
  98. procedure getdate(var year,month,mday,wday : word);
  99. begin
  100. dosregs.ax:=$2a00;
  101. msdos(dosregs);
  102. wday:=dosregs.al;
  103. year:=dosregs.cx;
  104. month:=dosregs.dh;
  105. mday:=dosregs.dl;
  106. end;
  107. procedure setdate(year,month,day : word);
  108. begin
  109. dosregs.cx:=year;
  110. dosregs.dh:=month;
  111. dosregs.dl:=day;
  112. dosregs.ah:=$2b;
  113. msdos(dosregs);
  114. end;
  115. procedure gettime(var hour,minute,second,sec100 : word);
  116. begin
  117. dosregs.ah:=$2c;
  118. msdos(dosregs);
  119. hour:=dosregs.ch;
  120. minute:=dosregs.cl;
  121. second:=dosregs.dh;
  122. sec100:=dosregs.dl;
  123. end;
  124. procedure settime(hour,minute,second,sec100 : word);
  125. begin
  126. dosregs.ch:=hour;
  127. dosregs.cl:=minute;
  128. dosregs.dh:=second;
  129. dosregs.dl:=sec100;
  130. dosregs.ah:=$2d;
  131. msdos(dosregs);
  132. end;
  133. function GetMsCount: int64;
  134. begin
  135. GetMsCount := int64 (MemL [$40:$6c]) * 55;
  136. end;
  137. {******************************************************************************
  138. --- Exec ---
  139. ******************************************************************************}
  140. procedure exec(const path : pathstr;const comline : comstr);
  141. type
  142. realptr = packed record
  143. ofs,seg : word;
  144. end;
  145. texecblock = packed record
  146. envseg : word;
  147. comtail : realptr;
  148. firstFCB : realptr;
  149. secondFCB : realptr;
  150. iniStack : realptr;
  151. iniCSIP : realptr;
  152. end;
  153. var
  154. current_dos_buffer_pos,
  155. arg_ofs,
  156. i,la_env,
  157. la_p,la_c,la_e,
  158. fcb1_la,fcb2_la : longint;
  159. execblock : texecblock;
  160. c,p : string;
  161. function paste_to_dos(src : string) : boolean;
  162. var
  163. c : array[0..255] of AnsiChar;
  164. begin
  165. paste_to_dos:=false;
  166. if current_dos_buffer_pos+length(src)+1>tb+tb_size then
  167. RunError(217);
  168. move(src[1],c[0],length(src));
  169. c[length(src)]:=#0;
  170. seg_move(get_ds,longint(@c),dosmemselector,current_dos_buffer_pos,length(src)+1);
  171. current_dos_buffer_pos:=current_dos_buffer_pos+length(src)+1;
  172. paste_to_dos:=true;
  173. end;
  174. begin
  175. { create command line }
  176. move(comline[0],c[1],length(comline)+1);
  177. c[length(comline)+2]:=#13;
  178. c[0]:=AnsiChar(length(comline)+2);
  179. { create path }
  180. p:=path;
  181. DoDirSeparators(p);
  182. if LFNSupport then
  183. GetShortName(p);
  184. { create buffer }
  185. la_env:=tb;
  186. while (la_env and 15)<>0 do
  187. inc(la_env);
  188. current_dos_buffer_pos:=la_env;
  189. { copy environment }
  190. for i:=1 to envcount do
  191. paste_to_dos(envstr(i));
  192. paste_to_dos(''); { adds a double zero at the end }
  193. { allow slash as backslash }
  194. la_p:=current_dos_buffer_pos;
  195. paste_to_dos(p);
  196. la_c:=current_dos_buffer_pos;
  197. paste_to_dos(c);
  198. la_e:=current_dos_buffer_pos;
  199. fcb1_la:=la_e;
  200. la_e:=la_e+16;
  201. fcb2_la:=la_e;
  202. la_e:=la_e+16;
  203. { allocate FCB see dosexec code }
  204. arg_ofs:=1;
  205. while (arg_ofs < Length (C)) and (c[arg_ofs] in [' ',#9]) do
  206. inc(arg_ofs);
  207. dosregs.ax:=$2901;
  208. dosregs.ds:=(la_c+arg_ofs) shr 4;
  209. dosregs.esi:=(la_c+arg_ofs) and 15;
  210. dosregs.es:=fcb1_la shr 4;
  211. dosregs.edi:=fcb1_la and 15;
  212. msdos(dosregs);
  213. { allocate second FCB see dosexec code }
  214. repeat
  215. inc(arg_ofs);
  216. until (Arg_Ofs >= Length (C)) or (c[arg_ofs] in [' ',#9,#13]);
  217. if (c[arg_ofs]<>#13) and (Arg_Ofs < Length (C)) then
  218. begin
  219. repeat
  220. inc(arg_ofs);
  221. until (Arg_Ofs > Length (C)) or not (c[arg_ofs] in [' ',#9]);
  222. end;
  223. dosregs.ax:=$2901;
  224. dosregs.ds:=(la_c+arg_ofs) shr 4;
  225. dosregs.si:=(la_c+arg_ofs) and 15;
  226. dosregs.es:=fcb2_la shr 4;
  227. dosregs.di:=fcb2_la and 15;
  228. msdos(dosregs);
  229. with execblock do
  230. begin
  231. envseg:=la_env shr 4;
  232. comtail.seg:=la_c shr 4;
  233. comtail.ofs:=la_c and 15;
  234. firstFCB.seg:=fcb1_la shr 4;
  235. firstFCB.ofs:=fcb1_la and 15;
  236. secondFCB.seg:=fcb2_la shr 4;
  237. secondFCB.ofs:=fcb2_la and 15;
  238. end;
  239. seg_move(get_ds,longint(@execblock),dosmemselector,la_e,sizeof(texecblock));
  240. dosregs.edx:=la_p and 15;
  241. dosregs.ds:=la_p shr 4;
  242. dosregs.ebx:=la_e and 15;
  243. dosregs.es:=la_e shr 4;
  244. dosregs.ax:=$4b00;
  245. msdos(dosregs);
  246. LoadDosError;
  247. if DosError=0 then
  248. begin
  249. dosregs.ax:=$4d00;
  250. msdos(dosregs);
  251. LastDosExitCode:=DosRegs.al
  252. end
  253. else
  254. LastDosExitCode:=0;
  255. end;
  256. procedure getcbreak(var breakvalue : boolean);
  257. begin
  258. dosregs.ax:=$3300;
  259. msdos(dosregs);
  260. breakvalue:=dosregs.dl<>0;
  261. end;
  262. procedure setcbreak(breakvalue : boolean);
  263. begin
  264. dosregs.ax:=$3301;
  265. dosregs.dl:=ord(breakvalue);
  266. msdos(dosregs);
  267. end;
  268. procedure getverify(var verify : boolean);
  269. begin
  270. dosregs.ah:=$54;
  271. msdos(dosregs);
  272. verify:=dosregs.al<>0;
  273. end;
  274. procedure setverify(verify : boolean);
  275. begin
  276. dosregs.ah:=$2e;
  277. dosregs.al:=ord(verify);
  278. msdos(dosregs);
  279. end;
  280. {******************************************************************************
  281. --- Disk ---
  282. ******************************************************************************}
  283. TYPE ExtendedFat32FreeSpaceRec=packed Record
  284. RetSize : WORD; { (ret) size of returned structure}
  285. Strucversion : WORD; {(call) structure version (0000h)
  286. (ret) actual structure version (0000h)}
  287. SecPerClus, {number of sectors per cluster}
  288. BytePerSec, {number of bytes per sector}
  289. AvailClusters, {number of available clusters}
  290. TotalClusters, {total number of clusters on the drive}
  291. AvailPhysSect, {physical sectors available on the drive}
  292. TotalPhysSect, {total physical sectors on the drive}
  293. AvailAllocUnits, {Available allocation units}
  294. TotalAllocUnits : DWORD; {Total allocation units}
  295. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  296. END;
  297. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  298. VAR
  299. S : String;
  300. Rec : ExtendedFat32FreeSpaceRec;
  301. procedure OldDosDiskData; inline;
  302. begin
  303. dosregs.dl:=drive;
  304. dosregs.ah:=$36;
  305. msdos(dosregs);
  306. if dosregs.ax<>$FFFF then
  307. begin
  308. if Free then
  309. Do_DiskData:=int64(dosregs.ax)*dosregs.bx*dosregs.cx
  310. else
  311. Do_DiskData:=int64(dosregs.ax)*dosregs.cx*dosregs.dx;
  312. end
  313. else
  314. do_diskdata:=-1;
  315. end;
  316. BEGIN
  317. if LFNSupport then
  318. begin
  319. S:='C:\'#0;
  320. if Drive=0 then
  321. begin
  322. GetDir(Drive,S);
  323. Setlength(S,4);
  324. S[4]:=#0;
  325. end
  326. else
  327. S[1]:=chr(Drive+64);
  328. Rec.Strucversion:=0;
  329. Rec.RetSize := 0;
  330. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  331. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  332. dosregs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  333. dosregs.ds:=tb_segment;
  334. dosregs.di:=tb_offset;
  335. dosregs.es:=tb_segment;
  336. dosregs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  337. dosregs.ax:=$7303;
  338. msdos(dosregs);
  339. if (dosregs.flags and fcarry) = 0 then {No error clausule in int except cf}
  340. begin
  341. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  342. if Rec.RetSize = 0 then (* Error - "FAT32" function not supported! *)
  343. OldDosDiskData
  344. else
  345. if Free then
  346. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  347. else
  348. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  349. end
  350. else
  351. Do_DiskData:=-1;
  352. end
  353. else
  354. OldDosDiskData;
  355. end;
  356. function diskfree(drive : byte) : int64;
  357. begin
  358. diskfree:=Do_DiskData(drive,TRUE);
  359. end;
  360. function disksize(drive : byte) : int64;
  361. begin
  362. disksize:=Do_DiskData(drive,false);
  363. end;
  364. {******************************************************************************
  365. --- LFNFindfirst LFNFindNext ---
  366. ******************************************************************************}
  367. type
  368. LFNSearchRec=packed record
  369. attr,
  370. crtime,
  371. crtimehi,
  372. actime,
  373. actimehi,
  374. lmtime,
  375. lmtimehi,
  376. sizehi,
  377. size : longint;
  378. reserved : array[0..7] of byte;
  379. name : array[0..259] of byte;
  380. shortname : array[0..13] of byte;
  381. end;
  382. procedure LFNSearchRec2Dos(const w:LFNSearchRec;hdl:longint;var d:Searchrec;from_findfirst : boolean);
  383. var
  384. Len : longint;
  385. begin
  386. With w do
  387. begin
  388. FillChar(d,sizeof(SearchRec),0);
  389. if DosError=0 then
  390. len:=StrLen(@Name)
  391. else
  392. len:=0;
  393. d.Name[0]:=chr(len);
  394. Move(Name[0],d.Name[1],Len);
  395. d.Time:=lmTime;
  396. d.Size:=Size;
  397. d.Attr:=Attr and $FF;
  398. if (DosError<>0) and from_findfirst then
  399. hdl:=-1;
  400. Move(hdl,d.Fill,4);
  401. end;
  402. end;
  403. procedure LFNFindFirst(path:PAnsiChar;attr:longint;var s:searchrec);
  404. var
  405. i : longint;
  406. w : LFNSearchRec;
  407. begin
  408. { allow slash as backslash }
  409. DoDirSeparators(path);
  410. dosregs.si:=1; { use ms-dos time }
  411. { don't include the label if not asked for it, needed for network drives }
  412. if attr=$8 then
  413. dosregs.ecx:=8
  414. else
  415. dosregs.ecx:=attr and (not 8) and $FF; { No required attributes }
  416. dosregs.edx:=tb_offset+Sizeof(LFNSearchrec)+1;
  417. dosmemput(tb_segment,tb_offset+Sizeof(LFNSearchrec)+1,path^,strlen(path)+1);
  418. dosregs.ds:=tb_segment;
  419. dosregs.edi:=tb_offset;
  420. dosregs.es:=tb_segment;
  421. dosregs.ax:=$714e;
  422. msdos(dosregs);
  423. LoadDosError;
  424. copyfromdos(w,sizeof(LFNSearchRec));
  425. LFNSearchRec2Dos(w,dosregs.ax,s,true);
  426. end;
  427. procedure LFNFindNext(var s:searchrec);
  428. var
  429. hdl : longint;
  430. w : LFNSearchRec;
  431. begin
  432. Move(s.Fill,hdl,4);
  433. dosregs.si:=1; { use ms-dos time }
  434. dosregs.edi:=tb_offset;
  435. dosregs.es:=tb_segment;
  436. dosregs.ebx:=hdl;
  437. dosregs.ax:=$714f;
  438. msdos(dosregs);
  439. LoadDosError;
  440. copyfromdos(w,sizeof(LFNSearchRec));
  441. LFNSearchRec2Dos(w,hdl,s,false);
  442. end;
  443. procedure LFNFindClose(var s:searchrec);
  444. var
  445. hdl : longint;
  446. begin
  447. Move(s.Fill,hdl,4);
  448. { Do not call MsDos if FindFirst returned with an error }
  449. if hdl=-1 then
  450. begin
  451. DosError:=0;
  452. exit;
  453. end;
  454. dosregs.ebx:=hdl;
  455. dosregs.ax:=$71a1;
  456. msdos(dosregs);
  457. LoadDosError;
  458. end;
  459. {******************************************************************************
  460. --- DosFindfirst DosFindNext ---
  461. ******************************************************************************}
  462. procedure dossearchrec2searchrec(var f : searchrec);
  463. var
  464. len : longint;
  465. begin
  466. { Check is necessary!! OS/2's VDM doesn't clear the name with #0 if the }
  467. { file doesn't exist! (JM) }
  468. if dosError = 0 then
  469. len:=StrLen(@f.Name)
  470. else len := 0;
  471. Move(f.Name[0],f.Name[1],Len);
  472. f.Name[0]:=chr(len);
  473. end;
  474. procedure DosFindfirst(path : PAnsiChar;attr : word;var f : searchrec);
  475. var
  476. i : longint;
  477. begin
  478. { allow slash as backslash }
  479. DoDirSeparators(path);
  480. copytodos(f,sizeof(searchrec));
  481. dosregs.edx:=tb_offset;
  482. dosregs.ds:=tb_segment;
  483. dosregs.ah:=$1a;
  484. msdos(dosregs);
  485. dosregs.ecx:=attr;
  486. dosregs.edx:=tb_offset+Sizeof(searchrec)+1;
  487. dosmemput(tb_segment,tb_offset+Sizeof(searchrec)+1,path^,strlen(path)+1);
  488. dosregs.ds:=tb_segment;
  489. dosregs.ah:=$4e;
  490. msdos(dosregs);
  491. copyfromdos(f,sizeof(searchrec));
  492. LoadDosError;
  493. dossearchrec2searchrec(f);
  494. end;
  495. procedure Dosfindnext(var f : searchrec);
  496. begin
  497. copytodos(f,sizeof(searchrec));
  498. dosregs.edx:=tb_offset;
  499. dosregs.ds:=tb_segment;
  500. dosregs.ah:=$1a;
  501. msdos(dosregs);
  502. dosregs.ah:=$4f;
  503. msdos(dosregs);
  504. copyfromdos(f,sizeof(searchrec));
  505. LoadDosError;
  506. dossearchrec2searchrec(f);
  507. end;
  508. {******************************************************************************
  509. --- Findfirst FindNext ---
  510. ******************************************************************************}
  511. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  512. var
  513. path0 : array[0..256] of AnsiChar;
  514. begin
  515. doserror:=0;
  516. strpcopy(path0,path);
  517. if LFNSupport then
  518. LFNFindFirst(path0,attr,f)
  519. else
  520. Dosfindfirst(path0,attr,f);
  521. end;
  522. procedure findnext(var f : searchRec);
  523. begin
  524. doserror:=0;
  525. if LFNSupport then
  526. LFNFindnext(f)
  527. else
  528. Dosfindnext(f);
  529. end;
  530. Procedure FindClose(Var f: SearchRec);
  531. begin
  532. DosError:=0;
  533. if LFNSupport then
  534. LFNFindClose(f);
  535. end;
  536. //type swap_proc = procedure;
  537. //var
  538. // _swap_in : swap_proc;external name '_swap_in';
  539. // _swap_out : swap_proc;external name '_swap_out';
  540. // _exception_exit : pointer;external name '_exception_exit';
  541. // _v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  542. (*
  543. procedure swapvectors;
  544. begin
  545. if _exception_exit<>nil then
  546. if _v2prt0_exceptions_on then
  547. _swap_out()
  548. else
  549. _swap_in();
  550. end;
  551. *)
  552. {******************************************************************************
  553. --- File ---
  554. ******************************************************************************}
  555. Function FSearch(path: pathstr; dirlist: string): pathstr;
  556. var
  557. p1 : longint;
  558. s : searchrec;
  559. newdir : pathstr;
  560. begin
  561. { No wildcards allowed in these things }
  562. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  563. begin
  564. fsearch:='';
  565. exit;
  566. end;
  567. { check if the file specified exists }
  568. findfirst(path,anyfile and not(directory),s);
  569. if doserror=0 then
  570. begin
  571. findclose(s);
  572. fsearch:=path;
  573. exit;
  574. end;
  575. findclose(s);
  576. { allow slash as backslash }
  577. DoDirSeparators(dirlist);
  578. repeat
  579. p1:=pos(';',dirlist);
  580. if p1<>0 then
  581. begin
  582. newdir:=copy(dirlist,1,p1-1);
  583. delete(dirlist,1,p1);
  584. end
  585. else
  586. begin
  587. newdir:=dirlist;
  588. dirlist:='';
  589. end;
  590. if (newdir<>'') and (not (newdir[length(newdir)] in [DirectorySeparator,DriveSeparator])) then
  591. newdir:=newdir+DirectorySeparator;
  592. findfirst(newdir+path,anyfile and not(directory),s);
  593. if doserror=0 then
  594. newdir:=newdir+path
  595. else
  596. newdir:='';
  597. findclose(s);
  598. until (dirlist='') or (newdir<>'');
  599. fsearch:=newdir;
  600. end;
  601. { change to short filename if successful DOS call PM }
  602. function GetShortName(var p : String) : boolean;
  603. var
  604. c : array[0..255] of AnsiChar;
  605. begin
  606. move(p[1],c[0],length(p));
  607. c[length(p)]:=#0;
  608. copytodos(c,length(p)+1);
  609. dosregs.ax:=$7160;
  610. dosregs.cx:=1;
  611. dosregs.ds:=tb_segment;
  612. dosregs.si:=tb_offset;
  613. dosregs.es:=tb_segment;
  614. dosregs.di:=tb_offset;
  615. msdos(dosregs);
  616. LoadDosError;
  617. if DosError=0 then
  618. begin
  619. copyfromdos(c,255);
  620. move(c[0],p[1],strlen(c));
  621. p[0]:=AnsiChar(strlen(c));
  622. GetShortName:=true;
  623. end
  624. else
  625. GetShortName:=false;
  626. end;
  627. { change to long filename if successful DOS call PM }
  628. function GetLongName(var p : String) : boolean;
  629. var
  630. c : array[0..255] of AnsiChar;
  631. begin
  632. move(p[1],c[0],length(p));
  633. c[length(p)]:=#0;
  634. copytodos(c,length(p)+1);
  635. dosregs.ax:=$7160;
  636. dosregs.cx:=2;
  637. dosregs.ds:=tb_segment;
  638. dosregs.si:=tb_offset;
  639. dosregs.es:=tb_segment;
  640. dosregs.di:=tb_offset;
  641. msdos(dosregs);
  642. LoadDosError;
  643. if DosError=0 then
  644. begin
  645. copyfromdos(c,255);
  646. move(c[0],p[1],strlen(c));
  647. p[0]:=AnsiChar(strlen(c));
  648. GetLongName:=true;
  649. end
  650. else
  651. GetLongName:=false;
  652. end;
  653. {******************************************************************************
  654. --- Get/Set File Time,Attr ---
  655. ******************************************************************************}
  656. procedure getftime(var f;var time : longint);
  657. begin
  658. dosregs.bx:=textrec(f).handle;
  659. dosregs.ax:=$5700;
  660. msdos(dosregs);
  661. loaddoserror;
  662. time:=(dosregs.dx shl 16)+dosregs.cx;
  663. end;
  664. procedure setftime(var f;time : longint);
  665. begin
  666. dosregs.bx:=textrec(f).handle;
  667. dosregs.cx:=time and $ffff;
  668. dosregs.dx:=time shr 16;
  669. dosregs.ax:=$5701;
  670. msdos(dosregs);
  671. loaddoserror;
  672. end;
  673. procedure getfattr(var f;var attr : word);
  674. begin
  675. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  676. dosregs.edx:=tb_offset;
  677. dosregs.ds:=tb_segment;
  678. if LFNSupport then
  679. begin
  680. dosregs.ax:=$7143;
  681. dosregs.bx:=0;
  682. end
  683. else
  684. dosregs.ax:=$4300;
  685. msdos(dosregs);
  686. LoadDosError;
  687. Attr:=dosregs.cx;
  688. end;
  689. procedure setfattr(var f;attr : word);
  690. begin
  691. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  692. dosregs.edx:=tb_offset;
  693. dosregs.ds:=tb_segment;
  694. if LFNSupport then
  695. begin
  696. dosregs.ax:=$7143;
  697. dosregs.bx:=1;
  698. end
  699. else
  700. dosregs.ax:=$4301;
  701. dosregs.cx:=attr;
  702. msdos(dosregs);
  703. LoadDosError;
  704. end;
  705. {******************************************************************************
  706. --- Environment ---
  707. ******************************************************************************}
  708. function envcount : longint;
  709. var
  710. hp : PPAnsiChar;
  711. begin
  712. hp:=envp;
  713. envcount:=0;
  714. while assigned(hp^) do
  715. begin
  716. inc(envcount);
  717. inc(hp);
  718. end;
  719. end;
  720. function EnvStr (Index: longint): string;
  721. begin
  722. if (index<=0) or (index>envcount) then
  723. begin
  724. envstr:='';
  725. exit;
  726. end;
  727. envstr:=strpas(PPAnsiChar(pointer(envp)+4*(index-1))^);
  728. end;
  729. Function GetEnv(envvar: string): string;
  730. var
  731. hp : PPAnsiChar;
  732. hs : string;
  733. eqpos : longint;
  734. begin
  735. envvar:=upcase(envvar);
  736. hp:=envp;
  737. getenv:='';
  738. while assigned(hp^) do
  739. begin
  740. hs:=strpas(hp^);
  741. eqpos:=pos('=',hs);
  742. if upcase(copy(hs,1,eqpos-1))=envvar then
  743. begin
  744. getenv:=copy(hs,eqpos+1,255);
  745. exit;
  746. end;
  747. inc(hp);
  748. end;
  749. end;
  750. end.