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.
784 lines
24 KiB
784 lines
24 KiB
/*++
|
|
|
|
Copyright (c) 1989-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ioctl.c
|
|
|
|
Abstract:
|
|
|
|
I/O Control of SMB6 device
|
|
|
|
Author:
|
|
|
|
Jiandong Ruan
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "nb30.h"
|
|
#include "ioctl.tmh"
|
|
|
|
#pragma alloc_text(PAGE, SmbCreateControl)
|
|
|
|
NTSTATUS
|
|
SmbCreateControl(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
PAGED_CODE();
|
|
|
|
SmbPrint(SMB_TRACE_CALL, ("Enter SmbCreateControl\n"));
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
IrpSp->FileObject->FsContext = NULL;
|
|
IrpSp->FileObject->FsContext2 = UlongToPtr(SMB_TDI_CONTROL);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbCloseControl(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
#pragma alloc_text(PAGE, SmbCloseControl)
|
|
{
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
PAGED_CODE();
|
|
|
|
SmbPrint(SMB_TRACE_CALL, ("Enter SmbCloseControl\n"));
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
ASSERT (IrpSp->FileObject->FsContext2 == UlongToPtr(SMB_TDI_CONTROL));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbQueryProviderCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles the completion event when the Query Provider
|
|
Information completes. This routine must decrement the MaxDgramSize
|
|
and max send size by the respective NBT header sizes.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
The final status from the operation (success or an exception).
|
|
|
|
--*/
|
|
{
|
|
PTDI_PROVIDER_INFO Provider;
|
|
|
|
if (!NT_SUCCESS(Irp->IoStatus.Status)) {
|
|
ASSERT(0);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
Provider = (PTDI_PROVIDER_INFO)MmGetMdlVirtualAddress(Irp->MdlAddress);
|
|
Provider->ServiceFlags = TDI_SERVICE_MESSAGE_MODE |
|
|
TDI_SERVICE_CONNECTION_MODE |
|
|
TDI_SERVICE_CONNECTIONLESS_MODE |
|
|
TDI_SERVICE_ERROR_FREE_DELIVERY |
|
|
TDI_SERVICE_BROADCAST_SUPPORTED |
|
|
TDI_SERVICE_MULTICAST_SUPPORTED |
|
|
TDI_SERVICE_DELAYED_ACCEPTANCE |
|
|
TDI_SERVICE_ROUTE_DIRECTED |
|
|
TDI_SERVICE_FORCE_ACCESS_CHECK;
|
|
Provider->MinimumLookaheadData = 128;
|
|
|
|
//
|
|
// Adjust maximum session packet size
|
|
//
|
|
if (Provider->MaxSendSize > SMB_SESSION_HEADER_SIZE) {
|
|
if (Provider->MaxSendSize > (0x1ffff + SMB_SESSION_HEADER_SIZE)) {
|
|
Provider->MaxSendSize = 0x1ffff;
|
|
} else {
|
|
Provider->MaxSendSize -= SMB_SESSION_HEADER_SIZE;
|
|
}
|
|
} else {
|
|
Provider->MaxSendSize = 0;
|
|
}
|
|
|
|
//
|
|
// SMB device doesn't support datagram
|
|
//
|
|
Provider->MaxDatagramSize = 0;
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbQueryProviderCompletion: Complete IRP %p\n", Irp));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbQueryTcpProviderInfo(
|
|
PFILE_OBJECT ControlFileObject,
|
|
PIRP Irp,
|
|
PTDI_PROVIDER_INFO TcpProvider
|
|
)
|
|
{
|
|
PMDL Mdl, SavedMdl;
|
|
NTSTATUS status;
|
|
|
|
TcpProvider->MaxSendSize = SMB_MAX_SESSION_PACKET;
|
|
if (NULL == ControlFileObject) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
Mdl = IoAllocateMdl(TcpProvider, sizeof(TDI_PROVIDER_INFO), FALSE, FALSE, NULL);
|
|
if (NULL == Mdl) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
MmBuildMdlForNonPagedPool(Mdl);
|
|
|
|
SavedMdl = Irp->MdlAddress;
|
|
TdiBuildQueryInformation(
|
|
Irp,
|
|
IoGetRelatedDeviceObject(ControlFileObject),
|
|
ControlFileObject,
|
|
NULL,
|
|
NULL,
|
|
TDI_QUERY_PROVIDER_INFO,
|
|
Mdl
|
|
);
|
|
status = SubmitSynchTdiRequest (ControlFileObject, Irp);
|
|
Irp->MdlAddress = SavedMdl;
|
|
if (status == STATUS_SUCCESS) {
|
|
if (TcpProvider->MaxSendSize > SMB_SESSION_HEADER_SIZE) {
|
|
if (TcpProvider->MaxSendSize > (0x1ffff + SMB_SESSION_HEADER_SIZE)) {
|
|
TcpProvider->MaxSendSize = 0x1ffff;
|
|
} else {
|
|
TcpProvider->MaxSendSize -= SMB_SESSION_HEADER_SIZE;
|
|
}
|
|
} else {
|
|
TcpProvider->MaxSendSize = 0;
|
|
}
|
|
SmbPrint(SMB_TRACE_TCP, ("SmbQueryTcpProviderInfo returns MaxSendSize = %d bytes\n",
|
|
TcpProvider->MaxSendSize));
|
|
SmbTrace(SMB_TRACE_TCP, ("returns MaxSendSize = %d bytes", TcpProvider->MaxSendSize));
|
|
} else {
|
|
SmbPrint(SMB_TRACE_TCP, ("SmbQueryTcpProviderInfo returns status = 0x%08lx\n", status));
|
|
SmbTrace(SMB_TRACE_TCP, ("returns %!status!", status));
|
|
}
|
|
|
|
IoFreeMdl(Mdl);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbQueryProviderInfo(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PTDI_PROVIDER_INFO TcpProvider = NULL, Provider = NULL;
|
|
DWORD BytesCopied = 0;
|
|
|
|
if (NULL == Irp->MdlAddress) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
TcpProvider = (PTDI_PROVIDER_INFO)ExAllocatePoolWithTag(
|
|
NonPagedPool, sizeof(TDI_PROVIDER_INFO), '6BMS');
|
|
Provider = (PTDI_PROVIDER_INFO)ExAllocatePoolWithTag(
|
|
NonPagedPool, sizeof(TDI_PROVIDER_INFO), '6BMS');
|
|
if (NULL == TcpProvider || NULL == Provider) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto cleanup;
|
|
}
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
RtlZeroMemory(Provider, sizeof(TDI_PROVIDER_INFO));
|
|
|
|
//
|
|
// Set SMB-specific information
|
|
//
|
|
Provider->Version = 0x0200;
|
|
Provider->MaxSendSize = SMB_MAX_SESSION_PACKET;
|
|
Provider->MaxConnectionUserData = 0;
|
|
Provider->MaxDatagramSize = 0;
|
|
Provider->ServiceFlags = TDI_SERVICE_MESSAGE_MODE |
|
|
TDI_SERVICE_CONNECTION_MODE |
|
|
TDI_SERVICE_CONNECTIONLESS_MODE |
|
|
TDI_SERVICE_ERROR_FREE_DELIVERY |
|
|
TDI_SERVICE_BROADCAST_SUPPORTED |
|
|
TDI_SERVICE_MULTICAST_SUPPORTED |
|
|
TDI_SERVICE_DELAYED_ACCEPTANCE |
|
|
TDI_SERVICE_ROUTE_DIRECTED |
|
|
TDI_SERVICE_FORCE_ACCESS_CHECK;
|
|
Provider->MinimumLookaheadData = 128;
|
|
Provider->MaximumLookaheadData = SMB_MAX_SESSION_PACKET;
|
|
|
|
//
|
|
// Query TCP4 info
|
|
//
|
|
if (SmbCfg.Tcp4Available) {
|
|
status = SmbQueryTcpProviderInfo(Device->Tcp4.TCPControlFileObject, Irp, TcpProvider);
|
|
if (status == STATUS_SUCCESS) {
|
|
if (Provider->MaxSendSize > TcpProvider->MaxSendSize) {
|
|
Provider->MaxSendSize = TcpProvider->MaxSendSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Query TCP6 info
|
|
//
|
|
if (SmbCfg.Tcp6Available) {
|
|
status = SmbQueryTcpProviderInfo(Device->Tcp6.TCPControlFileObject, Irp, TcpProvider);
|
|
if (status == STATUS_SUCCESS) {
|
|
if (Provider->MaxSendSize > TcpProvider->MaxSendSize) {
|
|
Provider->MaxSendSize = TcpProvider->MaxSendSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
BytesCopied = 0;
|
|
status = TdiCopyBufferToMdl (Provider, 0, sizeof(TDI_PROVIDER_INFO),
|
|
Irp->MdlAddress, 0, &BytesCopied);
|
|
|
|
cleanup:
|
|
if (NULL != TcpProvider) {
|
|
ExFreePool(TcpProvider);
|
|
TcpProvider = NULL;
|
|
}
|
|
if (NULL != Provider) {
|
|
ExFreePool(Provider);
|
|
Provider = NULL;
|
|
}
|
|
Irp->IoStatus.Status = status;
|
|
Irp->IoStatus.Information = (status != STATUS_SUCCESS)? 0: BytesCopied;
|
|
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbQueryAdapterStatus(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the local adapter status
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS.
|
|
Note: this routine should complete the IRP because
|
|
the caller doesn't complete it.
|
|
|
|
Smb device is netbiosless. We don't need to return
|
|
name cache as we do in legacy NetBT devices.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DWORD Size = 0, BytesCopied = 0;
|
|
ADAPTER_STATUS as = { 0 };
|
|
|
|
if (NULL == Irp->MdlAddress) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
Size = MmGetMdlByteCount (Irp->MdlAddress);
|
|
if (Size < sizeof(ADAPTER_STATUS)) {
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
goto cleanup;
|
|
}
|
|
|
|
RtlZeroMemory(&as, sizeof(ADAPTER_STATUS));
|
|
as.rev_major = 0x03;
|
|
as.adapter_type = 0xFE; // pretend it is an ethernet adapter
|
|
as.name_count = 0; // Smb device won't return the name cache
|
|
as.max_cfg_sess = (USHORT)0xffff;
|
|
as.max_sess = (USHORT)0xffff;
|
|
as.free_ncbs = (USHORT)0xffff;
|
|
as.max_cfg_ncbs = (USHORT)0xffff;
|
|
as.max_ncbs = (USHORT)0xffff;
|
|
as.max_dgram_size = 0; // Smb device doesn't support datagram
|
|
as.max_sess_pkt_size = 0xffff;
|
|
|
|
BytesCopied = 0;
|
|
status = TdiCopyBufferToMdl (&as, 0, sizeof(ADAPTER_STATUS),
|
|
Irp->MdlAddress, 0, &BytesCopied);
|
|
|
|
cleanup:
|
|
Irp->IoStatus.Status = status;
|
|
Irp->IoStatus.Information = (status != STATUS_SUCCESS)? 0: BytesCopied;
|
|
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbQueryPeerInfo(
|
|
PSMB_CONNECT ConnectObject,
|
|
PNBT_ADDRESS_PAIR_INFO AddressPair,
|
|
DWORD Size,
|
|
DWORD *BytesCopied
|
|
)
|
|
{
|
|
KIRQL Irql = 0;
|
|
NBT_ADDRESS_PAIR_INFO ap = { 0 };
|
|
DWORD RequiredSize = 0;
|
|
|
|
*BytesCopied = 0;
|
|
|
|
RtlZeroMemory(&ap, sizeof(ap));
|
|
ap.ActivityCount = 1;
|
|
ap.AddressPair.TAAddressCount = 2;
|
|
|
|
SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
|
|
if (NULL == ConnectObject->TcpContext) {
|
|
SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
|
|
return STATUS_CONNECTION_DISCONNECTED;
|
|
}
|
|
|
|
//
|
|
// Fill IP address
|
|
//
|
|
if (SMB_AF_INET == ConnectObject->RemoteIpAddress.sin_family) {
|
|
ap.AddressPair.AddressIP.AddressLength = TDI_ADDRESS_LENGTH_IP;
|
|
ap.AddressPair.AddressIP.AddressType = TDI_ADDRESS_TYPE_IP;
|
|
ap.AddressPair.AddressIP.Address.in_addr = ConnectObject->RemoteIpAddress.ip4.sin4_addr;
|
|
RequiredSize = sizeof(ap) +
|
|
sizeof(ap.AddressPair.AddressIP.Address) -
|
|
sizeof(ap.AddressPair.AddressIP.AddressIp6);
|
|
} else {
|
|
ap.AddressPair.AddressIP.AddressLength = TDI_ADDRESS_LENGTH_IP6;
|
|
ap.AddressPair.AddressIP.AddressType = TDI_ADDRESS_TYPE_IP6;
|
|
RtlCopyMemory(
|
|
ap.AddressPair.AddressIP.AddressIp6.sin6_addr,
|
|
ConnectObject->RemoteIpAddress.ip6.sin6_addr,
|
|
sizeof(ap.AddressPair.AddressIP.AddressIp6.sin6_addr)
|
|
);
|
|
ap.AddressPair.AddressIP.AddressIp6.sin6_scope_id = ConnectObject->RemoteIpAddress.ip6.sin6_scope_id;
|
|
RequiredSize = sizeof(ap);
|
|
}
|
|
|
|
//
|
|
// Fill Netbios address
|
|
//
|
|
ap.AddressPair.AddressNetBIOS.AddressType = TDI_ADDRESS_TYPE_NETBIOS;
|
|
ap.AddressPair.AddressNetBIOS.AddressLength = TDI_ADDRESS_LENGTH_NETBIOS;
|
|
ap.AddressPair.AddressNetBIOS.Address.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
|
|
RtlCopyMemory(
|
|
ap.AddressPair.AddressNetBIOS.Address.NetbiosName,
|
|
ConnectObject->RemoteName,
|
|
NETBIOS_NAME_SIZE
|
|
);
|
|
SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
|
|
|
|
if (Size > sizeof(ap)) {
|
|
Size = sizeof(ap);
|
|
}
|
|
|
|
RtlCopyMemory(AddressPair, &ap, Size);
|
|
*BytesCopied = Size;
|
|
|
|
//
|
|
// note: STATUS_BUFFER_OVERFLOW can pass NT_SUCCESS(status)
|
|
//
|
|
return (Size < RequiredSize)? STATUS_BUFFER_OVERFLOW: STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbQueryAddressInfo(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PSMB_CONNECT ConnectObject = NULL;
|
|
PIO_STACK_LOCATION IrpSp = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DWORD BytesCopied = 0;
|
|
|
|
if (NULL == Irp->MdlAddress) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
SmbPrint(SMB_TRACE_CALL, ("Client needs changes to use IP6 address %d of %s\n",
|
|
__LINE__, __FILE__));
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_TDI);
|
|
if (NULL == ConnectObject) {
|
|
ASSERT(0);
|
|
status = STATUS_NOT_SUPPORTED;
|
|
goto cleanup;
|
|
}
|
|
|
|
status = SmbQueryPeerInfo(ConnectObject,
|
|
(PNBT_ADDRESS_PAIR_INFO)MmGetMdlVirtualAddress(Irp->MdlAddress),
|
|
MmGetMdlByteCount (Irp->MdlAddress),
|
|
&BytesCopied
|
|
);
|
|
SmbDereferenceConnect(ConnectObject, SMB_REF_TDI);
|
|
|
|
cleanup:
|
|
Irp->IoStatus.Status = status;
|
|
Irp->IoStatus.Information = (status != STATUS_SUCCESS)? 0: BytesCopied;
|
|
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbQueryConnectionInfo(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION IrpSp = NULL;
|
|
PSMB_CONNECT ConnectObject = NULL;
|
|
PDEVICE_OBJECT DeviceObject = NULL;
|
|
PFILE_OBJECT TcpConnObject = NULL;
|
|
KIRQL Irql = 0;
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_TDI);
|
|
if (NULL == ConnectObject) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
|
|
if (NULL == ConnectObject->TcpContext) {
|
|
TcpConnObject = NULL;
|
|
DeviceObject = NULL;
|
|
} else {
|
|
TcpConnObject = ConnectObject->TcpContext->Connect.ConnectObject;
|
|
ASSERT(TcpConnObject != NULL);
|
|
ObReferenceObject(TcpConnObject);
|
|
DeviceObject = IoGetRelatedDeviceObject(TcpConnObject);
|
|
}
|
|
SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
|
|
|
|
if (NULL == TcpConnObject) {
|
|
SmbDereferenceConnect(ConnectObject, SMB_REF_TDI);
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
TdiBuildQueryInformation(
|
|
Irp,
|
|
DeviceObject,
|
|
TcpConnObject,
|
|
NULL, NULL,
|
|
TDI_QUERY_CONNECTION_INFO,
|
|
Irp->MdlAddress
|
|
);
|
|
|
|
status = IoCallDriver(DeviceObject, Irp);
|
|
|
|
SmbDereferenceConnect(ConnectObject, SMB_REF_TDI);
|
|
ObDereferenceObject(TcpConnObject);
|
|
SmbPrint(SMB_TRACE_CALL, ("TCP returns 0x%08lx for TDI_QUERY_CONNECTION_INFO "
|
|
"%d of %s\n", status, __LINE__, __FILE__));
|
|
return status;
|
|
|
|
cleanup:
|
|
Irp->IoStatus.Status = status;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbQueryInformation(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp,
|
|
BOOL *bComplete
|
|
)
|
|
{
|
|
PTDI_REQUEST_KERNEL_QUERY_INFORMATION Query = NULL;
|
|
PIO_STACK_LOCATION IrpSp = NULL;
|
|
NTSTATUS status = STATUS_NOT_SUPPORTED;
|
|
|
|
*bComplete = TRUE;
|
|
|
|
SmbPrint(SMB_TRACE_CALL, ("Entering SmbQueryInformation IRP %p\n", Irp));
|
|
SmbTrace(SMB_TRACE_CALL, ("Entering SmbQueryInformation"));
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
Query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)(&IrpSp->Parameters);
|
|
|
|
switch(Query->QueryType) {
|
|
case TDI_QUERY_BROADCAST_ADDRESS:
|
|
//
|
|
// Smb device doesn't support broadcast
|
|
//
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
ASSERT(0);
|
|
break;
|
|
|
|
case TDI_QUERY_PROVIDER_INFO:
|
|
*bComplete = FALSE;
|
|
return SmbQueryProviderInfo(Device, Irp);
|
|
|
|
case TDI_QUERY_ADAPTER_STATUS:
|
|
if (Query->RequestConnectionInformation &&
|
|
Query->RequestConnectionInformation->RemoteAddress) {
|
|
//
|
|
// Smb device doesn't support quering remote machine status
|
|
//
|
|
status = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
*bComplete = FALSE;
|
|
return SmbQueryAdapterStatus(Device, Irp);
|
|
|
|
case TDI_QUERY_CONNECTION_INFO:
|
|
*bComplete = FALSE;
|
|
return SmbQueryConnectionInfo(Device, Irp);
|
|
|
|
case TDI_QUERY_FIND_NAME:
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case TDI_QUERY_ADDRESS_INFO:
|
|
*bComplete = FALSE;
|
|
return SmbQueryAddressInfo(Device, Irp);
|
|
|
|
case TDI_QUERY_SESSION_STATUS:
|
|
default:
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbQueryInformatoin: unsupported query type 0x%08lx\n",
|
|
Query->QueryType));
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbSetEventHandler(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION IrpSp;
|
|
NTSTATUS status;
|
|
KIRQL Irql;
|
|
PSMB_CLIENT_ELEMENT ClientObject;
|
|
PTDI_REQUEST_KERNEL_SET_EVENT TdiEvent;
|
|
|
|
PAGED_CODE();
|
|
SmbPrint(SMB_TRACE_CALL, ("Entering SmbSetEventHandler\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("Entering SmbSetEventHandler"));
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
ClientObject = SmbVerifyAndReferenceClient(IrpSp->FileObject, SMB_REF_TDI);
|
|
if (NULL == ClientObject) {
|
|
ASSERT(0);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
TdiEvent = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
SMB_ACQUIRE_SPINLOCK(ClientObject, Irql);
|
|
switch(TdiEvent->EventType) {
|
|
case TDI_EVENT_CONNECT:
|
|
ClientObject->evConnect = TdiEvent->EventHandler;
|
|
ClientObject->ConEvContext = TdiEvent->EventContext;
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiConnectHandler\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiConnectHandler"));
|
|
break;
|
|
|
|
case TDI_EVENT_DISCONNECT:
|
|
ClientObject->evDisconnect = TdiEvent->EventHandler;
|
|
ClientObject->DiscEvContext = TdiEvent->EventContext;
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiDisconnectHandler\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiDisconnectHandler"));
|
|
break;
|
|
|
|
case TDI_EVENT_RECEIVE:
|
|
ClientObject->evReceive = TdiEvent->EventHandler;
|
|
ClientObject->RcvEvContext = TdiEvent->EventContext;
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiReceiveHandler\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiReceiveHandler"));
|
|
break;
|
|
|
|
case TDI_EVENT_ERROR:
|
|
ClientObject->evError = TdiEvent->EventHandler;
|
|
ClientObject->ErrorEvContext = TdiEvent->EventContext;
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiErrorHandler\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiErrorHandler"));
|
|
break;
|
|
|
|
case TDI_EVENT_RECEIVE_DATAGRAM:
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiReceiveDatagram (unsupported)\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiReceiveDatagram (unsupported)"));
|
|
break;
|
|
|
|
case TDI_EVENT_RECEIVE_EXPEDITED:
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiReceiveExpedited (unsupported)\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiReceiveExpedited (unsupported)"));
|
|
break;
|
|
|
|
case TDI_EVENT_SEND_POSSIBLE:
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiSendPossible (unsupported)\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set TdiSendPossible (unsupported)"));
|
|
break;
|
|
|
|
default:
|
|
//status = STATUS_NOT_SUPPORTED;
|
|
SmbPrint(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set unsupported TDI event handler %lx\n",
|
|
TdiEvent->EventType));
|
|
SmbTrace(SMB_TRACE_CALL, ("SmbSetEventHandler: Client set upsupported TDI event handler %lx",
|
|
TdiEvent->EventType));
|
|
ASSERT (0);
|
|
}
|
|
SMB_RELEASE_SPINLOCK(ClientObject, Irql);
|
|
|
|
ASSERT(status != STATUS_PENDING);
|
|
SmbDereferenceClient(ClientObject, SMB_REF_TDI);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbSetInformation(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
SmbPrint(SMB_TRACE_CALL, ("Entering SmbSetInformation\n"));
|
|
SmbTrace(SMB_TRACE_CALL, ("Entering SmbSetInformation"));
|
|
ASSERT(0);
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
SmbClientSetTcpInfo(
|
|
PSMB_DEVICE Device,
|
|
PIRP Irp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION IrpSp;
|
|
PVOID InfoBuffer;
|
|
ULONG InfoBufferLength;
|
|
PSMB_CONNECT ConnectObject;
|
|
PFILE_OBJECT TcpConnObject;
|
|
KIRQL Irql;
|
|
NTSTATUS status;
|
|
|
|
if (Irp->RequestorMode != KernelMode) {
|
|
return STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
// BREAK_WHEN_TAKE();
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
InfoBuffer = Irp->AssociatedIrp.SystemBuffer;
|
|
InfoBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
|
|
|
ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_TDI);
|
|
if (NULL == ConnectObject) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
|
|
if (NULL == ConnectObject->TcpContext) {
|
|
TcpConnObject = NULL;
|
|
} else {
|
|
TcpConnObject = ConnectObject->TcpContext->Connect.ConnectObject;
|
|
ASSERT(TcpConnObject != NULL);
|
|
ObReferenceObject(TcpConnObject);
|
|
}
|
|
SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
|
|
SmbDereferenceConnect(ConnectObject, SMB_REF_TDI);
|
|
|
|
if (NULL == TcpConnObject) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
status = SmbSendIoctl(
|
|
TcpConnObject,
|
|
IOCTL_TCP_SET_INFORMATION_EX,
|
|
InfoBuffer,
|
|
InfoBufferLength,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
SmbPrint(SMB_TRACE_TCP, ("SmbClientSetTcpInfo: SetTcpInfo FAILed <0x%x> InfoBuffer=%p Length=%d\n",
|
|
status, InfoBuffer, InfoBufferLength));
|
|
SmbTrace(SMB_TRACE_TCP, ("FAILed %!status! InfoBuffer=%p Length=%d",
|
|
status, InfoBuffer, InfoBufferLength));
|
|
}
|
|
|
|
ObDereferenceObject(TcpConnObject);
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
IoctlSetIPv6Protection(
|
|
PSMB_DEVICE pDeviceObject,
|
|
PIRP pIrp,
|
|
PIO_STACK_LOCATION pIrpSp
|
|
)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
DWORD dwInputBufferLength = 0;
|
|
PNBSMB_IPV6_PROTECTION_PARAM pInput = NULL;
|
|
ULONG uOldIPv6Protection = 0;
|
|
|
|
dwInputBufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
|
pInput = pIrp->AssociatedIrp.SystemBuffer;
|
|
if (dwInputBufferLength < sizeof(NBSMB_IPV6_PROTECTION_PARAM) || NULL == pInput) {
|
|
ntStatus = STATUS_INVALID_PARAMETER;
|
|
goto error;
|
|
}
|
|
|
|
SmbTrace(SMB_TRACE_IOCTL, ("uIPv6Protection: input %d", pInput->uIPv6ProtectionLevel));
|
|
|
|
if (SmbCfg.uIPv6Protection != pInput->uIPv6ProtectionLevel) {
|
|
|
|
uOldIPv6Protection = SmbCfg.uIPv6Protection;
|
|
SmbCfg.uIPv6Protection = pInput->uIPv6ProtectionLevel;
|
|
|
|
ntStatus = SmbSetInboundIPv6Protection(pDeviceObject);
|
|
SmbTrace(SMB_TRACE_IOCTL, ("Change IPv6 Protection for inbound return %!status!", ntStatus));
|
|
|
|
if (ntStatus != STATUS_SUCCESS) {
|
|
NTSTATUS LocalStatus = STATUS_SUCCESS;
|
|
|
|
SmbCfg.uIPv6Protection = uOldIPv6Protection;
|
|
LocalStatus = SmbSetInboundIPv6Protection(pDeviceObject);
|
|
SmbTrace(SMB_TRACE_IOCTL, ("Restore to the old settings on failure. Restore status %!status!",
|
|
LocalStatus));
|
|
}
|
|
|
|
}
|
|
|
|
if (ntStatus == STATUS_SUCCESS) {
|
|
SmbCfg.bIPv6EnableOutboundGlobal = pInput->bIPv6EnableOutboundGlobal;
|
|
}
|
|
|
|
error:
|
|
SmbTrace(SMB_TRACE_IOCTL, ("%!status!", ntStatus));
|
|
return ntStatus;
|
|
}
|
|
|