2275 lines
56 KiB
C++
2275 lines
56 KiB
C++
/*++
|
||
|
||
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
|