sysutils.pp 19 KB

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