|
|
/*++
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 <nt.h>
#include <ntdef.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdlib.h>
#include <nb30.h>
#include <lmaccess.h>
#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
|