dos.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  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. Type
  21. {Search record which is used by findfirst and findnext:}
  22. SearchRec = record
  23. case boolean of
  24. false: (Handle: THandle; {Used in os_OS2 mode}
  25. FStat: PFileFindBuf3;
  26. Fill: array [1..21 - SizeOf (THandle) - SizeOf (pointer)]
  27. of byte;
  28. Attr: byte;
  29. Time: longint;
  30. Size: longint;
  31. Name: string); {Filenames can be long in OS/2!}
  32. true: (Fill2: array [1..21] of byte;
  33. Attr2: byte;
  34. Time2: longint;
  35. Size2: longint;
  36. Name2: string); {Filenames can be long in OS/2!}
  37. end;
  38. {Flags for the exec procedure:
  39. }
  40. {$ifdef HASTHREADVAR}
  41. threadvar
  42. {$else HASTHREADVAR}
  43. var
  44. {$endif HASTHREADVAR}
  45. (* For compatibility with VP/2, used for runflags in Exec procedure. *)
  46. ExecFlags: cardinal;
  47. {$i dosh.inc}
  48. {OS/2 specific functions}
  49. function GetEnvPChar (EnvVar: string): PChar;
  50. function DosErrorModuleName: string;
  51. (* In case of an error in Dos.Exec returns the name of the module *)
  52. (* causing the problem - e.g. name of a missing or corrupted DLL. *)
  53. implementation
  54. {$DEFINE HAS_GETMSCOUNT}
  55. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  56. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  57. {$DEFINE FPC_FEXPAND_GETENV_PCHAR}
  58. {$I dos.inc}
  59. {$ifdef HASTHREADVAR}
  60. threadvar
  61. {$else HASTHREADVAR}
  62. var
  63. {$endif HASTHREADVAR}
  64. LastDosErrorModuleName: string;
  65. const FindResvdMask = $00003737; {Allowed bits in attribute
  66. specification for DosFindFirst call.}
  67. function GetMsCount: int64;
  68. var
  69. L: cardinal;
  70. begin
  71. DosQuerySysInfo (svMsCount, svMsCount, L, 4);
  72. GetMsCount := L;
  73. end;
  74. function fsearch(path:pathstr;dirlist:string):pathstr;
  75. Var
  76. A: array [0..255] of char;
  77. D, P: AnsiString;
  78. begin
  79. P:=Path;
  80. D:=DirList;
  81. DosError:=DosSearchPath(0, PChar(D), PChar(P), @A, 255);
  82. fsearch := StrPas (@A);
  83. end;
  84. procedure getftime(var f;var time:longint);
  85. var
  86. FStat: TFileStatus3;
  87. begin
  88. DosError := DosQueryFileInfo (FileRec (F).Handle, ilStandard, @FStat,
  89. SizeOf (FStat));
  90. if DosError=0 then
  91. begin
  92. Time := FStat.TimeLastWrite + longint (FStat.DateLastWrite) shl 16;
  93. if Time = 0 then
  94. Time := FStat.TimeCreation + longint (FStat.DateCreation) shl 16;
  95. end else
  96. Time:=0;
  97. end;
  98. procedure SetFTime (var F; Time: longint);
  99. var FStat: TFileStatus3;
  100. RC: cardinal;
  101. begin
  102. RC := DosQueryFileInfo (FileRec (F).Handle, ilStandard, @FStat,
  103. SizeOf (FStat));
  104. if RC = 0 then
  105. begin
  106. FStat.DateLastAccess := Hi (Time);
  107. FStat.DateLastWrite := Hi (Time);
  108. FStat.TimeLastAccess := Lo (Time);
  109. FStat.TimeLastWrite := Lo (Time);
  110. RC := DosSetFileInfo (FileRec (F).Handle, ilStandard, @FStat,
  111. SizeOf (FStat));
  112. end;
  113. DosError := integer (RC);
  114. end;
  115. procedure Exec (const Path: PathStr; const ComLine: ComStr);
  116. {Execute a program.}
  117. var Args: PByteArray;
  118. ArgSize: word;
  119. Res: TResultCodes;
  120. ObjName: string;
  121. const
  122. MaxArgsSize = 2048; (* Amount of memory reserved for arguments in bytes. *)
  123. begin
  124. { LastDosExitCode := Exec (Path, ExecRunFlags (ExecFlags), efDefault, ComLine);}
  125. GetMem (Args, MaxArgsSize);
  126. ArgSize := 0;
  127. Move (Path [1], Args^ [ArgSize], Length (Path));
  128. Inc (ArgSize, Length (Path));
  129. Args^ [ArgSize] := 0;
  130. Inc (ArgSize);
  131. {Now do the real arguments.}
  132. Move (ComLine [1], Args^ [ArgSize], Length (ComLine));
  133. Inc (ArgSize, Length (ComLine));
  134. Args^ [ArgSize] := 0;
  135. Inc (ArgSize);
  136. Args^ [ArgSize] := 0;
  137. DosError := DosExecPgm (ObjName, cardinal (ExecFlags), Args, nil, Res, Path);
  138. if DosError = 0 then
  139. begin
  140. LastDosExitCode := Res.ExitCode;
  141. LastDosErrorModuleName := '';
  142. end
  143. else
  144. begin
  145. LastDosErrorModuleName := ObjName;
  146. LastDosExitCode := 0; (* Needed for TP/BP compatibility *)
  147. end;
  148. FreeMem (Args, MaxArgsSize);
  149. end;
  150. function DosErrorModuleName: string;
  151. begin
  152. DosErrorModuleName := LastDosErrorModuleName;
  153. end;
  154. function dosversion:word;
  155. {Returns OS/2 version}
  156. var
  157. Minor, Major: Cardinal;
  158. begin
  159. DosQuerySysInfo(svMajorVersion, svMajorVersion, Major, 4);
  160. DosQuerySysInfo(svMinorVersion, svMinorVersion, Minor, 4);
  161. DosVersion:=Major or Minor shl 8;
  162. end;
  163. procedure GetDate (var Year, Month, MDay, WDay: word);
  164. Var
  165. dt: TDateTime;
  166. begin
  167. DosGetDateTime(dt);
  168. Year:=dt.year;
  169. Month:=dt.month;
  170. MDay:=dt.Day;
  171. WDay:=dt.Weekday;
  172. end;
  173. procedure SetDate (Year, Month, Day: word);
  174. var
  175. DT: TDateTime;
  176. begin
  177. DosGetDateTime (DT);
  178. DT.Year := Year;
  179. DT.Month := byte (Month);
  180. DT.Day := byte (Day);
  181. DosSetDateTime (DT);
  182. end;
  183. procedure GetTime (var Hour, Minute, Second, Sec100: word);
  184. var
  185. dt: TDateTime;
  186. begin
  187. DosGetDateTime(dt);
  188. Hour:=dt.Hour;
  189. Minute:=dt.Minute;
  190. Second:=dt.Second;
  191. Sec100:=dt.Hundredths;
  192. end;
  193. procedure SetTime (Hour, Minute, Second, Sec100: word);
  194. var
  195. DT: TDateTime;
  196. begin
  197. DosGetDateTime (DT);
  198. DT.Hour := byte (Hour);
  199. DT.Minute := byte (Minute);
  200. DT.Second := byte (Second);
  201. DT.Sec100 := byte (Sec100);
  202. DosSetDateTime (DT);
  203. end;
  204. function DiskFree (Drive: byte): int64;
  205. var FI: TFSinfo;
  206. RC: cardinal;
  207. begin
  208. {In OS/2, we use the filesystem information.}
  209. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  210. if RC = 0 then
  211. DiskFree := int64 (FI.Free_Clusters) *
  212. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  213. else
  214. DiskFree := -1;
  215. end;
  216. function DiskSize (Drive: byte): int64;
  217. var FI: TFSinfo;
  218. RC: cardinal;
  219. begin
  220. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  221. if RC = 0 then
  222. DiskSize := int64 (FI.Total_Clusters) *
  223. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  224. else
  225. DiskSize := -1;
  226. end;
  227. procedure DosSearchRec2SearchRec (var F: SearchRec);
  228. type
  229. TRec = record
  230. T, D: word;
  231. end;
  232. begin
  233. with F do
  234. begin
  235. Name := FStat^.Name;
  236. Size := FStat^.FileSize;
  237. Attr := byte(FStat^.AttrFile and $FF);
  238. TRec (Time).T := FStat^.TimeLastWrite;
  239. TRec (Time).D := FStat^.DateLastWrite;
  240. end;
  241. end;
  242. procedure FindFirst (const Path: PathStr; Attr: word; var F: SearchRec);
  243. var Count: cardinal;
  244. begin
  245. {No error.}
  246. DosError := 0;
  247. New (F.FStat);
  248. F.Handle := THandle ($FFFFFFFF);
  249. Count := 1;
  250. DosError := integer (DosFindFirst (Path, F.Handle,
  251. Attr and FindResvdMask, F.FStat, SizeOf (F.FStat^),
  252. Count, ilStandard));
  253. if (DosError = 0) and (Count = 0) then DosError := 18;
  254. DosSearchRec2SearchRec (F);
  255. end;
  256. procedure FindNext (var F: SearchRec);
  257. var
  258. Count: cardinal;
  259. begin
  260. {No error}
  261. DosError := 0;
  262. Count := 1;
  263. DosError := integer (DosFindNext (F.Handle, F.FStat, SizeOf (F.FStat^),
  264. Count));
  265. if (DosError = 0) and (Count = 0) then DosError := 18;
  266. DosSearchRec2SearchRec (F);
  267. end;
  268. procedure FindClose (var F: SearchRec);
  269. begin
  270. if F.Handle <> THandle ($FFFFFFFF) then DosError := DosFindClose (F.Handle);
  271. Dispose (F.FStat);
  272. end;
  273. function envcount:longint;
  274. begin
  275. envcount:=envc;
  276. end;
  277. function envstr (index : longint) : string;
  278. var hp:Pchar;
  279. begin
  280. if (index<=0) or (index>envcount) then
  281. begin
  282. envstr:='';
  283. exit;
  284. end;
  285. hp:=EnvP[index-1];
  286. envstr:=strpas(hp);
  287. end;
  288. function GetEnvPChar (EnvVar: string): PChar;
  289. (* The assembler version is more than three times as fast as Pascal. *)
  290. var
  291. P: PChar;
  292. begin
  293. EnvVar := UpCase (EnvVar);
  294. {$ASMMODE INTEL}
  295. asm
  296. cld
  297. mov edi, Environment
  298. lea esi, EnvVar
  299. xor eax, eax
  300. lodsb
  301. @NewVar:
  302. cmp byte ptr [edi], 0
  303. jz @Stop
  304. push eax { eax contains length of searched variable name }
  305. push esi { esi points to the beginning of the variable name }
  306. mov ecx, -1 { our character ('=' - see below) _must_ be found }
  307. mov edx, edi { pointer to beginning of variable name saved in edx }
  308. mov al, '=' { searching until '=' (end of variable name) }
  309. repne
  310. scasb { scan until '=' not found }
  311. neg ecx { what was the name length? }
  312. dec ecx { corrected }
  313. dec ecx { exclude the '=' character }
  314. pop esi { restore pointer to beginning of variable name }
  315. pop eax { restore length of searched variable name }
  316. push eax { and save both of them again for later use }
  317. push esi
  318. cmp ecx, eax { compare length of searched variable name with name }
  319. jnz @NotEqual { ... of currently found variable, jump if different }
  320. xchg edx, edi { pointer to current variable name restored in edi }
  321. repe
  322. cmpsb { compare till the end of variable name }
  323. xchg edx, edi { pointer to beginning of variable contents in edi }
  324. jz @Equal { finish if they're equal }
  325. @NotEqual:
  326. xor eax, eax { look for 00h }
  327. mov ecx, -1 { it _must_ be found }
  328. repne
  329. scasb { scan until found }
  330. pop esi { restore pointer to beginning of variable name }
  331. pop eax { restore length of searched variable name }
  332. jmp @NewVar { ... or continue with new variable otherwise }
  333. @Stop:
  334. xor eax, eax
  335. mov P, eax { Not found - return nil }
  336. jmp @End
  337. @Equal:
  338. pop esi { restore the stack position }
  339. pop eax
  340. mov P, edi { place pointer to variable contents in P }
  341. @End:
  342. end ['eax','ecx','edx','esi','edi'];
  343. GetEnvPChar := P;
  344. end;
  345. {$ASMMODE ATT}
  346. Function GetEnv(envvar: string): string;
  347. (* The assembler version is more than three times as fast as Pascal. *)
  348. begin
  349. GetEnv := StrPas (GetEnvPChar (EnvVar));
  350. end;
  351. procedure GetFAttr (var F; var Attr: word);
  352. var
  353. PathInfo: TFileStatus3;
  354. RC: cardinal;
  355. begin
  356. Attr := 0;
  357. RC := DosQueryPathInfo (@FileRec (F).Name, ilStandard,
  358. @PathInfo, SizeOf (PathInfo));
  359. DosError := integer (RC);
  360. if RC = 0 then
  361. Attr := PathInfo.AttrFile;
  362. end;
  363. procedure SetFAttr (var F; Attr: word);
  364. var
  365. PathInfo: TFileStatus3;
  366. RC: cardinal;
  367. begin
  368. RC := DosQueryPathInfo (@FileRec (F).Name, ilStandard,
  369. @PathInfo, SizeOf (PathInfo));
  370. if RC = 0 then
  371. begin
  372. PathInfo.AttrFile := Attr;
  373. RC := DosSetPathInfo (@FileRec (F).Name, ilStandard, @PathInfo,
  374. SizeOf (PathInfo), doWriteThru);
  375. end;
  376. DosError := integer (RC);
  377. end;
  378. {function GetShortName(var p : String) : boolean;
  379. begin
  380. GetShortName:=true;}
  381. {$WARNING EA .shortname support (see FAT32 driver) should be probably added here!}
  382. {end;
  383. function GetLongName(var p : String) : boolean;
  384. begin
  385. GetLongName:=true;}
  386. {$WARNING EA .longname support should be probably added here!}
  387. {end;}
  388. begin
  389. LastDosExitCode := 0;
  390. LastDosErrorModuleName := '';
  391. ExecFlags := 0;
  392. end.
  393. {
  394. $Log$
  395. Revision 1.42 2004-12-05 19:16:54 hajny
  396. * GetMsCount added, platform independent routines moved to single include file
  397. Revision 1.41 2004/05/23 21:47:34 hajny
  398. * final part of longint2cardinal fixes for doscalls
  399. Revision 1.40 2004/03/21 20:22:20 hajny
  400. * Exec cleanup
  401. Revision 1.39 2004/02/22 15:01:49 hajny
  402. * lots of fixes (regcall, THandle, string operations in sysutils, longint2cardinal according to OS/2 docs, dosh.inc, ...)
  403. Revision 1.38 2004/02/17 17:37:26 daniel
  404. * Enable threadvars again
  405. Revision 1.37 2004/02/16 22:16:59 hajny
  406. * LastDosExitCode changed back from threadvar temporarily
  407. Revision 1.36 2004/02/15 21:34:06 hajny
  408. * overloaded ExecuteProcess added, EnvStr param changed to longint
  409. Revision 1.35 2004/02/15 08:02:44 yuri
  410. * fixes for dosh.inc
  411. * Executeprocess iverloaded function
  412. * updated todo
  413. Revision 1.34 2004/02/09 12:03:16 michael
  414. + Switched to single interface in dosh.inc
  415. Revision 1.33 2003/11/05 09:13:59 yuri
  416. * exec fix
  417. * unused units removed
  418. Revision 1.32 2003/11/02 09:45:32 hajny
  419. SetFTime fix
  420. Revision 1.31 2003/11/01 18:35:12 hajny
  421. * GetFTime correction for case of no previous write access
  422. Revision 1.30 2003/10/25 23:55:22 hajny
  423. * Exec fix
  424. Revision 1.29 2003/10/25 22:45:37 hajny
  425. * file handling related fixes
  426. Revision 1.28 2003/10/05 22:06:43 hajny
  427. * result buffers must be allocated
  428. Revision 1.27 2003/10/03 21:46:41 peter
  429. * stdcall fixes
  430. Revision 1.26 2003/09/24 08:59:16 yuri
  431. * Prepared for native target (emx code replaced)
  432. Revision 1.25 2003/02/20 17:37:00 hajny
  433. * correction for previous mistyping
  434. Revision 1.24 2003/02/20 17:09:49 hajny
  435. * fixes for OS/2 v2.1 incompatibility
  436. Revision 1.23 2003/01/04 15:43:50 hajny
  437. + GetEnvPChar added
  438. Revision 1.22 2002/12/07 19:46:56 hajny
  439. * mistyping fixed
  440. Revision 1.21 2002/12/07 19:17:13 hajny
  441. * GetEnv correction, better PM support, ...
  442. Revision 1.20 2002/11/18 19:51:00 hajny
  443. * another bunch of type corrections
  444. Revision 1.19 2002/09/07 16:01:24 peter
  445. * old logs removed and tabs fixed
  446. Revision 1.18 2002/07/11 16:00:05 hajny
  447. * FindFirst fix (invalid attribute bits masked out)
  448. Revision 1.17 2002/07/07 18:00:48 hajny
  449. * DosGetInfoBlock modification to allow overloaded version (in DosCalls)
  450. Revision 1.16 2002/03/03 11:19:20 hajny
  451. * GetEnv rewritten to assembly - 3x faster now
  452. }