sysutils.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Sysutils unit for Go32v2
  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 sysutils;
  14. interface
  15. {$MODE objfpc}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. go32,dos;
  20. {$DEFINE HAS_SLEEP}
  21. { Include platform independent interface part }
  22. {$i sysutilh.inc}
  23. implementation
  24. uses
  25. sysconst;
  26. { Include platform independent implementation part }
  27. {$i sysutils.inc}
  28. {****************************************************************************
  29. File Functions
  30. ****************************************************************************}
  31. { some internal constants }
  32. const
  33. ofRead = $0000; { Open for reading }
  34. ofWrite = $0001; { Open for writing }
  35. ofReadWrite = $0002; { Open for reading/writing }
  36. faFail = $0000; { Fail if file does not exist }
  37. faCreate = $0010; { Create if file does not exist }
  38. faOpen = $0001; { Open if file exists }
  39. faOpenReplace = $0002; { Clear if file exists }
  40. Type
  41. PSearchrec = ^Searchrec;
  42. { converts S to a pchar and copies it to the transfer-buffer. }
  43. procedure StringToTB(const S: string);
  44. var
  45. P: pchar;
  46. Len: integer;
  47. begin
  48. Len := Length(S) + 1;
  49. P := StrPCopy(StrAlloc(Len), S);
  50. SysCopyToDos(longint(P), Len);
  51. StrDispose(P);
  52. end ;
  53. { Native OpenFile function.
  54. if return value <> 0 call failed. }
  55. function OpenFile(const FileName: string; var Handle: longint; Mode, Action: word): longint;
  56. var
  57. Regs: registers;
  58. begin
  59. result := 0;
  60. Handle := UnusedHandle;
  61. StringToTB(FileName);
  62. if LFNSupport then
  63. begin
  64. Regs.Eax := $716c; { Use LFN Open/Create API }
  65. Regs.Edx := Action; { Action if file does/doesn't exist }
  66. Regs.Esi := tb_offset;
  67. Regs.Ebx := $2000 + (Mode and $ff); { File open mode }
  68. end
  69. else
  70. begin
  71. if (Action and $00f0) <> 0 then
  72. Regs.Eax := $3c00 { Map to Create/Replace API }
  73. else
  74. Regs.Eax := $3d00 + (Mode and $ff); { Map to Open_Existing API }
  75. Regs.Edx := tb_offset;
  76. end;
  77. Regs.Ds := tb_segment;
  78. Regs.Ecx := $20; { Attributes }
  79. RealIntr($21, Regs);
  80. if (Regs.Flags and CarryFlag) <> 0 then
  81. result := Regs.Ax
  82. else
  83. Handle := Regs.Ax;
  84. end;
  85. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  86. var
  87. e: integer;
  88. Begin
  89. e := OpenFile(FileName, result, Mode, faOpen);
  90. if e <> 0 then
  91. result := -1;
  92. end;
  93. Function FileCreate (Const FileName : String) : Longint;
  94. var
  95. e: integer;
  96. begin
  97. e := OpenFile(FileName, result, ofReadWrite, faCreate or faOpenReplace);
  98. if e <> 0 then
  99. result := -1;
  100. end;
  101. Function FileCreate (Const FileName : String; Mode:longint) : Longint;
  102. begin
  103. FileCreate:=FileCreate(FileName);
  104. end;
  105. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  106. var
  107. regs : registers;
  108. size,
  109. readsize : longint;
  110. begin
  111. readsize:=0;
  112. while Count > 0 do
  113. begin
  114. if Count>tb_size then
  115. size:=tb_size
  116. else
  117. size:=Count;
  118. regs.realecx:=size;
  119. regs.realedx:=tb_offset;
  120. regs.realds:=tb_segment;
  121. regs.realebx:=Handle;
  122. regs.realeax:=$3f00;
  123. RealIntr($21,regs);
  124. if (regs.realflags and carryflag) <> 0 then
  125. begin
  126. Result:=-1;
  127. exit;
  128. end;
  129. syscopyfromdos(Longint(@Buffer)+readsize,lo(regs.realeax));
  130. inc(readsize,lo(regs.realeax));
  131. dec(Count,lo(regs.realeax));
  132. { stop when not the specified size is read }
  133. if lo(regs.realeax)<size then
  134. break;
  135. end;
  136. Result:=readsize;
  137. end;
  138. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  139. var
  140. regs : registers;
  141. size,
  142. writesize : longint;
  143. begin
  144. writesize:=0;
  145. while Count > 0 do
  146. begin
  147. if Count>tb_size then
  148. size:=tb_size
  149. else
  150. size:=Count;
  151. syscopytodos(Longint(@Buffer)+writesize,size);
  152. regs.realecx:=size;
  153. regs.realedx:=tb_offset;
  154. regs.realds:=tb_segment;
  155. regs.realebx:=Handle;
  156. regs.realeax:=$4000;
  157. RealIntr($21,regs);
  158. if (regs.realflags and carryflag) <> 0 then
  159. begin
  160. Result:=-1;
  161. exit;
  162. end;
  163. inc(writesize,lo(regs.realeax));
  164. dec(Count,lo(regs.realeax));
  165. { stop when not the specified size is written }
  166. if lo(regs.realeax)<size then
  167. break;
  168. end;
  169. Result:=WriteSize;
  170. end;
  171. Function FileSeek (Handle, FOffset, Origin : Longint) : Longint;
  172. var
  173. Regs: registers;
  174. begin
  175. Regs.Eax := $4200;
  176. Regs.Al := Origin;
  177. Regs.Edx := Lo(FOffset);
  178. Regs.Ecx := Hi(FOffset);
  179. Regs.Ebx := Handle;
  180. RealIntr($21, Regs);
  181. if Regs.Flags and CarryFlag <> 0 then
  182. result := -1
  183. else begin
  184. LongRec(result).Lo := Regs.Ax;
  185. LongRec(result).Hi := Regs.Dx;
  186. end ;
  187. end;
  188. Function FileSeek (Handle : Longint; FOffset,Origin : Int64) : Int64;
  189. begin
  190. {$warning need to add 64bit call }
  191. FileSeek:=FileSeek(Handle,Longint(FOffset),Longint(Origin));
  192. end;
  193. Procedure FileClose (Handle : Longint);
  194. var
  195. Regs: registers;
  196. begin
  197. if Handle<=4 then
  198. exit;
  199. Regs.Eax := $3e00;
  200. Regs.Ebx := Handle;
  201. RealIntr($21, Regs);
  202. end;
  203. Function FileTruncate (Handle,Size: Longint) : boolean;
  204. var
  205. regs : trealregs;
  206. begin
  207. FileSeek(Handle,Size,0);
  208. Regs.realecx := 0;
  209. Regs.realedx := tb_offset;
  210. Regs.ds := tb_segment;
  211. Regs.ebx := Handle;
  212. Regs.eax:=$4000;
  213. RealIntr($21, Regs);
  214. FileTruncate:=(regs.realflags and carryflag)=0;
  215. end;
  216. Function FileAge (Const FileName : String): Longint;
  217. var Handle: longint;
  218. begin
  219. Handle := FileOpen(FileName, 0);
  220. if Handle <> -1 then
  221. begin
  222. result := FileGetDate(Handle);
  223. FileClose(Handle);
  224. end
  225. else
  226. result := -1;
  227. end;
  228. Function FileExists (Const FileName : String) : Boolean;
  229. Var
  230. Sr : Searchrec;
  231. begin
  232. DOS.FindFirst(FileName,$3f,sr);
  233. if DosError = 0 then
  234. begin
  235. { No volumeid,directory }
  236. Result:=(sr.attr and $18)=0;
  237. Dos.FindClose(sr);
  238. end
  239. else
  240. Result:=false;
  241. end;
  242. Function DirectoryExists (Const Directory : String) : Boolean;
  243. Var
  244. Sr : Searchrec;
  245. begin
  246. DOS.FindFirst(Directory,$3f,sr);
  247. if DosError = 0 then
  248. begin
  249. Result:=(sr.attr and $10)=$10;
  250. Dos.FindClose(sr);
  251. end
  252. else
  253. Result:=false;
  254. end;
  255. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  256. Var Sr : PSearchrec;
  257. begin
  258. //!! Sr := New(PSearchRec);
  259. getmem(sr,sizeof(searchrec));
  260. Rslt.FindHandle := longint(Sr);
  261. DOS.FindFirst(Path, Attr, Sr^);
  262. result := -DosError;
  263. if result = 0 then
  264. begin
  265. Rslt.Time := Sr^.Time;
  266. Rslt.Size := Sr^.Size;
  267. Rslt.Attr := Sr^.Attr;
  268. Rslt.ExcludeAttr := 0;
  269. Rslt.Name := Sr^.Name;
  270. end ;
  271. end;
  272. Function FindNext (Var Rslt : TSearchRec) : Longint;
  273. var
  274. Sr: PSearchRec;
  275. begin
  276. Sr := PSearchRec(Rslt.FindHandle);
  277. if Sr <> nil then
  278. begin
  279. DOS.FindNext(Sr^);
  280. result := -DosError;
  281. if result = 0 then
  282. begin
  283. Rslt.Time := Sr^.Time;
  284. Rslt.Size := Sr^.Size;
  285. Rslt.Attr := Sr^.Attr;
  286. Rslt.ExcludeAttr := 0;
  287. Rslt.Name := Sr^.Name;
  288. end;
  289. end;
  290. end;
  291. Procedure FindClose (Var F : TSearchrec);
  292. var
  293. Sr: PSearchRec;
  294. begin
  295. Sr := PSearchRec(F.FindHandle);
  296. if Sr <> nil then
  297. begin
  298. //!! Dispose(Sr);
  299. // This call is non dummy if LFNSupport is true PM
  300. DOS.FindClose(SR^);
  301. freemem(sr,sizeof(searchrec));
  302. end;
  303. F.FindHandle := 0;
  304. end;
  305. Function FileGetDate (Handle : Longint) : Longint;
  306. var
  307. Regs: registers;
  308. begin
  309. //!! for win95 an alternative function is available.
  310. Regs.Ebx := Handle;
  311. Regs.Eax := $5700;
  312. RealIntr($21, Regs);
  313. if Regs.Flags and CarryFlag <> 0 then
  314. result := -1
  315. else
  316. begin
  317. LongRec(result).Lo := Regs.cx;
  318. LongRec(result).Hi := Regs.dx;
  319. end ;
  320. end;
  321. Function FileSetDate (Handle, Age : Longint) : Longint;
  322. var
  323. Regs: registers;
  324. begin
  325. Regs.Ebx := Handle;
  326. Regs.Eax := $5701;
  327. Regs.Ecx := Lo(Age);
  328. Regs.Edx := Hi(Age);
  329. RealIntr($21, Regs);
  330. if Regs.Flags and CarryFlag <> 0 then
  331. result := -Regs.Ax
  332. else
  333. result := 0;
  334. end;
  335. Function FileGetAttr (Const FileName : String) : Longint;
  336. var
  337. Regs: registers;
  338. begin
  339. StringToTB(FileName);
  340. Regs.Edx := tb_offset;
  341. Regs.Ds := tb_segment;
  342. if LFNSupport then
  343. begin
  344. Regs.Ax := $7143;
  345. Regs.Bx := 0;
  346. end
  347. else
  348. Regs.Ax := $4300;
  349. RealIntr($21, Regs);
  350. if Regs.Flags and CarryFlag <> 0 then
  351. result := -1
  352. else
  353. result := Regs.Cx;
  354. end;
  355. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  356. var
  357. Regs: registers;
  358. begin
  359. StringToTB(FileName);
  360. Regs.Edx := tb_offset;
  361. Regs.Ds := tb_segment;
  362. if LFNSupport then
  363. begin
  364. Regs.Ax := $7143;
  365. Regs.Bx := 1;
  366. end
  367. else
  368. Regs.Ax := $4301;
  369. Regs.Cx := Attr;
  370. RealIntr($21, Regs);
  371. if Regs.Flags and CarryFlag <> 0 then
  372. result := -Regs.Ax
  373. else
  374. result := 0;
  375. end;
  376. Function DeleteFile (Const FileName : String) : Boolean;
  377. var
  378. Regs: registers;
  379. begin
  380. StringToTB(FileName);
  381. Regs.Edx := tb_offset;
  382. Regs.Ds := tb_segment;
  383. if LFNSupport then
  384. Regs.Eax := $7141
  385. else
  386. Regs.Eax := $4100;
  387. Regs.Esi := 0;
  388. Regs.Ecx := 0;
  389. RealIntr($21, Regs);
  390. result := (Regs.Flags and CarryFlag = 0);
  391. end;
  392. Function RenameFile (Const OldName, NewName : String) : Boolean;
  393. var
  394. Regs: registers;
  395. begin
  396. StringToTB(OldName + #0 + NewName);
  397. Regs.Edx := tb_offset;
  398. Regs.Ds := tb_segment;
  399. Regs.Edi := tb_offset + Length(OldName) + 1;
  400. Regs.Es := tb_segment;
  401. if LFNSupport then
  402. Regs.Eax := $7156
  403. else
  404. Regs.Eax := $5600;
  405. Regs.Ecx := $ff;
  406. RealIntr($21, Regs);
  407. result := (Regs.Flags and CarryFlag = 0);
  408. end;
  409. {****************************************************************************
  410. Disk Functions
  411. ****************************************************************************}
  412. TYPE ExtendedFat32FreeSpaceRec=packed Record
  413. RetSize : WORD; { (ret) size of returned structure}
  414. Strucversion : WORD; {(call) structure version (0000h)
  415. (ret) actual structure version (0000h)}
  416. SecPerClus, {number of sectors per cluster}
  417. BytePerSec, {number of bytes per sector}
  418. AvailClusters, {number of available clusters}
  419. TotalClusters, {total number of clusters on the drive}
  420. AvailPhysSect, {physical sectors available on the drive}
  421. TotalPhysSect, {total physical sectors on the drive}
  422. AvailAllocUnits, {Available allocation units}
  423. TotalAllocUnits : DWORD; {Total allocation units}
  424. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  425. END;
  426. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  427. VAR S : String;
  428. Rec : ExtendedFat32FreeSpaceRec;
  429. regs : registers;
  430. BEGIN
  431. if (swap(dosversion)>=$070A) AND LFNSupport then
  432. begin
  433. DosError:=0;
  434. S:='C:\'#0;
  435. if Drive=0 then
  436. begin
  437. GetDir(Drive,S);
  438. Setlength(S,4);
  439. S[4]:=#0;
  440. end
  441. else
  442. S[1]:=chr(Drive+64);
  443. Rec.Strucversion:=0;
  444. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  445. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  446. regs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  447. regs.ds:=tb_segment;
  448. regs.di:=tb_offset;
  449. regs.es:=tb_segment;
  450. regs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  451. regs.ax:=$7303;
  452. msdos(regs);
  453. if regs.ax<>$ffff then
  454. begin
  455. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  456. if Free then
  457. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  458. else
  459. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  460. end
  461. else
  462. Do_DiskData:=-1;
  463. end
  464. else
  465. begin
  466. DosError:=0;
  467. regs.dl:=drive;
  468. regs.ah:=$36;
  469. msdos(regs);
  470. if regs.ax<>$FFFF then
  471. begin
  472. if Free then
  473. Do_DiskData:=int64(regs.ax)*regs.bx*regs.cx
  474. else
  475. Do_DiskData:=int64(regs.ax)*regs.cx*regs.dx;
  476. end
  477. else
  478. do_diskdata:=-1;
  479. end;
  480. end;
  481. function diskfree(drive : byte) : int64;
  482. begin
  483. diskfree:=Do_DiskData(drive,TRUE);
  484. end;
  485. function disksize(drive : byte) : int64;
  486. begin
  487. disksize:=Do_DiskData(drive,false);
  488. end;
  489. Function GetCurrentDir : String;
  490. begin
  491. GetDir(0, result);
  492. end;
  493. Function SetCurrentDir (Const NewDir : String) : Boolean;
  494. begin
  495. {$I-}
  496. ChDir(NewDir);
  497. {$I+}
  498. result := (IOResult = 0);
  499. end;
  500. Function CreateDir (Const NewDir : String) : Boolean;
  501. begin
  502. {$I-}
  503. MkDir(NewDir);
  504. {$I+}
  505. result := (IOResult = 0);
  506. end;
  507. Function RemoveDir (Const Dir : String) : Boolean;
  508. begin
  509. {$I-}
  510. RmDir(Dir);
  511. {$I+}
  512. result := (IOResult = 0);
  513. end;
  514. {****************************************************************************
  515. Time Functions
  516. ****************************************************************************}
  517. Procedure GetLocalTime(var SystemTime: TSystemTime);
  518. var
  519. Regs: Registers;
  520. begin
  521. Regs.ah := $2C;
  522. RealIntr($21, Regs);
  523. SystemTime.Hour := Regs.Ch;
  524. SystemTime.Minute := Regs.Cl;
  525. SystemTime.Second := Regs.Dh;
  526. SystemTime.MilliSecond := Regs.Dl*10;
  527. Regs.ah := $2A;
  528. RealIntr($21, Regs);
  529. SystemTime.Year := Regs.Cx;
  530. SystemTime.Month := Regs.Dh;
  531. SystemTime.Day := Regs.Dl;
  532. end ;
  533. {****************************************************************************
  534. Misc Functions
  535. ****************************************************************************}
  536. procedure Beep;
  537. begin
  538. end;
  539. {****************************************************************************
  540. Locale Functions
  541. ****************************************************************************}
  542. { Codepage constants }
  543. const
  544. CP_US = 437;
  545. CP_MultiLingual = 850;
  546. CP_SlavicLatin2 = 852;
  547. CP_Turkish = 857;
  548. CP_Portugal = 860;
  549. CP_IceLand = 861;
  550. CP_Canada = 863;
  551. CP_NorwayDenmark = 865;
  552. { CountryInfo }
  553. type
  554. TCountryInfo = packed record
  555. InfoId: byte;
  556. case integer of
  557. 1: ( Size: word;
  558. CountryId: word;
  559. CodePage: word;
  560. CountryInfo: array[0..33] of byte );
  561. 2: ( UpperCaseTable: longint );
  562. 4: ( FilenameUpperCaseTable: longint );
  563. 5: ( FilecharacterTable: longint );
  564. 6: ( CollatingTable: longint );
  565. 7: ( DBCSLeadByteTable: longint );
  566. end ;
  567. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  568. Var Regs: Registers;
  569. begin
  570. Regs.AH := $65;
  571. Regs.AL := InfoId;
  572. Regs.BX := CodePage;
  573. Regs.DX := CountryId;
  574. Regs.ES := transfer_buffer div 16;
  575. Regs.DI := transfer_buffer and 15;
  576. Regs.CX := SizeOf(TCountryInfo);
  577. RealIntr($21, Regs);
  578. DosMemGet(transfer_buffer div 16,
  579. transfer_buffer and 15,
  580. CountryInfo, Regs.CX );
  581. end;
  582. procedure InitAnsi;
  583. var
  584. CountryInfo: TCountryInfo; i: integer;
  585. begin
  586. { Fill table entries 0 to 127 }
  587. for i := 0 to 96 do
  588. UpperCaseTable[i] := chr(i);
  589. for i := 97 to 122 do
  590. UpperCaseTable[i] := chr(i - 32);
  591. for i := 123 to 127 do
  592. UpperCaseTable[i] := chr(i);
  593. for i := 0 to 64 do
  594. LowerCaseTable[i] := chr(i);
  595. for i := 65 to 90 do
  596. LowerCaseTable[i] := chr(i + 32);
  597. for i := 91 to 255 do
  598. LowerCaseTable[i] := chr(i);
  599. { Get country and codepage info }
  600. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  601. if CountryInfo.CodePage = 850 then
  602. begin
  603. { Special, known case }
  604. Move(CP850UCT, UpperCaseTable[128], 128);
  605. Move(CP850LCT, LowerCaseTable[128], 128);
  606. end
  607. else
  608. begin
  609. { this needs to be checked !!
  610. this is correct only if UpperCaseTable is
  611. and Offset:Segment word record (PM) }
  612. { get the uppercase table from dosmemory }
  613. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  614. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  615. for i := 128 to 255 do
  616. begin
  617. if UpperCaseTable[i] <> chr(i) then
  618. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  619. end;
  620. end;
  621. end;
  622. Procedure InitInternational;
  623. begin
  624. InitAnsi;
  625. end;
  626. function SysErrorMessage(ErrorCode: Integer): String;
  627. begin
  628. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  629. end;
  630. {****************************************************************************
  631. Os utils
  632. ****************************************************************************}
  633. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  634. begin
  635. Result:=FPCGetEnvVarFromP(envp,EnvVar);
  636. end;
  637. Function GetEnvironmentVariableCount : Integer;
  638. begin
  639. Result:=FPCCountEnvVar(EnvP);
  640. end;
  641. Function GetEnvironmentString(Index : Integer) : String;
  642. begin
  643. Result:=FPCGetEnvStrFromP(Envp,Index);
  644. end;
  645. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString):integer;
  646. var
  647. e : EOSError;
  648. CommandLine: AnsiString;
  649. begin
  650. dos.exec(path,comline);
  651. if (Dos.DosError <> 0) then
  652. begin
  653. if ComLine <> '' then
  654. CommandLine := Path + ' ' + ComLine
  655. else
  656. CommandLine := Path;
  657. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,Dos.DosError]);
  658. e.ErrorCode:=Dos.DosError;
  659. raise e;
  660. end;
  661. Result := DosExitCode;
  662. end;
  663. function ExecuteProcess (const Path: AnsiString;
  664. const ComLine: array of AnsiString): integer;
  665. var
  666. CommandLine: AnsiString;
  667. I: integer;
  668. begin
  669. Commandline := '';
  670. for I := 0 to High (ComLine) do
  671. if Pos (' ', ComLine [I]) <> 0 then
  672. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  673. else
  674. CommandLine := CommandLine + ' ' + Comline [I];
  675. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  676. end;
  677. {*************************************************************************
  678. Sleep
  679. *************************************************************************}
  680. procedure Sleep (MilliSeconds: Cardinal);
  681. var
  682. R: Registers;
  683. T0, T1, T2: int64;
  684. DayOver: boolean;
  685. begin
  686. (* Sleep is supposed to give up time slice - DOS Idle Interrupt chosen
  687. because it should be supported in all DOS versions. Not precise at all,
  688. though - the smallest step is 10 ms even in the best case. *)
  689. R.AH := $2C;
  690. RealIntr($21, R);
  691. T0 := R.CH * 3600000 + R.CL * 60000 + R.DH * 1000 + R.DL * 10;
  692. T2 := T0 + MilliSeconds;
  693. DayOver := T2 > (24 * 3600000);
  694. repeat
  695. Intr ($28, R);
  696. (* R.AH := $2C; - should be preserved. *)
  697. RealIntr($21, R);
  698. T1 := R.CH * 3600000 + R.CL * 60000 + R.DH * 1000 + R.DL * 10;
  699. if DayOver and (T1 < T0) then
  700. Inc (T1, 24 * 3600000);
  701. until T1 >= T2;
  702. end;
  703. {****************************************************************************
  704. Initialization code
  705. ****************************************************************************}
  706. Initialization
  707. InitExceptions; { Initialize exceptions. OS independent }
  708. InitInternational; { Initialize internationalization settings }
  709. Finalization
  710. DoneExceptions;
  711. end.
  712. {
  713. $Log$
  714. Revision 1.26 2004-12-18 20:22:17 hajny
  715. * FileOpen fixes for DR-DOS, resourcestring in ExecuteProcess, implementation of Sleep changed to give up timeslices
  716. Revision 1.25 2004/12/11 11:32:44 michael
  717. + Added GetEnvironmentVariableCount and GetEnvironmentString calls
  718. Revision 1.24 2004/02/15 21:34:06 hajny
  719. * overloaded ExecuteProcess added, EnvStr param changed to longint
  720. Revision 1.23 2004/01/25 13:05:08 jonas
  721. * fixed compilation errors
  722. Revision 1.22 2004/01/20 23:09:14 hajny
  723. * ExecuteProcess fixes, ProcessID and ThreadID added
  724. Revision 1.21 2004/01/10 20:25:14 michael
  725. + Added rtlconst dependency to classes.ppu and implemented sysutils.sleep
  726. Revision 1.20 2004/01/10 10:49:24 jonas
  727. * fixed compilation
  728. Revision 1.19 2003/11/26 20:00:19 florian
  729. * error handling for Variants improved
  730. Revision 1.18 2003/11/05 11:42:27 florian
  731. * applied patch from Joe da Silva to fix OpenFile on older DOS versions
  732. Revision 1.17 2003/10/25 23:42:35 hajny
  733. * THandle in sysutils common using System.THandle
  734. Revision 1.16 2003/06/03 07:54:27 michael
  735. + Patch from Peter for millisecond timing
  736. Revision 1.15 2003/04/02 15:18:28 peter
  737. * fix argument names
  738. Revision 1.14 2003/04/01 15:57:41 peter
  739. * made THandle platform dependent and unique type
  740. Revision 1.13 2003/03/29 18:21:42 hajny
  741. * DirectoryExists declaration changed to that one from fixes branch
  742. Revision 1.12 2003/03/28 19:06:59 peter
  743. * directoryexists added
  744. Revision 1.11 2003/01/03 20:41:04 peter
  745. * FileCreate(string,mode) overload added
  746. Revision 1.10 2002/09/07 16:01:19 peter
  747. * old logs removed and tabs fixed
  748. Revision 1.9 2002/05/09 08:42:24 carl
  749. * Merges from Fixes branch
  750. Revision 1.8 2002/01/25 16:23:03 peter
  751. * merged filesearch() fix
  752. Revision 1.7 2002/01/19 11:57:55 peter
  753. * merged fixes
  754. }