2025-04-27 07:49:33 -04:00

1834 lines
56 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (C) Microsoft Corporation, 2000
Module Name:
network.c
Abstract:
This file contains TDI support routines.
Environment:
kernel mode only
Revision History:
--*/
#include "port.h"
extern HANDLE iSpTdiNotificationHandle;
extern PISCSI_FDO_EXTENSION iSpGlobalFdoExtension;
ISCSI_EVENT_HANDLER ServerEvents[] = {
{TDI_EVENT_CONNECT, iSpConnectionHandler},
{TDI_EVENT_DISCONNECT, iSpDisconnectHandler},
{TDI_EVENT_RECEIVE, iSpReceiveHandler}
};
NTSTATUS
iSpTdiSendCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
iSpProcessReceivedData(
IN PISCSI_CONNECTION IScsiConnection,
IN ULONG BytesIndicated,
OUT PULONG BytesTaken,
IN PVOID DataBuffer
);
NTSTATUS
iSpReceiveCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
iSpStartNetwork(
IN PDEVICE_OBJECT DeviceObject
)
/*+++
Routine Description :
This routine sets up the TDI address for the server to which
the clients will connect to.
It also sets up the address for the client. This address will
be later used by the client to connect to the server.
Arguement :
DeviceObject
Return Value :
STATUS_SUCCESS if the addresses were setup correctly.
Appropriate NTStatus code on error.
--*/
{
PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
PIRP Irp = NULL;
PISCSI_CONNECTION iScsiConnection = NULL;
HANDLE threadHandle = NULL;
NTSTATUS status = STATUS_SUCCESS;
ULONG countOfEvents;
ULONG inx;
OBJECT_ATTRIBUTES ObjAttributes;
BOOLEAN nodeSetup = FALSE;
if ((commonExtension->IsServerNodeSetup) == FALSE) {
//
// Allocate an IRP to be used in various routines
//
if ((Irp = IoAllocateIrp((DeviceObject->StackSize) + 1, FALSE)) == NULL) {
DebugPrint((0, "Failed to allocate Irp\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
DebugPrint((3, "Will setup Server node\n"));
iScsiConnection = iSpAllocatePool(NonPagedPool,
sizeof(ISCSI_CONNECTION),
ISCSI_TAG_CONNECTION);
if (iScsiConnection == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto iSpStartNetworkExit;
}
RtlZeroMemory(iScsiConnection, sizeof(ISCSI_CONNECTION));
fdoExtension->ServerNodeInfo = iScsiConnection;
KeInitializeSemaphore(&(iScsiConnection->RequestSemaphore),
0, MAXLONG);
//
// Create the thread in which ISCSI requests
// will be processed.
//
InitializeObjectAttributes(&ObjAttributes,
NULL,
OBJ_KERNEL_HANDLE,
NULL,
NULL);
status = PsCreateSystemThread(&threadHandle,
(ACCESS_MASK) 0L,
&ObjAttributes,
(HANDLE) 0L,
NULL,
iSpProcessScsiCommand,
fdoExtension);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "Failed to create thread. Status %x\n"));
goto iSpStartNetworkExit;
}
status = ObReferenceObjectByHandle(threadHandle,
SYNCHRONIZE,
NULL,
KernelMode,
&(iScsiConnection->IScsiThread),
NULL );
ASSERT(NT_SUCCESS(status));
ZwClose(threadHandle);
threadHandle = NULL;
//
// Pre-Allocate buffers to process the requests from the client
//
for (inx = 0; inx <= MAX_PENDING_REQUESTS; inx++) {
(iScsiConnection->ActiveRequests[inx]).CommandBuffer
= iSpAllocatePool(NonPagedPool,
ISCSI_SCSI_COMMAND_BUFF_SIZE,
ISCSI_TAG_SCSI_CMD_BUFF);
if (((iScsiConnection->ActiveRequests[inx]).CommandBuffer)
== NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto iSpStartNetworkExit;
}
}
iScsiConnection->Type = ISCSI_CONNECTION_TYPE;
iScsiConnection->Size = sizeof(ISCSI_CONNECTION);
fdoExtension->CurrentProtocolState = PSNodeInitInProgress;
status = iSpSetupNetworkNode(ISCSI_ANY_ADDRESS,
ISCSI_TARGET_PORT,
Irp,
(PVOID) DeviceObject,
iScsiConnection);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "Failed to setup server node. Status %x\n",
status));
goto iSpStartNetworkExit;
}
nodeSetup = TRUE;
DebugPrint((3, "Server node setup. Will register event handlers\n"));
//
// Set the event handlers for the server
//
countOfEvents = countof(ServerEvents);
status = iSpTdiSetEventHandler(Irp,
iScsiConnection->AddressDeviceObject,
iScsiConnection->AddressFileObject,
ServerEvents,
countOfEvents,
(PVOID) fdoExtension);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "Failed to register event handlers\n"));
goto iSpStartNetworkExit;
} else {
DebugPrint((3, "Event handlers registered\n"));
iScsiConnection->DeviceObject = DeviceObject;
iScsiConnection->ConnectionState = ConnectionStateDisconnected;
iScsiConnection->ReceiveState = ReceiveHeader;
iScsiConnection->CompleteHeaderReceived = TRUE;
fdoExtension->CurrentProtocolState = PSWaitingForLogon;
commonExtension->IsServerNodeSetup = TRUE;
}
}
iSpStartNetworkExit:
if (!NT_SUCCESS(status)) {
DebugPrint((0, "Failure in StartNetwork. Status 0x%08x\n",
status));
if (iScsiConnection != NULL) {
if (iScsiConnection->IScsiThread) {
iScsiConnection->TerminateThread = TRUE;
KeReleaseSemaphore(&(iScsiConnection->RequestSemaphore),
(KPRIORITY) 0,
1,
FALSE );
KeWaitForSingleObject((iScsiConnection->IScsiThread),
Executive,
KernelMode,
FALSE,
NULL);
ObDereferenceObject(iScsiConnection->IScsiThread);
}
for (inx = 0; inx <= MAX_PENDING_REQUESTS; inx++) {
if (((iScsiConnection->ActiveRequests[inx]).CommandBuffer)) {
ExFreePool(
((iScsiConnection->ActiveRequests[inx]).CommandBuffer)
);
}
}
if (nodeSetup == TRUE) {
iSpStopNetwork(DeviceObject);
}
ExFreePool(iScsiConnection);
}
}
if (Irp != NULL) {
IoFreeIrp(Irp);
}
return status;
}
NTSTATUS
iSpSetupNetworkNode(
IN ULONG InAddress,
IN USHORT InPort,
IN PIRP Irp,
IN PVOID ConnectionContext,
OUT PISCSI_CONNECTION ConnectionInfo
)
{
NTSTATUS status;
TDI_REQUEST_KERNEL_QUERY_INFORMATION queryInfo;
PTDI_ADDRESS_INFO tdiAddressInfo;
PTA_ADDRESS tdiTAAddress;
PTRANSPORT_ADDRESS tdiTransportAddress;
PTDI_ADDRESS_IP tdiIPAddress;
HANDLE tdiAddrHandle;
PFILE_OBJECT tdiAddrFileObject;
PDEVICE_OBJECT tdiAddrDeviceObject;
HANDLE tdiConnectionHandle;
PFILE_OBJECT tdiConnectionFileObject;
PDEVICE_OBJECT tdiConnectionDeviceObject;
UCHAR tdiAddressBuffer[TDI_QUERY_ADDRESS_LENGTH_IP];
//
// Create the address with wellknown port number for the server.
// Clients will connect to this port to query for shared devices.
//
status = iSpCreateTdiAddressObject(InAddress,
InPort,
&tdiAddrHandle,
&tdiAddrFileObject,
&tdiAddrDeviceObject);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "Failed to setup address. Status %x\n", status));
return status;
}
//
// Query information to retrieve address, port number, etc of
// the address we just setup.
//
status = iSpTdiQueryInformation(tdiAddrDeviceObject,
tdiAddrFileObject,
(PTDI_ADDRESS_INFO)tdiAddressBuffer,
TDI_QUERY_ADDRESS_LENGTH_IP);
if (!NT_SUCCESS(status)) {
DebugPrint((0,
"Could not query address info for the server. Status %x\n",
status));
iSpCloseTdiAddress(tdiAddrHandle,
tdiAddrFileObject);
return status;
}
tdiAddressInfo = (PTDI_ADDRESS_INFO) tdiAddressBuffer;
tdiTransportAddress = (PTRANSPORT_ADDRESS) &(tdiAddressInfo->Address);
tdiTAAddress = tdiTransportAddress->Address;
ASSERT((tdiTAAddress->AddressType) == TDI_ADDRESS_TYPE_IP);
ASSERT((tdiTAAddress->AddressLength) == sizeof(TDI_ADDRESS_IP));
tdiIPAddress = (PTDI_ADDRESS_IP) tdiTAAddress->Address;
DebugPrint((3, "Query succeeded. Address 0x%x, Port Number 0x%x\n",
tdiIPAddress->in_addr,
ntohs(tdiIPAddress->sin_port)));
//
// Create the connection endpoint for the server address
//
status = iSpCreateTdiConnectionObject(DD_TCP_DEVICE_NAME,
ConnectionInfo,
&tdiConnectionHandle,
&tdiConnectionFileObject,
&tdiConnectionDeviceObject);
if (!NT_SUCCESS(status)) {
DebugPrint((0,
"Could not create connection for the server. Status %x\n",
status));
iSpCloseTdiAddress(tdiAddrHandle,
tdiAddrFileObject);
return status;
}
//
// Associate the address and the connection endpoint created above
//
status = iSpTdiAssociateAddress(Irp,
tdiAddrHandle,
tdiConnectionFileObject,
tdiConnectionDeviceObject
);
if (!NT_SUCCESS(status)) {
DebugPrint((0,
"Could not associate address for server. Status %x\n",
status));
iSpCloseTdiConnection(tdiConnectionHandle,
tdiConnectionFileObject);
iSpCloseTdiAddress(tdiAddrHandle,
tdiAddrFileObject);
return status;
}
//
// Done setting up the server. Save all the relevant info
// in our device extension
//
ConnectionInfo->AddressHandle = tdiAddrHandle;
ConnectionInfo->AddressFileObject = tdiAddrFileObject;
ConnectionInfo->AddressDeviceObject = tdiAddrDeviceObject;
ConnectionInfo->ConnectionHandle = tdiConnectionHandle;
ConnectionInfo->ConnectionFileObject = tdiConnectionFileObject;
ConnectionInfo->ConnectionDeviceObject = tdiConnectionDeviceObject;
RtlCopyMemory(&(ConnectionInfo->IPAddress),
tdiIPAddress,
sizeof(TDI_ADDRESS_IP));
DebugPrint((3, "Node setup. Address 0x%08x, Port Number 0x%x\n",
tdiIPAddress->in_addr,
ntohs(tdiIPAddress->sin_port)));
return STATUS_SUCCESS;
}
NTSTATUS
iSpCloseNetworkNode(
PISCSI_CONNECTION iScsiConnection
)
{
NTSTATUS status;
status = iSpTdiDisassociateAddress(iScsiConnection->ConnectionDeviceObject,
iScsiConnection->ConnectionFileObject);
if (NT_SUCCESS(status)) {
iSpCloseTdiConnection(iScsiConnection->ConnectionHandle,
iScsiConnection->ConnectionFileObject);
iSpCloseTdiAddress(iScsiConnection->AddressHandle,
iScsiConnection->AddressFileObject);
} else {
DebugPrint((0, "iSpTdiDisassociateAddress failed. Status %x\n",
status));
}
DebugPrint((3, "Status from iSpCloseNetworkNode : %x\n",
status));
return status;
}
NTSTATUS
iSpCreateTdiAddressObject(
IN ULONG InAddress,
IN USHORT InPort,
OUT PVOID *AddrHandle,
OUT PFILE_OBJECT *AddrFileObject,
OUT PDEVICE_OBJECT *AddrDeviceObject
)
{
TA_IP_ADDRESS IPAddress;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PVOID Handle;
PFILE_FULL_EA_INFORMATION eaBuffer;
UNICODE_STRING deviceName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
UCHAR eaBufferBuffer[FILE_FULL_EA_INFO_ADDR_LENGTH];
RtlZeroMemory(&IPAddress, sizeof(TA_IP_ADDRESS));
IPAddress.TAAddressCount = 1;
IPAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
IPAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
IPAddress.Address[0].Address[0].in_addr = htonl(InAddress);
IPAddress.Address[0].Address[0].sin_port = htons(InPort);
RtlInitUnicodeString(&deviceName, DD_TCP_DEVICE_NAME);
InitializeObjectAttributes(
&objectAttributes,
&deviceName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
eaBuffer = (FILE_FULL_EA_INFORMATION UNALIGNED *)eaBufferBuffer;
RtlZeroMemory(eaBuffer, sizeof(eaBufferBuffer));
eaBuffer->NextEntryOffset = 0;
eaBuffer->Flags = 0;
eaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
eaBuffer->EaValueLength = sizeof(TA_IP_ADDRESS);
//
// Set EaName
//
RtlMoveMemory(&(eaBuffer->EaName[0]),
TdiTransportAddress,
TDI_TRANSPORT_ADDRESS_LENGTH + 1);
//
// Set EaValue
//
RtlMoveMemory(&(eaBuffer->EaName[TDI_TRANSPORT_ADDRESS_LENGTH + 1]),
&IPAddress,
sizeof(TA_IP_ADDRESS)
);
status = ZwCreateFile(&Handle,
(GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE),
&objectAttributes,
&ioStatusBlock,
0,
0,
(FILE_SHARE_READ | FILE_SHARE_WRITE),
FILE_CREATE,
0,
eaBuffer,
FILE_FULL_EA_INFO_ADDR_LENGTH);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "CreateTdiAddress failed. Status %x\n",
status));
return status;
}
//
// Get the associated fileobject
//
status = ObReferenceObjectByHandle(Handle,
0,
NULL,
KernelMode,
&FileObject,
NULL);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "ObReferenceObjectByHandle failed. Status %x\n",
status));
ZwClose(Handle);
return status;
}
//
// Get the associated deviceobject
//
DeviceObject = IoGetRelatedDeviceObject(FileObject);
*AddrHandle = Handle;
*AddrFileObject = FileObject;
*AddrDeviceObject = DeviceObject;
return STATUS_SUCCESS;
}
NTSTATUS
iSpCreateTdiConnectionObject(
IN PWCHAR DeviceName,
IN CONNECTION_CONTEXT ConnectionContext,
OUT PVOID *ConnectionHandle,
OUT PFILE_OBJECT *ConnectionFileObject,
OUT PDEVICE_OBJECT *ConnectionDeviceObject
)
{
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PVOID Handle;
PFILE_FULL_EA_INFORMATION eaBuffer;
CONNECTION_CONTEXT *eaCEPContext;
UNICODE_STRING deviceName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
UCHAR eaBufferBuffer[FILE_FULL_EA_INFO_CEP_LENGTH];
RtlInitUnicodeString(&deviceName, DD_TCP_DEVICE_NAME);
InitializeObjectAttributes(
&objectAttributes,
&deviceName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
eaBuffer = (FILE_FULL_EA_INFORMATION UNALIGNED *)eaBufferBuffer;
eaBuffer->NextEntryOffset = 0;
eaBuffer->Flags = 0;
eaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
eaBuffer->EaValueLength = sizeof(CONNECTION_CONTEXT);
//
// Set EaName
//
RtlMoveMemory(eaBuffer->EaName,
TdiConnectionContext,
TDI_CONNECTION_CONTEXT_LENGTH + 1);
//
// Set EaValue
//
eaCEPContext = (CONNECTION_CONTEXT UNALIGNED *)
&(eaBuffer->EaName[TDI_CONNECTION_CONTEXT_LENGTH + 1]);
*eaCEPContext = (CONNECTION_CONTEXT)ConnectionContext;
status = ZwCreateFile(&Handle,
(GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE),
&objectAttributes,
&ioStatusBlock,
0,
0,
0,
FILE_CREATE,
0,
eaBuffer,
FILE_FULL_EA_INFO_CEP_LENGTH);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "CreateTdiConnection failed. Status %x\n",
status));
return status;
}
//
// Get the associated fileobject
//
status = ObReferenceObjectByHandle(Handle,
0,
NULL,
KernelMode,
&FileObject,
NULL);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "ObReferenceObjectByHandle failed. Status %x\n",
status));
ZwClose(Handle);
return status;
}
//
// Get the associated deviceobject
//
DeviceObject = IoGetRelatedDeviceObject(FileObject);
*ConnectionHandle = Handle;
*ConnectionFileObject = FileObject;
*ConnectionDeviceObject = DeviceObject;
return STATUS_SUCCESS;
}
NTSTATUS
iSpTdiAssociateAddress(
IN PIRP Irp,
IN PVOID AddrHandle,
IN PFILE_OBJECT ConnectionFileObject,
IN PDEVICE_OBJECT ConnectionDeviceObject
)
{
NTSTATUS status;
TdiBuildAssociateAddress(Irp,
ConnectionDeviceObject,
ConnectionFileObject,
iSpTdiCompletionRoutine,
NULL,
AddrHandle);
status = iSpTdiSendIrpSynchronous(ConnectionDeviceObject,
Irp);
return status;
}
NTSTATUS
iSpTdiDisassociateAddress(
IN PDEVICE_OBJECT ConnectionDeviceObject,
IN PFILE_OBJECT ConnectionFileObject
)
{
NTSTATUS status;
PIRP Irp;
Irp = IoAllocateIrp(ConnectionDeviceObject->StackSize, FALSE);
if (Irp != NULL) {
TdiBuildDisassociateAddress(Irp,
ConnectionDeviceObject,
ConnectionFileObject,
iSpTdiCompletionRoutine,
NULL);
status = iSpTdiSendIrpSynchronous(ConnectionDeviceObject,
Irp);
} else {
DebugPrint((0,
"iSpTdiDisassociateAddress : Failed to allocate IRP\n"));
status = STATUS_NO_MEMORY;
}
return status;
}
NTSTATUS
iSpTdiSetEventHandler(
IN PIRP Irp,
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject,
IN PISCSI_EVENT_HANDLER EventsToSet,
IN ULONG CountOfEvents,
IN PVOID EventContext
)
{
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS oldStatus = STATUS_SUCCESS;
ULONG inx, tmp;
for (inx = 0; inx < CountOfEvents; inx++) {
TdiBuildSetEventHandler(Irp,
DeviceObject,
FileObject,
iSpTdiCompletionRoutine,
NULL,
EventsToSet[inx].EventId,
EventsToSet[inx].EventHandler,
EventContext);
status = iSpTdiSendIrpSynchronous(DeviceObject,
Irp);
DebugPrint((3, "Status from iSpTdiSetEventHandler : %x\n",
status));
if (!NT_SUCCESS(status)) {
break;
}
}
oldStatus = status;
if (!NT_SUCCESS(status)) {
for (tmp = 0; tmp < inx; tmp++) {
TdiBuildSetEventHandler(Irp,
DeviceObject,
FileObject,
iSpTdiCompletionRoutine,
NULL,
EventsToSet[tmp].EventId,
NULL,
NULL);
status = iSpTdiSendIrpSynchronous(DeviceObject,
Irp);
DebugPrint((3, "Status from iSpTdiSetEventHandler : %x\n",
status));
}
}
return oldStatus;
}
NTSTATUS
iSpTdiResetEventHandler(
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject,
IN PISCSI_EVENT_HANDLER EventsToSet,
IN ULONG CountOfEvents
)
{
PIRP localIrp;
ULONG inx;
NTSTATUS status;
localIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (localIrp == NULL) {
DebugPrint((0, "iSpTdiResetEventHandler : Failed to allocate IRP\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
for (inx = 0; inx < CountOfEvents; inx++) {
TdiBuildSetEventHandler(localIrp,
DeviceObject,
FileObject,
iSpTdiCompletionRoutine,
NULL,
EventsToSet[inx].EventId,
NULL,
NULL);
status = iSpTdiSendIrpSynchronous(DeviceObject,
localIrp);
DebugPrint((3, "Status from iSpTdiResetEventHandler : %x\n",
status));
}
IoFreeIrp(localIrp);
return status;
}
NTSTATUS
iSpCloseTdiAddress(
HANDLE AddrHandle,
PFILE_OBJECT AddrFileObject
)
{
NTSTATUS status;
if (AddrFileObject != NULL) {
ObDereferenceObject(AddrFileObject);
}
if (AddrHandle != NULL ) {
status = ZwClose(AddrHandle);
DebugPrint((3, "Status from iSpCloseTdiAddress : %x\n",
status));
}
return STATUS_SUCCESS;
}
NTSTATUS
iSpCloseTdiConnection(
HANDLE ConnectionHandle,
PFILE_OBJECT ConnectionFileObject
)
{
NTSTATUS status;
if (ConnectionFileObject != NULL) {
ObDereferenceObject(ConnectionFileObject);
}
if (ConnectionHandle != NULL) {
status = ZwClose(ConnectionHandle);
DebugPrint((3, "Status from iSpCloseTdiConnection : %x\n",
status));
}
return STATUS_SUCCESS;
}
NTSTATUS
iSpTdiDeviceControl(
IN PIRP Irp,
IN PMDL Mdl,
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject,
IN UCHAR MajorFunction,
IN UCHAR MinorFunction,
IN PVOID IrpParameter,
IN ULONG IrpParameterLength,
IN PVOID MdlBuffer,
IN ULONG MdlBufferLength
)
{
PIRP localIrp;
PIO_STACK_LOCATION irpStack;
PMDL localMdl;
NTSTATUS status;
//
// If caller didn't provide an IRP, allocate one
//
if (Irp != NULL) {
localIrp = Irp;
} else {
localIrp = IoAllocateIrp((DeviceObject->StackSize) + 1,
FALSE);
if (localIrp == NULL) {
DebugPrint((0, "IoAllocateIrp failed in iSpTdiDeviceControl\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
}
if (MdlBuffer == NULL) {
localIrp->MdlAddress = NULL;
localMdl = NULL;
} else {
if (Mdl == NULL) {
localMdl = IoAllocateMdl(MdlBuffer,
MdlBufferLength,
FALSE,
FALSE,
localIrp);
if (localMdl == NULL) {
DebugPrint((0, "Failed to allocate MDL\n"));
if (Irp == NULL) {
IoFreeIrp(localIrp);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
} else {
localMdl = Mdl;
MmInitializeMdl(localMdl,
MdlBuffer,
MdlBufferLength);
}
MmBuildMdlForNonPagedPool(localMdl);
}
irpStack = IoGetCurrentIrpStackLocation(localIrp);
irpStack->FileObject = FileObject;
irpStack->DeviceObject = DeviceObject;
irpStack->MajorFunction = MajorFunction;
irpStack->MinorFunction = MinorFunction;
RtlCopyMemory(&(irpStack->Parameters),
IrpParameter,
IrpParameterLength);
status = iSpTdiSendIrpSynchronous(DeviceObject, localIrp);
if (Irp == NULL) {
IoFreeIrp(localIrp);
}
return status;
}
NTSTATUS
iSpTdiQueryInformation(
IN PDEVICE_OBJECT TdiDeviceObject,
IN PFILE_OBJECT TdiFileObject,
IN PTDI_ADDRESS_INFO TdiAddressBuffer,
IN ULONG TdiAddrBuffLen
)
{
PMDL queryMdl = NULL;
PMDL tmpMdlPtr = NULL;
PIRP queryIrp = NULL;
NTSTATUS status;
status = iSpAllocateMdlAndIrp(TdiAddressBuffer,
TdiAddrBuffLen,
(CCHAR)(TdiDeviceObject->StackSize),
TRUE,
&queryIrp,
&queryMdl);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "iSpAllocateMdlAndIrp returned %x\n",
status));
return status;
}
//
// Build the IRP for sending the query information request
//
TdiBuildQueryInformation(queryIrp,
TdiDeviceObject,
TdiFileObject,
iSpTdiCompletionRoutine,
NULL,
TDI_QUERY_ADDRESS_INFO,
queryMdl);
status = iSpTdiSendIrpSynchronous(TdiDeviceObject, queryIrp);
//
// Free MDLs and IRP
//
iSpFreeMdlAndIrp(queryMdl, queryIrp, FALSE);
return status;
}
NTSTATUS
iSpTdiConnect(
IN PDEVICE_OBJECT TdiConnDeviceObject,
IN PFILE_OBJECT TdiConnFileObject,
IN ULONG TdiIPAddress,
IN USHORT TdiPortNumber,
IN LARGE_INTEGER ConnectionTimeout
)
{
TDI_CONNECTION_INFORMATION requestConnectionInformation;
TDI_CONNECTION_INFORMATION returnConnectionInformation;
PIRP localIrp;
PTRANSPORT_ADDRESS tdiTransportAddress;
PTA_ADDRESS tdiTAAddress;
PTDI_ADDRESS_IP tdiIPAddress;
NTSTATUS status;
UCHAR tdiAddressBuffer[TDI_IP_ADDRESS_LENGTH];
PAGED_CODE ();
RtlZeroMemory(tdiAddressBuffer, TDI_IP_ADDRESS_LENGTH);
RtlZeroMemory (&requestConnectionInformation,
sizeof (requestConnectionInformation));
RtlZeroMemory (&returnConnectionInformation,
sizeof (returnConnectionInformation));
tdiTransportAddress = (PTRANSPORT_ADDRESS) tdiAddressBuffer;
tdiTransportAddress->TAAddressCount = 1;
tdiTAAddress = tdiTransportAddress->Address;
tdiTAAddress->AddressLength = sizeof (TDI_ADDRESS_IP);
tdiTAAddress->AddressType = TDI_ADDRESS_TYPE_IP;
tdiIPAddress = (PTDI_ADDRESS_IP) tdiTAAddress->Address;
tdiIPAddress->in_addr = TdiIPAddress;
tdiIPAddress->sin_port = TdiPortNumber;
requestConnectionInformation.RemoteAddressLength = TDI_IP_ADDRESS_LENGTH;
requestConnectionInformation.RemoteAddress = (PVOID) tdiTransportAddress;
localIrp = IoAllocateIrp (TdiConnDeviceObject->StackSize, FALSE);
if (localIrp == NULL) {
DebugPrint((0, "iSpTdiConnect : Failed to allocate IRP\n"));
return STATUS_NO_MEMORY;
}
TdiBuildConnect(
localIrp,
TdiConnDeviceObject,
TdiConnFileObject,
iSpTdiCompletionRoutine,
NULL,
&ConnectionTimeout,
&requestConnectionInformation,
&returnConnectionInformation);
status = iSpTdiSendIrpSynchronous(TdiConnDeviceObject, localIrp);
IoFreeIrp(localIrp);
DebugPrint((3, "iSpTdiConnect : return status %x\n",
status));
return status;
}
NTSTATUS
iSpTdiDisconnect(
IN PDEVICE_OBJECT TdiConnDeviceObject,
IN PFILE_OBJECT TdiConnFileObject,
IN ULONG DisconnectFlags,
IN PVOID CompletionRoutine,
IN PVOID CompletionContext,
IN LARGE_INTEGER DisconnectTimeout
)
{
PIRP localIrp;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
TDI_CONNECTION_INFORMATION disconnectRequest;
TDI_CONNECTION_INFORMATION disconnectReply;
localIrp = IoAllocateIrp (TdiConnDeviceObject->StackSize, FALSE);
if (localIrp == NULL) {
DebugPrint((0, "iSpTdiDisconnect : Failed to allocate IRP\n"));
return STATUS_NO_MEMORY;
}
localIrp->Flags = 0;
localIrp->UserIosb = &ioStatusBlock;
TdiBuildDisconnect(
localIrp,
TdiConnDeviceObject,
TdiConnFileObject,
CompletionRoutine,
CompletionContext,
&DisconnectTimeout,
DisconnectFlags,
&disconnectRequest,
&disconnectReply);
status = iSpTdiSendIrpSynchronous(TdiConnDeviceObject, localIrp);
IoFreeIrp(localIrp);
DebugPrint((3, "Return value from iSpTdiDisconnect : %x\n",
status));
return status;
}
NTSTATUS
iSpConnectionHandler(
IN PVOID TdiEventContext,
IN LONG RemoteAddressLength,
IN PVOID RemoteAddress,
IN LONG UserDataLength,
IN PVOID UserData,
IN LONG OptionsLength,
IN PVOID Options,
OUT CONNECTION_CONTEXT *ConnectionContext,
OUT PIRP *AcceptIrp
)
{
PISCSI_FDO_EXTENSION fdoExtension = (PISCSI_FDO_EXTENSION) TdiEventContext;
PISCSI_CONNECTION iScsiConnection = fdoExtension->ServerNodeInfo;
PTA_IP_ADDRESS receivedAddressPtr;
PIRP localIrp;
ULONG remoteAddress;
USHORT remotePortNumber;
UCHAR ipAddress[4];
TA_IP_ADDRESS receivedAddress;
DebugPrint((3, "Received connect request\n"));
receivedAddressPtr = RemoteAddress;
ASSERT(RemoteAddressLength == sizeof(TA_IP_ADDRESS));
ASSERT((receivedAddressPtr->TAAddressCount) == 1);
ASSERT(((receivedAddressPtr->Address[0]).AddressType) == TDI_ADDRESS_TYPE_IP);
RtlCopyMemory(&receivedAddress, receivedAddressPtr, sizeof(TA_IP_ADDRESS));
remoteAddress = ntohl(receivedAddress.Address[0].Address[0].in_addr);
ipAddress[0] = (UCHAR) ((remoteAddress >> 24) & 0xFF);
ipAddress[1] = (UCHAR) ((remoteAddress >> 16) & 0xFF);
ipAddress[2] = (UCHAR) ((remoteAddress >> 8) & 0xFF);
ipAddress[3] = (UCHAR) (remoteAddress & 0xFF);
remotePortNumber = ntohs(receivedAddress.Address[0].Address[0].sin_port);
DebugPrint((3, "Remote address : %d.%d.%d.%d, Port Number : %x\n",
ipAddress[0], ipAddress[1], ipAddress[2], ipAddress[3],
remotePortNumber));
*AcceptIrp = NULL;
localIrp = IoAllocateIrp((iScsiConnection->ConnectionDeviceObject)->StackSize,
FALSE);
if (localIrp != NULL) {
TdiBuildAccept(localIrp,
iScsiConnection->ConnectionDeviceObject,
iScsiConnection->ConnectionFileObject,
iSpConnectionComplete,
fdoExtension,
NULL,
NULL);
IoSetNextIrpStackLocation(localIrp);
*AcceptIrp = localIrp;
*ConnectionContext = (CONNECTION_CONTEXT) iScsiConnection;
iScsiConnection->ConnectionState = ConnectionStateConnected;
return STATUS_MORE_PROCESSING_REQUIRED;
} else {
return STATUS_NO_MEMORY;
}
}
NTSTATUS
iSpConnectionComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PISCSI_FDO_EXTENSION fdoExtension = (PISCSI_FDO_EXTENSION) Context;
PISCSI_CONNECTION iScsiConnection;
iScsiConnection = fdoExtension->ServerNodeInfo;
ASSERT(Irp);
if (!NT_SUCCESS((Irp->IoStatus.Status))) {
DebugPrint((0, "Failed to accept connection. Status %x\n",
(Irp->IoStatus.Status)));
iScsiConnection->ConnectionState = ConnectionStateDisconnected;
} else {
DebugPrint((3, "Accepted connection\n"));
}
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
iSpDisconnectHandler(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN LONG DisconnectDataLength,
IN PVOID DisconnectData,
IN LONG DisconnectInformationLength,
IN PVOID DisconnectInformation,
IN ULONG DisconnectFlags
)
{
PISCSI_FDO_EXTENSION fdoExtension = (PISCSI_FDO_EXTENSION) TdiEventContext;
PISCSI_CONNECTION iScsiConnection;
LARGE_INTEGER disconnectTimeout;
DebugPrint((0, "Disconnect flags is %x\n", DisconnectFlags));
iScsiConnection = fdoExtension->ServerNodeInfo;
ASSERT((iScsiConnection != NULL));
if ((iScsiConnection->ConnectionState) == ConnectionStateStopping) {
DebugPrint((0, "We initiated disconnect. Do nothing more here\n"));
iScsiConnection->ConnectionState = ConnectionStateDisconnected;
fdoExtension->CurrentProtocolState = PSWaitingForLogon;
return STATUS_SUCCESS;
}
DebugPrint((0, "We were told to disconnect. Process that now\n"));
iScsiConnection->ConnectionState = ConnectionStateDisconnected;
if (DisconnectFlags & TDI_DISCONNECT_RELEASE) {
PIO_WORKITEM workItem;
workItem = IoAllocateWorkItem(fdoExtension->DeviceObject);
if (workItem != NULL) {
IoQueueWorkItem(workItem, iSpPerformDisconnect,
DelayedWorkQueue,
workItem);
DebugPrint((3, "Queued work item to do disconnect\n"));
}
}
return STATUS_SUCCESS;
}
NTSTATUS
iSpPerformDisconnect(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
{
PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PISCSI_CONNECTION iScsiConnection;
LARGE_INTEGER disconnectTimeout;
NTSTATUS status;
IoFreeWorkItem((PIO_WORKITEM) Context);
iScsiConnection = fdoExtension->ServerNodeInfo;
disconnectTimeout.QuadPart = -100000000L;
DebugPrint((0, "In iSpPerformDisconnect\n"));
status = iSpTdiDisconnect(iScsiConnection->ConnectionDeviceObject,
iScsiConnection->ConnectionFileObject,
TDI_DISCONNECT_RELEASE,
iSpTdiCompletionRoutine,
iScsiConnection,
disconnectTimeout);
fdoExtension->CurrentProtocolState = PSWaitingForLogon;
DebugPrint((3, "iSpTdiDisconnect returned : %x\n",
status));
return STATUS_SUCCESS;
}
NTSTATUS
iSpSendData(
IN PDEVICE_OBJECT ConnectionDeviceObject,
IN PFILE_OBJECT ConnectionFileObject,
IN PVOID DataBuffer,
IN ULONG DataBufferLen,
OUT PULONG BytesSent
)
{
PIRP sendIrp = NULL;
PMDL sendMdl = NULL;
PMDL tmpMdlPtr = NULL;
NTSTATUS status;
DebugPrint((3, "Entering SendData\n"));
*BytesSent = 0;
status = iSpAllocateMdlAndIrp(DataBuffer,
DataBufferLen,
(CCHAR)(ConnectionDeviceObject->StackSize),
TRUE,
&sendIrp,
&sendMdl);
if (NT_SUCCESS(status)) {
TdiBuildSend(sendIrp,
ConnectionDeviceObject,
ConnectionFileObject,
iSpTdiSendCompletionRoutine,
NULL,
sendMdl,
0,
DataBufferLen);
/*
status = iSpTdiSendIrpSynchronous(ConnectionDeviceObject,
sendIrp);
if (NT_SUCCESS(status)) {
*BytesSent = sendIrp->IoStatus.Information;
DebugPrint((3, "Bytes sent : %d\n",
*BytesSent));
}
*/
status = IoCallDriver(ConnectionDeviceObject, sendIrp);
if (!NT_SUCCESS(status)) {
DebugPrint((0, "Send failed. Status 0x%x\n", status));
}
}
DebugPrint((3, "Status in SendData : %x\n",
status));
return status;
}
NTSTATUS
iSpReceiveHandler(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG *BytesTaken,
IN PVOID DataBuffer,
OUT PIRP *IoRequestPacket
)
{
PISCSI_FDO_EXTENSION fdoExtension = (PISCSI_FDO_EXTENSION) TdiEventContext;
PISCSI_CONNECTION iScsiConnection;
PDEVICE_OBJECT connectionDeviceObject;
PFILE_OBJECT connectionFileObject;
PIRP receiveIrp;
PMDL receiveMdl;
NTSTATUS status;
UCHAR protocolState;
DebugPrint((3, "In receive handler. Receive flags : 0x%08x\n",
ReceiveFlags));
iScsiConnection = fdoExtension->ServerNodeInfo;
ASSERT((iScsiConnection != NULL));
connectionDeviceObject = iScsiConnection->ConnectionDeviceObject;
connectionFileObject = iScsiConnection->ConnectionFileObject;
DebugPrint((3, "FDO Extension : %x, CurrentProtocolState : %d\n",
fdoExtension, fdoExtension->CurrentProtocolState));
protocolState = fdoExtension->CurrentProtocolState;
DebugPrint((3,
"PS State : %d, BytesIndicated : %d, BytesAvailable : %d\n",
protocolState, BytesIndicated, BytesAvailable));
ASSERT((iScsiConnection->ConnectionState) == ConnectionStateConnected);
//
// We won't send Read IRP for now
//
*IoRequestPacket = NULL;
status = STATUS_SUCCESS;
switch (protocolState) {
case PSWaitingForLogon: {
PIO_WORKITEM workItem;
PISCSI_LOGIN_COMMAND loginCommand;
ASSERT(BytesIndicated >= sizeof(ISCSI_LOGIN_COMMAND));
//
// Assuming that the entire packet is available
// when logon command is received.
//
loginCommand =
(PISCSI_LOGIN_COMMAND) iScsiConnection->IScsiHeader;
RtlCopyMemory(loginCommand,
DataBuffer,
sizeof(ISCSI_LOGIN_RESPONSE));
ASSERT(((loginCommand->OpCode) == ISCSIOP_LOGIN_COMMAND));
DebugPrint((3, "Received login command.\n"));
workItem = IoAllocateWorkItem(fdoExtension->DeviceObject);
if (workItem != NULL) {
IoQueueWorkItem(workItem, iSpSendLoginResponse,
DelayedWorkQueue,
workItem);
DebugPrint((3, "Queued work item to send login response\n"));
} else {
DebugPrint((0, "Failed to allocate workitem for logon\n"));
}
*BytesTaken = BytesIndicated;
break;
}
case PSFullFeaturePhase: {
PUCHAR commandBuffer;
PISCSI_SCSI_COMMAND iScsiCommand;
PACTIVE_REQUESTS currentRequest = NULL;
ULONG length;
ULONG receivedDataLen;
ULONG inx;
*BytesTaken = BytesIndicated;
//
// Process the received data
//
status = iSpProcessReceivedData(
iScsiConnection,
BytesIndicated,
BytesTaken,
DataBuffer);
if (BytesIndicated < BytesAvailable) {
PUCHAR readBuffer = NULL;
ULONG remainingBytes;
//
// Need to send read IRP to read
// the remaining bytes
//
remainingBytes = BytesAvailable - BytesIndicated;
DebugPrint((0, "Bytes Available %d, Bytes Remaining : %d\n",
BytesAvailable,
remainingBytes));
readBuffer = iSpAllocatePool(NonPagedPool,
remainingBytes,
ISCSI_TAG_READBUFFER);
if (readBuffer != NULL) {
status = iSpAllocateMdlAndIrp(
readBuffer,
remainingBytes,
(CCHAR)(connectionDeviceObject->StackSize),
TRUE,
&receiveIrp,
&receiveMdl);
if (NT_SUCCESS(status)) {
TdiBuildReceive(receiveIrp,
connectionDeviceObject,
connectionFileObject,
iSpReceiveCompletion,
iScsiConnection,
receiveMdl,
0,
remainingBytes);
iScsiConnection->RemainingBytes = remainingBytes;
status = STATUS_MORE_PROCESSING_REQUIRED;
*IoRequestPacket = receiveIrp;
IoSetNextIrpStackLocation(receiveIrp);
} else {
ExFreePool(readBuffer);
status = STATUS_NO_MEMORY;
}
} else {
status = STATUS_NO_MEMORY;
}
}
break;
}
default: {
DebugPrint((0, "Unknown protocol state : %d\n",
protocolState));
*BytesTaken = BytesIndicated;
ASSERT(FALSE);
break;
}
} // switch (protocolState)
return status;
}
NTSTATUS
iSpReceiveCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PISCSI_CONNECTION iScsiConnection = (PISCSI_CONNECTION) Context;
PVOID dataBuffer;
NTSTATUS status;
ULONG bytesTaken;
ULONG inx;
DebugPrint((0, "Inx in receive completion\n"));
dataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
//
// Free the MDL and IRP
//
iSpFreeMdlAndIrp(Irp->MdlAddress,
Irp,
FALSE);
status = iSpProcessReceivedData(
iScsiConnection,
(iScsiConnection->RemainingBytes),
&bytesTaken,
dataBuffer
);
ExFreePool(dataBuffer);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
iSpProcessReceivedData(
IN PISCSI_CONNECTION IScsiConnection,
IN ULONG BytesIndicated,
OUT PULONG BytesTaken,
IN PVOID DataBuffer
)
{
PISCSI_SCSI_COMMAND iScsiCommand;
PACTIVE_REQUESTS currentRequest;
PUCHAR commandBuffer;
ULONG length;
ULONG inx;
LONG bytesToCopy;
LONG byteCount;
*BytesTaken = BytesIndicated;
byteCount = (LONG) BytesIndicated;
while (byteCount > 0) {
if ((IScsiConnection->ReceiveState) == ReceiveHeader) {
DebugPrint((3, "Receiving header\n"));
if ((IScsiConnection->CompleteHeaderReceived) == FALSE) {
BOOLEAN headerComplete = FALSE;
bytesToCopy = sizeof(ISCSI_GENERIC_HEADER) -
(IScsiConnection->IScsiHeaderOffset);
DebugPrint((0, "CHR False. ToCopy : %d, Count : %d\n",
bytesToCopy, byteCount));
if (byteCount < bytesToCopy) {
bytesToCopy = byteCount;
} else {
headerComplete = TRUE;
}
RtlCopyMemory((IScsiConnection->IScsiHeader) +
(IScsiConnection->IScsiHeaderOffset),
DataBuffer,
bytesToCopy);
if (headerComplete == FALSE) {
DebugPrint((0, "CHR still FALSE\n"));
IScsiConnection->IScsiHeaderOffset += bytesToCopy;
return STATUS_SUCCESS;
} else {
DebugPrint((0, "Header complete\n"));
IScsiConnection->IScsiHeaderOffset = 0;
IScsiConnection->CompleteHeaderReceived = TRUE;
byteCount -= bytesToCopy;
ASSERT(byteCount >= 0);
(PUCHAR) DataBuffer += bytesToCopy;
}
} else if (byteCount < sizeof(ISCSI_GENERIC_HEADER)) {
DebugPrint((0,
"Complete header NOT received. Count : %d\n",
byteCount));
IScsiConnection->CompleteHeaderReceived = FALSE;
RtlCopyMemory((IScsiConnection->IScsiHeader),
DataBuffer,
byteCount);
IScsiConnection->IScsiHeaderOffset = byteCount;
return STATUS_SUCCESS;
} else {
RtlCopyMemory((IScsiConnection->IScsiHeader),
DataBuffer,
sizeof(ISCSI_GENERIC_HEADER));
byteCount -= sizeof(ISCSI_GENERIC_HEADER);
ASSERT(byteCount >= 0);
(PUCHAR) DataBuffer += sizeof(ISCSI_GENERIC_HEADER);
}
iScsiCommand = (PISCSI_SCSI_COMMAND) (IScsiConnection->IScsiHeader);
GetUlongFromArray((iScsiCommand->Length),
length);
DebugPrint((3, "Size of immediate data : %d\n",
length));
ASSERT(length <= ISCSI_SCSI_COMMAND_BUFF_SIZE);
inx = iSpGetActiveClientRequestIndex(IScsiConnection,
iScsiCommand);
currentRequest = &(IScsiConnection->ActiveRequests[inx]);
IScsiConnection->CurrentRequest = currentRequest;
RtlCopyMemory((currentRequest->IScsiHeader),
(IScsiConnection->IScsiHeader),
sizeof(ISCSI_SCSI_COMMAND));
if (length != 0) {
ULONG receivedDataLen;
IScsiConnection->ReceiveState = ReceiveData;
commandBuffer = currentRequest->CommandBuffer;
if ((LONG)length <= byteCount ) {
receivedDataLen = length;
} else {
receivedDataLen = byteCount;
}
RtlCopyMemory(commandBuffer,
DataBuffer,
receivedDataLen);
byteCount -= receivedDataLen;
ASSERT(byteCount >= 0);
(PUCHAR) DataBuffer += receivedDataLen;
currentRequest->ExpectedDataLength = length;
currentRequest->CommandBufferOffset = receivedDataLen;
currentRequest->ReceivedDataLength = receivedDataLen;
}
} else {
ASSERT((IScsiConnection->ReceiveState) == ReceiveData);
ASSERT(IScsiConnection->CurrentRequest);
DebugPrint((3, "Receiving data\n"));
currentRequest = IScsiConnection->CurrentRequest;
commandBuffer = (currentRequest->CommandBuffer) +
(currentRequest->CommandBufferOffset);
bytesToCopy = ((currentRequest->ExpectedDataLength) -
(currentRequest->ReceivedDataLength));
if ((LONG)bytesToCopy > byteCount) {
bytesToCopy = byteCount;
} else {
DebugPrint((3, "More bytes in current buffer than expected\n"));
}
RtlCopyMemory(commandBuffer, DataBuffer, bytesToCopy);
byteCount -= bytesToCopy;
ASSERT(byteCount >= 0);
(PUCHAR) DataBuffer += bytesToCopy;
currentRequest->CommandBufferOffset += bytesToCopy;
currentRequest->ReceivedDataLength += bytesToCopy;
}
if ((currentRequest->ReceivedDataLength) ==
(currentRequest->ExpectedDataLength)) {
IScsiConnection->ReceiveState = ReceiveHeader;
currentRequest->CommandBufferOffset = 0;
currentRequest->ExpectedDataLength = 0;
currentRequest->ReceivedDataLength = 0;
IScsiConnection->CurrentRequest = NULL;
DebugPrint((3, "Request complete. Will process it\n"));
KeReleaseSemaphore(&(IScsiConnection->RequestSemaphore),
(KPRIORITY) 0,
1,
FALSE);
}
}
return STATUS_SUCCESS;
}
NTSTATUS
iSpStopNetwork(
IN PDEVICE_OBJECT DeviceObject
)
{
PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
PISCSI_CONNECTION iScsiConnection = fdoExtension->ServerNodeInfo;
NTSTATUS status = STATUS_SUCCESS;
ULONG countOfEvents;
ULONG inx;
if (iScsiConnection == NULL) {
//
// Nothing to do
//
DebugPrint((1, "iSpStopNetwork : No node info\n"));
return STATUS_SUCCESS;
}
countOfEvents = countof(ServerEvents);
status = iSpTdiResetEventHandler(iScsiConnection->AddressDeviceObject,
iScsiConnection->AddressFileObject,
ServerEvents,
countOfEvents);
if (NT_SUCCESS(status)) {
status = iSpCloseNetworkNode(iScsiConnection);
for (inx = 0; inx <= MAX_PENDING_REQUESTS; inx++) {
ExFreePool(
(iScsiConnection->ActiveRequests[inx]).CommandBuffer
);
}
ExFreePool(iScsiConnection);
fdoExtension->ServerNodeInfo = NULL;
} else {
DebugPrint((0, "Failed to reset event handlers. Status %x\n",
status));
}
return status;
}
NTSTATUS
iSpTdiSendIrpSynchronous(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KEVENT event;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status = STATUS_SUCCESS;
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// Initialize the IRP fields
//
Irp->UserEvent = &event;
Irp->UserIosb = &ioStatusBlock;
//
// Submit the IRP and wait for it to complete, if necessary
//
status = IoCallDriver(DeviceObject, Irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
status = ioStatusBlock.Status;
}
return status;
}
NTSTATUS
iSpTdiCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
//
// Copy the IRP status and signal the event
//
*(Irp->UserIosb) = Irp->IoStatus;
KeSetEvent(Irp->UserEvent,
IO_NETWORK_INCREMENT,
FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
iSpTdiSendCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PVOID bufferAddress = NULL;
ASSERT(Irp != NULL);
if ((Irp->MdlAddress) != NULL) {
bufferAddress = MmGetMdlVirtualAddress(Irp->MdlAddress);
DebugPrint((3, "Buffer address in send complete : %x\n",
bufferAddress));
}
//
// Free MDLs and IRP
//
iSpFreeMdlAndIrp(Irp->MdlAddress, Irp, FALSE);
if (bufferAddress != NULL) {
ExFreePool(bufferAddress);
}
return STATUS_MORE_PROCESSING_REQUIRED;
}