#include #include #include #include "guids.h" #include "basesnap.h" #include "comp.h" #include "compdata.h" #include "about.h" #include "uddi.h" #include LONG UnRegisterServer( const CLSID& clsid ); // // Globals Variables // HINSTANCE g_hinst; BOOL WINAPI DllMain( HINSTANCE hinst, DWORD fdwReason, void* lpvReserved ) { if( DLL_PROCESS_ATTACH == fdwReason ) { g_hinst = hinst; } return TRUE; } STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvObj) { if( ( rclsid != CLSID_CUDDIServices ) && ( rclsid != CLSID_CSnapinAbout ) ) return CLASS_E_CLASSNOTAVAILABLE; if( !ppvObj ) return E_FAIL; *ppvObj = NULL; // // We can only hand out IUnknown and IClassFactory pointers. Fail // if they ask for anything else. // if( !IsEqualIID(riid, IID_IUnknown) && !IsEqualIID( riid, IID_IClassFactory ) ) return E_NOINTERFACE; CClassFactory *pFactory = NULL; // // make the factory passing in the creation function for the type of object they want // if( CLSID_CUDDIServices == rclsid ) pFactory = new CClassFactory( CClassFactory::COMPONENT ); else if( CLSID_CSnapinAbout == rclsid ) pFactory = new CClassFactory( CClassFactory::ABOUT ); if( NULL == pFactory ) return E_OUTOFMEMORY; HRESULT hr = pFactory->QueryInterface( riid, ppvObj ); return hr; } STDAPI DllCanUnloadNow(void) { if( ( 0 == g_uObjects ) && ( 0 == g_uSrvLock ) ) return S_OK; else return S_FALSE; } CClassFactory::CClassFactory(FACTORY_TYPE factoryType) : m_cref(0) , m_factoryType(factoryType) { OBJECT_CREATED } CClassFactory::~CClassFactory() { OBJECT_DESTROYED } STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, LPVOID *ppv) { if( !ppv ) return E_FAIL; *ppv = NULL; if( IsEqualIID( riid, IID_IUnknown ) ) *ppv = static_cast(this); else if( IsEqualIID(riid, IID_IClassFactory ) ) *ppv = static_cast(this); if( *ppv ) { reinterpret_cast(*ppv)->AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CClassFactory::AddRef() { return InterlockedIncrement( (LONG*)&m_cref ); } STDMETHODIMP_(ULONG) CClassFactory::Release() { if( 0 == InterlockedDecrement( (LONG *)&m_cref ) ) { delete this; return 0; } return m_cref; } STDMETHODIMP CClassFactory::CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, LPVOID * ppvObj ) { HRESULT hr; void* pObj; if( !ppvObj ) return E_FAIL; *ppvObj = NULL; // // Our object does does not support aggregation, so we need to // fail if they ask us to do aggregation. // if( pUnkOuter ) return CLASS_E_NOAGGREGATION; if( COMPONENT == m_factoryType ) { pObj = new CComponentData(); } else { pObj = new CSnapinAbout(); } if( !pObj ) return E_OUTOFMEMORY; // // QueryInterface will do the AddRef() for us, so we do not // do it in this function // hr = ( (LPUNKNOWN) pObj )->QueryInterface( riid, ppvObj ); if( FAILED(hr) ) delete pObj; return hr; } STDMETHODIMP CClassFactory::LockServer( BOOL fLock ) { if( fLock ) InterlockedIncrement( (LONG *) &g_uSrvLock ); else InterlockedDecrement( (LONG *) &g_uSrvLock); return S_OK; } // // Register the component in the registry. // HRESULT RegisterServer( HMODULE hModule, // DLL module handle const CLSID& clsid, // Class ID const _TCHAR* szFriendlyName ) // IDs { LPOLESTR wszCLSID = NULL; try { // // Get server location. // _TCHAR szModule[ MAX_PATH + 1]; DWORD dwResult = ::GetModuleFileName( hModule, szModule, sizeof(szModule)/sizeof(_TCHAR) ); szModule[ MAX_PATH ] = NULL; assert( 0 != dwResult ); // // Get CLSID // HRESULT hr = StringFromCLSID( clsid, &wszCLSID ); if( FAILED(hr) || ( NULL == wszCLSID ) ) { return hr; } // // Build the key CLSID\\{...} // tstring strKey( _T("CLSID\\") ); strKey += wszCLSID; CUDDIRegistryKey::Create( HKEY_CLASSES_ROOT, strKey ); CUDDIRegistryKey key( HKEY_CLASSES_ROOT, strKey ); key.SetValue( _T(""), szFriendlyName ); key.Close(); strKey += _T( "\\InprocServer32" ); CUDDIRegistryKey::Create( HKEY_CLASSES_ROOT, strKey ); CUDDIRegistryKey keyInprocServer32( HKEY_CLASSES_ROOT, strKey ); keyInprocServer32.SetValue( _T(""), szModule ); keyInprocServer32.SetValue( _T("ThreadingModel"), _T("Apartment") ); keyInprocServer32.Close(); // // Free memory. // CoTaskMemFree( wszCLSID ); return S_OK; } catch( ... ) { CoTaskMemFree( wszCLSID ); return E_OUTOFMEMORY; } } ////////////////////////////////////////////////////////// // // Exported functions // // // Server registration // STDAPI DllRegisterServer() { try { HRESULT hr = S_OK; _TCHAR szName[ 256 ]; _TCHAR szSnapInName[ 256 ]; _TCHAR szAboutName[ 256 ]; _TCHAR szProvider[ 256 ]; // // TODO: Fix the version thing here // //_TCHAR szVersion[ 100 ]; LoadString( g_hinst, IDS_UDDIMMC_NAME, szName, ARRAYLEN( szName ) ); LoadString( g_hinst, IDS_UDDIMMC_SNAPINNAME, szSnapInName, ARRAYLEN( szSnapInName ) ); LoadString( g_hinst, IDS_UDDIMMC_ABOUTNAME, szAboutName, ARRAYLEN( szAboutName ) ); LoadString( g_hinst, IDS_UDDIMMC_PROVIDER, szProvider, ARRAYLEN( szProvider ) ); // // TODO: Fix the version thing here // //LoadString( g_hinst, IDS_UDDIMMC_VERSION, szVersion, ARRAYLEN( szVersion ) ); // // Register our Components // hr = RegisterServer( g_hinst, CLSID_CUDDIServices, szName ); if( FAILED(hr) ) return hr; hr = RegisterServer( g_hinst, CLSID_CSnapinAbout, szAboutName ); if( FAILED(hr) ) return hr; // // Create the primary snapin nodes // LPOLESTR wszCLSID = NULL; hr = StringFromCLSID( CLSID_CUDDIServices, &wszCLSID ); if( FAILED(hr) ) { return hr; } LPOLESTR wszCLSIDAbout = NULL; hr = StringFromCLSID( CLSID_CSnapinAbout, &wszCLSIDAbout ); if( FAILED(hr) ) { CoTaskMemFree( wszCLSID ); return hr; } TCHAR szPath[ MAX_PATH + 1 ]; GetModuleFileName( g_hinst, szPath, MAX_PATH ); tstring strNameStringIndirect( _T("@") ); strNameStringIndirect += szPath; strNameStringIndirect += _T(",-"); _TCHAR szNameResourceIndex[ 10 ]; strNameStringIndirect += _itot( IDS_UDDIMMC_NAME, szNameResourceIndex, 10 ); tstring strMMCKey( g_szMMCBasePath ); strMMCKey += _T("\\SnapIns\\"); strMMCKey += wszCLSID; CUDDIRegistryKey::Create( HKEY_LOCAL_MACHINE, strMMCKey ); CUDDIRegistryKey keyMMC( strMMCKey ); keyMMC.SetValue( _T("About"), wszCLSIDAbout ); keyMMC.SetValue( _T("NameString"), szName ); keyMMC.SetValue( _T("NameStringIndirect"), strNameStringIndirect.c_str() ); keyMMC.SetValue( _T("Provider"), szProvider ); // // TODO: Fix the version thing here // keyMMC.SetValue( _T("Version" ), _T("1.0") ); keyMMC.Close(); tstring strStandAlone( strMMCKey ); strStandAlone += _T("\\StandAlone"); CUDDIRegistryKey::Create( HKEY_LOCAL_MACHINE, strStandAlone ); tstring strNodeTypes( strMMCKey ); strNodeTypes += _T("\\NodeTypes"); CUDDIRegistryKey::Create( HKEY_LOCAL_MACHINE, strNodeTypes ); // // No NodeTypes to register // We do not allow extensions of our nodes // // // Register as a dynamic extension to computer management // tstring strExtKey( g_szMMCBasePath ); strExtKey += _T("\\NodeTypes\\"); strExtKey += g_szServerAppsGuid; strExtKey += _T("\\Dynamic Extensions"); CUDDIRegistryKey dynamicExtensions( strExtKey ); dynamicExtensions.SetValue( wszCLSID, szSnapInName ); dynamicExtensions.Close(); // // Register as a namespace extension to computer management // tstring strNameSpaceExtensionKey( g_szMMCBasePath ); strNameSpaceExtensionKey += _T("\\NodeTypes\\"); strNameSpaceExtensionKey += g_szServerAppsGuid; strNameSpaceExtensionKey += _T("\\Extensions\\NameSpace"); CUDDIRegistryKey hkeyNameSpace( strNameSpaceExtensionKey ); hkeyNameSpace.SetValue( wszCLSID, szSnapInName ); hkeyNameSpace.Close(); CoTaskMemFree( wszCLSID ); CoTaskMemFree( wszCLSIDAbout ); return hr; } catch( ... ) { return E_FAIL; } } STDAPI DllUnregisterServer() { LPOLESTR wszCLSID = NULL; try { HRESULT hr = S_OK; UnRegisterServer( CLSID_CUDDIServices ); if( FAILED(hr) ) return hr; UnRegisterServer( CLSID_CSnapinAbout ); if( FAILED(hr) ) return hr; // // Remove \\SnapIns\\ entry // hr = StringFromCLSID( CLSID_CUDDIServices, &wszCLSID ); if( FAILED( hr) || ( NULL == wszCLSID ) ) { return hr; } tstring strMMCKey( g_szMMCBasePath ); strMMCKey += _T("\\SnapIns\\"); strMMCKey += wszCLSID; CUDDIRegistryKey::DeleteKey( HKEY_LOCAL_MACHINE, strMMCKey ); // // Remove \\Dynamic Extensions key // tstring strExtKey( g_szMMCBasePath ); strExtKey += _T("\\NodeTypes\\"); strExtKey += g_szServerAppsGuid; strExtKey += _T("\\Dynamic Extensions"); CUDDIRegistryKey dynamicExtensions( strExtKey ); dynamicExtensions.DeleteValue( wszCLSID ); dynamicExtensions.Close(); // // Delete \\NodeTypes\\...\\Extensions\\Namespace Value // tstring strNameSpaceExtensionKey( g_szMMCBasePath ); strNameSpaceExtensionKey += _T("\\NodeTypes\\"); strNameSpaceExtensionKey += g_szServerAppsGuid; strNameSpaceExtensionKey += _T("\\Extensions\\NameSpace"); CUDDIRegistryKey hkeyNameSpace( strNameSpaceExtensionKey ); hkeyNameSpace.DeleteValue( wszCLSID ); hkeyNameSpace.Close(); CoTaskMemFree( wszCLSID ); return S_OK; } catch(...) { CoTaskMemFree( wszCLSID ); return E_FAIL; } } // // Remove the component from the registry. // LONG UnRegisterServer( const CLSID& clsid ) { LPOLESTR wszCLSID = NULL; try { // // Get CLSID // HRESULT hr = StringFromCLSID( clsid, &wszCLSID ); if( FAILED(hr) || ( NULL == wszCLSID ) ) { return hr; } // // Build the key CLSID\\{...} // wstring wstrKey( L"CLSID\\" ); wstrKey += wszCLSID; // // Delete the CLSID Key - CLSID\{...} // CUDDIRegistryKey::DeleteKey( HKEY_CLASSES_ROOT, wstrKey ); } catch( ... ) { // // Free memory. // CoTaskMemFree( wszCLSID ); return E_OUTOFMEMORY; } // // Free memory. // CoTaskMemFree( wszCLSID ); return S_OK ; }