sysutils.pp 21 KB

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