[CDROM_NEW] Import Microsoft CDROM class driver from GitHub

The source code is licensed under MS-PL license, taken from Windows Driver Samples
repository (microsoft/Windows-driver-samples@master/storage/class/cdrom/)
Synched with commit 96eb96dfb613e4c745db6bd1f53a92fe7e2290fc
The driver is written for Windows 10 and uses KMDF so we compile it with ntoskrnl_vista
and wdf01000 statically linked (for wdf01000 this will likely be changed in future)

CORE-17129
This commit is contained in:
Victor Perevertkin 2020-10-16 04:37:10 +03:00
parent 3499b96682
commit 83b85e2124
No known key found for this signature in database
GPG key ID: C750B7222E9C7830
23 changed files with 35499 additions and 0 deletions

View file

@ -0,0 +1,41 @@
remove_definitions(-D_WIN32_WINNT=0x502)
list(APPEND SOURCE
aacs.c
autorun.c
cdrom.c
common.c
data.c
guid.c
init.c
ioctl.c
mmc.c
pnppower.c
scratch.c
sense.c
zpodd.c
cdrom.h)
add_library(cdrom MODULE ${SOURCE})
set_module_type(cdrom kernelmodedriver)
if(GCC OR CLANG)
target_compile_options(cdrom PRIVATE -Wno-format -Wno-unused-variable -Wno-pointer-sign)
endif()
if(GCC)
target_compile_options(cdrom PRIVATE -Wno-unknown-pragmas -Wno-incompatible-pointer-types -Wno-switch)
endif()
if(CLANG)
target_compile_options(cdrom PRIVATE -Wno-enum-conversion -Wno-tautological-constant-compare)
endif()
target_compile_definitions(cdrom PRIVATE DEBUG_USE_KDPRINT)
target_link_libraries(cdrom wdf01000 ntoskrnl_vista libcntpr ${PSEH_LIB})
add_importlibs(cdrom ntoskrnl hal)
# add_pch(cdrom cdrom.h SOURCE)
add_cd_file(TARGET cdrom DESTINATION reactos/system32/drivers NO_CAB FOR all)
add_driver_inf(cdrom cdrom.inf)

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,159 @@
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
[Version]
Signature = "$WINDOWS NT$"
LayoutFile = layout.inf
Class = CDROM
ClassGuid = {4D36E965-E325-11CE-BFC1-08002BE10318}
Provider = %MSFT%
; Git commit 96eb96d @ https://github.com/microsoft/Windows-driver-samples
DriverVer = 08/11/2016, 1.0
;[SourceDisksNames]
;3426=windows cd
;[SourceDisksFiles]
;cdrom.sys = 3426
[DestinationDirs]
cdrom_copyfiles = 12
[cdrom_copyfiles]
cdrom.sys,,,0x100
[ControlFlags]
BasicDriverOk=*
[Manufacturer]
%MITSUMI% = mitsumi_cdrom,NT$ARCH$
%GenManufacturer% = cdrom_device,NT$ARCH$
;[mitsumi_cdrom.NT$ARCH$]
[mitsumi_cdrom.NT]
%Mitsumi_cdrom_devdesc% = mitsumi_install,IDE\CdRomMITSUMI_CD-ROM________!A________________
;[cdrom_device.NT$ARCH$]
[cdrom_device.NT]
;;
;; 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
%gencdrom_devdesc% = cdrom_install_ISO_drive,SCSI\CdRomMsft____Virtual_DVD-ROM_
;;
;; Use to add filter drivers for the device
;;
[mitsumi_addreg]
HKR,,"FriendlyName",,%Mitsumi_Generic_FriendlyName%
;;
;; Give ISO drives a more friendly name
;;
[ISO_addreg]
HKR,,"FriendlyName",,%ISO_Generic_FriendlyName%
;;
;; 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.
;;
[autorun_addreg]
HKR,,"AutoRun",0x00010003,1
HKR,,"AutoRunAlwaysDisable", 0x00010008, "NEC MBR-7 "
HKR,,"AutoRunAlwaysDisable", 0x00010008, "NEC MBR-7.4 "
HKR,,"AutoRunAlwaysDisable", 0x00010008, "PIONEER CHANGR DRM-1804X"
HKR,,"AutoRunAlwaysDisable", 0x00010008, "PIONEER CD-ROM DRM-6324X"
HKR,,"AutoRunAlwaysDisable", 0x00010008, "PIONEER CD-ROM DRM-624X "
HKR,,"AutoRunAlwaysDisable", 0x00010008, "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
HKR,"Storport","MinimumIdleTimeoutInMS",0x00010001,0
;;
;; Installation section for mitsumi.
;;
[mitsumi_install]
CopyFiles=cdrom_copyfiles
[mitsumi_install.HW]
AddReg=nosync_addreg,mitsumi_addreg
[mitsumi_install.Services]
Needs=cdrom_install.Services
;;
;; Installation section for generic cdrom.
;;
[cdrom_install]
CopyFiles=cdrom_copyfiles
[cdrom_install.HW]
AddReg=nosync_addreg
[cdrom_install.Services]
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection,cdrom_EventLog_InstallSection
[cdrom_install_ISO_drive]
CopyFiles=cdrom_copyfiles
[cdrom_install_ISO_drive.HW]
AddReg=nosync_addreg,ISO_addreg
[cdrom_install_ISO_drive.Services]
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection,cdrom_EventLog_InstallSection
;;
;; Service install sections
;;
[cdrom_ServiceInstallSection]
DisplayName = %cdrom_ServiceDesc%
ServiceType = 1
StartType = 1
ErrorControl = 1
ServiceBinary = %12%\cdrom.sys
LoadOrderGroup = "SCSI CDROM Class"
AddReg=autorun_addreg
[cdrom_EventLog_InstallSection]
;AddReg=cdrom_EventLog_AddReg
;[cdrom_EventLog_AddReg]
;HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll"
;HKR,,TypesSupported,0x00010001,7
[Strings]
MSFT = "Microsoft"
;; Manufacturer specific strings
MITSUMI = "Mitsumi"
GenManufacturer = "(Standard CD-ROM drives)"
;; Descriptions for enumerated brands and models
Mitsumi_cdrom_devdesc = "Mitsumi CD-ROM Drive"
gencdrom_devdesc = "CD-ROM Drive"
;; Friendly names
Mitsumi_Generic_FriendlyName = "Mitsumi CD-ROM Drive"
ISO_Generic_FriendlyName = "Microsoft Virtual DVD-ROM"
;; Service descriptions
cdrom_ServiceDesc = "CD-ROM Driver"

View file

@ -0,0 +1,23 @@
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: scsicdrm.rc
//
//--------------------------------------------------------------------------
#include <verrsrc.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

