//------------------------------------------------------------------------------ // File: MultiVMR9.cpp // // Desc: DirectShow sample code - Implementation of DLL Exports. // // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ #include "stdafx.h" #include "resource.h" #include "MultiVMR9.h" #include #include #include "Wizard.h" #include "RenderEngine.h" #include "UILayer.h" #include "MixerControl.h" HINSTANCE g_hInst = NULL; class CCFMultiVMR9Wizard; class CCFMultiVMR9RenderEngine; class CCFMultiVMR9UILayer; class CCFMultiVMR9MixerControl; static CCFMultiVMR9Wizard g_WizardFactory; static CCFMultiVMR9RenderEngine g_RenderEngineFactory; static CCFMultiVMR9UILayer g_UILayerFactory; static CCFMultiVMR9MixerControl g_MixerControlFactory; // the com module's lock count + object count long g_CountWizard = 0; long g_CountRenderEngine = 0; long g_CountUILayer = 0; long g_CountMixerControl = 0; // forward declarations void MultiVMRRegisterClass( const CLSID& clsid, TCHAR *achClassName, BOOL bRegister); LONG recursiveDeleteKey(HKEY hKeyParent, TCHAR* achKeyChild); // DLL Entry Point BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { if (DLL_PROCESS_ATTACH == dwReason ) { g_hInst = hInstance; } return(TRUE); } // // stub entry points // STDAPI DllRegisterServer( void ) { // now go register components; they are in HKEY_CLASSES_ROOT\CLSID\{uuid} MultiVMRRegisterClass( CLSID_MultiVMR9Wizard, TEXT("MultiVMR9 Wizard"), TRUE); MultiVMRRegisterClass( CLSID_MultiVMR9RenderEngine, TEXT("MultiVMR9 Render Engine"), TRUE); MultiVMRRegisterClass( CLSID_MultiVMR9UILayer, TEXT("MultiVMR9 UI Layer"), TRUE); MultiVMRRegisterClass( CLSID_MultiVMR9MixerControl, TEXT("MultiVMR9 Mixer Control"), TRUE); return S_OK; } STDAPI DllUnregisterServer( void ) { // now go register components; they are in HKEY_CLASSES_ROOT\CLSID\{uuid} MultiVMRRegisterClass( CLSID_MultiVMR9Wizard, TEXT("MultiVMR9 Wizard"), FALSE); MultiVMRRegisterClass( CLSID_MultiVMR9RenderEngine, TEXT("MultiVMR9 Render Engine"), FALSE); MultiVMRRegisterClass( CLSID_MultiVMR9UILayer, TEXT("MultiVMR9 UI Layer"), FALSE); MultiVMRRegisterClass( CLSID_MultiVMR9MixerControl, TEXT("MultiVMR9 Mixer Control"), FALSE); return S_OK; } STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv) { if (CLSID_MultiVMR9Wizard == rclsid ) { return g_WizardFactory.QueryInterface(riid, ppv); } else if( CLSID_MultiVMR9RenderEngine == rclsid ) { return g_RenderEngineFactory.QueryInterface(riid, ppv); } else if( CLSID_MultiVMR9UILayer == rclsid ) { return g_UILayerFactory.QueryInterface(riid, ppv); } else if( CLSID_MultiVMR9MixerControl == rclsid ) { return g_MixerControlFactory.QueryInterface(riid, ppv); } else { *ppv = NULL; return CLASS_E_CLASSNOTAVAILABLE; } } STDAPI DllCanUnloadNow(void) { HRESULT hr = S_FALSE; if( 0 == g_CountWizard && 0 == g_CountRenderEngine && 0 == g_CountUILayer && 0 == g_CountMixerControl ) { hr = S_OK; } return hr; } // // Add entry to the registry about CLSID object // void MultiVMRRegisterClass( const CLSID& clsid, TCHAR *achClassName, BOOL bRegister) { HRESULT hr = S_OK; TCHAR achModule[MAX_PATH]; WCHAR wcModule[MAX_PATH]; WCHAR wcKey[MAX_PATH]; TCHAR achKey[MAX_PATH]; TCHAR achThreadingModel[] = TEXT("Both"); long err = 0; LPOLESTR wcCLSID = NULL; HKEY hKey = NULL; HKEY hSubKey = NULL; GetModuleFileName( g_hInst, achModule, sizeof(achModule) ); #ifdef UNICODE wcscpy( wcModule, achModule ); #else MultiByteToWideChar(CP_ACP, 0, achModule, -1, wcModule, MAX_PATH); #endif hr = StringFromCLSID(clsid, &wcCLSID); wcscpy( wcKey, L"CLSID\\"); wcscat( wcKey, wcCLSID); #ifdef UNICODE _tcscpy( achKey, wcKey); #else WideCharToMultiByte(CP_ACP, 0, wcKey, -1, achKey, MAX_PATH, 0, 0); #endif // first, delete wcKey if it exists err = recursiveDeleteKey( HKEY_CLASSES_ROOT, achKey); if( bRegister ) { // create new key err = RegCreateKeyEx( HKEY_CLASSES_ROOT, achKey, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL); if (ERROR_SUCCESS == err) { err = RegSetValueEx( hKey, NULL, 0, REG_SZ,(BYTE *)achClassName, sizeof(TCHAR) * ( _tcslen(achClassName)+1)); err = RegCreateKeyEx( hKey, TEXT("InprocServer32"), NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubKey, NULL); if( ERROR_SUCCESS == err) { err = RegSetValueEx( hSubKey, NULL, 0, REG_SZ,(BYTE *)achModule, sizeof(TCHAR) * ( _tcslen(achModule)+1)); err = RegSetValueEx( hSubKey, TEXT("ThreadingModel"), 0, REG_SZ,(BYTE *)achThreadingModel, sizeof(TCHAR) * ( _tcslen(achThreadingModel)+1)); RegCloseKey( hSubKey ); } RegCloseKey( hKey ); } } CoTaskMemFree(wcCLSID); } // // Delete a key and all of its descendents. // LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete TCHAR* achKeyChild) // Key to delete { // Open the child. HKEY hKeyChild; LONG lRes = RegOpenKeyEx(hKeyParent, achKeyChild, 0, KEY_ALL_ACCESS, &hKeyChild); if (lRes != ERROR_SUCCESS) { return lRes; } // Enumerate all of the decendents of this child. FILETIME time; TCHAR achBuffer[256]; DWORD dwSize = 256; while (RegEnumKeyEx(hKeyChild, 0, achBuffer, &dwSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) { // Delete the decendents of this child. lRes = recursiveDeleteKey(hKeyChild, achBuffer); if (lRes != ERROR_SUCCESS) { // Cleanup before exiting. RegCloseKey(hKeyChild); return lRes; } dwSize = 256; } // Close the child. RegCloseKey(hKeyChild); // Delete this child. return RegDeleteKey(hKeyParent, achKeyChild); } #ifdef _DEBUG void DbgMsg( char* szMessage, ... ) { char szFullMessage[MAX_PATH]; char szFormatMessage[MAX_PATH]; // format message va_list ap; va_start(ap, szMessage); _vsnprintf( szFormatMessage, MAX_PATH, szMessage, ap); va_end(ap); strncat( szFormatMessage, "\n", MAX_PATH); strcpy( szFullMessage, "~*~*~*~*~*~ "); strcat( szFullMessage, szFormatMessage ); OutputDebugStringA( szFullMessage ); } #else void DbgMsg( char* szMessage, ... ){;} #endif