home *** CD-ROM | disk | FTP | other *** search
- (*========================================================*)
- (* DMPI.PAS *)
- (* (c) 1993 G. Blumert & DMV-Verlag *)
- (*--------------------------------------------------------*)
- (* Compiler: Turbo-/Borland-Pascal für Windows *)
- (* *)
- (* Funktion: Implementiert die für die Kommunikation mit *)
- (* IPX nötigen Routinen. Stellt Datentypen und Routinen *)
- (* fⁿr die Kommunikation mit DPMI bereit. *)
- (* Das Programm mu▀ im Protected Mode laufen! *)
- (*========================================================*)
-
- UNIT DPMI;
- {$X+,B-}
-
- INTERFACE
-
- USES WinTypes;
-
- TYPE
- pDPMICallStruct = ^tDPMICallStruct;
- tDPMICallStruct = RECORD
- EDI, ESI, EBP, Reserved, EBX, EDX, ECX, EAX: LongInt;
- Flags, ES, DS, FS, GS, IP, CS, SP, SS: WORD
- END;
-
- (*--------------------------------------------------------*)
- (* Fⁿr die Kommunikation mit DPMI ben÷tigt das *)
- (* Demoprogramm 3 CALL-Strukturen *)
- (* - eine fⁿr die CallBack-Funktion, die ja jederzeit *)
- (* aufgerufen werden kann *)
- (* - und je eine fⁿr die Funktionen ListenForPacket und *)
- (* SendPacket. *)
- (* *)
- (* Die Strukturen mⁿssen entweder statisch im Datenseg- *)
- (* ment liegen oder mit GlobalAlloc reserviert werden. *)
- (* Eine Reservierung mit den TPW-Routinen New, GetMem *)
- (* oder MemAlloc bringt DPMI ins Schleudern, und mit *)
- (* etwas Glⁿck landet man wenigstens noch am freundlichen *)
- (* C:\> *)
-
- VAR
- CallStrc : pDPMICallStruct;
- CallBackStrc : pDPMICallStruct;
- ListenStrc : pDPMICallStruct;
- CallStrcHandle: tHandle; (* Es wird nur ein Handle *)
- (* angefordert *)
-
- CONST
- MyFunc = $0BDC5; (* Von WinNet installierte Funktion *)
- (* des Int 2Fh *)
-
- (* DOSAdr: von DPMI erhaltene Call-Back Adresse. Wird *)
- (* diese vom Real-Mode aus aufgerufen, so wird eine *)
- (* Protected-Mode-Routine aufgerufen, die das Datenpaket *)
- (* an einem sicheren Ort speichert. *)
- (* Wird diese direkt von IPX aufgerufen, so endet das *)
- (* leider mit einem Absturz (Warum? - Keine Ahnung!). *)
- (* Daher liegt das Real-Mode-Programm WinNet zwischen *)
- (* Windows-Anwendung und IPX. *)
- (* Der Rⁿckgabewert bezeichnet die an IPX zu ⁿbergebende *)
- (* Adresse des Event-Handlers, nΣmlich den Einsprung in *)
- (* WinNet, von dem aus dann erst die Call-Back-Prozedur *)
- (* aufgerufen wird. *)
- (* Speichert au▀erdem die von WinNet belegte Int.-Nummer *)
- (* in RealModeInt *)
- FUNCTION InitIpxInt(DOSAdr: POINTER): POINTER;
-
- (* Fⁿllt die ⁿbergebene Struktur mit den ⁿbergebenen *)
- (* Werten. Setzt alle anderen Felder auf 0. *)
- (* DPMI stellt einen Stack von 30 Worten zur Verfⁿgung, *)
- (* wenn SS:SP = NIL ist *)
- PROCEDURE FillStruc(aStruc: pDPMICallStruct;
- ES_SI: POINTER; AX, BX, CX, DX: WORD);
-
- (* Simuliert einen Real-Mode-Interrupt, und zwar den von *)
- (* WinNet installierten *)
- PROCEDURE RMInt(aStruc: pDPMICallStruct);
-
- (* Gibt eine Adresse zurⁿck, die im Real-Mode *)
- (* angesprungen werden kann, um die Prozedur ProcAdr zu *)
- (* starten *)
- FUNCTION GetCallBack(ProcAdr: POINTER): POINTER;
-
- (* Call-Back-Adresse wieder freigeben. Es ist der von *)
- (* GetCallBack erhaltene Pointer zurⁿckzugeben *)
- PROCEDURE FreeCallBack(ProcAdr: POINTER);
-
- IMPLEMENTATION
-
- USES
- {$IFDEF Ver70} Objects, {$ELSE} WObjects, {$ENDIF} WinProcs;
-
- CONST RealModeInt: BYTE = 0;
- (* Von WinNet belegter Interrupt *)
-
- PROCEDURE FillStruc(aStruc: pDPMICallStruct;
- ES_SI: POINTER; AX, BX, CX, DX: WORD);
- BEGIN
- FillChar(aStruc^, SizeOf(CallStrc^), 0);
- WITH aStruc^ DO BEGIN
- ES := PtrRec(ES_SI).Seg;
- ESI := PtrRec(ES_SI).Ofs;
- EAX := AX;
- EBX := BX;
- ECX := CX;
- EDX := DX
- END
- END;
-
- PROCEDURE RMInt(aStruc: pDPMICallStruct); ASSEMBLER;
- VAR Stack: LongInt;
- ASM
- XOR BX, BX (* BH = 1: Interrupt- *)
- (* Controller-Reset und A20 *)
- (* sperren *)
- MOV CX, BX (* 0 Bytes von Prot.-Mode- *)
- (* Stack auf Real-Mode *)
- (* Stack kopieren *)
- MOV BL, [RealModeInt] (* BL = Interruptnummer *)
- MOV AX, 0300H (* Funktion $300 *)
- LES DI, [aStruc] (* ES:DI = ^Struct *)
- Int 31H
- END;
-
- FUNCTION InitIpxInt(DOSAdr: POINTER): POINTER; ASSEMBLER;
- ASM
- MOV AX, MyFunc
- XOR SI, SI (* SI <> MyFunc! *)
- MOV BX, WORD Ptr [DOSAdr]
- MOV DX, WORD Ptr [DOSAdr+2]
- Int 2FH
- CMP AX, 0A5A5H (* WinNet geladen ? *)
- JE @WinNetGeladen
- XOR AX, AX (* Nein! *)
- MOV DX, AX (* NIL zurⁿckgeben *)
- JMP @Ende
- @WinNetGeladen:
- MOV [RealModeInt], DL (* Von WinNet belegte *)
- (* Interruptnummer merken *)
- MOV AX, BX (* IPX-Eventhandler in *)
- (* CX:BX nach DX:AX *)
- MOV DX, CX
- @Ende:
- END;
-
- FUNCTION GetCallBack(ProcAdr: POINTER): POINTER; ASSEMBLER;
- ASM
- PUSH DS
- LES DI, [CallBackStrc]
- LDS SI, [ProcAdr]
- MOV AX, 0303H (* Funktion $0303 *)
- Int 31H
- POP DS
- MOV AX, DX (* Adresse von CX:DX nach DX:AX *)
- MOV DX, CX
- END;
-
- PROCEDURE FreeCallBack(ProcAdr: POINTER); ASSEMBLER;
- ASM
- MOV DX, WORD Ptr [ProcAdr]
- MOV CX, WORD Ptr [ProcAdr+2]
- MOV AX, 0304H (* Funktion $0304 *)
- Int 31H
- END;
-
- VAR OldExitProc: POINTER;
-
- (* Gibt den Speicher fⁿr die DPMI-Strukturen wieder frei *)
- PROCEDURE MemExit; FAR;
- BEGIN
- ExitProc := OldExitProc;
- GlobalUnlock(CallStrcHandle);
- GlobalFree(CallStrcHandle)
- END;
-
- BEGIN
- (* Speicher fⁿr die DPMI-Strukturen reservieren - schont *)
- (* das Datensegment *)
- CallStrcHandle :=
- GlobalAlloc(gMem_Moveable,SizeOf(tDPMICallStruct) * 3);
- CallStrc := GlobalLock(CallStrcHandle);
- LongInt(CallBackStrc) := LongInt(CallStrc)
- + SizeOf(tDPMICallStruct);
- LongInt(ListenStrc) := LongInt(CallBackStrc)
- + SizeOf(tDPMICallStruct);
- OldExitProc := ExitProc; (* Exitprozedur installieren *)
- ExitProc := @MemExit
- END.
-
- (*========================================================*)
- (* Ende von DMPI.PAS *)
-
-