//+---------------------------------------------------------------------------- // // 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; }