|
|
///////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 1998-1999 Microsoft Corporation
//
// Name: Manager.cpp
//
// Description: Implementation of the CTerminalManager object
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "termmgr.h"
#include "manager.h"
#include "PTUtil.h"
#define INSTANTIATE_GUIDS_NOW
#include "allterm.h"
#undef INSTANTIATE_GUIDS_NOW
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// CTerminalManager constructor
//
// Parameters:
// None.
//
// Returns:
// Nothing.
//
CTerminalManager::CTerminalManager() { LOG((MSP_TRACE, "CTerminalManager::CTerminalManager - enter")); LOG((MSP_TRACE, "CTerminalManager::CTerminalManager - exit")); }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// GetDynamicTerminalClasses
//
// The MSP will call this method to get a list of dynamic terminal classes
// that the Terminal Manager supports. The MSP is responsible for allocating
// and deallocating the ppTerminals buffer.
//
// Parameters:
// dwMediaType: [in] A DWORD bitmask consisting of one or more
// TAPIMEDIATYPEs ORed together. Most MSPs will
// pass in (DWORD) (TAPIMEDIATYPE_AUDIO |
// TAPIMEDIATYPE_VIDEO). If an MSP is only
// interested in terminal classes that can be used
// to create terminals with a particular media
// type, it may pass in that media type instead
// (e.g., TAPIMEDIATYPE_AUDIO).
// pdwNumClasses: [in, out] Pointer to a DWORD. On entry, indicates
// the size of the buffer pointed to in
// pTerminalClasses. On success, it will be filled
// in with the actual number of class IIDs returned.
// If the buffer is not big enough, the method will
// return TAPI_E_NOTENOUGHMEMORY, and it will be
// filled in the with number of IIDs needed.
// pTerminalClasses: [out] On success, filled in with an array of terminal
// class IIDs that are supported by the MSP for this
// address. This value may be NULL, in which case
// pdwNumClasses will return the needed buffer size.
//
// Returns:
// S_OK Success.
// E_POINTER A pointer argument is invalid.
// TAPI_E_NOTENOUGHMEMORY The specified buffer is not large enough to
// contain all of the available dynamic
// terminal classes.
STDMETHODIMP CTerminalManager::GetDynamicTerminalClasses( IN DWORD dwMediaTypes, IN OUT DWORD * pdwNumClasses, OUT IID * pTerminalClasses ) { //
// no shared data = no locking here
//
LOG((MSP_TRACE, "CTerminalManager::GetDynamicTerminalClasses - enter"));
//
// Check parameters.
//
if ( TM_IsBadWritePtr(pdwNumClasses, sizeof(DWORD) ) ) { LOG((MSP_ERROR, "CTerminalManager::GetDynamicTerminalClasses - " "bad NumClasses pointer - returning E_POINTER")); return E_POINTER; }
//
// Let's find also the temrinals from the registry
//
CLSID* pTerminals = NULL; DWORD dwTerminals = 0; HRESULT hr = E_FAIL;
hr = CPTUtil::ListTerminalClasses( dwMediaTypes, &pTerminals, &dwTerminals );
if( FAILED(hr) ) {
LOG((MSP_ERROR, "CTerminalManager::GetDynamicTerminalClasses - " "ListTerminalClasses failed - returning 0x%08x", hr)); return hr; }
//
// If the caller is just asking for the needed buffer size, tell them.
//
if (pTerminalClasses == NULL) { *pdwNumClasses = dwTerminals; delete[] pTerminals;
LOG((MSP_TRACE, "CTerminalManager::GetDynamicTerminalClasses - " "provided needed buffer size - " "returning S_OK"));
return S_OK; }
//
// Otherwise, the caller is asking for the terminal classes.
//
if ( TM_IsBadWritePtr(pTerminalClasses, (*pdwNumClasses) * sizeof(IID) ) ) { delete[] pTerminals;
LOG((MSP_ERROR, "CTerminalManager::GetDynamicTerminalClasses - " "bad TerminalClasses pointer - returning E_POINTER")); return E_POINTER; }
//
// See if the caller gave us enough buffer space to return all the terminal
// classes. If not, tell them so and stop.
//
if ( dwTerminals > *pdwNumClasses ) { //
// Fill in the number of classes that are available.
//
*pdwNumClasses = dwTerminals; delete[] pTerminals;
LOG((MSP_ERROR, "CTerminalManager::GetDynamicTerminalClasses - " "not enough space for requested info - " "returning TAPI_E_NOTENOUGHMEMORY"));
return TAPI_E_NOTENOUGHMEMORY; }
//
// Copy the terminal classes that match this/these media type(s)
// and direction(s).
//
//
// Copy the terminals from registry
//
for( DWORD dwTerminal = 0; dwTerminal < dwTerminals; dwTerminal++) { pTerminalClasses[dwTerminal] = pTerminals[dwTerminal]; }
*pdwNumClasses = dwTerminals;
delete[] pTerminals;
LOG((MSP_TRACE, "CTerminalManager::GetDynamicTerminalClasses - exit S_OK")); return S_OK; }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// CreateDynamicTerminal
//
// This method is called by the MSP to create a dynamic terminal object. The
// Terminal Manager verifies that the MediaType and Direction are valid for
// the terminal class being created. This call AddRef()s the terminal object
// before returning it.
//
// Parameters:
// iidTerminalClass: [in] IID of the terminal class to be created.
// dwMediaType: [in] TAPI media type of the terminal to be created.
// Direction: [in] Terminal direction of the terminal to be
// created.
// ppTerminal: [out] Returned created terminal object
//
// Returns:
//
// S_OK Success.
// E_POINTER A pointer argument is invalid.
// E_OUTOFMEMORY There is not enough memory to create the terminal object.
// E_INVALIDARG The terminal class is invalid or not supported, or the media
// type or direction is invalid for the indicated terminal
// class.
//
STDMETHODIMP CTerminalManager::CreateDynamicTerminal( IN IUnknown * pOuterUnknown, IN IID iidTerminalClass, IN DWORD dwMediaType, IN TERMINAL_DIRECTION Direction, IN MSP_HANDLE htAddress, OUT ITTerminal ** ppTerminal ) { //
// no shared data = no locking here
//
LOG((MSP_TRACE, "CTerminalManager::CreateDynamicTerminal - enter"));
//
// Check parameters.
// Only one media type can be set.
//
if ( (pOuterUnknown != NULL) && IsBadReadPtr(pOuterUnknown, sizeof(IUnknown)) ) { LOG((MSP_ERROR, "CTerminalManager::CreateDynamicTerminal - " "outer unknown pointer invalid - returning E_POINTER"));
return E_POINTER; }
if ( TM_IsBadWritePtr(ppTerminal, sizeof(ITTerminal *)) ) { LOG((MSP_ERROR, "CTerminalManager::CreateDynamicTerminal - " "terminal output pointer invalid - returning E_POINTER"));
return E_POINTER; }
//
// dwMediaType can be a combination of media types, but it still must be
// legal
//
if ( !IsValidAggregatedMediaType(dwMediaType) ) { LOG((MSP_ERROR, "CTerminalManager::CreateDynamicTerminal - " "ivalid media type [%lx] requested - returning E_INVALIDARG", dwMediaType));
return E_INVALIDARG; }
//
// Verify also TD_MULTITRACK_MIXED
//
if ( ( Direction != TD_CAPTURE ) && ( Direction != TD_RENDER ) && ( Direction != TD_MULTITRACK_MIXED)) { LOG((MSP_ERROR, "CTerminalManager::CreateDynamicTerminal - " "invalid direction requested - returning E_INVALIDARG"));
return E_INVALIDARG; }
//
// Declare CLSID for plug-in terminal
//
CLSID clsidTerminal = CLSID_NULL;
//
// Go to find out the terminal in registry
//
HRESULT hr = E_FAIL; CPTTerminal Terminal;
hr = CPTUtil::SearchForTerminal( iidTerminalClass, dwMediaType, Direction, &Terminal);
if( FAILED(hr) ) { LOG((MSP_ERROR, "CTerminalManager::CreateDynamicTerminal - " "SearchForTerminal failed - returning 0x%08x", hr)); return hr; }
//
// Using the CLSID field in our array entry, CoCreate the dynamic
// terminal.
//
hr = CoCreateInstance(Terminal.m_clsidCOM, pOuterUnknown, CLSCTX_INPROC_SERVER, IID_ITTerminal, (void **) ppTerminal);
if ( FAILED(hr) ) { LOG((MSP_ERROR, "CTerminalManager::CreateDynamicTerminal - " "CoCreateInstance of requested terminal failed - " "returning 0x%08x", hr));
return hr; }
//
// Initialize the dynamic terminal instance with the media type
// and direction.
//
ITPluggableTerminalInitialization * pTerminalInitialization;
hr = (*ppTerminal)->QueryInterface(IID_ITPluggableTerminalInitialization, (void **) &pTerminalInitialization);
if ( FAILED(hr) ) { LOG((MSP_ERROR, "CTerminalManager::CreateDynamicTerminal - " "QueryInterface for private terminal interface failed - " "returning 0x%08x", hr));
(*ppTerminal)->Release(); *ppTerminal = NULL; // make buggy apps more explicitly buggy
return hr; }
hr = pTerminalInitialization->InitializeDynamic(iidTerminalClass, dwMediaType, Direction, htAddress);
pTerminalInitialization->Release();
if ( FAILED(hr) ) { LOG((MSP_ERROR, "CTerminalManager::CreateDynamicTerminal - " "private Initialize() failed - " "returning 0x%08x", hr));
(*ppTerminal)->Release(); *ppTerminal = NULL; // make buggy apps more explicitly buggy
return hr; }
LOG((MSP_TRACE, "CTerminalManager::CreateDynamicTerminal - " "exit S_OK")); return S_OK; }
// ITTerminalManager2
STDMETHODIMP CTerminalManager::GetPluggableSuperclasses( IN OUT DWORD * pdwNumSuperclasses, OUT IID * pSuperclasses ) { LOG((MSP_TRACE, "CTerminalManager::GetPluggableSuperclasses - enter"));
//
// Check parameters.
//
if ( TM_IsBadWritePtr(pdwNumSuperclasses, sizeof(DWORD) ) ) { LOG((MSP_ERROR, "CTerminalManager::GetPluggableSuperclasses - " "bad NumClasses pointer - returning E_POINTER")); return E_POINTER; }
//
// The SafeArray VAriant for Superclasses
//
HRESULT hr = E_FAIL; CLSID* pSuperclassesCLSID = NULL; DWORD dwSuperclasses = 0;
hr = CPTUtil::ListTerminalSuperclasses( &pSuperclassesCLSID, &dwSuperclasses );
if( FAILED(hr) ) { LOG((MSP_ERROR, "CTerminalManager::GetPluggableSuperclasses - " "ListTerminalSuperclasses failed - returning 0x%08x", hr)); return hr; }
//
// If the caller is just asking for the needed buffer size, tell them.
//
if (pSuperclasses == NULL) { *pdwNumSuperclasses = dwSuperclasses;
delete[] pSuperclassesCLSID;
LOG((MSP_TRACE, "CTerminalManager::GetPluggableSuperclasses - " "provided needed buffer size - returning S_OK"));
return S_OK; }
//
// Otherwise, the caller is asking for the terminal classes.
//
if ( TM_IsBadWritePtr(pSuperclasses, (*pdwNumSuperclasses) * sizeof(IID) ) ) { delete[] pSuperclassesCLSID;
LOG((MSP_ERROR, "CTerminalManager::GetPluggableSuperclasses - " "bad Superclasses pointer - returning E_POINTER")); return E_POINTER; }
//
// See if the caller gave us enough buffer space to return all the terminal
// classes. If not, tell them so and stop.
//
if ( dwSuperclasses > *pdwNumSuperclasses ) { //
// Fill in the number of classes that are available.
//
*pdwNumSuperclasses = dwSuperclasses;
delete[] pSuperclassesCLSID;
LOG((MSP_ERROR, "CTerminalManager::GetPluggableSuperclasses - " "not enough space for requested info - " "returning TAPI_E_NOTENOUGHMEMORY"));
return TAPI_E_NOTENOUGHMEMORY; }
//
// Copy the terminal classes that match this/these media type(s)
// and direction(s).
//
for( DWORD dwSuperclass = 0; dwSuperclass < dwSuperclasses; dwSuperclass++) { pSuperclasses[dwSuperclass] = pSuperclassesCLSID[dwSuperclass]; }
*pdwNumSuperclasses = dwSuperclasses;
// Clean-up
delete[] pSuperclassesCLSID; LOG((MSP_TRACE, "CTerminalManager::GetPluggableSuperclasses - exit S_OK")); return S_OK; }
STDMETHODIMP CTerminalManager::GetPluggableTerminalClasses( IN IID iidSuperclass, IN DWORD dwMediaTypes, IN OUT DWORD * pdwNumTerminals, OUT IID * pTerminals ) { LOG((MSP_TRACE, "CTerminalManager::GetPluggableTerminalClasses - enter"));
//
// Check parameters.
//
if ( TM_IsBadWritePtr(pdwNumTerminals, sizeof(DWORD) ) ) { LOG((MSP_ERROR, "CTerminalManager::GetPluggableTerminalClasses - " "bad NumSuperlasses pointer - returning E_POINTER")); return E_POINTER; }
//
// Get BSTR for iidSuperclass
//
if( dwMediaTypes == 0) { LOG((MSP_ERROR, "CTerminalManager::GetPluggableTerminalClasses exit -" "dwMediaTypes invalid, returns E_INVALIDARG"));
return E_INVALIDARG; }
if( (dwMediaTypes & ( ((long)TAPIMEDIATYPE_AUDIO) | ((long)TAPIMEDIATYPE_VIDEO) | ((long)TAPIMEDIATYPE_MULTITRACK))) != dwMediaTypes ) { LOG((MSP_ERROR, "CTerminalManager::GetPluggableTerminalClasses exit -" "dwMediaTypes invalid, returns E_INVALIDARG"));
return E_INVALIDARG; }
//
// Get the object Superclass
//
CPTSuperclass Superclass; Superclass.m_clsidSuperclass = iidSuperclass;
//
// Get the terminals for this superclass
//
CLSID* pTerminalClasses = NULL; DWORD dwTerminalClasses = 0; HRESULT hr = E_FAIL; hr = Superclass.ListTerminalClasses( dwMediaTypes, &pTerminalClasses, &dwTerminalClasses );
if( FAILED(hr) ) { LOG((MSP_ERROR, "CTerminalManager::GetPluggableTerminalClasses - " "ListTerminalClasses failed - returning 0x%08x", hr)); return hr; }
//
// If the caller is just asking for the needed buffer size, tell them.
//
if (pTerminals == NULL) { *pdwNumTerminals = dwTerminalClasses;
delete[] pTerminalClasses;
LOG((MSP_TRACE, "CTerminalManager::GetPluggableTerminalClasses - " "provided needed buffer size - " "returning S_OK"));
return S_OK; }
//
// Otherwise, the caller is asking for the terminal classes.
//
if ( TM_IsBadWritePtr(pTerminals, (*pdwNumTerminals) * sizeof(IID) ) ) { delete[] pTerminalClasses;
LOG((MSP_ERROR, "CTerminalManager::GetPluggableTerminalClasses - " "bad TerminalClasses pointer - returning E_POINTER")); return E_POINTER; }
//
// See if the caller gave us enough buffer space to return all the terminal
// classes. If not, tell them so and stop.
//
if ( dwTerminalClasses > *pdwNumTerminals ) { //
// Fill in the number of classes that are available.
//
*pdwNumTerminals = dwTerminalClasses;
delete[] pTerminalClasses;
LOG((MSP_ERROR, "CTerminalManager::GetPluggableTerminalClasses - " "not enough space for requested info - " "returning TAPI_E_NOTENOUGHMEMORY"));
return TAPI_E_NOTENOUGHMEMORY; }
//
// Copy the terminal classes that match this/these media type(s)
// and direction(s).
//
for( DWORD dwTerminal = 0; dwTerminal < dwTerminalClasses; dwTerminal++) { pTerminals[dwTerminal] = pTerminalClasses[dwTerminal]; }
*pdwNumTerminals = dwTerminalClasses;
// Clean-up
delete[] pTerminalClasses; LOG((MSP_TRACE, "CTerminalManager::GetPluggableTerminalClasses - exit S_OK")); return S_OK; }
// eof
|