|
|
#include "stdafx.h"
#include "wolfpack.h"
#ifndef _CHICAGO_
#include <windows.h>
#include <stdio.h>
#include <clusapi.h>
#include <resapi.h>
#include <helper.h>
#define INITIAL_RESOURCE_NAME_SIZE 256 // In characters not in bytes
#define IIS_RESOURCE_TYPE_NAME L"IIS Server Instance"
#define SMTP_RESOURCE_TYPE_NAME L"SMTP Server Instance"
#define NNTP_RESOURCE_TYPE_NAME L"NNTP Server Instance"
#define MAX_OFFLINE_RETRIES 5 // Number of times to try and take a resources offline before giving up
#define DELAY_BETWEEN_CALLS_TO_OFFLINE 1000*2 // in milliseconds
CONST LPCWSTR scClusterPath = _T("System\\CurrentControlSet\\Services\\ClusSvc"); CONST LPCWSTR scClusterPath2 = _T("System\\CurrentControlSet\\Services\\ClusSvc\\Parameters");
CStringList gcstrListOfClusResources;
int g_ClusterSVCExist = -1; // -1 = not checked, 1 = exist, 0 = not exist
typedef DWORD (WINAPI *PFN_RESUTILFINDSZPROPERTY)( IN LPVOID lpTheProperty, IN OUT LPDWORD nInBufferSize, IN LPCWSTR lpszResourceTypeName, OUT LPVOID lpOutBuffer);
typedef DWORD (WINAPI *PFN_RESUTILFINDDWORDPROPERTY)( IN LPVOID lpTheProperty, IN OUT LPDWORD nInBufferSize, IN LPCWSTR lpszResourceTypeName, OUT LPDWORD pdwPropertyValue);
typedef DWORD (WINAPI *PFN_CLUSTERRESOURCECONTROL)( IN HRESOURCE hResource, IN HNODE hNode, IN DWORD dwControlCode, IN LPVOID lpInBuffer, IN OUT DWORD nInBufferSize, OUT LPVOID lpOutBuffer, IN OUT DWORD nOutBufferSize, OUT LPDWORD lpBytesReturned );
typedef HCLUSTER (WINAPI *PFN_OPENCLUSTER)( IN LPCWSTR lpszClusterName );
typedef BOOL (WINAPI *PFN_CLOSECLUSTER)( IN HCLUSTER hCluster );
typedef DWORD (WINAPI *PFN_CREATECLUSTERRESOURCETYPE)( IN HCLUSTER hCluster, IN LPCWSTR lpszResourceTypeName, IN LPCWSTR lpszDisplayName, IN LPCWSTR lpszResourceTypeDll, IN DWORD dwLooksAlivePollInterval, IN DWORD dwIsAlivePollInterval );
typedef DWORD (WINAPI *PFN_DELETECLUSTERRESOURCETYPE)( IN HCLUSTER hCluster, IN LPCWSTR lpszResourceTypeName );
typedef HCLUSENUM (WINAPI *PFN_ClusterOpenEnum)( IN HCLUSTER hCluster, IN DWORD dwType );
typedef DWORD (WINAPI *PFN_ClusterEnum)( IN HCLUSENUM hEnum, IN DWORD dwIndex, OUT LPDWORD lpdwType, OUT LPWSTR lpszName, IN OUT LPDWORD lpcbName );
typedef DWORD (WINAPI *PFN_ClusterCloseEnum)( IN HCLUSENUM hEnum );
typedef HRESOURCE (WINAPI *PFN_OpenClusterResource)( IN HCLUSTER hCluster, IN LPCWSTR lpszResourceName );
typedef BOOL (WINAPI *PFN_CloseClusterResource)( IN HRESOURCE hResource );
typedef DWORD (WINAPI *PFN_DeleteClusterResource)( IN HRESOURCE hResource );
typedef DWORD (WINAPI *PFN_OfflineClusterResource)( IN HRESOURCE hResource );
typedef HKEY (WINAPI *PFN_GetClusterResourceKey)( IN HRESOURCE hResource, IN REGSAM samDesired );
typedef LONG (WINAPI *PFN_ClusterRegCloseKey)( IN HKEY hKey );
typedef LONG (WINAPI *PFN_ClusterRegQueryValue)( IN HKEY hKey, IN LPCWSTR lpszValueName, OUT LPDWORD lpValueType, OUT LPBYTE lpData, IN OUT LPDWORD lpcbData );
typedef CLUSTER_RESOURCE_STATE (WINAPI *PFN_GetClusterResourceState)( IN HRESOURCE hResource, OUT OPTIONAL LPWSTR lpszNodeName, IN OUT LPDWORD lpcbNodeName, OUT OPTIONAL LPWSTR lpszGroupName, IN OUT LPDWORD lpcbGroupName );
typedef DWORD (WINAPI *PFN_DLLREGISTERCLUADMINEXTENSION)( IN HCLUSTER hCluster );
typedef DWORD (WINAPI *PFN_DLLUNREGISTERCLUADMINEXTENSION)( IN HCLUSTER hCluster );
void ListOfClusResources_Add(TCHAR * szEntry) { //Add entry to the list if not already there
if (_tcsicmp(szEntry, _T("")) != 0) { // Add it if it is not already there.
if (TRUE != IsThisStringInThisCStringList(gcstrListOfClusResources, szEntry)) { gcstrListOfClusResources.AddTail(szEntry); //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ListOfClusResources_Add:%s\n"),szEntry));
} } return; }
INT ListOfClusResources_Check(TCHAR * szEntry) { int iReturn = FALSE;
//Add entry to the list if not already there
if (_tcsicmp(szEntry, _T("")) != 0) { // Return true if it's in there!
iReturn = IsThisStringInThisCStringList(gcstrListOfClusResources, szEntry); } return iReturn; }
BOOL RegisterIisServerInstanceResourceType( LPWSTR pszResType, LPWSTR pszResTypeDisplayName, LPWSTR pszPath, LPWSTR pszAdminPath ) { HCLUSTER hC; DWORD dwErr = ERROR_SUCCESS; HINSTANCE hClusapi; PFN_OPENCLUSTER pfnOpenCluster; PFN_CLOSECLUSTER pfnCloseCluster; PFN_CREATECLUSTERRESOURCETYPE pfnCreateClusterResourceType; HRESULT hres;
hClusapi = LoadLibrary( L"clusapi.dll" );
if ( hClusapi ) { pfnOpenCluster = (PFN_OPENCLUSTER)GetProcAddress( hClusapi, "OpenCluster" ); pfnCloseCluster = (PFN_CLOSECLUSTER)GetProcAddress( hClusapi, "CloseCluster" ); pfnCreateClusterResourceType = (PFN_CREATECLUSTERRESOURCETYPE)GetProcAddress( hClusapi, "CreateClusterResourceType" );
if ( pfnOpenCluster && pfnCloseCluster && pfnCreateClusterResourceType ) { hC = pfnOpenCluster( NULL );
if ( hC ) { hres = pfnCreateClusterResourceType( hC, pszResType, pszResType, pszPath, 5000, 60000 );
if ( SUCCEEDED( hres ) ) { HINSTANCE hAdmin; PFN_DLLREGISTERCLUADMINEXTENSION pfnDllRegisterCluAdminExtension;
hAdmin = LoadLibrary( pszAdminPath );
if ( hAdmin ) { pfnDllRegisterCluAdminExtension = (PFN_DLLREGISTERCLUADMINEXTENSION)GetProcAddress( hAdmin, "DllRegisterCluAdminExtension" ); if ( pfnDllRegisterCluAdminExtension ) { if ( FAILED(hres = pfnDllRegisterCluAdminExtension( hC )) ) { dwErr = hres; } } else { dwErr = GetLastError(); } FreeLibrary( hAdmin ); } else { dwErr = GetLastError(); } } else { dwErr = hres; }
pfnCloseCluster( hC );
if ( dwErr ) { SetLastError( dwErr ); } } } else { dwErr = GetLastError(); }
FreeLibrary( hClusapi ); } else { dwErr = GetLastError(); }
return dwErr == ERROR_SUCCESS ? TRUE : FALSE; }
BOOL UnregisterIisServerInstanceResourceType( LPWSTR pszResType, LPWSTR pszAdminPath, BOOL bGrabVRootFromResourceAndAddToIISVRoot, BOOL bDeleteAfterMove ) { CStringArray cstrArryName, cstrArryPath; CStringArray cstrArryNameftp, cstrArryPathftp;
HCLUSTER hC; DWORD dwErr = ERROR_SUCCESS; HINSTANCE hClusapi; PFN_OPENCLUSTER pfnOpenCluster; PFN_CLOSECLUSTER pfnCloseCluster; PFN_DELETECLUSTERRESOURCETYPE pfnDeleteClusterResourceType; PFN_ClusterOpenEnum pfnClusterOpenEnum; PFN_ClusterEnum pfnClusterEnum; PFN_ClusterCloseEnum pfnClusterCloseEnum; PFN_OpenClusterResource pfnOpenClusterResource; PFN_CloseClusterResource pfnCloseClusterResource; PFN_DeleteClusterResource pfnDeleteClusterResource; PFN_OfflineClusterResource pfnOfflineClusterResource; PFN_GetClusterResourceKey pfnGetClusterResourceKey; PFN_ClusterRegCloseKey pfnClusterRegCloseKey; PFN_ClusterRegQueryValue pfnClusterRegQueryValue; PFN_GetClusterResourceState pfnGetClusterResourceState; HRESULT hres; HCLUSENUM hClusEnum; WCHAR awchResType[256]; DWORD dwEnum; DWORD dwType; DWORD dwStrLen; HRESOURCE hRes; HKEY hKey; BOOL fDel; DWORD dwRetry; BUFFER buffResName;
hClusapi = NULL; hClusapi = LoadLibrary(L"clusapi.dll"); if (!hClusapi) { hClusapi = NULL; iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType:LoadLib clusapi.dll failed.\n"))); goto UnregisterIisServerInstanceResourceType_Exit; } pfnOpenCluster = (PFN_OPENCLUSTER)GetProcAddress( hClusapi, "OpenCluster" ); pfnCloseCluster = (PFN_CLOSECLUSTER)GetProcAddress( hClusapi, "CloseCluster" ); pfnDeleteClusterResourceType = (PFN_DELETECLUSTERRESOURCETYPE)GetProcAddress( hClusapi, "DeleteClusterResourceType" ); pfnClusterOpenEnum = (PFN_ClusterOpenEnum)GetProcAddress( hClusapi, "ClusterOpenEnum" ); pfnClusterEnum = (PFN_ClusterEnum)GetProcAddress( hClusapi, "ClusterEnum" ); pfnClusterCloseEnum = (PFN_ClusterCloseEnum)GetProcAddress( hClusapi, "ClusterCloseEnum" ); pfnOpenClusterResource = (PFN_OpenClusterResource)GetProcAddress( hClusapi, "OpenClusterResource" ); pfnCloseClusterResource = (PFN_CloseClusterResource)GetProcAddress( hClusapi, "CloseClusterResource" ); pfnDeleteClusterResource = (PFN_DeleteClusterResource)GetProcAddress( hClusapi, "DeleteClusterResource" ); pfnOfflineClusterResource = (PFN_OfflineClusterResource)GetProcAddress( hClusapi, "OfflineClusterResource" ); pfnGetClusterResourceKey = (PFN_GetClusterResourceKey)GetProcAddress( hClusapi, "GetClusterResourceKey" ); pfnClusterRegCloseKey = (PFN_ClusterRegCloseKey)GetProcAddress( hClusapi, "ClusterRegCloseKey" ); pfnClusterRegQueryValue = (PFN_ClusterRegQueryValue)GetProcAddress( hClusapi, "ClusterRegQueryValue" ); pfnGetClusterResourceState = (PFN_GetClusterResourceState)GetProcAddress( hClusapi, "GetClusterResourceState" );
if ( !pfnOpenCluster || !pfnCloseCluster || !pfnDeleteClusterResourceType || !pfnClusterOpenEnum || !pfnClusterEnum || !pfnClusterCloseEnum || !pfnOpenClusterResource || !pfnCloseClusterResource || !pfnDeleteClusterResource || !pfnOfflineClusterResource || !pfnGetClusterResourceKey || !pfnClusterRegCloseKey || !pfnClusterRegQueryValue || !pfnGetClusterResourceState ) { iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType:clusapi.dll missing export function.failure.\n"))); goto UnregisterIisServerInstanceResourceType_Exit; }
hC = pfnOpenCluster(NULL); // if we can't open the cluster, then maybe there are none.
if (!hC) {goto UnregisterIisServerInstanceResourceType_Exit;}
// Delete all resources of type pszResType
hClusEnum = pfnClusterOpenEnum(hC, CLUSTER_ENUM_RESOURCE); if (hClusEnum != NULL) { dwEnum = 0; int iClusterEnumReturn = ERROR_SUCCESS;
// allocate the initial buffer for pawchResName
if ( !buffResName.Resize( 256 * sizeof( WCHAR ) ) ) { goto UnregisterIisServerInstanceResourceType_Exit; }
do { iClusterEnumReturn = ERROR_SUCCESS; dwStrLen = buffResName.QuerySize() / sizeof(WCHAR); iClusterEnumReturn = pfnClusterEnum( hClusEnum, dwEnum, &dwType, (LPWSTR) buffResName.QueryPtr(), &dwStrLen ); if (iClusterEnumReturn != ERROR_SUCCESS) { // Check if failed because it needs more space.
if ( (iClusterEnumReturn == ERROR_MORE_DATA) && ( ( dwStrLen + 1 ) > buffResName.QuerySize() ) ) { if ( !buffResName.Resize( ( dwStrLen + 1 ) * sizeof(WCHAR) ) ) { iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType: realloc FAILED.out of memory.\n"))); goto UnregisterIisServerInstanceResourceType_Exit; } // try it again.
iClusterEnumReturn = ERROR_SUCCESS; dwStrLen = buffResName.QuerySize() / sizeof(WCHAR); iClusterEnumReturn = pfnClusterEnum( hClusEnum, dwEnum, &dwType, (LPWSTR) buffResName.QueryPtr(), &dwStrLen ); if (iClusterEnumReturn != ERROR_SUCCESS) { iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType: FAILED.err=0x%x.\n"), iClusterEnumReturn)); break; } } else { if (iClusterEnumReturn != ERROR_NO_MORE_ITEMS) { // failed for some other reason than no more data
iisDebugOut((LOG_TYPE_ERROR, _T("UnregisterIisServerInstanceResourceType: FAILED.err=0x%x.\n"), iClusterEnumReturn)); } break; } }
// proceed
hRes = pfnOpenClusterResource( hC, (LPWSTR) buffResName.QueryPtr() );
if ( hRes ) { hKey = pfnGetClusterResourceKey( hRes, KEY_READ );
if ( hKey ) { dwStrLen = sizeof(awchResType)/sizeof(WCHAR); // Check if it's for 'our' type of key (pszResType)
fDel = pfnClusterRegQueryValue( hKey, L"Type", &dwType, (LPBYTE)awchResType, &dwStrLen ) == ERROR_SUCCESS && !wcscmp( awchResType, pszResType ); pfnClusterRegCloseKey( hKey );
if ( fDel ) { if (bDeleteAfterMove) { // Take the resource off line so that we can actually delete it, i guess.
pfnOfflineClusterResource( hRes ); for ( dwRetry = 0 ;dwRetry < 30 && pfnGetClusterResourceState( hRes,NULL,&dwStrLen,NULL,&dwStrLen ) != ClusterResourceOffline; ++dwRetry ) { Sleep( 1000 ); } }
// At this point we have successfully got the cluster to go offline
if (bGrabVRootFromResourceAndAddToIISVRoot) { // At this point we have successfully got the cluster to go offline
// Get the vroot names and path's here and stick into the arrays....
GetClusterIISVRoot(hRes, L"W3SVC", cstrArryName, cstrArryPath);
// Do it for FTP now.
GetClusterIISVRoot(hRes, L"MSFTPSVC", cstrArryNameftp, cstrArryPathftp);
// No need to do it for gopher since there is none.
//GetClusterIISVRoot(hRes, L"GOPHERSVC", cstrArryName, cstrArryPath);
}
// We have saved all the important data into our Array's
// now it's okay to delete the Resource
if (bDeleteAfterMove) { pfnDeleteClusterResource( hRes ); } } }
pfnCloseClusterResource( hRes ); }
// Increment to the next one
++dwEnum;
} while(TRUE);
pfnClusterCloseEnum( hClusEnum ); }
if (bDeleteAfterMove) { dwErr = pfnDeleteClusterResourceType(hC,pszResType );
HINSTANCE hAdmin = LoadLibrary( pszAdminPath );
if ( hAdmin ) { PFN_DLLUNREGISTERCLUADMINEXTENSION pfnDllUnregisterCluAdminExtension; pfnDllUnregisterCluAdminExtension = (PFN_DLLUNREGISTERCLUADMINEXTENSION)GetProcAddress( hAdmin, "DllUnregisterCluAdminExtension" ); if ( pfnDllUnregisterCluAdminExtension ) { if ( FAILED(hres = pfnDllUnregisterCluAdminExtension( hC )) ) { dwErr = hres; } } else { dwErr = GetLastError(); } FreeLibrary( hAdmin ); } else { dwErr = GetLastError(); } }
pfnCloseCluster( hC );
if (dwErr) {SetLastError( dwErr );}
UnregisterIisServerInstanceResourceType_Exit: // Copy these to the iis virtual root registry....
MoveVRootToIIS3Registry(REG_W3SVC,cstrArryName,cstrArryPath); // Copy these to the iis virtual root registry....
MoveVRootToIIS3Registry(REG_MSFTPSVC,cstrArryNameftp,cstrArryPathftp);
if (hClusapi) {FreeLibrary(hClusapi);} return dwErr == ERROR_SUCCESS ? TRUE : FALSE; }
void TestClusterRead(LPWSTR pszClusterName) { iisDebugOut_Start(_T("TestClusterRead"));
LPWSTR pszResType = L"IIS Virtual Root";
CStringArray cstrArryName, cstrArryPath; CStringArray cstrArryNameftp, cstrArryPathftp;
HCLUSTER hC; DWORD dwErr = ERROR_SUCCESS; HINSTANCE hClusapi; PFN_OPENCLUSTER pfnOpenCluster; PFN_CLOSECLUSTER pfnCloseCluster; PFN_DELETECLUSTERRESOURCETYPE pfnDeleteClusterResourceType; PFN_ClusterOpenEnum pfnClusterOpenEnum; PFN_ClusterEnum pfnClusterEnum; PFN_ClusterCloseEnum pfnClusterCloseEnum; PFN_OpenClusterResource pfnOpenClusterResource; PFN_CloseClusterResource pfnCloseClusterResource; PFN_DeleteClusterResource pfnDeleteClusterResource; PFN_OfflineClusterResource pfnOfflineClusterResource; PFN_GetClusterResourceKey pfnGetClusterResourceKey; PFN_ClusterRegCloseKey pfnClusterRegCloseKey; PFN_ClusterRegQueryValue pfnClusterRegQueryValue; PFN_GetClusterResourceState pfnGetClusterResourceState; HCLUSENUM hClusEnum; WCHAR * pawchResName = NULL; WCHAR awchResType[256]; DWORD dwEnum; DWORD dwType; DWORD dwStrLen; HRESOURCE hRes; HKEY hKey; BOOL fDel;
hClusapi = NULL; hClusapi = LoadLibrary(L"clusapi.dll"); if (!hClusapi) { hClusapi = NULL; iisDebugOut((LOG_TYPE_TRACE, _T("fail 1\n"))); goto TestClusterRead_Exit; } pfnOpenCluster = (PFN_OPENCLUSTER)GetProcAddress( hClusapi, "OpenCluster" ); pfnCloseCluster = (PFN_CLOSECLUSTER)GetProcAddress( hClusapi, "CloseCluster" ); pfnDeleteClusterResourceType = (PFN_DELETECLUSTERRESOURCETYPE)GetProcAddress( hClusapi, "DeleteClusterResourceType" ); pfnClusterOpenEnum = (PFN_ClusterOpenEnum)GetProcAddress( hClusapi, "ClusterOpenEnum" ); pfnClusterEnum = (PFN_ClusterEnum)GetProcAddress( hClusapi, "ClusterEnum" ); pfnClusterCloseEnum = (PFN_ClusterCloseEnum)GetProcAddress( hClusapi, "ClusterCloseEnum" ); pfnOpenClusterResource = (PFN_OpenClusterResource)GetProcAddress( hClusapi, "OpenClusterResource" ); pfnCloseClusterResource = (PFN_CloseClusterResource)GetProcAddress( hClusapi, "CloseClusterResource" ); pfnDeleteClusterResource = (PFN_DeleteClusterResource)GetProcAddress( hClusapi, "DeleteClusterResource" ); pfnOfflineClusterResource = (PFN_OfflineClusterResource)GetProcAddress( hClusapi, "OfflineClusterResource" ); pfnGetClusterResourceKey = (PFN_GetClusterResourceKey)GetProcAddress( hClusapi, "GetClusterResourceKey" ); pfnClusterRegCloseKey = (PFN_ClusterRegCloseKey)GetProcAddress( hClusapi, "ClusterRegCloseKey" ); pfnClusterRegQueryValue = (PFN_ClusterRegQueryValue)GetProcAddress( hClusapi, "ClusterRegQueryValue" ); pfnGetClusterResourceState = (PFN_GetClusterResourceState)GetProcAddress( hClusapi, "GetClusterResourceState" );
if ( !pfnOpenCluster || !pfnCloseCluster || !pfnDeleteClusterResourceType || !pfnClusterOpenEnum || !pfnClusterEnum || !pfnClusterCloseEnum || !pfnOpenClusterResource || !pfnCloseClusterResource || !pfnDeleteClusterResource || !pfnOfflineClusterResource || !pfnGetClusterResourceKey || !pfnClusterRegCloseKey || !pfnClusterRegQueryValue || !pfnGetClusterResourceState ) { iisDebugOut((LOG_TYPE_TRACE, _T("fail 2\n"))); goto TestClusterRead_Exit; }
iisDebugOut((LOG_TYPE_TRACE, _T("try to open cluster=%s\n"),pszClusterName)); // try to open the cluster on the computer
hC = pfnOpenCluster( pszClusterName );
if ( hC ) { //
// Delete all resources of type pszResType
//
if ( (hClusEnum = pfnClusterOpenEnum( hC, CLUSTER_ENUM_RESOURCE )) != NULL ) { dwEnum = 0; int iClusterEnumReturn = ERROR_SUCCESS;
// allocate the initial buffer for pawchResName
dwStrLen = 256 * sizeof(WCHAR); pawchResName = NULL; pawchResName = (LPTSTR) malloc( dwStrLen ); if (!pawchResName) { iisDebugOut((LOG_TYPE_ERROR, _T("TestClusterRead: malloc FAILED.out of memory.\n"))); goto TestClusterRead_Exit; }
do { iClusterEnumReturn = pfnClusterEnum( hClusEnum, dwEnum, &dwType, pawchResName, &dwStrLen ); if (iClusterEnumReturn != ERROR_SUCCESS) { // Check if failed because it needs more space.
if (iClusterEnumReturn == ERROR_MORE_DATA) { LPTSTR pOldResName = pawchResName;
// dwStrLen should be set to the required length returned from pfnClusterEnum
dwStrLen = (dwStrLen + 1) * sizeof(WCHAR); pawchResName = (LPTSTR) realloc(pawchResName, dwStrLen); if (!pawchResName) { if ( pOldResName ) { free ( pOldResName ); } iisDebugOut((LOG_TYPE_ERROR, _T("TestClusterRead: realloc FAILED.out of memory.\n"))); goto TestClusterRead_Exit; } // try it again.
iClusterEnumReturn = pfnClusterEnum( hClusEnum, dwEnum, &dwType, pawchResName, &dwStrLen ); if (iClusterEnumReturn != ERROR_SUCCESS) { iisDebugOut((LOG_TYPE_ERROR, _T("TestClusterRead: FAILED.err=0x%x.\n"), iClusterEnumReturn)); break; } } else { if (iClusterEnumReturn != ERROR_NO_MORE_ITEMS) { // failed for some other reason.
iisDebugOut((LOG_TYPE_ERROR, _T("TestClusterRead: FAILED.err=0x%x.\n"), iClusterEnumReturn)); } break; } }
// proceed
hRes = pfnOpenClusterResource( hC, pawchResName );
if ( hRes ) { hKey = pfnGetClusterResourceKey( hRes, KEY_READ ) ;
if ( hKey ) { dwStrLen = sizeof(awchResType)/sizeof(WCHAR);
fDel = pfnClusterRegQueryValue( hKey, L"Type", &dwType, (LPBYTE)awchResType, &dwStrLen ) == ERROR_SUCCESS && !wcscmp( awchResType, pszResType );
iisDebugOut((LOG_TYPE_TRACE, _T("TestClusterRead():ClusterRegQueryValue:%s."),awchResType)); pfnClusterRegCloseKey( hKey );
if ( fDel ) { /*
pfnOfflineClusterResource( hRes ); for ( dwRetry = 0 ; dwRetry < 30 && pfnGetClusterResourceState( hRes,NULL,&dwStrLen,NULL,&dwStrLen ) != ClusterResourceOffline; ++dwRetry ) { Sleep( 1000 ); } */
// At this point we have successfully got the cluster to go offline
// Get the vroot names and path's here and stick into the arrays....
GetClusterIISVRoot(hRes, L"W3SVC", cstrArryName, cstrArryPath);
// Do it for FTP now.
GetClusterIISVRoot(hRes, L"MSFTPSVC", cstrArryNameftp, cstrArryPathftp);
// No need to do it for gopher since there is none.
//GetClusterIISVRoot(hRes, L"GOPHERSVC", cstrArryName, cstrArryPath);
} }
pfnCloseClusterResource( hRes ); }
// Increment to the next one
++dwEnum;
} while(TRUE);
pfnClusterCloseEnum( hClusEnum ); }
//dwErr = pfnDeleteClusterResourceType(hC,pszResType );
pfnCloseCluster( hC );
if (dwErr) {SetLastError( dwErr );} } else { iisDebugOut((LOG_TYPE_TRACE, _T("fail 3\n"))); }
TestClusterRead_Exit: // Copy these to the iis virtual root registry....
MoveVRootToIIS3Registry(REG_W3SVC,cstrArryName,cstrArryPath); // Copy these to the iis virtual root registry....
MoveVRootToIIS3Registry(REG_MSFTPSVC,cstrArryNameftp,cstrArryPathftp);
if (hClusapi) {FreeLibrary(hClusapi);} if (pawchResName) {free(pawchResName);} iisDebugOut_End(_T("TestClusterRead")); return; }
/****************************************************************************************
* * Function: GetClusterIISVRoot * * Args: [in] hResource , the resource whos info should be added to the list * * Retrurn: GetLastError, on error * ****************************************************************************************/ int GetClusterIISVRoot(HRESOURCE hResource, LPWSTR pszTheServiceType, CStringArray &strArryOfVrootNames, CStringArray &strArryOfVrootData) { //iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: start\n")));
int iReturn = FALSE; HINSTANCE hClusapi; HINSTANCE hResutils;
PFN_CLUSTERRESOURCECONTROL pfnClusterResourceControl; PFN_RESUTILFINDSZPROPERTY pfnResUtilFindSzProperty; PFN_RESUTILFINDDWORDPROPERTY pfnResUtilFindDwordProperty;
//
// Initial size of the buffer
//
DWORD dwBufferSize = 256; //
// The requested buffer size, and the number of bytes actually in the returned buffer
//
DWORD dwRequestedBufferSize = dwBufferSize;
//
// Result from the call to the cluster resource control function
//
DWORD dwResult;
//
// Buffer that holds the property list for this resource
//
LPVOID lpvPropList = NULL;
//
// The Proivate property that is being read
//
LPWSTR lpwszPrivateProp = NULL;
hClusapi = LoadLibrary( L"clusapi.dll" ); if (!hClusapi) { iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to loadlib clusapi.dll\n"))); goto GetIISVRoot_Exit; }
pfnClusterResourceControl = (PFN_CLUSTERRESOURCECONTROL)GetProcAddress( hClusapi, "ClusterResourceControl" ); if (!pfnClusterResourceControl) { iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to GetProcAddress clusapi.dll:ClusterResourceControl\n"))); goto GetIISVRoot_Exit; }
hResutils = LoadLibrary( L"resutils.dll" ); if (!hResutils) { iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to loadlib resutils.dll\n"))); goto GetIISVRoot_Exit; } pfnResUtilFindSzProperty = (PFN_RESUTILFINDSZPROPERTY)GetProcAddress( hResutils, "ResUtilFindSzProperty" ); if (!pfnResUtilFindSzProperty) { iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to GetProcAddress resutils.dll:ResUtilFindSzProperty\n"))); goto GetIISVRoot_Exit; } pfnResUtilFindDwordProperty = (PFN_RESUTILFINDDWORDPROPERTY)GetProcAddress( hResutils, "ResUtilFindDwordProperty" ); if (!pfnResUtilFindDwordProperty) { iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: failed to GetProcAddress resutils.dll:ResUtilFindDwordProperty\n"))); goto GetIISVRoot_Exit; }
//
// Allocate memory for the resource type
//
lpvPropList = (LPWSTR) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize * sizeof(WCHAR) ); if( lpvPropList == NULL) { lpvPropList = NULL; iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: E_OUTOFMEMORY\n"))); goto GetIISVRoot_Exit; }
//
// Allocate memory for the Property
//
lpwszPrivateProp = (LPWSTR) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, (_MAX_PATH+_MAX_PATH+1) * sizeof(WCHAR) ); if( lpwszPrivateProp == NULL) { lpvPropList = NULL; iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: E_OUTOFMEMORY\n"))); goto GetIISVRoot_Exit; } //
// Get the resource's private properties (Service , InstanceId)
//
while( 1 ) { dwResult = pfnClusterResourceControl(hResource,NULL,CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES,NULL,0,lpvPropList,dwBufferSize,&dwRequestedBufferSize ); if( ERROR_SUCCESS == dwResult ) { // ---------------------
// what the entries are:
// AccessMask (dword) = 5
// Alias (string) = "virtual dir name"
// Directory (string) = "c:\la\lalalala"
// ServiceName (string) = W3SVC, MSFTPSVC, GOPHERSVC
// ---------------------
//
// Get the "ServiceName" entry
//
dwResult = pfnResUtilFindSzProperty( lpvPropList, &dwRequestedBufferSize, L"ServiceName", &lpwszPrivateProp); if( dwResult != ERROR_SUCCESS ) { iisDebugOut((LOG_TYPE_ERROR, _T("Couldn't get 'ServiceName' property.fail\n"))); goto GetIISVRoot_Exit; }
if (_wcsicmp(lpwszPrivateProp, pszTheServiceType) == 0) { // okay, we want to do stuff with this one!!!
DWORD dwAccessMask; CString csAlias; CString csDirectory;
TCHAR szMyBigPath[_MAX_PATH + 20];
DWORD dwPrivateProp = 0; dwRequestedBufferSize = sizeof(DWORD);
// get the Access Mask.
dwResult = pfnResUtilFindDwordProperty( lpvPropList, &dwRequestedBufferSize, L"AccessMask", &dwPrivateProp); if( dwResult != ERROR_SUCCESS ) { iisDebugOut((LOG_TYPE_ERROR, _T("Couldn't get 'AccessMask' property.fail\n"))); goto GetIISVRoot_Exit; } dwAccessMask = dwPrivateProp;
// get the Alias
dwResult = pfnResUtilFindSzProperty( lpvPropList, &dwRequestedBufferSize, L"Alias", &lpwszPrivateProp); if( dwResult != ERROR_SUCCESS ) { iisDebugOut((LOG_TYPE_ERROR, _T("Couldn't get 'Alias' property.fail\n"))); goto GetIISVRoot_Exit; } csAlias = lpwszPrivateProp;
// Get the Directory
dwResult = pfnResUtilFindSzProperty( lpvPropList, &dwRequestedBufferSize, L"Directory", &lpwszPrivateProp); if( dwResult != ERROR_SUCCESS ) { iisDebugOut((LOG_TYPE_ERROR, _T("Couldn't get 'Directory' property.fail\n"))); goto GetIISVRoot_Exit; } TCHAR thepath[_MAX_PATH]; TCHAR * pmypath; csDirectory = lpwszPrivateProp;
// make sure it's a valid directory name!
if (0 != GetFullPathName(lpwszPrivateProp, _MAX_PATH, thepath, &pmypath)) {csDirectory = thepath;}
// --------------------
// formulate the string
// --------------------
//
// Put the Name into the array.
//
// "/Alias"
strArryOfVrootNames.Add(csAlias);
//
// "C:\inetpub\ASPSamp,,5"
//
_stprintf(szMyBigPath,_T("%s,,%d"),csDirectory, dwAccessMask); strArryOfVrootData.Add(szMyBigPath);
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("Entry=[%s] '%s=%s'\n"),pszTheServiceType,csAlias,szMyBigPath)); } goto GetIISVRoot_Exit; }
if( ERROR_MORE_DATA == dwResult ) { LPVOID lpvTemp = lpvPropList; //
// Set the buffer size to the required size reallocate the buffer
//
dwBufferSize = ++dwRequestedBufferSize;
lpvPropList = (LPWSTR) HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, lpvPropList, dwBufferSize * sizeof(WCHAR) ); if ( lpvPropList == NULL) { if ( lpvTemp ) { HeapFree( GetProcessHeap(), 0, lpvTemp ); } // out of memory!!!!
goto GetIISVRoot_Exit; } } }
GetIISVRoot_Exit: if (lpwszPrivateProp) {HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpwszPrivateProp);} if (lpvPropList) {HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpvPropList);} //iisDebugOut((LOG_TYPE_ERROR, _T("GetClusterIISVRoot: end\n")));
return iReturn; }
// REG_W3SVC, REG_MSFTPSVC
void MoveVRootToIIS3Registry(CString strRegPath, CStringArray &strArryOfVrootNames, CStringArray &strArryOfVrootData) { int nArrayItems = 0; int i = 0;
strRegPath +=_T("\\Parameters\\Virtual Roots"); CRegKey regVR( HKEY_LOCAL_MACHINE, strRegPath); if ((HKEY) regVR) { nArrayItems = (int)strArryOfVrootNames.GetSize(); // if the CString arrays are empty then we won't ever process anything (nArrayItems is 1 based)
for (i = 0; i < nArrayItems; i++ ) { regVR.SetValue(strArryOfVrootNames[i], strArryOfVrootData[i]); iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("Array[%d]:%s=%s\n"),i,strArryOfVrootNames[i], strArryOfVrootData[i])); } } return; }
void Upgrade_WolfPack() { iisDebugOut_Start(_T("Upgrade_WolfPack"),LOG_TYPE_TRACE);
CRegKey regClusSvc(HKEY_LOCAL_MACHINE, scClusterPath, KEY_READ); if ( (HKEY)regClusSvc ) { CString csPath; TCHAR szPath[MAX_PATH]; if (regClusSvc.QueryValue(_T("ImagePath"), csPath) == NERR_Success) { // string is formatted like this
// %SystemRoot%\cluster\clusprxy.exe
// Find the last \ and trim and paste the new file name on
csPath = csPath.Left(csPath.ReverseFind('\\')); if ( csPath.IsEmpty() ) { ASSERT(TRUE); return; } csPath += _T("\\iisclex3.dll"); if ( ExpandEnvironmentStrings( (LPCTSTR)csPath,szPath,sizeof(szPath)/sizeof(TCHAR))) { // in iis3.0 the resources were called 'IIS Virtual Root'
// in iis4.0 it is something else (iis50 is the same as iis4)
UnregisterIisServerInstanceResourceType(L"IIS Virtual Root",(LPTSTR)szPath,TRUE,TRUE); } else { ASSERT(TRUE); } }
ProcessSection(g_pTheApp->m_hInfHandle, _T("Wolfpack_Upgrade")); } iisDebugOut_End(_T("Upgrade_WolfPack"),LOG_TYPE_TRACE); }
/****************************************************
* * Known "problem": If a resource doesn't come offline after the five * retries than the function continues to try to take the other iis resources * offline but there is no error reported. You could change this pretty simply I think. * *****************************************************/ DWORD BringALLIISClusterResourcesOffline() { //
// The return code
//
DWORD dwError = ERROR_SUCCESS; //
// Handle for the cluster
//
HCLUSTER hCluster = NULL;
//
// Handle for the cluster enumerator
//
HCLUSENUM hClusResEnum = NULL;
//
// Handle to a resource
//
HRESOURCE hResource = NULL;
//
// The index of the resources we're taking offline
//
DWORD dwResourceIndex = 0;
//
// The type cluster object being enumerated returned by the ClusterEnum function
//
DWORD dwObjectType = 0;
//
// The name of the cluster resource returned by the ClusterEnum function
//
LPWSTR lpwszResourceName = NULL; //
// The return code from the call to ClusterEnum
//
DWORD dwResultClusterEnum = ERROR_SUCCESS;
//
// The size of the buffer (in characters) that is used to hold the resource name's length
//
DWORD dwResourceNameBufferLength = INITIAL_RESOURCE_NAME_SIZE;
//
// Size of the resource name passed to and returned by the ClusterEnum function
//
DWORD dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
BOOL iClusDependsOnIISServices = FALSE;
//
// Open the cluster
//
hCluster = OpenCluster(NULL);
if ( hCluster == NULL ) { dwError = GetLastError(); // This will fail with RPC_S_SERVER_UNAVAILABLE "The RPC server is unavailable" if there is no cluster on this system
if (hCluster == NULL) { if ( (dwError != RPC_S_SERVER_UNAVAILABLE) && (dwError != EPT_S_NOT_REGISTERED ) ) { iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOffline:OpenCluster failed err=0x%x.\n"),dwError)); } } else { iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOffline:OpenCluster failed err=0x%x.\n"),dwError)); } goto clean_up; }
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("BringALLIISClusterResourcesOffline:start.\n")));
//
// Get Enumerator for the cluster resouces
//
hClusResEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE );
if ( hClusResEnum == NULL ) { dwError = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOffline:ClusterOpenEnum failed err=0x%x.\n"),dwError)); goto clean_up; } //
// Enumerate the Resources in the cluster
//
//
// Allocate memory to hold the cluster resource name as we enumerate the resources
//
lpwszResourceName = (LPWSTR) LocalAlloc(LPTR, dwResourceNameBufferLength * sizeof(WCHAR));
if ( lpwszResourceName == NULL ) { dwError = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOffline:LocalAlloc failed err=0x%x.\n"),dwError)); goto clean_up; }
//
// Enumerate all of the resources in the cluster and take the IIS Server Instance's offline
//
dwResultClusterEnum = ClusterEnum(hClusResEnum, dwResourceIndex, &dwObjectType, lpwszResourceName, &dwClusterEnumResourceNameLength );
while( ERROR_NO_MORE_ITEMS != dwResultClusterEnum ) { //
// If we have a resource's name
//
if( ERROR_SUCCESS == dwResultClusterEnum ) { hResource = OpenClusterResource( hCluster, lpwszResourceName );
if ( hResource == NULL ) { dwError = GetLastError(); break; }
// If the resource type is "IIS Server Instance", or some other one that is
// dependent upon the iis services, then we need to stop it.
iClusDependsOnIISServices = CheckForIISDependentClusters(hResource); if (iClusDependsOnIISServices) { CLUSTER_RESOURCE_STATE TheState = GetClusterResourceState(hResource,NULL,0,NULL,0); if (TheState == ClusterResourceOnline || TheState == ClusterResourceOnlinePending) { HKEY hKey = GetClusterResourceKey( hResource, KEY_READ );
if ( hKey ) { //
// Get the resource name.
//
LPWSTR lpwsResourceName = NULL; lpwsResourceName = GetParameter( hKey, L"Name" ); if ( lpwsResourceName != NULL ) { // this is a resource which we will try to stop
// so we should save the name somewhere in like a global list
iisDebugOut((LOG_TYPE_TRACE, _T("OfflineClusterResource:'%s'\n"),lpwsResourceName)); ListOfClusResources_Add(lpwsResourceName); } if (lpwsResourceName){LocalFree((LPWSTR) lpwsResourceName);}
ClusterRegCloseKey(hKey); }
//
// If the resource doesn't come offline quickly then wait
//
if ( ERROR_IO_PENDING == OfflineClusterResource( hResource ) ) { for(int iRetry=0; iRetry < MAX_OFFLINE_RETRIES; iRetry++) { Sleep( DELAY_BETWEEN_CALLS_TO_OFFLINE );
if ( ERROR_SUCCESS == OfflineClusterResource( hResource ) ) { break; } } } } CloseClusterResource( hResource ); } dwResourceIndex++; dwResultClusterEnum = ClusterEnum(hClusResEnum, dwResourceIndex, &dwObjectType, lpwszResourceName, &dwClusterEnumResourceNameLength ); } //
// If the buffer wasn't large enough then retry with a larger buffer
//
if( ERROR_MORE_DATA == dwResultClusterEnum ) { //
// Set the buffer size to the required size reallocate the buffer
//
LPWSTR lpwszResourceNameTmp = lpwszResourceName;
//
// After returning from ClusterEnum dwClusterEnumResourceNameLength
// doesn't include the null terminator character
//
dwResourceNameBufferLength = dwClusterEnumResourceNameLength + 1; lpwszResourceName = (LPWSTR) LocalReAlloc (lpwszResourceName, dwResourceNameBufferLength * sizeof(WCHAR), 0);
if ( !lpwszResourceName ) { dwError = GetLastError();
LocalFree( lpwszResourceNameTmp ); lpwszResourceNameTmp = NULL; break; } }
//
// Reset dwResourceNameLength with the size of the number of characters in the buffer
// You have to do this because everytime you call ClusterEnum is sets your buffer length
// argument to the number of characters in the string it's returning.
//
dwClusterEnumResourceNameLength = dwResourceNameBufferLength; }
clean_up:
if ( lpwszResourceName ) { LocalFree( lpwszResourceName ); lpwszResourceName = NULL; } if ( hClusResEnum ) { ClusterCloseEnum( hClusResEnum ); hClusResEnum = NULL; }
if ( hCluster ) { CloseCluster( hCluster ); hCluster = NULL; }
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("BringALLIISClusterResourcesOffline:end.ret=0x%x\n"),dwError)); return dwError; }
DWORD BringALLIISClusterResourcesOnline() { //
// The return code
//
DWORD dwError = ERROR_SUCCESS;
//
// Handle for the cluster
//
HCLUSTER hCluster = NULL;
//
// Handle for the cluster enumerator
//
HCLUSENUM hClusResEnum = NULL;
//
// Handle to a resource
//
HRESOURCE hResource = NULL;
//
// The index of the resources we're taking offline
//
DWORD dwResourceIndex = 0;
//
// The type cluster object being enumerated returned by the ClusterEnum function
//
DWORD dwObjectType = 0;
//
// The name of the cluster resource returned by the ClusterEnum function
//
LPWSTR lpwszResourceName = NULL;
//
// The return code from the call to ClusterEnum
//
DWORD dwResultClusterEnum = ERROR_SUCCESS;
//
// The size of the buffer (in characters) that is used to hold the resource name's length
//
DWORD dwResourceNameBufferLength = INITIAL_RESOURCE_NAME_SIZE;
//
// Size of the resource name passed to and returned by the ClusterEnum function
//
DWORD dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
BOOL iClusDependsOnIISServices = FALSE;
//
// Open the cluster
//
hCluster = OpenCluster(NULL);
if ( !hCluster ) { dwError = GetLastError(); // This will fail with RPC_S_SERVER_UNAVAILABLE "The RPC server is unavailable" if there is no cluster on this system
if (hCluster == NULL) { if ( (dwError != RPC_S_SERVER_UNAVAILABLE) && (dwError != EPT_S_NOT_REGISTERED ) ) { iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOnline:OpenCluster failed err=0x%x.\n"),dwError)); } } else { iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOnline:OpenCluster failed err=0x%x.\n"),dwError)); } goto clean_up; }
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("BringALLIISClusterResourcesOnline:end.ret=0x%x\n"),dwError));
//
// Get Enumerator for the cluster resouces
//
hClusResEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE );
if ( !hClusResEnum ) { dwError = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOnline:ClusterOpenEnum failed err=0x%x.\n"),dwError)); goto clean_up; } //
// Enumerate the Resources in the cluster
//
//
// Allocate memory to hold the cluster resource name as we enumerate the resources
//
lpwszResourceName = (LPWSTR) LocalAlloc(LPTR, dwResourceNameBufferLength * sizeof(WCHAR));
if ( !lpwszResourceName ) { dwError = GetLastError(); iisDebugOut((LOG_TYPE_ERROR, _T("BringALLIISClusterResourcesOnline:LocalAlloc failed err=0x%x.\n"),dwError)); goto clean_up; }
//
// Enumerate all of the resources in the cluster and take the IIS Server Instance's offline
//
while( ERROR_NO_MORE_ITEMS != (dwResultClusterEnum = ClusterEnum(hClusResEnum, dwResourceIndex, &dwObjectType, lpwszResourceName, &dwClusterEnumResourceNameLength )) ) { //
// If we have a resource's name
//
if( ERROR_SUCCESS == dwResultClusterEnum ) {
hResource = OpenClusterResource( hCluster, lpwszResourceName );
if ( !hResource ) { dwError = GetLastError(); break; }
// If the resource type is "IIS Server Instance", or some other one that is
// dependent upon the iis services, then we probably stopped, it.
iClusDependsOnIISServices = CheckForIISDependentClusters(hResource); if (iClusDependsOnIISServices) { CLUSTER_RESOURCE_STATE TheState = GetClusterResourceState(hResource,NULL,0,NULL,0); if (TheState == ClusterResourceOffline || TheState == ClusterResourceOfflinePending) { int iRestart = FALSE; LPWSTR lpwsResourceName = NULL;
HKEY hKey; hKey = GetClusterResourceKey( hResource, KEY_READ );
if ( hKey ) { //
// Get the resource name.
//
lpwsResourceName = GetParameter( hKey, L"Name" ); if ( lpwsResourceName != NULL ) { iRestart = ListOfClusResources_Check(lpwsResourceName); } ClusterRegCloseKey(hKey); }
if (TRUE == iRestart) { iisDebugOut((LOG_TYPE_TRACE, _T("OnlineClusterResource:'%s'.\n"),lpwsResourceName)); OnlineClusterResource(hResource); if (lpwsResourceName){LocalFree((LPWSTR) lpwsResourceName);} } } } CloseClusterResource( hResource ); dwResourceIndex++; } //
// If the buffer wasn't large enough then retry with a larger buffer
//
if( ERROR_MORE_DATA == dwResultClusterEnum ) { //
// Set the buffer size to the required size reallocate the buffer
//
LPWSTR lpwszResourceNameTmp = lpwszResourceName;
//
// After returning from ClusterEnum dwClusterEnumResourceNameLength
// doesn't include the null terminator character
//
dwResourceNameBufferLength = dwClusterEnumResourceNameLength + 1; lpwszResourceName = (LPWSTR) LocalReAlloc (lpwszResourceName, dwResourceNameBufferLength * sizeof(WCHAR), 0);
if ( !lpwszResourceName ) { dwError = GetLastError();
LocalFree( lpwszResourceNameTmp ); lpwszResourceNameTmp = NULL; break; } }
//
// Reset dwResourceNameLength with the size of the number of characters in the buffer
// You have to do this because everytime you call ClusterEnum is sets your buffer length
// argument to the number of characters in the string it's returning.
//
dwClusterEnumResourceNameLength = dwResourceNameBufferLength; }
clean_up: if ( lpwszResourceName ) { LocalFree( lpwszResourceName ); lpwszResourceName = NULL; }
if ( hClusResEnum ) { ClusterCloseEnum( hClusResEnum ); hClusResEnum = NULL; }
if ( hCluster ) { CloseCluster( hCluster ); hCluster = NULL; }
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("BringALLIISClusterResourcesOnline:end.ret=0x%x\n"),dwError)); return dwError; }
LPWSTR GetParameter( IN HKEY ClusterKey, IN LPCWSTR ValueName ) /*++
Routine Description:
Reads a REG_SZ parameter from the cluster regitry, and allocates the necessary storage for it.
Arguments:
ClusterKey - supplies the cluster key where the parameter is stored.
ValueName - supplies the name of the value.
Return Value:
A pointer to a buffer containing the parameter value on success.
NULL on failure.
--*/ { LPWSTR value = NULL; DWORD valueLength; DWORD valueType; DWORD status;
valueLength = 0; status = ClusterRegQueryValue( ClusterKey,ValueName,&valueType,NULL,&valueLength ); if ( (status != ERROR_SUCCESS) && (status != ERROR_MORE_DATA) ) { SetLastError(status); return(NULL); } if ( valueType == REG_SZ ) { valueLength += sizeof(UNICODE_NULL); }
value = (LPWSTR) LocalAlloc(LMEM_FIXED, valueLength); if ( value == NULL ) {return(NULL);} status = ClusterRegQueryValue(ClusterKey,ValueName,&valueType,(LPBYTE)value,&valueLength); if ( status != ERROR_SUCCESS) { LocalFree(value); SetLastError(status); value = NULL; } return(value); }
INT CheckForIISDependentClusters(HRESOURCE hResource) { INT iReturn = FALSE;
// If the resource type is "IIS Server Instance",
// "SMTP Server Instance" or "NNTP Server Instance" then take it offline
iReturn = ResUtilResourceTypesEqual(IIS_RESOURCE_TYPE_NAME, hResource); if (!iReturn){iReturn = ResUtilResourceTypesEqual(SMTP_RESOURCE_TYPE_NAME, hResource);} if (!iReturn){iReturn = ResUtilResourceTypesEqual(NNTP_RESOURCE_TYPE_NAME, hResource);}
// check for other ones which might be listed in the inf file!
if (!iReturn && g_pTheApp->m_hInfHandle) { CStringList strList; TSTR strTheSection;
if ( strTheSection.Copy( _T("ClusterResType_DependsonIIS") ) && GetSectionNameToDo(g_pTheApp->m_hInfHandle, &strTheSection) ) { if (ERROR_SUCCESS == FillStrListWithListOfSections(g_pTheApp->m_hInfHandle, strList, strTheSection.QueryStr() )) { // loop thru the list returned back
if (strList.IsEmpty() == FALSE) { POSITION pos; CString csEntry;
pos = strList.GetHeadPosition(); while (pos) { csEntry = strList.GetAt(pos);
int iTempReturn = FALSE; iTempReturn = ResUtilResourceTypesEqual(csEntry, hResource); if (iTempReturn) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("CheckForIISDependentClusters:yes='%s'\n"),csEntry)); iReturn = TRUE; break; } strList.GetNext(pos); } } } } }
return iReturn; }
DWORD WINAPI DoesThisServiceTypeExistInCluster(PVOID pInfo) { INT iTemp = FALSE; CLUSTER_SVC_INFO_FILL_STRUCT * pMyStructOfInfo; pMyStructOfInfo = (CLUSTER_SVC_INFO_FILL_STRUCT *) pInfo;
//pMyStructOfInfo->szTheClusterName
//pMyStructOfInfo->pszTheServiceType
//pMyStructOfInfo->csTheReturnServiceResName
//pMyStructOfInfo->dwReturnStatus
//
// The return code
//
DWORD dwReturn = ERROR_NOT_FOUND; pMyStructOfInfo->dwReturnStatus = dwReturn;
//
// Handle for the cluster
//
HCLUSTER hCluster = NULL;
//
// Handle for the cluster enumerator
//
HCLUSENUM hClusResEnum = NULL;
//
// Handle to a resource
//
HRESOURCE hResource = NULL;
//
// The index of the resources we're taking offline
//
DWORD dwResourceIndex = 0;
//
// The type cluster object being enumerated returned by the ClusterEnum function
//
DWORD dwObjectType = 0;
//
// The name of the cluster resource returned by the ClusterEnum function
//
LPWSTR lpwszResourceName = NULL; //
// The return code from the call to ClusterEnum
//
DWORD dwResultClusterEnum = ERROR_SUCCESS;
//
// The size of the buffer (in characters) that is used to hold the resource name's length
//
DWORD dwResourceNameBufferLength = INITIAL_RESOURCE_NAME_SIZE;
//
// Size of the resource name passed to and returned by the ClusterEnum function
//
DWORD dwClusterEnumResourceNameLength = dwResourceNameBufferLength;
//
// Open the cluster
//
hCluster = OpenCluster(pMyStructOfInfo->szTheClusterName); if( !hCluster ) { dwReturn = GetLastError(); goto DoesThisServiceTypeExistInCluster_Exit; }
//
// Get Enumerator for the cluster resouces
//
hClusResEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_RESOURCE );
if ( !hClusResEnum ) { dwReturn = GetLastError(); goto DoesThisServiceTypeExistInCluster_Exit; }
//
// Enumerate the Resources in the cluster
//
//
// Allocate memory to hold the cluster resource name as we enumerate the resources
//
lpwszResourceName = (LPWSTR) LocalAlloc(LPTR, dwResourceNameBufferLength * sizeof(WCHAR));
if ( !lpwszResourceName ) { dwReturn = GetLastError(); goto DoesThisServiceTypeExistInCluster_Exit; }
//
// Enumerate all of the resources in the cluster
//
while( ERROR_NO_MORE_ITEMS != (dwResultClusterEnum = ClusterEnum(hClusResEnum,dwResourceIndex,&dwObjectType,lpwszResourceName,&dwClusterEnumResourceNameLength)) ) { //
// If we have a resource's name
//
if( ERROR_SUCCESS == dwResultClusterEnum ) { hResource = OpenClusterResource( hCluster, lpwszResourceName );
if ( !hResource ) { dwReturn = GetLastError(); break; }
// If the resource type is "IIS Server Instance", or one that depends upon iis like smtp or nntp then
// check further to see if they have our services (W3SVC or MSFTPSVC)
iTemp = ResUtilResourceTypesEqual(IIS_RESOURCE_TYPE_NAME, hResource); if (!iTemp){iTemp = ResUtilResourceTypesEqual(SMTP_RESOURCE_TYPE_NAME, hResource);} if (!iTemp){iTemp = ResUtilResourceTypesEqual(NNTP_RESOURCE_TYPE_NAME, hResource);}
if (TRUE == iTemp) { // if the resource hangs it will hang on this call
pMyStructOfInfo->dwReturnStatus = ERROR_INVALID_BLOCK; if (ERROR_SUCCESS == IsResourceThisTypeOfService(hResource, pMyStructOfInfo->pszTheServiceType)) { CString csResName; //
// Yes! we found it
//
dwReturn = ERROR_SUCCESS;
// Display the resource name for fun
if (TRUE == GetClusterResName(hResource, &csResName)) { // copy it to the return string
*pMyStructOfInfo->csTheReturnServiceResName = csResName; }
CloseClusterResource( hResource ); goto DoesThisServiceTypeExistInCluster_Exit; } dwReturn = ERROR_NOT_FOUND; CloseClusterResource( hResource ); } dwResourceIndex++; }
//
// If the buffer wasn't large enough then retry with a larger buffer
//
if( ERROR_MORE_DATA == dwResultClusterEnum ) { //
// Set the buffer size to the required size reallocate the buffer
//
LPWSTR lpwszResourceNameTmp = lpwszResourceName;
//
// After returning from ClusterEnum dwClusterEnumResourceNameLength
// doesn't include the null terminator character
//
dwResourceNameBufferLength = dwClusterEnumResourceNameLength + 1; lpwszResourceName = (LPWSTR) LocalReAlloc (lpwszResourceName, dwResourceNameBufferLength * sizeof(WCHAR), 0);
if ( !lpwszResourceName ) { dwReturn = GetLastError();
LocalFree( lpwszResourceNameTmp ); lpwszResourceNameTmp = NULL; break; } }
//
// Reset dwResourceNameLength with the size of the number of characters in the buffer
// You have to do this because everytime you call ClusterEnum is sets your buffer length
// argument to the number of characters in the string it's returning.
//
dwClusterEnumResourceNameLength = dwResourceNameBufferLength; }
DoesThisServiceTypeExistInCluster_Exit: if ( lpwszResourceName ) { LocalFree( lpwszResourceName ); lpwszResourceName = NULL; } if ( hClusResEnum ) { ClusterCloseEnum( hClusResEnum ); hClusResEnum = NULL; }
if ( hCluster ) { CloseCluster( hCluster ); hCluster = NULL; }
pMyStructOfInfo->dwReturnStatus = dwReturn; return dwReturn; }
DWORD IsResourceThisTypeOfService(HRESOURCE hResource, LPWSTR pszTheServiceType) { DWORD dwReturn = ERROR_NOT_FOUND; HINSTANCE hClusapi = NULL; HINSTANCE hResutils = NULL;
PFN_CLUSTERRESOURCECONTROL pfnClusterResourceControl; PFN_RESUTILFINDSZPROPERTY pfnResUtilFindSzProperty;
//
// Initial size of the buffer
//
DWORD dwBufferSize = 256; //
// The requested buffer size, and the number of bytes actually in the returned buffer
//
DWORD dwRequestedBufferSize = dwBufferSize;
//
// Result from the call to the cluster resource control function
//
DWORD dwResult;
//
// Buffer that holds the property list for this resource
//
LPVOID lpvPropList = NULL;
//
// The Proivate property that is being read
//
LPWSTR lpwszPrivateProp = NULL;
//
// Load cluster dll's
//
hClusapi = LoadLibrary( L"clusapi.dll" ); if (!hClusapi) { dwReturn = ERROR_PATH_NOT_FOUND; goto IsResourceThisTypeOfService_Exit; }
pfnClusterResourceControl = (PFN_CLUSTERRESOURCECONTROL)GetProcAddress( hClusapi, "ClusterResourceControl" ); if (!pfnClusterResourceControl) { dwReturn = ERROR_PROC_NOT_FOUND; goto IsResourceThisTypeOfService_Exit; }
hResutils = LoadLibrary( L"resutils.dll" ); if (!hResutils) { dwReturn = ERROR_PATH_NOT_FOUND; goto IsResourceThisTypeOfService_Exit; } pfnResUtilFindSzProperty = (PFN_RESUTILFINDSZPROPERTY)GetProcAddress( hResutils, "ResUtilFindSzProperty" ); if (!pfnResUtilFindSzProperty) { dwReturn = ERROR_PROC_NOT_FOUND; goto IsResourceThisTypeOfService_Exit; }
//
// Allocate memory for the resource type
//
lpvPropList = (LPWSTR) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufferSize * sizeof(WCHAR) ); if( lpvPropList == NULL) { lpvPropList = NULL; dwReturn = ERROR_OUTOFMEMORY; goto IsResourceThisTypeOfService_Exit; }
//
// Allocate memory for the Property
//
lpwszPrivateProp = (LPWSTR) HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, (_MAX_PATH+_MAX_PATH+1) * sizeof(WCHAR) ); if( lpwszPrivateProp == NULL) { lpvPropList = NULL; dwReturn = ERROR_OUTOFMEMORY; goto IsResourceThisTypeOfService_Exit; } //
// Get the resource's private properties (Service , InstanceId)
//
while( 1 ) { dwResult = pfnClusterResourceControl(hResource,NULL,CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES,NULL,0,lpvPropList,dwBufferSize,&dwRequestedBufferSize ); if( ERROR_SUCCESS == dwResult ) {
// ---------------------
// what the entries are:
// AccessMask (dword) = 5
// Alias (string) = "virtual dir name"
// Directory (string) = "c:\la\lalalala"
// ServiceName (string) = W3SVC, MSFTPSVC, GOPHERSVC
// ---------------------
//
// Get the "ServiceName" entry
//
dwResult = pfnResUtilFindSzProperty( lpvPropList, &dwRequestedBufferSize, L"ServiceName", &lpwszPrivateProp); if( dwResult != ERROR_SUCCESS ) { dwReturn = dwResult; goto IsResourceThisTypeOfService_Exit; }
if (_wcsicmp(lpwszPrivateProp, pszTheServiceType) == 0) { // Okay, we found at least 1 service name that matches
// the one that was passed -- which we're supposed to look for
// return success
dwReturn = ERROR_SUCCESS; } goto IsResourceThisTypeOfService_Exit; }
if( ERROR_MORE_DATA == dwResult ) { LPVOID lpdPropListTemp = lpvPropList; //
// Set the buffer size to the required size reallocate the buffer
//
dwBufferSize = ++dwRequestedBufferSize;
lpvPropList = (LPWSTR) HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, lpvPropList, dwBufferSize * sizeof(WCHAR) ); if ( lpvPropList == NULL) { if ( lpdPropListTemp ) { HeapFree( GetProcessHeap(), 0, lpdPropListTemp ); } dwReturn = ERROR_OUTOFMEMORY; goto IsResourceThisTypeOfService_Exit; } } }
IsResourceThisTypeOfService_Exit: if (lpwszPrivateProp) {HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpwszPrivateProp);} if (lpvPropList) {HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpvPropList);} if (hClusapi) {FreeLibrary(hClusapi);} if (hResutils) {FreeLibrary(hClusapi);} return dwReturn; }
INT GetClusterResName(HRESOURCE hResource, CString * csReturnedName) { int iReturn = FALSE; HKEY hKey = GetClusterResourceKey( hResource, KEY_READ );
if ( hKey ) { //
// Get the resource name.
//
LPWSTR lpwsResourceName = NULL; lpwsResourceName = GetParameter( hKey, L"Name" ); if ( lpwsResourceName != NULL ) { //wcscpy(csReturnedName,lpwsResourceName);
*csReturnedName = lpwsResourceName; iReturn = TRUE; } if (lpwsResourceName){LocalFree((LPWSTR) lpwsResourceName);}
ClusterRegCloseKey(hKey); } return iReturn; }
INT DoClusterServiceCheck(CLUSTER_SVC_INFO_FILL_STRUCT * pMyStructOfInfo) { int iReturn = FALSE; DWORD ThreadID = 0; DWORD status = 0; HANDLE hMyThread = CreateThread(NULL,0,DoesThisServiceTypeExistInCluster,pMyStructOfInfo,0,&ThreadID); if (hMyThread) { // wait for 30 secs only
DWORD res = WaitForSingleObject(hMyThread,30*1000); if (res == WAIT_TIMEOUT) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ERROR DoClusterServiceCheck thread never finished...\n"))); GetExitCodeThread(hMyThread, &status); if (status == STILL_ACTIVE) { if (hMyThread != NULL) {TerminateThread(hMyThread, 0);} } } else { GetExitCodeThread(hMyThread, &status); if (status == STILL_ACTIVE) { if (hMyThread != NULL) {TerminateThread(hMyThread, 0);} } else { if (ERROR_SUCCESS == status) {iReturn = TRUE;} }
if (hMyThread != NULL) {CloseHandle(hMyThread);} } }
return iReturn; }
INT DoesClusterServiceExist(void) { if (-1 == g_ClusterSVCExist) { CRegKey regClusSvc(HKEY_LOCAL_MACHINE, scClusterPath2, KEY_READ); if ( (HKEY) regClusSvc ) { g_ClusterSVCExist = 1; } else { g_ClusterSVCExist = 0; } } return g_ClusterSVCExist; } #endif //_CHICAGO_
|