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
|