Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1434 lines
37 KiB

/*++
Copyright (C) Microsoft Corporation, 1997 - 1999
Module Name:
senscfg.cxx
Abstract:
Code to do the configuration (install/uninstall) for SENS.
Author:
Gopal Parupudi <GopalP>
[Notes:]
optional-notes
Revision History:
GopalP 11/11/1997 Start.
--*/
#define INITGUID
#include <common.hxx>
#include <objbase.h>
#include <coguid.h>
#include <eventsys.h>
#include <sensevts.h>
#include <sens.h>
#include <wininet.h>
#include <winineti.h>
#include "senscfg.hxx"
#include "sensinfo.hxx"
#include "memfunc.hxx"
#define MAJOR_VER 1
#define MINOR_VER 0
#define DEFAULT_LCID 0x0
#define MAX_QUERY_SIZE 512
#define SENS_SETUP "SENSCFG: "
#define SENS_SERVICEA "SENS"
#define SENS_SETUPW SENS_BSTR("SENSCFG: ")
#define SENS_SERVICE SENS_STRING("SENS")
#define SENS_DISPLAY_NAME SENS_STRING("System Event Notification")
#define SENS_SERVICE_GROUP SENS_STRING("Network")
#define EVENTSYSTEM_REMOVE SENS_STRING("esserver /remove")
#define EVENTSYSTEM_INSTALL SENS_STRING("esserver /install")
#define SENS_WINLOGON_DLL SENS_STRING("senslogn.dll")
#define GUID_STR_SIZE sizeof("{12345678-1234-1234-1234-123456789012}")
#define EVENTSYSTEM_KEY SENS_STRING("SOFTWARE\\Microsoft\\EventSystem")
#define WINLOGON_NOTIFY_KEY SENS_STRING("SOFTWARE\\Microsoft\\Windows NT\\") \
SENS_STRING("CurrentVersion\\Winlogon\\Notify\\") \
SENS_STRING("senslogn")
#define WININET_SENS_EVENTS INETEVT_RAS_CONNECT | \
INETEVT_RAS_DISCONNECT | \
INETEVT_LOGON | \
INETEVT_LOGOFF
//
// DLL vs EXE dependent constants
//
#if defined(SENS_NT4)
#define SENS_TLBA "SENS.EXE"
#define SENS_BINARYA "SENS.EXE"
#define SENS_TLB SENS_STRING("SENS.EXE")
#define SENS_BINARY SENS_STRING("SENS.EXE")
#else // SENS_NT4
#define SENS_TLBA "SENS.DLL"
#define SENS_BINARYA "SENS.DLL"
#define SENS_TLB SENS_STRING("SENS.DLL")
#define SENS_BINARY SENS_STRING("SENS.DLL")
#endif // SENS_NT4
//
// Misc debugging constants
//
#ifdef STRICT_HRESULT_CHECKS
#ifdef SUCCEEDED
#undef SUCCEEDED
#define SUCCEEDED(_HR_) (_HR_ == S_OK)
#endif // SUCCEEDED
#ifdef FAILED
#undef FAILED
#define FAILED(_HR_) (_HR_ != S_OK)
#endif // FAILED
#endif // STRICT_HRESULT_CHECKS
//
// Globals
//
IEventSystem *gpIEventSystem;
ITypeLib *gpITypeLib;
#ifdef DBG
DWORD gdwDebugOutputLevel;
#endif // DBG
HRESULT APIENTRY
SensRegister(
void
)
/*++
Routine Description:
Register SENS.
Arguments:
None.
Return Value:
HRESULT returned from SensConfigurationHelper()
--*/
{
return (SensConfigurationHelper(FALSE));
}
HRESULT APIENTRY
SensUnregister(
void
)
/*++
Routine Description:
Unregister SENS.
Arguments:
None.
Return Value:
HRESULT returned from SensConfigurationHelper()
--*/
{
return (SensConfigurationHelper(TRUE));
}
HRESULT
SensConfigurationHelper(
BOOL bUnregister
)
/*++
Routine Description:
Main entry into the SENS configuration utility.
Arguments:
bUnregister - If TRUE, then unregister SENS as a publisher.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
HRESULT hr;
hr = S_OK;
gpIEventSystem = NULL;
gpITypeLib = NULL;
#ifdef DBG
EnableDebugOutputIfNecessary();
#endif // DBG
//
// Configure EventSystem first during an install and last during an uninstall.
//
if (FALSE == bUnregister)
{
hr = SensConfigureEventSystem(FALSE);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to configure EventSystem, HRESULT=%x\n", hr));
goto Cleanup;
}
SensPrintA(SENS_INFO, (SENS_SETUP "Successfully configured EventSystem\n"));
}
//
// Instantiate the Event System
//
hr = CoCreateInstance(
CLSID_CEventSystem,
NULL,
CLSCTX_SERVER,
IID_IEventSystem,
(LPVOID *) &gpIEventSystem
);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to create CEventSystem, HRESULT=%x\n", hr));
goto Cleanup;
}
SensPrintA(SENS_INFO, (SENS_SETUP "Successfully created CEventSystem\n"));
//
// Register Event Classes (and hence, indirectly events) published by SENS.
//
hr = RegisterSensEventClasses(bUnregister);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS Events"
" - hr = <%x>\n", bUnregister ? "un" : "", hr));
goto Cleanup;
}
SensPrintA(SENS_INFO, (SENS_SETUP "%segistered SENS Publisher Events.\n",
bUnregister ? "Unr" : "R", hr));
//
// Register the subscriptions of SENS.
//
hr = RegisterSensSubscriptions(bUnregister);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS Subscriptions"
" - hr = <%x>\n", bUnregister ? "un" : "", hr));
goto Cleanup;
}
SensPrintA(SENS_ERR, (SENS_SETUP "%segistered SENS Subscriptions.\n",
bUnregister ? "Unr" : "R", hr));
//
// Register the SENS TypeLibs.
//
hr = RegisterSensTypeLibraries(bUnregister);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS Type Libraries"
" - hr = <%x>\n", bUnregister ? "un" : "", hr));
// Abort only during the Install phase...
if (bUnregister == FALSE)
{
goto Cleanup;
}
}
SensPrintA(SENS_INFO, (SENS_SETUP "%segistered SENS Type Libraries.\n",
bUnregister ? "Unr" : "R", hr));
//
// Configure EventSystem first during an install and last during an uninstall.
//
if (TRUE == bUnregister)
{
hr = SensConfigureEventSystem(TRUE);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to configure EventSystem, HRESULT=%x\n", hr));
goto Cleanup;
}
SensPrintA(SENS_INFO, (SENS_SETUP "Successfully configured EventSystem\n"));
}
//
// Register SENS CLSID in the registry.
//
hr = RegisterSensCLSID(
SENSGUID_SUBSCRIBER_LCE,
SENS_SUBSCRIBER_NAME_EVENTOBJECTCHANGE,
bUnregister
);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS CLSID"
" - hr = <%x>\n", bUnregister ? "un" : "", hr));
goto Cleanup;
}
SensPrintA(SENS_INFO, (SENS_SETUP "%segistered SENS CLSID.\n",
bUnregister ? "Unr" : "R", hr));
//
// Update Configured value
//
hr = SensUpdateVersion(bUnregister);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to update SENS version"
" - hr = <%x>\n", hr));
goto Cleanup;
}
SensPrintA(SENS_INFO, (SENS_SETUP "Updated SENS version.\n"));
Cleanup:
//
// Cleanup
//
if (gpIEventSystem)
{
gpIEventSystem->Release();
}
if (gpITypeLib)
{
gpITypeLib->Release();
}
SensPrintA(SENS_ERR, ("\n" SENS_SETUP "SENS Configuration %s.\n",
SUCCEEDED(hr) ? "successful" : "failed"));
return (hr);
}
HRESULT
RegisterSensEventClasses(
BOOL bUnregister
)
/*++
Routine Description:
Register/Unregister all the Events published by SENS.
Arguments:
bUnregister - If TRUE, then unregister all SENS Events.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
int i;
int errorIndex;
HRESULT hr;
LPOLESTR strGuid;
LPOLESTR strEventClassID;
WCHAR szQuery[MAX_QUERY_SIZE];
BSTR bstrEventClassID;
BSTR bstrEventClassName;
BSTR bstrFiringInterface;
IEventClass *pIEventClass;
hr = S_OK;
strGuid = NULL;
errorIndex = 0;
strEventClassID = NULL;
bstrEventClassID = NULL;
bstrEventClassName = NULL;
bstrFiringInterface = NULL;
pIEventClass = NULL;
for (i = 0; i < SENS_PUBLISHER_EVENTCLASS_COUNT; i++)
{
// Get a new IEventClass.
hr = CoCreateInstance(
CLSID_CEventClass,
NULL,
CLSCTX_SERVER,
IID_IEventClass,
(LPVOID *) &pIEventClass
);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensEventClasses() failed to create "
"IEventClass - hr = <%x>\n", hr));
goto Cleanup;
}
if (bUnregister)
{
// Form the query
StringCchCopy(szQuery, MAX_QUERY_SIZE, SENS_BSTR("EventClassID="));
AllocateStrFromGuid(strEventClassID, *(gSensEventClasses[i].pEventClassID));
StringCchCat(szQuery, MAX_QUERY_SIZE, strEventClassID);
hr = gpIEventSystem->Remove(
PROGID_EventClass,
szQuery,
&errorIndex
);
FreeStr(strEventClassID);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensEventClasses(%d) failed to Store"
" - hr = <%x>\n", i, hr));
goto Cleanup;
}
pIEventClass->Release();
pIEventClass = NULL;
continue;
}
AllocateBstrFromGuid(bstrEventClassID, *(gSensEventClasses[i].pEventClassID));
hr = pIEventClass->put_EventClassID(bstrEventClassID);
ASSERT(SUCCEEDED(hr));
AllocateBstrFromString(bstrEventClassName, gSensEventClasses[i].strEventClassName);
hr = pIEventClass->put_EventClassName(bstrEventClassName);
ASSERT(SUCCEEDED(hr));
AllocateBstrFromGuid(bstrFiringInterface, *(gSensEventClasses[i].pFiringInterfaceGUID));
hr = pIEventClass->put_FiringInterfaceID(bstrFiringInterface);
ASSERT(SUCCEEDED(hr));
FreeBstr(bstrEventClassID);
FreeBstr(bstrEventClassName);
FreeBstr(bstrFiringInterface);
hr = gpIEventSystem->Store(PROGID_EventClass, pIEventClass);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensEventClasses(%d) failed to Store"
" - hr = <%x>\n", i, hr));
goto Cleanup;
}
pIEventClass->Release();
pIEventClass = NULL;
} // for loop
Cleanup:
//
// Cleanup
//
if (pIEventClass)
{
pIEventClass->Release();
}
FreeStr(strGuid);
return (hr);
}
HRESULT
RegisterSensSubscriptions(
BOOL bUnregister
)
/*++
Routine Description:
Register/Unregister the Event subscriptions of SENS.
Arguments:
bUnregister - If TRUE, then unregister all subscriptions of SENS.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
int i;
int errorIndex;
HRESULT hr;
LPOLESTR strGuid;
LPOLESTR strSubscriptionID;
LPOLESTR strEventClassID;
WCHAR szQuery[MAX_QUERY_SIZE];
BSTR bstrEventClassID;
BSTR bstrInterfaceID;
BSTR bstrPublisherID;
BSTR bstrSubscriptionID;
BSTR bstrSubscriptionName;
BSTR bstrSubscriberCLSID;
BSTR bstrMethodName;
BSTR bstrPublisherPropertyName;
BSTR bstrPublisherPropertyValue;
VARIANT variantPublisherPropertyValue;
BSTR bstrPROGID_EventSubscription;
IEventSubscription *pIEventSubscription;
hr = S_OK;
strGuid = NULL;
errorIndex = 0;
strEventClassID = NULL;
bstrEventClassID = NULL;
bstrInterfaceID = NULL;
bstrPublisherID = NULL;
strSubscriptionID = NULL;
bstrSubscriptionID = NULL;
bstrSubscriberCLSID = NULL;
bstrSubscriptionName = NULL;
bstrMethodName = NULL;
bstrPublisherPropertyName = NULL;
bstrPublisherPropertyValue = NULL;
bstrPROGID_EventSubscription = NULL;
pIEventSubscription = NULL;
AllocateBstrFromGuid(bstrPublisherID, SENSGUID_PUBLISHER);
AllocateBstrFromGuid(bstrSubscriberCLSID, SENSGUID_SUBSCRIBER_LCE);
AllocateBstrFromString(bstrPROGID_EventSubscription, PROGID_EventSubscription);
for (i = 0; i < SENS_SUBSCRIPTIONS_COUNT; i++)
{
if (bUnregister)
{
// Form the query
StringCchCopy(szQuery, MAX_QUERY_SIZE, SENS_BSTR("SubscriptionID="));
AllocateStrFromGuid(strSubscriptionID, *(gSensSubscriptions[i].pSubscriptionID));
StringCchCat(szQuery, MAX_QUERY_SIZE, strSubscriptionID);
hr = gpIEventSystem->Remove(
PROGID_EventSubscription,
szQuery,
&errorIndex
);
FreeStr(strSubscriptionID);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensSubscriptionis(%d) failed to Remove"
" - 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))
{
SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensSubscriptions(%d) failed to create "
"IEventSubscriptions - hr = <%x>\n", i, hr));
goto Cleanup;
}
AllocateBstrFromGuid(bstrSubscriptionID, *(gSensSubscriptions[i].pSubscriptionID));
hr = pIEventSubscription->put_SubscriptionID(bstrSubscriptionID);
ASSERT(SUCCEEDED(hr));
hr = pIEventSubscription->put_PublisherID(bstrPublisherID);
ASSERT(SUCCEEDED(hr));
hr = pIEventSubscription->put_SubscriberCLSID(bstrSubscriberCLSID);
ASSERT(SUCCEEDED(hr));
AllocateBstrFromString(bstrSubscriptionName, gSensSubscriptions[i].strSubscriptionName);
hr = pIEventSubscription->put_SubscriptionName(bstrSubscriptionName);
ASSERT(SUCCEEDED(hr));
AllocateBstrFromString(bstrMethodName, gSensSubscriptions[i].strMethodName);
hr = pIEventSubscription->put_MethodName(bstrMethodName);
ASSERT(SUCCEEDED(hr));
AllocateBstrFromGuid(bstrEventClassID, *(gSensSubscriptions[i].pEventClassID));
hr = pIEventSubscription->put_EventClassID(bstrEventClassID);
ASSERT(SUCCEEDED(hr));
AllocateBstrFromGuid(bstrInterfaceID, *(gSensSubscriptions[i].pInterfaceID));
hr = pIEventSubscription->put_InterfaceID(bstrInterfaceID);
ASSERT(SUCCEEDED(hr));
if (gSensSubscriptions[i].bPublisherPropertyPresent == TRUE)
{
if (NULL != (gSensSubscriptions[i].pPropertyEventClassIDValue))
{
// Create the Query string.
StringCchCopy(szQuery, MAX_QUERY_SIZE, gSensSubscriptions[i].strPropertyEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, *(gSensSubscriptions[i].pPropertyEventClassIDValue));
StringCchCat(szQuery, MAX_QUERY_SIZE, strEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR(" AND "));
StringCchCat(szQuery, MAX_QUERY_SIZE, gSensSubscriptions[i].strPropertyMethodName);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR("=\'"));
StringCchCat(szQuery, MAX_QUERY_SIZE, gSensSubscriptions[i].strPropertyMethodNameValue);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR("\'"));
AllocateBstrFromString(bstrPublisherPropertyName, SENS_BSTR("Criteria"));
AllocateBstrFromString(bstrPublisherPropertyValue, szQuery);
InitializeBstrVariant(&variantPublisherPropertyValue, bstrPublisherPropertyValue);
hr = pIEventSubscription->PutPublisherProperty(
bstrPublisherPropertyName,
&variantPublisherPropertyValue
);
ASSERT(SUCCEEDED(hr));
SensPrintA(SENS_INFO, (SENS_SETUP "PutPublisherProperty(Criteria) returned 0x%x\n", hr));
FreeStr(strEventClassID);
FreeBstr(bstrPublisherPropertyName);
FreeBstr(bstrPublisherPropertyValue);
}
else
{
//
// We are dealing with the "ANY" subscription of SENS.
//
// Create the Query string.
StringCchCopy(szQuery, MAX_QUERY_SIZE, gSensSubscriptions[i].strPropertyEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_NETWORK);
StringCchCat(szQuery, MAX_QUERY_SIZE, strEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR(" OR "));
FreeStr(strEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, gSensSubscriptions[i].strPropertyEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_LOGON);
StringCchCat(szQuery, MAX_QUERY_SIZE, strEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR(" OR "));
FreeStr(strEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, gSensSubscriptions[i].strPropertyEventClassID);
StringCchCat(szQuery, MAX_QUERY_SIZE, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_ONNOW);
StringCchCat(szQuery, MAX_QUERY_SIZE, strEventClassID);
FreeStr(strEventClassID);
AllocateBstrFromString(bstrPublisherPropertyName, SENS_BSTR("Criteria"));
AllocateBstrFromString(bstrPublisherPropertyValue, szQuery);
InitializeBstrVariant(&variantPublisherPropertyValue, bstrPublisherPropertyValue);
hr = pIEventSubscription->PutPublisherProperty(
bstrPublisherPropertyName,
&variantPublisherPropertyValue
);
ASSERT(SUCCEEDED(hr));
SensPrintA(SENS_INFO, (SENS_SETUP "PutPublisherProperty(Criteria) returned 0x%x\n", hr));
FreeBstr(bstrPublisherPropertyName);
FreeBstr(bstrPublisherPropertyValue);
}
}
FreeBstr(bstrSubscriptionID);
FreeBstr(bstrSubscriptionName);
FreeBstr(bstrMethodName);
FreeBstr(bstrEventClassID);
FreeBstr(bstrInterfaceID);
hr = gpIEventSystem->Store(bstrPROGID_EventSubscription, pIEventSubscription);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensSubscriptions(%d) failed to Store"
" - hr = <%x>\n", i, hr));
goto Cleanup;
}
pIEventSubscription->Release();
pIEventSubscription = NULL;
} // for loop
Cleanup:
//
// Cleanup
//
if (pIEventSubscription)
{
pIEventSubscription->Release();
}
FreeBstr(bstrPublisherID);
FreeBstr(bstrSubscriberCLSID);
FreeBstr(bstrPROGID_EventSubscription);
FreeStr(strGuid);
return (hr);
}
HRESULT
RegisterSensTypeLibraries(
BOOL bUnregister
)
/*++
Routine Description:
Register/Unregister the Type Libraries of SENS.
Arguments:
bUnregister - If TRUE, then unregister all subscriptions of SENS.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
HRESULT hr;
UINT uiLength;
TCHAR buffer[MAX_PATH+1+sizeof(SENS_BINARYA)+1]; // +1 for '\'
hr = S_OK;
uiLength = 0;
//
// Get the Full path name to the SENS TLB (which is a resource in SENS.EXE)
//
uiLength = GetSystemDirectory(
buffer,
MAX_PATH
);
if (uiLength == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
SensPrintA(SENS_ERR, (SENS_SETUP "GetSystemDirectory(%s) failed - hr = <%x>\n",
SENS_TLBA, hr));
goto Cleanup;
}
StringCbCat(buffer, sizeof(buffer), SENS_STRING("\\") SENS_TLB);
hr = LoadTypeLibEx(
buffer,
REGKIND_NONE,
&gpITypeLib
);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "LoadTypeLib(%s) failed "
" - hr = <%x>\n", SENS_TLBA, hr));
goto Cleanup;
}
//
// Ensure that the TypeLib is (un)registered
//
if (bUnregister)
{
hr = UnRegisterTypeLib(
LIBID_SensEvents,
MAJOR_VER,
MINOR_VER,
DEFAULT_LCID,
SYS_WIN32
);
}
else
{
hr = RegisterTypeLib(
gpITypeLib,
buffer,
NULL
);
}
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "%sRegisterTypeLib(%s) failed "
" - hr = <%x>\n", (bUnregister ? "Un" : ""), SENS_TLBA, hr));
}
Cleanup:
//
// Cleanup
//
return (hr);
}
HRESULT
RegisterSensCLSID(
REFIID clsid,
TCHAR* strSubscriberName,
BOOL bUnregister
)
/*++
Routine Description:
Register/Unregister the CLSID of SENS.
Arguments:
clsid - CLSID of the Subscriber for LCE events.
strSubscriberName - Name of the Subscriber.
bUnregister - If TRUE, then unregister the CLSID of SENS.
Notes:
This function also registers SENS to receive IE5's WININET events.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
HRESULT hr;
HMODULE hModule;
HKEY appidKey;
HKEY clsidKey;
HKEY serverKey;
WCHAR *szCLSID;
WCHAR *szCLSID2;
WCHAR *szLIBID;
TCHAR *szCLSID_t;
TCHAR *szCLSID2_t;
TCHAR *szLIBID_t;
TCHAR *szFriendlyName;
TCHAR szPath[MAX_PATH+1+sizeof(SENS_BINARYA)+1]; // +1 for '\'
UINT uiLength;
DWORD dwDisposition;
LONG lResult;
hr = S_OK;
appidKey = NULL;
clsidKey = NULL;
serverKey = NULL;
szCLSID = NULL;
szCLSID2 = NULL;
szLIBID = NULL;
szCLSID_t = NULL;
szCLSID2_t = NULL;
szLIBID_t = NULL;
uiLength = 0;
dwDisposition = 0x0;
szFriendlyName = strSubscriberName;
//
// Get the Full path name to the SENS executable
//
uiLength = GetSystemDirectory(
szPath,
MAX_PATH
);
if (uiLength == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
SensPrintA(SENS_ERR, (SENS_SETUP "GetSystemDirectory(%s) failed - hr = <%x>\n",
SENS_BINARYA, hr));
goto Cleanup;
}
StringCbCat(szPath, sizeof(szPath), SENS_STRING("\\") SENS_BINARY);
//
// Convert the CLSID into a WCHAR.
//
hr = StringFromCLSID(clsid, &szCLSID);
if (FAILED(hr))
{
goto Cleanup;
}
if (bUnregister == FALSE)
{
hr = StringFromCLSID(LIBID_SensEvents, &szLIBID);
if (FAILED(hr))
{
goto Cleanup;
}
}
szCLSID_t = szCLSID;
szLIBID_t = szLIBID;
// 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"),
szPath,
&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);
// Register APPID.
hr = CreateKey(
HKEY_CLASSES_ROOT,
appidKeyName,
szFriendlyName,
&appidKey
);
if (FAILED(hr))
{
goto Cleanup;
}
// Under AppId\{clsid} key, create a named value [LocalService = "SENS"]
hr = CreateNamedValue(appidKey, SENS_STRING("LocalService"), SENS_STRING("SENS"));
if (FAILED(hr))
{
goto Cleanup;
}
Cleanup:
//
// Cleanup
//
CoTaskMemFree(szCLSID);
CoTaskMemFree(szLIBID);
if (clsidKey != NULL)
{
RegCloseKey(clsidKey);
}
if (appidKey != NULL)
{
RegCloseKey(appidKey);
}
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
CreateNamedDwordValue(
HKEY hKey,
const TCHAR* title,
DWORD dwValue
)
/*++
Routine Description:
Create a named DWORD value under a key
Arguments:
hKey - Handle to the parent Key.
title - Name of the Value to create.
dwValue - 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_DWORD, // Value Type
(BYTE*) &dwValue, // Address of Value data
sizeof(DWORD) // 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);
}
HRESULT
SensConfigureEventSystem(
BOOL bUnregister
)
/*++
Routine Description:
As of NTbuild 1750, EventSystem is not auto-configured. So, SENS does
the work of configuring EventSystem.
Arguments:
bUnregister - If TRUE, then install EventSystem.
Notes:
o This is a dummy call on NT4 because we don't need to configure
EventSystem on NT4. IE5 setup (Webcheck.dll) configures LCE.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
return S_OK;
}
HRESULT
SensUpdateVersion(
BOOL bUnregister
)
/*++
Routine Description:
Update the version of SENS in the registry.
Arguments:
bUnregister - usual.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
HRESULT hr;
HKEY hKeySens;
LONG RegStatus;
DWORD dwConfigured;
hr = S_OK;
hKeySens = NULL;
RegStatus = ERROR_SUCCESS;
RegStatus = RegOpenKeyEx(
HKEY_LOCAL_MACHINE, // Handle of the key
SENS_REGISTRY_KEY, // String which represents the sub-key to open
0, // Reserved (MBZ)
KEY_ALL_ACCESS, // Security Access mask
&hKeySens // Returned HKEY
);
if (RegStatus != ERROR_SUCCESS)
{
SensPrintA(SENS_ERR, (SENS_SETUP "RegOpenKeyEx(Sens) returned %d.\n", RegStatus));
hr = HRESULT_FROM_WIN32(RegStatus);
goto Cleanup;
}
if (TRUE == bUnregister)
{
dwConfigured = CONFIG_VERSION_NONE;
}
else
{
dwConfigured = CONFIG_VERSION_CURRENT;
}
// Update registry to reflect that SENS is now configured.
RegStatus = RegSetValueEx(
hKeySens, // Key to set Value for.
IS_SENS_CONFIGURED, // Value to set
0, // Reserved
REG_DWORD, // Value Type
(BYTE*) &dwConfigured,// Address of Value data
sizeof(DWORD) // Size of Value
);
if (RegStatus != ERROR_SUCCESS)
{
SensPrintA(SENS_ERR, (SENS_SETUP "RegSetValueEx(IS_SENS_CONFIGURED) failed with 0x%x\n", RegStatus));
hr = HRESULT_FROM_WIN32(RegStatus);
goto Cleanup;
}
SensPrintA(SENS_INFO, (SENS_SETUP "SENS is now configured successfully. "
"Registry updated to 0x%x.\n", dwConfigured));
Cleanup:
//
// Cleanup
//
if (hKeySens)
{
RegCloseKey(hKeySens);
}
return hr;
}