/*++ Copyright (C) Microsoft Corporation, 1997 - 1999 Module Name: senssink.cxx Abstract: Main entry point for the Sample SENS Subscriber. Author: Gopal Parupudi [Notes:] optional-notes Revision History: GopalP 11/17/1997 Start. --*/ // Define this once and only once per exe. #define INITGUIDS #include #include #include #include #include #include #include #include #include "sinkcomn.hxx" #include "sinkguid.hxx" #include "senssink.hxx" #include "cfacnet.hxx" #include "cfaclogn.hxx" #include "cfacpwr.hxx" #define PER_USER 1 #if PER_USER #define REG_ROOT HKEY_CLASSES_ROOT #else #define REG_ROOT HKEY_CLASSES_ROOT #endif #if defined(SENS_NT4) #define SENS_TLB SENS_BSTR("SENS.EXE") #else // SENS_NT4 #define SENS_TLB SENS_BSTR("SENS.DLL") #endif // SENS_NT4 #define SUBSCRIBER SENS_STRING("SENS_SUBSCRIBER: ") #define MAX_QUERY_SIZE 512 #define MAJOR_VER 1 #define MINOR_VER 0 #define DEFAULT_LCID 0x0 // // Globals // IEventSystem *gpIEventSystem; ITypeInfo *gpITypeInfoNetwork; ITypeInfo *gpITypeInfoLogon; ITypeInfo *gpITypeInfoLogon2; ITypeInfo *gpITypeInfoOnNow; DWORD gTid; HANDLE ghEvent; #if defined(SENS_CHICAGO) #ifdef DBG DWORD gdwDebugOutputLevel; #endif // DBG #endif // SENS_CHICAGO int __cdecl main( int argc, char ** argv ) { HRESULT hr; DWORD dwVer; DWORD dwRegCO; DWORD dwWaitStatus; BOOL fInitialized; BOOL bUnregister; BOOL bSetupPhase; MSG msg; LPCLASSFACTORY pNetCF; LPCLASSFACTORY pLogonCF; LPCLASSFACTORY pLogon2CF; LPCLASSFACTORY pPowerCF; ITypeLib *pITypeLib; hr = S_OK; dwRegCO = 0x0; bUnregister = FALSE; bSetupPhase = FALSE; fInitialized = FALSE; pNetCF = NULL; pLogonCF = NULL; pLogon2CF = NULL; pPowerCF = NULL; gpIEventSystem = NULL; pITypeLib = NULL; gpITypeInfoNetwork = NULL; gpITypeInfoLogon = NULL; gpITypeInfoLogon2 = NULL; gpITypeInfoOnNow = NULL; dwVer = CoBuildVersion(); if (rmm != HIWORD(dwVer)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("CoBuildVersion() returned incompatible version.\n"))); return -1; } if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("CoInitializeEx() returned 0x%x.\n"), hr)); goto Cleanup; } fInitialized = TRUE; // // Check the command-line args // if ( ((argc == 2) && ((argv[1][0] != '-') && (argv[1][0] != '/'))) || (argc > 2)) { Usage(); return (-1); } if (argc == 2) { switch (argv[1][1]) { case 'i': case 'I': bSetupPhase = TRUE; bUnregister = FALSE; break; case 'u': case 'U': bSetupPhase = TRUE; bUnregister = TRUE; break; case 'e': case 'E': // SCM calls me with /Embedding flag break; default: Usage(); return (-1); } } if (bSetupPhase == TRUE) { hr = RegisterWithES(bUnregister); if (FAILED(hr)) { goto Cleanup; } // Network Subscriber hr = RegisterSubscriberCLSID( CLSID_SensTestSubscriberNetwork, TEST_SUBSCRIBER_NAME_NETWORK, bUnregister ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Failed to %sregister Test Subscriber Network CLSID") SENS_STRING(" - hr = <%x>\n"), bUnregister ? SENS_STRING("un") : SENS_STRING(""), hr)); } else { SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("%segistered Test Subscriber Network CLSID.\n"), bUnregister ? SENS_STRING("Unr") : SENS_STRING("R"))); } // Logon Subscriber hr = RegisterSubscriberCLSID( CLSID_SensTestSubscriberLogon, TEST_SUBSCRIBER_NAME_LOGON, bUnregister ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Failed to %sregister Test Subscriber Logon CLSID") SENS_STRING(" - hr = <%x>\n"), bUnregister ? SENS_STRING("un") : SENS_STRING(""), hr)); } else { SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("%segistered Test Subscriber Logon CLSID.\n"), bUnregister ? SENS_STRING("Unr") : SENS_STRING("R"))); } // Logon2 Subscriber hr = RegisterSubscriberCLSID( CLSID_SensTestSubscriberLogon2, TEST_SUBSCRIBER_NAME_LOGON2, bUnregister ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Failed to %sregister Test Subscriber Logon2 CLSID") SENS_STRING(" - hr = <%x>\n"), bUnregister ? SENS_STRING("un") : SENS_STRING(""), hr)); } else { SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("%segistered Test Subscriber Logon2 CLSID.\n"), bUnregister ? SENS_STRING("Unr") : SENS_STRING("R"))); } // Power Subscriber hr = RegisterSubscriberCLSID( CLSID_SensTestSubscriberOnNow, TEST_SUBSCRIBER_NAME_POWER, bUnregister ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Failed to %sregister Test Subscriber Power CLSID") SENS_STRING(" - hr = <%x>\n"), bUnregister ? SENS_STRING("un") : SENS_STRING(""), hr)); } else { SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("%segistered Test Subscriber Power CLSID.\n"), bUnregister ? SENS_STRING("Unr") : SENS_STRING("R"))); } goto Cleanup; } // // Get the ITypeInfo pointer. // hr = LoadRegTypeLib( LIBID_SensEvents, MAJOR_VER, MINOR_VER, DEFAULT_LCID, &pITypeLib ); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("LoadRegTypeLib() returned 0x%x\n"), hr)); if (FAILED(hr)) { hr = LoadTypeLib( SENS_TLB, &pITypeLib ); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("LoadTypeLib() returned 0x%x\n"), hr)); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Exiting...\n"))); goto Cleanup; } } // Get type information for the ISensNetwork interface. hr = pITypeLib->GetTypeInfoOfGuid( IID_ISensNetwork, &gpITypeInfoNetwork ); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("ITypeLib::GetTypeInfoOfGuid(ISensNetwork) returned 0x%x\n"), hr)); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Exiting...\n"))); goto Cleanup; } // Get type information for the ISensLogon interface. hr = pITypeLib->GetTypeInfoOfGuid( IID_ISensLogon, &gpITypeInfoLogon ); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("ITypeLib::GetTypeInfoOfGuid(ISensLogon) returned 0x%x\n"), hr)); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Exiting...\n"))); goto Cleanup; } // Get type information for the ISensLogon2 interface. hr = pITypeLib->GetTypeInfoOfGuid( IID_ISensLogon2, &gpITypeInfoLogon2 ); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("ITypeLib::GetTypeInfoOfGuid(ISensLogon2) returned 0x%x\n"), hr)); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Exiting...\n"))); goto Cleanup; } // Get type information for the ISensOnNow interface. hr = pITypeLib->GetTypeInfoOfGuid( IID_ISensOnNow, &gpITypeInfoOnNow ); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("ITypeLib::GetTypeInfoOfGuid(ISensOnNow) returned 0x%x\n"), hr)); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Exiting...\n"))); goto Cleanup; } // // Create the event // ghEvent = CreateEvent( NULL, // Security Attributes FALSE, // bManualReset FALSE, // Initial state SENS_STRING("SENS Test Subscriber Quit Event") ); if (ghEvent == NULL) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("CreateEvent() failed.\n"))); goto Cleanup; } // // Create the Network ClassFactory and register it with COM. // pNetCF = new CISensNetworkCF; if (NULL == pNetCF) { goto Cleanup; } pNetCF->AddRef(); // Because we hold on to it. SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("ClassFactory created successfully.\n"))); // Register the CLSID hr = CoRegisterClassObject( CLSID_SensTestSubscriberNetwork, (LPUNKNOWN) pNetCF, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegCO ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("CoRegisterClassObject(Network) returned 0x%x.\n"), hr)); } else { SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("Successfully registered the ISensNetwork Class Factory.\n"))); } // // Create the Logon ClassFactory and register it with COM. // pLogonCF = new CISensLogonCF; if (NULL == pLogonCF) { goto Cleanup; } pLogonCF->AddRef(); // Because we hold on to it. SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("ClassFactory created successfully.\n"))); hr = CoRegisterClassObject( CLSID_SensTestSubscriberLogon, (LPUNKNOWN) pLogonCF, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegCO ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("CoRegisterClassObject(Logon) returned 0x%x.\n"), hr)); } else { SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("Successfully registered the ISensLogon Class Factory.\n"))); } // // Create the Logon2 ClassFactory and register it with COM. // pLogon2CF = new CISensLogon2CF; if (NULL == pLogon2CF) { goto Cleanup; } pLogon2CF->AddRef(); // Because we hold on to it. SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("ClassFactory created successfully.\n"))); hr = CoRegisterClassObject( CLSID_SensTestSubscriberLogon2, (LPUNKNOWN) pLogon2CF, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegCO ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("CoRegisterClassObject(Logon2) returned 0x%x.\n"), hr)); } else { SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("Successfully registered the ISensLogon2 Class Factory.\n"))); } // // Create the Power ClassFactory and register it with COM. // pPowerCF = new CISensOnNowCF; if (NULL == pPowerCF) { goto Cleanup; } pPowerCF->AddRef(); // Because we hold on to it. SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("ClassFactory created successfully.\n"))); hr = CoRegisterClassObject( CLSID_SensTestSubscriberOnNow, (LPUNKNOWN) pPowerCF, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegCO ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("CoRegisterClassObject(Power) returned 0x%x.\n"), hr)); } else { SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("Successfully registered the ISensOnNow Class Factory.\n"))); } // // Wait to quit. // dwWaitStatus = WaitForSingleObject(ghEvent, INFINITE); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("WaitForSingleObject returned %d\n"), dwWaitStatus)); // // Cleanup // Cleanup: if ( (0L != dwRegCO) && (bSetupPhase == TRUE) && (bUnregister == TRUE)) { CoRevokeClassObject(dwRegCO); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("CoRevokeClassObject() returned 0x%x.\n"), hr)); } if (bSetupPhase == TRUE) { SensPrint(SENS_INFO, (SENS_STRING("\n") SUBSCRIBER SENS_STRING("Sens Test Subscriber Configuration %s.\n"), FAILED(hr) ? SENS_STRING("failed") : SENS_STRING("successful"))); } if (NULL != pNetCF) { pNetCF->Release(); } if (NULL != pLogonCF) { pLogonCF->Release(); } if (NULL != pLogon2CF) { pLogon2CF->Release(); } if (NULL != pPowerCF) { pPowerCF->Release(); } if (NULL != pITypeLib) { pITypeLib->Release(); } if (NULL != gpITypeInfoNetwork) { gpITypeInfoNetwork->Release(); } if (NULL != gpITypeInfoLogon) { gpITypeInfoLogon->Release(); } if (NULL != gpITypeInfoLogon2) { gpITypeInfoLogon2->Release(); } if (NULL != gpITypeInfoOnNow) { gpITypeInfoOnNow->Release(); } if (fInitialized) { CoUninitialize(); } return 0; } HRESULT RegisterWithES( BOOL bUnregister ) { HRESULT hr; hr = S_OK; // // Instantiate the Event System // hr = CoCreateInstance( CLSID_CEventSystem, NULL, CLSCTX_SERVER, IID_IEventSystem, (LPVOID *) &gpIEventSystem ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Failed to create CEventSystem, HRESULT=%x\n"), hr)); goto Cleanup; } SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("Successfully created CEventSystem\n"))); #if 0 // // Test to see if we can get the MachineName // BSTR bstrMachineName; hr = gpIEventQuery->get_MachineName(&bstrMachineName); if (SUCCEEDED(hr)) SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("Configuring Test Subscriber on %s...\n"), bstrMachineName)); else SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("get_MachineName failed, hr = %x\n"), hr)); #endif // 0 // // Register my Subscriber's subscriptions with SENS. // hr = RegisterSubscriptions(bUnregister); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("Failed to %sregister SensSink Subscriptions") SENS_STRING(" - hr = <%x>\n"), bUnregister ? SENS_STRING("un") : SENS_STRING(""), hr)); goto Cleanup; } SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("%segistered SensSink Subscriptions.\n"), bUnregister ? SENS_STRING("Unr") : SENS_STRING("R"))); Cleanup: // // Cleanup // if (gpIEventSystem) { gpIEventSystem->Release(); } return hr; } HRESULT RegisterSubscriptions( BOOL bUnregister ) { int i; int errorIndex; HRESULT hr; LPOLESTR strGuid; LPOLESTR strSubscriptionID; WCHAR szQuery[MAX_QUERY_SIZE]; BSTR bstrEventClassID; BSTR bstrInterfaceID; BSTR bstrSubscriberCLSID; BSTR bstrPublisherID; BSTR bstrSubscriptionID; BSTR bstrSubscriptionName; BSTR bstrMethodName; BSTR bstrPropertyName; BSTR bstrPropertyValue; ULONG ulPropertyValue; VARIANT variantPropertyValue; BSTR bstrPROGID_EventSubscription; IEventSubscription *pIEventSubscription; hr = S_OK; strGuid = NULL; errorIndex = 0; strSubscriptionID = NULL; bstrEventClassID = NULL; bstrInterfaceID = NULL; bstrSubscriberCLSID = NULL; bstrPublisherID = NULL; bstrSubscriptionID = NULL; bstrSubscriptionName = NULL; bstrMethodName = NULL; bstrPropertyName = NULL; bstrPropertyValue = NULL; ulPropertyValue = 0x0; bstrPROGID_EventSubscription = NULL; pIEventSubscription = NULL; // // Build a Subscriber // AllocateBstrFromGuid(bstrPublisherID, SENSGUID_PUBLISHER); AllocateBstrFromString(bstrPROGID_EventSubscription, PROGID_EventSubscription); for (i = 0; i < TEST_SUBSCRIPTIONS_COUNT; i++) { if (bUnregister) { // Form the query StringCbCopy(szQuery, sizeof(szQuery), SENS_BSTR("SubscriptionID=")); AllocateStrFromGuid(strSubscriptionID, *(gTestSubscriptions[i].pSubscriptionID)); StringCbCat(szQuery, sizeof(szQuery), strSubscriptionID); hr = gpIEventSystem->Remove( PROGID_EventSubscription, szQuery, &errorIndex ); FreeStr(strSubscriptionID); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("RegisterSubscriptions(%d) failed to unregister") SENS_STRING(" - hr = <%x>\n"), i, hr)); goto Cleanup; } continue; } // Get a new IEventSubscription object to play with. hr = CoCreateInstance( CLSID_CEventSubscription, NULL, CLSCTX_SERVER, IID_IEventSubscription, (LPVOID *) &pIEventSubscription ); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("RegisterSubscriptions(%d) failed to create ") SENS_STRING("IEventSubscriptions - hr = <%x>\n"), i, hr)); goto Cleanup; } AllocateBstrFromGuid(bstrSubscriptionID, *(gTestSubscriptions[i].pSubscriptionID)); hr = pIEventSubscription->put_SubscriptionID(bstrSubscriptionID); ASSERT(SUCCEEDED(hr)); AllocateBstrFromGuid(bstrSubscriberCLSID, *(gTestSubscriptions[i].pSubscriberCLSID)); hr = pIEventSubscription->put_SubscriberCLSID(bstrSubscriberCLSID); ASSERT(SUCCEEDED(hr)); hr = pIEventSubscription->put_PublisherID(bstrPublisherID); ASSERT(SUCCEEDED(hr)); hr = pIEventSubscription->put_SubscriptionID(bstrSubscriptionID); ASSERT(SUCCEEDED(hr)); AllocateBstrFromString(bstrSubscriptionName, gTestSubscriptions[i].strSubscriptionName); hr = pIEventSubscription->put_SubscriptionName(bstrSubscriptionName); ASSERT(SUCCEEDED(hr)); AllocateBstrFromString(bstrMethodName, gTestSubscriptions[i].strMethodName); hr = pIEventSubscription->put_MethodName(bstrMethodName); ASSERT(SUCCEEDED(hr)); AllocateBstrFromGuid(bstrEventClassID, *(gTestSubscriptions[i].pEventClassID)); hr = pIEventSubscription->put_EventClassID(bstrEventClassID); ASSERT(SUCCEEDED(hr)); AllocateBstrFromGuid(bstrInterfaceID, *(gTestSubscriptions[i].pInterfaceID)); hr = pIEventSubscription->put_InterfaceID(bstrInterfaceID); ASSERT(SUCCEEDED(hr)); #if 1 hr = pIEventSubscription->put_PerUser(TRUE); ASSERT(SUCCEEDED(hr)); #endif if (wcscmp(gTestSubscriptions[i].strMethodName, SENS_BSTR("ConnectionMadeNoQOCInfo")) == 0) { AllocateBstrFromString(bstrPropertyName, SENS_BSTR("ulConnectionMadeTypeNoQOC")); ulPropertyValue = CONNECTION_LAN; InitializeDwordVariant(&variantPropertyValue, ulPropertyValue); hr = pIEventSubscription->PutPublisherProperty( bstrPropertyName, &variantPropertyValue ); ASSERT(SUCCEEDED(hr)); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("PutPublisherProperty(WAN/LAN) returned 0x%x\n"), hr)); FreeBstr(bstrPropertyName); ulPropertyValue = 0x0; } else if ( (wcscmp(gTestSubscriptions[i].strMethodName, SENS_BSTR("DestinationReachable")) == 0) || (wcscmp(gTestSubscriptions[i].strMethodName, SENS_BSTR("DestinationReachableNoQOCInfo")) == 0)) { // Set the DestinationName for which we want to be notified for. AllocateBstrFromString(bstrPropertyName, gTestSubscriptions[i].strPropertyMethodName); AllocateBstrFromString(bstrPropertyValue, gTestSubscriptions[i].strPropertyMethodNameValue); InitializeBstrVariant(&variantPropertyValue, bstrPropertyValue); hr = pIEventSubscription->PutPublisherProperty( bstrPropertyName, &variantPropertyValue ); ASSERT(SUCCEEDED(hr)); SensPrint(SENS_INFO, (SUBSCRIBER SENS_STRING("PutPublisherProperty(DestinationName) returned 0x%x\n"), hr)); FreeBstr(bstrPropertyName); FreeBstr(bstrPropertyValue); } FreeBstr(bstrSubscriptionID); FreeBstr(bstrSubscriberCLSID); FreeBstr(bstrEventClassID); FreeBstr(bstrInterfaceID); FreeBstr(bstrSubscriptionName); FreeBstr(bstrMethodName); hr = gpIEventSystem->Store(bstrPROGID_EventSubscription, pIEventSubscription); if (FAILED(hr)) { SensPrint(SENS_ERR, (SUBSCRIBER SENS_STRING("RegisterSubscriptions(%d) failed to commit") SENS_STRING(" - hr = <%x>\n"), i, hr)); goto Cleanup; } pIEventSubscription->Release(); pIEventSubscription = NULL; } // for loop Cleanup: // // Cleanup // if (pIEventSubscription) { pIEventSubscription->Release(); } FreeBstr(bstrPublisherID); FreeBstr(bstrSubscriberCLSID); FreeStr(strGuid); return (hr); } HRESULT RegisterSubscriberCLSID( REFIID clsid, TCHAR* strSubscriberName, BOOL bUnregister ) /*++ Routine Description: Register/Unregister the CLSID of the Test subscriber. Arguments: clsid - CLSID of the Subscriber. strSubscriberName - Name of the Subscriber. bUnregister - If TRUE, then unregister all subscriptions of SENS Test subscriber. Return Value: S_OK, if successful hr, otherwise --*/ { HRESULT hr; HMODULE hModule; HKEY appidKey = 0; HKEY clsidKey = 0; HKEY serverKey = 0; TCHAR szModule[MAX_PATH+1]; WCHAR *szCLSID = 0; WCHAR *szLIBID = 0; TCHAR *szCLSID_t = 0; TCHAR *szLIBID_t = 0; TCHAR *szFriendlyName = strSubscriberName; hr = S_OK; // Convert the CLSID into a TCHAR. hr = StringFromCLSID(clsid, &szCLSID); if (FAILED(hr)) { goto Cleanup; } if (bUnregister == FALSE) { hr = StringFromCLSID(LIBID_SensEvents, &szLIBID); if (FAILED(hr)) { goto Cleanup; } hModule = GetModuleHandle(0); // Get Subscriber location. const size_t moduleBufSize = sizeof szModule / sizeof szModule[0]; DWORD dwResult = GetModuleFileName(hModule, szModule, moduleBufSize); if (dwResult == 0) { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); goto Cleanup; } } // // Convert UNICODE strings into ANSI, if necessary // #if !defined(SENS_CHICAGO) szCLSID_t = szCLSID; szLIBID_t = szLIBID; #else // SENS_CHICAGO szCLSID_t = SensUnicodeStringToAnsi(szCLSID); szLIBID_t = SensUnicodeStringToAnsi(szLIBID); if ( (NULL == szCLSID_t) || (NULL == szLIBID_t)) { goto Cleanup; } #endif // SENS_CHICAGO // Build the key CLSID\\{clsid} TCHAR clsidKeyName[sizeof "CLSID\\{12345678-1234-1234-1234-123456789012}"]; StringCbCopy(clsidKeyName, sizeof(clsidKeyName), SENS_STRING("CLSID\\")); StringCbCat(clsidKeyName, sizeof(clsidKeyName), szCLSID_t); // Build the key AppID\\{clsid} TCHAR appidKeyName[sizeof "AppID\\{12345678-1234-1234-1234-123456789012}"]; StringCbCopy(appidKeyName, sizeof(appidKeyName), SENS_STRING("AppID\\")); StringCbCat(appidKeyName, sizeof(appidKeyName), szCLSID_t); if (bUnregister) { hr = RecursiveDeleteKey(HKEY_CLASSES_ROOT, clsidKeyName); if (FAILED(hr)) { goto Cleanup; } hr = RecursiveDeleteKey(HKEY_CLASSES_ROOT, appidKeyName); goto Cleanup; } // Create the CLSID\\{clsid} key hr = CreateKey( HKEY_CLASSES_ROOT, clsidKeyName, szFriendlyName, &clsidKey ); if (FAILED(hr)) { goto Cleanup; } // // Under the CLSID\\{clsid} key, create a named value // AppID = {clsid} hr = CreateNamedValue(clsidKey, SENS_STRING("AppID"), szCLSID_t); if (FAILED(hr)) { goto Cleanup; } // // Create the appropriate server key beneath the clsid key. // For servers, this is CLSID\\{clsid}\\LocalServer32. // In both cases, the default value is the module path name. // hr = CreateKey( clsidKey, SENS_STRING("LocalServer32"), szModule, &serverKey ); if (FAILED(hr)) { goto Cleanup; } RegCloseKey(serverKey); // // Create CLSID\\{clsid}\\TypeLib subkey with a default value of // the LIBID of the TypeLib // hr = CreateKey( clsidKey, SENS_STRING("TypeLib"), szLIBID_t, &serverKey ); if (FAILED(hr)) { goto Cleanup; } RegCloseKey(serverKey); // We're finished with the CLSID\\{clsid} key RegCloseKey(clsidKey); // Register APPID. hr = CreateKey( HKEY_CLASSES_ROOT, appidKeyName, szFriendlyName, &appidKey ); if (FAILED(hr)) { goto Cleanup; } // Under AppId\{clsid} key, create a named value [RunAs = "Interactive User"] hr = CreateNamedValue(appidKey, SENS_STRING("RunAs"), SENS_STRING("Interactive User")); if (FAILED(hr)) { goto Cleanup; } RegCloseKey(appidKey); Cleanup: // // Cleanup // CoTaskMemFree(szCLSID); CoTaskMemFree(szLIBID); #if defined(SENS_CHICAGO) if (szCLSID_t != NULL) { delete szCLSID_t; } if (szLIBID_t != NULL) { delete szLIBID_t; } #endif // SENS_CHICAGO return hr; } HRESULT CreateKey( HKEY hParentKey, const TCHAR* KeyName, const TCHAR* defaultValue, HKEY* hKey ) /*++ Routine Description: Create a key (with an optional default value). The handle to the key is returned as an [out] parameter. If NULL is passed as the key parameter, the key is created in the registry, then closed. Arguments: hParentKey - Handle to the parent Key. KeyName - Name of the key to create. defaultValue - The default value for the key to create. hKey - OUT Handle to key that was created. Return Value: S_OK, if successful hr, otherwise --*/ { HKEY hTempKey; LONG lResult; hTempKey = NULL; lResult = RegCreateKeyEx( hParentKey, // Handle to open key KeyName, // Subkey name 0, // Reserved NULL, // Class string REG_OPTION_NON_VOLATILE, // Options Flag KEY_ALL_ACCESS, // Desired Security access NULL, // Pointer to Security Attributes structure &hTempKey, // Handle of the opened/created key NULL // Disposition value ); if (lResult != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(lResult); } // Set the default value for the key if (defaultValue != NULL) { lResult = RegSetValueEx( hTempKey, // Key to set Value for. NULL, // Value to set 0, // Reserved REG_SZ, // Value Type (BYTE*) defaultValue, // Address of Value data sizeof(TCHAR) * (_tcslen(defaultValue)+1) // Size of Value ); if (lResult != ERROR_SUCCESS) { RegCloseKey(hTempKey); return HRESULT_FROM_WIN32(lResult); } } if (hKey == NULL) { RegCloseKey(hTempKey); } else { *hKey = hTempKey; } return S_OK; } HRESULT CreateNamedValue( HKEY hKey, const TCHAR* title, const TCHAR* value ) /*++ Routine Description: Create a named value under a key Arguments: hKey - Handle to the parent Key. title - Name of the Value to create. value - The data for the Value under the Key. Return Value: S_OK, if successful hr, otherwise --*/ { HRESULT hr; LONG lResult; hr = S_OK; lResult = RegSetValueEx( hKey, // Key to set Value for. title, // Value to set 0, // Reserved REG_SZ, // Value Type (BYTE*) value, // Address of Value data sizeof(TCHAR) * (_tcslen(value)+1) // Size of Value ); if (lResult != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lResult); } return hr; } HRESULT RecursiveDeleteKey( HKEY hKeyParent, const TCHAR* lpszKeyChild ) /*++ Routine Description: Delete a key and all of its descendents. Arguments: hKeyParent - Handle to the parent Key. lpszKeyChild - The data for the Value under the Key. Return Value: S_OK, if successful hr, otherwise --*/ { HKEY hKeyChild; LONG lResult; // // Open the child. // lResult = RegOpenKeyEx( hKeyParent, // Handle to the Parent lpszKeyChild, // Name of the child key 0, // Reserved KEY_ALL_ACCESS, // Security Access Mask &hKeyChild // Handle to the opened key ); if (lResult != ERROR_SUCCESS) { return HRESULT_FROM_WIN32(lResult); } // // Enumerate all of the decendents of this child. // FILETIME time; TCHAR szBuffer[MAX_PATH+1]; const DWORD bufSize = sizeof szBuffer / sizeof szBuffer[0]; DWORD dwSize = bufSize; while (TRUE) { lResult = RegEnumKeyEx( hKeyChild, // Handle of the key to enumerate 0, // Index of the subkey to retrieve szBuffer, // OUT Name of the subkey &dwSize, // OUT Size of the buffer for name of subkey NULL, // Reserved NULL, // OUT Class of the enumerated subkey NULL, // OUT Size of the class of the subkey &time // OUT Last time the subkey was written to ); if (lResult != ERROR_SUCCESS) { break; } // Delete the decendents of this child. lResult = RecursiveDeleteKey(hKeyChild, szBuffer); if (lResult != ERROR_SUCCESS) { // Cleanup before exiting. RegCloseKey(hKeyChild); return HRESULT_FROM_WIN32(lResult); } dwSize = bufSize; } // while // Close the child. RegCloseKey(hKeyChild); // Delete this child. lResult = RegDeleteKey(hKeyParent, lpszKeyChild); return HRESULT_FROM_WIN32(lResult); }