/*++ Copyright (c) 1997 Microsoft Corporation Module Name: netioctl.c Abstract: Network control functions. Author: John Vert (jvert) 2-Mar-1997 Revision History: --*/ #include "nmp.h" // // Network Common properties. // // // Read-Write Common Properties. // RESUTIL_PROPERTY_ITEM NmpNetworkCommonProperties[] = { { CLUSREG_NAME_NET_DESC, NULL, CLUSPROP_FORMAT_SZ, (DWORD_PTR) NmpNullString, 0, 0, 0, FIELD_OFFSET(NM_NETWORK_INFO, Description) }, { CLUSREG_NAME_NET_ROLE, NULL, CLUSPROP_FORMAT_DWORD, ClusterNetworkRoleClientAccess, ClusterNetworkRoleNone, ClusterNetworkRoleInternalAndClient, 0, FIELD_OFFSET(NM_NETWORK_INFO, Role) }, { 0 } }; // // Read-Only Common Properties. // RESUTIL_PROPERTY_ITEM NmpNetworkROCommonProperties[] = { { CLUSREG_NAME_NET_NAME, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY, FIELD_OFFSET(NM_NETWORK_INFO, Name) }, { CLUSREG_NAME_NET_ADDRESS, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY, FIELD_OFFSET(NM_NETWORK_INFO, Address) }, { CLUSREG_NAME_NET_ADDRESS_MASK, NULL, CLUSPROP_FORMAT_SZ, 0, 0, 0, RESUTIL_PROPITEM_READ_ONLY, FIELD_OFFSET(NM_NETWORK_INFO, AddressMask) }, { 0 } }; // // Cluster registry API function pointers. // defined in ioctl.c // extern CLUSTER_REG_APIS NmpClusterRegApis; // // Local Functions // DWORD NmpNetworkControl( IN PNM_NETWORK Network, IN DWORD ControlCode, IN PUCHAR InBuffer, IN DWORD InBufferSize, OUT PUCHAR OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ); DWORD NmpNetworkEnumCommonProperties( OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ); DWORD NmpNetworkGetCommonProperties( IN PNM_NETWORK Network, IN BOOL ReadOnly, IN HDMKEY RegistryKey, OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ); DWORD NmpNetworkValidateCommonProperties( IN PNM_NETWORK Network, IN PVOID InBuffer, IN DWORD InBufferSize, OUT PNM_NETWORK_INFO NetworkInfo OPTIONAL ); DWORD NmpNetworkSetCommonProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, IN PVOID InBuffer, IN DWORD InBufferSize ); DWORD NmpNetworkEnumPrivateProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ); DWORD NmpNetworkGetPrivateProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ); DWORD NmpNetworkValidatePrivateProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, IN PVOID InBuffer, IN DWORD InBufferSize ); DWORD NmpNetworkSetPrivateProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, IN PVOID InBuffer, IN DWORD InBufferSize ); DWORD NmpNetworkGetFlags( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ); DWORD WINAPI NmNetworkControl( IN PNM_NETWORK Network, IN PNM_NODE HostNode OPTIONAL, IN DWORD ControlCode, IN PUCHAR InBuffer, IN DWORD InBufferSize, OUT PUCHAR OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ) /*++ Routine Description: Provides for arbitrary communication and control between an application and a specific instance of a network. Arguments: Network - Supplies the network to be controlled. HostNode - Supplies the host node on which the resource control should be delivered. If this is NULL, the local node is used. Not honored! ControlCode- Supplies the control code that defines the structure and action of the resource control. Values of ControlCode between 0 and 0x10000000 are reserved for future definition and use by Microsoft. All other values are available for use by ISVs InBuffer- Supplies a pointer to the input buffer to be passed to the resource. InBufferSize- Supplies the size, in bytes, of the data pointed to by lpInBuffer.. OutBuffer- Supplies a pointer to the output buffer to be filled in by the resource.. OutBufferSize- Supplies the size, in bytes, of the available space pointed to by lpOutBuffer. BytesReturned - Returns the number of bytes of lpOutBuffer actually filled in by the resource.. Required - Returns the number of bytes if the OutBuffer is not big enough. Return Value: ERROR_SUCCESS if successful Win32 error code otherwise --*/ { DWORD status; // // Cluster service ioctls were designed to have access modes, e.g. // read-only, read-write, etc. These access modes are not implemented. // If eventually they are implemented, an access mode check should be // placed here. // if ( CLUSCTL_GET_CONTROL_OBJECT( ControlCode ) != CLUS_OBJECT_NETWORK ) { return(ERROR_INVALID_FUNCTION); } if (NmpEnterApi(NmStateOnline)) { status = NmpNetworkControl( Network, ControlCode, InBuffer, InBufferSize, OutBuffer, OutBufferSize, BytesReturned, Required ); NmpLeaveApi(); } else { status = ERROR_NODE_NOT_AVAILABLE; ClRtlLogPrint(LOG_NOISE, "[NM] Not in valid state to process NetworkControl request.\n" ); } return(status); } // NmNetworkControl DWORD NmpNetworkControl( IN PNM_NETWORK Network, IN DWORD ControlCode, IN PUCHAR InBuffer, IN DWORD InBufferSize, OUT PUCHAR OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ) /*++ Routine Description: Provides for arbitrary communication and control between an application and a specific instance of a network. Arguments: Network - Supplies the network to be controlled. ControlCode- Supplies the control code that defines the structure and action of the network control. Values of ControlCode between 0 and 0x10000000 are reserved for future definition and use by Microsoft. All other values are available for use by ISVs InBuffer- Supplies a pointer to the input buffer to be passed to the network. InBufferSize- Supplies the size, in bytes, of the data pointed to by lpInBuffer. OutBuffer- Supplies a pointer to the output buffer to be filled in by the network. OutBufferSize- Supplies the size, in bytes, of the available space pointed to by lpOutBuffer. BytesReturned - Returns the number of bytes of lpOutBuffer actually filled in by the network. Required - Returns the number of bytes if the OutBuffer is not big enough. Return Value: ERROR_SUCCESS if successful Win32 error code otherwise --*/ { DWORD status; HDMKEY networkKey; CLUSPROP_BUFFER_HELPER props; DWORD bufSize; networkKey = DmOpenKey( DmNetworksKey, OmObjectId( Network ), MAXIMUM_ALLOWED ); if ( networkKey == NULL ) { return(GetLastError()); } switch ( ControlCode ) { case CLUSCTL_NETWORK_UNKNOWN: *BytesReturned = 0; status = ERROR_SUCCESS; break; case CLUSCTL_NETWORK_GET_NAME: if ( OmObjectName( Network ) == NULL ) { return(ERROR_NOT_READY); } props.pb = OutBuffer; bufSize = (lstrlenW( OmObjectName( Network ) ) + 1) * sizeof(WCHAR); if ( bufSize > OutBufferSize ) { *Required = bufSize; *BytesReturned = 0; status = ERROR_MORE_DATA; } else { lstrcpyW( props.psz, OmObjectName( Network ) ); *BytesReturned = bufSize; *Required = 0; status = ERROR_SUCCESS; } break; case CLUSCTL_NETWORK_GET_ID: if ( OmObjectId( Network ) == NULL ) { return(ERROR_NOT_READY); } props.pb = OutBuffer; bufSize = (lstrlenW( OmObjectId( Network ) ) + 1) * sizeof(WCHAR); if ( bufSize > OutBufferSize ) { *Required = bufSize; *BytesReturned = 0; status = ERROR_MORE_DATA; } else { lstrcpyW( props.psz, OmObjectId( Network ) ); *BytesReturned = bufSize; *Required = 0; status = ERROR_SUCCESS; } break; case CLUSCTL_NETWORK_ENUM_COMMON_PROPERTIES: status = NmpNetworkEnumCommonProperties( OutBuffer, OutBufferSize, BytesReturned, Required ); break; case CLUSCTL_NETWORK_GET_RO_COMMON_PROPERTIES: status = NmpNetworkGetCommonProperties( Network, TRUE, // ReadOnly networkKey, OutBuffer, OutBufferSize, BytesReturned, Required ); break; case CLUSCTL_NETWORK_GET_COMMON_PROPERTIES: status = NmpNetworkGetCommonProperties( Network, FALSE, // ReadOnly networkKey, OutBuffer, OutBufferSize, BytesReturned, Required ); break; case CLUSCTL_NETWORK_VALIDATE_COMMON_PROPERTIES: NmpAcquireLock(); status = NmpNetworkValidateCommonProperties( Network, InBuffer, InBufferSize, NULL ); NmpReleaseLock(); break; case CLUSCTL_NETWORK_SET_COMMON_PROPERTIES: status = NmpNetworkSetCommonProperties( Network, networkKey, InBuffer, InBufferSize ); break; case CLUSCTL_NETWORK_GET_RO_PRIVATE_PROPERTIES: if ( OutBufferSize < sizeof(DWORD) ) { *BytesReturned = 0; *Required = sizeof(DWORD); if ( OutBuffer == NULL ) { status = ERROR_SUCCESS; } else { status = ERROR_MORE_DATA; } } else { LPDWORD ptrDword = (LPDWORD) OutBuffer; *ptrDword = 0; *BytesReturned = sizeof(DWORD); status = ERROR_SUCCESS; } break; case CLUSCTL_NETWORK_GET_PRIVATE_PROPERTIES: status = NmpNetworkGetPrivateProperties( Network, networkKey, OutBuffer, OutBufferSize, BytesReturned, Required ); break; case CLUSCTL_NETWORK_VALIDATE_PRIVATE_PROPERTIES: status = NmpNetworkValidatePrivateProperties( Network, networkKey, InBuffer, InBufferSize ); break; case CLUSCTL_NETWORK_SET_PRIVATE_PROPERTIES: status = NmpNetworkSetPrivateProperties( Network, networkKey, InBuffer, InBufferSize ); break; case CLUSCTL_NETWORK_GET_CHARACTERISTICS: if ( OutBufferSize < sizeof(DWORD) ) { *BytesReturned = 0; *Required = sizeof(DWORD); if ( OutBuffer == NULL ) { status = ERROR_SUCCESS; } else { status = ERROR_MORE_DATA; } } else { *BytesReturned = sizeof(DWORD); *(LPDWORD)OutBuffer = 0; status = ERROR_SUCCESS; } break; case CLUSCTL_NETWORK_GET_FLAGS: status = NmpNetworkGetFlags( Network, networkKey, OutBuffer, OutBufferSize, BytesReturned, Required ); break; case CLUSCTL_NETWORK_ENUM_PRIVATE_PROPERTIES: status = NmpNetworkEnumPrivateProperties( Network, networkKey, OutBuffer, OutBufferSize, BytesReturned, Required ); break; default: status = ERROR_INVALID_FUNCTION; break; } DmCloseKey( networkKey ); return(status); } // NmpNetworkControl DWORD NmpNetworkEnumCommonProperties( OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ) /*++ Routine Description: Enumerates the common property names for a given network. Arguments: OutBuffer - Supplies the output buffer. OutBufferSize - Supplies the size of the output buffer. BytesReturned - The number of bytes returned in OutBuffer. Required - The required number of bytes if OutBuffer is too small. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status; // // Get the common properties. // status = ClRtlEnumProperties( NmpNetworkCommonProperties, OutBuffer, OutBufferSize, BytesReturned, Required ); return(status); } // NmpNetworkEnumCommonProperties DWORD NmpNetworkGetCommonProperties( IN PNM_NETWORK Network, IN BOOL ReadOnly, IN HDMKEY RegistryKey, OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ) /*++ Routine Description: Gets the common properties for a given network. Arguments: Network - Supplies the network. ReadOnly - TRUE if the read-only properties should be read. FALSE otherwise. RegistryKey - Supplies the registry key for this network. OutBuffer - Supplies the output buffer. OutBufferSize - Supplies the size of the output buffer. BytesReturned - The number of bytes returned in OutBuffer. Required - The required number of bytes if OutBuffer is too small. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status; NM_NETWORK_INFO networkInfo; PRESUTIL_PROPERTY_ITEM propertyTable; DWORD outBufferSize = OutBufferSize; // // Fetch the properties from the object // ZeroMemory(&networkInfo, sizeof(networkInfo)); NmpAcquireLock(); status = NmpGetNetworkObjectInfo(Network, &networkInfo); NmpReleaseLock(); if (status == ERROR_SUCCESS) { if ( ReadOnly ) { propertyTable = NmpNetworkROCommonProperties; } else { propertyTable = NmpNetworkCommonProperties; } status = ClRtlPropertyListFromParameterBlock( propertyTable, OutBuffer, &outBufferSize, (LPBYTE) &networkInfo, BytesReturned, Required ); ClNetFreeNetworkInfo(&networkInfo); } return(status); } // NmpNetworkGetCommonProperties DWORD NmpNetworkValidateCommonProperties( IN PNM_NETWORK Network, IN PVOID InBuffer, IN DWORD InBufferSize, OUT PNM_NETWORK_INFO NetworkInfo OPTIONAL ) /*++ Routine Description: Validates the common properties for a given network. Arguments: Network - Supplies the network object. InBuffer - Supplies the input buffer. InBufferSize - Supplies the size of the input buffer. NetworkInfo - On output, contains a pointer to a network information structure with the updates applied. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. Notes: Called with the NmpLock held. --*/ { DWORD status; NM_NETWORK_INFO infoBuffer; PNM_NETWORK_INFO networkInfo; LPCWSTR networkId = OmObjectId(Network); // // Check if there is input data. // if ( (InBuffer == NULL) || (InBufferSize < sizeof(DWORD)) ) { return(ERROR_INVALID_DATA); } if (NetworkInfo != NULL) { networkInfo = NetworkInfo; } else { networkInfo = &infoBuffer; } ZeroMemory(networkInfo, sizeof(NM_NETWORK_INFO)); // // Get a copy of the current network parameters. // status = NmpGetNetworkObjectInfo(Network, networkInfo); if ( status != ERROR_SUCCESS ) { goto error_exit; } // // Validate the property list and update the parameter block. // status = ClRtlVerifyPropertyTable( NmpNetworkCommonProperties, NULL, // Reserved FALSE, // Don't allow unknowns InBuffer, InBufferSize, (LPBYTE) networkInfo ); if ( status != ERROR_SUCCESS ) { ClRtlLogPrint( LOG_CRITICAL, "[NM] ValidateCommonProperties, error in verify routine.\n" ); goto error_exit; } CL_ASSERT(networkInfo->Role <= ClusterNetworkRoleInternalAndClient); // // If the role changed, ensure that the change is legal for this cluster. // if (Network->Role != ((CLUSTER_NETWORK_ROLE) networkInfo->Role)) { status = NmpValidateNetworkRoleChange( Network, networkInfo->Role ); if (status != ERROR_SUCCESS) { goto error_exit; } } // // The change is valid. // CL_ASSERT(status == ERROR_SUCCESS); error_exit: if ((status != ERROR_SUCCESS) || (networkInfo == &infoBuffer)) { ClNetFreeNetworkInfo(networkInfo); } return(status); } // NmpNetworkValidateCommonProperties DWORD NmpNetworkSetCommonProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, IN PVOID InBuffer, IN DWORD InBufferSize ) /*++ Routine Description: Sets the common properties for a given network. Arguments: Network - Supplies the network object. InBuffer - Supplies the input buffer. InBufferSize - Supplies the size of the input buffer. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status; LPCWSTR networkId = OmObjectId(Network); ClRtlLogPrint(LOG_NOISE, "[NM] Setting common properties for network %1!ws!.\n", networkId ); // // Issue a global update // status = GumSendUpdateEx( GumUpdateMembership, NmUpdateSetNetworkCommonProperties, 3, NM_WCSLEN(networkId), networkId, InBufferSize, InBuffer, sizeof(InBufferSize), &InBufferSize ); if (status != ERROR_SUCCESS) { ClRtlLogPrint(LOG_CRITICAL, "[NM] Global update to set common properties for network %1!ws! failed, status %2!u!.\n", networkId, status ); } return(status); } // NmpNetworkSetCommonProperties DWORD NmpNetworkEnumPrivateProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ) /*++ Routine Description: Enumerates the private property names for a given network. Arguments: Network - Supplies the network object. RegistryKey - Registry key for the network. OutBuffer - Supplies the output buffer. OutBufferSize - Supplies the size of the output buffer. BytesReturned - The number of bytes returned in OutBuffer. Required - The required number of bytes if OutBuffer is too small. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status; HDMKEY parametersKey; DWORD totalBufferSize = 0; *BytesReturned = 0; *Required = 0; // // Clear the output buffer // ZeroMemory( OutBuffer, OutBufferSize ); // // Open the cluster network parameters key. // parametersKey = DmOpenKey( RegistryKey, CLUSREG_KEYNAME_PARAMETERS, MAXIMUM_ALLOWED ); if ( parametersKey == NULL ) { status = GetLastError(); if ( status == ERROR_FILE_NOT_FOUND ) { status = ERROR_SUCCESS; } return(status); } // // Enum private properties for the network. // status = ClRtlEnumPrivateProperties( parametersKey, &NmpClusterRegApis, OutBuffer, OutBufferSize, BytesReturned, Required ); DmCloseKey( parametersKey ); return(status); } // NmpNetworkEnumPrivateProperties DWORD NmpNetworkGetPrivateProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ) /*++ Routine Description: Gets the private properties for a given network. Arguments: Network - Supplies the network object. OutBuffer - Supplies the output buffer. OutBufferSize - Supplies the size of the output buffer. BytesReturned - The number of bytes returned in OutBuffer. Required - The required number of bytes if OutBuffer is too small. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status; HDMKEY parametersKey; DWORD totalBufferSize = 0; *BytesReturned = 0; *Required = 0; // // Clear the output buffer // ZeroMemory( OutBuffer, OutBufferSize ); // // Open the cluster network parameters key. // parametersKey = DmOpenKey( RegistryKey, CLUSREG_KEYNAME_PARAMETERS, MAXIMUM_ALLOWED ); if ( parametersKey == NULL ) { status = GetLastError(); if ( status == ERROR_FILE_NOT_FOUND ) { // // If we don't have a parameters key, then return an // item count of 0 and an endmark. // totalBufferSize = sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX); if ( OutBufferSize < totalBufferSize ) { *Required = totalBufferSize; status = ERROR_MORE_DATA; } else { // This is somewhat redundant since we zero the // buffer above, but it's here for clarity. CLUSPROP_BUFFER_HELPER buf; buf.pb = OutBuffer; buf.pList->nPropertyCount = 0; buf.pdw++; buf.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK; *BytesReturned = totalBufferSize; status = ERROR_SUCCESS; } } return(status); } // // Get private properties for the network. // status = ClRtlGetPrivateProperties( parametersKey, &NmpClusterRegApis, OutBuffer, OutBufferSize, BytesReturned, Required ); DmCloseKey( parametersKey ); return(status); } // NmpNetworkGetPrivateProperties DWORD NmpNetworkValidatePrivateProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, IN PVOID InBuffer, IN DWORD InBufferSize ) /*++ Routine Description: Validates the private properties for a given network. Arguments: Network - Supplies the network object. RegistryKey - Registry key for the network. InBuffer - Supplies the input buffer. InBufferSize - Supplies the size of the input buffer. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status; // // Validate the property list. // status = ClRtlVerifyPrivatePropertyList( InBuffer, InBufferSize ); return(status); } // NmpNetworkValidatePrivateProperties DWORD NmpNetworkSetPrivateProperties( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, IN PVOID InBuffer, IN DWORD InBufferSize ) /*++ Routine Description: Sets the private properties for a given network. Arguments: Network - Supplies the network object. RegistryKey - Registry key for the network. InBuffer - Supplies the input buffer. InBufferSize - Supplies the size of the input buffer. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status; HDMKEY parametersKey; DWORD disposition; BOOLEAN setProperties = TRUE; // // Validate the property list. // status = ClRtlVerifyPrivatePropertyList( InBuffer, InBufferSize ); if ( status == ERROR_SUCCESS ) { // // Validate any multicast parameters being set. // status = NmpMulticastValidatePrivateProperties( Network, RegistryKey, InBuffer, InBufferSize ); if (status == ERROR_SUCCESS) { // // Open the cluster network\xx\parameters key // parametersKey = DmOpenKey( RegistryKey, CLUSREG_KEYNAME_PARAMETERS, MAXIMUM_ALLOWED ); if ( parametersKey == NULL ) { status = GetLastError(); if ( status == ERROR_FILE_NOT_FOUND ) { // // Try to create the parameters key. // parametersKey = DmCreateKey( RegistryKey, CLUSREG_KEYNAME_PARAMETERS, 0, KEY_READ | KEY_WRITE, NULL, &disposition ); if ( parametersKey == NULL ) { status = GetLastError(); return(status); } } } NmpMulticastManualConfigChange( Network, RegistryKey, parametersKey, InBuffer, InBufferSize, &setProperties ); if (setProperties) { status = ClRtlSetPrivatePropertyList( NULL, // IN HANDLE hXsaction parametersKey, &NmpClusterRegApis, InBuffer, InBufferSize ); } DmCloseKey( parametersKey ); } } return(status); } // NmpNetworkSetPrivateProperties DWORD NmpNetworkGetFlags( IN PNM_NETWORK Network, IN HDMKEY RegistryKey, OUT PVOID OutBuffer, IN DWORD OutBufferSize, OUT LPDWORD BytesReturned, OUT LPDWORD Required ) /*++ Routine Description: Gets the flags for a given network. Arguments: Network - Supplies the network. RegistryKey - Registry key for the network. OutBuffer - Supplies the output buffer. OutBufferSize - Supplies the size of the output buffer. BytesReturned - The number of bytes returned in OutBuffer. Required - The required number of bytes if OutBuffer is too small. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status; *BytesReturned = 0; if ( OutBufferSize < sizeof(DWORD) ) { *Required = sizeof(DWORD); if ( OutBuffer == NULL ) { status = ERROR_SUCCESS; } else { status = ERROR_MORE_DATA; } } else { DWORD valueType; // // Read the Flags value for the network. // *BytesReturned = OutBufferSize; status = DmQueryValue( RegistryKey, CLUSREG_NAME_FLAGS, &valueType, OutBuffer, BytesReturned ); if ( status == ERROR_FILE_NOT_FOUND ) { *BytesReturned = sizeof(DWORD); *(LPDWORD)OutBuffer = 0; status = ERROR_SUCCESS; } } return(status); } // NmpNetworkGetFlags