dos.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. {****************************************************************************
  2. $Id$
  3. Free Pascal Runtime-Library
  4. DOS unit for OS/2
  5. Copyright (c) 1997,1999-2000 by Daniel Mantione,
  6. member of the Free Pascal development team
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. ****************************************************************************}
  13. unit dos;
  14. {$ASMMODE ATT}
  15. {***************************************************************************}
  16. interface
  17. {***************************************************************************}
  18. {$PACKRECORDS 1}
  19. uses Strings, DosCalls;
  20. const
  21. FileNameLen = 255;
  22. Type
  23. {Search record which is used by findfirst and findnext:}
  24. SearchRec = record
  25. case boolean of
  26. false: (Handle: THandle; {Used in os_OS2 mode}
  27. FStat: PFileFindBuf3;
  28. Fill: array [1..21 - SizeOf (THandle) - SizeOf (pointer)]
  29. of byte;
  30. Attr: byte;
  31. Time: longint;
  32. Size: longint;
  33. Name: string); {Filenames can be long in OS/2!}
  34. true: (Fill2: array [1..21] of byte;
  35. Attr2: byte;
  36. Time2: longint;
  37. Size2: longint;
  38. Name2: string); {Filenames can be long in OS/2!}
  39. end;
  40. {Data structure for the registers needed by msdos and intr:}
  41. registers=packed record
  42. case i:integer of
  43. 0:(ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,
  44. f8,flags,fs,gs:word);
  45. 1:(al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh:byte);
  46. 2:(eax,ebx,ecx,edx,ebp,esi,edi:longint);
  47. end;
  48. {Flags for the exec procedure:
  49. }
  50. {$ifdef HASTHREADVAR}
  51. threadvar
  52. {$else HASTHREADVAR}
  53. var
  54. {$endif HASTHREADVAR}
  55. (* For compatibility with VP/2, used for runflags in Exec procedure. *)
  56. ExecFlags: cardinal;
  57. {$i dosh.inc}
  58. {OS/2 specific functions}
  59. function GetEnvPChar (EnvVar: string): PChar;
  60. function DosErrorModuleName: string;
  61. (* In case of an error in Dos.Exec returns the name of the module *)
  62. (* causing the problem - e.g. name of a missing or corrupted DLL. *)
  63. implementation
  64. {$ifdef HASTHREADVAR}
  65. threadvar
  66. {$else HASTHREADVAR}
  67. var
  68. {$endif HASTHREADVAR}
  69. LastDosExitCode: longint;
  70. LastDosErrorModuleName: string;
  71. const FindResvdMask = $00003737; {Allowed bits in attribute
  72. specification for DosFindFirst call.}
  73. function fsearch(path:pathstr;dirlist:string):pathstr;
  74. Var
  75. A: array [0..255] of char;
  76. D, P: AnsiString;
  77. begin
  78. P:=Path;
  79. D:=DirList;
  80. DosError:=DosSearchPath(0, PChar(D), PChar(P), @A, 255);
  81. fsearch := StrPas (@A);
  82. end;
  83. procedure getftime(var f;var time:longint);
  84. var
  85. FStat: TFileStatus3;
  86. begin
  87. DosError := DosQueryFileInfo (FileRec (F).Handle, ilStandard, @FStat,
  88. SizeOf (FStat));
  89. if DosError=0 then
  90. begin
  91. Time := FStat.TimeLastWrite + longint (FStat.DateLastWrite) shl 16;
  92. if Time = 0 then
  93. Time := FStat.TimeCreation + longint (FStat.DateCreation) shl 16;
  94. end else
  95. Time:=0;
  96. end;
  97. procedure SetFTime (var F; Time: longint);
  98. var FStat: TFileStatus3;
  99. RC: cardinal;
  100. begin
  101. RC := DosQueryFileInfo (FileRec (F).Handle, ilStandard, @FStat,
  102. SizeOf (FStat));
  103. if RC = 0 then
  104. begin
  105. FStat.DateLastAccess := Hi (Time);
  106. FStat.DateLastWrite := Hi (Time);
  107. FStat.TimeLastAccess := Lo (Time);
  108. FStat.TimeLastWrite := Lo (Time);
  109. RC := DosSetFileInfo (FileRec (F).Handle, ilStandard, @FStat,
  110. SizeOf (FStat));
  111. end;
  112. DosError := integer (RC);
  113. end;
  114. procedure Exec (const Path: PathStr; const ComLine: ComStr);
  115. {Execute a program.}
  116. var Args: PByteArray;
  117. ArgSize: word;
  118. Res: TResultCodes;
  119. ObjName: string;
  120. const
  121. MaxArgsSize = 2048; (* Amount of memory reserved for arguments in bytes. *)
  122. begin
  123. { LastDosExitCode := Exec (Path, ExecRunFlags (ExecFlags), efDefault, ComLine);}
  124. GetMem (Args, MaxArgsSize);
  125. ArgSize := 0;
  126. Move (Path [1], Args^ [ArgSize], Length (Path));
  127. Inc (ArgSize, Length (Path));
  128. Args^ [ArgSize] := 0;
  129. Inc (ArgSize);
  130. {Now do the real arguments.}
  131. Move (ComLine [1], Args^ [ArgSize], Length (ComLine));
  132. Inc (ArgSize, Length (ComLine));
  133. Args^ [ArgSize] := 0;
  134. Inc (ArgSize);
  135. Args^ [ArgSize] := 0;
  136. DosError := DosExecPgm (ObjName, cardinal (ExecFlags), Args, nil, Res, Path);
  137. if DosError = 0 then
  138. begin
  139. LastDosExitCode := Res.ExitCode;
  140. LastDosErrorModuleName := '';
  141. end
  142. else
  143. begin
  144. LastDosErrorModuleName := ObjName;
  145. LastDosExitCode := 0; (* Needed for TP/BP compatibility *)
  146. end;
  147. FreeMem (Args, MaxArgsSize);
  148. end;
  149. function DosExitCode: word;
  150. begin
  151. DosExitCode := LastDosExitCode and $FFFF;
  152. end;
  153. function DosErrorModuleName: string;
  154. begin
  155. DosErrorModuleName := LastDosErrorModuleName;
  156. end;
  157. function dosversion:word;
  158. {Returns OS/2 version}
  159. var
  160. Minor, Major: Cardinal;
  161. begin
  162. DosQuerySysInfo(svMajorVersion, svMajorVersion, Major, 4);
  163. DosQuerySysInfo(svMinorVersion, svMinorVersion, Minor, 4);
  164. DosVersion:=Major or Minor shl 8;
  165. end;
  166. procedure GetDate (var Year, Month, MDay, WDay: word);
  167. Var
  168. dt: TDateTime;
  169. begin
  170. DosGetDateTime(dt);
  171. Year:=dt.year;
  172. Month:=dt.month;
  173. MDay:=dt.Day;
  174. WDay:=dt.Weekday;
  175. end;
  176. procedure SetDate (Year, Month, Day: word);
  177. var
  178. DT: TDateTime;
  179. begin
  180. DosGetDateTime (DT);
  181. DT.Year := Year;
  182. DT.Month := byte (Month);
  183. DT.Day := byte (Day);
  184. DosSetDateTime (DT);
  185. end;
  186. procedure GetTime (var Hour, Minute, Second, Sec100: word);
  187. var
  188. dt: TDateTime;
  189. begin
  190. DosGetDateTime(dt);
  191. Hour:=dt.Hour;
  192. Minute:=dt.Minute;
  193. Second:=dt.Second;
  194. Sec100:=dt.Hundredths;
  195. end;
  196. procedure SetTime (Hour, Minute, Second, Sec100: word);
  197. var
  198. DT: TDateTime;
  199. begin
  200. DosGetDateTime (DT);
  201. DT.Hour := byte (Hour);
  202. DT.Minute := byte (Minute);
  203. DT.Second := byte (Second);
  204. DT.Sec100 := byte (Sec100);
  205. DosSetDateTime (DT);
  206. end;
  207. procedure getcbreak(var breakvalue:boolean);
  208. begin
  209. breakvalue := True;
  210. end;
  211. procedure setcbreak(breakvalue:boolean);
  212. begin
  213. end;
  214. procedure getverify(var verify:boolean);
  215. begin
  216. verify := true;
  217. end;
  218. procedure setverify(verify:boolean);
  219. begin
  220. end;
  221. function DiskFree (Drive: byte): int64;
  222. var FI: TFSinfo;
  223. RC: cardinal;
  224. begin
  225. {In OS/2, we use the filesystem information.}
  226. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  227. if RC = 0 then
  228. DiskFree := int64 (FI.Free_Clusters) *
  229. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  230. else
  231. DiskFree := -1;
  232. end;
  233. function DiskSize (Drive: byte): int64;
  234. var FI: TFSinfo;
  235. RC: cardinal;
  236. begin
  237. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  238. if RC = 0 then
  239. DiskSize := int64 (FI.Total_Clusters) *
  240. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  241. else
  242. DiskSize := -1;
  243. end;
  244. procedure SearchRec2DosSearchRec (var F: SearchRec);
  245. begin
  246. end;
  247. procedure DosSearchRec2SearchRec (var F: SearchRec);
  248. type
  249. TRec = record
  250. T, D: word;
  251. end;
  252. begin
  253. with F do
  254. begin
  255. Name := FStat^.Name;
  256. Size := FStat^.FileSize;
  257. Attr := byte(FStat^.AttrFile and $FF);
  258. TRec (Time).T := FStat^.TimeLastWrite;
  259. TRec (Time).D := FStat^.DateLastWrite;
  260. end;
  261. end;
  262. procedure FindFirst (const Path: PathStr; Attr: word; var F: SearchRec);
  263. var Count: cardinal;
  264. begin
  265. {No error.}
  266. DosError := 0;
  267. New (F.FStat);
  268. F.Handle := THandle ($FFFFFFFF);
  269. Count := 1;
  270. DosError := integer (DosFindFirst (Path, F.Handle,
  271. Attr and FindResvdMask, F.FStat, SizeOf (F.FStat^),
  272. Count, ilStandard));
  273. if (DosError = 0) and (Count = 0) then DosError := 18;
  274. DosSearchRec2SearchRec (F);
  275. end;
  276. procedure FindNext (var F: SearchRec);
  277. var
  278. Count: cardinal;
  279. begin
  280. {No error}
  281. DosError := 0;
  282. SearchRec2DosSearchRec (F);
  283. Count := 1;
  284. DosError := integer (DosFindNext (F.Handle, F.FStat, SizeOf (F.FStat^),
  285. Count));
  286. if (DosError = 0) and (Count = 0) then DosError := 18;
  287. DosSearchRec2SearchRec (F);
  288. end;
  289. procedure FindClose (var F: SearchRec);
  290. begin
  291. if F.Handle <> THandle ($FFFFFFFF) then DosError := DosFindClose (F.Handle);
  292. Dispose (F.FStat);
  293. end;
  294. procedure swapvectors;
  295. {For TP compatibility, this exists.}
  296. begin
  297. end;
  298. function envcount:longint;
  299. begin
  300. envcount:=envc;
  301. end;
  302. function envstr (index : longint) : string;
  303. var hp:Pchar;
  304. begin
  305. if (index<=0) or (index>envcount) then
  306. begin
  307. envstr:='';
  308. exit;
  309. end;
  310. hp:=EnvP[index-1];
  311. envstr:=strpas(hp);
  312. end;
  313. function GetEnvPChar (EnvVar: string): PChar;
  314. (* The assembler version is more than three times as fast as Pascal. *)
  315. var
  316. P: PChar;
  317. begin
  318. EnvVar := UpCase (EnvVar);
  319. {$ASMMODE INTEL}
  320. asm
  321. cld
  322. mov edi, Environment
  323. lea esi, EnvVar
  324. xor eax, eax
  325. lodsb
  326. @NewVar:
  327. cmp byte ptr [edi], 0
  328. jz @Stop
  329. push eax { eax contains length of searched variable name }
  330. push esi { esi points to the beginning of the variable name }
  331. mov ecx, -1 { our character ('=' - see below) _must_ be found }
  332. mov edx, edi { pointer to beginning of variable name saved in edx }
  333. mov al, '=' { searching until '=' (end of variable name) }
  334. repne
  335. scasb { scan until '=' not found }
  336. neg ecx { what was the name length? }
  337. dec ecx { corrected }
  338. dec ecx { exclude the '=' character }
  339. pop esi { restore pointer to beginning of variable name }
  340. pop eax { restore length of searched variable name }
  341. push eax { and save both of them again for later use }
  342. push esi
  343. cmp ecx, eax { compare length of searched variable name with name }
  344. jnz @NotEqual { ... of currently found variable, jump if different }
  345. xchg edx, edi { pointer to current variable name restored in edi }
  346. repe
  347. cmpsb { compare till the end of variable name }
  348. xchg edx, edi { pointer to beginning of variable contents in edi }
  349. jz @Equal { finish if they're equal }
  350. @NotEqual:
  351. xor eax, eax { look for 00h }
  352. mov ecx, -1 { it _must_ be found }
  353. repne
  354. scasb { scan until found }
  355. pop esi { restore pointer to beginning of variable name }
  356. pop eax { restore length of searched variable name }
  357. jmp @NewVar { ... or continue with new variable otherwise }
  358. @Stop:
  359. xor eax, eax
  360. mov P, eax { Not found - return nil }
  361. jmp @End
  362. @Equal:
  363. pop esi { restore the stack position }
  364. pop eax
  365. mov P, edi { place pointer to variable contents in P }
  366. @End:
  367. end ['eax','ecx','edx','esi','edi'];
  368. GetEnvPChar := P;
  369. end;
  370. {$ASMMODE ATT}
  371. Function GetEnv(envvar: string): string;
  372. (* The assembler version is more than three times as fast as Pascal. *)
  373. begin
  374. GetEnv := StrPas (GetEnvPChar (EnvVar));
  375. end;
  376. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  377. var ext:extstr);
  378. var p1,i : longint;
  379. dotpos : integer;
  380. begin
  381. { allow slash as backslash }
  382. for i:=1 to length(path) do
  383. if path[i]='/' then path[i]:='\';
  384. {Get drive name}
  385. p1:=pos(':',path);
  386. if p1>0 then
  387. begin
  388. dir:=path[1]+':';
  389. delete(path,1,p1);
  390. end
  391. else
  392. dir:='';
  393. { split the path and the name, there are no more path informtions }
  394. { if path contains no backslashes }
  395. while true do
  396. begin
  397. p1:=pos('\',path);
  398. if p1=0 then
  399. break;
  400. dir:=dir+copy(path,1,p1);
  401. delete(path,1,p1);
  402. end;
  403. { try to find out a extension }
  404. Ext:='';
  405. i:=Length(Path);
  406. DotPos:=256;
  407. While (i>0) Do
  408. Begin
  409. If (Path[i]='.') Then
  410. begin
  411. DotPos:=i;
  412. break;
  413. end;
  414. Dec(i);
  415. end;
  416. Ext:=Copy(Path,DotPos,255);
  417. Name:=Copy(Path,1,DotPos - 1);
  418. end;
  419. (*
  420. function FExpand (const Path: PathStr): PathStr;
  421. - declared in fexpand.inc
  422. *)
  423. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  424. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  425. {$I fexpand.inc}
  426. {$UNDEF FPC_FEXPAND_DRIVES}
  427. {$UNDEF FPC_FEXPAND_UNC}
  428. procedure packtime(var t:datetime;var p:longint);
  429. var zs:longint;
  430. begin
  431. p:=-1980;
  432. p:=p+t.year and 127;
  433. p:=p shl 4;
  434. p:=p+t.month;
  435. p:=p shl 5;
  436. p:=p+t.day;
  437. p:=p shl 16;
  438. zs:=t.hour;
  439. zs:=zs shl 6;
  440. zs:=zs+t.min;
  441. zs:=zs shl 5;
  442. zs:=zs+t.sec div 2;
  443. p:=p+(zs and $ffff);
  444. end;
  445. procedure unpacktime (p:longint;var t:datetime);
  446. begin
  447. t.sec:=(p and 31) * 2;
  448. p:=p shr 5;
  449. t.min:=p and 63;
  450. p:=p shr 6;
  451. t.hour:=p and 31;
  452. p:=p shr 5;
  453. t.day:=p and 31;
  454. p:=p shr 5;
  455. t.month:=p and 15;
  456. p:=p shr 4;
  457. t.year:=p+1980;
  458. end;
  459. procedure GetFAttr (var F; var Attr: word);
  460. var
  461. PathInfo: TFileStatus3;
  462. RC: cardinal;
  463. begin
  464. Attr := 0;
  465. RC := DosQueryPathInfo (FileRec (F).Name, ilStandard,
  466. @PathInfo, SizeOf (PathInfo));
  467. DosError := integer (RC);
  468. if RC = 0 then
  469. Attr := PathInfo.AttrFile;
  470. end;
  471. procedure SetFAttr (var F; Attr: word);
  472. var
  473. PathInfo: TFileStatus3;
  474. RC: cardinal;
  475. begin
  476. RC := DosQueryPathInfo (FileRec (F).Name, ilStandard,
  477. @PathInfo, SizeOf (PathInfo));
  478. if RC = 0 then
  479. begin
  480. PathInfo.AttrFile := Attr;
  481. RC := DosSetPathInfo (FileRec (F).Name, ilStandard, @PathInfo,
  482. SizeOf (PathInfo), doWriteThru);
  483. end;
  484. DosError := integer (RC);
  485. end;
  486. {******************************************************************************
  487. --- Not Supported ---
  488. ******************************************************************************}
  489. procedure Keep (ExitCode: word);
  490. begin
  491. end;
  492. procedure GetIntVec (IntNo: byte; var Vector: pointer);
  493. begin
  494. end;
  495. procedure SetIntVec (IntNo: byte; Vector: pointer);
  496. begin
  497. end;
  498. procedure Intr (IntNo: byte; var Regs: Registers);
  499. begin
  500. end;
  501. procedure MsDos (var Regs: Registers);
  502. begin
  503. end;
  504. function GetShortName(var p : String) : boolean;
  505. begin
  506. GetShortName:=true;
  507. {$WARNING EA .shortname support (see FAT32 driver) should be probably added here!}
  508. end;
  509. function GetLongName(var p : String) : boolean;
  510. begin
  511. GetLongName:=true;
  512. {$WARNING EA .longname support should be probably added here!}
  513. end;
  514. begin
  515. LastDosExitCode := 0;
  516. LastDosErrorModuleName := '';
  517. ExecFlags := 0;
  518. end.
  519. {
  520. $Log$
  521. Revision 1.41 2004-05-23 21:47:34 hajny
  522. * final part of longint2cardinal fixes for doscalls
  523. Revision 1.40 2004/03/21 20:22:20 hajny
  524. * Exec cleanup
  525. Revision 1.39 2004/02/22 15:01:49 hajny
  526. * lots of fixes (regcall, THandle, string operations in sysutils, longint2cardinal according to OS/2 docs, dosh.inc, ...)
  527. Revision 1.38 2004/02/17 17:37:26 daniel
  528. * Enable threadvars again
  529. Revision 1.37 2004/02/16 22:16:59 hajny
  530. * LastDosExitCode changed back from threadvar temporarily
  531. Revision 1.36 2004/02/15 21:34:06 hajny
  532. * overloaded ExecuteProcess added, EnvStr param changed to longint
  533. Revision 1.35 2004/02/15 08:02:44 yuri
  534. * fixes for dosh.inc
  535. * Executeprocess iverloaded function
  536. * updated todo
  537. Revision 1.34 2004/02/09 12:03:16 michael
  538. + Switched to single interface in dosh.inc
  539. Revision 1.33 2003/11/05 09:13:59 yuri
  540. * exec fix
  541. * unused units removed
  542. Revision 1.32 2003/11/02 09:45:32 hajny
  543. SetFTime fix
  544. Revision 1.31 2003/11/01 18:35:12 hajny
  545. * GetFTime correction for case of no previous write access
  546. Revision 1.30 2003/10/25 23:55:22 hajny
  547. * Exec fix
  548. Revision 1.29 2003/10/25 22:45:37 hajny
  549. * file handling related fixes
  550. Revision 1.28 2003/10/05 22:06:43 hajny
  551. * result buffers must be allocated
  552. Revision 1.27 2003/10/03 21:46:41 peter
  553. * stdcall fixes
  554. Revision 1.26 2003/09/24 08:59:16 yuri
  555. * Prepared for native target (emx code replaced)
  556. Revision 1.25 2003/02/20 17:37:00 hajny
  557. * correction for previous mistyping
  558. Revision 1.24 2003/02/20 17:09:49 hajny
  559. * fixes for OS/2 v2.1 incompatibility
  560. Revision 1.23 2003/01/04 15:43:50 hajny
  561. + GetEnvPChar added
  562. Revision 1.22 2002/12/07 19:46:56 hajny
  563. * mistyping fixed
  564. Revision 1.21 2002/12/07 19:17:13 hajny
  565. * GetEnv correction, better PM support, ...
  566. Revision 1.20 2002/11/18 19:51:00 hajny
  567. * another bunch of type corrections
  568. Revision 1.19 2002/09/07 16:01:24 peter
  569. * old logs removed and tabs fixed
  570. Revision 1.18 2002/07/11 16:00:05 hajny
  571. * FindFirst fix (invalid attribute bits masked out)
  572. Revision 1.17 2002/07/07 18:00:48 hajny
  573. * DosGetInfoBlock modification to allow overloaded version (in DosCalls)
  574. Revision 1.16 2002/03/03 11:19:20 hajny
  575. * GetEnv rewritten to assembly - 3x faster now
  576. }