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.
422 lines
10 KiB
422 lines
10 KiB
/*++
|
|
|
|
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
|