423 lines
10 KiB
C
423 lines
10 KiB
C
/*++
|
||
|
||
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
|