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.
2102 lines
68 KiB
2102 lines
68 KiB
#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_
|
|
|