Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1029 lines
27 KiB

/*++
Copyright (c) 1989-2001 Microsoft Corporation
Module Name:
Driver.c
Abstract:
This module implements the DRIVER_INITIALIZATION routine for the
SMB Transport and other routines that are specific to the NT implementation
of a driver.
Author:
Jiandong Ruan
Revision History:
--*/
#include "precomp.h"
#include "ip2netbios.h"
#include "driver2.tmh"
BOOL
IsNetBTSmbEnabled(
IN PUNICODE_STRING RegistryPath
);
NTSTATUS
NotifyNetBT(
IN DWORD dwNetBTAction
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, SmbDriverEntry)
#pragma alloc_text(INIT, IsNetBTSmbEnabled)
#pragma alloc_text(PAGE, NotifyNetBT)
#pragma alloc_text(PAGE, SmbDispatchCleanup)
#pragma alloc_text(PAGE, SmbDispatchClose)
#pragma alloc_text(PAGE, SmbDispatchCreate)
#pragma alloc_text(PAGE, SmbDispatchDevCtrl)
#pragma alloc_text(PAGE, SmbDispatchPnP)
#pragma alloc_text(PAGE, SmbUnload)
#endif
NTSTATUS
NotifyNetBT(
IN DWORD dwNetBTAction
)
{
UNICODE_STRING uncWinsDeviceName = { 0 };
PFILE_OBJECT pWinsFileObject = NULL;
PDEVICE_OBJECT pWinsDeviceObject = NULL;
PIRP pIrp = NULL;
IO_STATUS_BLOCK IoStatusBlock = { 0 };
KEVENT Event = { 0 };
NTSTATUS status = STATUS_UNSUCCESSFUL;
PAGED_CODE();
KeInitializeEvent(&Event, NotificationEvent, FALSE);
//
// Notify NetBT to destroy its NetbiosSmb
//
RtlInitUnicodeString(&uncWinsDeviceName, L"\\Device\\NetBt_Wins_Export");
status = IoGetDeviceObjectPointer(
&uncWinsDeviceName,
SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
&pWinsFileObject,
&pWinsDeviceObject
);
if (STATUS_SUCCESS != status) {
goto error;
}
pIrp = IoBuildDeviceIoControlRequest (
IOCTL_NETBT_ENABLE_DISABLE_NETBIOS_SMB,
pWinsDeviceObject,
&dwNetBTAction,
sizeof(dwNetBTAction),
NULL,
0,
FALSE,
&Event,
&IoStatusBlock
);
if (NULL == pIrp) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto error;
}
status = IoCallDriver(pWinsDeviceObject, pIrp);
if (STATUS_PENDING == status) {
ASSERT (0);
KeWaitForSingleObject(
&Event,
Executive,
KernelMode,
FALSE,
NULL
);
status = IoStatusBlock.Status;
}
error:
if (pWinsFileObject != NULL) {
ObDereferenceObject(pWinsFileObject);
pWinsFileObject = NULL;
}
return status;
}
BOOL
IsNetBTSmbEnabled(
IN PUNICODE_STRING RegistryPath
)
{
OBJECT_ATTRIBUTES ObAttr = { 0 };
NTSTATUS status = STATUS_SUCCESS;
HANDLE hRootKey = NULL;
HANDLE hKey = NULL;
UNICODE_STRING uncParams = { 0 };
BOOL fUseSmbFromNetBT = FALSE;
PAGED_CODE();
//
// Construct the registry path for the HKLM\System\CCS\Services
//
uncParams = RegistryPath[0];
while(uncParams.Length > 0 && uncParams.Buffer[uncParams.Length/sizeof(WCHAR) - 1] != L'\\') {
uncParams.Length -= sizeof(WCHAR);
}
uncParams.Length -= sizeof(WCHAR);
InitializeObjectAttributes (
&ObAttr,
&uncParams,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
status = ZwOpenKey (&hRootKey, KEY_READ | KEY_WRITE, &ObAttr);
BAIL_OUT_ON_ERROR(status);
RtlInitUnicodeString(&uncParams, L"NetBT");
InitializeObjectAttributes (
&ObAttr,
&uncParams,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
hRootKey,
NULL
);
status = ZwOpenKey(&hKey, KEY_READ | KEY_WRITE, &ObAttr);
ZwClose(hRootKey);
hRootKey = hKey;
hKey = NULL;
BAIL_OUT_ON_ERROR(status);
fUseSmbFromNetBT = TRUE;
//
// From now on, an error means NetBT's Smb enabled
//
RtlInitUnicodeString(&uncParams, L"Parameters");
InitializeObjectAttributes (
&ObAttr,
&uncParams,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
hRootKey,
NULL
);
status = ZwOpenKey (&hKey, KEY_READ | KEY_WRITE, &ObAttr);
ZwClose(hRootKey);
hRootKey = hKey;
hKey = NULL;
BAIL_OUT_ON_ERROR(status);
fUseSmbFromNetBT = !(SmbReadULong(hRootKey, L"UseNewSmb", 0, 0));
if (fUseSmbFromNetBT) {
goto cleanup;
}
status = NotifyNetBT(NETBT_DISABLE_NETBIOS_SMB);
status = STATUS_SUCCESS;
cleanup:
if (hRootKey != NULL) {
ZwClose(hRootKey);
}
if (hKey != NULL) {
ZwClose(hKey);
}
return fUseSmbFromNetBT;
}
static KTIMER DelayedInitTimer;
static KDPC DelayedInitDpc;
static WORK_QUEUE_ITEM DelayedInitWorkItem;
static VOID
SmbDelayedInitRtn(
PVOID pvUnused1
)
{
NTSTATUS status = STATUS_SUCCESS;
status = SmbInitTdi();
ObDereferenceObject(&(SmbCfg.SmbDeviceObject->DeviceObject));
}
static VOID
SmbDelayedInitTimeoutRtn(
IN PKDPC Dpc,
IN PVOID Ctx,
IN PVOID SystemArg1,
IN PVOID SystemArg2
)
{
ExInitializeWorkItem(&DelayedInitWorkItem, SmbDelayedInitRtn, NULL);
ExQueueWorkItem(&DelayedInitWorkItem, DelayedWorkQueue);
}
static NTSTATUS
SmbDelayedInitTdi(
DWORD dwDelayedTime
)
{
NTSTATUS status = STATUS_SUCCESS;
LARGE_INTEGER DueTime = { 0 };
KeInitializeTimer(&DelayedInitTimer);
KeInitializeDpc(&DelayedInitDpc, SmbDelayedInitTimeoutRtn, NULL);
DueTime.QuadPart = UInt32x32To64(dwDelayedTime,(LONG)10000);
DueTime.QuadPart = -DueTime.QuadPart;
ObReferenceObject(&(SmbCfg.SmbDeviceObject->DeviceObject));
KeSetTimer(&DelayedInitTimer, DueTime, &DelayedInitDpc);
return status;
}
NTSTATUS
SmbDriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN OUT PDEVICE_OBJECT *SmbDevice
)
/*++
Routine Description:
This is the initialization routine for the SMB device driver.
This routine creates the device object for the SMB
device and calls a routine to perform other driver initialization.
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
NTSTATUS - The function value is the final status from the initialization
operation.
--*/
{
NTSTATUS status;
PAGED_CODE();
RtlZeroMemory(&SmbCfg, sizeof(SmbCfg));
if (SmbDevice) {
*SmbDevice = NULL;
}
SmbCfg.DriverObject = DriverObject;
InitializeListHead(&SmbCfg.IPDeviceList);
InitializeListHead(&SmbCfg.PendingDeleteIPDeviceList);
KeInitializeSpinLock(&SmbCfg.UsedIrpsLock);
InitializeListHead(&SmbCfg.UsedIrps);
KeInitializeSpinLock(&SmbCfg.Lock);
SmbCfg.FspProcess =(PEPROCESS)PsGetCurrentProcess();
status = ExInitializeResourceLite(&SmbCfg.Resource);
BAIL_OUT_ON_ERROR(status);
status = SmbInitRegistry(RegistryPath);
BAIL_OUT_ON_ERROR(status);
#if DBG
if (SmbReadULong(SmbCfg.ParametersKey, L"Break", 0, 0)) {
DbgBreakPoint();
}
SmbCfg.DebugFlag = SmbReadULong(SmbCfg.ParametersKey, L"DebugFlag", 0, 0);
#endif
#ifdef STANDALONE_SMB
if (IsNetBTSmbEnabled(RegistryPath)) {
SmbPrint(SMB_TRACE_PNP, ("Abort the initialization of SMB since NetBT's Smb device is enabled\n"));
SmbTrace(SMB_TRACE_PNP, ("Abort the initialization of SMB since NetBT's Smb device is enabled"));
return STATUS_UNSUCCESSFUL;
}
#endif
SmbCfg.EnableNagling = SmbReadULong (
SmbCfg.ParametersKey,
SMB_REG_ENABLE_NAGLING,
0, // Disabled by default
0
);
SmbCfg.DnsTimeout = SmbReadULong (
SmbCfg.ParametersKey,
SMB_REG_DNS_TIME_OUT,
SMB_REG_DNS_TIME_OUT_DEFAULT,
SMB_REG_DNS_TIME_OUT_MIN
);
SmbCfg.DnsMaxResolver = SmbReadLong (
SmbCfg.ParametersKey,
SMB_REG_DNS_MAX_RESOLVER,
SMB_REG_DNS_RESOLVER_DEFAULT,
SMB_REG_DNS_RESOLVER_MIN
);
if (SmbCfg.DnsMaxResolver > DNS_MAX_RESOLVER) {
SmbCfg.DnsMaxResolver = DNS_MAX_RESOLVER;
}
SmbCfg.uIPv6Protection = SmbReadULong(
SmbCfg.ParametersKey,
SMB_REG_IPV6_PROTECTION,
SMB_REG_IPV6_PROTECTION_DEFAULT,
0
);
SmbCfg.bIPv6EnableOutboundGlobal = SmbReadULong(
SmbCfg.ParametersKey,
SMB_REG_IPV6_ENABLE_OUTBOUND_GLOBAL,
FALSE, // default value
0
);
#ifndef NO_LOOKASIDE_LIST
//
// Initialize Lookaside Lists
//
ExInitializeNPagedLookasideList(
&SmbCfg.ConnectObjectPool,
NULL,
NULL,
0,
sizeof(SMB_CONNECT),
CONNECT_OBJECT_POOL_TAG,
0
);
SmbCfg.ConnectObjectPoolInitialized = TRUE;
ExInitializeNPagedLookasideList(
&SmbCfg.TcpContextPool,
NULL,
NULL,
0,
sizeof(SMB_TCP_CONTEXT),
TCP_CONTEXT_POOL_TAG,
0
);
SmbCfg.TcpContextPoolInitialized = TRUE;
#endif
#ifdef STANDALONE_SMB
TdiInitialize();
#endif
status = SmbCreateSmbDevice(&SmbCfg.SmbDeviceObject, SMB_TCP_PORT, SMB_ENDPOINT_NAME);
BAIL_OUT_ON_ERROR(status);
status = SmbInitDnsResolver();
BAIL_OUT_ON_ERROR(status);
status = SmbInitIPv6NetbiosMappingTable();
BAIL_OUT_ON_ERROR(status);
#ifdef STANDALONE_SMB
status = SmbDelayedInitTdi(1000);
BAIL_OUT_ON_ERROR(status);
#endif
if (SmbDevice) {
*SmbDevice = &(SmbCfg.SmbDeviceObject->DeviceObject);
}
return (status);
cleanup:
SmbUnload(DriverObject);
return status;
}
//----------------------------------------------------------------------------
NTSTATUS
SmbDispatchCleanup(
IN PSMB_DEVICE Device,
IN PIRP Irp
)
/*++
Routine Description:
This is the SMB driver's dispatch function for IRP_MJ_CLEANUP
requests.
This function is called when the last reference to the handle is closed.
Hence, an NtClose() results in an IRP_MJ_CLEANUP first, and then an
IRP_MJ_CLOSE. This function runs down all activity on the object, and
when the close comes in the object is actually deleted.
Arguments:
device - ptr to device object for target device
pIrp - ptr to I/O request packet
Return Value:
STATUS_SUCCESS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
PAGED_CODE();
if (SmbCfg.Unloading) {
status = STATUS_INVALID_DEVICE_REQUEST;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IrpSp->MajorFunction == IRP_MJ_CLEANUP);
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return(status);
}
//----------------------------------------------------------------------------
NTSTATUS
SmbDispatchClose(
IN PSMB_DEVICE Device,
IN PIRP Irp
)
/*++
Routine Description:
This is the SMB driver's dispatch function for IRP_MJ_CLOSE
requests. This is called after Cleanup (above) is called.
Arguments:
device - ptr to device object for target device
pIrp - ptr to I/O request packet
Return Value:
an NT status code.
--*/
{
NTSTATUS status;
PIO_STACK_LOCATION IrpSp;
PAGED_CODE();
if (SmbCfg.Unloading) {
status = STATUS_INVALID_DEVICE_REQUEST;
goto cleanup;
}
ASSERT(Device == SmbCfg.SmbDeviceObject);
IrpSp = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IrpSp->MajorFunction == IRP_MJ_CLOSE);
switch(PtrToUlong(IrpSp->FileObject->FsContext2)) {
case SMB_TDI_CONTROL:
status = SmbCloseControl(Device, Irp);
break;
case SMB_TDI_CLIENT:
status = SmbCloseClient(Device, Irp);
break;
case SMB_TDI_CONNECT:
status = SmbCloseConnection(Device, Irp);
break;
default:
status = STATUS_SUCCESS;
}
ASSERT(status != STATUS_PENDING);
cleanup:
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return status;
}
PFILE_FULL_EA_INFORMATION
SmbFindInEA(
IN PFILE_FULL_EA_INFORMATION eabuf,
IN PCHAR wanted
);
#pragma alloc_text(PAGE, SmbFindInEA)
PFILE_FULL_EA_INFORMATION
SmbFindInEA(
IN PFILE_FULL_EA_INFORMATION eabuf,
IN PCHAR wanted
)
/*++
Routine Description:
This function check for the "Wanted" string in the Ea structure and
returns a pointer to the extended attribute structure
representing the given extended attribute name.
Arguments:
Return Value:
pointer to the extended attribute structure, or NULL if not found.
--*/
{
PAGED_CODE();
while(1) {
if (strncmp(eabuf->EaName, wanted, eabuf->EaNameLength) == 0) {
return eabuf;
}
if (0 == eabuf->NextEntryOffset) {
return NULL;
}
eabuf = (PFILE_FULL_EA_INFORMATION) ((PUCHAR)eabuf + eabuf->NextEntryOffset);
}
}
NTSTATUS
SmbDispatchCreate(
IN PSMB_DEVICE Device,
IN PIRP Irp
)
/*++
Routine Description:
This is the SMB driver's dispatch function for IRP_MJ_CREATE
requests. It is called as a consequence of one of the following:
a. TdiOpenConnection("\Device\Smb_Elnkii0"),
b. TdiOpenAddress("\Device\Smb_Elnkii0"),
Arguments:
Device - ptr to device object being opened
pIrp - ptr to I/O request packet
pIrp->Status => return status
pIrp->MajorFunction => IRP_MD_CREATE
pIrp->MinorFunction => not used
pIrp->FileObject => ptr to file obj created by I/O system. SMB fills in FsContext
pIrp->AssociatedIrp.SystemBuffer => ptr to EA buffer with address of obj to open(Netbios Name)
pIrp->Parameters.Create.EaLength => length of buffer specifying the Xport Addr.
Return Value:
STATUS_SUCCESS or STATUS_PENDING
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
PFILE_FULL_EA_INFORMATION ea, wanted_ea;
PAGED_CODE();
if (SmbCfg.Unloading) {
SmbPrint(SMB_TRACE_PNP, ("DispatchCreate: Smb is unloading\n"));
status = STATUS_INVALID_DEVICE_REQUEST;
goto cleanup;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
ASSERT(Device == SmbCfg.SmbDeviceObject);
ASSERT(IrpSp->MajorFunction == IRP_MJ_CREATE);
ea = Irp->AssociatedIrp.SystemBuffer;
if (NULL == ea || KernelMode != Irp->RequestorMode) {
status = SmbCreateControl(Device, Irp);
} else if (NULL != (wanted_ea = SmbFindInEA(ea, TdiConnectionContext))) {
// Not allow to pass in both a connection request and a transport address request
ASSERT(!SmbFindInEA(ea, TdiTransportAddress));
status = SmbCreateConnection(Device, Irp, wanted_ea);
} else if (NULL != (wanted_ea = SmbFindInEA(ea, TdiTransportAddress))) {
// Not allow to pass in both a connection request and a transport address request
ASSERT(!SmbFindInEA(ea, TdiConnectionContext));
status = SmbCreateClient(Device, Irp, wanted_ea);
} else {
status = STATUS_INVALID_EA_NAME;
}
cleanup:
ASSERT(status != STATUS_PENDING);
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return(status);
}
NTSTATUS
SmbDispatchDevCtrl(
IN PSMB_DEVICE Device,
IN PIRP Irp
)
/*++
Routine Description:
This is the SMB driver's dispatch function for all
IRP_MJ_DEVICE_CONTROL requests.
Arguments:
device - ptr to device object for target device
pIrp - ptr to I/O request packet
Return Value:
NTSTATUS -- Indicates whether the request was successfully queued.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
if (SmbCfg.Unloading) {
SmbPrint(SMB_TRACE_PNP, ("DispatchDevCtrl: Smb is unloading\n"));
status = STATUS_INVALID_DEVICE_REQUEST;
goto cleanup;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch(IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_SMB_START:
SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_SMB_START"));
SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_SMB_START\n"));
status = SmbTdiRegister(Device);
break;
case IOCTL_SMB_STOP:
SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_SMB_STOP"));
SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_SMB_STOP\n"));
status = SmbTdiDeregister(Device);
break;
case IOCTL_SMB_DNS:
status = SmbNewResolver(Device, Irp);
break;
case IOCTL_SMB_ENABLE_NAGLING:
SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_SMB_ENABLE_NAGLING"));
SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_SMB_ENABLE_NAGLING\n"));
SmbCfg.EnableNagling = TRUE;
status = STATUS_SUCCESS;
TODO("Turn on nagling for each connection in the pool");
break;
case IOCTL_SMB_DISABLE_NAGLING:
SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_SMB_DISABLE_NAGLING"));
SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_SMB_DISABLE_NAGLING\n"));
SmbCfg.EnableNagling = FALSE;
status = STATUS_SUCCESS;
TODO("Turn off nagling for each connection in the pool");
break;
case IOCTL_SMB_SET_IPV6_PROTECTION_LEVEL:
//
// Set IPv6 Protection level
//
status = IoctlSetIPv6Protection(Device, Irp, IrpSp);
break;
case IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER:
SmbTrace(SMB_TRACE_IOCTL, ("IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER"));
SmbPrint(SMB_TRACE_IOCTL, ("IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER\n"));
if (Irp->RequestorMode != KernelMode) {
//
// There is no point for usermode application to query FastSend
//
status = STATUS_ACCESS_DENIED;
break;
}
(PVOID)(IrpSp->Parameters.DeviceIoControl.Type3InputBuffer) = (PVOID)SmbSend;
status = STATUS_SUCCESS;
break;
//
// Legacy NetBT stuff
// The following Ioctl is used by the Rdr/Srv to add/remove addresses from the SmbDevice
//
case IOCTL_NETBT_SET_SMBDEVICE_BIND_INFO:
status = SmbSetBindingInfo(Device, Irp);
break;
//
// Used by Srv service
//
case IOCTL_NETBT_SET_TCP_CONNECTION_INFO:
status = SmbClientSetTcpInfo(Device, Irp);
break;
//
// Who is going to use this?
//
case IOCTL_NETBT_GET_CONNECTIONS:
status = STATUS_NOT_SUPPORTED;
break;
default:
status = STATUS_NOT_SUPPORTED;
break;
}
cleanup:
if (status != STATUS_PENDING) {
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
return status;
}
NTSTATUS
SmbDispatchInternalCtrl(
IN PSMB_DEVICE Device,
IN PIRP Irp
)
/*++
Routine Description:
This is the driver's dispatch function for all
IRP_MJ_INTERNAL_DEVICE_CONTROL requests.
Arguments:
device - ptr to device object for target device
pIrp - ptr to I/O request packet
Return Value:
NTSTATUS -- Indicates whether the request was successfully queued.
--*/
{
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
PIO_STACK_LOCATION IrpSp = NULL;
BOOL bShouldCompleteIrp = TRUE;
if (SmbCfg.Unloading) {
SmbPrint(SMB_TRACE_PNP, ("DispatchIntDevCtrl: Smb is unloading\n"));
status = STATUS_INVALID_DEVICE_REQUEST;
goto cleanup;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch(IrpSp->MinorFunction) {
case TDI_ACCEPT:
status = SmbAccept(Device, Irp);
break;
case TDI_LISTEN:
status = SmbListen(Device, Irp);
break;
case TDI_ASSOCIATE_ADDRESS:
status = SmbAssociateAddress(Device, Irp);
break;
case TDI_DISASSOCIATE_ADDRESS:
status = SmbDisAssociateAddress(Device, Irp);
break;
case TDI_CONNECT:
status = SmbConnect(Device, Irp);
break;
case TDI_DISCONNECT:
status = SmbDisconnect(Device, Irp);
break;
case TDI_SEND:
status = SmbSend(Device, Irp);
break;
case TDI_RECEIVE:
status = SmbReceive(Device, Irp);
break;
case TDI_SEND_DATAGRAM:
status = SmbSendDatagram(Device, Irp);
break;
case TDI_RECEIVE_DATAGRAM:
status = SmbReceiveDatagram(Device, Irp);
break;
case TDI_QUERY_INFORMATION:
status = SmbQueryInformation(Device, Irp, &bShouldCompleteIrp);
break;
case TDI_SET_EVENT_HANDLER:
status = SmbSetEventHandler(Device, Irp);
break;
case TDI_SET_INFORMATION:
status = SmbSetInformation(Device, Irp);
break;
#if DBG
//
// 0x7f is a request by the Redir to put a "magic bullet" out
// on the wire, to trigger the Network General Sniffer.
//
case 0x7f:
#endif
default:
status = STATUS_NOT_SUPPORTED;
break;
}
cleanup:
if (status != STATUS_PENDING && bShouldCompleteIrp) {
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
} else {
//
// Don't mark IRP pending here because it could have been completed.
//
}
return(status);
} // SmbDispatchInternalCtrl
NTSTATUS
SmbQueryTargetDeviceRelationForConnection(
PSMB_CONNECT ConnectObject,
PIRP Irp
)
{
PFILE_OBJECT TcpFileObject = NULL;
PDEVICE_OBJECT TcpDeviceObject = NULL;
PIO_STACK_LOCATION IrpSp = NULL, IrpSpNext = NULL;
KIRQL Irql;
NTSTATUS status = STATUS_CONNECTION_INVALID;
SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
if (NULL == ConnectObject->TcpContext) {
TcpFileObject = NULL;
} else {
TcpFileObject = ConnectObject->TcpContext->Connect.ConnectObject;
ASSERT(TcpFileObject != NULL);
TcpDeviceObject = IoGetRelatedDeviceObject (TcpFileObject);
if (NULL == TcpDeviceObject) {
TcpFileObject = NULL;
} else {
ObReferenceObject(TcpFileObject);
}
}
SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
SmbDereferenceConnect(ConnectObject, SMB_REF_TDI);
if (NULL == TcpFileObject) {
status = STATUS_CONNECTION_INVALID;
goto cleanup;
}
//
// Simply pass the Irp on by to the Transport, and let it
// fill in the info
//
IrpSp = IoGetCurrentIrpStackLocation(Irp);
IrpSpNext = IoGetNextIrpStackLocation (Irp);
*IrpSpNext = *IrpSp;
IoSetCompletionRoutine (Irp, NULL, NULL, FALSE, FALSE, FALSE);
IrpSpNext->FileObject = TcpFileObject;
IrpSpNext->DeviceObject = TcpDeviceObject;
status = IoCallDriver(TcpDeviceObject, Irp);
ObDereferenceObject(TcpFileObject);
//
// Irp could be completed. Don't access it anymore
//
return status;
cleanup:
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return status;
}
NTSTATUS
SmbDispatchPnP(
IN PSMB_DEVICE Device,
IN PIRP Irp
)
{
PIO_STACK_LOCATION IrpSp = NULL;
PSMB_CLIENT_ELEMENT ClientObject = NULL;
PSMB_CONNECT ConnectObject = NULL;
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MinorFunction) {
case IRP_MN_QUERY_DEVICE_RELATIONS:
if (IrpSp->Parameters.QueryDeviceRelations.Type==TargetDeviceRelation) {
ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_TDI);
ClientObject = SmbVerifyAndReferenceClient(IrpSp->FileObject, SMB_REF_TDI);
if (ConnectObject != NULL) {
ASSERT(ClientObject == NULL);
return SmbQueryTargetDeviceRelationForConnection(ConnectObject, Irp);
} else if (ClientObject != NULL) {
SmbDereferenceClient(ClientObject, SMB_REF_TDI);
status = STATUS_NOT_SUPPORTED;
} else {
ASSERT (0);
}
}
break;
default:
break;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
return status;
}
VOID
SmbUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
This is the SMB driver's dispatch function for Unload requests
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
None
--*/
{
PAGED_CODE();
SmbCfg.Unloading = TRUE;
if (NULL == SmbCfg.DriverObject) {
return;
}
#ifdef STANDALONE_SMB
SmbShutdownTdi();
#endif
SmbShutdownRegistry();
SmbShutdownDnsResolver();
SmbShutdownIPv6NetbiosMappingTable();
SmbDestroySmbDevice(SmbCfg.SmbDeviceObject);
SmbCfg.SmbDeviceObject = NULL;
#ifndef NO_LOOKASIDE_LIST
if (SmbCfg.ConnectObjectPoolInitialized) {
ExDeleteNPagedLookasideList(&SmbCfg.ConnectObjectPool);
SmbCfg.ConnectObjectPoolInitialized = FALSE;
}
if (SmbCfg.TcpContextPoolInitialized) {
ExDeleteNPagedLookasideList(&SmbCfg.TcpContextPool);
SmbCfg.TcpContextPoolInitialized = FALSE;
}
#endif
SmbCfg.DriverObject = NULL;
ExDeleteResourceLite(&SmbCfg.Resource);
NotifyNetBT(NETBT_RESTORE_NETBIOS_SMB);
}