|
|
/*++
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); }
|