Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2274 lines
56 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
#if !defined(SENS_CHICAGO)
//
// 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"));
}
#endif // SENS_CHICAGO
//
// 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));
#if !defined(SENS_CHICAGO)
#if defined(SENS_NT4)
//
// Register SENS as a service with SCM.
//
hr = RegisterSensAsService(bUnregister);
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS as a Service"
" - hr = <%x>\n", bUnregister ? "un" : "", hr));
goto Cleanup;
}
SensPrintA(SENS_INFO, (SENS_SETUP "%segistered SENS as a Service.\n",
bUnregister ? "Unr" : "R", hr));
#endif // SENS_NT4
//
// 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"));
}
#endif // SENS_CHICAGO
//
// 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
wcscpy(szQuery, SENS_BSTR("EventClassID"));
wcscat(szQuery, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, *(gSensEventClasses[i].pEventClassID));
wcscat(szQuery, strEventClassID);
wcscat(szQuery, SENS_BSTR(""));
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
wcscpy(szQuery, SENS_BSTR("SubscriptionID"));
wcscat(szQuery, SENS_BSTR("="));
AllocateStrFromGuid(strSubscriptionID, *(gSensSubscriptions[i].pSubscriptionID));
wcscat(szQuery, 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.
wcscpy(szQuery, gSensSubscriptions[i].strPropertyEventClassID);
wcscat(szQuery, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, *(gSensSubscriptions[i].pPropertyEventClassIDValue));
wcscat(szQuery, strEventClassID);
wcscat(szQuery, SENS_BSTR(" AND "));
wcscat(szQuery, gSensSubscriptions[i].strPropertyMethodName);
wcscat(szQuery, SENS_BSTR("=\'"));
wcscat(szQuery, gSensSubscriptions[i].strPropertyMethodNameValue);
wcscat(szQuery, 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.
wcscpy(szQuery, gSensSubscriptions[i].strPropertyEventClassID);
wcscat(szQuery, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_NETWORK);
wcscat(szQuery, strEventClassID);
wcscat(szQuery, SENS_BSTR(" OR "));
FreeStr(strEventClassID);
wcscat(szQuery, gSensSubscriptions[i].strPropertyEventClassID);
wcscat(szQuery, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_LOGON);
wcscat(szQuery, strEventClassID);
wcscat(szQuery, SENS_BSTR(" OR "));
FreeStr(strEventClassID);
wcscat(szQuery, gSensSubscriptions[i].strPropertyEventClassID);
wcscat(szQuery, SENS_BSTR("="));
AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_ONNOW);
wcscat(szQuery, 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 '\'
WCHAR *bufferW;
hr = S_OK;
uiLength = 0;
bufferW = NULL;
//
// 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;
}
_tcscat(buffer, SENS_STRING("\\"));
_tcscat(buffer, SENS_TLB);
//
// Convert the string to UNICODE, if necessary
//
#if !defined(SENS_CHICAGO)
bufferW = buffer;
#else // SENS_CHICAGO
bufferW = SensAnsiStringToUnicode(buffer);
if (NULL == bufferW)
{
goto Cleanup;
}
#endif // SENS_CHICAGO
hr = LoadTypeLibEx(
bufferW,
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,
bufferW,
NULL
);
}
if (FAILED(hr))
{
SensPrintA(SENS_ERR, (SENS_SETUP "%sRegisterTypeLib(%s) failed "
" - hr = <%x>\n", (bUnregister ? "Un" : ""), SENS_TLBA, hr));
}
Cleanup:
//
// Cleanup
//
#if defined(SENS_CHICAGO)
if (bufferW != NULL)
{
delete bufferW;
}
#endif // SENS_CHICAGO
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;
}
_tcscat(szPath, SENS_STRING("\\"));
_tcscat(szPath, 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;
}
}
//
// 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"),
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;
}
#if !defined(SENS_CHICAGO)
// Under AppId\{clsid} key, create a named value [LocalService = "SENS"]
hr = CreateNamedValue(appidKey, SENS_STRING("LocalService"), SENS_STRING("SENS"));
if (FAILED(hr))
{
goto Cleanup;
}
#else // SENS_CHICAGO
// 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;
}
#endif // SENS_CHICAGO
Cleanup:
//
// Cleanup
//
CoTaskMemFree(szCLSID);
CoTaskMemFree(szLIBID);
if (clsidKey != NULL)
{
RegCloseKey(clsidKey);
}
if (appidKey != NULL)
{
RegCloseKey(appidKey);
}
#if defined(SENS_CHICAGO)
if (szCLSID_t != NULL)
{
delete szCLSID_t;
}
if (szLIBID_t != NULL)
{
delete szLIBID_t;
}
#endif // SENS_CHICAGO
return hr;
}
#if defined(SENS_NT4)
HRESULT
RegisterSensAsService(
BOOL bUnregister
)
/*++
Routine Description:
Configure SENS as a Win32 System service.
Arguments:
bUnregister - If TRUE, then unregister SENS as a service.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
HRESULT hr;
hr = S_OK;
if (bUnregister)
{
hr = RemoveService();
}
else
{
hr = InstallService();
}
return hr;
}
HRESULT
InstallService(
void
)
/*++
Routine Description:
Install SENS as a service with the Service Control Manager.
Arguments:
None.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
HRESULT hr;
TCHAR szPath[MAX_PATH+1+sizeof(SENS_BINARYA)+1]; // +1 for '\'
LPTSTR pFilePart;
UINT uiLength;
SC_HANDLE hSCM;
SC_HANDLE hSens;
hr = S_OK;
pFilePart = NULL;
uiLength = 0;
hSCM = NULL;
hSens = NULL;
//
// 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;
}
_tcscat(szPath, SENS_STRING("\\"));
_tcscat(szPath, SENS_BINARY);
//
// Register ourselves with the SCM
//
// Open the SCM for the local machine.
hSCM = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (NULL == hSCM)
{
hr = HRESULT_FROM_WIN32(GetLastError());
SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("OpenSCManager(%s) failed - hr = <%x>\n"),
SENS_SERVICE, hr));
goto Cleanup;
}
hSens = CreateService(
hSCM, // Handle to SCM
SENS_SERVICE, // Name of the service executable
SENS_DISPLAY_NAME, // Service Display name
SERVICE_ALL_ACCESS, // Access to the service
SERVICE_WIN32_OWN_PROCESS, // Type of the service
SERVICE_DEMAND_START, // Start type of the service
SERVICE_ERROR_NORMAL, // Severity of the error during startup
szPath, // Binary path name
SENS_SERVICE_GROUP, // Load ordering group
NULL, // No tag identifier
SENS_STRING("EventSystem\0"), // Dependencies
NULL, // LocalSystem account
NULL // No password
);
if (NULL == hSens)
{
if (GetLastError() != ERROR_SERVICE_EXISTS)
{
hr = HRESULT_FROM_WIN32(GetLastError());
SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("CreateService(%s) failed - hr = <%x>\n"),
SENS_SERVICE, hr));
}
else
{
SensPrint(SENS_WARN, (SENS_SETUPW SENS_STRING("SENS service is already installed.\n")));
BOOL bRetValue;
//
// Get a handle to SCM
//
hSens = OpenService(
hSCM,
SENS_SERVICE,
SERVICE_ALL_ACCESS
);
if (NULL == hSens)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}
//
// Mark the service to demand-start by default.
// NULL parameter implies no change.
//
bRetValue = ChangeServiceConfig(
hSens, // Handle to service
SERVICE_NO_CHANGE, // Type of service
SERVICE_DEMAND_START, // When to start service
SERVICE_NO_CHANGE, // Severity if service fails to start
NULL, // Pointer to service binary file name
NULL, // Pointer to load ordering group name
NULL, // Pointer to variable to get tag identifier
NULL, // Pointer to array of dependency names
NULL, // Pointer to account name of service
NULL, // Pointer to password for service account
NULL // Pointer to display name
);
if (FALSE == bRetValue)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("ChangeServiceConfig(%s)")
SENS_STRING(" returned hr - <%x>\n"), SENS_SERVICE, hr));
}
goto Cleanup;
}
SensPrint(SENS_INFO, (SENS_SETUPW SENS_STRING("SENS service successfully installed.\n")));
Cleanup:
//
// Cleanup
//
if (hSens != NULL)
{
//
// Give everyone the ability to start the service.
//
hr = SetServiceWorldAccessMask(hSens, SERVICE_START);
SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("SerServiceWorldAccessMask(%s)")
SENS_STRING(" returned hr - <%x>\n"), SENS_SERVICE, hr));
CloseServiceHandle(hSens);
}
if (hSCM != NULL)
{
CloseServiceHandle(hSCM);
}
return hr;
}
HRESULT
RemoveService(
void
)
/*++
Routine Description:
Remove SENS as a service.
Arguments:
None.
Return Value:
S_OK, if successful
hr, otherwise
--*/
{
HRESULT hr;
SC_HANDLE hSCM;
SC_HANDLE hSens;
BOOL bSuccess;
SERVICE_STATUS SvcStatus;
hr = S_OK;
hSCM = NULL;
hSens = NULL;
bSuccess = FALSE;
//
// Unregister ourselves from the SCM
//
// Open the SCM for the local machine.
hSCM = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (NULL == hSCM)
{
hr = HRESULT_FROM_WIN32(GetLastError());
SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("OpenSCManager() failed - hr = <%x>\n"), hr));
goto Cleanup;
}
hSens = OpenService(
hSCM,
SENS_SERVICE,
SERVICE_ALL_ACCESS
);
if (NULL == hSens)
{
hr = HRESULT_FROM_WIN32(GetLastError());
SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("OpenService(%s) failed - hr = <%x>\n"),
SENS_SERVICE, hr));
goto Cleanup;
}
//
// Try to stop the service
//
bSuccess = ControlService(
hSens,
SERVICE_CONTROL_STOP,
&SvcStatus
);
if (bSuccess == TRUE)
{
SensPrint(SENS_INFO, (SENS_SETUPW SENS_STRING("Stopping %s."), SENS_SERVICE));
do
{
Sleep(1000);
if (SvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
SensPrint(SENS_INFO, (SENS_STRING(".")));
}
else
{
SensPrint(SENS_INFO, (SENS_STRING("\n")));
break;
}
}
while (QueryServiceStatus(hSens, &SvcStatus));
if (SvcStatus.dwCurrentState == SERVICE_STOPPED)
{
SensPrint(SENS_INFO, (SENS_SETUPW SENS_STRING("\n%s stopped.\n"), SENS_SERVICE));
}
else
{
SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("\n%s failed to stop.\n"), SENS_SERVICE));
}
}
//
// Now, remove the service
//
if (DeleteService(hSens))
{
SensPrint(SENS_INFO, (SENS_SETUPW SENS_STRING("%s removed.\n"), SENS_SERVICE));
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("%s removal failed.\n"), SENS_SERVICE));
}
Cleanup:
//
// Cleanup
//
if (hSens != NULL)
{
CloseServiceHandle(hSens);
}
if (hSCM != NULL)
{
CloseServiceHandle(hSCM);
}
return hr;
}
HRESULT
SetServiceWorldAccessMask(
SC_HANDLE hService,
DWORD dwAccessMask
)
/*++
Routine Description:
Add the access rights specified in the dwAccessMask to Everyone (World)
with respect to this service. This was written to add SERVICE_START right
to Everyone wrt SENS.
Arguments:
hService - The service in question.
dwAccessMask - The desired access rights to be set.
Notes:
a. This code assumes that the WorldSid is present in the DACL of SENS
service. This is true for NT4.
b. This a security hole. This security hole is not going to be plugged
in future Service Packs of NT4 since some applications will break.
c. This code needs to be modified to make it work on NT5.
Return Value:
S_OK, if successful.
HRESULT, on failure.
--*/
{
int i;
PSID pWorldSid;
SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
DWORD dwError;
DWORD dwSize;
PSECURITY_DESCRIPTOR pSD;
PACL pDacl;
BOOL bStatus;
BOOL bDaclPresent;
BOOL bDaclDefaulted;
PACCESS_ALLOWED_ACE pAce;
i = 0;
pWorldSid = NULL;
pSD = NULL;
pDacl = NULL;
dwSize = 0x0;
dwError = ERROR_SUCCESS;
bStatus = FALSE;
bDaclPresent = FALSE;
bDaclDefaulted = FALSE;
pAce = NULL;
//
// Allocate WorldSid
//
bStatus = AllocateAndInitializeSid(
&WorldAuthority, // Pointer to identifier authority
1, // Count of subauthority
SECURITY_WORLD_RID, // Subauthority 0
0, // Subauthority 1
0, // Subauthority 2
0, // Subauthority 3
0, // Subauthority 4
0, // Subauthority 5
0, // Subauthority 6
0, // Subauthority 7
&pWorldSid // pointer to pointer to SID
);
if (FALSE == bStatus)
{
dwError = GetLastError();
SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): AllocateAndInitiali"
"zeSid() failed with %d.\n", dwError));
goto Cleanup;
}
//
// Figure out how much buffer is needed for holding the service's
// Security Descriptor (SD).
//
// NOTE: We pass &pSD instead of pSD because this parameter should
// not be NULL. For this call to QueryServiceObjectSecurity()
// we just need to pass some non-zero and valid buffer.
//
bStatus = QueryServiceObjectSecurity(
hService, // Handle of the service
DACL_SECURITY_INFORMATION, // Type of info requested
&pSD, // Address of Security descriptor
0, // Size of SD buffer
&dwSize // Size of buffer needed
);
if ( (TRUE == bStatus)
|| (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
dwError = GetLastError();
SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): QueryServiceObject"
"Security() returned unexpected result - %d.\n", dwError));
goto Cleanup;
}
//
// Allocate the SD
//
pSD = (PSECURITY_DESCRIPTOR) new char[dwSize];
if (NULL == pSD)
{
dwError = ERROR_OUTOFMEMORY;
SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): Failed to allocate"
"memory for a Security Descriptor.\n"));
goto Cleanup;
}
//
// Now, we are ready to get the service's SD.
//
bStatus = QueryServiceObjectSecurity(
hService, // Handle of the service
DACL_SECURITY_INFORMATION, // Type of info requested
pSD, // Address of Security descriptor
dwSize, // Size of SD buffer
&dwSize // Size of buffer needed
);
if (FALSE == bStatus)
{
dwError = GetLastError();
ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): QueryServiceObject"
"Security() failed with %d.\n", dwError));
goto Cleanup;
}
//
// Get the DACL from SD, if present.
//
bStatus = GetSecurityDescriptorDacl(
pSD, // Address of SD
&bDaclPresent, // Address of flag for presence of DACL
&pDacl, // Address of pointer to DACL
&bDaclDefaulted // Address of flag that indicates if
); // DACL was defaulted.
if (FALSE == bStatus)
{
dwError = GetLastError();
SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): GetSecurityDescriptor"
"Dacl() failed with %d.\n", dwError));
goto Cleanup;
}
//
// For a service, we always expect to see a DACL.
//
ASSERT(bDaclPresent && (pDacl != NULL));
if ( (FALSE == bDaclPresent)
|| (NULL == pDacl))
{
dwError = E_UNEXPECTED;
SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): DACL is not present"
"or DACL is NULL. Returning %d.\n", dwError));
goto Cleanup;
}
//
// Find the WorldSid ACE in the ACL and update it's Mask.
//
for (i = 0; i < pDacl->AceCount; i++)
{
bStatus = GetAce(
pDacl, // pointer to ACL
i, // index of ACE to retrieve
(LPVOID*) &pAce // pointer to pointer to ACE
);
if (FALSE == bStatus)
{
dwError = GetLastError();
SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): GetAce()"
"failed with %d.\n", dwError));
goto Cleanup;
}
if (EqualSid(pWorldSid, &(pAce->SidStart)))
{
pAce->Mask |= dwAccessMask;
}
} // for ()
//
// Set the new SD on the service handle
//
bStatus = SetServiceObjectSecurity(
hService, // Handle to the service.
DACL_SECURITY_INFORMATION, // Type of info being set
pSD // Address of the new SD
);
if (FALSE == bStatus)
{
dwError = GetLastError();
SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): SetServiceObject"
"Security() failed with %d.\n", dwError));
goto Cleanup;
}
Cleanup:
//
// Cleanup
//
if (NULL != pWorldSid)
{
FreeSid(pWorldSid);
}
if (NULL != pSD)
{
delete pSD;
}
return HRESULT_FROM_WIN32(dwError);
}
void CALLBACK
MarkSensAsDemandStart(
HWND hwnd,
HINSTANCE hinst,
LPSTR lpszCmdLine,
int nCmdShow
)
/*++
Routine Description:
A function compatible with RunDll32 that will mark SENS as manual start.
Arguments:
hwnd - Window handle that should be used as the owner window for
any windows this DLL creates.
hinst - This DLL's instance handle
lpszCmdLine - ASCII command line the DLL should parse
nCmdShow - Describes how the DLL's windows should be displayed
Return Value:
None.
--*/
{
SC_HANDLE hSCM;
SC_HANDLE hSens;
BOOL bStatus;
DWORD dwError;
SERVICE_STATUS ServiceStatus;
bStatus = FALSE;
dwError = ERROR_SUCCESS;
#ifdef DBG
EnableDebugOutputIfNecessary();
#endif // DBG
hSCM = OpenSCManager(
NULL, // Local machine
NULL, // Default database - SERVICES_ACTIVE_DATABASE
SC_MANAGER_ALL_ACCESS // NT4 NOTE: Only for Administrators.
);
if (NULL == hSCM)
{
dwError = GetLastError();
SensPrintA(SENS_ERR, (SENS_SETUP "OpenSCManager() failed with 0x%x\n", dwError));
goto Cleanup;
}
//
// Get a handle to SCM
//
hSens = OpenService(
hSCM, // Handle to SCM database
SENS_SERVICE, // Name of the service in question
SERVICE_ALL_ACCESS // Type of access requested to the service
);
if (NULL == hSens)
{
dwError = GetLastError();
SensPrintA(SENS_ERR, (SENS_SETUP "OpenService() failed with 0x%x\n", dwError));
goto Cleanup;
}
//
// Mark the service to Manual. NULL parameter implies no change.
//
bStatus = ChangeServiceConfig(
hSens, // Handle to service
SERVICE_NO_CHANGE, // Type of service
SERVICE_DEMAND_START, // When to start service
SERVICE_NO_CHANGE, // Severity if service fails to start
NULL, // Pointer to service binary file name
NULL, // Pointer to load ordering group name
NULL, // Pointer to variable to get tag identifier
NULL, // Pointer to array of dependency names
NULL, // Pointer to account name of service
NULL, // Pointer to password for service account
NULL // Pointer to display name
);
if (FALSE == bStatus)
{
dwError = GetLastError();
SensPrintA(SENS_ERR, (SENS_SETUP "ChangeServiceConfig() failed with 0x%x\n", dwError));
goto Cleanup;
}
SensPrintA(SENS_ERR, (SENS_SETUP "SENS now marked as DEMAND START\n\n"));
Cleanup:
//
// Cleanup
//
if (NULL != hSCM)
{
CloseServiceHandle(hSCM);
}
if (NULL != hSens)
{
CloseServiceHandle(hSens);
}
}
#endif // SENS_NT4
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;
}
#if defined(SENS_CHICAGO)
extern "C" int APIENTRY
DllMain(
IN HINSTANCE hInstance,
IN DWORD dwReason,
IN LPVOID lpvReserved
)
/*++
Routine Description:
This routine will get called either when a process attaches to this dll
or when a process detaches from this dll.
Return Value:
TRUE - Initialization successfully occurred.
FALSE - Insufficient memory is available for the process to attach to
this dll.
--*/
{
BOOL bSuccess;
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
// Disable Thread attach/detach calls
bSuccess = DisableThreadLibraryCalls(hInstance);
ASSERT(bSuccess == TRUE);
break;
case DLL_PROCESS_DETACH:
break;
}
return(TRUE);
}
#endif // SENS_CHICAGO