You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1198 lines
29 KiB
1198 lines
29 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
|
|
Module Name:
|
|
|
|
senssvc.cxx
|
|
|
|
Abstract:
|
|
|
|
This file implements the Init/Uninit functionality of System Event
|
|
Notification service (SENS).
|
|
|
|
Author:
|
|
|
|
Gopal Parupudi <GopalP>
|
|
|
|
[Notes:]
|
|
|
|
optional-notes
|
|
|
|
Revision History:
|
|
|
|
GopalP 09-20-1997 Start.
|
|
|
|
--*/
|
|
|
|
|
|
#include <precomp.hxx>
|
|
|
|
|
|
#define MIN_CALL_THREADS 1
|
|
#define SENS_CLEANUP_TIMEOUT 15*1000 // Max wait
|
|
#define SENS_WAITFORINIT_TIMEOUT 30*1000 // 30 seconds max
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
IEventSystem *gpIEventSystem;
|
|
HANDLE ghSensHeap;
|
|
HANDLE ghSensStartedEvent;
|
|
CRITICAL_SECTION gSensLock;
|
|
DWORD gdwRegCO;
|
|
DWORD gdwLocked;
|
|
LPCLASSFACTORY gpChangeCF;
|
|
|
|
#ifdef DBG
|
|
DWORD gdwDebugOutputLevel;
|
|
#endif // DBG
|
|
|
|
//
|
|
// External Globals
|
|
//
|
|
|
|
// Common
|
|
extern LONG g_cFilterObj;
|
|
extern LONG g_cFilterLock;
|
|
extern LONG g_cSubChangeObj;
|
|
extern LONG g_cSubChangeLock;
|
|
extern LIST *gpReachList;
|
|
extern BOOL gbIpInitSuccessful;
|
|
extern BOOL gbIsRasInstalled;
|
|
extern long gdwLastLANTime;
|
|
extern long gdwLANState;
|
|
extern HANDLE ghReachTimer;
|
|
extern HANDLE ghMediaTimer;
|
|
extern long gdwLastWANTime;
|
|
extern long gdwWANState;
|
|
extern IF_STATE gIfState[MAX_IF_ENTRIES];
|
|
extern MIB_IPSTATS gIpStats;
|
|
extern SYSTEM_POWER_STATUS gSystemPowerState;
|
|
|
|
|
|
BOOL
|
|
SensInitialize(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main entry into SENS.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE, if successful.
|
|
|
|
FALSE, otherwise
|
|
|
|
--*/
|
|
{
|
|
BOOL bRetValue;
|
|
BOOL bComInitialized;
|
|
|
|
bRetValue = FALSE;
|
|
bComInitialized = FALSE;
|
|
|
|
#ifdef DBG
|
|
DWORD dwNow = GetTickCount();
|
|
EnableDebugOutputIfNecessary();
|
|
|
|
SensPrintA(SENS_INFO, ("[%d] Initializing SENS...\n", dwNow));
|
|
#endif // DBG
|
|
|
|
// This will Initialize COM on success.
|
|
if (FALSE == Init())
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] Init() failed.\n",
|
|
GetTickCount()));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
bComInitialized = TRUE;
|
|
|
|
//
|
|
// This will call CoRegisterClassObject and will help in service
|
|
// startup. So, call this before ConfigureSensIfNecessary()
|
|
//
|
|
if (FALSE == DoEventSystemSetup())
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] DoEventSystemSetup() failed.\n", GetTickCount()));
|
|
}
|
|
else
|
|
{
|
|
SensPrintA(SENS_INFO, ("[%d] DoEventSystemSetup() Succeeded.\n", GetTickCount()));
|
|
}
|
|
|
|
if (FALSE == ConfigureSensIfNecessary())
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] ConfigureSensIfNecessary() failed.\n", GetTickCount()));
|
|
}
|
|
else
|
|
{
|
|
SensPrintA(SENS_INFO, ("[%d] ConfigureSensIfNecessary() Succeeded.\n", GetTickCount()));
|
|
}
|
|
|
|
if (FALSE == DoWanSetup())
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] DoWanSetup() failed.\n", GetTickCount()));
|
|
}
|
|
else
|
|
{
|
|
SensPrintA(SENS_INFO, ("[%d] DoWanSetup() Succeeded.\n", GetTickCount()));
|
|
}
|
|
|
|
if (FALSE == DoLanSetup())
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] DoLanSetup() failed.\n", GetTickCount()));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
SensPrintA(SENS_INFO, ("[%d] DoLanSetup() Succeeded.\n", GetTickCount()));
|
|
|
|
if (FALSE == DoRpcSetup())
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] DoRpcSetup() failed.\n", GetTickCount()));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
SensPrintA(SENS_INFO, ("[%d] DoRpcSetup() Succeeded.\n", GetTickCount()));
|
|
|
|
bRetValue = TRUE;
|
|
|
|
SensPrintA(SENS_DBG, ("[%d] Service start took %d msec.\n", GetTickCount(), (GetTickCount() - dwNow)));
|
|
|
|
Cleanup:
|
|
//
|
|
// Cleanup
|
|
//
|
|
|
|
if (bComInitialized)
|
|
{
|
|
//
|
|
// This thread (service start) will exit shortly after we return. Our event system
|
|
// instance and other COM registrations are kept alive by the main svchost thread
|
|
// which is initialized MTA.
|
|
//
|
|
CoUninitialize();
|
|
}
|
|
|
|
return bRetValue;
|
|
}
|
|
|
|
|
|
inline void
|
|
InitializeSensGlobals(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the global variables. This is needed if we are to run
|
|
within svchost.exe.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
Some of the SENS globals are initialized during SensInitialize()
|
|
processing. Look at ServiceMain(), DoLanSetup(), DoWanSetup() etc.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Common across platforms
|
|
//
|
|
|
|
// Pointers
|
|
gpReachList = NULL;
|
|
gpIEventSystem = NULL;
|
|
gpSensCache = NULL;
|
|
gpChangeCF = NULL;
|
|
|
|
// Handles
|
|
ghSensHeap = NULL;
|
|
ghReachTimer = NULL;
|
|
ghSensFileMap = NULL;
|
|
ghSensStartedEvent = NULL;
|
|
// BOOLs
|
|
gbIpInitSuccessful = FALSE;
|
|
gbIsRasInstalled = FALSE;
|
|
gdwLocked = FALSE;
|
|
// DWORDs
|
|
gdwLastLANTime = 0x0;
|
|
gdwLANState = 0x0;
|
|
gdwLastWANTime = 0x0;
|
|
gdwWANState = 0x0;
|
|
gdwRegCO = 0x0;
|
|
g_cFilterObj = 0x0;
|
|
g_cFilterLock = 0x0;
|
|
g_cSubChangeObj = 0x0;
|
|
g_cSubChangeLock = 0x0;
|
|
gdwMediaSenseState = SENSSVC_START;
|
|
// Structures
|
|
memset(gIfState, 0x0, (sizeof(IF_STATE) * MAX_IF_ENTRIES));
|
|
memset(&gIpStats, 0x0, sizeof(MIB_IPSTATS));
|
|
memset(&gSystemPowerState, 0x0, sizeof(SYSTEM_POWER_STATUS));
|
|
memset(&gSensLock, 0x0, sizeof(CRITICAL_SECTION));
|
|
}
|
|
|
|
|
|
inline BOOL
|
|
Init(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Perform initialization at startup.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
This should be called early in SensInitialize().
|
|
|
|
Return Value:
|
|
|
|
TRUE, if successful.
|
|
|
|
FALSE, otherwise
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
BOOL bRetValue;
|
|
BOOL bComInitialized;
|
|
OSVERSIONINFO VersionInfo;
|
|
|
|
hr = S_OK;
|
|
bRetValue = FALSE;
|
|
bComInitialized = FALSE;
|
|
|
|
// Reset
|
|
InitializeSensGlobals();
|
|
|
|
//
|
|
// Initialize COM
|
|
//
|
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
ASSERT(SUCCEEDED(hr));
|
|
if (FAILED(hr))
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] CoInitializeEx() failed, HRESULT=%x\n", GetTickCount(), hr));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
bComInitialized = TRUE;
|
|
|
|
// Use Default Process heap
|
|
ghSensHeap = GetProcessHeap();
|
|
if (ghSensHeap == NULL)
|
|
{
|
|
SensPrintToDebugger(SENS_DBG, ("[SENS] Failed to obtain ProcessHeap() - 0x%x!\n", GetLastError()));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Initialize Sens Global lock
|
|
InitializeCriticalSection(&gSensLock);
|
|
|
|
// Destination Reachability Event setup
|
|
if (FALSE == InitReachabilityEngine())
|
|
{
|
|
SensPrintToDebugger(SENS_DBG, ("[SENS] Failed to initialize reachability engine!\n"));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
gpIEventSystem = NULL;
|
|
|
|
if (FALSE == CreateSensCache())
|
|
{
|
|
SensPrintToDebugger(SENS_DBG, ("[SENS] Failed to create SENS Cache!\n"));
|
|
}
|
|
|
|
// Get a handle to the SensStartEvent.
|
|
// The event may also be created in the wlnotify dll (winlogon).
|
|
ghSensStartedEvent = CreateEvent(NULL, // Specific Security Attributes
|
|
TRUE, // Event is ManualReset
|
|
FALSE, // Initial state is not Signalled
|
|
SENS_STARTED_EVENT
|
|
);
|
|
if (ghSensStartedEvent == NULL)
|
|
{
|
|
SensPrintToDebugger(SENS_DBG, ("[SENS] Failed to Open SensStartedEvent - 0x%x!\n", GetLastError()));
|
|
}
|
|
else
|
|
{
|
|
SensPrint(SENS_INFO, (SENS_STRING("[%d] Successfully opened SensStartedEvent.\n"), GetTickCount()));
|
|
}
|
|
|
|
bRetValue = TRUE;
|
|
|
|
Cleanup:
|
|
//
|
|
// Cleanup stuff when we fail to Init properly.
|
|
//
|
|
if (FALSE == bRetValue)
|
|
{
|
|
// Release EventSystem
|
|
if (gpIEventSystem != NULL)
|
|
{
|
|
gpIEventSystem->Release();
|
|
gpIEventSystem = 0;
|
|
}
|
|
|
|
// Uninit COM because SensUninitialize() is not going to be called.
|
|
if (TRUE == bComInitialized)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
}
|
|
|
|
return bRetValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CreateSids(
|
|
PSID* ppsidBuiltInAdministrators,
|
|
PSID* ppsidSystem,
|
|
PSID* ppsidWorld
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates and return pointers to three SIDs one for each of World,
|
|
Local Administrators, and System.
|
|
|
|
|
|
Note:
|
|
|
|
IDENTICAL TO A FUNCTION IN OLE32\DCOMSS\WRAPPER\EPTS.C.
|
|
|
|
Arguments:
|
|
|
|
ppsidBuiltInAdministrators - Receives pointer to SID representing local
|
|
administrators;
|
|
ppsidSystem - Receives pointer to SID representing System;
|
|
ppsidWorld - Receives pointer to SID representing World.
|
|
|
|
Return Value:
|
|
|
|
BOOL indicating success (TRUE) or failure (FALSE).
|
|
|
|
Caller must free returned SIDs by calling FreeSid() for each returned
|
|
SID when this function return TRUE; pointers should be assumed garbage
|
|
when the function returns FALSE.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// An SID is built from an Identifier Authority and a set of Relative IDs
|
|
// (RIDs). The Authority of interest to us SECURITY_NT_AUTHORITY.
|
|
//
|
|
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
|
|
|
//
|
|
// Each RID represents a sub-unit of the authority. Local
|
|
// Administrators is in the "built in" domain. The other SIDs, for
|
|
// Authenticated users and system, is based directly off of the
|
|
// authority.
|
|
//
|
|
// For examples of other useful SIDs consult the list in
|
|
// \nt\public\sdk\inc\ntseapi.h.
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&NtAuthority,
|
|
2, // 2 sub-authorities
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0,0,0,0,0,0,
|
|
ppsidBuiltInAdministrators)) {
|
|
|
|
// error
|
|
|
|
} else if (!AllocateAndInitializeSid(&NtAuthority,
|
|
1, // 1 sub-authorities
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0,0,0,0,0,0,0,
|
|
ppsidSystem)) {
|
|
|
|
// error
|
|
|
|
FreeSid(*ppsidBuiltInAdministrators);
|
|
*ppsidBuiltInAdministrators = NULL;
|
|
|
|
} else if (!AllocateAndInitializeSid(&WorldAuthority,
|
|
1, // 1 sub-authority
|
|
SECURITY_WORLD_RID,
|
|
0,0,0,0,0,0,0,
|
|
ppsidWorld)) {
|
|
|
|
// error
|
|
|
|
FreeSid(*ppsidBuiltInAdministrators);
|
|
*ppsidBuiltInAdministrators = NULL;
|
|
|
|
FreeSid(*ppsidSystem);
|
|
*ppsidSystem = NULL;
|
|
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
PSECURITY_DESCRIPTOR
|
|
CreateSd(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates and return a SECURITY_DESCRIPTOR with a DACL granting
|
|
(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | SYNCHRONIZE) to World,
|
|
and GENERIC_ALL to Local Administrators and System.
|
|
|
|
Notes:
|
|
|
|
SIMILAR TO A FUNCTION IN OLE32\DCOMSS\WRAPPER\EPTS.C.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Pointer to the created SECURITY_DESCRIPTOR, or NULL if an error occurred.
|
|
|
|
Caller must free returned SECURITY_DESCRIPTOR back to process heap by
|
|
a call to HeapFree.
|
|
|
|
--*/
|
|
{
|
|
PSID psidWorld;
|
|
PSID psidBuiltInAdministrators;
|
|
PSID psidSystem;
|
|
|
|
if (!CreateSids(&psidBuiltInAdministrators,
|
|
&psidSystem,
|
|
&psidWorld)) {
|
|
|
|
// error
|
|
|
|
} else {
|
|
|
|
//
|
|
// Calculate the size of and allocate a buffer for the DACL, we need
|
|
// this value independently of the total alloc size for ACL init.
|
|
//
|
|
|
|
PSECURITY_DESCRIPTOR Sd = NULL;
|
|
ULONG AclSize;
|
|
|
|
//
|
|
// "- sizeof (ULONG)" represents the SidStart field of the
|
|
// ACCESS_ALLOWED_ACE. Since we're adding the entire length of the
|
|
// SID, this field is counted twice.
|
|
//
|
|
|
|
AclSize = sizeof (ACL) +
|
|
(3 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
|
|
GetLengthSid(psidWorld) +
|
|
GetLengthSid(psidBuiltInAdministrators) +
|
|
GetLengthSid(psidSystem);
|
|
|
|
Sd = (PSID)new char[SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize];
|
|
|
|
if (!Sd) {
|
|
|
|
// error
|
|
|
|
} else {
|
|
|
|
ACL *Acl;
|
|
|
|
Acl = (ACL *)((BYTE *)Sd + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
|
|
if (!InitializeAcl(Acl,
|
|
AclSize,
|
|
ACL_REVISION)) {
|
|
|
|
// error
|
|
|
|
} else if (!AddAccessAllowedAce(Acl,
|
|
ACL_REVISION,
|
|
SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
|
|
psidWorld)) {
|
|
|
|
// Failed to build the ACE granting "WORLD"
|
|
// (SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE) access.
|
|
|
|
} else if (!AddAccessAllowedAce(Acl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psidBuiltInAdministrators)) {
|
|
|
|
// Failed to build the ACE granting "Built-in Administrators"
|
|
// (GENERIC_ALL) access.
|
|
|
|
} else if (!AddAccessAllowedAce(Acl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psidSystem)) {
|
|
|
|
// Failed to build the ACE granting "System"
|
|
// GENERIC_ALL access.
|
|
|
|
} else if (!InitializeSecurityDescriptor(Sd,
|
|
SECURITY_DESCRIPTOR_REVISION)) {
|
|
|
|
// error
|
|
|
|
} else if (!SetSecurityDescriptorDacl(Sd,
|
|
TRUE,
|
|
Acl,
|
|
FALSE)) {
|
|
|
|
// error
|
|
|
|
} else {
|
|
FreeSid(psidWorld);
|
|
FreeSid(psidBuiltInAdministrators);
|
|
FreeSid(psidSystem);
|
|
|
|
return Sd;
|
|
}
|
|
|
|
delete (char *)Sd;
|
|
}
|
|
|
|
FreeSid(psidWorld);
|
|
FreeSid(psidBuiltInAdministrators);
|
|
FreeSid(psidSystem);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
RPC_ENTRY
|
|
SENS_CheckLocalCallback(
|
|
RPC_IF_HANDLE ifhandle,
|
|
void *Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
SENS runs in a shared service host which means it is possible for a
|
|
caller on another machine to call SENS. This is not expected and is
|
|
blocked by this callback routine in order to reduce the potential
|
|
attack surface of RPC.
|
|
|
|
Arguments:
|
|
|
|
ifhandle - interface this callback is registered with (ignored)
|
|
context - context to discover information about the caller (ignored)
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - caller allowed to call methods in the interface
|
|
other - caller is blocked
|
|
|
|
--*/
|
|
{
|
|
unsigned fLocal = FALSE;
|
|
|
|
if ( (RPC_S_OK == I_RpcBindingIsClientLocal(0, &fLocal))
|
|
&& (fLocal) )
|
|
{
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
return RPC_S_ACCESS_DENIED;
|
|
}
|
|
|
|
|
|
BOOL
|
|
DoRpcSetup(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Perform RPC server initialization.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE, if successful.
|
|
|
|
FALSE, otherwise
|
|
|
|
--*/
|
|
{
|
|
RPC_STATUS status;
|
|
BOOL fDontWait;
|
|
BOOL bRetValue;
|
|
PSECURITY_DESCRIPTOR psd;
|
|
|
|
status = RPC_S_OK;
|
|
fDontWait = TRUE;
|
|
bRetValue = FALSE;
|
|
|
|
// Make sure RPC allocates thread stacks of sufficient size.
|
|
status = RpcMgmtSetServerStackSize(2*4096);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
psd = CreateSd();
|
|
if (!psd)
|
|
{
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
status = RpcServerUseProtseqEp(
|
|
SENS_PROTSEQ,
|
|
RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
|
|
SENS_ENDPOINT,
|
|
psd // Security descriptor
|
|
);
|
|
|
|
delete (char *)psd;
|
|
|
|
if (RPC_S_DUPLICATE_ENDPOINT == status)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] DoRpcSetup(): Endpoint already created. Continuing!\n", GetTickCount()));
|
|
status = RPC_S_OK;
|
|
}
|
|
|
|
if (RPC_S_OK != status)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] DoRpcSetup(): RpcServerUseProtseqEp() returned 0x%x\n", GetTickCount(), status));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// On NT platforms, use auto-listen interfaces. We don't need to call
|
|
// RpcServerListen().
|
|
//
|
|
|
|
// SENS API interface
|
|
status = RpcServerRegisterIfEx(
|
|
SensApi_ServerIfHandle, // The interface
|
|
NULL, // MgrTypeUuid
|
|
NULL, // MgrEpv
|
|
RPC_IF_AUTOLISTEN, // Flags
|
|
RPC_C_LISTEN_MAX_CALLS_DEFAULT,// Max calls value
|
|
SENS_CheckLocalCallback // Security Callback function
|
|
);
|
|
if (RPC_S_OK != status)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] DoRpcSetup(): RpcServerRegisterIfEx(1) returned 0x%x\n", GetTickCount(), status));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// SensNotify interface
|
|
status = RpcServerRegisterIfEx(
|
|
SENSNotify_ServerIfHandle, // The interface
|
|
NULL, // MgrTypeUuid
|
|
NULL, // MgrEpv
|
|
RPC_IF_AUTOLISTEN, // Flags
|
|
RPC_C_LISTEN_MAX_CALLS_DEFAULT,// Max calls value
|
|
SENS_CheckLocalCallback // Security Callback function
|
|
);
|
|
if (RPC_S_OK != status)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] DoRpcSetup(): RpcServerRegisterIfEx(2) returned 0x%x\n", GetTickCount(), status));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// All's well.
|
|
bRetValue = TRUE;
|
|
|
|
Cleanup:
|
|
//
|
|
// Cleanup
|
|
//
|
|
return bRetValue;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
SensUninitialize(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Perform any cleanup.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE, if successful.
|
|
|
|
FALSE, otherwise
|
|
|
|
--*/
|
|
{
|
|
int err;
|
|
RPC_STATUS status;
|
|
BOOL bRetValue;
|
|
HRESULT hr;
|
|
DWORD dwNow;
|
|
|
|
bRetValue = TRUE;
|
|
hr = S_OK;
|
|
dwNow = GetTickCount();
|
|
|
|
SensPrintA(SENS_ERR, ("[%d] Begin stopping of SENS Service...\n", dwNow));
|
|
|
|
// Unregister media sense notifications.
|
|
if (FALSE == MediaSenseUnregister())
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): MediaSenseUnregister() failed.\n", GetTickCount()));
|
|
}
|
|
else
|
|
{
|
|
SensPrintA(SENS_INFO, ("[%d] SensUninitialize(): MediaSenseUnregister() succeeded.\n", GetTickCount()));
|
|
}
|
|
|
|
// Unregister the RPC interface #1
|
|
status = RpcServerUnregisterIf(
|
|
SensApi_ServerIfHandle,
|
|
NULL, // MgrTypeUuid
|
|
FALSE // WaitForCallsToComplete
|
|
);
|
|
ASSERT(status == RPC_S_OK);
|
|
if (RPC_S_OK != status)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): RpcServerUnegisterIf(1) returned 0x%x\n", GetTickCount(), status));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
SensPrintA(SENS_INFO, ("[%d] SensUninitialize(): RpcServerUnregisterIf(1) succeeded.\n", GetTickCount()));
|
|
|
|
// Unregister the RPC interface #2
|
|
status = RpcServerUnregisterIf(
|
|
SENSNotify_ServerIfHandle,
|
|
NULL, // MgrTypeUuid
|
|
FALSE // WaitForCallsToComplete
|
|
);
|
|
ASSERT(status == RPC_S_OK);
|
|
if (RPC_S_OK != status)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): RpcServerUnegisterIf(2) returned 0x%x\n", GetTickCount(), status));
|
|
bRetValue = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
SensPrintA(SENS_INFO, ("[%d] SensUninitialize(): RpcServerUnregisterIf(2) succeeded.\n", GetTickCount()));
|
|
|
|
//
|
|
// Remove our classfactory from COM's cache.
|
|
//
|
|
if (0x0 != gdwRegCO)
|
|
{
|
|
hr = CoRevokeClassObject(gdwRegCO);
|
|
}
|
|
|
|
if (NULL != gpChangeCF)
|
|
{
|
|
gpChangeCF->Release();
|
|
}
|
|
|
|
//
|
|
// EventSystem specific cleanup.
|
|
//
|
|
if (gpIEventSystem)
|
|
{
|
|
gpIEventSystem->Release();
|
|
}
|
|
|
|
//
|
|
// Stop Reachability polling
|
|
//
|
|
StopReachabilityEngine();
|
|
|
|
//
|
|
// Empty the destination reachability list
|
|
//
|
|
if (NULL != gpReachList)
|
|
{
|
|
delete gpReachList;
|
|
|
|
gpReachList = NULL;
|
|
}
|
|
|
|
//
|
|
// Destroy SENS Cache
|
|
//
|
|
DeleteSensCache();
|
|
|
|
// Cleanup started event handle
|
|
ResetEvent(ghSensStartedEvent);
|
|
CloseHandle(ghSensStartedEvent);
|
|
ghSensStartedEvent = 0;
|
|
|
|
// Delete Global SENS lock
|
|
DeleteCriticalSection(&gSensLock);
|
|
|
|
bRetValue = TRUE;
|
|
|
|
SensPrintToDebugger(SENS_DBG, ("\n[SENS] [%d] Service Stopped.\n\n", GetTickCount()));
|
|
|
|
Cleanup:
|
|
//
|
|
// Cleanup
|
|
//
|
|
|
|
// Cleanup Winsock.
|
|
err = WSACleanup();
|
|
if (err != 0)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): WSACleanup() returned GLE of %d\n", GetTickCount(),
|
|
WSAGetLastError()));
|
|
}
|
|
|
|
SensPrintA(SENS_INFO, ("[%d] Stopping SENS took %d msec.\n\n", GetTickCount(), (GetTickCount()-dwNow)));
|
|
|
|
return bRetValue;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
DoEventSystemSetup(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Perform the EventSystem specific initialization here.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE, if successful.
|
|
|
|
FALSE, otherwise
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
BOOL bRetValue;
|
|
|
|
hr = S_OK;
|
|
bRetValue = FALSE;
|
|
|
|
//
|
|
// Instantiate the Event System
|
|
//
|
|
hr = CoCreateInstance(
|
|
CLSID_CEventSystem,
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
IID_IEventSystem,
|
|
(LPVOID *) &gpIEventSystem
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] Failed to create CEventSystem, HRESULT=%x\n", GetTickCount(), hr));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Create the IEventObjectChange ClassFactory and register it with COM.
|
|
//
|
|
gpChangeCF = new CIEventObjectChangeCF;
|
|
if (NULL == gpChangeCF)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] Failed to allocate IEventObjectChange ClassFactory object", GetTickCount()));
|
|
goto Cleanup;
|
|
}
|
|
// Add our reference to it.
|
|
gpChangeCF->AddRef();
|
|
|
|
SensPrintA(SENS_INFO, ("[%d] ClassFactory created successfully.\n", GetTickCount()));
|
|
|
|
// Register the CLSID
|
|
hr = CoRegisterClassObject(
|
|
SENSGUID_SUBSCRIBER_LCE,
|
|
(LPUNKNOWN) gpChangeCF,
|
|
CLSCTX_LOCAL_SERVER,
|
|
REGCLS_MULTIPLEUSE,
|
|
&gdwRegCO
|
|
);
|
|
if (FAILED(hr))
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] CoRegisterClassObject(IEventObjectChange) returned 0x%x.\n", GetTickCount(), hr));
|
|
goto Cleanup;
|
|
}
|
|
|
|
SensPrintA(SENS_ERR, ("[%d] Successfully registered the Class Factories.\n", GetTickCount()));
|
|
bRetValue = TRUE;
|
|
|
|
Cleanup:
|
|
//
|
|
// Cleanup
|
|
//
|
|
if (FALSE == bRetValue)
|
|
{
|
|
if (0x0 != gdwRegCO)
|
|
{
|
|
hr = CoRevokeClassObject(gdwRegCO);
|
|
gdwRegCO = 0x0;
|
|
}
|
|
|
|
if (gpChangeCF)
|
|
{
|
|
delete gpChangeCF;
|
|
gpChangeCF = NULL;
|
|
}
|
|
}
|
|
|
|
return bRetValue;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
ConfigureSensIfNecessary(
|
|
void
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Perform the configuration necessary for SENS.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE, if successful.
|
|
|
|
FALSE, otherwise
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
HKEY hKeySens;
|
|
LONG RegStatus;
|
|
BOOL bStatus;
|
|
DWORD dwType;
|
|
DWORD cbData;
|
|
DWORD dwConfigured;
|
|
LPBYTE lpbData;
|
|
HMODULE hSensCfgDll;
|
|
FARPROC pRegisterFunc;
|
|
|
|
hr = S_OK;
|
|
hKeySens = NULL;
|
|
RegStatus = ERROR_SUCCESS;
|
|
bStatus = FALSE;
|
|
dwType = 0x0;
|
|
cbData = 0x0;
|
|
dwConfigured = CONFIG_VERSION_NONE;
|
|
lpbData = NULL;
|
|
hSensCfgDll = NULL;
|
|
pRegisterFunc = NULL;
|
|
|
|
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, ("RegOpenKeyEx(Sens) returned %d.\n", RegStatus));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Query the Configured value
|
|
//
|
|
lpbData = (LPBYTE) &dwConfigured;
|
|
cbData = sizeof(DWORD);
|
|
|
|
RegStatus = RegQueryValueEx(
|
|
hKeySens, // Handle of the sub-key
|
|
IS_SENS_CONFIGURED, // Name of the Value
|
|
NULL, // Reserved (MBZ)
|
|
&dwType, // Address of the type of the Value
|
|
lpbData, // Address of the data of the Value
|
|
&cbData // Address of size of data of the Value
|
|
);
|
|
if (RegStatus != ERROR_SUCCESS)
|
|
{
|
|
SensPrintA(SENS_ERR, ("RegQueryValueEx(IS_SENS_CONFIGURED) failed with 0x%x\n", RegStatus));
|
|
goto Cleanup;
|
|
}
|
|
ASSERT(dwType == REG_DWORD);
|
|
|
|
if (dwConfigured >= CONFIG_VERSION_CURRENT)
|
|
{
|
|
SensPrintA(SENS_ERR, ("[%d] SENS is already configured!\n", GetTickCount()));
|
|
bStatus = TRUE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Sens is not yet configured to the latest version. So, do the necessary
|
|
// work now.
|
|
//
|
|
|
|
// Try to Load the Configuration Dll
|
|
hSensCfgDll = LoadLibrary(SENS_CONFIGURATION_DLL);
|
|
if (hSensCfgDll == NULL)
|
|
{
|
|
SensPrintA(SENS_ERR, ("LoadLibrary(SensCfg) returned 0x%x.\n", GetLastError()));
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Get the required entry point.
|
|
pRegisterFunc = GetProcAddress(hSensCfgDll, SENS_REGISTER_FUNCTION);
|
|
if (pRegisterFunc == NULL)
|
|
{
|
|
SensPrintA(SENS_ERR, ("GetProcAddress(Register) returned 0x%x.\n", GetLastError()));
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Do the registration now.
|
|
hr = (HRESULT)((*pRegisterFunc)());
|
|
if (FAILED(hr))
|
|
{
|
|
SensPrintA(SENS_ERR, ("RegisterSens() returned with 0x%x\n", hr));
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Update registry to reflect that SENS is now configured.
|
|
dwConfigured = CONFIG_VERSION_CURRENT;
|
|
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, ("RegSetValueEx(IS_SENS_CONFIGURED) failed with 0x%x\n", RegStatus));
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
SensPrintA(SENS_INFO, ("[%d] SENS is now configured successfully. Registry updated.\n", GetTickCount()));
|
|
bStatus = TRUE;
|
|
|
|
Cleanup:
|
|
//
|
|
// Cleanup
|
|
//
|
|
if (hKeySens)
|
|
{
|
|
RegCloseKey(hKeySens);
|
|
}
|
|
if (hSensCfgDll)
|
|
{
|
|
FreeLibrary(hSensCfgDll);
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
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);
|
|
|
|
// Use Default Process heap
|
|
ghSensHeap = GetProcessHeap();
|
|
ASSERT(ghSensHeap != NULL);
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|