mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 20:05:41 +00:00
[SPTILIB] Introduce SPTI static library for storage drivers (#8209)
Add a SCSI and ATA passthrough support helper library for direct use from low-level storage drivers. Tested with: CDRoller, CloneCD, Magic ISO NOTE: Vbox seems to lack support for CD/DVD burning; tested on real hardware. CORE-10191 CORE-16452 CORE-14788 CORE-18241 CORE-17256 CORE-13866
This commit is contained in:
parent
5bd84f6f71
commit
b558596409
12 changed files with 1285 additions and 14 deletions
|
@ -1,6 +1,9 @@
|
|||
|
||||
spec2def(scsiport.sys scsiport.spec ADD_IMPORTLIB)
|
||||
|
||||
include_directories(
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/drivers/sptilib)
|
||||
|
||||
# Embed RTC libs
|
||||
if (STACK_PROTECTOR)
|
||||
target_sources(libscsiport PRIVATE $<TARGET_OBJECTS:gcc_ssp_scsiport>)
|
||||
|
@ -27,5 +30,6 @@ add_library(scsiport MODULE
|
|||
|
||||
add_pch(scsiport scsiport.h "${PCH_SKIP_SOURCE}")
|
||||
set_module_type(scsiport kernelmodedriver)
|
||||
target_link_libraries(scsiport sptilib ${PSEH_LIB})
|
||||
add_importlibs(scsiport ntoskrnl hal)
|
||||
add_cd_file(TARGET scsiport DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include "scsiport.h"
|
||||
#include <sptilib.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
@ -276,7 +277,6 @@ PdoHandleQueryProperty(
|
|||
}
|
||||
default:
|
||||
{
|
||||
UNREACHABLE;
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
goto completeIrp;
|
||||
}
|
||||
|
@ -288,6 +288,56 @@ completeIrp:
|
|||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
PdoHandleScsiPassthrough(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PIRP Irp)
|
||||
{
|
||||
PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
|
||||
PSCSI_PORT_DEVICE_EXTENSION portExt;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||||
ASSERT(!lunExt->Common.IsFDO);
|
||||
|
||||
/* Skip requests that bypassed the class driver. See also cdrom!RequestHandleScsiPassThrough */
|
||||
if ((IoGetCurrentIrpStackLocation(Irp)->MinorFunction == 0) && lunExt->DeviceClaimed)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
portExt = lunExt->Common.LowerDevice->DeviceExtension;
|
||||
|
||||
return SptiHandleScsiPassthru(DeviceObject,
|
||||
Irp,
|
||||
portExt->PortCapabilities.MaximumTransferLength,
|
||||
portExt->PortCapabilities.MaximumPhysicalPages);
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
FdoHandleScsiPassthrough(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PIRP Irp)
|
||||
{
|
||||
PSCSI_PORT_DEVICE_EXTENSION portExt;
|
||||
PSCSI_PORT_LUN_EXTENSION lunExt;
|
||||
PSCSI_PASS_THROUGH spt;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||||
|
||||
if (!VerifyIrpInBufferSize(Irp, RTL_SIZEOF_THROUGH_FIELD(SCSI_PASS_THROUGH, Lun)))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
portExt = DeviceObject->DeviceExtension;
|
||||
ASSERT(portExt->Common.IsFDO);
|
||||
|
||||
spt = Irp->AssociatedIrp.SystemBuffer;
|
||||
lunExt = GetLunByPath(portExt, spt->PathId, spt->TargetId, spt->Lun);
|
||||
if (!lunExt)
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
|
||||
return PdoHandleScsiPassthrough(lunExt->Common.DeviceObject, Irp);
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
FdoHandleQueryProperty(
|
||||
|
@ -409,6 +459,7 @@ ScsiPortDeviceControl(
|
|||
PSCSI_PORT_COMMON_EXTENSION comExt = DeviceObject->DeviceExtension;
|
||||
PSCSI_PORT_DEVICE_EXTENSION portExt;
|
||||
PSCSI_PORT_LUN_EXTENSION lunExt;
|
||||
ULONG IoControlCode;
|
||||
NTSTATUS status;
|
||||
|
||||
DPRINT("ScsiPortDeviceControl()\n");
|
||||
|
@ -416,8 +467,9 @@ ScsiPortDeviceControl(
|
|||
Irp->IoStatus.Information = 0;
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
|
||||
|
||||
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
switch (IoControlCode)
|
||||
{
|
||||
case IOCTL_STORAGE_QUERY_PROPERTY:
|
||||
{
|
||||
|
@ -534,20 +586,27 @@ ScsiPortDeviceControl(
|
|||
break;
|
||||
|
||||
case IOCTL_SCSI_PASS_THROUGH:
|
||||
DPRINT1("IOCTL_SCSI_PASS_THROUGH unimplemented!\n");
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
case IOCTL_SCSI_PASS_THROUGH_DIRECT:
|
||||
{
|
||||
DPRINT(" IOCTL_SCSI_PASS_THROUGH%s\n",
|
||||
IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT ? "_DIRECT" : "");
|
||||
|
||||
if (comExt->IsFDO)
|
||||
status = FdoHandleScsiPassthrough(DeviceObject, Irp);
|
||||
else
|
||||
status = PdoHandleScsiPassthrough(DeviceObject, Irp);
|
||||
break;
|
||||
}
|
||||
|
||||
case IOCTL_ATA_PASS_THROUGH:
|
||||
case IOCTL_ATA_PASS_THROUGH_DIRECT:
|
||||
/* ATA passthrough IOCTLs not supported by MS scsiport */
|
||||
DPRINT1("ATA passthrough IOCTLs not supported: 0x%lX\n",
|
||||
Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||
DPRINT1("ATA passthrough IOCTLs not supported: 0x%lX\n", IoControlCode);
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT1("unknown ioctl code: 0x%lX\n", Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||
DPRINT1("unknown ioctl code: 0x%lX\n", IoControlCode);
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
|
||||
spec2def(storport.sys storport.spec ADD_IMPORTLIB)
|
||||
|
||||
include_directories(
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/drivers/sptilib)
|
||||
|
||||
list(APPEND SOURCE
|
||||
fdo.c
|
||||
miniport.c
|
||||
|
@ -20,5 +23,6 @@ add_library(storport MODULE
|
|||
|
||||
add_pch(storport precomp.h "${PCH_SKIP_SOURCE}")
|
||||
set_module_type(storport kernelmodedriver)
|
||||
target_link_libraries(storport sptilib ${PSEH_LIB})
|
||||
add_importlibs(storport ntoskrnl hal)
|
||||
add_cd_file(TARGET storport DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
|
||||
include_directories(
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/drivers/sptilib)
|
||||
|
||||
list(APPEND SOURCE
|
||||
descriptor.c
|
||||
disk.c
|
||||
|
@ -19,6 +22,7 @@ add_library(usbstor MODULE
|
|||
usbstor.rc)
|
||||
|
||||
set_module_type(usbstor kernelmodedriver)
|
||||
target_link_libraries(usbstor sptilib ${PSEH_LIB})
|
||||
add_importlibs(usbstor ntoskrnl hal usbd)
|
||||
add_pch(usbstor usbstor.h "${PCH_SKIP_SOURCE}")
|
||||
add_cd_file(TARGET usbstor DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||
|
|
|
@ -9,10 +9,13 @@
|
|||
*/
|
||||
|
||||
#include "usbstor.h"
|
||||
#include <sptilib.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
// See CORE-10515 and CORE-10755
|
||||
#define USBSTOR_DEFAULT_MAX_PHYS_PAGES (USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH / PAGE_SIZE + 1)
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
|
@ -394,7 +397,7 @@ USBSTOR_HandleQueryProperty(
|
|||
.Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8),
|
||||
.Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8),
|
||||
.MaximumTransferLength = USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH,
|
||||
.MaximumPhysicalPages = USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH / PAGE_SIZE + 1, // See CORE-10515 and CORE-10755
|
||||
.MaximumPhysicalPages = USBSTOR_DEFAULT_MAX_PHYS_PAGES,
|
||||
.BusType = BusTypeUsb,
|
||||
.BusMajorVersion = 2, //FIXME verify
|
||||
.BusMinorVersion = 0 //FIXME
|
||||
|
@ -429,13 +432,27 @@ USBSTOR_HandleDeviceControl(
|
|||
Status = USBSTOR_HandleQueryProperty(DeviceObject, Irp);
|
||||
break;
|
||||
case IOCTL_SCSI_PASS_THROUGH:
|
||||
DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH NOT implemented\n");
|
||||
Status = STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
case IOCTL_SCSI_PASS_THROUGH_DIRECT:
|
||||
DPRINT1("USBSTOR_HandleDeviceControl IOCTL_SCSI_PASS_THROUGH_DIRECT NOT implemented\n");
|
||||
Status = STATUS_NOT_SUPPORTED;
|
||||
{
|
||||
PDODeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||||
ASSERT(PDODeviceExtension);
|
||||
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||
|
||||
/* Skip requests that bypassed the class driver. See also cdrom!RequestHandleScsiPassThrough */
|
||||
if ((IoGetCurrentIrpStackLocation(Irp)->MinorFunction == 0) && PDODeviceExtension->Claimed)
|
||||
{
|
||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
Status = SptiHandleScsiPassthru(DeviceObject,
|
||||
Irp,
|
||||
USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH,
|
||||
USBSTOR_DEFAULT_MAX_PHYS_PAGES);
|
||||
break;
|
||||
}
|
||||
case IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER:
|
||||
DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
|
||||
Status = STATUS_NOT_SUPPORTED;
|
||||
|
@ -461,7 +478,7 @@ USBSTOR_HandleDeviceControl(
|
|||
if (Capabilities)
|
||||
{
|
||||
Capabilities->MaximumTransferLength = USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH;
|
||||
Capabilities->MaximumPhysicalPages = USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH / PAGE_SIZE + 1; // See CORE-10515 and CORE-10755
|
||||
Capabilities->MaximumPhysicalPages = USBSTOR_DEFAULT_MAX_PHYS_PAGES;
|
||||
Capabilities->SupportedAsynchronousEvents = 0;
|
||||
Capabilities->AlignmentMask = 0;
|
||||
Capabilities->TaggedQueuing = FALSE;
|
||||
|
|
|
@ -1886,6 +1886,27 @@ typedef union _CDB {
|
|||
UCHAR Streaming:1;
|
||||
UCHAR Control;
|
||||
} WRITE12;
|
||||
struct _ATA_PASSTHROUGH12 {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1:1;
|
||||
UCHAR Protocol:4;
|
||||
UCHAR MultipleCount:3;
|
||||
UCHAR TLength:2;
|
||||
UCHAR ByteBlock:1;
|
||||
UCHAR TDir:1;
|
||||
UCHAR Reserved2:1;
|
||||
UCHAR CkCond:1;
|
||||
UCHAR Offline:2;
|
||||
UCHAR Features;
|
||||
UCHAR SectorCount;
|
||||
UCHAR LbaLow;
|
||||
UCHAR LbaMid;
|
||||
UCHAR LbaHigh;
|
||||
UCHAR Device;
|
||||
UCHAR Command;
|
||||
UCHAR Reserved3;
|
||||
UCHAR Control;
|
||||
} ATA_PASSTHROUGH12;
|
||||
struct _READ16 {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1:3;
|
||||
|
@ -1944,6 +1965,31 @@ typedef union _CDB {
|
|||
UCHAR Reserved2:7;
|
||||
UCHAR Control;
|
||||
} READ_CAPACITY16;
|
||||
struct _ATA_PASSTHROUGH16 {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Extend:1;
|
||||
UCHAR Protocol:4;
|
||||
UCHAR MultipleCount:3;
|
||||
UCHAR TLength:2;
|
||||
UCHAR ByteBlock:1;
|
||||
UCHAR TDir:1;
|
||||
UCHAR Reserved1:1;
|
||||
UCHAR CkCond:1;
|
||||
UCHAR Offline:2;
|
||||
UCHAR Features15_8;
|
||||
UCHAR Features7_0;
|
||||
UCHAR SectorCount15_8;
|
||||
UCHAR SectorCount7_0;
|
||||
UCHAR LbaLow15_8;
|
||||
UCHAR LbaLow7_0;
|
||||
UCHAR LbaMid15_8;
|
||||
UCHAR LbaMid7_0;
|
||||
UCHAR LbaHigh15_8;
|
||||
UCHAR LbaHigh7_0;
|
||||
UCHAR Device;
|
||||
UCHAR Command;
|
||||
UCHAR Control;
|
||||
} ATA_PASSTHROUGH16;
|
||||
struct _TOKEN_OPERATION {
|
||||
UCHAR OperationCode;
|
||||
UCHAR ServiceAction:5;
|
||||
|
|
|
@ -256,6 +256,7 @@ typedef struct _SCSI_PASS_THROUGH_DIRECT32_EX
|
|||
#define ATA_FLAGS_DATA_OUT (1 << 2)
|
||||
#define ATA_FLAGS_48BIT_COMMAND (1 << 3)
|
||||
#define ATA_FLAGS_USE_DMA (1 << 4)
|
||||
#define ATA_FLAGS_NO_MULTIPLE (1 << 5)
|
||||
|
||||
typedef struct _SCSI_BUS_DATA {
|
||||
UCHAR NumberOfLogicalUnits;
|
||||
|
|
|
@ -9,5 +9,6 @@ add_subdirectory(rdbsslib)
|
|||
add_subdirectory(rtlver)
|
||||
add_subdirectory(rxce)
|
||||
add_subdirectory(sound)
|
||||
add_subdirectory(sptilib)
|
||||
add_subdirectory(virtio)
|
||||
add_subdirectory(wdf)
|
||||
|
|
7
sdk/lib/drivers/sptilib/CMakeLists.txt
Normal file
7
sdk/lib/drivers/sptilib/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
sptilib.c)
|
||||
|
||||
add_library(sptilib ${SOURCE})
|
||||
target_link_libraries(sptilib PRIVATE ${PSEH_LIB})
|
||||
add_dependencies(sptilib xdk)
|
1008
sdk/lib/drivers/sptilib/sptilib.c
Normal file
1008
sdk/lib/drivers/sptilib/sptilib.c
Normal file
File diff suppressed because it is too large
Load diff
85
sdk/lib/drivers/sptilib/sptilib.h
Normal file
85
sdk/lib/drivers/sptilib/sptilib.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Storage Stack
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Public header of the ATA and SCSI Pass Through Interface for storage drivers
|
||||
* COPYRIGHT: Copyright 2025 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* ATA Protocol field definitions for the ATA passthrough commands
|
||||
* (SCSIOP_ATA_PASSTHROUGH12 and SCSIOP_ATA_PASSTHROUGH16).
|
||||
*/
|
||||
/*@{*/
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_HARDWARE_RESET 0x0
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_SOFTWARE_RESET 0x1
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_NON_DATA 0x3
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_PIO_DATA_IN 0x4
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_PIO_DATA_OUT 0x5
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_DMA 0x6
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_DEVICE_DIAG 0x8
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_DEVICE_RESET 0x9
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_UDMA_DATA_IN 0xA
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_UDMA_DATA_OUT 0xB
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_NCQ 0xC
|
||||
#define ATA_PASSTHROUGH_PROTOCOL_RETURN_RESPONSE 0xF
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* Additional sense code for the successfully completed ATA passthrough commands
|
||||
* with check condition enabled.
|
||||
*/
|
||||
#define SCSI_SENSEQ_ATA_PASS_THROUGH_INFORMATION_AVAILABLE 0x1D
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Handler for the IOCTL_ATA_PASS_THROUGH and IOCTL_ATA_PASS_THROUGH_DIRECT requests.
|
||||
*
|
||||
* @param[in] DeviceObject
|
||||
* PDO device object.
|
||||
*
|
||||
* @param[in,out] Irp
|
||||
* Pointer to the IOCTL request.
|
||||
*
|
||||
* @param[in] MaximumTransferLength
|
||||
* Maximum size of data transfer for a device.
|
||||
*
|
||||
* @param[in] MaximumPhysicalPages
|
||||
* Maximum number of physical pages per data transfer for a device.
|
||||
*
|
||||
* @return Status.
|
||||
*/
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
SptiHandleAtaPassthru(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ ULONG MaximumTransferLength,
|
||||
_In_ ULONG MaximumPhysicalPages);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Handler for the IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT requests.
|
||||
*
|
||||
* @param[in] DeviceObject
|
||||
* PDO device object.
|
||||
*
|
||||
* @param[in,out] Irp
|
||||
* Pointer to the IOCTL request.
|
||||
*
|
||||
* @param[in] MaximumTransferLength
|
||||
* Maximum size of data transfer for a device.
|
||||
*
|
||||
* @param[in] MaximumPhysicalPages
|
||||
* Maximum number of physical pages per data transfer for a device.
|
||||
*
|
||||
* @return Status.
|
||||
*/
|
||||
CODE_SEG("PAGE")
|
||||
NTSTATUS
|
||||
SptiHandleScsiPassthru(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_Inout_ PIRP Irp,
|
||||
_In_ ULONG MaximumTransferLength,
|
||||
_In_ ULONG MaximumPhysicalPages);
|
35
sdk/lib/drivers/sptilib/sptilibp.h
Normal file
35
sdk/lib/drivers/sptilib/sptilibp.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Storage Stack
|
||||
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||
* PURPOSE: Private header of the ATA and SCSI Pass Through Interface for storage drivers
|
||||
* COPYRIGHT: Copyright 2025 Dmitry Borisov <di.sean@protonmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SPTI allocation tag.
|
||||
*/
|
||||
#define TAG_SPTI 'ITPS'
|
||||
|
||||
/**
|
||||
* Timeouts to wait for a request to be completed, in seconds.
|
||||
*/
|
||||
/*@{*/
|
||||
#define PASSTHROUGH_CMD_TIMEOUT_MIN_SEC 1
|
||||
#define PASSTHROUGH_CMD_TIMEOUT_MAX_SEC (30 * 60 * 60) // 30 hours
|
||||
/*@}*/
|
||||
|
||||
#define GET_IOCTL(IoStack) ((IoStack)->Parameters.DeviceIoControl.IoControlCode)
|
||||
|
||||
typedef union _PASSTHROUGH_DATA
|
||||
{
|
||||
PVOID Buffer;
|
||||
ULONG_PTR BufferOffset;
|
||||
} PASSTHROUGH_DATA, *PPASSTHROUGH_DATA;
|
||||
|
||||
typedef struct _PASSTHROUGH_IRP_CONTEXT
|
||||
{
|
||||
SCSI_REQUEST_BLOCK Srb;
|
||||
PIRP Irp;
|
||||
} PASSTHROUGH_IRP_CONTEXT, *PPASSTHROUGH_IRP_CONTEXT;
|
Loading…
Add table
Add a link
Reference in a new issue