716 lines
18 KiB
C
716 lines
18 KiB
C
/*++
|
||
|
||
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
|
||
|