/*++ Copyright (c) 1996-2000 Microsoft Corporation Module Name: namechk.c Abstract: Check on network names given by the cluster network name resource dll. Author: Rod Gamache (rodga) 1-Aug-1997 Environment: User Mode Revision History: --*/ #define UNICODE 1 #include #include #include #include #include #include #include #include #include "namechk.h" #include "resapi.h" #include "netname.h" #include "nameutil.h" #include "clusres.h" #define NET_NAME_SVC L"LanmanServer" #define BUFF_SIZE 650 #define NBT_MAXIMUM_BINDINGS 20 NTSTATUS CheckNbtName( IN HANDLE Fd, IN LPCWSTR Name, IN ULONG Type, IN RESOURCE_HANDLE ResourceHandle ); NTSTATUS ReadRegistry( IN UCHAR pDeviceName[][MAX_PATH_SIZE] ); NTSTATUS OpenNbt( IN char path[][MAX_PATH_SIZE], OUT PHANDLE pHandle ); DWORD NetNameCheckNbtName( IN LPCWSTR NetName, IN DWORD NameHandleCount, IN HANDLE * NameHandleList, IN RESOURCE_HANDLE ResourceHandle ) /*++ Routine Description: Checks a network name. Arguments: NetName - pointer to the network name to validate. Return Value: ERROR_SUCCESS if successful. A Win32 error code on failure. --*/ { DWORD status = ERROR_SUCCESS; NTSTATUS ntStatus; // // loop through the list of handles we acquired when bringing the // name online and check that our netname is still registered // on each device // while ( NameHandleCount-- ) { // // Check the workstation name. If this fails, immediate failure! // ntStatus = CheckNbtName( *NameHandleList, NetName, 0x00, ResourceHandle ); if ( !NT_SUCCESS(ntStatus) ) { status = RtlNtStatusToDosError(ntStatus); return(status); } // // Check the server name. If this fails, then only fail if Srv service // is not running. // ntStatus = CheckNbtName( *NameHandleList, NetName, 0x20, ResourceHandle ); if ( !NT_SUCCESS(ntStatus) ) { if ( ResUtilVerifyResourceService( NET_NAME_SVC) == ERROR_SUCCESS ) { status = ERROR_RESOURCE_FAILED; } } ++NameHandleList; } return(status); } // NetNameCheckName NTSTATUS CheckNbtName( IN HANDLE fd, IN LPCWSTR Name, IN ULONG Type, IN RESOURCE_HANDLE ResourceHandle ) /*++ Routine Description: This procedure does an adapter status query to get the local name table. Arguments: Return Value: 0 if successful, -1 otherwise. --*/ { LONG Count; ULONG BufferSize = sizeof( tADAPTERSTATUS ); tADAPTERSTATUS staticBuffer; PVOID pBuffer = (PVOID)&staticBuffer; NTSTATUS status; tADAPTERSTATUS *pAdapterStatus; NAME_BUFFER *pNames; ULONG Ioctl; TDI_REQUEST_QUERY_INFORMATION QueryInfo; PVOID pInput; ULONG SizeInput; UCHAR netBiosName[NETBIOS_NAME_SIZE +4]; OEM_STRING netBiosNameString; UNICODE_STRING unicodeName; NTSTATUS ntStatus; // // set the correct Ioctl for the call to NBT, to get either // the local name table or the remote name table // Ioctl = IOCTL_TDI_QUERY_INFORMATION; QueryInfo.QueryType = TDI_QUERY_ADAPTER_STATUS; // node status or whatever SizeInput = sizeof(TDI_REQUEST_QUERY_INFORMATION); pInput = &QueryInfo; do { status = DeviceIoCtrl(fd, pBuffer, BufferSize, Ioctl, pInput, SizeInput); if (status == STATUS_BUFFER_OVERFLOW) { if ( pBuffer != &staticBuffer ) { LocalFree(pBuffer); } BufferSize += sizeof( staticBuffer.Names ); pBuffer = LocalAlloc(LMEM_FIXED, BufferSize); if (!pBuffer || (BufferSize >= 0xFFFF)) { LocalFree(pBuffer); (NetNameLogEvent)( ResourceHandle, LOG_ERROR, L"Unable to allocate memory for name query.\n" ); return(STATUS_INSUFFICIENT_RESOURCES); } } } while (status == STATUS_BUFFER_OVERFLOW); if (status != STATUS_SUCCESS) { (NetNameLogEvent)( ResourceHandle, LOG_ERROR, L"Name query request failed, status %1!u!.\n", status ); goto error_exit; } pAdapterStatus = (tADAPTERSTATUS *)pBuffer; Count = pAdapterStatus->AdapterInfo.name_count; pNames = pAdapterStatus->Names; status = STATUS_NOT_FOUND; if (Count == 0) { (NetNameLogEvent)( ResourceHandle, LOG_ERROR, L"Name query request returned zero entries.\n" ); goto error_exit; } // // Convert the ServerName to an OEM string // RtlInitUnicodeString( &unicodeName, Name ); netBiosNameString.Buffer = (PCHAR)netBiosName; netBiosNameString.MaximumLength = sizeof( netBiosName ); ntStatus = RtlUpcaseUnicodeStringToOemString( &netBiosNameString, &unicodeName, FALSE ); if (ntStatus != STATUS_SUCCESS) { status = RtlNtStatusToDosError(ntStatus); (NetNameLogEvent)( ResourceHandle, LOG_ERROR, L"Unable to convert name %1!ws! to an OEM string, status %2!u!\n", Name, status ); return(status); } // // blank fill the name // memset(&netBiosName[netBiosNameString.Length], ' ', NETBIOS_NAME_SIZE - netBiosNameString.Length); while ( Count-- ) { // // Make sure the type and name matches // if ( (pNames->name[NETBIOS_NAME_SIZE-1] == Type) && (memcmp(pNames->name, netBiosName, NETBIOS_NAME_SIZE-1) == 0) ) { switch(pNames->name_flags & 0x0F) { case REGISTERING: case REGISTERED: status = STATUS_SUCCESS; break; case DUPLICATE_DEREG: case DUPLICATE: (NetNameLogEvent)( ResourceHandle, LOG_ERROR, L"Name %1!ws!<%2!x!> is in conflict.\n", Name, Type ); status = STATUS_DUPLICATE_NAME; break; case DEREGISTERED: (NetNameLogEvent)( ResourceHandle, LOG_ERROR, L"Name %1!ws!<%2!x!> was deregistered.\n", Name, Type ); status = STATUS_NOT_FOUND; break; default: (NetNameLogEvent)( ResourceHandle, LOG_ERROR, L"Name %1!ws!<%2!x!> is in unknown state %3!x!.\n", Name, Type, (pNames->name_flags & 0x0F) ); status = STATUS_UNSUCCESSFUL; break; } } pNames++; } if (status == STATUS_NOT_FOUND) { (NetNameLogEvent)( ResourceHandle, LOG_ERROR, L"Name %1!ws!<%2!x!> is no longer registered with NBT.\n", Name, Type ); } error_exit: if ( pBuffer != &staticBuffer ) { LocalFree(pBuffer); } return(status); } // CheckNbtName //------------------------------------------------------------------------ NTSTATUS DeviceIoCtrl( IN HANDLE fd, IN PVOID ReturnBuffer, IN ULONG BufferSize, IN ULONG Ioctl, IN PVOID pInput, IN ULONG SizeInput ) /*++ Routine Description: This procedure performs an ioctl(I_STR) on a stream. Arguments: fd - NT file handle iocp - pointer to a strioctl structure Return Value: 0 if successful, -1 otherwise. --*/ { NTSTATUS status; int retval; ULONG QueryType; IO_STATUS_BLOCK iosb; status = NtDeviceIoControlFile( fd, // Handle NULL, // Event NULL, // ApcRoutine NULL, // ApcContext &iosb, // IoStatusBlock Ioctl, // IoControlCode pInput, // InputBuffer SizeInput, // InputBufferSize (PVOID) ReturnBuffer, // OutputBuffer BufferSize); // OutputBufferSize if (status == STATUS_PENDING) { status = NtWaitForSingleObject( fd, // Handle TRUE, // Alertable NULL); // Timeout if (NT_SUCCESS(status)) { status = iosb.Status; } } return(status); } // DeviceIoCtrl