[CLASSPNP][DISK_NEW][CDROM_NEW] Remove the drivers

Due to WDK/DDK licensing issues

CORE-17129
This commit is contained in:
Victor Perevertkin 2020-08-28 05:44:08 +03:00
parent 3da77f9173
commit c57350e295
No known key found for this signature in database
GPG key ID: C750B7222E9C7830
43 changed files with 0 additions and 51483 deletions

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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__ */

View file

@ -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"

View file

@ -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

View file

@ -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"

View file

@ -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;
}

View file

@ -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 */ \
)

View file

@ -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

View file

@ -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"

View file

@ -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_ */

View file

@ -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)

View file

@ -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()

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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 */

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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_ */

View file

@ -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"

View file

@ -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

View file

@ -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