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.
 
 
 
 
 
 

953 lines
25 KiB

/*++
Copyright (c) 1989-2001 Microsoft Corporation
Module Name:
sock.c
Abstract:
Pseudo-socket
Author:
Jiandong Ruan
Revision History:
Feb-14-2001 First functional version
Feb-16-2001 Support IPv4
--*/
#include "precomp.h"
#include "sock.tmh"
NTSTATUS
SmbOpenAddress(
IN PUNICODE_STRING ucDevice,
IN PSMB_IP_ADDRESS addr,
IN USHORT port,
IN OUT PSMB_TCP_ADDRESS context
);
NTSTATUS
TdiOpenConnection(
IN HANDLE hAddress,
IN OUT PSMB_TCP_CONNECT Connect,
IN PVOID ConnectionContext
);
NTSTATUS
TdiAssociateConnection(
IN PSMB_TCP_ADDRESS Address,
IN PSMB_TCP_CONNECT Connect
);
NTSTATUS
TdiSetEventHandler(
PFILE_OBJECT FileObject,
ULONG EventType,
PVOID EventHandler,
PVOID Context
);
#pragma alloc_text(PAGE, SmbOpenTcpAddress)
#pragma alloc_text(PAGE, SmbOpenUdpAddress)
#pragma alloc_text(PAGE, SmbOpenAddress)
#pragma alloc_text(PAGE, SmbCloseAddress)
#pragma alloc_text(PAGE, SmbSetTcpEventHandlers)
#pragma alloc_text(PAGE, TdiAssociateConnection)
#pragma alloc_text(PAGE, TdiOpenConnection)
#pragma alloc_text(PAGE, TdiSetEventHandler)
NTSTATUS
SmbSynchTdiCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine doesn't free the IRP. It just signal an event to allow
the synchronous part of the SMB driver to proceed.
Arguments:
Return Value:
--*/
{
KeSetEvent((PKEVENT)Context, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
SubmitSynchTdiRequest (
IN PFILE_OBJECT FileObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine submits a request to TDI and waits for it to complete.
Arguments:
IN PFILE_OBJECT FileObject - Connection or Address handle for TDI request
IN PIRP Irp - TDI request to submit.
Return Value:
NTSTATUS - Final status of request.
--*/
{
KEVENT Event;
NTSTATUS status;
PAGED_CODE();
KeInitializeEvent (&Event, NotificationEvent, FALSE);
// set the address of the routine to be executed when the IRP
// finishes. This routine signals the event and allows the code
// below to continue (i.e. KeWaitForSingleObject)
//
IoSetCompletionRoutine(
Irp,
(PIO_COMPLETION_ROUTINE)SmbSynchTdiCompletion,
&Event,
TRUE,
TRUE,
TRUE
);
status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
//
// If it failed immediately, return now, otherwise wait.
//
if (!NT_SUCCESS(status)) {
SmbPrint(SMB_TRACE_TCP, ("SubmitSynchTdiRequest: Failed to Submit Tdi Request, status = 0x%08lx\n", status));
SmbTrace(SMB_TRACE_TCP, ("Failed to Submit Tdi Request, %!status!", status));
return status;
}
if (status == STATUS_PENDING) {
status = KeWaitForSingleObject (
&Event,
Executive,
KernelMode,
FALSE,
NULL
);
if (status != STATUS_WAIT_0) {
ASSERT(0);
SmbTrace(SMB_TRACE_TCP, ("KeWaitForSingleObject return %!status!", status));
return status;
}
status = Irp->IoStatus.Status;
}
SmbPrint(SMB_TRACE_TCP, ("SubmitSynchTdiRequest returns status = 0x%08lx\n", status));
SmbTrace(SMB_TRACE_TCP, ("returns %!status!", status));
return (status);
}
PVOID
SmbPrepareTdiAddress(
IN PSMB_IP_ADDRESS addr, // network order
IN USHORT port, // network order
OUT USHORT *pAddrSize
)
/*++
Routine Description:
This function set up an ipaddr in TDI format.
Arguments:
Return Value:
--*/
{
PTA_IP6_ADDRESS pIP6Addr = NULL;
PTA_IP_ADDRESS pIP4Addr = NULL;
PVOID pAddr = NULL;
USHORT IpAddrSize;
if (addr->sin_family == SMB_AF_INET) {
IpAddrSize = sizeof(TA_IP_ADDRESS);
} else if (addr->sin_family == SMB_AF_INET6) {
IpAddrSize = sizeof(TA_IP6_ADDRESS);
} else {
SmbTrace(SMB_TRACE_TCP, ("Invalid IP address family"));
return NULL;
}
pAddr = ExAllocatePoolWithTag(NonPagedPool, IpAddrSize, 'jBMS');
if(NULL == pAddr) {
return NULL;
}
//
// Setup the IP address
//
RtlZeroMemory(pAddr, IpAddrSize);
if (addr->sin_family == SMB_AF_INET) {
pIP4Addr = (PTA_IP_ADDRESS)pAddr;
pIP4Addr->TAAddressCount = 1;
pIP4Addr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
pIP4Addr->Address[0].AddressLength = sizeof(pIP4Addr->Address[0].Address[0]);
pIP4Addr->Address[0].Address[0].sin_port = port;
pIP4Addr->Address[0].Address[0].in_addr = addr->ip4.sin4_addr;
} else {
pIP6Addr = (PTA_IP6_ADDRESS)pAddr;
pIP6Addr->TAAddressCount = 1;
pIP6Addr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP6;
pIP6Addr->Address[0].AddressLength = sizeof(pIP6Addr->Address[0].Address[0]);
pIP6Addr->Address[0].Address[0].sin6_port = port;
RtlCopyMemory(pIP6Addr->Address[0].Address[0].sin6_addr, addr->ip6.sin6_addr, sizeof(addr->ip6.sin6_addr));
pIP6Addr->Address[0].Address[0].sin6_flowinfo = 0;
pIP6Addr->Address[0].Address[0].sin6_scope_id = addr->ip6.sin6_scope_id;
}
*pAddrSize = IpAddrSize;
return pAddr;
}
NTSTATUS
SmbPrepareEaBuffer(
IN PSMB_IP_ADDRESS addr,
IN USHORT port,
PFILE_FULL_EA_INFORMATION *pEaBuffer,
USHORT *pEaBufferSize
)
{
PTA_IP6_ADDRESS pIP6Addr = NULL;
PTA_IP_ADDRESS pIP4Addr = NULL;
PVOID pAddr = NULL;
USHORT IpAddrSize;
USHORT EaBufferSize;
PFILE_FULL_EA_INFORMATION EaBuffer = NULL;
*pEaBuffer = NULL;
*pEaBufferSize = 0;
pAddr = SmbPrepareTdiAddress(addr, port, &IpAddrSize);
if (NULL == pAddr) {
return STATUS_NO_MEMORY;
}
//
// Allocate Ea buffer for holding the TdiTransportAddress and the IP6 address
//
EaBufferSize = sizeof(FILE_FULL_EA_INFORMATION) +
TDI_TRANSPORT_ADDRESS_LENGTH +
IpAddrSize;
EaBuffer = (PFILE_FULL_EA_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, EaBufferSize, 'jBMS');
if(NULL == EaBuffer) {
ExFreePool(pAddr);
return STATUS_NO_MEMORY;
}
//
// Setup the ea buffer
//
EaBuffer->NextEntryOffset = 0;
EaBuffer->Flags = 0;
EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
EaBuffer->EaValueLength = IpAddrSize;
RtlCopyMemory(EaBuffer->EaName, TdiTransportAddress, EaBuffer->EaNameLength + 1);
RtlCopyMemory((PUCHAR)EaBuffer->EaName + EaBuffer->EaNameLength + 1, pAddr, IpAddrSize);
ExFreePool(pAddr);
*pEaBuffer = EaBuffer;
*pEaBufferSize = EaBufferSize;
return STATUS_SUCCESS;
}
NTSTATUS
SmbOpenAddress(
IN PUNICODE_STRING ucDevice,
IN PSMB_IP_ADDRESS addr,
IN USHORT port,
IN OUT PSMB_TCP_ADDRESS context
)
/*++
Routine Description:
Open a Tcp/Udp address
Arguments:
ucDevice The device name of TCP or UDP
addr The local address to be opened (network order)
port The local port to be opened (network order)
We will claim for exclusive ownership for a non-zero port
This happens when SMB device open 445 port (for listening).
For outbound connection request, SMB use 0 port which means
TCP will pick up a proper port # for us.
context The TCP context used to receive the opened address object
Return Value:
STATUS_SUCCES
failed
--*/
{
OBJECT_ATTRIBUTES AddrAttr = { 0 };
NTSTATUS status = STATUS_SUCCESS;
USHORT EaBufferSize = 0;
PFILE_FULL_EA_INFORMATION EaBuffer = NULL;
IO_STATUS_BLOCK IoStatusBlock = { 0 };
HANDLE AddrHandle = NULL;
PFILE_OBJECT AddrFileObject = NULL;
PAGED_CODE();
if (context->AddressHandle || context->AddressObject) {
ASSERT(0);
return STATUS_INVALID_PARAMETER;
}
AddrHandle = NULL;
AddrFileObject = NULL;
status = SmbPrepareEaBuffer(addr, port, &EaBuffer, &EaBufferSize);
BAIL_OUT_ON_ERROR(status);
//
// Open address with the transport
//
InitializeObjectAttributes(
&AddrAttr,
ucDevice,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
status = ZwCreateFile(
&AddrHandle,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&AddrAttr,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
(port)? 0: FILE_SHARE_READ | FILE_SHARE_WRITE, // Claim exclusive ownership for SMB port
FILE_OPEN_IF,
0,
EaBuffer,
EaBufferSize
);
ExFreePool(EaBuffer);
EaBuffer = NULL;
SmbPrint(SMB_TRACE_TCP, ("ZwCreateFile returns status 0x%08lx\n", status));
BAIL_OUT_ON_ERROR(status);
status = IoStatusBlock.Status;
BAIL_OUT_ON_ERROR(status);
status = ObReferenceObjectByHandle(
AddrHandle,
0,
NULL,
KernelMode,
&AddrFileObject,
NULL
);
BAIL_OUT_ON_ERROR(status);
ObDereferenceObject(AddrFileObject);
context->AddressHandle = AddrHandle;
context->AddressObject = AddrFileObject;
context->DeviceObject = IoGetRelatedDeviceObject(AddrFileObject);
SmbTrace(SMB_TRACE_TCP, ("%!status!", status));
return status;
cleanup:
if (NULL != EaBuffer) {
ExFreePool(EaBuffer);
EaBuffer = NULL;
}
if (AddrHandle) {
ZwClose(AddrHandle);
}
SmbTrace(SMB_TRACE_TCP, ("%!status!", status));
return status;
}
NTSTATUS
SmbCloseAddress(
IN OUT PSMB_TCP_ADDRESS context
)
{
NTSTATUS status;
PAGED_CODE();
if (NULL == context->AddressHandle ||
NULL == context->AddressObject ||
NULL == context->DeviceObject) {
ASSERT(0);
return STATUS_INVALID_PARAMETER;
}
status = ZwClose(context->AddressHandle);
if (status == STATUS_SUCCESS) {
context->AddressHandle = NULL;
context->AddressObject = NULL;
context->DeviceObject = NULL;
} else {
ASSERT (0);
}
return status;
}
NTSTATUS
SmbOpenTcpAddress(
IN PSMB_IP_ADDRESS addr,
IN USHORT port,
IN OUT PSMB_TCP_ADDRESS context
)
{
UNICODE_STRING ucName = { 0 };
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS LocStatus = STATUS_SUCCESS;
ULONG uIPv6ProtectionLevel = SmbCfg.uIPv6Protection;
PAGED_CODE();
if (addr->sin_family == SMB_AF_INET) {
RtlInitUnicodeString(&ucName, DD_TCP_DEVICE_NAME);
} else if (addr->sin_family == SMB_AF_INET6) {
RtlInitUnicodeString(&ucName, DD_TCPV6_DEVICE_NAME);
} else {
return STATUS_INVALID_PARAMETER;
}
status = SmbOpenAddress(&ucName, addr, port, context);
BAIL_OUT_ON_ERROR(status);
if (addr->sin_family == SMB_AF_INET6) {
LocStatus = SmbSetTcpInfo (
context->AddressObject,
CL_TL_ENTITY,
INFO_CLASS_PROTOCOL,
AO_OPTION_PROTECT,
INFO_TYPE_ADDRESS_OBJECT,
uIPv6ProtectionLevel
);
SmbTrace(SMB_TRACE_TCP, ("Set IPv6Protection Level %d on AddrOb %p %!status!",
uIPv6ProtectionLevel, context->AddressObject, LocStatus));
}
cleanup:
return status;
}
NTSTATUS
SmbOpenUdpAddress(
IN PSMB_IP_ADDRESS addr,
IN USHORT port,
IN OUT PSMB_TCP_ADDRESS context
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
UNICODE_STRING ucName;
NTSTATUS status;
PAGED_CODE();
if (addr->sin_family == SMB_AF_INET) {
RtlInitUnicodeString(&ucName, DD_UDP_DEVICE_NAME);
} else if (addr->sin_family == SMB_AF_INET6) {
RtlInitUnicodeString(&ucName, DD_UDPV6_DEVICE_NAME);
} else {
return STATUS_INVALID_PARAMETER;
}
status = SmbOpenAddress(&ucName, addr, port, context);
BAIL_OUT_ON_ERROR(status);
cleanup:
return status;
}
NTSTATUS
SmbSetTcpEventHandlers(
PFILE_OBJECT AddressObject,
PVOID Context
)
{
NTSTATUS status;
PAGED_CODE();
status = TdiSetEventHandler(
AddressObject,
TDI_EVENT_CONNECT,
SmbTdiConnectHandler,
Context
);
BAIL_OUT_ON_ERROR(status);
status = TdiSetEventHandler(
AddressObject,
TDI_EVENT_DISCONNECT,
SmbTdiDisconnectHandler,
Context
);
BAIL_OUT_ON_ERROR(status);
status = TdiSetEventHandler(
AddressObject,
TDI_EVENT_RECEIVE,
SmbTdiReceiveHandler,
Context
);
BAIL_OUT_ON_ERROR(status);
cleanup:
return status;
}
NTSTATUS
TdiOpenConnection(
IN HANDLE hAddress,
IN OUT PSMB_TCP_CONNECT Connect,
IN PVOID ConnectionContext
)
/*++
Routine Description:
Open a TCP connection.
Arguments:
Return Value:
--*/
{
UNICODE_STRING RelativeDeviceName = { 0, 0, NULL };
USHORT EaBufferSize;
PFILE_FULL_EA_INFORMATION EaBuffer;
OBJECT_ATTRIBUTES ObAttr;
HANDLE ConnectHandle;
PFILE_OBJECT ConnectObject;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS status;
ConnectHandle = NULL;
EaBuffer = NULL;
PAGED_CODE();
//
// Open the connection object with TCP
//
InitializeObjectAttributes(
&ObAttr,
&RelativeDeviceName,
OBJ_KERNEL_HANDLE,
hAddress, // Use a relative file handle
NULL
);
EaBufferSize = sizeof(FILE_FULL_EA_INFORMATION) +
TDI_CONNECTION_CONTEXT_LENGTH +
sizeof(CONNECTION_CONTEXT);
EaBuffer = (PFILE_FULL_EA_INFORMATION)
ExAllocatePoolWithTag(NonPagedPool, EaBufferSize, 'xBMS');
if (NULL == EaBuffer) {
return STATUS_NO_MEMORY;
}
EaBuffer->NextEntryOffset = 0;
EaBuffer->Flags = 0;
EaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
EaBuffer->EaValueLength = sizeof(CONNECTION_CONTEXT);
RtlCopyMemory(EaBuffer->EaName, TdiConnectionContext, EaBuffer->EaNameLength + 1);
ASSERT(sizeof(PVOID) == sizeof(CONNECTION_CONTEXT));
RtlCopyMemory(
(PUCHAR)EaBuffer->EaName + EaBuffer->EaNameLength + 1,
&ConnectionContext,
sizeof(CONNECTION_CONTEXT)
);
status = ZwCreateFile(
&ConnectHandle,
GENERIC_READ | GENERIC_WRITE,
&ObAttr,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_CREATE,
0,
EaBuffer,
EaBufferSize
);
ExFreePool(EaBuffer);
EaBuffer = NULL;
SmbPrint(SMB_TRACE_TCP, ("ZwCreateFile returns status 0x%08lx\n", status));
BAIL_OUT_ON_ERROR(status);
status = IoStatusBlock.Status;
BAIL_OUT_ON_ERROR(status);
status = ObReferenceObjectByHandle(
ConnectHandle,
0,
NULL,
KernelMode,
&ConnectObject,
NULL
);
BAIL_OUT_ON_ERROR(status);
ObDereferenceObject(ConnectObject);
Connect->ConnectHandle = ConnectHandle;
Connect->ConnectObject = ConnectObject;
if (SmbCfg.EnableNagling) {
status = SmbSetTcpInfo(
ConnectObject,
CO_TL_ENTITY,
INFO_CLASS_PROTOCOL,
TCP_SOCKET_NODELAY,
INFO_TYPE_CONNECTION,
FALSE
);
} else {
status = SmbSetTcpInfo(
ConnectObject,
CO_TL_ENTITY,
INFO_CLASS_PROTOCOL,
TCP_SOCKET_NODELAY,
INFO_TYPE_CONNECTION,
TRUE
);
}
if (STATUS_SUCCESS != status) {
SmbPrint(SMB_TRACE_TCP, ("Nagling: <0x%x> EnableNagling=%d\n",
status, SmbCfg.EnableNagling));
SmbTrace(SMB_TRACE_TCP, ("Nagling: %!status! EnableNagling=%d",
status, SmbCfg.EnableNagling));
status = STATUS_SUCCESS;
}
return status;
cleanup:
if (NULL != EaBuffer) {
ExFreePool(EaBuffer);
EaBuffer = NULL;
}
if (ConnectHandle) {
ZwClose(ConnectHandle);
}
return status;
}
NTSTATUS
TdiAssociateConnection(
IN PSMB_TCP_ADDRESS Address,
IN PSMB_TCP_CONNECT Connect
)
{
PIRP Irp;
NTSTATUS status;
PAGED_CODE();
ASSERT(Address->DeviceObject == IoGetRelatedDeviceObject(Connect->ConnectObject));
Irp = SmbAllocIrp(Address->DeviceObject->StackSize);
if (Irp == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
TdiBuildAssociateAddress(
Irp,
Address->DeviceObject,
Connect->ConnectObject,
NULL,
NULL,
Address->AddressHandle
);
status = SubmitSynchTdiRequest(Connect->ConnectObject, Irp);
SmbFreeIrp(Irp);
SmbTrace (SMB_TRACE_TCP, ("return %!status!", status));
SmbPrint (SMB_TRACE_TCP, ("TdiAssociateConnection return 0x%08lx\n", status));
return status;
}
NTSTATUS
SmbOpenTcpConnection(
IN PSMB_TCP_ADDRESS Address,
IN OUT PSMB_TCP_CONNECT Connect,
IN PVOID ConnectionContext
)
/*++
Routine Description:
Open a TCP connection and associate it with the Address
Arguments:
Return Value:
--*/
{
NTSTATUS status;
SMB_TCP_CONNECT LocalConnect;
if (NULL == Connect || Connect->ConnectHandle || Connect->ConnectObject) {
ASSERT (0);
return STATUS_INVALID_PARAMETER;
}
if (NULL == Address->AddressHandle ||
NULL == Address->AddressObject ||
NULL == Address->DeviceObject) {
ASSERT (0);
return STATUS_INVALID_PARAMETER;
}
status = TdiOpenConnection(
Address->AddressHandle,
&LocalConnect,
ConnectionContext
);
BAIL_OUT_ON_ERROR(status);
status = TdiAssociateConnection(
Address,
&LocalConnect
);
if (status != STATUS_SUCCESS) {
ZwClose(LocalConnect.ConnectHandle);
} else {
*Connect = LocalConnect;
}
cleanup:
return status;
}
NTSTATUS
SmbCloseTcpConnection(
IN OUT PSMB_TCP_CONNECT Connect
)
{
NTSTATUS status;
if (NULL == Connect->ConnectHandle || NULL == Connect->ConnectObject) {
ASSERT(0);
return STATUS_INVALID_PARAMETER;
}
status = ZwClose(Connect->ConnectHandle);
if (STATUS_SUCCESS == status) {
Connect->ConnectHandle = NULL;
Connect->ConnectObject = NULL;
}
return status;
}
NTSTATUS
TdiConnectComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PSMB_CONNECT_CONTEXT Context
)
{
PSMB_CONNECT ConnectObject;
ConnectObject = (PSMB_CONNECT)Context->ClientContext;
ASSERT(Context->AsyncInternalContext);
if (Context->AsyncInternalContext) {
ExFreePool(Context->AsyncInternalContext);
Context->AsyncInternalContext = NULL;
}
SmbTrace (SMB_TRACE_CONNECT, ("pIrp %p complete with %!status! info=%d",
Irp, Irp->IoStatus.Status, (ULONG)(Irp->IoStatus.Information)));
Context->status = Irp->IoStatus.Status;
Context->Completion((PSMB_ASYNC_CONTEXT)Context);
//
// We're actully using the client's IRP. The Context->Completion will complete it.
// Don't allow IO manager to proceed.
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
void
SmbAsyncConnect(
IN PSMB_IP_ADDRESS ipaddr,
IN USHORT port,
IN PSMB_CONNECT_CONTEXT Context
)
{
PIRP Irp = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
PSMB_CONNECT ConnectObject = NULL;
PTDI_CONNECTION_INFORMATION SendInfo = NULL;
PTRANSPORT_ADDRESS pAddr = NULL;
USHORT IpAddrSize = 0;
NTSTATUS status = STATUS_SUCCESS;
#if DBG
if (ipaddr->sin_family == SMB_AF_INET6) {
CHAR target_ip[40];
inet_ntoa6(target_ip, 40, &ipaddr->ip6);
SmbPrint(SMB_TRACE_CALL, ("SmbAsyncConnect %s:%d\n", target_ip, ntohs(port)));
}
#endif
ConnectObject = (PSMB_CONNECT)Context->ClientContext;
//
// Use the client's IRP so that the client can cancel it
//
Irp = ConnectObject->PendingIRPs[SMB_PENDING_CONNECT];
if (NULL == Irp) {
ASSERT(0);
SmbTrace(SMB_TRACE_CONNECT, ("Internal Error: Expect a non-NULL Pending Connect Irp"));
Context->status = STATUS_INTERNAL_ERROR;
Context->Completion((PSMB_ASYNC_CONTEXT)Context);
return;
}
pAddr = SmbPrepareTdiAddress(ipaddr, port, &IpAddrSize);
if (pAddr == NULL) {
SmbTrace(SMB_TRACE_CONNECT, ("cannot prepare TA_IP_ADDRESS or TA_IP6_ADDRESS"));
Context->status = STATUS_INTERNAL_ERROR;
Context->Completion((PSMB_ASYNC_CONTEXT)Context);
return;
}
SendInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(SendInfo[0]) + IpAddrSize, 'uBMS');
if (NULL == SendInfo) {
ExFreePool(pAddr);
Context->status = STATUS_INSUFFICIENT_RESOURCES;
Context->Completion((PSMB_ASYNC_CONTEXT)Context);
return;
}
SendInfo->UserDataLength = 0;
SendInfo->UserData = NULL;
SendInfo->OptionsLength = 0;
SendInfo->Options = NULL;
SendInfo->RemoteAddressLength = IpAddrSize;
SendInfo->RemoteAddress = (&SendInfo[1]);
RtlCopyMemory(SendInfo->RemoteAddress, pAddr, IpAddrSize);
ExFreePool(pAddr);
pAddr = NULL;
DeviceObject = IoGetRelatedDeviceObject(Context->TcpConnect.ConnectObject);
Context->AsyncInternalContext = SendInfo;
TdiBuildConnect(
Irp,
DeviceObject,
Context->TcpConnect.ConnectObject,
(PVOID)TdiConnectComplete,
Context,
NULL, // No timeout
SendInfo,
NULL
);
status = IoCallDriver(DeviceObject, Irp);
SmbTrace (SMB_TRACE_CONNECT, ("pIrp %p return %!status!", Irp, status));
}
NTSTATUS
SmbTcpDisconnect(
PSMB_TCP_CONTEXT TcpContext,
LONG TimeoutMilliseconds,
ULONG Flags
)
{
PIRP Irp = NULL;
PFILE_OBJECT FileObject = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
LARGE_INTEGER Timeout = { 0 };
NTSTATUS status = STATUS_SUCCESS;
FileObject = TcpContext->Connect.ConnectObject;
if (NULL == FileObject) {
ASSERT (0);
SmbTrace(SMB_TRACE_CONNECT, ("NULL FileObject !!!!"));
return STATUS_INVALID_PARAMETER;
}
DeviceObject = IoGetRelatedDeviceObject(FileObject);
Irp = SmbAllocIrp(DeviceObject->StackSize);
if (NULL == Irp) {
SmbTrace(SMB_TRACE_CONNECT, ("no free IRP !!!!"));
return STATUS_INSUFFICIENT_RESOURCES;
}
Timeout.QuadPart = -Int32x32To64(TimeoutMilliseconds, SMB_ONE_MILLISECOND);
TdiBuildDisconnect(
Irp,
DeviceObject,
FileObject,
NULL,
NULL,
&Timeout,
Flags,
NULL,
NULL
);
status = SubmitSynchTdiRequest(FileObject, Irp);
SmbFreeIrp(Irp);
SmbTrace (SMB_TRACE_CONNECT, ("return %!status!", status));
return status;
}