@ -0,0 +1,383 @@
/*++
Copyright (C) Microsoft Corporation. All rights reserved.
Module Name:
cdromp.h
Abstract:
Private header file for cdrom.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 __CDROMP_H__
#define __CDROMP_H__
#include <scsi.h>
#include <storduid.h>
#include <mountdev.h>
#include <ioevent.h>
#include <ntintsafe.h>
/*
* IA64 requires 8-byte alignment for pointers, but the IA64 NT kernel expects 16-byte alignment
*/
#ifdef _WIN64
#define PTRALIGN DECLSPEC_ALIGN(16)
#else
#define PTRALIGN
#endif
// NOTE: Start with a smaller 100 second maximum, due to current assert in CLASSPNP
// 0x0000 00C9'2A69 C000 (864,000,000,000) is 24 hours in 100ns units
// 0x0000 0000'3B9A CA00 ( 1,000,000,000) is 100 seconds in 100ns units
#define MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS (0x3B9ACA00)
// structures to simplify matching devices, ids, and hacks required for
// these ids.
typedef struct _CDROM_SCAN_FOR_SPECIAL_INFO {
//
// * NULL pointers indicates that no match is required.
// * empty string will only match an empty string. non-existant strings
// in the device descriptor are considered empty strings for this match.
// (ie. "" will only match "")
// * all other strings will do partial matches, based upon
// string provided (ie. "hi" will match "hitazen" and "higazui")
// * array must end with all three PCHARs being set to NULL.
//
PCHAR VendorId;
PCHAR ProductId;
PCHAR ProductRevision;
//
// marked as a ULONG_PTR to allow use as either a ptr to a data block
// or 32 bits worth of flags. (64 bits on 64 bit systems) no longer a
// const so that it may be dynamically built.
//
ULONG_PTR Data;
} CDROM_SCAN_FOR_SPECIAL_INFO, *PCDROM_SCAN_FOR_SPECIAL_INFO;
// Define the various states that media can be in for autorun.
typedef enum _MEDIA_CHANGE_DETECTION_STATE {
MediaUnknown,
MediaPresent,
MediaNotPresent,
MediaUnavailable // e.g. cd-r media undergoing burn
} MEDIA_CHANGE_DETECTION_STATE, *PMEDIA_CHANGE_DETECTION_STATE;
/*++////////////////////////////////////////////////////////////////////////////
This structure defines the history kept for a given transfer packet.
It includes a srb status/sense data structure that is always either valid
or zero-filled for the full 18 bytes, time sent/completed, and how long
the retry delay was requested to be.
--*/
typedef struct _SRB_HISTORY_ITEM {
LARGE_INTEGER TickCountSent; // 0x00..0x07
LARGE_INTEGER TickCountCompleted; // 0x08..0x0F
ULONG MillisecondsDelayOnRetry; // 0x10..0x13
SENSE_DATA NormalizedSenseData; // 0x14..0x25 (0x12 bytes)
UCHAR SrbStatus; // 0x26
UCHAR ClassDriverUse; // 0x27 -- one byte free (alignment)
} SRB_HISTORY_ITEM, *PSRB_HISTORY_ITEM;
typedef struct _SRB_HISTORY {
ULONG_PTR ClassDriverUse[4]; // for the class driver to use as they please
_Field_range_(1,30000)
ULONG TotalHistoryCount;
_Field_range_(0,TotalHistoryCount)
ULONG UsedHistoryCount;
_Field_size_part_(TotalHistoryCount, UsedHistoryCount)
SRB_HISTORY_ITEM History[1];
} SRB_HISTORY, *PSRB_HISTORY;
extern CDROM_SCAN_FOR_SPECIAL_INFO CdRomBadItems[];
/*++////////////////////////////////////////////////////////////////////////////*/
// legacy registry key and values.
#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 WINPE_REG_KEY_NAME (L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\MiniNT")
#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_RESERVE6 (0x00000008)
#define FDO_HACK_GESN_IGNORE_OPCHANGE (0x00000010)
#define FDO_HACK_NO_STREAMING (0x00000020)
#define FDO_HACK_NO_ASYNCHRONOUS_NOTIFICATION (0x00000040)
#define FDO_HACK_VALID_FLAGS (0x0000007F)
#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
/*
* We retry failed I/O requests at 1-second intervals.
* In the case of a failure due to bus reset, we want to make sure that we retry after the allowable
* reset time. For SCSI, the allowable reset time is 5 seconds. ScsiPort queues requests during
* a bus reset, which should cause us to retry after the reset is over; but the requests queued in
* the miniport are failed all the way back to us immediately. In any event, in order to make
* extra sure that our retries span the allowable reset time, we should retry more than 5 times.
*/
//#define NUM_IO_RETRIES 8
#define CDROM_VOLUME_VERIFY_CHECKED 0x34
#define CDROM_TAG_PRIVATE_DATA 'CPcS'
typedef struct _MEDIA_CHANGE_DETECTION_INFO {
// Use AN if supported so that we don't need to poll for media change notifications.
BOOLEAN AsynchronousNotificationSupported;
// If AN is turned on and we received an AN signal when the device is exclusively locked,
// we should take a note and send down a GESN when the lock is lifted, since otherwise
// we will lose the signal. Even worse, some ODD models will signal the event again next
// time a SYNC CACHE is sent down, and processing the event in that arbitrary timing may
// cause unexpected behaviors.
BOOLEAN ANSignalPendingDueToExclusiveLock;
// Mutex to synchronize enable/disable requests and media state changes
KMUTEX MediaChangeMutex;
// For request erialization use.
// This irp is used in timer callback routine, will be sent to the device itself.
// so that the sequentail queue will get request wrapped on this irp. After doing
// the real work, this irp will be completed to indicate it's ok to send the next
// MCN request.
PIRP MediaChangeSyncIrp;
// The last known state of the media (present, not present, unknown).
// Protected by MediaChangeMutex.
MEDIA_CHANGE_DETECTION_STATE LastKnownMediaDetectionState;
// The last state of the media (present, not present, unknown) reported to apps
// via notifications. Protected by MediaChangeMutex
MEDIA_CHANGE_DETECTION_STATE LastReportedMediaDetectionState;
// 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;
// recent changes allowed instant retries of the MCN REQUEST. 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 REQUEST is currently in use.
// If this value is zero, then the REQUEST 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
//
// This protect is needed in the polling case since the timer is fired asynchronous
// to our sequential I/O queues, and when the timer is fired, our Sync Irp could be
// still using the MediaChangeRequest. However, if AN is used, then each interrupt
// will cause us to queue a request, so interrupts are serialized, and within the
// handling of each request, we already sequentially use the MediaChangeRequest if
// we need retries. We still use it in case of AN to be consistent with polling, but
// if in the future we remove polling altogether, then we don't need this field anymore.
LONG MediaChangeRequestInUse;
// Pointer to the REQUEST to be used for media change detection.
// protected by Interlocked MediaChangeRequestInUse
WDFREQUEST MediaChangeRequest;
// The srb for the media change detection.
// protected by Interlocked MediaChangeIrpInUse
SCSI_REQUEST_BLOCK MediaChangeSrb;
PUCHAR SenseBuffer;
ULONG SrbFlags;
// Handle to the display state notification registration.
PVOID DisplayStateCallbackHandle;
} MEDIA_CHANGE_DETECTION_INFO, *PMEDIA_CHANGE_DETECTION_INFO;
#define DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS (60 * 1000)
#define DELAY_TIME_TO_ENTER_AOAC_IDLE_POWER_IN_MS (10 * 1000)
#define BECOMING_READY_RETRY_COUNT (15)
#define BECOMING_READY_RETRY_INTERNVAL_IN_100NS (2 * 1000 * 1000)
typedef struct _ZERO_POWER_ODD_INFO {
UCHAR LoadingMechanism; // From Removable Medium Feature Descriptor
UCHAR Load; // From Removable Medium Feature Descriptor
D3COLD_SUPPORT_INTERFACE D3ColdInterface; // D3Cold interface from ACPI
BOOLEAN Reserved; // Reserved
BOOLEAN InZeroPowerState; // Is device currently in Zero Power State
BOOLEAN RetryFirstCommand; // First command after power resume should be retried
BOOLEAN MonitorStartStopUnit; // If 1. drawer 2. soft eject 3. no media 4. Immed=0,
// we will not receive any GESN events, and so we should
// monitor the command to get notified
ULONG BecomingReadyRetryCount; // How many times we should retry for becoming ready
UCHAR SenseKey; // sense code from TUR to check media & tray status
UCHAR AdditionalSenseCode; // sense code from TUR to check media & tray status
UCHAR AdditionalSenseCodeQualifier; // sense code from TUR to check media & tray status
PGET_CONFIGURATION_HEADER GetConfigurationBuffer; // Cached Get Configuration response from device
ULONG GetConfigurationBufferSize; // Size of the above buffer
} ZERO_POWER_ODD_INFO, *PZERO_POWER_ODD_INFO;
typedef enum {
SimpleMediaLock,
SecureMediaLock,
InternalMediaLock
} MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE;
typedef enum _CDROM_DETECTION_STATE {
CdromDetectionUnknown = 0,
CdromDetectionUnsupported = 1,
CdromDetectionSupported = 2
} CDROM_DETECTION_STATE, *PCDROM_DETECTION_STATE;
typedef struct _CDROM_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!)
} CDROM_ERROR_LOG_DATA, *PCDROM_ERROR_LOG_DATA;
#define NUM_ERROR_LOG_ENTRIES 16
//
// add to the front of this structure to help prevent illegal
// snooping by other utilities.
//
typedef struct _CDROM_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 ReEnableThreshhold; // 0 means never
} Perf;
ULONG_PTR HackFlags;
STORAGE_HOTPLUG_INFO HotplugInfo;
BOOLEAN TimerStarted;
BOOLEAN LoggedTURFailureSinceLastIO;
BOOLEAN LoggedSYNCFailure;
// not use WDFSPINLOCK to avoid exposing private object creation
// in initialization code. (cdrom.sys was in WDK example)
KSPIN_LOCK SpinLock;
// Circular array of timestamped logs of errors that occurred on this device.
ULONG ErrorLogNextIndex;
CDROM_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES];
}CDROM_PRIVATE_FDO_DATA, *PCDROM_PRIVATE_FDO_DATA;
//
// this is a private structure, but must be kept here
// to properly compile size of FUNCTIONAL_DEVICE_EXTENSION
//
typedef struct _FILE_OBJECT_CONTEXT {
WDFFILEOBJECT FileObject;
WDFDEVICE DeviceObject;
ULONG LockCount;
ULONG McnDisableCount;
BOOLEAN EnforceStreamingRead;
BOOLEAN EnforceStreamingWrite;
} FILE_OBJECT_CONTEXT, *PFILE_OBJECT_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FILE_OBJECT_CONTEXT, FileObjectGetContext)
#define NOT_READY_RETRY_INTERVAL 10
#define MODE_PAGE_DATA_SIZE 192
//
// per session device
//
#define INVALID_SESSION ((ULONG)-1)
#endif // __CDROMP_H__

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,283 @@
/*++
Copyright (C) Microsoft Corporation. All rights reserved.
Module Name:
Abstract:
Environment:
Notes:
Revision History:
--*/
#include "ntddk.h"
#include "cdrom.h"
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("PAGEDATA")
#endif
/*
#define CDROM_HACK_DEC_RRD (0x00000001)
#define CDROM_HACK_FUJITSU_FMCD_10x (0x00000002)
#define CDROM_HACK_HITACHI_1750 (0x00000004) - obsolete.
#define CDROM_HACK_HITACHI_GD_2000 (0x00000008)
#define CDROM_HACK_TOSHIBA_SD_W1101 (0x00000010)
#define CDROM_HACK_TOSHIBA_XM_3xx (0x00000020) - obsolete.
#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)
*/
CDROM_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 automatcially 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 , NULL, 0x0040 },
// plextor defined a "READ_CD" type command before there was
// a standard, so fall back on this as an option.
{ "PLEXTOR ", NULL , 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, 0x0200 },
// 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 },
// Polling frequently on virtual optical devices created by Hyper-V will
// cause a significant perf / power hit. These devices need to be polled
// less frequently for device state changes.
{ "MSFT ", NULL , NULL, 0x2000 },
// and finally, a place to finish the list. :)
{ NULL , NULL , NULL, 0x0000 }
};
CDROM_SCAN_FOR_SPECIAL_INFO CdRomBadItems[] = { // Type (HH, slim) + WHQL Date, if known
{ "" , "MITSUMI CD-ROM FX240" , NULL , 0x02 },
{ "" , "MITSUMI CD-ROM FX320" , NULL , 0x02 },
{ "" , "MITSUMI CD-ROM FX322" , NULL , 0x02 },
{ "" , "TEAC DV-28E-A" , "2.0A", 0x02 },
{ "" , "HP CD-Writer cd16h" , "Q000", 0x02 },
{ "" , "_NEC NR-7800A" , "1.33", 0x02 },
{ "" , "COMPAQ CRD-8481B" , NULL , 0x04 },
// The following is a list of device that report too many OpChange/Add events.
// They require ignoring (or not sending) the OpChange flag in the GESN command.
// This list contains vendor ID and product ID as separate strings for USB/1394 interface.
{ "HL-DT-ST", "DVDRAM GMA-4020B" , NULL , 0x10 }, // hh , 2002/04/22
{ "HL-DT-ST", "DVD-RW GCA-4020B" , NULL , 0x10 }, // hh , 2002/05/14
{ "HL-DT-ST", "DVDRAM GSA-4040B" , NULL , 0x10 }, // hh , 2003/05/06
{ "HL-DT-ST", "DVDRAM GMA-4040B" , NULL , 0x10 }, // hh , 2003/07/27
{ "HL-DT-ST", "DVD-RW GWA-4040B" , NULL , 0x10 }, // hh , 2003/11/18
{ "HL-DT-ST", "DVDRAM GSA-4081B" , NULL , 0x10 }, // hh , 2003/11/06
{ "HL-DT-ST", "DVDRAM GSA-4082B" , NULL , 0x10 }, // hh , 2004/01/27
{ "HL-DT-ST", "DVD-RW GWA-4082B" , NULL , 0x10 }, // hh , 2004/03/11
{ "HL-DT-ST", "DVDRAM GSA-4120B" , NULL , 0x10 }, // hh , 2004/05/16
{ "HL-DT-ST", "DVD+RW GRA-4120B" , NULL , 0x10 }, // hh , 2004/04/28
{ "HL-DT-ST", "DVDRAM GSA-4160B" , NULL , 0x10 }, // hh , 2004/08/12
{ "HL-DT-ST", "DVD-RW GWA-4160B" , NULL , 0x10 }, // hh , 2004/08/24
{ "HL-DT-ST", "DVDRAM GSA-4163B" , NULL , 0x10 }, // hh , 2004/11/09
{ "HL-DT-ST", "DVD-RW GWA-4163B" , NULL , 0x10 }, // hh , 2004/12/29
{ "HL-DT-ST", "DVDRAM GSA-4165B" , NULL , 0x10 }, // hh , 2005/06/09
{ "HL-DT-ST", "DVDRAM_GSA-4165B" , NULL , 0x10 }, // hh , 2005/06/28
{ "HL-DT-ST", "DVD-RW GWA-4165B" , NULL , 0x10 }, // hh , 2005/08/23
{ "HL-DT-ST", "DVDRAM GSA-4167B" , NULL , 0x10 }, // hh , 2005/07/01
{ "HL-DT-ST", "DVDRAM GSA-H10N" , NULL , 0x10 }, // hh , 2006/02/16
{ "HL-DT-ST", "DVDRAM_GSA-H10N" , NULL , 0x10 }, // hh , 2006/02/16
{ "HL-DT-ST", "DVDRAM GSA-H10L" , NULL , 0x10 }, // hh , 2006/02/27
{ "HL-DT-ST", "DVDRAM_GSA-H10L" , NULL , 0x10 }, // hh , 2006/04/21
{ "HL-DT-ST", "DVDRAM GSA-H10A" , NULL , 0x10 }, // hh , 2006/01/03
{ "HL-DT-ST", "DVDRAM_GSA-H10A" , NULL , 0x10 }, // hh , 2006/05/14
{ "HL-DT-ST", "DVD-RW GSA-H11N" , NULL , 0x10 }, // hh , 2006/04/28
{ "HL-DT-ST", "DVD-RW_GSA-H11N" , NULL , 0x10 }, // hh , 2006/02/22
{ "HL-DT-ST", "DVDRAM GSA-4080N" , NULL , 0x10 }, // slim, 2004/08/08
{ "HL-DT-ST", "DVDRAM GMA-4080N" , NULL , 0x10 }, // slim, 2004/11/09
{ "HL-DT-ST", "DVD-RW GCA-4080N" , NULL , 0x10 }, // slim, 2004/11/22
{ "HL-DT-ST", "DVD-RW GWA-4080N" , NULL , 0x10 }, // slim, 2004/08/17
{ "HL-DT-ST", "DVDRAM GSA-4082N" , NULL , 0x10 }, // slim, 2005/07/12
{ "HL-DT-ST", "DVDRAM_GSA-4082N" , NULL , 0x10 }, // slim, 2005/09/21
{ "HL-DT-ST", "DVDRAM GMA-4082N" , NULL , 0x10 }, // slim, 2005/10/20
{ "HL-DT-ST", "DVD-RW GRA-4082N" , NULL , 0x10 }, // slim, 2006/06/07
{ "HL-DT-ST", "DVD-RW GWA-4082N" , NULL , 0x10 }, // slim, 2005/05/24
{ "HL-DT-ST", "DVDRAM GMA4082Nf" , NULL , 0x10 }, // slim, 2006/02/28
{ "HL-DT-ST", "DVDRAM GMA4082Nj" , NULL , 0x10 }, // slim, 2006/01/26
{ "HL-DT-ST", "DVDRAM GSA-4084N" , NULL , 0x10 }, // slim, 2005/12/21
{ "HL-DT-ST", "DVDRAM GMA-4084N" , NULL , 0x10 }, // slim, 2006/02/15
{ "HP" , "DVD Writer 550s" , NULL , 0x10 }, // slim, 2006/05/08
{ "HL-DT-ST", "DVDRAM GSA-T10N" , NULL , 0x10 }, // slim, 2006/07/26
{ "HL-DT-ST", "DVDRAM_GSA-T10N" , NULL , 0x10 }, // slim, 2006/07/26
{ "HL-DT-ST", "DVD+-RW GSA-T11N" , NULL , 0x10 }, // slim, 2006/07/25
{ "HL-DT-ST", "DVD-ROM GDR8160B" , NULL , 0x10 }, // hh , 2001/10/12
{ "COMPAQ" , "DVD-ROM GDR8160B" , NULL , 0x10 }, // hh , 2001/11/08
{ "HL-DT-ST", "DVD-ROM GDR8161B" , NULL , 0x10 }, // hh , 2002/07/19
{ "HL-DT-ST", "DVD-ROM GDR8162B" , NULL , 0x10 }, // hh , 2003/04/22
{ "HL-DT-ST", "DVD-ROM GDR8163B" , NULL , 0x10 }, // hh , 2004/05/19
{ "HL-DT-ST", "DVD-ROM GDR8164B" , NULL , 0x10 }, // hh , 2005/06/29
{ "HL-DT-ST", "DVD-ROM GDRH10N" , NULL , 0x10 }, // hh , 2006/03/07
{ "HL-DT-ST", "DVD-ROM GDR8081N" , NULL , 0x10 }, // slim, 2001/08/27
{ "HL-DT-ST", "DVD-ROM GDR8082N" , NULL , 0x10 }, // slim, 2003/02/02
{ "HL-DT-ST", "DVD-ROM GDR8083N" , NULL , 0x10 }, // slim, 2003/02/02
{ "HL-DT-ST", "DVD-ROM GDR8085N" , NULL , 0x10 }, // slim, 2005/11/10
{ "HL-DT-ST", "RW/DVD GCC-4080N" , NULL , 0x10 }, // slim, 2001/08/21
{ "HL-DT-ST", "RW/DVD_GCC-4080N" , NULL , 0x10 }, // slim,
{ "HL-DT-ST", "RW/DVD GCC-4160N" , NULL , 0x10 }, // slim, 2002/04/08
{ "HL-DT-ST", "RW/DVD GCC-4240N" , NULL , 0x10 }, // slim, 2002/04/26
{ "HL-DT-ST", "RW/DVD GCC-4241N" , NULL , 0x10 }, // slim, 2003/04/07
{ "HL-DT-ST", "RW/DVD_GCC-4241N" , NULL , 0x10 }, // slim, 2004/03/07
{ "HL-DT-ST", "RW/DVD GCC-4242N" , NULL , 0x10 }, // slim, 2003/12/21
{ "HL-DT-ST", "RW/DVD GCC-4246N" , NULL , 0x10 }, // slim, 2005/05/23
{ "HL-DT-ST", "BD-RE GBW-H10N" , NULL , 0x10 }, // hh , 2006/06/27
{ "HL-DT-ST", "DVDRAM GSA-4083N" , NULL , 0x10 }, // hh , 2006/05/17
{ "HL-DT-ST", "DVD+-RW GWA4083N" , NULL , 0x10 }, // hh , 2006/06/05
{ "PIONEER", "DVD-RW DVR-106D" , NULL , 0x10 }, // hh , ?
{ "ASUS", "DVD-RW DRW-0402P" , NULL , 0x10 }, // hh , ?
//
// This list contains devices that claims to support asynchronous notification, but
// doesn't handle it well (e.g., some TSST devices will not report media removal if
// the GESN command is sent down immediately after the AN interrupt, they need some
// time in between to be able to correctly report media removal).
//
{ "TSSTcorp", "CDDVDW SN-S083A" , "SB00", 0x40 }, // slim, ?
//
// This list contains vendor ID and product ID as a single string for ATAPI interface.
//
{ "", "HL-DT-ST DVDRAM GMA-4020B" , NULL , 0x10 }, // hh , 2002/04/22
{ "", "HL-DT-ST DVD-RW GCA-4020B" , NULL , 0x10 }, // hh , 2002/05/14
{ "", "HL-DT-ST DVDRAM GSA-4040B" , NULL , 0x10 }, // hh , 2003/05/06
{ "", "HL-DT-ST DVDRAM GMA-4040B" , NULL , 0x10 }, // hh , 2003/07/27
{ "", "HL-DT-ST DVD-RW GWA-4040B" , NULL , 0x10 }, // hh , 2003/11/18
{ "", "HL-DT-ST DVDRAM GSA-4081B" , NULL , 0x10 }, // hh , 2003/11/06
{ "", "HL-DT-ST DVDRAM GSA-4082B" , NULL , 0x10 }, // hh , 2004/01/27
{ "", "HL-DT-ST DVD-RW GWA-4082B" , NULL , 0x10 }, // hh , 2004/03/11
{ "", "HL-DT-ST DVDRAM GSA-4120B" , NULL , 0x10 }, // hh , 2004/05/16
{ "", "HL-DT-ST DVD+RW GRA-4120B" , NULL , 0x10 }, // hh , 2004/04/28
{ "", "HL-DT-ST DVDRAM GSA-4160B" , NULL , 0x10 }, // hh , 2004/08/12
{ "", "HL-DT-ST DVD-RW GWA-4160B" , NULL , 0x10 }, // hh , 2004/08/24
{ "", "HL-DT-ST DVDRAM GSA-4163B" , NULL , 0x10 }, // hh , 2004/11/09
{ "", "HL-DT-ST DVD-RW GWA-4163B" , NULL , 0x10 }, // hh , 2004/12/29
{ "", "HL-DT-ST DVDRAM GSA-4165B" , NULL , 0x10 }, // hh , 2005/06/09
{ "", "HL-DT-ST DVDRAM_GSA-4165B" , NULL , 0x10 }, // hh , 2005/06/28
{ "", "HL-DT-ST DVD-RW GWA-4165B" , NULL , 0x10 }, // hh , 2005/08/23
{ "", "HL-DT-ST DVDRAM GSA-4167B" , NULL , 0x10 }, // hh , 2005/07/01
{ "", "HL-DT-ST DVDRAM GSA-H10N" , NULL , 0x10 }, // hh , 2006/02/16
{ "", "HL-DT-ST DVDRAM_GSA-H10N" , NULL , 0x10 }, // hh , 2006/02/16
{ "", "HL-DT-ST DVDRAM GSA-H10L" , NULL , 0x10 }, // hh , 2006/02/27
{ "", "HL-DT-ST DVDRAM_GSA-H10L" , NULL , 0x10 }, // hh , 2006/04/21
{ "", "HL-DT-ST DVDRAM GSA-H10A" , NULL , 0x10 }, // hh , 2006/01/03
{ "", "HL-DT-ST DVDRAM_GSA-H10A" , NULL , 0x10 }, // hh , 2006/05/14
{ "", "HL-DT-ST DVD-RW GSA-H11N" , NULL , 0x10 }, // hh , 2006/04/28
{ "", "HL-DT-ST DVD-RW_GSA-H11N" , NULL , 0x10 }, // hh , 2006/02/22
{ "", "HL-DT-ST DVDRAM GSA-4080N" , NULL , 0x10 }, // slim, 2004/08/08
{ "", "HL-DT-ST DVDRAM GMA-4080N" , NULL , 0x10 }, // slim, 2004/11/09
{ "", "HL-DT-ST DVD-RW GCA-4080N" , NULL , 0x10 }, // slim, 2004/11/22
{ "", "HL-DT-ST DVD-RW GWA-4080N" , NULL , 0x10 }, // slim, 2004/08/17
{ "", "HL-DT-ST DVDRAM GSA-4082N" , NULL , 0x10 }, // slim, 2005/07/12
{ "", "HL-DT-ST DVDRAM_GSA-4082N" , NULL , 0x10 }, // slim, 2005/09/21
{ "", "HL-DT-ST DVDRAM GMA-4082N" , NULL , 0x10 }, // slim, 2005/10/20
{ "", "HL-DT-ST DVD-RW GRA-4082N" , NULL , 0x10 }, // slim, 2006/06/07
{ "", "HL-DT-ST DVD-RW GWA-4082N" , NULL , 0x10 }, // slim, 2005/05/24
{ "", "HL-DT-ST DVDRAM GMA4082Nf" , NULL , 0x10 }, // slim, 2006/02/28
{ "", "HL-DT-ST DVDRAM GMA4082Nj" , NULL , 0x10 }, // slim, 2006/01/26
{ "", "HL-DT-ST DVDRAM GSA-4084N" , NULL , 0x10 }, // slim, 2005/12/21
{ "", "HL-DT-ST DVDRAM GMA-4084N" , NULL , 0x10 }, // slim, 2006/02/15
{ "", "HP DVD Writer 550s" , NULL , 0x10 }, // slim, 2006/05/08
{ "", "HL-DT-ST DVDRAM GSA-T10N" , NULL , 0x10 }, // slim, 2006/07/26
{ "", "HL-DT-ST DVDRAM_GSA-T10N" , NULL , 0x10 }, // slim, 2006/07/26
{ "", "HL-DT-ST DVD+-RW GSA-T11N" , NULL , 0x10 }, // slim, 2006/07/25
{ "", "HL-DT-ST DVD-ROM GDR8160B" , NULL , 0x10 }, // hh , 2001/10/12
{ "", "COMPAQ DVD-ROM GDR8160B" , NULL , 0x10 }, // hh , 2001/11/08
{ "", "HL-DT-ST DVD-ROM GDR8161B" , NULL , 0x10 }, // hh , 2002/07/19
{ "", "HL-DT-ST DVD-ROM GDR8162B" , NULL , 0x10 }, // hh , 2003/04/22
{ "", "HL-DT-ST DVD-ROM GDR8163B" , NULL , 0x10 }, // hh , 2004/05/19
{ "", "HL-DT-ST DVD-ROM GDR8164B" , NULL , 0x10 }, // hh , 2005/06/29
{ "", "HL-DT-ST DVD-ROM GDRH10N" , NULL , 0x10 }, // hh , 2006/03/07
{ "", "HL-DT-ST DVD-ROM GDR8081N" , NULL , 0x10 }, // slim, 2001/08/27
{ "", "HL-DT-ST DVD-ROM GDR8082N" , NULL , 0x10 }, // slim, 2003/02/02
{ "", "HL-DT-ST DVD-ROM GDR8083N" , NULL , 0x10 }, // slim, 2003/02/02
{ "", "HL-DT-ST DVD-ROM GDR8085N" , NULL , 0x10 }, // slim, 2005/11/10
{ "", "HL-DT-ST RW/DVD GCC-4080N" , NULL , 0x10 }, // slim, 2001/08/21
{ "", "HL-DT-ST RW/DVD_GCC-4080N" , NULL , 0x10 }, // slim,
{ "", "HL-DT-ST RW/DVD GCC-4160N" , NULL , 0x10 }, // slim, 2002/04/08
{ "", "HL-DT-ST RW/DVD GCC-4240N" , NULL , 0x10 }, // slim, 2002/04/26
{ "", "HL-DT-ST RW/DVD GCC-4241N" , NULL , 0x10 }, // slim, 2003/04/07
{ "", "HL-DT-ST RW/DVD_GCC-4241N" , NULL , 0x10 }, // slim, 2004/03/07
{ "", "HL-DT-ST RW/DVD GCC-4242N" , NULL , 0x10 }, // slim, 2003/12/21
{ "", "HL-DT-ST RW/DVD GCC-4246N" , NULL , 0x10 }, // slim, 2005/05/23
{ "", "HL-DT-ST BD-RE GBW-H10N" , NULL , 0x10 }, // hh , 2006/06/27
{ "", "HL-DT-ST DVDRAM GSA-4083N" , NULL , 0x10 }, // hh , 2006/05/17
{ "", "HL-DT-ST DVD+-RW GWA4083N" , NULL , 0x10 }, // hh , 2006/06/05
{ "", "PIONEER DVD-RW DVR-106D" , NULL , 0x10 }, // hh , ?
{ "", "ASUS DVD-RW DRW-0402P" , NULL , 0x10 }, // hh , ?
// Sony sourced some drives from LG also....
{ NULL , NULL , NULL , 0x00 },
};
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#endif

