mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[CLASSPNP][DISK_NEW][CDROM_NEW] Remove the drivers
Due to WDK/DDK licensing issues CORE-17129
This commit is contained in:
parent
3da77f9173
commit
c57350e295
43 changed files with 0 additions and 51483 deletions
|
@ -126,7 +126,6 @@ storport.sys = 1,,,,,,x,4,,,,1,4
|
|||
fastfat.sys = 1,,,,,,x,4,,,,1,4
|
||||
btrfs.sys = 1,,,,,,x,4,,,,1,4
|
||||
ramdisk.sys = 1,,,,,,x,4,,,,1,4
|
||||
classpnp.sys = 1,,,,,,,4,,,,1,4
|
||||
pciide.sys = 1,,,,,,,4,,,,1,4
|
||||
pciidex.sys = 1,,,,,,,4,,,,1,4
|
||||
pcix.sys = 1,,,,,,,4,,,,1,4
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
add_subdirectory(cdrom)
|
||||
add_subdirectory(cdrom_new)
|
||||
add_subdirectory(class2)
|
||||
add_subdirectory(classpnp)
|
||||
add_subdirectory(disk)
|
||||
add_subdirectory(disk_new)
|
||||
add_subdirectory(ramdisk)
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/drivers/storage/class)
|
||||
|
||||
list(APPEND SOURCE
|
||||
cdrom.c
|
||||
data.c
|
||||
ioctl.c
|
||||
mmc.c
|
||||
sec.c
|
||||
cdrom.h)
|
||||
|
||||
add_library(cdrom_new MODULE ${SOURCE})
|
||||
target_link_libraries(cdrom_new libcntpr wdmguid)
|
||||
|
||||
if(USE_CLANG_CL OR (NOT MSVC))
|
||||
target_compile_options(cdrom_new PRIVATE -Wno-format -Wno-unused-variable -Wno-pointer-sign)
|
||||
if(USE_CLANG_CL)
|
||||
target_compile_options(cdrom_new PRIVATE -Wno-enum-conversion -Wno-tautological-constant-compare)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_module_type(cdrom_new kernelmodedriver)
|
||||
add_importlibs(cdrom_new classpnp ntoskrnl hal)
|
||||
add_pch(cdrom_new cdrom.h SOURCE)
|
File diff suppressed because it is too large
Load diff
|
@ -1,879 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
cdromp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Private header file for cdrom.sys. This contains private
|
||||
structure and function declarations as well as constant
|
||||
values which do not need to be exported.
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __CDROMP_H__
|
||||
#define __CDROMP_H__
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <ntddcdvd.h>
|
||||
#include <classpnp.h>
|
||||
#include <ntddmmc.h>
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
extern CLASSPNP_SCAN_FOR_SPECIAL_INFO CdromHackItems[];
|
||||
|
||||
typedef enum {
|
||||
CdromDebugError = 0, // always printed
|
||||
CdromDebugWarning = 1, // set bit 0x00000001 in nt!kd_cdrom_mask
|
||||
CdromDebugTrace = 2, // set bit 0x00000002 in nt!kd_cdrom_mask
|
||||
CdromDebugInfo = 3, // set bit 0x00000004 in nt!kd_cdrom_mask
|
||||
#if 0
|
||||
CdromDebug = z, // set bit 0x00000000 in nt!kd_cdrom_mask
|
||||
CdromDebug = z, // set bit 0x00000000 in nt!kd_cdrom_mask
|
||||
CdromDebug = z, // set bit 0x00000000 in nt!kd_cdrom_mask
|
||||
CdromDebug = z, // set bit 0x00000000 in nt!kd_cdrom_mask
|
||||
#endif
|
||||
CdromDebugFeatures = 32 // set bit 0x80000000 in nt!kd_cdrom_mask
|
||||
}CdromError;
|
||||
|
||||
#define CDROM_GET_CONFIGURATION_TIMEOUT (0x4)
|
||||
|
||||
#define CDROM_HACK_DEC_RRD (0x00000001)
|
||||
#define CDROM_HACK_FUJITSU_FMCD_10x (0x00000002)
|
||||
#define CDROM_HACK_HITACHI_1750 (0x00000004)
|
||||
#define CDROM_HACK_HITACHI_GD_2000 (0x00000008)
|
||||
#define CDROM_HACK_TOSHIBA_SD_W1101 (0x00000010)
|
||||
#define CDROM_HACK_TOSHIBA_XM_3xx (0x00000020)
|
||||
#define CDROM_HACK_NEC_CDDA (0x00000040)
|
||||
#define CDROM_HACK_PLEXTOR_CDDA (0x00000080)
|
||||
#define CDROM_HACK_BAD_GET_CONFIG_SUPPORT (0x00000100)
|
||||
#define CDROM_HACK_FORCE_READ_CD_DETECTION (0x00000200)
|
||||
#define CDROM_HACK_READ_CD_SUPPORTED (0x00000400)
|
||||
#define CDROM_HACK_LOCKED_PAGES (0x80000000) // not a valid flag to save
|
||||
|
||||
#define CDROM_HACK_VALID_FLAGS (0x000007ff)
|
||||
#define CDROM_HACK_INVALID_FLAGS (~CDROM_HACK_VALID_FLAGS)
|
||||
|
||||
|
||||
typedef struct _XA_CONTEXT {
|
||||
|
||||
//
|
||||
// Pointer to the device object.
|
||||
//
|
||||
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
//
|
||||
// Pointer to the original request when
|
||||
// a mode select must be sent.
|
||||
//
|
||||
|
||||
PIRP OriginalRequest;
|
||||
|
||||
//
|
||||
// Pointer to the mode select srb.
|
||||
//
|
||||
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
} XA_CONTEXT, *PXA_CONTEXT;
|
||||
|
||||
typedef struct _ERROR_RECOVERY_DATA {
|
||||
MODE_PARAMETER_HEADER Header;
|
||||
MODE_PARAMETER_BLOCK BlockDescriptor;
|
||||
MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
|
||||
} ERROR_RECOVERY_DATA, *PERROR_RECOVERY_DATA;
|
||||
|
||||
typedef struct _ERROR_RECOVERY_DATA10 {
|
||||
MODE_PARAMETER_HEADER10 Header10;
|
||||
MODE_PARAMETER_BLOCK BlockDescriptor10;
|
||||
MODE_READ_RECOVERY_PAGE ReadRecoveryPage10;
|
||||
} ERROR_RECOVERY_DATA10, *PERROR_RECOVERY_DATA10;
|
||||
|
||||
//
|
||||
// CdRom specific addition to device extension.
|
||||
//
|
||||
|
||||
typedef struct _CDROM_DRIVER_EXTENSION {
|
||||
ULONG InterlockedCdRomCounter;
|
||||
PVOID Reserved[3];
|
||||
} CDROM_DRIVER_EXTENSION, *PCDROM_DRIVER_EXTENSION;
|
||||
|
||||
#define CdromMmcUpdateComplete 0
|
||||
#define CdromMmcUpdateRequired 1
|
||||
#define CdromMmcUpdateStarted 2
|
||||
|
||||
typedef struct _CDROM_MMC_EXTENSION {
|
||||
|
||||
ULONG IsMmc; // allow quick checks
|
||||
ULONG WriteAllowed;
|
||||
|
||||
LONG UpdateState;
|
||||
|
||||
SLIST_HEADER DelayedIrps; // irps delayed due to
|
||||
KSPIN_LOCK DelayedLock; // lock for delayed irps
|
||||
|
||||
PIO_WORKITEM CapabilitiesWorkItem;
|
||||
PIRP CapabilitiesIrp;
|
||||
PMDL CapabilitiesMdl;
|
||||
PGET_CONFIGURATION_HEADER CapabilitiesBuffer;
|
||||
ULONG CapabilitiesBufferSize;
|
||||
KEVENT CapabilitiesEvent;
|
||||
SCSI_REQUEST_BLOCK CapabilitiesSrb;
|
||||
|
||||
} CDROM_MMC_EXTENSION, *PCDROM_MMC_EXTENSION;
|
||||
|
||||
|
||||
#define CDROM_DRIVER_EXTENSION_ID CdRomAddDevice
|
||||
|
||||
typedef struct _CDROM_DATA {
|
||||
|
||||
//
|
||||
// Pointer to the cdrom driver extension
|
||||
//
|
||||
|
||||
PCDROM_DRIVER_EXTENSION DriverExtension;
|
||||
|
||||
|
||||
//
|
||||
// These bits allow detection of when to requery the
|
||||
// drive's capabilities.
|
||||
//
|
||||
|
||||
CDROM_MMC_EXTENSION Mmc;
|
||||
|
||||
//
|
||||
// hack flags for ScanForSpecial routines
|
||||
//
|
||||
|
||||
ULONG_PTR HackFlags;
|
||||
|
||||
//
|
||||
// the error handling routines need to be per-device,
|
||||
// not per-driver....
|
||||
//
|
||||
|
||||
PCLASS_ERROR ErrorHandler;
|
||||
|
||||
//
|
||||
// Indicates whether an audio play operation
|
||||
// is currently being performed.
|
||||
// Only thing this does is prevent reads and
|
||||
// toc requests while playing audio.
|
||||
//
|
||||
|
||||
BOOLEAN PlayActive;
|
||||
|
||||
//
|
||||
// Indicates whether the blocksize used for user data
|
||||
// is 2048 or 2352.
|
||||
//
|
||||
|
||||
BOOLEAN RawAccess;
|
||||
|
||||
//
|
||||
// Indicates that this is a DEC RRD cdrom.
|
||||
// This drive requires software to fix responses
|
||||
// from the faulty firmware
|
||||
//
|
||||
|
||||
BOOLEAN IsDecRrd;
|
||||
|
||||
//
|
||||
// This points to an irp which needs to be delayed for a bit before a
|
||||
// retry can be attempted. The interval counter is set by the deferring
|
||||
// routine and will be decremented to zero in the tick handler. Once
|
||||
// the counter goes to zero the irp will be issued again.
|
||||
// DelayedRetryResend controls whether the irp is resent to the lower
|
||||
// driver (TRUE) or reissued into the startio routine (FALSE)
|
||||
//
|
||||
|
||||
BOOLEAN DelayedRetryResend;
|
||||
|
||||
PIRP DelayedRetryIrp;
|
||||
|
||||
ULONG DelayedRetryInterval;
|
||||
|
||||
KSPIN_LOCK DelayedRetrySpinLock;
|
||||
|
||||
//
|
||||
// indicate we need to pick a default dvd region
|
||||
// for the user if we can
|
||||
//
|
||||
|
||||
ULONG PickDvdRegion;
|
||||
|
||||
//
|
||||
// The interface strings registered for this device.
|
||||
//
|
||||
|
||||
UNICODE_STRING CdromInterfaceString;
|
||||
UNICODE_STRING VolumeInterfaceString;
|
||||
|
||||
//
|
||||
// The well known name link for this device.
|
||||
//
|
||||
|
||||
UNICODE_STRING WellKnownName;
|
||||
|
||||
//
|
||||
// Indicates whether 6 or 10 bytes mode sense/select
|
||||
// should be used
|
||||
//
|
||||
|
||||
ULONG XAFlags;
|
||||
|
||||
//
|
||||
// keep track of what type of DVD device we are
|
||||
//
|
||||
|
||||
BOOLEAN DvdRpc0Device;
|
||||
BOOLEAN DvdRpc0LicenseFailure;
|
||||
UCHAR Rpc0SystemRegion; // bitmask, one means prevent play
|
||||
UCHAR Rpc0SystemRegionResetCount;
|
||||
|
||||
ULONG Rpc0RetryRegistryCallback; // one until initial region chosen
|
||||
|
||||
KMUTEX Rpc0RegionMutex;
|
||||
|
||||
//
|
||||
// Storage for the error recovery page. This is used
|
||||
// as an easy method to switch block sizes.
|
||||
//
|
||||
// NOTE - doubly unnamed structs just aren't very clean looking code - this
|
||||
// should get cleaned up at some point in the future.
|
||||
//
|
||||
|
||||
union {
|
||||
ERROR_RECOVERY_DATA;
|
||||
ERROR_RECOVERY_DATA10;
|
||||
};
|
||||
|
||||
} CDROM_DATA, *PCDROM_DATA;
|
||||
|
||||
#define DEVICE_EXTENSION_SIZE sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(CDROM_DATA)
|
||||
#define SCSI_CDROM_TIMEOUT 10
|
||||
#define SCSI_CHANGER_BONUS_TIMEOUT 10
|
||||
#define HITACHI_MODE_DATA_SIZE 12
|
||||
#define MODE_DATA_SIZE 64
|
||||
#define RAW_SECTOR_SIZE 2352
|
||||
#define COOKED_SECTOR_SIZE 2048
|
||||
#define CDROM_SRB_LIST_SIZE 4
|
||||
|
||||
#define PLAY_ACTIVE(x) (((PCDROM_DATA)(x->CommonExtension.DriverData))->PlayActive)
|
||||
|
||||
#define MSF_TO_LBA(Minutes,Seconds,Frames) \
|
||||
(ULONG)((60 * 75 * (Minutes)) + (75 * (Seconds)) + ((Frames) - 150))
|
||||
|
||||
#define LBA_TO_MSF(Lba,Minutes,Seconds,Frames) \
|
||||
{ \
|
||||
(Minutes) = (UCHAR)(Lba / (60 * 75)); \
|
||||
(Seconds) = (UCHAR)((Lba % (60 * 75)) / 75); \
|
||||
(Frames) = (UCHAR)((Lba % (60 * 75)) % 75); \
|
||||
}
|
||||
|
||||
#define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10))
|
||||
|
||||
//
|
||||
// Define flags for XA, CDDA, and Mode Select/Sense
|
||||
//
|
||||
|
||||
#define XA_USE_6_BYTE 0x01
|
||||
#define XA_USE_10_BYTE 0x02
|
||||
|
||||
#define XA_NOT_SUPPORTED 0x10
|
||||
#define XA_USE_READ_CD 0x20
|
||||
#define XA_PLEXTOR_CDDA 0x40
|
||||
#define XA_NEC_CDDA 0x80
|
||||
|
||||
//
|
||||
// Sector types for READ_CD
|
||||
//
|
||||
|
||||
#define ANY_SECTOR 0
|
||||
#define CD_DA_SECTOR 1
|
||||
#define YELLOW_MODE1_SECTOR 2
|
||||
#define YELLOW_MODE2_SECTOR 3
|
||||
#define FORM2_MODE1_SECTOR 4
|
||||
#define FORM2_MODE2_SECTOR 5
|
||||
|
||||
#define MAX_COPY_PROTECT_AGID 4
|
||||
|
||||
#ifdef ExAllocatePool
|
||||
#undef ExAllocatePool
|
||||
#define ExAllocatePool #assert(FALSE)
|
||||
#endif
|
||||
|
||||
#define CDROM_TAG_GET_CONFIG 'cCcS' // "ScCc" - ioctl GET_CONFIGURATION
|
||||
#define CDROM_TAG_DC_EVENT 'ECcS' // "ScCE" - device control synch event
|
||||
#define CDROM_TAG_FEATURE 'FCcS' // "ScCF" - allocated by CdRomGetConfiguration(), free'd by caller
|
||||
#define CDROM_TAG_DISK_GEOM 'GCcS' // "ScCG" - disk geometry buffer
|
||||
#define CDROM_TAG_HITACHI_ERROR 'HCcS' // "ScCH" - hitachi error buffer
|
||||
#define CDROM_TAG_SENSE_INFO 'ICcS' // "ScCI" - sense info buffers
|
||||
#define CDROM_TAG_POWER_IRP 'iCcS' // "ScCi" - irp for power request
|
||||
#define CDROM_TAG_SRB 'SCcS' // "ScCS" - srb allocation
|
||||
#define CDROM_TAG_STRINGS 'sCcS' // "ScCs" - assorted string data
|
||||
#define CDROM_TAG_MODE_DATA 'MCcS' // "ScCM" - mode data buffer
|
||||
#define CDROM_TAG_READ_CAP 'PCcS' // "ScCP" - read capacity buffer
|
||||
#define CDROM_TAG_PLAY_ACTIVE 'pCcS' // "ScCp" - play active checks
|
||||
#define CDROM_TAG_SUB_Q 'QCcS' // "ScCQ" - read sub q buffer
|
||||
#define CDROM_TAG_RAW 'RCcS' // "ScCR" - raw mode read buffer
|
||||
#define CDROM_TAG_TOC 'TCcS' // "ScCT" - read toc buffer
|
||||
#define CDROM_TAG_TOSHIBA_ERROR 'tCcS' // "ScCt" - toshiba error buffer
|
||||
#define CDROM_TAG_DEC_ERROR 'dCcS' // "ScCt" - DEC error buffer
|
||||
#define CDROM_TAG_UPDATE_CAP 'UCcS' // "ScCU" - update capacity path
|
||||
#define CDROM_TAG_VOLUME 'VCcS' // "ScCV" - volume control buffer
|
||||
#define CDROM_TAG_VOLUME_INT 'vCcS' // "ScCv" - volume control buffer
|
||||
|
||||
#define DVD_TAG_READ_STRUCTURE 'SVcS' // "ScVS" - used for dvd structure reads
|
||||
#define DVD_TAG_READ_KEY 'kVcS' // "ScVk" - read buffer for dvd key
|
||||
#define DVD_TAG_SEND_KEY 'KVcS' // "ScVK" - write buffer for dvd key
|
||||
#define DVD_TAG_RPC2_CHECK 'sVcS' // "ScVs" - read buffer for dvd/rpc2 check
|
||||
#define DVD_TAG_DVD_REGION 'tVcS' // "ScVt" - read buffer for rpc2 check
|
||||
#define DVD_TAG_SECURITY 'XVcS' // "ScVX" - security descriptor
|
||||
|
||||
|
||||
#define CDROM_SUBKEY_NAME (L"CdRom") // store new settings here
|
||||
#define CDROM_READ_CD_NAME (L"ReadCD") // READ_CD support previously detected
|
||||
#define CDROM_NON_MMC_DRIVE_NAME (L"NonMmc") // MMC commands hang
|
||||
//
|
||||
// DVD Registry Value Names for RPC0 Device
|
||||
//
|
||||
#define DVD_DEFAULT_REGION (L"DefaultDvdRegion") // this is init. by the dvd class installer
|
||||
#define DVD_CURRENT_REGION (L"DvdR")
|
||||
#define DVD_REGION_RESET_COUNT (L"DvdRCnt")
|
||||
#define DVD_MAX_REGION_RESET_COUNT 2
|
||||
#define DVD_MAX_REGION 8
|
||||
|
||||
#define BAIL_OUT(Irp) \
|
||||
DebugPrint((2, "Cdrom: [%p] Bailing with status " \
|
||||
" %lx at line %x file %s\n", \
|
||||
(Irp), (Irp)->IoStatus.Status, \
|
||||
__LINE__, __FILE__))
|
||||
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine grabs an extra remove lock using a local variable
|
||||
for a unique tag. It then completes the irp in question, and
|
||||
the just-acquired removelock guarantees that it is still safe
|
||||
to call IoStartNextPacket(). When that finishes, we release
|
||||
the newly acquired RemoveLock and return.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - the device object for the StartIo queue
|
||||
Irp - the request we are completing
|
||||
|
||||
Return Value:
|
||||
|
||||
None
|
||||
|
||||
Notes:
|
||||
|
||||
This is implemented as an inline function to allow the compiler
|
||||
to optimize this as either a function call or as actual inline code.
|
||||
|
||||
This routine will not work with IoXxxRemoveLock() calls, as the
|
||||
behavior is different. ClassXxxRemoveLock() calls succeed until
|
||||
the remove has completed, while IoXxxRemoveLock() calls fail as
|
||||
soon as the call to IoReleaseRemoveLockAndWait() has been called.
|
||||
The Class version allows this routine to work in a safe manner.
|
||||
|
||||
replaces the following two lines:
|
||||
IoStartNextPacket(DeviceObject, FALSE);
|
||||
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||
and raises irql as needed to call IoStartNextPacket()
|
||||
|
||||
--*/
|
||||
static inline
|
||||
VOID
|
||||
CdRomCompleteIrpAndStartNextPacketSafely(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
{
|
||||
UCHAR uniqueAddress;
|
||||
KIRQL oldIrql = KeGetCurrentIrql();
|
||||
|
||||
ClassAcquireRemoveLock(DeviceObject, (PIRP)&uniqueAddress);
|
||||
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||
ClassCompleteRequest(DeviceObject, Irp, IO_CD_ROM_INCREMENT);
|
||||
|
||||
if (oldIrql > DISPATCH_LEVEL) {
|
||||
ASSERT(!"Cannot call IoStartNextPacket at raised IRQL!");
|
||||
} else if (oldIrql < DISPATCH_LEVEL) {
|
||||
KeRaiseIrqlToDpcLevel();
|
||||
} else { // (oldIrql == DISPATCH_LEVEL)
|
||||
NOTHING;
|
||||
}
|
||||
|
||||
IoStartNextPacket(DeviceObject, FALSE);
|
||||
|
||||
if (oldIrql > DISPATCH_LEVEL) {
|
||||
ASSERT(!"Cannot call IoStartNextPacket at raised IRQL!");
|
||||
} else if (oldIrql < DISPATCH_LEVEL) {
|
||||
KeLowerIrql(oldIrql);
|
||||
} else { // (oldIrql == DISPATCH_LEVEL)
|
||||
NOTHING;
|
||||
}
|
||||
|
||||
ClassReleaseRemoveLock(DeviceObject, (PIRP)&uniqueAddress);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomDeviceControlDvdReadStructure(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP OriginalIrp,
|
||||
IN PIRP NewIrp,
|
||||
IN PSCSI_REQUEST_BLOCK Srb
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomDeviceControlDvdEndSession(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP OriginalIrp,
|
||||
IN PIRP NewIrp,
|
||||
IN PSCSI_REQUEST_BLOCK Srb
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomDeviceControlDvdStartSessionReadKey(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP OriginalIrp,
|
||||
IN PIRP NewIrp,
|
||||
IN PSCSI_REQUEST_BLOCK Srb
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomDeviceControlDvdSendKey(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP OriginalIrp,
|
||||
IN PIRP NewIrp,
|
||||
IN PSCSI_REQUEST_BLOCK Srb
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomUnload(
|
||||
IN PDRIVER_OBJECT DriverObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomAddDevice(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT Pdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomOpenClose(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomReadWriteVerification(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomSwitchMode(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN ULONG SectorSize,
|
||||
IN PIRP OriginalRequest
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomDeviceControlDispatch(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomDeviceControlCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomSetVolumeIntermediateCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomSwitchModeCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomXACompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomClassIoctlCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomStartIo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomTickHandler(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomUpdateCapacity(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension,
|
||||
IN PIRP IrpToComplete,
|
||||
IN OPTIONAL PKEVENT IoctlEvent
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomCreateDeviceObject(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT Pdo
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ScanForSpecialHandler(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
ULONG_PTR HackFlags
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ScanForSpecial(
|
||||
PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CdRomIsPlayActive(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomErrorHandler(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PSCSI_REQUEST_BLOCK Srb,
|
||||
NTSTATUS *Status,
|
||||
BOOLEAN *Retry
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HitachiProcessErrorGD2000(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PSCSI_REQUEST_BLOCK Srb,
|
||||
NTSTATUS *Status,
|
||||
BOOLEAN *Retry
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HitachiProcessError(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PSCSI_REQUEST_BLOCK Srb,
|
||||
NTSTATUS *Status,
|
||||
BOOLEAN *Retry
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ToshibaProcessError(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PSCSI_REQUEST_BLOCK Srb,
|
||||
NTSTATUS *Status,
|
||||
BOOLEAN *Retry
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ToshibaProcessErrorCompletion(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID Context
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomCreateNamedEvent(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension,
|
||||
IN ULONG DeviceNumber
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomInitDevice(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomStartDevice(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomStopDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR Type
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomRemoveDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR Type
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomDvdEndAllSessionsCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomDvdReadDiskKeyCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
DEVICE_TYPE
|
||||
NTAPI
|
||||
CdRomGetDeviceType(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomCreateWellKnownName(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomDeleteWellKnownName(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomGetDeviceParameter (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PWSTR ParameterName,
|
||||
IN OUT PULONG ParameterValue
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomSetDeviceParameter (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PWSTR ParameterName,
|
||||
IN ULONG ParameterValue
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomPickDvdRegion (
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomRetryRequest(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PIRP Irp,
|
||||
IN ULONG Delay,
|
||||
IN BOOLEAN ResendIrp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomRerunRequest(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN OPTIONAL PIRP Irp,
|
||||
IN BOOLEAN ResendIrp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomGetRpc0Settings(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomSetRpc0Settings(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN UCHAR NewRegion
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomShutdownFlush(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomIsDeviceMmcDevice(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
OUT PBOOLEAN IsMmc
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomMmcErrorHandler(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN PSCSI_REQUEST_BLOCK Srb,
|
||||
OUT PNTSTATUS Status,
|
||||
OUT PBOOLEAN Retry
|
||||
);
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
CdRomFindFeaturePage(
|
||||
IN PGET_CONFIGURATION_HEADER FeatureBuffer,
|
||||
IN ULONG Length,
|
||||
IN FEATURE_NUMBER Feature
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomGetConfiguration(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
OUT PGET_CONFIGURATION_HEADER *Buffer,
|
||||
OUT PULONG BytesReturned,
|
||||
IN FEATURE_NUMBER StartingFeature,
|
||||
IN ULONG RequestedType
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomUpdateMmcDriveCapabilities(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN PVOID Context // RESERVED == NULL
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomFindProfileInProfiles(
|
||||
IN PFEATURE_DATA_PROFILE_LIST ProfileHeader,
|
||||
IN FEATURE_PROFILE_TYPE ProfileToFind,
|
||||
OUT PBOOLEAN Exists
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomAllocateMmcResources(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomDeAllocateMmcResources(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdromFakePartitionInfo(
|
||||
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRomInterpretReadCapacity(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN PREAD_CAPACITY_DATA ReadCapacityBuffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomShutdownFlushCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PIRP Context
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CdRompFlushDelayedList(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN PCDROM_MMC_EXTENSION MmcData,
|
||||
IN NTSTATUS Status,
|
||||
IN BOOLEAN CalledFromWorkItem
|
||||
);
|
||||
|
||||
#endif /* __CDROMP_H__ */
|
|
@ -1,379 +0,0 @@
|
|||
;
|
||||
; cdrom.inf -- INF file for installing CDROM drives
|
||||
;
|
||||
; Copyright (c) 1993-1997, Microsoft Corporation
|
||||
|
||||
[Version]
|
||||
Signature="$WINDOWS NT$"
|
||||
Class=CDROM
|
||||
ClassGuid={4D36E965-E325-11CE-BFC1-08002BE10318}
|
||||
Provider=%DDK_SAMPLE%
|
||||
DriverVer=03/15/2001,5.1.2462.0
|
||||
CatalogFile=ddk_sample.cat
|
||||
|
||||
[cdaudio_copyfiles]
|
||||
cdaudio.sys
|
||||
|
||||
[changer_copyfiles]
|
||||
changer.sys
|
||||
|
||||
[cdrom_copyfiles]
|
||||
cdrom.sys
|
||||
redbook.sys
|
||||
|
||||
[storprop_copyfiles]
|
||||
storprop.dll
|
||||
|
||||
[DestinationDirs]
|
||||
cdrom_copyfiles = 12
|
||||
cdaudio_copyfiles = 12
|
||||
changer_copyfiles = 12
|
||||
storprop_copyfiles = 11
|
||||
|
||||
[Manufacturer]
|
||||
%ATAPI_CHGR% = atapi_chgr
|
||||
%CHINON% = chinon_cdrom
|
||||
%DENON% = denon_cdrom
|
||||
%FUJITSU% = fujitsu_cdrom
|
||||
%HITACHI% = hitachi_cdrom
|
||||
%HP% = hp_cdrom
|
||||
%MITSUMI% = mitsumi_cdrom
|
||||
%NEC% = nec_cdrom
|
||||
%OTI% = oti_cdrom
|
||||
%PIONEER% = pioneer_cdrom
|
||||
%WEARNES% = wearnes_cdrom
|
||||
%GenManufacturer% = cdrom_device
|
||||
|
||||
[atapi_chgr]
|
||||
%NecChanger_devdesc% = changer_install,IDE\CdRomNEC_CD-ROM_DRIVE:251____________________
|
||||
%NecChanger_devdesc% = changer_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:251
|
||||
%NecChanger_devdesc% = changer_install,IDE\CdRomNEC_CD-ROM_DRIVE:253____________________
|
||||
%NecChanger_devdesc% = changer_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:253
|
||||
%NecChanger_devdesc% = changer_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:252
|
||||
%AlpsChanger_devdesc% = changer_install,IDE\CdRomALPS_DC544______________________________
|
||||
%TorisanChanger_devdesc% = changer_install,IDE\CdRomTORiSAN_CD-ROM_CDR-C3G__________________
|
||||
%TorisanChanger_devdesc% = changer_install,SCSI\CdRomTORiSAN_CD-ROM_CDR-C3G__
|
||||
%TorisanChanger_devdesc% = changer_install,IDE\CdRomTORiSAN_CD-ROM_CDR_C36__________________
|
||||
%PanasonicChanger_devdesc% = changer_install,IDE\CdRomMATSHITA_RD-DRC001-M____________________
|
||||
%PanasonicChanger_devdesc% = changer_install,IDE\CdRomMATSHITA_RD-DRC002-S____________________
|
||||
%PanasonicChanger_devdesc% = changer_install,SCSI\CdRomNAKAMICHMJ-5.16_________
|
||||
|
||||
[fujitsu_cdrom]
|
||||
%fujitsu_devdesc% = cdaudio_install,SCSI\CdRomFUJITSU_
|
||||
|
||||
[chinon_cdrom]
|
||||
%chinon_devdesc% = cdaudio_install,SCSI\CdRomCHINON__
|
||||
|
||||
[denon_cdrom]
|
||||
%denon_devdesc% = cdaudio_install,SCSI\CdRomDENON___
|
||||
|
||||
[hp_cdrom]
|
||||
%hp_devdesc% = cdaudio_install,SCSI\CdRomHP______C4324/C4325_____
|
||||
|
||||
[hitachi_cdrom]
|
||||
%hitachi_devdesc% = cdaudio_install,SCSI\CdRomHITACHI_CDR-3650/1650S__
|
||||
%hitachi_devdesc% = cdaudio_install,SCSI\CdRomHITACHI_CDR-1750S_______
|
||||
|
||||
[mitsumi_cdrom]
|
||||
%Mitsumi_cdrom_devdesc% = mitsumi_install,IDE\CdRomMITSUMI_CD-ROM________!A________________
|
||||
|
||||
[nec_cdrom]
|
||||
%NecMultispin_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:38_
|
||||
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE_4_M
|
||||
%NecIntersect_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:80_
|
||||
%NecIntersect_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:82_
|
||||
%NecIntersect_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:83_
|
||||
%NecIntersect_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:84_
|
||||
%NecMultispin_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:841
|
||||
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:400
|
||||
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:401
|
||||
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:500
|
||||
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:501
|
||||
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:900
|
||||
|
||||
[oti_cdrom]
|
||||
%oti_devdesc% = cdaudio_install,IDE\CdRomOTI_DOLPHIN_8001_IDE____________________
|
||||
|
||||
[pioneer_cdrom]
|
||||
%pioneer_devdesc% = cdaudio_install,SCSI\CdRomPIONEER_CD-ROM_DRM-600__
|
||||
%pioneer_devdesc% = cdaudio_install,SCSI\CdRomPIONEER_CD-ROM_DRM-600x_
|
||||
|
||||
[wearnes_cdrom]
|
||||
%wearnes_devdesc% = cdaudio_install,IDE\CdRomWEARNES_
|
||||
|
||||
|
||||
[cdrom_device]
|
||||
;;
|
||||
;; if none of the above matched, then only cdrom.sys is required for this drive
|
||||
;;
|
||||
%gencdrom_devdesc% = cdrom_install,SCSI\WormPIONEER_CD-WO_DR-R504X__
|
||||
%gencdrom_devdesc% = cdrom_install,SCSI\WormSONY____CD-R___CDU920S__
|
||||
%gencdrom_devdesc% = cdrom_install,SCSI\WormSONY____CD-R___CDU948S__
|
||||
%gencdrom_devdesc% = cdrom_install,GenCdRom
|
||||
|
||||
;;
|
||||
;; Use to add filter drivers for the device
|
||||
;;
|
||||
|
||||
[cdaudio_addreg]
|
||||
HKR,,"UpperFilters",0x00010008,"cdaudio"
|
||||
|
||||
[changer_addreg]
|
||||
HKR,,"UpperFilters",0x00010008,"changer"
|
||||
|
||||
[mitsumi_addreg]
|
||||
HKR,,"FriendlyName",,%Mitsumi_Generic_FriendlyName%
|
||||
|
||||
;;
|
||||
;; more addreg sections
|
||||
;;
|
||||
|
||||
[dvd_property_provider_AddReg]
|
||||
HKR,,EnumPropPages32,,"storprop.dll,DvdPropPageProvider"
|
||||
|
||||
[autorun_addreg]
|
||||
;;
|
||||
;; The AutoRunAlwaysDisable key is only for use when the hardware cannot
|
||||
;; accepts TEST_UNIT_READY commands. Disabling 'AutoRun' or including
|
||||
;; devices in this list will prevent removable media services from being
|
||||
;; able to properly handle these devices.
|
||||
;;
|
||||
HKLM,"System\CurrentControlSet\Services\cdrom","AutoRun",0x00010003,1
|
||||
HKLM,"System\CurrentControlSet\Services\cdrom","AutoRunAlwaysDisable",\
|
||||
0x00010000,\
|
||||
"NEC MBR-7 ", \
|
||||
"NEC MBR-7.4 ", \
|
||||
"PIONEER CHANGR DRM-1804X", \
|
||||
"PIONEER CD-ROM DRM-6324X", \
|
||||
"PIONEER CD-ROM DRM-624X ", \
|
||||
"TORiSAN CD-ROM CDR_C36"
|
||||
|
||||
;;
|
||||
;; Use to disable synchronous transfers to this device. Sync transfers will
|
||||
;; always be turned off by default in this INF for any cdrom-type device
|
||||
;;
|
||||
[nosync_addreg]
|
||||
HKR,,"DefaultRequestFlags",0x00010001,8
|
||||
|
||||
;;
|
||||
;; Installation section for cdaudio. Sets cdrom as the service and adds
|
||||
;; cdaudio as an upper filter
|
||||
;;
|
||||
|
||||
[cdaudio_install]
|
||||
CopyFiles=cdaudio_copyfiles,cdrom_copyfiles,storprop_copyfiles
|
||||
AddReg=dvd_property_provider_AddReg
|
||||
|
||||
[cdaudio_install.HW]
|
||||
AddReg=nosync_addreg,cdaudio_addreg
|
||||
|
||||
[cdaudio_install.Services]
|
||||
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection
|
||||
AddService=cdaudio,,cdaudio_ServiceInstallSection
|
||||
AddService=redbook,,redbook_ServiceInstallSection,redbook_InstallEventLogSection
|
||||
|
||||
;;
|
||||
;; Installation section for changer
|
||||
;;
|
||||
|
||||
[changer_install]
|
||||
CopyFiles=changer_copyfiles,cdrom_copyfiles,storprop_copyfiles
|
||||
AddReg=dvd_property_provider_AddReg
|
||||
|
||||
[changer_install.HW]
|
||||
AddReg=changer_addreg
|
||||
|
||||
[changer_install.Services]
|
||||
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection
|
||||
AddService=changer,,changer_ServiceInstallSection
|
||||
AddService=redbook,,redbook_ServiceInstallSection,redbook_InstallEventLogSection
|
||||
|
||||
;;
|
||||
;; Installation section for mitsumi.
|
||||
;;
|
||||
|
||||
[mitsumi_install]
|
||||
CopyFiles=cdrom_copyfiles,storprop_copyfiles
|
||||
AddReg=dvd_property_provider_AddReg
|
||||
|
||||
[mitsumi_install.HW]
|
||||
AddReg=nosync_addreg,mitsumi_addreg
|
||||
|
||||
[mitsumi_install.Services]
|
||||
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection
|
||||
AddService=redbook,,redbook_ServiceInstallSection,redbook_InstallEventLogSection
|
||||
|
||||
;;
|
||||
;; Installation section for generic cdrom.
|
||||
;;
|
||||
|
||||
[cdrom_install]
|
||||
CopyFiles=cdrom_copyfiles,storprop_copyfiles
|
||||
AddReg=dvd_property_provider_AddReg
|
||||
|
||||
[cdrom_install.HW]
|
||||
AddReg=nosync_addreg
|
||||
|
||||
[cdrom_install.Services]
|
||||
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection
|
||||
AddService=redbook,,redbook_ServiceInstallSection,redbook_InstallEventLogSection
|
||||
|
||||
;;
|
||||
;; Service install sections for cdrom and cdaudio
|
||||
;;
|
||||
|
||||
[cdrom_ServiceInstallSection]
|
||||
DisplayName = %cdrom_ServiceDesc%
|
||||
ServiceType = 1
|
||||
StartType = 1
|
||||
ErrorControl = 1
|
||||
ServiceBinary = %12%\cdrom.sys
|
||||
LoadOrderGroup = SCSI CDROM Class
|
||||
AddReg=autorun_addreg
|
||||
|
||||
[cdaudio_ServiceInstallSection]
|
||||
DisplayName = %cdaudio_ServiceDesc%
|
||||
ServiceType = 1
|
||||
StartType = 1
|
||||
ErrorControl = 1
|
||||
ServiceBinary = %12%\cdaudio.sys
|
||||
LoadOrderGroup = Pnp Filter
|
||||
|
||||
[changer_ServiceInstallSection]
|
||||
DisplayName = %changer_ServiceDesc%
|
||||
ServiceType = 1
|
||||
StartType = 1
|
||||
ErrorControl = 1
|
||||
ServiceBinary = %12%\changer.sys
|
||||
LoadOrderGroup = Pnp Filter
|
||||
|
||||
[redbook_ServiceInstallSection]
|
||||
DisplayName = %redbook_ServiceDesc%
|
||||
ServiceType = 1
|
||||
StartType = 1
|
||||
ErrorControl = 1
|
||||
ServiceBinary = %12%\redbook.sys
|
||||
LoadOrderGroup = Pnp Filter
|
||||
|
||||
[redbook_InstallEventLogSection]
|
||||
AddReg = redbook_EventLog_addreg
|
||||
|
||||
[redbook_EventLog_addreg]
|
||||
HKR,,"EventMessageFile",0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\redbook.sys"
|
||||
HKR,,"TypesSupported",0x00010001,7
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[Strings]
|
||||
DDK_SAMPLE="DDK Sample Provider"
|
||||
CDClassName = "DVD/CD-ROM drives"
|
||||
|
||||
;; Manufacturer specific strings
|
||||
ATAPI_CHGR = "Atapi 2.5 Changer Devices"
|
||||
CHINON = "Chinon"
|
||||
DENON = "Denon"
|
||||
FUJITSU = "Fujitsu"
|
||||
HITACHI = "Hitachi"
|
||||
HP = "Hewlett Packard"
|
||||
MITSUMI = "Mitsumi"
|
||||
NEC = "NEC"
|
||||
OTI = "OTI"
|
||||
PIONEER = "Pioneer"
|
||||
WEARNES = "Wearnes"
|
||||
GenManufacturer = "(Standard CD-ROM drives)"
|
||||
|
||||
;; Descriptions for enumerated brands and models
|
||||
AlpsChanger_devdesc = "Alps CD-ROM Changer"
|
||||
chinon_devdesc = "Chinon CD-ROM Drive"
|
||||
denon_devdesc = "Denon CD-ROM Drive"
|
||||
fujitsu_devdesc = "Fujitsu CD-ROM Drive"
|
||||
hp_devdesc = "Hewlett Packard CD-ROM Drive"
|
||||
hitachi_devdesc = "Hitachi CD-ROM Drive"
|
||||
Mitsumi_cdrom_devdesc = "Mitsumi CD-ROM Drive"
|
||||
NecChanger_devdesc = "NEC CD-ROM Changer"
|
||||
NecIntersect_devdesc = "NEC Intersect CD-ROM Drive"
|
||||
NecMultispin_devdesc = "NEC Multispin CD-ROM Drive"
|
||||
NecOem_devdesc = "NEC CD-ROM Drive"
|
||||
oti_devdesc = "OTI CD-ROM Drive"
|
||||
PanasonicChanger_devdesc = "Panasonic CD-ROM Changer"
|
||||
pioneer_devdesc = "Pioneer CD-ROM Drive"
|
||||
TorisanChanger_devdesc = "Torisan CD-ROM Changer"
|
||||
wearnes_devdesc = "Wearnes CD-ROM Drive"
|
||||
gencdrom_devdesc = "CD-ROM Drive"
|
||||
|
||||
;; Mitsumi Friendly name explicitly listed
|
||||
Mitsumi_Generic_FriendlyName = "Mitsumi CD-ROM Drive"
|
||||
|
||||
;; Service descriptions
|
||||
cdrom_ServiceDesc = "CD-ROM Driver"
|
||||
cdaudio_ServiceDesc = "CD-Audio Filter Driver"
|
||||
changer_ServiceDesc = "CD-Changer Filter Driver"
|
||||
redbook_ServiceDesc = "Digital CD Audio Playback Filter Driver"
|
||||
|
||||
[Strings.0418]
|
||||
DDK_SAMPLE="Mostră de producător DDK"
|
||||
CDClassName = "Dispozitive DVD/CD-ROM"
|
||||
|
||||
;; Manufacturer specific strings
|
||||
ATAPI_CHGR = "Dispozitive Atapi 2.5 Changer"
|
||||
|
||||
GenManufacturer = "(Dispozitive CD-ROM standard)"
|
||||
|
||||
;; Descriptions for enumerated brands and models
|
||||
AlpsChanger_devdesc = "Dispozitiv CD-ROM-multiple Alps"
|
||||
chinon_devdesc = "Dispozitiv CD-ROM Chinon"
|
||||
denon_devdesc = "Dispozitiv Denon"
|
||||
fujitsu_devdesc = "Dispozitiv Fujitsu"
|
||||
hp_devdesc = "Dispozitiv CD-ROM Hewlett Packard"
|
||||
hitachi_devdesc = "Dispozitiv CD-ROM Hitachi"
|
||||
Mitsumi_cdrom_devdesc = "Dispozitiv CD-ROM Mitsumi"
|
||||
NecChanger_devdesc = "Dispozitiv CD-ROM-multiple NEC"
|
||||
NecIntersect_devdesc = "Dispozitiv CD-ROM NEC Intersect"
|
||||
NecMultispin_devdesc = "Dispozitiv CD-ROM NEC Multispin"
|
||||
NecOem_devdesc = "Dispozitiv CD-ROM NEC"
|
||||
oti_devdesc = "Dispozitiv CD-ROM OTI"
|
||||
PanasonicChanger_devdesc = "Dispozitiv CD-ROM-multiple Panasonic"
|
||||
pioneer_devdesc = "Dispozitiv CD-ROM Pioneer"
|
||||
TorisanChanger_devdesc = "Dispozitiv CD-ROM-multiple Torisan"
|
||||
wearnes_devdesc = "Dispozitiv CD-ROM Wearnes"
|
||||
gencdrom_devdesc = "Dispozitiv CD-ROM"
|
||||
|
||||
;; Mitsumi Friendly name explictly listed
|
||||
Mitsumi_Generic_FriendlyName = "Dispozitiv CD-ROM Mitsumi"
|
||||
|
||||
;; Service descriptions
|
||||
cdrom_ServiceDesc = "Modúl-pilot CD-ROM"
|
||||
cdaudio_ServiceDesc = "Modúl-pilot filtru CD-Audio"
|
||||
changer_ServiceDesc = "Modúl-pilot filtru multi-CD"
|
||||
redbook_ServiceDesc = "Modúl-pilot filtru pentru CD audio digital"
|
|
@ -1,97 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "cdrom.h"
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("PAGE")
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
#define CDROM_HACK_DEC_RRD (0x00000001)
|
||||
#define CDROM_HACK_FUJITSU_FMCD_10x (0x00000002)
|
||||
#define CDROM_HACK_HITACHI_1750 (0x00000004)
|
||||
#define CDROM_HACK_HITACHI_GD_2000 (0x00000008)
|
||||
#define CDROM_HACK_TOSHIBA_SD_W1101 (0x00000010)
|
||||
#define CDROM_HACK_TOSHIBA_XM_3xx (0x00000020)
|
||||
#define CDROM_HACK_NEC_CDDA (0x00000040)
|
||||
#define CDROM_HACK_PLEXTOR_CDDA (0x00000080)
|
||||
#define CDROM_HACK_BAD_GET_CONFIG_SUPPORT (0x00000100)
|
||||
#define CDROM_HACK_FORCE_READ_CD_DETECTION (0x00000200)
|
||||
#define CDROM_HACK_READ_CD_SUPPORTED (0x00000400)
|
||||
|
||||
*/
|
||||
|
||||
CLASSPNP_SCAN_FOR_SPECIAL_INFO CdromHackItems[] = {
|
||||
// digital put out drives using 512 byte block sizes,
|
||||
// and needed us to send a mode page to set the sector
|
||||
// size back to 2048.
|
||||
{ "DEC" , "RRD" , NULL, 0x0001 },
|
||||
// these fujitsu drives take longer than ten seconds to
|
||||
// timeout commands when audio discs are placed in them
|
||||
{ "FUJITSU" , "FMCD-101" , NULL, 0x0002 },
|
||||
{ "FUJITSU" , "FMCD-102" , NULL, 0x0002 },
|
||||
// these hitachi drives don't work properly in PIO mode
|
||||
{ "HITACHI ", "CDR-1750S" , NULL, 0x0004 },
|
||||
{ "HITACHI ", "CDR-3650/1650S" , NULL, 0x0004 },
|
||||
// this particular gem doesn't automatically spin up
|
||||
// on some media access commands.
|
||||
{ "" , "HITACHI GD-2000" , NULL, 0x0008 },
|
||||
{ "" , "HITACHI DVD-ROM GD-2000" , NULL, 0x0008 },
|
||||
// this particular drive doesn't support DVD playback.
|
||||
// just print an error message in CHK builds.
|
||||
{ "TOSHIBA ", "SD-W1101 DVD-RAM" , NULL, 0x0010 },
|
||||
// not sure what this device's issue was. seems to
|
||||
// require mode selects at various times.
|
||||
{ "TOSHIBA ", "CD-ROM XM-3" , NULL, 0x0020 },
|
||||
// NEC defined a "READ_CD" type command before there was
|
||||
// a standard, so fall back on this as an option.
|
||||
{ "NEC" , "" , NULL, 0x0040 },
|
||||
// plextor defined a "READ_CD" type command before there was
|
||||
// a standard, so fall back on this as an option.
|
||||
{ "PLEXTOR ", "" , NULL, 0x0080 },
|
||||
// this drive times out and sometimes disappears from the bus
|
||||
// when send GET_CONFIGURATION commands. don't send them.
|
||||
{ "" , "LG DVD-ROM DRD-840B" , NULL, 0x0100 },
|
||||
{ "" , "SAMSUNG DVD-ROM SD-608" , NULL, 0x0300 },
|
||||
// these drives should have supported READ_CD, but at least
|
||||
// some firmware revisions did not. force READ_CD detection.
|
||||
{ "" , "SAMSUNG DVD-ROM SD-" , NULL, 0x2000 },
|
||||
// the mitsumi drive below doesn't follow the block-only spec,
|
||||
// and we end up hanging when sending it commands it doesn't
|
||||
// understand. this causes complications later, also.
|
||||
{ "MITSUMI ", "CR-4802TE " , NULL, 0x0100 },
|
||||
// some drives return various funky errors (such as 3/2/0 NO_SEEK_COMPLETE)
|
||||
// during the detection of READ_CD support, resulting in iffy detection.
|
||||
// since they probably don't support mode switching, which is really old
|
||||
// legacy stuff anyways, the ability to read digitally is lost when
|
||||
// these drives return unexpected error codes. note: MMC compliant drives
|
||||
// are presumed to support READ_CD, as are DVD drives, and anything
|
||||
// connected to a bus type other than IDE or SCSI, and therefore don't
|
||||
// need to be here.
|
||||
{ "YAMAHA ", "CRW8424S " , NULL, 0x0400 },
|
||||
// and finally, a place to finish the list. :)
|
||||
{ NULL , NULL , NULL, 0x0000 }
|
||||
};
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg()
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,23 +0,0 @@
|
|||
//+-------------------------------------------------------------------------
|
||||
//
|
||||
// Microsoft Windows
|
||||
//
|
||||
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||||
//
|
||||
// File: scsicdrm.rc
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_DRV
|
||||
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
|
||||
#define VER_FILEDESCRIPTION_STR "SCSI CD-ROM Driver"
|
||||
#define VER_INTERNALNAME_STR "cdrom.sys"
|
||||
#define VER_ORIGINALFILENAME_STR "cdrom.sys"
|
||||
#define VER_LANGNEUTRAL
|
||||
|
||||
#include "common.ver"
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/*--
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1999
|
||||
|
||||
--*/
|
||||
|
||||
#include "cdrom.h"
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomGetRpc0Settings(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
|
||||
PCDROM_DATA cddata = (PCDROM_DATA)(commonExtension->DriverData);
|
||||
|
||||
cddata->Rpc0SystemRegion = (UCHAR)(~1); // region one
|
||||
cddata->Rpc0SystemRegionResetCount = 0; // no resets
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CdRomSetRpc0Settings(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN UCHAR NewRegion
|
||||
)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
|
||||
WPP_DEFINE_CONTROL_GUID specifies the GUID used for this filter.
|
||||
*** REPLACE THE GUID WITH YOUR OWN UNIQUE ID ***
|
||||
WPP_DEFINE_BIT allows setting debug bit masks to selectively print.
|
||||
|
||||
everything else can revert to the default?
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define TraceLogger(x, ...) DbgPrint(__VA_ARGS__)
|
||||
#define TraceLog(x) TraceLogger x
|
||||
#define WPP_INIT_TRACING(x, y)
|
||||
#define WPP_CLEANUP(x)
|
||||
|
||||
#define WPP_CONTROL_GUIDS \
|
||||
WPP_DEFINE_CONTROL_GUID(Cdrom,(58db8e03,0537,45cb,b29b,597f6cbebbfd), \
|
||||
WPP_DEFINE_BIT(CdromDebugError) /* bit 0 = 0x00000001 */ \
|
||||
WPP_DEFINE_BIT(CdromDebugWarning) /* bit 1 = 0x00000002 */ \
|
||||
WPP_DEFINE_BIT(CdromDebugTrace) /* bit 2 = 0x00000004 */ \
|
||||
WPP_DEFINE_BIT(CdromDebugInfo) /* bit 3 = 0x00000008 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD04) /* bit 4 = 0x00000010 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD05) /* bit 5 = 0x00000020 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD06) /* bit 6 = 0x00000040 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD07) /* bit 7 = 0x00000080 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD08) /* bit 8 = 0x00000100 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD09) /* bit 9 = 0x00000200 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD10) /* bit 10 = 0x00000400 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD11) /* bit 11 = 0x00000800 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD12) /* bit 12 = 0x00001000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD13) /* bit 13 = 0x00002000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD14) /* bit 14 = 0x00004000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD15) /* bit 15 = 0x00008000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD16) /* bit 16 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD17) /* bit 17 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD18) /* bit 18 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD19) /* bit 19 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD20) /* bit 20 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD21) /* bit 21 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD22) /* bit 22 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD23) /* bit 23 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD24) /* bit 24 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD25) /* bit 25 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD26) /* bit 26 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD27) /* bit 27 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD28) /* bit 28 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(FilterDebugD29) /* bit 29 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(CdromSecError) /* bit 30 = 0x00000000 */ \
|
||||
WPP_DEFINE_BIT(CdromSecInfo) /* bit 31 = 0x00000000 */ \
|
||||
)
|
|
@ -1,42 +0,0 @@
|
|||
|
||||
include_directories(../../inc)
|
||||
spec2def(classpnp.sys classpnp.spec ADD_IMPORTLIB)
|
||||
|
||||
add_definitions(
|
||||
-DCLASS_GLOBAL_BREAK_ON_LOST_IRPS=0
|
||||
-DCLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB=100
|
||||
-DCLASS_GLOBAL_USE_DELAYED_RETRY=1
|
||||
-DCLASS_GLOBAL_BUFFERED_DEBUG_PRINT=0
|
||||
-DCLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE=512
|
||||
-DCLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS=512)
|
||||
|
||||
list(APPEND SOURCE
|
||||
autorun.c
|
||||
class.c
|
||||
classwmi.c
|
||||
clntirp.c
|
||||
create.c
|
||||
data.c
|
||||
debug.c
|
||||
dictlib.c
|
||||
lock.c
|
||||
obsolete.c
|
||||
power.c
|
||||
retry.c
|
||||
utils.c
|
||||
xferpkt.c)
|
||||
|
||||
list(APPEND PCH_SKIP_SOURCE
|
||||
guid.c)
|
||||
|
||||
add_library(classpnp MODULE
|
||||
${SOURCE}
|
||||
${PCH_SKIP_SOURCE}
|
||||
class.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/classpnp.def)
|
||||
|
||||
add_pch(classpnp classp.h "${PCH_SKIP_SOURCE}")
|
||||
target_link_libraries(classpnp ${PSEH_LIB} libcntpr)
|
||||
set_module_type(classpnp kernelmodedriver)
|
||||
add_importlibs(classpnp hal ntoskrnl)
|
||||
add_cd_file(TARGET classpnp DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,23 +0,0 @@
|
|||
//+-------------------------------------------------------------------------
|
||||
//
|
||||
// Microsoft Windows
|
||||
//
|
||||
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||||
//
|
||||
// File: class.rc
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_DRV
|
||||
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
|
||||
#define VER_FILEDESCRIPTION_STR "SCSI Class System Dll"
|
||||
#define VER_INTERNALNAME_STR "Classpnp.sys"
|
||||
#define VER_ORIGINALFILENAME_STR "Classpnp.sys"
|
||||
#define VER_LANGNEUTRAL
|
||||
|
||||
#include "common.ver"
|
||||
|
|
@ -1,872 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
classp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Private header file for classpnp.sys modules. This contains private
|
||||
structure and function declarations as well as constant values which do
|
||||
not need to be exported.
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _CLASSPNP_PCH_
|
||||
#define _CLASSPNP_PCH_
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <classpnp.h>
|
||||
#include <ioevent.h>
|
||||
#include <pseh/pseh2.h>
|
||||
|
||||
extern CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[];
|
||||
|
||||
extern GUID ClassGuidQueryRegInfoEx;
|
||||
|
||||
|
||||
#define CLASSP_REG_SUBKEY_NAME (L"Classpnp")
|
||||
|
||||
#define CLASSP_REG_HACK_VALUE_NAME (L"HackMask")
|
||||
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME (L"MMCDetectionState")
|
||||
#define CLASSP_REG_WRITE_CACHE_VALUE_NAME (L"WriteCacheEnableOverride")
|
||||
#define CLASSP_REG_PERF_RESTORE_VALUE_NAME (L"RestorePerfAtCount")
|
||||
#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME (L"UserRemovalPolicy")
|
||||
|
||||
#define CLASS_PERF_RESTORE_MINIMUM (0x10)
|
||||
#define CLASS_ERROR_LEVEL_1 (0x4)
|
||||
#define CLASS_ERROR_LEVEL_2 (0x8)
|
||||
|
||||
#define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001)
|
||||
#define FDO_HACK_GESN_IS_BAD (0x00000002)
|
||||
#define FDO_HACK_NO_SYNC_CACHE (0x00000004)
|
||||
|
||||
#define FDO_HACK_VALID_FLAGS (0x00000007)
|
||||
#define FDO_HACK_INVALID_FLAGS (~FDO_HACK_VALID_FLAGS)
|
||||
|
||||
/*
|
||||
* Lots of retries of synchronized SCSI commands that devices may not
|
||||
* even support really slows down the system (especially while booting).
|
||||
* (Even GetDriveCapacity may be failed on purpose if an external disk is powered off).
|
||||
* If a disk cannot return a small initialization buffer at startup
|
||||
* in two attempts (with delay interval) then we cannot expect it to return
|
||||
* data consistently with four retries.
|
||||
* So don't set the retry counts as high here as for data SRBs.
|
||||
*
|
||||
* If we find that these requests are failing consecutively,
|
||||
* despite the retry interval, on otherwise reliable media,
|
||||
* then we should either increase the retry interval for
|
||||
* that failure or (by all means) increase these retry counts as appropriate.
|
||||
*/
|
||||
#define NUM_LOCKMEDIAREMOVAL_RETRIES 1
|
||||
#define NUM_MODESENSE_RETRIES 1
|
||||
#define NUM_DRIVECAPACITY_RETRIES 1
|
||||
|
||||
|
||||
#define CLASS_FILE_OBJECT_EXTENSION_KEY 'eteP'
|
||||
#define CLASSP_VOLUME_VERIFY_CHECKED 0x34
|
||||
|
||||
#define CLASS_TAG_PRIVATE_DATA 'CPcS'
|
||||
#define CLASS_TAG_PRIVATE_DATA_FDO 'FPcS'
|
||||
#define CLASS_TAG_PRIVATE_DATA_PDO 'PPcS'
|
||||
|
||||
struct _MEDIA_CHANGE_DETECTION_INFO {
|
||||
|
||||
//
|
||||
// Mutex to synchronize enable/disable requests and media state changes
|
||||
//
|
||||
|
||||
KMUTEX MediaChangeMutex;
|
||||
|
||||
//
|
||||
// The current state of the media (present, not present, unknown)
|
||||
// protected by MediaChangeSynchronizationEvent
|
||||
//
|
||||
|
||||
MEDIA_CHANGE_DETECTION_STATE MediaChangeDetectionState;
|
||||
|
||||
//
|
||||
// This is a count of how many time MCD has been disabled. if it is
|
||||
// set to zero, then we'll poll the device for MCN events with the
|
||||
// then-current method (ie. TEST UNIT READY or GESN). this is
|
||||
// protected by MediaChangeMutex
|
||||
//
|
||||
|
||||
LONG MediaChangeDetectionDisableCount;
|
||||
|
||||
|
||||
//
|
||||
// The timer value to support media change events. This is a countdown
|
||||
// value used to determine when to poll the device for a media change.
|
||||
// The max value for the timer is 255 seconds. This is not protected
|
||||
// by an event -- simply InterlockedExchanged() as needed.
|
||||
//
|
||||
|
||||
LONG MediaChangeCountDown;
|
||||
|
||||
//
|
||||
// recent changes allowed instant retries of the MCN irp. Since this
|
||||
// could cause an infinite loop, keep a count of how many times we've
|
||||
// retried immediately so that we can catch if the count exceeds an
|
||||
// arbitrary limit.
|
||||
//
|
||||
|
||||
LONG MediaChangeRetryCount;
|
||||
|
||||
//
|
||||
// use GESN if it's available
|
||||
//
|
||||
|
||||
struct {
|
||||
BOOLEAN Supported;
|
||||
BOOLEAN HackEventMask;
|
||||
UCHAR EventMask;
|
||||
UCHAR NoChangeEventMask;
|
||||
PUCHAR Buffer;
|
||||
PMDL Mdl;
|
||||
ULONG BufferSize;
|
||||
} Gesn;
|
||||
|
||||
//
|
||||
// If this value is one, then the irp is currently in use.
|
||||
// If this value is zero, then the irp is available.
|
||||
// Use InterlockedCompareExchange() to set from "available" to "in use".
|
||||
// ASSERT that InterlockedCompareExchange() showed previous value of
|
||||
// "in use" when changing back to "available" state.
|
||||
// This also implicitly protects the MediaChangeSrb and SenseBuffer
|
||||
//
|
||||
|
||||
LONG MediaChangeIrpInUse;
|
||||
|
||||
//
|
||||
// Pointer to the irp to be used for media change detection.
|
||||
// protected by Interlocked MediaChangeIrpInUse
|
||||
//
|
||||
|
||||
PIRP MediaChangeIrp;
|
||||
|
||||
//
|
||||
// The srb for the media change detection.
|
||||
// protected by Interlocked MediaChangeIrpInUse
|
||||
//
|
||||
|
||||
SCSI_REQUEST_BLOCK MediaChangeSrb;
|
||||
PUCHAR SenseBuffer;
|
||||
ULONG SrbFlags;
|
||||
|
||||
//
|
||||
// Second timer to keep track of how long the media change IRP has been
|
||||
// in use. If this value exceeds the timeout (#defined) then we should
|
||||
// print out a message to the user and set the MediaChangeIrpLost flag
|
||||
// protected by using Interlocked() operations in ClasspSendMediaStateIrp,
|
||||
// the only routine which should modify this value.
|
||||
//
|
||||
|
||||
LONG MediaChangeIrpTimeInUse;
|
||||
|
||||
//
|
||||
// Set by CdRomTickHandler when we determine that the media change irp has
|
||||
// been lost
|
||||
//
|
||||
|
||||
BOOLEAN MediaChangeIrpLost;
|
||||
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SimpleMediaLock,
|
||||
SecureMediaLock,
|
||||
InternalMediaLock
|
||||
} MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE;
|
||||
|
||||
typedef struct _FAILURE_PREDICTION_INFO {
|
||||
FAILURE_PREDICTION_METHOD Method;
|
||||
ULONG CountDown; // Countdown timer
|
||||
ULONG Period; // Countdown period
|
||||
|
||||
PIO_WORKITEM WorkQueueItem;
|
||||
|
||||
KEVENT Event;
|
||||
} FAILURE_PREDICTION_INFO, *PFAILURE_PREDICTION_INFO;
|
||||
|
||||
|
||||
|
||||
//
|
||||
// This struct must always fit within four PVOIDs of info,
|
||||
// as it uses the irp's "PVOID DriverContext[4]" to store
|
||||
// this info
|
||||
//
|
||||
typedef struct _CLASS_RETRY_INFO {
|
||||
struct _CLASS_RETRY_INFO *Next;
|
||||
} CLASS_RETRY_INFO, *PCLASS_RETRY_INFO;
|
||||
|
||||
|
||||
|
||||
typedef struct _CSCAN_LIST {
|
||||
|
||||
//
|
||||
// The current block which has an outstanding request.
|
||||
//
|
||||
|
||||
ULONGLONG BlockNumber;
|
||||
|
||||
//
|
||||
// The list of blocks past the CurrentBlock to which we're going to do
|
||||
// i/o. This list is maintained in sorted order.
|
||||
//
|
||||
|
||||
LIST_ENTRY CurrentSweep;
|
||||
|
||||
//
|
||||
// The list of blocks behind the current block for which we'll have to
|
||||
// wait until the next scan across the disk. This is kept as a stack,
|
||||
// the cost of sorting it is taken when it's moved over to be the
|
||||
// running list.
|
||||
//
|
||||
|
||||
LIST_ENTRY NextSweep;
|
||||
|
||||
} CSCAN_LIST, *PCSCAN_LIST;
|
||||
|
||||
//
|
||||
// add to the front of this structure to help prevent illegal
|
||||
// snooping by other utilities.
|
||||
//
|
||||
|
||||
|
||||
|
||||
typedef enum _CLASS_DETECTION_STATE {
|
||||
ClassDetectionUnknown = 0,
|
||||
ClassDetectionUnsupported = 1,
|
||||
ClassDetectionSupported = 2
|
||||
} CLASS_DETECTION_STATE, *PCLASS_DETECTION_STATE;
|
||||
|
||||
|
||||
typedef struct _CLASS_ERROR_LOG_DATA {
|
||||
LARGE_INTEGER TickCount; // Offset 0x00
|
||||
ULONG PortNumber; // Offset 0x08
|
||||
|
||||
UCHAR ErrorPaging : 1; // Offset 0x0c
|
||||
UCHAR ErrorRetried : 1;
|
||||
UCHAR ErrorUnhandled : 1;
|
||||
UCHAR ErrorReserved : 5;
|
||||
|
||||
UCHAR Reserved[3];
|
||||
|
||||
SCSI_REQUEST_BLOCK Srb; // Offset 0x10
|
||||
|
||||
/*
|
||||
* We define the SenseData as the default length.
|
||||
* Since the sense data returned by the port driver may be longer,
|
||||
* SenseData must be at the end of this structure.
|
||||
* For our internal error log, we only log the default length.
|
||||
*/
|
||||
SENSE_DATA SenseData; // Offset 0x50 for x86 (or 0x68 for ia64) (ULONG32 Alignment required!)
|
||||
} CLASS_ERROR_LOG_DATA, *PCLASS_ERROR_LOG_DATA;
|
||||
|
||||
#define NUM_ERROR_LOG_ENTRIES 16
|
||||
|
||||
|
||||
|
||||
typedef struct _TRANSFER_PACKET {
|
||||
|
||||
SLIST_ENTRY SlistEntry; // for when in free list (use fast slist)
|
||||
LIST_ENTRY AllPktsListEntry; // entry in fdoData's static AllTransferPacketsList
|
||||
|
||||
PIRP Irp;
|
||||
PDEVICE_OBJECT Fdo;
|
||||
|
||||
/*
|
||||
* This is the client IRP that this TRANSFER_PACKET is currently
|
||||
* servicing.
|
||||
*/
|
||||
PIRP OriginalIrp;
|
||||
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes;
|
||||
|
||||
/*
|
||||
* Stuff for retrying the transfer.
|
||||
*/
|
||||
ULONG NumRetries;
|
||||
KTIMER RetryTimer;
|
||||
KDPC RetryTimerDPC;
|
||||
ULONG RetryIntervalSec;
|
||||
|
||||
/*
|
||||
* Event for synchronizing the transfer (optional).
|
||||
* (Note that we can't have the event in the packet itself because
|
||||
* by the time a thread waits on an event the packet may have
|
||||
* been completed and re-issued.
|
||||
*/
|
||||
PKEVENT SyncEventPtr;
|
||||
|
||||
/*
|
||||
* Stuff for retrying during extreme low-memory stress
|
||||
* (when we retry 1 page at a time).
|
||||
*/
|
||||
BOOLEAN InLowMemRetry;
|
||||
PUCHAR LowMemRetry_remainingBufPtr;
|
||||
ULONG LowMemRetry_remainingBufLen;
|
||||
LARGE_INTEGER LowMemRetry_nextChunkTargetLocation;
|
||||
|
||||
/*
|
||||
* Fields used for cancelling the packet.
|
||||
*/
|
||||
// BOOLEAN Cancelled;
|
||||
// KEVENT CancelledEvent;
|
||||
|
||||
/*
|
||||
* We keep the buffer and length values here as well
|
||||
* as in the SRB because some miniports return
|
||||
* the transferred length in SRB.DataTransferLength,
|
||||
* and if the SRB failed we need that value again for the retry.
|
||||
* We don't trust the lower stack to preserve any of these values in the SRB.
|
||||
*/
|
||||
PUCHAR BufPtrCopy;
|
||||
ULONG BufLenCopy;
|
||||
LARGE_INTEGER TargetLocationCopy;
|
||||
|
||||
/*
|
||||
* This is a standard SCSI structure that receives a detailed
|
||||
* report about a SCSI error on the hardware.
|
||||
*/
|
||||
SENSE_DATA SrbErrorSenseData;
|
||||
|
||||
/*
|
||||
* This is the SRB block for this TRANSFER_PACKET.
|
||||
* For IOCTLs, the SRB block includes two DWORDs for
|
||||
* device object and ioctl code; so these must
|
||||
* immediately follow the SRB block.
|
||||
*/
|
||||
SCSI_REQUEST_BLOCK Srb;
|
||||
// ULONG SrbIoctlDevObj; // not handling ioctls yet
|
||||
// ULONG SrbIoctlCode;
|
||||
|
||||
} TRANSFER_PACKET, *PTRANSFER_PACKET;
|
||||
|
||||
/*
|
||||
* MIN_INITIAL_TRANSFER_PACKETS is the minimum number of packets that
|
||||
* we preallocate at startup for each device (we need at least one packet
|
||||
* to guarantee forward progress during memory stress).
|
||||
* MIN_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
|
||||
* we allow to build up and remain for each device;
|
||||
* we _lazily_ work down to this number when they're not needed.
|
||||
* MAX_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
|
||||
* that we _immediately_ reduce to when they are not needed.
|
||||
*
|
||||
* The absolute maximum number of packets that we will allocate is
|
||||
* whatever is required by the current activity, up to the memory limit;
|
||||
* as soon as stress ends, we snap down to MAX_WORKINGSET_TRANSFER_PACKETS;
|
||||
* we then lazily work down to MIN_WORKINGSET_TRANSFER_PACKETS.
|
||||
*/
|
||||
#define MIN_INITIAL_TRANSFER_PACKETS 1
|
||||
#define MIN_WORKINGSET_TRANSFER_PACKETS_Consumer 4
|
||||
#define MAX_WORKINGSET_TRANSFER_PACKETS_Consumer 64
|
||||
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server 64
|
||||
#define MAX_WORKINGSET_TRANSFER_PACKETS_Server 1024
|
||||
#define MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise 256
|
||||
#define MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise 2048
|
||||
|
||||
|
||||
//
|
||||
// add to the front of this structure to help prevent illegal
|
||||
// snooping by other utilities.
|
||||
//
|
||||
struct _CLASS_PRIVATE_FDO_DATA {
|
||||
|
||||
//
|
||||
// this private structure allows us to
|
||||
// dynamically re-enable the perf benefits
|
||||
// lost due to transient error conditions.
|
||||
// in w2k, a reboot was required. :(
|
||||
//
|
||||
struct {
|
||||
ULONG OriginalSrbFlags;
|
||||
ULONG SuccessfulIO;
|
||||
ULONG ReEnableThreshold; // 0 means never
|
||||
} Perf;
|
||||
|
||||
ULONG_PTR HackFlags;
|
||||
|
||||
STORAGE_HOTPLUG_INFO HotplugInfo;
|
||||
|
||||
// Legacy. Still used by obsolete legacy code.
|
||||
struct {
|
||||
LARGE_INTEGER Delta; // in ticks
|
||||
LARGE_INTEGER Tick; // when it should fire
|
||||
PCLASS_RETRY_INFO ListHead; // singly-linked list
|
||||
ULONG Granularity; // static
|
||||
KSPIN_LOCK Lock; // protective spin lock
|
||||
KDPC Dpc; // DPC routine object
|
||||
KTIMER Timer; // timer to fire DPC
|
||||
} Retry;
|
||||
|
||||
BOOLEAN TimerStarted;
|
||||
BOOLEAN LoggedTURFailureSinceLastIO;
|
||||
|
||||
//
|
||||
// privately allocated release queue irp
|
||||
// protected by fdoExtension->ReleaseQueueSpinLock
|
||||
//
|
||||
BOOLEAN ReleaseQueueIrpAllocated;
|
||||
PIRP ReleaseQueueIrp;
|
||||
|
||||
/*
|
||||
* Queues for TRANSFER_PACKETs that contextualize the IRPs and SRBs
|
||||
* that we send down to the port driver.
|
||||
* (The free list is an slist so that we can use fast
|
||||
* interlocked operations on it; but the relatively-static
|
||||
* AllTransferPacketsList list has to be
|
||||
* a doubly-linked list since we have to dequeue from the middle).
|
||||
*/
|
||||
LIST_ENTRY AllTransferPacketsList;
|
||||
SLIST_HEADER FreeTransferPacketsList;
|
||||
ULONG NumFreeTransferPackets;
|
||||
ULONG NumTotalTransferPackets;
|
||||
ULONG DbgPeakNumTransferPackets;
|
||||
|
||||
/*
|
||||
* Queue for deferred client irps
|
||||
*/
|
||||
LIST_ENTRY DeferredClientIrpList;
|
||||
|
||||
/*
|
||||
* Precomputed maximum transfer length for the hardware.
|
||||
*/
|
||||
ULONG HwMaxXferLen;
|
||||
|
||||
/*
|
||||
* SCSI_REQUEST_BLOCK template preconfigured with the constant values.
|
||||
* This is slapped into the SRB in the TRANSFER_PACKET for each transfer.
|
||||
*/
|
||||
SCSI_REQUEST_BLOCK SrbTemplate;
|
||||
|
||||
KSPIN_LOCK SpinLock;
|
||||
|
||||
/*
|
||||
* Circular array of timestamped logs of errors that occurred on this device.
|
||||
*/
|
||||
ULONG ErrorLogNextIndex;
|
||||
CLASS_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES];
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
|
||||
#define NOT_READY_RETRY_INTERVAL 10
|
||||
#define MINIMUM_RETRY_UNITS ((LONGLONG)32)
|
||||
|
||||
|
||||
/*
|
||||
* Simple singly-linked-list queuing macros, with no synchronization.
|
||||
*/
|
||||
static inline VOID SimpleInitSlistHdr(SLIST_ENTRY *SListHdr)
|
||||
{
|
||||
SListHdr->Next = NULL;
|
||||
}
|
||||
static inline VOID SimplePushSlist(SLIST_ENTRY *SListHdr, SLIST_ENTRY *SListEntry)
|
||||
{
|
||||
SListEntry->Next = SListHdr->Next;
|
||||
SListHdr->Next = SListEntry;
|
||||
}
|
||||
static inline SLIST_ENTRY *SimplePopSlist(SLIST_ENTRY *SListHdr)
|
||||
{
|
||||
SLIST_ENTRY *sListEntry = SListHdr->Next;
|
||||
if (sListEntry){
|
||||
SListHdr->Next = sListEntry->Next;
|
||||
sListEntry->Next = NULL;
|
||||
}
|
||||
return sListEntry;
|
||||
}
|
||||
static inline BOOLEAN SimpleIsSlistEmpty(SLIST_ENTRY *SListHdr)
|
||||
{
|
||||
return (SListHdr->Next == NULL);
|
||||
}
|
||||
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
DRIVER_UNLOAD ClassUnload;
|
||||
|
||||
DRIVER_DISPATCH ClassCreateClose;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspCreateClose(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspCleanupProtectedLocks(
|
||||
IN PFILE_OBJECT_EXTENSION FsContext
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspEjectionControl(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN PIRP Irp,
|
||||
IN MEDIA_LOCK_TYPE LockType,
|
||||
IN BOOLEAN Lock
|
||||
);
|
||||
|
||||
DRIVER_DISPATCH ClassReadWrite;
|
||||
|
||||
DRIVER_DISPATCH ClassDeviceControlDispatch;
|
||||
|
||||
DRIVER_DISPATCH ClassDispatchPnp;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassPnpStartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassShutdownFlush(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
DRIVER_DISPATCH ClassSystemControl;
|
||||
|
||||
//
|
||||
// Class internal routines
|
||||
//
|
||||
|
||||
DRIVER_ADD_DEVICE ClassAddDevice;
|
||||
|
||||
IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion;
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
RetryRequest(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PSCSI_REQUEST_BLOCK Srb,
|
||||
BOOLEAN Associated,
|
||||
ULONG RetryInterval
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassIoCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassPnpQueryFdoRelations(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassRetrieveDeviceRelations(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN DEVICE_RELATION_TYPE RelationType,
|
||||
OUT PDEVICE_RELATIONS *DeviceRelations
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassGetPdoId(
|
||||
IN PDEVICE_OBJECT Pdo,
|
||||
IN BUS_QUERY_ID_TYPE IdType,
|
||||
IN PUNICODE_STRING IdString
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassQueryPnpCapabilities(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN PDEVICE_CAPABILITIES Capabilities
|
||||
);
|
||||
|
||||
DRIVER_STARTIO ClasspStartIo;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspPagingNotificationCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PDEVICE_OBJECT RealDeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspMediaChangeCompletion(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID Context
|
||||
);
|
||||
|
||||
PFILE_OBJECT_EXTENSION
|
||||
NTAPI
|
||||
ClasspGetFsContext(
|
||||
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
|
||||
IN PFILE_OBJECT FileObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspMcnControl(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PIRP Irp,
|
||||
IN PSCSI_REQUEST_BLOCK Srb
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspRegisterMountedDeviceInterface(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspDisableTimer(
|
||||
PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspEnableTimer(
|
||||
PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
//
|
||||
// routines for dictionary list support
|
||||
//
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
InitializeDictionary(
|
||||
IN PDICTIONARY Dictionary
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
TestDictionarySignature(
|
||||
IN PDICTIONARY Dictionary
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
AllocateDictionaryEntry(
|
||||
IN PDICTIONARY Dictionary,
|
||||
IN ULONGLONG Key,
|
||||
IN ULONG Size,
|
||||
IN ULONG Tag,
|
||||
OUT PVOID *Entry
|
||||
);
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
GetDictionaryEntry(
|
||||
IN PDICTIONARY Dictionary,
|
||||
IN ULONGLONG Key
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
FreeDictionaryEntry(
|
||||
IN PDICTIONARY Dictionary,
|
||||
IN PVOID Entry
|
||||
);
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspAllocateReleaseRequest(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspFreeReleaseRequest(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion;
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspReleaseQueue(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP ReleaseQueueIrp
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspDisablePowerNotification(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
//
|
||||
// class power routines
|
||||
//
|
||||
|
||||
DRIVER_DISPATCH ClassDispatchPower;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassMinimalPowerHandler(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
//
|
||||
// Child list routines
|
||||
//
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClassAddChild(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
|
||||
IN PPHYSICAL_DEVICE_EXTENSION Child,
|
||||
IN BOOLEAN AcquireLock
|
||||
);
|
||||
|
||||
PPHYSICAL_DEVICE_EXTENSION
|
||||
NTAPI
|
||||
ClassRemoveChild(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
|
||||
IN PPHYSICAL_DEVICE_EXTENSION Child,
|
||||
IN BOOLEAN AcquireLock
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspRetryDpcTimer(
|
||||
IN PCLASS_PRIVATE_FDO_DATA FdoData
|
||||
);
|
||||
|
||||
KDEFERRED_ROUTINE ClasspRetryRequestDpc;
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClassFreeOrReuseSrb(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PSCSI_REQUEST_BLOCK Srb
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClassRetryRequest(
|
||||
IN PDEVICE_OBJECT SelfDeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN LARGE_INTEGER TimeDelta100ns // in 100ns units
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspBuildRequestEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN PIRP Irp,
|
||||
IN PSCSI_REQUEST_BLOCK Srb
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspAllocateReleaseQueueIrp(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspInitializeGesn(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PMEDIA_CHANGE_DETECTION_INFO Info
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspSendNotification(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN const GUID * Guid,
|
||||
IN ULONG ExtraDataSize,
|
||||
IN PVOID ExtraData
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClassSendEjectionNotification(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspScanForSpecialInRegistry(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspScanForClassHacks(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN ULONG_PTR Data
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspInitializeHotplugInfo(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspPerfIncrementErrorCount(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspPerfIncrementSuccessfulIo(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
PTRANSFER_PACKET NTAPI NewTransferPacket(PDEVICE_OBJECT Fdo);
|
||||
VOID NTAPI DestroyTransferPacket(PTRANSFER_PACKET Pkt);
|
||||
VOID NTAPI EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt);
|
||||
PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded);
|
||||
VOID NTAPI SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp);
|
||||
VOID NTAPI SubmitTransferPacket(PTRANSFER_PACKET Pkt);
|
||||
NTSTATUS NTAPI TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context);
|
||||
VOID NTAPI ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp);
|
||||
VOID NTAPI TransferPacketRetryTimerDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
||||
BOOLEAN NTAPI InterpretTransferPacketError(PTRANSFER_PACKET Pkt);
|
||||
BOOLEAN NTAPI RetryTransferPacket(PTRANSFER_PACKET Pkt);
|
||||
VOID NTAPI EnqueueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp);
|
||||
PIRP NTAPI DequeueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData);
|
||||
VOID NTAPI InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation);
|
||||
BOOLEAN NTAPI StepLowMemRetry(PTRANSFER_PACKET Pkt);
|
||||
VOID NTAPI SetupEjectionTransferPacket(TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp);
|
||||
VOID NTAPI SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, PIRP OriginalIrp);
|
||||
VOID NTAPI SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp);
|
||||
PMDL NTAPI BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen);
|
||||
VOID NTAPI FreeDeviceInputMdl(PMDL Mdl);
|
||||
NTSTATUS NTAPI InitializeTransferPackets(PDEVICE_OBJECT Fdo);
|
||||
VOID NTAPI DestroyAllTransferPackets(PDEVICE_OBJECT Fdo);
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#endif /* _CLASSPNP_PCH_ */
|
|
@ -1,59 +0,0 @@
|
|||
|
||||
@ stdcall ClassInitialize(ptr ptr ptr)
|
||||
@ stdcall ClassInitializeEx(ptr ptr ptr)
|
||||
@ stdcall ClassGetDescriptor(ptr ptr ptr)
|
||||
@ stdcall ClassReadDriveCapacity(ptr)
|
||||
@ stdcall ClassReleaseQueue(ptr)
|
||||
@ stdcall ClassAsynchronousCompletion(ptr ptr ptr)
|
||||
@ stdcall ClassSplitRequest(ptr ptr long)
|
||||
@ stdcall ClassDeviceControl(ptr ptr)
|
||||
@ stdcall ClassIoComplete(ptr ptr ptr)
|
||||
@ stdcall ClassIoCompleteAssociated(ptr ptr ptr)
|
||||
@ stdcall ClassInterpretSenseInfo(ptr ptr long long long ptr ptr)
|
||||
@ stdcall ClassSendDeviceIoControlSynchronous(long ptr ptr long long long ptr)
|
||||
@ stdcall ClassSendIrpSynchronous(ptr ptr)
|
||||
@ stdcall ClassForwardIrpSynchronous(ptr ptr)
|
||||
@ stdcall ClassSendSrbSynchronous(ptr ptr ptr long long)
|
||||
@ stdcall ClassSendSrbAsynchronous(ptr ptr ptr ptr long long)
|
||||
@ stdcall ClassBuildRequest(ptr ptr)
|
||||
@ stdcall ClassModeSense(ptr ptr long long)
|
||||
@ stdcall ClassFindModePage(ptr long long long)
|
||||
@ stdcall ClassClaimDevice(ptr long)
|
||||
@ stdcall ClassInternalIoControl(ptr ptr)
|
||||
@ stdcall ClassCreateDeviceObject(ptr ptr ptr long ptr)
|
||||
@ stdcall ClassRemoveDevice(ptr long)
|
||||
@ stdcall ClassInitializeSrbLookasideList(ptr long)
|
||||
@ stdcall ClassDeleteSrbLookasideList(ptr)
|
||||
@ stdcall ClassQueryTimeOutRegistryValue(ptr)
|
||||
@ stdcall ClassInvalidateBusRelations(ptr)
|
||||
@ stdcall ClassMarkChildrenMissing(ptr)
|
||||
@ stdcall ClassMarkChildMissing(ptr long)
|
||||
@ varargs ClassDebugPrint(long long)
|
||||
@ stdcall ClassGetDriverExtension(ptr)
|
||||
@ stdcall ClassCompleteRequest(ptr ptr long)
|
||||
@ stdcall ClassReleaseRemoveLock(ptr ptr)
|
||||
@ stdcall ClassAcquireRemoveLockEx(ptr ptr ptr long)
|
||||
@ stdcall ClassUpdateInformationInRegistry(ptr ptr long ptr long)
|
||||
@ stdcall ClassWmiCompleteRequest(ptr ptr long long long)
|
||||
@ stdcall ClassWmiFireEvent(ptr ptr long long ptr)
|
||||
@ stdcall ClassGetVpb(ptr)
|
||||
@ stdcall ClassSetFailurePredictionPoll(ptr long long)
|
||||
@ stdcall ClassNotifyFailurePredicted(ptr ptr long long long long long long)
|
||||
@ stdcall ClassInitializeTestUnitPolling(ptr long)
|
||||
@ stdcall ClassSignalCompletion(ptr ptr ptr)
|
||||
@ stdcall ClassSendStartUnit(ptr)
|
||||
@ stdcall ClassSetMediaChangeState(ptr long long)
|
||||
@ stdcall ClassResetMediaChangeTimer(ptr)
|
||||
@ stdcall ClassCheckMediaState(ptr)
|
||||
@ stdcall ClassInitializeMediaChangeDetection(ptr ptr)
|
||||
@ stdcall ClassCleanupMediaChangeDetection(ptr)
|
||||
@ stdcall ClassEnableMediaChangeDetection(ptr)
|
||||
@ stdcall ClassDisableMediaChangeDetection(ptr)
|
||||
@ stdcall ClassSpinDownPowerHandler(ptr ptr)
|
||||
@ stdcall ClassStopUnitPowerHandler(ptr ptr)
|
||||
@ stdcall ClassAcquireChildLock(ptr)
|
||||
@ stdcall ClassReleaseChildLock(ptr)
|
||||
@ stdcall ClassScanForSpecial(ptr ptr ptr)
|
||||
@ stdcall ClassSetDeviceParameter(ptr ptr ptr long)
|
||||
@ stdcall ClassGetDeviceParameter(ptr ptr ptr ptr)
|
||||
|
|
@ -1,771 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
classwmi.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI class driver routines
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
#include <wmistr.h>
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassSystemControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
ClassFindGuid(
|
||||
PGUIDREGINFO GuidList,
|
||||
ULONG GuidCount,
|
||||
LPGUID Guid,
|
||||
PULONG GuidIndex
|
||||
);
|
||||
|
||||
//
|
||||
// This is the name for the MOF resource that must be part of all drivers that
|
||||
// register via this interface.
|
||||
#define MOFRESOURCENAME L"MofResourceName"
|
||||
|
||||
//
|
||||
// What can be paged ???
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, ClassSystemControl)
|
||||
#pragma alloc_text(PAGE, ClassFindGuid)
|
||||
#endif
|
||||
|
||||
|
||||
/*++////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassFindGuid()
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will search the list of guids registered and return
|
||||
the index for the one that was registered.
|
||||
|
||||
Arguments:
|
||||
|
||||
GuidList is the list of guids to search
|
||||
|
||||
GuidCount is the count of guids in the list
|
||||
|
||||
Guid is the guid being searched for
|
||||
|
||||
*GuidIndex returns the index to the guid
|
||||
|
||||
Return Value:
|
||||
|
||||
TRUE if guid is found else FALSE
|
||||
|
||||
--*/
|
||||
BOOLEAN
|
||||
ClassFindGuid(
|
||||
PGUIDREGINFO GuidList,
|
||||
ULONG GuidCount,
|
||||
LPGUID Guid,
|
||||
PULONG GuidIndex
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
for (i = 0; i < GuidCount; i++)
|
||||
{
|
||||
if (IsEqualGUID(Guid, &GuidList[i].Guid))
|
||||
{
|
||||
*GuidIndex = i;
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
} // end ClassFindGuid()
|
||||
|
||||
/*++////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassSystemControl()
|
||||
|
||||
Routine Description:
|
||||
|
||||
Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process
|
||||
all wmi requests received, forwarding them if they are not for this
|
||||
driver or determining if the guid is valid and if so passing it to
|
||||
the driver specific function for handing wmi requests.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - Supplies a pointer to the device object for this request.
|
||||
|
||||
Irp - Supplies the Irp making the request.
|
||||
|
||||
Return Value:
|
||||
|
||||
status
|
||||
|
||||
--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassSystemControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||
PCLASS_DRIVER_EXTENSION driverExtension;
|
||||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
ULONG isRemoved;
|
||||
ULONG bufferSize;
|
||||
PUCHAR buffer;
|
||||
NTSTATUS status;
|
||||
UCHAR minorFunction;
|
||||
ULONG guidIndex;
|
||||
PCLASS_WMI_INFO classWmiInfo;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// Make sure device has not been removed
|
||||
isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp);
|
||||
if(isRemoved)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
||||
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
|
||||
return STATUS_DEVICE_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
//
|
||||
// If the irp is not a WMI irp or it is not targeted at this device
|
||||
// or this device has not registered with WMI then just forward it on.
|
||||
minorFunction = irpStack->MinorFunction;
|
||||
if ((minorFunction > IRP_MN_EXECUTE_METHOD) ||
|
||||
(irpStack->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject) ||
|
||||
((minorFunction != IRP_MN_REGINFO) &&
|
||||
(commonExtension->GuidRegInfo == NULL)))
|
||||
{
|
||||
//
|
||||
// CONSIDER: Do I need to hang onto lock until IoCallDriver returns ?
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||
return(IoCallDriver(commonExtension->LowerDeviceObject, Irp));
|
||||
}
|
||||
|
||||
buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
|
||||
bufferSize = irpStack->Parameters.WMI.BufferSize;
|
||||
|
||||
if (minorFunction != IRP_MN_REGINFO)
|
||||
{
|
||||
//
|
||||
// For all requests other than query registration info we are passed
|
||||
// a guid. Determine if the guid is one that is supported by the
|
||||
// device.
|
||||
if (ClassFindGuid(commonExtension->GuidRegInfo,
|
||||
commonExtension->GuidCount,
|
||||
(LPGUID)irpStack->Parameters.WMI.DataPath,
|
||||
&guidIndex))
|
||||
{
|
||||
status = STATUS_SUCCESS;
|
||||
} else {
|
||||
status = STATUS_WMI_GUID_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status) &&
|
||||
((minorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
|
||||
(minorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) ||
|
||||
(minorFunction == IRP_MN_CHANGE_SINGLE_ITEM) ||
|
||||
(minorFunction == IRP_MN_EXECUTE_METHOD)))
|
||||
{
|
||||
if ( (((PWNODE_HEADER)buffer)->Flags) &
|
||||
WNODE_FLAG_STATIC_INSTANCE_NAMES)
|
||||
{
|
||||
if ( ((PWNODE_SINGLE_INSTANCE)buffer)->InstanceIndex != 0 )
|
||||
{
|
||||
status = STATUS_WMI_INSTANCE_NOT_FOUND;
|
||||
}
|
||||
} else {
|
||||
status = STATUS_WMI_INSTANCE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
if (! NT_SUCCESS(status))
|
||||
{
|
||||
Irp->IoStatus.Status = status;
|
||||
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
|
||||
return(status);
|
||||
}
|
||||
}
|
||||
|
||||
driverExtension = commonExtension->DriverExtension;
|
||||
|
||||
classWmiInfo = commonExtension->IsFdo ?
|
||||
&driverExtension->InitData.FdoData.ClassWmiInfo :
|
||||
&driverExtension->InitData.PdoData.ClassWmiInfo;
|
||||
switch(minorFunction)
|
||||
{
|
||||
case IRP_MN_REGINFO:
|
||||
{
|
||||
ULONG guidCount;
|
||||
PGUIDREGINFO guidList;
|
||||
PWMIREGINFOW wmiRegInfo;
|
||||
PWMIREGGUIDW wmiRegGuid;
|
||||
//PDEVICE_OBJECT pdo;
|
||||
PUNICODE_STRING regPath;
|
||||
PWCHAR stringPtr;
|
||||
ULONG retSize;
|
||||
ULONG registryPathOffset;
|
||||
ULONG mofResourceOffset;
|
||||
ULONG bufferNeeded;
|
||||
ULONG i;
|
||||
ULONG_PTR nameInfo;
|
||||
ULONG nameSize, nameOffset, nameFlags;
|
||||
UNICODE_STRING name, mofName;
|
||||
PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx;
|
||||
|
||||
name.Buffer = NULL;
|
||||
name.Length = 0;
|
||||
name.MaximumLength = 0;
|
||||
nameFlags = 0;
|
||||
|
||||
ClassQueryWmiRegInfoEx = commonExtension->IsFdo ?
|
||||
driverExtension->ClassFdoQueryWmiRegInfoEx :
|
||||
driverExtension->ClassPdoQueryWmiRegInfoEx;
|
||||
|
||||
if (ClassQueryWmiRegInfoEx == NULL)
|
||||
{
|
||||
status = classWmiInfo->ClassQueryWmiRegInfo(
|
||||
DeviceObject,
|
||||
&nameFlags,
|
||||
&name);
|
||||
|
||||
RtlInitUnicodeString(&mofName, MOFRESOURCENAME);
|
||||
} else {
|
||||
RtlInitUnicodeString(&mofName, L"");
|
||||
status = (*ClassQueryWmiRegInfoEx)(
|
||||
DeviceObject,
|
||||
&nameFlags,
|
||||
&name,
|
||||
&mofName);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status) &&
|
||||
(! (nameFlags & WMIREG_FLAG_INSTANCE_PDO) &&
|
||||
(name.Buffer == NULL)))
|
||||
{
|
||||
//
|
||||
// if PDO flag not specified then an instance name must be
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
guidList = classWmiInfo->GuidRegInfo;
|
||||
guidCount = classWmiInfo->GuidCount;
|
||||
|
||||
nameOffset = sizeof(WMIREGINFO) +
|
||||
guidCount * sizeof(WMIREGGUIDW);
|
||||
|
||||
if (nameFlags & WMIREG_FLAG_INSTANCE_PDO)
|
||||
{
|
||||
nameSize = 0;
|
||||
nameInfo = commonExtension->IsFdo ?
|
||||
(ULONG_PTR)((PFUNCTIONAL_DEVICE_EXTENSION)commonExtension)->LowerPdo :
|
||||
(ULONG_PTR)DeviceObject;
|
||||
} else {
|
||||
nameFlags |= WMIREG_FLAG_INSTANCE_LIST;
|
||||
nameSize = name.Length + sizeof(USHORT);
|
||||
nameInfo = nameOffset;
|
||||
}
|
||||
|
||||
mofResourceOffset = nameOffset + nameSize;
|
||||
|
||||
registryPathOffset = mofResourceOffset +
|
||||
mofName.Length + sizeof(USHORT);
|
||||
|
||||
regPath = &driverExtension->RegistryPath;
|
||||
bufferNeeded = registryPathOffset +
|
||||
regPath->Length + sizeof(USHORT);
|
||||
|
||||
if (bufferNeeded <= bufferSize)
|
||||
{
|
||||
retSize = bufferNeeded;
|
||||
|
||||
commonExtension->GuidCount = guidCount;
|
||||
commonExtension->GuidRegInfo = guidList;
|
||||
|
||||
wmiRegInfo = (PWMIREGINFO)buffer;
|
||||
wmiRegInfo->BufferSize = bufferNeeded;
|
||||
wmiRegInfo->NextWmiRegInfo = 0;
|
||||
wmiRegInfo->MofResourceName = mofResourceOffset;
|
||||
wmiRegInfo->RegistryPath = registryPathOffset;
|
||||
wmiRegInfo->GuidCount = guidCount;
|
||||
|
||||
for (i = 0; i < guidCount; i++)
|
||||
{
|
||||
wmiRegGuid = &wmiRegInfo->WmiRegGuid[i];
|
||||
wmiRegGuid->Guid = guidList[i].Guid;
|
||||
wmiRegGuid->Flags = guidList[i].Flags | nameFlags;
|
||||
wmiRegGuid->InstanceInfo = nameInfo;
|
||||
wmiRegGuid->InstanceCount = 1;
|
||||
}
|
||||
|
||||
if ( nameFlags & WMIREG_FLAG_INSTANCE_LIST)
|
||||
{
|
||||
stringPtr = (PWCHAR)((PUCHAR)buffer + nameOffset);
|
||||
*stringPtr++ = name.Length;
|
||||
RtlCopyMemory(stringPtr,
|
||||
name.Buffer,
|
||||
name.Length);
|
||||
}
|
||||
|
||||
stringPtr = (PWCHAR)((PUCHAR)buffer + mofResourceOffset);
|
||||
*stringPtr++ = mofName.Length;
|
||||
RtlCopyMemory(stringPtr,
|
||||
mofName.Buffer,
|
||||
mofName.Length);
|
||||
|
||||
stringPtr = (PWCHAR)((PUCHAR)buffer + registryPathOffset);
|
||||
*stringPtr++ = regPath->Length;
|
||||
RtlCopyMemory(stringPtr,
|
||||
regPath->Buffer,
|
||||
regPath->Length);
|
||||
} else {
|
||||
*((PULONG)buffer) = bufferNeeded;
|
||||
retSize = sizeof(ULONG);
|
||||
}
|
||||
} else {
|
||||
retSize = 0;
|
||||
}
|
||||
|
||||
if (name.Buffer != NULL)
|
||||
{
|
||||
ExFreePool(name.Buffer);
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
Irp->IoStatus.Information = retSize;
|
||||
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
|
||||
return(status);
|
||||
}
|
||||
|
||||
case IRP_MN_QUERY_ALL_DATA:
|
||||
{
|
||||
PWNODE_ALL_DATA wnode;
|
||||
ULONG bufferAvail;
|
||||
|
||||
wnode = (PWNODE_ALL_DATA)buffer;
|
||||
|
||||
if (bufferSize < sizeof(WNODE_ALL_DATA))
|
||||
{
|
||||
bufferAvail = 0;
|
||||
} else {
|
||||
bufferAvail = bufferSize - sizeof(WNODE_ALL_DATA);
|
||||
}
|
||||
|
||||
wnode->DataBlockOffset = sizeof(WNODE_ALL_DATA);
|
||||
|
||||
status = classWmiInfo->ClassQueryWmiDataBlock(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
bufferAvail,
|
||||
buffer + sizeof(WNODE_ALL_DATA));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_QUERY_SINGLE_INSTANCE:
|
||||
{
|
||||
PWNODE_SINGLE_INSTANCE wnode;
|
||||
ULONG dataBlockOffset;
|
||||
|
||||
wnode = (PWNODE_SINGLE_INSTANCE)buffer;
|
||||
|
||||
dataBlockOffset = wnode->DataBlockOffset;
|
||||
|
||||
status = classWmiInfo->ClassQueryWmiDataBlock(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
bufferSize - dataBlockOffset,
|
||||
(PUCHAR)wnode + dataBlockOffset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_CHANGE_SINGLE_INSTANCE:
|
||||
{
|
||||
PWNODE_SINGLE_INSTANCE wnode;
|
||||
|
||||
wnode = (PWNODE_SINGLE_INSTANCE)buffer;
|
||||
|
||||
status = classWmiInfo->ClassSetWmiDataBlock(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
wnode->SizeDataBlock,
|
||||
(PUCHAR)wnode + wnode->DataBlockOffset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_CHANGE_SINGLE_ITEM:
|
||||
{
|
||||
PWNODE_SINGLE_ITEM wnode;
|
||||
|
||||
wnode = (PWNODE_SINGLE_ITEM)buffer;
|
||||
|
||||
status = classWmiInfo->ClassSetWmiDataItem(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
wnode->ItemId,
|
||||
wnode->SizeDataItem,
|
||||
(PUCHAR)wnode + wnode->DataBlockOffset);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_EXECUTE_METHOD:
|
||||
{
|
||||
PWNODE_METHOD_ITEM wnode;
|
||||
|
||||
wnode = (PWNODE_METHOD_ITEM)buffer;
|
||||
|
||||
status = classWmiInfo->ClassExecuteWmiMethod(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
wnode->MethodId,
|
||||
wnode->SizeDataBlock,
|
||||
bufferSize - wnode->DataBlockOffset,
|
||||
buffer + wnode->DataBlockOffset);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_ENABLE_EVENTS:
|
||||
{
|
||||
status = classWmiInfo->ClassWmiFunctionControl(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
EventGeneration,
|
||||
TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_DISABLE_EVENTS:
|
||||
{
|
||||
status = classWmiInfo->ClassWmiFunctionControl(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
EventGeneration,
|
||||
FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_ENABLE_COLLECTION:
|
||||
{
|
||||
status = classWmiInfo->ClassWmiFunctionControl(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
DataBlockCollection,
|
||||
TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_DISABLE_COLLECTION:
|
||||
{
|
||||
status = classWmiInfo->ClassWmiFunctionControl(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
guidIndex,
|
||||
DataBlockCollection,
|
||||
FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(status);
|
||||
} // end ClassSystemControl()
|
||||
|
||||
/*++////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassWmiCompleteRequest()
|
||||
|
||||
Routine Description:
|
||||
|
||||
|
||||
This routine will do the work of completing a WMI irp. Depending upon the
|
||||
the WMI request this routine will fixup the returned WNODE appropriately.
|
||||
|
||||
NOTE: This routine assumes that the ClassRemoveLock is held and it will
|
||||
release it.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - Supplies a pointer to the device object for this request.
|
||||
|
||||
Irp - Supplies the Irp making the request.
|
||||
|
||||
Status - Status to complete the irp with. STATUS_BUFFER_TOO_SMALL is used
|
||||
to indicate that more buffer is required for the data requested.
|
||||
|
||||
BufferUsed - number of bytes of actual data to return (not including WMI
|
||||
specific structures)
|
||||
|
||||
PriorityBoost - priority boost to pass to ClassCompleteRequest
|
||||
|
||||
Return Value:
|
||||
|
||||
status
|
||||
|
||||
--*/
|
||||
SCSIPORTAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassWmiCompleteRequest(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN NTSTATUS Status,
|
||||
IN ULONG BufferUsed,
|
||||
IN CCHAR PriorityBoost
|
||||
)
|
||||
{
|
||||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
//UCHAR MinorFunction;
|
||||
PUCHAR buffer;
|
||||
ULONG retSize;
|
||||
UCHAR minorFunction;
|
||||
|
||||
minorFunction = irpStack->MinorFunction;
|
||||
buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
|
||||
|
||||
switch(minorFunction)
|
||||
{
|
||||
case IRP_MN_QUERY_ALL_DATA:
|
||||
{
|
||||
PWNODE_ALL_DATA wnode;
|
||||
PWNODE_TOO_SMALL wnodeTooSmall;
|
||||
ULONG bufferNeeded;
|
||||
|
||||
wnode = (PWNODE_ALL_DATA)buffer;
|
||||
|
||||
bufferNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed;
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
retSize = bufferNeeded;
|
||||
wnode->WnodeHeader.BufferSize = bufferNeeded;
|
||||
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
|
||||
wnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE;
|
||||
wnode->FixedInstanceSize = BufferUsed;
|
||||
wnode->InstanceCount = 1;
|
||||
|
||||
} else if (Status == STATUS_BUFFER_TOO_SMALL) {
|
||||
wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
|
||||
|
||||
wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
|
||||
wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
|
||||
wnodeTooSmall->SizeNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed;
|
||||
retSize = sizeof(WNODE_TOO_SMALL);
|
||||
Status = STATUS_SUCCESS;
|
||||
} else {
|
||||
retSize = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_QUERY_SINGLE_INSTANCE:
|
||||
{
|
||||
PWNODE_SINGLE_INSTANCE wnode;
|
||||
PWNODE_TOO_SMALL wnodeTooSmall;
|
||||
ULONG bufferNeeded;
|
||||
|
||||
wnode = (PWNODE_SINGLE_INSTANCE)buffer;
|
||||
|
||||
bufferNeeded = wnode->DataBlockOffset + BufferUsed;
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
retSize = bufferNeeded;
|
||||
wnode->WnodeHeader.BufferSize = bufferNeeded;
|
||||
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
|
||||
wnode->SizeDataBlock = BufferUsed;
|
||||
|
||||
} else if (Status == STATUS_BUFFER_TOO_SMALL) {
|
||||
wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
|
||||
|
||||
wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
|
||||
wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
|
||||
wnodeTooSmall->SizeNeeded = bufferNeeded;
|
||||
retSize = sizeof(WNODE_TOO_SMALL);
|
||||
Status = STATUS_SUCCESS;
|
||||
} else {
|
||||
retSize = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IRP_MN_EXECUTE_METHOD:
|
||||
{
|
||||
PWNODE_METHOD_ITEM wnode;
|
||||
PWNODE_TOO_SMALL wnodeTooSmall;
|
||||
ULONG bufferNeeded;
|
||||
|
||||
wnode = (PWNODE_METHOD_ITEM)buffer;
|
||||
|
||||
bufferNeeded = wnode->DataBlockOffset + BufferUsed;
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
retSize = bufferNeeded;
|
||||
wnode->WnodeHeader.BufferSize = bufferNeeded;
|
||||
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
|
||||
wnode->SizeDataBlock = BufferUsed;
|
||||
|
||||
} else if (Status == STATUS_BUFFER_TOO_SMALL) {
|
||||
wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
|
||||
|
||||
wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
|
||||
wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
|
||||
wnodeTooSmall->SizeNeeded = bufferNeeded;
|
||||
retSize = sizeof(WNODE_TOO_SMALL);
|
||||
Status = STATUS_SUCCESS;
|
||||
} else {
|
||||
retSize = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
//
|
||||
// All other requests don't return any data
|
||||
retSize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = retSize;
|
||||
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||
ClassCompleteRequest(DeviceObject, Irp, PriorityBoost);
|
||||
return(Status);
|
||||
} // end ClassWmiCompleteRequest()
|
||||
|
||||
/*++////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassWmiFireEvent()
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will fire a WMI event using the data buffer passed. This
|
||||
routine may be called at or below DPC level
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - Supplies a pointer to the device object for this event
|
||||
|
||||
Guid is pointer to the GUID that represents the event
|
||||
|
||||
InstanceIndex is the index of the instance of the event
|
||||
|
||||
EventDataSize is the number of bytes of data that is being fired with
|
||||
with the event
|
||||
|
||||
EventData is the data that is fired with the events. This may be NULL
|
||||
if there is no data associated with the event
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
status
|
||||
|
||||
--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassWmiFireEvent(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN LPGUID Guid,
|
||||
IN ULONG InstanceIndex,
|
||||
IN ULONG EventDataSize,
|
||||
IN PVOID EventData
|
||||
)
|
||||
{
|
||||
|
||||
ULONG sizeNeeded;
|
||||
PWNODE_SINGLE_INSTANCE event;
|
||||
NTSTATUS status;
|
||||
|
||||
if (EventData == NULL)
|
||||
{
|
||||
EventDataSize = 0;
|
||||
}
|
||||
|
||||
sizeNeeded = sizeof(WNODE_SINGLE_INSTANCE) + EventDataSize;
|
||||
|
||||
event = ExAllocatePoolWithTag(NonPagedPool, sizeNeeded, CLASS_TAG_WMI);
|
||||
if (event != NULL)
|
||||
{
|
||||
event->WnodeHeader.Guid = *Guid;
|
||||
event->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(DeviceObject);
|
||||
event->WnodeHeader.BufferSize = sizeNeeded;
|
||||
event->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE |
|
||||
WNODE_FLAG_EVENT_ITEM |
|
||||
WNODE_FLAG_STATIC_INSTANCE_NAMES;
|
||||
KeQuerySystemTime(&event->WnodeHeader.TimeStamp);
|
||||
|
||||
event->InstanceIndex = InstanceIndex;
|
||||
event->SizeDataBlock = EventDataSize;
|
||||
event->DataBlockOffset = sizeof(WNODE_SINGLE_INSTANCE);
|
||||
if (EventData != NULL)
|
||||
{
|
||||
RtlCopyMemory( &event->VariableData, EventData, EventDataSize);
|
||||
}
|
||||
|
||||
status = IoWMIWriteEvent(event);
|
||||
if (! NT_SUCCESS(status))
|
||||
{
|
||||
ExFreePool(event);
|
||||
}
|
||||
} else {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
return(status);
|
||||
} // end ClassWmiFireEvent()
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
clntirp.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Client IRP queuing routines for CLASSPNP
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
/*
|
||||
* EnqueueDeferredClientIrp
|
||||
*
|
||||
* Note: we currently do not support Cancel for storage irps.
|
||||
*/
|
||||
VOID NTAPI EnqueueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
|
||||
KeAcquireSpinLock(&FdoData->SpinLock, &oldIrql);
|
||||
InsertTailList(&FdoData->DeferredClientIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||
KeReleaseSpinLock(&FdoData->SpinLock, oldIrql);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DequeueDeferredClientIrp
|
||||
*
|
||||
*/
|
||||
PIRP NTAPI DequeueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PLIST_ENTRY listEntry;
|
||||
PIRP irp;
|
||||
|
||||
KeAcquireSpinLock(&FdoData->SpinLock, &oldIrql);
|
||||
if (IsListEmpty(&FdoData->DeferredClientIrpList)){
|
||||
listEntry = NULL;
|
||||
}
|
||||
else {
|
||||
listEntry = RemoveHeadList(&FdoData->DeferredClientIrpList);
|
||||
}
|
||||
KeReleaseSpinLock(&FdoData->SpinLock, oldIrql);
|
||||
|
||||
if (listEntry == NULL) {
|
||||
irp = NULL;
|
||||
} else {
|
||||
irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
|
||||
ASSERT(irp->Type == IO_TYPE_IRP);
|
||||
InitializeListHead(&irp->Tail.Overlay.ListEntry);
|
||||
}
|
||||
|
||||
return irp;
|
||||
}
|
|
@ -1,977 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
class.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI class driver routines
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
ULONG BreakOnClose = 0;
|
||||
|
||||
PCSTR LockTypeStrings[] = {
|
||||
"Simple",
|
||||
"Secure",
|
||||
"Internal"
|
||||
};
|
||||
|
||||
|
||||
PFILE_OBJECT_EXTENSION
|
||||
NTAPI
|
||||
ClasspGetFsContext(
|
||||
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
|
||||
IN PFILE_OBJECT FileObject
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspCleanupDisableMcn(
|
||||
IN PFILE_OBJECT_EXTENSION FsContext
|
||||
);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, ClassCreateClose)
|
||||
#pragma alloc_text(PAGE, ClasspCreateClose)
|
||||
#pragma alloc_text(PAGE, ClasspCleanupProtectedLocks)
|
||||
#pragma alloc_text(PAGE, ClasspEjectionControl)
|
||||
#pragma alloc_text(PAGE, ClasspCleanupDisableMcn)
|
||||
#pragma alloc_text(PAGE, ClasspGetFsContext)
|
||||
#endif
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClassCreateClose(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
SCSI class driver create and close routine. This is called by the I/O system
|
||||
when the device is opened or closed.
|
||||
|
||||
Arguments:
|
||||
|
||||
DriverObject - Pointer to driver object created by system.
|
||||
|
||||
Irp - IRP involved.
|
||||
|
||||
Return Value:
|
||||
|
||||
Device-specific drivers return value or STATUS_SUCCESS.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||
ULONG removeState;
|
||||
NTSTATUS status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// If we're getting a close request then we know the device object hasn't
|
||||
// been completely destroyed. Let the driver cleanup if necessary.
|
||||
//
|
||||
|
||||
removeState = ClassAcquireRemoveLock(DeviceObject, Irp);
|
||||
|
||||
//
|
||||
// Invoke the device-specific routine, if one exists. Otherwise complete
|
||||
// with SUCCESS
|
||||
//
|
||||
|
||||
if((removeState == NO_REMOVE) ||
|
||||
IS_CLEANUP_REQUEST(IoGetCurrentIrpStackLocation(Irp)->MajorFunction)) {
|
||||
|
||||
status = ClasspCreateClose(DeviceObject, Irp);
|
||||
|
||||
if((NT_SUCCESS(status)) &&
|
||||
(commonExtension->DevInfo->ClassCreateClose)) {
|
||||
|
||||
return commonExtension->DevInfo->ClassCreateClose(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
} else {
|
||||
status = STATUS_DEVICE_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspCreateClose(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will handle create/close operations for a given classpnp
|
||||
device if the class driver doesn't supply it's own handler. If there
|
||||
is a file object supplied for our driver (if it's a FO_DIRECT_DEVICE_OPEN
|
||||
file object) then it will initialize a file extension on create or destroy
|
||||
the extension on a close.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - the device object being opened or closed.
|
||||
|
||||
Irp - the create/close irp
|
||||
|
||||
Return Value:
|
||||
|
||||
status
|
||||
|
||||
--*/
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
PFILE_OBJECT fileObject = irpStack->FileObject;
|
||||
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
|
||||
//
|
||||
// ISSUE-2000/3/28-henrygab - if lower stack fails create/close, we end up
|
||||
// in an inconsistent state. re-write to verify all args and allocate all
|
||||
// required resources, then pass the irp down, then complete the
|
||||
// transaction. this is because we also cannot forward the irp, then fail
|
||||
// it after it has succeeded a lower-level driver.
|
||||
//
|
||||
|
||||
if(irpStack->MajorFunction == IRP_MJ_CREATE) {
|
||||
|
||||
PIO_SECURITY_CONTEXT securityContext =
|
||||
irpStack->Parameters.Create.SecurityContext;
|
||||
DebugPrint((2,
|
||||
"ClasspCREATEClose: create received for device %p\n",
|
||||
DeviceObject));
|
||||
DebugPrint((2,
|
||||
"ClasspCREATEClose: desired access %lx\n",
|
||||
securityContext->DesiredAccess));
|
||||
DebugPrint((2,
|
||||
"ClasspCREATEClose: file object %lx\n",
|
||||
irpStack->FileObject));
|
||||
|
||||
ASSERT(BreakOnClose == FALSE);
|
||||
|
||||
if(irpStack->FileObject != NULL) {
|
||||
|
||||
PFILE_OBJECT_EXTENSION fsContext;
|
||||
|
||||
//
|
||||
// Allocate our own file object extension for this device object.
|
||||
//
|
||||
|
||||
status = AllocateDictionaryEntry(
|
||||
&commonExtension->FileObjectDictionary,
|
||||
(ULONG_PTR)irpStack->FileObject,
|
||||
sizeof(FILE_OBJECT_EXTENSION),
|
||||
CLASS_TAG_FILE_OBJECT_EXTENSION,
|
||||
(PVOID *)&fsContext);
|
||||
|
||||
if(NT_SUCCESS(status)) {
|
||||
|
||||
RtlZeroMemory(fsContext,
|
||||
sizeof(FILE_OBJECT_EXTENSION));
|
||||
|
||||
fsContext->FileObject = irpStack->FileObject;
|
||||
fsContext->DeviceObject = DeviceObject;
|
||||
} else if (status == STATUS_OBJECT_NAME_COLLISION) {
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspCreateCLOSE: close received for device %p\n",
|
||||
DeviceObject));
|
||||
DebugPrint((2,
|
||||
"ClasspCreateCLOSE: file object %p\n",
|
||||
fileObject));
|
||||
|
||||
if(irpStack->FileObject != NULL) {
|
||||
|
||||
PFILE_OBJECT_EXTENSION fsContext =
|
||||
ClasspGetFsContext(commonExtension, irpStack->FileObject);
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspCreateCLOSE: file extension %p\n",
|
||||
fsContext));
|
||||
|
||||
if(fsContext != NULL) {
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspCreateCLOSE: extension is ours - "
|
||||
"freeing\n"));
|
||||
ASSERT(BreakOnClose == FALSE);
|
||||
|
||||
ClasspCleanupProtectedLocks(fsContext);
|
||||
|
||||
ClasspCleanupDisableMcn(fsContext);
|
||||
|
||||
FreeDictionaryEntry(&(commonExtension->FileObjectDictionary),
|
||||
fsContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Notify the lower levels about the create or close operation - give them
|
||||
// a chance to cleanup too.
|
||||
//
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspCreateClose: %s for devobj %p\n",
|
||||
(NT_SUCCESS(status) ? "Success" : "FAILED"),
|
||||
DeviceObject));
|
||||
|
||||
|
||||
if(NT_SUCCESS(status)) {
|
||||
|
||||
KEVENT event;
|
||||
|
||||
//
|
||||
// Set up the event to wait on
|
||||
//
|
||||
|
||||
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
||||
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
IoSetCompletionRoutine( Irp, ClassSignalCompletion, &event,
|
||||
TRUE, TRUE, TRUE);
|
||||
|
||||
status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
|
||||
|
||||
if(status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DebugPrint((ClassDebugError,
|
||||
"ClasspCreateClose: Lower driver failed, but we "
|
||||
"succeeded. This is a problem, lock counts will be "
|
||||
"out of sync between levels.\n"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspCleanupProtectedLocks(
|
||||
IN PFILE_OBJECT_EXTENSION FsContext
|
||||
)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension =
|
||||
FsContext->DeviceObject->DeviceExtension;
|
||||
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
|
||||
commonExtension->PartitionZeroExtension;
|
||||
|
||||
ULONG newDeviceLockCount = 1;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspCleanupProtectedLocks called for %p\n",
|
||||
FsContext->DeviceObject));
|
||||
DebugPrint((2,
|
||||
"ClasspCleanupProtectedLocks - FsContext %p is locked "
|
||||
"%d times\n", FsContext, FsContext->LockCount));
|
||||
|
||||
ASSERT(BreakOnClose == FALSE);
|
||||
|
||||
//
|
||||
// Synchronize with ejection and ejection control requests.
|
||||
//
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
KeWaitForSingleObject(&(fdoExtension->EjectSynchronizationEvent),
|
||||
UserRequest,
|
||||
UserMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
//
|
||||
// For each secure lock on this handle decrement the secured lock count
|
||||
// for the FDO. Keep track of the new value.
|
||||
//
|
||||
|
||||
if(FsContext->LockCount != 0) {
|
||||
|
||||
do {
|
||||
|
||||
InterlockedDecrement((PLONG)&FsContext->LockCount);
|
||||
|
||||
newDeviceLockCount =
|
||||
InterlockedDecrement(&fdoExtension->ProtectedLockCount);
|
||||
|
||||
} while(FsContext->LockCount != 0);
|
||||
|
||||
//
|
||||
// If the new lock count has been dropped to zero then issue a lock
|
||||
// command to the device.
|
||||
//
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspCleanupProtectedLocks: FDO secured lock count = %d "
|
||||
"lock count = %d\n",
|
||||
fdoExtension->ProtectedLockCount,
|
||||
fdoExtension->LockCount));
|
||||
|
||||
if((newDeviceLockCount == 0) && (fdoExtension->LockCount == 0)) {
|
||||
|
||||
SCSI_REQUEST_BLOCK srb;
|
||||
PCDB cdb;
|
||||
NTSTATUS status;
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspCleanupProtectedLocks: FDO lock count dropped "
|
||||
"to zero\n"));
|
||||
|
||||
RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||
cdb = (PCDB) &(srb.Cdb);
|
||||
|
||||
srb.CdbLength = 6;
|
||||
|
||||
cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
|
||||
|
||||
//
|
||||
// TRUE - prevent media removal.
|
||||
// FALSE - allow media removal.
|
||||
//
|
||||
|
||||
cdb->MEDIA_REMOVAL.Prevent = FALSE;
|
||||
|
||||
//
|
||||
// Set timeout value.
|
||||
//
|
||||
|
||||
srb.TimeOutValue = fdoExtension->TimeOutValue;
|
||||
status = ClassSendSrbSynchronous(fdoExtension->DeviceObject,
|
||||
&srb,
|
||||
NULL,
|
||||
0,
|
||||
FALSE);
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspCleanupProtectedLocks: unlock request to drive "
|
||||
"returned status %lx\n", status));
|
||||
}
|
||||
}
|
||||
|
||||
KeSetEvent(&fdoExtension->EjectSynchronizationEvent,
|
||||
IO_NO_INCREMENT,
|
||||
FALSE);
|
||||
KeLeaveCriticalRegion();
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspCleanupDisableMcn(
|
||||
IN PFILE_OBJECT_EXTENSION FsContext
|
||||
)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension =
|
||||
FsContext->DeviceObject->DeviceExtension;
|
||||
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
|
||||
commonExtension->PartitionZeroExtension;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DebugPrint((ClassDebugTrace,
|
||||
"ClasspCleanupDisableMcn called for %p\n",
|
||||
FsContext->DeviceObject));
|
||||
DebugPrint((ClassDebugTrace,
|
||||
"ClasspCleanupDisableMcn - FsContext %p is disabled "
|
||||
"%d times\n", FsContext, FsContext->McnDisableCount));
|
||||
|
||||
//
|
||||
// For each secure lock on this handle decrement the secured lock count
|
||||
// for the FDO. Keep track of the new value.
|
||||
//
|
||||
|
||||
while(FsContext->McnDisableCount != 0) {
|
||||
FsContext->McnDisableCount--;
|
||||
ClassEnableMediaChangeDetection(fdoExtension);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* BUGBUG REMOVE this old function implementation as soon as the
|
||||
* boottime pagefile problems with the new one (below)
|
||||
* are resolved.
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspEjectionControl(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN PIRP Irp,
|
||||
IN MEDIA_LOCK_TYPE LockType,
|
||||
IN BOOLEAN Lock
|
||||
)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension = Fdo->DeviceExtension;
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension =
|
||||
(PCOMMON_DEVICE_EXTENSION) FdoExtension;
|
||||
|
||||
PFILE_OBJECT_EXTENSION fsContext = NULL;
|
||||
NTSTATUS status;
|
||||
volatile PSCSI_REQUEST_BLOCK srb = NULL;
|
||||
BOOLEAN countChanged = FALSE;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// Interlock with ejection and secure lock cleanup code. This is a
|
||||
// user request so we can allow the stack to get swapped out while we
|
||||
// wait for synchronization.
|
||||
//
|
||||
|
||||
status = KeWaitForSingleObject(
|
||||
&(FdoExtension->EjectSynchronizationEvent),
|
||||
UserRequest,
|
||||
UserMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
ASSERT(status == STATUS_SUCCESS);
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspEjectionControl: "
|
||||
"Received request for %s lock type\n",
|
||||
LockTypeStrings[LockType]
|
||||
));
|
||||
|
||||
_SEH2_TRY {
|
||||
PCDB cdb;
|
||||
|
||||
srb = ClasspAllocateSrb(FdoExtension);
|
||||
|
||||
if(srb == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||
|
||||
cdb = (PCDB) srb->Cdb;
|
||||
|
||||
//
|
||||
// Determine if this is a "secured" request.
|
||||
//
|
||||
|
||||
if(LockType == SecureMediaLock) {
|
||||
|
||||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT fileObject = irpStack->FileObject;
|
||||
|
||||
//
|
||||
// Make sure that the file object we are supplied has a
|
||||
// proper FsContext before we try doing a secured lock.
|
||||
//
|
||||
|
||||
if(fileObject != NULL) {
|
||||
fsContext = ClasspGetFsContext(commonExtension, fileObject);
|
||||
}
|
||||
|
||||
if (fsContext == NULL) {
|
||||
|
||||
//
|
||||
// This handle isn't setup correctly. We can't let the
|
||||
// operation go.
|
||||
//
|
||||
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
}
|
||||
|
||||
if(Lock) {
|
||||
|
||||
//
|
||||
// This is a lock command. Reissue the command in case bus or
|
||||
// device was reset and the lock was cleared.
|
||||
// note: may need to decrement count if actual lock operation
|
||||
// failed....
|
||||
//
|
||||
|
||||
switch(LockType) {
|
||||
|
||||
case SimpleMediaLock: {
|
||||
FdoExtension->LockCount++;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case SecureMediaLock: {
|
||||
fsContext->LockCount++;
|
||||
FdoExtension->ProtectedLockCount++;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case InternalMediaLock: {
|
||||
FdoExtension->InternalLockCount++;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// This is an unlock command. If it's a secured one then make sure
|
||||
// the caller has a lock outstanding or return an error.
|
||||
// note: may need to re-increment the count if actual unlock
|
||||
// operation fails....
|
||||
//
|
||||
|
||||
switch(LockType) {
|
||||
|
||||
case SimpleMediaLock: {
|
||||
if(FdoExtension->LockCount != 0) {
|
||||
FdoExtension->LockCount--;
|
||||
countChanged = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SecureMediaLock: {
|
||||
if(fsContext->LockCount == 0) {
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
fsContext->LockCount--;
|
||||
FdoExtension->ProtectedLockCount--;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
case InternalMediaLock: {
|
||||
ASSERT(FdoExtension->InternalLockCount != 0);
|
||||
FdoExtension->InternalLockCount--;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// We only send an unlock command to the drive if both the
|
||||
// secured and unsecured lock counts have dropped to zero.
|
||||
//
|
||||
|
||||
if((FdoExtension->ProtectedLockCount != 0) ||
|
||||
(FdoExtension->InternalLockCount != 0) ||
|
||||
(FdoExtension->LockCount != 0)) {
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
|
||||
|
||||
srb->CdbLength = 6;
|
||||
cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
|
||||
|
||||
//
|
||||
// TRUE - prevent media removal.
|
||||
// FALSE - allow media removal.
|
||||
//
|
||||
|
||||
cdb->MEDIA_REMOVAL.Prevent = Lock;
|
||||
|
||||
//
|
||||
// Set timeout value.
|
||||
//
|
||||
|
||||
srb->TimeOutValue = FdoExtension->TimeOutValue;
|
||||
|
||||
//
|
||||
// The actual lock operation on the device isn't so important
|
||||
// as the internal lock counts. Ignore failures.
|
||||
//
|
||||
|
||||
status = ClassSendSrbSynchronous(FdoExtension->DeviceObject,
|
||||
srb,
|
||||
NULL,
|
||||
0,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
} _SEH2_FINALLY {
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DebugPrint((2,
|
||||
"ClasspEjectionControl: FAILED status %x -- "
|
||||
"reverting lock counts\n", status));
|
||||
|
||||
if (countChanged) {
|
||||
|
||||
//
|
||||
// have to revert to previous counts if the
|
||||
// lock/unlock operation actually failed.
|
||||
//
|
||||
|
||||
if(Lock) {
|
||||
|
||||
switch(LockType) {
|
||||
|
||||
case SimpleMediaLock: {
|
||||
FdoExtension->LockCount--;
|
||||
break;
|
||||
}
|
||||
|
||||
case SecureMediaLock: {
|
||||
fsContext->LockCount--;
|
||||
FdoExtension->ProtectedLockCount--;
|
||||
break;
|
||||
}
|
||||
|
||||
case InternalMediaLock: {
|
||||
FdoExtension->InternalLockCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
switch(LockType) {
|
||||
|
||||
case SimpleMediaLock: {
|
||||
FdoExtension->LockCount++;
|
||||
break;
|
||||
}
|
||||
|
||||
case SecureMediaLock: {
|
||||
fsContext->LockCount++;
|
||||
FdoExtension->ProtectedLockCount++;
|
||||
break;
|
||||
}
|
||||
|
||||
case InternalMediaLock: {
|
||||
FdoExtension->InternalLockCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspEjectionControl: Succeeded\n"));
|
||||
|
||||
}
|
||||
|
||||
DebugPrint((2,
|
||||
"ClasspEjectionControl: "
|
||||
"Current Counts: Internal: %x Secure: %x Simple: %x\n",
|
||||
FdoExtension->InternalLockCount,
|
||||
FdoExtension->ProtectedLockCount,
|
||||
FdoExtension->LockCount
|
||||
));
|
||||
|
||||
KeSetEvent(&(FdoExtension->EjectSynchronizationEvent),
|
||||
IO_NO_INCREMENT,
|
||||
FALSE);
|
||||
if (srb) {
|
||||
ClassFreeOrReuseSrb(FdoExtension, srb);
|
||||
}
|
||||
|
||||
} _SEH2_END;
|
||||
return status;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* BUGBUG RESTORE
|
||||
* This is a new implementation of the function that doesn't thrash memory
|
||||
* or depend on the srbLookasideList.
|
||||
* HOWEVER, it seems to cause pagefile initialization to fail during boot
|
||||
* for some reason. Need to resolve this before switching to this function.
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ClasspEjectionControl(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN PIRP Irp,
|
||||
IN MEDIA_LOCK_TYPE LockType,
|
||||
IN BOOLEAN Lock
|
||||
)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||
PFILE_OBJECT_EXTENSION fsContext;
|
||||
BOOLEAN fileHandleOk = TRUE;
|
||||
BOOLEAN countChanged = FALSE;
|
||||
NTSTATUS status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
status = KeWaitForSingleObject(
|
||||
&fdoExt->EjectSynchronizationEvent,
|
||||
UserRequest,
|
||||
UserMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
ASSERT(status == STATUS_SUCCESS);
|
||||
|
||||
/*
|
||||
* If this is a "secured" request, we have to make sure
|
||||
* that the file handle is valid.
|
||||
*/
|
||||
if (LockType == SecureMediaLock){
|
||||
PIO_STACK_LOCATION thisSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/*
|
||||
* Make sure that the file object we are supplied has a
|
||||
* proper FsContext before we try doing a secured lock.
|
||||
*/
|
||||
if (thisSp->FileObject){
|
||||
PCOMMON_DEVICE_EXTENSION commonExt = (PCOMMON_DEVICE_EXTENSION)fdoExt;
|
||||
fsContext = ClasspGetFsContext(commonExt, thisSp->FileObject);
|
||||
}
|
||||
else {
|
||||
fsContext = NULL;
|
||||
}
|
||||
|
||||
if (!fsContext){
|
||||
ASSERT(fsContext);
|
||||
fileHandleOk = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileHandleOk){
|
||||
|
||||
/*
|
||||
* Adjust the lock counts and make sure they make sense.
|
||||
*/
|
||||
status = STATUS_SUCCESS;
|
||||
if (Lock){
|
||||
switch(LockType) {
|
||||
case SimpleMediaLock:
|
||||
fdoExt->LockCount++;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
case SecureMediaLock:
|
||||
fsContext->LockCount++;
|
||||
fdoExt->ProtectedLockCount++;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
case InternalMediaLock:
|
||||
fdoExt->InternalLockCount++;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* This is an unlock command. If it's a secured one then make sure
|
||||
* the caller has a lock outstanding or return an error.
|
||||
*/
|
||||
switch (LockType){
|
||||
case SimpleMediaLock:
|
||||
if (fdoExt->LockCount > 0){
|
||||
fdoExt->LockCount--;
|
||||
countChanged = TRUE;
|
||||
}
|
||||
else {
|
||||
ASSERT(fdoExt->LockCount > 0);
|
||||
status = STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
case SecureMediaLock:
|
||||
if (fsContext->LockCount > 0){
|
||||
ASSERT(fdoExt->ProtectedLockCount > 0);
|
||||
fsContext->LockCount--;
|
||||
fdoExt->ProtectedLockCount--;
|
||||
countChanged = TRUE;
|
||||
}
|
||||
else {
|
||||
ASSERT(fsContext->LockCount > 0);
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
}
|
||||
break;
|
||||
case InternalMediaLock:
|
||||
ASSERT(fdoExt->InternalLockCount > 0);
|
||||
fdoExt->InternalLockCount--;
|
||||
countChanged = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)){
|
||||
/*
|
||||
* We only send an unlock command to the drive if
|
||||
* all the lock counts have dropped to zero.
|
||||
*/
|
||||
if (!Lock &&
|
||||
(fdoExt->ProtectedLockCount ||
|
||||
fdoExt->InternalLockCount ||
|
||||
fdoExt->LockCount)){
|
||||
|
||||
/*
|
||||
* The lock count is still positive, so don't unlock yet.
|
||||
*/
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
|
||||
/*
|
||||
* The device isn't removable media. don't send a cmd.
|
||||
*/
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
TRANSFER_PACKET *pkt;
|
||||
|
||||
pkt = DequeueFreeTransferPacket(Fdo, TRUE);
|
||||
if (pkt){
|
||||
KEVENT event;
|
||||
|
||||
/*
|
||||
* Store the number of packets servicing the irp (one)
|
||||
* inside the original IRP. It will be used to counted down
|
||||
* to zero when the packet completes.
|
||||
* Initialize the original IRP's status to success.
|
||||
* If the packet fails, we will set it to the error status.
|
||||
*/
|
||||
Irp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/*
|
||||
* Set this up as a SYNCHRONOUS transfer, submit it,
|
||||
* and wait for the packet to complete. The result
|
||||
* status will be written to the original irp.
|
||||
*/
|
||||
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
||||
SetupEjectionTransferPacket(pkt, Lock, &event, Irp);
|
||||
SubmitTransferPacket(pkt);
|
||||
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
|
||||
status = Irp->IoStatus.Status;
|
||||
}
|
||||
else {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status) && countChanged) {
|
||||
|
||||
//
|
||||
// have to revert to previous counts if the
|
||||
// lock/unlock operation actually failed.
|
||||
//
|
||||
|
||||
if(Lock) {
|
||||
|
||||
switch(LockType) {
|
||||
|
||||
case SimpleMediaLock: {
|
||||
FdoExtension->LockCount--;
|
||||
break;
|
||||
}
|
||||
|
||||
case SecureMediaLock: {
|
||||
fsContext->LockCount--;
|
||||
FdoExtension->ProtectedLockCount--;
|
||||
break;
|
||||
}
|
||||
|
||||
case InternalMediaLock: {
|
||||
FdoExtension->InternalLockCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
switch(LockType) {
|
||||
|
||||
case SimpleMediaLock: {
|
||||
FdoExtension->LockCount++;
|
||||
break;
|
||||
}
|
||||
|
||||
case SecureMediaLock: {
|
||||
fsContext->LockCount++;
|
||||
FdoExtension->ProtectedLockCount++;
|
||||
break;
|
||||
}
|
||||
|
||||
case InternalMediaLock: {
|
||||
FdoExtension->InternalLockCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
KeSetEvent(&fdoExt->EjectSynchronizationEvent, IO_NO_INCREMENT, FALSE);
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
PFILE_OBJECT_EXTENSION
|
||||
NTAPI
|
||||
ClasspGetFsContext(
|
||||
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
|
||||
IN PFILE_OBJECT FileObject
|
||||
)
|
||||
{
|
||||
PAGED_CODE();
|
||||
return GetDictionaryEntry(&(CommonExtension->FileObjectDictionary),
|
||||
(ULONG_PTR)FileObject);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
disk.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI disk class driver
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("PAGE")
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001)
|
||||
#define FDO_HACK_GESN_IS_BAD (0x00000002)
|
||||
*/
|
||||
|
||||
CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[] = {
|
||||
{ "" , "MITSUMI CD-ROM FX240" , NULL, 0x02 },
|
||||
{ "" , "MITSUMI CD-ROM FX320" , NULL, 0x02 },
|
||||
{ "" , "MITSUMI CD-ROM FX322" , NULL, 0x02 },
|
||||
{ "" , "COMPAQ CRD-8481B" , NULL, 0x04 },
|
||||
{ NULL , NULL , NULL, 0x0 }
|
||||
};
|
||||
|
||||
|
||||
GUID ClassGuidQueryRegInfoEx = GUID_CLASSPNP_QUERY_REGINFOEX;
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg()
|
||||
#endif
|
||||
|
|
@ -1,693 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
debug.c
|
||||
|
||||
Abstract:
|
||||
|
||||
CLASSPNP debug code and data
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
#if DBG
|
||||
|
||||
//
|
||||
// default to not breaking in for lost irps, five minutes before we even
|
||||
// bother checking for lost irps, using standard debug print macros, and
|
||||
// using a 64k debug print buffer
|
||||
//
|
||||
|
||||
#ifndef CLASS_GLOBAL_BREAK_ON_LOST_IRPS
|
||||
#error "CLASS_GLOBAL_BREAK_ON_LOST_IRPS undefined"
|
||||
#define CLASS_GLOBAL_BREAK_ON_LOST_IRPS 0
|
||||
#endif // CLASS_GLOBAL_BREAK_ON_LOST_IRPS
|
||||
|
||||
#ifndef CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB
|
||||
#error "CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB undefined"
|
||||
#define CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB 300
|
||||
#endif // CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB
|
||||
|
||||
#ifndef CLASS_GLOBAL_USE_DELAYED_RETRY
|
||||
#error "CLASS_GLOBAL_USE_DELAYED_RETRY undefined"
|
||||
#define CLASS_GLOBAL_USE_DELAYED_RETRY 1
|
||||
#endif // CLASS_GLOBAL_USE_DELAYED_RETRY
|
||||
|
||||
#ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT
|
||||
#error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT undefined"
|
||||
#define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT 0
|
||||
#endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT
|
||||
|
||||
#ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE
|
||||
#error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE undefined"
|
||||
#define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE 512
|
||||
#endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE
|
||||
|
||||
#ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS
|
||||
#error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS undefined"
|
||||
#define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS 512
|
||||
#endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("NONPAGE")
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
CLASSPNP_GLOBALS ClasspnpGlobals;
|
||||
|
||||
//
|
||||
// the low sixteen bits are used to see if the debug level is high enough
|
||||
// the high sixteen bits are used to singly enable debug levels 1-16
|
||||
//
|
||||
LONG ClassDebug = 0xFFFFFFFF;
|
||||
|
||||
BOOLEAN DebugTrapOnWarn = FALSE;
|
||||
|
||||
VOID ClasspInitializeDebugGlobals()
|
||||
{
|
||||
KIRQL irql;
|
||||
|
||||
if (InterlockedCompareExchange(&ClasspnpGlobals.Initializing, 1, 0) == 0) {
|
||||
|
||||
KeInitializeSpinLock(&ClasspnpGlobals.SpinLock);
|
||||
|
||||
KeAcquireSpinLock(&ClasspnpGlobals.SpinLock, &irql);
|
||||
|
||||
DebugPrint((1, "CLASSPNP.SYS => Initializing ClasspnpGlobals...\n"));
|
||||
|
||||
ClasspnpGlobals.Buffer = NULL;
|
||||
ClasspnpGlobals.Index = -1;
|
||||
ClasspnpGlobals.BreakOnLostIrps = CLASS_GLOBAL_BREAK_ON_LOST_IRPS;
|
||||
ClasspnpGlobals.EachBufferSize = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE;
|
||||
ClasspnpGlobals.NumberOfBuffers = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS;
|
||||
ClasspnpGlobals.SecondsToWaitForIrps = CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB;
|
||||
|
||||
//
|
||||
// this should be the last item set
|
||||
//
|
||||
|
||||
ClasspnpGlobals.UseBufferedDebugPrint = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT;
|
||||
|
||||
KeReleaseSpinLock(&ClasspnpGlobals.SpinLock, irql);
|
||||
|
||||
InterlockedExchange(&ClasspnpGlobals.Initialized, 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*++////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassDebugPrint()
|
||||
|
||||
Routine Description:
|
||||
|
||||
Debug print for all class drivers, NOOP on FRE versions.
|
||||
Allows printing to a debug buffer (with auto fallback to kdprint) by
|
||||
properly setting the Globals in classpnp on CHK versions.
|
||||
|
||||
Arguments:
|
||||
|
||||
Debug print level, or from 0 to 3 for legacy drivers.
|
||||
|
||||
Return Value:
|
||||
|
||||
None
|
||||
|
||||
--*/
|
||||
VOID ClassDebugPrint(CLASS_DEBUG_LEVEL DebugPrintLevel, PCCHAR DebugMessage, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, DebugMessage);
|
||||
|
||||
if ((DebugPrintLevel <= (ClassDebug & 0x0000ffff)) ||
|
||||
((1 << (DebugPrintLevel + 15)) & ClassDebug)) {
|
||||
|
||||
if (ClasspnpGlobals.UseBufferedDebugPrint &&
|
||||
ClasspnpGlobals.Buffer == NULL) {
|
||||
|
||||
//
|
||||
// this double-check prevents always taking
|
||||
// a spinlock just to ensure we have a buffer
|
||||
//
|
||||
|
||||
KIRQL irql;
|
||||
|
||||
KeAcquireSpinLock(&ClasspnpGlobals.SpinLock, &irql);
|
||||
if (ClasspnpGlobals.Buffer == NULL) {
|
||||
|
||||
SIZE_T bufferSize;
|
||||
bufferSize = ClasspnpGlobals.NumberOfBuffers *
|
||||
ClasspnpGlobals.EachBufferSize;
|
||||
DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
|
||||
"ClassDebugPrint: Allocating %x bytes for "
|
||||
"classdebugprint buffer\n", bufferSize);
|
||||
ClasspnpGlobals.Index = -1;
|
||||
ClasspnpGlobals.Buffer =
|
||||
ExAllocatePoolWithTag(NonPagedPool, bufferSize, 'bDcS');
|
||||
DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
|
||||
"ClassDebugPrint: Allocated buffer at %p\n",
|
||||
ClasspnpGlobals.Buffer);
|
||||
|
||||
}
|
||||
KeReleaseSpinLock(&ClasspnpGlobals.SpinLock, irql);
|
||||
|
||||
}
|
||||
|
||||
if (ClasspnpGlobals.UseBufferedDebugPrint &&
|
||||
ClasspnpGlobals.Buffer != NULL) {
|
||||
|
||||
//
|
||||
// we never free the buffer, so once it exists,
|
||||
// we can just print to it with immunity
|
||||
//
|
||||
|
||||
ULONG index;
|
||||
PSTR buffer;
|
||||
index = InterlockedIncrement((PLONG)&ClasspnpGlobals.Index);
|
||||
index %= ClasspnpGlobals.NumberOfBuffers;
|
||||
index *= (ULONG)ClasspnpGlobals.EachBufferSize;
|
||||
|
||||
buffer = ClasspnpGlobals.Buffer;
|
||||
buffer += index;
|
||||
|
||||
_vsnprintf(buffer, ClasspnpGlobals.EachBufferSize, DebugMessage, ap);
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// either we could not allocate a buffer for debug prints
|
||||
// or buffered debug prints are disabled
|
||||
//
|
||||
vDbgPrintEx(-1, DPFLTR_ERROR_LEVEL, DebugMessage, ap);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
}
|
||||
|
||||
|
||||
char *DbgGetIoctlStr(ULONG ioctl)
|
||||
{
|
||||
char *ioctlStr = "?";
|
||||
|
||||
switch (ioctl){
|
||||
|
||||
#undef MAKE_CASE
|
||||
#define MAKE_CASE(ioctlCode) case ioctlCode: ioctlStr = #ioctlCode; break;
|
||||
|
||||
MAKE_CASE(IOCTL_STORAGE_CHECK_VERIFY)
|
||||
MAKE_CASE(IOCTL_STORAGE_CHECK_VERIFY2)
|
||||
MAKE_CASE(IOCTL_STORAGE_MEDIA_REMOVAL)
|
||||
MAKE_CASE(IOCTL_STORAGE_EJECT_MEDIA)
|
||||
MAKE_CASE(IOCTL_STORAGE_LOAD_MEDIA)
|
||||
MAKE_CASE(IOCTL_STORAGE_LOAD_MEDIA2)
|
||||
MAKE_CASE(IOCTL_STORAGE_RESERVE)
|
||||
MAKE_CASE(IOCTL_STORAGE_RELEASE)
|
||||
MAKE_CASE(IOCTL_STORAGE_FIND_NEW_DEVICES)
|
||||
MAKE_CASE(IOCTL_STORAGE_EJECTION_CONTROL)
|
||||
MAKE_CASE(IOCTL_STORAGE_MCN_CONTROL)
|
||||
MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_TYPES)
|
||||
MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_TYPES_EX)
|
||||
MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
|
||||
MAKE_CASE(IOCTL_STORAGE_GET_HOTPLUG_INFO)
|
||||
MAKE_CASE(IOCTL_STORAGE_RESET_BUS)
|
||||
MAKE_CASE(IOCTL_STORAGE_RESET_DEVICE)
|
||||
MAKE_CASE(IOCTL_STORAGE_GET_DEVICE_NUMBER)
|
||||
MAKE_CASE(IOCTL_STORAGE_PREDICT_FAILURE)
|
||||
MAKE_CASE(IOCTL_STORAGE_QUERY_PROPERTY)
|
||||
MAKE_CASE(OBSOLETE_IOCTL_STORAGE_RESET_BUS)
|
||||
MAKE_CASE(OBSOLETE_IOCTL_STORAGE_RESET_DEVICE)
|
||||
}
|
||||
|
||||
return ioctlStr;
|
||||
}
|
||||
|
||||
char *DbgGetScsiOpStr(PSCSI_REQUEST_BLOCK Srb)
|
||||
{
|
||||
PCDB pCdb = (PCDB)Srb->Cdb;
|
||||
UCHAR scsiOp = pCdb->CDB6GENERIC.OperationCode;
|
||||
char *scsiOpStr = "?";
|
||||
|
||||
switch (scsiOp){
|
||||
|
||||
#undef MAKE_CASE
|
||||
#define MAKE_CASE(scsiOpCode) case scsiOpCode: scsiOpStr = #scsiOpCode; break;
|
||||
|
||||
MAKE_CASE(SCSIOP_TEST_UNIT_READY)
|
||||
MAKE_CASE(SCSIOP_REWIND) // aka SCSIOP_REZERO_UNIT
|
||||
MAKE_CASE(SCSIOP_REQUEST_BLOCK_ADDR)
|
||||
MAKE_CASE(SCSIOP_REQUEST_SENSE)
|
||||
MAKE_CASE(SCSIOP_FORMAT_UNIT)
|
||||
MAKE_CASE(SCSIOP_READ_BLOCK_LIMITS)
|
||||
MAKE_CASE(SCSIOP_INIT_ELEMENT_STATUS) // aka SCSIOP_REASSIGN_BLOCKS
|
||||
MAKE_CASE(SCSIOP_RECEIVE) // aka SCSIOP_READ6
|
||||
MAKE_CASE(SCSIOP_SEND) // aka SCSIOP_WRITE6, SCSIOP_PRINT
|
||||
MAKE_CASE(SCSIOP_SLEW_PRINT) // aka SCSIOP_SEEK6, SCSIOP_TRACK_SELECT
|
||||
MAKE_CASE(SCSIOP_SEEK_BLOCK)
|
||||
MAKE_CASE(SCSIOP_PARTITION)
|
||||
MAKE_CASE(SCSIOP_READ_REVERSE)
|
||||
MAKE_CASE(SCSIOP_FLUSH_BUFFER) // aka SCSIOP_WRITE_FILEMARKS
|
||||
MAKE_CASE(SCSIOP_SPACE)
|
||||
MAKE_CASE(SCSIOP_INQUIRY)
|
||||
MAKE_CASE(SCSIOP_VERIFY6)
|
||||
MAKE_CASE(SCSIOP_RECOVER_BUF_DATA)
|
||||
MAKE_CASE(SCSIOP_MODE_SELECT)
|
||||
MAKE_CASE(SCSIOP_RESERVE_UNIT)
|
||||
MAKE_CASE(SCSIOP_RELEASE_UNIT)
|
||||
MAKE_CASE(SCSIOP_COPY)
|
||||
MAKE_CASE(SCSIOP_ERASE)
|
||||
MAKE_CASE(SCSIOP_MODE_SENSE)
|
||||
MAKE_CASE(SCSIOP_START_STOP_UNIT) // aka SCSIOP_STOP_PRINT, SCSIOP_LOAD_UNLOAD
|
||||
MAKE_CASE(SCSIOP_RECEIVE_DIAGNOSTIC)
|
||||
MAKE_CASE(SCSIOP_SEND_DIAGNOSTIC)
|
||||
MAKE_CASE(SCSIOP_MEDIUM_REMOVAL)
|
||||
MAKE_CASE(SCSIOP_READ_FORMATTED_CAPACITY)
|
||||
MAKE_CASE(SCSIOP_READ_CAPACITY)
|
||||
MAKE_CASE(SCSIOP_READ)
|
||||
MAKE_CASE(SCSIOP_WRITE)
|
||||
MAKE_CASE(SCSIOP_SEEK) // aka SCSIOP_LOCATE, SCSIOP_POSITION_TO_ELEMENT
|
||||
MAKE_CASE(SCSIOP_WRITE_VERIFY)
|
||||
MAKE_CASE(SCSIOP_VERIFY)
|
||||
MAKE_CASE(SCSIOP_SEARCH_DATA_HIGH)
|
||||
MAKE_CASE(SCSIOP_SEARCH_DATA_EQUAL)
|
||||
MAKE_CASE(SCSIOP_SEARCH_DATA_LOW)
|
||||
MAKE_CASE(SCSIOP_SET_LIMITS)
|
||||
MAKE_CASE(SCSIOP_READ_POSITION)
|
||||
MAKE_CASE(SCSIOP_SYNCHRONIZE_CACHE)
|
||||
MAKE_CASE(SCSIOP_COMPARE)
|
||||
MAKE_CASE(SCSIOP_COPY_COMPARE)
|
||||
MAKE_CASE(SCSIOP_WRITE_DATA_BUFF)
|
||||
MAKE_CASE(SCSIOP_READ_DATA_BUFF)
|
||||
MAKE_CASE(SCSIOP_CHANGE_DEFINITION)
|
||||
MAKE_CASE(SCSIOP_READ_SUB_CHANNEL)
|
||||
MAKE_CASE(SCSIOP_READ_TOC)
|
||||
MAKE_CASE(SCSIOP_READ_HEADER)
|
||||
MAKE_CASE(SCSIOP_PLAY_AUDIO)
|
||||
MAKE_CASE(SCSIOP_GET_CONFIGURATION)
|
||||
MAKE_CASE(SCSIOP_PLAY_AUDIO_MSF)
|
||||
MAKE_CASE(SCSIOP_PLAY_TRACK_INDEX)
|
||||
MAKE_CASE(SCSIOP_PLAY_TRACK_RELATIVE)
|
||||
MAKE_CASE(SCSIOP_GET_EVENT_STATUS)
|
||||
MAKE_CASE(SCSIOP_PAUSE_RESUME)
|
||||
MAKE_CASE(SCSIOP_LOG_SELECT)
|
||||
MAKE_CASE(SCSIOP_LOG_SENSE)
|
||||
MAKE_CASE(SCSIOP_STOP_PLAY_SCAN)
|
||||
MAKE_CASE(SCSIOP_READ_DISK_INFORMATION)
|
||||
MAKE_CASE(SCSIOP_READ_TRACK_INFORMATION)
|
||||
MAKE_CASE(SCSIOP_RESERVE_TRACK_RZONE)
|
||||
MAKE_CASE(SCSIOP_SEND_OPC_INFORMATION)
|
||||
MAKE_CASE(SCSIOP_MODE_SELECT10)
|
||||
MAKE_CASE(SCSIOP_MODE_SENSE10)
|
||||
MAKE_CASE(SCSIOP_CLOSE_TRACK_SESSION)
|
||||
MAKE_CASE(SCSIOP_READ_BUFFER_CAPACITY)
|
||||
MAKE_CASE(SCSIOP_SEND_CUE_SHEET)
|
||||
MAKE_CASE(SCSIOP_PERSISTENT_RESERVE_IN)
|
||||
MAKE_CASE(SCSIOP_PERSISTENT_RESERVE_OUT)
|
||||
MAKE_CASE(SCSIOP_REPORT_LUNS)
|
||||
MAKE_CASE(SCSIOP_BLANK)
|
||||
MAKE_CASE(SCSIOP_SEND_KEY)
|
||||
MAKE_CASE(SCSIOP_REPORT_KEY)
|
||||
MAKE_CASE(SCSIOP_MOVE_MEDIUM)
|
||||
MAKE_CASE(SCSIOP_LOAD_UNLOAD_SLOT) // aka SCSIOP_EXCHANGE_MEDIUM
|
||||
MAKE_CASE(SCSIOP_SET_READ_AHEAD)
|
||||
MAKE_CASE(SCSIOP_READ_DVD_STRUCTURE)
|
||||
MAKE_CASE(SCSIOP_REQUEST_VOL_ELEMENT)
|
||||
MAKE_CASE(SCSIOP_SEND_VOLUME_TAG)
|
||||
MAKE_CASE(SCSIOP_READ_ELEMENT_STATUS)
|
||||
MAKE_CASE(SCSIOP_READ_CD_MSF)
|
||||
MAKE_CASE(SCSIOP_SCAN_CD)
|
||||
MAKE_CASE(SCSIOP_SET_CD_SPEED)
|
||||
MAKE_CASE(SCSIOP_PLAY_CD)
|
||||
MAKE_CASE(SCSIOP_MECHANISM_STATUS)
|
||||
MAKE_CASE(SCSIOP_READ_CD)
|
||||
MAKE_CASE(SCSIOP_SEND_DVD_STRUCTURE)
|
||||
MAKE_CASE(SCSIOP_INIT_ELEMENT_RANGE)
|
||||
}
|
||||
|
||||
return scsiOpStr;
|
||||
}
|
||||
|
||||
|
||||
char *DbgGetSrbStatusStr(PSCSI_REQUEST_BLOCK Srb)
|
||||
{
|
||||
char *srbStatStr = "?";
|
||||
|
||||
switch (Srb->SrbStatus){
|
||||
|
||||
#undef MAKE_CASE
|
||||
#define MAKE_CASE(srbStat) \
|
||||
case srbStat: \
|
||||
srbStatStr = #srbStat; \
|
||||
break; \
|
||||
case srbStat|SRB_STATUS_QUEUE_FROZEN: \
|
||||
srbStatStr = #srbStat "|SRB_STATUS_QUEUE_FROZEN"; \
|
||||
break; \
|
||||
case srbStat|SRB_STATUS_AUTOSENSE_VALID: \
|
||||
srbStatStr = #srbStat "|SRB_STATUS_AUTOSENSE_VALID"; \
|
||||
break; \
|
||||
case srbStat|SRB_STATUS_QUEUE_FROZEN|SRB_STATUS_AUTOSENSE_VALID: \
|
||||
srbStatStr = #srbStat "|SRB_STATUS_QUEUE_FROZEN|SRB_STATUS_AUTOSENSE_VALID"; \
|
||||
break;
|
||||
|
||||
MAKE_CASE(SRB_STATUS_PENDING)
|
||||
MAKE_CASE(SRB_STATUS_SUCCESS)
|
||||
MAKE_CASE(SRB_STATUS_ABORTED)
|
||||
MAKE_CASE(SRB_STATUS_ABORT_FAILED)
|
||||
MAKE_CASE(SRB_STATUS_ERROR)
|
||||
MAKE_CASE(SRB_STATUS_BUSY)
|
||||
MAKE_CASE(SRB_STATUS_INVALID_REQUEST)
|
||||
MAKE_CASE(SRB_STATUS_INVALID_PATH_ID)
|
||||
MAKE_CASE(SRB_STATUS_NO_DEVICE)
|
||||
MAKE_CASE(SRB_STATUS_TIMEOUT)
|
||||
MAKE_CASE(SRB_STATUS_SELECTION_TIMEOUT)
|
||||
MAKE_CASE(SRB_STATUS_COMMAND_TIMEOUT)
|
||||
MAKE_CASE(SRB_STATUS_MESSAGE_REJECTED)
|
||||
MAKE_CASE(SRB_STATUS_BUS_RESET)
|
||||
MAKE_CASE(SRB_STATUS_PARITY_ERROR)
|
||||
MAKE_CASE(SRB_STATUS_REQUEST_SENSE_FAILED)
|
||||
MAKE_CASE(SRB_STATUS_NO_HBA)
|
||||
MAKE_CASE(SRB_STATUS_DATA_OVERRUN)
|
||||
MAKE_CASE(SRB_STATUS_UNEXPECTED_BUS_FREE)
|
||||
MAKE_CASE(SRB_STATUS_PHASE_SEQUENCE_FAILURE)
|
||||
MAKE_CASE(SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
|
||||
MAKE_CASE(SRB_STATUS_REQUEST_FLUSHED)
|
||||
MAKE_CASE(SRB_STATUS_INVALID_LUN)
|
||||
MAKE_CASE(SRB_STATUS_INVALID_TARGET_ID)
|
||||
MAKE_CASE(SRB_STATUS_BAD_FUNCTION)
|
||||
MAKE_CASE(SRB_STATUS_ERROR_RECOVERY)
|
||||
MAKE_CASE(SRB_STATUS_NOT_POWERED)
|
||||
MAKE_CASE(SRB_STATUS_INTERNAL_ERROR)
|
||||
}
|
||||
|
||||
return srbStatStr;
|
||||
}
|
||||
|
||||
|
||||
char *DbgGetSenseCodeStr(PSCSI_REQUEST_BLOCK Srb)
|
||||
{
|
||||
char *senseCodeStr = "?";
|
||||
|
||||
if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
|
||||
PSENSE_DATA senseData;
|
||||
UCHAR senseCode;
|
||||
|
||||
ASSERT(Srb->SenseInfoBuffer);
|
||||
senseData = Srb->SenseInfoBuffer;
|
||||
senseCode = senseData->SenseKey & 0xf;
|
||||
|
||||
switch (senseCode){
|
||||
|
||||
#undef MAKE_CASE
|
||||
#define MAKE_CASE(snsCod) case snsCod: senseCodeStr = #snsCod; break;
|
||||
|
||||
MAKE_CASE(SCSI_SENSE_NO_SENSE)
|
||||
MAKE_CASE(SCSI_SENSE_RECOVERED_ERROR)
|
||||
MAKE_CASE(SCSI_SENSE_NOT_READY)
|
||||
MAKE_CASE(SCSI_SENSE_MEDIUM_ERROR)
|
||||
MAKE_CASE(SCSI_SENSE_HARDWARE_ERROR)
|
||||
MAKE_CASE(SCSI_SENSE_ILLEGAL_REQUEST)
|
||||
MAKE_CASE(SCSI_SENSE_UNIT_ATTENTION)
|
||||
MAKE_CASE(SCSI_SENSE_DATA_PROTECT)
|
||||
MAKE_CASE(SCSI_SENSE_BLANK_CHECK)
|
||||
MAKE_CASE(SCSI_SENSE_UNIQUE)
|
||||
MAKE_CASE(SCSI_SENSE_COPY_ABORTED)
|
||||
MAKE_CASE(SCSI_SENSE_ABORTED_COMMAND)
|
||||
MAKE_CASE(SCSI_SENSE_EQUAL)
|
||||
MAKE_CASE(SCSI_SENSE_VOL_OVERFLOW)
|
||||
MAKE_CASE(SCSI_SENSE_MISCOMPARE)
|
||||
MAKE_CASE(SCSI_SENSE_RESERVED)
|
||||
}
|
||||
}
|
||||
|
||||
return senseCodeStr;
|
||||
}
|
||||
|
||||
|
||||
char *DbgGetAdditionalSenseCodeStr(PSCSI_REQUEST_BLOCK Srb)
|
||||
{
|
||||
char *adSenseCodeStr = "?";
|
||||
|
||||
if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
|
||||
PSENSE_DATA senseData;
|
||||
UCHAR adSenseCode;
|
||||
|
||||
ASSERT(Srb->SenseInfoBuffer);
|
||||
senseData = Srb->SenseInfoBuffer;
|
||||
adSenseCode = senseData->AdditionalSenseCode;
|
||||
|
||||
switch (adSenseCode){
|
||||
|
||||
#undef MAKE_CASE
|
||||
#define MAKE_CASE(adSnsCod) case adSnsCod: adSenseCodeStr = #adSnsCod; break;
|
||||
|
||||
MAKE_CASE(SCSI_ADSENSE_NO_SENSE)
|
||||
MAKE_CASE(SCSI_ADSENSE_LUN_NOT_READY)
|
||||
MAKE_CASE(SCSI_ADSENSE_TRACK_ERROR)
|
||||
MAKE_CASE(SCSI_ADSENSE_SEEK_ERROR)
|
||||
MAKE_CASE(SCSI_ADSENSE_REC_DATA_NOECC)
|
||||
MAKE_CASE(SCSI_ADSENSE_REC_DATA_ECC)
|
||||
MAKE_CASE(SCSI_ADSENSE_ILLEGAL_COMMAND)
|
||||
MAKE_CASE(SCSI_ADSENSE_ILLEGAL_BLOCK)
|
||||
MAKE_CASE(SCSI_ADSENSE_INVALID_CDB)
|
||||
MAKE_CASE(SCSI_ADSENSE_INVALID_LUN)
|
||||
MAKE_CASE(SCSI_ADSENSE_WRITE_PROTECT) // aka SCSI_ADWRITE_PROTECT
|
||||
MAKE_CASE(SCSI_ADSENSE_MEDIUM_CHANGED)
|
||||
MAKE_CASE(SCSI_ADSENSE_BUS_RESET)
|
||||
MAKE_CASE(SCSI_ADSENSE_INVALID_MEDIA)
|
||||
MAKE_CASE(SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)
|
||||
MAKE_CASE(SCSI_ADSENSE_POSITION_ERROR)
|
||||
MAKE_CASE(SCSI_ADSENSE_OPERATOR_REQUEST)
|
||||
MAKE_CASE(SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED)
|
||||
MAKE_CASE(SCSI_ADSENSE_COPY_PROTECTION_FAILURE)
|
||||
MAKE_CASE(SCSI_ADSENSE_VENDOR_UNIQUE)
|
||||
MAKE_CASE(SCSI_ADSENSE_MUSIC_AREA)
|
||||
MAKE_CASE(SCSI_ADSENSE_DATA_AREA)
|
||||
MAKE_CASE(SCSI_ADSENSE_VOLUME_OVERFLOW)
|
||||
}
|
||||
}
|
||||
|
||||
return adSenseCodeStr;
|
||||
}
|
||||
|
||||
|
||||
char *DbgGetAdditionalSenseCodeQualifierStr(PSCSI_REQUEST_BLOCK Srb)
|
||||
{
|
||||
char *adSenseCodeQualStr = "?";
|
||||
|
||||
if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
|
||||
PSENSE_DATA senseData;
|
||||
UCHAR adSenseCode;
|
||||
UCHAR adSenseCodeQual;
|
||||
|
||||
ASSERT(Srb->SenseInfoBuffer);
|
||||
senseData = Srb->SenseInfoBuffer;
|
||||
adSenseCode = senseData->AdditionalSenseCode;
|
||||
adSenseCodeQual = senseData->AdditionalSenseCodeQualifier;
|
||||
|
||||
switch (adSenseCode){
|
||||
|
||||
#undef MAKE_CASE
|
||||
#define MAKE_CASE(adSnsCodQual) case adSnsCodQual: adSenseCodeQualStr = #adSnsCodQual; break;
|
||||
|
||||
case SCSI_ADSENSE_LUN_NOT_READY:
|
||||
switch (adSenseCodeQual){
|
||||
MAKE_CASE(SCSI_SENSEQ_CAUSE_NOT_REPORTABLE)
|
||||
MAKE_CASE(SCSI_SENSEQ_BECOMING_READY)
|
||||
MAKE_CASE(SCSI_SENSEQ_INIT_COMMAND_REQUIRED)
|
||||
MAKE_CASE(SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED)
|
||||
MAKE_CASE(SCSI_SENSEQ_FORMAT_IN_PROGRESS)
|
||||
MAKE_CASE(SCSI_SENSEQ_REBUILD_IN_PROGRESS)
|
||||
MAKE_CASE(SCSI_SENSEQ_RECALCULATION_IN_PROGRESS)
|
||||
MAKE_CASE(SCSI_SENSEQ_OPERATION_IN_PROGRESS)
|
||||
MAKE_CASE(SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS)
|
||||
}
|
||||
break;
|
||||
case SCSI_ADSENSE_NO_SENSE:
|
||||
switch (adSenseCodeQual){
|
||||
MAKE_CASE(SCSI_SENSEQ_FILEMARK_DETECTED)
|
||||
MAKE_CASE(SCSI_SENSEQ_END_OF_MEDIA_DETECTED)
|
||||
MAKE_CASE(SCSI_SENSEQ_SETMARK_DETECTED)
|
||||
MAKE_CASE(SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED)
|
||||
}
|
||||
break;
|
||||
case SCSI_ADSENSE_ILLEGAL_BLOCK:
|
||||
switch (adSenseCodeQual){
|
||||
MAKE_CASE(SCSI_SENSEQ_ILLEGAL_ELEMENT_ADDR)
|
||||
}
|
||||
break;
|
||||
case SCSI_ADSENSE_POSITION_ERROR:
|
||||
switch (adSenseCodeQual){
|
||||
MAKE_CASE(SCSI_SENSEQ_DESTINATION_FULL)
|
||||
MAKE_CASE(SCSI_SENSEQ_SOURCE_EMPTY)
|
||||
}
|
||||
break;
|
||||
case SCSI_ADSENSE_INVALID_MEDIA:
|
||||
switch (adSenseCodeQual){
|
||||
MAKE_CASE(SCSI_SENSEQ_INCOMPATIBLE_MEDIA_INSTALLED)
|
||||
MAKE_CASE(SCSI_SENSEQ_UNKNOWN_FORMAT)
|
||||
MAKE_CASE(SCSI_SENSEQ_INCOMPATIBLE_FORMAT)
|
||||
MAKE_CASE(SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED)
|
||||
}
|
||||
break;
|
||||
case SCSI_ADSENSE_OPERATOR_REQUEST:
|
||||
switch (adSenseCodeQual){
|
||||
MAKE_CASE(SCSI_SENSEQ_STATE_CHANGE_INPUT)
|
||||
MAKE_CASE(SCSI_SENSEQ_MEDIUM_REMOVAL)
|
||||
MAKE_CASE(SCSI_SENSEQ_WRITE_PROTECT_ENABLE)
|
||||
MAKE_CASE(SCSI_SENSEQ_WRITE_PROTECT_DISABLE)
|
||||
}
|
||||
break;
|
||||
case SCSI_ADSENSE_COPY_PROTECTION_FAILURE:
|
||||
switch (adSenseCodeQual){
|
||||
MAKE_CASE(SCSI_SENSEQ_AUTHENTICATION_FAILURE)
|
||||
MAKE_CASE(SCSI_SENSEQ_KEY_NOT_PRESENT)
|
||||
MAKE_CASE(SCSI_SENSEQ_KEY_NOT_ESTABLISHED)
|
||||
MAKE_CASE(SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION)
|
||||
MAKE_CASE(SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT)
|
||||
MAKE_CASE(SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR)
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return adSenseCodeQualStr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DbgCheckReturnedPkt
|
||||
*
|
||||
* Check a completed TRANSFER_PACKET for all sorts of error conditions
|
||||
* and warn/trap appropriately.
|
||||
*/
|
||||
VOID DbgCheckReturnedPkt(TRANSFER_PACKET *Pkt)
|
||||
{
|
||||
PCDB pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||
|
||||
ASSERT(Pkt->Srb.OriginalRequest == Pkt->Irp);
|
||||
ASSERT(Pkt->Srb.DataBuffer == Pkt->BufPtrCopy);
|
||||
ASSERT(Pkt->Srb.DataTransferLength <= Pkt->BufLenCopy);
|
||||
ASSERT(!Pkt->Irp->CancelRoutine);
|
||||
|
||||
if (SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_PENDING){
|
||||
DBGERR(("SRB completed with status PENDING in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
|
||||
Pkt,
|
||||
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||
(ULONG)Pkt->Srb.SrbStatus,
|
||||
Pkt->Irp->IoStatus.Status));
|
||||
}
|
||||
else if (SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS){
|
||||
/*
|
||||
* Make sure SRB and IRP status match.
|
||||
*/
|
||||
if (!NT_SUCCESS(Pkt->Irp->IoStatus.Status)){
|
||||
DBGWARN(("SRB and IRP status don't match in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
|
||||
Pkt,
|
||||
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||
(ULONG)Pkt->Srb.SrbStatus,
|
||||
Pkt->Irp->IoStatus.Status));
|
||||
}
|
||||
|
||||
if (Pkt->Irp->IoStatus.Information != Pkt->Srb.DataTransferLength){
|
||||
DBGERR(("SRB and IRP result transfer lengths don't match in succeeded packet %ph: (op=%s, SrbStatus=%s, Srb.DataTransferLength=%xh, Irp->IoStatus.Information=%xh).",
|
||||
Pkt,
|
||||
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||
Pkt->Srb.DataTransferLength,
|
||||
Pkt->Irp->IoStatus.Information));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (NT_SUCCESS(Pkt->Irp->IoStatus.Status)){
|
||||
DBGWARN(("SRB and IRP status don't match in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
|
||||
Pkt,
|
||||
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||
(ULONG)Pkt->Srb.SrbStatus,
|
||||
Pkt->Irp->IoStatus.Status));
|
||||
}
|
||||
DBGTRACE(ClassDebugWarning, ("Packet %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)",
|
||||
Pkt,
|
||||
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||
(ULONG)Pkt->Srb.SrbStatus,
|
||||
Pkt->Irp->IoStatus.Status,
|
||||
DBGGETSENSECODESTR(&Pkt->Srb),
|
||||
DBGGETADSENSECODESTR(&Pkt->Srb),
|
||||
DBGGETADSENSEQUALIFIERSTR(&Pkt->Srb)));
|
||||
|
||||
/*
|
||||
* If the SRB failed with underrun or overrun, then the actual
|
||||
* transferred length should be returned in both SRB and IRP.
|
||||
* (SRB's only have an error status for overrun, so it's overloaded).
|
||||
*/
|
||||
if ((SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) &&
|
||||
(Pkt->Irp->IoStatus.Information != Pkt->Srb.DataTransferLength)){
|
||||
DBGERR(("SRB and IRP result transfer lengths don't match in failed packet %ph: (op=%s, SrbStatus=%s, Srb.DataTransferLength=%xh, Irp->IoStatus.Information=%xh).",
|
||||
Pkt,
|
||||
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||
Pkt->Srb.DataTransferLength,
|
||||
Pkt->Irp->IoStatus.Information));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Some miniport drivers have been caught changing the SCSI operation
|
||||
* code in the SRB. This is absolutely disallowed as it breaks our error handling.
|
||||
*/
|
||||
switch (pCdb->CDB10.OperationCode){
|
||||
case SCSIOP_MEDIUM_REMOVAL:
|
||||
case SCSIOP_MODE_SENSE:
|
||||
case SCSIOP_READ_CAPACITY:
|
||||
case SCSIOP_READ:
|
||||
case SCSIOP_WRITE:
|
||||
case SCSIOP_START_STOP_UNIT:
|
||||
break;
|
||||
default:
|
||||
DBGERR(("Miniport illegally changed Srb.Cdb.OperationCode in packet %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)",
|
||||
Pkt,
|
||||
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||
(ULONG)Pkt->Srb.SrbStatus,
|
||||
Pkt->Irp->IoStatus.Status,
|
||||
DBGGETSENSECODESTR(&Pkt->Srb),
|
||||
DBGGETADSENSECODESTR(&Pkt->Srb),
|
||||
DBGGETADSENSEQUALIFIERSTR(&Pkt->Srb)));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// We have to keep this in the retail build for legacy.
|
||||
VOID ClassDebugPrint(CLASS_DEBUG_LEVEL DebugPrintLevel, PCCHAR DebugMessage, ...)
|
||||
{
|
||||
DbgPrint("retail build\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
debug.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
VOID ClassDebugPrint(CLASS_DEBUG_LEVEL DebugPrintLevel, PCCHAR DebugMessage, ...);
|
||||
|
||||
#if DBG
|
||||
|
||||
typedef struct _CLASSPNP_GLOBALS {
|
||||
|
||||
//
|
||||
// whether or not to ASSERT for lost irps
|
||||
//
|
||||
|
||||
ULONG BreakOnLostIrps;
|
||||
ULONG SecondsToWaitForIrps;
|
||||
|
||||
//
|
||||
// use a buffered debug print to help
|
||||
// catch timing issues that do not
|
||||
// reproduce with std debugprints enabled
|
||||
//
|
||||
|
||||
ULONG UseBufferedDebugPrint;
|
||||
ULONG UseDelayedRetry;
|
||||
|
||||
//
|
||||
// the next four are the buffered printing support
|
||||
// (currently unimplemented) and require the spinlock
|
||||
// to use
|
||||
//
|
||||
|
||||
ULONG Index; // index into buffer
|
||||
KSPIN_LOCK SpinLock;
|
||||
PSTR Buffer; // requires spinlock to access
|
||||
ULONG NumberOfBuffers; // number of buffers available
|
||||
SIZE_T EachBufferSize; // size of each buffer
|
||||
|
||||
//
|
||||
// interlocked variables to initialize
|
||||
// this data only once
|
||||
//
|
||||
|
||||
LONG Initializing;
|
||||
LONG Initialized;
|
||||
|
||||
} CLASSPNP_GLOBALS, *PCLASSPNP_GLOBALS;
|
||||
|
||||
#define DBGTRACE(dbgTraceLevel, args_in_parens) \
|
||||
if (ClassDebug & (1 << (dbgTraceLevel+15))){ \
|
||||
DbgPrint("CLASSPNP> *** TRACE *** (file %s, line %d)\n", __FILE__, __LINE__ ); \
|
||||
DbgPrint(" > "); \
|
||||
DbgPrint args_in_parens; \
|
||||
DbgPrint("\n"); \
|
||||
if (DebugTrapOnWarn && (dbgTraceLevel == ClassDebugWarning)){ \
|
||||
DbgBreakPoint(); \
|
||||
} \
|
||||
}
|
||||
#define DBGWARN(args_in_parens) \
|
||||
{ \
|
||||
DbgPrint("CLASSPNP> *** WARNING *** (file %s, line %d)\n", __FILE__, __LINE__ ); \
|
||||
DbgPrint(" > "); \
|
||||
DbgPrint args_in_parens; \
|
||||
DbgPrint("\n"); \
|
||||
if (DebugTrapOnWarn){ \
|
||||
DbgBreakPoint(); \
|
||||
} \
|
||||
}
|
||||
#define DBGERR(args_in_parens) \
|
||||
{ \
|
||||
DbgPrint("CLASSPNP> *** ERROR *** (file %s, line %d)\n", __FILE__, __LINE__ ); \
|
||||
DbgPrint(" > "); \
|
||||
DbgPrint args_in_parens; \
|
||||
DbgPrint("\n"); \
|
||||
DbgBreakPoint(); \
|
||||
}
|
||||
#define DBGTRAP(args_in_parens) \
|
||||
{ \
|
||||
DbgPrint("CLASSPNP> *** COVERAGE TRAP *** (file %s, line %d)\n", __FILE__, __LINE__ ); \
|
||||
DbgPrint(" > "); \
|
||||
DbgPrint args_in_parens; \
|
||||
DbgPrint("\n"); \
|
||||
DbgBreakPoint(); \
|
||||
}
|
||||
|
||||
|
||||
#define DBGGETIOCTLSTR(_ioctl) DbgGetIoctlStr(_ioctl)
|
||||
#define DBGGETSCSIOPSTR(_pSrb) DbgGetScsiOpStr(_pSrb)
|
||||
#define DBGGETSENSECODESTR(_pSrb) DbgGetSenseCodeStr(_pSrb)
|
||||
#define DBGGETADSENSECODESTR(_pSrb) DbgGetAdditionalSenseCodeStr(_pSrb)
|
||||
#define DBGGETADSENSEQUALIFIERSTR(_pSrb) DbgGetAdditionalSenseCodeQualifierStr(_pSrb)
|
||||
#define DBGCHECKRETURNEDPKT(_pkt) DbgCheckReturnedPkt(_pkt)
|
||||
#define DBGGETSRBSTATUSSTR(_pSrb) DbgGetSrbStatusStr(_pSrb)
|
||||
|
||||
VOID ClasspInitializeDebugGlobals(VOID);
|
||||
char *DbgGetIoctlStr(ULONG ioctl);
|
||||
char *DbgGetScsiOpStr(PSCSI_REQUEST_BLOCK Srb);
|
||||
char *DbgGetSenseCodeStr(PSCSI_REQUEST_BLOCK Srb);
|
||||
char *DbgGetAdditionalSenseCodeStr(PSCSI_REQUEST_BLOCK Srb);
|
||||
char *DbgGetAdditionalSenseCodeQualifierStr(PSCSI_REQUEST_BLOCK Srb);
|
||||
VOID DbgCheckReturnedPkt(TRANSFER_PACKET *Pkt);
|
||||
char *DbgGetSrbStatusStr(PSCSI_REQUEST_BLOCK Srb);
|
||||
|
||||
|
||||
extern CLASSPNP_GLOBALS ClasspnpGlobals;
|
||||
extern LONG ClassDebug;
|
||||
extern BOOLEAN DebugTrapOnWarn;
|
||||
|
||||
#else
|
||||
|
||||
#define ClasspInitializeDebugGlobals()
|
||||
#define DBGWARN(args_in_parens)
|
||||
#define DBGERR(args_in_parens)
|
||||
#define DBGTRACE(dbgTraceLevel, args_in_parens)
|
||||
#define DBGTRAP(args_in_parens)
|
||||
|
||||
#define DBGGETIOCTLSTR(_ioctl)
|
||||
#define DBGGETSCSIOPSTR(_pSrb)
|
||||
#define DBGGETSENSECODESTR(_pSrb)
|
||||
#define DBGGETADSENSECODESTR(_pSrb)
|
||||
#define DBGGETADSENSEQUALIFIERSTR(_pSrb)
|
||||
#define DBGCHECKRETURNEDPKT(_pkt)
|
||||
#define DBGGETSRBSTATUSSTR(_pSrb)
|
||||
|
||||
#endif
|
|
@ -1,212 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1990 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
dictlib.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Support library for maintaining a dictionary list (list of objects
|
||||
referenced by a key value).
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
This module generates a static library
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
#define DICTIONARY_SIGNATURE 'dsig'
|
||||
|
||||
typedef struct _DICTIONARY_HEADER {
|
||||
struct _DICTIONARY_HEADER* Next;
|
||||
ULONGLONG Key;
|
||||
UCHAR Data[0];
|
||||
} DICTIONARY_HEADER, *PDICTIONARY_HEADER;
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
InitializeDictionary(
|
||||
IN PDICTIONARY Dictionary
|
||||
)
|
||||
{
|
||||
RtlZeroMemory(Dictionary, sizeof(DICTIONARY));
|
||||
Dictionary->Signature = DICTIONARY_SIGNATURE;
|
||||
KeInitializeSpinLock(&Dictionary->SpinLock);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
TestDictionarySignature(
|
||||
IN PDICTIONARY Dictionary
|
||||
)
|
||||
{
|
||||
return Dictionary->Signature == DICTIONARY_SIGNATURE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
AllocateDictionaryEntry(
|
||||
IN PDICTIONARY Dictionary,
|
||||
IN ULONGLONG Key,
|
||||
IN ULONG Size,
|
||||
IN ULONG Tag,
|
||||
OUT PVOID *Entry
|
||||
)
|
||||
{
|
||||
PDICTIONARY_HEADER header;
|
||||
KIRQL oldIrql;
|
||||
PDICTIONARY_HEADER *entry;
|
||||
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
*Entry = NULL;
|
||||
|
||||
header = ExAllocatePoolWithTag(NonPagedPool,
|
||||
Size + sizeof(DICTIONARY_HEADER),
|
||||
Tag);
|
||||
|
||||
if(header == NULL) {
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlZeroMemory(header, sizeof(DICTIONARY_HEADER) + Size);
|
||||
header->Key = Key;
|
||||
|
||||
//
|
||||
// Find the correct location for this entry in the dictionary.
|
||||
//
|
||||
|
||||
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
||||
|
||||
TRY {
|
||||
|
||||
entry = &(Dictionary->List);
|
||||
|
||||
while(*entry != NULL) {
|
||||
if((*entry)->Key == Key) {
|
||||
|
||||
//
|
||||
// Dictionary must have unique keys.
|
||||
//
|
||||
|
||||
status = STATUS_OBJECT_NAME_COLLISION;
|
||||
LEAVE;
|
||||
|
||||
} else if ((*entry)->Key < Key) {
|
||||
|
||||
//
|
||||
// We will go ahead and insert the key in here.
|
||||
//
|
||||
break;
|
||||
} else {
|
||||
entry = &((*entry)->Next);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If we make it here then we will go ahead and do the insertion.
|
||||
//
|
||||
|
||||
header->Next = *entry;
|
||||
*entry = header;
|
||||
|
||||
} FINALLY {
|
||||
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
||||
|
||||
if(!NT_SUCCESS(status)) {
|
||||
ExFreePool(header);
|
||||
} else {
|
||||
*Entry = (PVOID) header->Data;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
GetDictionaryEntry(
|
||||
IN PDICTIONARY Dictionary,
|
||||
IN ULONGLONG Key
|
||||
)
|
||||
{
|
||||
PDICTIONARY_HEADER entry;
|
||||
PVOID data;
|
||||
KIRQL oldIrql;
|
||||
|
||||
|
||||
data = NULL;
|
||||
|
||||
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
||||
|
||||
entry = Dictionary->List;
|
||||
while (entry != NULL) {
|
||||
|
||||
if (entry->Key == Key) {
|
||||
data = entry->Data;
|
||||
break;
|
||||
} else {
|
||||
entry = entry->Next;
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
FreeDictionaryEntry(
|
||||
IN PDICTIONARY Dictionary,
|
||||
IN PVOID Entry
|
||||
)
|
||||
{
|
||||
PDICTIONARY_HEADER header;
|
||||
PDICTIONARY_HEADER *entry;
|
||||
KIRQL oldIrql;
|
||||
BOOLEAN found;
|
||||
|
||||
found = FALSE;
|
||||
header = CONTAINING_RECORD(Entry, DICTIONARY_HEADER, Data);
|
||||
|
||||
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
||||
|
||||
entry = &(Dictionary->List);
|
||||
while(*entry != NULL) {
|
||||
|
||||
if(*entry == header) {
|
||||
*entry = header->Next;
|
||||
found = TRUE;
|
||||
break;
|
||||
} else {
|
||||
entry = &(*entry)->Next;
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
||||
|
||||
//
|
||||
// calling this w/an invalid pointer invalidates the dictionary system,
|
||||
// so ASSERT() that we never try to Free something not in the list
|
||||
//
|
||||
|
||||
ASSERT(found);
|
||||
if (found) {
|
||||
ExFreePool(header);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
|
||||
|
||||
#include <ntdef.h>
|
||||
#include <initguid.h>
|
||||
#include <ioevent.h>
|
||||
|
||||
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
|
|
@ -1,419 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1990 - 1998
|
||||
|
||||
Module Name:
|
||||
|
||||
lock.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This is the NT SCSI port driver.
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
This module is a driver dll for scsi miniports.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
LONG LockHighWatermark = 0;
|
||||
LONG LockLowWatermark = 0;
|
||||
LONG MaxLockedMinutes = 5;
|
||||
|
||||
//
|
||||
// Structure used for tracking remove lock allocations in checked builds
|
||||
//
|
||||
typedef struct _REMOVE_TRACKING_BLOCK {
|
||||
struct _REMOVE_TRACKING_BLOCK *NextBlock;
|
||||
PVOID Tag;
|
||||
LARGE_INTEGER TimeLocked;
|
||||
PCSTR File;
|
||||
ULONG Line;
|
||||
} REMOVE_TRACKING_BLOCK, *PREMOVE_TRACKING_BLOCK;
|
||||
|
||||
|
||||
/*++////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassAcquireRemoveLockEx()
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine is called to acquire the remove lock on the device object.
|
||||
While the lock is held, the caller can assume that no pending pnp REMOVE
|
||||
requests will be completed.
|
||||
|
||||
The lock should be acquired immediately upon entering a dispatch routine.
|
||||
It should also be acquired before creating any new reference to the
|
||||
device object if there's a chance of releasing the reference before the
|
||||
new one is done.
|
||||
|
||||
This routine will return TRUE if the lock was successfully acquired or
|
||||
FALSE if it cannot be because the device object has already been removed.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - the device object to lock
|
||||
|
||||
Tag - Used for tracking lock allocation and release. If an irp is
|
||||
specified when acquiring the lock then the same Tag must be
|
||||
used to release the lock before the Tag is completed.
|
||||
|
||||
Return Value:
|
||||
|
||||
The value of the IsRemoved flag in the device extension. If this is
|
||||
non-zero then the device object has received a Remove irp and non-cleanup
|
||||
IRP's should fail.
|
||||
|
||||
If the value is REMOVE_COMPLETE, the caller should not even release the
|
||||
lock.
|
||||
|
||||
--*/
|
||||
ULONG
|
||||
NTAPI
|
||||
ClassAcquireRemoveLockEx(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OPTIONAL PVOID Tag,
|
||||
IN PCSTR File,
|
||||
IN ULONG Line
|
||||
)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||
LONG lockValue;
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Grab the remove lock
|
||||
//
|
||||
lockValue = InterlockedIncrement(&commonExtension->RemoveLock);
|
||||
|
||||
#if DBG
|
||||
|
||||
DebugPrint((ClassDebugRemoveLock, "ClassAcquireRemoveLock: "
|
||||
"Acquired for Object %p & irp %p - count is %d\n",
|
||||
DeviceObject, Tag, lockValue));
|
||||
|
||||
ASSERTMSG("ClassAcquireRemoveLock - lock value was negative : ",
|
||||
(lockValue > 0));
|
||||
|
||||
ASSERTMSG("RemoveLock increased to meet LockHighWatermark",
|
||||
((LockHighWatermark == 0) ||
|
||||
(lockValue != LockHighWatermark)));
|
||||
|
||||
if (commonExtension->IsRemoved != REMOVE_COMPLETE){
|
||||
PREMOVE_TRACKING_BLOCK trackingBlock;
|
||||
|
||||
trackingBlock = ExAllocatePool(NonPagedPool,
|
||||
sizeof(REMOVE_TRACKING_BLOCK));
|
||||
|
||||
if(trackingBlock == NULL) {
|
||||
|
||||
KIRQL oldIrql;
|
||||
|
||||
KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||
&oldIrql);
|
||||
|
||||
commonExtension->RemoveTrackingUntrackedCount++;
|
||||
|
||||
DebugPrint((ClassDebugWarning, ">>>>>ClassAcquireRemoveLock: "
|
||||
"Cannot track Tag %p - currently %d untracked requests\n",
|
||||
Tag, commonExtension->RemoveTrackingUntrackedCount));
|
||||
|
||||
KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||
oldIrql);
|
||||
}
|
||||
else {
|
||||
PREMOVE_TRACKING_BLOCK *removeTrackingList =
|
||||
(PREMOVE_TRACKING_BLOCK*)&commonExtension->RemoveTrackingList;
|
||||
|
||||
KIRQL oldIrql;
|
||||
|
||||
trackingBlock->Tag = Tag;
|
||||
|
||||
trackingBlock->File = File;
|
||||
trackingBlock->Line = Line;
|
||||
|
||||
KeQueryTickCount((&trackingBlock->TimeLocked));
|
||||
|
||||
KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||
&oldIrql);
|
||||
|
||||
while(*removeTrackingList != NULL) {
|
||||
|
||||
if((*removeTrackingList)->Tag > Tag) {
|
||||
break;
|
||||
}
|
||||
|
||||
if((*removeTrackingList)->Tag == Tag) {
|
||||
|
||||
DebugPrint((ClassDebugError, ">>>>>ClassAcquireRemoveLock: "
|
||||
"already tracking Tag %p\n", Tag));
|
||||
DebugPrint((ClassDebugError, ">>>>>ClassAcquireRemoveLock: "
|
||||
"acquired in file %s on line %d\n",
|
||||
(*removeTrackingList)->File,
|
||||
(*removeTrackingList)->Line));
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
removeTrackingList = &((*removeTrackingList)->NextBlock);
|
||||
}
|
||||
|
||||
trackingBlock->NextBlock = *removeTrackingList;
|
||||
*removeTrackingList = trackingBlock;
|
||||
|
||||
KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||
oldIrql);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return (commonExtension->IsRemoved);
|
||||
}
|
||||
|
||||
/*++////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassReleaseRemoveLock()
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine is called to release the remove lock on the device object. It
|
||||
must be called when finished using a previously locked reference to the
|
||||
device object. If an Tag was specified when acquiring the lock then the
|
||||
same Tag must be specified when releasing the lock.
|
||||
|
||||
When the lock count reduces to zero, this routine will signal the waiting
|
||||
remove Tag to delete the device object. As a result the DeviceObject
|
||||
pointer should not be used again once the lock has been released.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - the device object to lock
|
||||
|
||||
Tag - The irp (if any) specified when acquiring the lock. This is used
|
||||
for lock tracking purposes
|
||||
|
||||
Return Value:
|
||||
|
||||
none
|
||||
|
||||
--*/
|
||||
VOID
|
||||
NTAPI
|
||||
ClassReleaseRemoveLock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OPTIONAL PIRP Tag
|
||||
)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||
LONG lockValue;
|
||||
|
||||
#if DBG
|
||||
PREMOVE_TRACKING_BLOCK *listEntry =
|
||||
(PREMOVE_TRACKING_BLOCK*)&commonExtension->RemoveTrackingList;
|
||||
|
||||
BOOLEAN found = FALSE;
|
||||
|
||||
LONGLONG maxCount;
|
||||
|
||||
BOOLEAN isRemoved = (commonExtension->IsRemoved == REMOVE_COMPLETE);
|
||||
|
||||
KIRQL oldIrql;
|
||||
|
||||
if(isRemoved) {
|
||||
DBGTRAP(("ClassReleaseRemoveLock: REMOVE_COMPLETE set; this should never happen"));
|
||||
InterlockedDecrement(&(commonExtension->RemoveLock));
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check the tick count and make sure this thing hasn't been locked
|
||||
// for more than MaxLockedMinutes.
|
||||
//
|
||||
|
||||
maxCount = KeQueryTimeIncrement() * 10; // microseconds
|
||||
maxCount *= 1000; // milliseconds
|
||||
maxCount *= 1000; // seconds
|
||||
maxCount *= 60; // minutes
|
||||
maxCount *= MaxLockedMinutes;
|
||||
|
||||
DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: "
|
||||
"maxCount = %0I64x\n", maxCount));
|
||||
|
||||
KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||
&oldIrql);
|
||||
|
||||
while(*listEntry != NULL) {
|
||||
|
||||
PREMOVE_TRACKING_BLOCK block;
|
||||
LARGE_INTEGER difference;
|
||||
|
||||
block = *listEntry;
|
||||
|
||||
KeQueryTickCount((&difference));
|
||||
|
||||
difference.QuadPart -= block->TimeLocked.QuadPart;
|
||||
|
||||
DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: "
|
||||
"Object %p (tag %p) locked for %I64d ticks\n",
|
||||
DeviceObject, block->Tag, difference.QuadPart));
|
||||
|
||||
if(difference.QuadPart >= maxCount) {
|
||||
|
||||
DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: "
|
||||
"Object %p (tag %p) locked for %I64d ticks - TOO LONG\n",
|
||||
DeviceObject, block->Tag, difference.QuadPart));
|
||||
DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: "
|
||||
"Lock acquired in file %s on line %d\n",
|
||||
block->File, block->Line));
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
if((found == FALSE) && ((*listEntry)->Tag == Tag)) {
|
||||
|
||||
*listEntry = block->NextBlock;
|
||||
ExFreePool(block);
|
||||
found = TRUE;
|
||||
|
||||
} else {
|
||||
|
||||
listEntry = &((*listEntry)->NextBlock);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
if(commonExtension->RemoveTrackingUntrackedCount == 0) {
|
||||
DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: "
|
||||
"Couldn't find Tag %p in the lock tracking list\n",
|
||||
Tag));
|
||||
ASSERT(FALSE);
|
||||
} else {
|
||||
DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: "
|
||||
"Couldn't find Tag %p in the lock tracking list - "
|
||||
"may be one of the %d untracked requests still "
|
||||
"outstanding\n",
|
||||
Tag,
|
||||
commonExtension->RemoveTrackingUntrackedCount));
|
||||
|
||||
commonExtension->RemoveTrackingUntrackedCount--;
|
||||
ASSERT(commonExtension->RemoveTrackingUntrackedCount >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||
oldIrql);
|
||||
|
||||
#endif
|
||||
|
||||
lockValue = InterlockedDecrement(&commonExtension->RemoveLock);
|
||||
|
||||
DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: "
|
||||
"Released for Object %p & irp %p - count is %d\n",
|
||||
DeviceObject, Tag, lockValue));
|
||||
|
||||
ASSERT(lockValue >= 0);
|
||||
|
||||
ASSERTMSG("RemoveLock decreased to meet LockLowWatermark",
|
||||
((LockLowWatermark == 0) || !(lockValue == LockLowWatermark)));
|
||||
|
||||
if(lockValue == 0) {
|
||||
|
||||
ASSERT(commonExtension->IsRemoved);
|
||||
|
||||
//
|
||||
// The device needs to be removed. Signal the remove event
|
||||
// that it's safe to go ahead.
|
||||
//
|
||||
|
||||
DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: "
|
||||
"Release for object %p & irp %p caused lock to go to zero\n",
|
||||
DeviceObject, Tag));
|
||||
|
||||
KeSetEvent(&commonExtension->RemoveEvent,
|
||||
IO_NO_INCREMENT,
|
||||
FALSE);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*++////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClassCompleteRequest()
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine is a wrapper around (and should be used instead of)
|
||||
IoCompleteRequest. It is used primarily for debugging purposes.
|
||||
The routine will assert if the Irp being completed is still holding
|
||||
the release lock.
|
||||
|
||||
Arguments:
|
||||
|
||||
DeviceObject - the device object that was handling this request
|
||||
|
||||
Irp - the irp to be completed by IoCompleteRequest
|
||||
|
||||
PriorityBoost - the priority boost to pass to IoCompleteRequest
|
||||
|
||||
Return Value:
|
||||
|
||||
none
|
||||
|
||||
--*/
|
||||
VOID
|
||||
NTAPI
|
||||
ClassCompleteRequest(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN CCHAR PriorityBoost
|
||||
)
|
||||
{
|
||||
|
||||
#if DBG
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||
PREMOVE_TRACKING_BLOCK *listEntry =
|
||||
(PREMOVE_TRACKING_BLOCK*)&commonExtension->RemoveTrackingList;
|
||||
|
||||
KIRQL oldIrql;
|
||||
|
||||
KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||
&oldIrql);
|
||||
|
||||
while(*listEntry != NULL) {
|
||||
|
||||
if((*listEntry)->Tag == Irp) {
|
||||
break;
|
||||
}
|
||||
|
||||
listEntry = &((*listEntry)->NextBlock);
|
||||
}
|
||||
|
||||
if(*listEntry != NULL) {
|
||||
|
||||
DebugPrint((ClassDebugError, ">>>>>ClassCompleteRequest: "
|
||||
"Irp %p completed while still holding the remove lock\n",
|
||||
Irp));
|
||||
DebugPrint((ClassDebugError, ">>>>>ClassCompleteRequest: "
|
||||
"Lock acquired in file %s on line %d\n",
|
||||
(*listEntry)->File, (*listEntry)->Line));
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql);
|
||||
#endif
|
||||
|
||||
IoCompleteRequest(Irp, PriorityBoost);
|
||||
return;
|
||||
} // end ClassCompleteRequest()
|
||||
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,341 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
retry.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Packet retry routines for CLASSPNP
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
/*
|
||||
* InterpretTransferPacketError
|
||||
*
|
||||
* Interpret the SRB error into a meaningful IRP status.
|
||||
* ClassInterpretSenseInfo also may modify the SRB for the retry.
|
||||
*
|
||||
* Return TRUE iff packet should be retried.
|
||||
*/
|
||||
BOOLEAN NTAPI InterpretTransferPacketError(PTRANSFER_PACKET Pkt)
|
||||
{
|
||||
BOOLEAN shouldRetry = FALSE;
|
||||
PCDB pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||
|
||||
/*
|
||||
* Interpret the error using the returned sense info first.
|
||||
*/
|
||||
Pkt->RetryIntervalSec = 0;
|
||||
if (pCdb->MEDIA_REMOVAL.OperationCode == SCSIOP_MEDIUM_REMOVAL){
|
||||
/*
|
||||
* This is an Ejection Control SRB. Interpret its sense info specially.
|
||||
*/
|
||||
shouldRetry = ClassInterpretSenseInfo(
|
||||
Pkt->Fdo,
|
||||
&Pkt->Srb,
|
||||
IRP_MJ_SCSI,
|
||||
0,
|
||||
MAXIMUM_RETRIES - Pkt->NumRetries,
|
||||
&Pkt->Irp->IoStatus.Status,
|
||||
&Pkt->RetryIntervalSec);
|
||||
if (shouldRetry){
|
||||
/*
|
||||
* If the device is not ready, wait at least 2 seconds before retrying.
|
||||
*/
|
||||
PSENSE_DATA senseInfoBuffer = Pkt->Srb.SenseInfoBuffer;
|
||||
ASSERT(senseInfoBuffer);
|
||||
if (((Pkt->Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY) &&
|
||||
(senseInfoBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)) ||
|
||||
(SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)){
|
||||
|
||||
Pkt->RetryIntervalSec = MAX(Pkt->RetryIntervalSec, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((pCdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) ||
|
||||
(pCdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE10)){
|
||||
/*
|
||||
* This is an Mode Sense SRB. Interpret its sense info specially.
|
||||
*/
|
||||
shouldRetry = ClassInterpretSenseInfo(
|
||||
Pkt->Fdo,
|
||||
&Pkt->Srb,
|
||||
IRP_MJ_SCSI,
|
||||
0,
|
||||
MAXIMUM_RETRIES - Pkt->NumRetries,
|
||||
&Pkt->Irp->IoStatus.Status,
|
||||
&Pkt->RetryIntervalSec);
|
||||
if (shouldRetry){
|
||||
/*
|
||||
* If the device is not ready, wait at least 2 seconds before retrying.
|
||||
*/
|
||||
PSENSE_DATA senseInfoBuffer = Pkt->Srb.SenseInfoBuffer;
|
||||
ASSERT(senseInfoBuffer);
|
||||
if (((Pkt->Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY) &&
|
||||
(senseInfoBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)) ||
|
||||
(SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)){
|
||||
|
||||
Pkt->RetryIntervalSec = MAX(Pkt->RetryIntervalSec, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some special cases for mode sense.
|
||||
*/
|
||||
if (Pkt->Irp->IoStatus.Status == STATUS_VERIFY_REQUIRED){
|
||||
shouldRetry = TRUE;
|
||||
}
|
||||
else if (SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN){
|
||||
/*
|
||||
* This is a HACK.
|
||||
* Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
|
||||
* underrun (i.e. success, and the buffer is longer than needed).
|
||||
* So treat this as a success.
|
||||
*/
|
||||
Pkt->Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
InterlockedExchangeAdd((PLONG)&Pkt->OriginalIrp->IoStatus.Information, (LONG)Pkt->Srb.DataTransferLength);
|
||||
shouldRetry = FALSE;
|
||||
}
|
||||
}
|
||||
else if (pCdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY){
|
||||
/*
|
||||
* This is a Drive Capacity SRB. Interpret its sense info specially.
|
||||
*/
|
||||
shouldRetry = ClassInterpretSenseInfo(
|
||||
Pkt->Fdo,
|
||||
&Pkt->Srb,
|
||||
IRP_MJ_SCSI,
|
||||
0,
|
||||
MAXIMUM_RETRIES - Pkt->NumRetries,
|
||||
&Pkt->Irp->IoStatus.Status,
|
||||
&Pkt->RetryIntervalSec);
|
||||
if (Pkt->Irp->IoStatus.Status == STATUS_VERIFY_REQUIRED){
|
||||
shouldRetry = TRUE;
|
||||
}
|
||||
}
|
||||
else if ((pCdb->CDB10.OperationCode == SCSIOP_READ) ||
|
||||
(pCdb->CDB10.OperationCode == SCSIOP_WRITE)){
|
||||
/*
|
||||
* This is a Read/Write Data packet.
|
||||
*/
|
||||
PIO_STACK_LOCATION origCurrentSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp);
|
||||
|
||||
shouldRetry = ClassInterpretSenseInfo(
|
||||
Pkt->Fdo,
|
||||
&Pkt->Srb,
|
||||
origCurrentSp->MajorFunction,
|
||||
0,
|
||||
MAXIMUM_RETRIES - Pkt->NumRetries,
|
||||
&Pkt->Irp->IoStatus.Status,
|
||||
&Pkt->RetryIntervalSec);
|
||||
/*
|
||||
* Deal with some special cases.
|
||||
*/
|
||||
if (Pkt->Irp->IoStatus.Status == STATUS_INSUFFICIENT_RESOURCES){
|
||||
/*
|
||||
* We are in extreme low-memory stress.
|
||||
* We will retry in smaller chunks.
|
||||
*/
|
||||
shouldRetry = TRUE;
|
||||
}
|
||||
else if (TEST_FLAG(origCurrentSp->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
|
||||
(Pkt->Irp->IoStatus.Status == STATUS_VERIFY_REQUIRED)){
|
||||
/*
|
||||
* We are still verifying a (possibly) reloaded disk/cdrom.
|
||||
* So retry the request.
|
||||
*/
|
||||
Pkt->Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
|
||||
shouldRetry = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBGERR(("Unhandled SRB Function %xh in error path for packet %p (did miniport change Srb.Cdb.OperationCode ?)", (ULONG)pCdb->CDB10.OperationCode, Pkt));
|
||||
}
|
||||
|
||||
return shouldRetry;
|
||||
}
|
||||
|
||||
/*
|
||||
* RetryTransferPacket
|
||||
*
|
||||
* Retry sending a TRANSFER_PACKET.
|
||||
*
|
||||
* Return TRUE iff the packet is complete.
|
||||
* (if so the status in pkt->irp is the final status).
|
||||
*/
|
||||
BOOLEAN NTAPI RetryTransferPacket(PTRANSFER_PACKET Pkt)
|
||||
{
|
||||
BOOLEAN packetDone;
|
||||
|
||||
DBGTRACE(ClassDebugTrace, ("retrying failed transfer (pkt=%ph, op=%s)", Pkt, DBGGETSCSIOPSTR(&Pkt->Srb)));
|
||||
|
||||
ASSERT(Pkt->NumRetries > 0);
|
||||
Pkt->NumRetries--;
|
||||
|
||||
/*
|
||||
* Tone down performance on the retry.
|
||||
* This increases the chance for success on the retry.
|
||||
* We've seen instances of drives that fail consistently but then start working
|
||||
* once this scale-down is applied.
|
||||
*/
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||
CLEAR_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
|
||||
Pkt->Srb.QueueTag = SP_UNTAGGED;
|
||||
|
||||
if (Pkt->Irp->IoStatus.Status == STATUS_INSUFFICIENT_RESOURCES){
|
||||
PCDB pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||
BOOLEAN isReadWrite = ((pCdb->CDB10.OperationCode == SCSIOP_READ) ||
|
||||
(pCdb->CDB10.OperationCode == SCSIOP_WRITE));
|
||||
|
||||
if (Pkt->InLowMemRetry || !isReadWrite){
|
||||
/*
|
||||
* This should never happen.
|
||||
* The memory manager guarantees that at least four pages will
|
||||
* be available to allow forward progress in the port driver.
|
||||
* So a one-page transfer should never fail with insufficient resources.
|
||||
*/
|
||||
ASSERT(isReadWrite && !Pkt->InLowMemRetry);
|
||||
packetDone = TRUE;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* We are in low-memory stress.
|
||||
* Start the low-memory retry state machine, which tries to
|
||||
* resend the packet in little one-page chunks.
|
||||
*/
|
||||
InitLowMemRetry( Pkt,
|
||||
Pkt->BufPtrCopy,
|
||||
Pkt->BufLenCopy,
|
||||
Pkt->TargetLocationCopy);
|
||||
StepLowMemRetry(Pkt);
|
||||
packetDone = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Retry the packet by simply resending it after a delay.
|
||||
* Put the packet back in the pending queue and
|
||||
* schedule a timer to retry the transfer.
|
||||
*
|
||||
* Do not call SetupReadWriteTransferPacket again because:
|
||||
* (1) The minidriver may have set some bits
|
||||
* in the SRB that it needs again and
|
||||
* (2) doing so would reset numRetries.
|
||||
*
|
||||
* BECAUSE we do not call SetupReadWriteTransferPacket again,
|
||||
* we have to reset a couple fields in the SRB that
|
||||
* some miniports overwrite when they fail an SRB.
|
||||
*/
|
||||
|
||||
Pkt->Srb.DataBuffer = Pkt->BufPtrCopy;
|
||||
Pkt->Srb.DataTransferLength = Pkt->BufLenCopy;
|
||||
|
||||
if (Pkt->RetryIntervalSec == 0){
|
||||
/*
|
||||
* Always delay by at least a little when retrying.
|
||||
* Some problems (e.g. CRC errors) are not recoverable without a slight delay.
|
||||
*/
|
||||
LARGE_INTEGER timerPeriod;
|
||||
|
||||
timerPeriod.HighPart = -1;
|
||||
timerPeriod.LowPart = -(LONG)((ULONG)MINIMUM_RETRY_UNITS*KeQueryTimeIncrement());
|
||||
KeInitializeTimer(&Pkt->RetryTimer);
|
||||
KeInitializeDpc(&Pkt->RetryTimerDPC, TransferPacketRetryTimerDpc, Pkt);
|
||||
KeSetTimer(&Pkt->RetryTimer, timerPeriod, &Pkt->RetryTimerDPC);
|
||||
}
|
||||
else {
|
||||
LARGE_INTEGER timerPeriod;
|
||||
|
||||
ASSERT(Pkt->RetryIntervalSec < 100); // sanity check
|
||||
timerPeriod.HighPart = -1;
|
||||
timerPeriod.LowPart = Pkt->RetryIntervalSec*-10000000;
|
||||
KeInitializeTimer(&Pkt->RetryTimer);
|
||||
KeInitializeDpc(&Pkt->RetryTimerDPC, TransferPacketRetryTimerDpc, Pkt);
|
||||
KeSetTimer(&Pkt->RetryTimer, timerPeriod, &Pkt->RetryTimerDPC);
|
||||
}
|
||||
packetDone = FALSE;
|
||||
}
|
||||
|
||||
return packetDone;
|
||||
}
|
||||
|
||||
VOID NTAPI TransferPacketRetryTimerDpc(IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2)
|
||||
{
|
||||
PTRANSFER_PACKET pkt = (PTRANSFER_PACKET)DeferredContext;
|
||||
SubmitTransferPacket(pkt);
|
||||
}
|
||||
|
||||
VOID NTAPI InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation)
|
||||
{
|
||||
ASSERT(Len > 0);
|
||||
ASSERT(!Pkt->InLowMemRetry);
|
||||
Pkt->InLowMemRetry = TRUE;
|
||||
Pkt->LowMemRetry_remainingBufPtr = BufPtr;
|
||||
Pkt->LowMemRetry_remainingBufLen = Len;
|
||||
Pkt->LowMemRetry_nextChunkTargetLocation = TargetLocation;
|
||||
}
|
||||
|
||||
/*
|
||||
* StepLowMemRetry
|
||||
*
|
||||
* During extreme low-memory stress, this function retries
|
||||
* a packet in small one-page chunks, sent serially.
|
||||
*
|
||||
* Returns TRUE iff the packet is done.
|
||||
*/
|
||||
BOOLEAN NTAPI StepLowMemRetry(PTRANSFER_PACKET Pkt)
|
||||
{
|
||||
BOOLEAN packetDone;
|
||||
|
||||
if (Pkt->LowMemRetry_remainingBufLen == 0){
|
||||
packetDone = TRUE;
|
||||
}
|
||||
else {
|
||||
ULONG thisChunkLen;
|
||||
ULONG bytesToNextPageBoundary;
|
||||
|
||||
/*
|
||||
* Make sure the little chunk we send is <= a page length
|
||||
* AND that it does not cross any page boundaries.
|
||||
*/
|
||||
bytesToNextPageBoundary = PAGE_SIZE-(ULONG)((ULONG_PTR)Pkt->LowMemRetry_remainingBufPtr%PAGE_SIZE);
|
||||
thisChunkLen = MIN(Pkt->LowMemRetry_remainingBufLen, bytesToNextPageBoundary);
|
||||
|
||||
/*
|
||||
* Set up the transfer packet for the new little chunk.
|
||||
* This will reset numRetries so that we retry each chunk as required.
|
||||
*/
|
||||
SetupReadWriteTransferPacket(Pkt,
|
||||
Pkt->LowMemRetry_remainingBufPtr,
|
||||
thisChunkLen,
|
||||
Pkt->LowMemRetry_nextChunkTargetLocation,
|
||||
Pkt->OriginalIrp);
|
||||
|
||||
Pkt->LowMemRetry_remainingBufPtr += thisChunkLen;
|
||||
Pkt->LowMemRetry_remainingBufLen -= thisChunkLen;
|
||||
Pkt->LowMemRetry_nextChunkTargetLocation.QuadPart += thisChunkLen;
|
||||
|
||||
SubmitTransferPacket(Pkt);
|
||||
packetDone = FALSE;
|
||||
}
|
||||
|
||||
return packetDone;
|
||||
}
|
|
@ -1,553 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
utils.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI class driver routines
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, ClassGetDeviceParameter)
|
||||
#pragma alloc_text(PAGE, ClassScanForSpecial)
|
||||
#pragma alloc_text(PAGE, ClassSetDeviceParameter)
|
||||
#endif
|
||||
|
||||
// custom string match -- careful!
|
||||
BOOLEAN NTAPI ClasspMyStringMatches(IN PCSTR StringToMatch OPTIONAL, IN PCSTR TargetString)
|
||||
{
|
||||
ULONG length; // strlen returns an int, not size_t (!)
|
||||
PAGED_CODE();
|
||||
ASSERT(TargetString);
|
||||
// if no match requested, return TRUE
|
||||
if (StringToMatch == NULL) {
|
||||
return TRUE;
|
||||
}
|
||||
// cache the string length for efficiency
|
||||
length = strlen(StringToMatch);
|
||||
// ZERO-length strings may only match zero-length strings
|
||||
if (length == 0) {
|
||||
return (strlen(TargetString) == 0);
|
||||
}
|
||||
// strncmp returns zero if the strings match
|
||||
return (strncmp(StringToMatch, TargetString, length) == 0);
|
||||
}
|
||||
|
||||
VOID NTAPI ClassGetDeviceParameter(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PWSTR SubkeyName OPTIONAL,
|
||||
IN PWSTR ParameterName,
|
||||
IN OUT PULONG ParameterValue // also default value
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
RTL_QUERY_REGISTRY_TABLE queryTable[2];
|
||||
HANDLE deviceParameterHandle;
|
||||
HANDLE deviceSubkeyHandle;
|
||||
ULONG defaultParameterValue;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// open the given parameter
|
||||
//
|
||||
|
||||
status = IoOpenDeviceRegistryKey(FdoExtension->LowerPdo,
|
||||
PLUGPLAY_REGKEY_DEVICE,
|
||||
KEY_READ,
|
||||
&deviceParameterHandle);
|
||||
|
||||
if (NT_SUCCESS(status) && (SubkeyName != NULL)) {
|
||||
|
||||
UNICODE_STRING subkeyName;
|
||||
OBJECT_ATTRIBUTES objectAttributes;
|
||||
|
||||
RtlInitUnicodeString(&subkeyName, SubkeyName);
|
||||
InitializeObjectAttributes(&objectAttributes,
|
||||
&subkeyName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
deviceParameterHandle,
|
||||
NULL);
|
||||
|
||||
status = ZwOpenKey(&deviceSubkeyHandle,
|
||||
KEY_READ,
|
||||
&objectAttributes);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
ZwClose(deviceParameterHandle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
|
||||
RtlZeroMemory(queryTable, sizeof(queryTable));
|
||||
|
||||
defaultParameterValue = *ParameterValue;
|
||||
|
||||
queryTable->Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
||||
queryTable->Name = ParameterName;
|
||||
queryTable->EntryContext = ParameterValue;
|
||||
queryTable->DefaultType = REG_DWORD;
|
||||
queryTable->DefaultData = NULL;
|
||||
queryTable->DefaultLength = 0;
|
||||
|
||||
status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
|
||||
(PWSTR)(SubkeyName ?
|
||||
deviceSubkeyHandle :
|
||||
deviceParameterHandle),
|
||||
queryTable,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
*ParameterValue = defaultParameterValue; // use default value
|
||||
}
|
||||
|
||||
//
|
||||
// close what we open
|
||||
//
|
||||
|
||||
if (SubkeyName) {
|
||||
ZwClose(deviceSubkeyHandle);
|
||||
}
|
||||
|
||||
ZwClose(deviceParameterHandle);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} // end ClassGetDeviceParameter()
|
||||
|
||||
NTSTATUS NTAPI ClassSetDeviceParameter(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PWSTR SubkeyName OPTIONAL,
|
||||
IN PWSTR ParameterName,
|
||||
IN ULONG ParameterValue)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE deviceParameterHandle;
|
||||
HANDLE deviceSubkeyHandle;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// open the given parameter
|
||||
//
|
||||
|
||||
status = IoOpenDeviceRegistryKey(FdoExtension->LowerPdo,
|
||||
PLUGPLAY_REGKEY_DEVICE,
|
||||
KEY_READ | KEY_WRITE,
|
||||
&deviceParameterHandle);
|
||||
|
||||
if (NT_SUCCESS(status) && (SubkeyName != NULL)) {
|
||||
|
||||
UNICODE_STRING subkeyName;
|
||||
OBJECT_ATTRIBUTES objectAttributes;
|
||||
|
||||
RtlInitUnicodeString(&subkeyName, SubkeyName);
|
||||
InitializeObjectAttributes(&objectAttributes,
|
||||
&subkeyName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
deviceParameterHandle,
|
||||
NULL);
|
||||
|
||||
status = ZwCreateKey(&deviceSubkeyHandle,
|
||||
KEY_READ | KEY_WRITE,
|
||||
&objectAttributes,
|
||||
0, NULL, 0, NULL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
ZwClose(deviceParameterHandle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
|
||||
status = RtlWriteRegistryValue(
|
||||
RTL_REGISTRY_HANDLE,
|
||||
(PWSTR) (SubkeyName ?
|
||||
deviceSubkeyHandle :
|
||||
deviceParameterHandle),
|
||||
ParameterName,
|
||||
REG_DWORD,
|
||||
&ParameterValue,
|
||||
sizeof(ULONG));
|
||||
|
||||
//
|
||||
// close what we open
|
||||
//
|
||||
|
||||
if (SubkeyName) {
|
||||
ZwClose(deviceSubkeyHandle);
|
||||
}
|
||||
|
||||
ZwClose(deviceParameterHandle);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
} // end ClassSetDeviceParameter()
|
||||
|
||||
/*
|
||||
* ClassScanForSpecial
|
||||
*
|
||||
* This routine was written to simplify scanning for special
|
||||
* hardware based upon id strings. it does not check the registry.
|
||||
*/
|
||||
|
||||
VOID NTAPI ClassScanForSpecial(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN CLASSPNP_SCAN_FOR_SPECIAL_INFO DeviceList[],
|
||||
IN PCLASS_SCAN_FOR_SPECIAL_HANDLER Function)
|
||||
{
|
||||
PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
|
||||
PCSTR vendorId;
|
||||
PCSTR productId;
|
||||
PCSTR productRevision;
|
||||
CHAR nullString[] = "";
|
||||
//ULONG j;
|
||||
|
||||
PAGED_CODE();
|
||||
ASSERT(DeviceList);
|
||||
ASSERT(Function);
|
||||
|
||||
deviceDescriptor = FdoExtension->DeviceDescriptor;
|
||||
|
||||
if (DeviceList == NULL) {
|
||||
return;
|
||||
}
|
||||
if (Function == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// SCSI sets offsets to -1, ATAPI sets to 0. check for both.
|
||||
//
|
||||
|
||||
if (deviceDescriptor->VendorIdOffset != 0 &&
|
||||
deviceDescriptor->VendorIdOffset != -1) {
|
||||
vendorId = ((PCSTR)deviceDescriptor);
|
||||
vendorId += deviceDescriptor->VendorIdOffset;
|
||||
} else {
|
||||
vendorId = nullString;
|
||||
}
|
||||
if (deviceDescriptor->ProductIdOffset != 0 &&
|
||||
deviceDescriptor->ProductIdOffset != -1) {
|
||||
productId = ((PCSTR)deviceDescriptor);
|
||||
productId += deviceDescriptor->ProductIdOffset;
|
||||
} else {
|
||||
productId = nullString;
|
||||
}
|
||||
if (deviceDescriptor->VendorIdOffset != 0 &&
|
||||
deviceDescriptor->VendorIdOffset != -1) {
|
||||
productRevision = ((PCSTR)deviceDescriptor);
|
||||
productRevision += deviceDescriptor->ProductRevisionOffset;
|
||||
} else {
|
||||
productRevision = nullString;
|
||||
}
|
||||
|
||||
//
|
||||
// loop while the device list is valid (not null-filled)
|
||||
//
|
||||
|
||||
for (;(DeviceList->VendorId != NULL ||
|
||||
DeviceList->ProductId != NULL ||
|
||||
DeviceList->ProductRevision != NULL);DeviceList++) {
|
||||
|
||||
if (ClasspMyStringMatches(DeviceList->VendorId, vendorId) &&
|
||||
ClasspMyStringMatches(DeviceList->ProductId, productId) &&
|
||||
ClasspMyStringMatches(DeviceList->ProductRevision, productRevision)
|
||||
) {
|
||||
|
||||
DebugPrint((1, "ClasspScanForSpecialByInquiry: Found matching "
|
||||
"controller Ven: %s Prod: %s Rev: %s\n",
|
||||
vendorId, productId, productRevision));
|
||||
|
||||
//
|
||||
// pass the context to the call back routine and exit
|
||||
//
|
||||
|
||||
(Function)(FdoExtension, DeviceList->Data);
|
||||
|
||||
//
|
||||
// for CHK builds, try to prevent wierd stacks by having a debug
|
||||
// print here. it's a hack, but i know of no other way to prevent
|
||||
// the stack from being wrong.
|
||||
//
|
||||
|
||||
DebugPrint((16, "ClasspScanForSpecialByInquiry: "
|
||||
"completed callback\n"));
|
||||
return;
|
||||
|
||||
} // else the strings did not match
|
||||
|
||||
} // none of the devices matched.
|
||||
|
||||
DebugPrint((1, "ClasspScanForSpecialByInquiry: no match found for %p\n",
|
||||
FdoExtension->DeviceObject));
|
||||
return;
|
||||
|
||||
} // end ClasspScanForSpecialByInquiry()
|
||||
|
||||
//
|
||||
// In order to provide better performance without the need to reboot,
|
||||
// we need to implement a self-adjusting method to set and clear the
|
||||
// srb flags based upon current performance.
|
||||
//
|
||||
// whenever there is an error, immediately grab the spin lock. the
|
||||
// MP perf hit here is acceptable, since we're in an error path. this
|
||||
// is also necessary because we are guaranteed to be modifying the
|
||||
// SRB flags here, setting SuccessfulIO to zero, and incrementing the
|
||||
// actual error count (which is always done within this spinlock).
|
||||
//
|
||||
// whenever there is no error, increment a counter. if there have been
|
||||
// errors on the device, and we've enabled dynamic perf, *and* we've
|
||||
// just crossed the perf threshold, then grab the spin lock and
|
||||
// double check that the threshold has, indeed been hit(*). then
|
||||
// decrement the error count, and if it's dropped sufficiently, undo
|
||||
// some of the safety changes made in the SRB flags due to the errors.
|
||||
//
|
||||
// * this works in all cases. even if lots of ios occur after the
|
||||
// previous guy went in and cleared the successfulio counter, that
|
||||
// just means that we've hit the threshold again, and so it's proper
|
||||
// to run the inner loop again.
|
||||
//
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspPerfIncrementErrorCount(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
)
|
||||
{
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
|
||||
KIRQL oldIrql;
|
||||
ULONG errors;
|
||||
|
||||
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||
|
||||
fdoData->Perf.SuccessfulIO = 0; // implicit interlock
|
||||
errors = InterlockedIncrement((PLONG)&FdoExtension->ErrorCount);
|
||||
|
||||
if (errors >= CLASS_ERROR_LEVEL_1) {
|
||||
|
||||
//
|
||||
// If the error count has exceeded the error limit, then disable
|
||||
// any tagged queuing, multiple requests per lu queueing
|
||||
// and synchronous data transfers.
|
||||
//
|
||||
// Clearing the no queue freeze flag prevents the port driver
|
||||
// from sending multiple requests per logical unit.
|
||||
//
|
||||
|
||||
CLEAR_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||
CLEAR_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
|
||||
|
||||
SET_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||
|
||||
DebugPrint((ClassDebugError, "ClasspPerfIncrementErrorCount: "
|
||||
"Too many errors; disabling tagged queuing and "
|
||||
"synchronous data tranfers.\n"));
|
||||
|
||||
}
|
||||
|
||||
if (errors >= CLASS_ERROR_LEVEL_2) {
|
||||
|
||||
//
|
||||
// If a second threshold is reached, disable disconnects.
|
||||
//
|
||||
|
||||
SET_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
|
||||
DebugPrint((ClassDebugError, "ClasspPerfIncrementErrorCount: "
|
||||
"Too many errors; disabling disconnects.\n"));
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ClasspPerfIncrementSuccessfulIo(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
)
|
||||
{
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
|
||||
KIRQL oldIrql;
|
||||
ULONG errors;
|
||||
ULONG succeeded = 0;
|
||||
|
||||
//
|
||||
// don't take a hit from the interlocked op unless we're in
|
||||
// a degraded state and we've got a threshold to hit.
|
||||
//
|
||||
|
||||
if (FdoExtension->ErrorCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fdoData->Perf.ReEnableThreshold == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
succeeded = InterlockedIncrement((PLONG)&fdoData->Perf.SuccessfulIO);
|
||||
if (succeeded < fdoData->Perf.ReEnableThreshold) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// if we hit the threshold, grab the spinlock and verify we've
|
||||
// actually done so. this allows us to ignore the spinlock 99%
|
||||
// of the time.
|
||||
//
|
||||
|
||||
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||
|
||||
//
|
||||
// re-read the value, so we don't run this multiple times
|
||||
// for a single threshold being hit. this keeps errorcount
|
||||
// somewhat useful.
|
||||
//
|
||||
|
||||
succeeded = fdoData->Perf.SuccessfulIO;
|
||||
|
||||
if ((FdoExtension->ErrorCount != 0) &&
|
||||
(fdoData->Perf.ReEnableThreshold <= succeeded)
|
||||
) {
|
||||
|
||||
fdoData->Perf.SuccessfulIO = 0; // implicit interlock
|
||||
|
||||
ASSERT(FdoExtension->ErrorCount > 0);
|
||||
errors = InterlockedDecrement((PLONG)&FdoExtension->ErrorCount);
|
||||
|
||||
//
|
||||
// note: do in reverse order of the sets "just in case"
|
||||
//
|
||||
|
||||
if (errors < CLASS_ERROR_LEVEL_2) {
|
||||
if (errors == CLASS_ERROR_LEVEL_2 - 1) {
|
||||
DebugPrint((ClassDebugError, "ClasspPerfIncrementSuccessfulIo: "
|
||||
"Error level 2 no longer required.\n"));
|
||||
}
|
||||
if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||
SRB_FLAGS_DISABLE_DISCONNECT)) {
|
||||
CLEAR_FLAG(FdoExtension->SrbFlags,
|
||||
SRB_FLAGS_DISABLE_DISCONNECT);
|
||||
}
|
||||
}
|
||||
|
||||
if (errors < CLASS_ERROR_LEVEL_1) {
|
||||
if (errors == CLASS_ERROR_LEVEL_1 - 1) {
|
||||
DebugPrint((ClassDebugError, "ClasspPerfIncrementSuccessfulIo: "
|
||||
"Error level 1 no longer required.\n"));
|
||||
}
|
||||
if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||
SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
|
||||
CLEAR_FLAG(FdoExtension->SrbFlags,
|
||||
SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||
}
|
||||
if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||
SRB_FLAGS_QUEUE_ACTION_ENABLE)) {
|
||||
SET_FLAG(FdoExtension->SrbFlags,
|
||||
SRB_FLAGS_QUEUE_ACTION_ENABLE);
|
||||
}
|
||||
if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||
SRB_FLAGS_NO_QUEUE_FREEZE)) {
|
||||
SET_FLAG(FdoExtension->SrbFlags,
|
||||
SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||
}
|
||||
}
|
||||
} // end of threshold definitely being hit for first time
|
||||
|
||||
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||
return;
|
||||
}
|
||||
|
||||
PMDL NTAPI BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen)
|
||||
{
|
||||
PMDL mdl;
|
||||
|
||||
mdl = IoAllocateMdl(Buffer, BufferLen, FALSE, FALSE, NULL);
|
||||
if (mdl){
|
||||
_SEH2_TRY {
|
||||
/*
|
||||
* We are reading from the device.
|
||||
* Therefore, the device is WRITING to the locked memory.
|
||||
* So we request IoWriteAccess.
|
||||
*/
|
||||
MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
|
||||
|
||||
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
NTSTATUS status = _SEH2_GetExceptionCode();
|
||||
|
||||
DBGWARN(("BuildReadMdl: MmProbeAndLockPages failed with %xh.", status));
|
||||
IoFreeMdl(mdl);
|
||||
mdl = NULL;
|
||||
} _SEH2_END;
|
||||
}
|
||||
else {
|
||||
DBGWARN(("BuildReadMdl: IoAllocateMdl failed"));
|
||||
}
|
||||
|
||||
return mdl;
|
||||
}
|
||||
|
||||
VOID NTAPI FreeDeviceInputMdl(PMDL Mdl)
|
||||
{
|
||||
MmUnlockPages(Mdl);
|
||||
IoFreeMdl(Mdl);
|
||||
}
|
||||
|
||||
#if 0
|
||||
VOID
|
||||
ClasspPerfResetCounters(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
)
|
||||
{
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
|
||||
KIRQL oldIrql;
|
||||
|
||||
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||
DebugPrint((ClassDebugError, "ClasspPerfResetCounters: "
|
||||
"Resetting all perf counters.\n"));
|
||||
fdoData->Perf.SuccessfulIO = 0;
|
||||
FdoExtension->ErrorCount = 0;
|
||||
|
||||
if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||
SRB_FLAGS_DISABLE_DISCONNECT)) {
|
||||
CLEAR_FLAG(FdoExtension->SrbFlags,
|
||||
SRB_FLAGS_DISABLE_DISCONNECT);
|
||||
}
|
||||
if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||
SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
|
||||
CLEAR_FLAG(FdoExtension->SrbFlags,
|
||||
SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||
}
|
||||
if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||
SRB_FLAGS_QUEUE_ACTION_ENABLE)) {
|
||||
SET_FLAG(FdoExtension->SrbFlags,
|
||||
SRB_FLAGS_QUEUE_ACTION_ENABLE);
|
||||
}
|
||||
if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||
SRB_FLAGS_NO_QUEUE_FREEZE)) {
|
||||
SET_FLAG(FdoExtension->SrbFlags,
|
||||
SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||
}
|
||||
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||
return;
|
||||
}
|
||||
#endif
|
|
@ -1,892 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
xferpkt.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Packet routines for CLASSPNP
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "classp.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, InitializeTransferPackets)
|
||||
#pragma alloc_text(PAGE, DestroyAllTransferPackets)
|
||||
#pragma alloc_text(PAGE, SetupEjectionTransferPacket)
|
||||
#pragma alloc_text(PAGE, SetupModeSenseTransferPacket)
|
||||
#endif
|
||||
|
||||
|
||||
ULONG MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||
ULONG MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||
|
||||
|
||||
/*
|
||||
* InitializeTransferPackets
|
||||
*
|
||||
* Allocate/initialize TRANSFER_PACKETs and related resources.
|
||||
*/
|
||||
NTSTATUS NTAPI InitializeTransferPackets(PDEVICE_OBJECT Fdo)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExt = Fdo->DeviceExtension;
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExt->PartitionZeroExtension->AdapterDescriptor;
|
||||
ULONG hwMaxPages;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/*
|
||||
* Precompute the maximum transfer length
|
||||
*/
|
||||
ASSERT(adapterDesc->MaximumTransferLength);
|
||||
ASSERT(adapterDesc->MaximumPhysicalPages);
|
||||
hwMaxPages = adapterDesc->MaximumPhysicalPages ? adapterDesc->MaximumPhysicalPages-1 : 0;
|
||||
|
||||
#if defined(_AMD64_SIMULATOR_)
|
||||
|
||||
//
|
||||
// The simulator appears to have a problem with large transfers.
|
||||
//
|
||||
|
||||
if (hwMaxPages > 4) {
|
||||
hwMaxPages = 4;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
fdoData->HwMaxXferLen = MIN(adapterDesc->MaximumTransferLength, hwMaxPages << PAGE_SHIFT);
|
||||
fdoData->HwMaxXferLen = MAX(fdoData->HwMaxXferLen, PAGE_SIZE);
|
||||
|
||||
fdoData->NumTotalTransferPackets = 0;
|
||||
fdoData->NumFreeTransferPackets = 0;
|
||||
InitializeSListHead(&fdoData->FreeTransferPacketsList);
|
||||
InitializeListHead(&fdoData->AllTransferPacketsList);
|
||||
InitializeListHead(&fdoData->DeferredClientIrpList);
|
||||
|
||||
/*
|
||||
* Set the packet threshold numbers based on the Windows SKU.
|
||||
*/
|
||||
if (ExVerifySuite(Personal)){
|
||||
// this is Windows Personal
|
||||
MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||
MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||
}
|
||||
else if (ExVerifySuite(Enterprise) || ExVerifySuite(DataCenter)){
|
||||
// this is Advanced Server or Datacenter
|
||||
MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise;
|
||||
MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise;
|
||||
}
|
||||
else if (ExVerifySuite(TerminalServer)){
|
||||
// this is standard Server or Pro with terminal server
|
||||
MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Server;
|
||||
MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Server;
|
||||
}
|
||||
else {
|
||||
// this is Professional without terminal server
|
||||
MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||
MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||
}
|
||||
|
||||
while (fdoData->NumFreeTransferPackets < MIN_INITIAL_TRANSFER_PACKETS){
|
||||
PTRANSFER_PACKET pkt = NewTransferPacket(Fdo);
|
||||
if (pkt){
|
||||
InterlockedIncrement((PLONG)&fdoData->NumTotalTransferPackets);
|
||||
EnqueueFreeTransferPacket(Fdo, pkt);
|
||||
}
|
||||
else {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fdoData->DbgPeakNumTransferPackets = fdoData->NumTotalTransferPackets;
|
||||
|
||||
/*
|
||||
* Pre-initialize our SCSI_REQUEST_BLOCK template with all
|
||||
* the constant fields. This will save a little time for each xfer.
|
||||
* NOTE: a CdbLength field of 10 may not always be appropriate
|
||||
*/
|
||||
RtlZeroMemory(&fdoData->SrbTemplate, sizeof(SCSI_REQUEST_BLOCK));
|
||||
fdoData->SrbTemplate.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||
fdoData->SrbTemplate.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||
fdoData->SrbTemplate.QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
||||
fdoData->SrbTemplate.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||
fdoData->SrbTemplate.CdbLength = 10;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID NTAPI DestroyAllTransferPackets(PDEVICE_OBJECT Fdo)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
TRANSFER_PACKET *pkt;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(IsListEmpty(&fdoData->DeferredClientIrpList));
|
||||
|
||||
while ((pkt = DequeueFreeTransferPacket(Fdo, FALSE))){
|
||||
DestroyTransferPacket(pkt);
|
||||
InterlockedDecrement((PLONG)&fdoData->NumTotalTransferPackets);
|
||||
}
|
||||
|
||||
ASSERT(fdoData->NumTotalTransferPackets == 0);
|
||||
}
|
||||
|
||||
PTRANSFER_PACKET NTAPI NewTransferPacket(PDEVICE_OBJECT Fdo)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
PTRANSFER_PACKET newPkt;
|
||||
|
||||
newPkt = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSFER_PACKET), 'pnPC');
|
||||
if (newPkt){
|
||||
RtlZeroMemory(newPkt, sizeof(TRANSFER_PACKET)); // just to be sure
|
||||
|
||||
/*
|
||||
* Allocate resources for the packet.
|
||||
*/
|
||||
newPkt->Irp = IoAllocateIrp(Fdo->StackSize, FALSE);
|
||||
if (newPkt->Irp){
|
||||
KIRQL oldIrql;
|
||||
|
||||
newPkt->Fdo = Fdo;
|
||||
|
||||
/*
|
||||
* Enqueue the packet in our static AllTransferPacketsList
|
||||
* (just so we can find it during debugging if its stuck somewhere).
|
||||
*/
|
||||
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||
InsertTailList(&fdoData->AllTransferPacketsList, &newPkt->AllPktsListEntry);
|
||||
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||
}
|
||||
else {
|
||||
ExFreePool(newPkt);
|
||||
newPkt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return newPkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* DestroyTransferPacket
|
||||
*
|
||||
*/
|
||||
VOID NTAPI DestroyTransferPacket(PTRANSFER_PACKET Pkt)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
KIRQL oldIrql;
|
||||
|
||||
ASSERT(!Pkt->SlistEntry.Next);
|
||||
ASSERT(!Pkt->OriginalIrp);
|
||||
|
||||
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||
|
||||
/*
|
||||
* Delete the packet from our all-packets queue.
|
||||
*/
|
||||
ASSERT(!IsListEmpty(&Pkt->AllPktsListEntry));
|
||||
ASSERT(!IsListEmpty(&fdoData->AllTransferPacketsList));
|
||||
RemoveEntryList(&Pkt->AllPktsListEntry);
|
||||
InitializeListHead(&Pkt->AllPktsListEntry);
|
||||
|
||||
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||
|
||||
IoFreeIrp(Pkt->Irp);
|
||||
ExFreePool(Pkt);
|
||||
}
|
||||
|
||||
VOID NTAPI EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
KIRQL oldIrql;
|
||||
ULONG newNumPkts;
|
||||
|
||||
ASSERT(!Pkt->SlistEntry.Next);
|
||||
|
||||
InterlockedPushEntrySList(&fdoData->FreeTransferPacketsList, &Pkt->SlistEntry);
|
||||
newNumPkts = InterlockedIncrement((PLONG)&fdoData->NumFreeTransferPackets);
|
||||
ASSERT(newNumPkts <= fdoData->NumTotalTransferPackets);
|
||||
|
||||
/*
|
||||
* If the total number of packets is larger than MinWorkingSetTransferPackets,
|
||||
* that means that we've been in stress. If all those packets are now
|
||||
* free, then we are now out of stress and can free the extra packets.
|
||||
* Free down to MaxWorkingSetTransferPackets immediately, and
|
||||
* down to MinWorkingSetTransferPackets lazily (one at a time).
|
||||
*/
|
||||
if (fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets){
|
||||
|
||||
/*
|
||||
* 1. Immediately snap down to our UPPER threshold.
|
||||
*/
|
||||
if (fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets){
|
||||
SLIST_ENTRY pktList;
|
||||
PSLIST_ENTRY slistEntry;
|
||||
PTRANSFER_PACKET pktToDelete;
|
||||
|
||||
DBGTRACE(ClassDebugTrace, ("Exiting stress, block freeing (%d-%d) packets.", fdoData->NumTotalTransferPackets, MaxWorkingSetTransferPackets));
|
||||
|
||||
/*
|
||||
* Check the counter again with lock held. This eliminates a race condition
|
||||
* while still allowing us to not grab the spinlock in the common codepath.
|
||||
*
|
||||
* Note that the spinlock does not synchronize with threads dequeuing free
|
||||
* packets to send (DequeueFreeTransferPacket does that with a lightweight
|
||||
* interlocked exchange); the spinlock prevents multiple threads in this function
|
||||
* from deciding to free too many extra packets at once.
|
||||
*/
|
||||
SimpleInitSlistHdr(&pktList);
|
||||
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||
while ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) &&
|
||||
(fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets)){
|
||||
|
||||
pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);
|
||||
if (pktToDelete){
|
||||
SimplePushSlist(&pktList, &pktToDelete->SlistEntry);
|
||||
InterlockedDecrement((PLONG)&fdoData->NumTotalTransferPackets);
|
||||
}
|
||||
else {
|
||||
DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (1).", MaxWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
|
||||
break;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||
|
||||
while ((slistEntry = SimplePopSlist(&pktList))){
|
||||
pktToDelete = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
|
||||
DestroyTransferPacket(pktToDelete);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 2. Lazily work down to our LOWER threshold (by only freeing one packet at a time).
|
||||
*/
|
||||
if (fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets){
|
||||
/*
|
||||
* Check the counter again with lock held. This eliminates a race condition
|
||||
* while still allowing us to not grab the spinlock in the common codepath.
|
||||
*
|
||||
* Note that the spinlock does not synchronize with threads dequeuing free
|
||||
* packets to send (DequeueFreeTransferPacket does that with a lightweight
|
||||
* interlocked exchange); the spinlock prevents multiple threads in this function
|
||||
* from deciding to free too many extra packets at once.
|
||||
*/
|
||||
PTRANSFER_PACKET pktToDelete = NULL;
|
||||
|
||||
DBGTRACE(ClassDebugTrace, ("Exiting stress, lazily freeing one of %d/%d packets.", fdoData->NumTotalTransferPackets, MinWorkingSetTransferPackets));
|
||||
|
||||
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||
if ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) &&
|
||||
(fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets)){
|
||||
|
||||
pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);
|
||||
if (pktToDelete){
|
||||
InterlockedDecrement((PLONG)&fdoData->NumTotalTransferPackets);
|
||||
}
|
||||
else {
|
||||
DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (2).", MinWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
|
||||
}
|
||||
}
|
||||
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||
|
||||
if (pktToDelete){
|
||||
DestroyTransferPacket(pktToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
PTRANSFER_PACKET pkt;
|
||||
PSLIST_ENTRY slistEntry;
|
||||
//KIRQL oldIrql;
|
||||
|
||||
slistEntry = InterlockedPopEntrySList(&fdoData->FreeTransferPacketsList);
|
||||
if (slistEntry){
|
||||
slistEntry->Next = NULL;
|
||||
pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
|
||||
ASSERT(fdoData->NumFreeTransferPackets > 0);
|
||||
InterlockedDecrement((PLONG)&fdoData->NumFreeTransferPackets);
|
||||
}
|
||||
else {
|
||||
if (AllocIfNeeded){
|
||||
/*
|
||||
* We are in stress and have run out of lookaside packets.
|
||||
* In order to service the current transfer,
|
||||
* allocate an extra packet.
|
||||
* We will free it lazily when we are out of stress.
|
||||
*/
|
||||
pkt = NewTransferPacket(Fdo);
|
||||
if (pkt){
|
||||
InterlockedIncrement((PLONG)&fdoData->NumTotalTransferPackets);
|
||||
fdoData->DbgPeakNumTransferPackets = max(fdoData->DbgPeakNumTransferPackets, fdoData->NumTotalTransferPackets);
|
||||
}
|
||||
else {
|
||||
DBGWARN(("DequeueFreeTransferPacket: packet allocation failed"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
pkt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* SetupReadWriteTransferPacket
|
||||
*
|
||||
* This function is called once to set up the first attempt to send a packet.
|
||||
* It is not called before a retry, as SRB fields may be modified for the retry.
|
||||
*
|
||||
* Set up the Srb of the TRANSFER_PACKET for the transfer.
|
||||
* The Irp is set up in SubmitTransferPacket because it must be reset
|
||||
* for each packet submission.
|
||||
*/
|
||||
VOID NTAPI SetupReadWriteTransferPacket(PTRANSFER_PACKET Pkt,
|
||||
PVOID Buf,
|
||||
ULONG Len,
|
||||
LARGE_INTEGER DiskLocation,
|
||||
PIRP OriginalIrp)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(OriginalIrp);
|
||||
UCHAR majorFunc = origCurSp->MajorFunction;
|
||||
ULONG logicalBlockAddr;
|
||||
ULONG numTransferBlocks;
|
||||
PCDB pCdb;
|
||||
|
||||
logicalBlockAddr = (ULONG)Int64ShrlMod32(DiskLocation.QuadPart, fdoExt->SectorShift);
|
||||
numTransferBlocks = Len >> fdoExt->SectorShift;
|
||||
|
||||
/*
|
||||
* Slap the constant SRB fields in from our pre-initialized template.
|
||||
* We'll then only have to fill in the unique fields for this transfer.
|
||||
* Tell lower drivers to sort the SRBs by the logical block address
|
||||
* so that disk seeks are minimized.
|
||||
*/
|
||||
Pkt->Srb = fdoData->SrbTemplate; // copies _contents_ of SRB blocks
|
||||
Pkt->Srb.DataBuffer = Buf;
|
||||
Pkt->Srb.DataTransferLength = Len;
|
||||
Pkt->Srb.QueueSortKey = logicalBlockAddr;
|
||||
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||
Pkt->Srb.TimeOutValue = (Len/0x10000) + ((Len%0x10000) ? 1 : 0);
|
||||
Pkt->Srb.TimeOutValue *= fdoExt->TimeOutValue;
|
||||
|
||||
/*
|
||||
* Arrange values in CDB in big-endian format.
|
||||
*/
|
||||
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||
pCdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte3;
|
||||
pCdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte2;
|
||||
pCdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte1;
|
||||
pCdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte0;
|
||||
pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1;
|
||||
pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0;
|
||||
pCdb->CDB10.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ : SCSIOP_WRITE;
|
||||
|
||||
/*
|
||||
* Set SRB and IRP flags
|
||||
*/
|
||||
Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
|
||||
if (TEST_FLAG(OriginalIrp->Flags, IRP_PAGING_IO) ||
|
||||
TEST_FLAG(OriginalIrp->Flags, IRP_SYNCHRONOUS_PAGING_IO)){
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_CLASS_FLAGS_PAGING);
|
||||
}
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, (majorFunc==IRP_MJ_READ) ? SRB_FLAGS_DATA_IN : SRB_FLAGS_DATA_OUT);
|
||||
|
||||
/*
|
||||
* Allow caching only if this is not a write-through request.
|
||||
* If write-through and caching is enabled on the device, force
|
||||
* media access.
|
||||
*/
|
||||
if (TEST_FLAG(origCurSp->Flags, SL_WRITE_THROUGH)){
|
||||
if (TEST_FLAG(fdoExt->DeviceFlags, DEV_WRITE_CACHE)){
|
||||
pCdb->CDB10.ForceUnitAccess = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember the buf and len in the SRB because miniports
|
||||
* can overwrite SRB.DataTransferLength and we may need it again
|
||||
* for the retry.
|
||||
*/
|
||||
Pkt->BufPtrCopy = Buf;
|
||||
Pkt->BufLenCopy = Len;
|
||||
Pkt->TargetLocationCopy = DiskLocation;
|
||||
|
||||
Pkt->OriginalIrp = OriginalIrp;
|
||||
Pkt->NumRetries = MAXIMUM_RETRIES;
|
||||
Pkt->SyncEventPtr = NULL;
|
||||
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* SubmitTransferPacket
|
||||
*
|
||||
* Set up the IRP for the TRANSFER_PACKET submission and send it down.
|
||||
*/
|
||||
VOID NTAPI SubmitTransferPacket(PTRANSFER_PACKET Pkt)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension;
|
||||
PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject;
|
||||
PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(Pkt->Irp);
|
||||
|
||||
ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1);
|
||||
|
||||
/*
|
||||
* Attach the SRB to the IRP.
|
||||
* The reused IRP's stack location has to be rewritten for each retry
|
||||
* call because IoCompleteRequest clears the stack locations.
|
||||
*/
|
||||
IoReuseIrp(Pkt->Irp, STATUS_NOT_SUPPORTED);
|
||||
nextSp->MajorFunction = IRP_MJ_SCSI;
|
||||
nextSp->Parameters.Scsi.Srb = &Pkt->Srb;
|
||||
Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0;
|
||||
if (Pkt->CompleteOriginalIrpWhenLastPacketCompletes){
|
||||
/*
|
||||
* Only dereference the "original IRP"'s stack location
|
||||
* if its a real client irp (as opposed to a static irp
|
||||
* we're using just for result status for one of the non-IO scsi commands).
|
||||
*
|
||||
* For read/write, propagate the storage-specific IRP stack location flags
|
||||
* (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH).
|
||||
*/
|
||||
PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp);
|
||||
nextSp->Flags = origCurSp->Flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write MDL address to new IRP. In the port driver the SRB DataBuffer
|
||||
* field is used as the actual buffer pointer within the MDL,
|
||||
* so the same MDL can be used for each partial transfer.
|
||||
* This saves having to build a new MDL for each partial transfer.
|
||||
*/
|
||||
Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress;
|
||||
|
||||
IoSetCompletionRoutine(Pkt->Irp, TransferPktComplete, Pkt, TRUE, TRUE, TRUE);
|
||||
IoCallDriver(nextDevObj, Pkt->Irp);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
|
||||
{
|
||||
PTRANSFER_PACKET pkt = (PTRANSFER_PACKET)Context;
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = pkt->Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
PIO_STACK_LOCATION origCurrentSp = IoGetCurrentIrpStackLocation(pkt->OriginalIrp);
|
||||
BOOLEAN packetDone = FALSE;
|
||||
|
||||
/*
|
||||
* Put all the assertions and spew in here so we don't have to look at them.
|
||||
*/
|
||||
DBGCHECKRETURNEDPKT(pkt);
|
||||
|
||||
if (SRB_STATUS(pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS){
|
||||
|
||||
fdoData->LoggedTURFailureSinceLastIO = FALSE;
|
||||
|
||||
/*
|
||||
* The port driver should not have allocated a sense buffer
|
||||
* if the SRB succeeded.
|
||||
*/
|
||||
ASSERT(!PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb));
|
||||
|
||||
/*
|
||||
* Add this packet's transferred length to the original IRP's.
|
||||
*/
|
||||
InterlockedExchangeAdd((PLONG)&pkt->OriginalIrp->IoStatus.Information,
|
||||
(LONG)pkt->Srb.DataTransferLength);
|
||||
|
||||
if (pkt->InLowMemRetry){
|
||||
packetDone = StepLowMemRetry(pkt);
|
||||
}
|
||||
else {
|
||||
packetDone = TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* The packet failed. We may retry it if possible.
|
||||
*/
|
||||
BOOLEAN shouldRetry;
|
||||
|
||||
/*
|
||||
* Make sure IRP status matches SRB error status (since we propagate it).
|
||||
*/
|
||||
if (NT_SUCCESS(Irp->IoStatus.Status)){
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret the SRB error (to a meaningful IRP status)
|
||||
* and determine if we should retry this packet.
|
||||
* This call looks at the returned SENSE info to figure out what to do.
|
||||
*/
|
||||
shouldRetry = InterpretTransferPacketError(pkt);
|
||||
|
||||
/*
|
||||
* Sometimes the port driver can allocates a new 'sense' buffer
|
||||
* to report transfer errors, e.g. when the default sense buffer
|
||||
* is too small. If so, it is up to us to free it.
|
||||
* Now that we're done interpreting the sense info, free it if appropriate.
|
||||
*/
|
||||
if (PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb)) {
|
||||
DBGTRACE(ClassDebugSenseInfo, ("Freeing port-allocated sense buffer for pkt %ph.", pkt));
|
||||
FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExt, &pkt->Srb);
|
||||
pkt->Srb.SenseInfoBuffer = &pkt->SrbErrorSenseData;
|
||||
pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the SRB queue is locked-up, release it.
|
||||
* Do this after calling the error handler.
|
||||
*/
|
||||
if (pkt->Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN){
|
||||
ClassReleaseQueue(pkt->Fdo);
|
||||
}
|
||||
|
||||
if (shouldRetry && (pkt->NumRetries > 0)){
|
||||
packetDone = RetryTransferPacket(pkt);
|
||||
}
|
||||
else {
|
||||
packetDone = TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* If the packet is completed, put it back in the free list.
|
||||
* If it is the last packet servicing the original request, complete the original irp.
|
||||
*/
|
||||
if (packetDone){
|
||||
LONG numPacketsRemaining;
|
||||
PIRP deferredIrp;
|
||||
PDEVICE_OBJECT Fdo = pkt->Fdo;
|
||||
UCHAR uniqueAddr;
|
||||
|
||||
/*
|
||||
* In case a remove is pending, bump the lock count so we don't get freed
|
||||
* right after we complete the original irp.
|
||||
*/
|
||||
ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddr);
|
||||
|
||||
/*
|
||||
* The original IRP should get an error code
|
||||
* if any one of the packets failed.
|
||||
*/
|
||||
if (!NT_SUCCESS(Irp->IoStatus.Status)){
|
||||
pkt->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
|
||||
|
||||
/*
|
||||
* If the original I/O originated in user space (i.e. it is thread-queued),
|
||||
* and the error is user-correctable (e.g. media is missing, for removable media),
|
||||
* alert the user.
|
||||
* Since this is only one of possibly several packets completing for the original IRP,
|
||||
* we may do this more than once for a single request. That's ok; this allows
|
||||
* us to test each returned status with IoIsErrorUserInduced().
|
||||
*/
|
||||
if (IoIsErrorUserInduced(Irp->IoStatus.Status) &&
|
||||
pkt->CompleteOriginalIrpWhenLastPacketCompletes &&
|
||||
pkt->OriginalIrp->Tail.Overlay.Thread){
|
||||
|
||||
IoSetHardErrorOrVerifyDevice(pkt->OriginalIrp, pkt->Fdo);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We use a field in the original IRP to count
|
||||
* down the transfer pieces as they complete.
|
||||
*/
|
||||
numPacketsRemaining = InterlockedDecrement(
|
||||
(PLONG)&pkt->OriginalIrp->Tail.Overlay.DriverContext[0]);
|
||||
|
||||
if (numPacketsRemaining > 0){
|
||||
/*
|
||||
* More transfer pieces remain for the original request.
|
||||
* Wait for them to complete before completing the original irp.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
|
||||
/*
|
||||
* All the transfer pieces are done.
|
||||
* Complete the original irp if appropriate.
|
||||
*/
|
||||
ASSERT(numPacketsRemaining == 0);
|
||||
if (pkt->CompleteOriginalIrpWhenLastPacketCompletes){
|
||||
if (NT_SUCCESS(pkt->OriginalIrp->IoStatus.Status)){
|
||||
ASSERT((ULONG)pkt->OriginalIrp->IoStatus.Information == origCurrentSp->Parameters.Read.Length);
|
||||
ClasspPerfIncrementSuccessfulIo(fdoExt);
|
||||
}
|
||||
ClassReleaseRemoveLock(pkt->Fdo, pkt->OriginalIrp);
|
||||
|
||||
ClassCompleteRequest(pkt->Fdo, pkt->OriginalIrp, IO_DISK_INCREMENT);
|
||||
|
||||
/*
|
||||
* We may have been called by one of the class drivers (e.g. cdrom)
|
||||
* via the legacy API ClassSplitRequest.
|
||||
* This is the only case for which the packet engine is called for an FDO
|
||||
* with a StartIo routine; in that case, we have to call IoStartNextPacket
|
||||
* now that the original irp has been completed.
|
||||
*/
|
||||
if (fdoExt->CommonExtension.DriverExtension->InitData.ClassStartIo) {
|
||||
if (TEST_FLAG(pkt->Srb.SrbFlags, SRB_FLAGS_DONT_START_NEXT_PACKET)){
|
||||
DBGTRAP(("SRB_FLAGS_DONT_START_NEXT_PACKET should never be set here (?)"));
|
||||
}
|
||||
else {
|
||||
KIRQL oldIrql;
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
||||
IoStartNextPacket(pkt->Fdo, FALSE);
|
||||
KeLowerIrql(oldIrql);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the packet was synchronous, write the final
|
||||
* result back to the issuer's status buffer and
|
||||
* signal his event.
|
||||
*/
|
||||
if (pkt->SyncEventPtr){
|
||||
KeSetEvent(pkt->SyncEventPtr, 0, FALSE);
|
||||
pkt->SyncEventPtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the completed packet.
|
||||
*/
|
||||
pkt->OriginalIrp = NULL;
|
||||
pkt->InLowMemRetry = FALSE;
|
||||
EnqueueFreeTransferPacket(pkt->Fdo, pkt);
|
||||
|
||||
/*
|
||||
* Now that we have freed some resources,
|
||||
* try again to send one of the previously deferred irps.
|
||||
*/
|
||||
deferredIrp = DequeueDeferredClientIrp(fdoData);
|
||||
if (deferredIrp){
|
||||
DBGWARN(("... retrying deferred irp %xh.", deferredIrp));
|
||||
ServiceTransferRequest(pkt->Fdo, deferredIrp);
|
||||
}
|
||||
|
||||
ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddr);
|
||||
}
|
||||
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
/*
|
||||
* SetupEjectionTransferPacket
|
||||
*
|
||||
* Set up a transferPacket for a synchronous Ejection Control transfer.
|
||||
*/
|
||||
VOID NTAPI SetupEjectionTransferPacket( TRANSFER_PACKET *Pkt,
|
||||
BOOLEAN PreventMediaRemoval,
|
||||
PKEVENT SyncEventPtr,
|
||||
PIRP OriginalIrp)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||
PCDB pCdb;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||
|
||||
Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||
Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||
Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
||||
Pkt->Srb.CdbLength = 6;
|
||||
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||
Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||
Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
|
||||
|
||||
Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||
|
||||
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||
pCdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
|
||||
pCdb->MEDIA_REMOVAL.Prevent = PreventMediaRemoval;
|
||||
|
||||
Pkt->BufPtrCopy = NULL;
|
||||
Pkt->BufLenCopy = 0;
|
||||
|
||||
Pkt->OriginalIrp = OriginalIrp;
|
||||
Pkt->NumRetries = NUM_LOCKMEDIAREMOVAL_RETRIES;
|
||||
Pkt->SyncEventPtr = SyncEventPtr;
|
||||
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* SetupModeSenseTransferPacket
|
||||
*
|
||||
* Set up a transferPacket for a synchronous Mode Sense transfer.
|
||||
*/
|
||||
VOID NTAPI SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt,
|
||||
PKEVENT SyncEventPtr,
|
||||
PVOID ModeSenseBuffer,
|
||||
UCHAR ModeSenseBufferLen,
|
||||
UCHAR PageMode,
|
||||
PIRP OriginalIrp)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||
PCDB pCdb;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||
|
||||
Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||
Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||
Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
||||
Pkt->Srb.CdbLength = 6;
|
||||
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||
Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||
Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
|
||||
Pkt->Srb.DataBuffer = ModeSenseBuffer;
|
||||
Pkt->Srb.DataTransferLength = ModeSenseBufferLen;
|
||||
|
||||
Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DATA_IN);
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||
|
||||
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||
pCdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
||||
pCdb->MODE_SENSE.PageCode = PageMode;
|
||||
pCdb->MODE_SENSE.AllocationLength = (UCHAR)ModeSenseBufferLen;
|
||||
|
||||
Pkt->BufPtrCopy = ModeSenseBuffer;
|
||||
Pkt->BufLenCopy = ModeSenseBufferLen;
|
||||
|
||||
Pkt->OriginalIrp = OriginalIrp;
|
||||
Pkt->NumRetries = NUM_MODESENSE_RETRIES;
|
||||
Pkt->SyncEventPtr = SyncEventPtr;
|
||||
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* SetupDriveCapacityTransferPacket
|
||||
*
|
||||
* Set up a transferPacket for a synchronous Drive Capacity transfer.
|
||||
*/
|
||||
VOID NTAPI SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt,
|
||||
PVOID ReadCapacityBuffer,
|
||||
ULONG ReadCapacityBufferLen,
|
||||
PKEVENT SyncEventPtr,
|
||||
PIRP OriginalIrp)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||
PCDB pCdb;
|
||||
|
||||
RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||
|
||||
Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||
Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||
Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
||||
Pkt->Srb.CdbLength = 10;
|
||||
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||
Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||
Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
|
||||
Pkt->Srb.DataBuffer = ReadCapacityBuffer;
|
||||
Pkt->Srb.DataTransferLength = ReadCapacityBufferLen;
|
||||
|
||||
Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DATA_IN);
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||
|
||||
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||
pCdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
|
||||
|
||||
Pkt->BufPtrCopy = ReadCapacityBuffer;
|
||||
Pkt->BufLenCopy = ReadCapacityBufferLen;
|
||||
|
||||
Pkt->OriginalIrp = OriginalIrp;
|
||||
Pkt->NumRetries = NUM_DRIVECAPACITY_RETRIES;
|
||||
Pkt->SyncEventPtr = SyncEventPtr;
|
||||
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* SetupSendStartUnitTransferPacket
|
||||
*
|
||||
* Set up a transferPacket for a synchronous Send Start Unit transfer.
|
||||
*/
|
||||
VOID SetupSendStartUnitTransferPacket( TRANSFER_PACKET *Pkt,
|
||||
PIRP OriginalIrp)
|
||||
{
|
||||
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||
PCDB pCdb;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||
|
||||
/*
|
||||
* Initialize the SRB.
|
||||
* Use a very long timeout value to give the drive time to spin up.
|
||||
*/
|
||||
Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||
Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||
Pkt->Srb.TimeOutValue = START_UNIT_TIMEOUT;
|
||||
Pkt->Srb.CdbLength = 6;
|
||||
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||
Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||
Pkt->Srb.Lun = 0;
|
||||
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_DATA_TRANSFER);
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_AUTOSENSE);
|
||||
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||
|
||||
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||
pCdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
|
||||
pCdb->START_STOP.Start = 1;
|
||||
pCdb->START_STOP.Immediate = 0;
|
||||
pCdb->START_STOP.LogicalUnitNumber = 0;
|
||||
|
||||
Pkt->OriginalIrp = OriginalIrp;
|
||||
Pkt->NumRetries = 0;
|
||||
Pkt->SyncEventPtr = NULL;
|
||||
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
|
||||
}
|
||||
#endif
|
|
@ -1,25 +0,0 @@
|
|||
|
||||
include_directories(..)
|
||||
|
||||
list(APPEND SOURCE
|
||||
data.c
|
||||
disk.c
|
||||
diskwmi.c
|
||||
enum.c
|
||||
geometry.c
|
||||
part.c
|
||||
pnp.c
|
||||
disk.h)
|
||||
|
||||
add_library(disk_new MODULE ${SOURCE} disk.rc)
|
||||
target_link_libraries(disk_new libcntpr wdmguid)
|
||||
|
||||
if(USE_CLANG_CL OR (NOT MSVC))
|
||||
target_compile_options(disk_new PRIVATE -Wno-format -Wno-pointer-sign)
|
||||
endif()
|
||||
|
||||
set_module_type(disk_new kernelmodedriver)
|
||||
add_importlibs(disk_new classpnp ntoskrnl hal)
|
||||
add_pch(disk_new disk.h SOURCE)
|
||||
add_cd_file(TARGET disk_new DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||
#add_driver_inf(disk_new diskdev.inf)
|
|
@ -1,81 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
disk.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI disk class driver
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "disk.h"
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("PAGE")
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define HackDisableTaggedQueuing (0x01)
|
||||
#define HackDisableSynchronousTransfers (0x02)
|
||||
#define HackDisableSpinDown (0x04)
|
||||
#define HackDisableWriteCache (0x08)
|
||||
#define HackCauseNotReportableHack (0x10)
|
||||
#define HackRequiresStartUnitCommand (0x20)
|
||||
*/
|
||||
|
||||
CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers[] = {
|
||||
{ "COMPAQ" , "PD-1" , NULL, 0x02 },
|
||||
{ "CONNER" , "CP3500" , NULL, 0x02 },
|
||||
{ "FUJITSU" , "M2652S-512" , NULL, 0x01 },
|
||||
{ "HP ", "C1113F " , NULL, 0x20 },
|
||||
// iomegas require START_UNIT commands so be sure to match all of them.
|
||||
{ "iomega" , "jaz" , NULL, 0x30 },
|
||||
{ "iomega" , NULL , NULL, 0x20 },
|
||||
{ "IOMEGA" , "ZIP" , NULL, 0x27 },
|
||||
{ "IOMEGA" , NULL , NULL, 0x20 },
|
||||
{ "MAXTOR" , "MXT-540SL" , "I1.2", 0x01 },
|
||||
{ "MICROP" , "1936-21MW1002002" , NULL, 0x03 },
|
||||
{ "OLIVETTI", "CP3500" , NULL, 0x02 },
|
||||
{ "SEAGATE" , "ST41601N" , "0102", 0x02 },
|
||||
{ "SEAGATE" , "ST3655N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST3390N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST12550N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST32430N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST31230N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST15230N" , NULL, 0x08 },
|
||||
{ "SyQuest" , "SQ5110" , "CHC", 0x03 },
|
||||
{ "TOSHIBA" , "MK538FB" , "60", 0x01 },
|
||||
{ NULL , NULL , NULL, 0x0 }
|
||||
};
|
||||
|
||||
//
|
||||
// ======== ROS DIFF ========
|
||||
// Added MediaTypes in their own brace nesting level
|
||||
// ======== ROS DIFF ========
|
||||
//
|
||||
DISK_MEDIA_TYPES_LIST const DiskMediaTypes[] = {
|
||||
{ "COMPAQ" , "PD-1 LF-1094" , NULL, 1, 1, {PC_5_RW , 0 , 0 , 0 }},
|
||||
{ "HP" , NULL , NULL, 2, 2, {MO_5_WO , MO_5_RW, 0 , 0 }},
|
||||
{ "iomega" , "jaz" , NULL, 1, 1, {IOMEGA_JAZ , 0 , 0 , 0 }},
|
||||
{ "IOMEGA" , "ZIP" , NULL, 1, 1, {IOMEGA_ZIP , 0 , 0 , 0 }},
|
||||
{ "PINNACLE", "Apex 4.6GB" , NULL, 3, 2, {PINNACLE_APEX_5_RW, MO_5_RW, MO_5_WO, 0 }},
|
||||
{ "SONY" , "SMO-F541" , NULL, 2, 2, {MO_5_WO , MO_5_RW, 0 , 0 }},
|
||||
{ "SONY" , "SMO-F551" , NULL, 2, 2, {MO_5_WO , MO_5_RW, 0 , 0 }},
|
||||
{ NULL , NULL , NULL, 0, 0, {0 , 0 , 0 , 0 }}
|
||||
};
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg()
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,982 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
disk.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI disk class driver
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _DISK_NEW_H_
|
||||
#define _DISK_NEW_H_
|
||||
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define NTDDI_VERSION NTDDI_WINXP
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <wmidata.h>
|
||||
#include <classpnp.h>
|
||||
|
||||
#if defined(JAPAN) && defined(_X86_)
|
||||
#include <machine.h>
|
||||
#endif
|
||||
|
||||
#if defined(_X86_)
|
||||
#include <mountdev.h>
|
||||
#endif
|
||||
|
||||
#ifdef ExAllocatePool
|
||||
#undef ExAllocatePool
|
||||
#define ExAllocatePool #assert(FALSE)
|
||||
#endif
|
||||
|
||||
#define DISK_TAG_GENERAL ' DcS' // "ScD " - generic tag
|
||||
#define DISK_TAG_SMART 'aDcS' // "ScDa" - SMART allocations
|
||||
#define DISK_TAG_INFO_EXCEPTION 'ADcS' // "ScDA" - Info Exceptions
|
||||
#define DISK_TAG_DISABLE_CACHE 'CDcS' // "ScDC" - disable cache paths
|
||||
#define DISK_TAG_CCONTEXT 'cDcS' // "ScDc" - disk allocated completion context
|
||||
#define DISK_TAG_DISK_GEOM 'GDcS' // "ScDG" - disk geometry buffer
|
||||
#define DISK_TAG_UPDATE_GEOM 'gDcS' // "ScDg" - update disk geometry paths
|
||||
#define DISK_TAG_SENSE_INFO 'IDcS' // "ScDI" - sense info buffers
|
||||
#define DISK_TAG_PNP_ID 'iDcS' // "ScDp" - pnp ids
|
||||
#define DISK_TAG_MODE_DATA 'MDcS' // "ScDM" - mode data buffer
|
||||
#define DISK_CACHE_MBR_CHECK 'mDcS' // "ScDM" - mbr checksum code
|
||||
#define DISK_TAG_NAME 'NDcS' // "ScDN" - disk name code
|
||||
#define DISK_TAG_READ_CAP 'PDcS' // "ScDP" - read capacity buffer
|
||||
#define DISK_TAG_PART_LIST 'pDcS' // "ScDp" - disk partition lists
|
||||
#define DISK_TAG_SRB 'SDcS' // "ScDS" - srb allocation
|
||||
#define DISK_TAG_START 'sDcS' // "ScDs" - start device paths
|
||||
#define DISK_TAG_UPDATE_CAP 'UDcS' // "ScDU" - update capacity path
|
||||
#define DISK_TAG_WI_CONTEXT 'WDcS' // "ScDW" - work-item context
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(NTAPI *PDISK_UPDATE_PARTITIONS) (
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
|
||||
);
|
||||
|
||||
#if defined(_X86_)
|
||||
|
||||
//
|
||||
// Disk device data
|
||||
//
|
||||
|
||||
typedef enum _DISK_GEOMETRY_SOURCE {
|
||||
DiskGeometryUnknown,
|
||||
DiskGeometryFromBios,
|
||||
DiskGeometryFromPort,
|
||||
DiskGeometryFromNec98,
|
||||
DiskGeometryGuessedFromBios,
|
||||
DiskGeometryFromDefault
|
||||
} DISK_GEOMETRY_SOURCE, *PDISK_GEOMETRY_SOURCE;
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
typedef struct _DISK_DATA {
|
||||
|
||||
//
|
||||
// This field is the ordinal of a partition as it appears on a disk.
|
||||
//
|
||||
|
||||
ULONG PartitionOrdinal;
|
||||
|
||||
//
|
||||
// How has this disk been partitioned? Either EFI or MBR.
|
||||
//
|
||||
|
||||
PARTITION_STYLE PartitionStyle;
|
||||
|
||||
union {
|
||||
|
||||
struct {
|
||||
|
||||
//
|
||||
// Disk signature (from MBR)
|
||||
//
|
||||
|
||||
ULONG Signature;
|
||||
|
||||
//
|
||||
// MBR checksum
|
||||
//
|
||||
|
||||
ULONG MbrCheckSum;
|
||||
|
||||
//
|
||||
// Number of hidden sectors for BPB.
|
||||
//
|
||||
|
||||
ULONG HiddenSectors;
|
||||
|
||||
//
|
||||
// Partition type of this device object
|
||||
//
|
||||
// This field is set by:
|
||||
//
|
||||
// 1. Initially set according to the partition list entry
|
||||
// partition type returned by IoReadPartitionTable.
|
||||
//
|
||||
// 2. Subsequently set by the
|
||||
// IOCTL_DISK_SET_PARTITION_INFORMATION I/O control
|
||||
// function when IoSetPartitionInformation function
|
||||
// successfully updates the partition type on the disk.
|
||||
//
|
||||
|
||||
UCHAR PartitionType;
|
||||
|
||||
//
|
||||
// Boot indicator - indicates whether this partition is a
|
||||
// bootable (active) partition for this device
|
||||
//
|
||||
// This field is set according to the partition list entry boot
|
||||
// indicator returned by IoReadPartitionTable.
|
||||
//
|
||||
|
||||
BOOLEAN BootIndicator;
|
||||
|
||||
} Mbr;
|
||||
|
||||
struct {
|
||||
|
||||
//
|
||||
// The DiskGUID field from the EFI partition header.
|
||||
//
|
||||
|
||||
GUID DiskId;
|
||||
|
||||
//
|
||||
// Partition type of this device object.
|
||||
//
|
||||
|
||||
GUID PartitionType;
|
||||
|
||||
//
|
||||
// Unique partition identifier for this partition.
|
||||
//
|
||||
|
||||
GUID PartitionId;
|
||||
|
||||
//
|
||||
// EFI partition attributes for this partition.
|
||||
//
|
||||
|
||||
ULONG64 Attributes;
|
||||
|
||||
//
|
||||
// EFI partition name of this partition.
|
||||
//
|
||||
|
||||
WCHAR PartitionName[36];
|
||||
|
||||
} Efi;
|
||||
|
||||
}; // unnamed union
|
||||
|
||||
struct {
|
||||
//
|
||||
// This flag is set when the well known name is created (through
|
||||
// DiskCreateSymbolicLinks) and cleared when destroying it
|
||||
// (by calling DiskDeleteSymbolicLinks).
|
||||
//
|
||||
|
||||
BOOLEAN WellKnownNameCreated : 1;
|
||||
|
||||
//
|
||||
// This flag is set when the PhysicalDriveN link is created (through
|
||||
// DiskCreateSymbolicLinks) and is cleared when destroying it (through
|
||||
// DiskDeleteSymbolicLinks)
|
||||
//
|
||||
|
||||
BOOLEAN PhysicalDriveLinkCreated : 1;
|
||||
|
||||
} LinkStatus;
|
||||
|
||||
//
|
||||
// ReadyStatus - STATUS_SUCCESS indicates that the drive is ready for
|
||||
// use. Any error status is to be returned as an explanation for why
|
||||
// a request is failed.
|
||||
//
|
||||
// This was done solely for the zero-length partition case of having no
|
||||
// media in a removable disk drive. When that occurs, and a read is sent
|
||||
// to the zero-length non-partition-zero PDO that was created, we had to
|
||||
// be able to fail the request with a reasonable value. This may not have
|
||||
// been the best way to do this, but it works.
|
||||
//
|
||||
|
||||
NTSTATUS ReadyStatus;
|
||||
|
||||
//
|
||||
// Routine to be called when updating the disk partitions. This routine
|
||||
// is different for removable and non-removable media and is called by
|
||||
// (among other things) DiskEnumerateDevice
|
||||
//
|
||||
|
||||
PDISK_UPDATE_PARTITIONS UpdatePartitionRoutine;
|
||||
|
||||
//
|
||||
// SCSI address used for SMART operations.
|
||||
//
|
||||
|
||||
SCSI_ADDRESS ScsiAddress;
|
||||
|
||||
//
|
||||
// Event used to synchronize partitioning operations and enumerations.
|
||||
//
|
||||
|
||||
KEVENT PartitioningEvent;
|
||||
|
||||
//
|
||||
// These unicode strings hold the disk and volume interface strings. If
|
||||
// the interfaces were not registered or could not be set then the string
|
||||
// buffer will be NULL.
|
||||
//
|
||||
|
||||
UNICODE_STRING DiskInterfaceString;
|
||||
UNICODE_STRING PartitionInterfaceString;
|
||||
|
||||
//
|
||||
// What type of failure prediction mechanism is available
|
||||
//
|
||||
|
||||
FAILURE_PREDICTION_METHOD FailurePredictionCapability;
|
||||
BOOLEAN AllowFPPerfHit;
|
||||
|
||||
#if defined(_X86_)
|
||||
//
|
||||
// This flag indicates that a non-default geometry for this drive has
|
||||
// already been determined by the disk driver. This field is ignored
|
||||
// for removable media drives.
|
||||
//
|
||||
|
||||
DISK_GEOMETRY_SOURCE GeometrySource;
|
||||
|
||||
//
|
||||
// If GeometryDetermined is TRUE this will contain the geometry which was
|
||||
// reported by the firmware or by the BIOS. For removable media drives
|
||||
// this will contain the last geometry used when media was present.
|
||||
//
|
||||
|
||||
DISK_GEOMETRY RealGeometry;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Indicates that the cached partition table is valid when set.
|
||||
//
|
||||
|
||||
ULONG CachedPartitionTableValid;
|
||||
|
||||
//
|
||||
// The cached partition table - this is only valid if the previous
|
||||
// flag is set. When invalidated the cached partition table will be
|
||||
// freed and replaced the next time one of the partitioning functions is
|
||||
// called. This allows the error handling routines to invalidate it by
|
||||
// setting the flag and doesn't require that they obtain a lock.
|
||||
//
|
||||
|
||||
PDRIVE_LAYOUT_INFORMATION_EX CachedPartitionTable;
|
||||
|
||||
//
|
||||
// This mutex prevents more than one IOCTL_DISK_VERIFY from being
|
||||
// sent down to the disk. This greatly reduces the possibility of
|
||||
// a Denial-of-Service attack
|
||||
//
|
||||
|
||||
KMUTEX VerifyMutex;
|
||||
|
||||
} DISK_DATA, *PDISK_DATA;
|
||||
|
||||
// Define a general structure of identifying disk controllers with bad
|
||||
// hardware.
|
||||
//
|
||||
|
||||
#define HackDisableTaggedQueuing (0x01)
|
||||
#define HackDisableSynchronousTransfers (0x02)
|
||||
#define HackDisableSpinDown (0x04)
|
||||
#define HackDisableWriteCache (0x08)
|
||||
#define HackCauseNotReportableHack (0x10)
|
||||
#define HackRequiresStartUnitCommand (0x20)
|
||||
#define HackDisableWriteCacheNotSupported (0x40)
|
||||
|
||||
|
||||
#define DiskDeviceParameterSubkey L"Disk"
|
||||
#define DiskDeviceSpecialFlags L"SpecialFlags"
|
||||
#define DiskDeviceUserWriteCacheSetting L"UserWriteCacheSetting"
|
||||
|
||||
|
||||
#define FUNCTIONAL_EXTENSION_SIZE sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA)
|
||||
#define PHYSICAL_EXTENSION_SIZE sizeof(PHYSICAL_DEVICE_EXTENSION) + sizeof(DISK_DATA)
|
||||
|
||||
#define MODE_DATA_SIZE 192
|
||||
#define VALUE_BUFFER_SIZE 2048
|
||||
#define SCSI_DISK_TIMEOUT 10
|
||||
#define PARTITION0_LIST_SIZE 4
|
||||
|
||||
#define MAX_MEDIA_TYPES 4
|
||||
typedef struct _DISK_MEDIA_TYPES_LIST {
|
||||
PCHAR VendorId;
|
||||
PCHAR ProductId;
|
||||
PCHAR Revision;
|
||||
const ULONG NumberOfTypes;
|
||||
const ULONG NumberOfSides;
|
||||
const STORAGE_MEDIA_TYPE MediaTypes[MAX_MEDIA_TYPES];
|
||||
} DISK_MEDIA_TYPES_LIST, *PDISK_MEDIA_TYPES_LIST;
|
||||
|
||||
//
|
||||
// WMI reregistration structures used for reregister work item
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
SINGLE_LIST_ENTRY Next;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PIRP Irp;
|
||||
} DISKREREGREQUEST, *PDISKREREGREQUEST;
|
||||
|
||||
//
|
||||
// Write cache setting as defined by the user
|
||||
//
|
||||
typedef enum _DISK_USER_WRITE_CACHE_SETTING
|
||||
{
|
||||
DiskWriteCacheDisable = 0,
|
||||
DiskWriteCacheEnable = 1,
|
||||
DiskWriteCacheDefault = -1
|
||||
|
||||
} DISK_USER_WRITE_CACHE_SETTING, *PDISK_USER_WRITE_CACHE_SETTING;
|
||||
|
||||
#define MAX_SECTORS_PER_VERIFY 0x200
|
||||
|
||||
//
|
||||
// This is based off 100ns units
|
||||
//
|
||||
#define ONE_MILLI_SECOND ((ULONGLONG)10 * 1000)
|
||||
|
||||
//
|
||||
// Context for the work-item
|
||||
//
|
||||
typedef struct _DISK_VERIFY_WORKITEM_CONTEXT
|
||||
{
|
||||
PIRP Irp;
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
PIO_WORKITEM WorkItem;
|
||||
|
||||
} DISK_VERIFY_WORKITEM_CONTEXT, *PDISK_VERIFY_WORKITEM_CONTEXT;
|
||||
|
||||
//
|
||||
// Poll for Failure Prediction every hour
|
||||
//
|
||||
#define DISK_DEFAULT_FAILURE_POLLING_PERIOD 1 * 60 * 60
|
||||
|
||||
//
|
||||
// Static global lookup tables.
|
||||
//
|
||||
|
||||
extern CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers[];
|
||||
extern const DISK_MEDIA_TYPES_LIST DiskMediaTypes[];
|
||||
|
||||
//
|
||||
// Macros
|
||||
//
|
||||
|
||||
//
|
||||
// Routine prototypes.
|
||||
//
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskUnload(
|
||||
IN PDRIVER_OBJECT DriverObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskAddDevice(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT Pdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskInitFdo(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskInitPdo(
|
||||
IN PDEVICE_OBJECT Pdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskStartFdo(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskStartPdo(
|
||||
IN PDEVICE_OBJECT Pdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskStopDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR Type
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskRemoveDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR Type
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskReadWriteVerification(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskDeviceControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskFdoProcessError(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PSCSI_REQUEST_BLOCK Srb,
|
||||
NTSTATUS *Status,
|
||||
BOOLEAN *Retry
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskShutdownFlush(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskGetCacheInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PDISK_CACHE_INFORMATION CacheInfo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskSetCacheInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PDISK_CACHE_INFORMATION CacheInfo
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DisableWriteCache(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_WORKITEM WorkItem
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskIoctlVerify(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PDISK_VERIFY_WORKITEM_CONTEXT Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskModeSelect(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PCHAR ModeSelectBuffer,
|
||||
IN ULONG Length,
|
||||
IN BOOLEAN SavePage
|
||||
);
|
||||
|
||||
//
|
||||
// We need to validate that the self test subcommand is valid and
|
||||
// appropriate. Right now we allow subcommands 0, 1 and 2 which are non
|
||||
// captive mode tests. Once we figure out a way to know if it is safe to
|
||||
// run a captive test then we can allow captive mode tests. Also if the
|
||||
// atapi 5 spec is ever updated to denote that bit 7 is the captive
|
||||
// mode bit, we can allow any request that does not have bit 7 set. Until
|
||||
// that is done we want to be sure
|
||||
//
|
||||
#define DiskIsValidSmartSelfTest(Subcommand) \
|
||||
( ((Subcommand) == SMART_OFFLINE_ROUTINE_OFFLINE) || \
|
||||
((Subcommand) == SMART_SHORT_SELFTEST_OFFLINE) || \
|
||||
((Subcommand) == SMART_EXTENDED_SELFTEST_OFFLINE) )
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskPerformSmartCommand(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN ULONG SrbControlCode,
|
||||
IN UCHAR Command,
|
||||
IN UCHAR Feature,
|
||||
IN UCHAR SectorCount,
|
||||
IN UCHAR SectorNumber,
|
||||
IN OUT PSRB_IO_CONTROL SrbControl,
|
||||
OUT PULONG BufferSize
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskGetInfoExceptionInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
OUT PMODE_INFO_EXCEPTIONS ReturnPageData
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskSetInfoExceptionInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PMODE_INFO_EXCEPTIONS PageData
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskDetectFailurePrediction(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
PFAILURE_PREDICTION_METHOD FailurePredictCapability
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
EnumerateBusKey(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension,
|
||||
HANDLE BusKey,
|
||||
PULONG DiskNumber
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskCreateFdo(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT LowerDeviceObject,
|
||||
IN PULONG DeviceCount,
|
||||
IN BOOLEAN DasdAccessOnly
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
UpdateDeviceObjects(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskSetSpecialHacks(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN ULONG_PTR Data
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskScanRegistryForSpecial(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ResetBus(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskEnumerateDevice(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskQueryId(
|
||||
IN PDEVICE_OBJECT Pdo,
|
||||
IN BUS_QUERY_ID_TYPE IdType,
|
||||
IN PUNICODE_STRING UnicodeIdString
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskQueryPnpCapabilities(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PDEVICE_CAPABILITIES Capabilities
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskGenerateDeviceName(
|
||||
IN BOOLEAN IsFdo,
|
||||
IN ULONG DeviceNumber,
|
||||
IN OPTIONAL ULONG PartitionNumber,
|
||||
IN OPTIONAL PLARGE_INTEGER StartingOffset,
|
||||
IN OPTIONAL PLARGE_INTEGER PartitionLength,
|
||||
OUT PUCHAR *RawName
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskCreateSymbolicLinks(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskUpdatePartitions(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskUpdateRemovablePartitions(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskCreatePdo(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN ULONG PartitionOrdinal,
|
||||
IN PPARTITION_INFORMATION_EX PartitionEntry,
|
||||
IN PARTITION_STYLE PartitionStyle,
|
||||
OUT PDEVICE_OBJECT *Pdo
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskDeleteSymbolicLinks(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskPdoQueryWmiRegInfo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT ULONG *RegFlags,
|
||||
OUT PUNICODE_STRING InstanceName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskPdoQueryWmiDataBlock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG BufferAvail,
|
||||
OUT PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskPdoSetWmiDataBlock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG BufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskPdoSetWmiDataItem(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG DataItemId,
|
||||
IN ULONG BufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskPdoExecuteWmiMethod(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG MethodId,
|
||||
IN ULONG InBufferSize,
|
||||
IN ULONG OutBufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskFdoQueryWmiRegInfo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT ULONG *RegFlags,
|
||||
OUT PUNICODE_STRING InstanceName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskFdoQueryWmiRegInfoEx(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT ULONG *RegFlags,
|
||||
OUT PUNICODE_STRING InstanceName,
|
||||
OUT PUNICODE_STRING MofName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskFdoQueryWmiDataBlock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG BufferAvail,
|
||||
OUT PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskFdoSetWmiDataBlock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG BufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskFdoSetWmiDataItem(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG DataItemId,
|
||||
IN ULONG BufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskFdoExecuteWmiMethod(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG MethodId,
|
||||
IN ULONG InBufferSize,
|
||||
IN ULONG OutBufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskWmiFunctionControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN CLASSENABLEDISABLEFUNCTION Function,
|
||||
IN BOOLEAN Enable
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskReadFailurePredictStatus(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskReadFailurePredictData(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskEnableDisableFailurePrediction(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
BOOLEAN Enable
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskEnableDisableFailurePredictPolling(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
BOOLEAN Enable,
|
||||
ULONG PollTimeInSeconds
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskAcquirePartitioningLock(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskReleasePartitioningLock(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
NTSTATUS NTAPI DiskInitializeReregistration(
|
||||
void
|
||||
);
|
||||
|
||||
extern GUIDREGINFO DiskWmiFdoGuidList[];
|
||||
extern GUIDREGINFO DiskWmiPdoGuidList[];
|
||||
|
||||
#if defined(_X86_)
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskReadDriveCapacity(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
#else
|
||||
#define DiskReadDriveCapacity(Fdo) ClassReadDriveCapacity(Fdo)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_X86_)
|
||||
|
||||
#if 0
|
||||
NTSTATUS
|
||||
DiskQuerySuggestedLinkName(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
#endif
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskSaveDetectInfo(
|
||||
PDRIVER_OBJECT DriverObject
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskCleanupDetectInfo(
|
||||
IN PDRIVER_OBJECT DriverObject
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskDriverReinitialization (
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PVOID Nothing,
|
||||
IN ULONG Count
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DiskConvertPartitionToExtended(
|
||||
IN PPARTITION_INFORMATION Partition,
|
||||
OUT PPARTITION_INFORMATION_EX PartitionEx
|
||||
);
|
||||
|
||||
PDRIVE_LAYOUT_INFORMATION_EX
|
||||
NTAPI
|
||||
DiskConvertLayoutToExtended(
|
||||
IN CONST PDRIVE_LAYOUT_INFORMATION Layout
|
||||
);
|
||||
|
||||
PDRIVE_LAYOUT_INFORMATION
|
||||
NTAPI
|
||||
DiskConvertExtendedToLayout(
|
||||
IN CONST PDRIVE_LAYOUT_INFORMATION_EX LayoutEx
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskReadPartitionTableEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN BypassCache,
|
||||
OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskWritePartitionTableEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskSetPartitionInformationEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN ULONG PartitionNumber,
|
||||
IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskSetPartitionInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN ULONG SectorSize,
|
||||
IN ULONG PartitionNumber,
|
||||
IN ULONG PartitionType
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskVerifyPartitionTable(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN FixErrors
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
DiskInvalidatePartitionTable(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN PartitionLockHeld
|
||||
);
|
||||
|
||||
#if defined (_X86_)
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskGetDetectInfo(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
OUT PDISK_DETECTION_INFO DetectInfo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskReadSignature(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
#else
|
||||
#define DiskGetDetectInfo(FdoExtension, DetectInfo) (STATUS_UNSUCCESSFUL)
|
||||
#endif
|
||||
|
||||
|
||||
#define DiskHashGuid(Guid) (((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0])
|
||||
|
||||
#endif /* _DISK_NEW_H_ */
|
|
@ -1,23 +0,0 @@
|
|||
//+-------------------------------------------------------------------------
|
||||
//
|
||||
// Microsoft Windows
|
||||
//
|
||||
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||||
//
|
||||
// File: disk.rc
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_DRV
|
||||
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
|
||||
#define VER_FILEDESCRIPTION_STR "PnP Disk Driver"
|
||||
#define VER_INTERNALNAME_STR "scsidisk.sys"
|
||||
#define VER_ORIGINALFILENAME_STR "scsidisk.sys"
|
||||
#define VER_LANGNEUTRAL
|
||||
|
||||
#include "common.ver"
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
; disk.inf
|
||||
;
|
||||
; Installation inf for the Disk drive adapter.
|
||||
;
|
||||
; SAMPLE INF File for Class Driver
|
||||
; FOR DDK - Driver Development Kit
|
||||
;
|
||||
; (c) Copyright 1999 Microsoft Corp.
|
||||
;
|
||||
|
||||
[Version]
|
||||
Signature="$Windows NT$"
|
||||
Provider=%MS%
|
||||
ClassGUID={4d36e967-e325-11ce-bfc1-08002be10318}
|
||||
Class=DiskDrive
|
||||
; CatalogFile=disk.cat ; Supply your own catalog file
|
||||
; see DDK Doc.
|
||||
DriverVer=08/27/1999
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir = 12
|
||||
|
||||
;
|
||||
; Driver information
|
||||
;
|
||||
|
||||
[Manufacturer]
|
||||
%MS% = MS.Mfg
|
||||
|
||||
[MS.Mfg]
|
||||
%MS.DeviceDesc0% = disk, GenDisk
|
||||
%MS.DeviceDesc1% = disk, GenOptical
|
||||
|
||||
|
||||
;
|
||||
; General installation section
|
||||
;
|
||||
|
||||
[disk]
|
||||
|
||||
;
|
||||
; File sections
|
||||
;
|
||||
|
||||
|
||||
;
|
||||
; Service Installation
|
||||
;
|
||||
|
||||
[disk.Services]
|
||||
AddService = disk, 0x00000002 , disk_Service_Inst
|
||||
|
||||
[disk_Service_Inst]
|
||||
DisplayName = %disk.SvcDesc%
|
||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
||||
StartType = 1 ; SERVICE_SYSTEM_START
|
||||
ErrorControl = 0x1 ; SERVICE_ERROR_NORMAL
|
||||
LoadOrderGroup = Pointer Port
|
||||
ServiceBinary = %12%\disk.sys
|
||||
|
||||
|
||||
;
|
||||
; Source file information
|
||||
;
|
||||
|
||||
[SourceDisksNames.x86]
|
||||
1 = %DiskId1%,,,""
|
||||
|
||||
[SourceDisksFiles]
|
||||
; Files for disk Microsoft Corp. Installation Disk #1 (DiskDrive)
|
||||
disk.sys = 1,,
|
||||
|
||||
|
||||
[Strings]
|
||||
|
||||
;
|
||||
; Non-Localizable Strings
|
||||
;
|
||||
|
||||
REG_SZ = 0x00000000
|
||||
REG_MULTI_SZ = 0x00010000
|
||||
REG_EXPAND_SZ = 0x00020000
|
||||
REG_BINARY = 0x00000001
|
||||
REG_DWORD = 0x00010001
|
||||
SERVICEROOT = "System\CurrentControlSet\Services"
|
||||
|
||||
;
|
||||
; Localizable Strings
|
||||
;
|
||||
|
||||
MS.DeviceDesc0 = "Disk drive"
|
||||
MS.DeviceDesc1 = "Optical disk drive"
|
||||
DiskId1 = "Microsoft Corp. Installation Disk #1 (DiskDrive)"
|
||||
MS = "Microsoft Corp."
|
||||
disk.SvcDesc="Disk Drive"
|
||||
|
||||
[Strings.0418]
|
||||
MS.DeviceDesc0 = "Dispozitiv de disc"
|
||||
MS.DeviceDesc1 = "Dispozitiv de disc optic"
|
||||
DiskId1 = "Disc de instalare #1 (DiskDrive) al Microsoft Corp."
|
||||
MS = "Microsoft Corp."
|
||||
disk.SvcDesc="Dispozitiv de disc"
|
||||
|
||||
[Strings.041f]
|
||||
MS.DeviceDesc0 = "Disk sürücüsü"
|
||||
MS.DeviceDesc1 = "Işıklık disk sürücüsü"
|
||||
DiskId1 = "Microsoft Ortaklığı Kurulum Diski #1 (DiskDrive)"
|
||||
MS = "Microsoft Ortaklığı"
|
||||
disk.SvcDesc="Disk Sürücüsü"
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,331 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
disk.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI disk class driver
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "disk.h"
|
||||
|
||||
#define PtCache ClassDebugExternal1
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
|
||||
#pragma alloc_text(PAGE, DiskReadPartitionTableEx)
|
||||
#pragma alloc_text(PAGE, DiskWritePartitionTableEx)
|
||||
#pragma alloc_text(PAGE, DiskSetPartitionInformationEx)
|
||||
#endif
|
||||
|
||||
ULONG DiskBreakOnPtInval = FALSE;
|
||||
|
||||
//
|
||||
// By default, 64-bit systems can see GPT disks and 32-bit systems
|
||||
// cannot. This will likely change in the future.
|
||||
//
|
||||
|
||||
#if defined(_WIN64)
|
||||
ULONG DiskDisableGpt = FALSE;
|
||||
#else
|
||||
ULONG DiskDisableGpt = TRUE;
|
||||
#endif
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskReadPartitionTableEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN BypassCache,
|
||||
OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will return the current layout information for the disk.
|
||||
If the cached information is still valid then it will be returned,
|
||||
otherwise the layout will be retrieved from the kernel and cached for
|
||||
future use.
|
||||
|
||||
This routine must be called with the partitioning lock held. The
|
||||
partition list which is returned is not guaranteed to remain valid
|
||||
once the lock has been released.
|
||||
|
||||
Arguments:
|
||||
|
||||
Fdo - a pointer to the FDO for the disk.
|
||||
|
||||
DriveLayout - a location to store a pointer to the drive layout information.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful or an error status indicating what failed.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
NTSTATUS status;
|
||||
PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
|
||||
|
||||
layoutEx = NULL;
|
||||
|
||||
if(BypassCache) {
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
DebugPrint((PtCache, "DiskRPTEx: cache bypassed and invalidated for "
|
||||
"FDO %#p\n", Fdo));
|
||||
}
|
||||
|
||||
//
|
||||
// If the cached partition table is present then return a copy of it.
|
||||
//
|
||||
|
||||
if (diskData->CachedPartitionTableValid != FALSE) {
|
||||
|
||||
ULONG partitionNumber;
|
||||
PDRIVE_LAYOUT_INFORMATION_EX layout = diskData->CachedPartitionTable;
|
||||
|
||||
//
|
||||
// Clear the partition numbers from the list entries
|
||||
//
|
||||
|
||||
for(partitionNumber = 0;
|
||||
partitionNumber < layout->PartitionCount;
|
||||
partitionNumber++) {
|
||||
layout->PartitionEntry[partitionNumber].PartitionNumber = 0;
|
||||
}
|
||||
|
||||
*DriveLayout = diskData->CachedPartitionTable;
|
||||
|
||||
DebugPrint((PtCache, "DiskRPTEx: cached PT returned (%#p) for "
|
||||
"FDO %#p\n",
|
||||
*DriveLayout, Fdo));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ASSERTMSG("DiskReadPartitionTableEx is not using cached partition table",
|
||||
(DiskBreakOnPtInval == FALSE));
|
||||
|
||||
//
|
||||
// If there's a cached partition table still around then free it.
|
||||
//
|
||||
|
||||
if(diskData->CachedPartitionTable) {
|
||||
DebugPrint((PtCache, "DiskRPTEx: cached PT (%#p) freed for FDO %#p\n",
|
||||
diskData->CachedPartitionTable, Fdo));
|
||||
|
||||
ExFreePool(diskData->CachedPartitionTable);
|
||||
diskData->CachedPartitionTable = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// By default, X86 disables recognition of GPT disks. Instead we
|
||||
// return the protective MBR partition. Use IoReadPartitionTable
|
||||
// to get this.
|
||||
//
|
||||
|
||||
status = IoReadPartitionTableEx(Fdo->DeviceObject, &layoutEx);
|
||||
|
||||
if (DiskDisableGpt) {
|
||||
PDRIVE_LAYOUT_INFORMATION layout;
|
||||
|
||||
if (NT_SUCCESS (status) &&
|
||||
layoutEx->PartitionStyle == PARTITION_STYLE_GPT) {
|
||||
|
||||
//
|
||||
// ISSUE - 2000/29/08 - math: Remove from final product.
|
||||
// Leave this debug print in for a while until everybody
|
||||
// has had a chance to convert their GPT disks to MBR.
|
||||
//
|
||||
|
||||
DbgPrint ("DISK: Disk %p recognized as a GPT disk on a system without GPT support.\n"
|
||||
" Disk will appear as RAW.\n",
|
||||
Fdo->DeviceObject);
|
||||
|
||||
ExFreePool (layoutEx);
|
||||
status = IoReadPartitionTable(Fdo->DeviceObject,
|
||||
Fdo->DiskGeometry.BytesPerSector,
|
||||
FALSE,
|
||||
&layout);
|
||||
if (NT_SUCCESS (status)) {
|
||||
layoutEx = DiskConvertLayoutToExtended(layout);
|
||||
ExFreePool (layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diskData->CachedPartitionTable = layoutEx;
|
||||
|
||||
//
|
||||
// If the routine fails make sure we don't have a stale partition table
|
||||
// pointer. Otherwise indicate that the table is now valid.
|
||||
//
|
||||
|
||||
if(!NT_SUCCESS(status)) {
|
||||
diskData->CachedPartitionTable = NULL;
|
||||
} else {
|
||||
diskData->CachedPartitionTableValid = TRUE;
|
||||
}
|
||||
|
||||
*DriveLayout = diskData->CachedPartitionTable;
|
||||
|
||||
DebugPrint((PtCache, "DiskRPTEx: returning PT %#p for FDO %#p with status "
|
||||
"%#08lx. PT is %scached\n",
|
||||
*DriveLayout,
|
||||
Fdo,
|
||||
status,
|
||||
(diskData->CachedPartitionTableValid ? "" : "not ")));
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskWritePartitionTableEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will invalidate the cached partition table. It will then
|
||||
write the new drive layout to disk.
|
||||
|
||||
Arguments:
|
||||
|
||||
Fdo - the FDO for the disk getting the new partition table.
|
||||
|
||||
DriveLayout - the new drive layout.
|
||||
|
||||
Return Value:
|
||||
|
||||
status
|
||||
|
||||
--*/
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
|
||||
//
|
||||
// Invalidate the cached partition table. Do not free it as it may be
|
||||
// the very drive layout that was passed in to us.
|
||||
//
|
||||
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
|
||||
DebugPrint((PtCache, "DiskWPTEx: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
|
||||
if (DiskDisableGpt) {
|
||||
if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT) {
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return IoWritePartitionTableEx(Fdo->DeviceObject, DriveLayout);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskSetPartitionInformationEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN ULONG PartitionNumber,
|
||||
IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
|
||||
)
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
DebugPrint((PtCache, "DiskSPIEx: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
|
||||
if (DiskDisableGpt) {
|
||||
if (PartitionInfo->PartitionStyle == PARTITION_STYLE_GPT) {
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return IoSetPartitionInformationEx(Fdo->DeviceObject,
|
||||
PartitionNumber,
|
||||
PartitionInfo);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskSetPartitionInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN ULONG SectorSize,
|
||||
IN ULONG PartitionNumber,
|
||||
IN ULONG PartitionType
|
||||
)
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
DebugPrint((PtCache, "DiskSPI: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
|
||||
return IoSetPartitionInformation(Fdo->DeviceObject,
|
||||
SectorSize,
|
||||
PartitionNumber,
|
||||
PartitionType);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
DiskInvalidatePartitionTable(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN PartitionLockHeld
|
||||
)
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
BOOLEAN wasValid;
|
||||
|
||||
wasValid = (BOOLEAN) (diskData->CachedPartitionTableValid ? TRUE : FALSE);
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
|
||||
DebugPrint((PtCache, "DiskIPT: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
|
||||
if((PartitionLockHeld) && (diskData->CachedPartitionTable != NULL)) {
|
||||
DebugPrint((PtCache, "DiskIPT: Freeing PT cache (%#p) for FDO %#p\n",
|
||||
diskData->CachedPartitionTable, Fdo));
|
||||
ExFreePool(diskData->CachedPartitionTable);
|
||||
diskData->CachedPartitionTable = NULL;
|
||||
}
|
||||
|
||||
return wasValid;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DiskVerifyPartitionTable(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN FixErrors
|
||||
)
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
|
||||
if(FixErrors) {
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
DebugPrint((PtCache, "DiskWPTEx: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
}
|
||||
|
||||
return IoVerifyPartitionTable(Fdo->DeviceObject, FixErrors);
|
||||
}
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue