|
|
#include <objbase.h>
#include <mbctype.h>
#include "infgen.h"
HINSTANCE g_hMyInstance; long g_cKeepAlive;
LONG IncrementKeepAlive( void ) { return InterlockedIncrement( &g_cKeepAlive ); }
LONG DecrementKeepAlive( void ) { return InterlockedDecrement( &g_cKeepAlive ); }
class CInfGeneratorFactory : public IClassFactory { public: // IUnknown
ULONG __stdcall AddRef( void ); ULONG __stdcall Release( void ); HRESULT __stdcall QueryInterface( REFIID riid, void **ppv );
// IClassFactory
HRESULT __stdcall CreateInstance( IUnknown *pUnkOuter, REFIID riid, void **ppv ); HRESULT __stdcall LockServer( BOOL bLock );
CInfGeneratorFactory(): m_cRef(1) {} ~CInfGeneratorFactory() {}
private: long m_cRef; long m_cLocks; };
ULONG CInfGeneratorFactory::AddRef( void ) { IncrementKeepAlive(); return InterlockedIncrement(&m_cRef); }
ULONG CInfGeneratorFactory::Release( void ) { if ( 0L == InterlockedDecrement(&m_cRef) ) { delete this; DecrementKeepAlive(); return 0L; }
DecrementKeepAlive(); return m_cRef; }
HRESULT CInfGeneratorFactory::QueryInterface( REFIID riid, void **ppv ) { *ppv = NULL;
if ( IID_IUnknown == riid || IID_IClassFactory == riid ) { *ppv = (IClassFactory *)this; } else { return E_NOINTERFACE; }
AddRef(); return S_OK; }
HRESULT CInfGeneratorFactory::CreateInstance( IUnknown *pUnkOuter, REFIID riid, void **ppv ) { *ppv = NULL;
if ( NULL != pUnkOuter ) { return CLASS_E_NOAGGREGATION; }
CUpdateInf *pUpdateInf = new CUpdateInf; if ( NULL == pUpdateInf ) return E_OUTOFMEMORY; if ( !pUpdateInf->Init() ) { delete pUpdateInf; return E_FAIL; }
HRESULT hr = pUpdateInf->QueryInterface( riid, ppv ); if ( S_OK != hr ) delete pUpdateInf; else pUpdateInf->Release();
return hr; }
HRESULT CInfGeneratorFactory::LockServer( BOOL bLock ) { if ( bLock ) { IncrementKeepAlive(); InterlockedIncrement( &m_cLocks ); } else if ( 0 != m_cLocks ) { InterlockedDecrement( &m_cLocks ); DecrementKeepAlive(); } else return E_FAIL;
return S_OK; }
inline long AssignKeyValue( HKEY hParentKey, LPTSTR szKeyName, LPTSTR szValue, LPTSTR szData, HKEY *phNewKey ) { LONG lResult; DWORD dwDisposition; HKEY hKey;
if ( NULL != szKeyName ) { lResult = RegCreateKeyEx( hParentKey, szKeyName, (0), (0), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition ); if ( ERROR_SUCCESS != lResult ) goto failure; } else { hKey = hParentKey; } lResult = RegSetValueEx( hKey, szValue, (0), REG_SZ, (PBYTE)szData, sizeof( TCHAR ) * _tcslen( szData ) ); if ( ERROR_SUCCESS != lResult ) goto failure;
if ( NULL != phNewKey ) { *phNewKey = hKey; } else { RegCloseKey( hKey ); hKey = NULL; }
return ERROR_SUCCESS;
failure: if ( NULL != hKey ) RegCloseKey( hKey ); return lResult; }
HRESULT DllRegisterServer( void ) { LONG lResult; DWORD dwDisposition; TCHAR szMe[_MAX_PATH]; HKEY hKeyParent = NULL, hKey = NULL; ITypeLib *pTypeLib; HRESULT hr;
// Open the CLSID key
lResult = RegCreateKeyEx( HKEY_CLASSES_ROOT, _T("CLSID"), (0), (0), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyParent, &dwDisposition ); if ( ERROR_SUCCESS != lResult ) goto failure;
// Store our class ID
lResult = AssignKeyValue( hKeyParent, _T("{9cd916b9-2004-42b1-b639-572fbf647204}"), NULL, _T("Update INF Generator"), &hKey ); // Done with CLSID key
RegCloseKey( hKeyParent ); hKeyParent = NULL;
if ( ERROR_SUCCESS != lResult ) goto failure;
// Find out my full path
if ( !GetModuleFileName( g_hMyInstance, szMe, _MAX_PATH ) ) goto failure;
// Store our location
hKeyParent = hKey; lResult = AssignKeyValue( hKeyParent, _T("InprocServer32"), NULL, szMe, &hKey ); if ( ERROR_SUCCESS != lResult ) goto failure;
// Store our threading model
lResult = AssignKeyValue( hKey, _T("ThreadingModel"), NULL, _T("Apartment"), NULL ); if ( ERROR_SUCCESS != lResult ) goto failure; RegCloseKey( hKey ); hKey = NULL;
// Store our type-lib info
#ifndef UNICODE
size_t lenMe = strlen(szMe) + 1; wchar_t *wszMe = new wchar_t[lenMe]; if ( NULL == wszMe ) { return false; } if ( 0 == MultiByteToWideChar( _getmbcp(), 0L, szMe, lenMe, wszMe, lenMe ) ) { return false; } hr = LoadTypeLibEx( wszMe, REGKIND_REGISTER, &pTypeLib ); delete [] wszMe; #else
hr = LoadTypeLibEx( szMe, REGKIND_REGISTER, &pTypeLib ); #endif
if ( FAILED(hr) ) { lResult = hr; goto failure; } pTypeLib->Release();
// Now store pointer to the type-lib info
lResult = AssignKeyValue( hKeyParent, _T("TypeLib"), NULL, _T("{7c1b689f-3b9f-4c65-aa65-9951a5048e47}"), NULL ); if ( ERROR_SUCCESS != lResult ) goto failure;
// Store our ProgID value
lResult = AssignKeyValue( hKeyParent, _T("ProgID"), NULL, _T("InfGenerator"), NULL ); if ( ERROR_SUCCESS != lResult ) goto failure;
// Done with CLSID\{value} key
RegCloseKey( hKeyParent ); hKey = NULL;
// *
// Store our ProgID entry and associated values
// *
lResult = AssignKeyValue( HKEY_CLASSES_ROOT, _T("InfGenerator"), NULL, _T("Update INF Generator"), &hKey ); if ( ERROR_SUCCESS != lResult ) goto failure;
lResult = AssignKeyValue( hKey, _T("CLSID"), NULL, _T("{9cd916b9-2004-42b1-b639-572fbf647204}"), NULL ); if ( ERROR_SUCCESS != lResult ) goto failure;
lResult = AssignKeyValue( hKey, _T("CurVer"), NULL, _T("InfGenerator.1"), NULL ); if ( ERROR_SUCCESS != lResult ) goto failure; // Done with <ProgID> key
RegCloseKey( hKey ); hKey = NULL;
lResult = AssignKeyValue( HKEY_CLASSES_ROOT, _T("InfGenerator.1"), NULL, _T("Update INF Generator"), &hKey ); if ( ERROR_SUCCESS != lResult ) goto failure;
lResult = AssignKeyValue( hKey, _T("CLSID"), NULL, _T("{9cd916b9-2004-42b1-b639-572fbf647204}"), NULL ); if ( ERROR_SUCCESS != lResult ) goto failure;
// Done with version-specific <ProgID> key
RegCloseKey( hKey ); hKey = NULL; return S_OK;
failure: if ( hKeyParent ) RegCloseKey( hKeyParent ); if ( hKey ) RegCloseKey( hKey ); // Undo anything we might have done
DllUnregisterServer(); return lResult; }
long DeleteKeyTree( HKEY hKeyParent, LPTSTR szKeyName ) { FILETIME ftLastWrite; DWORD i = 0, dwSizeOfKey = _MAX_PATH; TCHAR szSubkey[_MAX_PATH]; LONG lResult, lFirstFailure = ERROR_SUCCESS; HKEY hKey;
lResult = RegOpenKeyEx( hKeyParent, szKeyName, (0), KEY_ALL_ACCESS, &hKey ); if ( ERROR_SUCCESS != lResult ) { lFirstFailure = lResult; goto failure; }
while ( ERROR_SUCCESS == (lResult = RegEnumKeyEx( hKey, i++, szSubkey, &dwSizeOfKey, (0), NULL, (0), &ftLastWrite )) ) { lResult = DeleteKeyTree( hKey, szSubkey ); if ( ERROR_SUCCESS != lResult && ERROR_SUCCESS != lFirstFailure ) { lFirstFailure = lResult; }
dwSizeOfKey = _MAX_PATH; }
if ( ERROR_NO_MORE_ITEMS != lResult && ERROR_SUCCESS != lFirstFailure ) { lFirstFailure = lResult; } RegCloseKey( hKey );
failure: // Attempt to delete key regardless of previous failures
lResult = RegDeleteKey( hKeyParent, szKeyName ); if ( ERROR_SUCCESS != lResult && ERROR_SUCCESS != lFirstFailure ) { lFirstFailure = lResult; }
// Check for successful completion
return lFirstFailure; }
HRESULT __stdcall DllCanUnloadNow( void ) { if ( 0L == InterlockedCompareExchange( &g_cKeepAlive, 0L, 0L ) ) return S_OK; else return S_FALSE; }
HRESULT __stdcall DllGetClassObject( REFCLSID clsid, REFIID riid, void **ppv ) { *ppv = NULL; if ( CLSID_InfGenerator != clsid ) return CLASS_E_CLASSNOTAVAILABLE;
CInfGeneratorFactory *pInfGeneratorFactory = new CInfGeneratorFactory; if ( NULL == pInfGeneratorFactory ) return E_OUTOFMEMORY;
HRESULT hr = pInfGeneratorFactory->QueryInterface( riid, ppv ); pInfGeneratorFactory->Release();
return hr; }
HRESULT DllUnregisterServer( void ) { long lResult; HKEY hKey;
// Remove type-lib info
UnRegisterTypeLib( LIBID_InfGeneratorLib, (1), (0), LANG_NEUTRAL, SYS_WIN32 );
lResult = RegOpenKeyEx( HKEY_CLASSES_ROOT, _T("CLSID"), (0), KEY_ALL_ACCESS, &hKey ); if ( ERROR_SUCCESS == lResult ) { // Get rid of our CLSID entry
lResult = DeleteKeyTree( hKey, _T("{6324c2cf-aad4-4477-8388-4fdba25188d4}") ); RegCloseKey( hKey ); }
// Get rid of our PROGID entry
lResult = DeleteKeyTree( HKEY_CLASSES_ROOT, _T("InfGenerator") ); if ( ERROR_SUCCESS != lResult ) { return E_FAIL; }
// And our versioned PROGID entry
lResult = DeleteKeyTree( HKEY_CLASSES_ROOT, _T("InfGenerator.1") ); if ( ERROR_SUCCESS != lResult ) { return E_FAIL; }
return S_OK; }
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReasonFlag, PVOID pvReserved ) { // Remember instance handle
g_hMyInstance = hInstance;
return TRUE; }
|