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.
 
 
 
 
 
 

270 lines
6.8 KiB

/*++
Copyright (c) 1989-2001 Microsoft Corporation
Module Name:
send.c
Abstract:
Implement TDI_SEND
Author:
Jiandong Ruan
Revision History:
--*/
#include "precomp.h"
#include "send.tmh"
PMDL
SmbAllocateNetBuffer(
ULONG uNumOfBytes
)
{
PVOID pvBuf = NULL;
PVOID pvMappedBuf = NULL;
PMDL pMdl = NULL;
pvBuf = ExAllocatePoolWithTag(
NonPagedPool,
uNumOfBytes,
NBT_HEADER_TAG
);
if (NULL == pvBuf) {
goto error;
}
pMdl = IoAllocateMdl(pvBuf, uNumOfBytes, FALSE, FALSE, NULL);
if (NULL == pMdl) {
ExFreePool(pvBuf);
goto error;
}
MmBuildMdlForNonPagedPool(pMdl);
//
// Verify the mapped system address == pvBuf
// SmbFreeNetBuffer depends on this assumption.
//
pvMappedBuf = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
if (pvMappedBuf != pvBuf) {
ExFreePool(pvBuf);
IoFreeMdl(pMdl);
ASSERT(0);
pMdl = NULL;
}
error:
return pMdl;
}
VOID
SmbFreeNetBuffer(
PMDL pMdl
)
{
PVOID pvBuf = NULL;
if (NULL == pMdl) {
goto error;
}
pvBuf = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
if (NULL != pvBuf) {
ExFreePool(pvBuf);
pvBuf = NULL;
}
IoFreeMdl(pMdl);
pMdl = NULL;
error:
return;
}
NTSTATUS
SmbSendCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PSMB_CONNECT ConnectObject
)
/*++
Routine Description:
This the completion routine of sending a packet
Arguments:
Return Value:
--*/
{
PMDL Mdl;
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
Mdl = Irp->MdlAddress;
if (Mdl->MdlFlags & MDL_NETWORK_HEADER) {
(PUCHAR)Mdl->MappedSystemVa += SMB_SESSION_HEADER_SIZE;
Mdl->ByteOffset += SMB_SESSION_HEADER_SIZE;
Mdl->ByteCount -= SMB_SESSION_HEADER_SIZE;
} else {
ASSERT(NULL != Mdl->Next);
Irp->MdlAddress = Mdl->Next;
ASSERT(MmGetMdlByteCount(Mdl) == SMB_SESSION_HEADER_SIZE);
SmbFreeNetBuffer(Mdl);
Mdl = NULL;
}
if (Irp->IoStatus.Status == STATUS_SUCCESS && Irp->IoStatus.Information >= SMB_SESSION_HEADER_SIZE) {
SmbPrint(SMB_TRACE_TCP, ("SmbSendCompletion: Send %d bytes\n", Irp->IoStatus.Information));
Irp->IoStatus.Information -= SMB_SESSION_HEADER_SIZE;
ConnectObject->BytesSent += (ULONG)(Irp->IoStatus.Information);
} else {
Irp->IoStatus.Information = 0;
SmbPrint(SMB_TRACE_TCP, ("SmbSendCompletion: status=0x%08lx\n", Irp->IoStatus.Status));
ASSERT (Irp->IoStatus.Status != STATUS_CONNECTION_ACTIVE);
}
ConnectObject->PendingIRPs[SMB_PENDING_SEND] = NULL;
SmbDereferenceConnect(ConnectObject, SMB_REF_SEND);
return STATUS_SUCCESS;
}
NTSTATUS
SmbSend(
PSMB_DEVICE Device,
PIRP Irp
)
/*++
Routine Description:
TDI_SEND
RDR/SRV is using backfill mode only at this time. So non-backfill mode is postponed.
Arguments:
Return Value:
--*/
{
PIO_STACK_LOCATION IrpSp = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
PTDI_REQUEST_KERNEL_SEND TdiRequest = NULL;
PMDL Mdl = NULL;
PSMB_CONNECT ConnectObject = NULL;
PULONG SmbHdr = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
PFILE_OBJECT FileObject = NULL;
DWORD SendLength = 0;
KIRQL Irql;
PMDL pMdlNbtHdr = NULL;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TdiRequest = (PTDI_REQUEST_KERNEL_SEND)&IrpSp->Parameters;
Mdl = Irp->MdlAddress;
if (NULL == Mdl) {
return STATUS_INVALID_PARAMETER;
}
SendLength = TdiRequest->SendLength;
if (SendLength > SMB_MAX_SESSION_PACKET) {
//
// Shouldn't happen, in case ......
//
ASSERT(0);
return STATUS_INVALID_PARAMETER;
}
ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_SEND);
if (NULL == ConnectObject) {
ASSERT(0);
return STATUS_INVALID_HANDLE;
}
SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
if (ConnectObject->State != SMB_CONNECTED || ConnectObject->TcpContext == NULL) {
SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
SmbDereferenceConnect(ConnectObject, SMB_REF_SEND);
return STATUS_INVALID_DEVICE_REQUEST;
}
FileObject = ConnectObject->TcpContext->Connect.ConnectObject;
ASSERT(FileObject != NULL);
ConnectObject->PendingIRPs[SMB_PENDING_SEND] = Irp;
//
// Reference the FileObject in case that it is closed and freed.
//
ObReferenceObject(FileObject);
SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
DeviceObject = IoGetRelatedDeviceObject(FileObject);
if (Mdl->MdlFlags & MDL_NETWORK_HEADER) {
//
// Backfill mode
//
(PUCHAR)Mdl->MappedSystemVa -= SMB_SESSION_HEADER_SIZE;
Mdl->ByteOffset -= SMB_SESSION_HEADER_SIZE;
Mdl->ByteCount += SMB_SESSION_HEADER_SIZE;
SmbHdr = (PULONG)Mdl->MappedSystemVa;
*SmbHdr = htonl(SendLength);
} else {
//
// we need to attach our own header
//
pMdlNbtHdr = SmbAllocateNetBuffer(SMB_SESSION_HEADER_SIZE);
if (NULL == pMdlNbtHdr) {
ConnectObject->PendingIRPs[SMB_PENDING_SEND] = NULL;
SmbDereferenceConnect(ConnectObject, SMB_REF_SEND);
ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
ASSERT(0 == (pMdlNbtHdr->MdlFlags & MDL_NETWORK_HEADER));
SmbHdr = (PULONG)pMdlNbtHdr->MappedSystemVa;
*SmbHdr = htonl(SendLength);
pMdlNbtHdr->Next = Irp->MdlAddress;
Irp->MdlAddress = pMdlNbtHdr;
}
TdiBuildSend(
Irp,
DeviceObject,
FileObject,
(PVOID)SmbSendCompletion,
ConnectObject,
Irp->MdlAddress,
0,
SendLength + 4
);
IoMarkIrpPending(Irp);
if (ConnectObject->FastSend) {
IoSetNextIrpStackLocation(Irp);
status = ConnectObject->FastSend(Irp, IoGetCurrentIrpStackLocation(Irp));
SmbPrint(SMB_TRACE_TCP, ("SmbSend: FastSend %d bytes IoCallDriver return 0x%08lx\n", SendLength + 4, status));
} else {
status = IoCallDriver(DeviceObject, Irp);
SmbPrint(SMB_TRACE_TCP, ("SmbSend: Send %d bytes IoCallDriver return 0x%08lx\n", SendLength + 4, status));
}
ObDereferenceObject(FileObject);
return STATUS_PENDING;
}