View file

@ -0,0 +1,16 @@
/*--
Copyright (C) Microsoft Corporation. All rights reserved.
--*/
#include "initguid.h"
#include "ntddk.h"
#include "ntddstor.h"
#include "mountmgr.h"
#include "ioevent.h"
#include "devpkey.h"
#include "wdmguid.h"
// no code, just GUIDs being defined

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,847 @@
/*++
Copyright (C) Microsoft Corporation. All rights reserved.
Module Name:
ioctl.h
Abstract:
Functions to handle IOCTLs.
Author:
Environment:
kernel mode only
Notes:
Revision History:
--*/
#ifndef __IOCTL_H__
#define __IOCTL_H__
BOOLEAN
RequestDispatchProcessDirectly(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters
);
BOOLEAN
RequestDispatchToSequentialQueue(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters
);
BOOLEAN
RequestDispatchSyncWithSequentialQueue(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters
);
BOOLEAN
RequestDispatchSpecialIoctls(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters
);
BOOLEAN
RequestDispatchUnknownRequests(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters
);
//
// I/O Request Handlers
//
// Handlers that are called directly in dispatch routine.
NTSTATUS
RequestHandleGetInquiryData(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestHandleGetMediaTypeEx(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_Out_ size_t * DataLength
);
NTSTATUS
RequestHandleMountQueryUniqueId(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestHandleMountQueryDeviceName(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestHandleMountQuerySuggestedLinkName(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestHandleGetDeviceNumber(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestHandleGetHotPlugInfo(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestHandleSetHotPlugInfo(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleEventNotification(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_opt_ WDFREQUEST Request,
_In_opt_ PWDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
// Handlers that are called in RequestProcessSerializedIoctl in a work item.
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleGetDvdRegion(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_Out_ size_t * DataLength
);
NTSTATUS
RequestHandleQueryPropertyRetrieveCachedData(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleReadTOC(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleReadTocEx(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleGetConfiguration(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
RequestHandleGetDriveGeometry(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleDiskVerify(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleCheckVerify(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleFakePartitionInfo(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
RequestHandleEjectionControl(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
RequestHandleLoadEjectMedia(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleMcnControl(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
RequestHandleReserveRelease(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
RequestHandlePersistentReserve(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
#if (NTDDI_VERSION >= NTDDI_WIN8)
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleAreVolumesReady(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleVolumeOnline(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
#endif
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceHandleRawRead(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandlePlayAudioMsf(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleReadQChannel(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandlePauseAudio(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleResumeAudio(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleSeekAudioMsf(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleStopAudio(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleGetSetVolume(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleReadDvdStructure(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleDvdEndSession(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleDvdStartSessionReadKey(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleDvdSendKey(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleSetReadAhead(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleSetSpeed(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsReadMediaKeyBlock(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsStartSession(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsEndSession(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsSendCertificate(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsGetCertificate(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsGetChallengeKey(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleSendChallengeKey(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleReadVolumeId(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsReadSerialNumber(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsReadMediaId(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsReadBindingNonce(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
DeviceHandleAacsGenerateBindingNonce(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleEnableStreaming(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleSendOpcInformation(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleGetPerformance(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleMcnSyncFakeIoctl(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_Out_ size_t * DataLength
);
// Handlers that will be called by Sync process.
// RequestHandleUnknownIoctl could be called at DISPATCH_LEVEL.
NTSTATUS
RequestHandleUnknownIoctl(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleExclusiveAccessQueryLockState(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleExclusiveAccessLockDevice(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleExclusiveAccessUnlockDevice(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
NTSTATUS
RequestHandleQueryPropertyDeviceUniqueId(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
NTSTATUS
RequestHandleQueryPropertyWriteCache(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
RequestHandleScsiPassThrough(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
// Read/write handler called possibly at DISPATCH_LEVEL.
NTSTATUS
RequestHandleReadWrite(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters
);
//
// I/O Request Validation helpers
//
NTSTATUS
RequestValidateRawRead(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateReadTocEx(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateReadToc(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateGetLastSession(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateReadQChannel(
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateDvdReadStructure(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateDvdStartSession(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateDvdSendKey(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateDvdReadKey(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateGetConfiguration(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateSetSpeed(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsReadMediaKeyBlock(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsStartSession(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsSendCertificate(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsGetCertificate(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsGetChallengeKey(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsSendChallengeKey(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsReadVolumeId(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsReadSerialNumber(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsReadMediaId(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsBindingNonce(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateExclusiveAccess(
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateEnableStreaming(
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateSendOpcInformation(
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateGetPerformance(
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
BOOLEAN
RequestIsRealtimeStreaming(
_In_ WDFREQUEST Request,
_In_ BOOLEAN IsReadRequest
);
NTSTATUS
RequestValidateReadWrite(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters
);
NTSTATUS
RequestValidatePersistentReserve(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateDvdEndSession(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
NTSTATUS
RequestValidateAacsEndSession(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST Request,
_In_ WDF_REQUEST_PARAMETERS RequestParameters,
_Out_ size_t * DataLength
);
//
// completion routines
//
#endif // __IOCTL_H__

View file

@ -0,0 +1,23 @@
The Microsoft Public License (MS-PL)
Copyright (c) 2015 Microsoft
This license governs use of the accompanying software. If you use the software, you
accept this license. If you do not accept the license, do not use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.

View file

@ -0,0 +1,17 @@
// this defines how to log a len/buffer pair.
// This function should be in trace.h
DEFINE_CPLX_TYPE(HEXDUMP, WPP_LOGHEXDUMP, xstr_t, ItemHEXDump,"s", _HEX_, 0,2);
// DEFINE_CPLX_TYPE(
// name, // i.e. HEXDUMP // %!HEXDUMP!
// macro, // i.e. WPP_LOGHEXDUMP // Marshalling macro, defined in trace.h
// structure, // i.e. xstr_t // Argument type (structure to be created by above macro)
// item type, // i.e. ItemHEXDump // MOF type that TracePrt can understand
// format specifier, // i.e. "s" // a format specifier that TracePrt can understand
// ???? // i.e. _HEX_ // Type signature (becomes a part of function name)
// ???? // i.e. 0 // Weight (0 is variable data length)
// ???? // i.e. 2 // Slots used by this entry (optional, 1 default)
// )

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,122 @@
/*++
Copyright (C) Microsoft Corporation. All rights reserved.
Module Name:
mmc.h
Abstract:
Functions for MMC area.
Author:
Environment:
kernel mode only
Notes:
Revision History:
--*/
#ifndef __MMC_H__
#define __MMC_H__
_IRQL_requires_max_(APC_LEVEL)
VOID
DeviceDeallocateMmcResources(
_In_ WDFDEVICE Device
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceAllocateMmcResources(
_In_ WDFDEVICE Device
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceUpdateMmcCapabilities(
_In_ WDFDEVICE Device
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceGetConfigurationWithAlloc(
_In_ WDFDEVICE Device,
_Outptr_result_bytebuffer_all_(*BytesReturned)
PGET_CONFIGURATION_HEADER * Buffer,
_Out_ PULONG BytesReturned,
FEATURE_NUMBER const StartingFeature,
ULONG const RequestedType
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceGetConfiguration(
_In_ WDFDEVICE Device,
_Out_writes_bytes_to_(BufferSize, *ValidBytes)
PGET_CONFIGURATION_HEADER Buffer,
_In_ ULONG const BufferSize,
_Out_ PULONG ValidBytes,
_In_ FEATURE_NUMBER const StartingFeature,
_In_ ULONG const RequestedType
);
_IRQL_requires_max_(APC_LEVEL)
VOID
DeviceUpdateMmcWriteCapability(
_In_reads_bytes_(BufferSize)
PGET_CONFIGURATION_HEADER Buffer,
ULONG const BufferSize,
BOOLEAN const CurrentOnly, // TRUE == can drive write now, FALSE == can drive ever write
_Out_ PBOOLEAN Writable,
_Out_ PFEATURE_NUMBER ValidationSchema,
_Out_ PULONG BlockingFactor
);
_IRQL_requires_max_(APC_LEVEL)
PVOID
MmcDataFindFeaturePage(
_In_reads_bytes_(Length)
PGET_CONFIGURATION_HEADER FeatureBuffer,
ULONG const Length,
FEATURE_NUMBER const Feature
);
_IRQL_requires_max_(APC_LEVEL)
VOID
MmcDataFindProfileInProfiles(
_In_ FEATURE_DATA_PROFILE_LIST const* ProfileHeader,
_In_ FEATURE_PROFILE_TYPE const ProfileToFind,
_In_ BOOLEAN const CurrentOnly,
_Out_ PBOOLEAN Found
);
_IRQL_requires_max_(APC_LEVEL)
_Ret_range_(-1,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
LONGLONG
DeviceRetryTimeGuessBasedOnProfile(
FEATURE_PROFILE_TYPE const Profile
);
_IRQL_requires_max_(APC_LEVEL)
_Ret_range_(-1,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
LONGLONG
DeviceRetryTimeDetectionBasedOnModePage2A(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
);
_IRQL_requires_max_(APC_LEVEL)
_Ret_range_(-1,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
LONGLONG
DeviceRetryTimeDetectionBasedOnGetPerformance(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN UseLegacyNominalPerformance
);
#endif // __MMC_H__

View file

@ -0,0 +1,689 @@
/*--
Copyright (C) Microsoft Corporation. All rights reserved.
Module Name:
pnppower.c
Abstract:
Functions to handle PnP and Power IRPs.
Environment:
kernel mode only
Notes:
optical devices do not need to issue SPIN UP when power up.
The device itself should SPIN UP to process commands.
Revision History:
--*/
#include "ntddk.h"
#include "wdfcore.h"
#include "cdrom.h"
#include "ioctl.h"
#include "scratch.h"
#include "mmc.h"
#ifdef DEBUG_USE_WPP
#include "pnppower.tmh"
#endif
NTSTATUS
DeviceScratchSyncCache(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
);
NTSTATUS
DeviceScratchPreventMediaRemoval(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN Prevent
);
NTSTATUS
RequestIssueShutdownFlush(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ PIRP Irp
);
IO_COMPLETION_ROUTINE RequestProcessPowerIrpCompletion;
EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestUnlockQueueCompletion;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DevicePowerSettingCallback)
#endif
#pragma warning(push)
#pragma warning(disable:4152) // nonstandard extension, function/data pointer conversion in expression
#pragma warning(disable:28118) // Dispatch routines for IRP_MJ_SHUTDOWN, IRP_MJ_FLUSH_BUFFERS occur at PASSIVE_LEVEL.
// WDF defines EVT_WDFDEVICE_WDM_IRP_PREPROCESS with _IRQL_requires_max_(DISPATCH_LEVEL),
// triggering a false positive for this warning.
NTSTATUS
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
RequestProcessShutdownFlush(
WDFDEVICE Device,
PIRP Irp
)
/*++
Routine Description:
process IRP: IRP_MJ_SHUTDOWN, IRP_MJ_FLUSH_BUFFERS
Arguments:
Device - device object
Irp - the irp
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION currentStack = NULL;
PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
//add trace info
// acquire the shutdown/flush lock
WdfWaitLockAcquire(deviceExtension->ShutdownFlushWaitLock, NULL);
currentStack = IoGetCurrentIrpStackLocation(Irp);
// finish all current requests
WdfIoQueueStopSynchronously(deviceExtension->SerialIOQueue);
// sync cache
if (NT_SUCCESS(status))
{
// safe to use scratch srb to send the request.
status = DeviceScratchSyncCache(deviceExtension);
}
// For SHUTDOWN, allow media removal.
if (NT_SUCCESS(status))
{
if (currentStack->MajorFunction == IRP_MJ_SHUTDOWN)
{
// safe to use scratch srb to send the request.
status = DeviceScratchPreventMediaRemoval(deviceExtension, FALSE);
}
}
// Use original IRP, send SRB_FUNCTION_SHUTDOWN or SRB_FUNCTION_FLUSH (no retry)
if (NT_SUCCESS(status))
{
status = RequestIssueShutdownFlush(deviceExtension, Irp);
}
// restart queue to allow processing further requests.
WdfIoQueueStart(deviceExtension->SerialIOQueue);
// release the shutdown/flush lock
WdfWaitLockRelease(deviceExtension->ShutdownFlushWaitLock);
// 6. complete the irp
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, 0);
return status;
}
NTSTATUS
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
RequestProcessSetPower(
WDFDEVICE Device,
PIRP Irp
)
/*++
Routine Description:
process IRP: IRP_MJ_POWER
Arguments:
Device - device object
Irp - the irp
Return Value:
NTSTATUS
--*/
{
PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
PIO_STACK_LOCATION currentStack;
NTSTATUS status;
BOOLEAN IrpMarkedPending = FALSE;
currentStack = IoGetCurrentIrpStackLocation(Irp);
if ((currentStack->Parameters.Power.Type == DevicePowerState) &&
(currentStack->Parameters.Power.State.DeviceState != PowerDeviceD0))
{
// We need to unlock the device queue in D3 postprocessing.
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
RequestProcessPowerIrpCompletion,
deviceExtension,
TRUE,
TRUE,
TRUE);
// Mark the Irp pending as we'll defer the I/O completion.
IoMarkIrpPending(Irp);
IrpMarkedPending = TRUE;
}
else {
IoSkipCurrentIrpStackLocation(Irp);
}
#pragma warning(push)
#pragma warning(disable: 28193) // OACR will complain that the status variable is not examined.
//
// Deliver the IRP back to the framework.
//
status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
if (IrpMarkedPending)
{
UNREFERENCED_PARAMETER(status);
return STATUS_PENDING;
}
#pragma warning(pop)
return status;
}
// use scratch SRB to issue SYNC CACHE command.
NTSTATUS
DeviceScratchSyncCache(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
use scratch buffer to send SYNC CACHE command
Arguments:
DeviceExtension - device context
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ULONG transferSize = 0;
CDB cdb;
ScratchBuffer_BeginUse(DeviceExtension);
RtlZeroMemory(&cdb, sizeof(CDB));
// Set up the CDB
cdb.SYNCHRONIZE_CACHE10.OperationCode = SCSIOP_SYNCHRONIZE_CACHE;
//srb->QueueTag = SP_UNTAGGED;
//srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, NULL, transferSize, FALSE, &cdb, 10, TimeOutValueGetCapValue(DeviceExtension->TimeOutValue, 4));
ScratchBuffer_EndUse(DeviceExtension);
return status;
}
NTSTATUS
DeviceScratchPreventMediaRemoval(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN Prevent
)
/*++
Routine Description:
use scratch SRB to issue ALLOW/PREVENT MEDIA REMOVAL command.
Arguments:
DeviceExtension - device context
Prevent - TRUE (prevent media removal); FALSE (allow media removal)
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ULONG transferSize = 0;
CDB cdb;
ScratchBuffer_BeginUse(DeviceExtension);
RtlZeroMemory(&cdb, sizeof(CDB));
// Set up the CDB
cdb.MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
cdb.MEDIA_REMOVAL.Prevent = Prevent;
//srb->QueueTag = SP_UNTAGGED;
//srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
status = ScratchBuffer_ExecuteCdb(DeviceExtension, NULL, transferSize, FALSE, &cdb, 6);
ScratchBuffer_EndUse(DeviceExtension);
return status;
}
NTSTATUS
RequestIssueShutdownFlush(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ PIRP Irp
)
/*++
Routine Description:
issue SRB function Flush/Shutdown command.
Arguments:
DeviceExtension - device context
Irp - the irp
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb;
PIO_STACK_LOCATION currentStack = NULL;
ULONG transferSize = 0;
BOOLEAN shouldRetry = TRUE;
ULONG timesAlreadyRetried = 0;
LONGLONG retryIn100nsUnits = 0;
currentStack = IoGetCurrentIrpStackLocation(Irp);
ScratchBuffer_BeginUse(DeviceExtension);
// no retry needed.
{
ScratchBuffer_SetupSrb(DeviceExtension, NULL, transferSize, FALSE);
// Set up the SRB/CDB
srb->QueueTag = SP_UNTAGGED;
srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
srb->TimeOutValue = TimeOutValueGetCapValue(DeviceExtension->TimeOutValue, 4);
srb->CdbLength = 0;
if (currentStack->MajorFunction == IRP_MJ_SHUTDOWN)
{
srb->Function = SRB_FUNCTION_SHUTDOWN;
}
else
{
srb->Function = SRB_FUNCTION_FLUSH;
}
ScratchBuffer_SendSrb(DeviceExtension, TRUE, NULL);
shouldRetry = RequestSenseInfoInterpretForScratchBuffer(DeviceExtension,
timesAlreadyRetried,
&status,
&retryIn100nsUnits);
UNREFERENCED_PARAMETER(shouldRetry); //defensive coding, avoid PREFAST warning.
UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning.
// retrieve the real status from the request.
status = WdfRequestGetStatus(DeviceExtension->ScratchContext.ScratchRequest);
}
ScratchBuffer_EndUse(DeviceExtension);
return status;
}
VOID
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
RequestUnlockQueueCompletion (
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS Params,
_In_ WDFCONTEXT Context
)
{
PIRP Irp = Context;
WDFDEVICE device = WdfIoTargetGetDevice(Target);
PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
UNREFERENCED_PARAMETER(Request);
UNREFERENCED_PARAMETER(Params);
deviceExtension->PowerContext.Options.LockQueue = FALSE;
PowerContextEndUse(deviceExtension);
// Complete the original power irp
IoCompleteRequest( Irp, IO_NO_INCREMENT );
}
NTSTATUS
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
RequestProcessPowerIrpCompletion(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID Context
)
/*++
Routine Description:
Free the Irp.
Arguments:
DeviceObject - device that the completion routine fires on.
Irp - The irp to be completed.
Context - IRP context
Return Value:
NTSTATUS
--*/
{
PCDROM_DEVICE_EXTENSION deviceExtension = Context;
PIO_STACK_LOCATION currentStack;
UNREFERENCED_PARAMETER(DeviceObject);
if (Irp->PendingReturned)
{
IoMarkIrpPending( Irp );
}
currentStack = IoGetCurrentIrpStackLocation(Irp);
NT_ASSERT(currentStack->Parameters.Power.Type == DevicePowerState);
NT_ASSERT(currentStack->Parameters.Power.State.DeviceState != PowerDeviceD0);
_Analysis_assume_(deviceExtension != NULL);
deviceExtension->PowerContext.PowerChangeState.PowerDown++;
// Step 5. UNLOCK QUEUE
if (deviceExtension->PowerContext.Options.LockQueue)
{
(VOID)DeviceSendPowerDownProcessRequest(deviceExtension,
RequestUnlockQueueCompletion,
Irp);
// Let the completion routine complete the Irp
return STATUS_MORE_PROCESSING_REQUIRED;
}
// Release the power context if it wasn't already done as part of D0Exit handling
if (deviceExtension->PowerContext.InUse)
{
PowerContextEndUse(deviceExtension);
}
return STATUS_CONTINUE_COMPLETION;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS
PowerContextReuseRequest(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
reset fields for the request.
Arguments:
DeviceExtension - device context
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
WDF_REQUEST_REUSE_PARAMS reuseParams;
PIRP irp = NULL;
RtlZeroMemory(&(DeviceExtension->PowerContext.SenseData), sizeof(DeviceExtension->PowerContext.SenseData));
RtlZeroMemory(&(DeviceExtension->PowerContext.Srb), sizeof(DeviceExtension->PowerContext.Srb));
irp = WdfRequestWdmGetIrp(DeviceExtension->PowerContext.PowerRequest);
// Re-use the previously created PowerRequest object and format it
WDF_REQUEST_REUSE_PARAMS_INIT(&reuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED);
status = WdfRequestReuse(DeviceExtension->PowerContext.PowerRequest, &reuseParams);
if (NT_SUCCESS(status))
{
// This request was preformated during initialization so this call should never fail.
status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget,
DeviceExtension->PowerContext.PowerRequest,
IOCTL_SCSI_EXECUTE_IN,
NULL, NULL,
NULL, NULL,
NULL, NULL);
if (!NT_SUCCESS(status))
{
TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"PowerContextReuseRequest: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n",
status));
}
}
// Do some basic initialization of the PowerRequest, the rest will be done by the caller
// of this function
if (NT_SUCCESS(status))
{
PIO_STACK_LOCATION nextStack = NULL;
nextStack = IoGetNextIrpStackLocation(irp);
nextStack->MajorFunction = IRP_MJ_SCSI;
nextStack->Parameters.Scsi.Srb = &(DeviceExtension->PowerContext.Srb);
DeviceExtension->PowerContext.Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
DeviceExtension->PowerContext.Srb.OriginalRequest = irp;
DeviceExtension->PowerContext.Srb.SenseInfoBuffer = &(DeviceExtension->PowerContext.SenseData);
DeviceExtension->PowerContext.Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
}
return status;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS
PowerContextBeginUse(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
initialize fields in power context
Arguments:
DeviceExtension - device context
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
NT_ASSERT(!DeviceExtension->PowerContext.InUse);
DeviceExtension->PowerContext.InUse = TRUE;
DeviceExtension->PowerContext.RetryCount = MAXIMUM_RETRIES;
DeviceExtension->PowerContext.RetryIntervalIn100ns = 0;
KeQueryTickCount(&DeviceExtension->PowerContext.StartTime);
RtlZeroMemory(&(DeviceExtension->PowerContext.Options), sizeof(DeviceExtension->PowerContext.Options));
RtlZeroMemory(&(DeviceExtension->PowerContext.PowerChangeState), sizeof(DeviceExtension->PowerContext.PowerChangeState));
status = PowerContextReuseRequest(DeviceExtension);
RequestClearSendTime(DeviceExtension->PowerContext.PowerRequest);
return status;
}
_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS
PowerContextEndUse(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
inidate that power context using is finished.
Arguments:
DeviceExtension - device context
Return Value:
NTSTATUS
--*/
{
NT_ASSERT(DeviceExtension->PowerContext.InUse);
DeviceExtension->PowerContext.InUse = FALSE;
KeQueryTickCount(&DeviceExtension->PowerContext.CompleteTime);
return STATUS_SUCCESS;
}
_Function_class_(POWER_SETTING_CALLBACK)
_IRQL_requires_same_
NTSTATUS
NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
DevicePowerSettingCallback(
_In_ LPCGUID SettingGuid,
_In_reads_bytes_(ValueLength) PVOID Value,
_In_ ULONG ValueLength,
_Inout_opt_ PVOID Context
)
/*++
Description:
This function is the callback for power setting notifications (registered
when ClasspGetD3IdleTimeout() is called for the first time).
Currently, this function is used to get the disk idle timeout value from
the system power settings.
This function is guaranteed to be called at PASSIVE_LEVEL.
Arguments:
SettingGuid - The power setting GUID.
Value - Pointer to the power setting value.
ValueLength - Size of the Value buffer.
Context - The FDO's device extension.
Return Value:
STATUS_SUCCESS
--*/
{
PCDROM_DEVICE_EXTENSION DeviceExtension = Context;
MONITOR_DISPLAY_STATE DisplayState;
PAGED_CODE();
if (IsEqualGUID(SettingGuid, &GUID_CONSOLE_DISPLAY_STATE)) {
if ((ValueLength == sizeof(ULONG)) && (Value != NULL)) {
DisplayState = *((PULONG)Value);
_Analysis_assume_(DeviceExtension != NULL);
//
// Power setting callbacks are asynchronous so make sure the device
// is completely initialized before taking any actions.
//
if (DeviceExtension->IsInitialized) {
//
// If monitor is off, change media change requests to not keep device active.
// This allows the devices to go to sleep if there are no other active requests.
//
if (DisplayState == PowerMonitorOff) {
//
// Mark the device inactive so that it can enter a low power state.
//
DeviceMarkActive(DeviceExtension, FALSE, TRUE);
SET_FLAG(DeviceExtension->MediaChangeDetectionInfo->SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE);
}
else
{
CLEAR_FLAG(DeviceExtension->MediaChangeDetectionInfo->SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE);
DeviceMarkActive(DeviceExtension, TRUE, TRUE);
}
}
}
}
return STATUS_SUCCESS;
}
#pragma warning(pop) // un-sets any local warning changes

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,187 @@
/*++
Copyright (C) Microsoft Corporation. All rights reserved.
Module Name:
mmc.h
Abstract:
Functions/macros for using the scratch buffer and scratch request/SRB
in the serial I/O queue context
Author:
Environment:
kernel mode only
Notes:
Revision History:
--*/
#ifndef __SCRATCH_H__
#define __SCRATCH_H__
_IRQL_requires_max_(APC_LEVEL)
VOID
ScratchBuffer_Deallocate(
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension
);
_IRQL_requires_max_(APC_LEVEL)
BOOLEAN
ScratchBuffer_Allocate(
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension
);
VOID
ScratchBuffer_ResetItems(
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN ResetRequestHistory
);
_IRQL_requires_max_(APC_LEVEL)
VOID
ScratchBuffer_SetupSrb(
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_opt_ WDFREQUEST OriginalRequest,
_In_ ULONG MaximumTransferLength,
_In_ BOOLEAN GetDataFromDevice
);
VOID
ScratchBuffer_SetupReadWriteSrb(
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ WDFREQUEST OriginalRequest,
_In_ LARGE_INTEGER StartingOffset,
_In_ ULONG RequiredLength,
_Inout_updates_bytes_(RequiredLength) UCHAR* DataBuffer,
_In_ BOOLEAN IsReadRequest,
_In_ BOOLEAN UsePartialMdl
);
NTSTATUS
ScratchBuffer_SendSrb(
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN SynchronousSrb,
_When_(SynchronousSrb, _Pre_null_)
_When_(!SynchronousSrb, _In_opt_)
PSRB_HISTORY_ITEM *SrbHistoryItem
);
NTSTATUS
ScratchBuffer_PerformNextReadWrite(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN FirstTry
);
#if DBG
#define ScratchBuffer_BeginUse(context) ScratchBuffer_BeginUseX((context), __FILE__, __LINE__)
#else
#define ScratchBuffer_BeginUse(context) ScratchBuffer_BeginUseX((context), NULL, (ULONG)-1)
#endif
__inline VOID ScratchBuffer_BeginUseX(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_opt_ LPCSTR File, ULONG Line)
{
// NOTE: these are not "real" locks. They are simply to help
// avoid multiple uses of the scratch buffer. Thus, it
// is not critical to have atomic operations here.
PVOID tmp = InterlockedCompareExchangePointer((PVOID)&(DeviceExtension->ScratchContext.ScratchInUse), (PVOID)-1, NULL);
NT_ASSERT(tmp == NULL);
UNREFERENCED_PARAMETER(tmp); //defensive coding, avoid PREFAST warning.
DeviceExtension->ScratchContext.ScratchInUseFileName = File;
DeviceExtension->ScratchContext.ScratchInUseLineNumber = Line;
ScratchBuffer_ResetItems(DeviceExtension, TRUE);
RequestClearSendTime(DeviceExtension->ScratchContext.ScratchRequest);
return;
}
__inline VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
{
// NOTE: these are not "real" locks. They are simply to help
// avoid multiple uses of the scratch buffer. Thus, it
// is not critical to have atomic operations here.
// On lock release, we erase ScratchInUseFileName and ScratchInUseLineNumber _before_ releasing ScratchInUse,
// because otherwise we may erase these after the lock has been acquired again by another thread. We store the
// old values of ScratchInUseFileName and ScratchInUseLineNumber in local variables to facilitate debugging,
// if the ASSERT at the end of the function is hit.
PCSTR scratchInUseFileName;
ULONG scratchInUseLineNumber;
PVOID tmp;
scratchInUseFileName = DeviceExtension->ScratchContext.ScratchInUseFileName;
scratchInUseLineNumber = DeviceExtension->ScratchContext.ScratchInUseLineNumber;
UNREFERENCED_PARAMETER(scratchInUseFileName);
UNREFERENCED_PARAMETER(scratchInUseLineNumber);
DeviceExtension->ScratchContext.ScratchInUseFileName = NULL;
DeviceExtension->ScratchContext.ScratchInUseLineNumber = 0;
//
// If we have used the PartialMdl in the scratch context we should notify MM that we will be reusing it
// otherwise it may leak System VA if some one below us has mapped the same.
//
if (DeviceExtension->ScratchContext.PartialMdlIsBuilt != FALSE)
{
MmPrepareMdlForReuse(DeviceExtension->ScratchContext.PartialMdl);
DeviceExtension->ScratchContext.PartialMdlIsBuilt = FALSE;
}
tmp = InterlockedCompareExchangePointer((PVOID)&(DeviceExtension->ScratchContext.ScratchInUse), NULL, (PVOID)-1);
NT_ASSERT(tmp == ((PVOID)-1));
UNREFERENCED_PARAMETER(tmp); //defensive coding, avoid PREFAST warning.
return;
}
VOID
CompressSrbHistoryData(
_Inout_ PSRB_HISTORY RequestHistory
);
VOID
ValidateSrbHistoryDataPresumptions(
_In_ SRB_HISTORY const* RequestHistory
);
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
ScratchBuffer_ExecuteCdbEx(
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_opt_ WDFREQUEST OriginalRequest,
_In_ ULONG TransferSize,
_In_ BOOLEAN GetDataFromDevice,
_In_ PCDB Cdb,
_In_ UCHAR OprationLength,
_In_ ULONG TimeoutValue
);
_IRQL_requires_max_(APC_LEVEL)
__inline
NTSTATUS
ScratchBuffer_ExecuteCdb(
_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_opt_ WDFREQUEST OriginalRequest,
_In_ ULONG TransferSize,
_In_ BOOLEAN GetDataFromDevice,
_In_ PCDB Cdb,
_In_ UCHAR OprationLength
)
{
return ScratchBuffer_ExecuteCdbEx(DeviceExtension,
OriginalRequest,
TransferSize,
GetDataFromDevice,
Cdb,
OprationLength,
0);
}
KDEFERRED_ROUTINE ScratchBuffer_ReadWriteTimerRoutine;
#endif //__SCRATCH_H__

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,832 @@
/*++
Copyright (C) Microsoft Corporation. All rights reserved.
Module Name:
zpodd.c
Abstract:
Code for Zero Power ODD support.
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include "ntddk.h"
#include "ntddstor.h"
#include "wdmguid.h"
#include "cdrom.h"
#include "mmc.h"
#include "ioctl.h"
#include "scratch.h"
#ifdef DEBUG_USE_WPP
#include "zpodd.tmh"
#endif
_IRQL_requires_max_(PASSIVE_LEVEL)
ULONG
DeviceGetZPODDEnabledFromRegistry();
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceQueryD3ColdInterface(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_Out_ PD3COLD_SUPPORT_INTERFACE D3ColdInterface
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceSendEnableIdlePowerIoctl(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN WakeCapable,
_In_ BOOLEAN Enable,
_In_ ULONG D3IdleTimeout
);
#if ALLOC_PRAGMA
#pragma alloc_text(PAGE, DeviceInitializeZPODD)
#pragma alloc_text(PAGE, DeviceGetZPODDEnabledFromRegistry)
#pragma alloc_text(PAGE, DeviceQueryD3ColdInterface)
#pragma alloc_text(PAGE, DeviceSendEnableIdlePowerIoctl)
#pragma alloc_text(PAGE, DeviceReleaseZPODDResources)
#pragma alloc_text(PAGE, DeviceZPODDIsInHomePosition)
#pragma alloc_text(PAGE, DeviceMarkActive)
#endif
#pragma warning(push)
#pragma warning(disable:4152) // nonstandard extension, function/data pointer conversion in expression
#pragma warning(disable:26000) // read overflow reported because of pointer type conversion
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceInitializeZPODD(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine initialize the contents of ZPODD structure.
Arguments:
DeviceExtension - the device extension
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS tempStatus = STATUS_SUCCESS;
PZERO_POWER_ODD_INFO zpoddInfo = NULL;
PFEATURE_DATA_REMOVABLE_MEDIUM removableMediumHeader = NULL;
ULONG ZPODDEnabledInRegistry = 0;
PD3COLD_SUPPORT_INTERFACE d3ColdInterface = NULL;
DEVICE_WAKE_DEPTH deepestWakeableDstate = DeviceWakeDepthNotWakeable;
BOOLEAN inHomePosition = FALSE;
PAGED_CODE();
if (DeviceExtension->ZeroPowerODDInfo != NULL)
{
//
// Already initialized.
//
goto Cleanup;
}
ZPODDEnabledInRegistry = DeviceGetZPODDEnabledFromRegistry();
if (ZPODDEnabledInRegistry == 0)
{
//
// User has explicitly disabled Zero Power ODD.
//
status = STATUS_NOT_SUPPORTED;
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
"DeviceInitializeZPODD: ZPODD not enabled due to registry settings.\n"
));
goto Cleanup;
}
zpoddInfo = ExAllocatePoolWithTag(NonPagedPoolNx,
sizeof(ZERO_POWER_ODD_INFO),
CDROM_TAG_ZERO_POWER_ODD);
if (zpoddInfo == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
RtlZeroMemory(zpoddInfo, sizeof (ZERO_POWER_ODD_INFO));
//
// Check the system for the following prerequisites:
//
// 1. SATA: Device Attention line
// 2. SATA: Asynchronous Notification
// 3. ODD: LoChange / MediaRemoval
// 4. ACPI: Wake capable
//
// Only drawer and slot loading types have well defined behaviors in the spec, so only these two
// types are supported.
//
//
// Check for DA & AN
//
if ((DeviceExtension->PowerDescriptor == NULL) ||
(DeviceExtension->PowerDescriptor->DeviceAttentionSupported == FALSE) ||
(DeviceExtension->PowerDescriptor->AsynchronousNotificationSupported == FALSE))
{
status = STATUS_NOT_SUPPORTED;
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
"DeviceInitializeZPODD: ZPODD not enabled due to SATA features not present.\n"
));
goto Cleanup;
}
//
// Check for LoChange / MediaRemoval
//
removableMediumHeader = (PFEATURE_DATA_REMOVABLE_MEDIUM)
DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer,
DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize,
FeatureRemovableMedium);
if ((removableMediumHeader == NULL) ||
(!((removableMediumHeader->LoadingMechanism == LOADING_MECHANISM_TRAY) && (removableMediumHeader->Load == 0) && // Drawer ...
(removableMediumHeader->DBML != FALSE)) && // requires LoChange/NotBusy
!((removableMediumHeader->LoadingMechanism == LOADING_MECHANISM_CADDY) && (removableMediumHeader->Load == 0) && // Slot ...
(DeviceExtension->MediaChangeDetectionInfo->Gesn.Supported != FALSE)))) // requires MediaRemoval
{
status = STATUS_NOT_SUPPORTED;
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
"DeviceInitializeZPODD: ZPODD not enabled due to ODD features not present.\n"
));
goto Cleanup;
}
zpoddInfo->LoadingMechanism = removableMediumHeader->LoadingMechanism;
zpoddInfo->Load = removableMediumHeader->Load;
//
// Check for ACPI
//
status = DeviceQueryD3ColdInterface(DeviceExtension, &zpoddInfo->D3ColdInterface);
if (!NT_SUCCESS(status))
{
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
"DeviceInitializeZPODD: Query D3Cold support interface failed.\n"
));
goto Cleanup;
}
//
// If the platform supports Zero Power ODD, the following conditions must be met:
//
// 1. The deepest wakeable D-state for the device is D3Cold;
// 2. The platform supports D3Cold for the device.
//
d3ColdInterface = &zpoddInfo->D3ColdInterface;
status = d3ColdInterface->GetIdleWakeInfo(d3ColdInterface->Context,
PowerSystemWorking,
&deepestWakeableDstate);
if (!NT_SUCCESS(status))
{
goto Cleanup;
}
//
// DeviceExtension->PowerDescriptor->D3ColdSupported is retrieved from lower layer.
// It has more accurate supportive information than just uses d3ColdInterface->GetD3ColdCapability
//
if ((deepestWakeableDstate != DeviceWakeDepthD3cold) ||
(DeviceExtension->PowerDescriptor->D3ColdSupported == FALSE))
{
status = STATUS_NOT_SUPPORTED;
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
"DeviceInitializeZPODD: ZPODD not enabled due to ACPI support not present.\n"
));
goto Cleanup;
}
//
// The system meets all requirements. Go ahead and enable ZPODD.
//
//
// Register with the runtime power framework.
// Note that no un-registration is needed during tear-down.
// D3Cold will be enabled (success case of following call) or disabled by port driver during processing Enable Idle Power IOCTL.
//
status = DeviceSendEnableIdlePowerIoctl(DeviceExtension, TRUE, TRUE, DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS);
if (!NT_SUCCESS(status))
{
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
"DeviceInitializeZPODD: ZPODD not enabled due to runtime power framework.\n"
));
goto Cleanup;
}
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
"DeviceInitializeZPODD: ZPODD is enabled.\n"
));
DeviceExtension->ZeroPowerODDInfo = zpoddInfo;
//
// If device is not in home position, then we should take an active reference here
// to prevent it from being powered off.
//
inHomePosition = DeviceZPODDIsInHomePosition(DeviceExtension);
if (inHomePosition == FALSE)
{
TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
"DeviceInitializeZPODD: not ready to power off, device marked as active\n"));
DeviceMarkActive(DeviceExtension, TRUE, FALSE);
}
else
{
//
// cache get configuration response.
// failing is not critical, so we don't want to check for status here.
//
if (zpoddInfo->GetConfigurationBuffer == NULL)
{
tempStatus = DeviceGetConfigurationWithAlloc(DeviceExtension->Device,
&zpoddInfo->GetConfigurationBuffer,
&zpoddInfo->GetConfigurationBufferSize,
FeatureProfileList,
SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL);
UNREFERENCED_PARAMETER(tempStatus); // Avoid PREFAST warning.
}
}
Cleanup:
if (!NT_SUCCESS(status))
{
//
// We register always even in non-ZPODD case, per request from storport.
//
tempStatus = DeviceSendEnableIdlePowerIoctl(DeviceExtension, FALSE, FALSE, DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS);
if (NT_SUCCESS(tempStatus))
{
//
// Mark the device active; this reference will never be released unless the system enters a
// low power state.
//
DeviceMarkActive(DeviceExtension, TRUE, FALSE);
}
FREE_POOL(zpoddInfo);
}
//
// If Zero Power ODD is not supported, we should not block the device init sequence.
//
return STATUS_SUCCESS;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
ULONG
DeviceGetZPODDEnabledFromRegistry()
/*++
Routine Description:
Get the ZeroPowerODDEnabled value from registry, which dictates if Zero Power ODD
should be enabled or not. If the value is not in registry, by default Zero
Power ODD is enabled.
Arguments:
None
Return Value:
ULONG
--*/
{
NTSTATUS status = STATUS_SUCCESS;
WDFKEY registryKey = NULL;
ULONG ZPODDEnabled = 0;
DECLARE_CONST_UNICODE_STRING(registryValueName, L"ZeroPowerODDEnabled");
PAGED_CODE();
//
// open the Parameters key under the service key.
//
status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(),
KEY_READ,
WDF_NO_OBJECT_ATTRIBUTES,
&registryKey);
if (NT_SUCCESS(status))
{
status = WdfRegistryQueryULong(registryKey,
&registryValueName,
&ZPODDEnabled);
WdfRegistryClose(registryKey);
}
if (!NT_SUCCESS(status))
{
//
// By default, Zero Power ODD is enabled
//
ZPODDEnabled = 1;
}
return ZPODDEnabled;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceQueryD3ColdInterface(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_Out_ PD3COLD_SUPPORT_INTERFACE D3ColdInterface
)
/*++
Routine Description:
Queries ACPI for the D3Cold support interface.
Arguments:
DeviceExtension - the device extension
D3ColdInterface - output buffer receiving the interface
Return Value:
NTSTATUS
--*/
{
PIRP irp = NULL;
KEVENT event;
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT targetDevice = NULL;
IO_STATUS_BLOCK ioStatus = {0};
PIO_STACK_LOCATION irpStack = NULL;
PAGED_CODE();
RtlZeroMemory(D3ColdInterface, sizeof(D3COLD_SUPPORT_INTERFACE));
//
// Query D3COLD support interface synchronously
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
targetDevice = IoGetAttachedDeviceReference(DeviceExtension->DeviceObject);
irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
targetDevice,
NULL,
0,
0,
&event,
&ioStatus);
if (irp == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
irp->IoStatus.Information = 0;
irpStack = IoGetNextIrpStackLocation(irp);
irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_D3COLD_SUPPORT_INTERFACE;
irpStack->Parameters.QueryInterface.Size = sizeof (D3COLD_SUPPORT_INTERFACE);
irpStack->Parameters.QueryInterface.Version = D3COLD_SUPPORT_INTERFACE_VERSION;
irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) D3ColdInterface;
irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
status = IoCallDriver(targetDevice, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
if (!NT_SUCCESS(status))
{
goto Cleanup;
}
NT_ASSERT(D3ColdInterface->SetD3ColdSupport != NULL);
NT_ASSERT(D3ColdInterface->GetIdleWakeInfo != NULL);
NT_ASSERT(D3ColdInterface->GetD3ColdCapability != NULL);
Cleanup:
ObDereferenceObject(targetDevice);
return status;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DeviceSendEnableIdlePowerIoctl(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN WakeCapable,
_In_ BOOLEAN Enable,
_In_ ULONG D3IdleTimeout
)
/*++
Routine Description:
Enables idle power support.
Arguments:
DeviceExtension - the device extension
WakeCapable - whether the device is wake capable
Enable - enable / disable idle power management
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
STORAGE_IDLE_POWER idlePower = {0};
IO_STATUS_BLOCK ioStatus = {0};
PIRP irp = NULL;
KEVENT event;
PAGED_CODE();
idlePower.Version = 1;
idlePower.Size = sizeof (STORAGE_IDLE_POWER);
idlePower.WakeCapableHint = WakeCapable;
idlePower.D3ColdSupported = Enable;
idlePower.D3IdleTimeout = D3IdleTimeout;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_ENABLE_IDLE_POWER,
DeviceExtension->LowerPdo,
&idlePower,
sizeof(STORAGE_IDLE_POWER),
NULL,
0,
FALSE,
&event,
&ioStatus);
if (irp == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
//
// Send the synchronous request to port driver.
//
status = IoCallDriver(DeviceExtension->LowerPdo, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
}
TracePrint((TRACE_LEVEL_INFORMATION,
TRACE_FLAG_POWER,
"DeviceSendEnableIdlePowerIoctl: Port driver returned status (%x) for FDO (%p)\n"
"\tD3ColdSupported: %u\n"
"\tD3IdleTimeout: %u (ms)",
status,
DeviceExtension->DeviceObject,
Enable,
DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS));
return status;
}
_IRQL_requires_max_(APC_LEVEL)
VOID
DeviceReleaseZPODDResources(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine will cleanup any resources allocated for ZPODD.
Arguments:
DeviceExtension - the device context
Return Value:
None.
--*/
{
PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
PAGED_CODE()
if (zpoddInfo != NULL)
{
FREE_POOL(zpoddInfo->GetConfigurationBuffer);
FREE_POOL(zpoddInfo);
}
return;
}
NTSTATUS
DeviceZPODDGetPowerupReason(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_Out_ PSTORAGE_IDLE_POWERUP_REASON PowerupReason
)
/*++
Routine Description:
This routine queries the port driver for what caused the power up.
Arguments:
DeviceExtension - device extension.
PowerupReason - what caused the power up.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PIRP irp = NULL;
IO_STATUS_BLOCK ioStatus = {0};
KEVENT event;
RtlZeroMemory(PowerupReason, sizeof (STORAGE_IDLE_POWERUP_REASON));
PowerupReason->Size = sizeof (STORAGE_IDLE_POWERUP_REASON);
PowerupReason->Version = STORAGE_IDLE_POWERUP_REASON_VERSION_V1;
//
// Setup a synchronous irp.
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_IDLE_POWERUP_REASON,
DeviceExtension->LowerPdo,
PowerupReason,
sizeof (STORAGE_IDLE_POWERUP_REASON),
PowerupReason,
sizeof (STORAGE_IDLE_POWERUP_REASON),
FALSE,
&event,
&ioStatus);
if (irp == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
//
// Send the synchronous request to port driver.
//
status = IoCallDriver(DeviceExtension->LowerPdo, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
}
return status;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
BOOLEAN
DeviceZPODDIsInHomePosition(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
Checks to see if the device is ready to be powered off.
Requirements are: 1. tray closed 2. no media present.
Arguments:
DeviceExtension - device extension.
Return Value:
BOOLEAN
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
SCSI_REQUEST_BLOCK srb = {0};
PCDB cdb = (PCDB) srb.Cdb;
BOOLEAN inHomePosition = FALSE;
PAGED_CODE();
if (zpoddInfo != NULL)
{
//
// Clear sense data.
//
zpoddInfo->SenseKey = 0;
zpoddInfo->AdditionalSenseCode = 0;
zpoddInfo->AdditionalSenseCodeQualifier = 0;
//
// Send a Test Unit Ready to check media & tray status.
//
RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
srb.CdbLength = 6;
cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
srb.TimeOutValue = CDROM_TEST_UNIT_READY_TIMEOUT;
status = DeviceSendSrbSynchronously(DeviceExtension->Device,
&srb,
NULL,
0,
FALSE,
NULL);
#ifdef __REACTOS__
if (!NT_SUCCESS(status))
{
return FALSE;
}
#endif
//
// At this time, sense data, if available, is already copied into zpoddInfo.
//
// We don't check for status because we expect it to fail in case there is no media in device.
//
// Should enter Zero Power state if:
//
// Drawer: 02/3A/01
// Slot: 02/3A/xx
//
if (((zpoddInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) && (zpoddInfo->Load == 0) && // Drawer
(zpoddInfo->SenseKey == SCSI_SENSE_NOT_READY) &&
(zpoddInfo->AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE) &&
(zpoddInfo->AdditionalSenseCodeQualifier == 0x01)) ||
((zpoddInfo->LoadingMechanism == LOADING_MECHANISM_CADDY) && (zpoddInfo->Load == 0) && // Slot
(zpoddInfo->SenseKey == SCSI_SENSE_NOT_READY) &&
(zpoddInfo->AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)))
{
inHomePosition = TRUE;
}
}
return inHomePosition;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
DeviceMarkActive(
_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
_In_ BOOLEAN IsActive,
_In_ BOOLEAN SetIdleTimeout
)
/*++
Routine Description:
This routine will mark the device as active / idle.
Arguments:
DeviceExtension - the device context
IsActive - if the device should be marked as active
Return Value:
None.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
PAGED_CODE()
if (DeviceExtension->IsActive != IsActive)
{
if ((IsActive == FALSE) && (zpoddInfo != NULL))
{
// cache get configuration response.
// failing is not critical, so we don't want to check for status here.
if (zpoddInfo->GetConfigurationBuffer == NULL)
{
(VOID)DeviceGetConfigurationWithAlloc(DeviceExtension->Device,
&zpoddInfo->GetConfigurationBuffer,
&zpoddInfo->GetConfigurationBufferSize,
FeatureProfileList,
SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL);
}
}
if (SetIdleTimeout)
{
status = DeviceSendEnableIdlePowerIoctl(DeviceExtension,
FALSE,
FALSE,
IsActive ? DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS : DELAY_TIME_TO_ENTER_AOAC_IDLE_POWER_IN_MS);
}
if (NT_SUCCESS(status))
{
DeviceSendIoctlAsynchronously(DeviceExtension,
IsActive ? IOCTL_STORAGE_POWER_ACTIVE : IOCTL_STORAGE_POWER_IDLE,
DeviceExtension->LowerPdo);
}
DeviceExtension->IsActive = IsActive;
}
}
#pragma warning(pop) // un-sets any local warning changes