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.
256 lines
8.1 KiB
256 lines
8.1 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1995, Microsoft Corporation
|
|
//
|
|
// File: dfsclustersupport.cxx
|
|
//
|
|
// Contents: DfsClusterSupport
|
|
//
|
|
// Classes:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "DfsClusterSupport.hxx"
|
|
|
|
typedef struct _DFS_CLUSTER_CONTEXT {
|
|
PUNICODE_STRING pShareName;
|
|
PUNICODE_STRING pVSName ;
|
|
|
|
} DFS_CLUSTER_CONTEXT;
|
|
|
|
DWORD
|
|
ClusterCallBackFunction(
|
|
HRESOURCE hSelf,
|
|
HRESOURCE hResource,
|
|
PVOID Context)
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER( hSelf );
|
|
|
|
HKEY HKey = NULL;
|
|
HKEY HParamKey = NULL;
|
|
ULONG NameSize = MAX_PATH;
|
|
WCHAR ClusterName[MAX_PATH];
|
|
DFS_CLUSTER_CONTEXT *pContext = (DFS_CLUSTER_CONTEXT *)Context;
|
|
LPWSTR ResShareName = NULL;
|
|
UNICODE_STRING VsName;
|
|
|
|
DWORD Status = ERROR_SUCCESS;
|
|
DWORD TempStatus;
|
|
DWORD Value = 0;
|
|
|
|
HKey = GetClusterResourceKey(hResource, KEY_READ);
|
|
|
|
if (HKey == NULL)
|
|
{
|
|
Status = GetLastError();
|
|
return Status;
|
|
}
|
|
|
|
TempStatus = ClusterRegOpenKey( HKey,
|
|
L"Parameters",
|
|
KEY_READ,
|
|
&HParamKey );
|
|
ClusterRegCloseKey( HKey );
|
|
|
|
//
|
|
// Apparently there can be (small) window during which a resource may not
|
|
// have the Parameters key set. In such a case, we should keep enumerating,
|
|
// so don't return an error.
|
|
//
|
|
if (TempStatus != ERROR_SUCCESS)
|
|
{
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// Find the logical share name to see if that's what we've been looking for.
|
|
ResShareName = ResUtilGetSzValue( HParamKey,
|
|
L"ShareName" );
|
|
|
|
//
|
|
// It is possible for a Share resource to be configured without the sharename parameter
|
|
// set. In such a case this function shouldn't return an error; we need to keep enumerating.
|
|
//
|
|
if (ResShareName != NULL)
|
|
{
|
|
Status = DfsRtlInitUnicodeStringEx(&VsName, ResShareName);
|
|
if(Status == ERROR_SUCCESS)
|
|
{
|
|
if (pContext->pShareName->Length == VsName.Length)
|
|
{
|
|
//
|
|
// Look to see if this is a dfs root. It is legitimate to find
|
|
// this property not set, so don't propagate the return status. We shouldn't terminate
|
|
// our enumeration just because this property doesn't exist on this resource.
|
|
//
|
|
TempStatus = ResUtilGetDwordValue(HParamKey, L"IsDfsRoot", &Value, 0);
|
|
|
|
if ((ERROR_SUCCESS == TempStatus) &&
|
|
(Value == 1))
|
|
{
|
|
|
|
if (_wcsnicmp(pContext->pShareName->Buffer,
|
|
VsName.Buffer,
|
|
VsName.Length) == 0)
|
|
{
|
|
//
|
|
// We've found what we wanted. Grab the virtual-cluster name
|
|
// and return that in a separately allocated string.
|
|
// We know for a fact that the dfs root name can't be
|
|
// longer than MAX_PATH. So we don't bother checking for
|
|
// ERROR_MORE_DATA.
|
|
//
|
|
if ((GetClusterResourceNetworkName( hResource,
|
|
ClusterName,
|
|
&NameSize )) == TRUE)
|
|
{
|
|
ASSERT(pContext->pVSName->Buffer == NULL);
|
|
Status = DfsCreateUnicodeStringFromString( pContext->pVSName,
|
|
ClusterName );
|
|
//
|
|
// Return ERROR_NO_MORE_ITEMS to ResUtilEnumResources so that
|
|
// the enumeration will get terminated, but the return status to
|
|
// GetRootClusterInformation will be SUCCESS.
|
|
//
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
Status = ERROR_NO_MORE_ITEMS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Return this error and terminate the enumeration.
|
|
Status = GetLastError();
|
|
ASSERT( Status != ERROR_MORE_DATA );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LocalFree( ResShareName );
|
|
}
|
|
|
|
ClusterRegCloseKey( HParamKey );
|
|
|
|
return Status;
|
|
}
|
|
#if 0
|
|
|
|
DoNotUse()
|
|
{
|
|
|
|
DWORD Status = ERROR_SUCCESS;
|
|
DWORD BufSize = ClusDocEx_DEFAULT_CB;
|
|
LPVOID pOutBuffer = NULL;
|
|
DWORD ControlCode = CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES;
|
|
|
|
pOutBuffer = new BYTE [ BufSize ];
|
|
|
|
if( pOutBuffer == NULL )
|
|
{
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
Status = ClusterResourceControl( hResource, // resource handle
|
|
NULL,
|
|
ControlCode,
|
|
NULL, // input buffer (not used)
|
|
0, // input buffer size (not used)
|
|
pOutBuffer, // output buffer: property list
|
|
OutBufferSize, // allocated buffer size (bytes)
|
|
pBytesReturned );
|
|
|
|
|
|
dwResult = ResUtilFindDwordProperty( lpPropList,
|
|
cbPropListSize,
|
|
lpszPropName,
|
|
lpdwPropValue );
|
|
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Guarantees that the pVSName is allocated upon SUCCESS.
|
|
// Caller needs to free it with DfsFreeUnicodeString.
|
|
//
|
|
DWORD
|
|
GetRootClusterInformation(
|
|
PUNICODE_STRING pShareName,
|
|
PUNICODE_STRING pVSName )
|
|
|
|
{
|
|
DWORD Status;
|
|
DFS_CLUSTER_CONTEXT Context;
|
|
|
|
(VOID)RtlInitUnicodeString( pVSName, NULL );
|
|
Context.pShareName = pShareName;
|
|
Context.pVSName = pVSName;
|
|
|
|
Status = ResUtilEnumResources(NULL,
|
|
L"File Share",
|
|
ClusterCallBackFunction,
|
|
(PVOID)&Context );
|
|
|
|
//
|
|
// ClusterCallbackFunction above returns ERROR_NO_MORE_ITEMS
|
|
// to ResUtilEnumResources to terminate the enumeration. ResUtilEnumResources
|
|
// converts that error code to SUCCESS. So, under the current behavior it isn't possible
|
|
// for us to have allocated the VSName and still get an error. The following is a feeble
|
|
// attempt to not be dependent on that unadvertised behavior.
|
|
//
|
|
if ((Status != ERROR_SUCCESS) &&
|
|
(pVSName->Buffer != NULL))
|
|
{
|
|
// If we've allocated a VSName, we have succeeded.
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
// xxx Longhorn
|
|
else if (Status == ERROR_SUCCESS &&
|
|
pVSName->Buffer == NULL)
|
|
{
|
|
// Always return some error when the VSName isn't allocated.
|
|
Status = ERROR_NOT_FOUND;
|
|
}
|
|
*/
|
|
|
|
return Status;
|
|
|
|
|
|
}
|
|
|
|
DFSSTATUS
|
|
DfsClusterInit(
|
|
PBOOLEAN pIsCluster )
|
|
{
|
|
DFSSTATUS Status = ERROR_SUCCESS;
|
|
DWORD ClusterState;
|
|
|
|
*pIsCluster = FALSE;
|
|
|
|
Status = GetNodeClusterState( NULL, // local node
|
|
&ClusterState );
|
|
|
|
if (Status == ERROR_SUCCESS)
|
|
{
|
|
if ( (ClusterStateRunning == ClusterState) ||
|
|
(ClusterStateNotRunning == ClusterState) )
|
|
{
|
|
*pIsCluster = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|