dos.pp 19 KB

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