我想通过网络分享cdrom设备。
在客户端,我创建了根枚举设备(scsi总线)。在服务器端(cdrom设备所在的位置)我用我自己的设备堆栈替换设备堆栈(换句话说 - cdrom.sys被另一个驱动程序替换)。
使用Windows套接字将请求从客户端重定向到服务器。
通过网络(从客户端到服务器)传输的数据格式:USER_HEADER, USER_SCSI_REQUEST_BLOCK, [data to be transferred to device]
通过网络传输的数据格式(从服务器到客户端):
USER_HEADER, USER_SCSI_REQUEST_BLOCK, [data to be transferred from device / sense data]
结构定义如下:
struct USER_HEADER
{
ULONG Id;
ULONG Length;
ULONG MajorFunction;
ULONG MinorFunction;
ULONG IoControlCode;
ULONG InputBufferLength;
ULONG OutputBufferLength;
NTSTATUS Status;
ULONG Information;
};
struct USER_SCSI_REQUEST_BLOCK
{
UCHAR Function;
UCHAR SrbStatus;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR QueueTag;
UCHAR QueueAction;
UCHAR CdbLength;
UCHAR SenseInfoBufferLength;
ULONG SrbFlags;
ULONG DataTransferLength;
ULONG TimeOutValue;
ULONG QueueSortKey;
UCHAR Cdb[16];
};
用于打包和解压缩从cdrom.sys发送的请求的客户端代码:
PVOID GetBuffer(MDL *pSourceMdl, MDL *pTargetMdl, PVOID pBuffer, ULONG Length, BOOLEAN *pUnmap)
{
PVOID pBuffer2;
if (pSourceMdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
{
pBuffer2 = (UCHAR*)pSourceMdl->MappedSystemVa + ((UCHAR*)pBuffer - ((UCHAR*)pSourceMdl->StartVa + pSourceMdl->ByteOffset));
*pUnmap = FALSE;
}
else
{
IoBuildPartialMdl(pSourceMdl, pTargetMdl, pBuffer, Length);
pBuffer2 = MmMapLockedPagesSpecifyCache(pTargetMdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
*pUnmap = TRUE;
}
return pBuffer2;
}
void PackRequest(IRP *pIrp, USER_HEADER *pUserHeader, STORAGE_EXTENSION *pStorageExtension)
{
BOOLEAN Unmap;
PVOID pBuffer;
IO_STACK_LOCATION *pStack;
USER_SCSI_REQUEST_BLOCK *pUserSrb;
SCSI_REQUEST_BLOCK *pSrb;
pStack = IoGetCurrentIrpStackLocation(pIrp);
pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pStorageExtension->Id;
pUserHeader->Id = pStorageExtension->Id;
++pStorageExtension->Id;
pUserHeader->Status = 0;
pUserHeader->Information = 0;
pUserHeader->MajorFunction = pStack->MajorFunction;
pUserHeader->MinorFunction = pStack->MinorFunction;
if (pStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)
{
pUserHeader->IoControlCode = 0;
pUserHeader->InputBufferLength = 0;
pUserHeader->OutputBufferLength = 0;
pUserHeader->Length = sizeof(USER_HEADER) + sizeof(USER_SCSI_REQUEST_BLOCK);
pUserSrb = (USER_SCSI_REQUEST_BLOCK*)((UCHAR*)pUserHeader + sizeof(USER_HEADER));
pSrb = pStack->Parameters.Scsi.Srb;
pUserSrb->Function = pSrb->Function;
pUserSrb->SrbStatus = pSrb->SrbStatus;
pUserSrb->ScsiStatus = pSrb->ScsiStatus;
pUserSrb->PathId = pSrb->PathId;
pUserSrb->TargetId = pSrb->TargetId;
pUserSrb->Lun = pSrb->Lun;
pUserSrb->QueueTag = pSrb->QueueTag;
pUserSrb->QueueAction = pSrb->QueueAction;
pUserSrb->CdbLength = pSrb->CdbLength;
pUserSrb->SenseInfoBufferLength = pSrb->SenseInfoBufferLength;
pUserSrb->SrbFlags = pSrb->SrbFlags;
pUserSrb->DataTransferLength = pSrb->DataTransferLength;
pUserSrb->TimeOutValue = pSrb->TimeOutValue;
if ((pSrb->DataTransferLength) && (pSrb->SrbFlags & SRB_FLAGS_DATA_OUT))
{
pBuffer = GetBuffer(pIrp->MdlAddress, pStorageExtension->pMdl, pSrb->DataBuffer, pSrb->DataTransferLength, &Unmap);
memcpy((UCHAR*)pUserSrb + sizeof(USER_SCSI_REQUEST_BLOCK), pBuffer, pSrb->DataTransferLength);
if (Unmap) MmUnmapLockedPages(pBuffer, pStorageExtension->pMdl);
pUserHeader->Length += pSrb->DataTransferLength;
}
pUserSrb->QueueSortKey = pSrb->QueueSortKey;
memcpy(pUserSrb->Cdb, pSrb->Cdb, sizeof(pSrb->Cdb));
}
else
{
pUserHeader->IoControlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
pUserHeader->InputBufferLength = pStack->Parameters.DeviceIoControl.InputBufferLength;
pUserHeader->OutputBufferLength = pStack->Parameters.DeviceIoControl.OutputBufferLength;
pUserHeader->Length = sizeof(USER_HEADER);
if ((pUserHeader->IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY) ||
(pUserHeader->IoControlCode == IOCTL_STORAGE_ENABLE_IDLE_POWER))
{
pUserHeader->Length += pUserHeader->InputBufferLength;
memcpy((UCHAR*)pUserHeader + sizeof(USER_HEADER), pIrp->AssociatedIrp.SystemBuffer, pUserHeader->InputBufferLength);
}
else if ((pUserHeader->IoControlCode != IOCTL_STORAGE_POWER_ACTIVE) &&
(pUserHeader->IoControlCode != IOCTL_SCSI_GET_ADDRESS))
{
__debugbreak();
}
}
}
void UnpackRequest(USER_HEADER *pUserHeader, IRP *pIrp, STORAGE_EXTENSION *pStorageExtension)
{
BOOLEAN Unmap;
PVOID pBuffer;
IO_STACK_LOCATION *pStack;
USER_SCSI_REQUEST_BLOCK *pUserSrb;
SCSI_REQUEST_BLOCK *pSrb;
pStack = IoGetCurrentIrpStackLocation(pIrp);
if (pUserHeader->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)
{
pUserSrb = (USER_SCSI_REQUEST_BLOCK*)((UCHAR*)pUserHeader + sizeof(USER_HEADER));
pSrb = pStack->Parameters.Scsi.Srb;
pSrb->SrbStatus = pUserSrb->SrbStatus;
pSrb->ScsiStatus = pUserSrb->ScsiStatus;
pSrb->SenseInfoBufferLength = pUserSrb->SenseInfoBufferLength;
pSrb->DataTransferLength = pUserSrb->DataTransferLength;
if (NT_SUCCESS(pUserHeader->Status))
{
if ((pUserSrb->DataTransferLength) && (pUserSrb->SrbFlags & SRB_FLAGS_DATA_IN))
{
pBuffer = GetBuffer(pIrp->MdlAddress, pStorageExtension->pMdl, pSrb->DataBuffer, pUserSrb->DataTransferLength, &Unmap);
memcpy(pBuffer, (UCHAR*)pUserSrb + sizeof(USER_SCSI_REQUEST_BLOCK), pUserSrb->DataTransferLength);
if (Unmap) MmUnmapLockedPages(pBuffer, pStorageExtension->pMdl);
}
else
{
if (pUserSrb->Function == SRB_FUNCTION_CLAIM_DEVICE) pSrb->DataBuffer = pStack->DeviceObject;
}
}
else
{
if ((pUserSrb->SenseInfoBufferLength) && (pUserSrb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID))
{
memcpy(pSrb->SenseInfoBuffer, (UCHAR*)pUserSrb + sizeof(USER_SCSI_REQUEST_BLOCK), pUserSrb->SenseInfoBufferLength);
}
}
}
else
{
if (NT_SUCCESS(pUserHeader->Status))
{
if ((pUserHeader->IoControlCode == IOCTL_SCSI_GET_ADDRESS) ||
(pUserHeader->IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY))
{
memcpy(pIrp->AssociatedIrp.SystemBuffer, (UCHAR*)pUserHeader + sizeof(USER_HEADER), pUserHeader->Information);
}
}
}
}
分配请求和IO完成例程的服务器端代码:
NTSTATUS AllocateRequest(DEVICE_EXTENSION *pDeviceExtension, IRP *pIrp, IRP **ppIrp2)
{
IRP *pIrp2;
PVOID pBuffer;
NTSTATUS Status;
IO_STACK_LOCATION *pStack;
SCSI_REQUEST_BLOCK *pSrb;
USER_SCSI_REQUEST_BLOCK *pUserSrb;
DEVICE_OBJECT *pDeviceObject;
USER_HEADER *pUserHeader;
pUserHeader = (USER_HEADER*)MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
pDeviceObject = pDeviceExtension->pLowerDeviceObject;
pIrp2 = IoAllocateIrp(pDeviceObject->StackSize, FALSE);
if (pIrp2)
{
pStack = IoGetNextIrpStackLocation(pIrp2);
pStack->DeviceObject = pDeviceObject;
pIrp2->Tail.Overlay.Thread = PsGetCurrentThread();
pStack->MajorFunction = pUserHeader->MajorFunction;
pStack->MinorFunction = pUserHeader->MinorFunction;
if (pUserHeader->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)
{
pUserSrb = (USER_SCSI_REQUEST_BLOCK*)((UCHAR*)pUserHeader + sizeof(USER_HEADER));
pSrb = (SCSI_REQUEST_BLOCK*)((UCHAR*)pUserSrb + (sizeof(USER_SCSI_REQUEST_BLOCK) + pUserSrb->DataTransferLength + pUserSrb->SenseInfoBufferLength));
pSrb->Length = sizeof(SCSI_REQUEST_BLOCK);
pSrb->Function = pUserSrb->Function;
pSrb->SrbStatus = pUserSrb->SrbStatus;
pSrb->ScsiStatus = pUserSrb->ScsiStatus;
pSrb->PathId = pUserSrb->PathId;
pSrb->TargetId = pUserSrb->TargetId;
pSrb->Lun = pUserSrb->Lun;
pSrb->QueueTag = pUserSrb->QueueTag;
pSrb->QueueAction = pUserSrb->QueueAction;
pSrb->CdbLength = pUserSrb->CdbLength;
pSrb->SenseInfoBufferLength = pUserSrb->SenseInfoBufferLength;
pSrb->SrbFlags = pUserSrb->SrbFlags;
pSrb->DataTransferLength = pUserSrb->DataTransferLength;
pSrb->TimeOutValue = pUserSrb->TimeOutValue;
if (pUserSrb->DataTransferLength)
{
pSrb->DataBuffer = (UCHAR*)pIrp->MdlAddress->StartVa + pIrp->MdlAddress->ByteOffset + (sizeof(USER_HEADER) + sizeof(USER_SCSI_REQUEST_BLOCK));
IoBuildPartialMdl(pIrp->MdlAddress, pDeviceExtension->pMdl, pSrb->DataBuffer, pUserSrb->DataTransferLength);
pIrp2->MdlAddress = pDeviceExtension->pMdl;
}
else pSrb->DataBuffer = NULL;
if (pUserSrb->SenseInfoBufferLength)
{
pSrb->SenseInfoBuffer = (UCHAR*)pUserSrb + (sizeof(USER_SCSI_REQUEST_BLOCK) + pUserSrb->DataTransferLength);
}
else pSrb->SenseInfoBuffer = NULL;
pSrb->NextSrb = NULL;
pSrb->OriginalRequest = pIrp2;
pSrb->SrbExtension = NULL;
pSrb->QueueSortKey = pUserSrb->QueueSortKey;
memcpy(pSrb->Cdb, pUserSrb->Cdb, sizeof(pSrb->Cdb));
pStack->Parameters.Scsi.Srb = pSrb;
}
else
{
pStack->Parameters.DeviceIoControl.IoControlCode = pUserHeader->IoControlCode;
pBuffer = (UCHAR*)pUserHeader + sizeof(USER_HEADER);
if (pUserHeader->IoControlCode == IOCTL_SCSI_GET_ADDRESS)
{
pStack->Parameters.DeviceIoControl.OutputBufferLength = pUserHeader->OutputBufferLength;
pIrp2->AssociatedIrp.SystemBuffer = pBuffer;
}
else if (pUserHeader->IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY)
{
pStack->Parameters.DeviceIoControl.InputBufferLength = pUserHeader->InputBufferLength;
pStack->Parameters.DeviceIoControl.OutputBufferLength = pUserHeader->OutputBufferLength;
pIrp2->AssociatedIrp.SystemBuffer = pBuffer;
}
else if (pUserHeader->IoControlCode == IOCTL_STORAGE_ENABLE_IDLE_POWER)
{
pStack->Parameters.DeviceIoControl.InputBufferLength = pUserHeader->InputBufferLength;
pIrp2->AssociatedIrp.SystemBuffer = pBuffer;
}
}
*ppIrp2 = pIrp2;
Status = STATUS_SUCCESS;
}
else Status = STATUS_INSUFFICIENT_RESOURCES;
return Status;
}
NTSTATUS IoCompletionRoutine3(DEVICE_OBJECT *pDeviceObject, IRP *pIrp2, void *pContext)
{
IRP *pIrp;
USER_HEADER *pUserHeader;
DEVICE_EXTENSION *pDeviceExtension;
USER_SCSI_REQUEST_BLOCK *pUserSrb;
SCSI_REQUEST_BLOCK *pSrb;
pDeviceExtension = (DEVICE_EXTENSION*)pIrp2->Tail.Overlay.DriverContext[0];
pIrp = (IRP*)pIrp2->Tail.Overlay.DriverContext[1];
pUserHeader = (USER_HEADER*)MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
pUserHeader->Status = pIrp2->IoStatus.Status;
pUserHeader->Information = pIrp2->IoStatus.Information;
if (pUserHeader->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)
{
pUserSrb = (USER_SCSI_REQUEST_BLOCK*)((UCHAR*)pUserHeader + sizeof(USER_HEADER));
pSrb = (SCSI_REQUEST_BLOCK*)((UCHAR*)pUserSrb + (sizeof(USER_SCSI_REQUEST_BLOCK) + pUserSrb->DataTransferLength + pUserSrb->SenseInfoBufferLength));
pUserSrb->SrbStatus = pSrb->SrbStatus;
pUserSrb->ScsiStatus = pSrb->ScsiStatus;
pUserSrb->SenseInfoBufferLength = pSrb->SenseInfoBufferLength;
pUserSrb->DataTransferLength = pSrb->DataTransferLength;
pUserHeader->Length = sizeof(USER_HEADER) + sizeof(USER_SCSI_REQUEST_BLOCK);
if (NT_SUCCESS(pUserHeader->Status))
{
if ((pSrb->DataTransferLength) && (pSrb->SrbFlags & SRB_FLAGS_DATA_IN))
{
pUserHeader->Length += pUserSrb->DataTransferLength;
}
}
else
{
if ((pSrb->SenseInfoBufferLength) && (pSrb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID))
{
pUserHeader->Length += pUserSrb->SenseInfoBufferLength;
if (pSrb->DataTransferLength)
{
memmove((UCHAR*)pUserSrb + sizeof(USER_SCSI_REQUEST_BLOCK), (UCHAR*)pUserSrb + (sizeof(USER_SCSI_REQUEST_BLOCK) + pUserSrb->DataTransferLength), pUserSrb->SenseInfoBufferLength);
}
}
}
}
else
{
pUserHeader->Length = sizeof(USER_HEADER);
if (pUserHeader->IoControlCode == IOCTL_SCSI_GET_ADDRESS)
{
pUserHeader->Length += pUserHeader->Information;
}
else if (pUserHeader->IoControlCode == IOCTL_STORAGE_QUERY_PROPERTY)
{
pUserHeader->Length += pUserHeader->Information;
}
}
IoFreeIrp(pIrp2);
CompleteRequest(pIrp, STATUS_SUCCESS, 0);
IoReleaseRemoveLock(&pDeviceExtension->RemoveLock, pIrp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
一切运行正常(请求在服务器和客户端之间传递,没有BSOD等),但cdrom设备只是没有出现在客户端。我认为它可能是srb数据缓冲区访问的东西。你能帮我解决一下吗?谢谢。