/*++ Copyright (c) 1997-1999 Microsoft Corporation Module Name: ptutil.cpp Abstract: Implementation of Plug terminal registration classes. --*/ #include "stdafx.h" #include "PTUtil.h" #include "manager.h" /////////////////////////////////////////// // CPTUtil implementation // HRESULT CPTUtil::RecursiveDeleteKey( IN HKEY hKey, IN BSTR bstrKeyChild ) { LOG((MSP_TRACE, "CPTUtil::RecursiveDeleteKey - enter")); // // Validates the arguments // if( NULL == hKey ) { LOG((MSP_TRACE, "CPTUtil::RecursiveDeleteKey exit -" "hKey was NULL")); return S_OK; } if( IsBadStringPtr( bstrKeyChild, (UINT)-1)) { LOG((MSP_ERROR, "CPTUtil::RecursiveDeleteKey exit - " "bstrKeyChild invalid, returns E_INVALIDARG")); return E_INVALIDARG; } // // Open the child key // HKEY hKeyChild; LONG lResult = RegOpenKeyEx( hKey, bstrKeyChild, 0, KEY_ALL_ACCESS, &hKeyChild); if( ERROR_SUCCESS != lResult ) { LOG((MSP_ERROR, "CPTUtil::RecursiveDeleteKey exit - " "RegOpenKeyEx failed, returns E_UNEXPECTED")); return E_UNEXPECTED; } // // Enumerate the descendents // FILETIME time; TCHAR szBuffer[PTKEY_MAXSIZE]; DWORD dwSize = PTKEY_MAXSIZE; while( RegEnumKeyEx( hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) { // // Put the child name into a BSTR // BSTR bstrChild = SysAllocString(szBuffer); if( IsBadStringPtr( bstrChild, (UINT)(-1)) ) { RegCloseKey(hKeyChild); LOG((MSP_ERROR, "CPTUtil::RecursiveDeleteKey exit - " "SysAllocString failed, return E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Delete the child // HRESULT hr; hr = RecursiveDeleteKey(hKeyChild, bstrChild); // // Clean-up bstrChild // SysFreeString(bstrChild); if( FAILED(hr) ) { RegFlushKey(hKeyChild); RegCloseKey(hKeyChild); LOG((MSP_ERROR, "CPTUtil::RecursiveDeleteKey exit - " "RecursiveDeleteKey failed, returns 0%08x", hr)); return hr; } // // Reset the buffer size // dwSize = PTKEY_MAXSIZE; } // // Close the child // RegFlushKey(hKeyChild); RegCloseKey(hKeyChild); HRESULT hr; hr = RegDeleteKey( hKey, bstrKeyChild); RegFlushKey( hKey ); LOG((MSP_TRACE, "CPTUtil::RecursiveDeleteKey - exit 0x%08x", hr)); return hr; } HRESULT CPTUtil::ListTerminalSuperclasses( OUT CLSID** ppSuperclasses, OUT DWORD* pdwCount ) { LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - enter")); // // Validates argument // if( TM_IsBadWritePtr( ppSuperclasses, sizeof(CLSID*)) ) { LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit -" "pClasses invalid, returns E_POINTER")); return E_POINTER; } if( TM_IsBadWritePtr( pdwCount, sizeof(DWORD)) ) { LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit -" "pClasses invalid, returns E_POINTER")); return E_POINTER; } // // Initialize the output arguments // *ppSuperclasses = NULL; *pdwCount = 0; // // Get the key path for terminal class // WCHAR szKey[ 256 ]; wsprintf( szKey, L"%s", PTKEY_TERMINALS ); LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - " "TerminalsKey is %s", szKey)); // // Open the terminal class key // HKEY hKey; LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey); // // Validates registry operation // if( ERROR_SUCCESS != lResult ) { LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit - " "RegOpenKeyEx failed, returns E_UNEXPECTED")); return E_UNEXPECTED; } // // Create the buffer for the CLSIDs // DWORD dwArraySize = 8; CLSID* pCLSIDs = new CLSID[ dwArraySize ]; if( pCLSIDs == NULL ) { // Clean-up hKey RegCloseKey( hKey ); LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit - " "new operator failed, returns E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Enumerate the descendents // HRESULT hr = S_OK; // The error code FILETIME time; // We need this in RegEnumKeyEx TCHAR szBuffer[PTKEY_MAXSIZE]; // Buffer DWORD dwSize = PTKEY_MAXSIZE; // Buffer size DWORD dwChildKey = 0; // Child key index from the registry DWORD dwCLSIDIndex = 0; // CLSID index into the array while( RegEnumKeyEx( hKey, dwChildKey, szBuffer, &dwSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) { LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - " "we read the buffer: %s", szBuffer)); // Prepare for the next child key dwChildKey++; dwSize = PTKEY_MAXSIZE; // Try to get the CLSID from this key CLSID clsid = CLSID_NULL; HRESULT hr = CLSIDFromString( szBuffer, &clsid); if( FAILED(hr) ) { // Go to the next child key continue; } // Have we enougth space for this element? if( dwArraySize <= dwCLSIDIndex ) { LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - " "we have to increase the buffer size")); // We have to increase the space, double the size dwArraySize *= 2; CLSID* pNewCLSIDs = new CLSID[ dwArraySize ]; if( pNewCLSIDs == NULL ) { hr = E_OUTOFMEMORY; break; } // Copies into the new buffer the old buffer memcpy( pNewCLSIDs, pCLSIDs, sizeof(CLSID)*dwArraySize/2); // Delete the old array delete[] pCLSIDs; // Set the new array to the old pointer pCLSIDs = pNewCLSIDs; } // We set the item into the CLSID array pCLSIDs[ dwCLSIDIndex] = clsid; dwCLSIDIndex++; } // // Clean-up hKey // RegCloseKey( hKey ); if( FAILED(hr) ) { // Clean-up delete[] pCLSIDs; LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit - " "failed, returns 0x%08x", hr)); return hr; } // // Set the returning values // *ppSuperclasses = pCLSIDs; *pdwCount = dwCLSIDIndex; LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - exit")); return S_OK; } HRESULT CPTUtil::SearchForTerminal( IN IID iidTerminal, IN DWORD dwMediaType, IN TERMINAL_DIRECTION Direction, OUT CPTTerminal* pTerminal ) { LOG((MSP_TRACE, "CPTUtil::SearchForTerminal - enter")); // // Get the plug-in terminal superclasses // CLSID* pSuperclasses = NULL; DWORD dwSuperclasses = 0; HRESULT hr = E_FAIL; hr = ListTerminalSuperclasses( &pSuperclasses, &dwSuperclasses ); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTUtil::SearchForTerminal - exit " "ListTerminalSuperclasses failed, returns 0x%08x", hr)); return hr; } // // Enumerate the plug-in terminal superclasses // for( DWORD dwSuperclass = 0; dwSuperclass < dwSuperclasses; dwSuperclass++) { // // If we want a exact terminal (Exact) or just first matching // terminal from this superclass // BOOL bPTExact = (pSuperclasses[dwSuperclass] != iidTerminal); // // Get the terminal // hr = FindTerminal( pSuperclasses[dwSuperclass], bPTExact ? iidTerminal : CLSID_NULL, dwMediaType, Direction, bPTExact, pTerminal); if( FAILED(hr)) { if( !bPTExact) { // // We had to find a terminal in this terminal class // sorry!!! break; } } else { // // cool! we found it // break; } } // // Clean-up superclasses array, bstrTermialGUID // delete[] pSuperclasses; // // Return // LOG((MSP_TRACE, "CPTUtil::SearchForTerminal - exit 0x%08x", hr)); return hr; } HRESULT CPTUtil::FindTerminal( IN CLSID clsidSuperclass, IN CLSID clsidTerminal, IN DWORD dwMediaType, IN TERMINAL_DIRECTION Direction, IN BOOL bExact, OUT CPTTerminal* pTerminal) { LOG((MSP_TRACE, "CPTUtil::FindTerminal - exit")); // // Terminal class object // CPTSuperclass Superclass; Superclass.m_clsidSuperclass = clsidSuperclass; // // The terminals array // CLSID* pTerminals = NULL; DWORD dwTerminals = 0; HRESULT hr = E_FAIL; // // Lists the terminals for a specific terminal class // hr = Superclass.ListTerminalClasses( dwMediaType, &pTerminals, &dwTerminals ); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTUtil::FindTerminal - exit " "ListTerminalSuperclasses failed, returns 0x%08x", hr)); return hr; } // // Enumerate terminals // hr = E_FAIL; for( DWORD dwTerminal = 0; dwTerminal < dwTerminals; dwTerminal++) { // // CPTTerminal object from registry // CPTTerminal Terminal; Terminal.m_clsidTerminalClass = pTerminals[dwTerminal]; hr = Terminal.Get( clsidSuperclass ); if( FAILED(hr) ) { continue; } // // try to log the name of the terminal that we are looking at // if (NULL != Terminal.m_bstrName) { // // log the name // LOG((MSP_TRACE, "CPTUtil::FindTerminal - checking terminal %S", Terminal.m_bstrName)); } else { // // no name?? strange, but not much we can do... // LOG((MSP_TRACE, "CPTUtil::FindTerminal - terminal name is unavaliable")); } // // Is matching // if( (dwMediaType & Terminal.m_dwMediaTypes) == 0 ) { LOG((MSP_TRACE, "CPTUtil::FindTerminal - MediaType unmatched")); hr = E_FAIL; continue; } // // map TERMINAL_DIRECTION values to OR'able TMGR_DIRECTION values // DWORD dwRegistryDirection = 0; if (Direction == TD_RENDER) { dwRegistryDirection = TMGR_TD_RENDER; } else if (Direction == TD_CAPTURE) { dwRegistryDirection = TMGR_TD_CAPTURE; } else { // // should not happen, really // LOG((MSP_ERROR, "CPTUtil::FindTerminal - bad direction value %lx", Direction)); hr = E_FAIL; // // this is strange, so debug to see how we got here // TM_ASSERT(FALSE); break; } // // requested direction -- is it one of the directions supported by this terminal? // if ((dwRegistryDirection & Terminal.m_dwDirections) == 0) { LOG((MSP_TRACE, "CPTUtil::FindTerminal - Direction unmatched")); hr = E_FAIL; continue; } if( bExact ) { if( Terminal.m_clsidTerminalClass != clsidTerminal ) { LOG((MSP_TRACE, "CPTUtil::FindTerminal - PublicCLSID unmatched")); hr = E_FAIL; continue; } } if( SUCCEEDED(hr) ) { LOG((MSP_TRACE, "CPTUtil::FindTerminal - find a matching")); *pTerminal = Terminal; break; } } // // Clean-up the safearray // delete[] pTerminals; // // Return // LOG((MSP_TRACE, "CPTUtil::FindTerminal - exit 0x%08x", hr)); return hr; } HRESULT CPTUtil::ListTerminalClasses( IN DWORD dwMediaTypes, OUT CLSID** ppTerminalsClasses, OUT DWORD* pdwCount ) { LOG((MSP_TRACE, "CPTUtil::ListTerminalClasses - enter")); // // reset the output arguments // *ppTerminalsClasses = NULL; *pdwCount = 0; // // Get all terminal classes // HRESULT hr = E_FAIL; CLSID* pSuperclasses = NULL; DWORD dwSuperclasses = 0; hr = ListTerminalSuperclasses( &pSuperclasses, &dwSuperclasses ); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTUtil::ListTerminalClasses - exit " "ListTerminalSuperclasses failed, returns 0x%08x", hr)); return hr; } DWORD dwArraySize = 8; CLSID* pTerminals = new CLSID[ dwArraySize]; DWORD dwIndex = 0; if( pTerminals == NULL ) { // Cleanup delete[] pSuperclasses; LOG((MSP_ERROR, "CPTUtil::ListTerminalClasses - exit " "new operator failed, returns E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Enumerate all superclasses // for( DWORD dwSuperclass = 0; dwSuperclass < dwSuperclasses; dwSuperclass++) { // // List the terminals for this class // CPTSuperclass Superclass; Superclass.m_clsidSuperclass = pSuperclasses[dwSuperclass]; CLSID* pLocalTerminals = NULL; DWORD dwLocalTerminals = 0; hr = Superclass.ListTerminalClasses( 0, &pLocalTerminals, &dwLocalTerminals ); if( FAILED(hr) ) { hr = S_OK; LOG((MSP_TRACE, "CPTUtil::ListTerminalClasses - " "ListTerminalSuperclasses failed")); continue; } // // Increase the array room if it's necessary // if( dwArraySize <= dwIndex + dwLocalTerminals) { CLSID* pOldTerminals = pTerminals; // Create the new buffer dwArraySize *= 2; pTerminals = new CLSID[dwArraySize]; if( pTerminals == NULL ) { // Clean-up delete[] pLocalTerminals; // // Recover the old list of terminals // pTerminals = pOldTerminals; LOG((MSP_TRACE, "CPTUtil::ListTerminalClasses - " "new operator failed")); break; } // Copies the old one into the new one memcpy( pTerminals, pOldTerminals, sizeof(CLSID) * dwArraySize/2); // Delete old terminals delete[] pOldTerminals; } // // Add the terminals into terminals array // for( DWORD dwTerminal = 0; dwTerminal < dwLocalTerminals; dwTerminal++) { // // MediaTypes is right? // CPTTerminal Terminal; Terminal.m_clsidTerminalClass = pLocalTerminals[dwTerminal]; hr = Terminal.Get( pSuperclasses[dwSuperclass] ); if( FAILED(hr) ) { hr = S_OK; LOG((MSP_TRACE, "CPTUtil::ListTerminalClasses - " "GetTerminal failed")); continue; } if( 0 == (dwMediaTypes & Terminal.m_dwMediaTypes) ) { LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - " "wrong mediatype")); continue; } // // Add public clasid to the base safearray // pTerminals[dwIndex] = pLocalTerminals[dwTerminal]; dwIndex++; } // Clean-up delete[] pLocalTerminals; } // Clean-up delete[] pSuperclasses; // // Return values // if( SUCCEEDED(hr) ) { *ppTerminalsClasses = pTerminals; *pdwCount = dwIndex; } LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - exit 0x%08x", hr)); return hr; } /////////////////////////////////////////// // CPTTerminal Implementation // // Constructor/destructor CPTTerminal::CPTTerminal() { LOG((MSP_TRACE, "CPTTerminal::CPTTerminal - enter")); m_bstrName = NULL; m_bstrCompany = NULL; m_bstrVersion = NULL; m_clsidTerminalClass = CLSID_NULL; m_clsidCOM = CLSID_NULL; // // initialize with invalid direction and media type -- there is no other // good default // m_dwDirections = 0; m_dwMediaTypes = 0; LOG((MSP_TRACE, "CPTTerminal::CPTTerminal - exit")); } CPTTerminal::~CPTTerminal() { LOG((MSP_TRACE, "CPTTerminal::~CPTTerminal - enter")); if(m_bstrName) SysFreeString( m_bstrName ); if( m_bstrCompany) SysFreeString( m_bstrCompany ); if( m_bstrVersion) SysFreeString( m_bstrVersion ); LOG((MSP_TRACE, "CPTTerminal::~CPTTerminal - exit")); } // CPTTerminal methods HRESULT CPTTerminal::Add( IN CLSID clsidSuperclass ) { LOG((MSP_TRACE, "CPTTerminal::Add - enter")); // // we should have a valid media type // if ( !IsValidAggregatedMediaType(m_dwMediaTypes) ) { LOG((MSP_ERROR, "CPTTerminal::Add exit -" "media type is not valid %lx. return TAPI_E_INVALIDMEDIATYPE", m_dwMediaTypes)); return TAPI_E_INVALIDMEDIATYPE; } // // we should have a valid direction // if ( ( TMGR_TD_CAPTURE != m_dwDirections ) && ( TMGR_TD_RENDER != m_dwDirections ) && ( TMGR_TD_BOTH != m_dwDirections ) ) { LOG((MSP_ERROR, "CPTTerminal::Add exit - " "direction is not valid %lx. return TAPI_E_INVALIDDIRECTION", TAPI_E_INVALIDDIRECTION)); return TAPI_E_INVALIDDIRECTION; } // // We determine the terminal path into registry // LPOLESTR lpszSuperclass = NULL; LPOLESTR lpszTerminalClass = NULL; HRESULT hr = E_FAIL; hr = StringFromCLSID( clsidSuperclass, &lpszSuperclass ); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTTerminal::Add exit -" "StringFromCLSID for Superclass failed, returns 0x%08x", hr)); return hr; } hr = StringFromCLSID( m_clsidTerminalClass, &lpszTerminalClass ); if( FAILED(hr) ) { CoTaskMemFree( lpszSuperclass ); LOG((MSP_ERROR, "CPTTerminal::Add exit -" "StringFromCLSID for Superclass failed, returns 0x%08x", hr)); return hr; } WCHAR szKey[PTKEY_MAXSIZE]; WCHAR szKeySuperclass[PTKEY_MAXSIZE]; wsprintf( szKey, TEXT("%s\\%s\\%s"), PTKEY_TERMINALS, lpszSuperclass, lpszTerminalClass ); wsprintf( szKeySuperclass, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclass); // Clean-up, we need later the TerminalClass CoTaskMemFree( lpszSuperclass ); CoTaskMemFree( lpszTerminalClass ); // // Try to see if the superclass key exist // HKEY hKeySuperclass = NULL; long lResult; lResult = RegOpenKey( HKEY_LOCAL_MACHINE, szKeySuperclass, &hKeySuperclass); if( ERROR_SUCCESS != lResult ) { // We don't have the superclass LOG((MSP_ERROR, "CPTTerminal::Add exit -" "RegOpenKey for superclass failed, returns E_FAIL")); return E_FAIL; } RegCloseKey( hKeySuperclass ); // // Open or create key // HKEY hKey = NULL; lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL); // // Validates registry operation // if( ERROR_SUCCESS != lResult ) { LOG((MSP_ERROR, "CPTTerminal::Add exit -" "RegCreateKeyEx failed, returns E_UNEXPECTED")); return E_UNEXPECTED; } // // Edit terminal name // if( !IsBadStringPtr(m_bstrName, (UINT)-1) ) { lResult = RegSetValueEx( hKey, PTKEY_NAME, 0, REG_SZ, (BYTE *)m_bstrName, (SysStringLen( m_bstrName) + 1) * sizeof(WCHAR) ); } // // Edit company name // if( !IsBadStringPtr(m_bstrCompany, (UINT)-1) ) { lResult = RegSetValueEx( hKey, PTKEY_COMPANY, 0, REG_SZ, (BYTE *)m_bstrCompany, (SysStringLen( m_bstrCompany) + 1) * sizeof(WCHAR) ); } // // Edit terminal version // if( !IsBadStringPtr(m_bstrVersion, (UINT)-1) ) { lResult = RegSetValueEx( hKey, PTKEY_VERSION, 0, REG_SZ, (BYTE *)m_bstrVersion, (SysStringLen( m_bstrVersion) + 1) * sizeof(WCHAR) ); } // // Edit terminal CLSID create // if( m_clsidCOM != CLSID_NULL ) { LPOLESTR lpszCOM = NULL; hr = StringFromCLSID( m_clsidCOM, &lpszCOM ); if( SUCCEEDED(hr) ) { lResult = RegSetValueEx( hKey, PTKEY_CLSIDCREATE, 0, REG_SZ, (BYTE *)lpszCOM, (wcslen( lpszCOM) + 1) * sizeof(WCHAR) ); // Clean-up CoTaskMemFree( lpszCOM ); } } // // Edit terminal directions // lResult = RegSetValueEx( hKey, PTKEY_DIRECTIONS, 0, REG_DWORD, (BYTE *)&m_dwDirections, sizeof( m_dwDirections ) ); // // Edit terminal mediatypes // lResult = RegSetValueEx( hKey, PTKEY_MEDIATYPES, 0, REG_DWORD, (BYTE *)&m_dwMediaTypes, sizeof( m_dwMediaTypes ) ); // // Clean-up hKey // RegFlushKey( hKey ); RegCloseKey( hKey ); LOG((MSP_TRACE, "CPTTerminal::Add - exit")); return S_OK; } HRESULT CPTTerminal::Delete( IN CLSID clsidSuperclass ) { LOG((MSP_TRACE, "CPTTerminal::Delete - enter")); // // We determine the terminal path into registry // LPOLESTR lpszSuperclass = NULL; LPOLESTR lpszTerminalClass = NULL; HRESULT hr = E_FAIL; hr = StringFromCLSID( clsidSuperclass, &lpszSuperclass ); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTTerminal::Delete exit -" "StringFromCLSID for Superclass failed, returns 0x%08x", hr)); return hr; } hr = StringFromCLSID( m_clsidTerminalClass, &lpszTerminalClass ); if( FAILED(hr) ) { CoTaskMemFree( lpszSuperclass ); LOG((MSP_ERROR, "CPTTerminal::Delete exit -" "StringFromCLSID for Superclass failed, returns 0x%08x", hr)); return hr; } WCHAR szKey[PTKEY_MAXSIZE]; wsprintf( szKey, TEXT("%s\\%s\\%s"), PTKEY_TERMINALS, lpszSuperclass, lpszTerminalClass ); // Clean-up, we need later the TerminalClass CoTaskMemFree( lpszSuperclass ); CoTaskMemFree( lpszTerminalClass ); // // Remove key // hr = CPTUtil::RecursiveDeleteKey( HKEY_LOCAL_MACHINE, szKey ); // // Return value // LOG((MSP_TRACE, "CPTTerminal::Delete - exit (0x%08x)", hr)); return hr; } HRESULT CPTTerminal::Get( IN CLSID clsidSuperclass ) { LOG((MSP_TRACE, "CPTTerminal::Get - enter")); // // Reset members // if(m_bstrName) { SysFreeString( m_bstrName ); m_bstrName = NULL; } if( m_bstrCompany) { SysFreeString( m_bstrCompany ); m_bstrCompany = NULL; } if( m_bstrVersion) { SysFreeString( m_bstrVersion ); m_bstrVersion = NULL; } m_clsidCOM = CLSID_NULL; // // initialize with invalid direction and media type // m_dwDirections = 0; m_dwMediaTypes = 0; // // We determine the terminal path into registry // LPOLESTR lpszSuperclass = NULL; LPOLESTR lpszTerminalClass = NULL; HRESULT hr = E_FAIL; hr = StringFromCLSID( clsidSuperclass, &lpszSuperclass ); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTTerminal::Get exit -" "StringFromCLSID for Superclass failed, returns 0x%08x", hr)); return hr; } hr = StringFromCLSID( m_clsidTerminalClass, &lpszTerminalClass ); if( FAILED(hr) ) { CoTaskMemFree( lpszSuperclass ); LOG((MSP_ERROR, "CPTTerminal::Get exit -" "StringFromCLSID for Superclass failed, returns 0x%08x", hr)); return hr; } WCHAR szKey[PTKEY_MAXSIZE]; wsprintf( szKey, TEXT("%s\\%s\\%s"), PTKEY_TERMINALS, lpszSuperclass, lpszTerminalClass ); // Clean-up, we need later the TerminalClass CoTaskMemFree( lpszSuperclass ); CoTaskMemFree( lpszTerminalClass ); // // Open terminal key // HKEY hKey = NULL; LONG lResult; lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hKey); // // Validates registry operation // if( ERROR_SUCCESS != lResult ) { LOG((MSP_ERROR, "CPTTerminal::Get exit -" "RegOpenKeyEx failed, returns E_UNEXPECTED")); return E_UNEXPECTED; } // // Query for name // TCHAR szBuffer[PTKEY_MAXSIZE]; DWORD dwSize = PTKEY_MAXSIZE * sizeof( TCHAR ); DWORD dwType = REG_SZ; lResult = RegQueryValueEx( hKey, PTKEY_NAME, 0, &dwType, (LPBYTE)szBuffer, &dwSize); if( ERROR_SUCCESS == lResult ) { m_bstrName = SysAllocString( szBuffer ); } // // Query for company // dwSize = PTKEY_MAXSIZE * sizeof( TCHAR ); dwType = REG_SZ; lResult = RegQueryValueEx( hKey, PTKEY_COMPANY, 0, &dwType, (LPBYTE)szBuffer, &dwSize); if( ERROR_SUCCESS == lResult ) { m_bstrCompany = SysAllocString( szBuffer ); } // // Query for version // dwSize = PTKEY_MAXSIZE * sizeof( TCHAR ); dwType = REG_SZ; lResult = RegQueryValueEx( hKey, PTKEY_VERSION, 0, &dwType, (LPBYTE)szBuffer, &dwSize); if( ERROR_SUCCESS == lResult ) { m_bstrVersion = SysAllocString( szBuffer ); } // // Query for CLSID create // dwSize = PTKEY_MAXSIZE * sizeof( TCHAR ); dwType = REG_SZ; lResult = RegQueryValueEx( hKey, PTKEY_CLSIDCREATE, 0, &dwType, (LPBYTE)szBuffer, &dwSize); if( ERROR_SUCCESS == lResult ) { HRESULT hr = CLSIDFromString( szBuffer, &m_clsidCOM); if( FAILED(hr) ) { m_clsidCOM = CLSID_NULL; } } // // Query for directions // dwType = REG_DWORD; DWORD dwValue = 0; dwSize = sizeof( dwValue ); lResult = RegQueryValueEx( hKey, PTKEY_DIRECTIONS, 0, &dwType, (LPBYTE)&dwValue, &dwSize); if( ERROR_SUCCESS == lResult ) { m_dwDirections = dwValue; } // // Query for media types // dwSize = sizeof( dwValue ); dwType = REG_DWORD; dwValue = 0; lResult = RegQueryValueEx( hKey, PTKEY_MEDIATYPES, 0, &dwType, (LPBYTE)&dwValue, &dwSize); if( ERROR_SUCCESS == lResult ) { m_dwMediaTypes = dwValue; } // // Clean-up hKey // RegCloseKey( hKey ); LOG((MSP_TRACE, "CPTTerminal::Get - exit")); return S_OK; } /////////////////////////////////////////// // CPTSuperclass Implementation // // Constructor/Destructor CPTSuperclass::CPTSuperclass() { LOG((MSP_TRACE, "CPTSuperclass::CPTSuperclass - enter")); m_bstrName = NULL; m_clsidSuperclass = CLSID_NULL; LOG((MSP_TRACE, "CPTSuperclass::CPTSuperclass - exit")); } CPTSuperclass::~CPTSuperclass() { LOG((MSP_TRACE, "CPTSuperclass::~CPTSuperclass - enter")); if(m_bstrName) SysFreeString( m_bstrName ); LOG((MSP_TRACE, "CPTSuperclass::~CPTSuperclass - exit")); } // CPTSuperclass methods HRESULT CPTSuperclass::Add() { LOG((MSP_TRACE, "CPTSuperclass::Add - enter")); // // Get the superclass CLSID as string // LPOLESTR lpszSuperclassCLSID = NULL; HRESULT hr = E_FAIL; hr = StringFromCLSID( m_clsidSuperclass, &lpszSuperclassCLSID); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTSuperclass::Add exit -" "StringFromCLSID failed, returns E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Create key path for superclass // WCHAR szKey[PTKEY_MAXSIZE]; wsprintf( szKey, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclassCLSID); // Clean-up CoTaskMemFree( lpszSuperclassCLSID ); // // Open the registry key // HKEY hKey = NULL; long lResult; lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL); // // Validates the registry operation // if( ERROR_SUCCESS != lResult ) { LOG((MSP_ERROR, "CPTSuperclass::Add exit -" "RegCreateKeyEx failed, returns E_UNEXPECTED")); return E_UNEXPECTED; } // // Edit the name of the terminal class // if( !IsBadStringPtr(m_bstrName, (UINT)-1) ) { lResult = RegSetValueEx( hKey, PTKEY_NAME, 0, REG_SZ, (BYTE *)m_bstrName, (SysStringLen( m_bstrName) + 1) * sizeof(WCHAR) ); } // // Clean-up hKey // RegFlushKey( hKey ); RegCloseKey( hKey ); LOG((MSP_TRACE, "CPTSuperclass::Add - exit")); return S_OK; } HRESULT CPTSuperclass::Delete() { LOG((MSP_TRACE, "CPTSuperclass::Delete - enter")); // // Get the superclass CLSID as string // LPOLESTR lpszSuperclassCLSID = NULL; HRESULT hr = E_FAIL; hr = StringFromCLSID( m_clsidSuperclass, &lpszSuperclassCLSID); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTSuperclass::Delete exit -" "StringFromCLSID failed, returns E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Create key path for superclass // WCHAR szKey[PTKEY_MAXSIZE]; wsprintf( szKey, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclassCLSID); // Clean-up CoTaskMemFree( lpszSuperclassCLSID ); // // Remove key // hr = CPTUtil::RecursiveDeleteKey( HKEY_LOCAL_MACHINE, szKey ); // // Return value // LOG((MSP_TRACE, "CPTSuperclass::Delete - exit (0x%08x)", hr)); return hr; } HRESULT CPTSuperclass::Get() { LOG((MSP_TRACE, "CPTSuperclass::Get - enter")); // // Get the superclass CLSID as string // LPOLESTR lpszSuperclassCLSID = NULL; HRESULT hr = E_FAIL; hr = StringFromCLSID( m_clsidSuperclass, &lpszSuperclassCLSID); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTSuperclass::Get exit -" "StringFromCLSID failed, returns E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Create key path for superclass // WCHAR szKey[PTKEY_MAXSIZE]; wsprintf( szKey, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclassCLSID); // Clean-up CoTaskMemFree( lpszSuperclassCLSID ); // // Reset members // if(m_bstrName) { SysFreeString( m_bstrName ); m_bstrName = NULL; } // // Open terminal key // HKEY hKey = NULL; LONG lResult; lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hKey); // // Validates registry operation // if( ERROR_SUCCESS != lResult ) { LOG((MSP_ERROR, "CPTSuperclass::Get exit -" "RegOpenKeyEx failed, returns E_UNEXPECTED")); return E_UNEXPECTED; } // // Query for name // TCHAR szBuffer[PTKEY_MAXSIZE]; DWORD dwSize = PTKEY_MAXSIZE * sizeof( TCHAR ); DWORD dwType = REG_SZ; lResult = RegQueryValueEx( hKey, PTKEY_NAME, 0, &dwType, (LPBYTE)szBuffer, &dwSize); if( ERROR_SUCCESS == lResult ) { m_bstrName = SysAllocString( szBuffer ); } else { m_bstrName = SysAllocString(_T("")); } // // Clean-up hKey // RegCloseKey( hKey ); LOG((MSP_TRACE, "CPTSuperclass::Get - exit")); return S_OK; } HRESULT CPTSuperclass::ListTerminalClasses( IN DWORD dwMediaTypes, OUT CLSID** ppTerminals, OUT DWORD* pdwCount ) { LOG((MSP_TRACE, "CPTSuperclass::ListTerminalSuperclasses - enter")); // // Validates argument // if( TM_IsBadWritePtr( ppTerminals, sizeof(CLSID*)) ) { LOG((MSP_ERROR, "CPTSuperclass::ListTerminalSuperclasses exit -" "pTerminals invalid, returns E_INVALIDARG")); return E_INVALIDARG; } // // Reset the output arguments // *ppTerminals = NULL; *pdwCount = 0; // // Get the superclass CLSID as string // LPOLESTR lpszSuperclassCLSID = NULL; HRESULT hr = E_FAIL; hr = StringFromCLSID( m_clsidSuperclass, &lpszSuperclassCLSID); if( FAILED(hr) ) { LOG((MSP_ERROR, "CPTSuperclass::Get exit -" "StringFromCLSID failed, returns E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Create key path for superclass // WCHAR szKey[PTKEY_MAXSIZE]; wsprintf( szKey, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclassCLSID); // Clean-up CoTaskMemFree( lpszSuperclassCLSID ); // // Open the terminal class key // HKEY hKey; LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey); // // Validates registry operation // if( ERROR_SUCCESS != lResult ) { LOG((MSP_ERROR, "CPTSuperclass::ListTerminalSuperclasses exit - " "RegOpenKeyEx failed, returns E_INVALIDARG")); return E_INVALIDARG; } DWORD dwArraySize = 8; CLSID* pTerminals = new CLSID[dwArraySize]; if( pTerminals == NULL ) { // Clean-up hKey RegCloseKey( hKey ); LOG((MSP_ERROR, "CPTSuperclass::ListTerminalSuperclasses exit - " "new operator failed, returns E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // // Enumerate the descendents // FILETIME time; TCHAR szBuffer[PTKEY_MAXSIZE]; // Buffer DWORD dwSize = PTKEY_MAXSIZE; // Buffer size DWORD dwIndex = 0; // Index into array DWORD dwChildIndex = 0; // Child index into registry while( RegEnumKeyEx( hKey, dwChildIndex, szBuffer, &dwSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) { // // Prepare for the nex child // dwChildIndex++; dwSize = PTKEY_MAXSIZE; // // I have to qury MediaType value for this entry // CPTTerminal Terminal; HRESULT hr = CLSIDFromString( szBuffer, &Terminal.m_clsidTerminalClass); if( FAILED(hr) ) { hr = S_OK; continue; } if( dwMediaTypes ) { HRESULT hr = E_FAIL; hr = Terminal.Get( m_clsidSuperclass ); if( FAILED(hr) ) { hr = S_OK; continue; } if( !(Terminal.m_dwMediaTypes & dwMediaTypes) ) { continue; } } // // Increase the array room if it's necessary // if( dwArraySize <= dwIndex) { // Old buffer CLSID* pOldTerminals = pTerminals; // New buffer dwArraySize *= 2; pTerminals = new CLSID[dwArraySize]; if( pTerminals == NULL ) { delete[] pOldTerminals; LOG((MSP_ERROR, "CPTSuperclass::ListTerminalSuperclasses exit - " "new operator failed, returns E_OUTOFMEMORY")); return E_OUTOFMEMORY; } // Copies the old buffer into the new one memcpy( pTerminals, pOldTerminals, sizeof(CLSID)*dwArraySize/2); // Delete the old buffer delete[] pOldTerminals; } // // Add the terminal class // pTerminals[dwIndex] = Terminal.m_clsidTerminalClass; dwIndex++; } // // Clean-up hKey // RegCloseKey( hKey ); // // Return values // if( SUCCEEDED(hr) ) { *ppTerminals = pTerminals; *pdwCount = dwIndex; } LOG((MSP_TRACE, "CPTSuperclass::ListTerminalSuperclasses - exit Len=%ld, 0x%08x", dwIndex, hr)); return hr; } // eof