PAGE 58,132 .386p ; ; Client has: ; States -> state is set by writing to port ; data is retrieved by reading from port ; ; State 0: Get Identification "ITVXDDRV" ; State 1: Get Server string (64 bytes) ; State 2: Get buffer used ; State 3: Reset Client ; State 4: Get debug value ; State 5: Get TSC ; ; ; Server interface: ; Write 0 to reset ; If read, returns "ITSERVER", else 01h if Server has been validated. ; Needs to receive "ITSERVER" to validate. ; If validated, receives server string of max 64 bytes, no 0 permitted. ; .XLIST INCLUDE VMM.Inc INCLUDE Debug.Inc INCLUDE Shell.inc .LIST VSound_Client_Address EQU 400h VSound_Server_Address EQU 401h VSound_Data_Address EQU 402h VSOUND_CLIENTSTATES EQU 7 VSOUND_BUFFERSIZE EQU (64*1024) ;****************************************************************************** ; V I R T U A L D E V I C E D E C L A R A T I O N ;****************************************************************************** Declare_Virtual_Device VSOUND, 1, 0, VSOUND_Control, Undefined_Device_ID ,,, ;****************************************************************************** ; L O C A L D A T A ;****************************************************************************** VxD_LOCKED_DATA_SEG VSound_Data DB VSOUND_BUFFERSIZE Dup (0) VSound_HeadPointer DD 0 VSound_TailPointer DD 0 VSound_Client DD 0 VSound_Server DD 0 VSound_ClientCallback DD 0 VSound_ID DB "ITVXDDRV" VSound_State DD 0 VSound_BufferUsed DD 0 VSound_StatePos DD 0 VSound_ServerID DB "ITSERVER" VSound_ServerInPos DD 0 VSound_ServerOutPos DD 0 VSound_ServerValid DD 0 VSound_DebugValue DD 0 VSound_TimeStamp1 DD 0 VSound_TimeStamp2 DD 0 VSound_InTable DD Offset32 VSound_Identification DD Offset32 VSound_GetServerString DD Offset32 VSound_GetBufferUsed DD Offset32 VSound_GetDebugValue DD Offset32 VSound_Get0 DD Offset32 VSound_GetDebugValue DD Offset32 VSound_GetTSC VSound_OutTable DD Offset32 VSound_Out_ResetStatePos DD Offset32 VSound_Out_ResetStatePos DD Offset32 VSound_Out_GetBufferUsed DD Offset32 VSound_Out_ResetClient DD Offset32 VSound_Out_SetCallbackAddress DD Offset32 VSound_Out_ResetStatePos DD Offset32 VSound_Out_GetTSC VSound_ServerString DB 64 Dup (0) VxD_LOCKED_DATA_ENDS ;****************************************************************************** ; I N I T I A L I Z A T I O N C O D E ;****************************************************************************** VxD_IDATA_SEG Begin_Vxd_IO_Table IO_Table Vxd_IO VSound_Client_Address, VSound_Client_Hook Vxd_IO VSound_Server_Address, VSound_Server_Hook Vxd_IO VSound_Data_Address, VSound_Data_Hook End_Vxd_IO_Table IO_Table VxD_IDATA_ENDS VxD_ICODE_SEG ;****************************************************************************** ; ; VSOUND_Device_Init ; ; DESCRIPTION: ; ; This routine is called during Windows startup. It needs to ; install the I/O handler for our device, and set up the system ; VM as the default owner. ; ; ;============================================================================== BeginProc VSOUND_Device_Init Xor EAX, EAX Mov VSound_Client, EAX ; no current owner Mov VSound_Server, EAX ; no current owner Mov VSound_ClientCallback, EAX ; No callback Mov EDI, OFFSET32 IO_Table VMMCall Install_Mult_IO_Handlers Ret EndProc VSOUND_Device_Init VxD_ICODE_ENDS ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VxD_CODE_SEG ;****************************************************************************** ; ; VSOUND_Destroy_VM ; ; DESCRIPTION: ; ; This routine is called when a VM is destroyed. We need to check ; to see if the VM in question is the current owner of the device. ; ;============================================================================== BeginProc VSOUND_Destroy_VM Xor EAX, EAX Cmp EBX, VSound_Client ; Destroying device owner? JNE Short VDM_Client Mov VSound_Client, EAX Mov VSound_ClientCallback, EAX VDM_Client: Cmp EBX, VSound_Server JNE VDM_Server Mov VSound_Server, EAX Mov VSound_ServerValid, EAX VDM_Server: ClC Ret EndProc VSOUND_Destroy_VM VxD_CODE_ENDS ;****************************************************************************** VxD_LOCKED_CODE_SEG ;****************************************************************************** ; ; VSound_Control ; ; DESCRIPTION: ; ; This is a call-back routine to handle the messages that are sent ; to VxD's to control system operation. ; ;============================================================================== BeginProc VSound_Control Control_Dispatch Device_Init, VSound_Device_Init Control_Dispatch Destroy_VM, VSound_Destroy_VM ClC Ret EndProc VSound_Control VxD_LOCKED_CODE_ENDS VxD_CODE_SEG ;***************************************************************************** ; ; VSound_Client_Hook ; ; DESCRIPTION: ; ; This routine is called for every I/O access to our port. First, ; it checks to see if the VM issuing the I/O is the current owner. ; If not, it displays a dialog box so the user can decide what to ; do. ; ;***************************************************************************** VSound_Identification: Pop EAX Push ECX Mov ECX, VSound_StatePos Mov AL, [VSound_ID+ECX] Inc ECX And ECX, 7 Mov VSound_StatePos, ECX Pop ECX Ret VSound_GetServerString: Pop EAX Push ECX Mov ECX, VSound_StatePos Mov AL, [VSound_ServerString+ECX] Inc ECX And ECX, 63 Mov VSound_StatePos, ECX Pop ECX Ret VSound_GetBufferUsed: Pop EAX Push ECX Mov ECX, VSound_StatePos Xor ECX, 1 Mov AL, [Byte Ptr VSound_BufferUsed+ECX] Mov VSound_StatePos, ECX Pop ECX Ret VSound_GetTSC: Pop EAX Push ECX Mov ECX, VSound_StatePos Mov AL, [Byte Ptr VSound_TimeStamp1+ECX] Inc ECX And ECX, 7 Mov VSound_StatePos, ECX Pop ECX Ret VSound_Get0: Xor AL, AL Pop ECX Ret VSound_GetDebugValue: Pop EAX Push ECX Mov ECX, VSound_StatePos Mov AL, [Byte Ptr VSound_DebugValue+ECX] Inc ECX And ECX, 3 Mov VSound_StatePos, ECX Pop ECX Ret BeginProc VSound_Client_Hook ;--------------------------------------------------------------------- ; Resolve Contention ;--------------------------------------------------------------------- Push EAX Mov EAX, VSound_Client Cmp VSound_ServerValid, 0 JE NoValidServer Cmp EAX, EBX ; Is the request from the JE Process_IO ; current owner? Test EAX, EAX ; Was there a previous owner? JZ New_Owner NoValidServer: Pop EAX Dispatch_Byte_IO Fall_Through, Mov AL, 80h Blocked_IO: Ret New_Owner: Mov VSound_Client, EBX Mov VSound_ClientCallback, 0 Process_IO: Pop EAX Dispatch_Byte_IO Fall_Through, Push EAX Mov EAX, VSound_State Cmp EAX, VSOUND_CLIENTSTATES JAE VSound_Unknown Jmp [VSound_InTable+EAX*4] VSound_Unknown: Pop EAX Xor AL, AL Ret VSound_Out: Push EAX Mov Byte Ptr VSound_State, AL And EAX, 0FFh Cmp EAX, VSOUND_CLIENTSTATES JAE VSound_Out_Nothing Jmp [VSound_OutTable+EAX*4] VSound_Out_GetTSC: DB 0Fh DB 31h ; RdTSC Mov VSound_TimeStamp1, EAX Mov VSound_TimeStamp2, EDX Jmp VSound_Out_ResetStatePos VSound_Out_GetBufferUsed: Mov EAX, VSound_TailPointer Sub EAX, VSound_HeadPointer And EAX, VSOUND_BUFFERSIZE-1 Mov VSound_BufferUsed, EAX VSound_Out_ResetStatePos: Mov VSound_StatePos, 0 VSound_Out_Nothing: Pop EAX Ret VSound_Out_ResetClient: Xor EAX, EAX Mov VSound_Client, EAX Mov VSound_ClientCallback, EAX Pop EAX Ret VSound_Out_SetCallbackAddress: Mov AX, [EBP+CLIENT_REG_STRUC.CLIENT_CS] ShL EAX, 16 Mov AX, [EBP+CLIENT_REG_STRUC.CLIENT_BX] Mov VSound_ClientCallback, EAX Pop EAX Ret EndProc VSound_Client_Hook ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ;-------------------------------------------------------------------- BeginProc VSound_Server_Hook Push EAX Mov EAX, VSound_Server Cmp EAX, EBX ; Is the request from the JE Process_Server_IO ; current owner? Test EAX, EAX ; Was there a previous owner? JZ New_Server Pop EAX Dispatch_Byte_IO Fall_Through, Mov AL, 80h Server_Blocked_IO: Ret New_Server: Mov VSound_Server, EBX Process_Server_IO: Pop EAX Dispatch_Byte_IO Fall_Through, Cmp VSound_ServerValid, 1 JE VSound_Server_Validated Mov ECX, VSound_ServerInPos Mov AL, [VSound_ServerID+ECX] Inc ECX And ECX, 7 Mov VSound_ServerInPos, ECX Ret VSound_Server_Validated: Mov ECX, VSound_Client Add ECX, 0FFFFFFFFh SBB AL, AL ; Returns 0 if not connected, 0FFh if connected Ret VSound_Server_Out: Test AL, AL ; Reset? JZ VSound_Server_Reset Mov ECX, VSound_ServerOutPos Cmp VSound_ServerValid, 1 JE VSound_ReceiveServerString Cmp [VSound_ServerID+ECX], AL JE VSound_ValidByte Mov VSound_ServerOutPos, 0 Ret VSound_ValidByte: Inc ECX And ECX, 7 Mov VSound_ServerOutPos, ECX JNZ VSound_ServerNotValidated Mov VSound_ServerValid, 1 VSound_ServerNotValidated: Ret VSound_ReceiveServerString: Mov [VSound_ServerString+ECX], AL Inc ECX And ECX, 63 Mov VSound_ServerOutPos, ECX Ret VSound_Server_Reset: Xor ECX, ECX Mov VSound_Server, ECX Mov VSound_ServerValid, ECX Mov VSound_ServerInPos, ECX Mov VSound_ServerOutPos, ECX Ret EndProc VSound_Server_Hook ;--------------------------------------------------------------------- BeginProc VSound_Data_Hook Cmp EBX, VSound_Server JE VSound_Data_Server Cmp EBX, VSound_Client JE VSound_Data_Client Ret VSound_Data_Client: Cmp CX, String_IO or Rep_IO or Byte_Output JNE Data_Client_Simulate PushAD Push ES PushF ClI Push DS Pop ES ShR ECX, 16 ; ECX = segment. Mov EAX, [EBP+CLIENT_REG_STRUC.CLIENT_ECX] ShL ECX, 4 Mov ESI, [EBP+CLIENT_REG_STRUC.CLIENT_ESI] And ESI, 0FFFFh Mov EDI, VSound_TailPointer Add ESI, ECX ; ESI = data source. And EAX, 0FFFFh ; EAX = byte count Test EAX, 3 ; Must be multiple of 4 bytes JNZ VSound_DataClientExit LEA EDX, [EDI+EAX] Add EDI, Offset VSound_Data Cmp EDX, VSOUND_BUFFERSIZE JB VSound_DataClient1 Mov ECX, VSOUND_BUFFERSIZE LEA EAX, [EDX-VSOUND_BUFFERSIZE] Sub ECX, VSound_TailPointer ShR ECX, 2 Rep MovsD Mov EDI, Offset VSound_Data VSound_DataClient1: ShR EAX, 2 And EDX, VSOUND_BUFFERSIZE-1 Mov ECX, EAX Mov VSound_TailPointer, EDX Rep MovsD VSound_DataClientExit: PopF Pop ES PopAD Data_Client_Simulate: Ret VSound_Data_Server: ; ; The server will only receive data if: ; 1) A Rep InsB instruction is used. No other instruction will work ; 2) The ECX count is a multiple of 4 ; 3) The ECX count must be less than BUFFERSIZE Cmp CX, String_IO or Rep_IO or Addr_32_IO or Byte_Input JNE Data_Server_Simulate PushAD Push ES PushF ClI ShR ECX, 16 Mov ES, CX Mov EAX, [EBP+CLIENT_REG_STRUC.CLIENT_ECX] Mov EDI, [EBP+CLIENT_REG_STRUC.CLIENT_EDI] Test EAX, 3 JNZ VSound_DataServerExit Cmp EAX, VSOUND_BUFFERSIZE JAE VSound_DataServerExit ; Want minimum of bytes available and bytes requested Mov ESI, VSound_HeadPointer Mov EBX, VSound_TailPointer Sub EBX, ESI And EBX, VSOUND_BUFFERSIZE-1 ; EBX = bytes available ; EAX = bytes requested Cmp EBX, EAX JB VSound_DataServer1 Mov EBX, EAX VSound_DataServer1: ; EBX = bytes to transfer Sub EAX, EBX ; EAX = bytes to zero LEA EDX, [ESI+EBX] ShR EBX, 2 ; EBX = dwords to transfer Add ESI, Offset VSound_Data Cmp EDX, VSOUND_BUFFERSIZE ; Does it span the buffer boundary? JB VSound_DataServer2 LEA EBX, [EDX-VSOUND_BUFFERSIZE] Mov ECX, VSOUND_BUFFERSIZE ShR EBX, 2 Sub ECX, VSound_HeadPointer ShR ECX, 2 Rep MovsD Mov ESI, Offset VSound_Data VSound_DataServer2: ShR EAX, 2 Mov ECX, EBX Rep MovsD Mov ECX, EAX And EDX, VSOUND_BUFFERSIZE-1 Xor EAX, EAX Mov VSound_HeadPointer, EDX Rep StosD ; ECX = 0 Mov EBX, VSound_Client Cmp VSound_ClientCallback, ECX JE VSound_DataServerExit Test EBX, EBX JZ VSound_DataServerExit Mov EBP, [EBX+CB_S.CB_Client_Pointer] VMMCall Set_Execution_Focus JC VSound_DataServerExit Push_Client_State VMMCall Begin_Nest_V86_Exec MovZX EDX, Word Ptr [VSound_ClientCallback] MovZX ECX, Word Ptr [VSound_ClientCallback+2] VMMCall Simulate_Far_Call VMMCall Resume_Exec VMMCall End_Nest_Exec Pop_Client_State VSound_DataServerExit: PopF Pop ES PopAD Data_Server_Simulate: Ret EndProc VSound_Data_Hook ;--------------------------------------------------------------------- VxD_CODE_ENDS END