windows-nt/Source/XPSP1/NT/base/cluster/resdll/netname/namechk.c
2020-09-26 16:20:57 +08:00

423 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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