You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
477 lines
11 KiB
477 lines
11 KiB
#include <objbase.h>
|
|
#include <olectl.h>
|
|
#include <initguid.h>
|
|
#include "guids.h"
|
|
#include "basesnap.h"
|
|
#include "comp.h"
|
|
#include "compdata.h"
|
|
#include "about.h"
|
|
#include "uddi.h"
|
|
#include <assert.h>
|
|
|
|
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<IClassFactory *>(this);
|
|
else
|
|
if( IsEqualIID(riid, IID_IClassFactory ) )
|
|
*ppv = static_cast<IClassFactory *>(this);
|
|
|
|
if( *ppv )
|
|
{
|
|
reinterpret_cast<IUnknown *>(*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 ;
|
|
}
|