home *** CD-ROM | disk | FTP | other *** search
- Unit DosUtils; { Utility-Routinen zur DOS-Programmierung }
- Interface
- uses Dos;
-
- Type { Struktur eines File Control Blocks }
- FCBRec = Record
- Drive: Byte; { Laufwerksnummer: 1 = A:, 2 = B: usw. }
- Name: Array[1..8] of Char; { Dateiname, aufgefüllt mit Leerz. }
- Suffix: Array[1..3] of Char; { Suffix, aufgefüllt mit Leerzeichen }
- CurrBlock: Word; { momentane Blocknummer (Datensatz/128) }
- RecSize: Word; { Datensatzgröße in Bytes }
- FileSize: LongInt; { Dateigröße in Bytes }
- ModDate: Word; { Datum der letzten Modifikation }
- ModTime: Word; { Uhrzeit der letzten Modifikation }
- Reserved: Array[1..8] of Byte; { Betriebssystem-intern verwendet }
- CurrRec: Byte; { momentane Datensatznummer (0..127) }
- RandRec: LongInt; { Recordnummer für R/W Random }
- end;
- FCBPointer = ^FCBRec; { Zeiger darauf }
-
- { Kopfinformation von Gerätetreibern }
- DriverPointer = ^DriverHead;
- DriverHead = Record { Gerätetreiber-Kopf }
- DNext: DriverPointer; { Zeiger auf den nächsten Treiber }
- DAttr: Word; { Geräteattribut, <> Func $4400! }
- DStrat: Word; { Offset-Adresse der "Strategy"-Routine }
- DIntr: Word; { Offset-Adresse der "Interrupt"-Routine }
- case Integer of
- 0: (Name: Array[1..8] of Char);
- 1: (Drives: Byte);
- end;
-
- Type
- PSPSegment = Record
- INT20 : Array[1..2] of Byte; { INT $20-Befehl }
- MemEnd: Word; { Höchste Speicheradresse in Paragraphs }
- Fill1: Byte; { unbenutzt }
- DOSJmp: Array[1..5] of Byte; { JMP FAR zu DOS, mit 1. Prog-Seg }
- OrgInt22: Pointer; { Originalwert INT $22, d.h. Rücksprungadresse }
- OrgInt23: Pointer; { Originalwert INT $23 }
- OrgInt24: Pointer; { Originalwert INT $24 }
- ParentPSP: Word; { PSP-Segment des aufrufenden Programms }
- JFT: Array[0..19] of Byte; { Offene Dateien }
- EnvSeg: Word; { Environment-Segment }
- SPSave: Word; { SP beim letzten DOS-Aufruf }
- SSSave: Word; { SS beim letzten DOS-Aufruf }
- FILES: Word; { DOS 3.x: Maximalzahl offener Dateien }
- JFTAddr: Pointer; { DOS 3.x: Datei-Tabelle, normalerweise @FTable }
- PrevPSP: Pointer; { DOS 3.x: vorangehendes PSP ($FFFFF) }
- Fill2: Array[1..20] of Byte; { unbenutzt }
- DOSCall: Array[1..3] of Byte; { INT $21 / RETF }
- Fill3: Array[1..9] of Byte; { unbenutzt }
- { FCB }
- Drive: Byte; { Laufwerksnummer: 1 = A:, 2 = B: usw. }
- Name: Array[1..8] of Char; { Dateiname, aufgefüllt mit Leerz. }
- Suffix: Array[1..3] of Char; { Suffix, aufgefüllt mit Leerzeichen }
- CurrBlock: Word; { momentane Blocknummer }
- RecSize: Word; { Datensatzgröße in Bytes }
- NewDrive: Byte; { für den FCB: FileSize, ModDate... }
- NewName: Array[1..8] of Char;
- NewSuffix: Array[1..3] of Char;
- Fill4: Array[1..8] of Byte;
- DTA: Array[0..$7F] of Char;
- end;
- PSPSegPointer = ^PSPSegment;
-
- var
- ExtErrInfo : Record { wird von GetExtError gesetzt und }
- Code: Word; { von GetExtError als Parameter benutzt }
- Class, Action, Locus: Byte;
- ExtPointer: Pointer;
- end;
-
- Procedure ShowExtError; { Ausgabe des Fehlerstatus (Funktion $59) }
-
- Procedure CallCommand(Cmd: String); { Aufruf von COMMAND.COM }
-
- Type { Struktur eines Speicherkontrollblocks ab V 4.0 }
- MCBRec = Record { bzw. DR-DOS 5.0 }
- Flag: Char; { 'M' oder 'Z' }
- OwnerPSP: Word; { PSP-Segment des "Besitzers" }
- Size: Word; { Größe in Paragraphs }
- Resvd: Array[1..3] of Byte; { "reserviert" }
- OwnerID: Array[1..8] of Char;
- end;
- MCBPtr = ^MCBRec;
-
- Type { für die Funktionen $5Dxx }
- ServerCallBlock = Record
- AX,BX,CX,DX,SI,DI,DS,ES: Word; { Register }
- Resvd: Word; { sollte immer 0 sein }
- SysID: Word; { Stations-ID: 0 für die eigene Maschine }
- ProcID: Word; { = PSP-Segment des aufrufenden Prozesses }
- end;
-
- Type { für die Funktion $6501 }
- Func6501Country = Record
- SubFuncNo: Byte; { immer $01 }
- DataSize: Word; { Umfang der folgenden Daten }
- CountryCode: Word; { Nummer des aktuellen/angegebenen Landes }
- CodePage: Word; { Nummer aktuelle/angegebene Codeseite (CON) }
-
- { ab hier: wie bei Funktion $38 }
- DateFmt: Word; { 0=USA,1=Europa,2=Japan }
- Currency: Array[0..4] of Char; { ASCIIz-String }
- TSep: Char; { Trennzeichen für Tausender }
- Dummy1: Byte;
- DSep: Char; { Trennzeichen für Nachkommastellen }
- Dummy2: Byte; { unbenutzt }
- DateSep: Char; { Trennzeichen für Datum }
- Dummy3: Char;
- TimeSep: Char; { Trennzeichen für Zeit }
- Dummy4: Byte;
- CurrFmt: Byte; { Bit 0 = 0 -> DM xxxx, 1-> xxxx DM }
- { Bit 1 = 0 -> DMxxxx, 1-> DM xxxx }
- Precision: Byte; { Anzahl Nachkommastellen }
- TimeFmt: Byte; { 0 = 12 Stunden, 1 = 24 Stunden }
- UpcasePtr: Pointer; { Zeiger auf Upcase-Routine }
- Dummy5: Array[22..33] of Byte; { unbenutzt }
- end;
-
- Type
- DiskSerialInfo = Record { Funktionen $69xx und $440D/$46 bzw. $66 }
- InfoLevel: Word; { immer 0 }
- SerialNo: LongInt; { Seriennummer des Volumes }
- VLabel: Array[1..11] of Char; { Volume-Label }
- FileSystem: Array[1..8] of Char; { Dateisystem ('FATxx') }
- end;
-
-
- { Ausgabe im Hexadezimalformat mit führenden Nullen }
- Function HexB(b: Byte): String;
- Function HexW(w: Word): String;
- Function HexP(p: Pointer): String;
- Function HexL(l: LongInt): String;
-
- { Umwandlung zwischen ASCIIZ und Pascal-Strings }
- Function StrtoZ(PascalStr: String): String;
- Function ZtoStr(ZStr: Pointer): String;
-
- Procedure AbsRead(Drive: Byte; DTA: Pointer; { Abs. Sektor lesen }
- StartSec: LongInt; NumSecs: Word);
- Procedure AbsWrite(Drive: Byte; DTA: Pointer; { Abs. Sektor schreiben }
- StartSec: LongInt; NumSecs: Word);
-
- { Lokalisieren und Bearbeiten von Gerätetreibern }
- Function LocateDriver(DriverName: String): DriverPointer;
- Procedure GetDriver (DriverName: String; var Attributes: Word;
- var Strategy: Pointer; var Intrupt: Pointer);
-
- { Speichert bei jedem Aufruf den als NewVal übergebenen Wert in seinem
- Codesegment und liefert den dort zuletzt gespeicherten Wert zurück,
- wird für EXEC und andere Routinen gebraucht, die das DS-Register
- und den Stack verändern.
- }
- Function SwapValInCS(NewVal: Word): Word;
-
-
- { ------- CP/M-kompatible DOS-Funktionen -------- }
- { $01 } Function GetChar01: Char; { Zeicheneingabe }
- { $02 } Procedure PutChar02(Ch: Char); { Zeichenausgabe }
- { $03 } Function GetChar03: Char; { Zeicheneingabe AUX }
- { $04 } Procedure PutChar04(Ch: Char); { Zeichenausgabe AUX }
- { $05 } Procedure PutChar05(Ch: Char); { Zeichenausgabe PRN }
- { $06 } Function GetChar06: Char; { Zeicheneingabe }
- Procedure PutChar06(Ch: Char); { Zeichenausgabe }
- { $07 } Function GetChar07: Char; { Zeicheneingabe }
- { $08 } Function GetChar08: Char; { Zeichenausgabe }
- { $09 } Procedure WriteString09(s: String); { Ausgabe CP/M-String }
- { $0A } Function ReadString0A(MaxLen: Integer): String; { Stringeingabe }
- { $0B } Function CharAvailable: Boolean; { Test auf "Zeichen bereit" }
- { $0C } Function FlushRead(FuncNo: Byte): Char;
- { $0D } Procedure DriverFlush0D; { vor Diskettenwechsel }
- { $0E } Procedure SetDefaultDrive(NewDrive: Byte); { Standardlaufwerk setzen }
- { $0F } Procedure OpenFileFCB(FCB: Pointer); { CP/M-kompatibles OPEN }
- { $10 } Procedure CloseFileFCB(FCB: Pointer); { CP/M-kompatibles CLOSE }
- { $11 } Procedure FindFirstCPM(StartFCB: Pointer); { Datei via FCB suchen }
- { $12 } Procedure FindNextCPM (NextFCB: Pointer); { weitere Dateien suchen }
- { $13 } Procedure DeleteFileFCB(FCB: Pointer); { CP/M-kompatibles Löschen }
- { $14 } Function ReadSequential(FCB: Pointer): Integer; { sequ. Lesen }
- { $15 } Function WriteSequential(FCB: Pointer): Integer; { sequ. Schreiben }
- { $16 } Procedure CreateFileFCB(FCB: Pointer); { CP/M-kompatibles CREATE }
- { $17 } Procedure RenameFCB(FCB: Pointer); { CP/M-kompatibles RENAME }
- { $18 } { nicht definiert }
- { $19 } Function GetCurrentDrive: Byte; { aktuelles Laufwerk }
- { $1A } Procedure SetDTA(DTA: Pointer); { setzt die DTA }
-
- Type { Von den Funktionen $1B und $1C zurückgelieferte Daten als Record }
- FATInfoType = Record
- SecsCluster: Word; { Sektoren pro Cluster }
- BytesSec: Word; { Bytes pro Sektor }
- NumCluster: Word; { Gesamtzahl Cluster }
- MediaID: Byte; { eigentlich: Zeiger auf Media-ID }
- end;
- { $1B } Procedure GetCurrFATInfo(var Info: FATInfoType);
- { $1C } Procedure GetAnyFATInfo(var Info: FATInfoType; DiskNum: Byte);
- { $1D } { undefiniert }
- { $1E } { undefiniert }
- { $1F } Function GetCurrentDPB: Pointer; { aktuellen DPB ermitteln }
- { $20 } { undefiniert }
- { $21 } Function ReadFCBRand(FCB: FCBPointer; RecNo: LongInt): Integer;
- { $22 } Function WriteFCBRand(FCB: FCBPointer; RecNo: LongInt): Integer;
- { $23 } Function GetFileSizeFCB(FCBPtr: FCBPointer): LongInt;
- { $24 } Procedure SetRandRecNo(FCB: FCBPointer);
-
- { ------- DOS-Funktionen --------- }
- { $25 - DOS - Procedure SetIntVec(IntNo: Byte; Vector: Pointer); }
- { $26 } Procedure MakeNewPSP(PSPAddr: Word);
- { $27 } Function ReadRandRecs(FCB: FCBPointer; FirstRec: LongInt;
- NumBlocks: Word): Integer;
- { $28 } Function WriteRandRecs(FCB: FCBPointer; FirstRec: LongInt;
- NumBlocks: Word): Integer;
- { $29 } Function ParseFName(CmdLine: Pointer; FCBAddr: Pointer): Pointer;
- { $2A - DOS - Procedure GetDate(var Year,Month,Day,DayofWeek: Word); }
- { $2B } Procedure SetDate(Year,Month,Day: Word); { setzt DosError }
- { $2C - DOS - Procedure GetTime(var Hour, Minute, Second, Sec100: Word); }
- { $2D } Procedure SetTime(Hour,Minute,Second,Sec100: Word);
- { $2E - DOS - Procedure SetVerify(Verify: Boolean); }
- { $2F } Function GetDTA: Pointer; { Ermittelt die momentane DTA }
- { $30 } Function DosVersion: Word; { echte Versionsnummer }
- { $31 - DOS - Procedure Keep(ExitCode: Word); }
- { $32 } Function GetAnyDPB(DriveNo: Byte): Pointer;
- { $3300 - DOS - Procedure GetCBreak(var Break: Boolean); }
- { $3301 - DOS - Procedure SetCBreak(Break: Boolean); }
- { $3302 } Function SwapCBreak(NewBreak: Boolean): Boolean;
- { $3305 } Function GetBootDrive: Byte;
- { $3306 } Function GetDosHIGH: Boolean; { (zusätzlich: Versionsnummer) }
- { $34 } Procedure GetDOSFlags(var InDosPtr, CritErrPtr);
- { $35 - DOS - Procedure GetIntVec(IntNo: Byte; var Vector: Pointer); }
- { $36 - DOS - Function DiskFree(Drive: Byte): LongInt; }
- { $3700 } Function GetSwitChar: Char; { Trennzeichen ermitteln }
- { $3701 } Function SetSwitChar(NewSwitch: Char): Boolean;
- { $3702 } Function GetDevAvail: Boolean;
- { $3703 } Procedure SetDevAvail(NewState: Boolean);
- { $38 } Function GetCountry(Mode: Byte; CountryNo: Word; var CInfo): Integer;
- Function SetCountry(CountryNo: Word): Boolean;
- { $39 - DOS - Procedure MkDir(s: String); }
- { $3A - DOS - Procedure RmDir(s: String); }
- { $3B - DOS - Procedure ChDir(s: String); }
- { $3C } Function CreateFile(s: String; Attrib: Byte): Word;
- { $3D } Function OpenFile(s: String): Word; { SHARE-Flags via FileMode }
- { $3E } Procedure CloseFile(Handle: Word); { schließt eine Datei }
- { $3F } Function ReadFile(FHandle: Word; Count: Word;
- BufPtr: Pointer): Word;
- { $40 } Procedure WriteFile(Handle,Count: Word; BufPtr: Pointer);
- { $41 - DOS - Procedure Erase(FileName: String); }
- { $42 } Function FileSeek(Handle: Word; Offset: LongInt;
- Action: Integer): LongInt;
- { $4300 - DOS - Function GetFAttr(FName: String): Word; }
- { $4301 - DOS - Procedure SetFAttr(FName: String; NewAttrs: Word); }
- { $4302 } Function GetFPass(FName: String): Byte; { nur DR-DOS }
- { $4303 } Procedure SetFPass(FName, Pass: String; Mode: Byte); { nur DR }
-
- { $4400 } Function GetDevAttributes(Handle: Word): Word;
- { $4401 } Procedure SetDevAttributes(Handle: Word; Attr: Word);
- { $4402 } Function IOCTLReadHandle(Handle, Count: Word;
- Buf: Pointer): Word;
- { $4403 } Function IOCTLWriteHandle(Handle, Count: Word;
- Buf: Pointer): Word;
- { $4404 } Function IOCTLReadBlock(Drive, Count: Word;
- Buf: Pointer): Word;
- { $4405 } Function IOCTLWriteBlock(Drive, Count: Word;
- Buf: Pointer): Word;
- { $4406 } Function IOCTLInReady(Handle: Byte): Boolean;
- { $4407 } Function IOCTLOutReady(Handle: Byte): Boolean;
- { $4408 } Function IOCTLChangeable(Drive: Byte): Boolean;
- { $4409 } Function IOCTLDevLocal(Drive: Byte): Word;
- { $440A } Function IOCTLHandleLocal(Handle: Word): Word;
- { $440B } Procedure IOCTLSetRetry(Repeats, Counter: Word);
- { $440C } Procedure IOCTLGenericHandle(Handle,Category,Subcode: Byte;
- var ParmBlock);
- { $440D } Procedure IOCTLGenericBlock(Drive,Subcode: Byte; var ParmBlock);
- { $440E } Function IOCTLGetLogMap(Drive: Byte): Byte;
- { $440F } Procedure IOCTLSetLogMap(NewDrive: Byte);
- { $4410 } Function IOCTLSupportH(Handle: Word; Categorie, Subcode: Byte): Boolean;
- { $4411 } Function IOCTLSupportB(Drive: Word; Subcode: Byte): Boolean;
-
- { $45 } Function DupHandle(Handle: Word): Word;
- { $46 } Procedure SetHandle2(Handle1, Handle2: Word);
- { $47 - DOS - Procedure GetDir(Drive: Byte; var s: String); }
- { $48 } Function GetMemBlock(Size: LongInt): Word;
- Function GetFreeMainMem: LongInt;
- { $49 } Procedure FreeMemBlock(BlockSeg: Word);
- { $4A } Procedure SetMemBlock(BlockSeg,BlockSize: Word);
- { $4B00 - DOS - Procedure Exec(Path, CmdLine: String); }
- { $4B01 } Procedure ExecLoad(Path, CmdLine: String; var ProgRegs);
- { $4B02 } { undefiniert }
- { $4B03 } Procedure LoadOverlay(Name: String);
- { $4B04 } { undefiniert }
- { $4B05 } { funktioniert leider noch nicht! }
- { $4C - DOS - Procedure TerminateProcess(ExitCode: Byte); }
- { $4D - DOS - Function DosExitCode: Word; }
- { $4E - DOS - Procedure FindFirst(Path: String;
- Attr: Word; var S: SearchRec); }
- { $4F - DOS - Procedure FindNext(var S: SearchRec); }
- { $50 } Procedure SetActivePSP(PSPSeg: Word); { Aktives PSP setzen }
- { $51 } Function GetPSPAddr51 : Word;
- { $52 } Function GetDosDataArea: Pointer;
- { $53 } Procedure MakeDPB(DriveNo: Byte; DPB: Pointer);
- { $54 - DOS - Procedure GetVerify(var Verify: Boolean); }
- { $55 } Procedure CreateNewPSP(NewSeg, MemTop: Word);
- { $56 - DOS - Procedure Rename(var F; NewName: String); }
- { $5700 - DOS - Procedure GetFTime(var F; Time: LongInt; }
- { $5701 - DOS - Procedure SetFTime(var F; Time: LongInt; }
- { $5800 } Function GetAllocStrat: Byte;
- { $5801 } Procedure SetAllocStrat(Strat: Byte);
- { $5802 } Function GetUMBLink: Boolean;
- { $5803 } Procedure SetUMBLink(LinkState: Boolean);
-
- { $59 } Procedure GetExtError; { setzt die Variable ExtErrInfo }
- { $5A } Function TmpFile(Path: PathStr): String;
- { $5B } Function CreateNewFile(Name: String): Word;
-
- { $5C00 } Procedure Lock(var F; Offset, Len: LongInt);
- { $5C01 } Procedure Unlock(var F; Offset, Len: LongInt);
-
- { $5D00 } Procedure ServerCall(Params: ServerCallBlock);
- { $5D01 } Procedure UpdateAllFiles;
- { $5D02 } Procedure CloseFileName(FName: String);
- { $5D03 } Procedure CloseMachineFiles(StatID: Word);
- { $5D04 } Procedure CloseProcessFiles(ProcPSP: Word);
- { $5D05 } Procedure GetSHAREEntry(SHIndex, SFTIndex: Word;
- var Regs: Registers);
- { $5D06 } Procedure GetDosVars(var p: Pointer; var Header,MaxSize: Word);
- { $5D07 } Function RedirPrinterGetJob: Boolean;
- { $5D08 } Procedure RedirPrinterSetJob(Join: Boolean);
- { $5D09 } Procedure RedirPrinterNewJob;
- { $5D0A } Procedure SetExtError(ErrCode,Class,
- Locus,Action: Word; p: Pointer);
- { $5E00 } Function GetStationName(var Number: Byte;
- var Name: String): Boolean;
- { $5E01 } Procedure SetStationName(Number: Byte; Name: String);
- { $5E02 } Procedure ReDirPrinterSetInit(DevName: String; InitStr: String);
- { $5E03 } Function ReDirPrinterGetInit(DevName: String): String;
- { $5E04 } Procedure ReDirPrinterSetTabs(DevName: String; Tabs: Boolean);
- { $5E05 } Function ReDirPrinterGetTabs(DevName: String): Boolean;
- { $5F00 } Function ReDirPrinterGetMode: Boolean;
- Function ReDirDriveGetMode : Boolean;
- { $5F01 } Procedure ReDirPrinterSetMode(Mode: Boolean);
- Procedure ReDirDriveSetMode(Mode: Boolean);
- { $5F02 } Function ReDirGetEntry(LocalName: string;
- var NetName: String): Integer;
- { $5F03 } Procedure ReDirSetEntry(DevCode: Byte; UserVal: Word;
- LocalName, NetName: String);
- { $5F04 } Procedure ReDirDeleteEntry(LocalName: String);
- { $5F05 } Function GetDirGetExtEntry(LocalName: string;
- var NetName: String; var NetBIOSNo: Word): Integer;
- { $5F06 - *** existiert - Arbeitsweise bis dato unbekannt *** }
- { $5F07 } Function ActivateLocalDrive(Drive: Byte): Boolean;
- { $5F08 } Function DeactivateLocalDrive(Drive: Byte): Boolean;
-
- { $60 } Function RealFName(FName: String): String; { echter Dateiname }
- { $61 } { undefiniert }
- { $62 } Function GetActivePSP : Word; { Liefert aktives PSP }
- { $63 } { Ih Minh Hoho Tschi! }
- { $64 } Procedure SetPRINTFlag(NewVal: Byte);
- { $6500 } { undefiniert }
- { $6501 } Procedure GetExtCountryInfo(CCode,CodeP: Integer;
- var CountryRec: Func6501Country);
- { $6502 } Procedure GetASCIIHiXLate(var Size: Word; var TablePtr);
- { $6503 } { undefiniert }
- { $6504 } Procedure GetFNamecase(var Size: Word; var TablePtr);
- { $6505 } Procedure GetFNameTerminators(var Size: Word; var TablePtr);
- { $6506 } Procedure GetSortTable(var Size: Word; var TablePtr);
- { $6507 } Procedure GetDBCSTable(var Size: Word; var TablePtr);
- { $6520 } Function Upcase6520(Ch: Char): Char;
- { $6521 } Function Upcase6521(s: String): String;
- { $6522 } Procedure Upcase6522(s: Pointer); { Umsetzung ASCIIZ-String }
- { $6523 } Function Query6523(Ch: Char): Integer;
-
- { $6600 } { undefiniert }
- { $6601 } Procedure GetCodePage(var CurrPage, SysPage: Word);
- { $6602 } Procedure SetCodePage(NewPage: Word);
-
- { $67 } Procedure SetHandleCount(Handles: Word);
- { $68 } Procedure UpdateFile(Handle: Word);
- { $6900 } Procedure GetDiskSerialNo(Drive: Byte; var Buf: DiskSerialInfo);
- { $6901 } Procedure SetDiskSerialNo(Drive: Byte; var Buf: DiskSerialInfo);
-
- { $6A } { *** existiert, Arbeitsweise vorläufig unbekannt *** }
- { $6B } { undefiniert }
- { $6C } Function CreateExtended(FName: String; Attr: Word;
- Action: Byte): Word; { = Handle }
-
-
- { *********************************************** }
- Implementation
- { *********************************************** }
- var DRDos341, DRDos500: Boolean; { durch Initialisierungsteil gesetzt }
- CurrDosVersion: Word; { echte DOS-Version, dito }
-
- { Speichert bei jedem Aufruf den als NewVal übergebenen Wert in seinem
- Codesegment und liefert den dort zuletzt gespeicherten Wert zurück.
- ACHTUNG: Diese Funktion darf *nicht* rein als INLINE codiert werden,
- weil sonst jeder Aufruf eine separate Kopie des Codes erzeugen würde!
- }
- Function SwapValInCS(NewVal: Word): Word;
- begin
- inline($8B/$46/<NewVal/ { mov ax,NewVal[bp] }
- $E8/$02/$00/ { call L1 ; @(nop/nop) -> Stack }
- $90/$90/ { nop / nop ; Speicherplatz(!) }
- $5B/ { L1: pop bx ; RET-Adresse als Zeiger }
- $2E/$87/$07/ { xchg ax,cs:[bx] ; Austausch }
- $89/$46/$FE { mov [bp-2],ax ; Fkt-Ergebnis }
- );
- end;
-
- { Aufruf des residenten Teils von COMMAND über INT $2E }
- Procedure CallCommand(Cmd: String);
- Const
- TurboSS : Word = 0; { zum Sichern von SS,SP und BP }
- TurboSP : Word = 0;
- TurboBP : Word = 0;
- var Regs: Registers;
- OrgProgSize: Word; { Originalgröße des Programms }
- begin
- OrgProgSize := Word(Ptr(PrefixSeg,$02)^) - PrefixSeg;
- { Reduktion des Programms auf die tatsächliche Größe }
- SetMemBlock(PrefixSeg,Seg(HeapPtr^)-PrefixSeg);
- Cmd[Length(Cmd)+1] := #13; { RET-Zeichen anhängen }
- TurboSS := SSeg;
- inline($89/$2E/TurboBP); { mov [TurboBP],BP - BP festhalten }
- if SwapValInCS(DSeg) <> 0 then ; { DS sichern }
- inline
- ($16/$1F/ { push ss; pop ds ; DS:SI = @Cmd }
- $8D/$36/Cmd/ { lea si,[Cmd] }
- $CD/$2E { int $2E ; Ausführung }
- );
- if SwapValInCS(0) <> 0 then ; { liefert DS in AX zurück }
- inline
- ($8E/$D8/ { mov ds,ax ; Turbo-DS }
- $8E/$16/TurboSS/ { mov ss,TurboSS ; Turbo-SS }
- $8B/$26/TurboSP/ { mov sp,TurboSP ; Turbo-SP }
- $8B/$2E/TurboBP { mov bp,TurboBP ; Turbo-BP }
- );
- SetMemblock(PrefixSeg,OrgProgSize); { zurück auf Originalgröße }
- end;
-
- { Sucht die Treiber-Kette von DOS ab und ermittelt das Attribut
- sowie die Aufrufadressen der Strategie- und Interrupt-Routinen.
- Bei Aufruf mit einem Nullstring wird der zuletzt eingebaute
- Blocktreiber lokalisiert, ansonsten gehts um Zeichentreiber.
- }
- Function LocateDriver(DriverName: String): DriverPointer;
- var Regs: Registers;
- DHead: DriverPointer; { Zeiger auf den aktuellen Treiberkopf }
- DosV: Word; { Dos-Versionsnummer, umgedreht }
- SearchBlock: Boolean;
- begin
- if Length(DriverName) = 0 then SearchBlock := True
- else
- begin { Treibernamen auf volle Länge bringen, soweit notwendig }
- while Length(DriverName) < 8 do DriverName := DriverName + ' ';
- SearchBlock := False;
- end;
-
- { DOS-Datenbereich ermitteln. Je nach Version steht der Kopf der
- Treiberkette (Gerät NUL) hier ab dem Offset $17, $28 oder $22:
- }
- Regs.AH := $52; Intr($21,Regs); { DOS-Datenbereich }
- DosV := Swap(DosVersion); { $1403 (20.3) -> $0314 (3.20) }
- if DosV < $0300 then DHead := Ptr(Regs.ES,Regs.BX+$17)
- else if DosV < $030A then DHead := Ptr(Regs.ES,Regs.BX+$28)
- else DHead := Ptr(Regs.ES,Regs.BX+$22); { Version 4.x, 5.0 }
-
- { Hat die Sache geklappt? }
- if DHead^.Name <> 'NUL ' then { 'NUL'+ 5 Leerzeichen }
- begin
- Writeln('Kopf der Treiberkette (NUL) nicht gefunden!');
- Writeln('Welches Betriebssystem ist das?');
- Halt;
- end;
-
- { Absuchen der Kette nach dem entsprechenden Gerät oder dem
- zuletzt eingebauten Blocktreiber }
- while (not SearchBlock and (DHead^.Name <> DriverName)) or
- (SearchBlock and ((DHead^.DAttr and $8000) <> 0)) do
- begin
- DHead := DHead^.DNext; { nächster Treiberkopf }
- if Ofs(DHead^) = $FFFF then { Kettenende? }
- begin
- LocateDriver := NIL; Exit;
- end;
- end;
- LocateDriver := DHead;
- end;
-
- { Ruft LocateDriver auf und stellt die Ergebnisse dar }
- Procedure GetDriver (DriverName: String; var Attributes: Word;
- var Strategy: Pointer; var Intrupt: Pointer);
- var DHead : DriverPointer;
- begin
- DHead := LocateDriver(DriverName);
- if DHead = NIL then
- begin
- Writeln('Treiber ', DriverName,' nicht gefunden!');
- Halt;
- end;
- if DriverName = ''
- then Writeln('Blocktreiber für ',Ord(DHead^.Drives),
- ' Laufwerke gefunden.')
- else Writeln('Zeichentreiber "',DriverName,'" gefunden.');
- Attributes := DHead^.DAttr;
- Strategy := Ptr(Seg(DHead^),DHead^.DStrat);
- Intrupt := Ptr(Seg(DHead^),DHead^.DIntr);
- Writeln('Attribute: $',HexW(Attributes),
- ', Strategie: $',HexP(Strategy),
- ', Interrupt: $',HexP(Intrupt));
- end;
- Procedure ShowExtError;
- begin
- GetExtError; { setzt die Variable ExtErrInfo }
- with ExtErrInfo do
- Writeln('Extended Error - Code: ',Code,', Klasse: ',Class,
- ', Ort: ',Locus,', Aktion: ',Action,
- ', Ptr: $',HexP(ExtPointer));
- end;
-
-
- Function HexB(b: Byte): String;
- var x: Integer;
- begin
- HexB[0] := #2; { Längenbyte direkt setzen }
- for x := 2 downto 1 do
- begin
- if b and $0F > 9 then HexB[x] := Chr((b and $0F)-10+Ord('A'))
- else HexB[x] := Chr((b and $0F)+Ord('0'));
- b := b shr 4;
- end;
- end;
-
- Function HexW(w: Word): String;
- begin HexW := HexB(Hi(w)) + HexB(Lo(w)); end;
-
- Function HexP(p: Pointer): String;
- begin HexP := HexW(LongInt(p) shr 16) + ':' + HexW(LongInt(p)); end;
-
- Function HexL(l: LongInt): String;
- begin HexL := HexW(l shr 16) + HexW(l); end;
-
- Function StrtoZ(PascalStr: String): String; { Pascal -> ASCIIZ }
- begin
- StrtoZ := PascalStr + #0;
- end;
-
- Function ZtoStr(ZStr: Pointer): String;
- Type
- CharArray = Array[1..254] of Char;
- CharPtr = ^CharArray;
- var x, Len: Byte;
- begin
- Len := Pos(#0,CharPtr(ZStr)^)-1;
- ZtoStr[0] := Chr(Len);
- for x:= 1 to Len do ZtoStr[x] := CharPtr(ZStr)^[x];
- end;
-
- Procedure AbsRead(Drive: Byte; DTA: Pointer;
- StartSec: LongInt; NumSecs: Word);
- var Regs: Registers;
- ParmBlock: Record { für DR-DOS 3.41, 5.0 sowie MS-DOS ab 4.0 }
- SSec: LongInt; { Start-Sektor (long) }
- NSecs: Word; { Anzahl Sektoren }
- Target: Pointer; { Zielpuffer }
- end;
- begin
- if (Swap(CurrDosVersion) < $0329) { MS-DOS 2.x, 3.x }
- then inline
- ($1E/ { asm push ds }
- $8A/$46/<Drive/ { mov al,[Drive] ; 0=A:,1=B: usw. }
- $8B/$4E/<NumSecs/ { mov cx,[NumSecs] ; Anzahl Sektoren }
- $8B/$56/<StartSec/ { mov dx,[StartSec] ; erster Sektor }
- $C5/$5E/<DTA/ { lds bx,[DTA] ; DS:BX = Zielpuffer }
- $55/ { PUSH BP ; wird von 3.x zerstört! }
- $CD/$25/ { int $25 ; Aufruf }
- $59/ { pop cx ; STACK-KORREKTUR }
- $5D/ { POP BP ; BP wieder zurück }
- $72/$02/ { jb @L1 ; -> Fehler }
- $30/$C0/ { xor al,al ; sonst Status = 0 }
- $30/$E4/ { @L1:xor ah,ah ; AH = undefiniert }
- $1F/ { pop ds }
- $A3/DosError { mov [DosError],ax ; Status setzen }
- )
- else
- with ParmBlock do
- begin
- SSec := StartSec; NSecs := NumSecs; Target := DTA;
- inline
- ($1E/ { asm push ds }
- $8A/$46/<Drive/ { mov al,[Drive] ; 0=A:,1=B: usw. }
- $16/ { push ss ; DS:BX = @ParmBlock }
- $1F/ { pop ds ; (auf dem Stack) }
- $8D/$5E/<ParmBlock/{ lea bx,[ParmBlock] ; (Offset-Anteil) }
- $B9/$FFFF/ { mov cx,$FFFF ; Flag für ParmBlock }
- $CD/$25/ { int $25 ; Aufruf }
- $59/ { pop cx ; STACK-KORREKTUR }
- $72/$02/ { jb @L1 ; -> Fehler }
- $30/$C0/ { xor al,al ; sonst Status = 0 }
- $30/$E4/ { @L1:xor ah,ah ; AH = undefiniert }
- $1F/ { pop ds }
- $A3/DosError { mov [DosError],ax ; Status setzen }
- )
- end; { with ParmBlock }
- end;
-
- Procedure AbsWrite(Drive: Byte; DTA: Pointer;
- StartSec: LongInt; NumSecs: Word);
- var Regs: Registers;
- ParmBlock: Record { für DR-DOS 3.41, 5.0 sowie MS-DOS ab 4.0 }
- SSec: LongInt; { Start-Sektor (long) }
- NSecs: Word; { Anzahl Sektoren }
- Target: Pointer; { Quellpuffer }
- end;
- begin
- if (Swap(CurrDosVersion) < $0329) { MS-DOS 2.x, 3.x }
- then inline
- ($1E/ { asm push ds }
- $8A/$46/<Drive/ { mov al,[Drive] ; 0=A:,1=B: usw. }
- $8B/$4E/<NumSecs/ { mov cx,[NumSecs] ; Anzahl Sektoren }
- $8B/$56/<StartSec/ { mov dx,[StartSec] ; erster Sektor }
- $C5/$5E/<DTA/ { lds bx,[DTA] ; DS:BX = Zielpuffer }
- $55/ { PUSH BP ; wird von 3.x zerstört! }
- $CD/$26/ { int $26 ; Aufruf }
- $59/ { pop cx ; STACK-KORREKTUR }
- $5D/ { POP BP ; BP wieder zurück }
- $72/$02/ { jb @L1 ; -> Fehler }
- $30/$C0/ { xor al,al ; sonst Status = 0 }
- $30/$E4/ { @L1:xor ah,ah ; AH = undefiniert }
- $1F/ { pop ds }
- $A3/DosError { mov [DosError],ax ; Status setzen }
- )
- else
- with ParmBlock do
- begin
- SSec := StartSec; NSecs := NumSecs; Target := DTA;
- inline
- ($1E/ { asm push ds }
- $8A/$46/<Drive/ { mov al,[Drive] ; 0=A:,1=B: usw. }
- $16/ { push ss ; DS:BX = @ParmBlock }
- $1F/ { pop ds ; (auf dem Stack) }
- $8D/$5E/<ParmBlock/{ lea bx,[ParmBlock] ; (Offset-Anteil) }
- $B9/$FFFF/ { mov cx,$FFFF ; Flag für ParmBlock }
- $CD/$26/ { int $26 ; Aufruf }
- $59/ { pop cx ; STACK-KORREKTUR }
- $72/$02/ { jb @L1 ; -> Fehler }
- $30/$C0/ { xor al,al ; sonst Status = 0 }
- $30/$E4/ { @L1:xor ah,ah ; AH = undefiniert }
- $1F/ { pop ds }
- $A3/DosError { mov [DosError],ax ; Status setzen }
- )
- end; { with ParmBlock }
- end;
-
- { --------------- CP/M-kompatible DOS-Funktionen ---------- }
- { Eingabe eines Zeichens über die DOS-Funktion $01 }
- Function GetChar01: Char;
- var Regs: Registers;
- begin
- Regs.AH := $01; { Funktionsnummer }
- Intr($21,Regs); { DOS-Aufruf }
- GetChar01 := Chr(Regs.AL); { ASCII-Code }
- end;
-
- { Ausgabe eines Zeichens über die DOS-Funktion $02 }
- Procedure PutChar02(Ch: Char);
- var Regs: Registers;
- begin
- Regs.AH := $02; { Funktionsnummer }
- Regs.DL := Ord(Ch); { ASCII-Code des Zeichens }
- Intr($21,Regs); { DOS-Aufruf }
- end;
-
- { Eingabe eines Zeichens über die serielle Schnittstelle via DOS }
- Function GetChar03: Char;
- var Regs: Registers;
- begin
- Regs.AH := $03; { Funktionsnummer }
- Intr($21,Regs);
- GetChar03 := Chr(Regs.AL); { ASCII-Code des Zeichens }
- end;
-
- { Ausgabe eines Zeichens über die serielle Schnittstelle via DOS }
- Procedure PutChar04(Ch: Char);
- var Regs: Registers;
- begin
- Regs.AH := $04; { Funktionsnummer }
- Regs.DL := Ord(Ch); { auszugebendes Zeichen }
- Intr($21,Regs);
- end;
-
- { Ausgabe eines Zeichens zum Drucker via DOS }
- Procedure PutChar05(Ch: Char);
- var Regs: Registers;
- begin
- Regs.AH := $05; { Funktionsnummer }
- Regs.DL := Ord(Ch); { auszugebendes Zeichen }
- Intr($21,Regs);
- end;
-
- { Eingabe eines Zeichens über die DOS-Funktion $06 }
- Function GetChar06: Char;
- var Regs: Registers;
- begin
- Regs.AH := $06; { Funktionsnummer }
- Regs.DL := $FF; { Flag für Eingabe }
- Intr($21,Regs); { DOS-Aufruf }
- if Regs.Flags and FZero = 0
- then GetChar06 := Chr(Regs.AL) { ASCII-Code des Zeichens }
- else GetChar06 := Chr(255);
- end;
-
- { Ausgabe eines Zeichens über die DOS-Funktion $06 }
- Procedure PutChar06(Ch: Char);
- var Regs: Registers;
- begin
- Regs.AH := $06; { Funktionsnummer }
- Regs.DL := Ord(Ch); { auszugebendes Zeichen }
- Intr($21,Regs); { DOS-Aufruf }
- end;
-
- { Eingabe eines Zeichens über die DOS-Funktion $07 }
- Function GetChar07: Char;
- var Regs: Registers;
- begin
- Regs.AH := $07; { Funktionsnummer }
- Intr($21,Regs); { DOS-Aufruf }
- GetChar07 := Chr(Regs.AL); { ASCII-Code des Zeichens }
- end;
-
- { Eingabe eines Zeichens über die DOS-Funktion $08 }
- Function GetChar08: Char;
- var Regs: Registers;
- begin
- Regs.AH := $08; { Funktionsnummer }
- Intr($21,Regs); { DOS-Aufruf }
- GetChar08 := Chr(Regs.AL); { ASCII-Code des Zeichens }
- end;
-
- Procedure WriteString09(s: String);
- var Regs: Registers;
- begin
- s := s + '$'; { Abschlußzeichen anhängen }
- Regs.AH := $09; { Funktionsnummer }
- Regs.AL := 0; { unnötig - nur zur Demonstration }
- Regs.DS := Seg(s); { Segmentadresse des Strings (Stack) }
- Regs.DX := Ofs(s)+1; { Offsetadresse des Strings (Stack), ohne Längenbyte! }
- Intr($21,Regs);
- end;
-
- Function ReadString0A(MaxLen: Integer): String;
- Type CharArray = Array[1..257] of Char;
- var p: ^CharArray;
- Regs: Registers;
- begin
- if MaxLen > 255 then MaxLen := 255; { Begrenzung }
- GetMem(p,MaxLen+2); { Puffer erzeugen }
- p^[1] := Chr(MaxLen); { Eintrag der Maximallänge }
- Regs.Ah := $0A; { Funktionsnummer }
- Regs.DX := Ofs(p^); { Startadresse des Puffers }
- Regs.DS := Seg(p^);
- Intr($21, Regs); { DOS-Aufruf }
-
- ReadString0A := String(Ptr(Regs.DS,Regs.DX+1)^); { ab 2. Byte }
- FreeMem(p,MaxLen+2);
- end;
-
- { Test auf "Zeichen bereit" - funktioniert auch bei Umleitungen }
- Function CharAvailable: Boolean;
- var Regs: Registers;
- begin
- Regs.AH := $0B;
- Intr($21,Regs);
- CharAvailable := (Regs.AL = 255);
- end;
-
- { Clear Keyboard and Input - DOS-Funktion $0C }
- Function FlushRead(FuncNo: Byte): Char;
- var Regs: Registers;
- begin
- Regs.AH := $0C; Regs.AL := FuncNo;
- Regs.DL := $FF; { nur für Funktion $06 }
- Intr($21,Regs);
- if (FuncNo = $06) and ((Regs.Flags and FZero <> 0))
- then FlushRead := Chr($FF)
- else FlushRead := Chr(Regs.AL);
- end;
-
- { Erzwingt das physikalische Schreiben der Treiber-Puffer }
- Procedure DriverFlush0D;
- var Regs: Registers;
- begin
- Regs.AH := $0D;
- Intr($21,Regs);
- end;
-
- Procedure SetDefaultDrive(NewDrive: Byte);
- var Regs: Registers;
- begin
- Regs.AH := $0E;
- Regs.DL := NewDrive;
- Intr($21,Regs);
- end;
-
- Procedure OpenFileFCB(FCB: Pointer); { CP/M-kompatibles OPEN }
- var Regs: Registers;
- begin
- with Regs do
- begin
- AH := $0F; { Funktion: "Open File via FCB" }
- DS := Seg(FCB^); DX := Ofs(FCB^);
- Intr($21,Regs);
- if AL <> 0 then InOutRes := 2; { "Datei nicht gefunden" }
- end;
- end;
-
- Procedure CloseFileFCB(FCB: Pointer); { CP/M-kompatibles CLOSE }
- var Regs: Registers;
- begin
- Regs.AH := $10; { Funktion: Close File (FCB) }
- Regs.DS := Seg(FCB^);
- Regs.DX := Ofs(FCB^); { DS:DX = FCB-Adresse }
- Intr($21,Regs);
- if Regs.AL <> 0 then InOutRes := 6; { "Handle" existiert nicht }
- end;
-
- Procedure FindFirstCPM(StartFCB: Pointer); { Datei via FCB suchen }
- var Regs : Registers;
- begin
- Regs.AH := $11; { Funktion: "Find First [Entry]" }
- Regs.DS := Seg(StartFCB^);
- Regs.DX := Ofs(StartFCB^); { DS:DX = FCB-Adresse }
- Intr($21,Regs);
- if Regs.AL = 0 then DosError := 0
- else DosError := 18; { "keine weiteren Einträge" }
- end;
-
- Procedure FindNextCPM (NextFCB: Pointer); { weitere Dateien suchen }
- var Regs : Registers;
- begin
- Regs.AH := $12; { Funktion: "Find Next [Entry]" }
- Regs.DS := Seg(NextFCB^);
- Regs.DX := Ofs(NextFCB^);
- Intr($21,Regs);
- if Regs.AL = 0 then DosError := 0
- else DosError := 18;
- end;
-
- Procedure DeleteFileFCB(FCB: Pointer); { CP/M-kompatibles Löschen }
- var Regs: Registers;
- begin
- Regs.AH := $13; { Funktionsnummer }
- Regs.DS := Seg(FCB^); { DS:DX = FCB-Adresse }
- Regs.DX := Ofs(FCB^);
- Intr($21, Regs);
- if Regs.AL <> 0
- then InOutRes := 2; { "Datei nicht gefunden" }
- end;
-
- Function ReadSequential(FCB: Pointer): Integer; { sequ. Lesen }
- var Regs: Registers;
- begin
- Regs.AH := $14; { DOS-Funktion: Read Sequential via FCB }
- Regs.DS := Seg(FCB^); { DS:DX = FCB }
- Regs.DX := Ofs(FCB^);
- Intr($21,Regs); { liest $80 Bytes in die Standard-DTA }
- ReadSequential := Regs.AL;
- end;
-
- Function WriteSequential(FCB: Pointer): Integer; { sequ. Schreiben }
- var Regs: Registers;
- begin
- Regs.AH := $15; { DOS-Funktion: Write Sequential via FCB }
- Regs.DS := Seg(FCB^); { DS:DX = FCB }
- Regs.DX := Ofs(FCB^);
- Intr($21,Regs); { schreibt RecSize Bytes aus der Standard-DTA }
- WriteSequential := Regs.AL;
- end;
-
- Procedure CreateFileFCB(FCB: Pointer); { CP/M-kompatibles CREATE }
- var Regs: Registers;
- begin
- Regs.AH := $16; { Funktionsnummer }
- Regs.DS := Seg(FCB^); { DS:DX = FCB }
- Regs.DX := Ofs(FCB^);
- Intr($21,Regs);
- if Regs.AL <> 0
- then InOutRes := 5; { "Zugriff verweigert" }
- end;
-
- Procedure RenameFCB(FCB: Pointer); { Funktion $17 }
- var Regs: Registers;
- begin
- with Regs do
- begin
- AH := $17; { Funtion: "Rename via FCB" }
- DS := Seg(FCB^); DX := Ofs(FCB^); { DS:DX = FCB }
- Intr($21,Regs);
- if AL <> 0 then InOutRes := 2; { "Datei nicht gefunden" }
- end;
- end;
-
- { Liefert die Kennziffer des aktuellen Laufwerks zurück. }
- Function GetCurrentDrive: Byte;
- var Regs: Registers;
- begin
- Regs.AH := $19; { Funktionsnummer }
- Intr($21,Regs);
- GetCurrentDrive := Regs.AL;
- end;
-
- Procedure SetDTA(DTA: Pointer); { setzt die DTA }
- var Regs: Registers;
- begin
- Regs.AH := $1A; { Funktion: "Set DTA Address" }
- Regs.DS := Seg(DTA^); Regs.DX := Ofs(DTA^);
- Intr($21,Regs);
- end;
-
- Procedure GetCurrFATInfo(var Info: FATInfoType); { Funktion $1B }
- var Regs: Registers;
- begin
- Regs.AH := $1B; { Funktionsnummer }
- Intr($21,Regs); { Aufruf }
- with Info do
- begin
- SecsCluster := Regs.AL; { Sektoren pro Cluster }
- BytesSec := Regs.CX; { Bytes pro Sektor }
- NumCluster := Regs.DX; { Gesamtzahl Cluster }
- MediaID := Byte(Ptr(Regs.DS,Regs.BX)^);
- end;
- end;
-
- Procedure GetAnyFATInfo(var Info: FATInfoType; DiskNum: Byte); { Funktion $1C }
- var Regs: Registers;
- begin
- Regs.AH := $1C; { Funktion: "Get FAT Info, Any Drive" }
- Regs.DL := DiskNum; { Laufwerks-Kennziffer }
- Intr($21,Regs); { Aufruf }
- with Info do
- begin
- SecsCluster := Regs.AL; { Sektoren pro Cluster }
- BytesSec := Regs.CX; { Bytes pro Sektor }
- NumCluster := Regs.DX; { Gesamtzahl Cluster }
- MediaID := Byte(Ptr(Regs.DS,Regs.BX)^);
- end;
- end;
-
- Function GetCurrentDPB: Pointer; { Funktion $1F }
- var Regs: Registers;
- begin
- Regs.AH := $1F; { inoffizielle Funktion: "Get DPB" }
- Intr($21,Regs);
- GetCurrentDPB := Ptr(Regs.DS,Regs.BX);
- end;
-
- Function ReadFCBRand(FCB: FCBPointer; RecNo: LongInt): Integer;
- var Regs: Registers;
- begin
- FCB^.RandRec := RecNo; { Eintrag der Recordnummer }
- Regs.AH := $21; { Funktion "Read Random" }
- Regs.DS := Seg(FCB^); { DS:DX = FCB }
- Regs.DX := Ofs(FCB^);
- Intr($21,Regs);
- ReadFCBRand := Regs.AL;
- end;
-
- Function WriteFCBRand(FCB: FCBPointer; RecNo: LongInt): Integer;
- var Regs: Registers;
- begin
- FCB^.RandRec := RecNo; { Eintrag der Recordnummer }
- Regs.AH := $22; { Write Random }
- Regs.DS := Seg(FCB^); { DS:DX = FCB }
- Regs.DX := Ofs(FCB^);
- Intr($21,Regs);
- WriteFCBRand := Regs.AL;
- end;
-
- Function GetFileSizeFCB(FCBPtr: FCBPointer): LongInt;
- var Regs: Registers;
- begin
- Regs.AH := $23; { Funktion: "Get File Size" }
- Regs.DS := Seg(FCBPtr^);
- Regs.DX := Ofs(FCBPtr^); { DS:DX auf die Adresse des FCB }
- FCBPtr^.Recsize := 1; { "Recordgröße" = 1 }
- FCBPtr^.RandRec := 0;
- Intr($21,Regs);
- if Regs.AL = 0 then GetFileSizeFCB := FCBPtr^.RandRec
- else GetFileSizeFCB := -1;
- end;
-
- Procedure SetRandRecNo(FCB: FCBPointer);
- var Regs: Registers;
- begin
- Regs.AH := $24; { Set Random Record }
- Regs.DS := Seg(FCB^); { DS:DX = FCB }
- Regs.DX := Ofs(FCB^);
- Intr($21,Regs);
- end;
-
- { Procedure SetIntVec - ist im Unit DOS - }
-
- Procedure MakeNewPSP(PSPAddr: Word); { Funktion $26 }
- var Regs: Registers;
- begin
- Regs.AH := $26; { Funktion: Create New PSP }
- Regs.DX := PSPAddr; { Segment des PSP }
- Intr($21,Regs);
- end;
-
- Function ReadRandRecs(FCB: FCBPointer; FirstRec: LongInt;
- NumBlocks: Word): Integer;
- var Regs: Registers;
- begin
- Regs.AH := $27; { Read Random Records }
- Regs.CX := NumBlocks; { Anzahl zu lesender Datensätze }
- FCB^.RandRec := FirstRec; { Nummer des ersten Datensatzes }
- Regs.DS := Seg(FCB^); { DS:DX = FCB }
- Regs.DX := Ofs(FCB^);
- Intr($21,Regs);
- ReadRandRecs := Regs.AL;
- end;
-
- Function WriteRandRecs(FCB: FCBPointer; FirstRec: LongInt;
- NumBlocks: Word): Integer;
- var Regs: Registers;
- begin
- Regs.AH := $28; { Write Random }
- Regs.CX := NumBlocks; { Anzahl zu schreibender Datensätze }
- Regs.DS := Seg(FCB^); { DS:DX = FCB }
- Regs.DX := Ofs(FCB^);
- FCB^.RandRec := FirstRec; { Nummer des ersten Records }
- Intr($21,Regs);
- WriteRandRecs := Regs.AL;
- end;
-
- Function ParseFName(CmdLine: Pointer; FCBAddr: Pointer): Pointer;
- var x: Integer; { Funktion $29 }
- Regs:Registers;
- begin
- with Regs do
- begin
- DS := Seg(CmdLine^); SI := Ofs(CmdLine^);
- ES := Seg(FCBAddr^); DI := Ofs(FCBAddr^);
- AH := $29; { Funktion: "Parse Filename" }
- AL := 1; { führende Trennz. ignorieren, alle Felder setzen }
- Intr($21,Regs);
- ParseFName := Ptr(DS,SI); { Zeiger auf 1. Zeichen nach Dateiname }
- end;
- end;
-
- { Procedure GetDate - ist im Unit DOS - }
-
- { Nachkonstruktion, setzt zusätzlich DosError }
- Procedure SetDate(Year,Month,Day: Word);
- var Regs: Registers;
- begin
- with Regs do
- begin
- AH := $2B; CX := Year;
- DH := Month; DL := Day;
- Intr($21,Regs);
- if AL = 0 then DosError := 0
- else DosError := 13; { Ungültige Daten }
- end
- end;
-
- { Procedure GetTime - ist im Unit DOS - }
-
- { Nachkonstruktion, setzt zusätzlich DosError }
- Procedure SetTime(Hour,Minute,Second,Sec100: Word);
- var Regs: Registers;
- begin
- with Regs do
- begin
- AH := $2D;
- CH := Hour; CL := Minute;
- DH := Second; DL := Sec100;
- Intr($21,Regs);
- if AL = 0 then DosError := 0
- else DosError := 13; { Ungültige Daten }
- end
- end;
-
- { Procedure SetVerify - ist im Unit DOS - }
-
- Function GetDTA: Pointer; { Ermittelt die momentane DTA }
- var Regs: Registers;
- begin
- Regs.AH := $2F; { Funktion "Get DTA Address" }
- Intr($21,Regs);
- GetDTA := Ptr(Regs.ES,Regs.BX);
- end;
-
- Function DosVersion: Word; { Liefert die echte DOS-Versionsnummer }
- var Regs: Registers;
- begin
- if DRDos341 then DosVersion := $2903 { "3.41" }
- else if DrDos500 then DosVersion := $3203 { "3.50" }
- else
- begin
- Regs.AX := $3306; Intr($21,Regs); { "Get DosVersion/Location" }
- if Regs.AX = $3306 then DosVersion := Regs.BX
- else
- begin
- Regs.AH := $30; Intr($21,Regs); DosVersion := Regs.AX;
- end;
- end;
- end;
-
- { Procedure Keep - ist im Unit DOS - }
-
- Function GetAnyDPB(DriveNo: Byte): Pointer; { Funktion $32 }
- var Regs: Registers;
- begin
- Regs.AH := $32; { inoffizielle Funktion: "Get DPB, Any Drive" }
- Regs.DL := DriveNo; { 0 = aktuelles Laufwerk, 1 = A: usw. }
- Intr($21,Regs);
- if Regs.AL <> $FF then GetAnyDPB := Ptr(Regs.DS,Regs.BX)
- else GetAnyDPB := nil;
- end;
-
- { Procedure GetCBreak - ist im Unit DOS - }
-
- { Procedure SetCBreak - ist im Unit DOS - }
-
- Function SwapCBreak(NewBreak: Boolean): Boolean; { Fkt. $3302 }
- var Regs: Registers;
- Temp: Boolean;
- begin
- Regs.AX := $3302; { Funktion: "Exchange Control Break" }
- Regs.DL := Ord(NewBreak);
- Intr($21,Regs);
- if Regs.AL <> $FF then SwapCBreak := Boolean(Regs.DL)
- else
- begin
- GetCBreak(Temp); SwapCBreak := Temp;
- SetCBreak(NewBreak);
- end;
- end;
-
- Function GetBootDrive: Byte; { Funktion $3305 }
- var Regs: Registers;
- begin
- Regs.AX := $3305; { Funktion: "Get Boot Drive" }
- Intr($21,Regs);
- GetBootDrive := Regs.DL;
- end;
-
- Function GetDosHIGH: Boolean; { Funktion $3306 }
- var Regs: Registers;
- begin
- Regs.AX := $3306; { Funktion: "Get DOS Location" }
- Intr($21,Regs);
- GetDosHIGH := (Regs.DX = $1000);
- end;
-
- Procedure GetDOSFlags(var InDosPtr, CritErrPtr); { Funktion $34 }
- var Regs: Registers;
- InDos, CritErr: ^Byte;
- begin
- with Regs do
- begin
- AH := $34; { inoffizielle Funktion: "Get InDos Flag Address" }
- Intr($21,Regs);
- InDos := Ptr(ES,BX);
- if Lo(DosVersion) = 2 { ein Byte davor }
- then CritErr := Ptr(Seg(InDos^)-1,Ofs(InDos^)+15)
- else if DosVersion = $0003
- then CritErr := Ptr(Seg(InDos^),Ofs(InDos^)+1)
- else { DOS-Version > 3.0 -> direkte Abfrage }
- begin
- AX := $5D06; Intr($21,Regs);
- CritErr := Ptr(DS,SI);
- end;
- end;
- Pointer(InDosPtr) := InDos; Pointer(CritErrPtr) := CritErr;
- end;
-
- { Procedure GetIntVec - ist im Unit DOS - }
-
- { Function DiskFree - ist im Unit DOS - }
-
- Function GetSwitChar: Char; { Funktion $3700 - Trennzeichen ermitteln }
- var Regs: Registers;
- begin
- Regs.AX := $3700; { undokumentierte Funktion: "Get Switchar" }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0
- then GetSwitChar := #0
- else GetSwitChar := Chr(Regs.DL);
- end;
-
- Function SetSwitChar(NewSwitch: Char): Boolean; { Funktion $3701 }
- var Regs: Registers;
- begin
- FillChar(Regs,SizeOf(Regs),0);
- Regs.AX := $3701; { undokumentierte Funktion: "Set Switchar" }
- Regs.DL := Ord(NewSwitch);
- Intr($21,Regs);
- SetSwitchar := (Regs.Flags and FCarry = 0); { TRUE für OK }
- if Regs.DL <> Ord(NewSwitch)
- then Regs.DL := 0;
- end;
-
- { Liefert TRUE, wenn Geräte auch ohne
- vorangestelltes \DEV verfügbar sind
- }
- Function GetDevAvail: Boolean; { Funktion $3702 }
- var Regs: Registers;
- begin
- Regs.AX := $3702; { undokumentierte Funktion: "Get DevAvail" }
- Intr($21,Regs);
- if Regs.AL = $FF { Funktion nicht unterstützt }
- then GetDevAvail := True
- else GetDevAvail := Regs.DL = $FF;
- end;
-
- { Versucht beim Aufruf mit FALSE, das Voranstellen von \DEV\
- vor Gerätenamen zwingend zu machen (und hat nur unter DOS 2.x
- ein sichtbares Resultat).
- }
- Procedure SetDevAvail(NewState: Boolean); { Funktion $3703 }
- var Regs: Registers;
- begin
- Regs.AX := $3703; { undokumentierte Funktion: "Set DevAvail" }
- if NewState then Regs.DL := $FF { Geräte direkt erreichbar }
- else Regs.DL := 0; { Geräte nur via \DEV\ erreichbar }
- Intr($21,Regs);
- end;
-
- Function GetCountry(Mode: Byte; CountryNo: Word; var CInfo): Integer;
- var Regs: Registers;
- begin
- Regs.AH := $38; { Funktion: "Get/Set Country Information" }
- Regs.AL := Mode; { 0 = aktuelles Land lesen, 1..254 Landescode }
- if Mode = 255 then Regs.BX := CountryNo; { 255: Landescode in BX }
- Regs.DS := Seg(CInfo);
- Regs.DX := Ofs(CInfo);
- Intr($21,Regs);
- if (Regs.Flags and FCarry) = 0 then GetCountry := Regs.BX
- else GetCountry := -1;
- end;
-
- Function SetCountry(CountryNo: Word): Boolean;
- var Regs: Registers;
- begin
- Regs.AH := $38; { Funktion: "Get/Set Country Info" }
- if CountryNo > 254 then
- begin
- Regs.AL := 255; Regs.BX := CountryNo;
- end
- else Regs.AL := CountryNo;
- Regs.DX := $FFFF; { *** Dieser Wert unterscheidet }
- Intr($21,Regs); { "Get" und "Set"! }
- SetCountry := (Regs.Flags and FCarry = 0); { TRUE f. OK }
- end;
-
- { Procedure MkDir - ist im Unit DOS - }
-
- { Procedure RmDir - ist im Unit DOS - }
-
- { Procedure ChDir - ist im Unit DOS - }
-
- { Ergebnis: Handle der Datei }
- Function CreateFile(s: String; Attrib: Byte): Word;
- var Regs: Registers; { Funktion $3C }
- begin
- s := StrtoZ(s); { wandelt die Lokalkopie von s in ASCIIZ um }
- Regs.AH := $3C; { Funktion: "Create File" }
- Regs.CX := Attrib; { Attribute }
- Regs.DS := Seg(s); Regs.DX := Ofs(s) + 1;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX;
- CreateFile := Regs.AX; { Handle der geöffneten Datei }
- end;
-
- { SHARE-Flags via FileMode; Ergebnis: Handle der Datei }
- Function OpenFile(s: String): Word; { Funktion $3D }
- var Regs: Registers;
- begin
- s := StrtoZ(s); { wandelt die Lokalkopie von s in ASCIIZ um }
- Regs.AH := $3D; { Funktion: "Open File" }
- Regs.AL := FileMode; { R/W und SHARE-Modus }
- Regs.DS := Seg(s); Regs.DX := Ofs(s)+1; { hinter Längenbyte }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0
- then InOutRes := Regs.AX;
- OpenFile := Regs.AX; { Handle der geöffneten Datei }
- end;
-
- Procedure CloseFile(Handle: Word); { Funktion $3E }
- var Regs: Registers;
- begin
- Regs.AH := $3E; { Funktion: "Close File" }
- Regs.BX := Handle;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX;
- end;
-
- Function ReadFile(FHandle: Word; Count: Word; BufPtr: Pointer): Word;
- var Regs: Registers;
- DevAttr: Word;
- begin
- Regs.AH := $3F; { Funktion: "Read File/Device" }
- Regs.BX := FHandle;
- Regs.CX := Count;
- Regs.DS := Seg(BufPtr^); Regs.DX := Ofs(BufPtr^);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX
- else if Regs.AX < Regs.CX then { weniger gelesen als gewünscht }
- begin
- DevAttr := GetDevAttributes(FHandle);
- if (DevAttr and $0120 <> 0) { Datei oder "Raw-Gerät" }
- then InOutRes := 100 { ja - Eof überschritten }
- end;
- ReadFile := Regs.AX;
- end;
-
- Procedure WriteFile(Handle,Count: Word; BufPtr: Pointer);
- var Regs: Registers; { Funktion $40 }
- begin
- Regs.AH := $40; { Funktion: "Write File/Device" }
- Regs.BX := Handle;
- Regs.CX := Count;
- Regs.DS := Seg(BufPtr^); Regs.DX := Ofs(BufPtr^);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX
- else if Regs.AX <> Regs.CX { Anzahl geschriebener Bytes }
- then InOutRes := 101;
- end;
-
- { Procedure Erase - im Unit DOS - } { Funktion $41 }
-
- Function FileSeek(Handle: Word; Offset: LongInt; Action: Integer): LongInt;
- var Regs: Registers; { Funktion $42 }
- begin
- Regs.AH := $42; { Funktion: "Move File Pointer" }
- Regs.AL := Action; { 0: Start, 1: Relativ, 2:Ende }
- Regs.BX := Handle; { Kennziffer der offenen Datei }
- Regs.CX := Offset shr 16;
- Regs.DX := Offset; { CX:DX = Offset bzw. neue Position }
- Intr($21,Regs);
- FileSeek := -1;
- if Regs.Flags and FCarry <> 0 then
- begin
- InOutRes := Regs.AX; FileSeek := -1;
- end
- else FileSeek := Regs.AX + LongInt(Regs.DX) shl 16;
- end;
-
- { Arbeitet mit einem Dateinamen anstelle einer Dateivariablen
- und ist deshalb nur ein funktionelles Äquivalent der
- gleichnamigen Prozedur
- }
- Function GetFAttr(FName: String): Word; { Funktion $4300 }
- var Regs: Registers;
- begin
- FName := StrtoZ(FName); { Umwandlung des Namens in ASCIIZ }
- Regs.AH := $43; { Funktion: "Get/Set File Attribute" }
- Regs.AL := 0; { Subfunktion: "Get" }
- Regs.DS := Seg(FName); Regs.DX := Ofs(FName)+1;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0
- then InOutRes := Regs.AX
- else GetFAttr := Regs.CX;
- end;
-
- { Arbeitet ebenfalls mit einem Dateinamen anstelle einer
- Dateivariablen und ist deshalb lediglich ein funktionelles
- Äquivalent der gleichnamigen Routine.
- }
- Procedure SetFAttr(FName: String; NewAttrs: Word); { Funktion $4301 }
- var Regs: Registers;
- begin
- FName := StrtoZ(FName); { Umwandlung des Namens in ASCIIZ }
- Regs.AH := $43; { Funktion: "Get/Set File Attribute" }
- Regs.AL := 1; { Subfunktion: "Set" }
- Regs.CX := NewAttrs;
- Regs.DS := Seg(FName); Regs.DX := Ofs(FName)+1;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX;
- end;
-
- { Ermittelt die Paßwort-Bits einer Datei und ist
- eine Spezialität von DR-DOS
- }
- Function GetFPass(FName: String): Byte; { Funktion $4302 }
- var Regs: Registers;
- begin
- FName := StrtoZ(FName); { Pascal -> ASCIIZ }
- Regs.AX := $4302; { Funktion: "Get Password Mode" }
- Regs.DS := Seg(FName); { DS:DX = Dateiname }
- Regs.DX := Ofs(FName)+1;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX
- else GetFPass := Regs.CX and $0F;
- { Bits 0..3: "Delete/Rename", n/a, "Write", "Read" }
- end;
-
- { Setzt das Paßwort einer Datei sowie den Modus
- und ist eine Spezialität von DR-DOS
- }
- Procedure SetFPass(FName, Pass: String; Mode: Byte); { Funktion $4303 }
- var Regs: Registers;
- begin
- FName := StrtoZ(FName); { Umwandlung des Namens in ASCIIZ }
- { Paßwort auf 8 Zeichen Länge bringen }
- while Length(Pass) < 8 do Pass := Pass + ' ';
- SetDTA(@Pass[1]); { und DTA darauf setzen }
- Regs.AX := $4303; { Funktion: "Set Password/Mode" }
- Mode := Mode and $0F; { für "World", "Group" und "Owner" }
- Regs.CX := Mode or (Mode shl 4) or (Mode shl 8) or $8000;
- Regs.DS := Seg(FName); { DS:DX = Dateiname }
- Regs.DX := Ofs(FName)+1;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX
- end;
-
- Function GetDevAttributes(Handle: Word): Word; { Funktion $4400 }
- var Regs: Registers;
- begin
- Regs.AH := $44; { Funktion "IOCTL" }
- Regs.AL := $00; { Unterfunktion "Get Device Attribute" }
- Regs.BX := Handle;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX
- else GetDevAttributes := Regs.DX;
- end;
-
- Procedure SetDevAttributes(Handle: Word; Attr: Word); { Funktion $4401 }
- var Regs: Registers;
- begin
- Regs.AH := $44; { Funktion: "IOCTL" }
- Regs.AL := $01; { Unterfunktion "Set Device Attribute" }
- Regs.BX := Handle;
- Regs.DX := Attr and $00FF; { B8..15 *müssen* gelöscht werden! }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX;
- end;
-
- Function IOCTLReadHandle(Handle,Count: Word;
- Buf: Pointer): Word; { Funktion $4402 }
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $4402; { Funktion: Read Control Char }
- BX := Handle; { Handle des Geräts }
- CX := Count;
- DS := Seg(Buf^); DX := Ofs(Buf^);
- Intr($21,Regs);
- if (Flags and FCarry) <> 0 then
- begin
- DosError := AX; IOCTLReadHandle := 0;
- end else
- begin { Anzahl gelesener Bytes }
- DosError := 0; IOCTLReadHandle := AX;
- end;
- end;
- end;
-
-
- Function IOCTLWriteHandle(Handle, Count: Word; { Funktion $4403 }
- Buf: Pointer): Word;
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $4403; { Funktion: Write Control Char }
- BX := Handle; { Handle des Geräts }
- CX := Count;
- DS := Seg(Buf^); DX := Ofs(Buf^);
- Intr($21,Regs);
- if (Flags and FCarry) <> 0 then
- begin
- DosError := AX; IOCTLWriteHandle := 0;
- end else
- begin { Anzahl geschriebener Bytes }
- DosError := 0; IOCTLWriteHandle := AX;
- end;
- end;
- end;
-
- Function IOCTLReadBlock(Drive,Count: Word;
- Buf: Pointer): Word; { Funktion $4404 }
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $4404; { Funktion: Read Control Char (Block) }
- BX := Drive; { Laufwerksnummer }
- CX := Count;
- DS := Seg(Buf^); DX := Ofs(Buf^);
- Intr($21,Regs);
- if (Flags and FCarry) <> 0 then
- begin
- DosError := AX; IOCTLReadBlock := 0;
- end else
- begin { Anzahl gelesener Bytes }
- DosError := 0; IOCTLReadBlock := AX;
- end;
- end;
- end;
-
- Function IOCTLWriteBlock(Drive,Count: Word;
- Buf: Pointer): Word; { Funktion $4405 }
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $4402; { Funktion: Write Control Char (Block) }
- BX := Drive; { Laufwerksnummer }
- CX := Count;
- DS := Seg(Buf^); DX := Ofs(Buf^);
- Intr($21,Regs);
- if (Flags and FCarry) <> 0 then
- begin
- DosError := AX; IOCTLWriteBlock := 0;
- end else
- begin { Anzahl geschriebener Bytes }
- DosError := 0; IOCTLWriteBlock := AX;
- end;
- end;
- end;
-
- Function IOCTLInReady(Handle: Byte): Boolean; { Funktion $4406 }
- var Regs: Registers;
- begin
- Regs.AX := $4406; { IOCTL: "Get Input Status" }
- Regs.BX := Handle;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else IOCTLInReady := (Regs.AL = $FF); { TRUE für "ready" }
- end;
-
- Function IOCTLOutReady(Handle: Byte): Boolean; { Funktion $4407 }
- var Regs: Registers;
- begin
- Regs.AX := $4407; { IOCTL: "Get Output Status" }
- Regs.BX := Handle;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else IOCTLOutReady := (Regs.AL = $FF); { TRUE für "ready" }
- end;
-
- Function IOCTLChangeable(Drive: Byte): Boolean; { Funktion $4408 }
- var Regs: Registers;
- begin
- Regs.AX := $4408; { IOCTL: "Changeable Media" }
- Regs.BL := Drive;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- IOCTLChangeable := (Regs.AX = 0); { TRUE für "wechselbar" }
- end;
-
- Function IOCTLDevLocal(Drive: Byte): Word; { Funktion $4409 }
- var Regs: Registers;
- begin
- Regs.AX := $4409; { IOCTL: "Device Local/Remote" }
- Regs.BL := Drive;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- IOCTLDevLocal := Regs.DX; { Laufwerks-Attribute }
- end;
-
- Function IOCTLHandleLocal(Handle: Word): Word; { Funktion $440A }
- var Regs: Registers;
- begin
- Regs.AH := $44; { Funktion "IOCTL" }
- Regs.AL := $0A; { Unterfunktion "Handle Local/Remote" }
- Regs.BX := Handle;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX
- else IOCTLHandleLocal := Regs.DX;
- end;
-
- Procedure IOCTLSetRetry(Repeats, Counter: Word); { Funktion $440B }
- var Regs: Registers;
- begin
- Regs.AX := $440B; { IOCTL: "Set SHARE Retry Count" }
- Regs.CX := Counter; { Verzögerungszähler }
- Regs.DX := Repeats; { Anzahl der Wiederholungen }
- Intr($21,Regs);
- if (Regs.Flags and FCarry) <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
-
- Procedure IOCTLGenericHandle(Handle, Category,Subcode: Byte;
- var ParmBlock); { Funktion $440C }
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $440C; { Funktion: "Generic IOCTL (Handle)" }
- BX := Handle;
- CH := Category; { 1=PRN,3=CON,5=COM }
- CL := Subcode;
- DS := Seg(ParmBlock); DX := Ofs(ParmBlock);
- Intr($21,Regs);
- if (Flags and FCarry) <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- Procedure IOCTLGenericBlock(Drive,Subcode: Byte; var ParmBlock);
- var Regs: Registers; { Funktion $440D }
- begin
- with Regs do
- begin
- AX := $440D; { Funktion: "Generic IOCTL (Block)" }
- BX := Drive; { Laufwerksnummer }
- CH := $08; { "Gerätekategorie", immer $08 (= Laufwerk) }
- CL := Subcode;
- DS := Seg(ParmBlock); DX := Ofs(ParmBlock);
- Intr($21,Regs);
- if (Flags and FCarry) <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- Function IOCTLGetLogMap(Drive: Byte): Byte; { Funktion $440E }
- var Regs: Registers;
- begin
- Regs.AX := $440E; { IOCTL: "Get Logical Drive Map" }
- Regs.BL := Drive; { Laufwerksnummer }
- Intr($21,Regs);
- if (Regs.Flags and FCarry) <> 0 then DosError := Regs.AX
- else DosError := 0;
- IOCTLGetLogMap := Regs.AL; { logische Laufwerksnummer }
- end;
-
- Procedure IOCTLSetLogMap(NewDrive: Byte); { Funktion $440F }
- var Regs: Registers;
- begin
- Regs.AX := $440F; { IOCTL: "Set Logical Drive Map" }
- Regs.BL := NewDrive-1; { neue interne Laufwerksnummer }
- Intr($21,Regs);
- if (Regs.Flags and FCarry) <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
-
- Function IOCTLSupportH(Handle: Word; Categorie, Subcode: Byte): Boolean;
- var Regs: Registers; { Funktion $4410 }
- begin
- with Regs do
- begin
- AX := $4410; { Funktion: "Query IOCTL Supported (Handle)" }
- BX := Handle;
- CH := Categorie; CL := Subcode;
- Intr($21,Regs);
- IOCTLSupportH := Flags and FCarry = 0;
- end;
- end;
-
- Function IOCTLSupportB(Drive: Word; Subcode: Byte): Boolean;
- var Regs: Registers; { Funktion $4411 }
- begin
- with Regs do
- begin
- AX := $4411; { Funktion: "Query IOCTL Supported (Block)" }
- BX := Drive;
- CH := $08;
- CL := Subcode;
- Intr($21,Regs);
- IOCTLSupportB := Flags and FCarry = 0;
- end;
- end;
-
- Function DupHandle(Handle: Word): Word; { Funktion $45 }
- var Regs: Registers;
- begin
- Regs.AH := $45; { Funktion: Duplicate Handle }
- Regs.BX := Handle; { Handle der offenen Datei }
- Intr($21,Regs);
- if (Regs.Flags and FCarry) <> 0
- then InOutRes := Regs.AX
- else DupHandle := Regs.AX;
- end;
-
- Procedure SetHandle2(Handle1, Handle2: Word); { Funktion $46 }
- var Regs: Registers;
- begin
- Regs.AH := $46; { Funktion: "Set 2nd Handle" }
- Regs.BX := Handle1;
- Regs.CX := Handle2;
- Intr($21,Regs);
- if (Regs.Flags and FCarry) <> 0
- then InOutRes := Regs.AX;
- end;
-
- { Procedure GetDir - ist im Unit DOS - }
-
- Function GetMemBlock(Size: LongInt): Word; { Funktion $48 }
- var Regs: Registers;
- begin
- Regs.AH := $48; { Funktion: "Allocate Memory Block" }
- Regs.BX := (Size + $F) div 16; { Aufrundung auf Paragraphs }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then
- begin
- GetMemBlock := 0; DosError := Regs.AX;
- end else
- begin
- GetMemBlock := Regs.AX; DosError := 0;
- end;
- end;
-
- Function GetFreeMainMem: LongInt; { Funktion $48, andere Anwendung }
- var Regs: Registers;
- begin
- Regs.AH := $48; { Funktion: "Allocate Memory Block" }
- Regs.BX := $FFFF; { eine "unmögliche" Größe }
- Intr($21,Regs);
- GetFreeMainMem := LongInt(Regs.BX) * 16;
- end;
-
- Procedure FreeMemBlock(BlockSeg: Word); { Funktion $49 }
- var Regs: Registers;
- begin
- Regs.AH := $49; { Funktion: "Free Memory Block" }
- Regs.ES := BlockSeg; { Segment des freizugebenden Blocks }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
-
- Procedure SetMemBlock(BlockSeg,BlockSize: Word); { Funktion $4A }
- var Regs: Registers;
- begin
- Regs.AH := $4A; { Funktion: "Modify Allocated Memory" }
- Regs.BX := BlockSize; { neue Größe in Paragraphs }
- Regs.ES := BlockSeg; { Block-Segment }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
-
- { Procedure Exec - ist im Unit DOS - }
-
- Procedure ExecLoad(Path, CmdLine: String; var ProgRegs);
- Type { Funktion $4B01 }
- SSIPBlock = Record
- rSP,rSS: Word; { SS:SP des geladenen Programms }
- rCS,rIP: Word; { CS:IP des geladenen Programms }
- end;
- Const
- TurboSS: Word = 0; { zum Zwischenspeichern }
- TurboBP: Word = 0; { von SS und BP }
- var
- FCBPart1, FCBPart2 : Array[1..16] of Char; { Laufwerk/Name/Suffix }
- ExecParams : Record
- EnvSeg : Word; { Environment d. aufrufenden Programms }
- CmdAddr: Pointer; { Kommandozeile }
- FCBP1 : Pointer; { erster Teil-FCB }
- FCBP2 : Pointer; { zweiter Teil-FCB }
- { Erweiterungen des Parameterblocks für die Funktion $4B01 }
- SP, SS: Word; { SS:SP des geladenen Programms }
- IP, CS: Word; { CS:IP des geladenen Programms }
- end;
- begin
- { Die ersten drei Schritte sind eine exakte Kopie der
- Funktion $4B00 }
- { 1. Register sichern }
- TurboSS := SSeg; { SS festhalten }
- if SwapValInCS(DSeg) <> 0 then ; { DS festhalten }
- inline($89/$2E/TurboBP); { mov [TurboBP],BP - BP festhalten }
-
- { 2. Einsetzen der Kommandozeile in die beiden Teil-FCBs }
- CmdLine := CmdLine + Chr($0D); { RETURN-Zeichen anhängen }
- if ParseFName(ParseFName(@CmdLine[1],@FCBPart1),@FCBPart2)
- <> NIL then ; { 2. Ergebnis nicht verwertet }
-
- { 3. Besetzen des Parameterblocks }
- with ExecParams do
- begin { Endadresse dieses Programms als Env-Seg des neuen Prog. }
- EnvSeg := Word(Ptr(PrefixSeg,$02)^);
- CmdAddr := @CmdLine; { Kommandozeile, incl. Längenbyte }
- FCBP1 := @FCBPart1;
- FCBP2 := @FCBPart2;
- end;
- Path := StrtoZ(Path); { NUL-Zeichen als Ende des Programmnamens }
-
- { 4. DOS-Aufruf. Verändert ist nur die Funktionsnummer }
- inline
- ($B8/$4B01/ { mov ax,$4B01 ; Dos-Funktion EXEC/Load }
- $8D/$96/>Path/ { lea dx,Path }
- $42/ { inc dx ; hinter dem Längenbyte }
- $16/$1F/ { push ss / pop ds ; DS:DX = Prog.-Name }
- $8D/$9E/>ExecParams/{ lea bx,ExecParams }
- $16/$07/ { push ss / pop es ; ES:BX = Parameter }
- $CD/$21/ { int $21 ; DOS-Aufruf }
- $72/$02/ { jc L1 ; Fehler? }
- $31/$C0/ { xor ax,ax ; nein: AX = 0 }
- $50 { L1:push ax ; DOS-Ergebniscode }
- );
- if SwapValInCS(0) <> 0 then ; { Liefert altes DS in AX }
- inline
- ($8E/$D8/ { mov ds,ax ; DS zurück auf TURBO }
- $58/ { pop ax ; DOS-Ergebniscode }
- $A3/DosError/ { mov [DosError],ax ; setzen }
- $8B/$2E/TurboBP/ { mov bp,[TurboBP] ; BP zurück auf TURBO }
- $8E/$16/TurboSS { mov ss,[TurboSS] ; SS zurück auf TURBO }
- );
-
- { 5. Speichern der zurückgelieferten Werte. Läuft rein über BP! }
- with SSIPBlock(ProgRegs),ExecParams do
- begin
- rSS := SS; rSP := SP; rCS := CS; rIP := IP;
- end;
- end; { <- führt als erstes den Befehl MOV SP,BP aus, d.h. setzt SP }
-
- Procedure LoadOverlay(Name: String); { Funktion $4B03 }
- var Regs: Registers;
- OvlyParams : Record
- LoadAddr: Word; { Ladesegment }
- Reloc: Word; { Relozierungskonstante }
- end;
- begin
- Name := StrtoZ(Name); { Pascal-String -> ASCIIZ }
- with OvlyParams do
- begin
- LoadAddr := Seg(HeapPtr^)+1;
- Reloc := 0;
- end;
- with Regs do
- begin
- AX := $4B03; { Funktion: "Load Overlay" }
- DS := Seg(Name); DX := Ofs(Name)+1; { hinter Längenbyte }
- ES := Seg(OvlyParams); BX := Ofs(OvlyParams);
- Intr($21,Regs);
- if Flags and FCarry <> 0 then InOutRes := AX;
- end;
- end;
-
- { Procedure TerminateProcess - ist im Unit DOS - (Halt) }
-
- { Function DosExitCode - ist im Unit DOS - }
-
- { Procedure FindFirst - ist im Unit DOS - }
-
- { Procedure FindNext - ist im Unit DOS - }
-
- Procedure SetActivePSP(PSPSeg: Word); { Aktives PSP setzen }
- var Regs: Registers; { Funktion $50 }
- begin
- Regs.AH := $50; Regs.BX := PSPSeg;
- Intr($21,Regs);
- end;
-
- { Liefert die Segmentadresse des PSP zurück }
- Function GetPSPAddr51 : Word; { Funktion $51 }
- var Regs: Registers;
- begin
- Regs.AH := $51; { Funktion: "Get PSP Address" }
- Intr($21,Regs); { (äquivalent zur Funktion $62) }
- GetPSPAddr51 := Regs.BX;
- end;
-
- Function GetDosDataArea: Pointer; { Funktion $52 }
- var Regs: Registers;
- begin
- Regs.AH := $52; Intr($21,Regs);
- GetDosDataArea := Ptr(Regs.ES,Regs.BX);
- end;
-
- Procedure MakeDPB(DriveNo: Byte; DPB: Pointer); { Funktion $53 }
- var Regs: Registers;
- SecBuf: Array[0..511] of Byte;
- begin
- AbsRead(DriveNo,@SecBuf,0,1); { Lesen des "Boot"-Sektors }
- with Regs do
- begin
- AH := $53; { inoffizielle Funktion: "Translate BPB" }
- ES := Seg(DPB^); BP := Ofs(DPB^); { soll hier gespeichert werden }
- DS := Seg(SecBuf); SI := Ofs(SecBuf)+11;
- Intr($21,Regs);
- end;
- end;
-
- { Procedure GetVerify(var Verify: Boolean); - ist im Unit DOS - }
-
- Procedure CreateNewPSP(NewSeg, MemTop: Word); { Funktion $55 }
- var Regs: Registers;
- begin
- with Regs do
- begin
- AH := $55; { inoffizielle Funktion: "Create New PSP" }
- SI := MemTop; { ab DOS 3.0: Speicher-Endadresse }
- DX := NewSeg;
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- { Procedure Rename - im Unit DOS - }
-
- { Procedure GetFTime - im Unit DOS - } { Funktion $5700 }
-
- { Procedure SetFTime - im Unit DOS - } { Funktion $5701 }
-
- Function GetAllocStrat: Byte; { Funktion $5800 }
- var Regs: Registers;
- begin
- Regs.AX := $5800; { Funktion: "Get Allocation Strategy" }
- Intr($21,Regs);
- GetAllocStrat := Regs.AX;
- end;
-
- Procedure SetAllocStrat(Strat: Byte); { Funktion $5801 }
- var Regs: Registers;
- begin
- Regs.AX := $5801; { Funktion: "Set Allocation Strategy" }
- Regs.BX := Strat;
- Intr($21,Regs);
- end;
-
- Function GetUMBLink: Boolean; { Funktion $5802 }
- var Regs: Registers;
- MCB: MCBPtr; p: ^Word;
- begin
- if DosVersion = $3203 then { DR-DOS 5.0 }
- begin
- p := GetDosDataArea; Dec(LongInt(p),2);
- MCB := Ptr(p^,0); { DOS-Datenbereich, Offset - 2 }
- while MCB^.Flag <> 'Z' do { MCB-Kette verfolgen }
- MCB := Ptr(Seg(MCB^)+1+MCB^.Size,0);
- GetUMBLink := Seg(MCB^)+MCB^.Size > $A000;
- end else
- begin
- Regs.AX := $5802; { Funktion: "Get UMB Link State" }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then GetUMBLink := False
- else GetUMBLink := (Regs.AL <> 0); { TRUE für "UMB eingebunden" }
- end;
- end;
-
- Procedure SetUMBLink(LinkState: Boolean); { Funktion $5803 }
- var Regs: Registers;
- MCB: MCBPtr; p: ^Word;
- NextMCB: Word; Done: Boolean;
- begin
- if DosVersion = $3203 then { DR-DOS 5.0 }
- begin
- p := GetDosDataArea; Dec(LongInt(p),2);
- MCB := Ptr(p^,0); { DOS-Datenbereich, Offset - 2 }
- Done := False;
- { MCB-Kette bis < $9FFF verfolgen }
- while (MCB^.Flag <> 'Z') and not Done do
- begin
- NextMCB := Seg(MCB^)+1+MCB^.Size;
- if NextMCB >= $9FFF then Done := True
- else MCB := Ptr(NextMCB,0);
- end;
- if NextMCB < $9FFF then NextMCB := Seg(MCB^)+1+MCB^.Size;
- if ((NextMCB and $FF00) = $9F00) and { MCB mit ID von MEMMAX auf $9Fxx? }
- (MCBPtr(Ptr(NextMCB,0))^.OwnerPSP = $0007) then
- begin
- if LinkState then MCB^.Flag := 'M'
- else MCB^.Flag := 'Z';
- end
- else DosError := 1; { Funktion nicht unterstützt }
- end else
- begin { MS-DOS }
- Regs.AX := $5803; { Funktion: "Set UMB Link" }
- Regs.BX := Ord(LinkState);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
- end;
-
- Procedure GetExtError; { setzt die globale Variable ExtErrInfo }
- var Regs: Registers; { Funktion $59 }
- begin
- with Regs, ExtErrInfo do
- begin
- AH := $59; Intr($21,Regs); { Funktion: "Get Extended Error" }
- Code := AX;
- Class := BH; Action := BL; { Fehlerklasse, vorgeschlagene Aktion }
- Locus := CH; { "Ort" des Fehlers }
- ExtPointer := Ptr(ES,DI); { nur von SetExtError aktiv gesetzt }
- end;
- end;
-
- { Legt eine Datei mit einem "einzigartigen" Namen an
- und liefert diesen Namen zurück }
- Function TmpFile(Path: PathStr): String; { Funktion $5A }
- var Regs: Registers;
- begin
- Path := StrtoZ(Path);
- with Regs do
- begin
- AH := $5A; { Funktion: "Create Temporary File" }
- CX := 0; { keine Attribute }
- DS := Seg(Path); DX := Ofs(Path)+1;
- Intr($21,Regs);
- if Flags and FCarry <> 0 then InOutRes := AX;
- end;
- TmpFile := ZtoStr(@Path[1]);
- end;
-
- Function CreateNewFile(Name: String): Word; { Funktion $5B }
- var Regs: Registers;
- begin
- Name := StrtoZ(Name);
- with Regs do
- begin
- AH := $5B; { Funktion: "Create New File" }
- CX := $00; { keine Attribute }
- DS := Seg(Name); DX := Ofs(Name) + 1;
- Intr($21,Regs);
- if Flags and FCarry <> 0 then InOutRes := 5 { "Zugriff verweigert" }
- else CreateNewFile := AX; { Handle }
- end;
- end;
-
- { SHARE: Sperrt einen Dateibereich }
- Procedure Lock(var F; Offset, Len: LongInt);
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $5C00; { Funktion: "Lock File Access" }
- BX := FileRec(F).Handle; { Handle der Datei }
- DX := Offset; CX := Offset shr 16;
- DI := Len; SI := Len shr 16;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := AX
- end;
- end;
-
- Procedure Unlock(var F; Offset, Len: LongInt);
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $5C01; { Funktion: "Unlock File Access" }
- BX := FileRec(F).Handle; { Handle der Datei }
- DX := Offset; CX := Offset shr 16;
- DI := Len; SI := Len shr 16;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := AX
- end;
- end;
-
- Procedure ServerCall(Params: ServerCallBlock); { Funktion $5D00 }
- var Regs: Registers;
- begin
- with Params do
- begin
- Resvd := 0; SysID := 0; ProcID := PrefixSeg;
- end;
- with Regs do
- begin
- AX := $5D00; { undokumentierte Funktion: "Server Call" }
- DS := Seg(Params); DX := Ofs(Params);
- Intr($21,Regs);
- end;
- end;
-
- Procedure UpdateAllFiles; { Funktion $5D01 }
- var Regs: Registers;
- PBlock : ServerCallBlock;
- begin
- with Regs, PBlock do
- begin
- Resvd := 0; SysID := 0; ProcID := PrefixSeg;
- AX := $5D01; { undokumentierte Funktion: "Update all Files" }
- DS := Seg(PBlock); DX := Ofs(PBlock);
- Intr($21,Regs);
- if Flags and FCarry <> 0 then InOutRes := AX;
- end;
- end;
-
- Procedure CloseFileName(FName: String); { Funktion $5D02 }
- var PBlock: ServerCallBlock;
- Regs: Registers;
- begin
- FName := RealFName(FName); { "absoluter" Dateiname (Funktion $60) }
- FName := StrtoZ(FName); { Umwandlung in ASCIIZ }
- with PBlock do
- begin
- Resvd := 0; SysID := 0; ProcID := PrefixSeg;
- DS := Seg(FName); DX := Ofs(FName)+1;
- end;
- with Regs do
- begin
- AX := $5D02; { undokumentierte Funktion: "Close File by Name" }
- DS := Seg(PBlock); DX := Ofs(PBlock);
- Intr($21,Regs);
- if Flags and FCarry <> 0 then InOutRes := AX;
- end;
- end;
-
- Procedure CloseMachineFiles(StatID: Word); { Funktion $5D03 }
- var Regs: Registers;
- PBlock : ServerCallBlock;
- begin
- with PBlock do
- begin
- Resvd := 0; SysID := StatID;
- end;
- with Regs do
- begin
- AX := $5D03; { undokumentierte Funktion: "Close Machine's Files" }
- DS := Seg(PBlock); DX := Ofs(PBlock);
- Intr($21,Regs);
- if Flags and FCarry <> 0 then InOutRes := AX;
- end;
- end;
-
- Procedure CloseProcessFiles(ProcPSP: Word); { Funktion $5D04 }
- var Regs: Registers;
- PBlock : ServerCallBlock;
- begin
- with PBlock do
- begin
- Resvd := 0; SysID := 0; ProcID := ProcPSP;
- end;
- with Regs do
- begin
- AX := $5D04; { undokumentierte Funktion: "Close Process Files" }
- DS := Seg(PBlock); DX := Ofs(PBlock);
- Intr($21,Regs);
- if Flags and FCarry <> 0 then InOutRes := AX;
- end;
- end;
-
- Procedure GetSHAREEntry(SHIndex, SFTIndex: Word;
- var Regs: Registers); { Funktion $5D05 }
- var PBlock : ServerCallBlock;
- begin
- with PBlock do
- begin
- Resvd := 0; SysID := 0; ProcID := PrefixSeg;
- BX := SHIndex; CX := SFTIndex;
- end;
- with Regs do
- begin
- AX := $5D05; { undokumentierte Funktion: "Get Open List File Entry" }
- DS := Seg(PBlock); DX := Ofs(PBlock);
- Intr($21,Regs);
- end;
- end;
-
- Procedure GetDosVars(var p: Pointer; var Header,MaxSize: Word);
- var Regs: Registers; { Funktion $5D06 }
- begin
- Regs.AX := $5D06; { undokumentierte Funktion: "Get DOS Variable Area" }
- Intr($21,Regs);
- if Regs.AX <> $5D06 then DosError := 1 { nicht unterstützt }
- else
- begin
- p := Ptr(Regs.DS,Regs.SI);
- Header := Regs.DX; MaxSize := Regs.CX;
- DosError := 0;
- end;
- end;
-
- Function RedirPrinterGetJob: Boolean; { Funktion $5D07 }
- var Regs: Registers;
- begin
- Regs.AX := $5D07; { Undokumentierte Funktion: "Get Redir Printer Mode" }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0
- then RedirPrinterGetJob := False
- else RedirPrinterGetJob := (Regs.DL = 1);
- end;
-
- Procedure RedirPrinterSetJob(Join: Boolean); { Funktion $5D08 }
- var Regs: Registers;
- begin
- Regs.AX := $5D08; { Undokumentierte Funktion: "Set Redir Printer Mode" }
- Regs.DL := Ord(Join);
- Intr($21,Regs);
- end;
-
- Procedure RedirPrinterNewJob; { Funktion $5D09 }
- var Regs: Registers;
- begin
- Regs.AX := $5D09; { Undokumentierte Funktion: "Flush Redir Printer" }
- Intr($21,Regs);
- end;
-
- Procedure SetExtError(ErrCode,Class,Locus,Action: Word; p: Pointer);
- var Regs: Registers;
- PBlock : ServerCallBlock; { Funktion $5D0A }
- begin
- with PBlock do
- begin
- AX := ErrCode;
- BX := (Class shl 8) + Action;
- CX := Locus;
- ES := Seg(p^); DI := Ofs(p^);
- SysID := 0; Resvd := 0; ProcID := PrefixSeg;
- end;
- with Regs do
- begin
- AX := $5D0A; { Undokumentierte Funktion: "Set Extended Error" }
- DS := Seg(PBlock); DX := Ofs(PBlock);
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- Function GetStationName(var Number: Byte; var Name: String): Boolean;
- var Regs: Registers;
- begin { Funktion $5E00 }
- with Regs do
- begin
- AX := $5E00; { Funktion: "Get Machine Name" }
- DS := Seg(Name); DX := Ofs(Name);
- Intr($21,Regs);
- if (Flags and FCarry <> 0) then
- begin
- DosError := AX; Name := ''; GetStationName := False;
- end else
- begin
- DosError := 0;
- GetStationName := CH <> 0; { Name definiert / nicht def. }
- Name := ZtoStr(@Name);
- Number := CL; { Knotennummer }
- end;
- end;
- end;
-
- Procedure SetStationName(Number: Byte; Name: String);
- var Regs: Registers; { Funktion $5E01 }
- begin
- Name := StrtoZ(Name); { Pascal-String -> ASCIIZ }
- with Regs do
- begin
- AX := $5E01; { Undokumentierte Funktion: "Set Machine Name" }
- CH := 1; { Namen definieren, nicht löschen }
- CL := Number; { Knotennummer, nur für NETBIOS }
- DS := Seg(Name); DX := Ofs(Name) + 1;
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- { Setzt den Initialisierungsstring eines Netz-Druckers }
- Procedure ReDirPrinterSetInit(DevName: String; InitStr: String);
- var Regs: Registers; { Funktion $5E02 }
- NetName: String; { Dummy }
- Index: Integer;
- begin
- Index := ReDirGetEntry(DevName, NetName);
- if Index = -1 then DosError := 18
- else
- with Regs do
- begin
- AX := $5E02; { Funktion: "Set Printer Setup" }
- BX := Index;
- CX := Length(InitStr); if CX > 64 then CX := 64;
- DS := Seg(InitStr); SI := Ofs(InitStr)+1;
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- { Ermittelt den Initialisierungsstring eines Netz-Druckers }
- Function ReDirPrinterGetInit(DevName: String): String;
- var Regs: Registers;
- Res: String; { Funktion $5E03 }
- Index: Integer;
- begin
- Index := ReDirGetEntry(DevName,Res); { Res: Dummy }
- if Index = -1 then DosError := 18
- else
- with Regs do
- begin
- AX := $5E03; { Funktion: "Get Printer Setup" }
- BX := Index;
- ES := Seg(Res); DI := Ofs(Res)+1;
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else DosError := 0;
- Res[0] := Chr(CX);
- end;
- RedirPrinterGetInit := Res;
- end;
-
- Procedure ReDirPrinterSetTabs(DevName: String; Tabs: Boolean);
- var Regs: Registers;
- NetName: String; { Dummy }
- Index: Integer; { Funktion $5F04 }
- begin
- Index := ReDirGetEntry(DevName, NetName);
- if Index = -1 then DosError := 18
- else
- with Regs do
- begin
- AX := $5E04; { Funktion: "Set Printer Tabs" }
- BX := Index;
- DX := Ord(Tabs); { 0 -> keine Interpretation, 1 -> Interpretation }
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- Function ReDirPrinterGetTabs(DevName: String): Boolean;
- var Regs: Registers;
- Dummy: String; { Funktion $5F05 }
- Index: Integer;
- begin
- Index := ReDirGetEntry(DevName,Dummy); { (Netz-Name) }
- if Index = -1 then DosError := 18
- else
- with Regs do
- begin
- AX := $5E05; { Funktion: "Get Printer Tabs" }
- BX := Index;
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else DosError := 0;
- ReDirPrinterGetTabs := DX = 1; { TRUE für "Interpretation" }
- end;
- end;
-
- Function ReDirPrinterGetMode: Boolean; { Funktion $5F00 }
- var Regs: Registers;
- begin
- Regs.AX := $5F00; { Funktion: "Get Redirection Mode" }
- Regs.BX := $03; { Abfrage Drucker }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- ReDirPrinterGetMode := (Regs.BH = 1);
- end;
-
- Function ReDirDriveGetMode : Boolean; { Funktion $5F00 }
- var Regs: Registers;
- begin
- Regs.AX := $5F00; { Funktion: "Get Redirection Mode" }
- Regs.BX := $04; { Abfrage Disk-Laufwerk. Laufwerksnummer? }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- ReDirDriveGetMode := (Regs.BH = 1);
- end;
-
- Procedure ReDirPrinterSetMode(Mode: Boolean);
- var Regs: Registers;
- begin { Funktion $5F01 }
- Regs.AX := $5F01;
- Regs.BL := $03; { Drucker }
- Regs.BX := Ord(Mode);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
-
- Procedure ReDirDriveSetMode(Mode: Boolean);
- var Regs: Registers; { Funktion $5F01 }
- begin
- Regs.AX := $5F01;
- Regs.BL := $04; { Disk }
- Regs.BX := Ord(Mode);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
-
- { Sucht die Redirektionsliste nach einem Eintrag ab.
- Aufruf mit dem lokalen Namen des Gerätes, zurückgeliefert
- wird der Netz-Name und die Indexnummer.
- }
- Function ReDirGetEntry(LocalName: string; var NetName: String): Integer;
- var Regs: Registers;
- LocalTemp: String[16]; { Funktion $5F02 }
- x,y: Integer;
- Found: Boolean;
- begin
- for x := 1 to Length(LocalName) do
- LocalName[x] := Upcase(LocalName[x]);
-
- x := 0; Found := False; DosError := 0;
- while (DosError = 0) and not Found do
- with Regs do
- begin
- AX := $5F02; { Funktion: "Get ReDir List Entry" }
- BX := x; { Indexnummer }
- SI := Ofs(LocalTemp); DS := Seg(LocalTemp);
- DI := Ofs(NetName); ES := Seg(NetName);
- Intr($21,Regs); { Aufruf }
- if (Flags and FCarry) <> 0 then DosError := AX
- else if BH = 0 then { besetzter, d.h. gültiger Eintrag }
- begin
- LocalTemp := ZToStr(@LocalTemp[0]);
- if BL = 4 then { Laufwerk: Suche nach Unterverzeichnis }
- begin
- y := 0; while NetName[y] <> #0 do Inc(y);
- NetName[y] := ':';
- end;
- NetName := ZToStr(@NetName[0]); { ASCIIZ-> Pascal }
- Found := LocalTemp = LocalName;
- if Found then ReDirGetEntry := x;
- end;
- Inc(x); { Nächster Eintrag }
- end;
- end;
-
- { Funktion $5F03 - Legt einen Eintrag in der Redirektionsliste an }
- Procedure ReDirSetEntry(DevCode: Byte; UserVal: Word;
- LocalName, NetName: String);
- var Regs: Registers;
- begin
- LocalName := StrToZ(LocalName); NetName := StrToZ(NetName);
- with Regs do
- begin
- AX := $5F03; { Funktion: "Set Redirection List" }
- BX := DevCode; { 3 = Drucker, 4 = Disk }
- CX := UserVal; { benutzerdefinierbarer Wert }
- SI := Ofs(LocalName)+1; { DS:SI = lokaler Name }
- DS := Seg(LocalName);
- DI := Ofs(NetName)+1; { ES:DI = Netz-Name }
- ES := Seg(NetName);
- Intr($21,Regs); { Aufruf }
- if (Flags and FCarry) <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- { Funktion $5F04 - löscht einen Eintrag der Redirektionsliste }
- Procedure ReDirDeleteEntry(LocalName: String);
- var Regs: Registers;
- begin
- LocalName := StrToZ(LocalName);
- with Regs do
- begin
- AX := $5F04; { Funktion: "Cancel Redirection" }
- SI := Ofs(LocalName)+1; { DS:SI = Gerätename }
- DS := Seg(LocalName);
- Intr($21,Regs); { Aufruf }
- if (Flags and FCarry) <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
-
- { Sucht die Redirektionsliste nach einem Eintrag ab.
- Aufruf mit dem lokalen Namen des Gerätes, zurückgeliefert
- wird der Netz-Name und die Indexnummer.
- }
- Function GetDirGetExtEntry(LocalName: string; var NetName: String;
- var NetBIOSNo: Word): Integer;
- var Regs: Registers;
- LocalTemp: String[16]; { Funktion $5F05 }
- x,y: Integer;
- Found: Boolean;
- begin
- for x := 1 to Length(LocalName) do
- LocalName[x] := Upcase(LocalName[x]);
-
- x := 0; Found := False; DosError := 0;
- while (DosError = 0) and not Found do
- with Regs do
- begin
- AX := $5F05; { Funktion: "Get Ext ReDir List Entry" }
- BX := x; { Indexnummer }
- SI := Ofs(LocalTemp); DS := Seg(LocalTemp);
- DI := Ofs(NetName); ES := Seg(NetName);
- Intr($21,Regs); { Aufruf }
- if (Flags and FCarry) <> 0 then DosError := AX
- else if BH = 0 then { besetzter, d.h. gültiger Eintrag }
- begin
- LocalTemp := ZToStr(@LocalTemp[0]);
- if BL = 4 then { Laufwerk: Suche nach Unterverzeichnis }
- begin
- y := 0; while NetName[y] <> #0 do Inc(y);
- NetName[y] := ':';
- end;
- NetName := ZToStr(@NetName[0]); { ASCIIZ-> Pascal }
- Found := LocalTemp = LocalName;
- if Found then
- begin
- GetDirGetExtEntry := x;
- NetBIOSNo := BP;
- end;
- end;
- Inc(x); { Nächster Eintrag }
- end;
- end;
-
- { Stellt ein (zuvor via $5F08 unterdrücktes) lokales Laufwerk
- wieder zur Verfügung
- }
- Function ActivateLocalDrive(Drive: Byte): Boolean;
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $5F07; { Funktion: "Activate Drive" }
- DX := Drive; { 0 = A:, 1 = B: usw. }
- Intr($21,Regs);
- if (Flags and FCarry) <> 0 then
- begin
- DosError := AX; ActivateLocalDrive := FALSE;
- end else
- begin
- DosError := 0; ActivateLocalDrive := TRUE;
- end;
- end;
- end;
-
- { Unterdrückt ein lokales Laufwerk (DOS 4.x: unterdrückt sämtliche
- Laufwerke ab der angegebenen Kennziffer)
- }
- Function DeactivateLocalDrive(Drive: Byte): Boolean;
- var Regs: Registers;
- begin
- with Regs do
- begin
- AX := $5F08; { Funktion: "Deactivate Drive" }
- DX := Drive; { 0 = A:, 1 = B: usw. }
- Intr($21,Regs);
- if (Flags and FCarry) <> 0 then
- begin
- DosError := AX; DeactivateLocalDrive := FALSE;
- end else
- begin
- DosError := 0; DeactivateLocalDrive := TRUE;
- end;
- end;
- end;
-
- { Ergänzt einen Dateinamen um Laufwerk/Suchweg, bleibt von
- JOIN, SUBST und ASSIGN unbeeindruckt }
- Function RealFName(FName: String): String; { Funktion $60 }
- var Regs: Registers;
- RFName: String;
- x: Integer;
- begin
- if Lo(DosVersion) < 3 then
- begin
- RealFName := FExpand(FName);
- Exit;
- end;
- FName := StrtoZ(FName);
- with Regs do
- begin
- AH := $60; { undokumentierte Funktion: "Expand Filename" }
- DS := Seg(FName); SI := Ofs(FName)+1; { hinter Längenbyte }
- ES := Seg(RFName); DI := Ofs(RFName); { Ergebnis }
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else
- begin
- DosError := 0;
- RFName := ZtoStr(@RFName);
- end;
- end;
- RealFName := RFName;
- end;
-
- { Liefert die Segmentadresse des PSP zurück }
- Function GetActivePSP : Word; { Funktion $62 }
- var Regs: Registers;
- begin
- Regs.AH := $62; { Funktion: "Get PSP Address" }
- Intr($21,Regs);
- GetActivePSP := Regs.BX;
- end;
-
- Procedure SetPRINTFlag(NewVal: Byte); { Funktion $64 }
- var Regs: Registers;
- begin
- Regs.AH := $64;
- Regs.AL := NewVal;
- Intr($21,Regs);
- end;
-
- Procedure GetExtCountryInfo(CCode,CodeP: Integer;
- var CountryRec: Func6501Country);
- var Regs: Registers; { Funktion $6501 }
- begin
- with Regs do
- begin
- { Abfrage über die Funktion $6501: aktuelle Codeseite/aktuelles Land }
- AX := $6501;
- Integer(BX) := CodeP; { Codeseite: $FFFF = aktuelle Seite von CON }
- CX := SizeOf(Func6501Country); { Größe Ergebnispuffer }
- Integer(DX) := CCode; { Landescode: $FFFF = aktuelles Land }
- ES := Seg(CountryRec); DI := Ofs(CountryRec);
- Intr($21,Regs);
- if Flags and FCarry <> 0 then DosError := AX
- else DosError := 0;
- end;
- end;
- { Gemeinsame Rahmenroutine für die Funktionen $6502 bis $6507 }
- { Ist nicht öffentlich deklariert, d.h. nur im Implementationsteil }
- Procedure CallFunc650x(SubFunc: Byte; var Size: Word; var CharPtr);
- Type TableStruc = Record
- Size: Word;
- Chars: Array [0..255] of Char;
- end;
- TablePtr = ^TableStruc; { Zeiger auf eine solche Struktur }
- var Regs: Registers;
- Buf: Record
- SubF: Byte;
- Res: TablePtr;
- end;
- begin
- with Regs do
- begin
- AH := $65; AL := SubFunc;
- BX := $FFFF; DX := $FFFF; { "aktuelle" Einstellungen }
- CX := $05; { Puffergröße }
- ES := Seg(Buf); DI := Ofs(Buf);
- Intr($21,Regs);
- if (Flags and FCarry <> 0) or (Buf.SubF <> SubFunc)
- then DosError := AX
- else DosError := 0;
- end;
- with Buf do
- begin
- Size := Res^.Size; { Größe des Arrays }
- Pointer(CharPtr) := Ptr(Seg(Res^),Ofs(Res^)+2); { Array-Adresse }
- end;
- end;
-
- Procedure GetASCIIHiXLate(var Size: Word; var TablePtr);
- begin { Funktion $6502 }
- CallFunc650x($02,Size,TablePtr);
- end;
-
- Procedure GetFNamecase(var Size: Word; var TablePtr);
- begin { Funktion $6504 }
- CallFunc650x($04,Size,TablePtr);
- end;
-
- Procedure GetFNameTerminators(var Size: Word; var TablePtr);
- begin { Funktion $6505 }
- CallFunc650x($05,Size,TablePtr);
- end;
-
- Procedure GetSortTable(var Size: Word; var TablePtr);
- begin { Funktion $6506 }
- CallFunc650x($06,Size,TablePtr);
- end;
-
- Procedure GetDBCSTable(var Size: Word; var TablePtr);
- begin { Funktion $6507 }
- CallFunc650x($07,Size,TablePtr);
- end;
-
- { Landesspezifische Umsetzung von Klein- in Großbuchstaben }
- Function Upcase6520(Ch: Char): Char; { Funktion $6520 }
- var Regs: Registers;
- begin
- Regs.AX := $6520; { Funktion: "Capitalize Character" }
- Regs.DL := Ord(Ch);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- Upcase6520 := Chr(Regs.DL);
- end;
-
- Function Upcase6521(s: String): String;
- var Regs: Registers; { Funktion $6521 }
- begin
- Regs.AX := $6521; { Funktion: "Capitalize String" }
- Regs.CX := Ord(s[0]); { Länge des Strings }
- Regs.DS := Seg(s); Regs.DX := Ofs(s)+1;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- Upcase6521 := s;
- end;
-
- Procedure Upcase6522(s: Pointer); { Umsetzung ASCIIZ-String }
- var Regs: Registers; { Funktion $6522 }
- begin
- Regs.AX := $6522; { Funktion: "Capitalize ASCIIZ String" }
- Regs.DS := Seg(s^); Regs.DX := Ofs(s^);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
-
- { Prüfung auf "Ja", "Nein" oder "weder noch" }
- Function Query6523(Ch: Char): Integer; { Funktion $6523 }
- var Regs: Registers;
- begin
- Regs.AX := $6523; { Funktion: "Get Yes/No Prompt" }
- Regs.DL := Ord(Ch);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- Query6523 := Regs.AL; { 0 = Nein, 1 = Ja, 2 = weder noch }
- end;
- Procedure GetCodePage(var CurrPage, SysPage: Word);
- var Regs: Registers; { Funktion $6601 }
- begin
- Regs.AX := $6601; { Funktion "Get Code Page" }
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0
- then DosError := Regs.AX
- else DosError := 0;
- CurrPage := Regs.BX;
- SysPage := Regs.DX;
- end;
-
- Procedure SetCodePage(NewPage: Word);
- var Regs: Registers; { Funktion $6602 }
- begin
- Regs.AX := $6602; { Funktion "Set Code Page" }
- Regs.BX := NewPage;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0
- then DosError := Regs.AX
- else DosError := 0;
- end;
-
- Procedure SetHandleCount(Handles: Word); { Funktion $67 }
- var Regs: Registers;
- begin
- Regs.AH := $67; { Funktion: "Set Handle Count" }
- Regs.BX := Handles;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then DosError := Regs.AX
- else DosError := 0;
- end;
-
- Procedure UpdateFile(Handle: Word); { Funktion $68 }
- var Regs: Registers;
- begin
- Regs.AH := $68; { Funktion: "Update File (Entry)" }
- Regs.BX := Handle;
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0 then InOutRes := Regs.AX;
- end;
-
- Procedure GetDiskSerialNo(Drive: Byte; var Buf: DiskSerialInfo);
- var Regs: Registers; { Funktion $6900 }
- begin
- Regs.AX := $6900; { Funktion: "Get Disk Serial Number" }
- Regs.BL := Drive; { 0 = Standard, 1 = A: 2 = B: usw. }
- Regs.DS := Seg(Buf); Regs.DX := Ofs(Buf);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0
- then DosError := Regs.AX
- else DosError := 0;
- end;
-
- Procedure SetDiskSerialNo(Drive: Byte; var Buf: DiskSerialInfo);
- var Regs: Registers; { Funktion $6901 }
- begin
- Regs.AX := $6901; { Funktion: "Set Disk Serial Number" }
- Regs.BL := Drive; { 0 = Standard, 1 = A: 2 = B: usw. }
- Regs.DS := Seg(Buf); Regs.DX := Ofs(Buf);
- Intr($21,Regs);
- if Regs.Flags and FCarry <> 0
- then DosError := Regs.AX
- else DosError := 0;
- end;
-
- { *** Funktion $6A existiert, Arbeitsweise aber vorläufig noch unbekannt }
-
- { Funktion $6B - undefiniert }
-
- { Ergebnis: Handle der Datei }
- Function CreateExtended(FName: String; Attr: Word; Action: Byte): Word;
- var Regs: Registers; { Funktion $6C }
- begin
- FName := StrtoZ(FName); { Pascal -> ASCIIZ }
- with Regs do
- begin
- AH := $6C; { Funktion: "Extended Create/Open" }
- BX := FileMode or $2000; { kein Auto Commit, kein INT $24 für Fehler }
- CX := Attr;
- DX := Action; { Verhalten bei neuen/existierenden Dateien }
- DS := Seg(FName); SI := Ofs(FName) + 1;
- Intr($21,Regs);
- if Flags and FCarry <> 0 then InOutRes := AX
- else CreateExtended := AX; { Handle }
- end;
- end;
-
- { ------ Prüfung auf DR-DOS, Versionen 3.41 und 5.0 ------ }
- Procedure CheckDRDos;
- var Regs: Registers;
- p : ^Pointer;
- F: Text; Time: LongInt;
- begin
- DRDos341 := False; DRDos500 := False;
- p := Pointer(GetDosDataArea); { Adresse DOS-Datenbereich }
- if Swap(DosVersion) = $031F then { Dos-Version 3.31? }
- begin { Ja - Prüfung, ob Geräten eine "Öffnungszeit" zugeordnet wird }
- Assign(F,'CON'); Reset(F); GetFTime(F,Time); Close(F);
- if Time = 0 then { OK - ist DR-DOS }
- begin
- p := Ptr(Seg(p^),Ofs(p^)+$04); { Adresse der SFT-Adresse }
- p := p^; { SFT-Start }
- if (MemW[Seg(p^):Ofs(p^)+6] < 2) and { Handle-Zahl von AUX }
- (MemW[Seg(p^):Ofs(p^)+6+$35] < 2) { Handle-Zahl von CON }
- then DRDos341 := True { gleich 1? -> DR-DOS 3.41 }
- else DRDos500 := True; { > 1, d.h. MS-DOS-kompatibel? -> DR-DOS 5.0 }
- end;
- end;
- end;
-
- { --- Initialisierungsteil --- }
- begin
- CheckDRDos; { setzt die Variablen DRDos341 bzw. DRDos500 }
- CurrDosVersion := DosVersion; { echte DosVersion }
- end.
-
-