windows-nt/Source/XPSP1/NT/com/mobile/sens/conn/senssink/senssink.cxx

1238 lines
32 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (C) Microsoft Corporation, 1997 - 1999
Module Name:
senssink.cxx
Abstract:
Main entry point for the Sample SENS Subscriber.
Author:
Gopal Parupudi <GopalP>
[Notes:]
optional-notes
Revision History:
GopalP 11/17/1997 Start.
--*/
// Define this once and only once per exe.
#define INITGUIDS
#include <common.hxx>
#include <objbase.h>
#include <windows.h>
#include <ole2ver.h>
#include <initguid.h>
#include <eventsys.h>
#include <sensevts.h>
#include <sens.h>
#include "sinkcomn.hxx"
#include "sinkguid.hxx"
#include "senssink.hxx"
#include "cfacnet.hxx"
#include "cfaclogn.hxx"
#include "cfacpwr.hxx"
#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
wcscpy(szQuery, SENS_BSTR("SubscriptionID"));
wcscat(szQuery, SENS_BSTR("="));
AllocateStrFromGuid(strSubscriptionID, *(gTestSubscriptions[i].pSubscriptionID));
wcscat(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 (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}"];
_tcscpy(clsidKeyName, SENS_STRING("CLSID\\"));
_tcscat(clsidKeyName, szCLSID_t);
// Build the key AppID\\{clsid}
TCHAR appidKeyName[sizeof "AppID\\{12345678-1234-1234-1234-123456789012}"];
_tcscpy(appidKeyName, SENS_STRING("AppID\\"));
_tcscat(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);
}