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.
363 lines
9.1 KiB
363 lines
9.1 KiB
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1996-2002 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// Notifications.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of functions that send out notifications.
|
|
//
|
|
// Author:
|
|
// Galen Barbee GalenB 20-SEP-2001
|
|
// Vijayendra Vasu vvasu 17-AUG-2000
|
|
//
|
|
// Revision History:
|
|
// None.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define UNICODE 1
|
|
#define _UNICODE 1
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Include files
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
#include <objbase.h>
|
|
#include <ClusCfgInternalGuids.h>
|
|
#include <ClusCfgServer.h>
|
|
#include "clusrtl.h"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Constants
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// ClRtlStartupNotifyThreadProc
|
|
//
|
|
// Routine Description:
|
|
// Thread proc that invokes the startup notification processing and
|
|
// unloads the COM libraries.
|
|
//
|
|
// Arguments:
|
|
// lpvThreadContextIn
|
|
// The context arguments for this thread.
|
|
//
|
|
// Return Value:
|
|
// ERROR_SUCCESS
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
static DWORD
|
|
ClRtlStartupNotifyThreadProc(
|
|
LPVOID lpvThreadContextIn
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrInit = S_OK;
|
|
IClusCfgStartupNotify * pccsnNotify = NULL;
|
|
|
|
//
|
|
// Initialize COM - make sure it really init'ed or that we're just trying
|
|
// to change modes on the calling thread. Attempting to change the mode
|
|
// is not reason to fail this function.
|
|
//
|
|
|
|
hrInit = CoInitializeEx( NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE );
|
|
if ( ( hrInit != S_OK ) && ( hrInit != S_FALSE ) && ( hrInit != RPC_E_CHANGED_MODE ) )
|
|
{
|
|
hr = hrInit;
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_ClusCfgStartupNotify
|
|
, NULL
|
|
, CLSCTX_LOCAL_SERVER
|
|
, __uuidof( pccsnNotify )
|
|
, reinterpret_cast< void ** >( &pccsnNotify )
|
|
);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto CleanupCOM;
|
|
} // if: we could not get a pointer to synchronous notification interface
|
|
|
|
hr = pccsnNotify->SendNotifications();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto CleanupCOM;
|
|
} // if:
|
|
|
|
CleanupCOM:
|
|
|
|
if ( pccsnNotify != NULL )
|
|
{
|
|
pccsnNotify->Release();
|
|
} // if: we had obtained a pointer to the synchronous notification interface
|
|
|
|
//
|
|
// Free the no longer needed COM libraries...
|
|
//
|
|
|
|
CoFreeUnusedLibrariesEx( 0, 0 );
|
|
|
|
//
|
|
// Did the call to CoInitializeEx() above succeed? If it did then
|
|
// we need to call CoUnitialize(). Mode changed means we don't need
|
|
// to call CoUnitialize().
|
|
//
|
|
|
|
if ( hrInit != RPC_E_CHANGED_MODE )
|
|
{
|
|
CoUninitialize();
|
|
} // if:
|
|
|
|
Cleanup:
|
|
|
|
return ERROR_SUCCESS; // There isn't anyone around to see this...
|
|
|
|
} //*** ClRtlStartupNotifyThreadProc
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// ClRtlInitiateStartupNotification
|
|
//
|
|
// Routine Description:
|
|
// Initiate operations that inform interested parties that the cluster
|
|
// service is starting up.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// S_OK
|
|
// If the notification process was successfully initiated
|
|
//
|
|
// Other HRESULTS
|
|
// In case of error
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
ClRtlInitiateStartupNotification( void )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HANDLE hThread = NULL;
|
|
DWORD dwThreadID = 0;
|
|
|
|
//
|
|
// Create the thread...
|
|
//
|
|
|
|
hThread = CreateThread( NULL, 0, ClRtlStartupNotifyThreadProc, NULL, 0, &dwThreadID );
|
|
if ( hThread != NULL )
|
|
{
|
|
CloseHandle( hThread );
|
|
hr = S_OK;
|
|
} // if:
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
} // else:
|
|
|
|
return hr;
|
|
|
|
} //*** ClRtlInitiateStartupNotification
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// ClRtlEvictNotifyThreadProc
|
|
//
|
|
// Routine Description:
|
|
// Thread proc that invokes the evict notification processing and unloads
|
|
// the COM libraries.
|
|
//
|
|
// Arguments:
|
|
// LPVOID lpvThreadContext
|
|
// The context arguments for this thread.
|
|
//
|
|
// Return Value:
|
|
// ERROR_SUCCESS
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
static DWORD
|
|
ClRtlEvictNotifyThreadProc(
|
|
LPVOID lpvThreadContextIn
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrInit = S_OK;
|
|
IClusCfgEvictNotify * pccenNotify = NULL;
|
|
BSTR bstrEvictedNodeName = NULL;
|
|
|
|
bstrEvictedNodeName = (BSTR) lpvThreadContextIn;
|
|
|
|
//
|
|
// Initialize COM - make sure it really init'ed or that we're just trying
|
|
// to change modes on the calling thread. Attempting to change the mode
|
|
// is not reason to fail this function.
|
|
//
|
|
|
|
hrInit = CoInitializeEx( NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE );
|
|
if ( ( hrInit != S_OK ) && ( hrInit != S_FALSE ) && ( hrInit != RPC_E_CHANGED_MODE ) )
|
|
{
|
|
hr = hrInit;
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
hr = CoCreateInstance(
|
|
CLSID_ClusCfgEvictNotify
|
|
, NULL
|
|
, CLSCTX_LOCAL_SERVER
|
|
, __uuidof( pccenNotify )
|
|
, reinterpret_cast< void ** >( &pccenNotify )
|
|
);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto CleanupCOM;
|
|
} // if: we could not get a pointer to synchronous notification interface
|
|
|
|
//
|
|
// Make the sync COM call...
|
|
//
|
|
|
|
hr = pccenNotify->SendNotifications( bstrEvictedNodeName );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto CleanupCOM;
|
|
} // if:
|
|
|
|
CleanupCOM:
|
|
|
|
if ( pccenNotify != NULL )
|
|
{
|
|
pccenNotify->Release();
|
|
} // if: we had obtained a pointer to the synchronous notification interface
|
|
|
|
//
|
|
// Free the no longer needed COM libraries...
|
|
//
|
|
|
|
CoFreeUnusedLibrariesEx( 0, 0 );
|
|
|
|
//
|
|
// Did the call to CoInitializeEx() above succeed? If it did then
|
|
// we need to call CoUnitialize(). Mode changed means we don't need
|
|
// to call CoUnitialize().
|
|
//
|
|
|
|
if ( hrInit != RPC_E_CHANGED_MODE )
|
|
{
|
|
CoUninitialize();
|
|
} // if:
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// This routine must clean this up!
|
|
//
|
|
|
|
SysFreeString( bstrEvictedNodeName );
|
|
|
|
return ERROR_SUCCESS; // There isn't anyone around to see this...
|
|
|
|
} //*** ClRtlEvictNotifyThreadProc
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// ClRtlInitiateEvictNotification
|
|
//
|
|
// Routine Description:
|
|
// Initiate operations that inform interested parties that a node
|
|
// has been evicted from the cluster.
|
|
//
|
|
// Arguments:
|
|
// pcszNodeNameIn
|
|
// The name of the node that was evicted. Since this function is
|
|
// not called when the last node is evicted this argument should
|
|
// never be NULL.
|
|
//
|
|
// Return Value:
|
|
// S_OK
|
|
// If the notification process was successfully initiated
|
|
//
|
|
// Other HRESULTS
|
|
// In case of error
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
ClRtlInitiateEvictNotification(
|
|
LPCWSTR pcszNodeNameIn
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrNodeName = NULL;
|
|
HANDLE hThread = NULL;
|
|
DWORD dwThreadID = 0;
|
|
|
|
//
|
|
// Validate our arguments...
|
|
//
|
|
|
|
if ( pcszNodeNameIn == NULL )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
//
|
|
// Copy the node name into dynamic memory. BSTRs work well here since we
|
|
// don't have to keep track of the length...
|
|
//
|
|
|
|
bstrNodeName = SysAllocString( pcszNodeNameIn );
|
|
if ( bstrNodeName == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
} // if:
|
|
|
|
//
|
|
// Create the thread...
|
|
//
|
|
|
|
hThread = CreateThread( NULL, 0, ClRtlEvictNotifyThreadProc, bstrNodeName, 0, &dwThreadID );
|
|
if ( hThread == NULL )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
goto Cleanup;
|
|
} // else:
|
|
|
|
CloseHandle( hThread );
|
|
|
|
//
|
|
// Now that the thread has been launched we can give away ownership of
|
|
// this memory to the thread as we don't want to delete it below.
|
|
//
|
|
// It's the thread procs responsibility to cleanup this memory.
|
|
//
|
|
|
|
bstrNodeName = NULL; // give away ownership...
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
|
|
SysFreeString( bstrNodeName );
|
|
|
|
return hr;
|
|
|
|
} //*** ClRtlInitiateEvictNotification
|