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.
518 lines
17 KiB
518 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
upgrade.c
|
|
|
|
Abstract:
|
|
|
|
code related to upgrade situations.
|
|
|
|
This currently covers upgrades to Windows Server 2003 either from NT4 or W2K. In
|
|
Windows Server 2003, netname now creates a computer object which is used by apps
|
|
like MSMQ. In the upgrade case, MSMQ has already create the computer object. If
|
|
Netname detects an existing computer object and Kerberos support is disabled, the
|
|
netname resource will not go online. This code enums the MSMQ resources
|
|
and enables Kerberos support on their dependent netname resources.
|
|
|
|
Test for MSMQ DS vs workgroup mode supplied by IlanH
|
|
|
|
Author:
|
|
|
|
Charlie Wickham (charlwi) 07-Nov-2001
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#define UNICODE 1
|
|
|
|
#include "clusres.h"
|
|
#include "netname.h"
|
|
|
|
#define FALCON_REG_KEY TEXT("SOFTWARE\\Microsoft\\MSMQ\\Parameters")
|
|
#define MSMQ_WORKGROUP_REGNAME TEXT("Workgroup")
|
|
|
|
//
|
|
// private routines
|
|
//
|
|
|
|
DWORD
|
|
NetNameMSMQEnumCallback(
|
|
HRESOURCE hSelf,
|
|
HRESOURCE MSMQRes,
|
|
PVOID pParameter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback routine for FixupNetnamesOnUpgrade. For a given MSMQ resource
|
|
(MSMQRes), get its dependent netname resource and set the RequireKerberos
|
|
property to one.
|
|
|
|
REMOVE AFTER THE NEXT MAJOR RELEASE OF NT AFTER RELEASE OF
|
|
WINDOWS XP/SERVER 2003
|
|
|
|
Arguments:
|
|
|
|
standard ResUtilEnumResources args - hSelf is not used; pParameter is a
|
|
pointer to a DWORD which is incremented when the RequireKerberos property
|
|
is set.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
#define RESNAME_CHARS 64
|
|
|
|
WCHAR msmqResNameBuffer[ RESNAME_CHARS ];
|
|
PWCHAR msmqResName = msmqResNameBuffer;
|
|
DWORD msmqBufferSize = RESNAME_CHARS * sizeof( *msmqResName );
|
|
WCHAR nnResName[ RESNAME_CHARS ];
|
|
DWORD status;
|
|
DWORD bytesReturned;
|
|
DWORD bufSize;
|
|
DWORD bytesRequired;
|
|
PDWORD updateCount = pParameter;
|
|
|
|
PVOID propList = NULL;
|
|
DWORD propListSize = 0;
|
|
|
|
HRESOURCE nnHandle = NULL;
|
|
|
|
struct _RESOURCE_PRIVATEPROPS {
|
|
DWORD RequireKerberos;
|
|
} privateProps;
|
|
|
|
RESUTIL_PROPERTY_ITEM privatePropTable[] = {
|
|
{ L"RequireKerberos", NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 0, 0,
|
|
FIELD_OFFSET( struct _RESOURCE_PRIVATEPROPS, RequireKerberos ) },
|
|
{ 0 }
|
|
};
|
|
|
|
//
|
|
// get the name of the MSMQ resource
|
|
//
|
|
retry_get_msmq_resname:
|
|
status = ClusterResourceControl( MSMQRes,
|
|
NULL,
|
|
CLUSCTL_RESOURCE_GET_NAME,
|
|
NULL,
|
|
0,
|
|
msmqResName,
|
|
msmqBufferSize,
|
|
&bytesReturned );
|
|
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
msmqResName = (PWCHAR)LocalAlloc( LMEM_FIXED, bytesReturned );
|
|
if ( msmqResName == NULL ) {
|
|
status = GetLastError();
|
|
} else {
|
|
msmqBufferSize = bytesReturned;
|
|
goto retry_get_msmq_resname;
|
|
}
|
|
}
|
|
|
|
if ( status != ERROR_SUCCESS ) {
|
|
(NetNameLogEvent)( L"rtNetwork Name",
|
|
LOG_ERROR,
|
|
L"Couldn't get name of MSMQ resource - status %u\n",
|
|
status );
|
|
msmqResName = NULL;
|
|
}
|
|
|
|
//
|
|
// get a handle to its dependent netname resource
|
|
//
|
|
nnHandle = ResUtilGetResourceDependency( MSMQRes, L"Network Name" );
|
|
if ( nnHandle != NULL ) {
|
|
|
|
//
|
|
// get the name of the netname resource
|
|
//
|
|
bufSize = RESNAME_CHARS;
|
|
if ( !GetClusterResourceNetworkName( MSMQRes, nnResName, &bufSize )) {
|
|
nnResName[ COUNT_OF( nnResName ) - 1 ] = UNICODE_NULL;
|
|
_snwprintf( nnResName,
|
|
COUNT_OF( nnResName ) - 1,
|
|
L"Dependent network name resource of '%ws'",
|
|
msmqResName);
|
|
}
|
|
|
|
//
|
|
// set our unknown prop to one
|
|
//
|
|
privateProps.RequireKerberos = 1;
|
|
|
|
//
|
|
// get the size of the prop list buffer
|
|
//
|
|
status = ResUtilPropertyListFromParameterBlock(privatePropTable,
|
|
NULL,
|
|
&propListSize,
|
|
(LPBYTE) &privateProps,
|
|
&bytesReturned,
|
|
&bytesRequired );
|
|
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
propList = LocalAlloc( LMEM_FIXED, bytesRequired );
|
|
if ( propList == NULL ) {
|
|
(NetNameLogEvent)( L"rtNetwork Name",
|
|
LOG_ERROR,
|
|
L"Unable to create property list for resource '%1!ws!'. error %2!u!\n",
|
|
nnResName,
|
|
GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
propListSize = bytesRequired;
|
|
|
|
status = ResUtilPropertyListFromParameterBlock(privatePropTable,
|
|
propList,
|
|
&propListSize,
|
|
(LPBYTE) &privateProps,
|
|
&bytesReturned,
|
|
&bytesRequired );
|
|
}
|
|
|
|
if ( status != ERROR_SUCCESS ) {
|
|
(NetNameLogEvent)( L"rtNetwork Name",
|
|
LOG_ERROR,
|
|
L"Couldn't create property list for resource '%1!ws!'. error %2!u!\n",
|
|
nnResName,
|
|
status);
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// set the RequireKerberos property to one for the netname resource
|
|
//
|
|
status = ClusterResourceControl( nnHandle,
|
|
NULL,
|
|
CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES,
|
|
propList,
|
|
propListSize,
|
|
NULL,
|
|
0,
|
|
NULL );
|
|
|
|
if ( status == ERROR_SUCCESS || status == ERROR_RESOURCE_PROPERTIES_STORED ) {
|
|
(NetNameLogEvent)( L"rtNetwork Name",
|
|
LOG_INFORMATION,
|
|
L"Successfully set RequireKerberos property for resource '%1!ws!'\n",
|
|
nnResName );
|
|
|
|
++*updateCount;
|
|
} else {
|
|
(NetNameLogEvent)( L"rtNetwork Name",
|
|
LOG_ERROR,
|
|
L"Failed to set RequireKerberos property for resource '%1!ws!' - status %2!u!\n",
|
|
nnResName,
|
|
status );
|
|
}
|
|
|
|
}
|
|
else {
|
|
(NetNameLogEvent)( L"rtNetwork Name",
|
|
LOG_ERROR,
|
|
L"Unable to get handle to dependent network name resource of MSMQ "
|
|
L"resource '%1!ws!' - status '%2!u!'. This resource may fail to go "
|
|
L"online.\n",
|
|
msmqResName,
|
|
GetLastError() );
|
|
}
|
|
|
|
cleanup:
|
|
if ( propList ) {
|
|
LocalFree( propList );
|
|
}
|
|
|
|
if ( nnHandle ) {
|
|
CloseClusterResource( nnHandle );
|
|
}
|
|
|
|
if ( msmqResName != NULL && msmqResName != msmqResNameBuffer ) {
|
|
LocalFree( msmqResName );
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} // NetNameMSMQEnumCallback
|
|
|
|
static BOOL
|
|
GetMsmqDWORDKeyValue(
|
|
LPCWSTR RegKey,
|
|
LPCWSTR RegName,
|
|
DWORD * Value
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read falcon DWORD registry key.
|
|
|
|
Arguments:
|
|
|
|
RegName - Registry name (under HKLM\msmq\parameters)
|
|
|
|
Return Value:
|
|
|
|
DWORD key value (0 if the key not exist)
|
|
|
|
--*/
|
|
|
|
{
|
|
HKEY hKey;
|
|
LONG regStatus;
|
|
DWORD valueType = REG_DWORD;
|
|
DWORD valueSize = sizeof(DWORD);
|
|
|
|
regStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
RegKey,
|
|
0,
|
|
KEY_READ,
|
|
&hKey
|
|
);
|
|
|
|
if ( regStatus != ERROR_SUCCESS) {
|
|
// printf("At this point MSMQ Registry must exist, rc = 0x%x\n", rc);
|
|
return FALSE;
|
|
}
|
|
|
|
*Value = 0;
|
|
regStatus = RegQueryValueEx( hKey,
|
|
RegName,
|
|
0L,
|
|
&valueType,
|
|
(BYTE *)Value,
|
|
&valueSize
|
|
);
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
if ( regStatus != ERROR_SUCCESS && regStatus != ERROR_FILE_NOT_FOUND ) {
|
|
// printf("We should get either ERROR_SUCCESS or ERROR_FILE_NOT_FOUND, rc = 0x%x\n", rc);
|
|
return FALSE;
|
|
}
|
|
|
|
// printf("%ls = %d\n", RegName, *Value);
|
|
return TRUE;
|
|
|
|
} // GetMsmqDWORDKeyValue
|
|
|
|
|
|
//
|
|
// public routines
|
|
//
|
|
|
|
BOOL
|
|
DoesMsmqNeedComputerObject(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD dwWorkGroup = 0;
|
|
|
|
if( !GetMsmqDWORDKeyValue( FALCON_REG_KEY, MSMQ_WORKGROUP_REGNAME, &dwWorkGroup )) {
|
|
return TRUE;
|
|
}
|
|
|
|
if(dwWorkGroup != 0) {
|
|
// printf("MSMQ in workgroup mode, no need for computer object\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// printf("MSMQ in domain mode, need computer object\n");
|
|
return TRUE;
|
|
} // DoesMsmqNeedComputerObject
|
|
|
|
DWORD
|
|
UpgradeMSMQDependentNetnameToKerberos(
|
|
PNETNAME_RESOURCE Resource
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
After an upgrade to XP, check if this netname is a provider for an MSMQ
|
|
resource. If so, set a flag that will set the RequireKerberos property to
|
|
one during the next online. We can't set the property at this point in
|
|
time since this routine is called when the API is read-only.
|
|
|
|
REMOVE AFTER THE NEXT MAJOR RELEASE OF NT AFTER RELEASE OF
|
|
WINDOWS XP/SERVER 2003
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
HCLUSTER clusterHandle;
|
|
HRESENUM providerEnum;
|
|
DWORD status;
|
|
|
|
(NetNameLogEvent)( Resource->ResourceHandle,
|
|
LOG_INFORMATION,
|
|
L"Kerberos Support Upgrade Check: this resource will be "
|
|
L"checked for a dependent MSMQ resources.\n");
|
|
|
|
//
|
|
// get a handle to the cluster since we'll need it later on
|
|
//
|
|
clusterHandle = OpenCluster( NULL );
|
|
if ( clusterHandle == NULL ) {
|
|
(NetNameLogEvent)( Resource->ResourceHandle,
|
|
LOG_ERROR,
|
|
L"Unable to open handle to the cluster - status %1!u!. Any MSMQ resource "
|
|
L"dependent on this resource may fail to go online.\n",
|
|
status = GetLastError() );
|
|
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// get a enum handle for this netname resource that will provide us a list
|
|
// of the resources that are dependent on this resource
|
|
//
|
|
// THIS CALL REQUIRES WORKER THREAD ONLY!!!
|
|
//
|
|
providerEnum = ClusterResourceOpenEnum( Resource->ClusterResourceHandle,
|
|
CLUSTER_RESOURCE_ENUM_PROVIDES );
|
|
|
|
if ( providerEnum != NULL ) {
|
|
DWORD enumIndex = 0;
|
|
PWCHAR nameBuffer;
|
|
WCHAR dependentResName[ 128 ];
|
|
DWORD nameBufferSize;
|
|
DWORD enumType;
|
|
|
|
do {
|
|
nameBuffer = dependentResName;
|
|
nameBufferSize = COUNT_OF( dependentResName );
|
|
|
|
enum_again:
|
|
//
|
|
// WORKER THREAD ONLY!!!!
|
|
//
|
|
status = ClusterResourceEnum( providerEnum,
|
|
enumIndex,
|
|
&enumType,
|
|
nameBuffer,
|
|
&nameBufferSize);
|
|
|
|
if ( status == ERROR_MORE_DATA ) {
|
|
//
|
|
// need more space for this resource's name; it's very
|
|
// unlikely that this code can be in a loop, but just in case,
|
|
// we'll free any previously allocated memory
|
|
//
|
|
if ( nameBuffer != NULL && nameBuffer != dependentResName ) {
|
|
LocalFree( nameBuffer );
|
|
}
|
|
|
|
nameBuffer = LocalAlloc( LMEM_FIXED, ++nameBufferSize * sizeof( WCHAR ));
|
|
if ( nameBuffer != NULL ) {
|
|
goto enum_again;
|
|
}
|
|
|
|
status = GetLastError();
|
|
}
|
|
else if ( status == ERROR_SUCCESS ) {
|
|
HRESOURCE dependentResource;
|
|
|
|
dependentResource = OpenClusterResource( clusterHandle, nameBuffer );
|
|
if ( dependentResource != NULL ) {
|
|
//
|
|
// if this resource is MSMQ, then mark this netname for kerberos support
|
|
//
|
|
if ( ResUtilResourceTypesEqual( CLUS_RESTYPE_NAME_MSMQ, dependentResource ) ||
|
|
ResUtilResourceTypesEqual( CLUS_RESTYPE_NAME_NEW_MSMQ, dependentResource ))
|
|
{
|
|
Resource->Params.RequireKerberos = TRUE;
|
|
|
|
status = ResUtilSetDwordValue( Resource->ParametersKey,
|
|
PARAM_NAME__REQUIRE_KERBEROS,
|
|
1,
|
|
NULL);
|
|
|
|
if ( status != ERROR_SUCCESS ) {
|
|
(NetNameLogEvent)( Resource->ResourceHandle,
|
|
LOG_ERROR,
|
|
L"Unable to set RequireKerberos property after an "
|
|
L"upgrade - status %1!u!. This resource requires that "
|
|
L"the RequireKerberos property be set to one in order "
|
|
L"for its dependent MSMQ resource to be successfully "
|
|
L"brought online.\n",
|
|
status);
|
|
} else {
|
|
(NetNameLogEvent)( Resource->ResourceHandle,
|
|
LOG_INFORMATION,
|
|
L"This resource has been upgraded for Kerberos Support due to "
|
|
L"the presence of a dependent MSMQ resource\n");
|
|
//
|
|
// stop enum'ing dependent resources
|
|
//
|
|
status = ERROR_NO_MORE_ITEMS;
|
|
}
|
|
}
|
|
|
|
CloseClusterResource( dependentResource );
|
|
} else {
|
|
(NetNameLogEvent)( Resource->ResourceHandle,
|
|
LOG_ERROR,
|
|
L"Unable to get a handle to cluster resource '%1!ws!' - status "
|
|
L"'%2!u!'. Any MSMQ resource dependent on this Network Name resource "
|
|
L"may fail to go online.\n",
|
|
status = GetLastError() );
|
|
}
|
|
}
|
|
else if ( status != ERROR_SUCCESS && status != ERROR_NO_MORE_ITEMS ) {
|
|
(NetNameLogEvent)( Resource->ResourceHandle,
|
|
LOG_ERROR,
|
|
L"Unable to enumerate resources dependent on this Network Name resource "
|
|
L" - status '%1!u!'. Any MSMQ resource dependent on this resource "
|
|
L"may fail to go online.\n",
|
|
status );
|
|
}
|
|
|
|
if ( nameBuffer != dependentResName ) {
|
|
LocalFree( nameBuffer );
|
|
}
|
|
|
|
++enumIndex;
|
|
} while ( status == ERROR_SUCCESS );
|
|
|
|
status = ClusterResourceCloseEnum( providerEnum );
|
|
} else {
|
|
(NetNameLogEvent)( Resource->ResourceHandle,
|
|
LOG_ERROR,
|
|
L"Unable to get handle enumerate the MSMQ dependent resources - status '%1!u!'. "
|
|
L"Any MSMQ resource dependent on this resource may fail to go online.\n",
|
|
GetLastError() );
|
|
}
|
|
|
|
CloseCluster( clusterHandle );
|
|
|
|
return status;
|
|
} // UpgradeMSMQDependentNetnameToKerberos
|
|
|
|
/* end upgrade.c */
|