|
|
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1997 Microsoft Corporation. All Rights Reserved.
//
//
// History:
// 22-Aug-97 TKB Created Initial Interface Version
//
//==========================================================================;
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <setupapi.h>
#include <spapip.h>
#include <string.h>
#include <devioctl.h>
#include <ks.h>
#include <iks.h>
//////////////////////////////////////////////////////////////
// IKSDriver::
//////////////////////////////////////////////////////////////
IKSDriver::IKSDriver(LPCGUID lpCategory, LPCSTR lpszFriendlyName) { if ( lpszFriendlyName && *lpszFriendlyName ) { if ( m_lpszDriver = GetSymbolicName( lpCategory, lpszFriendlyName ) ) { if ( OpenDriver( GENERIC_READ | GENERIC_WRITE, FILE_FLAG_OVERLAPPED ) ) { } else { // Throw a open failure exception
} } } else { // Throw a bad parameter exception.
} }
IKSDriver::~IKSDriver() { if ( m_lpszDriver ) { delete m_lpszDriver; m_lpszDriver = NULL;
if ( m_hKSDriver ) { if ( CloseDriver() ) { } else { // Throw a close failure exception
} } } }
BOOL IKSDriver::Ioctl(ULONG dwControlCode, LPBYTE pIn, ULONG nIn, LPBYTE pOut, ULONG nOut, ULONG *nReturned, LPOVERLAPPED lpOS ) { BOOL bStatus = FALSE;
if ( IsValid() ) { bStatus = DeviceIoControl( m_hKSDriver, dwControlCode, pIn, nIn, pOut, nOut, nReturned, lpOS ); } else { // Throw an invalid object exception
}
return bStatus; }
#if DBG && 0
#define TRACE printf
#else
#define TRACE
#endif
LPWSTR IKSDriver::GetSymbolicName(LPCGUID lpCategory, LPCSTR szRequestedDevice ) { int index = 0; LPWSTR lpszSymbolicName = NULL; HDEVINFO hDevInfo = SetupDiGetClassDevs( const_cast<GUID*>(lpCategory), NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); if (hDevInfo != INVALID_HANDLE_VALUE) { PSP_DEVICE_INTERFACE_DETAIL_DATA_W pDeviceDetails; SP_DEVICE_INTERFACE_DATA DeviceData = {sizeof(DeviceData)}; BYTE Storage[sizeof(*pDeviceDetails) + MAX_PATH * sizeof(WCHAR)]; SP_DEVINFO_DATA DeviceInfoData = {sizeof(DeviceInfoData)}; CHAR szDeviceDesc[MAX_PATH]; WCHAR wszSymbolicPath[MAX_PATH];
pDeviceDetails = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(Storage); pDeviceDetails->cbSize = sizeof(*pDeviceDetails);
TRACE("Begin SetupDiEnumDeviceInterfaces\n"); while ( SetupDiEnumDeviceInterfaces(hDevInfo, NULL, const_cast<GUID*>(lpCategory), index++, &DeviceData ) ) { TRACE("A) SetupDiGetDeviceInterfaceDetail\n"); if ( SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceData, pDeviceDetails, sizeof(Storage), NULL, &DeviceInfoData) ) { SP_INTERFACE_TO_DEVICE_PARAMS_W Translate;
// Save off the original device path so it can be returned if we match the name
wcscpy( wszSymbolicPath, pDeviceDetails->DevicePath);
ZeroMemory(&Translate,sizeof(Translate)); Translate.ClassInstallHeader.cbSize = sizeof(Translate.ClassInstallHeader); Translate.ClassInstallHeader.InstallFunction = DIF_INTERFACE_TO_DEVICE; Translate.Interface = pDeviceDetails->DevicePath;
TRACE("B) SetupDiSetClassInstallParams\n"); if ( SetupDiSetClassInstallParamsW( hDevInfo, &DeviceInfoData, (PSP_CLASSINSTALL_HEADER)&Translate, sizeof(Translate)) ) { TRACE("C) SetupDiCallClassInstaller\n"); if ( SetupDiCallClassInstaller(DIF_INTERFACE_TO_DEVICE, hDevInfo, &DeviceInfoData) ) { // it was translated find out what to
TRACE("D) SetupDiGetClassInstallParams\n"); if( SetupDiGetClassInstallParamsW(hDevInfo, &DeviceInfoData, (PSP_CLASSINSTALL_HEADER)&Translate, sizeof(Translate), NULL)) { TRACE("E) SetupDiOpenDeviceInfo\n"); if( SetupDiOpenDeviceInfoW(hDevInfo, Translate.DeviceId, NULL, 0, &DeviceInfoData)) { TRACE("F) SetupDiGetDeviceRegistryProperty\n"); if ( SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, NULL, (LPBYTE)&szDeviceDesc, sizeof(szDeviceDesc), NULL ) ) { TRACE("G) Name=%s\n",szDeviceDesc); if ( *szRequestedDevice && *szDeviceDesc && strncmp( szRequestedDevice, szDeviceDesc, min( strlen(szRequestedDevice), strlen(szDeviceDesc) ) ) == 0 ) { TRACE("H) Matched Sympath=%S\n", wszSymbolicPath); lpszSymbolicName = wcscpy( new WCHAR[wcslen(wszSymbolicPath)+1], wszSymbolicPath ); break; } } else { TRACE("SetupDiGetDeviceRegistryProperty()=0x%lx\n", GetLastError()); } } else { TRACE("SetupDiOpenDeviceInfo()=0x%lx\n", GetLastError()); } } else { TRACE("SetupDiGetClassInstallParams()=0x%lx\n", GetLastError()); } } else { TRACE("SetupDiCallClassInstaller()=0x%lx\n", GetLastError()); } } else { TRACE("I) SetupDiGetDeviceRegistryProperty\n"); if ( SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, NULL, (LPBYTE)&szDeviceDesc, sizeof(szDeviceDesc), NULL ) ) { TRACE("J) Name=%s\n",szDeviceDesc); if ( *szRequestedDevice && *szDeviceDesc && strncmp( szRequestedDevice, szDeviceDesc, min( strlen(szRequestedDevice), strlen(szDeviceDesc) ) ) == 0 ) { TRACE("K) Matched Sympath=%S\n",wszSymbolicPath); lpszSymbolicName = wcscpy( new WCHAR[wcslen(wszSymbolicPath)+1], wszSymbolicPath ); break; } } else { TRACE("SetupDiCallClassInstaller()=0x%lx\n", GetLastError()); }
} } } } TRACE("End SetupDiEnumDeviceInterfaces\n");
return lpszSymbolicName; }
BOOL IKSDriver::OpenDriver(DWORD dwAccess, DWORD dwFlags) { BOOL bStatus = FALSE;
SECURITY_ATTRIBUTES SecurityAttributes; SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); SecurityAttributes.bInheritHandle = TRUE; SecurityAttributes.lpSecurityDescriptor = NULL;
m_hKSDriver = CreateFileW( m_lpszDriver, dwAccess, FILE_SHARE_READ | FILE_SHARE_WRITE, &SecurityAttributes, OPEN_EXISTING, dwFlags, NULL );
if ( m_hKSDriver != (HANDLE)-1 ) { bStatus = TRUE; } else { m_hKSDriver = NULL; }
return bStatus; }
BOOL IKSDriver::CloseDriver() { BOOL bStatus = CloseHandle(m_hKSDriver);
m_hKSDriver = NULL;
return bStatus; }
//////////////////////////////////////////////////////////////
// IKSPin::
//////////////////////////////////////////////////////////////
IKSPin::IKSPin(IKSDriver &driver, int nPin, PKSDATARANGE pKSDataRange ) { m_bRunning = FALSE; m_IKSDriver = &driver; m_nPin = nPin; if ( pKSDataRange ) { if ( OpenPin( pKSDataRange ) ) { if ( Run() ) { // We are good to go!
} else { // Throw an run failure exception
} } else { // Throw an open failure exception
} } else { // Throw a bad parameter exception.
} }
IKSPin::~IKSPin() { if ( m_nPin ) { m_nPin = -1; if ( m_hKSPin ) { if ( m_bRunning ) { if ( Stop() ) { } else { // Throw a stop failure exception
} } if ( ClosePin() ) { // We are all destructed.
} else { // Throw a close failure exception
} } } }
BOOL IKSPin::Ioctl(ULONG dwControlCode, void *pInput, ULONG nInput, void *pOutput, ULONG nOutput, ULONG *nReturned, LPOVERLAPPED lpOS ) { BOOL bStatus = FALSE;
if ( IsValid() ) { bStatus = DeviceIoControl( m_hKSPin, dwControlCode, pInput, nInput, pOutput, nOutput, nReturned, lpOS ); if ( !bStatus ) { int nError = GetLastError(); if ( nError == ERROR_IO_PENDING ) bStatus = TRUE; } } else { }
return bStatus; }
int IKSPin::ReadData( LPBYTE lpBuffer, int nBytes, DWORD *lpcbReturned, LPOVERLAPPED lpOS ) { int nStatus = -1; static int counter = 0;
if ( lpBuffer && IsValid() ) { if ( lpOS ) { DWORD dwReturnedHeaderSize; // Ignored in this case.
KSSTREAM_HEADER *lpStreamHeader = (KSSTREAM_HEADER *)GlobalAlloc(GMEM_FIXED, sizeof(KSSTREAM_HEADER) ); if ( lpStreamHeader ) { // Cache away the stream header structure so that we can get the "DataUsed" member later
lpOS->Offset = (DWORD)lpStreamHeader;
RtlZeroMemory(lpStreamHeader, sizeof(*lpStreamHeader) ); lpStreamHeader->PresentationTime.Numerator = 1; lpStreamHeader->PresentationTime.Denominator = 1; lpStreamHeader->Size = sizeof(*lpStreamHeader); lpStreamHeader->Data = lpBuffer; lpStreamHeader->FrameExtent = nBytes;
if ( Ioctl( IOCTL_KS_READ_STREAM, NULL, 0, (LPBYTE)lpStreamHeader, sizeof(*lpStreamHeader), &dwReturnedHeaderSize, lpOS ) ) { nStatus = 0; } } *lpcbReturned = 0; } else { #ifdef SUPPORT_NON_OVERLAPPED_READS
DWORD dwReturnedHeaderSize; KSSTREAM_HEADER StreamHeader; RtlZeroMemory(&StreamHeader, sizeof(StreamHeader) ); StreamHeader.PresentationTime.Numerator = 1; StreamHeader.PresentationTime.Denominator = 1; StreamHeader.Size = sizeof(StreamHeader); StreamHeader.Data = lpBuffer; StreamHeader.FrameExtent = nBytes;
if ( Ioctl( IOCTL_KS_READ_STREAM, NULL, 0, (LPBYTE)&StreamHeader, sizeof(StreamHeader), &dwReturnedHeaderSize, lpOS ) && dwReturnedHeaderSize == sizeof(StreamHeader) ) { *lpcbReturned = StreamHeader.DataUsed; nStatus = 0; } #endif
} }
return nStatus; }
int IKSPin::GetOverlappedResult( LPOVERLAPPED lpOS, LPDWORD lpdwTransferred , BOOL bWait ) { int nStatus = -1; if ( IsValid() && lpOS && lpOS->hEvent ) { // Get the cached STREAM_HEADER memory so we can get the actual data transferred.
KSSTREAM_HEADER *lpStreamHeader = (KSSTREAM_HEADER *)lpOS->Offset;
if ( lpdwTransferred ) *lpdwTransferred = 0;
if ( lpStreamHeader && WaitForSingleObject( lpOS->hEvent, 0 ) == WAIT_OBJECT_0 ) { DWORD dwKSBuffer = 0; if ( ::GetOverlappedResult( m_hKSPin, lpOS, &dwKSBuffer, bWait ) && dwKSBuffer == sizeof(KSSTREAM_HEADER) && lpOS->InternalHigh == sizeof(KSSTREAM_HEADER) ) {
if ( lpdwTransferred ) *lpdwTransferred = lpStreamHeader->DataUsed;
// Delete the KSSTREAM_HEADER we allocated
GlobalFree( (HGLOBAL)lpStreamHeader ); lpOS->Offset = 0; nStatus = 0; } else { nStatus = GetLastError(); } } else nStatus = ERROR_IO_PENDING; }
return nStatus; }
BOOL IKSPin::Run() { BOOL bCompleted = FALSE; if ( !m_bRunning ) { if ( SetRunState( KSSTATE_RUN ) ) { // We are now running
m_bRunning = TRUE; bCompleted = TRUE; } else { // Throw a run failure exception
} } else { // Throw an invalid state exception
} return bCompleted; }
BOOL IKSPin::Stop() { BOOL bCompleted = FALSE; if ( m_bRunning ) { if ( SetRunState(KSSTATE_STOP) ) { // We are now stopped.
m_bRunning = FALSE; bCompleted = TRUE; } else { // Log the stop failure
} } else { // Throw an invalid state exception
} return bCompleted; }
BOOL IKSPin::GetRunState( PKSSTATE pKSState ) { KSPROPERTY KSProp={0}; KSProp.Set = KSPROPSETID_Connection; KSProp.Id = KSPROPERTY_CONNECTION_STATE; KSProp.Flags = KSPROPERTY_TYPE_GET; DWORD dwReturned = 0; BOOL bStatus = Ioctl( IOCTL_KS_PROPERTY, &KSProp, sizeof(KSProp), pKSState, sizeof(*pKSState), &dwReturned);
return bStatus && dwReturned == sizeof(pKSState); }
BOOL IKSPin::SetRunState( KSSTATE KSState ) { KSPROPERTY KSProp={0}; KSProp.Set = KSPROPSETID_Connection; KSProp.Id = KSPROPERTY_CONNECTION_STATE; KSProp.Flags = KSPROPERTY_TYPE_SET; DWORD dwReturned = 0; BOOL bStatus = Ioctl( IOCTL_KS_PROPERTY, &KSProp, sizeof(KSProp), &KSState, sizeof(KSState), &dwReturned);
return bStatus && dwReturned == sizeof(KSState); }
BOOL IKSPin::OpenPin(PKSDATARANGE pKSDataRange ) { BOOL bStatus = FALSE; struct tagPIN_CONNECT_DATARANGE { KSPIN_CONNECT PinConnect; KSDATARANGE DataRange; BYTE reserved[1024]; // Large enough for any reasonable specifier structure.
} PinGlob;
RtlZeroMemory(&PinGlob, sizeof(PinGlob));
if ( pKSDataRange->FormatSize <= sizeof(KSDATARANGE)+sizeof(PinGlob.reserved) ) { PinGlob.PinConnect.Interface.Set = KSINTERFACESETID_Standard; PinGlob.PinConnect.Interface.Id = KSINTERFACE_STANDARD_STREAMING; // STREAMING
PinGlob.PinConnect.Medium.Set = KSMEDIUMSETID_Standard; PinGlob.PinConnect.Medium.Id = KSMEDIUM_STANDARD_DEVIO; PinGlob.PinConnect.PinId = m_nPin; PinGlob.PinConnect.PinToHandle = NULL; // no "connect to"
PinGlob.PinConnect.Priority.PriorityClass = KSPRIORITY_NORMAL; PinGlob.PinConnect.Priority.PrioritySubClass = 1; RtlCopyMemory( &PinGlob.DataRange, pKSDataRange, pKSDataRange->FormatSize ); if ( KsCreatePin( m_IKSDriver->m_hKSDriver, &PinGlob.PinConnect, GENERIC_READ | GENERIC_WRITE, &m_hKSPin ) == 0 && m_hKSPin > 0 ) bStatus = TRUE; else m_hKSPin = 0; } else { // Throw a bad parameter exception.
}
return bStatus; }
BOOL IKSPin::ClosePin() { BOOL bStatus = TRUE;
bStatus = CloseHandle(m_hKSPin); m_hKSPin = NULL;
return bStatus; }
//////////////////////////////////////////////////////////////
// IKSProperty::
//////////////////////////////////////////////////////////////
IKSProperty::IKSProperty(IKSDriver &driver, LPCGUID Set, ULONG Id, ULONG Size) : m_Set(*Set), m_Id(Id), m_Size(Size), m_IKSPin(NULL), m_IKSDriver(NULL) { if ( m_Size > 0 ) { if ( OpenProperty() ) { m_IKSDriver = &driver; } else { // Throw an open failure exception
} } else { // Throw a bad parameter exception.
} }
IKSProperty::IKSProperty(IKSPin &pin, LPCGUID Set, ULONG Id, ULONG Size) : m_Set(*Set), m_Id(Id), m_Size(Size), m_IKSPin(NULL), m_IKSDriver(NULL) { if ( m_Size > 0 ) { if ( OpenProperty() ) { m_IKSPin = &pin; } else { // Throw an open failure exception
} } else { // Throw a bad parameter exception.
} }
IKSProperty::~IKSProperty() { if ( m_hKSProperty ) { if ( CloseProperty() ) { } else { // Throw a close failure exception
} } }
BOOL IKSProperty::SetValue(void *nValue) { BOOL bStatus = FALSE; PKSPROPERTY pKSProperty = (PKSPROPERTY)m_hKSProperty; LPBYTE pProperty = (LPBYTE)(pKSProperty+1); DWORD nReturned = 0; if ( IsValid() ) { ZeroMemory(pKSProperty, sizeof(KSPROPERTY)+m_Size); pKSProperty->Flags = KSPROPERTY_TYPE_SET; pKSProperty->Set = m_Set; pKSProperty->Id = m_Id;
CopyMemory( pProperty, nValue, m_Size );
if ( m_IKSDriver ) { bStatus = m_IKSDriver->Ioctl( IOCTL_KS_PROPERTY, (LPBYTE)pKSProperty, sizeof(KSPROPERTY)+m_Size, (LPBYTE)pKSProperty, sizeof(KSPROPERTY)+m_Size, &nReturned, NULL); } else if ( m_IKSPin ) { bStatus = m_IKSPin->Ioctl( IOCTL_KS_PROPERTY, (LPBYTE)pKSProperty, sizeof(KSPROPERTY)+m_Size, (LPBYTE)pKSProperty, sizeof(KSPROPERTY)+m_Size, &nReturned, NULL); } } else { }
return bStatus; }
BOOL IKSProperty::GetValue(void *nValue) { BOOL bStatus = FALSE; PKSPROPERTY pKSProperty = (PKSPROPERTY)m_hKSProperty; LPBYTE pProperty = (LPBYTE)(pKSProperty+1); DWORD nReturned = 0;
if ( IsValid() ) { ZeroMemory(pKSProperty, sizeof(KSPROPERTY)+m_Size); pKSProperty->Flags = KSPROPERTY_TYPE_GET; pKSProperty->Set = m_Set; pKSProperty->Id = m_Id;
if ( m_IKSDriver ) { bStatus = m_IKSDriver->Ioctl( IOCTL_KS_PROPERTY, (LPBYTE)pKSProperty, sizeof(KSPROPERTY)+m_Size, (LPBYTE)pKSProperty, sizeof(KSPROPERTY)+m_Size, &nReturned, NULL); } else if ( m_IKSPin ) { bStatus = m_IKSPin->Ioctl( IOCTL_KS_PROPERTY, (LPBYTE)pKSProperty, sizeof(KSPROPERTY)+m_Size, (LPBYTE)pKSProperty, sizeof(KSPROPERTY)+m_Size, &nReturned, NULL); }
if ( bStatus ) CopyMemory( nValue, pProperty, m_Size ); } else { }
return bStatus; }
// Prob: the buffer is overrun during the Ioctl w/CCDECODE substreams.
#define BUFFER_SLOP 4
BOOL IKSProperty::OpenProperty() { BOOL bStatus = TRUE; LONG nTotalSize = sizeof(KSPROPERTY)+m_Size+BUFFER_SLOP; m_hKSProperty = (HANDLE)new BYTE[nTotalSize]; return bStatus; }
BOOL IKSProperty::CloseProperty() { BOOL bStatus = TRUE;
delete (void *)m_hKSProperty; m_hKSProperty = NULL;
return bStatus; }
//////////////////////////////////////////////////////////////
// Embedded class tests
//////////////////////////////////////////////////////////////
#if defined(_CLASSTESTS)
IKSDriver TestDriver(&KSCATEGORY_VBICODEC,"Closed Caption Decoder"); IKSPin TestPin(TestDriver, &GUID_NULL, &GUID_NULL, &GUID_NULL); IKSProperty TestProperty1(TestDriver, 0); IKSProperty TestProperty2(TestPin, 0);
#endif
/*EOF*/
|