mirror of https://github.com/tongzx/nt5src
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.
715 lines
18 KiB
715 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
nbtmgmt.c
|
|
|
|
Abstract:
|
|
|
|
Routines for managing NBT interfaces.
|
|
|
|
Author:
|
|
|
|
David Dion (daviddio) December 9, 1999
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----------------------------------------------
|
|
daviddio 12-09-99 created
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include "clusnet.h"
|
|
#include "nbtmgmt.tmh"
|
|
|
|
//
|
|
// Types
|
|
//
|
|
typedef struct _NBT_IF {
|
|
LIST_ENTRY Linkage;
|
|
ULONG InstanceNumber;
|
|
PFILE_OBJECT FileObject;
|
|
WCHAR IfName[1];
|
|
} NBT_IF, *PNBT_IF;
|
|
|
|
|
|
//
|
|
// Data
|
|
//
|
|
LIST_ENTRY NbtIfList = {NULL,NULL};
|
|
KSPIN_LOCK NbtIfListLock = 0;
|
|
|
|
|
|
//
|
|
// Local function prototypes
|
|
//
|
|
NTSTATUS
|
|
NbtIfOpenDevice(
|
|
IN LPWSTR DeviceName,
|
|
OUT PFILE_OBJECT *FileObject
|
|
);
|
|
|
|
NTSTATUS
|
|
NbtIfIssueDeviceControl(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN ULONG IoControlCode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
IN PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength
|
|
);
|
|
|
|
PNBT_IF
|
|
NbtFindIf(
|
|
IN LPWSTR DeviceName,
|
|
IN ULONG Length
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
|
|
#pragma alloc_text(INIT, NbtIfLoad)
|
|
#pragma alloc_text(PAGE, NbtIfOpenDevice)
|
|
#pragma alloc_text(PAGE, NbtIfIssueDeviceControl)
|
|
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
|
|
|
|
NTSTATUS
|
|
NbtIfIssueDeviceControl(
|
|
IN PFILE_OBJECT FileObject,
|
|
IN ULONG IoControlCode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
IN PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS -- Indicates the status of the request.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
IO_STATUS_BLOCK iosb;
|
|
KEVENT event;
|
|
PIRP irp;
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
|
|
|
irp = IoBuildDeviceIoControlRequest(
|
|
IoControlCode,
|
|
IoGetRelatedDeviceObject(FileObject),
|
|
InputBuffer,
|
|
InputBufferLength,
|
|
OutputBuffer,
|
|
OutputBufferLength,
|
|
FALSE,
|
|
&event,
|
|
&iosb
|
|
);
|
|
|
|
if (irp != NULL) {
|
|
|
|
status = IoCallDriver(
|
|
IoGetRelatedDeviceObject(FileObject),
|
|
irp
|
|
);
|
|
|
|
if (status == STATUS_PENDING) {
|
|
|
|
status = KeWaitForSingleObject(
|
|
&event,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
CnAssert(status == STATUS_SUCCESS);
|
|
|
|
status = iosb.Status;
|
|
}
|
|
|
|
} else {
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT((
|
|
"[Clusnet] Failed to build NBT request irp, status %lx\n",
|
|
status
|
|
));
|
|
}
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfIrpAllocFailed,
|
|
"[Clusnet] Failed to build NBT request irp, status %!status!.",
|
|
status // LOGSTATUS
|
|
);
|
|
}
|
|
|
|
return(status);
|
|
|
|
} // NbtIfIssueDeviceControl
|
|
|
|
|
|
NTSTATUS
|
|
NbtIfOpenDevice(
|
|
IN LPWSTR DeviceName,
|
|
OUT PFILE_OBJECT *FileObject
|
|
)
|
|
|
|
{
|
|
UNICODE_STRING nameString;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
IO_STATUS_BLOCK iosb;
|
|
HANDLE handle;
|
|
NTSTATUS status;
|
|
|
|
*FileObject = (PFILE_OBJECT) NULL;
|
|
|
|
//
|
|
// Open the NBT device.
|
|
//
|
|
RtlInitUnicodeString(&nameString, DeviceName);
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
&nameString,
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
(HANDLE) NULL,
|
|
(PSECURITY_DESCRIPTOR) NULL
|
|
);
|
|
|
|
status = ZwCreateFile(
|
|
&handle,
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&objectAttributes,
|
|
&iosb,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF,
|
|
0,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
// Get a pointer to the corresponding file object. The file
|
|
// object pointer is used to issue ioctls to the device.
|
|
status = ObReferenceObjectByHandle(
|
|
handle,
|
|
0,
|
|
NULL,
|
|
KernelMode,
|
|
FileObject,
|
|
NULL
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
*FileObject = (PFILE_OBJECT) NULL;
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfObDerefFailed,
|
|
"[Clusnet] Failed to deref NBT device handle %p "
|
|
"for device %ls, status %!status!.",
|
|
handle,
|
|
DeviceName, // LOGWSTR
|
|
status // LOGSTATUS
|
|
);
|
|
IF_CNDBG(CN_DEBUG_INIT) {
|
|
CNPRINT(("[Clusnet] Failed to deref NBT device handle %p "
|
|
"for device %S, status %lx\n",
|
|
handle, DeviceName, status));
|
|
}
|
|
}
|
|
|
|
ZwClose(handle);
|
|
|
|
} else {
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfOpenDeviceFailed,
|
|
"[Clusnet] Failed to open NBT device %ls, status %!status!.",
|
|
DeviceName, // LOGWSTR
|
|
status // LOGSTATUS
|
|
);
|
|
IF_CNDBG(CN_DEBUG_INIT) {
|
|
CNPRINT(("[Clusnet] Failed to open NBT device %S, status %lx\n",
|
|
DeviceName, status));
|
|
}
|
|
}
|
|
|
|
return(status);
|
|
|
|
} // NbtIfOpenDevice
|
|
|
|
|
|
PNBT_IF
|
|
NbtFindIf(
|
|
LPWSTR DeviceName,
|
|
ULONG Length
|
|
)
|
|
{
|
|
PNBT_IF nbtif;
|
|
PLIST_ENTRY entry;
|
|
|
|
|
|
for ( entry = NbtIfList.Flink;
|
|
entry != &NbtIfList;
|
|
entry = entry->Flink
|
|
)
|
|
{
|
|
nbtif = CONTAINING_RECORD(entry, NBT_IF, Linkage);
|
|
|
|
if (RtlCompareMemory(
|
|
&nbtif->IfName[0],
|
|
DeviceName,
|
|
Length - sizeof(UNICODE_NULL)
|
|
) == Length - sizeof(UNICODE_NULL)) {
|
|
return(nbtif);
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
|
|
} // NbtFindIf
|
|
|
|
|
|
//
|
|
// Public Routines
|
|
//
|
|
NTSTATUS
|
|
NbtIfLoad(
|
|
VOID
|
|
)
|
|
{
|
|
IF_CNDBG(CN_DEBUG_INIT) {
|
|
CNPRINT(("[Clusnet] NBT support loading.\n"));
|
|
}
|
|
|
|
KeInitializeSpinLock(&NbtIfListLock);
|
|
InitializeListHead(&NbtIfList);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
} // NbtIfLoad
|
|
|
|
|
|
VOID
|
|
NbtIfShutdown(
|
|
VOID
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
KIRQL irql;
|
|
PLIST_ENTRY entry;
|
|
PNBT_IF nbtif;
|
|
LIST_ENTRY deletelist;
|
|
|
|
|
|
IF_CNDBG(CN_DEBUG_INIT) {
|
|
CNPRINT(("[Clusnet] Destroying all cluster NBT interfaces...\n"));
|
|
}
|
|
|
|
KeAcquireSpinLock( &NbtIfListLock, &irql );
|
|
|
|
//
|
|
// Move the contents of NbtIfList to the delete list
|
|
//
|
|
if (!IsListEmpty( &NbtIfList )) {
|
|
RtlCopyMemory( &deletelist, &NbtIfList, sizeof(NbtIfList) );
|
|
deletelist.Flink->Blink = &deletelist;
|
|
deletelist.Blink->Flink = &deletelist;
|
|
InitializeListHead( &NbtIfList );
|
|
} else {
|
|
InitializeListHead( &deletelist );
|
|
}
|
|
|
|
KeReleaseSpinLock( &NbtIfListLock, irql );
|
|
|
|
while (!IsListEmpty( &deletelist )) {
|
|
|
|
entry = RemoveHeadList( &deletelist );
|
|
|
|
nbtif = CONTAINING_RECORD( entry, NBT_IF, Linkage );
|
|
|
|
status = NbtIfIssueDeviceControl(
|
|
nbtif->FileObject,
|
|
IOCTL_NETBT_DELETE_INTERFACE,
|
|
NULL, // request
|
|
0, // request size
|
|
NULL, // response
|
|
0 // response size
|
|
);
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
LPWSTR deviceName = (LPWSTR) &nbtif->IfName[0];
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfDeleteFailed,
|
|
"[Clusnet] Failed to delete NBT interface %ls "
|
|
"file object %p, status %!status!.",
|
|
deviceName, // LOGWSTR
|
|
nbtif->FileObject,
|
|
status // LOGSTATUS
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT(("[Clusnet] Failed to delete NBT interface %S "
|
|
"file object %p, status %lx\n",
|
|
deviceName,
|
|
nbtif->FileObject,
|
|
status
|
|
));
|
|
}
|
|
|
|
} else {
|
|
|
|
LPWSTR deviceName = (LPWSTR) &nbtif->IfName[0];
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfDeleted,
|
|
"[Clusnet] Delete NBT interface %ls.",
|
|
deviceName // LOGWSTR
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT(("[Clusnet] Deleted NBT interface %S.\n",
|
|
deviceName
|
|
));
|
|
}
|
|
}
|
|
|
|
// Release the reference that was taken when the NBT device
|
|
// was created.
|
|
ObDereferenceObject(nbtif->FileObject);
|
|
|
|
CnFreePool(nbtif);
|
|
}
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfShutdownIfsDeleted,
|
|
"[Clusnet] All cluster NBT interfaces destroyed."
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_INIT) {
|
|
CNPRINT(("[Clusnet] All cluster NBT interfaces destroyed.\n"));
|
|
}
|
|
|
|
return;
|
|
|
|
} // NbtIfShutdown
|
|
|
|
|
|
NTSTATUS
|
|
NbtAddIf(
|
|
IN PNETBT_ADD_DEL_IF Request,
|
|
IN ULONG RequestSize,
|
|
OUT PNETBT_ADD_DEL_IF Response,
|
|
IN OUT PULONG ResponseSize
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PFILE_OBJECT requestFileObject;
|
|
PFILE_OBJECT responseFileObject;
|
|
PNBT_IF nbtif;
|
|
KIRQL irql;
|
|
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfAdding,
|
|
"[Clusnet] Creating new NBT interface for NBT device %ls.",
|
|
Request->IfName // LOGWSTR
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT((
|
|
"[Clusnet] Creating new NBT interface for NBT device %S...\n",
|
|
Request->IfName
|
|
));
|
|
}
|
|
|
|
//
|
|
// Open the NBT device specified in the request. This corresponds
|
|
// to a particular TCP/IP interface.
|
|
//
|
|
status = NbtIfOpenDevice( Request->IfName, &requestFileObject );
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// Allocate a record for the NBT interface
|
|
//
|
|
nbtif = CnAllocatePool(
|
|
FIELD_OFFSET( NBT_IF, IfName[0] )
|
|
+ Response->Length
|
|
);
|
|
|
|
if (nbtif != NULL) {
|
|
|
|
//
|
|
// Issue an ioctl to create a new NBT interface.
|
|
// The response contains the name of the new NBT
|
|
// interface device object.
|
|
//
|
|
status = NbtIfIssueDeviceControl(
|
|
requestFileObject,
|
|
IOCTL_NETBT_ADD_INTERFACE,
|
|
NULL,
|
|
0,
|
|
Response,
|
|
*ResponseSize
|
|
);
|
|
|
|
if (NT_SUCCESS(status)
|
|
&& NT_SUCCESS(Response->Status)) {
|
|
|
|
//
|
|
// Open the new NBT interface device object.
|
|
//
|
|
status = NbtIfOpenDevice(
|
|
(LPWSTR) Response->IfName,
|
|
&responseFileObject
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
LPWSTR deviceName = (LPWSTR) &Response->IfName[0];
|
|
|
|
//
|
|
// Store the interface name, instance, and
|
|
// file object corresponding to the new NBT
|
|
// interface device object.
|
|
//
|
|
RtlZeroMemory(
|
|
nbtif,
|
|
FIELD_OFFSET( NBT_IF, IfName[0] ) + Response->Length
|
|
);
|
|
|
|
RtlCopyMemory(
|
|
&nbtif->IfName[0],
|
|
deviceName,
|
|
Response->Length
|
|
);
|
|
|
|
nbtif->InstanceNumber = Response->InstanceNumber;
|
|
nbtif->FileObject = responseFileObject;
|
|
|
|
KeAcquireSpinLock(&NbtIfListLock, &irql);
|
|
|
|
InsertTailList(&NbtIfList, &(nbtif->Linkage));
|
|
|
|
KeReleaseSpinLock(&NbtIfListLock, irql);
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfAdded,
|
|
"[Clusnet] Created new NBT interface device %ls.",
|
|
deviceName // LOGWSTR
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT((
|
|
"[Clusnet] Created new NBT interface "
|
|
"device %S.\n",
|
|
deviceName
|
|
));
|
|
}
|
|
|
|
} else {
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfAddOpenNewFailed,
|
|
"[Clusnet] Failed to open NBT device for new "
|
|
"interface %ls, status %!status!.",
|
|
Request->IfName, // LOGWSTR
|
|
status // LOGSTATUS
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT((
|
|
"[Clusnet] Failed to open NBT device for "
|
|
"new interface %S: %x\n",
|
|
Request->IfName,
|
|
status
|
|
));
|
|
}
|
|
|
|
CnFreePool(nbtif);
|
|
}
|
|
} else {
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfAddFailed,
|
|
"[Clusnet] Failed to add NBT interface for "
|
|
"NBT device %ls, status %!status!, %!status!.",
|
|
Request->IfName, // LOGWSTR
|
|
status, // LOGSTATUS
|
|
Response->Status // LOGSTATUS
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT((
|
|
"[Clusnet] Failed to add NBT interface "
|
|
"for NBT device %S: %x, %x\n",
|
|
Request->IfName,
|
|
status,
|
|
Response->Status
|
|
));
|
|
}
|
|
|
|
CnFreePool(nbtif);
|
|
}
|
|
} else {
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfAddAllocFailed,
|
|
"[Clusnet] Failed to allocate record for NBT "
|
|
"interface %ls, status %!status!.",
|
|
Request->IfName, // LOGWSTR
|
|
status // LOGSTATUS
|
|
);
|
|
}
|
|
|
|
//
|
|
// Release reference on NBT device object corresponding
|
|
// to TCP/IP interface.
|
|
//
|
|
ObDereferenceObject(requestFileObject);
|
|
|
|
} else {
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfAddOpenFailed,
|
|
"[Clusnet] Failed to open NBT device %ls for add, "
|
|
"status %!status!.",
|
|
Request->IfName, // LOGWSTR
|
|
status // LOGSTATUS
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT((
|
|
"[Clusnet] Failed to open NBT device %S: %x\n",
|
|
Request->IfName,
|
|
status
|
|
));
|
|
}
|
|
}
|
|
|
|
return(status);
|
|
|
|
} // NbtAddIf
|
|
|
|
|
|
NTSTATUS
|
|
NbtDeleteIf(
|
|
IN PNETBT_ADD_DEL_IF Request,
|
|
IN ULONG RequestSize
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PNBT_IF nbtif;
|
|
KIRQL irql;
|
|
ULONG responseSize = 0;
|
|
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfDeleting,
|
|
"[Clusnet] Deleting NBT interface %ls.",
|
|
Request->IfName // LOGWSTR
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT((
|
|
"[Clusnet] Attempting to delete NBT interface %S...\n",
|
|
(LPWSTR) &Request->IfName[0]
|
|
));
|
|
}
|
|
|
|
KeAcquireSpinLock(&NbtIfListLock, &irql);
|
|
|
|
nbtif = NbtFindIf( (LPWSTR) &Request->IfName[0], Request->Length );
|
|
|
|
if (nbtif != NULL) {
|
|
|
|
RemoveEntryList(&(nbtif->Linkage));
|
|
|
|
KeReleaseSpinLock(&NbtIfListLock, irql);
|
|
|
|
status = NbtIfIssueDeviceControl(
|
|
nbtif->FileObject,
|
|
IOCTL_NETBT_DELETE_INTERFACE,
|
|
NULL, // request
|
|
0, // request size
|
|
NULL, // response
|
|
0 // response size
|
|
);
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
LPWSTR deviceName = (LPWSTR) &nbtif->IfName[0];
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfDeleteFailed,
|
|
"[Clusnet] Failed to delete NBT interface %ls "
|
|
"file object %p, status %!status!.",
|
|
deviceName, // LOGWSTR
|
|
nbtif->FileObject,
|
|
status // LOGSTATUS
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT(("[Clusnet] Failed to delete NBT interface %S "
|
|
"file object %p, status %lx\n",
|
|
deviceName,
|
|
nbtif->FileObject,
|
|
status
|
|
));
|
|
}
|
|
|
|
} else {
|
|
|
|
LPWSTR deviceName = (LPWSTR) &nbtif->IfName[0];
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfDeleted,
|
|
"[Clusnet] Delete NBT interface %ls.",
|
|
deviceName // LOGWSTR
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT(("[Clusnet] Deleted NBT interface %S.\n",
|
|
deviceName
|
|
));
|
|
}
|
|
}
|
|
|
|
// Release the reference that was taken when the NBT device
|
|
// was created.
|
|
ObDereferenceObject(nbtif->FileObject);
|
|
|
|
CnFreePool(nbtif);
|
|
|
|
} else {
|
|
KeReleaseSpinLock(&NbtIfListLock, irql);
|
|
|
|
CnTrace(NTEMGMT_DETAIL, NbtIfDeleteNotFound,
|
|
"[Clusnet] NBT interface %ls does not exist.",
|
|
Request->IfName // LOGWSTR
|
|
);
|
|
|
|
IF_CNDBG(CN_DEBUG_NTE) {
|
|
CNPRINT(("[Clusnet] NBT interface %S does not exist.\n",
|
|
(LPWSTR) &Request->IfName[0]));
|
|
}
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
return (status);
|
|
|
|
} // NbtDeleteIf
|
|
|