diff options
| author | Adonais Romero González <[email protected]> | 2024-05-06 16:21:31 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-05-06 16:21:31 -0700 |
| commit | a74a241c664c4e1d7c0838287b34076c19d9858a (patch) | |
| tree | 6ff7562612967b122acf8acf8a69c4dcfd5905db /storage | |
| parent | def8e8e34ed2b7b1deb2fc9112ac4255f1a0f2ba (diff) | |
| parent | 15477ce52bbb6b42ca591ecdfb484cac089f89ab (diff) | |
Merge develop changes prior to upcoming WDK release (May 2024)
Diffstat (limited to 'storage')
55 files changed, 215 insertions, 41027 deletions
diff --git a/storage/class/cdrom/README.md b/storage/class/cdrom/README.md deleted file mode 100644 index 4b081014..00000000 --- a/storage/class/cdrom/README.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -page_type: sample -description: "Provide access to CD, DVD and Blu-ray drives, supports Plug and Play, Power Management, and AutoRun (media change notification)." -languages: -- cpp -products: -- windows -- windows-wdk ---- - -# CDROM Storage Class Driver - -The CD ROM driver is used to provide access to CD, DVD and Blu-ray drives. It supports Plug and Play, Power Management, and AutoRun (media change notification). - -## Build the sample - -You can build the sample in two ways: using Microsoft Visual Studio or the command line (*MSBuild*). - -> [!NOTE] -> When building in Visual Studio, INFVerifer will throw errors. This is intended. Fix those errors with your custom values to build successfully. - -## Building a Driver Using Visual Studio - -You build a driver the same way you build any project or solution in Visual Studio. When you create a new driver project using a Windows driver template, the template defines a default (active) project configuration and a default (active) solution build configuration. When you create a project from existing driver sources or convert existing driver code that was built with previous versions of the WDK, the conversion process preserves the target version information (operating systems and platform). - -The default Solution build configuration is Visual Studio Debug and Win32. - -1. Open the driver project or solution in Visual Studio (find *samplename*.sln or *samplename*.vcxproj). - -1. Right-click the solution in the **Solutions Explorer** and select **Configuration Manager**. - -1. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Debug or Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in. - -1. From the Build menu, click **Build Solution** (Ctrl+Shift+B). - -## Building a Driver Using the Command Line (MSBuild) - -You can build a driver from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe) Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. You can now use the Visual Studio Command Prompt window for all build configurations. - -1. Open a Visual Studio Command Prompt window at the **Start** screen. From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file. - -1. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called *filtername*.vcxproj, navigate to the project directory and enter the following MSBuild command: - - `msbuild /t:clean /t:build .\<samplename>.vcxproj` - -## Installation and Operation - -The in-box CD ROM driver is protected by the system, and thus a normal device driver update attempt through the Device Manager will fail. Users are not encouraged to replace the in-box CD ROM driver. The following work-around is provided in case there is a need, but the users are warned that this may harm the system. - -1. Locate the "cdrom.inf" file in the binary output directory, and update the file by replacing all "cdrom.sys" occurrences with "mycdrom.sys". - -1. Rename the "cdrom.inf" file to "mycdrom.inf". - -1. Copy "mycdrom.sys" and "mycdrom.inf" from the binary output directory to the test machine, if applicable. - -1. Launch the Device Manager - -1. Select the appropriate device under the "DVD/CD-ROM drives" category. - -1. On the right-click menu, select "Update Driver Software...". - -1. Select "Browse my computer for driver software". - -1. Select "Let me pick from a list of device drivers on my computer". - -1. Click "Have Disk...", and point to the directory that contains "mycdrom.inf" and "mycdrom.sys". - -1. Click "Next". If you get a warning dialog about installing unsigned driver, click "Yes". - -1. Click "Next" to complete the driver upgrade. - -1. After installation completes successfully, "mycdrom.sys" will be the effective driver for the device, "cdrom.sys" will no longer be used. - -For more information, see [CD-ROM Drivers](https://docs.microsoft.com/windows-hardware/drivers/storage/cd-rom-drivers) in the storage technologies design guide. diff --git a/storage/class/cdrom/cdrom.sln b/storage/class/cdrom/cdrom.sln deleted file mode 100644 index 4516f3dc..00000000 --- a/storage/class/cdrom/cdrom.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0 -MinimumVisualStudioVersion = 12.0 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdrom", "src\cdrom.vcxproj", "{9DB6E759-C294-4E18-9013-82FD8F3DD5E6}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9DB6E759-C294-4E18-9013-82FD8F3DD5E6}.Debug|Win32.ActiveCfg = Debug|Win32 - {9DB6E759-C294-4E18-9013-82FD8F3DD5E6}.Debug|Win32.Build.0 = Debug|Win32 - {9DB6E759-C294-4E18-9013-82FD8F3DD5E6}.Release|Win32.ActiveCfg = Release|Win32 - {9DB6E759-C294-4E18-9013-82FD8F3DD5E6}.Release|Win32.Build.0 = Release|Win32 - {9DB6E759-C294-4E18-9013-82FD8F3DD5E6}.Debug|x64.ActiveCfg = Debug|x64 - {9DB6E759-C294-4E18-9013-82FD8F3DD5E6}.Debug|x64.Build.0 = Debug|x64 - {9DB6E759-C294-4E18-9013-82FD8F3DD5E6}.Release|x64.ActiveCfg = Release|x64 - {9DB6E759-C294-4E18-9013-82FD8F3DD5E6}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/storage/class/cdrom/src/aacs.c b/storage/class/cdrom/src/aacs.c deleted file mode 100644 index 191ba6b0..00000000 --- a/storage/class/cdrom/src/aacs.c +++ /dev/null @@ -1,1481 +0,0 @@ -/*-- - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - aacs.c - -Abstract: - - The CDROM class driver implementation of handling AACS IOCTLs. - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - -#include "stddef.h" -#include "string.h" - -#include "ntddk.h" -#include "ntddstor.h" -#include "cdrom.h" -#include "ioctl.h" -#include "scratch.h" - -#ifdef DEBUG_USE_WPP -#include "aacs.tmh" -#endif - -#ifdef ALLOC_PRAGMA - -#pragma alloc_text(PAGE, DeviceHandleAacsReadMediaKeyBlock) -#pragma alloc_text(PAGE, DeviceHandleAacsStartSession) -#pragma alloc_text(PAGE, DeviceHandleAacsEndSession) -#pragma alloc_text(PAGE, DeviceHandleAacsSendCertificate) -#pragma alloc_text(PAGE, DeviceHandleAacsGetCertificate) -#pragma alloc_text(PAGE, DeviceHandleAacsGetChallengeKey) -#pragma alloc_text(PAGE, DeviceHandleAacsReadSerialNumber) -#pragma alloc_text(PAGE, DeviceHandleAacsReadMediaId) -#pragma alloc_text(PAGE, DeviceHandleAacsReadBindingNonce) -#pragma alloc_text(PAGE, DeviceHandleAacsGenerateBindingNonce) -#pragma alloc_text(PAGE, DeviceHandleReadVolumeId) -#pragma alloc_text(PAGE, DeviceHandleSendChallengeKey) - -#endif - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsReadMediaKeyBlock( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTLs: - IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE - IOCTL_AACS_READ_MEDIA_KEY_BLOCK -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PAACS_LAYER_NUMBER layerNumber = NULL; - PVOID outputBuffer = NULL; - ULONG transferSize = sizeof(READ_DVD_STRUCTURES_HEADER); - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&layerNumber, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_AACS_READ_MEDIA_KEY_BLOCK) - { - // maximum size for this transfer is one pack + header - transferSize += AACS_MKB_PACK_SIZE; - } - - if (transferSize > DeviceExtension->ScratchContext.ScratchBufferSize) - { - // rare case. normally the size of scratch buffer is 64k. - status = STATUS_INTERNAL_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - UCHAR rmdBlockNumber = 0; - BOOLEAN sendChangedCommand = TRUE; - BOOLEAN shouldRetry = TRUE; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE; - // cdb->AsByte[1] = 0x01; // AACS sub-command not required for this - - cdb.READ_DVD_STRUCTURE.LayerNumber = (UCHAR)(*layerNumber); - cdb.READ_DVD_STRUCTURE.Format = 0x83; // MKB - cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(transferSize >> (8*1)); - cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(transferSize >> (8*0)); - - while (sendChangedCommand) - { - // RMDBlockNumber is set to zero.... - // RMDBlockNumber[3] maybe changed for other blocks. - cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3] = rmdBlockNumber; - - if (shouldRetry) - { - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, TRUE, &cdb, 12); - } - - #ifdef ENABLE_AACS_TESTING - if (RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE) - { - static const UCHAR results[] = { 0x80, 0x02, 0x00, 0x02 }; - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; - } - else if (RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_AACS_READ_MEDIA_KEY_BLOCK) - { - static const UCHAR results[] = { 0x80, 0x02, 0x00, 0x02 }; - static const UCHAR defaultFill = 0x30; // '0' - RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x8004, defaultFill); - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; - } - #endif //ENABLE_AACS_TESTING - - if (NT_SUCCESS(status)) - { - // command succeeded, process data... - PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - UCHAR thisPackNumber = cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3]; - UCHAR otherPacks = header->Reserved[1]; - - // validate and zero-base the otherPacks - if (otherPacks == 0) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "AACS: Device is reporting zero total packs (invalid)\n")); - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - else - { - otherPacks--; - - if (RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE) - { - // if not already requested last pack, do so now - if (otherPacks != thisPackNumber) - { - // re-send the command for the other pack number. - // this is safe here because NT_SUCCESS() is TRUE, - // and all the rest of this routine does is SetHardError() - // and release of resources we're still about to use. - - // re-zero the output buffer - RtlZeroMemory(DeviceExtension->ScratchContext.ScratchBuffer, sizeof(READ_DVD_STRUCTURES_HEADER)); - - // modify the CDB to get the very last pack of the MKB - rmdBlockNumber = otherPacks; - - transferSize = sizeof(READ_DVD_STRUCTURES_HEADER); - - // keep items clean - ScratchBuffer_ResetItems(DeviceExtension, TRUE); - - // make sure the loop will be executed for modified command. - sendChangedCommand = TRUE; - shouldRetry = TRUE; - } - else - { - // this request already got the last pack - // so just interpret the data - REVERSE_SHORT(&header->Length); - if (header->Length < sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length)) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - else - { - ULONG totalSize = header->Length; - // subtract out any remaining bytes in the header - // to get the number of usable bytes in this pack - totalSize -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - totalSize += otherPacks * AACS_MKB_PACK_SIZE; - - // save the result and complete the request - *((PULONG)outputBuffer) = totalSize; - *DataLength = sizeof(ULONG); - status = STATUS_SUCCESS; - } - // This will exit the loop of sendChangedCommand - sendChangedCommand = FALSE; - shouldRetry = FALSE; - } - } - else if (RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_AACS_READ_MEDIA_KEY_BLOCK) - { - // make length field native byte ordering - REVERSE_SHORT(&header->Length); - - // exit if getting invalid data from the drive - if (header->Length < sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length)) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - else - { - // success, how many bytes to copy for this pack? - ULONG totalSize = header->Length; - size_t originalBufferSize; - - // subtract out any remaining bytes in the header - // to get the number of usable bytes in this pack - totalSize -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - - // if not the final pack, this should be a full transfer per spec - NT_ASSERT( (totalSize == AACS_MKB_PACK_SIZE) || (thisPackNumber == otherPacks) ); - - // validate the user's buffer is large enough to accept the full data - originalBufferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength; - - if (originalBufferSize < (totalSize + (AACS_MKB_PACK_SIZE*thisPackNumber))) - { - // just return a slightly bigger-than-normal size - *DataLength = (otherPacks + 1)*AACS_MKB_PACK_SIZE; - status = STATUS_BUFFER_TOO_SMALL; - } - else - { - PUCHAR whereToCopy; - // determine where to copy to the user's memory - whereToCopy = outputBuffer; - whereToCopy += AACS_MKB_PACK_SIZE * thisPackNumber; - - RtlCopyMemory(whereToCopy, header->Data, totalSize); - - // update the Information field here because we already - // have calculated the size of the block - *DataLength = totalSize + (AACS_MKB_PACK_SIZE * thisPackNumber); - status = STATUS_SUCCESS; - - // if there are more packs to get from the device, send it again.... - if (thisPackNumber != otherPacks) - { - // re-send the command for the next pack number. - // this is safe here because NT_SUCCESS() is TRUE, - // and all the rest of this routine does is SetHardError() - // and release of resources we're still about to use. - - // re-zero the output buffer - RtlZeroMemory(DeviceExtension->ScratchContext.ScratchBuffer, sizeof(READ_DVD_STRUCTURES_HEADER)); - - // modify the CDB to get the next pack of the MKB - rmdBlockNumber = cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3]++; - - // modify the SRB to be resent - // - transferSize = AACS_MKB_PACK_SIZE + sizeof(READ_DVD_STRUCTURES_HEADER); - - // keep items clean - ScratchBuffer_ResetItems(DeviceExtension, FALSE); - - // make sure the loop will be executed for modified command. - sendChangedCommand = TRUE; - shouldRetry = TRUE; - } - else - { - // else, that was the end of the transfer, so just complete the request - sendChangedCommand = FALSE; - } - } - } - - } // end of IOCTL_AACS_READ_MEDIA_KEY_BLOCK - } - } // end of NT_SUCCESS(status) - - if (!NT_SUCCESS(status)) - { - // command failed. - sendChangedCommand = FALSE; - } - } //end of while (sendChangedCommand) - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsStartSession( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_START_SESSION -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsGetAgid - - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID sessionId = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&sessionId, - NULL); - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(CDVD_REPORT_AGID_DATA); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY; - cdb.AsByte[7] = 0x02; // AACS key class - cdb.REPORT_KEY.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.REPORT_KEY.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.REPORT_KEY.KeyFormat = 0x00; // DVD_REPORT_AGID? - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - static const UCHAR results[] = { 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0 }; - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - PCDVD_KEY_HEADER keyHeader = DeviceExtension->ScratchContext.ScratchBuffer; - PCDVD_REPORT_AGID_DATA keyData = (PCDVD_REPORT_AGID_DATA)keyHeader->Data; - - *sessionId = (DVD_SESSION_ID)(keyData->AGID); - *DataLength = sizeof(DVD_SESSION_ID); - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsEndSession( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_END_SESSION -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsReleaseAgid - - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID sessionId = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&sessionId, - NULL); - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - DVD_SESSION_ID currentSession = 0; - DVD_SESSION_ID limitSession = 0; - - if(*sessionId == DVD_END_ALL_SESSIONS) - { - currentSession = 0; - limitSession = MAX_COPY_PROTECT_AGID - 1; - } - else - { - currentSession = *sessionId; - limitSession = *sessionId; - } - - ScratchBuffer_BeginUse(DeviceExtension); - - do - { - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.SEND_KEY.OperationCode = SCSIOP_SEND_KEY; - cdb.AsByte[7] = 0x02; // AACS key class - cdb.SEND_KEY.AGID = (UCHAR)(currentSession); - cdb.SEND_KEY.KeyFormat = DVD_INVALIDATE_AGID; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 12); - - currentSession++; - } while ((currentSession <= limitSession) && NT_SUCCESS(status)); - -#ifdef ENABLE_AACS_TESTING - status = STATUS_SUCCESS; -#endif - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsSendCertificate( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_SEND_CERTIFICATE -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsSendHostCertificate - - NTSTATUS status = STATUS_SUCCESS; - PAACS_SEND_CERTIFICATE input = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_CERTIFICATE); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - // copy the input buffer to the data buffer for the transfer - { - PCDVD_KEY_HEADER header = (PCDVD_KEY_HEADER)DeviceExtension->ScratchContext.ScratchBuffer; - ULONG tmp = dataTransferLength; - - tmp -= RTL_SIZEOF_THROUGH_FIELD(CDVD_KEY_HEADER, DataLength); - - header->DataLength[0] = (UCHAR)(tmp >> (8*1)); - header->DataLength[1] = (UCHAR)(tmp >> (8*0)); - RtlCopyMemory(header->Data, &(input->Certificate), sizeof(AACS_CERTIFICATE)); - } - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.SEND_KEY.OperationCode = SCSIOP_SEND_KEY; - cdb.AsByte[7] = 0x02; // AACS key class - cdb.SEND_KEY.ParameterListLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.SEND_KEY.ParameterListLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.SEND_KEY.AGID = (UCHAR)( input->SessionId ); - cdb.SEND_KEY.KeyFormat = 0x01; // Send Host Challenge Certificate - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, FALSE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - *DataLength = 0; - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsGetCertificate( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_GET_CERTIFICATE -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsGetDriveCertificate - - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID input = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_CERTIFICATE); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY; - cdb.AsByte[7] = 0x02; // AACS key class - cdb.REPORT_KEY.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.REPORT_KEY.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.REPORT_KEY.AGID = (UCHAR)(*input); - cdb.REPORT_KEY.KeyFormat = 0x01; // Return a drive certificate challenge - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - static const UCHAR results[] = { 0x00, 0x72, 0x00, 0x00 }; - static const UCHAR defaultFill = 0x31; // '1' - RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0074, defaultFill); - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - ULONG dataLengthToCopy = sizeof(AACS_CERTIFICATE); - - // make length field native byte ordering - REVERSE_SHORT(&header->Length); - - // exit if getting invalid data from the drive - if (header->Length < (sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length))) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - - if (NT_SUCCESS(status)) - { - // adjust data length to reflect only the addition data - header->Length -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - - // exit if the drive is returning an unexpected data size - if (header->Length != dataLengthToCopy) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // else copy the data to the user's buffer - RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy); - *DataLength = dataLengthToCopy; - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsGetChallengeKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_GET_CHALLENGE_KEY -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsGetChallengeKey - - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID input = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_CHALLENGE_KEY); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY; - cdb.AsByte[7] = 0x02; // AACS key class - cdb.REPORT_KEY.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.REPORT_KEY.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.REPORT_KEY.AGID = (UCHAR)(*input); - cdb.REPORT_KEY.KeyFormat = 0x02; // Return a drive certificate challenge - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - static const UCHAR results[] = { 0x00, 0x52, 0x00, 0x00 }; - static const UCHAR defaultFill = 0x32; // '2' - RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0054, defaultFill); - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - ULONG dataLengthToCopy = sizeof(AACS_CHALLENGE_KEY); - - // make length field native byte ordering - REVERSE_SHORT(&header->Length); - - // exit if getting invalid data from the drive - if (header->Length < sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length)) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - - if (NT_SUCCESS(status)) - { - // adjust data length to reflect only the addition data - header->Length -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - - // exit if the drive is returning an unexpected data size - if (header->Length != dataLengthToCopy) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // else copy the data to the user's buffer - RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy); - *DataLength = dataLengthToCopy; - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleSendChallengeKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_SEND_CHALLENGE_KEY -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsSendChallengeKey - - NTSTATUS status = STATUS_SUCCESS; - PAACS_SEND_CHALLENGE_KEY input = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_CHALLENGE_KEY); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - // copy the input buffer to the data buffer for the transfer - { - PCDVD_KEY_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - ULONG tmp = dataTransferLength; - tmp -= RTL_SIZEOF_THROUGH_FIELD(CDVD_KEY_HEADER, DataLength); - - header->DataLength[0] = (UCHAR)(tmp >> (8*1)); - header->DataLength[1] = (UCHAR)(tmp >> (8*0)); - RtlCopyMemory(header->Data, &(input->ChallengeKey), sizeof(AACS_CHALLENGE_KEY)); - } - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.SEND_KEY.OperationCode = SCSIOP_SEND_KEY; - cdb.AsByte[7] = 0x02; // AACS key class - cdb.SEND_KEY.ParameterListLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.SEND_KEY.ParameterListLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.SEND_KEY.AGID = (UCHAR)( input->SessionId ); - cdb.SEND_KEY.KeyFormat = 0x02; // Send Host Challenge Certificate - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, FALSE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - *DataLength = 0; - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleReadVolumeId( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_READ_VOLUME_ID -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsReadVolumeID - - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID input = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_VOLUME_ID); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE; - cdb.READ_DVD_STRUCTURE.Format = 0x80; // Return the AACS volumeID - cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.READ_DVD_STRUCTURE.AGID = (UCHAR)(*input); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 }; - static const UCHAR defaultFill = 0x33; // '3' - RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill); - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - ULONG dataLengthToCopy = sizeof(AACS_VOLUME_ID); - - // make length field native byte ordering - REVERSE_SHORT(&header->Length); - - // exit if getting invalid data from the drive - if (header->Length < sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length)) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - - if (NT_SUCCESS(status)) - { - // adjust data length to reflect only the addition data - header->Length -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - - // exit if the drive is returning an unexpected data size - if (header->Length != dataLengthToCopy) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // else copy the data to the user's buffer - RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy); - *DataLength = dataLengthToCopy; - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsReadSerialNumber( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_READ_SERIAL_NUMBER -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsReadSerialNumber - - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID input = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_SERIAL_NUMBER); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE; - cdb.READ_DVD_STRUCTURE.Format = 0x81; // Return the AACS volumeID - cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.READ_DVD_STRUCTURE.AGID = (UCHAR)(*input); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 }; - static const UCHAR defaultFill = 0x34; // '4' - RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill); - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - ULONG dataLengthToCopy = sizeof(AACS_SERIAL_NUMBER); - - // make length field native byte ordering - REVERSE_SHORT(&header->Length); - - // exit if getting invalid data from the drive - if (header->Length < sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length)) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - - if (NT_SUCCESS(status)) - { - // adjust data length to reflect only the addition data - header->Length -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - - // exit if the drive is returning an unexpected data size - if (header->Length != dataLengthToCopy) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // else copy the data to the user's buffer - RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy); - *DataLength = dataLengthToCopy; - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsReadMediaId( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_READ_MEDIA_ID -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsReadMediaID - - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID input = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_MEDIA_ID); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE; - cdb.READ_DVD_STRUCTURE.Format = 0x82; // Return the AACS volumeID - cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.READ_DVD_STRUCTURE.AGID = (UCHAR)(*input); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 }; - static const UCHAR defaultFill = 0x35; // '5' - RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill); - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - ULONG dataLengthToCopy = sizeof(AACS_MEDIA_ID); - - // make length field native byte ordering - REVERSE_SHORT(&header->Length); - - // exit if getting invalid data from the drive - if (header->Length < sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length)) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - - if (NT_SUCCESS(status)) - { - // adjust data length to reflect only the addition data - header->Length -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - - // exit if the drive is returning an unexpected data size - if (header->Length != dataLengthToCopy) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // else copy the data to the user's buffer - RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy); - *DataLength = dataLengthToCopy; - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsReadBindingNonce( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_READ_BINDING_NONCE -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsReadBindingNonce - - NTSTATUS status = STATUS_SUCCESS; - PAACS_READ_BINDING_NONCE input = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_BINDING_NONCE); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY; - cdb.REPORT_KEY.LogicalBlockAddress[0] = (UCHAR)( input->StartLba >> (3*8) ); - cdb.REPORT_KEY.LogicalBlockAddress[1] = (UCHAR)( input->StartLba >> (2*8) ); - cdb.REPORT_KEY.LogicalBlockAddress[2] = (UCHAR)( input->StartLba >> (1*8) ); - cdb.REPORT_KEY.LogicalBlockAddress[3] = (UCHAR)( input->StartLba >> (0*8) ); - cdb.AsByte[6] = (UCHAR)( input->NumberOfSectors ); - cdb.AsByte[7] = 0x02; // AACS key class - cdb.REPORT_KEY.AllocationLength[0] = (UCHAR)(dataTransferLength >> (8*1)); - cdb.REPORT_KEY.AllocationLength[1] = (UCHAR)(dataTransferLength >> (8*0)); - cdb.REPORT_KEY.AGID = (UCHAR)( input->SessionId ); - cdb.REPORT_KEY.KeyFormat = 0x21; // Return an existing binding nonce - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 }; - static const UCHAR defaultFill = 0x36; // '6' - RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill); - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - ULONG dataLengthToCopy = sizeof(AACS_BINDING_NONCE); - - // make length field native byte ordering - REVERSE_SHORT(&header->Length); - - // exit if getting invalid data from the drive - if (header->Length < sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length)) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - - if (NT_SUCCESS(status)) - { - // adjust data length to reflect only the addition data - header->Length -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - - // exit if the drive is returning an unexpected data size - if (header->Length != dataLengthToCopy) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // else copy the data to the user's buffer - RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy); - *DataLength = dataLengthToCopy; - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleAacsGenerateBindingNonce( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - This routine is used to process IOCTL: - IOCTL_AACS_GENERATE_BINDING_NONCE -Arguments: - DeviceExtension - device context - - Request - the request that will be formatted - - RequestParameters - request parameter structur - - DataLength - data transferred length - -Return Value: - NTSTATUS - - --*/ -{ - //AacsGenerateBindingNonce - - NTSTATUS status = STATUS_SUCCESS; - PAACS_READ_BINDING_NONCE input = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&input, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - ULONG dataTransferLength = sizeof(CDVD_KEY_HEADER) + sizeof(AACS_BINDING_NONCE); - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, dataTransferLength, TRUE, &cdb, 12); - -#ifdef ENABLE_AACS_TESTING - static const UCHAR results[] = { 0x00, 0x22, 0x00, 0x00 }; - static const UCHAR defaultFill = 0x37; // '7' - RtlFillMemory(DeviceExtension->ScratchContext.ScratchBuffer, 0x0024, defaultFill); - RtlCopyMemory(DeviceExtension->ScratchContext.ScratchBuffer, results, SIZEOF_ARRAY(results)); - status = STATUS_SUCCESS; -#endif - if (NT_SUCCESS(status)) - { - PDVD_DESCRIPTOR_HEADER header = DeviceExtension->ScratchContext.ScratchBuffer; - ULONG dataLengthToCopy = sizeof(AACS_BINDING_NONCE); - - // make length field native byte ordering - REVERSE_SHORT(&header->Length); - - // exit if getting invalid data from the drive - if (header->Length < sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length)) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - - if (NT_SUCCESS(status)) - { - // adjust data length to reflect only the addition data - header->Length -= sizeof(DVD_DESCRIPTOR_HEADER) - RTL_SIZEOF_THROUGH_FIELD(DVD_DESCRIPTOR_HEADER, Length); - - // exit if the drive is returning an unexpected data size - if (header->Length != dataLengthToCopy) - { - *DataLength = 0; - status = STATUS_IO_DEVICE_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // else copy the data to the user's buffer - RtlCopyMemory(outputBuffer, header->Data, dataLengthToCopy); - *DataLength = dataLengthToCopy; - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - diff --git a/storage/class/cdrom/src/autorun.c b/storage/class/cdrom/src/autorun.c deleted file mode 100644 index 57bacec5..00000000 --- a/storage/class/cdrom/src/autorun.c +++ /dev/null @@ -1,3072 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - autorun.c - -Abstract: - - Code for support of media change detection in the cd/dvd driver - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - -#include "stddef.h" -#include "string.h" - -#include "ntddk.h" -#include "ntddstor.h" -#include "cdrom.h" -#include "mmc.h" -#include "ioctl.h" - -#include "ntstrsafe.h" - -#ifdef DEBUG_USE_WPP -#include "autorun.tmh" -#endif - -#define GESN_TIMEOUT_VALUE (0x4) -#define GESN_BUFFER_SIZE (0x8) -#define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS (2) - -#define MAXIMUM_IMMEDIATE_MCN_RETRIES (0x20) -#define MCN_REG_SUBKEY_NAME (L"MediaChangeNotification") -#define MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME (L"AlwaysDisableMCN") -#define MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME (L"AlwaysEnableMCN") - -// -// Only send polling irp when device is fully powered up and a -// power down irp is not in progress. -// -// NOTE: This helps close a window in time where a polling irp could cause -// a drive to spin up right after it has powered down. The problem is -// that SCSIPORT, ATAPI and SBP2 will be in the process of powering -// down (which may take a few seconds), but won't know that. It would -// then get a polling irp which will be put into its queue since it -// the disk isn't powered down yet. Once the disk is powered down it -// will find the polling irp in the queue and then power up the -// device to do the poll. They do not want to check if the polling -// irp has the SRB_NO_KEEP_AWAKE flag here since it is in a critical -// path and would slow down all I/Os. A better way to fix this -// would be to serialize the polling and power down irps so that -// only one of them is sent to the device at a time. -// - -_IRQL_requires_max_(PASSIVE_LEVEL) -BOOLEAN -DeviceIsMediaChangeDisabledDueToHardwareLimitation( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -BOOLEAN -DeviceIsMediaChangeDisabledForClass( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceMediaChangeDeviceInstanceOverride( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Out_ PBOOLEAN Enabled - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeMcn( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN AllowDriveToSleep - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeGesn( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -GesnDataInterpret( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PNOTIFICATION_EVENT_STATUS_HEADER Header, - _Out_ PBOOLEAN ResendImmediately - ); - -RTL_QUERY_REGISTRY_ROUTINE DeviceMediaChangeRegistryCallBack; - -EVT_WDF_WORKITEM DeviceDisableGesn; - -#if ALLOC_PRAGMA - -#pragma alloc_text(PAGE, DeviceInitializeMediaChangeDetection) -#pragma alloc_text(PAGE, DeviceEnableMediaChangeDetection) -#pragma alloc_text(PAGE, DeviceDisableMediaChangeDetection) -#pragma alloc_text(PAGE, DeviceSendDelayedMediaChangeNotifications) -#pragma alloc_text(PAGE, DeviceReleaseMcnResources) -#pragma alloc_text(PAGE, DeviceMediaChangeRegistryCallBack) -#pragma alloc_text(PAGE, DeviceInitializeMcn) -#pragma alloc_text(PAGE, DeviceDisableGesn) - -#pragma alloc_text(PAGE, DeviceIsMediaChangeDisabledDueToHardwareLimitation) -#pragma alloc_text(PAGE, DeviceMediaChangeDeviceInstanceOverride) -#pragma alloc_text(PAGE, DeviceIsMediaChangeDisabledForClass) - -#pragma alloc_text(PAGE, DeviceDisableMainTimer) - -#pragma alloc_text(PAGE, GesnDataInterpret) - -#pragma alloc_text(PAGE, RequestSetupMcnRequest) -#pragma alloc_text(PAGE, RequestPostWorkMcnRequest) -#pragma alloc_text(PAGE, RequestSendMcnRequest) - -// -// DeviceEnableMainTimer is called by EvtDeviceD0Entry which can't be made pageable -// so neither is DeviceEnableMainTimer -// -//#pragma alloc_text(PAGE, DeviceEnableMainTimer) - -#pragma alloc_text(PAGE, DeviceInitializeGesn) - -#pragma alloc_text(PAGE, RequestHandleMcnControl) - -#endif - -#pragma warning(push) -#pragma warning(disable:4152) // nonstandard extension, function/data pointer conversion in expression - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -GesnDataInterpret( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PNOTIFICATION_EVENT_STATUS_HEADER Header, - _Out_ PBOOLEAN ResendImmediately - ) -/*++ - -Routine Description: - - This routine will interpret the data returned for a GESN command, and - (if appropriate) set the media change event, and broadcast the - appropriate events to user mode for applications who care. - -Arguments: - - DeviceExtension - the device extension - - Header - the resulting data from a GESN event. - requires at least EIGHT valid bytes (header == 4, data == 4) - - ResendImmediately - whether or not to immediately resend the request. - this should be FALSE if there was no event, FALSE if the reported - event was of the DEVICE BUSY class, else true. - -Return Value: - - STATUS_SUCCESS if successful, an error code otherwise - -Notes: - - DataBuffer must be at least four bytes of valid data (header == 4 bytes), - and have at least eight bytes of allocated memory (all events == 4 bytes). - - The call to StartNextPacket may occur before this routine is completed. - the operational change notifications are informational in nature, and - while useful, are not neccessary to ensure proper operation. For example, - if the device morphs to no longer supporting WRITE commands, all further - write commands will fail. There exists a small timing window wherein - IOCTL_IS_DISK_WRITABLE may be called and get an incorrect response. If - a device supports software write protect, it is expected that the - application can handle such a case. - - NOTE: perhaps setting the updaterequired byte to one should be done here. - if so, it relies upon the setting of a 32-byte value to be an atomic - operation. unfortunately, there is no simple way to notify a class driver - which wants to know that the device behavior requires updating. - - Not ready events may be sent every second. For example, if we were - to minimize the number of asynchronous notifications, an application may - register just after a large busy time was reported. This would then - prevent the application from knowing the device was busy until some - arbitrarily chosen timeout has occurred. Also, the GESN request would - have to still occur, since it checks for non-busy events (such as user - keybutton presses and media change events) as well. The specification - states that the lower-numered events get reported first, so busy events, - while repeating, will only be reported when all other events have been - cleared from the device. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - LONG dataLength = 0; - LONG requiredLength = 0; - BOOLEAN inHomePosition = FALSE; - - PAGED_CODE(); - - // note: don't allocate anything in this routine so that we can - // always just 'return'. - *ResendImmediately = FALSE; - - if (Header->NEA) - { - return status; - } - if (Header->NotificationClass == NOTIFICATION_NO_CLASS_EVENTS) - { - return status; - } - - // HACKHACK - REF #0001 - // This loop is only taken initially, due to the inability to reliably - // auto-detect drives that report events correctly at boot. When we - // detect this behavior during the normal course of running, we will - // disable the hack, allowing more efficient use of the system. This - // should occur "nearly" instantly, as the drive should have multiple - // events queue'd (ie. power, morphing, media). - if (info->Gesn.HackEventMask) - { - // all events use the low four bytes of zero to indicate - // that there was no change in status. - UCHAR thisEvent = Header->ClassEventData[0] & 0xf; - UCHAR lowestSetBit; - UCHAR thisEventBit = (1 << Header->NotificationClass); - - if (!TEST_FLAG(info->Gesn.EventMask, thisEventBit)) - { - // The drive is reporting an event that wasn't requested - return STATUS_DEVICE_PROTOCOL_ERROR; - } - - // some bit magic here... this results in the lowest set bit only - lowestSetBit = info->Gesn.EventMask; - lowestSetBit &= (info->Gesn.EventMask - 1); - lowestSetBit ^= (info->Gesn.EventMask); - - if (thisEventBit != lowestSetBit) - { - // HACKHACK - REF #0001 - // the first time we ever see an event set that is not the lowest - // set bit in the request (iow, highest priority), we know that the - // hack is no longer required, as the device is ignoring "no change" - // events when a real event is waiting in the other requested queues. - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN::NONE: Compliant drive found, " - "removing GESN hack (%x, %x)\n", - thisEventBit, info->Gesn.EventMask)); - - info->Gesn.HackEventMask = FALSE; - } - else if (thisEvent == 0) // NOTIFICATION_*_EVENT_NO_CHANGE - { - // HACKHACK - REF #0001 - // note: this hack prevents poorly implemented firmware from constantly - // returning "No Event". we do this by cycling through the - // supported list of events here. - SET_FLAG(info->Gesn.NoChangeEventMask, thisEventBit); - CLEAR_FLAG(info->Gesn.EventMask, thisEventBit); - - // if we have cycled through all supported event types, then - // we need to reset the events we are asking about. else we - // want to resend this request immediately in case there was - // another event pending. - if (info->Gesn.EventMask == 0) - { - info->Gesn.EventMask = info->Gesn.NoChangeEventMask; - info->Gesn.NoChangeEventMask = 0; - } - else - { - *ResendImmediately = TRUE; - } - return status; - } - - } // end if (info->Gesn.HackEventMask) - - dataLength = (Header->EventDataLength[0] << 8) | - (Header->EventDataLength[1] & 0xff); - dataLength -= 2; - requiredLength = 4; // all events are four bytes - - if (dataLength < requiredLength) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "error - GESN returned only %x bytes data for fdo %p\n", - dataLength, DeviceExtension->DeviceObject)); - - return STATUS_DEVICE_PROTOCOL_ERROR; - } - - if (dataLength > requiredLength) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "error - GESN returned too many (%x) bytes data for fdo %p\n", - dataLength, DeviceExtension->DeviceObject)); - } - - if ((Header->ClassEventData[0] & 0xf) == 0) - { - // a zero event is a "no change event, so do not retry - return status; - } - - // because a event other than "no change" occurred, - // we should immediately resend this request. - *ResendImmediately = TRUE; - - switch (Header->NotificationClass) - { - - case NOTIFICATION_OPERATIONAL_CHANGE_CLASS_EVENTS: // 0x01 - { - PNOTIFICATION_OPERATIONAL_STATUS opChangeInfo = - (PNOTIFICATION_OPERATIONAL_STATUS)(Header->ClassEventData); - ULONG event; - - if (opChangeInfo->OperationalEvent == NOTIFICATION_OPERATIONAL_EVENT_CHANGE_REQUESTED) - { - break; - } - - event = (opChangeInfo->Operation[0] << 8) | - (opChangeInfo->Operation[1] ) ; - - // Workaround some hardware that is buggy but prevalent in the market - // This hardware has the property that it will report OpChange events repeatedly, - // causing us to retry immediately so quickly that we will eventually disable - // GESN to prevent an infinite loop. - // (only one valid OpChange event type now, only two ever defined) - if (info->MediaChangeRetryCount >= 4) - { - // - // HACKHACK - REF #0002 - // Some drives incorrectly report OpChange/Change (001b/0001h) events - // continuously when the tray has been ejected. This causes this routine - // to set ResendImmediately to "TRUE", and that results in our cycling - // 32 times immediately resending. At that point, we give up detecting - // the infinite retry loop, and disable GESN on these drives. This - // prevents Media Eject Request (from eject button) from being reported. - // Thus, instead we should attempt to workaround this issue by detecting - // this behavior. - // - - static UCHAR const OpChangeMask = 0x02; - - // At least one device reports "temporarily busy" (which is useless) on eject - // At least one device reports "OpChange" repeatedly when re-inserting media - // All seem to work well using this workaround - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_MCN, - "GESN OpChange events are broken. Working around this problem in software (for WDFDEVICE %p)\n", - DeviceExtension->Device)); - - // OpChange is not the only bit set -- Media class is required.... - NT_ASSERT(CountOfSetBitsUChar(info->Gesn.EventMask) != 1); - - // Force the use of the hackhack (ref #0001) to workaround the - // issue noted this hackhack (ref #0002). - SET_FLAG(info->Gesn.NoChangeEventMask, OpChangeMask); - CLEAR_FLAG(info->Gesn.EventMask, OpChangeMask); - info->Gesn.HackEventMask = TRUE; - - // don't request the opChange event again. use the method - // defined by hackhack (ref #0001) as the workaround. - if (info->Gesn.EventMask == 0) - { - info->Gesn.EventMask = info->Gesn.NoChangeEventMask; - info->Gesn.NoChangeEventMask = 0; - *ResendImmediately = FALSE; - } - else - { - *ResendImmediately = TRUE; - } - - break; - } - - - if ((event == NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_ADDED) | - (event == NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_CHANGE)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN says features added/changed for WDFDEVICE %p\n", - DeviceExtension->Device)); - - // don't notify that new media arrived, just set the - // DO_VERIFY to force a FS reload. - - if (IsVolumeMounted(DeviceExtension->DeviceObject)) - { - SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME); - } - - // Call error handler with - // a "fake" media change error in case it needs to update - // internal structures as though a media change occurred. - { - SCSI_REQUEST_BLOCK srb = {0}; - SENSE_DATA sense = {0}; - NTSTATUS tempStatus; - BOOLEAN retry; - - tempStatus = STATUS_MEDIA_CHANGED; - retry = FALSE; - - srb.CdbLength = 6; - srb.Length = sizeof(SCSI_REQUEST_BLOCK); - srb.SrbStatus = SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_ERROR; - srb.SenseInfoBuffer = &sense; - srb.SenseInfoBufferLength = sizeof(SENSE_DATA); - - sense.AdditionalSenseLength = sizeof(SENSE_DATA) - - RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength); - - sense.SenseKey = SCSI_SENSE_UNIT_ATTENTION; - sense.AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED; - - if (DeviceExtension->DeviceAdditionalData.ErrorHandler) - { - DeviceExtension->DeviceAdditionalData.ErrorHandler(DeviceExtension, - &srb, - &tempStatus, - &retry); - } - } // end error handler - - } - break; - } - - case NOTIFICATION_EXTERNAL_REQUEST_CLASS_EVENTS: // 0x3 - { - PNOTIFICATION_EXTERNAL_STATUS externalInfo = - (PNOTIFICATION_EXTERNAL_STATUS)(Header->ClassEventData); - DEVICE_EVENT_EXTERNAL_REQUEST externalData = {0}; - - // unfortunately, due to time constraints, we will only notify - // about keys being pressed, and not released. this makes keys - // single-function, but simplifies the code significantly. - if (externalInfo->ExternalEvent != NOTIFICATION_EXTERNAL_EVENT_BUTTON_DOWN) - { - break; - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN::EXTERNAL: Event: %x Status %x Req %x\n", - externalInfo->ExternalEvent, externalInfo->ExternalStatus, - (externalInfo->Request[0] << 8) | externalInfo->Request[1] - )); - - externalData.Version = 1; - externalData.DeviceClass = 0; - externalData.ButtonStatus = externalInfo->ExternalEvent; - externalData.Request = (externalInfo->Request[0] << 8) | - (externalInfo->Request[1] & 0xff); - KeQuerySystemTime(&(externalData.SystemTime)); - externalData.SystemTime.QuadPart *= (LONGLONG)KeQueryTimeIncrement(); - - DeviceSendNotification(DeviceExtension, - &GUID_IO_DEVICE_EXTERNAL_REQUEST, - sizeof(DEVICE_EVENT_EXTERNAL_REQUEST), - &externalData); - - return status; - } - - case NOTIFICATION_MEDIA_STATUS_CLASS_EVENTS: // 0x4 - { - PNOTIFICATION_MEDIA_STATUS mediaInfo = - (PNOTIFICATION_MEDIA_STATUS)(Header->ClassEventData); - - if ((mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_NEW_MEDIA) || - (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_MEDIA_CHANGE)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN::MEDIA ARRIVAL, Status %x\n", - mediaInfo->MediaStatus)); - - if (IsVolumeMounted(DeviceExtension->DeviceObject)) - { - SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME); - } - DeviceSetMediaChangeStateEx(DeviceExtension, - MediaPresent, - NULL); - - // If media is inserted into slot loading type, mark the device active - // to not power off. - if ((DeviceExtension->ZeroPowerODDInfo != NULL) && - (DeviceExtension->ZeroPowerODDInfo->LoadingMechanism == LOADING_MECHANISM_CADDY) && - (DeviceExtension->ZeroPowerODDInfo->Load == 0)) // Slot - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "GesnDataInterpret: MediaArrival event detected, device marked as active\n")); - - DeviceMarkActive(DeviceExtension, TRUE, FALSE); - } - } - else if (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN::MEDIA REMOVAL, Status %x\n", - mediaInfo->MediaStatus)); - - DeviceSetMediaChangeStateEx(DeviceExtension, - MediaNotPresent, - NULL); - - // If media is removed from slot loading type, start powering off the device - // if it is ZPODD capable. - if ((DeviceExtension->ZeroPowerODDInfo != NULL) && - (DeviceExtension->ZeroPowerODDInfo->LoadingMechanism == LOADING_MECHANISM_CADDY) && - (DeviceExtension->ZeroPowerODDInfo->Load == 0)) // Slot - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "GesnDataInterpret: MediaRemoval event detected, device marked as idle\n")); - - DeviceMarkActive(DeviceExtension, FALSE, FALSE); - } - } - else if (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN::MEDIA EJECTION, Status %x\n", - mediaInfo->MediaStatus)); - - DeviceSendNotification(DeviceExtension, - &GUID_IO_MEDIA_EJECT_REQUEST, - 0, - NULL); - } - - break; - } - - case NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS: // lowest priority events... - { - PNOTIFICATION_BUSY_STATUS busyInfo = - (PNOTIFICATION_BUSY_STATUS)(Header->ClassEventData); - DEVICE_EVENT_BECOMING_READY busyData = {0}; - - // else we want to report the approximated time till it's ready. - busyData.Version = 1; - busyData.Reason = busyInfo->DeviceBusyStatus; - busyData.Estimated100msToReady = (busyInfo->Time[0] << 8) | - (busyInfo->Time[1] & 0xff); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN::BUSY: Event: %x Status %x Time %x\n", - busyInfo->DeviceBusyEvent, busyInfo->DeviceBusyStatus, - busyData.Estimated100msToReady - )); - - // Ignore the notification if the time is small - if (busyData.Estimated100msToReady >= GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GesnDataInterpret: media BECOMING_READY\n")); - - DeviceSendNotification(DeviceExtension, - &GUID_IO_DEVICE_BECOMING_READY, - sizeof(DEVICE_EVENT_BECOMING_READY), - &busyData); - } - - // If manual loading operation is observed for slot loading type, start powering off the device - // if it is ZPODD capable. - if ((DeviceExtension->ZeroPowerODDInfo != NULL) && - (DeviceExtension->ZeroPowerODDInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) && - (DeviceExtension->ZeroPowerODDInfo->Load == 0) && // Drawer - (busyInfo->DeviceBusyEvent == NOTIFICATION_BUSY_EVENT_LO_CHANGE) && - (busyInfo->DeviceBusyStatus == NOTIFICATION_BUSY_STATUS_NO_EVENT)) - { - inHomePosition = DeviceZPODDIsInHomePosition(DeviceExtension); - - if (inHomePosition == FALSE) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "GesnDataInterpret: LoChange event detected, device marked as active\n")); - - DeviceMarkActive(DeviceExtension, TRUE, FALSE); - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "GesnDataInterpret: LoChange event detected, device marked as idle\n")); - - DeviceMarkActive(DeviceExtension, FALSE, FALSE); - } - } - - break; - } - - default: - { - break; - } - - } // end switch on notification class - - return status; -} - - -VOID -DeviceInternalSetMediaChangeState( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ MEDIA_CHANGE_DETECTION_STATE NewState, - _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState - ) -/*++ - -Routine Description: - - This routine will (if appropriate) set the media change event for the - device. The event will be set if the media state is changed and - media change events are enabled. Otherwise the media state will be - tracked but the event will not be set. - - This routine will lock out the other media change routines if possible - but if not a media change notification may be lost after the enable has - been completed. - -Arguments: - - DeviceExtension - the device extension - - NewState - new state for setting - - OldState - optional storage for the old state - -Return Value: - - none - ---*/ -{ -#if DBG - LPCSTR states[] = {"Unknown", "Present", "Not Present", "Unavailable"}; -#endif - MEDIA_CHANGE_DETECTION_STATE oldMediaState; - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - CLASS_MEDIA_CHANGE_CONTEXT mcnContext; - - if (!((NewState >= MediaUnknown) && (NewState <= MediaUnavailable))) - { - return; - } - - if (info == NULL) - { - return; - } - - oldMediaState = info->LastKnownMediaDetectionState; - if (OldState) - { - *OldState = oldMediaState; - } - - info->LastKnownMediaDetectionState = NewState; - - // Increment MediaChangeCount on transition to MediaPresent - if (NewState == MediaPresent && oldMediaState != NewState) - { - InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount); - } - - if (info->MediaChangeDetectionDisableCount != 0) - { -#if DBG - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInternalSetMediaChangeState: MCN not enabled, state " - "changed from %s to %s\n", - states[oldMediaState], states[NewState])); -#endif - return; - } -#if DBG - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInternalSetMediaChangeState: State change from %s to %s\n", - states[oldMediaState], states[NewState])); -#endif - - if (info->LastReportedMediaDetectionState == info->LastKnownMediaDetectionState) - { - // Media is in the same state as we reported last time, no need to report again. - return; - } - - // make the data useful -- it used to always be zero. - mcnContext.MediaChangeCount = DeviceExtension->MediaChangeCount; - mcnContext.NewState = NewState; - - if (NewState == MediaPresent) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInternalSetMediaChangeState: Reporting media ARRIVAL\n")); - - DeviceSendNotification(DeviceExtension, - &GUID_IO_MEDIA_ARRIVAL, - sizeof(CLASS_MEDIA_CHANGE_CONTEXT), - &mcnContext); - } - else if ((NewState == MediaNotPresent) || (NewState == MediaUnavailable)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInternalSetMediaChangeState: Reporting media REMOVAL\n")); - DeviceSendNotification(DeviceExtension, - &GUID_IO_MEDIA_REMOVAL, - sizeof(CLASS_MEDIA_CHANGE_CONTEXT), - &mcnContext); - } - else - { - // Don't notify of changed going to unknown. - return; - } - - info->LastReportedMediaDetectionState = info->LastKnownMediaDetectionState; - - return; -} // end DeviceInternalSetMediaChangeState() - - -VOID -DeviceSetMediaChangeStateEx( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ MEDIA_CHANGE_DETECTION_STATE NewState, - _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState - ) -/*++ - -Routine Description: - - This routine will (if appropriate) set the media change event for the - device. The event will be set if the media state is changed and - media change events are enabled. Otherwise the media state will be - tracked but the event will not be set. - -Arguments: - - DeviceExtension - the device extension - - NewState - new state for setting - - OldState - optional storage for the old state - -Return Value: - - none - ---*/ -{ - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - LARGE_INTEGER zero; - NTSTATUS status; - - // timeout value must be 0, as this function can be called at DISPATCH_LEVEL. - zero.QuadPart = 0; - - if (info == NULL) - { - return; - } - - status = KeWaitForMutexObject(&info->MediaChangeMutex, - Executive, - KernelMode, - FALSE, - &zero); - - if (status == STATUS_TIMEOUT) - { - // Someone else is in the process of setting the media state. - return; - } - - // Change the media present state and signal an event, if applicable - DeviceInternalSetMediaChangeState(DeviceExtension, NewState, OldState); - - KeReleaseMutex(&info->MediaChangeMutex, FALSE); - - return; -} // end DeviceSetMediaChangeStateEx() - - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceSendDelayedMediaChangeNotifications( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine sends the so-called delayed media change notifications. - These notifications get accumulated while the MCN mechanism is disabled - and need to be sent to the application on MCN enabling, if MCN enabling - happens as a part of exclusive access unlock and the application has not - requested us explicitly to not send the delayed notifications. - -Arguments: - - DeviceExtension - the device extension - -Return Value: - - none - ---*/ -{ - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - LARGE_INTEGER zero; - NTSTATUS status; - - PAGED_CODE(); - - zero.QuadPart = 0; - - if (info == NULL) - { - return; - } - - status = KeWaitForMutexObject(&info->MediaChangeMutex, - Executive, - KernelMode, - FALSE, - &zero); - - if (status == STATUS_TIMEOUT) - { - // Someone else is in the process of setting the media state. - // That's totally okay, we'll send delayed notifications later. - return; - } - - // If the last reported state and the last known state are different and - // MCN is enabled, generate a notification based on the last known state. - if ((info->LastKnownMediaDetectionState != info->LastReportedMediaDetectionState) && - (info->MediaChangeDetectionDisableCount == 0)) - { - DeviceInternalSetMediaChangeState(DeviceExtension, info->LastKnownMediaDetectionState, NULL); - } - - KeReleaseMutex(&info->MediaChangeMutex, FALSE); - - return; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestSetupMcnRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN UseGesn -) -/*++ - -Routine Description: - - This routine sets up the fields of the request for MCN - -Arguments: - DeviceExtension - device context - - UseGesn - If TRUE, the device supports GESN and it's currently the mechanism for MCN - -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSCSI_REQUEST_BLOCK srb; - PIRP irp; - PIO_STACK_LOCATION nextIrpStack; - PCDB cdb; - PVOID buffer; - WDF_REQUEST_REUSE_PARAMS params; - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - - PAGED_CODE(); - - irp = WdfRequestWdmGetIrp(info->MediaChangeRequest); - NT_ASSERT(irp != NULL); - - // deassign the MdlAddress, this is the value we assign explicitly. - // this is to prevent WdfRequestReuse to release the Mdl unexpectly. - if (irp->MdlAddress) - { - irp->MdlAddress = NULL; - } - - if (NT_SUCCESS(status)) - { - // Setup the IRP to perform a test unit ready. - WDF_REQUEST_REUSE_PARAMS_INIT(¶ms, - WDF_REQUEST_REUSE_NO_FLAGS, - STATUS_NOT_SUPPORTED); - - status = WdfRequestReuse(info->MediaChangeRequest, ¶ms); - } - - if (NT_SUCCESS(status)) - { - // Format the request. - status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget, - info->MediaChangeRequest, - IOCTL_SCSI_EXECUTE_IN, - NULL, NULL, - NULL, NULL, - NULL, NULL); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "RequestSetupMcnRequest: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n", - status)); - } - } - - if (NT_SUCCESS(status)) - { - RequestClearSendTime(info->MediaChangeRequest); - - nextIrpStack = IoGetNextIrpStackLocation(irp); - - nextIrpStack->Flags = SL_OVERRIDE_VERIFY_VOLUME; - nextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - nextIrpStack->Parameters.Scsi.Srb = &(info->MediaChangeSrb); - - // Prepare the SRB for execution. - srb = nextIrpStack->Parameters.Scsi.Srb; - buffer = info->SenseBuffer; - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - RtlZeroMemory(buffer, SENSE_BUFFER_SIZE); - - srb->QueueTag = SP_UNTAGGED; - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - srb->Length = sizeof(SCSI_REQUEST_BLOCK); - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->SenseInfoBuffer = buffer; - srb->SrbStatus = 0; - srb->ScsiStatus = 0; - srb->OriginalRequest = irp; - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - - srb->SrbFlags = DeviceExtension->SrbFlags; - SET_FLAG(srb->SrbFlags, info->SrbFlags); - - if (!UseGesn) - { - srb->TimeOutValue = CDROM_TEST_UNIT_READY_TIMEOUT; - srb->CdbLength = 6; - srb->DataTransferLength = 0; - SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_DATA_TRANSFER); - nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_NONE; - srb->DataBuffer = NULL; - srb->DataTransferLength = 0; - irp->MdlAddress = NULL; - - cdb = (PCDB) &srb->Cdb[0]; - cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; - } - else - { - NT_ASSERT(info->Gesn.Buffer); - - srb->TimeOutValue = GESN_TIMEOUT_VALUE; // much shorter timeout for GESN - - srb->CdbLength = 10; - SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_IN); - nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; - srb->DataBuffer = info->Gesn.Buffer; - srb->DataTransferLength = info->Gesn.BufferSize; - irp->MdlAddress = info->Gesn.Mdl; - - cdb = (PCDB) &srb->Cdb[0]; - cdb->GET_EVENT_STATUS_NOTIFICATION.OperationCode = SCSIOP_GET_EVENT_STATUS; - cdb->GET_EVENT_STATUS_NOTIFICATION.Immediate = 1; - cdb->GET_EVENT_STATUS_NOTIFICATION.EventListLength[0] = (UCHAR)((info->Gesn.BufferSize) >> 8); - cdb->GET_EVENT_STATUS_NOTIFICATION.EventListLength[1] = (UCHAR)((info->Gesn.BufferSize) & 0xff); - cdb->GET_EVENT_STATUS_NOTIFICATION.NotificationClassRequest = info->Gesn.EventMask; - } - } - - return status; -} - - -VOID -DeviceDisableGesn( - _In_ WDFWORKITEM WorkItem - ) -/*++ - -Routine Description: - - Work item routine to set the hack flag in the registry to disable GESN - This routine is invoked when the device reports TOO many events that affects system - -Arguments: - WorkItem - the work item be perfromed. - -Return Value: - None - ---*/ -{ - WDFDEVICE device = WdfWorkItemGetParentObject(WorkItem); - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device); - - PAGED_CODE(); - - // - // Set the hack flag in the registry - // - DeviceSetParameter(deviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_MMC_DETECTION_VALUE_NAME, - CdromDetectionUnsupported); - - WdfObjectDelete(WorkItem); - - return; -} - -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -RequestPostWorkMcnRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine handles the completion of the test unit ready irps used to - determine if the media has changed. If the media has changed, this code - signals the named event to wake up other system services that react to - media change (aka AutoPlay). - -Arguments: - - DeviceExtension - the device context - -Return Value: - - BOOLEAN - TRUE (needs retry); FALSE (shoule not retry) - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - PIRP irp; - BOOLEAN retryImmediately = FALSE; - - PAGED_CODE(); - - NT_ASSERT(info->MediaChangeRequest != NULL); - irp = WdfRequestWdmGetIrp(info->MediaChangeRequest); - - NT_ASSERT(!TEST_FLAG(info->MediaChangeSrb.SrbStatus, SRB_STATUS_QUEUE_FROZEN)); - - // use InterpretSenseInfo routine to check for media state, and also - // to call ClassError() with correct parameters. - if (SRB_STATUS(info->MediaChangeSrb.SrbStatus) != SRB_STATUS_SUCCESS) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, "MCN request - failed - srb status=%x, sense=%x/%x/%x.\n", - info->MediaChangeSrb.SrbStatus, - ((PSENSE_DATA)(info->MediaChangeSrb.SenseInfoBuffer))->SenseKey, - ((PSENSE_DATA)(info->MediaChangeSrb.SenseInfoBuffer))->AdditionalSenseCode, - ((PSENSE_DATA)(info->MediaChangeSrb.SenseInfoBuffer))->AdditionalSenseCodeQualifier)); - - if (SRB_STATUS(info->MediaChangeSrb.SrbStatus) != SRB_STATUS_NOT_POWERED) - { - // Release the queue if it is frozen. - if (info->MediaChangeSrb.SrbStatus & SRB_STATUS_QUEUE_FROZEN) - { - DeviceReleaseQueue(DeviceExtension->Device); - } - - RequestSenseInfoInterpret(DeviceExtension, - info->MediaChangeRequest, - &info->MediaChangeSrb, - 0, - &status, - NULL); - } - } - else - { - DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO = FALSE; - - if (!info->Gesn.Supported) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "MCN request - succeeded (GESN NOT supported, setting MediaPresent).\n")); - - // success != media for GESN case - DeviceSetMediaChangeStateEx(DeviceExtension, - MediaPresent, - NULL); - } - else - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, - "MCN request - succeeded (GESN supported).\n")); - } - } - - if (info->Gesn.Supported) - { - if (status == STATUS_DATA_OVERRUN) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "MCN Request - Data Overrun\n")); - status = STATUS_SUCCESS; - } - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "MCN Request: GESN failed with status %x\n", status)); - } - else - { - // for GESN, need to interpret the results of the data. - // this may also require an immediate retry - if (irp->IoStatus.Information == 8 ) - { - GesnDataInterpret(DeviceExtension, - (PVOID)info->Gesn.Buffer, - &retryImmediately); - } - - } // end of NT_SUCCESS(status) - - } // end of Info->Gesn.Supported - - // free port-allocated sense buffer, if any. - if (PORT_ALLOCATED_SENSE(DeviceExtension, &info->MediaChangeSrb)) - { - FREE_PORT_ALLOCATED_SENSE_BUFFER(DeviceExtension, &info->MediaChangeSrb); - } - - // Remember the IRP and SRB for use the next time. - NT_ASSERT(IoGetNextIrpStackLocation(irp)); - IoGetNextIrpStackLocation(irp)->Parameters.Scsi.Srb = &info->MediaChangeSrb; - - // run a sanity check to make sure we're not recursing continuously - if (retryImmediately) - { - info->MediaChangeRetryCount++; - - if (info->MediaChangeRetryCount > MAXIMUM_IMMEDIATE_MCN_RETRIES) - { - // Disable GESN on this device. - // Create a work item to set the value in the registry - WDF_OBJECT_ATTRIBUTES attributes; - WDF_WORKITEM_CONFIG workitemConfig; - WDFWORKITEM workItem; - - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = DeviceExtension->Device; - - WDF_WORKITEM_CONFIG_INIT(&workitemConfig, DeviceDisableGesn); - workitemConfig.AutomaticSerialization = FALSE; - - status = WdfWorkItemCreate(&workitemConfig, - &attributes, - &workItem); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "MCN Request: Disabling GESN for WDFDEVICE %p\n", DeviceExtension->Device)); - - if (NT_SUCCESS(status)) - { - WdfWorkItemEnqueue(workItem); - } - - info->Gesn.Supported = FALSE; - info->Gesn.EventMask = 0; - info->Gesn.BufferSize = 0; - info->MediaChangeRetryCount = 0; - retryImmediately = FALSE; - // should we log an error in event log? - } - } - else - { - info->MediaChangeRetryCount = 0; - } - - return retryImmediately; -} - - -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -RequestSendMcnRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine sends the formatted MCN request sychronizely to lower driver. - -Arguments: - - DeviceExtension - the device context - -Return Value: - BOOLEAN - TRUE (requst successfully sent); FALSE (request failed to send) - ---*/ -{ - BOOLEAN requestSent = FALSE; - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - - PAGED_CODE(); - - RequestSend(DeviceExtension, - info->MediaChangeRequest, - DeviceExtension->IoTarget, - WDF_REQUEST_SEND_OPTION_SYNCHRONOUS, - &requestSent); - - return requestSent; -} // end RequestSendMcnRequest() - - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeMcn( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN AllowDriveToSleep - ) -/*++ - -Routine Description: - - This routine initialize the contents of MCN structure. - -Arguments: - - DeviceExtension - the device extension - - AllowDriveToSleep - for CDROM, this parameter should be always FALSE - -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PMEDIA_CHANGE_DETECTION_INFO mediaChangeInfo = NULL; - PIRP irp = NULL; - PVOID senseBuffer = NULL; - WDF_OBJECT_ATTRIBUTES attributes; - - PAGED_CODE(); - - if (DeviceExtension->MediaChangeDetectionInfo != NULL) - { - //Already initialized. - return STATUS_SUCCESS; - } - - DeviceExtension->KernelModeMcnContext.FileObject = (PVOID)-1; - DeviceExtension->KernelModeMcnContext.DeviceObject = (PVOID)-1; - DeviceExtension->KernelModeMcnContext.LockCount = 0; - DeviceExtension->KernelModeMcnContext.McnDisableCount = 0; - - mediaChangeInfo = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(MEDIA_CHANGE_DETECTION_INFO), - CDROM_TAG_MEDIA_CHANGE_DETECTION); - - if (mediaChangeInfo == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - - if (NT_SUCCESS(status)) - { - if ((DeviceExtension->PowerDescriptor != NULL) && - (DeviceExtension->PowerDescriptor->AsynchronousNotificationSupported != FALSE) && - (!TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_ASYNCHRONOUS_NOTIFICATION))) - { - mediaChangeInfo->AsynchronousNotificationSupported = TRUE; - } - } - - // Allocate an IRP to carry the IOCTL_MCN_SYNC_FAKE_IOCTL. - if (NT_SUCCESS(status)) - { - irp = IoAllocateIrp(DeviceExtension->DeviceObject->StackSize, FALSE); - - if (irp == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - attributes.ParentObject = DeviceExtension->Device; - status = WdfRequestCreate(&attributes, - DeviceExtension->IoTarget, - &mediaChangeInfo->MediaChangeRequest); - } - - if (NT_SUCCESS(status)) - { - // Preformat the media change request. With this being done, we never need to worry about - // WdfIoTargetFormatRequestForInternalIoctlOthers ever failing later. - status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget, - mediaChangeInfo->MediaChangeRequest, - IOCTL_SCSI_EXECUTE_IN, - NULL, NULL, - NULL, NULL, - NULL, NULL); - } - - if (NT_SUCCESS(status)) - { - senseBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - SENSE_BUFFER_SIZE, - CDROM_TAG_MEDIA_CHANGE_DETECTION); - if (senseBuffer == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - mediaChangeInfo->MediaChangeSyncIrp = irp; - mediaChangeInfo->SenseBuffer = senseBuffer; - - // Set default values for the media change notification - // configuration. - mediaChangeInfo->MediaChangeDetectionDisableCount = 0; - - // Assume that there is initially no media in the device - // only notify upper layers if there is something there - mediaChangeInfo->LastKnownMediaDetectionState = MediaUnknown; - mediaChangeInfo->LastReportedMediaDetectionState = MediaUnknown; - - // setup all extra flags we'll be setting for this irp - mediaChangeInfo->SrbFlags = 0; - - SET_FLAG(mediaChangeInfo->SrbFlags, SRB_CLASS_FLAGS_LOW_PRIORITY); - SET_FLAG(mediaChangeInfo->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE); - SET_FLAG(mediaChangeInfo->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); - - if (AllowDriveToSleep) //FALSE for CD/DVD devices - { - SET_FLAG(mediaChangeInfo->SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE); - } - - KeInitializeMutex(&mediaChangeInfo->MediaChangeMutex, 0x100); - - // It is ok to support media change events on this device. - DeviceExtension->MediaChangeDetectionInfo = mediaChangeInfo; - - // check the device supports GESN or not, initialize GESN structure if it supports. - { - // This is only valid for type5 devices. - NTSTATUS tempStatus = STATUS_SUCCESS; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInitializeMcn: Testing for GESN\n")); - tempStatus = DeviceInitializeGesn(DeviceExtension); - - if (NT_SUCCESS(tempStatus)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInitializeMcn: GESN available for %p\n", - DeviceExtension->DeviceObject)); - NT_ASSERT(mediaChangeInfo->Gesn.Supported ); - NT_ASSERT(mediaChangeInfo->Gesn.Buffer != NULL); - NT_ASSERT(mediaChangeInfo->Gesn.BufferSize != 0); - NT_ASSERT(mediaChangeInfo->Gesn.EventMask != 0); - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInitializeMcn: GESN *NOT* available for %p\n", - DeviceExtension->DeviceObject)); - NT_ASSERT(!mediaChangeInfo->Gesn.Supported); - NT_ASSERT(mediaChangeInfo->Gesn.Buffer == NULL); - NT_ASSERT(mediaChangeInfo->Gesn.BufferSize == 0); - NT_ASSERT(mediaChangeInfo->Gesn.EventMask == 0); - mediaChangeInfo->Gesn.Supported = FALSE; // just in case.... - } - } - } - - if (NT_SUCCESS(status)) - { - // Register for display state change on AOAC capable systems so we can put the - // device to low power state when not required. - if (mediaChangeInfo->DisplayStateCallbackHandle == NULL) - { - POWER_PLATFORM_INFORMATION PlatformInfo = {0}; - - status = ZwPowerInformation(PlatformInformation, - NULL, - 0, - &PlatformInfo, - sizeof(PlatformInfo)); - - if (NT_SUCCESS(status) && PlatformInfo.AoAc) - { - PoRegisterPowerSettingCallback(DeviceExtension->DeviceObject, - &GUID_CONSOLE_DISPLAY_STATE, - &DevicePowerSettingCallback, - DeviceExtension, - &mediaChangeInfo->DisplayStateCallbackHandle); - } - - // Ignore any failures above. - status = STATUS_SUCCESS; - } - } - - if (!NT_SUCCESS(status)) - { - if (irp != NULL) - { - IoFreeIrp(irp); - } - FREE_POOL(senseBuffer); - FREE_POOL(mediaChangeInfo); - } - - return status; - -} // end DeviceInitializeMcn() - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeGesn( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine initialize the contents of GESN structure. - -Arguments: - - DeviceExtension - the device extension - -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PNOTIFICATION_EVENT_STATUS_HEADER header = NULL; - CDROM_DETECTION_STATE detectionState = CdromDetectionUnknown; - PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = DeviceExtension->DeviceDescriptor; - BOOLEAN retryImmediately = TRUE; - ULONG i = 0; - ULONG atapiResets = 0; - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - - PAGED_CODE(); - - NT_ASSERT(info != NULL); - - // read if we already know the abilities of the device - DeviceGetParameter(DeviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_MMC_DETECTION_VALUE_NAME, - (PULONG)&detectionState); - - if (detectionState == CdromDetectionUnsupported) - { - status = STATUS_NOT_SUPPORTED; - } - - // check if the device has a hack flag saying never to try this. - if (NT_SUCCESS(status) && - (TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_GESN_IS_BAD)) ) - { - DeviceSetParameter(DeviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_MMC_DETECTION_VALUE_NAME, - CdromDetectionUnsupported); - status = STATUS_NOT_SUPPORTED; - } - - // else go through the process since we allocate buffers and - // get all sorts of device settings. - if (NT_SUCCESS(status)) - { - if (info->Gesn.Buffer == NULL) - { - info->Gesn.Buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - GESN_BUFFER_SIZE, - CDROM_TAG_GESN); - } - - if (info->Gesn.Buffer == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - if (info->Gesn.Mdl != NULL) - { - IoFreeMdl(info->Gesn.Mdl); - } - - info->Gesn.Mdl = IoAllocateMdl(info->Gesn.Buffer, - GESN_BUFFER_SIZE, - FALSE, - FALSE, - NULL); - if (info->Gesn.Mdl == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - MmBuildMdlForNonPagedPool(info->Gesn.Mdl); - info->Gesn.BufferSize = GESN_BUFFER_SIZE; - info->Gesn.EventMask = 0; - - // all items are prepared to use GESN (except the event mask, so don't - // optimize this part out!). - // - // now see if it really works. we have to loop through this because - // many SAMSUNG (and one COMPAQ) drives timeout when requesting - // NOT_READY events, even when the IMMEDIATE bit is set. :( - // - // using a drive list is cumbersome, so this might fix the problem. - for (i = 0; (i < 16) && retryImmediately; i++) - { - status = RequestSetupMcnRequest(DeviceExtension, TRUE); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "Setup Mcn request failed %x for WDFDEVICE %p\n", - status, DeviceExtension->Device)); - break; - } - - NT_ASSERT(TEST_FLAG(info->MediaChangeSrb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE)); - - status = DeviceSendRequestSynchronously(DeviceExtension->Device, info->MediaChangeRequest, TRUE); - - if (SRB_STATUS(info->MediaChangeSrb.SrbStatus) != SRB_STATUS_SUCCESS) - { - // Release the queue if it is frozen. - if (info->MediaChangeSrb.SrbStatus & SRB_STATUS_QUEUE_FROZEN) - { - DeviceReleaseQueue(DeviceExtension->Device); - } - - RequestSenseInfoInterpret(DeviceExtension, - info->MediaChangeRequest, - &(info->MediaChangeSrb), - 0, - &status, - NULL); - } - - if ((deviceDescriptor->BusType == BusTypeAtapi) && - (info->MediaChangeSrb.SrbStatus == SRB_STATUS_BUS_RESET)) - { - // - // ATAPI unfortunately returns SRB_STATUS_BUS_RESET instead - // of SRB_STATUS_TIMEOUT, so we cannot differentiate between - // the two. if we get this status four time consecutively, - // stop trying this command. it is too late to change ATAPI - // at this point, so special-case this here. (07/10/2001) - // NOTE: any value more than 4 may cause the device to be - // marked missing. - // - atapiResets++; - if (atapiResets >= 4) - { - status = STATUS_IO_DEVICE_ERROR; - break; - } - } - - if (status == STATUS_DATA_OVERRUN) - { - status = STATUS_SUCCESS; - } - - if ((status == STATUS_INVALID_DEVICE_REQUEST) || - (status == STATUS_TIMEOUT) || - (status == STATUS_IO_DEVICE_ERROR) || - (status == STATUS_IO_TIMEOUT)) - { - // with these error codes, we don't ever want to try this command - // again on this device, since it reacts poorly. - DeviceSetParameter( DeviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_MMC_DETECTION_VALUE_NAME, - CdromDetectionUnsupported); - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "GESN test failed %x for WDFDEVICE %p\n", - status, DeviceExtension->Device)); - break; - } - - if (!NT_SUCCESS(status)) - { - // this may be other errors that should not disable GESN - // for all future start_device calls. - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "GESN test failed %x for WDFDEVICE %p\n", - status, DeviceExtension->Device)); - break; - } - else if (i == 0) - { - // the first time, the request was just retrieving a mask of - // available bits. use this to mask future requests. - header = (PNOTIFICATION_EVENT_STATUS_HEADER)(info->Gesn.Buffer); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "WDFDEVICE %p supports event mask %x\n", - DeviceExtension->Device, header->SupportedEventClasses)); - - if (TEST_FLAG(header->SupportedEventClasses, - NOTIFICATION_MEDIA_STATUS_CLASS_MASK)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN supports MCN\n")); - } - if (TEST_FLAG(header->SupportedEventClasses, - NOTIFICATION_DEVICE_BUSY_CLASS_MASK)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN supports DeviceBusy\n")); - } - if (TEST_FLAG(header->SupportedEventClasses, - NOTIFICATION_OPERATIONAL_CHANGE_CLASS_MASK)) - { - if (TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, - FDO_HACK_GESN_IGNORE_OPCHANGE)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN supports OpChange, but must ignore these events for compatibility\n")); - CLEAR_FLAG(header->SupportedEventClasses, - NOTIFICATION_OPERATIONAL_CHANGE_CLASS_MASK); - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN supports OpChange\n")); - } - } - info->Gesn.EventMask = header->SupportedEventClasses; - - // - // realistically, we are only considering the following events: - // EXTERNAL REQUEST - this is being tested for play/stop/etc. - // MEDIA STATUS - autorun and ejection requests. - // DEVICE BUSY - to allow us to predict when media will be ready. - // therefore, we should not bother querying for the other, - // unknown events. clear all but the above flags. - // - info->Gesn.EventMask &= NOTIFICATION_OPERATIONAL_CHANGE_CLASS_MASK | - NOTIFICATION_EXTERNAL_REQUEST_CLASS_MASK | - NOTIFICATION_MEDIA_STATUS_CLASS_MASK | - NOTIFICATION_DEVICE_BUSY_CLASS_MASK ; - - - // - // HACKHACK - REF #0001 - // Some devices will *never* report an event if we've also requested - // that it report lower-priority events. this is due to a - // misunderstanding in the specification wherein a "No Change" is - // interpreted to be a real event. what should occur is that the - // device should ignore "No Change" events when multiple event types - // are requested unless there are no other events waiting. this - // greatly reduces the number of requests that the host must send - // to determine if an event has occurred. Since we must work on all - // drives, default to enabling the hack until we find evidence of - // proper firmware. - // - if (info->Gesn.EventMask == 0) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN supported, but not mask we care about (%x) for FDO %p\n", - header->SupportedEventClasses, - DeviceExtension->DeviceObject)); - // NOTE: the status is still status_sucess. - break; - } - else if (CountOfSetBitsUChar(info->Gesn.EventMask) == 1) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN hack not required for FDO %p\n", - DeviceExtension->DeviceObject)); - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN hack enabled for FDO %p\n", - DeviceExtension->DeviceObject)); - info->Gesn.HackEventMask = 1; - } - } - else - { - // i > 0; not the first time looping through, so interpret the results. - status = GesnDataInterpret(DeviceExtension, - (PVOID)info->Gesn.Buffer, - &retryImmediately); - - if (!NT_SUCCESS(status)) - { - // This drive does not support GESN correctly - DeviceSetParameter( DeviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_MMC_DETECTION_VALUE_NAME, - CdromDetectionUnsupported); - break; - } - } - } // end 'for' loop of GESN requests.... - } - - if (NT_SUCCESS(status)) - { - // - // we can only use this if it can be relied upon for media changes, - // since we are (by definition) no longer going to be polling via - // a TEST_UNIT_READY irp, and drives will not report UNIT ATTENTION - // for this command (although a filter driver, such as one for burning - // cd's, might still fake those errors). - // - // since we also rely upon NOT_READY events to change the cursor - // into a "wait" cursor; GESN is still more reliable than other - // methods, and includes eject button requests, so we'll use it - // without DEVICE_BUSY in Windows Vista. - // - - if (TEST_FLAG(info->Gesn.EventMask, NOTIFICATION_MEDIA_STATUS_CLASS_MASK)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "Enabling GESN support for WDFDEVICE %p\n", - DeviceExtension->Device)); - info->Gesn.Supported = TRUE; - - DeviceSetParameter( DeviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_MMC_DETECTION_VALUE_NAME, - CdromDetectionSupported); - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "GESN available but not enabled for WDFDEVICE %p\n", - DeviceExtension->Device)); - status = STATUS_NOT_SUPPORTED; - } - } - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "GESN support detection failed for WDFDEVICE %p with status %08x\n", - DeviceExtension->Device, status)); - - if (info->Gesn.Mdl) - { - PIRP irp = WdfRequestWdmGetIrp(info->MediaChangeRequest); - - IoFreeMdl(info->Gesn.Mdl); - info->Gesn.Mdl = NULL; - irp->MdlAddress = NULL; - } - - FREE_POOL(info->Gesn.Buffer); - info->Gesn.Supported = FALSE; - info->Gesn.EventMask = 0; - info->Gesn.BufferSize = 0; - } - - return status; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeMediaChangeDetection( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine checks to see if it is safe to initialize MCN (the back end - to autorun) for a given device. It will then check the device-type wide - key "Autorun" in the service key (for legacy reasons), and then look in - the device-specific key to potentially override that setting. - - If MCN is to be enabled, all neccessary structures and memory are - allocated and initialized. - - This routine MUST be called only from the DeviceInit...() . - -Arguments: - - DeviceExtension - the device to initialize MCN for, if appropriate - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - BOOLEAN disabled = FALSE; - BOOLEAN instanceOverride; - - PAGED_CODE(); - - // NOTE: This assumes that DeviceInitializeMediaChangeDetection is always - // called in the context of the DeviceInitDevicePhase2. If called - // after then this check will have already been made and the - // once a second timer will not have been enabled. - - disabled = DeviceIsMediaChangeDisabledDueToHardwareLimitation(DeviceExtension); - - if (disabled) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInitializeMediaChangeDetection: Disabled due to hardware" - "limitations for this device\n")); - } - else - { - // autorun should now be enabled by default for all media types. - disabled = DeviceIsMediaChangeDisabledForClass(DeviceExtension); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInitializeMediaChangeDetection: MCN is %s\n", - (disabled ? "disabled" : "enabled"))); - - status = DeviceMediaChangeDeviceInstanceOverride(DeviceExtension, - &instanceOverride); // default value - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInitializeMediaChangeDetection: Instance using default\n")); - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInitializeMediaChangeDetection: Instance override: %s MCN\n", - (instanceOverride ? "Enabling" : "Disabling"))); - disabled = !instanceOverride; - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceInitializeMediaChangeDetection: Instance MCN is %s\n", - (disabled ? "disabled" : "enabled"))); - } - - if (!disabled) - { - // if the drive is not a CDROM, allow the drive to sleep - status = DeviceInitializeMcn(DeviceExtension, FALSE); - } - - return status; -} // end DeviceInitializeMediaChangeDetection() - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceMediaChangeDeviceInstanceOverride( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Out_ PBOOLEAN Enabled - ) -/*++ - -Routine Description: - - The user can override the global setting to enable or disable Autorun on a - specific cdrom device via the control panel. This routine checks and/or - sets this value. - -Arguments: - - DeviceExtension - the device to set/get the value for - - Enabled - TRUE (Autorun is enabled) - FALSE (Autorun is disabled) -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_UNSUCCESSFUL; - WDFKEY deviceKey = NULL; - WDFKEY subKey = NULL; - - UNICODE_STRING subkeyName; - UNICODE_STRING enableMcnValueName; - UNICODE_STRING disableMcnValueName; - ULONG alwaysEnable = 0; - ULONG alwaysDisable = 0; - - PAGED_CODE(); - - status = WdfDeviceOpenRegistryKey(DeviceExtension->Device, - PLUGPLAY_REGKEY_DEVICE, - KEY_ALL_ACCESS, - WDF_NO_OBJECT_ATTRIBUTES, - &deviceKey); - if (!NT_SUCCESS(status)) - { - // this can occur when a new device is added to the system - // this is due to cdrom.sys being an 'essential' driver - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceMediaChangeDeviceInstanceOverride: " - "Could not open device registry key [%lx]\n", status)); - } - else - { - RtlInitUnicodeString(&subkeyName, MCN_REG_SUBKEY_NAME); - - status = WdfRegistryOpenKey(deviceKey, - &subkeyName, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - &subKey); - } - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceMediaChangeDeviceInstanceOverride: " - "subkey could not be created. %lx\n", status)); - } - else - { - // Default to not changing autorun behavior, based upon setting - // registryValue to zero. - RtlInitUnicodeString(&enableMcnValueName, MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME); - RtlInitUnicodeString(&disableMcnValueName, MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME); - - // Ignore failures on reading of subkeys - (VOID) WdfRegistryQueryULong(subKey, - &enableMcnValueName, - &alwaysEnable); - (VOID) WdfRegistryQueryULong(subKey, - &disableMcnValueName, - &alwaysDisable); - } - - // set return value and cleanup - - if (subKey != NULL) - { - WdfRegistryClose(subKey); - } - - if (deviceKey != NULL) - { - WdfRegistryClose(deviceKey); - } - - if (alwaysEnable && alwaysDisable) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceMediaChangeDeviceInstanceOverride: %s selected\n", - "Both Enable and Disable set -- DISABLE")); - NT_ASSERT(NT_SUCCESS(status)); - status = STATUS_SUCCESS; - *Enabled = FALSE; - } - else if (alwaysDisable) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceMediaChangeDeviceInstanceOverride: %s selected\n", - "DISABLE")); - NT_ASSERT(NT_SUCCESS(status)); - status = STATUS_SUCCESS; - *Enabled = FALSE; - } - else if (alwaysEnable) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceMediaChangeDeviceInstanceOverride: %s selected\n", - "ENABLE")); - NT_ASSERT(NT_SUCCESS(status)); - status = STATUS_SUCCESS; - *Enabled = TRUE; - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceMediaChangeDeviceInstanceOverride: %s selected\n", - "DEFAULT")); - status = STATUS_UNSUCCESSFUL; - } - - return status; -} // end DeviceMediaChangeDeviceInstanceOverride() - - -NTSTATUS -DeviceMediaChangeRegistryCallBack( - _In_z_ PWSTR ValueName, - _In_ ULONG ValueType, - _In_reads_bytes_opt_(ValueLength) PVOID ValueData, - _In_ ULONG ValueLength, - _In_opt_ PVOID Context, - _In_opt_ PVOID EntryContext - ) -/*++ - -Routine Description: - - This callback for a registry SZ or MULTI_SZ is called once for each - SZ in the value. It will attempt to match the data with the - UNICODE_STRING passed in as Context, and modify EntryContext if a - match is found. Written for ClasspCheckRegistryForMediaChangeCompletion - -Arguments: - - ValueName - name of the key that was opened - ValueType - type of data stored in the value (REG_SZ for this routine) - ValueData - data in the registry, in this case a wide string - ValueLength - length of the data including the terminating null - Context - unicode string to compare against ValueData - EntryContext - should be initialized to 0, will be set to 1 if match found - -Return Value: - - STATUS_SUCCESS - EntryContext will be 1 if found - ---*/ -{ - PULONG valueFound; - PUNICODE_STRING deviceString; - PWSTR keyValue; - - PAGED_CODE(); - - UNREFERENCED_PARAMETER(ValueName); - - if ((Context == NULL) || (EntryContext == NULL)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "DeviceMediaChangeRegistryCallBack: NULL context should never be passed to registry call-back!\n")); - - return STATUS_SUCCESS; - } - - // if we have already set the value to true, exit - valueFound = EntryContext; - if ((*valueFound) != 0) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceMediaChangeRegistryCallBack: already set to true\n")); - return STATUS_SUCCESS; - } - - if (ValueLength == sizeof(WCHAR)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "DeviceMediaChangeRegistryCallBack: NULL string should never be passed to registry call-back!\n")); - return STATUS_SUCCESS; - } - - // if the data is not a terminated string, exit - if (ValueType != REG_SZ) - { - return STATUS_SUCCESS; - } - - deviceString = Context; - keyValue = ValueData; - ValueLength -= sizeof(WCHAR); // ignore the null character - - // do not compare more memory than is in deviceString - if (ValueLength > deviceString->Length) - { - ValueLength = deviceString->Length; - } - - if (keyValue == NULL) - { - return STATUS_SUCCESS; - } - - // if the strings match, disable autorun - if (RtlCompareMemory(deviceString->Buffer, keyValue, ValueLength) == ValueLength) - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "DeviceMediaChangeRegistryCallBack: Match found\n")); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "DeviceMediaChangeRegistryCallBack: DeviceString at %p\n", - deviceString->Buffer)); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, - "DeviceMediaChangeRegistryCallBack: KeyValue at %p\n", - keyValue)); - (*valueFound) = TRUE; - } - - return STATUS_SUCCESS; -} // end DeviceMediaChangeRegistryCallBack() - - -_IRQL_requires_max_(PASSIVE_LEVEL) -BOOLEAN -DeviceIsMediaChangeDisabledDueToHardwareLimitation( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - The key AutoRunAlwaysDisable contains a MULTI_SZ of hardware IDs for - which to never enable MediaChangeNotification. - - The user can override the global setting to enable or disable Autorun on a - specific cdrom device via the control panel. - - NOTE: It's intended that not use WdfRegistryQueryMultiString in this funciton, - as it's much more complicated.(needs WDFCOLLECTION, WDFSTRING other than - UNICODE_STRING) - -Arguments: - - FdoExtension - - RegistryPath - pointer to the unicode string inside - ...\CurrentControlSet\Services\Cdrom - -Return Value: - - TRUE - no autorun. - FALSE - Autorun may be enabled - ---*/ -{ - NTSTATUS status; - - PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = DeviceExtension->DeviceDescriptor; - WDFKEY wdfKey; - HANDLE serviceKey = NULL; - RTL_QUERY_REGISTRY_TABLE parameters[2] = {0}; - - UNICODE_STRING deviceUnicodeString = {0}; - ANSI_STRING deviceString = {0}; - ULONG mediaChangeNotificationDisabled = 0; - - PAGED_CODE(); - - // open the service key. - status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), - KEY_ALL_ACCESS, - WDF_NO_OBJECT_ATTRIBUTES, - &wdfKey); - - if(!NT_SUCCESS(status)) - { - NT_ASSERT(FALSE); - - // always take the safe path. if we can't open the service key, disable autorun - return TRUE; - } - - if(NT_SUCCESS(status)) - { - // Determine if drive is in a list of those requiring - // autorun to be disabled. this is stored in a REG_MULTI_SZ - // named AutoRunAlwaysDisable. this is required as some autochangers - // must load the disc to reply to ChkVerify request, causing them - // to cycle discs continuously. - - PWSTR nullMultiSz; - PUCHAR vendorId = NULL; - PUCHAR productId = NULL; - PUCHAR revisionId = NULL; - size_t length; - size_t offset; - - deviceString.Buffer = NULL; - deviceUnicodeString.Buffer = NULL; - - serviceKey = WdfRegistryWdmGetHandle(wdfKey); - - // there may be nothing to check against - if ((deviceDescriptor->VendorIdOffset == 0) && - (deviceDescriptor->ProductIdOffset == 0)) - { - // no valid data in device extension. - status = STATUS_INTERNAL_ERROR; - } - - // build deviceString using VendorId, Model and Revision. - // this string will be used to checked if it's one of devices in registry disable list. - if (NT_SUCCESS(status)) - { - length = 0; - - if (deviceDescriptor->VendorIdOffset == 0) - { - vendorId = NULL; - } - else - { - vendorId = (PUCHAR) deviceDescriptor + deviceDescriptor->VendorIdOffset; - length = strlen((LPCSTR)vendorId); - } - - if ( deviceDescriptor->ProductIdOffset == 0 ) - { - productId = NULL; - } - else - { - productId = (PUCHAR) deviceDescriptor + deviceDescriptor->ProductIdOffset; - length += strlen((LPCSTR)productId); - } - - if ( deviceDescriptor->ProductRevisionOffset == 0 ) - { - revisionId = NULL; - } - else - { - revisionId = (PUCHAR) deviceDescriptor + deviceDescriptor->ProductRevisionOffset; - length += strlen((LPCSTR)revisionId); - } - - // allocate a buffer for the string - deviceString.Length = (USHORT)( length ); - deviceString.MaximumLength = deviceString.Length + 1; - deviceString.Buffer = (PCHAR)ExAllocatePool2(POOL_FLAG_NON_PAGED, - deviceString.MaximumLength, - CDROM_TAG_AUTORUN_DISABLE - ); - if (deviceString.Buffer == NULL) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceIsMediaChangeDisabledDueToHardwareLimitation: Unable to alloc string buffer\n" )); - status = STATUS_INTERNAL_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // copy strings to the buffer - offset = 0; - - if (vendorId != NULL) - { - RtlCopyMemory(deviceString.Buffer + offset, - vendorId, - strlen((LPCSTR)vendorId)); - offset += strlen((LPCSTR)vendorId); - } - - if ( productId != NULL ) - { - RtlCopyMemory(deviceString.Buffer + offset, - productId, - strlen((LPCSTR)productId)); - offset += strlen((LPCSTR)productId); - } - if ( revisionId != NULL ) - { - RtlCopyMemory(deviceString.Buffer + offset, - revisionId, - strlen((LPCSTR)revisionId)); - offset += strlen((LPCSTR)revisionId); - } - - NT_ASSERT(offset == deviceString.Length); - - #pragma warning(suppress:6386) // Not an issue as deviceString.Buffer is of size deviceString.MaximumLength, which is equal to (deviceString.Length + 1) - deviceString.Buffer[deviceString.Length] = '\0'; // Null-terminated - - // convert to unicode as registry deals with unicode strings - status = RtlAnsiStringToUnicodeString( &deviceUnicodeString, - &deviceString, - TRUE - ); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceIsMediaChangeDisabledDueToHardwareLimitation: cannot convert " - "to unicode %lx\n", status)); - } - } - - if (NT_SUCCESS(status)) - { - // query the value, setting valueFound to true if found - nullMultiSz = L"\0"; - parameters[0].QueryRoutine = DeviceMediaChangeRegistryCallBack; - parameters[0].Flags = RTL_QUERY_REGISTRY_REQUIRED; - parameters[0].Name = L"AutoRunAlwaysDisable"; - parameters[0].EntryContext = &mediaChangeNotificationDisabled; - parameters[0].DefaultType = REG_MULTI_SZ; - parameters[0].DefaultData = nullMultiSz; - parameters[0].DefaultLength = 0; - - status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - serviceKey, - parameters, - &deviceUnicodeString, - NULL); - UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning. - } - } - - // Cleanup - { - - FREE_POOL( deviceString.Buffer ); - if (deviceUnicodeString.Buffer != NULL) - { - RtlFreeUnicodeString( &deviceUnicodeString ); - } - - // handle serviceKey will be closed by framework while it closes registry key. - WdfRegistryClose(wdfKey); - } - - if (mediaChangeNotificationDisabled > 0) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceIsMediaChangeDisabledDueToHardwareLimitation: Device is on MCN disable list\n")); - } - - return (mediaChangeNotificationDisabled > 0); - -} // end DeviceIsMediaChangeDisabledDueToHardwareLimitation() - - -_IRQL_requires_max_(PASSIVE_LEVEL) -BOOLEAN -DeviceIsMediaChangeDisabledForClass( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - The user must specify that AutoPlay is to run on the platform - by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\ - Services\<SERVICE>\Autorun:REG_DWORD:1. - - The user can override the global setting to enable or disable Autorun on a - specific cdrom device via the control panel. - -Arguments: - - DeviceExtension - device extension - -Return Value: - - TRUE - Autorun is disabled for this class - FALSE - Autorun is enabled for this class - ---*/ -{ - NTSTATUS status; - WDFKEY serviceKey = NULL; - WDFKEY parametersKey = NULL; - - UNICODE_STRING parameterKeyName; - UNICODE_STRING valueName; - - // Default to ENABLING MediaChangeNotification (!) - ULONG mcnRegistryValue = 1; - - PAGED_CODE(); - - // open the service key. - status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), - KEY_ALL_ACCESS, - WDF_NO_OBJECT_ATTRIBUTES, - &serviceKey); - if(!NT_SUCCESS(status)) - { - // return the default value, which is the inverse of the registry setting default - // since this routine asks if it's disabled - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceIsMediaChangeDisabledForClass: Defaulting to %s\n", - (mcnRegistryValue ? "Enabled" : "Disabled"))); - return (BOOLEAN)(mcnRegistryValue == 0); - } - else - { - // Open the parameters key (if any) beneath the services key. - RtlInitUnicodeString(¶meterKeyName, L"Parameters"); - - status = WdfRegistryOpenKey(serviceKey, - ¶meterKeyName, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - ¶metersKey); - } - - if (!NT_SUCCESS(status)) - { - parametersKey = NULL; - } - - RtlInitUnicodeString(&valueName, L"Autorun"); - // ignore failures - status = WdfRegistryQueryULong(serviceKey, - &valueName, - &mcnRegistryValue); - - if (NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, - "DeviceIsMediaChangeDisabledForClass: <Service>/Autorun flag = %d\n", - mcnRegistryValue)); - } - - if (parametersKey != NULL) - { - status = WdfRegistryQueryULong(parametersKey, - &valueName, - &mcnRegistryValue); - - if (NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, - "DeviceIsMediaChangeDisabledForClass: <Service>/Parameters/Autorun flag = %d\n", - mcnRegistryValue)); - } - - WdfRegistryClose(parametersKey); - } - - WdfRegistryClose(serviceKey); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceIsMediaChangeDisabledForClass: Autoplay for device %p is %s\n", - DeviceExtension->DeviceObject, - (mcnRegistryValue ? "on" : "off") - )); - - // return if it is _disabled_, which is the - // inverse of the registry setting - - return (BOOLEAN)(!mcnRegistryValue); -} // end DeviceIsMediaChangeDisabledForClass() - - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceEnableMediaChangeDetection( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Inout_ PFILE_OBJECT_CONTEXT FileObjectContext, - _In_ BOOLEAN IgnorePreviousMediaChanges - ) -/*++ - -Routine Description: - - When the disable count decrease to 0, enable the MCN - -Arguments: - - DeviceExtension - the device context - - FileObjectContext - the file object context - - IgnorePreviousMediaChanges - ignore all previous media changes - -Return Value: - None. - ---*/ -{ - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - LONG oldCount; - - PAGED_CODE(); - - if (FileObjectContext) - { - InterlockedDecrement((PLONG)&(FileObjectContext->McnDisableCount)); - } - - if (info == NULL) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceEnableMediaChangeDetection: not initialized\n")); - return; - } - - (VOID) KeWaitForMutexObject(&info->MediaChangeMutex, - UserRequest, - KernelMode, - FALSE, - NULL); - - oldCount = --info->MediaChangeDetectionDisableCount; - - NT_ASSERT(oldCount >= 0); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, - "DeviceEnableMediaChangeDetection: Disable count reduced to %d - \n", - info->MediaChangeDetectionDisableCount)); - - if (oldCount == 0) - { - if (IgnorePreviousMediaChanges) - { - info->LastReportedMediaDetectionState = info->LastKnownMediaDetectionState; - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "MCN is enabled\n")); - } - else - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "MCD still disabled\n")); - } - - // Let something else run. - KeReleaseMutex(&info->MediaChangeMutex, FALSE); - - return; -} // end DeviceEnableMediaChangeDetection() - - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceDisableMediaChangeDetection( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Inout_ PFILE_OBJECT_CONTEXT FileObjectContext - ) -/*++ - -Routine Description: - - Increase the disable count. - -Arguments: - - DeviceExtension - the device context - - FileObjectContext - the file object context - -Return Value: - None. - ---*/ -{ - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - - PAGED_CODE(); - - if (FileObjectContext) - { - InterlockedIncrement((PLONG)&(FileObjectContext->McnDisableCount)); - } - - if (info == NULL) - { - return; - } - - (VOID) KeWaitForMutexObject(&info->MediaChangeMutex, - UserRequest, - KernelMode, - FALSE, - NULL); - - info->MediaChangeDetectionDisableCount++; - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, - "DisableMediaChangeDetection: disable count is %d\n", - info->MediaChangeDetectionDisableCount)); - - KeReleaseMutex(&info->MediaChangeMutex, FALSE); - - return; -} // end DeviceDisableMediaChangeDetection() - - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceReleaseMcnResources( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine will cleanup any resources allocated for MCN. It is called - by classpnp during remove device, and therefore is not typically required - by external drivers. - -Arguments: - - DeviceExtension - the device context - -Return Value: - None. - ---*/ -{ - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - - PAGED_CODE() - - if(info == NULL) - { - return; - } - - if (info->Gesn.Mdl) - { - PIRP irp = WdfRequestWdmGetIrp(info->MediaChangeRequest); - IoFreeMdl(info->Gesn.Mdl); - irp->MdlAddress = NULL; - } - IoFreeIrp(info->MediaChangeSyncIrp); - FREE_POOL(info->Gesn.Buffer); - FREE_POOL(info->SenseBuffer); - - if (info->DisplayStateCallbackHandle) - { - PoUnregisterPowerSettingCallback(info->DisplayStateCallbackHandle); - info->DisplayStateCallbackHandle = NULL; - } - - FREE_POOL(info); - - DeviceExtension->MediaChangeDetectionInfo = NULL; - - return; -} // end DeviceReleaseMcnResources() - - -IO_COMPLETION_ROUTINE RequestMcnSyncIrpCompletion; - -NTSTATUS -RequestMcnSyncIrpCompletion( - _In_ PDEVICE_OBJECT DeviceObject, - _In_ PIRP Irp, - _In_reads_opt_(_Inexpressible_("varies")) PVOID Context - ) -/*++ - -Routine Description: - - The MCN work finishes, reset the fields to allow another MCN request - be scheduled. - -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 = NULL; - PMEDIA_CHANGE_DETECTION_INFO info = NULL; - - if (Context == NULL) - { - // this will never happen, but code must be there to prevent OACR warnings. - return STATUS_MORE_PROCESSING_REQUIRED; - } - - DeviceExtension = (PCDROM_DEVICE_EXTENSION) Context; - info = DeviceExtension->MediaChangeDetectionInfo; - -#ifndef DEBUG - UNREFERENCED_PARAMETER(Irp); -#endif - UNREFERENCED_PARAMETER(DeviceObject); - - NT_ASSERT(Irp == info->MediaChangeSyncIrp); - - IoReuseIrp(info->MediaChangeSyncIrp, STATUS_NOT_SUPPORTED); - - // reset the value to let timer routine be able to send the next request. - InterlockedCompareExchange((PLONG)&(info->MediaChangeRequestInUse), 0, 1); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - - -VOID -RequestSetupMcnSyncIrp( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - setup the MCN synchronization irp. - -Arguments: - - DeviceExtension - the device context - -Return Value: - None - ---*/ -{ - PIRP irp = NULL; - PIO_STACK_LOCATION irpStack = NULL; - PIO_STACK_LOCATION nextIrpStack = NULL; - - irp = DeviceExtension->MediaChangeDetectionInfo->MediaChangeSyncIrp; - NT_ASSERT(irp != NULL); - - // - // For the driver that creates an IRP, there is no 'current' stack location. - // Step down one IRP stack location so that the extra top one - // becomes our 'current' one. - // - IoSetNextIrpStackLocation(irp); - - /* - * Cache our device object in the extra top IRP stack location - * so we have it in our completion routine. - */ - irpStack = IoGetCurrentIrpStackLocation(irp); - irpStack->DeviceObject = DeviceExtension->DeviceObject; - - // - // If the irp is sent down when the volume needs to be - // verified, CdRomUpdateGeometryCompletion won't complete - // it since it's not associated with a thread. Marking - // it to override the verify causes it always be sent - // to the port driver - // - nextIrpStack = IoGetNextIrpStackLocation(irp); - - SET_FLAG(nextIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME); - - nextIrpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; - // pick up this IOCTL code as it's not normaly seen for CD/DVD drive and does not require input. - // set other fields to make this IOCTL recognizable by CDROM.SYS - nextIrpStack->Parameters.Others.Argument1 = RequestSetupMcnSyncIrp; - nextIrpStack->Parameters.Others.Argument2 = RequestSetupMcnSyncIrp; - nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_MCN_SYNC_FAKE_IOCTL; //Argument3. - nextIrpStack->Parameters.Others.Argument4 = RequestSetupMcnSyncIrp; - - IoSetCompletionRoutine(irp, - RequestMcnSyncIrpCompletion, - DeviceExtension, - TRUE, - TRUE, - TRUE); - - return; -} - - -VOID -DeviceMainTimerTickHandler( - _In_ WDFTIMER Timer - ) -/*++ - -Routine Description: - - This routine setup a sync irp and send it to the serial queue. - Serial queue will process MCN when receive this sync irp. - -Arguments: - - Timer - the timer object that fires. - -Return Value: - None - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - size_t dataLength = 0; - - deviceExtension = WdfObjectGetTypedContext(WdfTimerGetParentObject(Timer), CDROM_DEVICE_EXTENSION); - - (void) RequestHandleEventNotification(deviceExtension, NULL, NULL, &dataLength); - - return; -} // end DeviceMainTimerTickHandler() - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceEnableMainTimer( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine will allocate timer related resources on the first time call. - Start the timer. - -Arguments: - - DeviceExtension - the device context - -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - if ((DeviceExtension->MediaChangeDetectionInfo == NULL) || - (DeviceExtension->MediaChangeDetectionInfo->AsynchronousNotificationSupported != FALSE)) - { - // Asynchronous Notification is enabled, timer not needed. - return status; - } - - if (DeviceExtension->MainTimer == NULL) - { - //create main timer object. - WDF_TIMER_CONFIG timerConfig; - WDF_OBJECT_ATTRIBUTES timerAttributes; - - WDF_TIMER_CONFIG_INIT(&timerConfig, DeviceMainTimerTickHandler); - - // 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. - if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_MSFT_VIRTUAL_ODD)) - { - timerConfig.Period = 2000; // 2 seconds, in milliseconds. - } - else - { - timerConfig.Period = 1000; // 1 second, in milliseconds. - } - - timerConfig.TolerableDelay = 500; // 0.5 seconds, in milliseconds - - //Set the autoSerialization to FALSE, as the parent device's - //execute level is WdfExecutionLevelPassive. - timerConfig.AutomaticSerialization = FALSE; - - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = DeviceExtension->Device; - timerAttributes.ExecutionLevel = WdfExecutionLevelInheritFromParent; - - status = WdfTimerCreate(&timerConfig, - &timerAttributes, - &DeviceExtension->MainTimer); - } - - if (NT_SUCCESS(status)) - { - WdfTimerStart(DeviceExtension->MainTimer,WDF_REL_TIMEOUT_IN_MS(100)); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceEnableMainTimer: Once a second timer enabled for WDFDEVICE %p\n", - DeviceExtension->Device)); - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceEnableMainTimer: WDFDEVICE %p, Status %lx initializing timer\n", - DeviceExtension->Device, status)); - } - - return status; -} // end DeviceEnableMainTimer() - - -_IRQL_requires_max_(PASSIVE_LEVEL) -VOID -DeviceDisableMainTimer( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - stop the timer. - -Arguments: - - DeviceExtension - device context - -Return Value: - None - ---*/ -{ - PAGED_CODE(); - - if ((DeviceExtension->MediaChangeDetectionInfo == NULL) || - (DeviceExtension->MediaChangeDetectionInfo->AsynchronousNotificationSupported != FALSE)) - { - // Asynchronous Notification is enabled, timer not needed. - return; - } - - if (DeviceExtension->MainTimer != NULL) - { - // - // we are only going to stop the actual timer in remove device routine. - // it is the responsibility of the code within the timer routine to - // check if the device is removed and not processing io for the final - // call. - // this keeps the code clean and prevents lots of bugs. - // - WdfTimerStop(DeviceExtension->MainTimer,TRUE); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "DeviceDisableMainTimer: Once a second timer disabled for device %p\n", - DeviceExtension->Device)); - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "DeviceDisableMainTimer: Timer never enabled\n")); - } - - return; -} // end DeviceDisableMainTimer() - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleMcnControl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - This routine handles the process of IOCTL_STORAGE_MCN_CONTROL - -Arguments: - - DeviceExtension - device context - - Request - request object - - RequestParameters - request parameters - - DataLength - data transferred - -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDFFILEOBJECT fileObject = NULL; - PFILE_OBJECT_CONTEXT fileObjectContext = NULL; - PPREVENT_MEDIA_REMOVAL mediaRemoval = NULL; - - PAGED_CODE(); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(PREVENT_MEDIA_REMOVAL), - &mediaRemoval, - NULL); - - if (NT_SUCCESS(status)) - { - fileObject = WdfRequestGetFileObject(Request); - - // Check to make sure we have a file object extension to keep track of this - // request. If not we'll fail it before synchronizing. - if (fileObject != NULL) - { - fileObjectContext = FileObjectGetContext(fileObject); - } - - if ((fileObjectContext == NULL) && - (WdfRequestGetRequestorMode(Request) == KernelMode)) - { - fileObjectContext = &DeviceExtension->KernelModeMcnContext; - } - - if (fileObjectContext == NULL) - { - // This handle isn't setup correctly. We can't let the - // operation go. - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - if (mediaRemoval->PreventMediaRemoval) - { - // This is a lock command. Reissue the command in case bus or - // device was reset and the lock was cleared. - DeviceDisableMediaChangeDetection(DeviceExtension, fileObjectContext); - } - else - { - if (fileObjectContext->McnDisableCount == 0) - { - status = STATUS_INVALID_DEVICE_STATE; - } - else - { - DeviceEnableMediaChangeDetection(DeviceExtension, fileObjectContext, TRUE); - } - } - } - - return status; -} // end RequestHandleMcnControl() - -#pragma warning(pop) // un-sets any local warning changes - diff --git a/storage/class/cdrom/src/cdrom.c b/storage/class/cdrom/src/cdrom.c deleted file mode 100644 index fccf4a0e..00000000 --- a/storage/class/cdrom/src/cdrom.c +++ /dev/null @@ -1,4225 +0,0 @@ -/*-- - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - cdrom.c - -Abstract: - - The CDROM class driver tranlates IRPs to SRBs with embedded CDBs - and sends them to its devices through the port driver. - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - -// this definition is used to link _StorDebugPrint() function. -#define DEBUG_MAIN_SOURCE 1 - - -#include "ntddk.h" -#include "ntstrsafe.h" - -#include "ntddstor.h" -#include "ntddtape.h" -#include "wdfcore.h" -#include "devpkey.h" - -#include "cdrom.h" -#include "ioctl.h" -#include "mmc.h" -#include "scratch.h" - - -#ifdef DEBUG_USE_WPP -#include "cdrom.tmh" -#endif - -BOOLEAN -BootEnvironmentIsWinPE( - VOID - ); - -#ifdef ALLOC_PRAGMA - -#pragma alloc_text(INIT, DriverEntry) -#pragma alloc_text(INIT, BootEnvironmentIsWinPE) - -#pragma alloc_text(PAGE, DriverEvtCleanup) -#pragma alloc_text(PAGE, DriverEvtDeviceAdd) -#pragma alloc_text(PAGE, DeviceEvtCleanup) -#pragma alloc_text(PAGE, DeviceEvtSelfManagedIoCleanup) -#pragma alloc_text(PAGE, DeviceEvtD0Exit) -#pragma alloc_text(PAGE, CreateQueueEvtIoDefault) -#pragma alloc_text(PAGE, DeviceEvtFileClose) -#pragma alloc_text(PAGE, DeviceCleanupProtectedLocks) -#pragma alloc_text(PAGE, DeviceCleanupDisableMcn) -#pragma alloc_text(PAGE, RequestProcessSerializedIoctl) -#pragma alloc_text(PAGE, ReadWriteWorkItemRoutine) -#pragma alloc_text(PAGE, IoctlWorkItemRoutine) -#pragma alloc_text(PAGE, DeviceEvtSurpriseRemoval) - -#endif - -NTSTATUS -DriverEntry( - _In_ PDRIVER_OBJECT DriverObject, - _In_ PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - - Installable driver initialization entry point. - This entry point is called directly by the I/O system. - -Arguments: - - DriverObject - pointer to the driver object - - RegistryPath - pointer to a unicode string representing the path, - to driver-specific key in the registry. - -Return Value: - - STATUS_SUCCESS if successful, - STATUS_UNSUCCESSFUL otherwise. - ---*/ -{ - NTSTATUS status; - WDF_DRIVER_CONFIG config; - WDF_OBJECT_ATTRIBUTES attributes; - WDFDRIVER driverObject = NULL; - - PAGED_CODE(); - - // Initialize WPP Tracing - WPP_INIT_TRACING(DriverObject, RegistryPath); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "CDROM.SYS DriverObject %p loading\n", - DriverObject)); - - // Register DeviceAdd and DriverEvtCleanup callback. - // WPP_CLEANUP will be called in DriverEvtCleanup - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CDROM_DRIVER_EXTENSION); - attributes.EvtCleanupCallback = DriverEvtCleanup; - - WDF_DRIVER_CONFIG_INIT(&config, DriverEvtDeviceAdd); - - status = WdfDriverCreate(DriverObject, - RegistryPath, - &attributes, - &config, - &driverObject); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT, - "WdfDriverCreate failed. %x\n", - status)); - - // Cleanup tracing here because DriverUnload will not be called - // as we have failed to create WDFDRIVER object itself. - WPP_CLEANUP(DriverObject); - - } - else - { - PCDROM_DRIVER_EXTENSION driverExtension = DriverGetExtension(driverObject); - - // Copy the registry path into the driver extension so we can use it later - driverExtension->Version = 0x01; - driverExtension->DriverObject = DriverObject; - - if (BootEnvironmentIsWinPE()) { - - SET_FLAG(driverExtension->Flags, CDROM_FLAG_WINPE_MODE); - } - - } - - return status; -} - - -BOOLEAN -BootEnvironmentIsWinPE( - VOID - ) -/*++ - -Routine Description: - - This routine determines if the boot enviroment is WinPE - -Arguments: - - None - -Return Value: - - BOOLEAN - TRUE if the environment is WinPE; FALSE otherwise - ---*/ -{ - NTSTATUS status; - WDFKEY registryKey = NULL; - - DECLARE_CONST_UNICODE_STRING(registryKeyName, WINPE_REG_KEY_NAME); - - PAGED_CODE(); - - status = WdfRegistryOpenKey(NULL, - ®istryKeyName, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - ®istryKey); - - if (!NT_SUCCESS(status)) - { - return FALSE; - } - - WdfRegistryClose(registryKey); - return TRUE; -} // end BootEnvironmentIsWinPE() - - -VOID -DriverEvtCleanup( - _In_ WDFOBJECT Driver - ) -/*++ -Routine Description: - - Free all the resources allocated in DriverEntry. - -Arguments: - - Driver - handle to a WDF Driver object. - -Return Value: - - VOID. - ---*/ -{ - WDFDRIVER driver = (WDFDRIVER)Driver; - - PAGED_CODE (); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "CDROM.SYS DriverObject %p cleanup. Will be unloaded soon\n", - driver)); - - // Stop WPP Tracing - WPP_CLEANUP( WdfDriverWdmGetDriverObject(driver) ); - - - return; -} - - -NTSTATUS -DriverEvtDeviceAdd( - _In_ WDFDRIVER Driver, - _Inout_ PWDFDEVICE_INIT DeviceInit - ) -/*++ - -Routine Description: - - EvtDeviceAdd is called by the framework in response to AddDevice - call from the PnP manager. - - -Arguments: - - Driver - Handle to a framework driver object created in DriverEntry - - DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DRIVER_EXTENSION driverExtension = NULL; - WDFDEVICE device = NULL; - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - BOOLEAN deviceClaimed = FALSE; - - WDF_OBJECT_ATTRIBUTES attributes; - WDF_FILEOBJECT_CONFIG fileObjectConfig; - WDF_IO_TARGET_OPEN_PARAMS ioTargetOpenParams; - WDF_IO_QUEUE_CONFIG queueConfig; - WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; - WDF_REMOVE_LOCK_OPTIONS removeLockOptions; - PWCHAR wideDeviceName = NULL; - UNICODE_STRING unicodeDeviceName; - PDEVICE_OBJECT lowerPdo = NULL; - ULONG deviceNumber = 0; - ULONG devicePropertySessionId = INVALID_SESSION; - ULONG devicePropertySize = 0; - DEVPROPTYPE devicePropertyType = DEVPROP_TYPE_EMPTY; - - PAGED_CODE(); - - driverExtension = DriverGetExtension(Driver); - - // 0. Initialize the objects that we're going to use - RtlInitUnicodeString(&unicodeDeviceName, NULL); - - // 1. Register PnP&Power callbacks for any we are interested in. - // If a callback isn't set, Framework will take the default action by itself. - { - // Zero out the PnpPowerCallbacks structure. - WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); - - // Use this callback to init resources that are used by the device and only needs to be called once. - pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = DeviceEvtSelfManagedIoInit; - - // Use this callback to prepare device for coming back from a lower power mode to D0. - pnpPowerCallbacks.EvtDeviceD0Entry = DeviceEvtD0Entry; - - // Use this callback to prepare device for entering into a lower power mode. - pnpPowerCallbacks.EvtDeviceD0Exit = DeviceEvtD0Exit; - - // Use this callback to free any resources used by device and will be called when the device is - // powered down. - pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup = DeviceEvtSelfManagedIoCleanup; - - pnpPowerCallbacks.EvtDeviceSurpriseRemoval = DeviceEvtSurpriseRemoval; - - // Register the PnP and power callbacks. - WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); - } - - // 2. Register the EvtIoInCallerContext to deal with IOCTLs that need to stay in original context. - WdfDeviceInitSetIoInCallerContextCallback(DeviceInit, - DeviceEvtIoInCallerContext); - - // 3. Register PreprocessCallback for IRP_MJ_POWER, IRP_MJ_FLUSH_BUFFERS and IRP_MJ_SHUTDOWN - { - UCHAR minorFunctions[1]; - - minorFunctions[0] = IRP_MN_SET_POWER; - - status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit, - RequestProcessSetPower, - IRP_MJ_POWER, - minorFunctions, - RTL_NUMBER_OF(minorFunctions)); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_POWER failed, " - "status: 0x%X\n", status)); - - goto Exit; - } - - status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit, - RequestProcessShutdownFlush, - IRP_MJ_FLUSH_BUFFERS, - NULL, - 0); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_FLUSH_BUFFERS failed, " - "status: 0x%X\n", status)); - - goto Exit; - } - - status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit, - RequestProcessShutdownFlush, - IRP_MJ_SHUTDOWN, - NULL, - 0); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_SHUTDOWN failed, " - "status: 0x%X\n", status)); - - goto Exit; - } - } - - // 4. Set attributes to create Request Context area. - { - //Reuse this structure. - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - attributes.EvtCleanupCallback = RequestEvtCleanup; - - WdfDeviceInitSetRequestAttributes(DeviceInit, - &attributes); - } - - // 5. Register FileObject related callbacks - { - // Add FILE_OBJECT_EXTENSION as the context to the file object. - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FILE_OBJECT_CONTEXT); - - // Set Entry points for Create and Close.. - - // The framework doesn't sync the file create requests with pnp/power - // state. Re-direct all the file create requests to a dedicated - // queue, which will be purged manually during removal. - WDF_FILEOBJECT_CONFIG_INIT(&fileObjectConfig, - NULL, //CreateQueueEvtIoDefault, - DeviceEvtFileClose, - WDF_NO_EVENT_CALLBACK); // No callback for Cleanup - - fileObjectConfig.FileObjectClass = WdfFileObjectWdfCannotUseFsContexts; - - // Since we are registering file events and fowarding create request - // ourself, we must also set AutoForwardCleanupClose so that cleanup - // and close can also get forwarded. - fileObjectConfig.AutoForwardCleanupClose = WdfTrue; - attributes.SynchronizationScope = WdfSynchronizationScopeNone; - attributes.ExecutionLevel = WdfExecutionLevelPassive; - - // Indicate that file object is optional. - fileObjectConfig.FileObjectClass |= WdfFileObjectCanBeOptional; - - WdfDeviceInitSetFileObjectConfig(DeviceInit, - &fileObjectConfig, - &attributes); - } - - // 6. Initialize device-wide attributes - { - // Declare ourselves as NOT owning power policy. - // The power policy owner in storage stack is port driver. - WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE); - - // Set other DeviceInit attributes. - WdfDeviceInitSetExclusive(DeviceInit, FALSE); - WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CD_ROM); - WdfDeviceInitSetCharacteristics(DeviceInit, FILE_REMOVABLE_MEDIA, FALSE); - WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); - WdfDeviceInitSetPowerPageable(DeviceInit); - - // We require the framework to acquire a remove lock before delivering all IRP types - WDF_REMOVE_LOCK_OPTIONS_INIT(&removeLockOptions, - WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO); - - WdfDeviceInitSetRemoveLockOptions(DeviceInit, &removeLockOptions); - - // save the PDO for later reference - lowerPdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit); - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_DEVICE_EXTENSION); - - // We have a parallel queue, so WdfSynchronizationScopeNone is our only choice. - attributes.SynchronizationScope = WdfSynchronizationScopeNone; - attributes.ExecutionLevel = WdfExecutionLevelDispatch; - - // Provide a cleanup callback which will release memory allocated with ExAllocatePool* - attributes.EvtCleanupCallback = DeviceEvtCleanup; - } - - // 7. Now, the device can be created. - { - wideDeviceName = ExAllocatePool2(POOL_FLAG_NON_PAGED, - 64 * sizeof(WCHAR), - CDROM_TAG_STRINGS); - - if (wideDeviceName == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - goto Exit; - } - - // Find the lowest device number currently available. - do { - status = RtlStringCchPrintfW((NTSTRSAFE_PWSTR)wideDeviceName, - 64, - L"\\Device\\CdRom%d", - deviceNumber); - - if (!NT_SUCCESS(status)) { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: Format device name failed with error: 0x%X\n", status)); - - goto Exit; - } - - RtlInitUnicodeString(&unicodeDeviceName, wideDeviceName); - - status = WdfDeviceInitAssignName(DeviceInit, &unicodeDeviceName); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: WdfDeviceInitAssignName() failed with error: 0x%X\n", status)); - - goto Exit; - } - - status = WdfDeviceCreate(&DeviceInit, &attributes, &device); - - deviceNumber++; - - } while (status == STATUS_OBJECT_NAME_COLLISION); - - // When this loop exits the count is inflated by one - fix that. - deviceNumber--; - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: Can not create a new device, status: 0x%X\n", - status)); - - goto Exit; - } - } - - // 8. Fill up basic Device Extension settings and create a remote I/O target for the next-lower driver. - // The reason why we do not use the local I/O target is because we want to be able to close the - // I/O target on surprise removal. - { - deviceExtension = DeviceGetExtension(device); - - deviceExtension->Version = 0x01; - deviceExtension->Size = sizeof(CDROM_DEVICE_EXTENSION); - - deviceExtension->DeviceObject = WdfDeviceWdmGetDeviceObject(device); - deviceExtension->Device = device; - deviceExtension->DriverExtension = driverExtension; - - deviceExtension->LowerPdo = lowerPdo; - - deviceExtension->DeviceType = FILE_DEVICE_CD_ROM; //Always a FILE_DEVICE_CD_ROM for all device it manages. - deviceExtension->DeviceName = unicodeDeviceName; - - deviceExtension->DeviceNumber = deviceNumber; - } - { - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = deviceExtension->Device; - - status = WdfIoTargetCreate(deviceExtension->Device, - &attributes, - &deviceExtension->IoTarget); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: Can not create a remote I/O target object, status: 0x%X\n", - status)); - goto Exit; - } - - WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(&ioTargetOpenParams, - WdfDeviceWdmGetAttachedDevice(deviceExtension->Device)); - - status = WdfIoTargetOpen(deviceExtension->IoTarget, - &ioTargetOpenParams); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: Can not open a remote I/O target for the next-lower device, status: 0x%X\n", - status)); - - WdfObjectDelete(deviceExtension->IoTarget); - deviceExtension->IoTarget = NULL; - - goto Exit; - } - } - - // 9. Claim the device, so that port driver will only accept the commands from CDROM.SYS for this device. - // NOTE: The I/O should be issued after the device is started. But we would like to claim - // the device as soon as possible, so this legacy behavior is kept. - status = DeviceClaimRelease(deviceExtension, FALSE); - - if (!NT_SUCCESS(status)) - { - // Someone already had this device - we're in trouble - goto Exit; - } - else - { - deviceClaimed = TRUE; - } - - // - // CDROM Queueing Structure - // - // a. EvtIoInCallerContext (prior to queueing): - // This event will be used ONLY to forward down IOCTLs that come in at PASSIVE LEVEL - // and need to be forwarded down the stack in the original context. - // - // b. Main input queue: serial queue for main dispatching - // This queue will be used to do all dispatching of requests to serialize - // access to the device. Any request that was previously completed in - // the Dispatch routines will be completed here. Anything requiring device - // I/O will be sent through the serial I/O queue. - // - // 10. Set up IO queues after device being created. - // - { - WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, - WdfIoQueueDispatchSequential); - - queueConfig.PowerManaged = WdfFalse; - -#pragma prefast(push) -#pragma prefast(disable: 28155, "a joint handler for read/write cannot be EVT_WDF_IO_QUEUE_IO_READ and EVT_WDF_IO_QUEUE_IO_WRITE simultaneously") -#pragma prefast(disable: 28023, "a joint handler for read/write cannot be EVT_WDF_IO_QUEUE_IO_READ and EVT_WDF_IO_QUEUE_IO_WRITE simultaneously") - queueConfig.EvtIoRead = SequentialQueueEvtIoReadWrite; - queueConfig.EvtIoWrite = SequentialQueueEvtIoReadWrite; -#pragma prefast(pop) - - queueConfig.EvtIoDeviceControl = SequentialQueueEvtIoDeviceControl; - queueConfig.EvtIoCanceledOnQueue = SequentialQueueEvtCanceledOnQueue; - - status = WdfIoQueueCreate(device, - &queueConfig, - WDF_NO_OBJECT_ATTRIBUTES, - &(deviceExtension->SerialIOQueue)); - if (!NT_SUCCESS(status)) - { - goto Exit; - } - - // this queue is dedicated for file create requests. - WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); - - queueConfig.PowerManaged = WdfFalse; - queueConfig.EvtIoDefault = CreateQueueEvtIoDefault; - - //Reuse this structure. - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - - attributes.SynchronizationScope = WdfSynchronizationScopeNone; - attributes.ExecutionLevel = WdfExecutionLevelPassive; - - status = WdfIoQueueCreate(device, - &queueConfig, - &attributes, - &(deviceExtension->CreateQueue)); - - if (!NT_SUCCESS(status)) - { - goto Exit; - } - - // Configure the device to use driver created queue for dispatching create. - status = WdfDeviceConfigureRequestDispatching(device, - deviceExtension->CreateQueue, - WdfRequestTypeCreate); - - if (!NT_SUCCESS(status)) - { - goto Exit; - } - } - - // 11. Set the alignment requirements for the device based on the host adapter requirements. - // - // NOTE: this should have been set when device is attached on device stack, - // by keeping this legacy code, we could avoid issue that this value was not correctly set at that time. - if (deviceExtension->LowerPdo->AlignmentRequirement > deviceExtension->DeviceObject->AlignmentRequirement) - { - WdfDeviceSetAlignmentRequirement(deviceExtension->Device, - deviceExtension->LowerPdo->AlignmentRequirement); - } - - // 12. Initialization of miscellaneous internal properties - - // CDROMs are not partitionable so starting offset is 0. - deviceExtension->StartingOffset.LowPart = 0; - deviceExtension->StartingOffset.HighPart = 0; - - // Set the default geometry for the cdrom to match what NT 4 used. - // these values will be used to compute the cylinder count rather - // than using it's NT 5.0 defaults. - deviceExtension->DiskGeometry.MediaType = RemovableMedia; - deviceExtension->DiskGeometry.TracksPerCylinder = 0x40; - deviceExtension->DiskGeometry.SectorsPerTrack = 0x20; - - deviceExtension->DeviceAdditionalData.ReadWriteRetryDelay100nsUnits = WRITE_RETRY_DELAY_DVD_1x; - - // Clear the SrbFlags and disable synchronous transfers - deviceExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // Set timeout value in seconds. - deviceExtension->TimeOutValue = DeviceGetTimeOutValueFromRegistry(); - if ((deviceExtension->TimeOutValue > 30 * 60) || // longer than 30 minutes - (deviceExtension->TimeOutValue == 0)) - { - deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT; - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DriverEvtDeviceAdd: device timeout is set to %x seconds", - deviceExtension->TimeOutValue - )); - -#if (NTDDI_VERSION >= NTDDI_WIN8) - deviceExtension->IsVolumeOnlinePending = TRUE; - - WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); - - queueConfig.PowerManaged = WdfFalse; - - status = WdfIoQueueCreate(device, - &queueConfig, - WDF_NO_OBJECT_ATTRIBUTES, - &deviceExtension->ManualVolumeReadyQueue); - - if (!NT_SUCCESS(status)) - { - goto Exit; - } -#endif - - // 13. Initialize the stuff related to media locking - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = deviceExtension->Device; - status = WdfWaitLockCreate(&attributes, - &deviceExtension->EjectSynchronizationLock); - - deviceExtension->LockCount = 0; - - // 14. Initialize context structures needed for asynchronous release queue and power requests - - if (NT_SUCCESS(status)) - { - status = DeviceInitReleaseQueueContext(deviceExtension); - } - - if (NT_SUCCESS(status)) - { - status = DeviceInitPowerContext(deviceExtension); - } - - // 15. Create external access points other than device name. - if (NT_SUCCESS(status)) - { - status = DeviceCreateWellKnownName(deviceExtension); - } - - // 16. Query session id from the PDO. - if (NT_SUCCESS(status)) - { - status = IoGetDevicePropertyData(deviceExtension->LowerPdo, - &DEVPKEY_Device_SessionId, - 0, - 0, - sizeof(devicePropertySessionId), - &devicePropertySessionId, - &devicePropertySize, - &devicePropertyType); - - if (!NT_SUCCESS(status)) - { - // The device is global. - devicePropertySessionId = INVALID_SESSION; - status = STATUS_SUCCESS; - } - } - - // 17. Register interfaces for this device. - if (NT_SUCCESS(status)) - { - status = DeviceRegisterInterface(deviceExtension, CdRomDeviceInterface); - } - - if (NT_SUCCESS(status)) - { - // If this is a per-session DO, don't register for mount interface so that - // mountmgr will not automatically assign a drive letter. - if (devicePropertySessionId == INVALID_SESSION) - { - status = DeviceRegisterInterface(deviceExtension, MountedDeviceInterface); - } - } - - // 18. Initialize the shutdown/flush lock - if (NT_SUCCESS(status)) - { - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = deviceExtension->Device; - - status = WdfWaitLockCreate(&attributes, &deviceExtension->ShutdownFlushWaitLock); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DriverEvtDeviceAdd: Cannot create shutdown/flush waitlock, status: 0x%X\n", - status)); - } - } - - // 19. Initialize the work item that is used to initiate asynchronous reads/writes - if (NT_SUCCESS(status)) - { - WDF_WORKITEM_CONFIG workItemConfig; - WDF_OBJECT_ATTRIBUTES workItemAttributes; - - WDF_WORKITEM_CONFIG_INIT(&workItemConfig, - ReadWriteWorkItemRoutine - ); - - WDF_OBJECT_ATTRIBUTES_INIT(&workItemAttributes); - workItemAttributes.ParentObject = deviceExtension->Device; - - status = WdfWorkItemCreate(&workItemConfig, - &workItemAttributes, - &deviceExtension->ReadWriteWorkItem - ); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT, - "DriverEvtDeviceAdd: Cannot create read/write work item, status: 0x%X\n", - status)); - } - } - - // 20. Initialize the work item that is used to process most IOCTLs at PASSIVE_LEVEL. - if (NT_SUCCESS(status)) - { - WDF_WORKITEM_CONFIG workItemConfig; - WDF_OBJECT_ATTRIBUTES workItemAttributes; - - WDF_WORKITEM_CONFIG_INIT(&workItemConfig, - IoctlWorkItemRoutine - ); - - WDF_OBJECT_ATTRIBUTES_INIT(&workItemAttributes); - workItemAttributes.ParentObject = deviceExtension->Device; - - status = WdfWorkItemCreate(&workItemConfig, - &workItemAttributes, - &deviceExtension->IoctlWorkItem - ); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT, - "DriverEvtDeviceAdd: Cannot create ioctl work item, status: 0x%X\n", - status)); - } - } - - -Exit: - - if (!NT_SUCCESS(status)) - { - FREE_POOL(wideDeviceName); - - if (deviceExtension != NULL) - { - RtlInitUnicodeString(&deviceExtension->DeviceName, NULL); - } - - // Release the device with the port driver, if it was claimed - if ((deviceExtension != NULL) && deviceClaimed) - { - DeviceClaimRelease(deviceExtension, TRUE); - } - deviceClaimed = FALSE; - } - - return status; -} - - -VOID -DeviceEvtCleanup( - _In_ WDFOBJECT Device - ) -/*++ -Routine Description: - - Free all the resources allocated in DriverEvtDeviceAdd. - -Arguments: - - Device - handle to a WDF Device object. - -Return Value: - - VOID. - ---*/ -{ - WDFDEVICE device = (WDFDEVICE)Device; - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - - PAGED_CODE (); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "WDFDEVICE %p cleanup: The device is about to be destroyed.\n", - device)); - - deviceExtension = DeviceGetExtension(device); - - FREE_POOL(deviceExtension->DeviceName.Buffer); - RtlInitUnicodeString(&deviceExtension->DeviceName, NULL); - - if (deviceExtension->DeviceAdditionalData.WellKnownName.Buffer != NULL) - { - IoDeleteSymbolicLink(&deviceExtension->DeviceAdditionalData.WellKnownName); - } - - FREE_POOL(deviceExtension->DeviceAdditionalData.WellKnownName.Buffer); - RtlInitUnicodeString(&deviceExtension->DeviceAdditionalData.WellKnownName, NULL); - - return; -} - - -VOID -DeviceEvtSelfManagedIoCleanup( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - this function is called when the device is removed. - release the ownership of the device, release allocated resources. - -Arguments: - - Device - Handle to device object - -Return Value: - - None. - ---*/ -{ - NTSTATUS status; - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - - PAGED_CODE (); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, - "DeviceEvtSelfManagedIoCleanup: WDFDEVICE %p is being stopped.\n", - Device)); - - // extract the device and driver extensions - deviceExtension = DeviceGetExtension(Device); - - // Purge unprocessed requests, stop the IO queues. - // Incoming request will be completed with STATUS_INVALID_DEVICE_STATE status. - WdfIoQueuePurge(deviceExtension->SerialIOQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); - WdfIoQueuePurge(deviceExtension->CreateQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); - - // Close the IoTarget so that we are sure there are no outstanding I/Os in the stack. - if (deviceExtension->IoTarget) - { - WdfIoTargetClose(deviceExtension->IoTarget); - } - - // Release the device - if (!deviceExtension->SurpriseRemoved) - { - status = DeviceClaimRelease(deviceExtension, TRUE); //status is mainly for debugging. we don't really care. - UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning. - } - - // Be sure to flush the DPCs as the READ/WRITE timer routine may still be running - // during device removal. This call may take a while to complete. - KeFlushQueuedDpcs(); - - // Release all the memory that we have allocated. - - DeviceDeallocateMmcResources(Device); - ScratchBuffer_Deallocate(deviceExtension); - RtlZeroMemory(&(deviceExtension->DeviceAdditionalData.Mmc), sizeof(CDROM_MMC_EXTENSION)); - - FREE_POOL(deviceExtension->DeviceDescriptor); - FREE_POOL(deviceExtension->AdapterDescriptor); - FREE_POOL(deviceExtension->PowerDescriptor); - FREE_POOL(deviceExtension->SenseData); - - if (deviceExtension->DeviceAdditionalData.CachedInquiryData != NULL) - { - FREE_POOL(deviceExtension->DeviceAdditionalData.CachedInquiryData); - deviceExtension->DeviceAdditionalData.CachedInquiryDataByteCount = 0; - } - - FREE_POOL(deviceExtension->PrivateFdoData); - - DeviceReleaseMcnResources(deviceExtension); - - DeviceReleaseZPODDResources(deviceExtension); - - // Keep the system-wide CDROM count accurate, as programs use this info to - // know when they have found all the cdroms in a system. - IoGetConfigurationInformation()->CdRomCount--; - - deviceExtension->PartitionLength.QuadPart = 0; - - // All WDF objects related to Device will be automatically released - // when the root object is deleted. No need to release them manually. - - return; -} - -NTSTATUS -DeviceEvtD0Entry( - _In_ WDFDEVICE Device, - _In_ WDF_POWER_DEVICE_STATE PreviousState - ) -/*++ - -Routine Description: - - This function is called when the device is coming back from a lower power state to D0. - This function cannot be placed in a pageable section. - -Arguments: - - Device - Handle to device object - PreviousState - Power state the device was in. - -Return Value: - - NTSTATUS: alway STATUS_SUCCESS - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension; - NTSTATUS status = STATUS_SUCCESS; - PZERO_POWER_ODD_INFO zpoddInfo = NULL; - STORAGE_IDLE_POWERUP_REASON powerupReason = {0}; - - UNREFERENCED_PARAMETER(PreviousState); - deviceExtension = DeviceGetExtension(Device); - - // Make certain not to do anything before properly initialized - if (deviceExtension->IsInitialized) - { - zpoddInfo = deviceExtension->ZeroPowerODDInfo; - - if (zpoddInfo != NULL) - { - if (zpoddInfo->InZeroPowerState != FALSE) - { - // We just woke up from Zero Power state - zpoddInfo->InZeroPowerState = FALSE; - zpoddInfo->RetryFirstCommand = TRUE; - zpoddInfo->BecomingReadyRetryCount = BECOMING_READY_RETRY_COUNT; - - status = DeviceZPODDGetPowerupReason(deviceExtension, &powerupReason); - - if (NT_SUCCESS(status) && - (powerupReason.PowerupReason == StoragePowerupDeviceAttention)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "DeviceEvtD0Entry: Device has left zero power state due to eject button pressed\n" - )); - - // This wake-up is caused by user pressing the eject button. - // In case of drawer type, we need to soft eject the tray to emulate the effect. - // Note that the first command to the device after power resumed will - // be terminated with CHECK CONDITION status with sense code 6/29/00, - // but we already have a retry logic to handle this. - if ((zpoddInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) && (zpoddInfo->Load == 0)) // Drawer - { - DeviceSendIoctlAsynchronously(deviceExtension, IOCTL_STORAGE_EJECT_MEDIA, deviceExtension->DeviceObject); - } - } - else - { - // This wake-up is caused by non-cached CDB received or a 3rd-party driver - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "DeviceEvtD0Entry: Device has left zero power state due to IO received\n" - )); - - } - } - } - - DeviceEnableMainTimer(deviceExtension); - } - - return STATUS_SUCCESS; -} - -NTSTATUS -DeviceEvtD0Exit( - _In_ WDFDEVICE Device, - _In_ WDF_POWER_DEVICE_STATE TargetState - ) -/*++ - -Routine Description: - - This function is called when the device is entering lower powe state from D0 or it's removed. - We only care about the case of device entering D3. - The purpose of this function is to send SYNC CACHE command and STOP UNIT command if it's necessary. - -Arguments: - - Device - Handle to device object - TargetState - Power state the device is entering. - -Return Value: - - NTSTATUS: alway STATUS_SUCCESS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - PZERO_POWER_ODD_INFO zpoddInfo = NULL; - - PAGED_CODE (); - - deviceExtension = DeviceGetExtension(Device); - zpoddInfo = deviceExtension->ZeroPowerODDInfo; - - // we only process the situation that the device is going into D3. - if ((TargetState != WdfPowerDeviceD3) && - (TargetState != WdfPowerDeviceD3Final)) - { - return STATUS_SUCCESS; - } - - // Stop the main timer - DeviceDisableMainTimer(deviceExtension); - - // note: do not stop CreateQueue as the create request can be handled by port driver even the device is in D3 status. - - // If initialization was not finished or the device was removed, we cannot interact - // with it device, so we have to exit - if ((!deviceExtension->IsInitialized) || deviceExtension->SurpriseRemoved) - { - return STATUS_SUCCESS; - } - - -#ifdef DBG - #if (WINVER >= 0x0601) - // this API is introduced in Windows7 - { - ULONG secondsRemaining = 0; - BOOLEAN watchdogTimeSupported = FALSE; - - watchdogTimeSupported = PoQueryWatchdogTime(deviceExtension->LowerPdo, &secondsRemaining); - UNREFERENCED_PARAMETER(watchdogTimeSupported); - } - #endif -#endif - - deviceExtension->PowerDownInProgress = TRUE; - - status = PowerContextBeginUse(deviceExtension); - - deviceExtension->PowerContext.Options.PowerDown = TRUE; - - // Step 1. LOCK QUEUE - if (NT_SUCCESS(status) && - (TargetState != WdfPowerDeviceD3Final)) - { - status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL); - - if (NT_SUCCESS(status)) - { - deviceExtension->PowerContext.Options.LockQueue = TRUE; - } - - // Ignore failure. - status = STATUS_SUCCESS; - } - - deviceExtension->PowerContext.PowerChangeState.PowerDown++; - - // Step 2. QUIESCE QUEUE - if (NT_SUCCESS(status) && - (TargetState != WdfPowerDeviceD3Final)) - { - status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL); - UNREFERENCED_PARAMETER(status); - // We don't care about the status. - status = STATUS_SUCCESS; - } - - deviceExtension->PowerContext.PowerChangeState.PowerDown++; - - // Step 3. SYNC CACHE command should be sent to drive if the media is currently writable. - if (NT_SUCCESS(status) && - deviceExtension->DeviceAdditionalData.Mmc.WriteAllowed) - { - status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL); - UNREFERENCED_PARAMETER(status); - status = STATUS_SUCCESS; - } - - deviceExtension->PowerContext.PowerChangeState.PowerDown++; - - // Step 4. STOP UNIT - if (NT_SUCCESS(status) && - !TEST_FLAG(deviceExtension->ScanForSpecialFlags, CDROM_SPECIAL_DISABLE_SPIN_DOWN)) - { - status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL); - UNREFERENCED_PARAMETER(status); - status = STATUS_SUCCESS; - } - - if (TargetState == WdfPowerDeviceD3Final) - { - // We're done with the power context. - PowerContextEndUse(deviceExtension); - } - - // Bumping the media change count will force the file system to verify the volume when we resume - SET_FLAG(deviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME); - InterlockedIncrement((PLONG)&deviceExtension->MediaChangeCount); - - // If this power down is caused by Zero Power ODD, we should mark the device as in ZPODD mode. - if (zpoddInfo != NULL) - { - zpoddInfo->InZeroPowerState = TRUE; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "Device has entered zero power state\n" - )); - } - - deviceExtension->PowerDownInProgress = FALSE; - - return STATUS_SUCCESS; -} - - -VOID -DeviceEvtSurpriseRemoval( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - this function is called when the device is surprisely removed. - Stop all IO queues so that there will be no more request being sent down. - -Arguments: - - Device - Handle to device object - -Return Value: - - None. - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - - PAGED_CODE(); - - deviceExtension = DeviceGetExtension(Device); - - deviceExtension->SurpriseRemoved = TRUE; - - // Stop the main timer - DeviceDisableMainTimer(deviceExtension); - - // legacy behavior to set partition length to be 0. - deviceExtension->PartitionLength.QuadPart = 0; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "Surprisely remove a WDFDEVICE %p\n", Device)); - - return; -} - - -VOID -CreateQueueEvtIoDefault( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - this function is called when CREATE irp comes. - setup FileObject context fields, so it can be used to track MCN or exclusive lock/unlock. - -Arguments: - - Queue - Handle to device queue - - Request - the creation request - -Return Value: - - None - ---*/ -{ - WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request); - WDFDEVICE device = WdfIoQueueGetDevice(Queue); - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device); - PFILE_OBJECT_CONTEXT fileObjectContext = NULL; - - PAGED_CODE(); - - if (fileObject == NULL) { - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_QUEUE, - "Error: received a file create request with file object set to NULL\n")); - - RequestCompletion(deviceExtension, Request, STATUS_INTERNAL_ERROR, 0); - return; - } - - fileObjectContext = FileObjectGetContext(fileObject); - - // Initialize this WDFFILEOBJECT's context - fileObjectContext->DeviceObject = device; - fileObjectContext->FileObject = fileObject; - fileObjectContext->LockCount = 0; - fileObjectContext->McnDisableCount = 0; - fileObjectContext->EnforceStreamingRead = FALSE; - fileObjectContext->EnforceStreamingWrite = FALSE; - - // send down the create synchronously - status = DeviceSendRequestSynchronously(device, Request, FALSE); - - // Need to complete the request in this routine. - RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request)); - - return; -} - -VOID -DeviceEvtFileClose( - _In_ WDFFILEOBJECT FileObject - ) -/*++ - -Routine Description: - - this function is called when CLOSE irp comes. - clean up MCN / Lock if necessary - -Arguments: - - FileObject - WDF file object created for the irp. - -Return Value: - - None - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE(); - - if (FileObject != NULL) - { - WDFDEVICE device = WdfFileObjectGetDevice(FileObject); - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device); - PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData); - PFILE_OBJECT_CONTEXT fileObjectContext = FileObjectGetContext(FileObject); - - // cleanup locked media tray - status = DeviceCleanupProtectedLocks(deviceExtension, fileObjectContext); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "Failed to cleanup protected locks for WDFDEVICE %p, %!STATUS!\n", device, status)); - } - - // cleanup disabled MCN - status = DeviceCleanupDisableMcn(deviceExtension, fileObjectContext); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "Failed to disable MCN for WDFDEVICE %p, %!STATUS!\n", device, status)); - } - - // cleanup exclusive access - if (EXCLUSIVE_MODE(cdData) && EXCLUSIVE_OWNER(cdData, FileObject)) - { - status = DeviceUnlockExclusive(deviceExtension, FileObject, FALSE); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "Failed to release exclusive lock for WDFDEVICE %p, %!STATUS!\n", device, status)); - } - } - } - - return; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceCleanupProtectedLocks( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PFILE_OBJECT_CONTEXT FileObjectContext - ) -/*++ - -Routine Description: - - this function removes protected locks for the handle - -Arguments: - - DeviceExtension - device context - - FileObject - WDF file object created for the irp. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "CleanupProtectedLocks called for WDFDEVICE %p, WDFFILEOBJECT %p, locked %d times.\n", - DeviceExtension->Device, FileObjectContext->FileObject, FileObjectContext->LockCount)); - - // Synchronize with ejection and ejection control requests. - WdfWaitLockAcquire(DeviceExtension->EjectSynchronizationLock, NULL); - - // For each secure lock on this handle decrement the secured lock count - // for the FDO. Keep track of the new value. - if (FileObjectContext->LockCount != 0) - { - DeviceExtension->ProtectedLockCount -= FileObjectContext->LockCount; - FileObjectContext->LockCount = 0; - - // If the new lock count has been dropped to zero then issue a lock - // command to the device. - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "FDO secured lock count = %d " - "lock count = %d\n", - DeviceExtension->ProtectedLockCount, - DeviceExtension->LockCount)); - - if ((DeviceExtension->ProtectedLockCount == 0) && (DeviceExtension->LockCount == 0)) - { - SCSI_REQUEST_BLOCK srb = {0}; - PCDB cdb = (PCDB) &(srb.Cdb); - - srb.CdbLength = 6; - - cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL; - - // TRUE - prevent media removal. - // FALSE - allow media removal. - cdb->MEDIA_REMOVAL.Prevent = FALSE; - - // Set timeout value. - srb.TimeOutValue = DeviceExtension->TimeOutValue; - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - &srb, - NULL, - 0, - FALSE, - NULL); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "Allow media removal (unlock) request to drive returned %!STATUS!\n", - status)); - } - } - - WdfWaitLockRelease(DeviceExtension->EjectSynchronizationLock); - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceCleanupDisableMcn( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PFILE_OBJECT_CONTEXT FileObjectContext - ) -/*++ - -Routine Description: - - cleanup the MCN disable count for the handle - -Arguments: - - DeviceExtension - device context - - FileObject - WDF file object created for the irp. - -Return Value: - - NTSTATUS - ---*/ -{ - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CleanupDisableMcn called for WDFDEVICE %p, WDFFILEOBJECT %p, locked %d times.\n", - DeviceExtension->Device, FileObjectContext->FileObject, FileObjectContext->McnDisableCount)); - - // For each secure lock on this handle decrement the secured lock count - // for the FDO. Keep track of the new value. - while (FileObjectContext->McnDisableCount != 0) - { - DeviceEnableMediaChangeDetection(DeviceExtension, FileObjectContext, TRUE); - } - - return STATUS_SUCCESS; -} - -VOID -NormalizeIoctl( - _Inout_ PWDF_REQUEST_PARAMETERS requestParameters - ) -{ - ULONG ioctlCode; - ULONG baseCode; - ULONG functionCode; - - // if this is a class driver ioctl then we need to change the base code - // to IOCTL_STORAGE_BASE so that the switch statement can handle it. - // - // WARNING - currently the scsi class ioctl function codes are between - // 0x200 & 0x300. this routine depends on that fact - ioctlCode = requestParameters->Parameters.DeviceIoControl.IoControlCode; - baseCode = DEVICE_TYPE_FROM_CTL_CODE(ioctlCode); - functionCode = (ioctlCode & (~0xffffc003)) >> 2; - - if ((baseCode == IOCTL_SCSI_BASE) || - (baseCode == IOCTL_DISK_BASE) || - (baseCode == IOCTL_TAPE_BASE) || - (baseCode == IOCTL_DVD_BASE) || - (baseCode == IOCTL_CDROM_BASE)) - //IOCTL_STORAGE_BASE does not need to be converted. - { - if((functionCode >= 0x200) && (functionCode <= 0x300)) - { - ioctlCode = (ioctlCode & 0x0000ffff) | CTL_CODE(IOCTL_STORAGE_BASE, 0, 0, 0); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "IOCTL code recalibrate, New ioctl code is %lx\n", - ioctlCode)); - - // Set the code into request parameters, then "requestParameters" needs to be used for dispatch functions. - requestParameters->Parameters.DeviceIoControl.IoControlCode = ioctlCode; - } - } -} - -VOID -DeviceEvtIoInCallerContext( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ -Routine Description: - - Responds to EvtIoInCallerContext events from KMDF - It calls different functions to process different type of IOCTLs. - -Arguments: - - Device - handle to a WDF Device object - - Request - handle to the incoming WDF Request object - -Return Value: - - VOID. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - WDF_REQUEST_PARAMETERS requestParameters; - - requestContext->DeviceExtension = deviceExtension; - - // set the received time - RequestSetReceivedTime(Request); - - // get the request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - if (requestParameters.Type == WdfRequestTypeDeviceControl) - { - BOOLEAN processed = FALSE; - PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData); - PMEDIA_CHANGE_DETECTION_INFO info = deviceExtension->MediaChangeDetectionInfo; - - if (requestParameters.Parameters.DeviceIoControl.IoControlCode != IOCTL_MCN_SYNC_FAKE_IOCTL) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "Receiving IOCTL: %lx\n", - requestParameters.Parameters.DeviceIoControl.IoControlCode)); - } - else - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "Receiving IOCTL: %lx\n", - requestParameters.Parameters.DeviceIoControl.IoControlCode)); - } - - // If the device is in exclusive mode, check whether the request is from - // the handle that locked the device. - if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request))) - { - BOOLEAN isBlocked = FALSE; - - status = RequestIsIoctlBlockedByExclusiveAccess(Request, &isBlocked); - UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning. - - if (isBlocked) - { - if ((requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_EVENT_NOTIFICATION) && - (info != NULL) && (info->AsynchronousNotificationSupported != FALSE)) - { - // If AN is supported and we receive a signal but we can't send down GESN - // due to exclusive lock, we should save it and fire a GESN when it's unlocked. - // We just need true/false here and don't need count because we will keep sending - // GESN until we deplete all events. - info->ANSignalPendingDueToExclusiveLock = TRUE; - } - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "Access Denied! Device in exclusive mode.Failing Ioctl %lx\n", - requestParameters.Parameters.DeviceIoControl.IoControlCode)); - RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0); - - return; - } - } - - NormalizeIoctl(&requestParameters); - - // 1. All requests that don't need to access device can be processed immediately - if (!processed) - { - processed = RequestDispatchProcessDirectly(Device, Request, requestParameters); - } - - // 2. Requests that should be put in sequential queue. - if (!processed) - { - processed = RequestDispatchToSequentialQueue(Device, Request, requestParameters); - } - - // 3. Requests that need to be processed sequentially and in caller's context. - if (!processed) - { - processed = RequestDispatchSyncWithSequentialQueue(Device, Request, requestParameters); - } - - // 4. Special requests that needs different process in different cases. - if (!processed) - { - processed = RequestDispatchSpecialIoctls(Device, Request, requestParameters); - } - - // 5. This is default behavior for unknown IOCTLs. To pass it to lower level. - if (!processed) - { - processed = RequestDispatchUnknownRequests(Device, Request, requestParameters); - } - - // All requests should be processed already. - NT_ASSERT(processed); - UNREFERENCED_PARAMETER(processed); //defensive coding, avoid PREFAST warning. - } - else if (requestParameters.Type == WdfRequestTypeDeviceControlInternal) - { - RequestProcessInternalDeviceControl(Request, deviceExtension); - } - else - { - // Requests other than IOCTLs will be forwarded to default queue. - status = WdfDeviceEnqueueRequest(Device, Request); - if (!NT_SUCCESS(status)) - { - RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request)); - } - } - - return; -} - - -BOOLEAN -RequestDispatchProcessDirectly( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters - ) -/*++ -Routine Description: - - These requests can be processed in a non-serialized manner, most of them don't need to access device. - -Arguments: - - Device - handle to a WDF Device object - - Request - handle to the incoming WDF Request object - - RequestParameters - request parameters - -Return Value: - - BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function). - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN processed = FALSE; - size_t dataLength = 0; - - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode; - - switch (ioctlCode) - { - - case IOCTL_CDROM_GET_INQUIRY_DATA: - { - status = RequestHandleGetInquiryData(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_GET_MEDIA_TYPES_EX: - { - status = RequestHandleGetMediaTypeEx(deviceExtension, Request, &dataLength); - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: - { - status = RequestHandleMountQueryUniqueId(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: - { - status = RequestHandleMountQueryDeviceName(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: - { - status = RequestHandleMountQuerySuggestedLinkName(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_GET_DEVICE_NUMBER: - { - status = RequestHandleGetDeviceNumber(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_GET_HOTPLUG_INFO: - { - status = RequestHandleGetHotPlugInfo(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_SET_HOTPLUG_INFO: - { - status = RequestHandleSetHotPlugInfo(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_EVENT_NOTIFICATION: - { - status = RequestHandleEventNotification(deviceExtension, Request, &RequestParameters, &dataLength); - - processed = TRUE; - break; // complete the irp - } - -#if (NTDDI_VERSION >= NTDDI_WIN8) - case IOCTL_VOLUME_ONLINE: - { - // - // Mount manager and volume manager will - // follow this online with a post online - // but other callers may not. In those - // cases, we process this request right - // away. We approximate that these other - // callers are from user mode - // - - if (WdfRequestGetRequestorMode(Request) == KernelMode) - { - processed = TRUE; - } - break; - } -#endif - - default: - { - processed = FALSE; - break; - } - - } //end of switch (ioctlCode) - - if (processed) - { - UCHAR currentStackLocationFlags = 0; - currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request); - - if ((status == STATUS_VERIFY_REQUIRED) && - (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME)) - { - // If the status is verified required and this request - // should bypass verify required then retry the request. - status = STATUS_IO_DEVICE_ERROR; - UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding... - - processed = RequestDispatchProcessDirectly(Device, Request, RequestParameters); - } - else - { - // Complete the request after processing it. - RequestCompletion(deviceExtension, Request, status, dataLength); - } - } - - return processed; -} - - -BOOLEAN -RequestDispatchToSequentialQueue( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters - ) -/*++ -Routine Description: - - These requests can be processed in a non-serialized manner, most of them don't need to access device. - -Arguments: - - Device - handle to a WDF Device object - - Request - handle to the incoming WDF Request object - - RequestParameters - request parameters - -Return Value: - - BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function). - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN processed = FALSE; - size_t dataLength = 0; - BOOLEAN inZeroPowerState = FALSE; - - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode; - PZERO_POWER_ODD_INFO zpoddInfo = deviceExtension->ZeroPowerODDInfo; - - if ((zpoddInfo != NULL) && - (zpoddInfo->InZeroPowerState != FALSE)) - { - inZeroPowerState = TRUE; - } - - switch (ioctlCode) - { - - case IOCTL_CDROM_RAW_READ: - { - status = RequestValidateRawRead(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Get drive geometryEx\n")); - if ( RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - (ULONG)FIELD_OFFSET(DISK_GEOMETRY_EX, Data)) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = FIELD_OFFSET(DISK_GEOMETRY_EX, Data); - } - else if (inZeroPowerState != FALSE) - { - status = STATUS_NO_MEDIA_IN_DEVICE; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_DISK_GET_DRIVE_GEOMETRY: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Get drive geometry\n")); - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(DISK_GEOMETRY)) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = sizeof(DISK_GEOMETRY); - } - else if (inZeroPowerState != FALSE) - { - status = STATUS_NO_MEDIA_IN_DEVICE; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_CDROM_READ_TOC_EX: - { - status = RequestValidateReadTocEx(deviceExtension, Request, RequestParameters, &dataLength); - - if (inZeroPowerState != FALSE) - { - status = STATUS_NO_MEDIA_IN_DEVICE; - } - - processed = TRUE; - break; - } - - case IOCTL_CDROM_READ_TOC: - { - status = RequestValidateReadToc(deviceExtension, RequestParameters, &dataLength); - - if (inZeroPowerState != FALSE) - { - status = STATUS_NO_MEDIA_IN_DEVICE; - } - - processed = TRUE; - break; - } - - case IOCTL_CDROM_GET_LAST_SESSION: - { - status = RequestValidateGetLastSession(deviceExtension, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_CDROM_PLAY_AUDIO_MSF: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Play audio MSF\n")); - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_PLAY_AUDIO_MSF)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_CDROM_SEEK_AUDIO_MSF: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Seek audio MSF\n")); - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_SEEK_AUDIO_MSF)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_CDROM_PAUSE_AUDIO: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Pause audio\n")); - - status = STATUS_SUCCESS; - processed = TRUE; - break; - } - - case IOCTL_CDROM_RESUME_AUDIO: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Resume audio\n")); - - status = STATUS_SUCCESS; - processed = TRUE; - break; - } - - case IOCTL_CDROM_READ_Q_CHANNEL: - { - status = RequestValidateReadQChannel(Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_CDROM_GET_VOLUME: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Get volume control\n")); - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(VOLUME_CONTROL)) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = sizeof(VOLUME_CONTROL); - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_CDROM_SET_VOLUME: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Set volume control\n")); - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(VOLUME_CONTROL)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_CDROM_STOP_AUDIO: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Stop audio\n")); - - status = STATUS_SUCCESS; - processed = TRUE; - break; - } - - case IOCTL_STORAGE_CHECK_VERIFY: - case IOCTL_STORAGE_CHECK_VERIFY2: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] Check Verify\n", Request)); - - // Following check will let the condition "OutputBufferLength == 0" pass. - // Since it's legacy behavior in classpnp, we need to keep it. - if ((RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > 0) && - (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = sizeof(ULONG); - } - else if (inZeroPowerState != FALSE) - { - status = STATUS_NO_MEDIA_IN_DEVICE; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_DVD_GET_REGION: - { - // validation will be done when process it. - status = STATUS_SUCCESS; - processed = TRUE; - break; - } - - case IOCTL_DVD_READ_STRUCTURE: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_READ_STRUCTURE\n", Request)); - - status = RequestValidateDvdReadStructure(deviceExtension, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_DVD_READ_KEY: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_READ_KEY\n", Request)); - - status = RequestValidateDvdReadKey(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_DVD_START_SESSION: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_START_SESSION\n", Request)); - - status = RequestValidateDvdStartSession(deviceExtension, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_DVD_SEND_KEY: - case IOCTL_DVD_SEND_KEY2: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_SEND_KEY\n", Request)); - - status = RequestValidateDvdSendKey(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_STORAGE_SET_READ_AHEAD: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] SetReadAhead\n", Request)); - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(STORAGE_SET_READ_AHEAD)) - { - status = STATUS_INVALID_PARAMETER; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_DISK_IS_WRITABLE: - { - status = STATUS_SUCCESS; - - processed = TRUE; - break; - } - - case IOCTL_DISK_GET_DRIVE_LAYOUT: - { - ULONG requiredSize = 0; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Get drive layout\n")); - - requiredSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]); - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - requiredSize) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = requiredSize; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_DISK_GET_DRIVE_LAYOUT_EX: - { - ULONG requiredSize = 0; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Get drive layoutEx\n")); - - requiredSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]); - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - requiredSize) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = requiredSize; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_DISK_GET_PARTITION_INFO: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Get Partition Info\n")); - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(PARTITION_INFORMATION)) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = sizeof(PARTITION_INFORMATION); - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_DISK_GET_PARTITION_INFO_EX: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Get Partition InfoEx\n")); - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(PARTITION_INFORMATION_EX)) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = sizeof(PARTITION_INFORMATION_EX); - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_DISK_VERIFY: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: IOCTL_DISK_VERIFY to device %p through request %p\n", - Device, - Request)); - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(VERIFY_INFORMATION)) - { - status = STATUS_INVALID_PARAMETER; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_DISK_GET_LENGTH_INFO: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: Disk Get Length InfoEx\n")); - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(GET_LENGTH_INFORMATION)) - { - status = STATUS_BUFFER_TOO_SMALL; - dataLength = sizeof(GET_LENGTH_INFORMATION); - } - else if (inZeroPowerState != FALSE) - { - status = STATUS_NO_MEDIA_IN_DEVICE; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; - } - - case IOCTL_CDROM_GET_CONFIGURATION: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_GET_CONFIGURATION\n", Request)); - - status = RequestValidateGetConfiguration(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_CDROM_SET_SPEED: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_SET_SPEED\n", Request)); - - status = RequestValidateSetSpeed(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_DVD_END_SESSION: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_END_SESSION\n", Request)); - - status = RequestValidateDvdEndSession(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_END_SESSION: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_AACS_END_SESSION\n", Request)); - - status = RequestValidateAacsEndSession(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_READ_MEDIA_KEY_BLOCK: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Querying full MKB with bufferSize of %x bytes\n", - (int)RequestParameters.Parameters.DeviceIoControl.OutputBufferLength - )); - - status = RequestValidateAacsReadMediaKeyBlock(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_START_SESSION: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Requesting AGID\n" - )); - - status = RequestValidateAacsStartSession(deviceExtension, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_SEND_CERTIFICATE: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Sending host certificate to drive\n" - )); - - status = RequestValidateAacsSendCertificate(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_GET_CERTIFICATE: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Querying drive certificate\n" - )); - - status = RequestValidateAacsGetCertificate(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_GET_CHALLENGE_KEY: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Querying drive challenge key\n" - )); - - status = RequestValidateAacsGetChallengeKey(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_SEND_CHALLENGE_KEY: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Sending drive challenge key\n" - )); - - status = RequestValidateAacsSendChallengeKey(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_READ_VOLUME_ID: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Reading volume ID\n" - )); - - status = RequestValidateAacsReadVolumeId(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_READ_SERIAL_NUMBER: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Reading Serial Number\n" - )); - - status = RequestValidateAacsReadSerialNumber(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_READ_MEDIA_ID: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Reading media ID\n" - )); - - status = RequestValidateAacsReadMediaId(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_AACS_READ_BINDING_NONCE: - case IOCTL_AACS_GENERATE_BINDING_NONCE: - { - if (ioctlCode == IOCTL_AACS_GENERATE_BINDING_NONCE) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Generating new binding nonce\n" - )); - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "AACS: Reading existing binding nonce\n" - )); - } - - status = RequestValidateAacsBindingNonce(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_CDROM_ENABLE_STREAMING: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_ENABLE_STREAMING\n", Request)); - - status = RequestValidateEnableStreaming(Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_CDROM_SEND_OPC_INFORMATION: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_SEND_OPC_INFORMATION\n", Request)); - - status = RequestValidateSendOpcInformation(Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_CDROM_GET_PERFORMANCE: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_GET_PERFORMANCE\n", Request)); - - status = RequestValidateGetPerformance(Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_STORAGE_MEDIA_REMOVAL: - case IOCTL_STORAGE_EJECTION_CONTROL: - { - if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(PREVENT_MEDIA_REMOVAL)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_MCN_CONTROL: - { - if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(PREVENT_MEDIA_REMOVAL)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_RESERVE: - case IOCTL_STORAGE_RELEASE: - { - // there is no validate check currently. - status = STATUS_SUCCESS; - processed = TRUE; - break; - } - - case IOCTL_STORAGE_PERSISTENT_RESERVE_IN: - case IOCTL_STORAGE_PERSISTENT_RESERVE_OUT: - { - status = RequestValidatePersistentReserve(deviceExtension, Request, RequestParameters, &dataLength); - - processed = TRUE; - break; - } - - case IOCTL_STORAGE_EJECT_MEDIA: - case IOCTL_STORAGE_LOAD_MEDIA: - case IOCTL_STORAGE_LOAD_MEDIA2: - { - status = STATUS_SUCCESS; - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_FIND_NEW_DEVICES: - { - // process it. - IoInvalidateDeviceRelations(deviceExtension->LowerPdo, BusRelations); - - status = STATUS_SUCCESS; - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_READ_CAPACITY: - { - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_READ_CAPACITY)) - { - dataLength = sizeof(STORAGE_READ_CAPACITY); - status = STATUS_BUFFER_TOO_SMALL; - } - else if (inZeroPowerState != FALSE) - { - status = STATUS_NO_MEDIA_IN_DEVICE; - } - else - { - status = STATUS_SUCCESS; - } - - processed = TRUE; - break; // complete the irp - } - - case IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT: - { - // for disk.sys only in original classpnp - status = STATUS_NOT_SUPPORTED; - - processed = TRUE; - break; // complete the irp - } - -#if (NTDDI_VERSION >= NTDDI_WIN8) - case IOCTL_DISK_ARE_VOLUMES_READY: - { - // this request doesn't access device at all, so seemingly it can be processed - // directly; however, in case volume online is not received, we will need to - // park these requests in a queue, and the only way a request can be queued is - // if the request came out of another queue. - status = STATUS_SUCCESS; - - processed = TRUE; - break; - } - - case IOCTL_VOLUME_ONLINE: - case IOCTL_VOLUME_POST_ONLINE: - { - status = STATUS_SUCCESS; - - processed = TRUE; - break; - } -#endif - - default: - { - processed = FALSE; - break; - } - } //end of switch (ioctlCode) - - if (processed) - { - UCHAR currentStackLocationFlags = 0; - currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request); - - if ((status == STATUS_VERIFY_REQUIRED) && - (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME)) - { - // If the status is verified required and this request - // should bypass verify required then retry the request. - status = STATUS_IO_DEVICE_ERROR; - UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding... - - processed = RequestDispatchToSequentialQueue(Device, Request, RequestParameters); - } - else - { - if (NT_SUCCESS(status)) - { - // Forward the request to serialized queue. - status = WdfDeviceEnqueueRequest(Device, Request); - } - - if (!NT_SUCCESS(status)) - { - // Validation failed / forward failed, complete the request. - RequestCompletion(deviceExtension, Request, status, dataLength); - } - } - } - - return processed; -} - - -BOOLEAN -RequestDispatchSyncWithSequentialQueue( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters - ) -/*++ -Routine Description: - - These requests need to stay in caller's context and be processed in serialized manner. - -Arguments: - - Device - handle to a WDF Device object - - Request - handle to the incoming WDF Request object - - RequestParameters - request parameters - -Return Value: - - BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function). - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN processed = FALSE; - size_t dataLength = 0; - - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode; - - switch (ioctlCode) - { - - case IOCTL_CDROM_EXCLUSIVE_ACCESS: - { - //1. Validate - status = RequestValidateExclusiveAccess(Request, RequestParameters, &dataLength); - - //2. keep the request in serialized manner and stay in user's context. - if (NT_SUCCESS(status)) - { - PCDROM_EXCLUSIVE_ACCESS exclusiveAccess = NULL; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &exclusiveAccess, - NULL); - - if (NT_SUCCESS(status)) - { - // do not need to check "status" as it passed validation and cannot fail in WdfRequestRetrieveInputBuffer() - switch (exclusiveAccess->RequestType) - { - - case ExclusiveAccessQueryState: - { - status = RequestSetContextFields(Request, RequestHandleExclusiveAccessQueryLockState); - break; - } - - case ExclusiveAccessLockDevice: - { - status = RequestSetContextFields(Request, RequestHandleExclusiveAccessLockDevice); - break; - } - - case ExclusiveAccessUnlockDevice: - { - status = RequestSetContextFields(Request, RequestHandleExclusiveAccessUnlockDevice); - break; - } - default: - { - // already valicated in RequestValidateExclusiveAccess() - NT_ASSERT(FALSE); - break; - } - } - } - - if (NT_SUCCESS(status)) - { - // now, put the special synchronization information into the context - status = RequestSynchronizeProcessWithSerialQueue(Device, Request); - - // "status" is used for debugging in above statement, reset to success to avoid further work in this function. - status = STATUS_SUCCESS; - } - } - - processed = TRUE; - break; // complete the irp - } - - default: - { - processed = FALSE; - break; - } - } //end of switch (ioctlCode) - - // Following process is only valid if the request is not really processed. (failed in validation) - if (processed && !NT_SUCCESS(status)) - { - UCHAR currentStackLocationFlags = 0; - currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request); - - if ((status == STATUS_VERIFY_REQUIRED) && - (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME)) - { - // - // If the status is verified required and this request - // should bypass verify required then retry the request. - // - status = STATUS_IO_DEVICE_ERROR; - UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding... - - processed = RequestDispatchSyncWithSequentialQueue(Device, Request, RequestParameters); - } - else - { - // Validation failed / forward failed, complete the request. - RequestCompletion(deviceExtension, Request, status, dataLength); - } - } - - return processed; -} - - -BOOLEAN -RequestDispatchSpecialIoctls( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters - ) -/*++ -Routine Description: - - These requests need to be processed in different manner according to input parameters - -Arguments: - - Device - handle to a WDF Device object - - Request - handle to the incoming WDF Request object - - RequestParameters - request parameters - -Return Value: - - BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function). - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN processed = FALSE; - size_t dataLength = 0; - BOOLEAN requestCompleted = FALSE; - - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData); - ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode; - - switch (ioctlCode) - { - case IOCTL_SCSI_PASS_THROUGH: - case IOCTL_SCSI_PASS_THROUGH_DIRECT: - case IOCTL_SCSI_PASS_THROUGH_EX: - case IOCTL_SCSI_PASS_THROUGH_DIRECT_EX: - { - // SPTI is considered special case as we need to set the MinorFunction before pass to low level. - -#if defined (_WIN64) - if (WdfRequestIsFrom32BitProcess(Request)) - { - if ((ioctlCode == IOCTL_SCSI_PASS_THROUGH) || (ioctlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)) - { - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32)) - { - status = STATUS_INVALID_PARAMETER; - } - } - else - { - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32_EX)) - { - status = STATUS_INVALID_PARAMETER; - } - } - } - else -#endif - { - if ((ioctlCode == IOCTL_SCSI_PASS_THROUGH) || (ioctlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)) - { - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)) - { - status = STATUS_INVALID_PARAMETER; - } - } - else - { - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH_EX)) - { - status = STATUS_INVALID_PARAMETER; - } - } - } - - if (!NT_SUCCESS(status)) - { - // validation failed. - RequestCompletion(deviceExtension, Request, status, dataLength); - } - else - { - // keep the request in serialized manner and stay in user's context. - status = RequestSetContextFields(Request, RequestHandleScsiPassThrough); - - if (NT_SUCCESS(status)) - { - status = RequestSynchronizeProcessWithSerialQueue(Device, Request); - } - else - { - RequestCompletion(deviceExtension, Request, status, 0); - } - } - - requestCompleted = TRUE; - processed = TRUE; - break; - } - - case IOCTL_STORAGE_QUERY_PROPERTY: - { - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_PROPERTY_QUERY)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - PSTORAGE_PROPERTY_QUERY inputBuffer = NULL; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - if (!EXCLUSIVE_MODE(cdData) || // not locked - EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)) || // request is from lock owner - (inputBuffer->QueryType == PropertyExistsQuery)) // request not access device - { - if (inputBuffer->PropertyId == StorageDeviceUniqueIdProperty) - { - // previously handled in classpnp - // keep the request in serialized manner and stay in user's context. - status = RequestSetContextFields(Request, RequestHandleQueryPropertyDeviceUniqueId); - - if (NT_SUCCESS(status)) - { - status = RequestSynchronizeProcessWithSerialQueue(Device, Request); - // remeber that the request has been completed. - requestCompleted = TRUE; - } - } - else if (inputBuffer->PropertyId == StorageDeviceWriteCacheProperty) - { - // previously handled in classpnp - // keep the request in serialized manner and stay in user's context. - status = RequestSetContextFields(Request, RequestHandleQueryPropertyWriteCache); - - if (NT_SUCCESS(status)) - { - status = RequestSynchronizeProcessWithSerialQueue(Device, Request); - // remeber that the request has been completed. - requestCompleted = TRUE; - } - } - else - { - // Pass to port driver for handling - RequestDispatchUnknownRequests(Device, Request, RequestParameters); - - // remeber that the request has been completed. - requestCompleted = TRUE; - } - } - else - { - // If cached data exists, return cached data. Otherwise, fail the request. - if ((inputBuffer->QueryType == PropertyStandardQuery) && - ((inputBuffer->PropertyId == StorageDeviceProperty) || (inputBuffer->PropertyId == StorageAdapterProperty)) ) - { - status = RequestHandleQueryPropertyRetrieveCachedData(deviceExtension, Request, RequestParameters, &dataLength); - } - else - { - status = STATUS_ACCESS_DENIED; - } - } - } - } - - processed = TRUE; - break; - } - - // this IOCTL is a fake one, used for MCN process sync-ed with serial queue. - case IOCTL_MCN_SYNC_FAKE_IOCTL: - { - PIRP irp = WdfRequestWdmGetIrp(Request); - - if ((deviceExtension->MediaChangeDetectionInfo != NULL) && - (irp == deviceExtension->MediaChangeDetectionInfo->MediaChangeSyncIrp) && - (WdfRequestGetRequestorMode(Request) == KernelMode) && - (RequestParameters.Parameters.Others.Arg1 == RequestSetupMcnSyncIrp) && - (RequestParameters.Parameters.Others.Arg2 == RequestSetupMcnSyncIrp) && - (RequestParameters.Parameters.Others.Arg4 == RequestSetupMcnSyncIrp)) - { - // This is the requset we use to sync Media Change Detection with sequential queue. - status = WdfDeviceEnqueueRequest(Device, Request); - - if (!NT_SUCCESS(status)) - { - RequestCompletion(deviceExtension, Request, status, dataLength); - } - - requestCompleted = TRUE; - processed = TRUE; - } - else - { - // process as an unknown request. - processed = FALSE; - } - break; - } - - default: - { - processed = FALSE; - break; - } - } //end of switch (ioctlCode) - - if (processed && !requestCompleted) - { - UCHAR currentStackLocationFlags = 0; - currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request); - - if ((status == STATUS_VERIFY_REQUIRED) && - (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME)) - { - // If the status is verified required and this request - // should bypass verify required then retry the request. - status = STATUS_IO_DEVICE_ERROR; - UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding... - - processed = RequestDispatchSpecialIoctls(Device, Request, RequestParameters); - } - else - { - RequestCompletion(deviceExtension, Request, status, dataLength); - } - } - - return processed; -} - - -BOOLEAN -RequestDispatchUnknownRequests( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters - ) -/*++ -Routine Description: - - All unknown requests will be pass to lower level driver. - If IRQL is PASSIVE_LEVEL, the request will be serialized; - Otherwise, it'll be sent and forget. - -Arguments: - - Device - handle to a WDF Device object - - Request - handle to the incoming WDF Request object - - RequestParameters - request parameters - -Return Value: - - BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function). - ---*/ -{ - NTSTATUS status = STATUS_UNSUCCESSFUL; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - - ULONG baseCode = DEVICE_TYPE_FROM_CTL_CODE(RequestParameters.Parameters.DeviceIoControl.IoControlCode); - - if ((KeGetCurrentIrql() != PASSIVE_LEVEL) || - (baseCode == FILE_DEVICE_ACPI)) - { - // 1. When IRQL is higher than PASSIVE_LEVEL, - // 2. ataport sends IOCTL_ACPI_ASYNC_EVAL_METHOD before queue starts, - // send request directly to lower driver. - status = RequestHandleUnknownIoctl(Device, Request); - } - else - { - // keep the request in serialized manner and stay in user's context. - status = RequestSetContextFields(Request, RequestHandleUnknownIoctl); - - if (NT_SUCCESS(status)) - { - status = RequestSynchronizeProcessWithSerialQueue(Device, Request); - } - else - { - RequestCompletion(deviceExtension, Request, status, 0); - } - } - - UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning. - - // All unknown IOCTLs are processed in this function. - return TRUE; //processed -} - -VOID -RequestProcessInternalDeviceControl( - _In_ WDFREQUEST Request, - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ -Routine Description: - - all internal IOCTL will be send to lower driver asynchronously. - -Arguments: - - Request - handle to the incoming WDF Request object - DeviceExtension - device extension structure - -Return Value: - - None - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PIRP irp = NULL; - PIO_STACK_LOCATION irpStack = NULL; - PIO_STACK_LOCATION nextStack = NULL; - BOOLEAN requestSent = FALSE; - - irp = WdfRequestWdmGetIrp(Request); - irpStack = IoGetCurrentIrpStackLocation(irp); - nextStack = IoGetNextIrpStackLocation(irp); - - // Set the parameters in the next stack location. - nextStack->Parameters.Scsi.Srb = irpStack->Parameters.Scsi.Srb; - nextStack->MajorFunction = IRP_MJ_SCSI; - nextStack->MinorFunction = IRP_MN_SCSI_CLASS; - - WdfRequestSetCompletionRoutine(Request, RequestDummyCompletionRoutine, NULL); - - status = RequestSend(DeviceExtension, - Request, - DeviceExtension->IoTarget, - 0, - &requestSent); - - // send the request straight down (asynchronously) - if (!requestSent) - { - // fail the request - RequestCompletion(DeviceExtension, Request, status, WdfRequestGetInformation(Request)); - } - - return; -} - - - -// -// Serial I/O Queue Event callbacks -// - -VOID -SequentialQueueEvtIoReadWrite( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request, - _In_ size_t Length - ) -/*++ -Routine Description: - - validate and process read/write request. - -Arguments: - - Queue - parallel queue itself - - Request - handle to the incoming WDF Request object - - Length - read / write lenght - -Return Value: - - None - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDFDEVICE device = WdfIoQueueGetDevice(Queue); - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device); - WDF_REQUEST_PARAMETERS requestParameters; - PIRP wdmIrp = WdfRequestWdmGetIrp(Request); - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(wdmIrp); - PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData); - - // Get the request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - if (requestParameters.Type == WdfRequestTypeRead) - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, - "Receiving READ, Length %Ix\n", (ULONG) Length)); - } - else - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, - "Receiving WRITE, Length %Ix\n", (ULONG) Length)); - } - - // Check if a verify is required before a READ/WRITE - if (TEST_FLAG(deviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME) && - (requestParameters.MinorFunction != CDROM_VOLUME_VERIFY_CHECKED) && - !TEST_FLAG(currentIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME)) - { - // DO_VERIFY_VOLUME is set for the device object, - // but this request is not itself a verify request. - // So fail this request. - RequestCompletion(deviceExtension, Request, STATUS_VERIFY_REQUIRED, 0); - } - else - { - // Since we've bypassed the verify-required tests we don't need to repeat - // them with this IRP - in particular we don't want to worry about - // hitting them at the partition 0 level if the request has come through - // a non-zero partition. - currentIrpStack->MinorFunction = CDROM_VOLUME_VERIFY_CHECKED; - - // Fail READ/WRITE requests when music is playing - if (deviceExtension->DeviceAdditionalData.PlayActive) - { - RequestCompletion(deviceExtension, Request, STATUS_DEVICE_BUSY, 0); - - return; - } - - // Fail READ/WRITE requests from non-owners if the drive is locked - if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request))) - { - RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0); - - return; - } - - // Succeed READ/WRITE requests of length 0 - if (Length == 0) - { - // Several parts of the code turn 0 into 0xffffffff, - // so don't process a zero-length request any further. - RequestCompletion(deviceExtension, Request, STATUS_SUCCESS, Length); - - return; - } - - // If there is an unexpected write request, we want to rediscover MMC capabilities - if (!deviceExtension->DeviceAdditionalData.Mmc.WriteAllowed && - (requestParameters.Type == WdfRequestTypeWrite)) - { - // Schedule MMC capabilities update now, but perform it later in a work item - deviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired; - } - - // If MMC capabilities update is required, we create a separate work item to avoid blocking - // the current thread; otherwise, we initiate an async read/write in the current thread. - if (DeviceIsMmcUpdateRequired(deviceExtension->Device)) - { - deviceExtension->ReadWriteWorkItemContext.OriginalRequest = Request; - WdfWorkItemEnqueue(deviceExtension->ReadWriteWorkItem); - - status = STATUS_SUCCESS; - } - else - { - status = RequestValidateReadWrite(deviceExtension, Request, requestParameters); - - if (NT_SUCCESS(status)) - { - status = RequestHandleReadWrite(deviceExtension, Request, requestParameters); - } - } - - if (!NT_SUCCESS(status)) - { - RequestCompletion(deviceExtension, Request, status, 0); - } - } - - return; -} - - -VOID -ReadWriteWorkItemRoutine( - _In_ WDFWORKITEM WorkItem - ) -/*++ - -Routine Description: - - Work item routine for validating and initiating read and write requests. - The reason why we do that from a work item is because we may need to update MMC - capabilities before validating a read/write request and that is a sync operation. - -Arguments: - - WorkItem - WDF work item - -Return Value: - - none - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - WDFREQUEST readWriteRequest = NULL; - WDF_REQUEST_PARAMETERS readWriteRequestParameters; - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE (); - - deviceExtension = WdfObjectGetTypedContext(WdfWorkItemGetParentObject(WorkItem), CDROM_DEVICE_EXTENSION); - readWriteRequest = deviceExtension->ReadWriteWorkItemContext.OriginalRequest; - deviceExtension->ReadWriteWorkItemContext.OriginalRequest = NULL; - - WDF_REQUEST_PARAMETERS_INIT(&readWriteRequestParameters); - WdfRequestGetParameters(readWriteRequest, &readWriteRequestParameters); - - if (DeviceIsMmcUpdateRequired(deviceExtension->Device)) - { - // Issue command to update the drive capabilities. - // The failure of MMC update is not considered critical, so we'll - // continue to process the request even if MMC update fails. - (VOID) DeviceUpdateMmcCapabilities(deviceExtension->Device); - } - - // Now verify and process the request - if (NT_SUCCESS(status)) - { - status = RequestValidateReadWrite(deviceExtension, readWriteRequest, readWriteRequestParameters); - } - if (NT_SUCCESS(status)) - { - status = RequestHandleReadWrite(deviceExtension, readWriteRequest, readWriteRequestParameters); - } - - // Complete the request immediately on failure - if (!NT_SUCCESS(status)) - { - RequestCompletion(deviceExtension, readWriteRequest, status, 0); - } -} - - -VOID -SequentialQueueEvtIoDeviceControl( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request, - _In_ size_t OutputBufferLength, - _In_ size_t InputBufferLength, - _In_ ULONG IoControlCode - ) -/*++ -Routine Description: - - validate and process IOCTL request. - -Arguments: - - Queue - sequential queue - - Request - handle to the incoming WDF Request object - -Return Value: - - None - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDFDEVICE device = WdfIoQueueGetDevice(Queue); - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device); - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData); - WDF_REQUEST_PARAMETERS requestParameters; - - UNREFERENCED_PARAMETER(OutputBufferLength); - UNREFERENCED_PARAMETER(InputBufferLength); - UNREFERENCED_PARAMETER(IoControlCode); - - // get the request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - // If the device is in exclusive mode, check whether the request is from - // the handle that locked the device - if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request))) - { - BOOLEAN isBlocked = FALSE; - - status = RequestIsIoctlBlockedByExclusiveAccess(Request, &isBlocked); - if (NT_SUCCESS(status) && isBlocked) - { - if (requestContext->SyncRequired) - { - // set the following event, so RequestSynchronizeProcessWithSerialQueue() can contintue run to process the real request. - // this function will wait for the request process finishes. - KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE); - } - else - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DeviceEvtIoInCallerContext: Access Denied! Device in exclusive mode.Failing Ioctl %lx\n", - requestParameters.Parameters.DeviceIoControl.IoControlCode)); - RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0); - } - - return; - } - } - - if (!cdData->Mmc.WriteAllowed && - ((requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_IS_WRITABLE) || - (requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_VERIFY))) - { - cdData->Mmc.UpdateState = CdromMmcUpdateRequired; - } - - // check if this is a synchronized ioctl - if (requestContext->SyncRequired) - { - // set the following event, so RequestSynchronizeProcessWithSerialQueue() can contintue run to process the real request. - // this function will wait for the request process finishes. - KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE); - } - else - { - deviceExtension->IoctlWorkItemContext.OriginalRequest = Request; - - // all other IOCTL processing is currently processed via a - // work item running at PASSIVE_LEVEL. - WdfWorkItemEnqueue(deviceExtension->IoctlWorkItem); - } - - return; -} - - -VOID -IoctlWorkItemRoutine( - _In_ WDFWORKITEM WorkItem - ) -/*++ - -Routine Description: - - Work item routine for processing ioctl requests. - This is needed because event callbacks are called at DISPATCH_LEVEL and ioctl - requests are currently processed synchronously and not asynchronously. - -Arguments: - - WorkItem - WDF work item - -Return Value: - - none - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - - PAGED_CODE (); - - deviceExtension = WdfObjectGetTypedContext(WdfWorkItemGetParentObject(WorkItem), CDROM_DEVICE_EXTENSION); - - if (DeviceIsMmcUpdateRequired(deviceExtension->Device)) - { - // Issue command to update the drive capabilities. - // The failure of MMC update is not considered critical, - // so that we'll continue to process I/O even MMC update fails. - DeviceUpdateMmcCapabilities(deviceExtension->Device); - } - - RequestProcessSerializedIoctl(deviceExtension, deviceExtension->IoctlWorkItemContext.OriginalRequest); -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -RequestProcessSerializedIoctl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request - ) -/*++ -Routine Description: - - a dispatch routine for all functions to process IOCTLs. - -Arguments: - - DeviceExtension - device context - - Request - handle to the incoming WDF Request object - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - size_t information = 0; - WDF_REQUEST_PARAMETERS requestParameters; - BOOLEAN completeRequest = TRUE; - - PAGED_CODE (); - - // Get the Request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - NormalizeIoctl(&requestParameters); - - // process IOCTLs - switch (requestParameters.Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_CDROM_READ_TOC: - case IOCTL_CDROM_GET_LAST_SESSION: - status = RequestHandleReadTOC(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_CDROM_READ_TOC_EX: - status = RequestHandleReadTocEx(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_CDROM_GET_CONFIGURATION: - status = RequestHandleGetConfiguration(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_CDROM_RAW_READ: - status = DeviceHandleRawRead(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_DISK_GET_LENGTH_INFO: - case IOCTL_DISK_GET_DRIVE_GEOMETRY: - case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: - case IOCTL_STORAGE_READ_CAPACITY: - status = RequestHandleGetDriveGeometry(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_DISK_VERIFY: - status = RequestHandleDiskVerify(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_STORAGE_CHECK_VERIFY: - // IOCTL_STORAGE_CHECK_VERIFY2 was processed including send a Test Unit Read - // with srb flag SRB_CLASS_FLAGS_LOW_PRIORITY to port driver asynchronizelly. - // The original request was completed after TUR finishes. - // As CDROM.SYS serializes IOs need accessing device, it's not a big difference from above behavior to - // just process it in serialized manner. So I put it here and treat it as same as IOCTL_STORAGE_CHECK_VERIFY. - case IOCTL_STORAGE_CHECK_VERIFY2: - status = RequestHandleCheckVerify(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_DISK_GET_DRIVE_LAYOUT: - case IOCTL_DISK_GET_DRIVE_LAYOUT_EX: - case IOCTL_DISK_GET_PARTITION_INFO: - case IOCTL_DISK_GET_PARTITION_INFO_EX: - status = RequestHandleFakePartitionInfo(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_DISK_IS_WRITABLE: - // - // Even though this media is writable, the requester of this IOCTL really - // wants to know if thw media behaves like any other disk or not. This is - // so if FeatureDefectManagement and FeatureRandomWritable are current on - // the drive-represented by the FeatureDefectManagement validation schema - // - if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed && - (DeviceExtension->DeviceAdditionalData.Mmc.ValidationSchema == FeatureDefectManagement)) - { - status = STATUS_SUCCESS; - } - else - { - status = STATUS_MEDIA_WRITE_PROTECTED; - } - information = 0; - break; - - case IOCTL_CDROM_PLAY_AUDIO_MSF: - status = DeviceHandlePlayAudioMsf(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_CDROM_READ_Q_CHANNEL: - status = DeviceHandleReadQChannel(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_CDROM_PAUSE_AUDIO: - status = DeviceHandlePauseAudio(DeviceExtension, Request, &information); - break; - - case IOCTL_CDROM_RESUME_AUDIO: - status = DeviceHandleResumeAudio(DeviceExtension, Request, &information); - break; - - case IOCTL_CDROM_SEEK_AUDIO_MSF: - status = DeviceHandleSeekAudioMsf(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_CDROM_STOP_AUDIO: - status = DeviceHandleStopAudio(DeviceExtension, Request, &information); - break; - - case IOCTL_CDROM_GET_VOLUME: - case IOCTL_CDROM_SET_VOLUME: - status = DeviceHandleGetSetVolume(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_DVD_GET_REGION: - status = RequestHandleGetDvdRegion(DeviceExtension, Request, &information); - break; - - case IOCTL_DVD_READ_STRUCTURE: - status = DeviceHandleReadDvdStructure(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_DVD_END_SESSION: - status = DeviceHandleDvdEndSession(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_DVD_START_SESSION: - case IOCTL_DVD_READ_KEY: - status = DeviceHandleDvdStartSessionReadKey(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_DVD_SEND_KEY: - case IOCTL_DVD_SEND_KEY2: - status = DeviceHandleDvdSendKey(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_STORAGE_SET_READ_AHEAD: - status = DeviceHandleSetReadAhead(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_CDROM_SET_SPEED: - status = DeviceHandleSetSpeed(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE: - case IOCTL_AACS_READ_MEDIA_KEY_BLOCK: - status = DeviceHandleAacsReadMediaKeyBlock(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_START_SESSION: - status = DeviceHandleAacsStartSession(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_END_SESSION: - status = DeviceHandleAacsEndSession(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_SEND_CERTIFICATE: - status = DeviceHandleAacsSendCertificate(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_GET_CERTIFICATE: - status = DeviceHandleAacsGetCertificate(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_GET_CHALLENGE_KEY: - status = DeviceHandleAacsGetChallengeKey(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_SEND_CHALLENGE_KEY: - status = DeviceHandleSendChallengeKey(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_READ_VOLUME_ID: - status = DeviceHandleReadVolumeId(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_READ_SERIAL_NUMBER: - status = DeviceHandleAacsReadSerialNumber(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_READ_MEDIA_ID: - status = DeviceHandleAacsReadMediaId(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_READ_BINDING_NONCE: - status = DeviceHandleAacsReadBindingNonce(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_AACS_GENERATE_BINDING_NONCE: - status = DeviceHandleAacsGenerateBindingNonce(DeviceExtension, Request, requestParameters, &information); - break; - - case IOCTL_CDROM_ENABLE_STREAMING: - status = RequestHandleEnableStreaming(DeviceExtension, Request, &information); - break; - - case IOCTL_CDROM_SEND_OPC_INFORMATION: - status = RequestHandleSendOpcInformation(DeviceExtension, Request, &information); - break; - - case IOCTL_CDROM_GET_PERFORMANCE: - status = RequestHandleGetPerformance(DeviceExtension, Request, requestParameters, &information); - break; - - // This IOCTL is a fake one, used for MCN process sync-ed with serial queue. - case IOCTL_MCN_SYNC_FAKE_IOCTL: - status = RequestHandleMcnSyncFakeIoctl(DeviceExtension, &information); - break; - - case IOCTL_STORAGE_MEDIA_REMOVAL: - case IOCTL_STORAGE_EJECTION_CONTROL: - { - status = RequestHandleEjectionControl(DeviceExtension, Request, requestParameters, &information); - - break; - } - - case IOCTL_STORAGE_EJECT_MEDIA: - case IOCTL_STORAGE_LOAD_MEDIA: - case IOCTL_STORAGE_LOAD_MEDIA2: - { - status = RequestHandleLoadEjectMedia(DeviceExtension, Request, requestParameters, &information); - - break; - } - - case IOCTL_STORAGE_MCN_CONTROL: - { - status = RequestHandleMcnControl(DeviceExtension, Request, &information); - - break; - } - - case IOCTL_STORAGE_RESERVE: - case IOCTL_STORAGE_RELEASE: - { - status = RequestHandleReserveRelease(DeviceExtension, Request, requestParameters, &information); - - break; - } - - case IOCTL_STORAGE_PERSISTENT_RESERVE_IN: - case IOCTL_STORAGE_PERSISTENT_RESERVE_OUT: - { - status = RequestHandlePersistentReserve(DeviceExtension, Request, requestParameters, &information); - - break; - } - -#if (NTDDI_VERSION >= NTDDI_WIN8) - case IOCTL_DISK_ARE_VOLUMES_READY: - { - status = RequestHandleAreVolumesReady(DeviceExtension, Request, requestParameters, &information); - - completeRequest = FALSE; - - break; - } - - case IOCTL_VOLUME_ONLINE: - case IOCTL_VOLUME_POST_ONLINE: - { - status = RequestHandleVolumeOnline(DeviceExtension, Request, requestParameters, &information); - - break; - } -#endif - - default: - { - status = STATUS_ACCESS_DENIED; - break; - } - } // end of switch(ioctl) - - if (completeRequest) - { - RequestCompletion(DeviceExtension, Request, status, information); - } - - return status; -} - -VOID -SequentialQueueEvtCanceledOnQueue( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request - ) -/*++ -Routine Description: - - Perform cancellation when request is still in queue. - - If request is sych-ed in another thread, signal the event to let that thread be able to complete the request. - Otherwise, complete the request. - -Arguments: - - Queue - serial queue - Request - handle to the incoming WDF Request object - -Return Value: - - None - ---*/ -{ - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - - if (requestContext->SyncRequired) - { - KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE); - } - else - { - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - WDFDEVICE device = WdfIoQueueGetDevice(Queue); - - deviceExtension = DeviceGetExtension(device); - - RequestCompletion(deviceExtension, Request, STATUS_CANCELLED, 0); - - } - - return; -} - - -NTSTATUS -RequestSynchronizeProcessWithSerialQueue( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ -Routine Description: - - This is the mechanism to sync a request process in original thread with serialize queue. - initialize a EVENT and put the request inot serialize queue; - waiting for serialize queue processes to this request and signal the EVENT; - call the request handler to process this request. - -Arguments: - - DeviceExtension - device context - - Request - handle to the incoming WDF Request object - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - PKEVENT bufferToFree = requestContext->SyncEvent; - - if (KeGetCurrentIrql() >= DISPATCH_LEVEL) { - // cannot block at or above DISPATCH_LEVEL - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestSynchronousProcessWithSerialQueue called at DISPATCH_LEVEL or above")); - NT_ASSERT(FALSE); - RequestCompletion(deviceExtension, Request, STATUS_INVALID_LEVEL, 0); - return STATUS_INVALID_LEVEL; - } - - // init the synchronization event - KeInitializeEvent(requestContext->SyncEvent, NotificationEvent, FALSE); - - // do we still need to do something like this? - // SET_FLAG(nextStack->Flags, SL_OVERRIDE_VERIFY_VOLUME); - - // NOTE: this mechanism relies on that KMDF will not complete request by itself. - // Doing that will cause the syncEvent not fired thus this thread will stuck. - // This should not really happen: our EvtCanceledOnQueue callbacks should be - // called even if queues are purged for some reason. The only case when these - // callbacks are not called is when a request is owned by the driver (i.e. has - // already been passed to one of the registered handlers). In this case, it is - // our responsibility to cancel such requests properly. - status = WdfDeviceEnqueueRequest(Device, Request); - - if (!NT_SUCCESS(status)) - { - // Failed to forward request! Pretend the sync event already occured, otherwise we'll hit - // an assert in RequestEvtCleanup. - KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE); - RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request)); - } - else - { - NTSTATUS waitStatus = STATUS_UNSUCCESSFUL; - PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData); - BOOLEAN fCallSyncCallback = FALSE; - PIRP irp = WdfRequestWdmGetIrp(Request); - - // ok, now wait on the event - while (waitStatus != STATUS_SUCCESS) - { - waitStatus = KeWaitForSingleObject(requestContext->SyncEvent, Executive, KernelMode, TRUE, NULL); - if (waitStatus == STATUS_SUCCESS) // must check equality -- STATUS_ALERTED is success code - { - // do nothing - } - else if (waitStatus != STATUS_ALERTED) - { - // do nothing - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_IOCTL, - "Request %p on device object %p had a non-alert, non-success result from wait (%!HRESULT!)\n", - Request, Device, waitStatus)); - NT_ASSERT(FALSE); - } - else if (PsIsThreadTerminating(PsGetCurrentThread())) - { - // the thread was alerted and is terminating, so cancel the irp - // this will cause EvtIoCanceledOnQueue to be called, which will signal the event, - // so we will get out of the while loop and eventually complete the request. - if (IoCancelIrp(irp)) - { - // cancellation routine was called - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "Sychronize Ioctl: request %p cancelled from device %p\n", - Request, Device)); - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "Sychronize Ioctl: request %p could not be cancelled from device %p\n", - Request, Device)); - } - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "SPURIOUS ALERT waiting for Request %p on device %p (%!STATUS!)\n", - Request, Device, status)); - } - } // end of wait loop on the event - - // because we've waited an unknown amount of time, should check - // the cancelled flag to immediately fail the irp as appropriate - if (WdfRequestIsCanceled(Request)) - { - // the request was cancelled, thus we should always stop - // processing here if possible. - status = STATUS_CANCELLED; - RequestCompletion(deviceExtension, Request, status, 0); - } - else if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request))) - { - WDF_REQUEST_PARAMETERS requestParameters; - BOOLEAN isBlocked = FALSE; - - // get the request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - status = RequestIsIoctlBlockedByExclusiveAccess(Request, &isBlocked); - if (isBlocked) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "Access Denied! Device in exclusive mode.Failing Ioctl %lx\n", - requestParameters.Parameters.DeviceIoControl.IoControlCode)); - RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0); - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "Ioctl %lx not blocked by cdrom being in exclusive mode\n", - requestParameters.Parameters.DeviceIoControl.IoControlCode)); - fCallSyncCallback = TRUE; - } - } - else - { - fCallSyncCallback = TRUE; - } - - if (fCallSyncCallback) - { - // Synchronization completed successfully. Call the requested routine - status = requestContext->SyncCallback(Device, Request); - } - } - - // The next SequentialQueue evt routine will not be triggered until the current request is completed. - - // clean up the request context setting. - FREE_POOL(bufferToFree); - - return status; -} - -NTSTATUS -RequestIsIoctlBlockedByExclusiveAccess( - _In_ WDFREQUEST Request, - _Out_ PBOOLEAN IsBlocked - ) -/*++ -Routine Description: - - Check if the IOCTL request should be blocked or not according to - the exclusive lock stat. - -Arguments: - - Request - handle to the incoming WDF Request object - -Return Value: - - NTSTATUS - - IsBlocked - TRUE (be blocked); FALSE (not blocked) - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - ULONG ioctlCode = 0; - ULONG baseCode = 0; - WDF_REQUEST_PARAMETERS requestParameters; - - // Get the Request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - // check and initialize parameter - if (IsBlocked == NULL) - { - //This is an internal function and this parameter must be supplied. - NT_ASSERT(FALSE); - - return STATUS_INVALID_PARAMETER; - } - else - { - *IsBlocked = FALSE; - } - - // check if this is an IOCTL - if ((requestParameters.Type == WdfRequestTypeDeviceControl) || - (requestParameters.Type == WdfRequestTypeDeviceControlInternal)) - { - // - // Allow minimum set of commands that are required for the disk manager - // to show the CD device, while in exclusive mode. - // Note: These commands should not generate any requests to the device, - // and thus must be handled directly in StartIO during exclusive - // access (except for the exclusive owner, of course). - // - ioctlCode = requestParameters.Parameters.DeviceIoControl.IoControlCode; - baseCode = DEVICE_TYPE_FROM_CTL_CODE(ioctlCode); - - if (ioctlCode == IOCTL_SCSI_GET_ADDRESS || - ioctlCode == IOCTL_STORAGE_GET_HOTPLUG_INFO || - ioctlCode == IOCTL_STORAGE_GET_DEVICE_NUMBER || - ioctlCode == IOCTL_STORAGE_GET_MEDIA_TYPES_EX || - ioctlCode == IOCTL_CDROM_EXCLUSIVE_ACCESS || - ioctlCode == IOCTL_CDROM_GET_INQUIRY_DATA - ) - { - *IsBlocked = FALSE; - } - - // - // Handle IOCTL_STORAGE_QUERY_PROPERTY special because: - // (1) PropertyExistsQuery should not generate device i/o - // (2) Queries for StorageDeviceProperty and StorageAdapterDescriptor - // will return cache'd data - else if (ioctlCode == IOCTL_STORAGE_QUERY_PROPERTY) - { - PSTORAGE_PROPERTY_QUERY query = NULL; - status = WdfRequestRetrieveInputBuffer(Request, - requestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&query, - NULL); - - if (NT_SUCCESS(status)) - { - if (query != NULL) - { - if (query->QueryType == PropertyExistsQuery) - { - *IsBlocked = FALSE; - } - else if ((query->QueryType == PropertyStandardQuery) && - ((query->PropertyId == StorageDeviceProperty) || - (query->PropertyId == StorageAdapterProperty))) - { - *IsBlocked = FALSE; - } - } - } - } - - // Return TRUE for unknown IOCTLs with STORAGE bases - else if (baseCode == IOCTL_SCSI_BASE || - baseCode == IOCTL_DISK_BASE || - baseCode == IOCTL_CDROM_BASE || - baseCode == IOCTL_STORAGE_BASE || - baseCode == IOCTL_DVD_BASE ) - { - *IsBlocked = TRUE; - } - } - else - { - // this should only be called with an IOCTL - NT_ASSERT(FALSE); - - status = STATUS_INVALID_PARAMETER; - } - - return status; -} - -BOOLEAN -DeviceIsMmcUpdateRequired( - _In_ WDFDEVICE Device - ) -/*++ -Routine Description: - - Check if the device needs to update its MMC information. - -Arguments: - - Device - device to be checked. - -Return Value: - - TRUE (require update); FALSE (not require update) - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData); - - if ((cdData->Mmc.IsMmc) && - (cdData->Mmc.UpdateState == CdromMmcUpdateRequired)) - { - return TRUE; - } - else - { - // no update required: just proceed - return FALSE; - } -} - -VOID -RequestEvtCleanup( - _In_ WDFOBJECT Request - ) -/*++ -Routine Description: - - Request cleanup callback. - -Arguments: - - Request - request to clean up. - -Return Value: - - None - ---*/ -{ - WDFREQUEST request = (WDFREQUEST)Request; - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(request); - - if (requestContext->SyncRequired) - { - // the event should have been signaled, just check that - NT_ASSERT(KeReadStateEvent(requestContext->SyncEvent) != 0); - } -} - diff --git a/storage/class/cdrom/src/cdrom.h b/storage/class/cdrom/src/cdrom.h deleted file mode 100644 index 472e240e..00000000 --- a/storage/class/cdrom/src/cdrom.h +++ /dev/null @@ -1,1609 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - cdrom.h - -Abstract: - - Main header file for cdrom.sys. - This contains structure and function declarations as well as constant values. - -Author: - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - -#ifndef __CDROM_H__ -#define __CDROM_H__ - -#pragma warning(push) -#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union -#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int -#pragma warning(disable:4152) // nonstandard extension, function/data pointer conversion in expression - -#include "wdf.h" -#include "ntddmmc.h" -#include "ntddcdvd.h" -#include "ntddcdrm.h" -#include "ntdddisk.h" -#include "ntddtape.h" -#include "ntddscsi.h" -#include "ntddvol.h" -#include "specstrings.h" -#include "cdromp.h" - -// Set component ID for DbgPrintEx calls -#ifndef DEBUG_COMP_ID - #define DEBUG_COMP_ID DPFLTR_CDROM_ID -#endif - -// Include initguid.h so GUID_CONSOLE_DISPLAY_STATE is declared -#include <initguid.h> - -// Include header file and setup GUID for tracing -#include <storswtr.h> -#define WPP_GUID_CDROM (A4196372, C3C4, 42d5, 87BF, 7EDB2E9BCC27) -#ifndef WPP_CONTROL_GUIDS - #define WPP_CONTROL_GUIDS WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_CDROM) -#endif - -// This prototype is needed because, although NTIFS.H is now shipping with -// the WDK, can't include both it and the other headers we already use. -_IRQL_requires_max_(DISPATCH_LEVEL) -NTKERNELAPI -BOOLEAN -PsIsThreadTerminating( - _In_ PETHREAD Thread - ); - -// -// -extern CDROM_SCAN_FOR_SPECIAL_INFO CdromHackItems[]; - -#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) -- obsolete -//#define CDROM_HACK_PLEXTOR_CDDA (0x00000080) -- obsolete -#define CDROM_HACK_BAD_GET_CONFIG_SUPPORT (0x00000100) -//#define CDROM_HACK_FORCE_READ_CD_DETECTION (0x00000200) -- obsolete -//#define CDROM_HACK_READ_CD_SUPPORTED (0x00000400) -- obsolete -#define CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG (0x00000800) -#define CDROM_HACK_BAD_VENDOR_PROFILES (0x00001000) -#define CDROM_HACK_MSFT_VIRTUAL_ODD (0x00002000) -#define CDROM_HACK_LOCKED_PAGES (0x80000000) // not a valid flag to save - -#define CDROM_HACK_VALID_FLAGS (0x00003fff) -#define CDROM_HACK_INVALID_FLAGS (~CDROM_HACK_VALID_FLAGS) - - -// A 64k buffer to be written takes the following amount of time: -// 1x CD == 75 sectors/sec == 0.4266667 seconds == 4266667 100ns units -// 4x CD == 300 sectors/sec == 0.1066667 seconds == 1066667 100ns units -// 10x CD == 300 sectors/sec == 0.0426667 seconds == 426667 100ns units -// 1x DVD == 676 sectors/sec == 0.0473373 seconds == 473373 100ns units -// 16x DVD == 10,816 sectors/sec == 0.0029586 seconds == 29586 100ns units -// 1x HDDVD == 2,230 sectors/sec == 0.0143498 seconds == 143498 100ns units -#define WRITE_RETRY_DELAY_CD_1x ((LONGLONG)4266667) -#define WRITE_RETRY_DELAY_CD_4x ((LONGLONG)1066667) -#define WRITE_RETRY_DELAY_CD_10x ((LONGLONG) 426667) -#define WRITE_RETRY_DELAY_DVD_1x ((LONGLONG) 473373) -#define WRITE_RETRY_DELAY_DVD_4x ((LONGLONG) 118343) -#define WRITE_RETRY_DELAY_DVD_16x ((LONGLONG) 29586) -#define WRITE_RETRY_DELAY_HDDVD_1x ((LONGLONG) 143498) - -// -#define MAXIMUM_RETRIES 4 - -#define CDROM_GET_CONFIGURATION_TIMEOUT (0x4) -#define CDROM_READ_DISC_INFORMATION_TIMEOUT (0x4) -#define CDROM_TEST_UNIT_READY_TIMEOUT (0x14) -#define CDROM_GET_PERFORMANCE_TIMEOUT (0x14) -#define CDROM_READ_CAPACITY_TIMEOUT (0x14) - -#define START_UNIT_TIMEOUT (60 * 4) - -// Used to detect the loss of the autorun irp. -#define MEDIA_CHANGE_TIMEOUT_TIME 300 - -// Indicates whether is is safe to send StartUnit commands -// to this device. It will only be off for some removeable devices. -#define DEV_SAFE_START_UNIT 0x00000004 - -// Indicates that the device is connected to a backup power supply -// and hence write-through and synch cache requests may be ignored -#define DEV_POWER_PROTECTED 0x00000010 - -// The following CDROM_SPECIAL_ flags are set in ScanForSpecialFlags -// in the Device Extension - -// Never Spin Up/Down the drive (may not handle properly) -#define CDROM_SPECIAL_DISABLE_SPIN_DOWN 0x00000001 -//#define CDROM_SPECIAL_DISABLE_SPIN_UP 0x00000002 - -// Don't bother to lock the queue when powering down -// (used mostly to send a quick stop to a cdrom to abort audio playback) -//#define CDROM_SPECIAL_NO_QUEUE_LOCK 0x00000008 - -// Disable write cache due to known bugs -#define CDROM_SPECIAL_DISABLE_WRITE_CACHE 0x00000010 - -// Used to indicate that this request shouldn't invoke any power type operations -// like spinning up the drive. - -#define SRB_CLASS_FLAGS_LOW_PRIORITY 0x10000000 - -// Used to indicate that an SRB is the result of a paging operation. -#define SRB_CLASS_FLAGS_PAGING 0x40000000 - -typedef struct _ERROR_RECOVERY_DATA { - MODE_PARAMETER_HEADER Header; - MODE_PARAMETER_BLOCK BlockDescriptor; - MODE_READ_RECOVERY_PAGE ReadRecoveryPage; -} ERROR_RECOVERY_DATA, *PERROR_RECOVERY_DATA; - -// A compile-time check of the 30,000 limit not overflowing ULONG size... -// Note that it is not expected that a release (FRE) driver will normally -// have such a large history, instead using the compression function. -#define CDROM_INTERPRET_SENSE_INFO2_MAXIMUM_HISTORY_COUNT 30000 -C_ASSERT( (MAXULONG - sizeof(SRB_HISTORY)) / 30000 >= sizeof(SRB_HISTORY_ITEM) ); - -// Intended to reuse a defined IOCTL code that not seen in Optical stack and does not require input parameter. -// This fake IOCTL is used used for MCN process sync-ed with serial queue. -#define IOCTL_MCN_SYNC_FAKE_IOCTL IOCTL_DISK_UPDATE_DRIVE_SIZE - -/*++//////////////////////////////////////////////////////////////////////////// - -PCDROM_ERROR_HANDLER() - -Routine Description: - - This routine is a callback into the driver to handle errors. The queue - shall not be unfrozen when this error handler is called, even though the - SRB flags may mark the queue as having been frozen due to this SRB. - -Irql: - - This routine will be called at KIRQL <= DISPATCH_LEVEL - -Arguments: - - DeviceObject is the device object the error occurred on. - - Srb is the Srb that was being processed when the error occurred. - - Status may be overwritten by the routine if it decides that the error - was benign, or otherwise wishes to change the returned status code - for this command - - Retry may be overwritten to specify that this command should or should - not be retried (if the callee supports retrying commands) - -Return Value: - - status - ---*/ -struct _CDROM_DEVICE_EXTENSION; // *PCDROM_DEVICE_EXTENSION; -typedef struct _CDROM_DEVICE_EXTENSION - CDROM_DEVICE_EXTENSION, - *PCDROM_DEVICE_EXTENSION; - -typedef -VOID -(*PCDROM_ERROR_HANDLER) ( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _Inout_ PNTSTATUS Status, - _Inout_ PBOOLEAN Retry - ); - -// CdRom driver extension -typedef struct _CDROM_DRIVER_EXTENSION { - ULONG Version; - PDRIVER_OBJECT DriverObject; - ULONG Flags; - -} CDROM_DRIVER_EXTENSION, *PCDROM_DRIVER_EXTENSION; - -#define CDROM_FLAG_WINPE_MODE 0x00000001 - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CDROM_DRIVER_EXTENSION, DriverGetExtension) - -#define CdromMmcUpdateComplete 0 -#define CdromMmcUpdateRequired 1 -#define CdromMmcUpdateStarted 2 - -typedef struct _CDROM_MMC_EXTENSION { - - BOOLEAN IsMmc; // mmc device - BOOLEAN IsAACS; // aacs compatible device - BOOLEAN IsWriter; // the drive is a writer or not - BOOLEAN WriteAllowed; // currently allow write request or not - - BOOLEAN IsCssDvd; // A CSS protected DVD or CPPM-protected DVDAudio media in Drive. - BOOLEAN StreamingReadSupported; // the drive supports streaming for reads - BOOLEAN StreamingWriteSupported; // the drive supports streaming for writes - - LONG UpdateState; - - // The feature number defines the level and form of - // validation that needs to be performed on Io requests - FEATURE_NUMBER ValidationSchema; - ULONG Blocking; - - SCSI_REQUEST_BLOCK CapabilitiesSrb; - PIRP CapabilitiesIrp; - WDFREQUEST CapabilitiesRequest; - SENSE_DATA CapabilitiesSenseData; - _Field_size_bytes_(CapabilitiesBufferSize) - PGET_CONFIGURATION_HEADER CapabilitiesBuffer; - ULONG CapabilitiesBufferSize; - PMDL CapabilitiesMdl; - - BOOLEAN ReadCdC2Pointers; - BOOLEAN ReadCdSubCode; - -} CDROM_MMC_EXTENSION, *PCDROM_MMC_EXTENSION; - -typedef struct _CDROM_SCRATCH_READ_WRITE_CONTEXT { - - // Information about the data that we need to read/write - ULONG PacketsCount; - ULONG TransferedBytes; - ULONG EntireXferLen; - ULONG MaxLength; - PUCHAR DataBuffer; - LARGE_INTEGER StartingOffset; - BOOLEAN IsRead; - - // A pointer to the SRB history item to be filled upon completion - PSRB_HISTORY_ITEM SrbHistoryItem; - -} CDROM_SCRATCH_READ_WRITE_CONTEXT, *PCDROM_SCRATCH_READ_WRITE_CONTEXT; - -// Many commands get double-buffered. Since the max -// transfer size is typically 64k, most of these requests -// can be handled with a single pre-allocated buffer. -typedef struct _CDROM_SCRATCH_CONTEXT { - - _Field_range_(4*1024, 64*1024) ULONG ScratchBufferSize; // 0x1000..0x10000 (4k..64k) - _Field_size_bytes_(ScratchBufferSize) PVOID ScratchBuffer; // used to get data for clients - - PMDL ScratchBufferMdl; // used to get data for clients - - WDFREQUEST ScratchRequest; - PSCSI_REQUEST_BLOCK ScratchSrb; - PSENSE_DATA ScratchSense; - PSRB_HISTORY ScratchHistory; - - // This MDL is used to performed the request whose required transfer size is bigger than adaptor's max. - PMDL PartialMdl; - BOOLEAN PartialMdlIsBuilt; - - // For debugging, set/clear this field when using the scratch buffer/request - PVOID ScratchInUse; - PCSTR ScratchInUseFileName; - ULONG ScratchInUseLineNumber; - - // Stuff for asynchronous retrying of the transfer. - ULONG NumRetries; - - // Read Write context - CDROM_SCRATCH_READ_WRITE_CONTEXT ScratchReadWriteContext; - -} CDROM_SCRATCH_CONTEXT, *PCDROM_SCRATCH_CONTEXT; - -// Context structure for the IOCTL work item -typedef struct _CDROM_IOCTL_CONTEXT { - - WDFREQUEST OriginalRequest; - -} CDROM_IOCTL_CONTEXT, *PCDROM_IOCTL_CONTEXT; - -// Context structure for the read/write work item -typedef struct _CDROM_READ_WRITE_CONTEXT { - - WDFREQUEST OriginalRequest; - -} CDROM_READ_WRITE_CONTEXT, *PCDROM_READ_WRITE_CONTEXT; - -typedef struct _CDROM_DATA { - - CDROM_MMC_EXTENSION Mmc; - - // hack flags for ScanForSpecial routines - ULONG_PTR HackFlags; - - // the error handling routines need to be per-device, not per-driver.... - PCDROM_ERROR_HANDLER ErrorHandler; - - // Indicates whether an audio play operation is currently being performed. - // Only thing this does is prevent reads and toc requests while playing audio. - BOOLEAN PlayActive; - - // indicate we need to pick a default dvd region for the user if we can - ULONG PickDvdRegion; - - // The well known name link for this device. - UNICODE_STRING WellKnownName; - - // We need to distinguish between the two... - ULONG MaxPageAlignedTransferBytes; - ULONG MaxUnalignedTransferBytes; - - // Indicates that this is a DEC RRD cdrom. - // This drive requires software to fix responses from the faulty firmware - BOOLEAN IsDecRrd; - - // Storage for the error recovery page. This is used as the method - // to switch block sizes for some drive-specific error recovery routines. - // ERROR_RECOVERY_DATA recoveryData; //obsolete along with error process for TOSHIBA_XM_3xx - - // Indicates that the device is in exclusive mode and only - // the requests from the exclusive owner will be processed. - WDFFILEOBJECT ExclusiveOwner; - - // Caller name of the owner, if the device is in exclusive mode. - UCHAR CallerName[CDROM_EXCLUSIVE_CALLER_LENGTH]; - - // Indicates that the device speed should be set to - // default value on the next media change. - BOOLEAN RestoreDefaults; - - // How long to wait between retries if a READ/WRITE irp - // gets a LWIP (2/4/7, 2/4/8)? - LONGLONG ReadWriteRetryDelay100nsUnits; - - // Cached Device Type information. Maybe FILE_DEVICE_CD_ROM or FILE_DEVICE_DVD - // CommonExtension.DevInfo->DeviceType maybe FILE_DEVICE_CD_ROM when this field is FILE_DEVICE_DVD - DEVICE_TYPE DriveDeviceType; - - _Field_size_bytes_(CachedInquiryDataByteCount) - PINQUIRYDATA CachedInquiryData; - ULONG CachedInquiryDataByteCount; - -} CDROM_DATA, *PCDROM_DATA; - - -typedef struct _CDROM_POWER_OPTIONS { - ULONG PowerDown : 1; - ULONG LockQueue : 1; - ULONG HandleSpinDown : 1; - ULONG HandleSpinUp : 1; - ULONG Reserved : 27; -} CDROM_POWER_OPTIONS, *PCDROM_POWER_OPTIONS; - -// this is a private enum, but must be kept here -// to properly compile size of CDROM_DEVICE_EXTENSION -typedef enum { - PowerDownDeviceInitial, - PowerDownDeviceLocked, - PowerDownDeviceQuiesced, - PowerDownDeviceFlushed, - PowerDownDeviceStopped, - PowerDownDeviceOff, - PowerDownDeviceUnlocked -} CDROM_POWER_DOWN_STATE; - -// this is a private enum, but must be kept here -// to properly compile size of CDROM_DEVICE_EXTENSION -typedef enum { - PowerUpDeviceInitial, - PowerUpDeviceLocked, - PowerUpDeviceOn, - PowerUpDeviceStarted, - PowerUpDeviceUnlocked -} CDROM_POWER_UP_STATE; - -// this is a private structure, but must be kept here -// to properly compile size of CDROM_DEVICE_EXTENSION -typedef struct _CDROM_POWER_CONTEXT { - - BOOLEAN InUse; - - LARGE_INTEGER StartTime; - LARGE_INTEGER Step1CompleteTime; // for SYNC CACHE in power down case - LARGE_INTEGER CompleteTime; - - union { - CDROM_POWER_DOWN_STATE PowerDown; - CDROM_POWER_UP_STATE PowerUp; // currently not used. - } PowerChangeState; - - CDROM_POWER_OPTIONS Options; - - WDFREQUEST PowerRequest; - - SCSI_REQUEST_BLOCK Srb; - SENSE_DATA SenseData; - - ULONG RetryCount; - LONGLONG RetryIntervalIn100ns; - -} CDROM_POWER_CONTEXT, *PCDROM_POWER_CONTEXT; - -// device extension structure -typedef struct _CDROM_DEVICE_EXTENSION { - - // Version control field - ULONG Version; - - // structure size - ULONG Size; - - // the structure is fully ready to use - BOOLEAN IsInitialized; - - // the device is active - BOOLEAN IsActive; - - // the device is surprise removed. - BOOLEAN SurpriseRemoved; - - // Back pointer to device object - WDFDEVICE Device; - - // Save IoTarget here, do not retrieve anytime. - WDFIOTARGET IoTarget; - - // Additional WDF queue for serial I/O processing - WDFQUEUE SerialIOQueue; - - // A separate queue for all the create file requests in sync with device - // removal - WDFQUEUE CreateQueue; - - //Main timer of driver, will do Mcn work. (once per second) - WDFTIMER MainTimer; - - // Pointer to the initialization data for this driver. This is more - // efficient than constantly getting the driver extension. - PCDROM_DRIVER_EXTENSION DriverExtension; - - // WDM device information - PDEVICE_OBJECT DeviceObject; - - // Pointer to the physical device object we attached to - PDEVICE_OBJECT LowerPdo; - - // FILE_DEVICE_CD_ROM -- 2 - DEVICE_TYPE DeviceType; - - // The name of the object - UNICODE_STRING DeviceName; - - // System device number - ULONG DeviceNumber; - - // Values for the flags are below. - USHORT DeviceFlags; - - // Flags for special behaviour required by different hardware, - // such as never spinning down or disabling advanced features such as write cache - ULONG ScanForSpecialFlags; - - // Add default Srb Flags. - ULONG SrbFlags; - - // Request timeout in seconds; - ULONG TimeOutValue; - - //The SCSI address of the device. - SCSI_ADDRESS ScsiAddress; - - // Buffer for drive parameters returned in IO device control. - DISK_GEOMETRY DiskGeometry; - - // Log2 of sector size - UCHAR SectorShift; - - // Length of partition in bytes - LARGE_INTEGER PartitionLength; - - // Number of bytes before start of partition - LARGE_INTEGER StartingOffset; - - // Interface name string returned by IoRegisterDeviceInterface. - UNICODE_STRING MountedDeviceInterfaceName; - - // Device capabilities - PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor; - - // SCSI port driver capabilities - PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor; - - // Device power properties - PDEVICE_POWER_DESCRIPTOR PowerDescriptor; - - // Request Sense Buffer - PSENSE_DATA SenseData; - - // Total number of SCSI protocol errors on the device. - ULONG ErrorCount; - - // Lock count for removable media. - LONG LockCount; - LONG ProtectedLockCount; - LONG InternalLockCount; - - KEVENT EjectSynchronizationEvent; - WDFWAITLOCK EjectSynchronizationLock; - - // Indicates that the necessary data structures for media change - // detection have been initialized. - PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo; - - // Contains necessary data structures for ZPODD support. - PZERO_POWER_ODD_INFO ZeroPowerODDInfo; - - // File system context. Used for kernel-mode requests to disable autorun. - FILE_OBJECT_CONTEXT KernelModeMcnContext; - - // Count of media changes. This field is only valid for the root partition - // (ie. if PhysicalDevice == NULL). - ULONG MediaChangeCount; - - // Storage for a release queue request. - WDFSPINLOCK ReleaseQueueSpinLock; - WDFREQUEST ReleaseQueueRequest; - SCSI_REQUEST_BLOCK ReleaseQueueSrb; - WDFMEMORY ReleaseQueueInputMemory; //This is a wrapper of ReleaseQueueSrb - BOOLEAN ReleaseQueueNeeded; - BOOLEAN ReleaseQueueInProgress; - - // Context structure for power operations. Since we can only have - // one D irp at any time in the stack we don't need to worry about - // allocating multiple of these structures. - CDROM_POWER_CONTEXT PowerContext; - BOOLEAN PowerDownInProgress; - -#if (NTDDI_VERSION >= NTDDI_WIN8) - BOOLEAN IsVolumeOnlinePending; - WDFQUEUE ManualVolumeReadyQueue; -#endif - - // Lock for Shutdown/Flush operations that need to stop/start the queue - WDFWAITLOCK ShutdownFlushWaitLock; - - // device specific data area - CDROM_DATA DeviceAdditionalData; - - // scratch buffer related fields. - CDROM_SCRATCH_CONTEXT ScratchContext; - - // Hold new private data that only classpnp should modify - // in this structure. - PCDROM_PRIVATE_FDO_DATA PrivateFdoData; - - // Work item for async reads and writes and its context - WDFWORKITEM ReadWriteWorkItem; - CDROM_READ_WRITE_CONTEXT ReadWriteWorkItemContext; - - // Auxiliary WDF object for processing ioctl requests that need to go down - // to the port driver. - WDFWORKITEM IoctlWorkItem; - CDROM_IOCTL_CONTEXT IoctlWorkItemContext; - -} CDROM_DEVICE_EXTENSION, *PCDROM_DEVICE_EXTENSION; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CDROM_DEVICE_EXTENSION, DeviceGetExtension) - -// a type definition for functions to be called after synchronization -typedef -NTSTATUS -SYNC_HANDLER ( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ); - -typedef SYNC_HANDLER *PSYNC_HANDLER ; - -typedef struct _CDROM_REQUEST_CONTEXT { - PCDROM_DEVICE_EXTENSION DeviceExtension; - - WDFREQUEST OriginalRequest; - - LARGE_INTEGER TimeReceived; - LARGE_INTEGER TimeSentDownFirstTime; - LARGE_INTEGER TimeSentDownLasttTime; - - - ULONG RetriedCount; - - // Used to send down an incoming IOCTL in the original context - BOOLEAN SyncRequired; - PKEVENT SyncEvent; - PSYNC_HANDLER SyncCallback; - - // - // Used for READ/WRITE requests. - // The reason why kernel primitives are used for the spinlock and - // the timer instead of WDF object is there is a race condition - // between the cancel callback and the timer routine. - // Because of this, the timer and the spin lock need to be associated - // per request rather than using shared memory in the device extension - // and it is possible for the WDF object initialization to fail whereas - // the kernel primitives initialize provided memory. Initializing the - // kernel primitives will never fail. Since READ/WRITE is a critical - // code path, it is not desired for READs or WRITEs to fail due to - // an allocation failure that can be avoided and because it is not - // uncommon to see a failure during a READ or WRITE that may not - // occur upon a retry. - // - KSPIN_LOCK ReadWriteCancelSpinLock; - KTIMER ReadWriteTimer; - KDPC ReadWriteDpc; - BOOLEAN ReadWriteIsCompleted; - BOOLEAN ReadWriteRetryInitialized; - -} CDROM_REQUEST_CONTEXT, *PCDROM_REQUEST_CONTEXT; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CDROM_REQUEST_CONTEXT, RequestGetContext) - -// Define context structure for asynchronous completions. -typedef struct _COMPLETION_CONTEXT { - WDFDEVICE Device; - SCSI_REQUEST_BLOCK Srb; -} COMPLETION_CONTEXT, *PCOMPLETION_CONTEXT; - - -// -#define SCSI_CDROM_TIMEOUT 10 -#define SCSI_CHANGER_BONUS_TIMEOUT 10 - -// -// This value is used as the upper limit for all commands CDROM sends down -// to device, unless the default timeout value is overriden by registry value -// "TimeOutValue" and it is larger than this value. -// -#define SCSI_CDROM_OPC_TIMEOUT 260 - -#define HITACHI_MODE_DATA_SIZE 12 -#define MODE_DATA_SIZE 64 - -#define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 - -#define CDROM_SRB_LIST_SIZE 4 - -#define PLAY_ACTIVE(x) (x->DeviceAdditionalData.PlayActive) - -#define MSF_TO_LBA(Minutes,Seconds,Frames) \ - (ULONG)((60 * 75 * (Minutes)) + (75 * (Seconds)) + ((Frames) - 150)) - -// Sector types for READ_CD - -#define ANY_SECTOR 0 -#define CD_DA_SECTOR 1 -#define YELLOW_MODE1_SECTOR 2 -#define YELLOW_MODE2_SECTOR 3 -#define FORM2_MODE1_SECTOR 4 -#define FORM2_MODE2_SECTOR 5 - -#define MAX_COPY_PROTECT_AGID 4 - -#ifdef ExAllocatePool - #undef ExAllocatePool - #define ExAllocatePool #assert(FALSE) -#endif - -// memory allocation tags -// Sc?? - Mass storage driver tags -// ScC<number> - Class driver misc allocations -// ScC? - CdRom - -#define CDROM_TAG_AUTORUN_DISABLE 'ACcS' // "ScCA" - Autorun disable functionality -#define CDROM_TAG_MEDIA_CHANGE_DETECTION 'aCcS' // "ScCa" - Media change detection - -#define CDROM_TAG_SCRATCH 'BCcS' // "ScSB" - Scratch buffer (usually 64k) -#define CDROM_TAG_GET_CONFIG 'CCcS' // "ScCC" - Ioctl GET_CONFIGURATION -#define CDROM_TAG_COMPLETION_CONTEXT 'cCcS' // "ScCc" - Context of completion routine -#define CDROM_TAG_DESCRIPTOR 'DCcS' // "ScCD" - Adaptor & Device descriptor buffer -#define CDROM_TAG_DISC_INFO 'dCcS' // "ScCd" - Disc information -#define CDROM_TAG_SYNC_EVENT 'eCcS' // "ScCe" - Request sync event -#define CDROM_TAG_FEATURE 'FCcS' // "ScCF" - Feature descriptor -#define CDROM_TAG_GESN 'GCcS' // "ScCG" - GESN buffer -#define CDROM_TAG_SENSE_INFO 'ICcS' // "ScCI" - Sense info buffers -#define CDROM_TAG_INQUIRY 'iCcS' // "ScCi" - Cached inquiry buffer -#define CDROM_TAG_MODE_DATA 'MCcS' // "ScCM" - Mode data buffer -#define CDROM_TAG_STREAM 'OCCS' // "SCCO" - Set stream buffer -#define CDROM_TAG_NOTIFICATION 'oCcS' // "ScCo" - Device Notification buffer -#define CDROM_TAG_PLAY_ACTIVE 'pCcS' // "ScCp" - Play active checks -#define CDROM_TAG_REGISTRY 'rCcS' // "ScCr" - Registry string -#define CDROM_TAG_SRB 'SCcS' // "ScCS" - Srb allocation -#define CDROM_TAG_STRINGS 'sCcS' // "ScCs" - Assorted string data -#define CDROM_TAG_UPDATE_CAP 'UCcS' // "ScCU" - Update capacity path -#define CDROM_TAG_ZERO_POWER_ODD 'ZCcS' // "ScCZ" - Zero Power ODD - -#define DVD_TAG_READ_KEY 'uCcS' // "ScCu" - Read buffer for dvd key -#define DVD_TAG_RPC2_CHECK 'VCcS' // "ScCV" - Read buffer for dvd/rpc2 check -#define DVD_TAG_DVD_REGION 'vCcS' // "ScCv" - Read buffer for rpc2 check -#define DVD_TAG_SECURITY 'XCcS' // "ScCX" - Security descriptor - - -// registry keys and data entry names. -#define CDROM_SUBKEY_NAME (L"CdRom") // store new settings here -#define CDROM_READ_CD_NAME (L"ReadCD") // READ_CD support previously detected -#define CDROM_NON_MMC_DRIVE_NAME (L"NonMmc") // MMC commands hang -#define CDROM_TYPE_ONE_GET_CONFIG_NAME (L"NoTypeOneGetConfig") // Type One Get Config commands not supported -#define CDROM_NON_MMC_VENDOR_SPECIFIC_PROFILE (L"NonMmcVendorSpecificProfile") // GET_CONFIG returns vendor specific header - // profiles that are not per spec (length divisible by 4) -#define DVD_DEFAULT_REGION (L"DefaultDvdRegion") // this is init. by the dvd class installer -#define DVD_MAX_REGION 8 - -// AACS defines -#define AACS_MKB_PACK_SIZE 0x8000 // does not include header - -//enumeration of device interfaces need to be registered. -typedef enum { - CdRomDeviceInterface = 0, // CdRomClassGuid - MountedDeviceInterface // MOUNTDEV_MOUNTED_DEVICE_GUID -} CDROM_DEVICE_INTERFACES, *PCDROM_DEVICE_INTERFACES; - - -typedef -VOID -(*PCDROM_SCAN_FOR_SPECIAL_HANDLER) ( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG_PTR Data - ); - -// Rountines Definition - -#define FREE_POOL(_PoolPtr) \ - if (_PoolPtr != NULL) { \ - ExFreePool(_PoolPtr); \ - _PoolPtr = NULL; \ - } - -#define EXCLUSIVE_MODE(_CdData) (_CdData->ExclusiveOwner != NULL) -#define EXCLUSIVE_OWNER(_CdData, _FileObject) (_CdData->ExclusiveOwner == _FileObject) - -#define IS_SCSIOP_READ(opCode) \ - ((opCode == SCSIOP_READ6) || \ - (opCode == SCSIOP_READ) || \ - (opCode == SCSIOP_READ12) || \ - (opCode == SCSIOP_READ16)) - -#define IS_SCSIOP_WRITE(opCode) \ - ((opCode == SCSIOP_WRITE6) || \ - (opCode == SCSIOP_WRITE) || \ - (opCode == SCSIOP_WRITE12) || \ - (opCode == SCSIOP_WRITE16)) - -#define IS_SCSIOP_READWRITE(opCode) (IS_SCSIOP_READ(opCode) || IS_SCSIOP_WRITE(opCode)) - -// Bit Flag Macros -#define SET_FLAG(Flags, Bit) ((Flags) |= (Bit)) -#define CLEAR_FLAG(Flags, Bit) ((Flags) &= ~(Bit)) -#define TEST_FLAG(Flags, Bit) (((Flags) & (Bit)) != 0) - -__inline -BOOLEAN -ValidChar(UCHAR Ch) -{ - if (((Ch >= '0') && (Ch <= '9')) || - (((Ch|0x20) >= 'a') && ((Ch|0x20) <= 'z')) || - (strchr(" .,:;_-", Ch) != NULL)) - { - return TRUE; - } - return FALSE; -} - -// could be #define, but this allows typechecking -__inline -BOOLEAN -PORT_ALLOCATED_SENSE( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb - ) -{ - UNREFERENCED_PARAMETER(DeviceExtension); - return (BOOLEAN)((TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE) && - TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)) - ); -} - -__inline -VOID -FREE_PORT_ALLOCATED_SENSE_BUFFER( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb - ) -{ -#ifndef DEBUG - UNREFERENCED_PARAMETER(DeviceExtension); -#endif - NT_ASSERT(TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE)); - NT_ASSERT(TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)); - NT_ASSERT(Srb->SenseInfoBuffer != DeviceExtension->SenseData); - - ExFreePool(Srb->SenseInfoBuffer); - Srb->SenseInfoBuffer = NULL; - Srb->SenseInfoBufferLength = 0; - CLEAR_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER); - return; -} - -// Standard driver entry function -DRIVER_INITIALIZE DriverEntry; - -// Driver Event callbacks -EVT_WDF_DRIVER_DEVICE_ADD DriverEvtDeviceAdd; - -EVT_WDF_OBJECT_CONTEXT_CLEANUP DriverEvtCleanup; - -// Device Event callbacks - -EVT_WDF_OBJECT_CONTEXT_CLEANUP DeviceEvtCleanup; - -EVT_WDF_FILE_CLOSE DeviceEvtFileClose; - -EVT_WDF_IO_IN_CALLER_CONTEXT DeviceEvtIoInCallerContext; - -EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT DeviceEvtSelfManagedIoInit; - -EVT_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP DeviceEvtSelfManagedIoCleanup; - -EVT_WDF_DEVICE_D0_ENTRY DeviceEvtD0Entry; - -EVT_WDF_DEVICE_D0_EXIT DeviceEvtD0Exit; - -EVT_WDF_DEVICE_SURPRISE_REMOVAL DeviceEvtSurpriseRemoval; - -// Create Queue Event callbacks - -EVT_WDF_IO_QUEUE_IO_DEFAULT CreateQueueEvtIoDefault; - -// Sequential Queue Event callbacks - -// We do not use KMDF annotation for the following function, because it handles -// both read and write requests and there is no single annotation for that. -VOID -SequentialQueueEvtIoReadWrite( - _In_ WDFQUEUE Queue, - _In_ WDFREQUEST Request, - _In_ size_t Length - ); - -EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SequentialQueueEvtIoDeviceControl; - -EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE SequentialQueueEvtCanceledOnQueue; - -// Miscellaneous request callbacks - -EVT_WDF_OBJECT_CONTEXT_CLEANUP RequestEvtCleanup; - -EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessShutdownFlush; - -EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessSetPower; - - -// helper functions - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceClaimRelease( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN Release - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceReleaseMcnResources( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceRetrieveDescriptor( - _In_ WDFDEVICE Device, - _In_ PSTORAGE_PROPERTY_ID PropertyId, - _Outptr_ PSTORAGE_DESCRIPTOR_HEADER* Descriptor - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -VOID -DeviceRetrieveHackFlagsFromRegistry( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceHackFlagsScan( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG_PTR Data - ); - -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -StringsAreMatched( - _In_opt_z_ PCHAR StringToMatch, - _In_z_ PCHAR TargetString - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -VOID -DeviceGetParameter( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ PWSTR SubkeyName, - _In_ PWSTR ParameterName, - _Inout_ PULONG ParameterValue // also default value - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceSetParameter( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_z_ PWSTR SubkeyName, - _In_ PWSTR ParameterName, - _In_ ULONG ParameterValue - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -ULONG -DeviceGetTimeOutValueFromRegistry(); - -_IRQL_requires_max_(APC_LEVEL) -VOID -ScanForSpecialHandler( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG_PTR HackFlags - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceSendSrbSynchronously( - _In_ WDFDEVICE Device, - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_opt_ PVOID BufferAddress, - _In_ ULONG BufferLength, - _In_ BOOLEAN WriteToDevice, - _In_opt_ WDFREQUEST OriginalRequest - ); - -BOOLEAN -RequestSenseInfoInterpret( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, // get IRP MJ code, IoControlCode from it (or attached original request) - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_ ULONG RetriedCount, - _Out_ NTSTATUS* Status, - _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) - LONGLONG* RetryIntervalIn100ns - ); - -VOID -RequestSetReceivedTime( - _In_ WDFREQUEST Request - ); - -VOID -RequestSetSentTime( - _In_ WDFREQUEST Request - ); - -VOID -RequestClearSendTime( - _In_ WDFREQUEST Request - ); - -BOOLEAN -RequestSenseInfoInterpretForScratchBuffer( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG RetriedCount, - _Out_ NTSTATUS* Status, - _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) - LONGLONG* RetryIntervalIn100ns - ); - - -VOID -DeviceSendNotification( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ const GUID* Guid, - _In_ ULONG ExtraDataSize, - _In_opt_ PVOID ExtraData - ); - -VOID -DeviceSendStartUnit( - _In_ WDFDEVICE Device - ); - -EVT_WDF_REQUEST_COMPLETION_ROUTINE DeviceAsynchronousCompletion; - -VOID -DeviceReleaseQueue( - _In_ WDFDEVICE Device - ); - -EVT_WDF_REQUEST_COMPLETION_ROUTINE DeviceReleaseQueueCompletion; - -VOID -DevicePerfIncrementErrorCount( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceCacheDeviceInquiryData( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceCacheGetConfigurationData( - _In_ WDFDEVICE Device - ); - -_IRQL_requires_max_(APC_LEVEL) -PVOID -DeviceFindFeaturePage( - _In_reads_bytes_(Length) PGET_CONFIGURATION_HEADER FeatureBuffer, - _In_ ULONG const Length, - _In_ FEATURE_NUMBER const Feature - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DevicePrintAllFeaturePages( - _In_reads_bytes_(Usable) PGET_CONFIGURATION_HEADER Buffer, - _In_ ULONG const Usable - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceSetRawReadInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -MediaReadCapacity( - _In_ WDFDEVICE Device - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -MediaReadCapacityDataInterpret( - _In_ WDFDEVICE Device, - _In_ PREAD_CAPACITY_DATA ReadCapacityBuffer - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceInitReleaseQueueContext( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceInitPowerContext( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceCreateWellKnownName( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceInitializeDvd( - _In_ WDFDEVICE Device - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DevicePickDvdRegion( - _In_ WDFDEVICE Device - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceRegisterInterface( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ CDROM_DEVICE_INTERFACES InterfaceType - ); - -_IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS -DeviceSendPowerDownProcessRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine, - _In_opt_ WDFCONTEXT Context - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceScanForSpecial( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ CDROM_SCAN_FOR_SPECIAL_INFO DeviceList[], - _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeHotplugInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -NTSTATUS -DeviceErrorHandlerForMmc( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _Inout_ PNTSTATUS Status, - _Inout_ PBOOLEAN Retry - ); - -NTSTATUS -DeviceErrorHandlerForHitachiGD2000( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _Inout_ PNTSTATUS Status, - _Inout_ PBOOLEAN Retry - ); - -EVT_WDF_WORKITEM DeviceRestoreDefaultSpeed; - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeMediaChangeDetection( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -VOID -DeviceSetMediaChangeStateEx( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ MEDIA_CHANGE_DETECTION_STATE NewState, - _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceSendDelayedMediaChangeNotifications( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -NTSTATUS -RequestSynchronizeProcessWithSerialQueue( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceCleanupProtectedLocks( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PFILE_OBJECT_CONTEXT FileObjectContext - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceCleanupDisableMcn( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PFILE_OBJECT_CONTEXT FileObjectContext - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceUnlockExclusive( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFFILEOBJECT FileObject, - _In_ BOOLEAN IgnorePreviousMediaChanges - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -RequestProcessSerializedIoctl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request - ); - -NTSTATUS -RequestIsIoctlBlockedByExclusiveAccess( - _In_ WDFREQUEST Request, - _Out_ PBOOLEAN IsBlocked - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceSendRequestSynchronously( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ BOOLEAN RequestFormated - ); - -VOID -DeviceSendIoctlAsynchronously( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG IoControlCode, - _In_ PDEVICE_OBJECT TargetDeviceObject - ); - -IO_COMPLETION_ROUTINE RequestAsynchronousIrpCompletion; - -// MMC Update functions - -BOOLEAN -DeviceIsMmcUpdateRequired( - _In_ WDFDEVICE Device - ); - -// Helper functions - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceEnableMediaChangeDetection( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Inout_ PFILE_OBJECT_CONTEXT FileObjectContext, - _In_ BOOLEAN IgnorePreviousMediaChanges - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceDisableMediaChangeDetection( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Inout_ PFILE_OBJECT_CONTEXT FileObjectContext - ); - -NTSTATUS -RequestSetContextFields( - _In_ WDFREQUEST Request, - _In_ PSYNC_HANDLER Handler - ); - -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -DeviceIsPlayActive( - _In_ WDFDEVICE Device - ); - -NTSTATUS -RequestDuidGetDeviceIdProperty( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ); - -NTSTATUS -RequestDuidGetDeviceProperty( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ); - -_IRQL_requires_max_(APC_LEVEL) -ULONG -DeviceRetrieveModeSenseUsingScratch( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, - _In_ ULONG Length, - _In_ UCHAR PageCode, - _In_ UCHAR PageControl - ); - -_IRQL_requires_max_(APC_LEVEL) -PVOID -ModeSenseFindSpecificPage( - _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, - _In_ size_t Length, - _In_ UCHAR PageMode, - _In_ BOOLEAN Use6Byte - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -PerformEjectionControl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ MEDIA_LOCK_TYPE LockType, - _In_ BOOLEAN Lock - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -VOID -DeviceDisableMainTimer( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceEnableMainTimer( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -EVT_WDF_TIMER DeviceMainTimerTickHandler; - -VOID -RequestSetupMcnSyncIrp( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestSetupMcnRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN UseGesn - ); - -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -RequestSendMcnRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -RequestPostWorkMcnRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS -PowerContextReuseRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS -PowerContextBeginUse( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS -PowerContextEndUse( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -POWER_SETTING_CALLBACK DevicePowerSettingCallback; - -// Zero Power ODD functions - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeZPODD( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceReleaseZPODDResources( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -NTSTATUS -DeviceZPODDGetPowerupReason( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Out_ PSTORAGE_IDLE_POWERUP_REASON PowerupReason - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -BOOLEAN -DeviceZPODDIsInHomePosition( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -VOID -DeviceMarkActive( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN IsActive, - _In_ BOOLEAN SetIdleTimeout - ); - -// common routines for specific IOCTL process - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DvdStartSessionReadKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG IoControlCode, - _In_opt_ WDFREQUEST OriginalRequest, - _In_opt_ PVOID InputBuffer, - _In_ size_t InputBufferLength, - _In_ PVOID OutputBuffer, - _In_ size_t OutputBufferLength, - _Out_ size_t * DataLength - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -ReadDvdStructure( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ WDFREQUEST OriginalRequest, - _In_ PVOID InputBuffer, - _In_ size_t InputBufferLength, - _In_ PVOID OutputBuffer, - _In_ size_t OutputBufferLength, - _Out_ size_t * DataLength - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -ReadQChannel( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ WDFREQUEST OriginalRequest, - _In_ PVOID InputBuffer, - _In_ size_t InputBufferLength, - _In_ PVOID OutputBuffer, - _In_ size_t OutputBufferLength, - _Out_ size_t * DataLength - ); - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DvdSendKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ WDFREQUEST OriginalRequest, - _In_ PVOID InputBuffer, - _In_ size_t InputBufferLength, - _Out_ size_t * DataLength - ); - - -#ifndef SIZEOF_ARRAY - #define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0])) -#endif // !defined(SIZEOF_ARRAY) - - -// 100us to seconds -#define UNIT_100NS_PER_SECOND (10*1000*1000) -#define SECONDS_TO_100NS_UNITS(x) (((LONGLONG)x) * UNIT_100NS_PER_SECOND) - -// -// Bit Flag Macros -// -#define SET_FLAG(Flags, Bit) ((Flags) |= (Bit)) -#define CLEAR_FLAG(Flags, Bit) ((Flags) &= ~(Bit)) -#define TEST_FLAG(Flags, Bit) (((Flags) & (Bit)) != 0) - -// -// neat little hacks to count number of bits set efficiently -// -__inline ULONG CountOfSetBitsUChar(UCHAR _X) - { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; } -__inline ULONG CountOfSetBitsULong(ULONG _X) - { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; } -__inline ULONG CountOfSetBitsULong32(ULONG32 _X) - { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; } -__inline ULONG CountOfSetBitsULong64(ULONG64 _X) - { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; } -__inline ULONG CountOfSetBitsUlongPtr(ULONG_PTR _X) - { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; } - - -__inline -BOOLEAN -IsVolumeMounted( - _In_ PDEVICE_OBJECT DeviceObject - ) -{ -#pragma prefast(push) -#pragma prefast(disable: 28175, "there is no other way to check if there is volume mounted") - return (DeviceObject->Vpb != NULL) && - ((DeviceObject->Vpb->Flags & VPB_MOUNTED) != 0); -#pragma prefast(pop) -} - - -__inline _Ret_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) -LONGLONG -ConvertSectorsPerSecondTo100nsUnitsFor64kWrite( - _In_range_(1,0xFFFFFFFF) ULONG SectorsPerSecond // zero would cause divide-by-zero - ) -{ - // 64k write - // ---------------- == time per 64k write - // sectors/second - // - // (32 / N) == seconds - // (32 / N) * (1,000,000,000) == nanoseconds - // (32 / N) * (1,000,000,000) / 100 == 100ns increments - // (32 * 10,000,000) / N == 100ns increments - // - // 320,000,000 / N == 100ns increments - // And this is safe to run in kernel-mode (no floats) - // - - // this assert ensures that we _never_ can return a value - // larger than the maximum allowed. - C_ASSERT(320000000 < MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS); - - return 320000000 / SectorsPerSecond; -} - -__inline -UCHAR -RequestGetCurrentStackLocationFlags( - _In_ WDFREQUEST Request - ) -{ - PIRP irp = NULL; - PIO_STACK_LOCATION currentStack = NULL; - - irp = WdfRequestWdmGetIrp(Request); - currentStack = IoGetCurrentIrpStackLocation(irp); - - return currentStack->Flags; -} - -__inline -ULONG -TimeOutValueGetCapValue( - _In_ ULONG TimeOutValue, - _In_ ULONG Times - ) -{ - ULONG value = 0; - - if (TimeOutValue > SCSI_CDROM_OPC_TIMEOUT) - { - // if time out value is specified by user in registry, and is - // bigger than OPC time out, it should be big enough - value = TimeOutValue; - } - else - { - // otherwise, OPC time out value should be the upper limit - value = min(TimeOutValue * Times, SCSI_CDROM_OPC_TIMEOUT); - } - - return value; -} - -VOID -RequestCompletion( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ NTSTATUS Status, - _In_ ULONG_PTR Information - ); - -NTSTATUS -RequestSend( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDFIOTARGET IoTarget, - _In_ ULONG Flags, - _Out_opt_ PBOOLEAN RequestSent - ); - -EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestDummyCompletionRoutine; - -VOID -RequestProcessInternalDeviceControl( - _In_ WDFREQUEST Request, - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -EVT_WDF_WORKITEM IoctlWorkItemRoutine; - -EVT_WDF_WORKITEM ReadWriteWorkItemRoutine; - -#pragma warning(pop) // un-sets any local warning changes - -#endif // __CDROMP_H__ - - diff --git a/storage/class/cdrom/src/cdrom.inf b/storage/class/cdrom/src/cdrom.inf Binary files differdeleted file mode 100644 index d74fe65b..00000000 --- a/storage/class/cdrom/src/cdrom.inf +++ /dev/null diff --git a/storage/class/cdrom/src/cdrom.rc b/storage/class/cdrom/src/cdrom.rc deleted file mode 100644 index 688f9142..00000000 --- a/storage/class/cdrom/src/cdrom.rc +++ /dev/null @@ -1,23 +0,0 @@ -//+------------------------------------------------------------------------- -// -// 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" - diff --git a/storage/class/cdrom/src/cdrom.vcxproj b/storage/class/cdrom/src/cdrom.vcxproj deleted file mode 100644 index 689c9716..00000000 --- a/storage/class/cdrom/src/cdrom.vcxproj +++ /dev/null @@ -1,168 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{9DB6E759-C294-4E18-9013-82FD8F3DD5E6}</ProjectGuid> - <RootNamespace>$(MSBuildProjectName)</RootNamespace> - <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> - <SupportsPackaging>false</SupportsPackaging> - <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> - <SampleGuid>{E2CAD978-F695-4642-9CD1-65CB518B0B80}</SampleGuid> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <PropertyGroup> - <OutDir>$(IntDir)</OutDir> - </PropertyGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ItemGroup Label="WrappedTaskItems"> - <ClCompile Include="cdrom.c; init.c; common.c; ioctl.c; data.c; guid.c; sense.c; autorun.c; mmc.c; scratch.c; pnppower.c; aacs.c; zpodd.c"> - <WppEnabled>true</WppEnabled> - <WppKernelMode>true</WppKernelMode> - <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction> - </ClCompile> - <Inf Include="cdrom.inf"> - <Architecture>$(InfArch)</Architecture> - <SpecifyArchitecture>true</SpecifyArchitecture> - <CopyOutput>.\$(IntDir)\cdrom.inf</CopyOutput> - </Inf> - <OtherWpp Include="cdrom.rc"> - <WppEnabled>true</WppEnabled> - <WppKernelMode>true</WppKernelMode> - <WppTraceFunction>TracePrint((LEVEL,FLAGS,MSG,...))</WppTraceFunction> - </OtherWpp> - </ItemGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <TargetName>cdrom</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <TargetName>cdrom</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>cdrom</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>cdrom</TargetName> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ResourceCompile Include="cdrom.rc" /> - </ItemGroup> - <ItemGroup> - <Inf Exclude="@(Inf)" Include="*.inf" /> - <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> - </ItemGroup> - <ItemGroup> - <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> - <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> - <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> - </ItemGroup> - <ItemGroup> - <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project>
\ No newline at end of file diff --git a/storage/class/cdrom/src/cdrom.vcxproj.Filters b/storage/class/cdrom/src/cdrom.vcxproj.Filters deleted file mode 100644 index 57895acd..00000000 --- a/storage/class/cdrom/src/cdrom.vcxproj.Filters +++ /dev/null @@ -1,72 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> - <UniqueIdentifier>{1BE21169-AD4D-4A1B-AACD-6310066933B0}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files"> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - <UniqueIdentifier>{9B550B9E-2283-4A6B-BAC8-52E0EAB6DD60}</UniqueIdentifier> - </Filter> - <Filter Include="Resource Files"> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> - <UniqueIdentifier>{B3F87DD6-6AE2-4B7C-9C6F-6BC20F347A17}</UniqueIdentifier> - </Filter> - <Filter Include="Driver Files"> - <Extensions>inf;inv;inx;mof;mc;</Extensions> - <UniqueIdentifier>{4F903A62-C105-4A95-AB1A-2EB0F3AE253F}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="aacs.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="autorun.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="cdrom.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="common.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="data.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="guid.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="init.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="ioctl.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="mmc.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="pnppower.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="scratch.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="sense.c"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="zpodd.c"> - <Filter>Source Files</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <Inf Include="cdrom.inf"> - <Filter>Driver Files</Filter> - </Inf> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="cdrom.rc"> - <Filter>Resource Files</Filter> - </ResourceCompile> - </ItemGroup> -</Project>
\ No newline at end of file diff --git a/storage/class/cdrom/src/cdromp.h b/storage/class/cdrom/src/cdromp.h deleted file mode 100644 index 2fdf7118..00000000 --- a/storage/class/cdrom/src/cdromp.h +++ /dev/null @@ -1,383 +0,0 @@ -/*++ - -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__ diff --git a/storage/class/cdrom/src/common.c b/storage/class/cdrom/src/common.c deleted file mode 100644 index 13312ac6..00000000 --- a/storage/class/cdrom/src/common.c +++ /dev/null @@ -1,3872 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - common.c - -Abstract: - - shared private routines for cdrom.sys - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - - -#include "ntddk.h" -#include "ntddstor.h" -#include "ntstrsafe.h" - -#include "cdrom.h" -#include "scratch.h" - - -#ifdef DEBUG_USE_WPP -#include "common.tmh" -#endif - -#ifdef ALLOC_PRAGMA - -#pragma alloc_text(PAGE, DeviceGetParameter) -#pragma alloc_text(PAGE, DeviceSetParameter) -#pragma alloc_text(PAGE, DeviceSendSrbSynchronously) -#pragma alloc_text(PAGE, DevicePickDvdRegion) -#pragma alloc_text(PAGE, StringsAreMatched) -#pragma alloc_text(PAGE, PerformEjectionControl) -#pragma alloc_text(PAGE, DeviceFindFeaturePage) -#pragma alloc_text(PAGE, DevicePrintAllFeaturePages) -#pragma alloc_text(PAGE, DeviceRegisterInterface) -#pragma alloc_text(PAGE, DeviceRestoreDefaultSpeed) -#pragma alloc_text(PAGE, DeviceSendRequestSynchronously) -#pragma alloc_text(PAGE, MediaReadCapacity) -#pragma alloc_text(PAGE, MediaReadCapacityDataInterpret) -#pragma alloc_text(PAGE, DeviceRetrieveModeSenseUsingScratch) -#pragma alloc_text(PAGE, ModeSenseFindSpecificPage) -#pragma alloc_text(PAGE, DeviceUnlockExclusive) - -#endif - -LPCSTR LockTypeStrings[] = {"Simple", - "Secure", - "Internal" - }; - -VOID -RequestSetReceivedTime( - _In_ WDFREQUEST Request - ) -{ - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - LARGE_INTEGER temp; - - KeQueryTickCount(&temp); - - requestContext->TimeReceived = temp; - - return; -} - -VOID -RequestSetSentTime( - _In_ WDFREQUEST Request - ) -{ - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - LARGE_INTEGER temp; - - KeQueryTickCount(&temp); - - if (requestContext->TimeSentDownFirstTime.QuadPart == 0) - { - requestContext->TimeSentDownFirstTime = temp; - } - - requestContext->TimeSentDownLasttTime = temp; - - if (requestContext->OriginalRequest != NULL) - { - PCDROM_REQUEST_CONTEXT originalRequestContext = RequestGetContext(requestContext->OriginalRequest); - - if (originalRequestContext->TimeSentDownFirstTime.QuadPart == 0) - { - originalRequestContext->TimeSentDownFirstTime = temp; - } - - originalRequestContext->TimeSentDownLasttTime = temp; - } - - return; -} - -VOID -RequestClearSendTime( - _In_ WDFREQUEST Request - ) -/* -Routine Description: - - This function is used to clean SentTime fields in reusable request context. - -Arguments: - Request - - -Return Value: - N/A - -*/ -{ - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - - requestContext->TimeSentDownFirstTime.QuadPart = 0; - requestContext->TimeSentDownLasttTime.QuadPart = 0; - - return; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -VOID -DeviceGetParameter( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ PWSTR SubkeyName, - _In_ PWSTR ParameterName, - _Inout_ PULONG ParameterValue // also default value - ) -/*++ -Routine Description: - - retrieve device parameter from registry. - -Arguments: - - DeviceExtension - device context. - - SubkeyName - name of subkey - - ParameterName - the registry parameter to be retrieved - -Return Value: - - ParameterValue - registry value retrieved - ---*/ -{ - NTSTATUS status; - WDFKEY rootKey = NULL; - WDFKEY subKey = NULL; - UNICODE_STRING registrySubKeyName; - UNICODE_STRING registryValueName; - ULONG defaultParameterValue; - - PAGED_CODE(); - - RtlInitUnicodeString(®istryValueName, ParameterName); - - if (SubkeyName != NULL) - { - RtlInitUnicodeString(®istrySubKeyName, SubkeyName); - } - - // open the hardware key - status = WdfDeviceOpenRegistryKey(DeviceExtension->Device, - PLUGPLAY_REGKEY_DEVICE, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - &rootKey); - - // open the sub key - if (NT_SUCCESS(status) && (SubkeyName != NULL)) - { - status = WdfRegistryOpenKey(rootKey, - ®istrySubKeyName, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - &subKey); - - if (!NT_SUCCESS(status)) - { - WdfRegistryClose(rootKey); - rootKey = NULL; - } - } - - if (NT_SUCCESS(status) && (rootKey != NULL)) - { - defaultParameterValue = *ParameterValue; - - status = WdfRegistryQueryULong((subKey != NULL) ? subKey : rootKey, - ®istryValueName, - ParameterValue); - - if (!NT_SUCCESS(status)) - { - *ParameterValue = defaultParameterValue; // use default value - } - } - - // close what we open - if (subKey != NULL) - { - WdfRegistryClose(subKey); - subKey = NULL; - } - - if (rootKey != NULL) - { - WdfRegistryClose(rootKey); - rootKey = NULL; - } - - // Windows 2000 SP3 uses the driver-specific key, so look in there - if (!NT_SUCCESS(status)) - { - // open the software key - status = WdfDeviceOpenRegistryKey(DeviceExtension->Device, - PLUGPLAY_REGKEY_DRIVER, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - &rootKey); - - // open the sub key - if (NT_SUCCESS(status) && (SubkeyName != NULL)) - { - status = WdfRegistryOpenKey(rootKey, - ®istrySubKeyName, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - &subKey); - - if (!NT_SUCCESS(status)) - { - WdfRegistryClose(rootKey); - rootKey = NULL; - } - } - - if (NT_SUCCESS(status) && (rootKey != NULL)) - { - defaultParameterValue = *ParameterValue; - - status = WdfRegistryQueryULong((subKey != NULL) ? subKey : rootKey, - ®istryValueName, - ParameterValue); - - if (!NT_SUCCESS(status)) - { - *ParameterValue = defaultParameterValue; // use default value - } - else - { - // Migrate the value over to the device-specific key - DeviceSetParameter(DeviceExtension, SubkeyName, ParameterName, *ParameterValue); - } - } - - // close what we open - if (subKey != NULL) - { - WdfRegistryClose(subKey); - subKey = NULL; - } - - if (rootKey != NULL) - { - WdfRegistryClose(rootKey); - rootKey = NULL; - } - } - - return; - -} // end DeviceetParameter() - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceSetParameter( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_z_ PWSTR SubkeyName, - _In_ PWSTR ParameterName, - _In_ ULONG ParameterValue - ) -/*++ -Routine Description: - - set parameter to registry. - -Arguments: - - DeviceExtension - device context. - - SubkeyName - name of subkey - - ParameterName - the registry parameter to be retrieved - - ParameterValue - registry value to be set - -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status; - WDFKEY rootKey = NULL; - WDFKEY subKey = NULL; - UNICODE_STRING registrySubKeyName; - UNICODE_STRING registryValueName; - - PAGED_CODE(); - - RtlInitUnicodeString(®istryValueName, ParameterName); - - if (SubkeyName != NULL) - { - RtlInitUnicodeString(®istrySubKeyName, SubkeyName); - } - - // open the hardware key - status = WdfDeviceOpenRegistryKey(DeviceExtension->Device, - PLUGPLAY_REGKEY_DEVICE, - KEY_READ | KEY_WRITE, - WDF_NO_OBJECT_ATTRIBUTES, - &rootKey); - - // open the sub key - if (NT_SUCCESS(status) && (SubkeyName != NULL)) - { - status = WdfRegistryOpenKey(rootKey, - ®istrySubKeyName, - KEY_READ | KEY_WRITE, - WDF_NO_OBJECT_ATTRIBUTES, - &subKey); - - if (!NT_SUCCESS(status)) - { - WdfRegistryClose(rootKey); - rootKey = NULL; - } - } - - if (NT_SUCCESS(status) && (rootKey != NULL)) - { - status = WdfRegistryAssignULong((subKey != NULL) ? subKey : rootKey, - ®istryValueName, - ParameterValue); - } - - // close what we open - if (subKey != NULL) - { - WdfRegistryClose(subKey); - subKey = NULL; - } - - if (rootKey != NULL) - { - WdfRegistryClose(rootKey); - rootKey = NULL; - } - - return status; - -} // end DeviceSetParameter() - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceSendRequestSynchronously( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request, - _In_ BOOLEAN RequestFormated - ) -/*++ -Routine Description: - - send a request to lower driver synchronously. - -Arguments: - - Device - device object. - - Request - request object - - RequestFormated - if the request is already formatted, will no do it in this function - -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - BOOLEAN requestCancelled = FALSE; - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - - PAGED_CODE(); - - if (!RequestFormated) - { - // set request up for sending down - WdfRequestFormatRequestUsingCurrentType(Request); - } - - // get cancellation status for the original request - if (requestContext->OriginalRequest != NULL) - { - requestCancelled = WdfRequestIsCanceled(requestContext->OriginalRequest); - } - - if (!requestCancelled) - { - status = RequestSend(deviceExtension, - Request, - deviceExtension->IoTarget, - WDF_REQUEST_SEND_OPTION_SYNCHRONOUS, - NULL); - } - else - { - status = STATUS_CANCELLED; - } - - return status; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceSendSrbSynchronously( - _In_ WDFDEVICE Device, - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_opt_ PVOID BufferAddress, - _In_ ULONG BufferLength, - _In_ BOOLEAN WriteToDevice, - _In_opt_ WDFREQUEST OriginalRequest - ) -/*++ -Routine Description: - - Send a SRB structure to lower driver synchronously. - - Process of this function: - 1. Allocate SenseBuffer; Create Request; Allocate MDL - 2. Do following loop if necessary - 2.1 Reuse Request - 2.2 Format Srb, Irp - 2.3 Send Request - 2.4 Error Intepret and retry decision making. - 3. Release all allocated resosurces. - -Arguments: - - Device - device object. - - Request - request object - - RequestFormated - if the request is already formatted, will no do it in this function - -Return Value: - NTSTATUS - -NOTE: -The caller needs to setup following fields before calling this routine. - srb.CdbLength - srb.TimeOutValue - cdb - -BufferLength and WriteToDevice to control the data direction of the device - BufferLength = 0: No data transfer - BufferLenth != 0 && !WriteToDevice: get data from device - BufferLenth != 0 && WriteToDevice: send data to device ---*/ -{ - NTSTATUS status; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_PRIVATE_FDO_DATA fdoData = deviceExtension->PrivateFdoData; - PUCHAR senseInfoBuffer = NULL; - ULONG retryCount = 0; - BOOLEAN retry = FALSE; - ULONG ioctlCode = 0; - WDFREQUEST request = NULL; - PIRP irp = NULL; - PIO_STACK_LOCATION nextStack = NULL; - PMDL mdlAddress = NULL; - BOOLEAN memoryLocked = FALSE; - WDF_OBJECT_ATTRIBUTES attributes; - PZERO_POWER_ODD_INFO zpoddInfo = deviceExtension->ZeroPowerODDInfo; - - PAGED_CODE(); - - // NOTE: This code is only pagable because we are not freezing - // the queue. Allowing the queue to be frozen from a pagable - // routine could leave the queue frozen as we try to page in - // the code to unfreeze the queue. The result would be a nice - // case of deadlock. Therefore, since we are unfreezing the - // queue regardless of the result, just set the NO_FREEZE_QUEUE - // flag in the SRB. - NT_ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); - - //1. allocate SenseBuffer and initiate Srb common fields - // these fields will not be changed by lower driver. - { - // Write length to SRB. - Srb->Length = sizeof(SCSI_REQUEST_BLOCK); - Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - - // Sense buffer is in aligned nonpaged pool. - senseInfoBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - SENSE_BUFFER_SIZE, - CDROM_TAG_SENSE_INFO); - - if (senseInfoBuffer == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceSendSrbSynchronously: Can't allocate MDL\n")); - - goto Exit; - } - - Srb->SenseInfoBuffer = senseInfoBuffer; - Srb->DataBuffer = BufferAddress; - - // set timeout value to default value if it's not specifically set by caller. - if (Srb->TimeOutValue == 0) - { - Srb->TimeOutValue = deviceExtension->TimeOutValue; - } - } - - //2. Create Request object - { - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - - status = WdfRequestCreate(&attributes, - deviceExtension->IoTarget, - &request); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceSendSrbSynchronously: Can't create request: %lx\n", - status)); - - goto Exit; - } - - irp = WdfRequestWdmGetIrp(request); - } - - // 3. Build an MDL for the data buffer and stick it into the irp. - if (BufferAddress != NULL) - { - mdlAddress = IoAllocateMdl( BufferAddress, - BufferLength, - FALSE, - FALSE, - irp ); - if (mdlAddress == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceSendSrbSynchronously: Can't allocate MDL\n")); - - goto Exit; - } - - try - { - MmProbeAndLockPages(mdlAddress, - KernelMode, - (WriteToDevice ? IoReadAccess : IoWriteAccess)); - } - except(EXCEPTION_EXECUTE_HANDLER) - { - status = GetExceptionCode(); - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceSendSrbSynchronously: Exception %lx locking buffer\n", status)); - - goto Exit; - } - - memoryLocked = TRUE; - } - - // 4. Format Srb, Irp; Send request and retry when necessary - do - { - // clear the control variable. - retry = FALSE; - - // 4.1 reuse the request object; set originalRequest field. - { - WDF_REQUEST_REUSE_PARAMS params; - PCDROM_REQUEST_CONTEXT requestContext = NULL; - - // deassign the MdlAddress, this is the value we assign explicitly. - // doing this can prevent WdfRequestReuse to release the Mdl unexpectly. - if (irp->MdlAddress) - { - irp->MdlAddress = NULL; - } - - WDF_REQUEST_REUSE_PARAMS_INIT(¶ms, - WDF_REQUEST_REUSE_NO_FLAGS, - STATUS_SUCCESS); - - status = WdfRequestReuse(request, ¶ms); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceSendSrbSynchronously: WdfRequestReuse failed, %!STATUS!\n", - status)); - // exit the loop. - break; - } - - // WDF requests to format the request befor sending it - status = WdfIoTargetFormatRequestForInternalIoctlOthers(deviceExtension->IoTarget, - request, - ioctlCode, - NULL, NULL, - NULL, NULL, - NULL, NULL); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceSendSrbSynchronously: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n", - status)); - // exit the loop. - break; - } - - requestContext = RequestGetContext(request); - requestContext->OriginalRequest = OriginalRequest; - } - - // 4.2 Format Srb and Irp - { - Srb->OriginalRequest = irp; - Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - Srb->DataTransferLength = BufferLength; - Srb->SrbFlags = deviceExtension->SrbFlags; - - // Disable synchronous transfer for these requests. - SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); - SET_FLAG(Srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE); - - if (BufferAddress != NULL) - { - if (WriteToDevice) - { - SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_OUT); - ioctlCode = IOCTL_SCSI_EXECUTE_OUT; - } - else - { - SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN); - ioctlCode = IOCTL_SCSI_EXECUTE_IN; - } - } - else - { - ioctlCode = IOCTL_SCSI_EXECUTE_NONE; - } - - - // Zero out status. - Srb->ScsiStatus = 0; - Srb->SrbStatus = 0; - Srb->NextSrb = NULL; - - // irp related fields - irp->MdlAddress = mdlAddress; - - nextStack = IoGetNextIrpStackLocation(irp); - - nextStack->MajorFunction = IRP_MJ_SCSI; - nextStack->Parameters.DeviceIoControl.IoControlCode = ioctlCode; - nextStack->Parameters.Scsi.Srb = Srb; - } - - // 4.3 send Request to lower driver. - status = DeviceSendRequestSynchronously(Device, request, TRUE); - - if (status != STATUS_CANCELLED) - { - NT_ASSERT(SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_PENDING); - NT_ASSERT(status != STATUS_PENDING); - NT_ASSERT(!(Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN)); - - // 4.4 error process. - if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) - { - LONGLONG retryIntervalIn100ns = 0; - - // Update status and determine if request should be retried. - retry = RequestSenseInfoInterpret(deviceExtension, - request, - Srb, - retryCount, - &status, - &retryIntervalIn100ns); - - if (retry) - { - LARGE_INTEGER t; - t.QuadPart = -retryIntervalIn100ns; - retryCount++; - KeDelayExecutionThread(KernelMode, FALSE, &t); - } - } - else - { - // Request succeeded. - fdoData->LoggedTURFailureSinceLastIO = FALSE; - status = STATUS_SUCCESS; - retry = FALSE; - } - } - } while(retry); - - if ((zpoddInfo != NULL) && - (zpoddInfo->MonitorStartStopUnit != FALSE) && - (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "DeviceSendSrbSynchronously: soft eject detected, device marked as active\n")); - - DeviceMarkActive(deviceExtension, TRUE, FALSE); - } - - // 5. Release all allocated resources. - - // required even though we allocated our own, since the port driver may - // have allocated one also - if (PORT_ALLOCATED_SENSE(deviceExtension, Srb)) - { - FREE_PORT_ALLOCATED_SENSE_BUFFER(deviceExtension, Srb); - } - -Exit: - - if (senseInfoBuffer != NULL) - { - FREE_POOL(senseInfoBuffer); - } - - Srb->SenseInfoBuffer = NULL; - Srb->SenseInfoBufferLength = 0; - - if (mdlAddress) - { - if (memoryLocked) - { - MmUnlockPages(mdlAddress); - memoryLocked = FALSE; - } - - IoFreeMdl(mdlAddress); - irp->MdlAddress = NULL; - } - - if (request) - { - WdfObjectDelete(request); - } - - return status; -} - - -VOID -DeviceSendNotification( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ const GUID* Guid, - _In_ ULONG ExtraDataSize, - _In_opt_ PVOID ExtraData - ) -/*++ -Routine Description: - - send notification to other components - -Arguments: - - DeviceExtension - device context. - - Guid - GUID for the notification - - ExtraDataSize - data size along with notification - - ExtraData - data buffer send with notification - -Return Value: - None - ---*/ -{ - PTARGET_DEVICE_CUSTOM_NOTIFICATION notification; - ULONG requiredSize; - NTSTATUS status; - - status = RtlULongAdd((sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION) - sizeof(UCHAR)), - ExtraDataSize, - &requiredSize); - - if (!(NT_SUCCESS(status)) || (requiredSize > 0x0000ffff)) - { - // MAX_USHORT, max total size for these events! - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, - "Error sending event: size too large! (%x)\n", - requiredSize)); - return; - } - - notification = ExAllocatePool2(POOL_FLAG_NON_PAGED, - requiredSize, - CDROM_TAG_NOTIFICATION); - - // if none allocated, exit - if (notification == NULL) - { - return; - } - - // Prepare and send the request! - RtlZeroMemory(notification, requiredSize); - notification->Version = 1; - notification->Size = (USHORT)(requiredSize); - notification->FileObject = NULL; - notification->NameBufferOffset = -1; - notification->Event = *Guid; - - if (ExtraData != NULL) - { - RtlCopyMemory(notification->CustomDataBuffer, ExtraData, ExtraDataSize); - } - - IoReportTargetDeviceChangeAsynchronous(DeviceExtension->LowerPdo, - notification, - NULL, - NULL); - - FREE_POOL(notification); - - return; -} - - -VOID -DeviceSendStartUnit( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - Send command to SCSI unit to start or power up. - Because this command is issued asynchronounsly, that is, without - waiting on it to complete, the IMMEDIATE flag is not set. This - means that the CDB will not return until the drive has powered up. - This should keep subsequent requests from being submitted to the - device before it has completely spun up. - - This routine is called from the InterpretSense routine, when a - request sense returns data indicating that a drive must be - powered up. - - This routine may also be called from a class driver's error handler, - or anytime a non-critical start device should be sent to the device. - -Arguments: - - Device - The device object. - -Return Value: - - None. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - WDF_OBJECT_ATTRIBUTES attributes; - WDFREQUEST startUnitRequest = NULL; - WDFMEMORY inputMemory = NULL; - - PCOMPLETION_CONTEXT context = NULL; - PSCSI_REQUEST_BLOCK srb = NULL; - PCDB cdb = NULL; - - deviceExtension = DeviceGetExtension(Device); - - if (NT_SUCCESS(status)) - { - // Allocate Srb from nonpaged pool. - context = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(COMPLETION_CONTEXT), - CDROM_TAG_COMPLETION_CONTEXT); - - if (context == NULL) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceSendStartUnit: Failed to allocate completion context\n")); - - status = STATUS_INTERNAL_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - // Save the device object in the context for use by the completion - // routine. - context->Device = Device; - srb = &context->Srb; - - // Zero out srb. - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - - // setup SRB structure. - srb->Length = sizeof(SCSI_REQUEST_BLOCK); - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->TimeOutValue = START_UNIT_TIMEOUT; - - srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // setup CDB - srb->CdbLength = 6; - cdb = (PCDB)srb->Cdb; - - cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; - cdb->START_STOP.Start = 1; - cdb->START_STOP.Immediate = 0; - cdb->START_STOP.LogicalUnitNumber = srb->Lun; - - //Create Request for sending down to port driver - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - attributes.ParentObject = deviceExtension->IoTarget; - - status = WdfRequestCreate(&attributes, - deviceExtension->IoTarget, - &startUnitRequest); - } - - if (NT_SUCCESS(status)) - { - srb->OriginalRequest = WdfRequestWdmGetIrp(startUnitRequest); - NT_ASSERT(srb->OriginalRequest != NULL); - - //Prepare the request - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = startUnitRequest; - - status = WdfMemoryCreatePreallocated(&attributes, - (PVOID)srb, - sizeof(SCSI_REQUEST_BLOCK), - &inputMemory); - } - - if (NT_SUCCESS(status)) - { - status = WdfIoTargetFormatRequestForInternalIoctlOthers(deviceExtension->IoTarget, - startUnitRequest, - IOCTL_SCSI_EXECUTE_NONE, - inputMemory, - NULL, - NULL, - NULL, - NULL, - NULL); - } - - if (NT_SUCCESS(status)) - { - // Set a CompletionRoutine callback function. - WdfRequestSetCompletionRoutine(startUnitRequest, - DeviceAsynchronousCompletion, - context); - - status = RequestSend(deviceExtension, - startUnitRequest, - deviceExtension->IoTarget, - 0, - NULL); - } - - // release resources when failed. - if (!NT_SUCCESS(status)) - { - FREE_POOL(context); - if (startUnitRequest != NULL) - { - WdfObjectDelete(startUnitRequest); - } - } - - return; -} // end StartUnit() - - -VOID -DeviceSendIoctlAsynchronously( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG IoControlCode, - _In_ PDEVICE_OBJECT TargetDeviceObject - ) -/*++ - -Routine Description: - - Send an IOCTL asynchronously - -Arguments: - - DeviceExtension - device context. - IoControlCode - IOCTL code. - TargetDeviceObject - target device object. - -Return Value: - - None. - ---*/ -{ - PIRP irp = NULL; - PIO_STACK_LOCATION nextIrpStack = NULL; - - irp = IoAllocateIrp(DeviceExtension->DeviceObject->StackSize, FALSE); - - if (irp != NULL) - { - nextIrpStack = IoGetNextIrpStackLocation(irp); - - nextIrpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; - - nextIrpStack->Parameters.DeviceIoControl.OutputBufferLength = 0; - nextIrpStack->Parameters.DeviceIoControl.InputBufferLength = 0; - nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IoControlCode; - nextIrpStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL; - - IoSetCompletionRoutine(irp, - RequestAsynchronousIrpCompletion, - DeviceExtension, - TRUE, - TRUE, - TRUE); - - (VOID) IoCallDriver(TargetDeviceObject, irp); - } -} - -NTSTATUS -RequestAsynchronousIrpCompletion( - _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 - ---*/ -{ - UNREFERENCED_PARAMETER(DeviceObject); - UNREFERENCED_PARAMETER(Context); - - IoFreeIrp(Irp); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -VOID -DeviceAsynchronousCompletion( - _In_ WDFREQUEST Request, - _In_ WDFIOTARGET Target, - _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, - _In_ WDFCONTEXT Context - ) -/*++ - -Routine Description: - - This routine is called when an asynchronous I/O request - which was issused by the class driver completes. Examples of such requests - are release queue or START UNIT. This routine releases the queue if - necessary. It then frees the context and the IRP. - -Arguments: - - DeviceObject - The device object for the logical unit; however since this - is the top stack location the value is NULL. - - Irp - Supplies a pointer to the Irp to be processed. - - Context - Supplies the context to be used to process this request. - -Return Value: - - None. - ---*/ -{ - PCOMPLETION_CONTEXT context = (PCOMPLETION_CONTEXT)Context; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(context->Device); - - UNREFERENCED_PARAMETER(Target); - UNREFERENCED_PARAMETER(Params); - - // If this is an execute srb, then check the return status and make sure. - // the queue is not frozen. - if (context->Srb.Function == SRB_FUNCTION_EXECUTE_SCSI) - { - // Check for a frozen queue. - if (context->Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN) - { - // Unfreeze the queue getting the device object from the context. - DeviceReleaseQueue(context->Device); - } - } - - // free port-allocated sense buffer if we can detect - // - if (PORT_ALLOCATED_SENSE(deviceExtension, &context->Srb)) - { - FREE_PORT_ALLOCATED_SENSE_BUFFER(deviceExtension, &context->Srb); - } - - FREE_POOL(context); - - WdfObjectDelete(Request); - -} // end DeviceAsynchronousCompletion() - - -VOID -DeviceReleaseQueue( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - This routine issues an internal device control command - to the port driver to release a frozen queue. The call - is issued asynchronously as DeviceReleaseQueue will be invoked - from the IO completion DPC (and will have no context to - wait for a synchronous call to complete). - - This routine must be called with the remove lock held. - -Arguments: - - Device - The functional device object for the device with the frozen queue. - -Return Value: - - None. - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PSCSI_REQUEST_BLOCK srb = NULL; - KIRQL currentIrql; - - // we raise irql seperately so we're not swapped out or suspended - // while holding the release queue irp in this routine. this lets - // us release the spin lock before lowering irql. - KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); - - WdfSpinLockAcquire(deviceExtension->ReleaseQueueSpinLock); - - if (deviceExtension->ReleaseQueueInProgress) - { - // Someone is already doing this work - just set the flag to indicate that - // we need to release the queue again. - deviceExtension->ReleaseQueueNeeded = TRUE; - WdfSpinLockRelease(deviceExtension->ReleaseQueueSpinLock); - KeLowerIrql(currentIrql); - - return; - } - - // Mark that there is a release queue in progress and drop the spinlock. - deviceExtension->ReleaseQueueInProgress = TRUE; - - WdfSpinLockRelease(deviceExtension->ReleaseQueueSpinLock); - - srb = &(deviceExtension->ReleaseQueueSrb); - - // Optical media are removable, so we just flush the queue. This will also release it. - srb->Function = SRB_FUNCTION_FLUSH_QUEUE; - - srb->OriginalRequest = WdfRequestWdmGetIrp(deviceExtension->ReleaseQueueRequest); - - // Set a CompletionRoutine callback function. - WdfRequestSetCompletionRoutine(deviceExtension->ReleaseQueueRequest, - DeviceReleaseQueueCompletion, - Device); - // Send the request. If an error occurs, complete the request. - RequestSend(deviceExtension, - deviceExtension->ReleaseQueueRequest, - deviceExtension->IoTarget, - WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE, - NULL); - - KeLowerIrql(currentIrql); - - return; - -} // end DeviceReleaseQueue() - -VOID -DeviceReleaseQueueCompletion( - _In_ WDFREQUEST Request, - _In_ WDFIOTARGET Target, - _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, - _In_ WDFCONTEXT Context - ) -/*++ - -Routine Description: - - This routine is called when an asynchronous release queue request which - was issused in DeviceReleaseQueue completes. This routine prepares for - the next release queue request and resends it if necessary. - -Arguments: - - Request - The completed request. - - Target - IoTarget object - - Params - Completion parameters - - Context - WDFDEVICE object handle. - -Return Value: - - None. - ---*/ -{ - NTSTATUS status; - WDFDEVICE device = Context; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device); - - BOOLEAN releaseQueueNeeded = FALSE; - WDF_REQUEST_REUSE_PARAMS params = {0}; - - UNREFERENCED_PARAMETER(Target); - UNREFERENCED_PARAMETER(Params); - - WDF_REQUEST_REUSE_PARAMS_INIT(¶ms, - WDF_REQUEST_REUSE_NO_FLAGS, - STATUS_SUCCESS); - - // Grab the spinlock and clear the release queue in progress flag so others - // can run. Save (and clear) the state of the release queue needed flag - // so that we can issue a new release queue outside the spinlock. - WdfSpinLockAcquire(deviceExtension->ReleaseQueueSpinLock); - - releaseQueueNeeded = deviceExtension->ReleaseQueueNeeded; - - deviceExtension->ReleaseQueueNeeded = FALSE; - deviceExtension->ReleaseQueueInProgress = FALSE; - - // Reuse the ReleaseQueueRequest for the next time. - status = WdfRequestReuse(Request,¶ms); - - if (NT_SUCCESS(status)) - { - // Preformat the ReleaseQueueRequest for the next time. - // This should always succeed because it was already preformatted once during device initialization - status = WdfIoTargetFormatRequestForInternalIoctlOthers(deviceExtension->IoTarget, - Request, - IOCTL_SCSI_EXECUTE_NONE, - deviceExtension->ReleaseQueueInputMemory, - NULL, - NULL, - NULL, - NULL, - NULL); - } - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceReleaseQueueCompletion: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n", - status)); - } - - RequestClearSendTime(Request); - - WdfSpinLockRelease(deviceExtension->ReleaseQueueSpinLock); - - // If we need a release queue then issue one now. Another processor may - // have already started one in which case we'll try to issue this one after - // it is done - but we should never recurse more than one deep. - if (releaseQueueNeeded) - { - DeviceReleaseQueue(device); - } - - return; - -} // DeviceReleaseQueueCompletion() - - -// -// In order to provide better performance without the need to reboot, -// we need to implement a self-adjusting method to set and clear the -// srb flags based upon current performance. -// -// whenever there is an error, immediately grab the spin lock. the -// MP perf hit here is acceptable, since we're in an error path. this -// is also neccessary because we are guaranteed to be modifying the -// SRB flags here, setting SuccessfulIO to zero, and incrementing the -// actual error count (which is always done within this spinlock). -// -// whenever there is no error, increment a counter. if there have been -// errors on the device, and we've enabled dynamic perf, *and* we've -// just crossed the perf threshhold, then grab the spin lock and -// double check that the threshhold has, indeed been hit(*). then -// decrement the error count, and if it's dropped sufficiently, undo -// some of the safety changes made in the SRB flags due to the errors. -// -// * this works in all cases. even if lots of ios occur after the -// previous guy went in and cleared the successfulio counter, that -// just means that we've hit the threshhold again, and so it's proper -// to run the inner loop again. -// - -VOID -DevicePerfIncrementErrorCount( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -{ - PCDROM_PRIVATE_FDO_DATA fdoData = DeviceExtension->PrivateFdoData; - KIRQL oldIrql; - ULONG errors; - - KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql); - - fdoData->Perf.SuccessfulIO = 0; // implicit interlock - errors = InterlockedIncrement((PLONG)&DeviceExtension->ErrorCount); - - if (errors >= CLASS_ERROR_LEVEL_1) - { - // If the error count has exceeded the error limit, then disable - // any tagged queuing, multiple requests per lu queueing - // and sychronous data transfers. - // - // Clearing the no queue freeze flag prevents the port driver - // from sending multiple requests per logical unit. - CLEAR_FLAG(DeviceExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE); - CLEAR_FLAG(DeviceExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE); - - SET_FLAG(DeviceExtension->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "PerfIncrementErrorCount: Too many errors; disabling tagged queuing and " - "synchronous data tranfers.\n")); - } - - if (errors >= CLASS_ERROR_LEVEL_2) - { - // If a second threshold is reached, disable disconnects. - SET_FLAG(DeviceExtension->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT); - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "PerfIncrementErrorCount: Too many errors; disabling disconnects.\n")); - } - - KeReleaseSpinLock(&fdoData->SpinLock, oldIrql); - return; -} - - -_IRQL_requires_max_(APC_LEVEL) -PVOID -DeviceFindFeaturePage( - _In_reads_bytes_(Length) PGET_CONFIGURATION_HEADER FeatureBuffer, - _In_ ULONG const Length, - _In_ FEATURE_NUMBER const Feature - ) -/*++ -Routine Description: - - find the specific feature page in the buffer - -Arguments: - - FeatureBuffer - buffer contains the device feature set. - - Length - buffer length - - Feature - the feature number looking for. - -Return Value: - - PVOID - pointer to the starting location of the specific feature in buffer. - ---*/ -{ - PUCHAR buffer; - PUCHAR limit; - ULONG validLength; - - PAGED_CODE(); - - if (Length < sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER)) - { - return NULL; - } - - // Calculate the length of valid data available in the - // capabilities buffer from the DataLength field - REVERSE_BYTES(&validLength, FeatureBuffer->DataLength); - - validLength += RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength); - - // set limit to point to first illegal address - limit = (PUCHAR)FeatureBuffer; - limit += min(Length, validLength); - - // set buffer to point to first page - buffer = FeatureBuffer->Data; - - // loop through each page until we find the requested one, or - // until it's not safe to access the entire feature header - // (if equal, have exactly enough for the feature header) - while (buffer + sizeof(FEATURE_HEADER) <= limit) - { - PFEATURE_HEADER header = (PFEATURE_HEADER)buffer; - FEATURE_NUMBER thisFeature; - - thisFeature = (header->FeatureCode[0] << 8) | - (header->FeatureCode[1]); - - if (thisFeature == Feature) - { - PUCHAR temp; - - // if don't have enough memory to safely access all the feature - // information, return NULL - temp = buffer; - temp += sizeof(FEATURE_HEADER); - temp += header->AdditionalLength; - - if (temp > limit) - { - // this means the transfer was cut-off, an insufficiently - // small buffer was given, or other arbitrary error. since - // it's not safe to view the amount of data (even though - // the header is safe) in this feature, pretend it wasn't - // transferred at all... - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "Feature %x exists, but not safe to access all its data. returning NULL\n", - Feature)); - return NULL; - } - else - { - return buffer; - } - } - - if ((header->AdditionalLength % 4) && - !(Feature >= 0xff00 && Feature <= 0xffff)) - { - return NULL; - } - - buffer += sizeof(FEATURE_HEADER); - buffer += header->AdditionalLength; - } - - return NULL; -} - - -_IRQL_requires_max_(APC_LEVEL) -VOID -DevicePrintAllFeaturePages( - _In_reads_bytes_(Usable) PGET_CONFIGURATION_HEADER Buffer, - _In_ ULONG const Usable - ) -/*++ -Routine Description: - - print out all feature pages in the buffer - -Arguments: - - Buffer - buffer contains the device feature set. - - Usable - - -Return Value: - - none - ---*/ -{ -#if DBG - PFEATURE_HEADER header; - - PAGED_CODE(); - - //////////////////////////////////////////////////////////////////////////////// - // items expected to ALWAYS be current if they exist - //////////////////////////////////////////////////////////////////////////////// - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureProfileList); - if (header != NULL) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: CurrentProfile %x " - "with %x bytes of data at %p\n", - Buffer->CurrentProfile[0] << 8 | - Buffer->CurrentProfile[1], - Usable, Buffer)); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureCore); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "CORE Features" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureMorphing); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Morphing" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureRemovableMedium); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Removable Medium" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeaturePowerManagement); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Power Management" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureEmbeddedChanger); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Embedded Changer" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureMicrocodeUpgrade); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Microcode Update" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureTimeout); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Timeouts" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureLogicalUnitSerialNumber); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "LUN Serial Number" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureFirmwareDate); - if (header) { - - ULONG featureSize = header->AdditionalLength; - featureSize += RTL_SIZEOF_THROUGH_FIELD(FEATURE_HEADER, AdditionalLength); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Firmware Date" - )); - - if (featureSize >= RTL_SIZEOF_THROUGH_FIELD(FEATURE_DATA_FIRMWARE_DATE, Minute)) - { - PFEATURE_DATA_FIRMWARE_DATE date = (PFEATURE_DATA_FIRMWARE_DATE)header; - // show date as "YYYY/MM/DD hh:mm", which is 18 chars (17+NULL) - UCHAR dateString[18] = { 0 }; - dateString[ 0] = date->Year[0]; - dateString[ 1] = date->Year[1]; - dateString[ 2] = date->Year[2]; - dateString[ 3] = date->Year[3]; - dateString[ 4] = '/'; - dateString[ 5] = date->Month[0]; - dateString[ 6] = date->Month[1]; - dateString[ 7] = '/'; - dateString[ 8] = date->Day[0]; - dateString[ 9] = date->Day[1]; - dateString[10] = ' '; - dateString[11] = ' '; - dateString[12] = date->Hour[0]; - dateString[13] = date->Hour[1]; - dateString[14] = ':'; - dateString[15] = date->Minute[0]; - dateString[16] = date->Minute[1]; - dateString[17] = 0; - // SECONDS IS NOT AVAILABLE ON EARLY IMPLEMENTATIONS -- ignore it - //dateString[17] = ':'; - //dateString[18] = date->Seconds[0]; - //dateString[19] = date->Seconds[1]; - //dateString[20] = 0; - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: Firmware Date/Time %s (UTC)\n", - (PCSTR)dateString - )); - } - } - -//////////////////////////////////////////////////////////////////////////////// -// items expected not to always be current -//////////////////////////////////////////////////////////////////////////////// - - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureWriteProtect); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Software Write Protect" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureRandomReadable); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Random Reads" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureMultiRead); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Multi-Read" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureCdRead); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "reading from CD-ROM/R/RW" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdRead); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DVD Structure Reads" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureRandomWritable); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Random Writes" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureIncrementalStreamingWritable); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Incremental Streaming Writing" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureSectorErasable); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Sector Erasable Media" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureFormattable); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Formatting" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDefectManagement); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "defect management" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureWriteOnce); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Write Once Media" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureRestrictedOverwrite); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Restricted Overwrites" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureCdrwCAVWrite); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "CD-RW CAV recording" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureMrw); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Mount Rainier media" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureEnhancedDefectReporting); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Enhanced Defect Reporting" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdPlusRW); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DVD+RW media" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureRigidRestrictedOverwrite); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Rigid Restricted Overwrite" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureCdTrackAtOnce); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "CD Recording (Track At Once)" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureCdMastering); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "CD Recording (Mastering)" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdRecordableWrite); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DVD Recording (Mastering)" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDDCDRead); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DD CD Reading" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDDCDRWrite); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DD CD-R Writing" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDDCDRWWrite); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DD CD-RW Writing" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureLayerJumpRecording); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Layer Jump Recording" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureHDDVDRead); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "HD-DVD Reading" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureHDDVDWrite); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "HD-DVD Writing" - )); - } - - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureSMART); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "S.M.A.R.T." - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureCDAudioAnalogPlay); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Analogue CD Audio Operations" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdCSS); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DVD CSS" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureRealTimeStreaming); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "Real-time Streaming Reads" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDiscControlBlocks); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DVD Disc Control Blocks" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdCPRM); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "DVD CPRM" - )); - } - - header = DeviceFindFeaturePage(Buffer, Usable, FeatureAACS); - if (header) { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT, - "CdromGetConfiguration: %s %s\n", - (header->Current ? - "Currently supports" : "Is able to support"), - "AACS" - )); - } - -#else - PAGED_CODE(); - - UNREFERENCED_PARAMETER(Usable); - UNREFERENCED_PARAMETER(Buffer); - -#endif // DBG - return; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -MediaReadCapacity( - _In_ WDFDEVICE Device - ) -/*++ -Routine Description: - - Get media capacity - -Arguments: - - Device - the device that owns the media - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status; - SCSI_REQUEST_BLOCK srb; - PCDB cdb = NULL; - READ_CAPACITY_DATA capacityData; - - PAGED_CODE(); - - RtlZeroMemory(&srb, sizeof(srb)); - RtlZeroMemory(&capacityData, sizeof(capacityData)); - - cdb = (PCDB)(&srb.Cdb); - - //Prepare SCSI command fields - srb.CdbLength = 10; - srb.TimeOutValue = CDROM_READ_CAPACITY_TIMEOUT; - cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; - - status = DeviceSendSrbSynchronously(Device, - &srb, - &capacityData, - sizeof(READ_CAPACITY_DATA), - FALSE, - NULL); - - //Remember the result - if (!NT_SUCCESS(status)) - { - //Set the BytesPerBlock to zero, this is for safe as if error happens this field should stay zero (no change). - //it will be treated as error case in MediaReadCapacityDataInterpret() - capacityData.BytesPerBlock = 0; - } - - MediaReadCapacityDataInterpret(Device, &capacityData); - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -VOID -MediaReadCapacityDataInterpret( - _In_ WDFDEVICE Device, - _In_ PREAD_CAPACITY_DATA ReadCapacityBuffer - ) -/*++ -Routine Description: - - Interpret media capacity and set corresponding fields in device context - -Arguments: - - Device - the device that owns the media - - ReadCapacityBuffer - data buffer of capacity - -Return Value: - - none - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - ULONG lastSector = 0; - ULONG bps = 0; - ULONG lastBit = 0; - ULONG bytesPerBlock = 0; - BOOLEAN errorHappened = FALSE; - - PAGED_CODE(); - - NT_ASSERT(ReadCapacityBuffer); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "MediaReadCapacityDataInterpret: Entering\n")); - - // Swizzle bytes from Read Capacity and translate into - // the necessary geometry information in the device extension. - bytesPerBlock = ReadCapacityBuffer->BytesPerBlock; - - ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&bytesPerBlock)->Byte3; - ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&bytesPerBlock)->Byte2; - ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&bytesPerBlock)->Byte1; - ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&bytesPerBlock)->Byte0; - - // Insure that bps is a power of 2. - // This corrects a problem with the HP 4020i CDR where it - // returns an incorrect number for bytes per sector. - if (!bps) - { - // Set disk geometry to default values (per ISO 9660). - bps = 2048; - errorHappened = TRUE; - } - else - { - lastBit = (ULONG)(-1); - while (bps) - { - lastBit++; - bps = (bps >> 1); - } - bps = (1 << lastBit); - } - - deviceExtension->DiskGeometry.BytesPerSector = bps; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "MediaReadCapacityDataInterpret: Calculated bps %#x\n", - deviceExtension->DiskGeometry.BytesPerSector)); - - // Copy last sector in reverse byte order. - bytesPerBlock = ReadCapacityBuffer->LogicalBlockAddress; - - ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&bytesPerBlock)->Byte3; - ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&bytesPerBlock)->Byte2; - ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&bytesPerBlock)->Byte1; - ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&bytesPerBlock)->Byte0; - - // Calculate sector to byte shift. - WHICH_BIT(bps, deviceExtension->SectorShift); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, - "MediaReadCapacityDataInterpret: Sector size is %d\n", - deviceExtension->DiskGeometry.BytesPerSector)); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "MediaReadCapacityDataInterpret: Number of Sectors is %d\n", - lastSector + 1)); - - // Calculate media capacity in bytes. - if (errorHappened) - { - // Set disk geometry to default values (per ISO 9660). - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff); - } - else - { - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); - deviceExtension->PartitionLength.QuadPart = - (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); - } - - // we've defaulted to 32/64 forever. don't want to change this now... - deviceExtension->DiskGeometry.TracksPerCylinder = 0x40; - deviceExtension->DiskGeometry.SectorsPerTrack = 0x20; - - // Calculate number of cylinders. - deviceExtension->DiskGeometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1) / (32 * 64)); - - deviceExtension->DiskGeometry.MediaType = RemovableMedia; - - return; -} - - -_IRQL_requires_max_(APC_LEVEL) -VOID -DevicePickDvdRegion( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - pick a default dvd region - -Arguments: - - Device - Device Object - -Return Value: - - none - ---*/ -{ - NTSTATUS status; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - - // these five pointers all point to dvdReadStructure or part of - // its data, so don't deallocate them more than once! - PDVD_READ_STRUCTURE dvdReadStructure; - PDVD_COPY_PROTECT_KEY copyProtectKey; - PDVD_COPYRIGHT_DESCRIPTOR dvdCopyRight; - PDVD_RPC_KEY rpcKey; - PDVD_SET_RPC_KEY dvdRpcKey; - - size_t bytesReturned = 0; - ULONG bufferLen = 0; - UCHAR mediaRegion = 0; - ULONG pickDvdRegion = 0; - ULONG defaultDvdRegion = 0; - ULONG dvdRegion = 0; - WDFKEY registryKey = NULL; - - DECLARE_CONST_UNICODE_STRING(registryValueName, DVD_DEFAULT_REGION); - - PAGED_CODE(); - - if ((pickDvdRegion = InterlockedExchange((PLONG)&deviceExtension->DeviceAdditionalData.PickDvdRegion, 0)) == 0) - { - // it was non-zero, so either another thread will do this, or - // we no longer need to pick a region - return; - } - - bufferLen = max( - max(sizeof(DVD_DESCRIPTOR_HEADER) + - sizeof(DVD_COPYRIGHT_DESCRIPTOR), - sizeof(DVD_READ_STRUCTURE) - ), - max(DVD_RPC_KEY_LENGTH, - DVD_SET_RPC_KEY_LENGTH - ) - ); - - dvdReadStructure = (PDVD_READ_STRUCTURE) - ExAllocatePool2(POOL_FLAG_PAGED, bufferLen, DVD_TAG_DVD_REGION); - - if (dvdReadStructure == NULL) - { - InterlockedExchange((PLONG)&deviceExtension->DeviceAdditionalData.PickDvdRegion, pickDvdRegion); - return; - } - - copyProtectKey = (PDVD_COPY_PROTECT_KEY)dvdReadStructure; - - dvdCopyRight = (PDVD_COPYRIGHT_DESCRIPTOR) - ((PDVD_DESCRIPTOR_HEADER)dvdReadStructure)->Data; - - // get the media region - RtlZeroMemory (dvdReadStructure, bufferLen); - dvdReadStructure->Format = DvdCopyrightDescriptor; - - // Build and send a request for READ_KEY - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Getting Copyright Descriptor\n", - Device)); - - status = ReadDvdStructure(deviceExtension, - NULL, - dvdReadStructure, - sizeof(DVD_READ_STRUCTURE), - dvdReadStructure, - sizeof(DVD_DESCRIPTOR_HEADER) + sizeof(DVD_COPYRIGHT_DESCRIPTOR), - &bytesReturned); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Got Copyright Descriptor %x\n", - Device, status)); - - if ((NT_SUCCESS(status)) && - (dvdCopyRight->CopyrightProtectionType == 0x01)) - { - // keep the media region bitmap around - // a 1 means ok to play - if (dvdCopyRight->RegionManagementInformation == 0xff) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): RegionManagementInformation " - "is set to dis-allow playback for all regions. This is " - "most likely a poorly authored disc. defaulting to all " - "region disc for purpose of choosing initial region\n", - Device)); - dvdCopyRight->RegionManagementInformation = 0; - } - - mediaRegion = ~dvdCopyRight->RegionManagementInformation; - } - else - { - // can't automatically pick a default region on a drive without media, so just exit - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): failed to auto-choose a region due to status %x getting copyright descriptor\n", - Device, status)); - goto getout; - } - - // get the device region - RtlZeroMemory (copyProtectKey, bufferLen); - copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH; - copyProtectKey->KeyType = DvdGetRpcKey; - - // Build and send a request for READ_KEY for RPC key - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Getting RpcKey\n", - Device)); - status = DvdStartSessionReadKey(deviceExtension, - IOCTL_DVD_READ_KEY, - NULL, - copyProtectKey, - DVD_RPC_KEY_LENGTH, - copyProtectKey, - DVD_RPC_KEY_LENGTH, - &bytesReturned); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Got RpcKey %x\n", - Device, status)); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): failed to get RpcKey from " - "a DVD Device\n", Device)); - goto getout; - } - - // so we now have what we can get for the media region and the - // drive region. we will not set a region if the drive has one - // set already (mask is not all 1's), nor will we set a region - // if there are no more user resets available. - rpcKey = (PDVD_RPC_KEY)copyProtectKey->KeyData; - - if (rpcKey->RegionMask != 0xff) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): not picking a region since " - "it is already chosen\n", Device)); - goto getout; - } - - if (rpcKey->UserResetsAvailable <= 1) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): not picking a region since " - "only one change remains\n", Device)); - goto getout; - } - - // OOBE sets this key based upon the system locale - status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - ®istryKey); - - if (NT_SUCCESS(status)) - { - status = WdfRegistryQueryULong(registryKey, - ®istryValueName, - &defaultDvdRegion); - - WdfRegistryClose(registryKey); - } - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): failed to read registry value due to status %x\n", - Device, status)); - - // by default the default Dvd region is 0 - defaultDvdRegion = 0; - status = STATUS_SUCCESS; - } - - if (defaultDvdRegion > DVD_MAX_REGION) - { - // the registry has a bogus default - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): registry has a bogus default " - "region value of %x\n", Device, defaultDvdRegion)); - - defaultDvdRegion = 0; - } - - // if defaultDvdRegion == 0, it means no default. - - // we will select the initial dvd region for the user - - if ((defaultDvdRegion != 0) && - (mediaRegion & (1 << (defaultDvdRegion - 1)))) - { - // first choice: - // the media has region that matches - // the default dvd region. - dvdRegion = (1 << (defaultDvdRegion - 1)); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Choice #1: media matches " - "drive's default, chose region %x\n", Device, dvdRegion)); - } - else if (mediaRegion) - { - // second choice: - // pick the lowest region number from the media - UCHAR mask = 1; - dvdRegion = 0; - - while (mediaRegion && !dvdRegion) - { - // pick the lowest bit - dvdRegion = mediaRegion & mask; - mask <<= 1; - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Choice #2: choosing lowest " - "media region %x\n", Device, dvdRegion)); - } - else if (defaultDvdRegion) - { - // third choice: - // default dvd region from the dvd class installer - dvdRegion = (1 << (defaultDvdRegion - 1)); - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Choice #3: using default " - "region for this install %x\n", Device, dvdRegion)); - } - else - { - // unable to pick one for the user -- this should rarely - // happen, since the proppage dvd class installer sets - // the key based upon the system locale - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Choice #4: failed to choose " - "a media region\n", Device)); - goto getout; - } - - // now that we've chosen a region, set the region by sending the - // appropriate request to the drive - RtlZeroMemory (copyProtectKey, bufferLen); - copyProtectKey->KeyLength = DVD_SET_RPC_KEY_LENGTH; - copyProtectKey->KeyType = DvdSetRpcKey; - dvdRpcKey = (PDVD_SET_RPC_KEY)copyProtectKey->KeyData; - dvdRpcKey->PreferredDriveRegionCode = (UCHAR)~dvdRegion; - - // Build and send request for SEND_KEY - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Sending new Rpc Key to region %x\n", - Device, dvdRegion)); - - status = DvdSendKey(deviceExtension, - NULL, - copyProtectKey, - DVD_SET_RPC_KEY_LENGTH, - &bytesReturned); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "DevicePickDvdRegion (%p): Sent new Rpc Key %x\n", - Device, status)); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "DevicePickDvdRegion (%p): unable to set dvd initial " - " region code (%x)\n", Device, status)); - } - else - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, "DevicePickDvdRegion (%p): Successfully set dvd " - "initial region\n", Device)); - - pickDvdRegion = 0; - } - -getout: - if (dvdReadStructure) - { - FREE_POOL(dvdReadStructure); - } - - // update the new PickDvdRegion value - InterlockedExchange((PLONG)&deviceExtension->DeviceAdditionalData.PickDvdRegion, pickDvdRegion); - - return; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceRegisterInterface( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ CDROM_DEVICE_INTERFACES InterfaceType - ) -/*++ -Routine Description: - - used to register device class interface or mount device interface - -Arguments: - - DeviceExtension - device context - - InterfaceType - interface type to be registered. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status; - WDFSTRING string = NULL; - GUID* interfaceGuid = NULL; - PUNICODE_STRING savingString = NULL; - BOOLEAN setRestricted = FALSE; - UNICODE_STRING localString; - - PAGED_CODE(); - - //Get parameters - switch(InterfaceType) - { - case CdRomDeviceInterface: - interfaceGuid = (LPGUID)&GUID_DEVINTERFACE_CDROM; - setRestricted = TRUE; - savingString = &localString; - break; - case MountedDeviceInterface: - interfaceGuid = (LPGUID)&MOUNTDEV_MOUNTED_DEVICE_GUID; - savingString = &(DeviceExtension->MountedDeviceInterfaceName); - break; - default: - return STATUS_INVALID_PARAMETER; - } - - status = WdfDeviceCreateDeviceInterface(DeviceExtension->Device, - interfaceGuid, - NULL); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "DeviceRegisterInterface: Unable to register cdrom " - "DCA for fdo %p type: %s [%lx]\n", - DeviceExtension->Device, - (InterfaceType == CdRomDeviceInterface)? "CdRom Interface" : "Mounted Device Interface", - status)); - } - - // Retrieve interface string - if (NT_SUCCESS(status)) - { - // The string object will be released when its parent object is released. - WDF_OBJECT_ATTRIBUTES attributes; - - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = DeviceExtension->Device; - - status = WdfStringCreate(WDF_NO_OBJECT_ATTRIBUTES, - NULL, - &string); - } - - if (NT_SUCCESS(status)) - { - status = WdfDeviceRetrieveDeviceInterfaceString(DeviceExtension->Device, - interfaceGuid, - NULL, - string); - } - - if (NT_SUCCESS(status)) - { - WdfStringGetUnicodeString(string, savingString); - - if (setRestricted) { - - - WdfObjectDelete(string); - } - } - - return status; -} // end DeviceRegisterInterface() - - -VOID -DeviceRestoreDefaultSpeed( - _In_ WDFWORKITEM WorkItem - ) -/*++ - -Routine Description: - - This workitem is called on a media change when the CDROM device - speed should be restored to the default value. - -Arguments: - - Fdo - Supplies the device object for the CDROM device. - WorkItem - Supplies the pointer to the workitem. - -Return Value: - - None - ---*/ -{ - NTSTATUS status; - WDFDEVICE device = WdfWorkItemGetParentObject(WorkItem); - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device); - PPERFORMANCE_DESCRIPTOR perfDescriptor; - ULONG transferLength = sizeof(PERFORMANCE_DESCRIPTOR); - SCSI_REQUEST_BLOCK srb = {0}; - PCDB cdb = (PCDB)srb.Cdb; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DeviceRestoreDefaultSpeed: Restore device speed for %p\n", device)); - - perfDescriptor = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - transferLength, - CDROM_TAG_STREAM); - if (perfDescriptor == NULL) - { - return; - } - - RtlZeroMemory(perfDescriptor, transferLength); - - perfDescriptor->RestoreDefaults = TRUE; - - srb.TimeOutValue = deviceExtension->TimeOutValue; - - srb.CdbLength = 12; - cdb->SET_STREAMING.OperationCode = SCSIOP_SET_STREAMING; - REVERSE_BYTES_SHORT(&cdb->SET_STREAMING.ParameterListLength, &transferLength); - - status = DeviceSendSrbSynchronously(device, - &srb, - perfDescriptor, - transferLength, - TRUE, - NULL); - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DeviceRestoreDefaultSpeed: Set Streaming command completed with status: 0x%X\n", status)); - - FREE_POOL(perfDescriptor); - WdfObjectDelete(WorkItem); - - return; -} - -// custom string match -- careful! -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -StringsAreMatched( - _In_opt_z_ PCHAR StringToMatch, - _In_z_ PCHAR TargetString - ) -/*++ - -Routine Description: - - compares if two strings are identical - -Arguments: - - StringToMatch - source string. - TargetString - target string. - -Return Value: - - BOOLEAN - TRUE (identical); FALSE (not match) - ---*/ -{ - size_t length; - - PAGED_CODE(); - - NT_ASSERT(TargetString); - - // if no match requested, return TRUE - if (StringToMatch == NULL) - { - return TRUE; - } - - // cache the string length for efficiency - length = strlen(StringToMatch); - - // ZERO-length strings may only match zero-length strings - if (length == 0) - { - return (strlen(TargetString) == 0); - } - - // strncmp returns zero if the strings match - return (strncmp(StringToMatch, TargetString, length) == 0); -} - - -NTSTATUS -RequestSetContextFields( - _In_ WDFREQUEST Request, - _In_ PSYNC_HANDLER Handler - ) -/*++ - -Routine Description: - - set the request object context fields - -Arguments: - - Request - request object. - Handler - the function that finally handles this request. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - PKEVENT syncEvent = NULL; - - syncEvent = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(KEVENT), - CDROM_TAG_SYNC_EVENT); - - if (syncEvent == NULL) - { - // memory allocation failed. - status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - // now, put the special synchronization information into the context - requestContext->SyncRequired = TRUE; - requestContext->SyncEvent = syncEvent; - requestContext->SyncCallback = Handler; - - status = STATUS_SUCCESS; - } - - return status; -} - - -NTSTATUS -RequestDuidGetDeviceIdProperty( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - - -Arguments: - - DeviceExtension - device context - Request - request object. - RequestParameters - request parameter - DataLength - transferred data length. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSTORAGE_DEVICE_ID_DESCRIPTOR deviceIdDescriptor = NULL; - PSTORAGE_DESCRIPTOR_HEADER descHeader = NULL; - STORAGE_PROPERTY_ID propertyId = StorageDeviceIdProperty; - - *DataLength = 0; - - // Get the VPD page 83h data. - status = DeviceRetrieveDescriptor(DeviceExtension->Device, - &propertyId, - (PSTORAGE_DESCRIPTOR_HEADER*)&deviceIdDescriptor); - - if (NT_SUCCESS(status) && (deviceIdDescriptor == NULL)) - { - status = STATUS_NOT_FOUND; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &descHeader, - NULL); - } - - if (NT_SUCCESS(status)) - { - PSTORAGE_DEVICE_UNIQUE_IDENTIFIER storageDuid = NULL; - ULONG offset = descHeader->Size; - PUCHAR dest = (PUCHAR)descHeader + offset; - size_t outputBufferSize; - - outputBufferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength; - - // Adjust required size and potential destination location. - status = RtlULongAdd(descHeader->Size, deviceIdDescriptor->Size, &descHeader->Size); - - if (NT_SUCCESS(status) && - (outputBufferSize < descHeader->Size)) - { - // Output buffer is too small. Return error and make sure - // the caller gets info about required buffer size. - *DataLength = descHeader->Size; - status = STATUS_BUFFER_OVERFLOW; - } - - if (NT_SUCCESS(status)) - { - storageDuid = (PSTORAGE_DEVICE_UNIQUE_IDENTIFIER)descHeader; - storageDuid->StorageDeviceIdOffset = offset; - - RtlCopyMemory(dest, - deviceIdDescriptor, - deviceIdDescriptor->Size); - - *DataLength = storageDuid->Size; - status = STATUS_SUCCESS; - } - - FREE_POOL(deviceIdDescriptor); - } - - return status; -} - -NTSTATUS -RequestDuidGetDeviceProperty( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - - -Arguments: - - DeviceExtension - device context - Request - request object. - RequestParameters - request parameter - DataLength - transferred data length. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = DeviceExtension->DeviceDescriptor; - PSTORAGE_DESCRIPTOR_HEADER descHeader = NULL; - PSTORAGE_DEVICE_UNIQUE_IDENTIFIER storageDuid; - PUCHAR dest = NULL; - - if (deviceDescriptor == NULL) - { - status = STATUS_NOT_FOUND; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &descHeader, - NULL); - } - - if (NT_SUCCESS(status) && - (deviceDescriptor->SerialNumberOffset == 0)) - { - status = STATUS_NOT_FOUND; - } - - // Use this info only if serial number is available. - if (NT_SUCCESS(status)) - { - ULONG offset = descHeader->Size; - size_t outputBufferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength; - - // Adjust required size and potential destination location. - dest = (PUCHAR)descHeader + offset; - - status = RtlULongAdd(descHeader->Size, deviceDescriptor->Size, &descHeader->Size); - - if (NT_SUCCESS(status) && - (outputBufferSize < descHeader->Size)) - { - // Output buffer is too small. Return error and make sure - // the caller get info about required buffer size. - *DataLength = descHeader->Size; - status = STATUS_BUFFER_OVERFLOW; - } - - if (NT_SUCCESS(status)) - { - storageDuid = (PSTORAGE_DEVICE_UNIQUE_IDENTIFIER)descHeader; - storageDuid->StorageDeviceOffset = offset; - - RtlCopyMemory(dest, - deviceDescriptor, - deviceDescriptor->Size); - - *DataLength = storageDuid->Size; - status = STATUS_SUCCESS; - } - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -ULONG -DeviceRetrieveModeSenseUsingScratch( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, - _In_ ULONG Length, - _In_ UCHAR PageCode, - _In_ UCHAR PageControl - ) -/*++ - -Routine Description: - - retrieve mode sense informaiton of the device - -Arguments: - - DeviceExtension - device context - ModeSenseBuffer - buffer to savee the mode sense info. - Length - buffer length - PageCode - . - PageControl - - -Return Value: - - ULONG - transferred data length - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - ULONG transferSize = min(Length, DeviceExtension->ScratchContext.ScratchBufferSize); - CDB cdb; - - PAGED_CODE(); - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb.MODE_SENSE.PageCode = PageCode; - cdb.MODE_SENSE.Pc = PageControl; - cdb.MODE_SENSE.AllocationLength = (UCHAR)transferSize; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, NULL, transferSize, TRUE, &cdb, 6); - - if (NT_SUCCESS(status)) - { - transferSize = min(Length, DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength); - RtlCopyMemory(ModeSenseBuffer, - DeviceExtension->ScratchContext.ScratchBuffer, - transferSize); - } - - ScratchBuffer_EndUse(DeviceExtension); - - return transferSize; -} - -_IRQL_requires_max_(APC_LEVEL) -PVOID -ModeSenseFindSpecificPage( - _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, - _In_ size_t Length, - _In_ UCHAR PageMode, - _In_ BOOLEAN Use6BytesCdb - ) -/*++ - -Routine Description: - - This routine scans through the mode sense data and finds the requested - mode sense page code. - -Arguments: - ModeSenseBuffer - Supplies a pointer to the mode sense data. - - Length - Indicates the length of valid data. - - PageMode - Supplies the page mode to be searched for. - - Use6BytesCdb - Indicates whether 6 or 10 byte mode sense was used. - -Return Value: - - A pointer to the the requested mode page. If the mode page was not found - then NULL is return. - ---*/ -{ - PCHAR limit; - ULONG parameterHeaderLength; - PVOID result = NULL; - - PAGED_CODE(); - - limit = ModeSenseBuffer + Length; - parameterHeaderLength = (Use6BytesCdb) - ? sizeof(MODE_PARAMETER_HEADER) - : sizeof(MODE_PARAMETER_HEADER10); - - if (Length >= parameterHeaderLength) - { - PMODE_PARAMETER_HEADER10 modeParam10; - ULONG blockDescriptorLength; - - // Skip the mode select header and block descriptors. - if (Use6BytesCdb) - { - blockDescriptorLength = ((PMODE_PARAMETER_HEADER)ModeSenseBuffer)->BlockDescriptorLength; - } - else - { - modeParam10 = (PMODE_PARAMETER_HEADER10) ModeSenseBuffer; - blockDescriptorLength = modeParam10->BlockDescriptorLength[1]; - } - - ModeSenseBuffer += parameterHeaderLength + blockDescriptorLength; - - // ModeSenseBuffer now points at pages. Walk the pages looking for the - // requested page until the limit is reached. - while (ModeSenseBuffer + - RTL_SIZEOF_THROUGH_FIELD(MODE_DISCONNECT_PAGE, PageLength) < limit) - { - if (((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageCode == PageMode) - { - // found the mode page. make sure it's safe to touch it all - // before returning the pointer to caller - if (ModeSenseBuffer + ((PMODE_DISCONNECT_PAGE)ModeSenseBuffer)->PageLength > limit) - { - // Return NULL since the page is not safe to access in full - result = NULL; - } - else - { - result = ModeSenseBuffer; - } - break; - } - - // Advance to the next page which is 4-byte-aligned offset after this page. - ModeSenseBuffer += ((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageLength + - RTL_SIZEOF_THROUGH_FIELD(MODE_DISCONNECT_PAGE, PageLength); - } - } - - return result; -} // end ModeSenseFindSpecificPage() - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -PerformEjectionControl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ MEDIA_LOCK_TYPE LockType, - _In_ BOOLEAN Lock - ) -/*++ - -Routine Description: - - ejection control process - -Arguments: - - DeviceExtension - device extension - Request - WDF request to be used for communication with the device - LockType - the type of lock - Lock - if TRUE, lock the device; if FALSE, unlock it - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status; - PFILE_OBJECT_CONTEXT fileObjectContext = NULL; - SCSI_REQUEST_BLOCK srb; - PCDB cdb = NULL; - - LONG newLockCount = 0; - LONG newProtectedLockCount = 0; - LONG newInternalLockCount = 0; - LONG newFileLockCount = 0; - BOOLEAN countChanged = FALSE; - BOOLEAN previouslyLocked = FALSE; - BOOLEAN nowLocked = FALSE; - - PAGED_CODE(); - - // Prevent race conditions while working with lock counts - status = WdfWaitLockAcquire(DeviceExtension->EjectSynchronizationLock, NULL); - if (!NT_SUCCESS(status)) - { - NT_ASSERT(FALSE); - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "PerformEjectionControl: " - "Received request for %s lock type\n", - LockTypeStrings[LockType] - )); - - - // If this is a "secured" request, retrieve the file object context - if (LockType == SecureMediaLock) - { - WDFFILEOBJECT fileObject = NULL; - - fileObject = WdfRequestGetFileObject(Request); - - if (fileObject == NULL) - { - status = STATUS_INVALID_HANDLE; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "FileObject does not match to the one in IRP_MJ_CREATE, KMDF returns NULL\n")); - goto Exit; - } - - fileObjectContext = FileObjectGetContext(fileObject); - NT_ASSERT(fileObjectContext != NULL); - } - - // Lock counts should never fall below 0 - NT_ASSERT(DeviceExtension->LockCount >= 0); - NT_ASSERT(DeviceExtension->ProtectedLockCount >= 0); - NT_ASSERT(DeviceExtension->InternalLockCount >= 0); - - // Get the current lock counts - newLockCount = DeviceExtension->LockCount; - newProtectedLockCount = DeviceExtension->ProtectedLockCount; - newInternalLockCount = DeviceExtension->InternalLockCount; - if (fileObjectContext) - { - // fileObjectContext->LockCount is ULONG and should always >= 0 - newFileLockCount = fileObjectContext->LockCount; - } - - // Determine which lock counts need to be changed and how - if (Lock && LockType == SimpleMediaLock) - { - newLockCount++; - countChanged = TRUE; - } - else if (Lock && LockType == SecureMediaLock) - { - newFileLockCount++; - newProtectedLockCount++; - countChanged = TRUE; - } - else if (Lock && LockType == InternalMediaLock) - { - newInternalLockCount++; - countChanged = TRUE; - } - else if (!Lock && LockType == SimpleMediaLock) - { - if (newLockCount != 0) - { - newLockCount--; - countChanged = TRUE; - } - } - else if (!Lock && LockType == SecureMediaLock) - { - if ( (newFileLockCount == 0) || (newProtectedLockCount == 0) ) - { - status = STATUS_INVALID_DEVICE_STATE; - goto Exit; - } - newFileLockCount--; - newProtectedLockCount--; - countChanged = TRUE; - } - else if (!Lock && LockType == InternalMediaLock) - { - NT_ASSERT(newInternalLockCount != 0); - newInternalLockCount--; - countChanged = TRUE; - } - - if ( (DeviceExtension->LockCount != 0) || - (DeviceExtension->ProtectedLockCount != 0) || - (DeviceExtension->InternalLockCount != 0) ) - { - previouslyLocked = TRUE; - } - if ( (newLockCount != 0) || - (newProtectedLockCount != 0) || - (newInternalLockCount != 0) ) - { - nowLocked = TRUE; - } - - // Only send command down to device when necessary - if (previouslyLocked != nowLocked) - { - // Compose and send the PREVENT ALLOW MEDIA REMOVAL command. - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - srb.CdbLength = 6; - srb.TimeOutValue = DeviceExtension->TimeOutValue; - - cdb = (PCDB)&srb.Cdb; - cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL; - cdb->MEDIA_REMOVAL.Prevent = Lock; - - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - &srb, - NULL, - 0, - FALSE, - Request); - } - -Exit: - - // Store the updated lock counts on success - if (countChanged && NT_SUCCESS(status)) - { - DeviceExtension->LockCount = newLockCount; - DeviceExtension->ProtectedLockCount = newProtectedLockCount; - DeviceExtension->InternalLockCount = newInternalLockCount; - if (fileObjectContext) - { - fileObjectContext->LockCount = newFileLockCount; - } - } - - WdfWaitLockRelease(DeviceExtension->EjectSynchronizationLock); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "PerformEjectionControl: %!STATUS!, " - "Count Changed: %d, Command Sent: %d, " - "Current Counts: Internal: %x Secure: %x Simple: %x\n", - status, - countChanged, - previouslyLocked != nowLocked, - DeviceExtension->InternalLockCount, - DeviceExtension->ProtectedLockCount, - DeviceExtension->LockCount - )); - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceUnlockExclusive( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFFILEOBJECT FileObject, - _In_ BOOLEAN IgnorePreviousMediaChanges - ) -/*++ - -Routine Description: - - to unlock the exclusive lock - -Arguments: - - DeviceExtension - device context - FileObject - file object that currently holds the lock - IgnorePreviousMediaChanges - if TRUE, ignore previously accumulated media changes - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &DeviceExtension->DeviceAdditionalData; - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - BOOLEAN ANPending = 0; - LONG requestInUse = 0; - - PAGED_CODE(); - - if (!EXCLUSIVE_MODE(cdData)) - { - // Device is not locked for exclusive access. - // Can not process unlock request. - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessUnlockDevice: Device not locked for exclusive access, can't unlock device.\n")); - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (!EXCLUSIVE_OWNER(cdData, FileObject)) - { - // Request not from the exclusive owner, can't unlock the device. - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessUnlockDevice: Unable to unlock device, invalid file object\n")); - - status = STATUS_INVALID_HANDLE; - } - - if (NT_SUCCESS(status)) - { - // Unless we were explicitly requested not to do so, generate a media removal notification - // followed by a media arrival notification similar to volume lock/unlock file system events. - if (!IgnorePreviousMediaChanges) - { - MEDIA_CHANGE_DETECTION_STATE previousMediaState = MediaUnknown; - - // Change the media state to "unavailable", which will cause a removal notification if the media - // was previously present. At the same time, store the previous state in previousMediaState. - DeviceSetMediaChangeStateEx(DeviceExtension, MediaUnavailable, &previousMediaState); - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DeviceUnlockExclusive: Changing the media state to MediaUnavailable\n")); - - // Restore the previous media state, which will cause a media arrival notification if the media - // was originally present. - DeviceSetMediaChangeStateEx(DeviceExtension, previousMediaState, NULL); - } - - // Set DO_VERIFY_VOLUME so that the file system will remount on it. - if (IsVolumeMounted(DeviceExtension->DeviceObject)) - { - SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME); - } - - // Set MMC state to update required - cdData->Mmc.WriteAllowed = FALSE; - cdData->Mmc.UpdateState = CdromMmcUpdateRequired; - - // Send unlock notification - DeviceSendNotification(DeviceExtension, - &GUID_IO_CDROM_EXCLUSIVE_UNLOCK, - 0, - NULL); - - InterlockedExchangePointer((PVOID)&cdData->ExclusiveOwner, NULL); - - if ((info != NULL) && (info->AsynchronousNotificationSupported != FALSE)) - { - ANPending = info->ANSignalPendingDueToExclusiveLock; - info->ANSignalPendingDueToExclusiveLock = FALSE; - - if ((ANPending != FALSE) && (info->MediaChangeDetectionDisableCount == 0)) - { - // if the request is not in use, mark it as such. - requestInUse = InterlockedCompareExchange((PLONG)&info->MediaChangeRequestInUse, 1, 0); - - if (requestInUse == 0) - { - // The last MCN finished. ok to issue the new one. - RequestSetupMcnSyncIrp(DeviceExtension); - - // The irp will go into KMDF framework and a request will be created there to represent it. - IoCallDriver(DeviceExtension->DeviceObject, info->MediaChangeSyncIrp); - } - } - } - } - - return status; -} - - -VOID -RequestCompletion( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ NTSTATUS Status, - _In_ ULONG_PTR Information - ) -{ -#ifdef DBG - ULONG ioctlCode = 0; - WDF_REQUEST_PARAMETERS requestParameters; - - // Get the Request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - if (requestParameters.Type == WdfRequestTypeDeviceControl) - { - ioctlCode = requestParameters.Parameters.DeviceIoControl.IoControlCode; - - if (requestParameters.Parameters.DeviceIoControl.IoControlCode != IOCTL_MCN_SYNC_FAKE_IOCTL) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "Request complete - IOCTL - code: %X; Status: %X; Information: %X\n", - ioctlCode, - Status, - (ULONG)Information)); - } - else - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, - "Request complete - IOCTL - code: %X; Status: %X; Information: %X\n", - ioctlCode, - Status, - (ULONG)Information)); - } - } - else if (requestParameters.Type == WdfRequestTypeRead) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "Request complete - READ - Starting Offset: %X; Length: %X; Transferred Length: %X; Status: %X\n", - (ULONG)requestParameters.Parameters.Read.DeviceOffset, - (ULONG)requestParameters.Parameters.Read.Length, - (ULONG)Information, - Status)); - } - else if (requestParameters.Type == WdfRequestTypeWrite) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "Request complete - WRITE - Starting Offset: %X; Length: %X; Transferred Length: %X; Status: %X\n", - (ULONG)requestParameters.Parameters.Write.DeviceOffset, - (ULONG)requestParameters.Parameters.Write.Length, - (ULONG)Information, - Status)); - } -#endif - - if (IoIsErrorUserInduced(Status)) - { - PIRP irp = WdfRequestWdmGetIrp(Request); - if (irp->Tail.Overlay.Thread) - { - IoSetHardErrorOrVerifyDevice(irp, DeviceExtension->DeviceObject); - } - } - - if (!NT_SUCCESS(Status) && DeviceExtension->SurpriseRemoved == TRUE) - { - // IMAPI expects ERROR_DEV_NOT_EXISTS if recorder has been surprised removed, - // or it will retry WRITE commands for up to 3 minutes - // CDROM behavior should be consistent for all requests, including SCSI pass-through - Status = STATUS_DEVICE_DOES_NOT_EXIST; - } - - WdfRequestCompleteWithInformation(Request, Status, Information); - - return; -} - - -VOID -RequestDummyCompletionRoutine( - _In_ WDFREQUEST Request, - _In_ WDFIOTARGET Target, - _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, - _In_ WDFCONTEXT Context - ) -/*++ - -Routine Description: - - This is a dummy competion routine that simply calls WdfRequestComplete. We have to use - this dummy competion routine instead of WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET, because - the latter causes the framework to not check if the I/O target is closed or not. - -Arguments: - - Request - completed request - Target - the I/O target that completed the request - Params - request parameters - Context - not used - -Return Value: - - none - ---*/ -{ - UNREFERENCED_PARAMETER(Target); - UNREFERENCED_PARAMETER(Params); - UNREFERENCED_PARAMETER(Context); - - WdfRequestCompleteWithInformation(Request, - WdfRequestGetStatus(Request), - WdfRequestGetInformation(Request)); -} - - -_IRQL_requires_max_(DISPATCH_LEVEL) -NTSTATUS -DeviceSendPowerDownProcessRequest( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine, - _In_opt_ PVOID Context - ) -/*++ - -Routine Description: - - This function is called during processing power down request. - It is used to send either SYNC CACHE command or STOP UNIT command. - - Caller should set proper value in deviceExtension->PowerContext.PowerChangeState.PowerDown - to trigger the correct command be sent. - -Arguments: - - DeviceExtension - - - CompletionRoutine - Completion routine that needs to be set for the request - - Context - Completion context associated with the completion routine - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status; - BOOLEAN requestSent = FALSE; - - BOOLEAN shouldRetry = TRUE; - PCDB cdb = (PCDB)DeviceExtension->PowerContext.Srb.Cdb; - ULONG timeoutValue = DeviceExtension->TimeOutValue; - ULONG retryCount = 1; - - // reset some fields. - DeviceExtension->PowerContext.RetryIntervalIn100ns = 0; - status = PowerContextReuseRequest(DeviceExtension); - RequestClearSendTime(DeviceExtension->PowerContext.PowerRequest); - - if (!NT_SUCCESS(status)) - { - return status; - } - - // set proper timeout value and max retry count. - switch(DeviceExtension->PowerContext.PowerChangeState.PowerDown) - { - case PowerDownDeviceInitial: - case PowerDownDeviceQuiesced: - case PowerDownDeviceStopped: - break; - - case PowerDownDeviceLocked: - // Case of issuing SYNC CACHE command. Do not use power irp timeout remaining time in this case - // as we want to give best try on SYNC CACHE command. - retryCount = MAXIMUM_RETRIES; - timeoutValue = DeviceExtension->TimeOutValue; - break; - - case PowerDownDeviceFlushed: - { - // Case of issuing STOP UNIT command - // As "Imme" bit is set to '1', this command should be completed in short time. - // This command is at low importance, failure of this command has very small impact. - ULONG secondsRemaining = 0; - -#if (WINVER >= 0x0601) - // this API is introduced in Windows7 - PoQueryWatchdogTime(DeviceExtension->LowerPdo, &secondsRemaining); -#endif - - if (secondsRemaining == 0) - { - // not able to retrieve remaining time from PoQueryWatchdogTime API, use default values. - retryCount = MAXIMUM_RETRIES; - timeoutValue = SCSI_CDROM_TIMEOUT; - } - else - { - // plan to leave about 30 seconds to lower level drivers if possible. - if (secondsRemaining >= 32) - { - retryCount = (secondsRemaining - 30)/SCSI_CDROM_TIMEOUT + 1; - timeoutValue = SCSI_CDROM_TIMEOUT; - - if (retryCount > MAXIMUM_RETRIES) - { - retryCount = MAXIMUM_RETRIES; - } - - if (retryCount == 1) - { - timeoutValue = secondsRemaining - 30; - } - } - else - { - // issue the command with minimal timeout value and do not retry on it. - retryCount = 1; - timeoutValue = 2; - } - } - } - break; - default: - NT_ASSERT( FALSE ); - status = STATUS_NOT_IMPLEMENTED; - return status; - } - - DeviceExtension->PowerContext.RetryCount = retryCount; - - // issue command. - while (shouldRetry) - { - - // set SRB fields. - DeviceExtension->PowerContext.Srb.SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER | - SRB_FLAGS_NO_QUEUE_FREEZE | - SRB_FLAGS_BYPASS_LOCKED_QUEUE | - SRB_FLAGS_D3_PROCESSING; - - DeviceExtension->PowerContext.Srb.Function = SRB_FUNCTION_EXECUTE_SCSI; - DeviceExtension->PowerContext.Srb.TimeOutValue = timeoutValue; - - if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceInitial) - { - DeviceExtension->PowerContext.Srb.Function = SRB_FUNCTION_LOCK_QUEUE; - } - else if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceLocked) - { - DeviceExtension->PowerContext.Srb.Function = SRB_FUNCTION_QUIESCE_DEVICE; - } - else if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceQuiesced) - { - // Case of issuing SYNC CACHE command. - DeviceExtension->PowerContext.Srb.CdbLength = 10; - cdb->SYNCHRONIZE_CACHE10.OperationCode = SCSIOP_SYNCHRONIZE_CACHE; - } - else if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceFlushed) - { - // Case of issuing STOP UNIT command. - DeviceExtension->PowerContext.Srb.CdbLength = 6; - cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; - cdb->START_STOP.Start = 0; - cdb->START_STOP.Immediate = 1; - } - else if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceStopped) - { - DeviceExtension->PowerContext.Srb.Function = SRB_FUNCTION_UNLOCK_QUEUE; - } - - // Set up completion routine and context if requested - if (CompletionRoutine) - { - WdfRequestSetCompletionRoutine(DeviceExtension->PowerContext.PowerRequest, - CompletionRoutine, - Context); - } - - status = RequestSend(DeviceExtension, - DeviceExtension->PowerContext.PowerRequest, - DeviceExtension->IoTarget, - CompletionRoutine ? 0 : WDF_REQUEST_SEND_OPTION_SYNCHRONOUS, - &requestSent); - - if (requestSent) - { - if ((CompletionRoutine == NULL) && - (SRB_STATUS(DeviceExtension->PowerContext.Srb.SrbStatus) != SRB_STATUS_SUCCESS)) - { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_POWER, - "%p\tError occured when issuing %s command to device. Srb %p, Status %x\n", - DeviceExtension->PowerContext.PowerRequest, - (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceQuiesced) ? "SYNC CACHE" : "STOP UNIT", - &DeviceExtension->PowerContext.Srb, - DeviceExtension->PowerContext.Srb.SrbStatus)); - - NT_ASSERT(!(TEST_FLAG(DeviceExtension->PowerContext.Srb.SrbStatus, SRB_STATUS_QUEUE_FROZEN))); - - shouldRetry = RequestSenseInfoInterpret(DeviceExtension, - DeviceExtension->PowerContext.PowerRequest, - &(DeviceExtension->PowerContext.Srb), - retryCount - DeviceExtension->PowerContext.RetryCount, - &status, - &(DeviceExtension->PowerContext.RetryIntervalIn100ns)); - - if (shouldRetry && (DeviceExtension->PowerContext.RetryCount-- == 0)) - { - shouldRetry = FALSE; - } - } - else - { - // succeeded, do not need to retry. - shouldRetry = FALSE; - } - - } - else - { - // request failed to be sent - shouldRetry = FALSE; - } - - if (shouldRetry) - { - LARGE_INTEGER t; - t.QuadPart = -DeviceExtension->PowerContext.RetryIntervalIn100ns; - KeDelayExecutionThread(KernelMode, FALSE, &t); - - status = PowerContextReuseRequest(DeviceExtension); - if (!NT_SUCCESS(status)) - { - shouldRetry = FALSE; - } - } - } - - if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceQuiesced) - { - // record SYNC CACHE command completion time stamp. - KeQueryTickCount(&DeviceExtension->PowerContext.Step1CompleteTime); - } - - return status; -} - -NTSTATUS -RequestSend( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDFIOTARGET IoTarget, - _In_ ULONG Flags, - _Out_opt_ PBOOLEAN RequestSent - ) -/*++ - -Routine Description: - - Send the request to the target, wake up the device from Zero Power state if necessary. - -Arguments: - - DeviceExtension - device extension - Request - the request to be sent - IoTarget - target of the above request - Flags - flags for the operation - RequestSent - optional, if the request was sent - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN requestSent = FALSE; - WDF_REQUEST_SEND_OPTIONS options; - - UNREFERENCED_PARAMETER(DeviceExtension); - - if ((DeviceExtension->ZeroPowerODDInfo != NULL) && - (DeviceExtension->ZeroPowerODDInfo->InZeroPowerState != FALSE)) - { - } - - // Now send down the request - if (NT_SUCCESS(status)) - { - WDF_REQUEST_SEND_OPTIONS_INIT(&options, Flags); - - RequestSetSentTime(Request); - - // send request and check status - - // Disable SDV warning about infinitely waiting in caller's context: - // 1. Some requests (such as SCSI_PASS_THROUGH, contains buffer from user space) need to be sent down in callers context. - // Consequently, these requests wait in callers context until they are allowed to be sent down. - // 2. Considering the situation that during sleep, a request can be hold by storage port driver. When system resumes, any time out value (if we set using KMDF time out value) might be expires. - // This will cause the waiting request being failed (behavior change). Wed rather not set time out value. - - _Analysis_assume_(options.Timeout != 0); - requestSent = WdfRequestSend(Request, IoTarget, &options); - _Analysis_assume_(options.Timeout == 0); - - // If WdfRequestSend fails, or if the WDF_REQUEST_SEND_OPTION_SYNCHRONOUS flag is set, - // the driver can call WdfRequestGetStatus immediately after calling WdfRequestSend. - if ((requestSent == FALSE) || - (Flags & WDF_REQUEST_SEND_OPTION_SYNCHRONOUS)) - { - status = WdfRequestGetStatus(Request); - - if (requestSent == FALSE) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "WdfRequestSend failed: %lx\n", - status - )); - } - } - else - { - status = STATUS_SUCCESS; - } - - if (RequestSent != NULL) - { - *RequestSent = requestSent; - } - } - - return status; -} - diff --git a/storage/class/cdrom/src/data.c b/storage/class/cdrom/src/data.c deleted file mode 100644 index 72ec53b8..00000000 --- a/storage/class/cdrom/src/data.c +++ /dev/null @@ -1,283 +0,0 @@ -/*++ - -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 diff --git a/storage/class/cdrom/src/guid.c b/storage/class/cdrom/src/guid.c deleted file mode 100644 index 8af1f877..00000000 --- a/storage/class/cdrom/src/guid.c +++ /dev/null @@ -1,16 +0,0 @@ -/*-- -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 - - - diff --git a/storage/class/cdrom/src/init.c b/storage/class/cdrom/src/init.c deleted file mode 100644 index 0dc176fd..00000000 --- a/storage/class/cdrom/src/init.c +++ /dev/null @@ -1,2740 +0,0 @@ -/*-- - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - init.c - -Abstract: - - Initialization routines for CDROM - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - - -#include "ntddk.h" -#include "ntddstor.h" -#include "ntstrsafe.h" -#include "devpkey.h" - -#include "cdrom.h" -#include "scratch.h" -#include "mmc.h" - -#ifdef DEBUG_USE_WPP -#include "init.tmh" -#endif - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceInitAllocateBuffers( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceRetrieveScsiAddress( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_ADDRESS ScsiAddress - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceRetrieveDescriptorsAndTransferLength( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceScanSpecialDevices( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitMmcContext( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ); - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceGetMmcSupportInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Out_ PBOOLEAN IsMmcDevice - ); - -#if (NTDDI_VERSION >= NTDDI_WIN8) -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceIsPortable( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Out_ PBOOLEAN IsPortable - ); -#endif - - -#ifdef ALLOC_PRAGMA - -#pragma alloc_text(PAGE, DeviceClaimRelease) -#pragma alloc_text(PAGE, DeviceEvtSelfManagedIoInit) - -#pragma alloc_text(PAGE, DeviceInitReleaseQueueContext) -#pragma alloc_text(PAGE, DeviceInitAllocateBuffers) -#pragma alloc_text(PAGE, DeviceInitPowerContext) -#pragma alloc_text(PAGE, DeviceCreateWellKnownName) -#pragma alloc_text(PAGE, DeviceRetrieveScsiAddress) -#pragma alloc_text(PAGE, DeviceRetrieveDescriptorsAndTransferLength) -#pragma alloc_text(PAGE, DeviceInitializeHotplugInfo) -#pragma alloc_text(PAGE, DeviceScanSpecialDevices) -#pragma alloc_text(PAGE, DeviceGetTimeOutValueFromRegistry) -#pragma alloc_text(PAGE, DeviceGetMmcSupportInfo) -#pragma alloc_text(PAGE, DeviceRetrieveDescriptor) -#pragma alloc_text(PAGE, DeviceRetrieveHackFlagsFromRegistry) -#pragma alloc_text(PAGE, DeviceScanForSpecial) -#pragma alloc_text(PAGE, DeviceHackFlagsScan) -#pragma alloc_text(PAGE, DeviceInitMmcContext) -#pragma alloc_text(PAGE, ScanForSpecialHandler) -#pragma alloc_text(PAGE, DeviceSetRawReadInfo) -#pragma alloc_text(PAGE, DeviceInitializeDvd) -#pragma alloc_text(PAGE, DeviceCacheDeviceInquiryData) - -#if (NTDDI_VERSION >= NTDDI_WIN8) -#pragma alloc_text(PAGE, DeviceIsPortable) -#endif - -#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 -DeviceClaimRelease( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN Release - ) -/*++ - -Routine Description: - - This function claims a device in the port driver. The port driver object - is updated with the correct driver object if the device is successfully - claimed. - -Arguments: - - Device - The WDFDEVICE that needs to be claimed or released. - - Release - Indicates the logical unit should be released rather than claimed. - -Return Value: - - Returns a status indicating success or failure of the operation. - ---*/ -{ - NTSTATUS status; - SCSI_REQUEST_BLOCK srb = {0}; - WDF_MEMORY_DESCRIPTOR descriptor; - WDFREQUEST request; - WDF_OBJECT_ATTRIBUTES attributes; - - PAGED_CODE(); - - //Create a request - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - - status = WdfRequestCreate(&attributes, - DeviceExtension->IoTarget, - &request); - - if (NT_SUCCESS(status)) - { - //fill up srb structure - srb.OriginalRequest = WdfRequestWdmGetIrp(request); - NT_ASSERT(srb.OriginalRequest != NULL); - - srb.Length = sizeof(SCSI_REQUEST_BLOCK); - - srb.Function = Release - ? SRB_FUNCTION_RELEASE_DEVICE - : SRB_FUNCTION_CLAIM_DEVICE; - - - WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&descriptor, - &srb, - sizeof(srb)); - - status = WdfIoTargetSendInternalIoctlOthersSynchronously(DeviceExtension->IoTarget, - request, - IOCTL_SCSI_EXECUTE_NONE, - &descriptor, - NULL, - NULL, - NULL, - NULL); - - NT_ASSERT(!TEST_FLAG(srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)); - - // The request should be deleted. - WdfObjectDelete(request); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DeviceClaimRelease: Failed to %s device, status: 0x%X\n", - Release ? "Release" : "Claim", - status)); - } - } - else - { - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP, - "DeviceClaimRelease: Failed to create request, status: 0x%X\n", - status)); - } - - if (Release) - { - // We only release the device when we don't want to manage it. - // The failure status does not matter. - status = STATUS_SUCCESS; - } - - return status; -} // end DeviceClaimRelease() - - -NTSTATUS -DeviceEvtSelfManagedIoInit( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - This routine is called only once after the device is added in system, so it's used to do - hardware-dependent device initialization work and resource allocation. - If this routine fails, DeviceEvtSelfManagedIoCleanup will be invoked by the framework. - -Arguments: - - Device - Handle to device object - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, - "DeviceEvtSelfManagedIoInit: WDFDEVICE %p is being started.\n", - Device)); - - deviceExtension = DeviceGetExtension(Device); - - // 1. Set/retrieve basic information, some of the following operations may depend on it - if (NT_SUCCESS(status)) - { - // We do not care if this function fails, SCSI address is mainly for debugging/tracing purposes. - (VOID) DeviceRetrieveScsiAddress(deviceExtension, &deviceExtension->ScsiAddress); - } - - if (NT_SUCCESS(status)) - { - status = DeviceRetrieveDescriptorsAndTransferLength(deviceExtension); - } - - if (NT_SUCCESS(status)) - { - // This function should be called after DeviceRetrieveDescriptorsAndTransferLength() - // It depends on MaxTransferLenth fields. - status = DeviceInitAllocateBuffers(deviceExtension); - } - - // 2. The following functions depend on the allocated buffers. - - // perf re-enable after failing. Q: Is this one used by cdrom.sys? - if (NT_SUCCESS(status)) - { - // allow perf to be re-enabled after a given number of failed IOs - // require this number to be at least CLASS_PERF_RESTORE_MINIMUM - ULONG t = CLASS_PERF_RESTORE_MINIMUM; - - DeviceGetParameter(deviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_PERF_RESTORE_VALUE_NAME, - &t); - if (t >= CLASS_PERF_RESTORE_MINIMUM) - { - deviceExtension->PrivateFdoData->Perf.ReEnableThreshhold = t; - } - } - - // 3. Retrieve information about special devices and hack flags. - if (NT_SUCCESS(status)) - { - DeviceRetrieveHackFlagsFromRegistry(deviceExtension); - // scan for bad items. - DeviceScanForSpecial(deviceExtension, CdRomBadItems, DeviceHackFlagsScan); - // Check to see if it's a special device that needs special error process. - DeviceScanSpecialDevices(deviceExtension); // may send command to device - } - - // 4. Initialize the hotplug information only after the ScanForSpecial routines, - // as it relies upon the hack flags - deviceExtension->PrivateFdoData->HackFlags. - if (NT_SUCCESS(status)) - { - status = DeviceInitializeHotplugInfo(deviceExtension); - } - - if (NT_SUCCESS(status)) - { - // cache the device's inquiry data - status = DeviceCacheDeviceInquiryData(deviceExtension); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to cache the device's inquiry data, failng %!STATUS!\n", - status - )); - } - } - - // 5. Initialize MMC context, media change notification stuff and read media capacity - if (NT_SUCCESS(status)) - { - status = DeviceInitializeMediaChangeDetection(deviceExtension); - } - if (NT_SUCCESS(status)) - { - status = DeviceInitMmcContext(deviceExtension); - } - if (NT_SUCCESS(status)) - { - status = DeviceInitializeZPODD(deviceExtension); - } - if (NT_SUCCESS(status)) - { - // Do READ CAPACITY. This SCSI command returns the last sector address - // on the device and the bytes per sector. These are used to calculate - // the drive capacity in bytes. - status = MediaReadCapacity(Device); - - // If READ CAPACITY succeeded, we can safely conclude that there is a media present - if (NT_SUCCESS(status)) - { - DeviceSetMediaChangeStateEx(deviceExtension, - MediaPresent, - NULL); - } - - // READ CAPACITY is not critical for init, ignore all errors occuring during its execution - status = STATUS_SUCCESS; - } - - // 6. Perform DVD-specific initialization - if (NT_SUCCESS(status)) - { - status = DeviceInitializeDvd(Device); - } - - // 7. Miscellaneous initialization actions - if (NT_SUCCESS(status)) - { - if (deviceExtension->PrivateFdoData != NULL) - { - deviceExtension->PrivateFdoData->Perf.OriginalSrbFlags = deviceExtension->SrbFlags; - } - - if (deviceExtension->DeviceAdditionalData.Mmc.IsWriter) - { - // OPC can really take this long per IMAPIv1 timeout.... - deviceExtension->TimeOutValue = max(deviceExtension->TimeOutValue, SCSI_CDROM_OPC_TIMEOUT); - } - } - - // 8. Enable the main timer, create ARC name as needed - if (NT_SUCCESS(status)) - { - // Device successfully added and initialized, increase CdRomCount. - IoGetConfigurationInformation()->CdRomCount++; - - deviceExtension->IsInitialized = TRUE; - - DeviceEnableMainTimer(deviceExtension); - - } - -#if (NTDDI_VERSION >= NTDDI_WIN8) - // 9. Set volume interface properties - if (NT_SUCCESS(status)) - { - BOOLEAN isCritical = FALSE; - BOOLEAN isPortable = FALSE; - BOOLEAN isRemovable = TEST_FLAG(deviceExtension->DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA); - DEVPROP_BOOLEAN propCritical = DEVPROP_FALSE; - DEVPROP_BOOLEAN propPortable = DEVPROP_FALSE; - DEVPROP_BOOLEAN propRemovable = DEVPROP_FALSE; - - status = DeviceIsPortable(deviceExtension, &isPortable); - - if (NT_SUCCESS(status)) - { - if (isPortable) { - SET_FLAG(deviceExtension->DeviceObject->Characteristics, FILE_PORTABLE_DEVICE); - } - - propPortable = isPortable ? DEVPROP_TRUE : DEVPROP_FALSE; - - status = IoSetDeviceInterfacePropertyData(&deviceExtension->MountedDeviceInterfaceName, - &DEVPKEY_Storage_Portable, - 0, - 0, - DEVPROP_TYPE_BOOLEAN, - sizeof(DEVPROP_BOOLEAN), - &propPortable); - } - - if (NT_SUCCESS(status)) - { - propRemovable = isRemovable ? DEVPROP_TRUE : DEVPROP_FALSE; - - status = IoSetDeviceInterfacePropertyData(&deviceExtension->MountedDeviceInterfaceName, - &DEVPKEY_Storage_Removable_Media, - 0, - 0, - DEVPROP_TYPE_BOOLEAN, - sizeof(DEVPROP_BOOLEAN), - &propRemovable); - } - - if (NT_SUCCESS(status)) - { - isCritical = TEST_FLAG(deviceExtension->DeviceObject->Flags, - (DO_SYSTEM_SYSTEM_PARTITION | - DO_SYSTEM_BOOT_PARTITION | - DO_SYSTEM_CRITICAL_PARTITION)); - - propCritical = isCritical ? DEVPROP_TRUE : DEVPROP_FALSE; - - status = IoSetDeviceInterfacePropertyData(&deviceExtension->MountedDeviceInterfaceName, - &DEVPKEY_Storage_System_Critical, - 0, - 0, - DEVPROP_TYPE_BOOLEAN, - sizeof(DEVPROP_BOOLEAN), - &propCritical); - } - - } -#endif - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceInitReleaseQueueContext( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - Part of device initialize routine. Initialize ReleaseQueue related stuff. - -Arguments: - - DeviceExtension - device extension of WDFDEVICE. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDF_OBJECT_ATTRIBUTES attributes; - - PAGED_CODE(); - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - attributes.ParentObject = DeviceExtension->Device; - - status = WdfRequestCreate(&attributes, - DeviceExtension->IoTarget, - &(DeviceExtension->ReleaseQueueRequest)); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Cannot create the release queue request\n")); - - return status; - } - - // Initialize ReleaseQueueInputMemory, a wrapper around ReleaseQueueSrb - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = DeviceExtension->ReleaseQueueRequest; - - status = WdfMemoryCreatePreallocated(&attributes, - &DeviceExtension->ReleaseQueueSrb, - sizeof(SCSI_REQUEST_BLOCK), - &DeviceExtension->ReleaseQueueInputMemory); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Failed to allocate ReleaseQueueSrb.\n")); - - return status; - } - - // Preformat the release queue request here to ensure that this call will never - // fail during an actual release of the queue. - if (NT_SUCCESS(status)) - { - status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget, - DeviceExtension->ReleaseQueueRequest, - IOCTL_SCSI_EXECUTE_NONE, - DeviceExtension->ReleaseQueueInputMemory, - NULL, - NULL, - NULL, - NULL, - NULL); - } - - // Set a CompletionRoutine callback function for ReleaseQueueRequest. - if (NT_SUCCESS(status)) - { - WdfRequestSetCompletionRoutine(DeviceExtension->ReleaseQueueRequest, - DeviceReleaseQueueCompletion, - DeviceExtension->Device); - } - - // Create a spinlock for ReleaseQueueRequest - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = DeviceExtension->Device; - - status = WdfSpinLockCreate(&attributes, - &(DeviceExtension->ReleaseQueueSpinLock)); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, - "DeviceInitReleaseQueueContext: Cannot create the release queue spinlock\n")); - - return status; - } - - // Initialize miscellaneous ReleaseQueue related fields - DeviceExtension->ReleaseQueueNeeded = FALSE; - DeviceExtension->ReleaseQueueInProgress = FALSE; - DeviceExtension->ReleaseQueueSrb.Length = sizeof(SCSI_REQUEST_BLOCK); - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceInitPowerContext( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - Part of device initialize routine. Initialize PowerContext related stuff. - -Arguments: - - DeviceExtension - device extension of WDFDEVICE. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDF_OBJECT_ATTRIBUTES attributes; - - PAGED_CODE(); - - // create request object for Power operations - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - attributes.ParentObject = DeviceExtension->Device; - - status = WdfRequestCreate(&attributes, - DeviceExtension->IoTarget, - &(DeviceExtension->PowerContext.PowerRequest) ); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Cannot create the power request object.\n")); - - return status; - } - - // Preformat the power request. With this being done, we never need to worry about - // WdfIoTargetFormatRequestForInternalIoctlOthers ever failing later. - status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget, - DeviceExtension->PowerContext.PowerRequest, - IOCTL_SCSI_EXECUTE_IN, - NULL, NULL, - NULL, NULL, - NULL, NULL); - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceCreateWellKnownName( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine creates a symbolic link to the cdrom device object - under \dosdevices. The number of the cdrom device does not neccessarily - match between \dosdevices and \device, but usually will be the same. - - Saves the buffer - -Arguments: - - DeviceObject - - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - UNICODE_STRING unicodeLinkName = {0}; - WCHAR wideLinkName[64] = {0}; - PWCHAR savedName; - - LONG cdromNumber = DeviceExtension->DeviceNumber; - - PAGED_CODE(); - - // if already linked, assert then return - if (DeviceExtension->DeviceAdditionalData.WellKnownName.Buffer != NULL) - { - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, - "DeviceCreateWellKnownName: link already exists %p\n", - DeviceExtension->DeviceAdditionalData.WellKnownName.Buffer)); - - NT_ASSERT(FALSE); - - return STATUS_UNSUCCESSFUL; - } - - // find an unused CdRomNN to link to. - // It's doing this way because the same might be used for other device in another driver. - do - { - status = RtlStringCchPrintfW((NTSTRSAFE_PWSTR)wideLinkName, - RTL_NUMBER_OF(wideLinkName), - L"\\DosDevices\\CdRom%d", - cdromNumber); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, - "DeviceCreateWellKnownName: Format symbolic link failed with error: 0x%X\n", status)); - return status; - } - - RtlInitUnicodeString(&unicodeLinkName, wideLinkName); - - status = WdfDeviceCreateSymbolicLink(DeviceExtension->Device, - &unicodeLinkName); - - cdromNumber++; - - } while((status == STATUS_OBJECT_NAME_COLLISION) || - (status == STATUS_OBJECT_NAME_EXISTS)); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, - "DeviceCreateWellKnownName: Error %lx linking %wZ to " - "device %wZ\n", - status, - &unicodeLinkName, - &(DeviceExtension->DeviceName))); - return status; - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceCreateWellKnownName: successfully linked %wZ " - "to device %wZ\n", - &unicodeLinkName, - &(DeviceExtension->DeviceName))); - - // Save away the symbolic link name in the driver data block. We need - // it so we can delete the link when the device is removed. - savedName = ExAllocatePool2(POOL_FLAG_PAGED, - unicodeLinkName.MaximumLength, - CDROM_TAG_STRINGS); - - if (savedName == NULL) - { - // Test Note: test path should excise here to see if the symbolic is deleted by framework. - // IoDeleteSymbolicLink(&unicodeLinkName); - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "DeviceCreateWellKnownName: unable to allocate memory.\n")); - - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory(savedName, unicodeLinkName.MaximumLength); - RtlCopyMemory(savedName, unicodeLinkName.Buffer, unicodeLinkName.MaximumLength); - - RtlInitUnicodeString(&(DeviceExtension->DeviceAdditionalData.WellKnownName), savedName); - - // the name was saved and the link created - - return STATUS_SUCCESS; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceRetrieveScsiAddress( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_ADDRESS ScsiAddress - ) -/*++ - -Routine Description: - - retrieve SCSI address information and put into device extension - -Arguments: - - DeviceExtension - device context. - ScsiAddress - the buffer to put the scsi address info. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status; - WDF_MEMORY_DESCRIPTOR outputDescriptor; - - PAGED_CODE(); - - if ((DeviceExtension == NULL) || - (ScsiAddress == NULL)) - { - return STATUS_INVALID_PARAMETER; - } - - //Get IOTARGET for sending request to port driver. - WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor, - (PVOID)ScsiAddress, - sizeof(SCSI_ADDRESS)); - - status = WdfIoTargetSendIoctlSynchronously(DeviceExtension->IoTarget, - NULL, - IOCTL_SCSI_GET_ADDRESS, - NULL, - &outputDescriptor, - NULL, - NULL); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "DeviceRetrieveScsiAddress: Get Address failed %lx\n", - status)); - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "GetAddress: Port %x, Path %x, Target %x, Lun %x\n", - ScsiAddress->PortNumber, - ScsiAddress->PathId, - ScsiAddress->TargetId, - ScsiAddress->Lun)); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceInitAllocateBuffers( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - Part of device initialize routine. - Allocate all buffers in Device Extension. - -Arguments: - - DeviceExtension - device extension of WDFDEVICE. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PVOID senseData = NULL; - - PAGED_CODE(); - - // allocate a private extension for class data - if (DeviceExtension->PrivateFdoData == NULL) - { - DeviceExtension->PrivateFdoData = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(CDROM_PRIVATE_FDO_DATA), - CDROM_TAG_PRIVATE_DATA); - } - - if (DeviceExtension->PrivateFdoData == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - // initialize the struct's various fields. - RtlZeroMemory(DeviceExtension->PrivateFdoData, sizeof(CDROM_PRIVATE_FDO_DATA)); - } - - // Allocate request sense buffer. - senseData = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - SENSE_BUFFER_SIZE, - CDROM_TAG_SENSE_INFO); - - if (senseData == NULL) - { - // The buffer cannot be allocated. - status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - // Set the sense data pointer in the device extension. - DeviceExtension->SenseData = senseData; - } - - // Allocate scratch buffer -- Must occur after determining - // max transfer size, but before other CD specific detection - // (which relies upon this buffer). - if (!ScratchBuffer_Allocate(DeviceExtension)) - { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to allocate scratch buffer, failing %!STATUS!\n", - status - )); - } - - return status; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceRetrieveDescriptorsAndTransferLength( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - Part of device initialize routine. - Retrieve Device Descriptor and Adaptor Descriptor. - -Arguments: - - DeviceExtension - device extension of WDFDEVICE. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - STORAGE_PROPERTY_ID propertyId; - - PAGED_CODE(); - - if (NT_SUCCESS(status)) - { - // Call port driver to get adapter capabilities. - propertyId = StorageAdapterProperty; - - status = DeviceRetrieveDescriptor(DeviceExtension->Device, - &propertyId, - (PSTORAGE_DESCRIPTOR_HEADER*)&DeviceExtension->AdapterDescriptor); - } - if (NT_SUCCESS(status)) - { - // Call port driver to get device descriptor. - propertyId = StorageDeviceProperty; - - status = DeviceRetrieveDescriptor(DeviceExtension->Device, - &propertyId, - (PSTORAGE_DESCRIPTOR_HEADER*)&DeviceExtension->DeviceDescriptor); - } - if (NT_SUCCESS(status)) - { - // Call port driver to get device power property. - // Not all port drivers support this property, and it's not fatal if this query fails. - propertyId = StorageDevicePowerProperty; - - (void) DeviceRetrieveDescriptor(DeviceExtension->Device, - &propertyId, - (PSTORAGE_DESCRIPTOR_HEADER*)&DeviceExtension->PowerDescriptor); - } - - if (NT_SUCCESS(status)) - { - // Determine the maximum page-aligned and non-page-aligned transfer - // lengths here, so we needn't do this in common READ/WRITE code paths - - // start with the number of pages the adapter can support - ULONG maxAlignedTransfer = DeviceExtension->AdapterDescriptor->MaximumPhysicalPages; - ULONG maxUnalignedTransfer = DeviceExtension->AdapterDescriptor->MaximumPhysicalPages; - - - // Unaligned buffers could cross a page boundary. - if (maxUnalignedTransfer > 1) - { - maxUnalignedTransfer--; - } - - // if we'd overflow multiplying by page size, just max out the - // transfer length allowed by the number of pages limit. - if (maxAlignedTransfer >= (((ULONG)-1) / PAGE_SIZE)) - { - maxAlignedTransfer = (ULONG)-1; - } - else - { - maxAlignedTransfer *= PAGE_SIZE; - } - - if (maxUnalignedTransfer >= (((ULONG)-1) / PAGE_SIZE)) - { - maxUnalignedTransfer = (ULONG)-1; - } - else - { - maxUnalignedTransfer *= PAGE_SIZE; - } - - // finally, take the smaller of the above and the adapter's - // reported maximum number of bytes per transfer. - maxAlignedTransfer = min(maxAlignedTransfer, DeviceExtension->AdapterDescriptor->MaximumTransferLength); - maxUnalignedTransfer = min(maxUnalignedTransfer, DeviceExtension->AdapterDescriptor->MaximumTransferLength); - - // Make sure the values are reasonable and not zero. - maxAlignedTransfer = max(maxAlignedTransfer, PAGE_SIZE); - maxUnalignedTransfer = max(maxUnalignedTransfer, PAGE_SIZE); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "Device %p Max aligned/unaligned transfer size is %x/%x\n", - DeviceExtension->Device, - maxAlignedTransfer, - maxUnalignedTransfer - )); - DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes = maxAlignedTransfer; - DeviceExtension->DeviceAdditionalData.MaxUnalignedTransferBytes = maxUnalignedTransfer; - } - else - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DeviceRetrieveDescriptorsAndTransferLength failed %lx\n", status)); - } - - return status; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceRetrieveDescriptor( - _In_ WDFDEVICE Device, - _In_ PSTORAGE_PROPERTY_ID PropertyId, - _Outptr_ PSTORAGE_DESCRIPTOR_HEADER* Descriptor - ) -/*++ - -Routine Description: - - This routine will perform a query for the specified property id and will - allocate a non-paged buffer to store the data in. It is the responsibility - of the caller to ensure that this buffer is freed. - - This routine must be run at IRQL_PASSIVE_LEVEL - -Arguments: - - Device - the device object - PropertyId - type of property to retrieve - Descriptor - buffer allocated in this function to hold the descriptor data - -Return Value: - - status - ---*/ -{ - NTSTATUS status; - WDF_MEMORY_DESCRIPTOR memoryDescriptor; - - STORAGE_PROPERTY_QUERY query = {0}; - ULONG bufferLength = 0; - - PSTORAGE_DESCRIPTOR_HEADER descriptor = NULL; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - - PAGED_CODE(); - - // Set the passed-in descriptor pointer to NULL as default - *Descriptor = NULL; - - // On the first pass we just want to get the first few - // bytes of the descriptor so we can read it's size - query.PropertyId = *PropertyId; - query.QueryType = PropertyStandardQuery; - - descriptor = (PVOID)&query; - - NT_ASSERT(sizeof(STORAGE_PROPERTY_QUERY) >= (sizeof(ULONG)*2)); - - WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor, - (PVOID)&query, - sizeof(STORAGE_PROPERTY_QUERY)); - - status = WdfIoTargetSendIoctlSynchronously(deviceExtension->IoTarget, - NULL, - IOCTL_STORAGE_QUERY_PROPERTY, - &memoryDescriptor, - &memoryDescriptor, - NULL, - NULL); - - if(!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "DeviceRetrieveDescriptor: error %lx trying to " - "query properties #1\n", status)); - return status; - } - - if (descriptor->Size == 0) - { - // This DebugPrint is to help third-party driver writers - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "DeviceRetrieveDescriptor: size returned was zero?! (status " - "%x\n", status)); - return STATUS_UNSUCCESSFUL; - } - - // This time we know how much data there is so we can - // allocate a buffer of the correct size - bufferLength = descriptor->Size; - NT_ASSERT(bufferLength >= sizeof(STORAGE_PROPERTY_QUERY)); - bufferLength = max(bufferLength, sizeof(STORAGE_PROPERTY_QUERY)); - - descriptor = ExAllocatePool2(POOL_FLAG_NON_PAGED, bufferLength, CDROM_TAG_DESCRIPTOR); - - if(descriptor == NULL) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "DeviceRetrieveDescriptor: unable to memory for descriptor " - "(%d bytes)\n", bufferLength)); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // setup the query again, as it was overwritten above - RtlZeroMemory(&query, sizeof(STORAGE_PROPERTY_QUERY)); - query.PropertyId = *PropertyId; - query.QueryType = PropertyStandardQuery; - - // copy the input to the new outputbuffer - RtlCopyMemory(descriptor, - &query, - sizeof(STORAGE_PROPERTY_QUERY)); - - WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor, - (PVOID)descriptor, - bufferLength); - - status = WdfIoTargetSendIoctlSynchronously(deviceExtension->IoTarget, - NULL, - IOCTL_STORAGE_QUERY_PROPERTY, - &memoryDescriptor, - &memoryDescriptor, - NULL, - NULL); - - if(!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "DeviceRetrieveDescriptor: error %lx trying to " - "query properties #1\n", status)); - FREE_POOL(descriptor); - - return status; - } - - // return the memory we've allocated to the caller - *Descriptor = descriptor; - - return status; -} // end DeviceRetrieveDescriptor() - -_IRQL_requires_max_(PASSIVE_LEVEL) -VOID -DeviceRetrieveHackFlagsFromRegistry( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - try to retrieve hack flages from registry and put the information in - device extension. - -Arguments: - - DeviceExtension - the device context - -Return Value: - - none - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDFKEY hardwareKey = NULL; - WDFKEY subKey = NULL; - ULONG deviceHacks = 0; - - DECLARE_CONST_UNICODE_STRING(subKeyName, CLASSP_REG_SUBKEY_NAME); - DECLARE_CONST_UNICODE_STRING(valueName, CLASSP_REG_HACK_VALUE_NAME); - - PAGED_CODE(); - - status = WdfDeviceOpenRegistryKey(DeviceExtension->Device, - PLUGPLAY_REGKEY_DEVICE, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - &hardwareKey); - if (NT_SUCCESS(status)) - { - status = WdfRegistryOpenKey(hardwareKey, - &subKeyName, - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - &subKey); - - if (NT_SUCCESS(status)) - { - status = WdfRegistryQueryULong(subKey, - &valueName, - &deviceHacks); - if (NT_SUCCESS(status)) - { - // remove unknown values and save... - CLEAR_FLAG(deviceHacks, FDO_HACK_INVALID_FLAGS); - SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, deviceHacks); - } - - WdfRegistryClose(subKey); - } - - WdfRegistryClose(hardwareKey); - } - - - // - // we should modify the system hive to include another key for us to grab - // settings from. in this case: Classpnp\HackFlags - // - // the use of a DWORD value for the HackFlags allows 32 hacks w/o - // significant use of the registry, and also reduces OEM exposure. - // - // definition of bit flags: - // 0x00000001 -- Device succeeds PREVENT_MEDIUM_REMOVAL, but - // cannot actually prevent removal. - // 0x00000002 -- Device hard-hangs or times out for GESN requests. - // 0x00000008 -- Device does not support RESERVE(6) and RELEASE(6). - // 0x00000010 -- Device may incorrecly report operational changes in GESN. - // 0x00000020 -- Device does not support streaming READ(12) / WRITE(12). - // 0x00000040 -- Device does not support asynchronous notification. - // 0xffffff80 -- Currently reserved, may be used later. - // - - return; -} - -_IRQL_requires_max_(APC_LEVEL) -VOID DeviceScanForSpecial( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ CDROM_SCAN_FOR_SPECIAL_INFO DeviceList[], - _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function) -/*++ - -Routine Description: - - scan the list of devices that should be hacked or not supported. - -Arguments: - - DeviceExtension - the device context - DeviceList - the device list - Function - function used to scan from the list. - -Return Value: - - none - ---*/ -{ - PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor; - PUCHAR vendorId; - PUCHAR productId; - PUCHAR productRevision; - UCHAR nullString[] = ""; - - PAGED_CODE(); - NT_ASSERT(DeviceList); - NT_ASSERT(Function); - - if (DeviceList == NULL) - { - return; - } - if (Function == NULL) - { - return; - } - - deviceDescriptor = DeviceExtension->DeviceDescriptor; - - // SCSI sets offsets to -1, ATAPI sets to 0. check for both. - if (deviceDescriptor->VendorIdOffset != 0 && - deviceDescriptor->VendorIdOffset != -1) - { - vendorId = ((PUCHAR)deviceDescriptor); - vendorId += deviceDescriptor->VendorIdOffset; - } - else - { - vendorId = nullString; - } - - if (deviceDescriptor->ProductIdOffset != 0 && - deviceDescriptor->ProductIdOffset != -1) - { - productId = ((PUCHAR)deviceDescriptor); - productId += deviceDescriptor->ProductIdOffset; - } - else - { - productId = nullString; - } - - if (deviceDescriptor->ProductRevisionOffset != 0 && - deviceDescriptor->ProductRevisionOffset != -1) - { - productRevision = ((PUCHAR)deviceDescriptor); - productRevision += deviceDescriptor->ProductRevisionOffset; - } - else - { - productRevision = nullString; - } - - // loop while the device list is valid (not null-filled) - for (;(DeviceList->VendorId != NULL || - DeviceList->ProductId != NULL || - DeviceList->ProductRevision != NULL); DeviceList++) - { - if (StringsAreMatched(DeviceList->VendorId, (LPSTR)vendorId) && - StringsAreMatched(DeviceList->ProductId, (LPSTR)productId) && - StringsAreMatched(DeviceList->ProductRevision, (LPSTR)productRevision) - ) - { - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "DeviceScanForSpecial: Found matching " - "controller Ven: %s Prod: %s Rev: %s\n", - (LPCSTR)vendorId, (LPCSTR)productId, (LPCSTR)productRevision)); - - // pass the context to the call back routine and exit - (Function)(DeviceExtension, DeviceList->Data); - - // for CHK builds, try to prevent wierd stacks by having a debug - // print here. it's a hack, but i know of no other way to prevent - // the stack from being wrong. - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "DeviceScanForSpecial: " - "completed callback\n")); - return; - - } // else the strings did not match - - } // none of the devices matched. - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "DeviceScanForSpecial: no match found for %p\n", - DeviceExtension->DeviceObject)); - return; - -} // end DeviceScanForSpecial() - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceHackFlagsScan( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG_PTR Data - ) -{ - PAGED_CODE(); - - // remove invalid flags and save - CLEAR_FLAG(Data, FDO_HACK_INVALID_FLAGS); - SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, Data); - - return; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitializeHotplugInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - Retrieve information into struc STORAGE_HOTPLUG_INFO in DeviceExtension - initialize the hotplug information only after the ScanForSpecial routines, - as it relies upon the hack flags - DeviceExtension->PrivateFdoData->HackFlags. - -Arguments: - - DeviceExtension - the device context - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_PRIVATE_FDO_DATA fdoData = DeviceExtension->PrivateFdoData; - DEVICE_REMOVAL_POLICY deviceRemovalPolicy = 0; - ULONG resultLength = 0; - ULONG writeCacheOverride; - - PAGED_CODE(); - - // start with some default settings - RtlZeroMemory(&(fdoData->HotplugInfo), sizeof(STORAGE_HOTPLUG_INFO)); - - // set the size (aka version) - fdoData->HotplugInfo.Size = sizeof(STORAGE_HOTPLUG_INFO); - - // set if the device has removable media - if (DeviceExtension->DeviceDescriptor->RemovableMedia) - { - fdoData->HotplugInfo.MediaRemovable = TRUE; - } - else - { - fdoData->HotplugInfo.MediaRemovable = FALSE; - } - - // - // this refers to devices which, for reasons not yet understood, - // do not fail PREVENT_MEDIA_REMOVAL requests even though they - // have no way to lock the media into the drive. this allows - // the filesystems to turn off delayed-write caching for these - // devices as well. - // - - if (TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_CANNOT_LOCK_MEDIA)) - { - fdoData->HotplugInfo.MediaHotplug = TRUE; - } - else - { - fdoData->HotplugInfo.MediaHotplug = FALSE; - } - - // Query the default removal policy from the kernel - status = WdfDeviceQueryProperty(DeviceExtension->Device, - DevicePropertyRemovalPolicy, - sizeof(DEVICE_REMOVAL_POLICY), - (PVOID)&deviceRemovalPolicy, - &resultLength); - if (NT_SUCCESS(status)) - { - if (resultLength != sizeof(DEVICE_REMOVAL_POLICY)) - { - status = STATUS_UNSUCCESSFUL; - } - } - - if (NT_SUCCESS(status)) - { - // Look into the registry to see if the user has chosen - // to override the default setting for the removal policy. - // User can override only if the default removal policy is - // orderly or suprise removal. - - if ((deviceRemovalPolicy == RemovalPolicyExpectOrderlyRemoval) || - (deviceRemovalPolicy == RemovalPolicyExpectSurpriseRemoval)) - { - DEVICE_REMOVAL_POLICY userRemovalPolicy = 0; - - DeviceGetParameter(DeviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_REMOVAL_POLICY_VALUE_NAME, - (PULONG)&userRemovalPolicy); - - // Validate the override value and use it only if it is an - // allowed value. - if ((userRemovalPolicy == RemovalPolicyExpectOrderlyRemoval) || - (userRemovalPolicy == RemovalPolicyExpectSurpriseRemoval)) - { - deviceRemovalPolicy = userRemovalPolicy; - } - } - - // use this info to set the DeviceHotplug setting - // don't rely on DeviceCapabilities, since it can't properly - // determine device relations, etc. let the kernel figure this - // stuff out instead. - if (deviceRemovalPolicy == RemovalPolicyExpectSurpriseRemoval) - { - fdoData->HotplugInfo.DeviceHotplug = TRUE; - } - else - { - fdoData->HotplugInfo.DeviceHotplug = FALSE; - } - - // this refers to the *filesystem* caching, but has to be included - // here since it's a per-device setting. this may change to be - // stored by the system in the future. - writeCacheOverride = FALSE; - DeviceGetParameter(DeviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_WRITE_CACHE_VALUE_NAME, - &writeCacheOverride); - - if (writeCacheOverride) - { - fdoData->HotplugInfo.WriteCacheEnableOverride = TRUE; - } - else - { - fdoData->HotplugInfo.WriteCacheEnableOverride = FALSE; - } - } - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "Could not initialize hotplug information %lx\n", status)); - } - - return status; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceInitMmcContext( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine initializes and populates the internal data structures that are - used to discover various MMC-defined capabilities of the device. - - This routine will not clean up allocate resources if it fails - that - is left for device stop/removal routines - -Arguments: - - DeviceExtension - device extension - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE(); - - DeviceExtension->DeviceAdditionalData.Mmc.IsMmc = FALSE; - DeviceExtension->DeviceAdditionalData.Mmc.IsAACS = FALSE; - DeviceExtension->DeviceAdditionalData.Mmc.IsWriter = FALSE; - DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE; - DeviceExtension->DeviceAdditionalData.Mmc.IsCssDvd = FALSE; - DeviceExtension->DeviceAdditionalData.DriveDeviceType = FILE_DEVICE_CD_ROM; - - // Determine if the drive is MMC-Capable - if (NT_SUCCESS(status)) - { - status = DeviceGetMmcSupportInfo(DeviceExtension, - &DeviceExtension->DeviceAdditionalData.Mmc.IsMmc); - - if (!NT_SUCCESS(status)) - { - //Currently, only low resource error comes here. - //That is a success case for unsupporting this command. - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "DeviceInitMmcContext: Failed to get the support info for GET CONFIGURATION " - "command, failng %!STATUS!\n", status - )); - - DeviceExtension->DeviceAdditionalData.Mmc.IsMmc = FALSE; - status = STATUS_SUCCESS; - } - } - - if (NT_SUCCESS(status) && DeviceExtension->DeviceAdditionalData.Mmc.IsMmc) - { - // the drive supports at least a subset of MMC commands - // (and therefore supports READ_CD, etc...) - - // allocate a buffer for all the capabilities and such - status = DeviceAllocateMmcResources(DeviceExtension->Device); - } - - if (NT_SUCCESS(status) && DeviceExtension->DeviceAdditionalData.Mmc.IsMmc) - { - PFEATURE_HEADER header = NULL; - FEATURE_NUMBER validationSchema; - ULONG blockingFactor; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceInitMmcContext: FDO %p GET CONFIGURATION buffer %p\n", - DeviceExtension->Device, - DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer - )); - - // Update several properties using the retrieved Configuration Data. - - // print all the feature pages (DBG only) - DevicePrintAllFeaturePages(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer, - DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize); - - // if AACS feature exists, enable AACS flag in the driver - header = DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer, - DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize, - FeatureAACS); - if (header) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceInitMmcContext: Reporting AACS support for device due to " - "GET CONFIGURATION showing support\n" - )); - DeviceExtension->DeviceAdditionalData.Mmc.IsAACS = TRUE; - } - -#ifdef ENABLE_AACS_TESTING - DeviceExtension->DeviceAdditionalData.Mmc.IsAACS = TRUE; // just force it true for testing -#endif // ENABLE_AACS_TESTING - - // Check if it's a DVD device - header = DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer, - DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize, - FeatureDvdRead); - if (header != NULL) - { - DeviceExtension->DeviceAdditionalData.DriveDeviceType = FILE_DEVICE_DVD; - } - - // check if drive is writer - DeviceUpdateMmcWriteCapability(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer, - DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize, - FALSE, //Check if the drive has the ability to write. - (PBOOLEAN)&(DeviceExtension->DeviceAdditionalData.Mmc.IsWriter), - &validationSchema, - &blockingFactor); - - // check if there is a CSS protected DVD or CPPM-protected DVDAudio media in drive. - header = DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer, - DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize, - FeatureDvdCSS); - - DeviceExtension->DeviceAdditionalData.Mmc.IsCssDvd = (header != NULL) && (header->Current); - - // Flag the StartIo routine to update its state and hook in the error handler - DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired; - DeviceExtension->DeviceAdditionalData.ErrorHandler = DeviceErrorHandlerForMmc; - - SET_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT); - - // Read the CDROM mode sense page to get additional info for raw read requests. - // only valid for MMC devices - DeviceSetRawReadInfo(DeviceExtension); - } - - // Set Read-Only device flag for non-MMC device. - if (!(DeviceExtension->DeviceAdditionalData.Mmc.IsMmc)) - { - ULONG deviceCharacteristics = WdfDeviceGetCharacteristics(DeviceExtension->Device); - - deviceCharacteristics |= FILE_READ_ONLY_DEVICE; - - WdfDeviceSetCharacteristics(DeviceExtension->Device, deviceCharacteristics); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceInitMmcContext: FDO %p Device is not an MMC compliant device, so setting " - "to read-only (legacy) mode", - DeviceExtension->Device - )); - } - - // Set DEV_SAFE_START_UNIT flag for newer devices. - if (DeviceExtension->DeviceAdditionalData.DriveDeviceType == FILE_DEVICE_DVD) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceInitMmcContext: DVD Devices require START UNIT\n")); - SET_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT); - - } - else if ((DeviceExtension->DeviceDescriptor->BusType != BusTypeScsi) && - (DeviceExtension->DeviceDescriptor->BusType != BusTypeAtapi) && - (DeviceExtension->DeviceDescriptor->BusType != BusTypeUnknown) - ) - { - // devices on the newer busses require START_UNIT - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceInitMmcContext: Devices for newer buses require START UNIT\n")); - SET_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT); - } - - return status; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -ULONG -DeviceGetTimeOutValueFromRegistry() -/*++ - -Routine Description: - - get the device time out value from registry - -Arguments: - - None - -Return Value: - - ULONG - value of timeout - ---*/ -{ - NTSTATUS status; - WDFKEY registryKey = NULL; - ULONG timeOutValue = 0; - - DECLARE_CONST_UNICODE_STRING(registryValueName, L"TimeOutValue"); - - PAGED_CODE(); - - // open the service key. - status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), - KEY_READ, - WDF_NO_OBJECT_ATTRIBUTES, - ®istryKey); - - if (NT_SUCCESS(status)) - { - status = WdfRegistryQueryULong(registryKey, - ®istryValueName, - &timeOutValue); - - WdfRegistryClose(registryKey); - } - - if (!NT_SUCCESS(status)) - { - timeOutValue = 0; - } - - return timeOutValue; - -} // end DeviceGetTimeOutValueFromRegistry() - - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceScanSpecialDevices( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This function checks to see if an SCSI logical unit requires an special - initialization or error processing. - -Arguments: - - Device - device object. - -Return Value: - - None. - ---*/ -{ - - PAGED_CODE(); - - // set our hack flags - DeviceScanForSpecial(DeviceExtension, CdromHackItems, ScanForSpecialHandler); - - // - // All CDRom's can ignore the queue lock failure for power operations - // and do not require handling the SpinUp case (unknown result of sending - // a cdrom a START_UNIT command -- may eject disks?) - // - // We send the stop command mostly to stop outstanding asynch operations - // (like audio playback) from running when the system is powered off. - // Because of this and the unlikely chance that a PLAY command will be - // sent in the window between the STOP and the time the machine powers down - // we don't require queue locks. This is important because without them - // classpnp's power routines will send the START_STOP_UNIT command to the - // device whether or not it supports locking (atapi does not support locking - // and if we requested them we would end up not stopping audio on atapi - // devices). -// SET_FLAG(deviceExtension->ScanForSpecialFlags, CDROM_SPECIAL_DISABLE_SPIN_UP); -// SET_FLAG(deviceExtension->ScanForSpecialFlags, CDROM_SPECIAL_NO_QUEUE_LOCK); - - if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_TOSHIBA_SD_W1101)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceScanSpecialDevices: Found Toshiba SD-W1101 DVD-RAM " - "-- This drive will *NOT* support DVD-ROM playback.\n")); - } - else if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_HITACHI_GD_2000)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceScanSpecialDevices: Found Hitachi GD-2000\n")); - - // Setup an error handler to spin up the drive when it idles out - // since it seems to like to fail to spin itself back up on its - // own for a REPORT_KEY command. It may also lose the AGIDs that - // it has given, which will result in DVD playback failures. - // This routine will just do what it can... - DeviceExtension->DeviceAdditionalData.ErrorHandler = DeviceErrorHandlerForHitachiGD2000; - - // this drive may require START_UNIT commands to spin - // the drive up when it's spun itself down. - SET_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT); - } - else if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_FUJITSU_FMCD_10x)) - { - // When Read command is issued to FMCD-101 or FMCD-102 and there is a music - // cd in it. It takes longer time than SCSI_CDROM_TIMEOUT before returning - // error status. - DeviceExtension->TimeOutValue = 20; - } - else if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_DEC_RRD)) - { - NTSTATUS status; - PMODE_PARM_READ_WRITE_DATA modeParameters; - SCSI_REQUEST_BLOCK srb = {0}; - PCDB cdb; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceScanSpecialDevices: Found DEC RRD.\n")); - - DeviceExtension->DeviceAdditionalData.IsDecRrd = TRUE; - - // Setup an error handler to reinitialize the cd rom after it is reset? - // - //DeviceExtension->DevInfo->ClassError = DecRrdProcessError; - - // Found a DEC RRD cd-rom. These devices do not pass MS HCT - // multi-media tests because the DEC firmware modifieds the block - // from the PC-standard 2K to 512. Change the block transfer size - // back to the PC-standard 2K by using a mode select command. - - modeParameters = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(MODE_PARM_READ_WRITE_DATA), - CDROM_TAG_MODE_DATA); - if (modeParameters == NULL) - { - return; - } - - RtlZeroMemory(modeParameters, sizeof(MODE_PARM_READ_WRITE_DATA)); - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - // Set the block length to 2K. - modeParameters->ParameterListHeader.BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK); - - // Set block length to 2K (0x0800) in Parameter Block. - modeParameters->ParameterListBlock.BlockLength[0] = 0x00; //MSB - modeParameters->ParameterListBlock.BlockLength[1] = 0x08; - modeParameters->ParameterListBlock.BlockLength[2] = 0x00; //LSB - - // Build the mode select CDB. - srb.CdbLength = 6; - srb.TimeOutValue = DeviceExtension->TimeOutValue; - - cdb = (PCDB)srb.Cdb; - cdb->MODE_SELECT.PFBit = 1; - cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SELECT.ParameterListLength = HITACHI_MODE_DATA_SIZE; - - // Send the request to the device. - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - &srb, - modeParameters, - sizeof(MODE_PARM_READ_WRITE_DATA), - TRUE, - NULL); - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "DeviceScanSpecialDevices: Setting DEC RRD to 2K block" - "size failed [%x]\n", status)); - } - - ExFreePool(modeParameters); - } - - return; -} - -_IRQL_requires_max_(APC_LEVEL) -VOID -ScanForSpecialHandler( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG_PTR HackFlags - ) -{ - PAGED_CODE(); - - CLEAR_FLAG(HackFlags, CDROM_HACK_INVALID_FLAGS); - - DeviceExtension->DeviceAdditionalData.HackFlags = HackFlags; - - return; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceCacheDeviceInquiryData( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - get inquiry data from device and cache it into device extension - The first INQUIRY command sent is with 0x24 bytes required data, - as ATAport driver always sends this to enumerate devices and 0x24 - bytes is the minimum data device should return by spec. - -Arguments: - - DeviceExtension - device extension. - -Return Value: - - NTSTATUS. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - SCSI_REQUEST_BLOCK srb = {0}; - PCDB cdb = (PCDB)(&srb.Cdb); - PINQUIRYDATA tmpInquiry = NULL; - - // by spec, device should return at least 36 bytes. - ULONG requestedInquiryTransferBytes = MINIMUM_CDROM_INQUIRY_SIZE; - BOOLEAN needResendCommand = TRUE; - BOOLEAN portDriverHack = FALSE; - - // this ensures that the strings vendorID, productID, and firmwareRevision - // are all available in the inquiry data. In addition, MMC spec requires - // all type 5 devices to have minimum 36 bytes of inquiry. - static const UCHAR minInquiryAdditionalLength = - MINIMUM_CDROM_INQUIRY_SIZE - - RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, AdditionalLength); - - C_ASSERT( RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, AdditionalLength) <= 8 ); - C_ASSERT( RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, ProductRevisionLevel) == MINIMUM_CDROM_INQUIRY_SIZE ); - - PAGED_CODE(); - - // short-circuit here for if already cached for this device - // required to avoid use of scratch buffer after initialization - // of MCN code. - if (DeviceExtension->DeviceAdditionalData.CachedInquiryData != NULL) - { - NT_ASSERT(DeviceExtension->DeviceAdditionalData.CachedInquiryDataByteCount != 0); - return STATUS_SUCCESS; - } - - // 1. retrieve the inquiry data length - - // 1.1 allocate inquiry data buffer - tmpInquiry = ExAllocatePool2(POOL_FLAG_NON_PAGED, - requestedInquiryTransferBytes, - CDROM_TAG_INQUIRY); - if (tmpInquiry == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - - // 1.2 send INQUIRY command - if (NT_SUCCESS(status)) - { - srb.CdbLength = 6; - cdb->AsByte[0] = SCSIOP_INQUIRY; - cdb->AsByte[3] = (UCHAR)( requestedInquiryTransferBytes >> (8*1) ); - cdb->AsByte[4] = (UCHAR)( requestedInquiryTransferBytes >> (8*0) ); - - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - &srb, - tmpInquiry, - requestedInquiryTransferBytes, - FALSE, - NULL); - } - - // 1.3 get required data length - if (NT_SUCCESS(status)) - { - if ((requestedInquiryTransferBytes == srb.DataTransferLength) && - (requestedInquiryTransferBytes == (tmpInquiry->AdditionalLength + - RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, AdditionalLength))) ) - { - // device has only 36 bytes of INQUIRY data. do not need to resend the command. - needResendCommand = FALSE; - } - else - { - // workaround an ATAPI.SYS bug where additional length field is set to zero - if (tmpInquiry->AdditionalLength == 0) - { - tmpInquiry->AdditionalLength = minInquiryAdditionalLength; - portDriverHack = TRUE; - } - - requestedInquiryTransferBytes = - tmpInquiry->AdditionalLength + - RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, AdditionalLength); - - if (requestedInquiryTransferBytes >= MINIMUM_CDROM_INQUIRY_SIZE) - { - needResendCommand = TRUE; - } - else - { - needResendCommand = FALSE; - //Length is small than minimum length, error out. - status = STATUS_DEVICE_PROTOCOL_ERROR; - } - } - } - - // 2. retrieve the inquiry data if still needed. - - // 2.1 Clean up. - if (NT_SUCCESS(status) && needResendCommand) - { - FREE_POOL(tmpInquiry); - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - tmpInquiry = ExAllocatePool2(POOL_FLAG_NON_PAGED, - requestedInquiryTransferBytes, - CDROM_TAG_INQUIRY); - if (tmpInquiry == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - // 2.2 resend INQUIRY command - if (NT_SUCCESS(status) && needResendCommand) - { - srb.CdbLength = 6; - cdb->AsByte[0] = SCSIOP_INQUIRY; - cdb->AsByte[3] = (UCHAR)( requestedInquiryTransferBytes >> (8*1) ); - cdb->AsByte[4] = (UCHAR)( requestedInquiryTransferBytes >> (8*0) ); - - status = DeviceSendSrbSynchronously( DeviceExtension->Device, - &srb, - tmpInquiry, - requestedInquiryTransferBytes, - FALSE, - NULL); - - if (!NT_SUCCESS(status)) - { - // Workaround for drive reports that it has more INQUIRY data than reality. - if ((srb.SrbStatus == SRB_STATUS_DATA_OVERRUN) && - (srb.DataTransferLength < requestedInquiryTransferBytes) && - (srb.DataTransferLength >= MINIMUM_CDROM_INQUIRY_SIZE)) - { - //Port driver says buffer size mismatch (buffer underrun), - //retry with the real buffer size it could return. - requestedInquiryTransferBytes = srb.DataTransferLength; - - FREE_POOL(tmpInquiry); - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - tmpInquiry = ExAllocatePool2(POOL_FLAG_NON_PAGED, - requestedInquiryTransferBytes, - CDROM_TAG_INQUIRY); - if (tmpInquiry == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - srb.CdbLength = 6; - cdb->AsByte[0] = SCSIOP_INQUIRY; - cdb->AsByte[3] = (UCHAR)( requestedInquiryTransferBytes >> (8*1) ); - cdb->AsByte[4] = (UCHAR)( requestedInquiryTransferBytes >> (8*0) ); - - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - &srb, - tmpInquiry, - requestedInquiryTransferBytes, - FALSE, - NULL); - } - } - } - - //Check the transferred data length for safe. - if (NT_SUCCESS(status)) - { - requestedInquiryTransferBytes = srb.DataTransferLength; - - if (requestedInquiryTransferBytes < MINIMUM_CDROM_INQUIRY_SIZE) - { - // should never occur - status = STATUS_DEVICE_PROTOCOL_ERROR; - } - } - - // ensure we got some non-zero data.... - // This is done so we don't accidentally work around the - // ATAPI.SYS bug when no data was transferred. - if (NT_SUCCESS(status) && portDriverHack) - { - PULONG tmp = (PULONG)tmpInquiry; - ULONG i = MINIMUM_CDROM_INQUIRY_SIZE / sizeof(ULONG); - C_ASSERT( RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, ProductRevisionLevel) % sizeof(ULONG) == 0 ); - - // wouldn't you know it -- there is no RtlIsMemoryZero() function; Make one up. - for ( ; i != 0; i--) - { - if (*tmp != 0) - { - break; // out of this inner FOR loop -- guarantees 'i != 0' - } - tmp++; - } - - if (i == 0) // all loop'd successfully - { - // should never occur to successfully get all zero'd data - status = STATUS_DEVICE_PROTOCOL_ERROR; - } - } - } - - // if everything succeeded, then (and only then) modify the device extension - if (NT_SUCCESS(status)) - { - DeviceExtension->DeviceAdditionalData.CachedInquiryData = tmpInquiry; - DeviceExtension->DeviceAdditionalData.CachedInquiryDataByteCount = requestedInquiryTransferBytes; - } - else - { - FREE_POOL(tmpInquiry); - } - - return status; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceGetMmcSupportInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Out_ PBOOLEAN IsMmcDevice - ) -/*++ - -Routine Description: - - check if the device is MMC capable. - -Arguments: - - DeviceExtension - device extension. - -Return Value: - - NTSTATUS. - IsMmcDevice - TRUE (MMC capable); FALSE (not MMC device) - ---*/ -{ - NTSTATUS status; - ULONG size; - ULONG previouslyFailed; - - PAGED_CODE(); - - *IsMmcDevice = FALSE; - - // read the registry in case the drive failed previously, - // and a timeout is occurring. - previouslyFailed = FALSE; - DeviceGetParameter(DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_NON_MMC_DRIVE_NAME, - &previouslyFailed); - - if (previouslyFailed) - { - SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_GET_CONFIG_SUPPORT); - } - - // read from the registry in case the drive reports bad profile lengths - previouslyFailed = FALSE; - DeviceGetParameter(DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_NON_MMC_VENDOR_SPECIFIC_PROFILE, - &previouslyFailed); - - if (previouslyFailed) - { - SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_VENDOR_PROFILES); - } - - // check for the ProfileList feature to determine if the drive is MMC compliant - // and set the "size" local variable to total GetConfig data size available. - // NOTE: This will exit this function in some error paths. - { - GET_CONFIGURATION_HEADER localHeader = {0}; - ULONG usable = 0; - - status = DeviceGetConfiguration(DeviceExtension->Device, - &localHeader, - sizeof(GET_CONFIGURATION_HEADER), - &usable, - FeatureProfileList, - SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL); - - if (status == STATUS_INVALID_DEVICE_REQUEST || - status == STATUS_NO_MEDIA_IN_DEVICE || - status == STATUS_IO_DEVICE_ERROR || - status == STATUS_IO_TIMEOUT) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "GetConfiguration Failed (%x), device %p not mmc-compliant\n", - status, DeviceExtension->DeviceObject - )); - - previouslyFailed = TRUE; - DeviceSetParameter( DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_NON_MMC_DRIVE_NAME, - previouslyFailed); - - return STATUS_SUCCESS; - } - else if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "GetConfiguration Failed, status %x -- defaulting to -ROM\n", - status)); - - return STATUS_SUCCESS; - } - else if (usable < sizeof(GET_CONFIGURATION_HEADER)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "GetConfiguration Failed, returned only %x bytes!\n", usable)); - previouslyFailed = TRUE; - DeviceSetParameter( DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_NON_MMC_DRIVE_NAME, - previouslyFailed); - - return STATUS_SUCCESS; - } - - size = (localHeader.DataLength[0] << 24) | - (localHeader.DataLength[1] << 16) | - (localHeader.DataLength[2] << 8) | - (localHeader.DataLength[3] << 0) ; - - - if ((size <= 4) || (size + 4 < size)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "GetConfiguration Failed, claims MMC support but doesn't " - "correctly return config length! (%x)\n", - size - )); - previouslyFailed = TRUE; - DeviceSetParameter( DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_NON_MMC_DRIVE_NAME, - previouslyFailed); - - return STATUS_SUCCESS; - } - else if ((size % 4) != 0) - { - if ((size % 2) != 0) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "GetConfiguration Failed, returned odd number of bytes %x!\n", - size - )); - previouslyFailed = TRUE; - DeviceSetParameter( DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_NON_MMC_DRIVE_NAME, - previouslyFailed); - - return STATUS_SUCCESS; - } - else - { - if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_VENDOR_PROFILES)) - { - // we've already caught this and ASSERT'd once, so don't do it again - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "GetConfiguration returned a size that is not per spec (%x bytes), this is probably because of a vendor specific data header with a size not divisible by 4.\n", - size - )); - previouslyFailed = TRUE; - DeviceSetParameter(DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_NON_MMC_VENDOR_SPECIFIC_PROFILE, - previouslyFailed); - } - } - } - - size += 4; // sizeof the datalength fields - } - - *IsMmcDevice = TRUE; - - // This code doesn't handle total get config size over 64k - NT_ASSERT( size <= MAXUSHORT ); - - // Check for SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE support in the device. - // NOTE: This will exit this function in some error paths. - { - ULONG featureSize = sizeof(GET_CONFIGURATION_HEADER)+sizeof(FEATURE_HEADER); - ULONG usable = 0; - - PGET_CONFIGURATION_HEADER configBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, - featureSize, - CDROM_TAG_GET_CONFIG); - - if (configBuffer == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // read the registry in case the drive failed previously, - // and a timeout is occurring. - previouslyFailed = FALSE; - DeviceGetParameter( DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_TYPE_ONE_GET_CONFIG_NAME, - &previouslyFailed); - - if (previouslyFailed) - { - SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG); - FREE_POOL(configBuffer); - return STATUS_SUCCESS; - } - - // Get only the config and feature header - status = DeviceGetConfiguration(DeviceExtension->Device, - configBuffer, - featureSize, - &usable, - FeatureProfileList, - SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE); - - if (!NT_SUCCESS(status) || (usable < featureSize)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Type One GetConfiguration Failed. Usable buffer size: %d\n", usable)); - previouslyFailed = TRUE; - } - else - { - PFEATURE_HEADER featureHeader; - ULONG totalAvailableBytes = 0; - ULONG expectedAvailableBytes = 0; - - REVERSE_BYTES(&totalAvailableBytes, configBuffer->DataLength); - totalAvailableBytes += RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength); - - featureHeader = (PFEATURE_HEADER) ((PUCHAR)configBuffer + sizeof(GET_CONFIGURATION_HEADER)); - expectedAvailableBytes = sizeof(GET_CONFIGURATION_HEADER) + - sizeof(FEATURE_HEADER) + - featureHeader->AdditionalLength; - - if (totalAvailableBytes > expectedAvailableBytes) - { - // Device is returning more than required size. Most likely the device - // is returning TYPE ALL data. Set the flag to use TYPE ALL for TYPE ONE - // requets - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Type One GetConfiguration Failed. " - "Device returned %d bytes instead of %d bytes\n", - size, featureSize)); - - previouslyFailed = TRUE; - } - } - - FREE_POOL(configBuffer); - - if (previouslyFailed == TRUE) - { - DeviceSetParameter( DeviceExtension, - CDROM_SUBKEY_NAME, - CDROM_TYPE_ONE_GET_CONFIG_NAME, - previouslyFailed); - - SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG); - } - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceSetRawReadInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - This routine reads the CDROM capabilities mode page and save information - in the device extension needed for raw reads. - NOTE: this function is only valid for MMC device - -Arguments: - - DeviceExtension - device context - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PUCHAR buffer = NULL; - ULONG count = 0; - - PAGED_CODE(); - - // Check whether the device can return C2 error flag bits and the block - // error byte. If so, save this info and fill in appropriate flag during - // raw read requests. - - // Start by checking the GET_CONFIGURATION data - { - PFEATURE_DATA_CD_READ cdReadHeader = NULL; - ULONG additionalLength = sizeof(FEATURE_DATA_CD_READ) - sizeof(FEATURE_HEADER); - - cdReadHeader = DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer, - DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize, - FeatureCdRead); - - if ((cdReadHeader != NULL) && - (cdReadHeader->Header.AdditionalLength >= additionalLength) && - (cdReadHeader->C2ErrorData) - ) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DeviceSetRawReadInfo: FDO %p GET_CONFIG shows ability to read C2 error bits\n", - DeviceExtension->DeviceObject - )); - DeviceExtension->DeviceAdditionalData.Mmc.ReadCdC2Pointers = TRUE; // Device returns C2 error info. - } - } - - // Unfortunately, the only way to check for the ability to read R-W subcode - // information is via MODE_SENSE. Do so here, and check the C2 bit as well - // in case the drive has a firmware bug where it fails to report this ability - // in GET_CONFIG (which some drives do). - for (count = 0; count < 6; count++) - { - SCSI_REQUEST_BLOCK srb = {0}; - PCDB cdb = (PCDB)srb.Cdb; - ULONG bufferLength = 0; - - // Build the MODE SENSE CDB. Try 10-byte CDB first. - if ((count/3) == 0) - { - bufferLength = sizeof(CDVD_CAPABILITIES_PAGE) + - sizeof(MODE_PARAMETER_HEADER10) + - sizeof(MODE_PARAMETER_BLOCK); - - cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; - cdb->MODE_SENSE10.Dbd = 1; - cdb->MODE_SENSE10.PageCode = MODE_PAGE_CAPABILITIES; - cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(bufferLength >> 8); - cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(bufferLength >> 0); - srb.CdbLength = 10; - } - else - { - bufferLength = sizeof(CDVD_CAPABILITIES_PAGE) + - sizeof(MODE_PARAMETER_HEADER) + - sizeof(MODE_PARAMETER_BLOCK); - - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb->MODE_SENSE.Dbd = 1; - cdb->MODE_SENSE.PageCode = MODE_PAGE_CAPABILITIES; - cdb->MODE_SENSE.AllocationLength = (UCHAR)bufferLength; - srb.CdbLength = 6; - } - - // Set timeout value from device extension. - srb.TimeOutValue = DeviceExtension->TimeOutValue; - - buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, bufferLength, CDROM_TAG_MODE_DATA); - - if (buffer == NULL) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DeviceSetRawReadInfo: cannot allocate " - "buffer, so not setting raw read info for FDO %p\n", - DeviceExtension->DeviceObject - )); - status = STATUS_INSUFFICIENT_RESOURCES; - goto FnExit; - } - - RtlZeroMemory(buffer, bufferLength); - - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - &srb, - buffer, - bufferLength, - FALSE, - NULL); - - if (NT_SUCCESS(status) || - (status == STATUS_DATA_OVERRUN) || - (status == STATUS_BUFFER_OVERFLOW)) - { - PCDVD_CAPABILITIES_PAGE capabilities = NULL; - - // determine where the capabilities page really is - if ((count/3) == 0) - { - PMODE_PARAMETER_HEADER10 p = (PMODE_PARAMETER_HEADER10)buffer; - capabilities = (PCDVD_CAPABILITIES_PAGE)(buffer + - sizeof(MODE_PARAMETER_HEADER10) + - (p->BlockDescriptorLength[0] * 256) + - p->BlockDescriptorLength[1]); - } - else - { - PMODE_PARAMETER_HEADER p = (PMODE_PARAMETER_HEADER)buffer; - capabilities = (PCDVD_CAPABILITIES_PAGE)(buffer + - sizeof(MODE_PARAMETER_HEADER) + - p->BlockDescriptorLength); - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DeviceSetRawReadInfo: FDO %p CDVD Capabilities buffer %p\n", - DeviceExtension->DeviceObject, - buffer - )); - - if (capabilities->PageCode == MODE_PAGE_CAPABILITIES) - { - if (capabilities->C2Pointers) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DeviceSetRawReadInfo: FDO %p supports C2 error bits in READ_CD command\n", - DeviceExtension->DeviceObject - )); - DeviceExtension->DeviceAdditionalData.Mmc.ReadCdC2Pointers = TRUE; - } - - if (capabilities->RWSupported) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DeviceSetRawReadInfo: FDO %p supports raw subcode in READ_CD command\n", - DeviceExtension->DeviceObject - )); - DeviceExtension->DeviceAdditionalData.Mmc.ReadCdSubCode = TRUE; - } - - break; - } - } - - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DeviceSetRawReadInfo: FDO %p failed %x byte mode sense, status %x\n", - DeviceExtension->DeviceObject, - (((count/3) == 0) ? 10 : 6), - status - )); - - FREE_POOL(buffer); - } - - if (count == 6) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DeviceSetRawReadInfo: FDO %p couldn't get mode sense data\n", - DeviceExtension->DeviceObject - )); - } - -FnExit: - - if (buffer) - { - FREE_POOL(buffer); - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceInitializeDvd( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - This routine sets the region of DVD drive - NOTE: this routine uses ScratchBuffer, it must be called after ScratchBuffer allocated. - -Arguments: - - Device - device object - -Return Value: - - NTSTATUS - ---*/ - -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension; - PDVD_COPY_PROTECT_KEY copyProtectKey = NULL; - PDVD_RPC_KEY rpcKey = NULL; - ULONG bufferLen = 0; - size_t bytesReturned; - - PAGED_CODE(); - - deviceExtension = DeviceGetExtension(Device); - - // check to see if we have a DVD device - if (deviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD) - { - return STATUS_SUCCESS; - } - - // we got a DVD drive. - bufferLen = DVD_RPC_KEY_LENGTH; - copyProtectKey = (PDVD_COPY_PROTECT_KEY)ExAllocatePool2(POOL_FLAG_PAGED, - bufferLen, - DVD_TAG_RPC2_CHECK); - - if (copyProtectKey == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // get the device region - RtlZeroMemory (copyProtectKey, bufferLen); - copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH; - copyProtectKey->KeyType = DvdGetRpcKey; - - // perform IOCTL_DVD_READ_KEY - status = DvdStartSessionReadKey(deviceExtension, - IOCTL_DVD_READ_KEY, - NULL, - copyProtectKey, - DVD_RPC_KEY_LENGTH, - copyProtectKey, - DVD_RPC_KEY_LENGTH, - &bytesReturned); - - if (NT_SUCCESS(status)) - { - rpcKey = (PDVD_RPC_KEY)copyProtectKey->KeyData; - - // TypeCode of zero means that no region has been set. - if (rpcKey->TypeCode == 0) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, - "DVD Initialize (%p): must choose DVD region\n", - Device)); - deviceExtension->DeviceAdditionalData.PickDvdRegion = 1; - - // set the device region code to be the same as region code on media. - if (deviceExtension->DeviceAdditionalData.Mmc.IsCssDvd) - { - DevicePickDvdRegion(Device); - } - } - } - - FREE_POOL(copyProtectKey); - - // return status of IOCTL_DVD_READ_KEY will be ignored. - return STATUS_SUCCESS; -} - - -#if (NTDDI_VERSION >= NTDDI_WIN8) -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceIsPortable( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Out_ PBOOLEAN IsPortable - ) -/*++ - -Routine Description: - - This routine checks if the volume is on a portable storage device. - -Arguments: - - DeviceExtension - device context - IsPortable - device is portable - -Return Value: - - NTSTATUS. - ---*/ - -{ - DEVPROP_BOOLEAN isInternal = DEVPROP_FALSE; - BOOLEAN isPortable = FALSE; - ULONG size = 0; - NTSTATUS status = STATUS_SUCCESS; - DEVPROPTYPE type = DEVPROP_TYPE_EMPTY; - - PAGED_CODE(); - - *IsPortable = FALSE; - - // Check to see if the underlying device object is in local machine container - status = IoGetDevicePropertyData(DeviceExtension->LowerPdo, - &DEVPKEY_Device_InLocalMachineContainer, - 0, - 0, - sizeof(isInternal), - &isInternal, - &size, - &type); - - if (!NT_SUCCESS(status)) - { - goto Cleanup; - } - - NT_ASSERT(size == sizeof(isInternal)); - NT_ASSERT(type == DEVPROP_TYPE_BOOLEAN); - - // Volume is hot-pluggable if the disk pdo container id differs from that of root device - if (isInternal == DEVPROP_TRUE) - { - goto Cleanup; - } - - isPortable = TRUE; - - // Examine the bus type to ensure that this really is a fixed device - if (DeviceExtension->DeviceDescriptor->BusType == BusTypeFibre || - DeviceExtension->DeviceDescriptor->BusType == BusTypeiScsi || - DeviceExtension->DeviceDescriptor->BusType == BusTypeRAID) - { - isPortable = FALSE; - } - - *IsPortable = isPortable; - -Cleanup: - - return status; -} -#endif - - -#pragma warning(pop) // un-sets any local warning changes - diff --git a/storage/class/cdrom/src/ioctl.c b/storage/class/cdrom/src/ioctl.c deleted file mode 100644 index f0a540fc..00000000 --- a/storage/class/cdrom/src/ioctl.c +++ /dev/null @@ -1,9132 +0,0 @@ -/*-- - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - ioctl.c - -Abstract: - - Include all funtions for processing IOCTLs - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - -#include "stddef.h" -#include "string.h" - -#include "ntddk.h" -#include "ntddstor.h" -#include "cdrom.h" -#include "ioctl.h" -#include "scratch.h" -#include "mmc.h" - - -#ifdef DEBUG_USE_WPP -#include "ioctl.tmh" -#endif - - -#define FirstDriveLetter 'C' -#define LastDriveLetter 'Z' - -#if DBG - LPCSTR READ_DVD_STRUCTURE_FORMAT_STRINGS[DvdMaxDescriptor+1] = { - "Physical", - "Copyright", - "DiskKey", - "BCA", - "Manufacturer", - "Unknown" - }; -#endif // DBG - -_IRQL_requires_max_(APC_LEVEL) -VOID -GetConfigurationDataConversionTypeAllToTypeOne( - _In_ FEATURE_NUMBER RequestedFeature, - _In_ PSCSI_REQUEST_BLOCK Srb, - _Out_ size_t * DataLength - ); - -_IRQL_requires_max_(APC_LEVEL) -VOID -GetConfigurationDataSynthesize( - _In_reads_bytes_(InputBufferSize) PVOID InputBuffer, - _In_ ULONG InputBufferSize, - _Out_writes_bytes_(OutputBufferSize) PVOID OutputBuffer, - _In_ size_t OutputBufferSize, - _In_ FEATURE_NUMBER StartingFeature, - _In_ ULONG RequestType, - _Out_ size_t * DataLength - ); - -_IRQL_requires_max_(APC_LEVEL) -PCDB -RequestGetScsiPassThroughCdb( - _In_ PIRP Irp - ); - -#ifdef ALLOC_PRAGMA - -#pragma alloc_text(PAGE, DeviceIsPlayActive) -#pragma alloc_text(PAGE, RequestHandleGetDvdRegion) -#pragma alloc_text(PAGE, RequestHandleReadTOC) -#pragma alloc_text(PAGE, RequestHandleReadTocEx) -#pragma alloc_text(PAGE, RequestHandleGetConfiguration) -#pragma alloc_text(PAGE, RequestHandleGetDriveGeometry) -#pragma alloc_text(PAGE, RequestHandleDiskVerify) -#pragma alloc_text(PAGE, RequestHandleCheckVerify) -#pragma alloc_text(PAGE, RequestHandleFakePartitionInfo) -#pragma alloc_text(PAGE, RequestHandleEjectionControl) -#pragma alloc_text(PAGE, RequestHandleEnableStreaming) -#pragma alloc_text(PAGE, RequestHandleSendOpcInformation) -#pragma alloc_text(PAGE, RequestHandleGetPerformance) -#pragma alloc_text(PAGE, RequestHandleMcnSyncFakeIoctl) -#pragma alloc_text(PAGE, RequestHandleLoadEjectMedia) -#pragma alloc_text(PAGE, RequestHandleReserveRelease) -#pragma alloc_text(PAGE, RequestHandlePersistentReserve) -#pragma alloc_text(PAGE, DeviceHandleRawRead) -#pragma alloc_text(PAGE, DeviceHandlePlayAudioMsf) -#pragma alloc_text(PAGE, DeviceHandleReadQChannel) -#pragma alloc_text(PAGE, ReadQChannel) -#pragma alloc_text(PAGE, DeviceHandlePauseAudio) -#pragma alloc_text(PAGE, DeviceHandleResumeAudio) -#pragma alloc_text(PAGE, DeviceHandleSeekAudioMsf) -#pragma alloc_text(PAGE, DeviceHandleStopAudio) -#pragma alloc_text(PAGE, DeviceHandleGetSetVolume) -#pragma alloc_text(PAGE, DeviceHandleReadDvdStructure) -#pragma alloc_text(PAGE, ReadDvdStructure) -#pragma alloc_text(PAGE, DeviceHandleDvdEndSession) -#pragma alloc_text(PAGE, DeviceHandleDvdStartSessionReadKey) -#pragma alloc_text(PAGE, DvdStartSessionReadKey) -#pragma alloc_text(PAGE, DeviceHandleDvdSendKey) -#pragma alloc_text(PAGE, DvdSendKey) -#pragma alloc_text(PAGE, DeviceHandleSetReadAhead) -#pragma alloc_text(PAGE, DeviceHandleSetSpeed) -#pragma alloc_text(PAGE, RequestHandleExclusiveAccessQueryLockState) -#pragma alloc_text(PAGE, RequestHandleExclusiveAccessLockDevice) -#pragma alloc_text(PAGE, RequestHandleExclusiveAccessUnlockDevice) -#pragma alloc_text(PAGE, RequestHandleScsiPassThrough) -#pragma alloc_text(PAGE, RequestGetScsiPassThroughCdb) -#pragma alloc_text(PAGE, GetConfigurationDataConversionTypeAllToTypeOne) -#pragma alloc_text(PAGE, GetConfigurationDataSynthesize) - -#endif - -NTSTATUS -RequestHandleUnknownIoctl( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - All unknown IOCTLs will be forward to lower level driver. - -Arguments: - - Device - device object - Request - request to be handled - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_UNSUCCESSFUL; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - BOOLEAN syncRequired = requestContext->SyncRequired; - - ULONG sendOptionsFlags = 0; - BOOLEAN requestSent = FALSE; - - WdfRequestFormatRequestUsingCurrentType(Request); - - if (syncRequired) - { - sendOptionsFlags = WDF_REQUEST_SEND_OPTION_SYNCHRONOUS; - } - else - { - WdfRequestSetCompletionRoutine(Request, RequestDummyCompletionRoutine, NULL); - } - - status = RequestSend(deviceExtension, - Request, - deviceExtension->IoTarget, - sendOptionsFlags, - &requestSent); - - if (requestSent) - { - if (syncRequired) - { - // the request needs to be completed here. - RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request)); - } - } - else - { - // failed to send the request to IoTarget - RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request)); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -DeviceIsPlayActive( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - This routine determines if the cd is currently playing music. - -Arguments: - - Device - Device object. - -Return Value: - - BOOLEAN - TRUE if the device is playing music. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PSUB_Q_CURRENT_POSITION currentBuffer; - size_t bytesRead = 0; - - PAGED_CODE (); - - // if we don't think it is playing audio, don't bother checking. - if (!deviceExtension->DeviceAdditionalData.PlayActive) - { - return FALSE; - } - - // Allocate the required memory - NT_ASSERT(sizeof(SUB_Q_CURRENT_POSITION) >= sizeof(CDROM_SUB_Q_DATA_FORMAT)); - currentBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - sizeof(SUB_Q_CURRENT_POSITION), - CDROM_TAG_PLAY_ACTIVE); - if (currentBuffer == NULL) - { - return FALSE; - } - - // set the options in the output buffer format - ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Format = IOCTL_CDROM_CURRENT_POSITION; - ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Track = 0; - - // Send SCSI command to read Q Channel information. - status = ReadQChannel(deviceExtension, - NULL, - currentBuffer, - sizeof(CDROM_SUB_Q_DATA_FORMAT), - currentBuffer, - sizeof(SUB_Q_CURRENT_POSITION), - &bytesRead); - - if (!NT_SUCCESS(status)) - { - ExFreePool(currentBuffer); - return FALSE; - } - - // update the playactive flag appropriately - if (currentBuffer->Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) - { - deviceExtension->DeviceAdditionalData.PlayActive = TRUE; - } - else - { - deviceExtension->DeviceAdditionalData.PlayActive = FALSE; - } - - ExFreePool(currentBuffer); - - return deviceExtension->DeviceAdditionalData.PlayActive; -} - -NTSTATUS -RequestHandleGetInquiryData( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength) -/*++ - -Routine Description: - - Handler for IOCTL_CDROM_GET_INQUIRY_DATA - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength == 0) - { - status = STATUS_BUFFER_TOO_SMALL; - } - else - { - PVOID outputBuffer = NULL; - - *DataLength = min(cdData->CachedInquiryDataByteCount, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength); - - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - - if (NT_SUCCESS(status) && - (outputBuffer != NULL)) - { - // Always copy as much data as possible - RtlCopyMemory(outputBuffer, - cdData->CachedInquiryData, - *DataLength); - } - - // and finally decide between two possible status values - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < cdData->CachedInquiryDataByteCount) - { - status = STATUS_BUFFER_OVERFLOW; - } - } - - return status; -} - - -NTSTATUS -RequestHandleGetMediaTypeEx( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handler for IOCTL_STORAGE_GET_MEDIA_TYPES_EX - -Arguments: - - DeviceExtension - device context - Request - request to be handled - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - - PGET_MEDIA_TYPES mediaTypes = NULL; - PDEVICE_MEDIA_INFO mediaInfo = NULL; //&mediaTypes->MediaInfo[0]; - ULONG sizeNeeded = 0; - PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo; - - *DataLength = 0; - - // Must run below dispatch level. - if (KeGetCurrentIrql() >= DISPATCH_LEVEL) - { - NT_ASSERT(FALSE); - return STATUS_INVALID_LEVEL; - } - - sizeNeeded = sizeof(GET_MEDIA_TYPES); - - // IsMmc is static... - if (cdData->Mmc.IsMmc) - { - sizeNeeded += sizeof(DEVICE_MEDIA_INFO) * 1; // return two media types - } - - status = WdfRequestRetrieveOutputBuffer(Request, - sizeNeeded, - (PVOID*)&mediaTypes, - NULL); - - if (NT_SUCCESS(status) && - (mediaTypes != NULL)) - { - mediaInfo = &mediaTypes->MediaInfo[0]; - - RtlZeroMemory(mediaTypes, sizeNeeded); - - // ISSUE-2000/5/11-henrygab - need to update GET_MEDIA_TYPES_EX - - mediaTypes->DeviceType = cdData->DriveDeviceType; - - mediaTypes->MediaInfoCount = 1; - mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = CD_ROM; - mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1; - mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_READ_ONLY; - mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = DeviceExtension->DiskGeometry.Cylinders.QuadPart; - mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = DeviceExtension->DiskGeometry.TracksPerCylinder; - mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = DeviceExtension->DiskGeometry.SectorsPerTrack; - mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = DeviceExtension->DiskGeometry.BytesPerSector; - - if (cdData->Mmc.IsMmc) - { - // also report a removable disk - mediaTypes->MediaInfoCount += 1; - - mediaInfo++; - mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = RemovableMedia; - mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1; - mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_READ_WRITE; - mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = DeviceExtension->DiskGeometry.Cylinders.QuadPart; - mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = DeviceExtension->DiskGeometry.TracksPerCylinder; - mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = DeviceExtension->DiskGeometry.SectorsPerTrack; - mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = DeviceExtension->DiskGeometry.BytesPerSector; - mediaInfo--; - - } - - // Status will either be success, if media is present, or no media. - // It would be optimal to base from density code and medium type, but not all devices - // have values for these fields. - - // Send a TUR to determine if media is present, only if the device is not in ZPODD mode. - if ((!EXCLUSIVE_MODE(cdData) || - EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request))) && - ((zpoddInfo == NULL) || - (zpoddInfo->InZeroPowerState == FALSE))) - { - SCSI_REQUEST_BLOCK srb; - PCDB cdb = (PCDB)srb.Cdb; - - 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, - Request); - - if (NT_SUCCESS(status)) - { - // set the disk's media as current if we can write to it. - if (cdData->Mmc.IsMmc && cdData->Mmc.WriteAllowed) - { - mediaInfo++; - SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, - MEDIA_CURRENTLY_MOUNTED); - mediaInfo--; - } - else - { - SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, - MEDIA_CURRENTLY_MOUNTED); - } - } - else - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestHandleGetMediaTypeEx: GET_MEDIA_TYPES status of TUR - %lx\n", status)); - } - } - - // per legacy cdrom behavior, always return success - status = STATUS_SUCCESS; - } - - *DataLength = sizeNeeded; - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleGetDvdRegion( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handler for IOCTL_DVD_GET_REGION - -Arguments: - - DeviceExtension - device context - Request - request to be handled - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PVOID outputBuffer = NULL; - size_t bytesReturned = 0; - - PDVD_COPY_PROTECT_KEY copyProtectKey = NULL; - ULONG keyLength = 0; - PDVD_DESCRIPTOR_HEADER dvdHeader; - PDVD_COPYRIGHT_DESCRIPTOR copyRightDescriptor; - PDVD_REGION dvdRegion = NULL; - PDVD_READ_STRUCTURE readStructure = NULL; - PDVD_RPC_KEY rpcKey; - - PAGED_CODE (); - - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "RequestHandleGetDvdRegion: [%p] IOCTL_DVD_GET_REGION\n", Request)); - - *DataLength = 0; - - // reject the request if it's not a DVD device. - if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - sizeof(DVD_REGION), - &outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - // figure out how much data buffer we need - keyLength = max((sizeof(DVD_DESCRIPTOR_HEADER) + sizeof(DVD_COPYRIGHT_DESCRIPTOR)), - sizeof(DVD_READ_STRUCTURE)); - keyLength = max(keyLength, - DVD_RPC_KEY_LENGTH); - - // round the size to nearest ULONGLONG -- why? - // could this be to deal with device alignment issues? - keyLength += sizeof(ULONGLONG) - (keyLength & (sizeof(ULONGLONG) - 1)); - - readStructure = ExAllocatePool2(POOL_FLAG_NON_PAGED, - keyLength, - DVD_TAG_READ_KEY); - if (readStructure == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - RtlZeroMemory (readStructure, keyLength); - readStructure->Format = DvdCopyrightDescriptor; - - // use READ_STRUCTURE to read copyright descriptor - status = ReadDvdStructure(DeviceExtension, - Request, - readStructure, - keyLength, - readStructure, - sizeof(DVD_DESCRIPTOR_HEADER) + sizeof(DVD_COPYRIGHT_DESCRIPTOR), - &bytesReturned); - } - - if (NT_SUCCESS(status)) - { - // we got the copyright descriptor, so now get the region if possible - dvdHeader = (PDVD_DESCRIPTOR_HEADER) readStructure; - copyRightDescriptor = (PDVD_COPYRIGHT_DESCRIPTOR) dvdHeader->Data; - - // the original irp's systembuffer has a copy of the info that - // should be passed down in the request - dvdRegion = outputBuffer; - - dvdRegion->CopySystem = copyRightDescriptor->CopyrightProtectionType; - dvdRegion->RegionData = copyRightDescriptor->RegionManagementInformation; - - // now reuse the buffer to request the copy protection info - copyProtectKey = (PDVD_COPY_PROTECT_KEY) readStructure; - RtlZeroMemory (copyProtectKey, DVD_RPC_KEY_LENGTH); - copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH; - copyProtectKey->KeyType = DvdGetRpcKey; - - // send a request for READ_KEY - status = DvdStartSessionReadKey(DeviceExtension, - IOCTL_DVD_READ_KEY, - Request, - copyProtectKey, - DVD_RPC_KEY_LENGTH, - copyProtectKey, - DVD_RPC_KEY_LENGTH, - &bytesReturned); - } - - if (NT_SUCCESS(status)) - { - // the request succeeded. if a supported scheme is returned, - // then return the information to the caller - rpcKey = (PDVD_RPC_KEY) copyProtectKey->KeyData; - - if (rpcKey->RpcScheme == 1) - { - if (rpcKey->TypeCode) - { - dvdRegion->SystemRegion = ~rpcKey->RegionMask; - dvdRegion->ResetCount = rpcKey->UserResetsAvailable; - } - else - { - // the drive has not been set for any region - dvdRegion->SystemRegion = 0; - dvdRegion->ResetCount = rpcKey->UserResetsAvailable; - } - - *DataLength = sizeof(DVD_REGION); - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestHandleGetDvdRegion => rpcKey->RpcScheme != 1\n")); - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - - // Clean up - if (readStructure != NULL) - { - ExFreePool(readStructure); - } - - return status; -} - -NTSTATUS -RequestValidateRawRead( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_CDROM_RAW_READ - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - - PVOID inputBuffer = NULL; - PIRP irp = NULL; - PIO_STACK_LOCATION currentStack = NULL; - - LARGE_INTEGER startingOffset = {0}; - ULONGLONG transferBytes = 0; - ULONGLONG endOffset; - ULONGLONG mdlBytes; - RAW_READ_INFO rawReadInfo = {0}; - - *DataLength = 0; - - irp = WdfRequestWdmGetIrp(Request); - currentStack = IoGetCurrentIrpStackLocation(irp); - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - - // Check that ending sector is on disc and buffers are there and of - // correct size. - if (NT_SUCCESS(status) && - (RequestParameters.Parameters.DeviceIoControl.Type3InputBuffer == NULL)) - { - // This is a call from user space. This is the only time that we need to validate parameters. - // Validate the input and get the input buffer into Type3InputBuffer - // so the rest of the code will be uniform. - if (inputBuffer != NULL) - { - currentStack->Parameters.DeviceIoControl.Type3InputBuffer = inputBuffer; - RequestParameters.Parameters.DeviceIoControl.Type3InputBuffer = inputBuffer; - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(RAW_READ_INFO)) - { - *DataLength = sizeof(RAW_READ_INFO); - status = STATUS_BUFFER_TOO_SMALL; - } - } - else - { - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - // Since this ioctl is METHOD_OUT_DIRECT, we need to copy away the input buffer before interpreting it. - // This prevents a malicious app from messing with the input buffer while we are interpreting it. - rawReadInfo = *(PRAW_READ_INFO)RequestParameters.Parameters.DeviceIoControl.Type3InputBuffer; - - startingOffset.QuadPart = rawReadInfo.DiskOffset.QuadPart; - - if ((rawReadInfo.TrackMode == CDDA) || - (rawReadInfo.TrackMode == YellowMode2) || - (rawReadInfo.TrackMode == XAForm2) ) - { - transferBytes = (ULONGLONG)rawReadInfo.SectorCount * RAW_SECTOR_SIZE; - } - else if (rawReadInfo.TrackMode == RawWithSubCode) - { - transferBytes = (ULONGLONG)rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_SUBCODE_SIZE; - } - else if (rawReadInfo.TrackMode == RawWithC2) - { - transferBytes = (ULONGLONG)rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_C2_SIZE; - } - else if (rawReadInfo.TrackMode == RawWithC2AndSubCode) - { - transferBytes = (ULONGLONG)rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_C2_AND_SUBCODE_SIZE; - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: Invalid TrackMode type %x for XA read\n", - rawReadInfo.TrackMode - )); - } - - endOffset = (ULONGLONG)rawReadInfo.SectorCount * COOKED_SECTOR_SIZE; - endOffset += startingOffset.QuadPart; - - // check for overflows.... - if (rawReadInfo.SectorCount == 0) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: Invalid I/O parameters for XA " - "Read (zero sectors requested)\n")); - status = STATUS_INVALID_PARAMETER; - } - else if (transferBytes < (ULONGLONG)(rawReadInfo.SectorCount)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: Invalid I/O parameters for XA " - "Read (TransferBytes Overflow)\n")); - status = STATUS_INVALID_PARAMETER; - } - else if (endOffset < (ULONGLONG)startingOffset.QuadPart) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: Invalid I/O parameters for XA " - "Read (EndingOffset Overflow)\n")); - status = STATUS_INVALID_PARAMETER; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < transferBytes) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: Invalid I/O parameters for XA " - "Read (Bad buffer size)\n")); - status = STATUS_INVALID_PARAMETER; - } - else if (endOffset > (ULONGLONG)DeviceExtension->PartitionLength.QuadPart) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: Invalid I/O parameters for XA " - "Read (Request Out of Bounds)\n")); - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - // cannot validate the MdlAddress, since it is not included in any - // other location per the DDK and file system calls. - - // validate the mdl describes at least the number of bytes - // requested from us. - mdlBytes = (ULONGLONG)MmGetMdlByteCount(irp->MdlAddress); - if (mdlBytes < transferBytes) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: Invalid MDL %s, Irp %p\n", - "size (5)", irp)); - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - // check the buffer for alignment - // This is important for x86 as some busses (ie ATAPI) - // require word-aligned buffers. - if ( ((ULONG_PTR)MmGetMdlVirtualAddress(irp->MdlAddress)) & - DeviceExtension->AdapterDescriptor->AlignmentMask ) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: Invalid I/O parameters for " - "XA Read (Buffer %p not aligned with mask %x\n", - RequestParameters.Parameters.DeviceIoControl.Type3InputBuffer, - DeviceExtension->AdapterDescriptor->AlignmentMask)); - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - // Validate the request is not too large for the adapter - BOOLEAN bufferIsPageAligned = FALSE; - ULONG maxLength = 0; - - // if buffer is not page-aligned, then subtract one as the - // transfer could cross a page boundary. - if ((((ULONG_PTR)MmGetMdlVirtualAddress(irp->MdlAddress)) & (PAGE_SIZE-1)) == 0) - { - bufferIsPageAligned = TRUE; - } - - if (bufferIsPageAligned) - { - maxLength = cdData->MaxPageAlignedTransferBytes; - } - else - { - maxLength = cdData->MaxUnalignedTransferBytes; - } - - if (transferBytes > maxLength) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestValidateRawRead: The XA Read (type %x) would require %I64x bytes, " - "but the adapter can only handle %x bytes (for a%saligned buffer)\n", - rawReadInfo.TrackMode, - transferBytes, - maxLength, - (bufferIsPageAligned ? " " : "n un") - )); - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - // - // HACKHACK - REF #0001 - // The retry count will be in this irp's IRP_MN function, - // as the new irp was freed, and we therefore cannot use - // this irp's next stack location for this function. - // This may be a good location to store this info for - // when we remove RAW_READ (mode switching), as we will - // no longer have the nextIrpStackLocation to play with - // when that occurs - // - currentStack->MinorFunction = MAXIMUM_RETRIES; // HACKHACK - REF #0001 - } - - return status; -} - -NTSTATUS -RequestValidateReadTocEx( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_CDROM_READ_TOC_EX - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PCDROM_READ_TOC_EX inputBuffer = NULL; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_READ_TOC_EX)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - MINIMUM_CDROM_READ_TOC_EX_SIZE) - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = MINIMUM_CDROM_READ_TOC_EX_SIZE; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > - ((USHORT)-1)) - { - status = STATUS_INVALID_PARAMETER; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength & - DeviceExtension->AdapterDescriptor->AlignmentMask) - { - status = STATUS_INVALID_PARAMETER; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if ((inputBuffer->Reserved1 != 0) || - (inputBuffer->Reserved2 != 0) || - (inputBuffer->Reserved3 != 0)) - { - status = STATUS_INVALID_PARAMETER; - } - // NOTE: when adding new formats, ensure that first two bytes - // specify the amount of additional data available. - else if ((inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_TOC ) || - (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_FULL_TOC) || - (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_CDTEXT )) - { - // SessionTrack field is used - } - else if ((inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_SESSION) || - (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_PMA) || - (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_ATIP)) - { - // SessionTrack field is reserved - if (inputBuffer->SessionTrack != 0) - { - status = STATUS_INVALID_PARAMETER; - } - } - else - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateReadToc( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_CDROM_READ_TOC - -Arguments: - - DeviceExtension - device context - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(CDROM_TOC)) - { - // they didn't request the entire TOC -- use _EX version - // for partial transfers and such. - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(CDROM_TOC); - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength & - DeviceExtension->AdapterDescriptor->AlignmentMask) - { - status = STATUS_INVALID_PARAMETER; - } - - return status; -} - -NTSTATUS -RequestValidateGetLastSession( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_CDROM_GET_LAST_SESSION - -Arguments: - - DeviceExtension - device context - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(CDROM_TOC_SESSION_DATA)) - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(CDROM_TOC_SESSION_DATA); - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength & - DeviceExtension->AdapterDescriptor->AlignmentMask) - { - status = STATUS_INVALID_PARAMETER; - } - - return status; -} - -NTSTATUS -RequestValidateReadQChannel( - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_CDROM_READ_Q_CHANNEL - -Arguments: - - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_SUB_Q_DATA_FORMAT inputBuffer = NULL; - ULONG transferByteCount = 0; - - *DataLength = 0; - - if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_SUB_Q_DATA_FORMAT)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - // check for all valid types of request - if (inputBuffer->Format == IOCTL_CDROM_CURRENT_POSITION) - { - transferByteCount = sizeof(SUB_Q_CURRENT_POSITION); - } - else if (inputBuffer->Format == IOCTL_CDROM_MEDIA_CATALOG) - { - transferByteCount = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER); - } - else if (inputBuffer->Format == IOCTL_CDROM_TRACK_ISRC) - { - transferByteCount = sizeof(SUB_Q_TRACK_ISRC); - } - else - { - // Format not valid - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - transferByteCount) - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = transferByteCount; - } - } - - return status; -} - -NTSTATUS -RequestValidateDvdReadStructure( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_DVD_READ_STRUCTURE - -Arguments: - - DeviceExtension - device context - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(DVD_READ_STRUCTURE)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestValidateDvdReadStructure - input buffer " - "length too small (was %d should be %d)\n", - (int)RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - sizeof(DVD_READ_STRUCTURE))); - status = STATUS_INVALID_PARAMETER; - } - else if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(READ_DVD_STRUCTURES_HEADER)) - { - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestValidateDvdReadStructure - output buffer " - "cannot hold header information\n")); - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(READ_DVD_STRUCTURES_HEADER); - } - else if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > - MAXUSHORT) - { - // key length must fit in two bytes - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestValidateDvdReadStructure - output buffer " - "too large\n")); - status = STATUS_INVALID_PARAMETER; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength & - DeviceExtension->AdapterDescriptor->AlignmentMask) - { - status = STATUS_INVALID_PARAMETER; - } - else if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD) - { - // reject the request if it's not a DVD device. - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - - return status; -} - -NTSTATUS -RequestValidateDvdStartSession( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_DVD_START_SESSION - -Arguments: - - DeviceExtension - device context - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(DVD_SESSION_ID)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestValidateDvdStartSession: DVD_START_SESSION - output " - "buffer too small\n")); - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(DVD_SESSION_ID); - } - else if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD) - { - // reject the request if it's not a DVD device. - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - - return status; -} - -NTSTATUS -RequestValidateDvdSendKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_DVD_SEND_KEY, IOCTL_DVD_SEND_KEY2 - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDVD_COPY_PROTECT_KEY key = NULL; - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &key, - NULL); - - if (NT_SUCCESS(status)) - { - if((RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(DVD_COPY_PROTECT_KEY)) || - (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != key->KeyLength)) - { - - // - // Key is too small to have a header or the key length doesn't - // match the input buffer length. Key must be invalid - // - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestValidateDvdSendKey: [%p] IOCTL_DVD_SEND_KEY - " - "key is too small or does not match KeyLength\n", - Request)); - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - // allow only certain key type (non-destructive) to go through - // IOCTL_DVD_SEND_KEY (which only requires READ access to the device) - if (RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_DVD_SEND_KEY) - { - if ((key->KeyType != DvdChallengeKey) && - (key->KeyType != DvdBusKey2) && - (key->KeyType != DvdInvalidateAGID)) - { - status = STATUS_INVALID_PARAMETER; - } - } - else if ((key->KeyType != DvdChallengeKey) && - (key->KeyType != DvdBusKey1) && - (key->KeyType != DvdBusKey2) && - (key->KeyType != DvdTitleKey) && - (key->KeyType != DvdAsf) && - (key->KeyType != DvdSetRpcKey) && - (key->KeyType != DvdGetRpcKey) && - (key->KeyType != DvdDiskKey) && - (key->KeyType != DvdInvalidateAGID)) - { - status = STATUS_INVALID_PARAMETER; - } - else if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD) - { - // reject the request if it's not a DVD device. - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - - return status; -} - -NTSTATUS -RequestValidateGetConfiguration( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_CDROM_GET_CONFIGURATION - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(GET_CONFIGURATION_HEADER)) - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(GET_CONFIGURATION_HEADER); - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > 0xffff) - { - // output buffer is too large - status = STATUS_INVALID_BUFFER_SIZE; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength & - DeviceExtension->AdapterDescriptor->AlignmentMask) - { - // buffer is not proper size multiple - status = STATUS_INVALID_PARAMETER; - } - - if (NT_SUCCESS(status)) - { - -#if BUILD_WOW64_ENABLED && defined(_WIN64) - - if (WdfRequestIsFrom32BitProcess(Request)) - { - PGET_CONFIGURATION_IOCTL_INPUT32 inputBuffer = NULL; - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(GET_CONFIGURATION_IOCTL_INPUT32)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - // - // also verify the arguments are reasonable. - // - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->Feature > 0xffff) - { - status = STATUS_INVALID_PARAMETER; - } - else if ((inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) && - (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT) && - (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL)) - { - status = STATUS_INVALID_PARAMETER; - } - else if (inputBuffer->Reserved[0] || inputBuffer->Reserved[1]) - { - status = STATUS_INVALID_PARAMETER; - } - } - } - else - -#endif - - { - PGET_CONFIGURATION_IOCTL_INPUT inputBuffer = NULL; - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(GET_CONFIGURATION_IOCTL_INPUT)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - // also verify the arguments are reasonable. - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->Feature > 0xffff) - { - status = STATUS_INVALID_PARAMETER; - } - else if ((inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) && - (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT) && - (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL)) - { - status = STATUS_INVALID_PARAMETER; - } - else if (inputBuffer->Reserved[0] || inputBuffer->Reserved[1]) - { - status = STATUS_INVALID_PARAMETER; - } - } - } - } - - return status; -} - -NTSTATUS -RequestValidateSetSpeed( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_CDROM_SET_SPEED - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PCDROM_SET_SPEED inputBuffer = NULL; - ULONG requiredLength = 0; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(CDROM_SET_SPEED)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - // Get the request type using CDROM_SET_SPEED structure - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(CDROM_SET_SPEED), - &inputBuffer, - NULL); - - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->RequestType > CdromSetStreaming) - { - // Unknown request type. - status = STATUS_INVALID_PARAMETER; - } - else if (inputBuffer->RequestType == CdromSetSpeed) - { - requiredLength = sizeof(CDROM_SET_SPEED); - } - else - { - // Don't send SET STREAMING command if this is not a MMC compliant device - if (cdData->Mmc.IsMmc == FALSE) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - - requiredLength = sizeof(CDROM_SET_STREAMING); - } - } - - if (NT_SUCCESS(status)) - { - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < requiredLength) - { - // Input buffer too small - status = STATUS_INFO_LENGTH_MISMATCH; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsReadMediaKeyBlock( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_READ_MEDIA_KEY_BLOCK - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PAACS_LAYER_NUMBER layerNumber = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(AACS_LAYER_NUMBER)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < 8) - { - // This is a variable-length structure, but we're pretty sure - // it can never be less than eight bytes... - *DataLength = 8; - status = STATUS_BUFFER_TOO_SMALL; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &layerNumber, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (*layerNumber > 255) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsStartSession( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_START_SESSION - -Arguments: - - DeviceExtension - device context - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(DVD_SESSION_ID)) - { - *DataLength = sizeof(DVD_SESSION_ID); - status = STATUS_BUFFER_TOO_SMALL; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(DVD_SESSION_ID)) - { - status = STATUS_INVALID_BUFFER_SIZE; - } - - return status; -} - -NTSTATUS -RequestValidateAacsSendCertificate( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_SEND_CERTIFICATE - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PAACS_SEND_CERTIFICATE inputBuffer = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(AACS_SEND_CERTIFICATE)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->SessionId > MAX_COPY_PROTECT_AGID) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsGetCertificate( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_GET_CERTIFICATE - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PDVD_SESSION_ID sessionId = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_CERTIFICATE)) - { - *DataLength = sizeof(AACS_CERTIFICATE); - status = STATUS_BUFFER_TOO_SMALL; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_CERTIFICATE)) - { - status = STATUS_INVALID_BUFFER_SIZE; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &sessionId, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (*sessionId > MAX_COPY_PROTECT_AGID) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsGetChallengeKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_GET_CHALLENGE_KEY - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PDVD_SESSION_ID sessionId = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_CHALLENGE_KEY)) - { - *DataLength = sizeof(AACS_CHALLENGE_KEY); - status = STATUS_BUFFER_TOO_SMALL; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_CHALLENGE_KEY)) - { - status = STATUS_INVALID_BUFFER_SIZE; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &sessionId, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (*sessionId > MAX_COPY_PROTECT_AGID) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsSendChallengeKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_SEND_CHALLENGE_KEY - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PAACS_SEND_CHALLENGE_KEY inputBuffer = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(AACS_SEND_CHALLENGE_KEY)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->SessionId > MAX_COPY_PROTECT_AGID) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsReadVolumeId( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_READ_VOLUME_ID - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PDVD_SESSION_ID sessionId = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_VOLUME_ID)) - { - *DataLength = sizeof(AACS_VOLUME_ID); - status = STATUS_BUFFER_TOO_SMALL; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_VOLUME_ID)) - { - status = STATUS_INVALID_BUFFER_SIZE; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &sessionId, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (*sessionId > MAX_COPY_PROTECT_AGID) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsReadSerialNumber( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_READ_SERIAL_NUMBER - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PDVD_SESSION_ID sessionId = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_SERIAL_NUMBER)) - { - *DataLength = sizeof(AACS_SERIAL_NUMBER); - status = STATUS_BUFFER_TOO_SMALL; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_SERIAL_NUMBER)) - { - status = STATUS_INVALID_BUFFER_SIZE; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &sessionId, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (*sessionId > MAX_COPY_PROTECT_AGID) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsReadMediaId( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_READ_MEDIA_ID - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PDVD_SESSION_ID sessionId = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_MEDIA_ID)) - { - *DataLength = sizeof(AACS_MEDIA_ID); - status = STATUS_BUFFER_TOO_SMALL; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_MEDIA_ID)) - { - status = STATUS_INVALID_BUFFER_SIZE; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &sessionId, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (*sessionId > MAX_COPY_PROTECT_AGID) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateAacsBindingNonce( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_READ_BINDING_NONCE - IOCTL_AACS_GENERATE_BINDING_NONCE - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PAACS_READ_BINDING_NONCE inputBuffer = NULL; - - *DataLength = 0; - - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(AACS_READ_BINDING_NONCE)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_BINDING_NONCE)) - { - *DataLength = sizeof(AACS_BINDING_NONCE); - status = STATUS_BUFFER_TOO_SMALL; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_BINDING_NONCE)) - { - status = STATUS_INVALID_BUFFER_SIZE; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->SessionId > MAX_COPY_PROTECT_AGID) - { - status = STATUS_INVALID_PARAMETER; - } - else if (inputBuffer->NumberOfSectors > 255) - { - status = STATUS_INVALID_PARAMETER; - } - else if (inputBuffer->StartLba > MAXULONG) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - -NTSTATUS -RequestValidateExclusiveAccess( - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_CDROM_EXCLUSIVE_ACCESS - -Arguments: - - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_EXCLUSIVE_ACCESS exclusiveAccess = NULL; - - *DataLength = 0; - - if (KeGetCurrentIrql() != PASSIVE_LEVEL) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: IOCTL must be called at passive level.\n")); - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(CDROM_EXCLUSIVE_ACCESS)) - { - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: Input buffer too small\n")); - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &exclusiveAccess, - NULL); - } - - if (NT_SUCCESS(status)) - { - switch (exclusiveAccess->RequestType) - { - case ExclusiveAccessQueryState: - { - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(CDROM_EXCLUSIVE_LOCK_STATE)) - { - // - // Output buffer too small. - // - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: Output buffer too small\n")); - *DataLength = sizeof(CDROM_EXCLUSIVE_LOCK_STATE); - status = STATUS_BUFFER_TOO_SMALL; - } - break; - } - - case ExclusiveAccessLockDevice: - { - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_EXCLUSIVE_LOCK)) - { - // - // Input buffer too small - // - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: Input buffer too small\n")); - status = STATUS_INFO_LENGTH_MISMATCH; - } - break; - } - case ExclusiveAccessUnlockDevice: - { - // - // Nothing to check - // - break; - } - - default: - { - // - // Unknown request type. - // - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: Invalid request type\n")); - status = STATUS_INVALID_PARAMETER; - } - } - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleExclusiveAccessQueryLockState( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_EXCLUSIVE_ACCESS with ExclusiveAccessQueryState - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_DATA cdData = &deviceExtension->DeviceAdditionalData; - PCDROM_EXCLUSIVE_LOCK_STATE exclusiveLockState = NULL; - - PAGED_CODE(); - - status = WdfRequestRetrieveOutputBuffer(Request, - sizeof(CDROM_EXCLUSIVE_LOCK_STATE), - &exclusiveLockState, - NULL); - NT_ASSERT(NT_SUCCESS(status)); - - RtlZeroMemory(exclusiveLockState, sizeof(CDROM_EXCLUSIVE_LOCK_STATE)); - - if (EXCLUSIVE_MODE(cdData)) - { - // Device is locked for exclusive use - exclusiveLockState->LockState = TRUE; - - RtlCopyMemory(&exclusiveLockState->CallerName, - &cdData->CallerName, - CDROM_EXCLUSIVE_CALLER_LENGTH); - - } - else - { - // Device is not locked - exclusiveLockState->LockState = FALSE; - } - - RequestCompletion(deviceExtension, Request, status, sizeof(CDROM_EXCLUSIVE_LOCK_STATE)); - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleExclusiveAccessLockDevice( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_EXCLUSIVE_ACCESS with ExclusiveAccessLockDevice - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_DATA cdData = &deviceExtension->DeviceAdditionalData; - PCDROM_EXCLUSIVE_LOCK exclusiveLock = NULL; - PIO_ERROR_LOG_PACKET logEntry; - - WDFFILEOBJECT fileObject = NULL; - ULONG idx = 0; - ULONG nameLength = 0; - - PAGED_CODE(); - - fileObject = WdfRequestGetFileObject(Request); - - if (fileObject == NULL) - { - status = STATUS_INVALID_HANDLE; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessLockDevice: FileObject is NULL, cannot grant exclusive access\n")); - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(CDROM_EXCLUSIVE_LOCK), - &exclusiveLock, - NULL); - } - - if (NT_SUCCESS(status)) - { - // Validate the caller name string - for (idx = 0; (idx < CDROM_EXCLUSIVE_CALLER_LENGTH) && (exclusiveLock->CallerName[idx] != '\0'); idx++) - { - if (!ValidChar(exclusiveLock->CallerName[idx])) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessLockDevice: Invalid characters in caller name\n")); - // error out - status = STATUS_INVALID_PARAMETER; - break; - } - } - } - - if (NT_SUCCESS(status)) - { - if ((idx == 0) || (idx >= CDROM_EXCLUSIVE_CALLER_LENGTH)) - { - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessLockDevice: Not a valid null terminated string.\n")); - //error out - status = STATUS_INVALID_PARAMETER; - } - else - { - nameLength = idx+1; // Add 1 for the NULL character - NT_ASSERT(nameLength <= CDROM_EXCLUSIVE_CALLER_LENGTH); - } - } - - // If the file system is still mounted on this device fail the request, - // unless the force lock flag is set. - if (NT_SUCCESS(status)) - { - if ((TEST_FLAG(exclusiveLock->Access.Flags, CDROM_LOCK_IGNORE_VOLUME) == FALSE) && - IsVolumeMounted(deviceExtension->DeviceObject)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessLockDevice: Unable to lock device, file system mounted\n")); - status = STATUS_INVALID_DEVICE_STATE; - } - } - - // Lock the device for exclusive access if the device is not already locked - if (NT_SUCCESS(status)) - { - if (InterlockedCompareExchangePointer((PVOID)&cdData->ExclusiveOwner, (PVOID)fileObject, NULL) == NULL) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessLockDevice: Entering exclusive mode! Device locked by file object %p\n", fileObject)); - - // Zero out the CallerName before storing it in the extension - RtlZeroMemory(&cdData->CallerName, CDROM_EXCLUSIVE_CALLER_LENGTH); - RtlCopyMemory(&cdData->CallerName, - &exclusiveLock->CallerName, - nameLength); - - // Send Exclusive Lock notification - DeviceSendNotification(deviceExtension, - &GUID_IO_CDROM_EXCLUSIVE_LOCK, - 0, - NULL); - - // Log an informational event with the caller name - logEntry = IoAllocateErrorLogEntry( - deviceExtension->DeviceObject, - sizeof(IO_ERROR_LOG_PACKET) + CDROM_EXCLUSIVE_CALLER_LENGTH); - - if (logEntry != NULL) - { - PUCHAR dumpDataPtr = (PUCHAR) logEntry->DumpData; - - logEntry->FinalStatus = STATUS_SUCCESS; - logEntry->ErrorCode = IO_CDROM_EXCLUSIVE_LOCK; - logEntry->SequenceNumber = 0; - logEntry->MajorFunctionCode = IRP_MJ_DEVICE_CONTROL; - logEntry->IoControlCode = IOCTL_CDROM_EXCLUSIVE_ACCESS; - logEntry->RetryCount = 0; - logEntry->UniqueErrorValue = 0x1; - logEntry->DumpDataSize = CDROM_EXCLUSIVE_CALLER_LENGTH; - - RtlCopyMemory(dumpDataPtr, - (PUCHAR)&cdData->CallerName, - CDROM_EXCLUSIVE_CALLER_LENGTH); - - // Write the error log packet. - IoWriteErrorLogEntry(logEntry); - } - - } - else - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessLockDevice: Unable to lock device, device already locked.\n")); - - status = STATUS_ACCESS_DENIED; - } - } - - RequestCompletion(deviceExtension, Request, status, 0); - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleExclusiveAccessUnlockDevice( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_EXCLUSIVE_ACCESS with ExclusiveAccessUnlockDevice - -Arguments: - - Device - device handle - Request - request to be handled - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_EXCLUSIVE_ACCESS exclusiveAccess = NULL; - WDFFILEOBJECT fileObject = NULL; - - PAGED_CODE(); - - fileObject = WdfRequestGetFileObject(Request); - - if (fileObject == NULL) - { - // The device can be unlocked from exclusive mode only via the file object which locked it. - status = STATUS_INVALID_HANDLE; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleExclusiveAccessUnlockDevice: FileObject is NULL, cannot release exclusive access\n")); - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(PCDROM_EXCLUSIVE_ACCESS), - &exclusiveAccess, - NULL); - } - - if (NT_SUCCESS(status)) - { - status = DeviceUnlockExclusive(deviceExtension, fileObject, - TEST_FLAG(exclusiveAccess->Flags, CDROM_NO_MEDIA_NOTIFICATIONS)); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "RequestHandleExclusiveAccessUnlockDevice: Device unlocked\n")); - } - - RequestCompletion(deviceExtension, Request, status, 0); - - return status; -} - -NTSTATUS -RequestHandleQueryPropertyRetrieveCachedData( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_QUERY_PROPERTY when the required data is cached. - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSTORAGE_PROPERTY_QUERY inputBuffer = NULL; - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - if (inputBuffer->PropertyId == StorageDeviceProperty) - { - // check output buffer length - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength == 0) - { - // According to MSDN, an output buffer of size 0 can be used to determine if a property exists - // so this must be a success case with no data transferred - *DataLength = 0; - status = STATUS_SUCCESS; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_DESCRIPTOR_HEADER)) - { - // Buffer too small - *DataLength = DeviceExtension->DeviceDescriptor->Size; - status = STATUS_BUFFER_TOO_SMALL; - } - else - { - PSTORAGE_DEVICE_DESCRIPTOR outputDescriptor = NULL; - CHAR* localDescriptorBuffer = (CHAR*)DeviceExtension->DeviceDescriptor; - - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputDescriptor, - NULL); - - if (NT_SUCCESS(status)) - { - // transfer as much data out as the buffer will allow - *DataLength = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - DeviceExtension->DeviceDescriptor->Size); - - RtlCopyMemory(outputDescriptor, - DeviceExtension->DeviceDescriptor, - *DataLength); - - // walk through and update offset variables to reflect data that didn't make it into the output buffer - if ((*DataLength >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_DEVICE_DESCRIPTOR, VendorIdOffset)) && - (DeviceExtension->DeviceDescriptor->VendorIdOffset != 0) && - (DeviceExtension->DeviceDescriptor->VendorIdOffset != 0xFFFFFFFF)) - { - // set VendorIdOffset appropriately - if (*DataLength < - (DeviceExtension->DeviceDescriptor->VendorIdOffset + strlen(localDescriptorBuffer + DeviceExtension->DeviceDescriptor->VendorIdOffset))) - { - outputDescriptor->VendorIdOffset = 0; - } - } - - if ((*DataLength >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_DEVICE_DESCRIPTOR, ProductIdOffset)) && - (DeviceExtension->DeviceDescriptor->ProductIdOffset != 0) && - (DeviceExtension->DeviceDescriptor->ProductIdOffset != 0xFFFFFFFF)) - { - // set ProductIdOffset appropriately - if (*DataLength < - (DeviceExtension->DeviceDescriptor->ProductIdOffset + strlen(localDescriptorBuffer + DeviceExtension->DeviceDescriptor->ProductIdOffset))) - { - outputDescriptor->ProductIdOffset = 0; - } - } - - if ((*DataLength >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_DEVICE_DESCRIPTOR, ProductRevisionOffset)) && - (DeviceExtension->DeviceDescriptor->ProductRevisionOffset != 0) && - (DeviceExtension->DeviceDescriptor->ProductRevisionOffset != 0xFFFFFFFF)) - { - // set ProductRevisionOffset appropriately - if (*DataLength < - (DeviceExtension->DeviceDescriptor->ProductRevisionOffset + strlen(localDescriptorBuffer + DeviceExtension->DeviceDescriptor->ProductRevisionOffset))) - { - outputDescriptor->ProductRevisionOffset = 0; - } - } - - if ((*DataLength >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_DEVICE_DESCRIPTOR, SerialNumberOffset)) && - (DeviceExtension->DeviceDescriptor->SerialNumberOffset != 0) && - (DeviceExtension->DeviceDescriptor->SerialNumberOffset != 0xFFFFFFFF)) - { - // set SerialNumberOffset appropriately - if (*DataLength < - (DeviceExtension->DeviceDescriptor->SerialNumberOffset + strlen(localDescriptorBuffer + DeviceExtension->DeviceDescriptor->SerialNumberOffset))) - { - // NOTE: setting this to 0 since that is what most port drivers do - // [this could cause issues with SCSI port devices whose clients expect -1 in this field] - outputDescriptor->SerialNumberOffset = 0; - } - } - status = STATUS_SUCCESS; - } - } - } //end of StorageDeviceProperty - else if (inputBuffer->PropertyId == StorageAdapterProperty) - { - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength == 0) - { - // According to MSDN, an output buffer of size 0 can be used to determine if a property exists - // so this must be a success case with no data transferred - *DataLength = 0; - status = STATUS_SUCCESS; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_DESCRIPTOR_HEADER)) - { - // Buffer too small - *DataLength = DeviceExtension->AdapterDescriptor->Size; - status = STATUS_BUFFER_TOO_SMALL; - } - else - { - PSTORAGE_ADAPTER_DESCRIPTOR outputDescriptor = NULL; - - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputDescriptor, - NULL); - if (NT_SUCCESS(status)) - { - // copy as much data out as the buffer will allow - *DataLength = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - DeviceExtension->AdapterDescriptor->Size); - - RtlCopyMemory(outputDescriptor, - DeviceExtension->AdapterDescriptor, - *DataLength); - - // set status - status = STATUS_SUCCESS; - } - } - } - } - - return status; -} - -NTSTATUS -RequestHandleQueryPropertyDeviceUniqueId( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_QUERY_PROPERTY with StorageDeviceUniqueIdProperty. - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PSTORAGE_PROPERTY_QUERY inputBuffer = NULL; - PSTORAGE_DESCRIPTOR_HEADER descHeader = NULL; - size_t outLength = 0; - WDF_REQUEST_PARAMETERS requestParameters; - - // Get the Request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - status = WdfRequestRetrieveInputBuffer(Request, - requestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - BOOLEAN overflow = FALSE; - BOOLEAN infoFound = FALSE; - - // Must run at less then dispatch. - if (KeGetCurrentIrql() >= DISPATCH_LEVEL) - { - NT_ASSERT(FALSE); - outLength = 0; - status = STATUS_INVALID_LEVEL; - } - else if (inputBuffer->QueryType == PropertyExistsQuery) - { - outLength = 0; - status = STATUS_SUCCESS; - } - else if (inputBuffer->QueryType != PropertyStandardQuery) - { - outLength = 0; - status = STATUS_NOT_SUPPORTED; - } - else - { - // Check AdditionalParameters validity. - if (inputBuffer->AdditionalParameters[0] == DUID_INCLUDE_SOFTWARE_IDS) - { - // Do nothing - } - else if (inputBuffer->AdditionalParameters[0] == DUID_HARDWARE_IDS_ONLY) - { - // Do nothing - } - else - { - outLength = 0; - status = STATUS_INVALID_PARAMETER; - } - - if (NT_SUCCESS(status) && - (outLength < sizeof(STORAGE_DESCRIPTOR_HEADER))) - { - outLength = 0; - status = STATUS_INFO_LENGTH_MISMATCH; - } - } - - // From this point forward the status depends on the overflow - // and infoFound flags. - if (NT_SUCCESS(status)) - { - outLength = requestParameters.Parameters.DeviceIoControl.OutputBufferLength; - status = WdfRequestRetrieveOutputBuffer(Request, - requestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &descHeader, - NULL); - } - - if (NT_SUCCESS(status)) - { - RtlZeroMemory(descHeader, outLength); - - descHeader->Version = DUID_VERSION_1; - descHeader->Size = sizeof(STORAGE_DEVICE_UNIQUE_IDENTIFIER); - - // Try to build device unique id from StorageDeviceIdProperty. - status = RequestDuidGetDeviceIdProperty(deviceExtension, - Request, - requestParameters, - &outLength); - - if (status == STATUS_BUFFER_OVERFLOW) - { - overflow = TRUE; - } - - if (NT_SUCCESS(status)) - { - infoFound = TRUE; - } - - // Try to build device unique id from StorageDeviceProperty. - status = RequestDuidGetDeviceProperty(deviceExtension, - Request, - requestParameters, - &outLength); - - if (status == STATUS_BUFFER_OVERFLOW) - { - overflow = TRUE; - } - - if (NT_SUCCESS(status)) - { - infoFound = TRUE; - } - - // Return overflow, success, or a generic error. - if (overflow) - { - // If output buffer is STORAGE_DESCRIPTOR_HEADER, then return - // success to the user. Otherwise, send an error so the user - // knows a larger buffer is required. - if (outLength == sizeof(STORAGE_DESCRIPTOR_HEADER)) - { - status = STATUS_SUCCESS; - } - else - { - outLength = (ULONG)WdfRequestGetInformation(Request); - status = STATUS_BUFFER_OVERFLOW; - } - - } - else if (infoFound) - { - status = STATUS_SUCCESS; - - // Exercise the compare routine. This should always succeed. - NT_ASSERT(DuidExactMatch == CompareStorageDuids((PSTORAGE_DEVICE_UNIQUE_IDENTIFIER)descHeader, - (PSTORAGE_DEVICE_UNIQUE_IDENTIFIER)descHeader)); - - } - else - { - status = STATUS_NOT_FOUND; - } - } - } - - RequestCompletion(deviceExtension, Request, status, outLength); - - return status; -} - -NTSTATUS -RequestHandleQueryPropertyWriteCache( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_QUERY_PROPERTY with StorageDeviceWriteCacheProperty. - -Arguments: - - DeviceExtension - device context - Request - request to be handled - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PSTORAGE_PROPERTY_QUERY query = NULL; - PSTORAGE_WRITE_CACHE_PROPERTY writeCache = NULL; - PMODE_PARAMETER_HEADER modeData = NULL; - PMODE_CACHING_PAGE pageData = NULL; - size_t length = 0; - ULONG information = 0; - PSCSI_REQUEST_BLOCK srb = NULL; - WDF_REQUEST_PARAMETERS requestParameters; - - // Get the Request parameters - WDF_REQUEST_PARAMETERS_INIT(&requestParameters); - WdfRequestGetParameters(Request, &requestParameters); - - status = WdfRequestRetrieveInputBuffer(Request, - requestParameters.Parameters.DeviceIoControl.InputBufferLength, - &query, - NULL); - - if (NT_SUCCESS(status)) - { - - // Must run at less then dispatch. - if (KeGetCurrentIrql() >= DISPATCH_LEVEL) - { - NT_ASSERT(FALSE); - status = STATUS_INVALID_LEVEL; - } - else if (query->QueryType == PropertyExistsQuery) - { - information = 0; - status = STATUS_SUCCESS; - } - else if (query->QueryType != PropertyStandardQuery) - { - status = STATUS_NOT_SUPPORTED; - } - } - - if (NT_SUCCESS(status)) - { - length = requestParameters.Parameters.DeviceIoControl.OutputBufferLength; - - if (length < sizeof(STORAGE_DESCRIPTOR_HEADER)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - requestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &writeCache, - NULL); - } - - if (NT_SUCCESS(status)) - { - RtlZeroMemory(writeCache, length); - - // Set version and required size. - writeCache->Version = sizeof(STORAGE_WRITE_CACHE_PROPERTY); - writeCache->Size = sizeof(STORAGE_WRITE_CACHE_PROPERTY); - - if (length < sizeof(STORAGE_WRITE_CACHE_PROPERTY)) - { - // caller only wants header information, bail out. - information = sizeof(STORAGE_DESCRIPTOR_HEADER); - status = STATUS_SUCCESS; - - RequestCompletion(deviceExtension, Request, status, information); - return status; - } - } - - if (NT_SUCCESS(status)) - { - srb = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(SCSI_REQUEST_BLOCK) + - (sizeof(ULONG_PTR) * 2), - CDROM_TAG_SRB); - - if (srb == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - - // Set known values - writeCache->NVCacheEnabled = FALSE; - writeCache->UserDefinedPowerProtection = TEST_FLAG(deviceExtension->DeviceFlags, DEV_POWER_PROTECTED); - - // Check for flush cache support by sending a sync cache command - // to the device. - - // Set timeout value and mark the request as not being a tagged request. - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->TimeOutValue = TimeOutValueGetCapValue(deviceExtension->TimeOutValue, 4); - srb->QueueTag = SP_UNTAGGED; - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - srb->SrbFlags = deviceExtension->SrbFlags; - - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->CdbLength = 10; - - srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE; - - status = DeviceSendSrbSynchronously(Device, - srb, - NULL, - 0, - TRUE, //flush drive cache - Request); - - if (NT_SUCCESS(status)) - { - writeCache->FlushCacheSupported = TRUE; - } - else - { - // Device does not support sync cache - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "RequestHandleQueryPropertyWriteCache: Synchronize cache failed with status 0x%X\n", status)); - writeCache->FlushCacheSupported = FALSE; - - // Reset the status if there was any failure - status = STATUS_SUCCESS; - } - - modeData = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - MODE_PAGE_DATA_SIZE, - CDROM_TAG_MODE_DATA); - - if (modeData == NULL) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "RequestHandleQueryPropertyWriteCache: Unable to allocate mode data buffer\n")); - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - RtlZeroMemory(modeData, MODE_PAGE_DATA_SIZE); - - length = DeviceRetrieveModeSenseUsingScratch(deviceExtension, - (PCHAR)modeData, - MODE_PAGE_DATA_SIZE, - MODE_PAGE_CACHING, - MODE_SENSE_CURRENT_VALUES); - - if (length < sizeof(MODE_PARAMETER_HEADER)) - { - // Retry the request in case of a check condition. - length = DeviceRetrieveModeSenseUsingScratch(deviceExtension, - (PCHAR)modeData, - MODE_PAGE_DATA_SIZE, - MODE_PAGE_CACHING, - MODE_SENSE_CURRENT_VALUES); - - if (length < sizeof(MODE_PARAMETER_HEADER)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "RequestHandleQueryPropertyWriteCache: Mode Sense failed\n")); - status = STATUS_IO_DEVICE_ERROR; - } - } - } - - if (NT_SUCCESS(status)) - { - // If the length is greater than length indicated by the mode data reset - // the data to the mode data. - if (length > (ULONG) (modeData->ModeDataLength + 1)) - { - length = modeData->ModeDataLength + 1; - } - - // Look for caching page in the returned mode page data. - pageData = ModeSenseFindSpecificPage((PCHAR)modeData, - length, - MODE_PAGE_CACHING, - TRUE); - - // Check if valid caching page exists. - if (pageData == NULL) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "RequestHandleQueryPropertyWriteCache: Unable to find caching mode page.\n")); - - // Set write cache value as unknown. - writeCache->WriteCacheEnabled = WriteCacheEnableUnknown; - writeCache->WriteCacheType = WriteCacheTypeUnknown; - } - else - { - writeCache->WriteCacheEnabled = pageData->WriteCacheEnable - ? WriteCacheEnabled - : WriteCacheDisabled; - - writeCache->WriteCacheType = pageData->WriteCacheEnable - ? WriteCacheTypeWriteBack - : WriteCacheTypeUnknown; - } - - // Check write through support. - if (modeData->DeviceSpecificParameter & MODE_DSP_FUA_SUPPORTED) - { - writeCache->WriteThroughSupported = WriteThroughSupported; - } - else - { - writeCache->WriteThroughSupported = WriteThroughNotSupported; - } - - // Get the changeable caching mode page and check write cache is changeable. - RtlZeroMemory(modeData, MODE_PAGE_DATA_SIZE); - - length = DeviceRetrieveModeSenseUsingScratch(deviceExtension, - (PCHAR) modeData, - MODE_PAGE_DATA_SIZE, - MODE_PAGE_CACHING, - MODE_SENSE_CHANGEABLE_VALUES); - - if (length < sizeof(MODE_PARAMETER_HEADER)) - { - // Retry the request in case of a check condition. - length = DeviceRetrieveModeSenseUsingScratch(deviceExtension, - (PCHAR) modeData, - MODE_PAGE_DATA_SIZE, - MODE_PAGE_CACHING, - MODE_SENSE_CHANGEABLE_VALUES); - - if (length < sizeof(MODE_PARAMETER_HEADER)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "RequestHandleQueryPropertyWriteCache: Mode Sense failed\n")); - - // If the device fails to return changeable pages, then - // set the write cache changeable value to unknown. - writeCache->WriteCacheChangeable = WriteCacheChangeUnknown; - information = sizeof(STORAGE_WRITE_CACHE_PROPERTY); - } - } - } - - if (NT_SUCCESS(status)) - { - // If the length is greater than length indicated by the mode data reset - // the data to the mode data. - if (length > (ULONG) (modeData->ModeDataLength + 1)) - { - length = modeData->ModeDataLength + 1; - } - - // Look for caching page in the returned mode page data. - pageData = ModeSenseFindSpecificPage((PCHAR)modeData, - length, - MODE_PAGE_CACHING, - TRUE); - // Check if valid caching page exists. - if (pageData == NULL) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "RequestHandleQueryPropertyWriteCache: Unable to find caching mode page.\n")); - - // Set write cache changeable value to unknown. - writeCache->WriteCacheChangeable = WriteCacheChangeUnknown; - } - else - { - writeCache->WriteCacheChangeable = pageData->WriteCacheEnable - ? WriteCacheChangeable - : WriteCacheNotChangeable; - } - - information = sizeof(STORAGE_WRITE_CACHE_PROPERTY); - - } - - FREE_POOL(srb); - FREE_POOL(modeData); - - RequestCompletion(deviceExtension, Request, status, information); - - return status; -} - -NTSTATUS -RequestValidateDvdReadKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_DVD_READ_KEY - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDVD_COPY_PROTECT_KEY keyParameters = NULL; - ULONG keyLength = 0; - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &keyParameters, - NULL); - - if (NT_SUCCESS(status)) - { - if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(DVD_COPY_PROTECT_KEY)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DvdDeviceControl: EstablishDriveKey - challenge " - "key buffer too small\n")); - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - switch(keyParameters->KeyType) - { - - case DvdChallengeKey: - { - C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_CHALLENGE_KEY_LENGTH); - keyLength = DVD_CHALLENGE_KEY_LENGTH; - break; - } - case DvdBusKey1: - case DvdBusKey2: - { - C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_BUS_KEY_LENGTH); - keyLength = DVD_BUS_KEY_LENGTH; - break; - } - case DvdTitleKey: - { - C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_TITLE_KEY_LENGTH); - keyLength = DVD_TITLE_KEY_LENGTH; - break; - } - case DvdAsf: - { - C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_ASF_LENGTH); - keyLength = DVD_ASF_LENGTH; - break; - } - case DvdDiskKey: - { - C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_DISK_KEY_LENGTH); - keyLength = DVD_DISK_KEY_LENGTH; - break; - } - case DvdGetRpcKey: - { - C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_RPC_KEY_LENGTH); - keyLength = DVD_RPC_KEY_LENGTH; - break; - } - default: - { - keyLength = sizeof(DVD_COPY_PROTECT_KEY); - break; - } - } - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < keyLength) - { - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DvdDeviceControl: EstablishDriveKey - output " - "buffer too small\n")); - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = keyLength; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength & - DeviceExtension->AdapterDescriptor->AlignmentMask) - { - status = STATUS_INVALID_PARAMETER; - } - else if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD) - { - // reject the request if it's not a DVD device. - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - - return status; -} - - -NTSTATUS -RequestValidateDvdEndSession( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DVD_END_SESSION - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID sessionId = NULL; - - UNREFERENCED_PARAMETER(DeviceExtension); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &sessionId, - NULL); - - if (NT_SUCCESS(status)) - { - if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(DVD_SESSION_ID)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DvdDeviceControl: EndSession - input buffer too " - "small\n")); - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - - -NTSTATUS -RequestValidateAacsEndSession( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_AACS_END_SESSION - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID sessionId = NULL; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &sessionId, - NULL); - - if (NT_SUCCESS(status)) - { - if (!cdData->Mmc.IsAACS) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID)) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - - -NTSTATUS -RequestValidateEnableStreaming( - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validates an IOCTL_CDROM_ENABLE_STREAMING request - -Arguments: - - Request - request to be handled - RequestParameters - request parameters - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PCDROM_STREAMING_CONTROL inputBuffer = NULL; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_STREAMING_CONTROL)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - // Get the request type using CDROM_STREAMING_CONTROL structure - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(CDROM_STREAMING_CONTROL), - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->RequestType != CdromStreamingDisable && - inputBuffer->RequestType != CdromStreamingEnableForReadOnly && - inputBuffer->RequestType != CdromStreamingEnableForWriteOnly && - inputBuffer->RequestType != CdromStreamingEnableForReadWrite) - { - // Unknown request type - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - - -NTSTATUS -RequestValidateSendOpcInformation( - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validates an IOCTL_CDROM_SEND_OPC_INFORMATION request - -Arguments: - - Request - request to be handled - RequestParameters - request parameters - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PCDROM_SIMPLE_OPC_INFO inputBuffer = NULL; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_SIMPLE_OPC_INFO)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - // Get the request type using CDROM_SIMPLE_OPC_INFO structure - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(CDROM_SIMPLE_OPC_INFO), - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->RequestType != SimpleOpcInfo) - { - // Unknown request type - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - - -NTSTATUS -RequestValidateGetPerformance( - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validates an IOCTL_CDROM_GET_PERFORMANCE request - -Arguments: - - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_WRITE_SPEED_REQUEST writeSpeedRequest = NULL; - PCDROM_PERFORMANCE_REQUEST performanceRequest = NULL; - - *DataLength = 0; - - // CDROM_WRITE_SPEED_REQUEST is the smallest performance request that we support. - // We use it to retrieve request type and then check input length more carefully - // on a per request type basis. - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_WRITE_SPEED_REQUEST)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(CDROM_WRITE_SPEED_REQUEST), - (PVOID*)&writeSpeedRequest, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (writeSpeedRequest->RequestType == CdromPerformanceRequest) - { - // CDROM_PERFORMANCE_REQUEST is bigger than CDROM_WRITE_SPEED_REQUEST, - // so we perform more checks and retrieve more bytes through WDF. - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_PERFORMANCE_REQUEST)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(CDROM_PERFORMANCE_REQUEST), - &performanceRequest, - NULL); - } - - if (!NT_SUCCESS(status)) - { - // just pass the status code from above - } - // validate all enum-type fields of CDROM_PERFORMANCE_REQUEST - else if (performanceRequest->PerformanceType != CdromReadPerformance && - performanceRequest->PerformanceType != CdromWritePerformance) - { - status = STATUS_INVALID_PARAMETER; - } - else if (performanceRequest->Exceptions != CdromReadPerformance && - performanceRequest->Exceptions != CdromEntirePerformanceList && - performanceRequest->Exceptions != CdromPerformanceExceptionsOnly) - { - status = STATUS_INVALID_PARAMETER; - } - else if (performanceRequest->Tolerance != Cdrom10Nominal20Exceptions) - { - status = STATUS_INVALID_PARAMETER; - } - } - else if (writeSpeedRequest->RequestType == CdromWriteSpeedRequest) - { - // No additional checks here: all remaining fields are ignored - // if RequestType == CdromWriteSpeedRequest. - } - else - { - status = STATUS_INVALID_PARAMETER; - } - } - - // finally, check output buffer length - if (NT_SUCCESS(status)) - { - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(CDROM_PERFORMANCE_HEADER)) - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(CDROM_PERFORMANCE_HEADER); - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > - ((USHORT)-1)) - { - status = STATUS_INVALID_PARAMETER; - } - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -PCDB -RequestGetScsiPassThroughCdb( - _In_ PIRP Irp - ) -/*++ - -Routine Description: - - Get the CDB structure from the SCSI pass through - -Arguments: - - Irp - request to be handled - -Return Value: - - PCDB - ---*/ -{ - PCDB cdb = NULL; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - ULONG inputBufferLength = 0; - PVOID inputBuffer = NULL; - BOOLEAN legacyPassThrough = FALSE; - - PAGED_CODE(); - - if (((currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH) || - (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) || - (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_EX) || - (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT_EX)) && - (Irp->AssociatedIrp.SystemBuffer != NULL)) - { - inputBufferLength = currentIrpStack->Parameters.DeviceIoControl.InputBufferLength; - inputBuffer = Irp->AssociatedIrp.SystemBuffer; - legacyPassThrough = TRUE; - - if ((currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_EX) || - (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT_EX)) - { - legacyPassThrough = FALSE; - } - - // - // If this is a 32 bit application running on 64 bit then thunk the - // input structures to grab the cdb. - // - -#if BUILD_WOW64_ENABLED && defined(_WIN64) - - if (IoIs32bitProcess(Irp)) - { - if (legacyPassThrough) - { - if (inputBufferLength >= sizeof(SCSI_PASS_THROUGH32)) - { - cdb = (PCDB)((PSCSI_PASS_THROUGH32)inputBuffer)->Cdb; - } - } - else - { - if (inputBufferLength >= sizeof(SCSI_PASS_THROUGH32_EX)) - { - cdb = (PCDB)((PSCSI_PASS_THROUGH32_EX)inputBuffer)->Cdb; - } - } - - } - else - -#endif - - { - if (legacyPassThrough) - { - if (inputBufferLength >= sizeof(SCSI_PASS_THROUGH)) - { - cdb = (PCDB)((PSCSI_PASS_THROUGH)inputBuffer)->Cdb; - } - } - else - { - if (inputBufferLength >= sizeof(SCSI_PASS_THROUGH_EX)) - { - cdb = (PCDB)((PSCSI_PASS_THROUGH_EX)inputBuffer)->Cdb; - } - } - } - } - - return cdb; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleScsiPassThrough( - _In_ WDFDEVICE Device, - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - Handle request of IOCTL_SCSI_PASS_THROUGH - IOCTL_SCSI_PASS_THROUGH_DIRECT - - The function sets the MinorFunction field of irpStack, - and pass the request to lower level driver. - -Arguments: - - Device - device object - Request - request to be handled - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_UNSUCCESSFUL; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PIRP irp = WdfRequestWdmGetIrp(Request); - PZERO_POWER_ODD_INFO zpoddInfo = deviceExtension->ZeroPowerODDInfo; - PCDB cdb = NULL; - BOOLEAN isSoftEject = FALSE; - -#if DBG - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); -#endif - - - PAGED_CODE(); - -#if DBG - // SPTI is always processed in sync manner. - NT_ASSERT(requestContext->SyncRequired); -#endif - - if ((zpoddInfo != NULL) && - (zpoddInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) && - (zpoddInfo->Load == 0)) // Drawer - { - cdb = RequestGetScsiPassThroughCdb(irp); - - if ((cdb != NULL) && - (cdb->AsByte[0] == SCSIOP_START_STOP_UNIT) && - (cdb->START_STOP.LoadEject == 1) && - (cdb->START_STOP.Start == 0)) - { - isSoftEject = TRUE; - } - } - - WdfRequestFormatRequestUsingCurrentType(Request); - - // Special for SPTI, set the MinorFunction. - { - PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(irp); - - nextStack->MinorFunction = 1; - } - - - status = RequestSend(deviceExtension, - Request, - deviceExtension->IoTarget, - WDF_REQUEST_SEND_OPTION_SYNCHRONOUS, - NULL); - - - if (!NT_SUCCESS(status) && - (isSoftEject != FALSE)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, - "RequestHandleScsiPassThrough: soft eject detected, device marked as active\n")); - - DeviceMarkActive(deviceExtension, TRUE, FALSE); - } - - RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request)); - - return status; -} - -NTSTATUS -RequestHandleMountQueryUniqueId( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_MOUNTDEV_QUERY_UNIQUE_ID - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PMOUNTDEV_UNIQUE_ID uniqueId = NULL; - - *DataLength = 0; - - if (!DeviceExtension->MountedDeviceInterfaceName.Buffer) - { - status = STATUS_INVALID_PARAMETER; - } - else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_UNIQUE_ID)) - { - *DataLength = sizeof(MOUNTDEV_UNIQUE_ID); - status = STATUS_BUFFER_TOO_SMALL; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &uniqueId, - NULL); - } - - if (NT_SUCCESS(status)) - { - RtlZeroMemory(uniqueId, RequestParameters.Parameters.DeviceIoControl.OutputBufferLength); - - uniqueId->UniqueIdLength = DeviceExtension->MountedDeviceInterfaceName.Length; - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - (sizeof(USHORT) + DeviceExtension->MountedDeviceInterfaceName.Length)) - { - *DataLength = sizeof(MOUNTDEV_UNIQUE_ID); - status = STATUS_BUFFER_OVERFLOW; - } - } - - if (NT_SUCCESS(status)) - { - RtlCopyMemory(uniqueId->UniqueId, - DeviceExtension->MountedDeviceInterfaceName.Buffer, - uniqueId->UniqueIdLength); - - *DataLength = sizeof(USHORT) + uniqueId->UniqueIdLength; - status = STATUS_SUCCESS; - } - - return status; -} - -NTSTATUS -RequestHandleMountQueryDeviceName( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_MOUNTDEV_QUERY_DEVICE_NAME - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PMOUNTDEV_NAME name = NULL; - - *DataLength = 0; - - NT_ASSERT(DeviceExtension->DeviceName.Buffer); - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME)) - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(MOUNTDEV_NAME); - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &name, - NULL); - } - - if (NT_SUCCESS(status)) - { - RtlZeroMemory(name, RequestParameters.Parameters.DeviceIoControl.OutputBufferLength); - name->NameLength = DeviceExtension->DeviceName.Length; - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - (sizeof(USHORT) + DeviceExtension->DeviceName.Length)) - { - status = STATUS_BUFFER_OVERFLOW; - *DataLength = sizeof(MOUNTDEV_NAME); - } - } - - if (NT_SUCCESS(status)) - { - RtlCopyMemory(name->Name, - DeviceExtension->DeviceName.Buffer, - name->NameLength); - - status = STATUS_SUCCESS; - *DataLength = sizeof(USHORT) + name->NameLength; - } - - return status; -} - -NTSTATUS -RequestHandleMountQuerySuggestedLinkName( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PMOUNTDEV_SUGGESTED_LINK_NAME suggestedName = NULL; - - WCHAR driveLetterNameBuffer[10] = {0}; - RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0}; - PWSTR valueName = NULL; - UNICODE_STRING driveLetterName = {0}; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < - sizeof(MOUNTDEV_SUGGESTED_LINK_NAME)) - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME); - } - - if (NT_SUCCESS(status)) - { - valueName = ExAllocatePool2(POOL_FLAG_PAGED, - DeviceExtension->DeviceName.Length + sizeof(WCHAR), - CDROM_TAG_STRINGS); - if (valueName == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - RtlCopyMemory(valueName, - DeviceExtension->DeviceName.Buffer, - DeviceExtension->DeviceName.Length); - valueName[DeviceExtension->DeviceName.Length/sizeof(WCHAR)] = 0; - - driveLetterName.Buffer = driveLetterNameBuffer; - driveLetterName.MaximumLength = sizeof(driveLetterNameBuffer); - driveLetterName.Length = 0; - - queryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = valueName; - queryTable[0].EntryContext = &driveLetterName; - queryTable[0].DefaultType = (REG_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, - L"\\Registry\\Machine\\System\\DISK", // why hard coded? - queryTable, NULL, NULL); - } - - if (NT_SUCCESS(status)) - { - if ((driveLetterName.Length == 4) && - (driveLetterName.Buffer[0] == '%') && - (driveLetterName.Buffer[1] == ':')) - { - driveLetterName.Buffer[0] = 0xFF; - } - else if ((driveLetterName.Length != 4) || - (driveLetterName.Buffer[0] < FirstDriveLetter) || - (driveLetterName.Buffer[0] > LastDriveLetter) || - (driveLetterName.Buffer[1] != ':')) - { - status = STATUS_NOT_FOUND; - } - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &suggestedName, - NULL); - } - - if (NT_SUCCESS(status)) - { - RtlZeroMemory(suggestedName, RequestParameters.Parameters.DeviceIoControl.OutputBufferLength); - suggestedName->UseOnlyIfThereAreNoOtherLinks = TRUE; - suggestedName->NameLength = 28; - - *DataLength = FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME, Name) + 28; - - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < *DataLength) - { - *DataLength = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME); - status = STATUS_BUFFER_OVERFLOW; - } - } - - if (NT_SUCCESS(status)) - { - RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE, - L"\\Registry\\Machine\\System\\DISK", - valueName); - - RtlCopyMemory(suggestedName->Name, L"\\DosDevices\\", 24); - suggestedName->Name[12] = driveLetterName.Buffer[0]; - suggestedName->Name[13] = ':'; - } - - FREE_POOL(valueName); - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleReadTOC( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_READ_TOC - IOCTL_CDROM_GET_LAST_SESSION - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - VOID* outputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - if (DeviceIsPlayActive(DeviceExtension->Device)) - { - status = STATUS_DEVICE_BUSY; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - // handle the request - if (NT_SUCCESS(status)) - { - size_t transferSize; - CDB cdb; - - transferSize = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, sizeof(CDROM_TOC)); - - RtlZeroMemory(outputBuffer, transferSize); - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - if (RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_LAST_SESSION) - { - // Set format to return first and last session numbers. - cdb.READ_TOC.Format2 = CDROM_READ_TOC_EX_FORMAT_SESSION; - } - else - { - // Use MSF addressing - cdb.READ_TOC.Msf = 1; - } - - cdb.READ_TOC.OperationCode = SCSIOP_READ_TOC; - cdb.READ_TOC.AllocationLength[0] = (UCHAR)(transferSize >> 8); - cdb.READ_TOC.AllocationLength[1] = (UCHAR)(transferSize & 0xFF); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, (ULONG)transferSize, TRUE, &cdb, 10); - - if (NT_SUCCESS(status)) - { - *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength; - RtlCopyMemory(outputBuffer, - DeviceExtension->ScratchContext.ScratchBuffer, - *DataLength); - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleReadTocEx( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_READ_TOC_EX - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_READ_TOC_EX inputBuffer = NULL; - VOID* outputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - if (DeviceIsPlayActive(DeviceExtension->Device)) - { - status = STATUS_DEVICE_BUSY; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - // handle the request - if (NT_SUCCESS(status)) - { - size_t transferSize; - CDB cdb; - - transferSize = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, MAXUSHORT); - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.READ_TOC.OperationCode = SCSIOP_READ_TOC; - cdb.READ_TOC.Msf = inputBuffer->Msf; - cdb.READ_TOC.Format2 = inputBuffer->Format; - cdb.READ_TOC.StartingTrack = inputBuffer->SessionTrack; - cdb.READ_TOC.AllocationLength[0] = (UCHAR)(transferSize >> 8); - cdb.READ_TOC.AllocationLength[1] = (UCHAR)(transferSize & 0xFF); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, (ULONG)transferSize, TRUE, &cdb, 10); - - if (NT_SUCCESS(status)) - { - if (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength < MINIMUM_CDROM_READ_TOC_EX_SIZE) - { - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - else - { - *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength; - RtlCopyMemory(outputBuffer, - DeviceExtension->ScratchContext.ScratchBuffer, - *DataLength); - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -VOID -GetConfigurationDataConversionTypeAllToTypeOne( - _In_ FEATURE_NUMBER RequestedFeature, - _In_ PSCSI_REQUEST_BLOCK Srb, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Some CDROM devices do not handle the GET CONFIGURATION commands with - TYPE ONE request. The command will time out causing a bus reset. - To avoid this problem we set a device flag during start device if the device - fails a TYPE ONE request. If this flag is set the TYPE ONE requests will be - tried as TYPE ALL request and the data will be converted to TYPE ONE format - in this routine. - -Arguments: - - RequestedFeature - device context - Srb - request to be handled - DataLength - transfer data length - -Return Value: - - NTSTATUS - ---*/ -{ - PFEATURE_HEADER featureHeader = NULL; - FEATURE_NUMBER thisFeature; - ULONG totalLength = 0; - ULONG featureLength = 0; - ULONG headerLength = 0; - - PGET_CONFIGURATION_HEADER header = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - if (Srb->DataTransferLength < RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength)) - { - // do not have valid data. - return; - } - - // Calculate the length of valid data available in the - // capabilities buffer from the DataLength field - header = (PGET_CONFIGURATION_HEADER) Srb->DataBuffer; - REVERSE_BYTES(&totalLength, header->DataLength); - - totalLength += RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength); - - // Make sure the we have enough data in the SRB - totalLength = min(totalLength, Srb->DataTransferLength); - - // If we have received enough data from the device - // check for the given feature. - if (totalLength >= (sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER))) - { - // Feature information is present. Verify the feature. - featureHeader = (PFEATURE_HEADER)((PUCHAR)Srb->DataBuffer + sizeof(GET_CONFIGURATION_HEADER)); - - thisFeature = (featureHeader->FeatureCode[0] << 8) | (featureHeader->FeatureCode[1]); - - if (thisFeature == RequestedFeature) - { - // Calculate the feature length - featureLength = sizeof(FEATURE_HEADER) + featureHeader->AdditionalLength; - } - } - - // Calculate the total size - totalLength = sizeof(GET_CONFIGURATION_HEADER) + featureLength; - - headerLength = totalLength - - RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength); - - REVERSE_BYTES(header->DataLength, &headerLength); - - *DataLength = totalLength; - - return; -} - -_IRQL_requires_max_(APC_LEVEL) -VOID -GetConfigurationDataSynthesize( - _In_reads_bytes_(InputBufferSize) PVOID InputBuffer, - _In_ ULONG InputBufferSize, - _Out_writes_bytes_(OutputBufferSize) PVOID OutputBuffer, - _In_ size_t OutputBufferSize, - _In_ FEATURE_NUMBER StartingFeature, - _In_ ULONG RequestType, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Get Configuration is a frequently used command, and we don't want it to wake - up the device in case it is in Zero Power state. Before entering Zero Power state, - the complete response of the command is saved in cache, and since the response - is always the same in case there is no media, we can synthesize the response - based on the user request. - -Arguments: - - InputBuffer - buffer containing cached command response - InputBufferSize - size of above buffer - OutputBuffer - buffer to fill in result - OutputBufferSize - size of above buffer - StartingFeature - requested Starting Feature Number - RequestType - requested Request Type - DataLength - transfer data length - -Return Value: - ---*/ -{ - PFEATURE_HEADER featureHeader = NULL; - ULONG validLength = 0; - ULONG featureLength = 0; - ULONG headerLength = 0; - PUCHAR buffer = NULL; - ULONG bytesRemaining = 0; - FEATURE_NUMBER featureCode = 0; - BOOLEAN shouldCopy = FALSE; - size_t copyLength = 0; - size_t transferedLength = 0; - size_t requiredLength = 0; - - PGET_CONFIGURATION_HEADER header = NULL; - - PAGED_CODE (); - - if (InputBufferSize < sizeof (GET_CONFIGURATION_HEADER)) - { - // do not have valid data. - *DataLength = 0; - - return; - } - - // Calculate the length of valid data available in the - // capabilities buffer from the DataLength field - header = (PGET_CONFIGURATION_HEADER) InputBuffer; - REVERSE_BYTES(&validLength, header->DataLength); - - validLength += RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength); - - // Make sure we have enough data - validLength = min(validLength, InputBufferSize); - - // Copy the header first - copyLength = min(OutputBufferSize, sizeof (GET_CONFIGURATION_HEADER)); - - RtlMoveMemory(OutputBuffer, - InputBuffer, - copyLength); - - transferedLength = copyLength; - requiredLength = sizeof (GET_CONFIGURATION_HEADER); - - if (validLength > sizeof (GET_CONFIGURATION_HEADER)) - { - buffer = header->Data; - bytesRemaining = validLength - sizeof (GET_CONFIGURATION_HEADER); - - // Ignore incomplete feature descriptor - while (bytesRemaining >= sizeof (FEATURE_HEADER)) - { - featureHeader = (PFEATURE_HEADER) buffer; - shouldCopy = FALSE; - - featureCode = (featureHeader->FeatureCode[0] << 8) | (featureHeader->FeatureCode[1]); - featureLength = sizeof (FEATURE_HEADER) + featureHeader->AdditionalLength; - - if (featureCode >= StartingFeature) - { - switch (RequestType) { - - case SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL: - - shouldCopy = TRUE; - break; - - case SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT: - - if (featureHeader->Current) - { - shouldCopy = TRUE; - } - break; - - case SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE: - - if (featureCode == StartingFeature) - { - shouldCopy = TRUE; - } - break; - - default: - - break; - } - } - - if (shouldCopy != FALSE) - { - copyLength = min(featureLength, bytesRemaining); - copyLength = min(copyLength, OutputBufferSize - transferedLength); - - RtlMoveMemory((PUCHAR) OutputBuffer + transferedLength, - buffer, - copyLength); - - transferedLength += copyLength; - requiredLength += featureLength; - } - - buffer += min(featureLength, bytesRemaining); - bytesRemaining -= min(featureLength, bytesRemaining); - } - } - - // Adjust Data Length field in header - if (transferedLength >= RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength)) - { - headerLength = (ULONG) requiredLength - RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength); - - header = (PGET_CONFIGURATION_HEADER) OutputBuffer; - REVERSE_BYTES(header->DataLength, &headerLength); - } - - *DataLength = transferedLength; - - return; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleGetConfiguration( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_GET_CONFIGURATION - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PGET_CONFIGURATION_IOCTL_INPUT inputBuffer = NULL; - VOID* outputBuffer = NULL; - size_t transferByteCount = 0; - PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo; - BOOLEAN inZeroPowerState = FALSE; - - PAGED_CODE (); - - *DataLength = 0; - - // - if (!cdData->Mmc.IsMmc) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - else - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - // If device is Zero Power state, there should be no media in device, thus we can synthesize the response - // from our cache. Avoid waking up the device in this case. - if ((zpoddInfo != NULL) && - (zpoddInfo->InZeroPowerState != FALSE)) - { - inZeroPowerState = TRUE; - } - - if ((inZeroPowerState == FALSE) || - (zpoddInfo->GetConfigurationBuffer == NULL)) - { - CDB cdb; - - //The maximum number of bytes that a Drive may return - //to describe its Features in one GET CONFIGURATION Command is 65,534 - transferByteCount = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, (MAXUSHORT - 1)); - - // If this is a TYPE ONE request and if this device can't handle this - // request, then we need to send TYPE ALL request to the device and - // convert the data in the completion routine. If required allocate a big - // buffer to get both configuration and feature header. - if ((inputBuffer->RequestType == SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) && - TEST_FLAG(cdData->HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG)) - { - transferByteCount = max(transferByteCount, - sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER)); - } - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.GET_CONFIGURATION.OperationCode = SCSIOP_GET_CONFIGURATION; - cdb.GET_CONFIGURATION.AllocationLength[0] = (UCHAR)(transferByteCount >> 8); - cdb.GET_CONFIGURATION.AllocationLength[1] = (UCHAR)(transferByteCount & 0xff); - - cdb.GET_CONFIGURATION.StartingFeature[0] = (UCHAR)(inputBuffer->Feature >> 8); - cdb.GET_CONFIGURATION.StartingFeature[1] = (UCHAR)(inputBuffer->Feature & 0xff); - cdb.GET_CONFIGURATION.RequestType = (UCHAR)(inputBuffer->RequestType); - - // If the device does not support TYPE ONE get configuration commands - // then change the request type to TYPE ALL. Convert the returned data to - // TYPE ONE format in the completion routine. - if ((inputBuffer->RequestType == SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) && - TEST_FLAG(cdData->HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG)) - { - - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "DeviceHandleGetConfiguration: Changing TYPE_ONE Get Config to TYPE_ALL\n")); - cdb.GET_CONFIGURATION.RequestType = SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL; - } - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, (ULONG)transferByteCount, TRUE, &cdb, 12); - - if (NT_SUCCESS(status)) - { - if ((inputBuffer->RequestType == SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) && - TEST_FLAG(cdData->HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG)) - { - - if (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength < sizeof(GET_CONFIGURATION_HEADER)) - { - // Not enough data to calculate the data length. - // So assume feature is not present - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "DeviceHandleGetConfiguration: No get config header!\n")); - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - else - { - //Some CDROM devices do not handle the GET CONFIGURATION commands with - //TYPE ONE request. The command will time out causing a bus reset. - //To avoid this problem we set a device flag during start device if the device - //fails a TYPE ONE request. If this flag is set the TYPE ONE requests will be - //tried as TYPE ALL request and the data will be converted to TYPE ONE format - //in this routine. - GetConfigurationDataConversionTypeAllToTypeOne(inputBuffer->Feature, DeviceExtension->ScratchContext.ScratchSrb, DataLength); - *DataLength = min(*DataLength, RequestParameters.Parameters.DeviceIoControl.OutputBufferLength); - } - } - else - { - *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength; - } - - // copy data to output buffer - if (NT_SUCCESS(status)) - { - RtlMoveMemory(outputBuffer, - DeviceExtension->ScratchContext.ScratchBuffer, - *DataLength); - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - else - { - // We are in Zero Power state, and our cached response is available. - // Synthesize the requested data. - GetConfigurationDataSynthesize(zpoddInfo->GetConfigurationBuffer, - zpoddInfo->GetConfigurationBufferSize, - outputBuffer, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - inputBuffer->Feature, - inputBuffer->RequestType, - DataLength - ); - } - } - - return status; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -RequestHandleGetDriveGeometry( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DISK_GET_LENGTH_INFO - IOCTL_DISK_GET_DRIVE_GEOMETRY - IOCTL_DISK_GET_DRIVE_GEOMETRY_EX - IOCTL_CDROM_GET_DRIVE_GEOMETRY - IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX - IOCTL_STORAGE_READ_CAPACITY - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - VOID* outputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - - // Issue ReadCapacity to update device extension - // with information for current media. - if (NT_SUCCESS(status)) - { - status = MediaReadCapacity(DeviceExtension->Device); - } - - if (NT_SUCCESS(status)) - { - switch(RequestParameters.Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_DISK_GET_LENGTH_INFO: - { - PGET_LENGTH_INFORMATION lengthInfo = (PGET_LENGTH_INFORMATION)outputBuffer; - - lengthInfo->Length = DeviceExtension->PartitionLength; - *DataLength = sizeof(GET_LENGTH_INFORMATION); - break; - } - case IOCTL_DISK_GET_DRIVE_GEOMETRY: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY: - { - PDISK_GEOMETRY geometry = (PDISK_GEOMETRY)outputBuffer; - - *geometry = DeviceExtension->DiskGeometry; - *DataLength = sizeof(DISK_GEOMETRY); - break; - } - case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: - { - PDISK_GEOMETRY_EX geometryEx = (PDISK_GEOMETRY_EX)outputBuffer; - - geometryEx->DiskSize = DeviceExtension->PartitionLength; - geometryEx->Geometry = DeviceExtension->DiskGeometry; - *DataLength = FIELD_OFFSET(DISK_GEOMETRY_EX, Data); - break; - } - case IOCTL_STORAGE_READ_CAPACITY: - { - PSTORAGE_READ_CAPACITY readCapacity = (PSTORAGE_READ_CAPACITY)outputBuffer; - - readCapacity->Version = sizeof(STORAGE_READ_CAPACITY); - readCapacity->Size = sizeof(STORAGE_READ_CAPACITY); - - readCapacity->BlockLength = DeviceExtension->DiskGeometry.BytesPerSector; - if (readCapacity->BlockLength > 0) - { - readCapacity->NumberOfBlocks.QuadPart = DeviceExtension->PartitionLength.QuadPart/readCapacity->BlockLength; - } - else - { - readCapacity->NumberOfBlocks.QuadPart = 0; - } - - readCapacity->DiskLength = DeviceExtension->PartitionLength; - - *DataLength = sizeof(STORAGE_READ_CAPACITY); - break; - } - default: - { - NT_ASSERT(FALSE); - break; - } - } // end of switch() - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleDiskVerify( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DISK_VERIFY - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PVERIFY_INFORMATION verifyInfo = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - if (!cdData->Mmc.WriteAllowed) - { - status = STATUS_MEDIA_WRITE_PROTECTED; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &verifyInfo, - NULL); - } - - // handle the request - if (NT_SUCCESS(status)) - { - LARGE_INTEGER byteOffset = {0}; - - // Add disk offset to starting sector. - byteOffset.QuadPart = DeviceExtension->StartingOffset.QuadPart + - verifyInfo->StartingOffset.QuadPart; - - // prevent overflow returning success but only validating small area - if (((DeviceExtension->StartingOffset.QuadPart + verifyInfo->StartingOffset.QuadPart) < DeviceExtension->StartingOffset.QuadPart) || - ((verifyInfo->Length >> DeviceExtension->SectorShift) > MAXUSHORT) || - ((byteOffset.QuadPart >> DeviceExtension->SectorShift) > MAXULONG) ) - { - status = STATUS_INVALID_PARAMETER; - } - else - { - ULONG transferSize = 0; - ULONG timeoutValue = 0; - CDB cdb; - ULONG sectorOffset; - USHORT sectorCount; - - ScratchBuffer_BeginUse(DeviceExtension); - - // Convert byte offset to sector offset. - sectorOffset = (ULONG)(byteOffset.QuadPart >> DeviceExtension->SectorShift); - - // Convert ULONG byte count to USHORT sector count. - sectorCount = (USHORT)(verifyInfo->Length >> DeviceExtension->SectorShift); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.CDB10.OperationCode = SCSIOP_VERIFY; - - // Move little endian values into CDB in big endian format. - cdb.CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)§orOffset)->Byte3; - cdb.CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)§orOffset)->Byte2; - cdb.CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)§orOffset)->Byte1; - cdb.CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)§orOffset)->Byte0; - - cdb.CDB10.TransferBlocksMsb = ((PFOUR_BYTE)§orCount)->Byte1; - cdb.CDB10.TransferBlocksLsb = ((PFOUR_BYTE)§orCount)->Byte0; - - // The verify command is used by the NT FORMAT utility and - // requests are sent down for 5% of the volume size. The - // request timeout value is calculated based on the number of - // sectors verified. - if (sectorCount != 0) - { - // sectorCount is a USHORT, so no overflow here... - timeoutValue = TimeOutValueGetCapValue(DeviceExtension->TimeOutValue, ((sectorCount + 128) / 128)); - } - - status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, Request, transferSize, FALSE, &cdb, 10, timeoutValue); - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleCheckVerify( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_CHECK_VERIFY2 - IOCTL_STORAGE_CHECK_VERIFY - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE (); - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; - - status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, Request, transferSize, FALSE, &cdb, 6, CDROM_TEST_UNIT_READY_TIMEOUT); - - if (NT_SUCCESS(status)) - { - if((RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_CHECK_VERIFY) && - (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength)) - { - PULONG outputBuffer = NULL; - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - - if (outputBuffer != NULL) - { - *outputBuffer = DeviceExtension->MediaChangeCount; - *DataLength = sizeof(ULONG); - } - } - else - { - *DataLength = 0; - } - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleFakePartitionInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DISK_GET_DRIVE_LAYOUT - IOCTL_DISK_GET_DRIVE_LAYOUT_EX - IOCTL_DISK_GET_PARTITION_INFO - IOCTL_DISK_GET_PARTITION_INFO_EX - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - VOID* outputBuffer = NULL; - ULONG ioctl = RequestParameters.Parameters.DeviceIoControl.IoControlCode; - - PAGED_CODE (); - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - if ((ioctl != IOCTL_DISK_GET_DRIVE_LAYOUT) && - (ioctl != IOCTL_DISK_GET_DRIVE_LAYOUT_EX) && - (ioctl != IOCTL_DISK_GET_PARTITION_INFO) && - (ioctl != IOCTL_DISK_GET_PARTITION_INFO_EX)) - { - status = STATUS_INTERNAL_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - // handle the request - if (NT_SUCCESS(status)) - { - switch (ioctl) - { - case IOCTL_DISK_GET_DRIVE_LAYOUT: - *DataLength = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]); - RtlZeroMemory(outputBuffer, *DataLength); - break; - case IOCTL_DISK_GET_DRIVE_LAYOUT_EX: - *DataLength = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]); - RtlZeroMemory(outputBuffer, *DataLength); - break; - case IOCTL_DISK_GET_PARTITION_INFO: - *DataLength = sizeof(PARTITION_INFORMATION); - RtlZeroMemory(outputBuffer, *DataLength); - break; - case IOCTL_DISK_GET_PARTITION_INFO_EX: - *DataLength = sizeof(PARTITION_INFORMATION_EX); - RtlZeroMemory(outputBuffer, *DataLength); - break; - default: - NT_ASSERT(!"Invalid ioctl should not have reached this point\n"); - break; - } - - // if we are getting the drive layout, then we need to start by - // adding some of the non-partition stuff that says we have - // exactly one partition available. - if (ioctl == IOCTL_DISK_GET_DRIVE_LAYOUT) - { - PDRIVE_LAYOUT_INFORMATION layout; - layout = (PDRIVE_LAYOUT_INFORMATION)outputBuffer; - layout->PartitionCount = 1; - layout->Signature = 1; - outputBuffer = (PVOID)(layout->PartitionEntry); - ioctl = IOCTL_DISK_GET_PARTITION_INFO; - } - else if (ioctl == IOCTL_DISK_GET_DRIVE_LAYOUT_EX) - { - PDRIVE_LAYOUT_INFORMATION_EX layoutEx; - layoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)outputBuffer; - layoutEx->PartitionStyle = PARTITION_STYLE_MBR; - layoutEx->PartitionCount = 1; - layoutEx->Mbr.Signature = 1; - outputBuffer = (PVOID)(layoutEx->PartitionEntry); - ioctl = IOCTL_DISK_GET_PARTITION_INFO_EX; - } - - // NOTE: the local var 'ioctl' is now modified to either EX or - // non-EX version. the local var 'systemBuffer' is now pointing - // to the partition information structure. - if (ioctl == IOCTL_DISK_GET_PARTITION_INFO) - { - PPARTITION_INFORMATION partitionInfo; - partitionInfo = (PPARTITION_INFORMATION)outputBuffer; - partitionInfo->RewritePartition = FALSE; - partitionInfo->RecognizedPartition = TRUE; - partitionInfo->PartitionType = PARTITION_FAT32; - partitionInfo->BootIndicator = FALSE; - partitionInfo->HiddenSectors = 0; - partitionInfo->StartingOffset.QuadPart = 0; - partitionInfo->PartitionLength = DeviceExtension->PartitionLength; - partitionInfo->PartitionNumber = 0; - } - else - { - PPARTITION_INFORMATION_EX partitionInfo; - partitionInfo = (PPARTITION_INFORMATION_EX)outputBuffer; - partitionInfo->PartitionStyle = PARTITION_STYLE_MBR; - partitionInfo->RewritePartition = FALSE; - partitionInfo->Mbr.RecognizedPartition = TRUE; - partitionInfo->Mbr.PartitionType = PARTITION_FAT32; - partitionInfo->Mbr.BootIndicator = FALSE; - partitionInfo->Mbr.HiddenSectors = 0; - partitionInfo->StartingOffset.QuadPart = 0; - partitionInfo->PartitionLength = DeviceExtension->PartitionLength; - partitionInfo->PartitionNumber = 0; - } - } - - return status; -} - -NTSTATUS -RequestHandleGetDeviceNumber( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_GET_DEVICE_NUMBER - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - *DataLength = 0; - - if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >= - sizeof(STORAGE_DEVICE_NUMBER)) - { - PSTORAGE_DEVICE_NUMBER deviceNumber = NULL; - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &deviceNumber, - NULL); - if (NT_SUCCESS(status)) - { - deviceNumber->DeviceType = DeviceExtension->DeviceObject->DeviceType; - deviceNumber->DeviceNumber = DeviceExtension->DeviceNumber; - deviceNumber->PartitionNumber = (ULONG)-1; // legacy reason, return (-1) for this IOCTL. - - status = STATUS_SUCCESS; - *DataLength = sizeof(STORAGE_DEVICE_NUMBER); - } - } - else - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(STORAGE_DEVICE_NUMBER); - } - - return status; -} - -NTSTATUS -RequestHandleGetHotPlugInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_GET_HOTPLUG_INFO - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - *DataLength = 0; - - if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >= - sizeof(STORAGE_HOTPLUG_INFO)) - { - PSTORAGE_HOTPLUG_INFO info = NULL; - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &info, - NULL); - if (NT_SUCCESS(status)) - { - *info = DeviceExtension->PrivateFdoData->HotplugInfo; - - status = STATUS_SUCCESS; - *DataLength = sizeof(STORAGE_HOTPLUG_INFO); - } - } - else - { - status = STATUS_BUFFER_TOO_SMALL; - *DataLength = sizeof(STORAGE_HOTPLUG_INFO); - } - - return status; -} - -NTSTATUS -RequestHandleSetHotPlugInfo( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_SET_HOTPLUG_INFO - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSTORAGE_HOTPLUG_INFO info = NULL; - - *DataLength = 0; - - if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(STORAGE_HOTPLUG_INFO)) - { - // Indicate unsuccessful status and no data transferred. - status = STATUS_INFO_LENGTH_MISMATCH; - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &info, - NULL); - } - - if (NT_SUCCESS(status)) - { - if (info->Size != DeviceExtension->PrivateFdoData->HotplugInfo.Size) - { - status = STATUS_INVALID_PARAMETER_1; - } - - if (info->MediaRemovable != DeviceExtension->PrivateFdoData->HotplugInfo.MediaRemovable) - { - status = STATUS_INVALID_PARAMETER_2; - } - - if (info->MediaHotplug != DeviceExtension->PrivateFdoData->HotplugInfo.MediaHotplug) - { - status = STATUS_INVALID_PARAMETER_3; - } - - if (info->WriteCacheEnableOverride != DeviceExtension->PrivateFdoData->HotplugInfo.WriteCacheEnableOverride) - { - status = STATUS_INVALID_PARAMETER_5; - } - } - - if (NT_SUCCESS(status)) - { - DeviceExtension->PrivateFdoData->HotplugInfo.DeviceHotplug = info->DeviceHotplug; - - // Store the user-defined override in the registry - DeviceSetParameter(DeviceExtension, - CLASSP_REG_SUBKEY_NAME, - CLASSP_REG_REMOVAL_POLICY_VALUE_NAME, - (info->DeviceHotplug) ? RemovalPolicyExpectSurpriseRemoval : RemovalPolicyExpectOrderlyRemoval); - } - - return status; -} - -_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 - ) -/*++ - -Routine Description: - - This routine handles the process of IOCTL_STORAGE_EVENT_NOTIFICATION - -Arguments: - - DeviceExtension - device context - - Request - request to be handled - - RequestParameters - request parameter - - DataLength - data transferred - -Return Value: - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PMEDIA_CHANGE_DETECTION_INFO info = NULL; - LONG requestInUse; - PSTORAGE_EVENT_NOTIFICATION eventBuffer = NULL; - - *DataLength = 0; - - info = DeviceExtension->MediaChangeDetectionInfo; - - // Since AN is ASYNCHRONOUS and can happen at any time, - // make certain not to do anything before properly initialized. - if ((!DeviceExtension->IsInitialized) || (info == NULL)) - { - status = STATUS_UNSUCCESSFUL; - } - - if (NT_SUCCESS(status) && (Request != NULL) && (RequestParameters != NULL)) { - - // - // Validate IOCTL parameters - // - if (RequestParameters->Parameters.DeviceIoControl.InputBufferLength < - sizeof(STORAGE_EVENT_NOTIFICATION)) { - status = STATUS_INFO_LENGTH_MISMATCH; - } - - // - // Check for an supported event - // - if (NT_SUCCESS(status)) { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters->Parameters.DeviceIoControl.InputBufferLength, - &eventBuffer, - NULL); - if (NT_SUCCESS(status)) { - if ((eventBuffer->Version != STORAGE_EVENT_NOTIFICATION_VERSION_V1) || - (eventBuffer->Size != sizeof(STORAGE_EVENT_NOTIFICATION))) { - status = STATUS_INVALID_PARAMETER; - } else if ((eventBuffer->Events & - (STORAGE_EVENT_MEDIA_STATUS | STORAGE_EVENT_DEVICE_STATUS | STORAGE_EVENT_DEVICE_OPERATION)) == 0) { - status = STATUS_NOT_SUPPORTED; - } - } - } - - } - - if (NT_SUCCESS(status)) - { - if (info->MediaChangeDetectionDisableCount != 0) - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, - "RequestHandleEventNotification: device %p has detection disabled \n", - DeviceExtension->DeviceObject)); - status = STATUS_UNSUCCESSFUL; - } - } - - if (NT_SUCCESS(status)) - { - // if the request is not in use, mark it as such. - requestInUse = InterlockedCompareExchange((PLONG)&info->MediaChangeRequestInUse, 1, 0); - - if (requestInUse != 0) - { - status = STATUS_UNSUCCESSFUL; - } - } - - if (NT_SUCCESS(status)) - { - // The last MCN finished. ok to issue the new one. - RequestSetupMcnSyncIrp(DeviceExtension); - - // The irp will go into KMDF framework and a request will be created there to represent it. - IoCallDriver(DeviceExtension->DeviceObject, info->MediaChangeSyncIrp); - } - - return status; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -RequestHandleEjectionControl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_MEDIA_REMOVAL - IOCTL_STORAGE_EJECTION_CONTROL - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PPREVENT_MEDIA_REMOVAL mediaRemoval = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - sizeof(PREVENT_MEDIA_REMOVAL)) - { - status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &mediaRemoval, - NULL); - } - - if (NT_SUCCESS(status)) - { - status = PerformEjectionControl(DeviceExtension, - Request, - ((RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_EJECTION_CONTROL) - ? SecureMediaLock - : SimpleMediaLock), - mediaRemoval->PreventMediaRemoval); - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleEnableStreaming( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handles an IOCTL_CDROM_ENABLE_STREAMING request - -Arguments: - - DeviceExtension - device context - Request - request to be handled - DataLength - transferred data length - -Notes: - - This IOCTL is serialized because it changes read/write - behavior and we want to make sure that all previous - reads/writes have been completed before we change the - behavior. - -Return Value: - - NTSTATUS - ---*/ -{ - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PCDROM_PRIVATE_FDO_DATA fdoData = DeviceExtension->PrivateFdoData; - - WDFFILEOBJECT fileObject = NULL; - PFILE_OBJECT_CONTEXT fileObjectContext = NULL; - - NTSTATUS status = STATUS_SUCCESS; - PCDROM_STREAMING_CONTROL inputBuffer = NULL; - - BOOLEAN enforceStreamingRead = FALSE; - BOOLEAN enforceStreamingWrite = FALSE; - BOOLEAN streamingReadSupported, streamingWriteSupported; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(CDROM_STREAMING_CONTROL), - &inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - // get file object context - fileObject = WdfRequestGetFileObject(Request); - if (fileObject != NULL) { - fileObjectContext = FileObjectGetContext(fileObject); - } - NT_ASSERT(fileObjectContext != NULL); - - if (fileObjectContext == NULL) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleEnableStreaming: cannot find file object context\n")); - status = STATUS_INVALID_HANDLE; - } - } - - if (NT_SUCCESS(status)) - { - if (inputBuffer->RequestType == CdromStreamingDisable) - { - enforceStreamingRead = FALSE; - enforceStreamingWrite = FALSE; - } - else if (inputBuffer->RequestType == CdromStreamingEnableForReadOnly) - { - enforceStreamingRead = TRUE; - enforceStreamingWrite = FALSE; - } - else if (inputBuffer->RequestType == CdromStreamingEnableForWriteOnly) - { - enforceStreamingRead = FALSE; - enforceStreamingWrite = TRUE; - } - else if (inputBuffer->RequestType == CdromStreamingEnableForReadWrite) - { - enforceStreamingRead = TRUE; - enforceStreamingWrite = TRUE; - } - - streamingReadSupported = cdData->Mmc.StreamingReadSupported && !TEST_FLAG(fdoData->HackFlags, FDO_HACK_NO_STREAMING); - streamingWriteSupported = cdData->Mmc.StreamingWriteSupported && !TEST_FLAG(fdoData->HackFlags, FDO_HACK_NO_STREAMING); - if ((enforceStreamingRead && !streamingReadSupported) || - (enforceStreamingWrite && !streamingWriteSupported)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "RequestHandleEnableStreaming: requested Streaming mode is not supported\n")); - status = STATUS_INVALID_DEVICE_REQUEST; - } - else - { - fileObjectContext->EnforceStreamingRead = enforceStreamingRead; - fileObjectContext->EnforceStreamingWrite = enforceStreamingWrite; - } - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleSendOpcInformation( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handles an IOCTL_CDROM_SEND_OPC_INFORMATION request - -Arguments: - - DeviceExtension - device context - Request - request to be handled - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_SIMPLE_OPC_INFO inputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - sizeof(CDROM_SIMPLE_OPC_INFO), - (PVOID*)&inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - - // we support only the simplest version for now - cdb.SEND_OPC_INFORMATION.OperationCode = SCSIOP_SEND_OPC_INFORMATION; - cdb.SEND_OPC_INFORMATION.DoOpc = 1; - cdb.SEND_OPC_INFORMATION.Exclude0 = (inputBuffer->Exclude0 ? 1 : 0); - cdb.SEND_OPC_INFORMATION.Exclude1 = (inputBuffer->Exclude1 ? 1 : 0); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, 0, FALSE, &cdb, sizeof(cdb.SEND_OPC_INFORMATION)); - - // nothing to do after the command finishes - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleGetPerformance( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handles an IOCTL_CDROM_GET_PERFORMANCE request - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_PERFORMANCE_REQUEST inputBuffer = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - // Retrieve pointers to input/output data. The size has been validated earlier - // in RequestValidateGetPerformance, so we do not check it again. - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&inputBuffer, - NULL); - } - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - USHORT descriptorSize = 0; - USHORT descriptorCount = 0; - size_t transferSize = 0; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - // Set up the CDB - RtlZeroMemory(&cdb, sizeof(CDB)); - - if (inputBuffer->RequestType == CdromPerformanceRequest) - { - cdb.GET_PERFORMANCE.Type = 0; - - // 10b is the only defined tolerance in MMCr6 - cdb.GET_PERFORMANCE.Tolerance = 2; - - switch (inputBuffer->Exceptions) { - case CdromNominalPerformance: - cdb.GET_PERFORMANCE.Except = 0; - descriptorSize = sizeof(CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR); - break; - case CdromEntirePerformanceList: - cdb.GET_PERFORMANCE.Except = 1; - descriptorSize = sizeof(CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR); - break; - case CdromPerformanceExceptionsOnly: - cdb.GET_PERFORMANCE.Except = 2; - descriptorSize = sizeof(CDROM_EXCEPTION_PERFORMANCE_DESCRIPTOR); - break; - } - - switch (inputBuffer->PerformanceType) { - case CdromReadPerformance: - cdb.GET_PERFORMANCE.Write = 0; break; - case CdromWritePerformance: - cdb.GET_PERFORMANCE.Write = 1; break; - } - - REVERSE_BYTES(&cdb.GET_PERFORMANCE.StartingLBA, &inputBuffer->StaringLba); - } - else if (inputBuffer->RequestType == CdromWriteSpeedRequest) - { - cdb.GET_PERFORMANCE.Type = 3; - descriptorSize = sizeof(CDROM_WRITE_SPEED_DESCRIPTOR); - } - - cdb.GET_PERFORMANCE.OperationCode = SCSIOP_GET_PERFORMANCE; - - // calculate how many descriptors can fit into the output buffer - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >= - sizeof(CDROM_PERFORMANCE_HEADER) && - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <= - MAXUSHORT && - descriptorSize > 0) - { - descriptorCount = (USHORT)(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength - sizeof(CDROM_PERFORMANCE_HEADER)); - descriptorCount /= descriptorSize; - } - else - { - status = STATUS_INVALID_PARAMETER; - } - - REVERSE_BYTES_SHORT(&cdb.GET_PERFORMANCE.MaximumNumberOfDescriptors, &descriptorCount); - - // Calculate transfer size. We round it up to meet adapter requirements. - // Extra bytes are discarded later, when we copy data to the output buffer. - transferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength; - transferSize += DeviceExtension->AdapterDescriptor->AlignmentMask; - transferSize &= ~DeviceExtension->AdapterDescriptor->AlignmentMask; - - if (NT_SUCCESS(status)) - { - status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, Request, (ULONG)transferSize, TRUE, &cdb, sizeof(cdb.GET_PERFORMANCE), CDROM_GET_PERFORMANCE_TIMEOUT); - } - - if (NT_SUCCESS(status)) - { - if (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength < sizeof(CDROM_PERFORMANCE_HEADER)) - { - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - else - { - *DataLength = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength); - RtlCopyMemory(outputBuffer, - DeviceExtension->ScratchContext.ScratchBuffer, - *DataLength); - } - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleMcnSyncFakeIoctl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handles an IOCTL_MCN_SYNC_FAKE_IOCTL request - -Arguments: - - DeviceExtension - device context - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo; - BOOLEAN shouldRetry = TRUE; - BOOLEAN requestSent = FALSE; - - PAGED_CODE (); - - *DataLength = 0; - - // - // Try to acquire the media change event. If we can't do it immediately - // then bail out and assume the caller will try again later. - // - while (shouldRetry) - { - status = RequestSetupMcnRequest(DeviceExtension, - info->Gesn.Supported); - - if (!NT_SUCCESS(status)) - { - shouldRetry = FALSE; - } - - if (NT_SUCCESS(status)) - { - requestSent = RequestSendMcnRequest(DeviceExtension); - - if (requestSent) - { - shouldRetry = RequestPostWorkMcnRequest(DeviceExtension); - } - else - { - shouldRetry = FALSE; - } - } - } - - // If there were any media change notifications that were not delivered - // for some reason, make an attempt to do so at this time. - DeviceSendDelayedMediaChangeNotifications(DeviceExtension); - - // Set the status and then complete the original request. - // The timer handler will be able to send the next request. - status = STATUS_SUCCESS; - - return status; -} - -BOOLEAN -RequestIsRealtimeStreaming( - _In_ WDFREQUEST Request, - _In_ BOOLEAN IsReadRequest - ) -/*++ - -Routine Description: - - Checks whether a given read/write request should - be performed in Real-Time Streaming mode. - -Arguments: - - Request - request to be checked - IsReadRequest - TRUE = read request; FALSE = write request - -Return Value: - - TRUE - a Real-Time Streaming operation has to be performed - FALSE - a normal (non-Streaming) operation has to be performed - ---*/ -{ - BOOLEAN useStreaming = FALSE; - - if (!useStreaming) { - // - // Check if we're required to use Streaming via I/O Stack Location flags - // - UCHAR currentStackLocationFlags = 0; - currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request); - - useStreaming = TEST_FLAG(currentStackLocationFlags, SL_REALTIME_STREAM); - } - - if (!useStreaming) { - // - // Check if we were previously requested to enforce Streaming for - // the file handle through which this request was sent. - // - - WDFFILEOBJECT fileObject; - PFILE_OBJECT_CONTEXT fileObjectContext; - - fileObject = WdfRequestGetFileObject(Request); - - if (fileObject != NULL) { - fileObjectContext = FileObjectGetContext(fileObject); - NT_ASSERT(fileObjectContext != NULL); - - if (IsReadRequest && fileObjectContext->EnforceStreamingRead) - { - useStreaming = TRUE; - } - - if (!IsReadRequest && fileObjectContext->EnforceStreamingWrite) - { - useStreaming = TRUE; - } - } - } - - return useStreaming; -} - - -NTSTATUS -RequestValidateReadWrite( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters - ) -/*++ - -Routine Description: - - Validate Read/Write request - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - - BOOLEAN isValid = TRUE; - LONGLONG startingOffset = 0; - size_t transferByteCount = 0; - PIRP irp = NULL; - PIO_STACK_LOCATION currentStack = NULL; - - irp = WdfRequestWdmGetIrp(Request); - currentStack = IoGetCurrentIrpStackLocation(irp); - - if (TEST_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME) && - (currentStack->MinorFunction != CDROM_VOLUME_VERIFY_CHECKED) && - !TEST_FLAG(currentStack->Flags, SL_OVERRIDE_VERIFY_VOLUME)) - { - // DO_VERIFY_VOLUME is set for the device object, - // but this request is not itself a verify request. - // So fail this request. - - //set the status for volume verification. - status = STATUS_VERIFY_REQUIRED; - } - - if (NT_SUCCESS(status)) - { - if (PLAY_ACTIVE(DeviceExtension)) - { - status = STATUS_DEVICE_BUSY; - } - } - - if (NT_SUCCESS(status)) - { - // If the device is in exclusive mode, check whether the request is from - // the handle that locked the device. - if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request))) - { - // This request is not from the owner. We can't let the operation go. - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "RequestValidateReadWrite: Access Denied! Device in exclusive mode.\n")); - - status = STATUS_ACCESS_DENIED; - } - } - - // Validate the request alignment. - if (NT_SUCCESS(status)) - { - if (RequestParameters.Type == WdfRequestTypeRead) - { - startingOffset = RequestParameters.Parameters.Read.DeviceOffset; - transferByteCount = RequestParameters.Parameters.Read.Length; - } - else - { - startingOffset = RequestParameters.Parameters.Write.DeviceOffset; - transferByteCount = RequestParameters.Parameters.Write.Length; - } - - if (!DeviceExtension->DiskGeometry.BytesPerSector) - { - DeviceExtension->DiskGeometry.BytesPerSector = 2048; - } - - if (!DeviceExtension->SectorShift) - { - DeviceExtension->SectorShift = 11; - } - - // Perform some basic validation up front - if (TEST_FLAG(startingOffset, DeviceExtension->DiskGeometry.BytesPerSector - 1) || - TEST_FLAG(transferByteCount, DeviceExtension->DiskGeometry.BytesPerSector - 1)) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - - // validate the request against the current mmc schema - if (NT_SUCCESS(status)) - { - FEATURE_NUMBER schema = cdData->Mmc.ValidationSchema; - - // We validate read requests according to the RandomWritable schema, except in the - // case of IncrementalStreamingWritable, wherein the drive is responsible for all - // of the verification - if (RequestParameters.Type == WdfRequestTypeRead) - { - if (!cdData->Mmc.WriteAllowed) - { - // standard legacy validation of read irps - // if writing is not allowed on the media - schema = FeatureRandomWritable; - } - else if (schema != FeatureIncrementalStreamingWritable) - { - // standard legacy validation of read irps - // if not using streaming writes on writable media - schema = FeatureRandomWritable; - } - } - - // Fail write requests to read-only media - if ((RequestParameters.Type == WdfRequestTypeWrite) && - !(cdData->Mmc.WriteAllowed)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "RequestValidateReadWrite: Write request to read-only media\n")); - isValid = FALSE; - } - - if (isValid) - { - switch (schema) - { - case FeatureDefectManagement: - case FeatureRandomWritable: - // Ensure that the request is within bounds for ROM drives. - // Writer drives do not need to have bounds as outbounds request should not damage the drive. - if(!cdData->Mmc.IsWriter) - { - if ((startingOffset >= DeviceExtension->PartitionLength.QuadPart) || - startingOffset < 0) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "RequestValidateReadWrite: Request is out of bounds\n")); - isValid = FALSE; - - } - else - { - ULONGLONG bytesRemaining = DeviceExtension->PartitionLength.QuadPart - startingOffset; - - if ((ULONGLONG)transferByteCount > bytesRemaining) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "RequestValidateReadWrite: Request is out of bounds\n")); - isValid = FALSE; - } - } - } - break; - - case FeatureRigidRestrictedOverwrite: - // Ensure that the number of blocks is a multiple of the blocking size - if (((transferByteCount >> DeviceExtension->SectorShift) % cdData->Mmc.Blocking) != 0) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, - "RequestValidateReadWrite: Number of blocks is not a multiple of the blocking size (%x)\n", - cdData->Mmc.Blocking)); - - isValid = FALSE; - } - // Fall through - case FeatureRestrictedOverwrite: - // Ensure that the request begins on a blocking boundary - if ((Int64ShrlMod32(startingOffset, DeviceExtension->SectorShift) % cdData->Mmc.Blocking) != 0) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, - "RequestValidateReadWrite: Starting block is not a multiple of the blocking size (%x)\n", - cdData->Mmc.Blocking)); - - isValid = FALSE; - } - break; - - case FeatureIncrementalStreamingWritable: - // Let the drive handle the verification - break; - - default: - // Unknown schema. Fail the request - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, - "RequestValidateReadWrite: Unknown validation schema (%x)\n", - schema)); - - isValid = FALSE; - break; - } //end of switch (schema) - } // end of if (isValid) - - if (!isValid) - { - status = STATUS_INVALID_DEVICE_REQUEST; - } - } // end of mmc schema validation - - // validate that the Real-Time Streaming requests meet device capabilties - if (NT_SUCCESS(status)) - { - // We do not check for FDO_HACK_NO_STREAMING in DeviceExtension->PrivateFdoData->HackFlags here, - // because we're going to hide device failures related to streaming reads/writes from the sender - // of the request. FDO_HACK_NO_STREAMING is going to be taken into account later during actual - // processing of the request. - if (RequestIsRealtimeStreaming(Request, RequestParameters.Type == WdfRequestTypeRead)) - { - if (RequestParameters.Type == WdfRequestTypeRead && !cdData->Mmc.StreamingReadSupported) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, - "RequestValidateReadWrite: Streaming reads are not supported.\n")); - - status = STATUS_INVALID_DEVICE_REQUEST; - } - if (RequestParameters.Type == WdfRequestTypeWrite && !cdData->Mmc.StreamingWriteSupported) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, - "RequestValidateReadWrite: Streaming writes are not supported.\n")); - - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - } - - return status; -} - -NTSTATUS -RequestHandleReadWrite( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters - ) -/*++ - -Routine Description: - - Handle a read/write request - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - - size_t transferByteCount = 0; - PIRP irp = NULL; - PIO_STACK_LOCATION currentStack = NULL; - - PUCHAR dataBuffer; - - - irp = WdfRequestWdmGetIrp(Request); - currentStack = IoGetCurrentIrpStackLocation(irp); - dataBuffer = MmGetMdlVirtualAddress(irp->MdlAddress); - - if (NT_SUCCESS(status)) - { - if (RequestParameters.Type == WdfRequestTypeRead) - { - transferByteCount = RequestParameters.Parameters.Read.Length; - } - else - { - transferByteCount = RequestParameters.Parameters.Write.Length; - } - - if (transferByteCount == 0) - { - // Several parts of the code turn 0 into 0xffffffff, - // so don't process a zero-length request any further. - status = STATUS_SUCCESS; - RequestCompletion(DeviceExtension, Request, status, 0); - return status; - } - - // Add partition byte offset to make starting byte relative to - // beginning of disk. - currentStack->Parameters.Read.ByteOffset.QuadPart += (DeviceExtension->StartingOffset.QuadPart); - - //not very necessary as the starting offset for CD/DVD device is always 0. - if (RequestParameters.Type == WdfRequestTypeRead) - { - RequestParameters.Parameters.Read.DeviceOffset = currentStack->Parameters.Read.ByteOffset.QuadPart; - } - else - { - RequestParameters.Parameters.Write.DeviceOffset = currentStack->Parameters.Write.ByteOffset.QuadPart; - } - } - - if (NT_SUCCESS(status)) - { - ULONG entireXferLen = currentStack->Parameters.Read.Length; - ULONG maxLength = 0; - ULONG packetsCount = 0; - - PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext; - PCDROM_REQUEST_CONTEXT requestContext; - PCDROM_REQUEST_CONTEXT originalRequestContext; - - // get the count of packets we need to send. - if ((((ULONG_PTR)dataBuffer) & (PAGE_SIZE-1)) == 0) - { - maxLength = cdData->MaxPageAlignedTransferBytes; - } - else - { - maxLength = cdData->MaxUnalignedTransferBytes; - } - - packetsCount = entireXferLen / maxLength; - - if (entireXferLen % maxLength != 0) - { - packetsCount++; - } - - originalRequestContext = RequestGetContext(Request); - - - ScratchBuffer_BeginUse(DeviceExtension); - - readWriteContext = &DeviceExtension->ScratchContext.ScratchReadWriteContext; - requestContext = RequestGetContext(DeviceExtension->ScratchContext.ScratchRequest); - - readWriteContext->PacketsCount = packetsCount; - readWriteContext->EntireXferLen = entireXferLen; - readWriteContext->MaxLength = maxLength; - readWriteContext->StartingOffset = currentStack->Parameters.Read.ByteOffset; - readWriteContext->DataBuffer = dataBuffer; - readWriteContext->TransferedBytes = 0; - readWriteContext->IsRead = (RequestParameters.Type == WdfRequestTypeRead); - - requestContext->OriginalRequest = Request; - requestContext->DeviceExtension = DeviceExtension; - - // - // Setup the READ/WRITE fields in the original request which is what - // we use to properly synchronize cancellation logic between the - // cancel callback and the timer routine. - // - - originalRequestContext->ReadWriteIsCompleted = FALSE; - originalRequestContext->ReadWriteRetryInitialized = FALSE; - originalRequestContext->DeviceExtension = DeviceExtension; - - status = ScratchBuffer_PerformNextReadWrite(DeviceExtension, TRUE); - - // We do not call ScratchBuffer_EndUse here, because we're not releasing the scratch SRB. - // It will be released in the completion routine. - } - - return status; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -RequestHandleLoadEjectMedia( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_EJECT_MEDIA - IOCTL_STORAGE_LOAD_MEDIA - IOCTL_STORAGE_LOAD_MEDIA2 - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo; - - PAGED_CODE (); - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - // Synchronize with ejection control and ejection cleanup code as - // well as other eject/load requests. - WdfWaitLockAcquire(DeviceExtension->EjectSynchronizationLock, NULL); - - if(DeviceExtension->ProtectedLockCount != 0) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "RequestHandleLoadEjectMedia: call to eject protected locked " - "device - failure\n")); - status = STATUS_DEVICE_BUSY; - } - - if (NT_SUCCESS(status)) - { - SCSI_REQUEST_BLOCK srb; - PCDB cdb = (PCDB)srb.Cdb; - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - srb.CdbLength = 6; - - cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; - cdb->START_STOP.LoadEject = 1; - - if(RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_EJECT_MEDIA) - { - cdb->START_STOP.Start = 0; - - // We are sending down a soft eject, and in this case we should take an active ref - // if the command succeeds. - if ((zpoddInfo != NULL) && - (zpoddInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) && - (zpoddInfo->Load == 0)) // Drawer - { - zpoddInfo->MonitorStartStopUnit = TRUE; - } - } - else - { - cdb->START_STOP.Start = 1; - } - - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - &srb, - NULL, - 0, - FALSE, - Request); - - if (zpoddInfo != NULL) - { - zpoddInfo->MonitorStartStopUnit = FALSE; - } - } - - WdfWaitLockRelease(DeviceExtension->EjectSynchronizationLock); - } - - return status; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -RequestHandleReserveRelease( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_RESERVE - IOCTL_STORAGE_RELEASE - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSCSI_REQUEST_BLOCK srb = NULL; - PCDB cdb = NULL; - ULONG ioctlCode = 0; - - PAGED_CODE (); - - *DataLength = 0; - - srb = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(SCSI_REQUEST_BLOCK) + - (sizeof(ULONG_PTR) * 2), - CDROM_TAG_SRB); - - if (srb == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - - if (NT_SUCCESS(status)) - { - ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode; - cdb = (PCDB)srb->Cdb; - - if (TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6)) - { - srb->CdbLength = 10; - cdb->CDB10.OperationCode = (ioctlCode == IOCTL_STORAGE_RESERVE) ? SCSIOP_RESERVE_UNIT10 : SCSIOP_RELEASE_UNIT10; - } - else - { - srb->CdbLength = 6; - cdb->CDB6GENERIC.OperationCode = (ioctlCode == IOCTL_STORAGE_RESERVE) ? SCSIOP_RESERVE_UNIT : SCSIOP_RELEASE_UNIT; - } - - // Set timeout value. - srb->TimeOutValue = DeviceExtension->TimeOutValue; - - // Send reserves as tagged requests. - if (ioctlCode == IOCTL_STORAGE_RESERVE) - { - SET_FLAG(srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE); - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - } - - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - srb, - NULL, - 0, - FALSE, - Request); - // no data transfer. - *DataLength = 0; - - FREE_POOL(srb); - } - - return status; -} // end RequestHandleReserveRelease() - -__inline -BOOLEAN -ValidPersistentReserveScope( - UCHAR Scope) -{ - switch (Scope) { - case RESERVATION_SCOPE_LU: - case RESERVATION_SCOPE_ELEMENT: - - return TRUE; - - default: - - return FALSE; - } -} - -__inline -BOOLEAN -ValidPersistentReserveType( - UCHAR Type) -{ - switch (Type) { - case RESERVATION_TYPE_WRITE_EXCLUSIVE: - case RESERVATION_TYPE_EXCLUSIVE: - case RESERVATION_TYPE_WRITE_EXCLUSIVE_REGISTRANTS: - case RESERVATION_TYPE_EXCLUSIVE_REGISTRANTS: - - return TRUE; - - default: - - return FALSE; - } -} - -NTSTATUS -RequestValidatePersistentReserve( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Validate request of IOCTL_STORAGE_PERSISTENT_RESERVE_IN - IOCTL_STORAGE_PERSISTENT_RESERVE_OUT - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode; - - PPERSISTENT_RESERVE_COMMAND reserveCommand = NULL; - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&reserveCommand, - NULL); - if (NT_SUCCESS(status)) - { - if ((RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(PERSISTENT_RESERVE_COMMAND)) || - (reserveCommand->Size < sizeof(PERSISTENT_RESERVE_COMMAND))) - { - *DataLength = 0; - status = STATUS_INFO_LENGTH_MISMATCH; - } - else if ((ULONG_PTR)reserveCommand & DeviceExtension->AdapterDescriptor->AlignmentMask) - { - // Check buffer alignment. Only an issue if another kernel mode component - // (not the I/O manager) allocates the buffer. - *DataLength = 0; - status = STATUS_INVALID_USER_BUFFER; - } - } - - if (NT_SUCCESS(status)) - { - if (ioctlCode == IOCTL_STORAGE_PERSISTENT_RESERVE_IN) - { - if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < reserveCommand->PR_IN.AllocationLength) - { - *DataLength = 0; - status = STATUS_INVALID_PARAMETER; - } - else - { - switch (reserveCommand->PR_IN.ServiceAction) - { - case RESERVATION_ACTION_READ_KEYS: - if (reserveCommand->PR_IN.AllocationLength < sizeof(PRI_REGISTRATION_LIST)) - { - *DataLength = 0; - status = STATUS_INVALID_PARAMETER; - } - break; - - case RESERVATION_ACTION_READ_RESERVATIONS: - if (reserveCommand->PR_IN.AllocationLength < sizeof(PRI_RESERVATION_LIST)) - { - *DataLength = 0; - status = STATUS_INVALID_PARAMETER; - } - break; - - default: - *DataLength = 0; - status = STATUS_INVALID_PARAMETER; - break; - } - } - } - else // case of IOCTL_STORAGE_PERSISTENT_RESERVE_OUT - { - // Verify ServiceAction, Scope, and Type - switch (reserveCommand->PR_OUT.ServiceAction) - { - case RESERVATION_ACTION_REGISTER: - case RESERVATION_ACTION_REGISTER_IGNORE_EXISTING: - case RESERVATION_ACTION_CLEAR: - // Scope and type ignored. - break; - - case RESERVATION_ACTION_RESERVE: - case RESERVATION_ACTION_RELEASE: - case RESERVATION_ACTION_PREEMPT: - case RESERVATION_ACTION_PREEMPT_ABORT: - if (!ValidPersistentReserveScope(reserveCommand->PR_OUT.Scope) || - !ValidPersistentReserveType(reserveCommand->PR_OUT.Type)) - { - *DataLength = 0; - status = STATUS_INVALID_PARAMETER; - } - break; - - default: - *DataLength = 0; - status = STATUS_INVALID_PARAMETER; - break; - } - - // Check input buffer for PR Out. - // Caller must include the PR parameter list. - if (NT_SUCCESS(status)) - { - if ((RequestParameters.Parameters.DeviceIoControl.InputBufferLength < - (sizeof(PERSISTENT_RESERVE_COMMAND) + sizeof(PRO_PARAMETER_LIST))) || - (reserveCommand->Size < RequestParameters.Parameters.DeviceIoControl.InputBufferLength)) - { - *DataLength = 0; - status = STATUS_INVALID_PARAMETER; - } - } - } // end of validation for IOCTL_STORAGE_PERSISTENT_RESERVE_OUT - } - - return status; -} // end RequestValidatePersistentReserve() - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -RequestHandlePersistentReserve( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_PERSISTENT_RESERVE_IN - IOCTL_STORAGE_PERSISTENT_RESERVE_OUT - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode; - PSCSI_REQUEST_BLOCK srb = NULL; - PCDB cdb = NULL; - BOOLEAN writeToDevice; - - PPERSISTENT_RESERVE_COMMAND reserveCommand = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&reserveCommand, - NULL); - if (NT_SUCCESS(status)) - { - srb = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(SCSI_REQUEST_BLOCK) + - (sizeof(ULONG_PTR) * 2), - CDROM_TAG_SRB); - - if (srb == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - cdb = (PCDB)srb->Cdb; - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - } - } - - if (NT_SUCCESS(status)) - { - size_t dataBufLen = 0; - - // Fill in the CDB. - if (ioctlCode == IOCTL_STORAGE_PERSISTENT_RESERVE_IN) - { - cdb->PERSISTENT_RESERVE_IN.OperationCode = SCSIOP_PERSISTENT_RESERVE_IN; - cdb->PERSISTENT_RESERVE_IN.ServiceAction = reserveCommand->PR_IN.ServiceAction; - - REVERSE_BYTES_SHORT(&(cdb->PERSISTENT_RESERVE_IN.AllocationLength), - &(reserveCommand->PR_IN.AllocationLength)); - - dataBufLen = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength; - writeToDevice = FALSE; - } - else - { - cdb->PERSISTENT_RESERVE_OUT.OperationCode = SCSIOP_PERSISTENT_RESERVE_OUT; - cdb->PERSISTENT_RESERVE_OUT.ServiceAction = reserveCommand->PR_OUT.ServiceAction; - cdb->PERSISTENT_RESERVE_OUT.Scope = reserveCommand->PR_OUT.Scope; - cdb->PERSISTENT_RESERVE_OUT.Type = reserveCommand->PR_OUT.Type; - - cdb->PERSISTENT_RESERVE_OUT.ParameterListLength[1] = (UCHAR)sizeof(PRO_PARAMETER_LIST); - - // Move the parameter list to the beginning of the data buffer (so it is aligned - // correctly and that the MDL describes it correctly). - RtlMoveMemory(reserveCommand, - reserveCommand->PR_OUT.ParameterList, - sizeof(PRO_PARAMETER_LIST)); - - dataBufLen = sizeof(PRO_PARAMETER_LIST); - writeToDevice = TRUE; - } - - srb->CdbLength = 10; - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - - status = DeviceSendSrbSynchronously(DeviceExtension->Device, - srb, - reserveCommand, - (ULONG) dataBufLen, - writeToDevice, - Request); - - FREE_POOL(srb); - } - - return status; -} - -#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 - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DISK_ARE_VOLUMES_READY - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - BOOLEAN completeRequest = TRUE; - NTSTATUS status = STATUS_SUCCESS; - - UNREFERENCED_PARAMETER(RequestParameters); - - *DataLength = 0; - - if (DeviceExtension->IsVolumeOnlinePending == FALSE) - { - status = STATUS_SUCCESS; - goto Cleanup; - } - - // - // Add to the volume ready queue. No worries about request cancellation, - // since KMDF will automatically handle that while request is in queue. - // - status = WdfRequestForwardToIoQueue(Request, - DeviceExtension->ManualVolumeReadyQueue - ); - - if(!NT_SUCCESS(status)) - { - goto Cleanup; - } - - status = STATUS_PENDING; - completeRequest = FALSE; - -Cleanup: - - if (completeRequest) - { - RequestCompletion(DeviceExtension, Request, status, 0); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -RequestHandleVolumeOnline( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_VOLUME_ONLINE / IOCTL_VOLUME_POST_ONLINE - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDFREQUEST request; - PIRP irp = NULL; - PIO_STACK_LOCATION nextStack = NULL; - - UNREFERENCED_PARAMETER(RequestParameters); - - *DataLength = 0; - - DeviceExtension->IsVolumeOnlinePending = FALSE; - - // Complete all parked volume ready requests. - for (;;) - { - status = WdfIoQueueRetrieveNextRequest(DeviceExtension->ManualVolumeReadyQueue, - &request); - - if (!NT_SUCCESS(status)) - { - break; - } - - RequestCompletion(DeviceExtension, request, STATUS_SUCCESS, 0); - } - - // Change the IOCTL code to IOCTL_DISK_VOLUMES_ARE_READY, and forward the request down, - // so that if the underlying port driver will also know that volume is ready. - WdfRequestFormatRequestUsingCurrentType(Request); - irp = WdfRequestWdmGetIrp(Request); - nextStack = IoGetNextIrpStackLocation(irp); - - irp->AssociatedIrp.SystemBuffer = &DeviceExtension->DeviceNumber; - nextStack->Parameters.DeviceIoControl.OutputBufferLength = 0; - nextStack->Parameters.DeviceIoControl.InputBufferLength = sizeof (DeviceExtension->DeviceNumber); - nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_DISK_VOLUMES_ARE_READY; - - // Send the request straight down (synchronously). - RequestSend(DeviceExtension, - Request, - DeviceExtension->IoTarget, - WDF_REQUEST_SEND_OPTION_SYNCHRONOUS, - NULL); - - return STATUS_SUCCESS; -} -#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 - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_RAW_READ - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - // Determine whether the drive is currently in raw or cooked mode, - // and which command to use to read the data. - - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - RAW_READ_INFO rawReadInfo = {0}; - PVOID outputVirtAddr = NULL; - ULONG startingSector; - - PIRP irp = WdfRequestWdmGetIrp(Request); - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(irp); - - VOID* outputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - if (TEST_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME) && - (currentIrpStack->MinorFunction != CDROM_VOLUME_VERIFY_CHECKED) && - !TEST_FLAG(currentIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME)) - { - // DO_VERIFY_VOLUME is set for the device object, - // but this request is not itself a verify request. - // So fail this request. - (VOID) MediaReadCapacity(DeviceExtension->Device); - - *DataLength = 0; - //set the status for volume verification. - status = STATUS_VERIFY_REQUIRED; - } - - if (NT_SUCCESS(status)) - { - // Since this ioctl is METHOD_OUT_DIRECT, we need to copy away - // the input buffer before interpreting it. This prevents a - // malicious app from messing with the input buffer while we - // are interpreting it. This is done in dispacth. - // - // Here, we are going to get the input buffer out of saved place. - rawReadInfo = *(PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; - - if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength > 0) - { - // Make sure that any user buffer that we pass down to - // the hardware is properly aligned - NT_ASSERT(irp->MdlAddress); - outputVirtAddr = MmGetMdlVirtualAddress(irp->MdlAddress); - if ((ULONG_PTR)outputVirtAddr & DeviceExtension->AdapterDescriptor->AlignmentMask) - { - NT_ASSERT(!((ULONG_PTR)outputVirtAddr & DeviceExtension->AdapterDescriptor->AlignmentMask)); - *DataLength = 0; - status = STATUS_INVALID_PARAMETER; - } - } - else - { - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - switch (rawReadInfo.TrackMode) - { - case CDDA: - case YellowMode2: - case XAForm2: - // no check needed. - break; - - case RawWithC2AndSubCode: - if (!cdData->Mmc.ReadCdC2Pointers || !cdData->Mmc.ReadCdSubCode) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "Request to read C2 & Subcode rejected. " - "Is C2 supported: %d Is Subcode supported: %d\n", - cdData->Mmc.ReadCdC2Pointers, - cdData->Mmc.ReadCdSubCode - )); - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - break; - case RawWithC2: - if (!cdData->Mmc.ReadCdC2Pointers) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "Request to read C2 rejected because drive does not " - "report support for C2 pointers\n" - )); - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - break; - case RawWithSubCode: - - if (!cdData->Mmc.ReadCdSubCode) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "Request to read subcode rejected because drive does " - "not report support for reading the subcode data\n" - )); - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - break; - - default: - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - } - - if (NT_SUCCESS(status)) - { - PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb; - PCDB cdb = (PCDB)(srb->Cdb); - - size_t transferByteCount; - BOOLEAN shouldRetry = TRUE; - ULONG timesAlreadyRetried = 0; - LONGLONG retryIn100nsUnits = 0; - - transferByteCount = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength; - - ScratchBuffer_BeginUse(DeviceExtension); - - while (shouldRetry) - { - // Setup cdb depending upon the sector type we want. - switch (rawReadInfo.TrackMode) - { - case CDDA: - transferByteCount = rawReadInfo.SectorCount * RAW_SECTOR_SIZE; - cdb->READ_CD.ExpectedSectorType = CD_DA_SECTOR; - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 3; - cdb->READ_CD.IncludeSyncData = 1; - break; - - case YellowMode2: - transferByteCount = rawReadInfo.SectorCount * RAW_SECTOR_SIZE; - cdb->READ_CD.ExpectedSectorType = YELLOW_MODE2_SECTOR; - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 1; - cdb->READ_CD.IncludeSyncData = 1; - break; - - case XAForm2: - transferByteCount = rawReadInfo.SectorCount * RAW_SECTOR_SIZE; - cdb->READ_CD.ExpectedSectorType = FORM2_MODE2_SECTOR; - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 3; - cdb->READ_CD.IncludeSyncData = 1; - break; - - case RawWithC2AndSubCode: - transferByteCount = rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_C2_AND_SUBCODE_SIZE; - cdb->READ_CD.ExpectedSectorType = 0; // Any sector type - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 3; // Header and subheader returned - cdb->READ_CD.IncludeSyncData = 1; - cdb->READ_CD.ErrorFlags = 2; // C2 and block error - cdb->READ_CD.SubChannelSelection = 1; // raw subchannel data - break; - - case RawWithC2: - transferByteCount = rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_C2_SIZE; - cdb->READ_CD.ExpectedSectorType = 0; // Any sector type - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 3; // Header and subheader returned - cdb->READ_CD.IncludeSyncData = 1; - cdb->READ_CD.ErrorFlags = 2; // C2 and block error - break; - - case RawWithSubCode: - transferByteCount = rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_SUBCODE_SIZE; - cdb->READ_CD.ExpectedSectorType = 0; // Any sector type - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 3; // Header and subheader returned - cdb->READ_CD.IncludeSyncData = 1; - cdb->READ_CD.SubChannelSelection = 1; // raw subchannel data - break; - - default: - // should already checked before coming in loop. - NT_ASSERT(FALSE); - break; - } - - ScratchBuffer_SetupSrb(DeviceExtension, Request, (ULONG)transferByteCount, TRUE); - // Restore the buffer, buffer size and MdlAddress. They got changed but we don't want to use the scratch buffer. - { - PIRP scratchIrp = WdfRequestWdmGetIrp(DeviceExtension->ScratchContext.ScratchRequest); - scratchIrp->MdlAddress = irp->MdlAddress; - srb->DataBuffer = outputVirtAddr; - srb->DataTransferLength = (ULONG)transferByteCount; - } - // Calculate starting offset. - startingSector = (ULONG)(rawReadInfo.DiskOffset.QuadPart >> DeviceExtension->SectorShift); - - // Fill in CDB fields. - srb->CdbLength = 12; - - cdb->READ_CD.OperationCode = SCSIOP_READ_CD; - cdb->READ_CD.TransferBlocks[2] = (UCHAR) (rawReadInfo.SectorCount & 0xFF); - cdb->READ_CD.TransferBlocks[1] = (UCHAR) (rawReadInfo.SectorCount >> 8 ); - cdb->READ_CD.TransferBlocks[0] = (UCHAR) (rawReadInfo.SectorCount >> 16); - - cdb->READ_CD.StartingLBA[3] = (UCHAR) (startingSector & 0xFF); - cdb->READ_CD.StartingLBA[2] = (UCHAR) ((startingSector >> 8)); - cdb->READ_CD.StartingLBA[1] = (UCHAR) ((startingSector >> 16)); - cdb->READ_CD.StartingLBA[0] = (UCHAR) ((startingSector >> 24)); - - ScratchBuffer_SendSrb(DeviceExtension, TRUE, NULL); - - if ((DeviceExtension->ScratchContext.ScratchSrb->SrbStatus == SRB_STATUS_ABORTED) && - (DeviceExtension->ScratchContext.ScratchSrb->InternalStatus == STATUS_CANCELLED)) - { - shouldRetry = FALSE; - status = STATUS_CANCELLED; - } - else - { - shouldRetry = RequestSenseInfoInterpretForScratchBuffer(DeviceExtension, - timesAlreadyRetried, - &status, - &retryIn100nsUnits); - if (shouldRetry) - { - LARGE_INTEGER t; - t.QuadPart = -retryIn100nsUnits; - timesAlreadyRetried++; - KeDelayExecutionThread(KernelMode, FALSE, &t); - // keep items clean - ScratchBuffer_ResetItems(DeviceExtension, FALSE); - } - } - } - - if (NT_SUCCESS(status)) - { - *DataLength = srb->DataTransferLength; - } - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandlePlayAudioMsf( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_PLAY_AUDIO_MSF - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_PLAY_AUDIO_MSF inputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&inputBuffer, - NULL); - - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF; - - cdb.PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM; - cdb.PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS; - cdb.PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF; - - cdb.PLAY_AUDIO_MSF.EndingM = inputBuffer->EndingM; - cdb.PLAY_AUDIO_MSF.EndingS = inputBuffer->EndingS; - cdb.PLAY_AUDIO_MSF.EndingF = inputBuffer->EndingF; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 10); - - if (NT_SUCCESS(status)) - { - PLAY_ACTIVE(DeviceExtension) = TRUE; - *DataLength = 0; - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleReadQChannel( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_READ_Q_CHANNEL - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PVOID inputBuffer = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - status = ReadQChannel(DeviceExtension, - Request, - inputBuffer, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - outputBuffer, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - DataLength); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -ReadQChannel( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ WDFREQUEST OriginalRequest, - _In_ PVOID InputBuffer, - _In_ size_t InputBufferLength, - _In_ PVOID OutputBuffer, - _In_ size_t OutputBufferLength, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - base function to handle request of IOCTL_CDROM_READ_Q_CHANNEL - -Arguments: - - DeviceExtension - device context - OriginalRequest - original request to be handled - InputBuffer - input buffer - InputBufferLength - length of input buffer - OutputBuffer - output buffer - OutputBufferLength - length of output buffer - -Return Value: - - NTSTATUS - DataLength - returned data length - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - ULONG transferByteCount = 0; - CDB cdb; - PCDROM_SUB_Q_DATA_FORMAT inputBuffer = (PCDROM_SUB_Q_DATA_FORMAT)InputBuffer; - PSUB_Q_CHANNEL_DATA userChannelData = (PSUB_Q_CHANNEL_DATA)OutputBuffer; - - PAGED_CODE (); - - UNREFERENCED_PARAMETER(InputBufferLength); - - *DataLength = 0; - - // Set size of channel data -- however, this is dependent on - // what information we are requesting (which Format) - switch( inputBuffer->Format ) - { - case IOCTL_CDROM_CURRENT_POSITION: - transferByteCount = sizeof(SUB_Q_CURRENT_POSITION); - break; - - case IOCTL_CDROM_MEDIA_CATALOG: - transferByteCount = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER); - break; - - case IOCTL_CDROM_TRACK_ISRC: - transferByteCount = sizeof(SUB_Q_TRACK_ISRC); - break; - } - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - // Always logical unit 0, but only use MSF addressing - // for IOCTL_CDROM_CURRENT_POSITION - if (inputBuffer->Format==IOCTL_CDROM_CURRENT_POSITION) - { - cdb.SUBCHANNEL.Msf = CDB_USE_MSF; - } - - // Return subchannel data - cdb.SUBCHANNEL.SubQ = CDB_SUBCHANNEL_BLOCK; - - // Specify format of informatin to return - cdb.SUBCHANNEL.Format = inputBuffer->Format; - - // Specify which track to access (only used by Track ISRC reads) - if (inputBuffer->Format==IOCTL_CDROM_TRACK_ISRC) - { - cdb.SUBCHANNEL.TrackNumber = inputBuffer->Track; - } - - cdb.SUBCHANNEL.AllocationLength[0] = (UCHAR) (transferByteCount >> 8); - cdb.SUBCHANNEL.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF); - cdb.SUBCHANNEL.OperationCode = SCSIOP_READ_SUB_CHANNEL; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, OriginalRequest, transferByteCount, TRUE, &cdb, 10); - - if (NT_SUCCESS(status)) - { - PSUB_Q_CHANNEL_DATA subQPtr = DeviceExtension->ScratchContext.ScratchSrb->DataBuffer; - -#if DBG - switch( inputBuffer->Format ) - { - case IOCTL_CDROM_CURRENT_POSITION: - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Audio Status is %u\n", subQPtr->CurrentPosition.Header.AudioStatus )); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: ADR = 0x%x\n", subQPtr->CurrentPosition.ADR )); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Control = 0x%x\n", subQPtr->CurrentPosition.Control )); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Track = %u\n", subQPtr->CurrentPosition.TrackNumber )); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Index = %u\n", subQPtr->CurrentPosition.IndexNumber )); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Absolute Address = %x\n", *((PULONG)subQPtr->CurrentPosition.AbsoluteAddress) )); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Relative Address = %x\n", *((PULONG)subQPtr->CurrentPosition.TrackRelativeAddress) )); - break; - - case IOCTL_CDROM_MEDIA_CATALOG: - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Audio Status is %u\n", subQPtr->MediaCatalog.Header.AudioStatus )); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Mcval is %u\n", subQPtr->MediaCatalog.Mcval )); - break; - - case IOCTL_CDROM_TRACK_ISRC: - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Audio Status is %u\n", subQPtr->TrackIsrc.Header.AudioStatus )); - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Tcval is %u\n", subQPtr->TrackIsrc.Tcval )); - break; - } -#endif - - // Update the play active status. - if (subQPtr->CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) - { - PLAY_ACTIVE(DeviceExtension) = TRUE; - } - else - { - PLAY_ACTIVE(DeviceExtension) = FALSE; - } - - // Check if output buffer is large enough to contain - // the data. - if (OutputBufferLength < DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength) - { - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength = (ULONG)OutputBufferLength; - } - - // Copy our buffer into users. - RtlMoveMemory(userChannelData, - subQPtr, - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength); - - *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength; - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandlePauseAudio( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_PAUSE_AUDIO - -Arguments: - - DeviceExtension - device context - Request - request to be handled - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE (); - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME; - cdb.PAUSE_RESUME.Action = CDB_AUDIO_PAUSE; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 10); - - if (NT_SUCCESS(status)) - { - PLAY_ACTIVE(DeviceExtension) = FALSE; - *DataLength = 0; - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleResumeAudio( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_RESUME_AUDIO - -Arguments: - - DeviceExtension - device context - Request - request to be handled - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE (); - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME; - cdb.PAUSE_RESUME.Action = CDB_AUDIO_RESUME; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 10); - - if (NT_SUCCESS(status)) - { - PLAY_ACTIVE(DeviceExtension) = TRUE; //not in original code. But we should set it. - *DataLength = 0; - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleSeekAudioMsf( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_SEEK_AUDIO_MSF - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_SEEK_AUDIO_MSF inputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - ULONG logicalBlockAddress; - - logicalBlockAddress = MSF_TO_LBA(inputBuffer->M, inputBuffer->S, inputBuffer->F); - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.SEEK.OperationCode = SCSIOP_SEEK; - cdb.SEEK.LogicalBlockAddress[0] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; - cdb.SEEK.LogicalBlockAddress[1] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; - cdb.SEEK.LogicalBlockAddress[2] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; - cdb.SEEK.LogicalBlockAddress[3] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 10); - - if (NT_SUCCESS(status)) - { - *DataLength = 0; - } - - // nothing to do after the command finishes. - - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleStopAudio( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _Out_ size_t * DataLength - ) -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE (); - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; - cdb.START_STOP.Immediate = 1; - cdb.START_STOP.Start = 0; - cdb.START_STOP.LoadEject = 0; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 6); - - if (NT_SUCCESS(status)) - { - PLAY_ACTIVE(DeviceExtension) = FALSE; - *DataLength = 0; - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleGetSetVolume( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_GET_VOLUME - IOCTL_CDROM_SET_VOLUME - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE (); - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - ULONG transferSize = MODE_DATA_SIZE; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; - cdb.MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE; - cdb.MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8); - cdb.MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, TRUE, &cdb, 10); - - if (NT_SUCCESS(status)) - { - if (RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_VOLUME) - { - PAUDIO_OUTPUT audioOutput; - PVOLUME_CONTROL volumeControl; - ULONG bytesTransferred; - - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - (PVOID*)&volumeControl, - NULL); - if (NT_SUCCESS(status)) - { - audioOutput = ModeSenseFindSpecificPage((PCHAR)DeviceExtension->ScratchContext.ScratchSrb->DataBuffer, - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength, - CDROM_AUDIO_CONTROL_PAGE, - FALSE); - - // Verify the page is as big as expected. - bytesTransferred = (ULONG)((PCHAR)audioOutput - (PCHAR)DeviceExtension->ScratchContext.ScratchSrb->DataBuffer) + - sizeof(AUDIO_OUTPUT); - - if ((audioOutput != NULL) && - (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength >= bytesTransferred)) - { - ULONG i; - for (i=0; i<4; i++) - { - volumeControl->PortVolume[i] = audioOutput->PortOutput[i].Volume; - } - - // Set bytes transferred in IRP. - *DataLength = sizeof(VOLUME_CONTROL); - - } - else - { - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - } - else //IOCTL_CDROM_SET_VOLUME - { - PAUDIO_OUTPUT audioInput = NULL; - PAUDIO_OUTPUT audioOutput = NULL; - PVOLUME_CONTROL volumeControl = NULL; - ULONG i,bytesTransferred,headerLength; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&volumeControl, - NULL); - - if (NT_SUCCESS(status)) - { - audioInput = ModeSenseFindSpecificPage((PCHAR)DeviceExtension->ScratchContext.ScratchSrb->DataBuffer, - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength, - CDROM_AUDIO_CONTROL_PAGE, - FALSE); - - // Check to make sure the mode sense data is valid before we go on - if(audioInput == NULL) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "Mode Sense Page %d not found\n", - CDROM_AUDIO_CONTROL_PAGE)); - - *DataLength = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - - if (NT_SUCCESS(status)) - { - // keep items clean; clear the command history - ScratchBuffer_ResetItems(DeviceExtension, TRUE); - - headerLength = sizeof(MODE_PARAMETER_HEADER10); - bytesTransferred = sizeof(AUDIO_OUTPUT) + headerLength; - - // use the scratch buffer as input buffer. - // the content of this buffer will not be changed in the following loop. - audioOutput = (PAUDIO_OUTPUT)((PCHAR)DeviceExtension->ScratchContext.ScratchBuffer + headerLength); - - for (i=0; i<4; i++) - { - audioOutput->PortOutput[i].Volume = volumeControl->PortVolume[i]; - audioOutput->PortOutput[i].ChannelSelection = audioInput->PortOutput[i].ChannelSelection; - } - - audioOutput->CodePage = CDROM_AUDIO_CONTROL_PAGE; - audioOutput->ParameterLength = sizeof(AUDIO_OUTPUT) - 2; - audioOutput->Immediate = MODE_SELECT_IMMEDIATE; - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10; - cdb.MODE_SELECT10.ParameterListLength[0] = (UCHAR) (bytesTransferred >> 8); - cdb.MODE_SELECT10.ParameterListLength[1] = (UCHAR) (bytesTransferred & 0xFF); - cdb.MODE_SELECT10.PFBit = 1; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, bytesTransferred, FALSE, &cdb, 10); - - } - *DataLength = 0; - } - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleReadDvdStructure( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DVD_READ_STRUCTURE - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PVOID inputBuffer = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - if (NT_SUCCESS(status)) - { - status = ReadDvdStructure(DeviceExtension, - Request, - inputBuffer, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - outputBuffer, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - DataLength); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -ReadDvdStructure( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ WDFREQUEST OriginalRequest, - _In_ PVOID InputBuffer, - _In_ size_t InputBufferLength, - _In_ PVOID OutputBuffer, - _In_ size_t OutputBufferLength, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - base function to handle request of IOCTL_DVD_START_SESSION - IOCTL_DVD_READ_KEY - -Arguments: - - DeviceExtension - device context - OriginalRequest - original request to be handled - InputBuffer - input buffer - InputBufferLength - length of input buffer - OutputBuffer - output buffer - OutputBufferLength - length of output buffer - -Return Value: - - NTSTATUS - DataLength - returned data length - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDVD_READ_STRUCTURE request = (PDVD_READ_STRUCTURE)InputBuffer; - PDVD_DESCRIPTOR_HEADER header = (PDVD_DESCRIPTOR_HEADER)OutputBuffer; - CDB cdb; - - USHORT dataLength; - ULONG blockNumber; - PFOUR_BYTE fourByte; - - PAGED_CODE (); - - UNREFERENCED_PARAMETER(InputBufferLength); - - if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD) - { - *DataLength = 0; - return STATUS_INVALID_DEVICE_REQUEST; - } - - dataLength = (USHORT)OutputBufferLength; - blockNumber = (ULONG)(request->BlockByteOffset.QuadPart >> DeviceExtension->SectorShift); - fourByte = (PFOUR_BYTE)&blockNumber; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE; - cdb.READ_DVD_STRUCTURE.RMDBlockNumber[0] = fourByte->Byte3; - cdb.READ_DVD_STRUCTURE.RMDBlockNumber[1] = fourByte->Byte2; - cdb.READ_DVD_STRUCTURE.RMDBlockNumber[2] = fourByte->Byte1; - cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3] = fourByte->Byte0; - cdb.READ_DVD_STRUCTURE.LayerNumber = request->LayerNumber; - cdb.READ_DVD_STRUCTURE.Format = (UCHAR)request->Format; - -#if DBG - { - if ((UCHAR)request->Format > DvdMaxDescriptor) - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "READ_DVD_STRUCTURE format %x = %s (%x bytes)\n", - (UCHAR)request->Format, - READ_DVD_STRUCTURE_FORMAT_STRINGS[DvdMaxDescriptor], - dataLength - )); - } - else - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, - "READ_DVD_STRUCTURE format %x = %s (%x bytes)\n", - (UCHAR)request->Format, - READ_DVD_STRUCTURE_FORMAT_STRINGS[(UCHAR)request->Format], - dataLength - )); - } - } -#endif // DBG - - if (request->Format == DvdDiskKeyDescriptor) - { - cdb.READ_DVD_STRUCTURE.AGID = (UCHAR)request->SessionId; - } - - cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataLength >> 8); - cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataLength & 0xff); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, OriginalRequest, dataLength, TRUE, &cdb, 12); - - if (NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DvdDCCompletion - READ_STRUCTURE: descriptor format of %d\n", request->Format)); - - RtlMoveMemory(header, - DeviceExtension->ScratchContext.ScratchSrb->DataBuffer, - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength); - - // Cook the data. There are a number of fields that really - // should be byte-swapped for the caller. - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DvdDCCompletion - READ_STRUCTURE:\n" - "\tHeader at %p\n" - "\tDvdDCCompletion - READ_STRUCTURE: data at %p\n" - "\tDataBuffer was at %p\n" - "\tDataTransferLength was %lx\n", - header, - header->Data, - DeviceExtension->ScratchContext.ScratchSrb->DataBuffer, - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength)); - - // First the fields in the header - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "READ_STRUCTURE: header->Length %lx -> ", - header->Length)); - - REVERSE_SHORT(&header->Length); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "%lx\n", header->Length)); - - // Now the fields in the descriptor - if(request->Format == DvdPhysicalDescriptor) - { - ULONG tempLength = (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength > (ULONG)FIELD_OFFSET(DVD_DESCRIPTOR_HEADER, Data)) - ? (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength - FIELD_OFFSET(DVD_DESCRIPTOR_HEADER, Data)) - : 0; - - PDVD_LAYER_DESCRIPTOR layer = (PDVD_LAYER_DESCRIPTOR)&(header->Data[0]); - - // Make sure the buffer size is good for swapping bytes. - if (tempLength >= RTL_SIZEOF_THROUGH_FIELD(DVD_LAYER_DESCRIPTOR, StartingDataSector)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "READ_STRUCTURE: StartingDataSector %lx -> ", - layer->StartingDataSector)); - REVERSE_LONG(&(layer->StartingDataSector)); - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "%lx\n", layer->StartingDataSector)); - } - if (tempLength >= RTL_SIZEOF_THROUGH_FIELD(DVD_LAYER_DESCRIPTOR, EndDataSector)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "READ_STRUCTURE: EndDataSector %lx -> ", - layer->EndDataSector)); - REVERSE_LONG(&(layer->EndDataSector)); - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "%lx\n", layer->EndDataSector)); - } - if (tempLength >= RTL_SIZEOF_THROUGH_FIELD(DVD_LAYER_DESCRIPTOR, EndLayerZeroSector)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "READ_STRUCTURE: EndLayerZeroSector %lx -> ", - layer->EndLayerZeroSector)); - REVERSE_LONG(&(layer->EndLayerZeroSector)); - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "%lx\n", layer->EndLayerZeroSector)); - } - } - - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "Status is %lx\n", status)); - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DvdDeviceControlCompletion - " - "IOCTL_DVD_READ_STRUCTURE: data transfer length of %d\n", - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength)); - } - - *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength; - } - - ScratchBuffer_EndUse(DeviceExtension); - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleDvdEndSession( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DVD_END_SESSION - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDVD_SESSION_ID sessionId = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&sessionId, - NULL); - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - DVD_SESSION_ID currentSession = 0; - DVD_SESSION_ID limitSession = 0; - - if(*sessionId == DVD_END_ALL_SESSIONS) - { - currentSession = 0; - limitSession = MAX_COPY_PROTECT_AGID - 1; - } - else - { - currentSession = *sessionId; - limitSession = *sessionId; - } - - ScratchBuffer_BeginUse(DeviceExtension); - - do - { - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.SEND_KEY.OperationCode = SCSIOP_SEND_KEY; - cdb.SEND_KEY.AGID = (UCHAR)(currentSession); - cdb.SEND_KEY.KeyFormat = DVD_INVALIDATE_AGID; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 12); - - currentSession++; - } while ((currentSession <= limitSession) && NT_SUCCESS(status)); - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleDvdStartSessionReadKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DVD_START_SESSION - IOCTL_DVD_READ_KEY - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDVD_COPY_PROTECT_KEY keyParameters = NULL; - PVOID outputBuffer = NULL; - - PAGED_CODE (); - - if (NT_SUCCESS(status)) - { - status = WdfRequestRetrieveOutputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - &outputBuffer, - NULL); - } - - if (NT_SUCCESS(status) && RequestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_DVD_READ_KEY) - { - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&keyParameters, - NULL); - } - - if (NT_SUCCESS(status)) - { - status = DvdStartSessionReadKey(DeviceExtension, - RequestParameters.Parameters.DeviceIoControl.IoControlCode, - Request, - keyParameters, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - outputBuffer, - RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, - DataLength); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DvdStartSessionReadKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG IoControlCode, - _In_opt_ WDFREQUEST OriginalRequest, - _In_opt_ PVOID InputBuffer, - _In_ size_t InputBufferLength, - _In_ PVOID OutputBuffer, - _In_ size_t OutputBufferLength, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - base function to handle request of IOCTL_DVD_START_SESSION - IOCTL_DVD_READ_KEY - -Arguments: - - DeviceExtension - device context - IoControlCode - IOCTL_DVD_READ_KEY or IOCTL_DVD_START_SESSION - OriginalRequest - original request to be handled - InputBuffer - input buffer - InputBufferLength - length of input buffer - OutputBuffer - output buffer - OutputBufferLength - length of output buffer - -Return Value: - - NTSTATUS - DataLength - returned data length - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - ULONG keyLength = 0; - ULONG result = 0; - ULONG allocationLength; - PFOUR_BYTE fourByte; - PDVD_COPY_PROTECT_KEY keyParameters = (PDVD_COPY_PROTECT_KEY)InputBuffer; - - PAGED_CODE (); - - UNREFERENCED_PARAMETER(InputBufferLength); - - *DataLength = 0; - - fourByte = (PFOUR_BYTE)&allocationLength; - - if (IoControlCode == IOCTL_DVD_READ_KEY) - { - if (keyParameters == NULL) - { - status = STATUS_INTERNAL_ERROR; - } - - // First of all, initialize the DVD region of the drive, if it has not been set yet - if (NT_SUCCESS(status) && - (keyParameters->KeyType == DvdGetRpcKey) && - DeviceExtension->DeviceAdditionalData.Mmc.IsCssDvd) - { - DevicePickDvdRegion(DeviceExtension->Device); - } - - if (NT_SUCCESS(status) && - (keyParameters->KeyType == DvdDiskKey)) - { - // Special case - need to use READ DVD STRUCTURE command to get the disk key. - PDVD_COPY_PROTECT_KEY keyHeader = NULL; - PDVD_READ_STRUCTURE readStructureRequest = (PDVD_READ_STRUCTURE)keyParameters; - - // save the key header so we can restore the interesting parts later - keyHeader = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(DVD_COPY_PROTECT_KEY), - DVD_TAG_READ_KEY); - - if(keyHeader == NULL) - { - // Can't save the context so return an error - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DvdDeviceControl - READ_KEY: unable to allocate context\n")); - status = STATUS_INSUFFICIENT_RESOURCES; - } - - if (NT_SUCCESS(status)) - { - PREAD_DVD_STRUCTURES_HEADER rawKey = OutputBuffer; - PDVD_COPY_PROTECT_KEY outputKey = OutputBuffer; - - // save input parameters - RtlCopyMemory(keyHeader, - InputBuffer, - sizeof(DVD_COPY_PROTECT_KEY)); - - readStructureRequest->Format = DvdDiskKeyDescriptor; - readStructureRequest->BlockByteOffset.QuadPart = 0; - readStructureRequest->LayerNumber = 0; - readStructureRequest->SessionId = keyHeader->SessionId; - - status = ReadDvdStructure(DeviceExtension, - OriginalRequest, - InputBuffer, - sizeof(DVD_READ_STRUCTURE), - OutputBuffer, - sizeof(READ_DVD_STRUCTURES_HEADER) + sizeof(DVD_DISK_KEY_DESCRIPTOR), - DataLength); - - // fill the output buffer, it's not touched in DeviceHandleReadDvdStructure() - // for this specific request type: DvdDiskKeyDescriptor - if (NT_SUCCESS(status)) - { - // Shift the data down to its new position. - RtlMoveMemory(outputKey->KeyData, - rawKey->Data, - sizeof(DVD_DISK_KEY_DESCRIPTOR)); - - RtlCopyMemory(outputKey, - keyHeader, - sizeof(DVD_COPY_PROTECT_KEY)); - - outputKey->KeyLength = DVD_DISK_KEY_LENGTH; - - *DataLength = DVD_DISK_KEY_LENGTH; - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, - "StartSessionReadKey Failed with status %x, %xI64 (%x) bytes\n", - status, - (unsigned int)*DataLength, - ((rawKey->Length[0] << 16) | rawKey->Length[1]) )); - } - - FREE_POOL(keyHeader); - } - - // special process finished. return from here. - return status; - } - - if (NT_SUCCESS(status)) - { - status = RtlULongSub((ULONG)OutputBufferLength, - (ULONG)sizeof(DVD_COPY_PROTECT_KEY), &result); - } - - if (NT_SUCCESS(status)) - { - status = RtlULongAdd(result, sizeof(CDVD_KEY_HEADER), &keyLength); - } - - if (NT_SUCCESS(status)) - { - //The data length field of REPORT KEY Command occupies two bytes - keyLength = min(keyLength, MAXUSHORT); - } - } - else //IOCTL_DVD_START_SESSION - { - keyParameters = NULL; - keyLength = sizeof(CDVD_KEY_HEADER) + sizeof(CDVD_REPORT_AGID_DATA); - status = STATUS_SUCCESS; - } - - if (NT_SUCCESS(status)) - { - CDB cdb; - - allocationLength = keyLength; - - // Defensive coding. Prefix cannot recognize this usage. - UNREFERENCED_PARAMETER(allocationLength); - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY; - cdb.REPORT_KEY.AllocationLength[0] = fourByte->Byte1; - cdb.REPORT_KEY.AllocationLength[1] = fourByte->Byte0; - - // set the specific parameters.... - if(IoControlCode == IOCTL_DVD_READ_KEY) - { - if(keyParameters->KeyType == DvdTitleKey) - { - ULONG logicalBlockAddress; - - logicalBlockAddress = (ULONG)(keyParameters->Parameters.TitleOffset.QuadPart >> - DeviceExtension->SectorShift); - - fourByte = (PFOUR_BYTE)&(logicalBlockAddress); - - cdb.REPORT_KEY.LogicalBlockAddress[0] = fourByte->Byte3; - cdb.REPORT_KEY.LogicalBlockAddress[1] = fourByte->Byte2; - cdb.REPORT_KEY.LogicalBlockAddress[2] = fourByte->Byte1; - cdb.REPORT_KEY.LogicalBlockAddress[3] = fourByte->Byte0; - } - - cdb.REPORT_KEY.KeyFormat = (UCHAR)keyParameters->KeyType; - cdb.REPORT_KEY.AGID = (UCHAR)keyParameters->SessionId; - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DvdStartSessionReadKey => sending irp %p (%s)\n", - OriginalRequest, "READ_KEY")); - } - else - { - cdb.REPORT_KEY.KeyFormat = DVD_REPORT_AGID; - cdb.REPORT_KEY.AGID = 0; - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DvdStartSessionReadKey => sending irp %p (%s)\n", - OriginalRequest, "START_SESSION")); - } - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, OriginalRequest, keyLength, TRUE, &cdb, 12); - - if (NT_SUCCESS(status)) - { - if(IoControlCode == IOCTL_DVD_READ_KEY) - { - NTSTATUS tempStatus; - PDVD_COPY_PROTECT_KEY copyProtectKey = (PDVD_COPY_PROTECT_KEY)OutputBuffer; - PCDVD_KEY_HEADER keyHeader = DeviceExtension->ScratchContext.ScratchSrb->DataBuffer; - ULONG dataLength; - ULONG transferLength; - - tempStatus = RtlULongSub(DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength, - FIELD_OFFSET(CDVD_KEY_HEADER, Data), - &transferLength); - - dataLength = (keyHeader->DataLength[0] << 8) + keyHeader->DataLength[1]; - - if (NT_SUCCESS(tempStatus) && (dataLength >= 2)) - { - // Adjust the data length to ignore the two reserved bytes in the - // header. - dataLength -= 2; - - // take the minimum of the transferred length and the - // length as specified in the header. - if(dataLength < transferLength) - { - transferLength = dataLength; - } - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DvdDeviceControlCompletion: [%p] - READ_KEY with " - "transfer length of (%d or %d) bytes\n", - OriginalRequest, - dataLength, - DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength - 2)); - - // Copy the key data into the return buffer - if(copyProtectKey->KeyType == DvdTitleKey) - { - RtlMoveMemory(copyProtectKey->KeyData, - keyHeader->Data + 1, - transferLength - 1); - - copyProtectKey->KeyData[transferLength - 1] = 0; - - // If this is a title key then we need to copy the CGMS flags - // as well. - copyProtectKey->KeyFlags = *(keyHeader->Data); - - } - else - { - RtlMoveMemory(copyProtectKey->KeyData, - keyHeader->Data, - transferLength); - } - - copyProtectKey->KeyLength = sizeof(DVD_COPY_PROTECT_KEY); - copyProtectKey->KeyLength += transferLength; - - *DataLength = copyProtectKey->KeyLength; - } - else - { - //There is no valid data from drive. - //This may happen when Key Format = 0x3f that does not require data back from drive. - status = STATUS_SUCCESS; - *DataLength = 0; - } - } - else - { - PDVD_SESSION_ID sessionId = (PDVD_SESSION_ID)OutputBuffer; - PCDVD_KEY_HEADER keyHeader = DeviceExtension->ScratchContext.ScratchSrb->DataBuffer; - PCDVD_REPORT_AGID_DATA keyData = (PCDVD_REPORT_AGID_DATA)keyHeader->Data; - - *sessionId = keyData->AGID; - - *DataLength = sizeof(DVD_SESSION_ID); - } - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleDvdSendKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_DVD_SEND_KEY - IOCTL_DVD_SEND_KEY2 - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PVOID inputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - &inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - status = DvdSendKey(DeviceExtension, - Request, - inputBuffer, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - DataLength); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DvdSendKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ WDFREQUEST OriginalRequest, - _In_ PVOID InputBuffer, - _In_ size_t InputBufferLength, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - base function to handle request of IOCTL_DVD_SEND_KEY(2) - NOTE: cdrom does not process this IOCTL if the input buffer length is bigger than Port transfer length. - -Arguments: - - DeviceExtension - device context - OriginalRequest - original request to be handled - InputBuffer - input buffer - InputBufferLength - length of input buffer - -Return Value: - - NTSTATUS - DataLength - returned data length - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY)InputBuffer; - - ULONG keyLength = 0; - ULONG result = 0; - PFOUR_BYTE fourByte; - - PAGED_CODE (); - - UNREFERENCED_PARAMETER(InputBufferLength); - - *DataLength = 0; - - if (NT_SUCCESS(status)) - { - if ((key->KeyLength < sizeof(DVD_COPY_PROTECT_KEY)) || - ((key->KeyLength - sizeof(DVD_COPY_PROTECT_KEY)) > DeviceExtension->ScratchContext.ScratchBufferSize)) - { - NT_ASSERT(FALSE); - status = STATUS_INTERNAL_ERROR; - } - } - - if (NT_SUCCESS(status)) - { - status = RtlULongSub(key->KeyLength, sizeof(DVD_COPY_PROTECT_KEY), &result); - } - - if (NT_SUCCESS(status)) - { - status = RtlULongAdd(result, sizeof(CDVD_KEY_HEADER), &keyLength); - } - - if (NT_SUCCESS(status)) - { - keyLength = min(keyLength, DeviceExtension->ScratchContext.ScratchBufferSize); - - if (keyLength < 2) - { - status = STATUS_INVALID_PARAMETER; - } - } - - if (NT_SUCCESS(status)) - { - PCDVD_KEY_HEADER keyBuffer = NULL; - CDB cdb; - - ScratchBuffer_BeginUse(DeviceExtension); - - // prepare the input buffer - keyBuffer = (PCDVD_KEY_HEADER)DeviceExtension->ScratchContext.ScratchBuffer; - - // keylength is decremented here by two because the - // datalength does not include the header, which is two - // bytes. keylength is immediately incremented later - // by the same amount. - keyLength -= 2; - fourByte = (PFOUR_BYTE)&keyLength; - keyBuffer->DataLength[0] = fourByte->Byte1; - keyBuffer->DataLength[1] = fourByte->Byte0; - keyLength += 2; - - RtlMoveMemory(keyBuffer->Data, - key->KeyData, - key->KeyLength - sizeof(DVD_COPY_PROTECT_KEY)); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.REPORT_KEY.OperationCode = SCSIOP_SEND_KEY; - - cdb.SEND_KEY.ParameterListLength[0] = fourByte->Byte1; - cdb.SEND_KEY.ParameterListLength[1] = fourByte->Byte0; - cdb.SEND_KEY.KeyFormat = (UCHAR)key->KeyType; - cdb.SEND_KEY.AGID = (UCHAR)key->SessionId; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, OriginalRequest, keyLength, FALSE, &cdb, 12); - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleSetReadAhead( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_STORAGE_SET_READ_AHEAD - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSTORAGE_SET_READ_AHEAD readAhead = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&readAhead, - NULL); - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - ULONG blockAddress; - PFOUR_BYTE fourByte = (PFOUR_BYTE)&blockAddress; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.SET_READ_AHEAD.OperationCode = SCSIOP_SET_READ_AHEAD; - - blockAddress = (ULONG)(readAhead->TriggerAddress.QuadPart >> - DeviceExtension->SectorShift); - - // Defensive coding. Prefix cannot recognize this usage. - UNREFERENCED_PARAMETER(blockAddress); - - cdb.SET_READ_AHEAD.TriggerLBA[0] = fourByte->Byte3; - cdb.SET_READ_AHEAD.TriggerLBA[1] = fourByte->Byte2; - cdb.SET_READ_AHEAD.TriggerLBA[2] = fourByte->Byte1; - cdb.SET_READ_AHEAD.TriggerLBA[3] = fourByte->Byte0; - - blockAddress = (ULONG)(readAhead->TargetAddress.QuadPart >> - DeviceExtension->SectorShift); - - cdb.SET_READ_AHEAD.ReadAheadLBA[0] = fourByte->Byte3; - cdb.SET_READ_AHEAD.ReadAheadLBA[1] = fourByte->Byte2; - cdb.SET_READ_AHEAD.ReadAheadLBA[2] = fourByte->Byte1; - cdb.SET_READ_AHEAD.ReadAheadLBA[3] = fourByte->Byte0; - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 12); - - if (NT_SUCCESS(status)) - { - *DataLength = 0; - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - -_IRQL_requires_max_(APC_LEVEL) -NTSTATUS -DeviceHandleSetSpeed( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ WDF_REQUEST_PARAMETERS RequestParameters, - _Out_ size_t * DataLength - ) -/*++ - -Routine Description: - - Handle request of IOCTL_CDROM_SET_SPEED - -Arguments: - - DeviceExtension - device context - Request - request to be handled - RequestParameters - request parameter - DataLength - transferred data length - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData); - PCDROM_SET_SPEED inputBuffer = NULL; - - PAGED_CODE (); - - *DataLength = 0; - - status = WdfRequestRetrieveInputBuffer(Request, - RequestParameters.Parameters.DeviceIoControl.InputBufferLength, - (PVOID*)&inputBuffer, - NULL); - - if (NT_SUCCESS(status)) - { - ULONG transferSize = 0; - CDB cdb; - CDROM_SPEED_REQUEST requestType = inputBuffer->RequestType; - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - if (requestType == CdromSetSpeed) - { - PCDROM_SET_SPEED speed = inputBuffer; - - cdb.SET_CD_SPEED.OperationCode = SCSIOP_SET_CD_SPEED; - cdb.SET_CD_SPEED.RotationControl = speed->RotationControl; - REVERSE_BYTES_SHORT(&cdb.SET_CD_SPEED.ReadSpeed, &speed->ReadSpeed); - REVERSE_BYTES_SHORT(&cdb.SET_CD_SPEED.WriteSpeed, &speed->WriteSpeed); - } - else - { - PCDROM_SET_STREAMING stream = (PCDROM_SET_STREAMING)inputBuffer; - PPERFORMANCE_DESCRIPTOR perfDescriptor; - - transferSize = sizeof(PERFORMANCE_DESCRIPTOR); - - perfDescriptor = DeviceExtension->ScratchContext.ScratchBuffer; - RtlZeroMemory(perfDescriptor, transferSize); - - perfDescriptor->RandomAccess = stream->RandomAccess; - perfDescriptor->Exact = stream->SetExact; - perfDescriptor->RestoreDefaults = stream->RestoreDefaults; - perfDescriptor->WriteRotationControl = stream->RotationControl; - - REVERSE_BYTES(&perfDescriptor->StartLba, &stream->StartLba); - REVERSE_BYTES(&perfDescriptor->EndLba, &stream->EndLba); - REVERSE_BYTES(&perfDescriptor->ReadSize, &stream->ReadSize); - REVERSE_BYTES(&perfDescriptor->ReadTime, &stream->ReadTime); - REVERSE_BYTES(&perfDescriptor->WriteSize, &stream->WriteSize); - REVERSE_BYTES(&perfDescriptor->WriteTime, &stream->WriteTime); - - cdb.SET_STREAMING.OperationCode = SCSIOP_SET_STREAMING; - REVERSE_BYTES_SHORT(&cdb.SET_STREAMING.ParameterListLength, &transferSize); - - // set value in extension by user inputs. - cdData->RestoreDefaults = stream->Persistent ? FALSE : TRUE; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DeviceHandleSetSpeed: Restore default speed on media change set to %s\n", - cdData->RestoreDefaults ? "true" : "false")); - } - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 12); - - if (NT_SUCCESS(status)) - { - *DataLength = 0; - } - - // nothing to do after the command finishes. - ScratchBuffer_EndUse(DeviceExtension); - } - - return status; -} - - diff --git a/storage/class/cdrom/src/ioctl.h b/storage/class/cdrom/src/ioctl.h deleted file mode 100644 index 951561a9..00000000 --- a/storage/class/cdrom/src/ioctl.h +++ /dev/null @@ -1,847 +0,0 @@ -/*++ - -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__ diff --git a/storage/class/cdrom/src/localwpp.ini b/storage/class/cdrom/src/localwpp.ini deleted file mode 100644 index 0e793609..00000000 --- a/storage/class/cdrom/src/localwpp.ini +++ /dev/null @@ -1,17 +0,0 @@ - -// 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) -// ) - - diff --git a/storage/class/cdrom/src/mmc.c b/storage/class/cdrom/src/mmc.c deleted file mode 100644 index 5f96726c..00000000 --- a/storage/class/cdrom/src/mmc.c +++ /dev/null @@ -1,1629 +0,0 @@ -/*-- - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - mmc.c - -Abstract: - - Include all funtions relate to MMC - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - -#include "stddef.h" -#include "string.h" - -#include "ntddk.h" -#include "ntddstor.h" -#include "cdrom.h" -#include "mmc.h" -#include "scratch.h" - -#ifdef DEBUG_USE_WPP -#include "mmc.tmh" -#endif - -#ifdef ALLOC_PRAGMA - -#pragma alloc_text(PAGE, DeviceDeallocateMmcResources) -#pragma alloc_text(PAGE, DeviceAllocateMmcResources) -#pragma alloc_text(PAGE, DeviceUpdateMmcCapabilities) -#pragma alloc_text(PAGE, DeviceGetConfigurationWithAlloc) -#pragma alloc_text(PAGE, DeviceGetConfiguration) -#pragma alloc_text(PAGE, DeviceUpdateMmcWriteCapability) -#pragma alloc_text(PAGE, MmcDataFindFeaturePage) -#pragma alloc_text(PAGE, MmcDataFindProfileInProfiles) -#pragma alloc_text(PAGE, DeviceRetryTimeGuessBasedOnProfile) -#pragma alloc_text(PAGE, DeviceRetryTimeDetectionBasedOnModePage2A) -#pragma alloc_text(PAGE, DeviceRetryTimeDetectionBasedOnGetPerformance) - -#endif - -#pragma warning(push) -#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int - -_IRQL_requires_max_(APC_LEVEL) -VOID -DeviceDeallocateMmcResources( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - release MMC resources - -Arguments: - - Device - device object - -Return Value: - - none - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_DATA cddata = &(deviceExtension->DeviceAdditionalData); - PCDROM_MMC_EXTENSION mmcData = &cddata->Mmc; - - PAGED_CODE(); - - if (mmcData->CapabilitiesIrp) - { - IoFreeIrp(mmcData->CapabilitiesIrp); - mmcData->CapabilitiesIrp = NULL; - } - if (mmcData->CapabilitiesMdl) - { - IoFreeMdl(mmcData->CapabilitiesMdl); - mmcData->CapabilitiesMdl = NULL; - } - if (mmcData->CapabilitiesBuffer) - { - ExFreePool(mmcData->CapabilitiesBuffer); - mmcData->CapabilitiesBuffer = NULL; - } - if (mmcData->CapabilitiesRequest) - { - WdfObjectDelete(mmcData->CapabilitiesRequest); - mmcData->CapabilitiesRequest = NULL; - } - mmcData->CapabilitiesBufferSize = 0; - mmcData->IsMmc = FALSE; - mmcData->WriteAllowed = FALSE; - - return; -} - - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceAllocateMmcResources( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - allocate all MMC resources needed - -Arguments: - - Device - device object - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_DATA cddata = &(deviceExtension->DeviceAdditionalData); - PCDROM_MMC_EXTENSION mmcData = &(cddata->Mmc); - WDF_OBJECT_ATTRIBUTES attributes = {0}; - - PAGED_CODE(); - - NT_ASSERT(mmcData->CapabilitiesBuffer == NULL); - NT_ASSERT(mmcData->CapabilitiesBufferSize == 0); - - // allocate the buffer and set the buffer size. - // retrieve drive configuration information. - status = DeviceGetConfigurationWithAlloc(Device, - &mmcData->CapabilitiesBuffer, - &mmcData->CapabilitiesBufferSize, - FeatureProfileList, - SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL); - if (!NT_SUCCESS(status)) - { - NT_ASSERT(mmcData->CapabilitiesBuffer == NULL); - NT_ASSERT(mmcData->CapabilitiesBufferSize == 0); - return status; - } - - NT_ASSERT(mmcData->CapabilitiesBuffer != NULL); - NT_ASSERT(mmcData->CapabilitiesBufferSize != 0); - - // Create an MDL over the new Buffer (allocated by DeviceGetConfiguration) - mmcData->CapabilitiesMdl = IoAllocateMdl(mmcData->CapabilitiesBuffer, - mmcData->CapabilitiesBufferSize, - FALSE, FALSE, NULL); - if (mmcData->CapabilitiesMdl == NULL) - { - ExFreePool(mmcData->CapabilitiesBuffer); - mmcData->CapabilitiesBuffer = NULL; - mmcData->CapabilitiesBufferSize = 0; - return STATUS_INSUFFICIENT_RESOURCES; - } - - // Create an IRP from which we will create a WDFREQUEST - mmcData->CapabilitiesIrp = IoAllocateIrp(deviceExtension->DeviceObject->StackSize + 1, FALSE); - if (mmcData->CapabilitiesIrp == NULL) - { - IoFreeMdl(mmcData->CapabilitiesMdl); - mmcData->CapabilitiesMdl = NULL; - ExFreePool(mmcData->CapabilitiesBuffer); - mmcData->CapabilitiesBuffer = NULL; - mmcData->CapabilitiesBufferSize = 0; - return STATUS_INSUFFICIENT_RESOURCES; - } - - // create WDF request object - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - status = WdfRequestCreateFromIrp(&attributes, - mmcData->CapabilitiesIrp, - FALSE, - &mmcData->CapabilitiesRequest); - if (!NT_SUCCESS(status)) - { - return status; - } - - return STATUS_SUCCESS; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceUpdateMmcCapabilities( - _In_ WDFDEVICE Device - ) -/*++ - -Routine Description: - - issue get congiguration command ans save result in device extension - -Arguments: - - Device - device object - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData); - PCDROM_MMC_EXTENSION mmcData = &(cdData->Mmc); - ULONG returnedBytes = 0; - LONG updateState; - - PAGED_CODE(); - - // first of all, check if we're still in the CdromMmcUpdateRequired state - // and, if yes, change it to CdromMmcUpdateStarted. - updateState = InterlockedCompareExchange((PLONG)&(cdData->Mmc.UpdateState), - CdromMmcUpdateStarted, - CdromMmcUpdateRequired); - if (updateState != CdromMmcUpdateRequired) { - // Mmc capabilities have been already updated or are in the process of - // being updated - just return STATUS_SUCCESS - return STATUS_SUCCESS; - } - - // default to read-only, no Streaming, non-blank - mmcData->WriteAllowed = FALSE; - mmcData->StreamingReadSupported = FALSE; - mmcData->StreamingWriteSupported = FALSE; - - // Issue command to update the drive capabilities. - // The failure of MMC update is not considered critical, - // so that we'll continue to process I/O even MMC update fails. - status = DeviceGetConfiguration(Device, - mmcData->CapabilitiesBuffer, - mmcData->CapabilitiesBufferSize, - &returnedBytes, - FeatureProfileList, - SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT); - - if (NT_SUCCESS(status) && // succeeded. - (mmcData->CapabilitiesBufferSize >= returnedBytes)) // not overflow. - { - // update whether or not writes are allowed - // this should be the *ONLY* place writes are set to allowed - { - BOOLEAN writeAllowed = FALSE; - FEATURE_NUMBER validationSchema = 0; - ULONG blockingFactor = 1; - - DeviceUpdateMmcWriteCapability(mmcData->CapabilitiesBuffer, - returnedBytes, - TRUE, - &writeAllowed, - &validationSchema, - &blockingFactor); - - mmcData->WriteAllowed = writeAllowed; - mmcData->ValidationSchema = validationSchema; - mmcData->Blocking = blockingFactor; - } - - // Check if Streaming reads/writes are supported and cache - // this information for later use. - { - PFEATURE_HEADER header; - ULONG minAdditionalLength; - - minAdditionalLength = FIELD_OFFSET(FEATURE_DATA_REAL_TIME_STREAMING, Reserved2) - - sizeof(FEATURE_HEADER); - - header = MmcDataFindFeaturePage(mmcData->CapabilitiesBuffer, - returnedBytes, - FeatureRealTimeStreaming); - - if ((header != NULL) && - (header->Current) && - (header->AdditionalLength >= minAdditionalLength)) - { - PFEATURE_DATA_REAL_TIME_STREAMING feature = (PFEATURE_DATA_REAL_TIME_STREAMING)header; - - // If Real-Time feature is current, then Streaming reads are supported for sure. - mmcData->StreamingReadSupported = TRUE; - - // Streaming writes are supported if an appropriate bit is set in the feature page. - mmcData->StreamingWriteSupported = (feature->StreamRecording == 1); - } - } - - // update the flag to reflect that if the media is CSS protected DVD or CPPM-protected DVDAudio - { - PFEATURE_HEADER header; - - header = DeviceFindFeaturePage(mmcData->CapabilitiesBuffer, - returnedBytes, - FeatureDvdCSS); - - mmcData->IsCssDvd = (header != NULL) && (header->Current); - } - - // Update the guesstimate for the drive's write speed - // Use the GetConfig profile first as a quick-guess based - // on media "type", then continue with media-specific - // queries for older media types, and use GET_PERFORMANCE - // for all unknown/future media types. - { - // pseudo-code: - // 1) Determine default based on profile (slowest for media) - // 2) Determine default based on MODE PAGE 2Ah - // 3) Determine default based on GET PERFORMANCE data - // 4) Choose fastest reported speed (-1 == none reported) - // 5) If all failed (returned -1), go with very safe (slow) default - // - // This ensures that the retries do not overload the drive's processor. - // Sending at highest possible speed for the media is OK, because the - // major downside is drive processor usage. (bus usage too, but most - // storage is becoming a point-to-point link.) - - FEATURE_PROFILE_TYPE const profile = - mmcData->CapabilitiesBuffer->CurrentProfile[0] << (8*1) | - mmcData->CapabilitiesBuffer->CurrentProfile[1] << (8*0) ; - LONGLONG t1 = (LONGLONG)-1; - LONGLONG t2 = (LONGLONG)-1; - LONGLONG t3 = (LONGLONG)-1; - LONGLONG t4 = (LONGLONG)-1; - LONGLONG final; - - t1 = DeviceRetryTimeGuessBasedOnProfile(profile); - t2 = DeviceRetryTimeDetectionBasedOnModePage2A(deviceExtension); - t3 = DeviceRetryTimeDetectionBasedOnGetPerformance(deviceExtension, TRUE); - t4 = DeviceRetryTimeDetectionBasedOnGetPerformance(deviceExtension, FALSE); - - // use the "fastest" value returned - final = MAXLONGLONG; - if (t4 != -1) - { - final = min(final, t4); - } - if (t3 != -1) - { - final = min(final, t3); - } - if (t2 != -1) - { - final = min(final, t2); - } - if (t1 != -1) - { - final = min(final, t1); - } - if (final == MAXLONGLONG) - { - // worst case -- use relatively slow default.... - final = WRITE_RETRY_DELAY_CD_4x; - } - - cdData->ReadWriteRetryDelay100nsUnits = final; - } - - } - else - { - // Rediscovery of MMC capabilities has failed - we'll need to retry - cdData->Mmc.UpdateState = CdromMmcUpdateRequired; - } - - // Change the state to CdromMmcUpdateComplete if it is CdromMmcUpdateStarted. - // If it is not, some error must have happened while this function was executed - // and the state is CdromMmcUpdateRequired now. In that case, we want to perform - // everything again, so we do not set CdromMmcUpdateComplete. - InterlockedCompareExchange((PLONG)&(cdData->Mmc.UpdateState), - CdromMmcUpdateComplete, - CdromMmcUpdateStarted); - - return status; -} - -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DeviceGetConfigurationWithAlloc( - _In_ WDFDEVICE Device, - _Outptr_result_bytebuffer_all_(*BytesReturned) - PGET_CONFIGURATION_HEADER* Buffer, // this routine allocates this memory - _Out_ PULONG BytesReturned, - FEATURE_NUMBER const StartingFeature, - ULONG const RequestedType - ) -/*++ - -Routine Description: - - This function will allocates configuration buffer and set the size. - -Arguments: - - Device - device object - Buffer - to be allocated by this function - BytesReturned - size of the buffer - StartingFeature - the starting point of the feature list - RequestedType - - -Return Value: - - NTSTATUS - -NOTE: does not handle case where more than 65000 bytes are returned, - which requires multiple calls with different starting feature - numbers. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - GET_CONFIGURATION_HEADER header = {0}; // eight bytes, not a lot - PGET_CONFIGURATION_HEADER buffer = NULL; - ULONG returned = 0; - ULONG size = 0; - ULONG i = 0; - - PAGED_CODE(); - - *Buffer = NULL; - *BytesReturned = 0; - - // send the first request down to just get the header - status = DeviceGetConfiguration(Device, - &header, - sizeof(header), - &returned, - StartingFeature, - RequestedType); - - // now send command again, using information returned to allocate just enough memory - if (NT_SUCCESS(status)) - { - size = header.DataLength[0] << 24 | - header.DataLength[1] << 16 | - header.DataLength[2] << 8 | - header.DataLength[3] << 0 ; - - // the loop is in case that the retrieved data length is bigger than last time reported. - for (i = 0; (i < 4) && NT_SUCCESS(status); i++) - { - // the datalength field is the size *following* itself, so adjust accordingly - size += 4*sizeof(UCHAR); - - // make sure the size is reasonable - if (size <= sizeof(FEATURE_HEADER)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DeviceGetConfigurationWithAlloc: drive reports only %x bytes?\n", - size)); - status = STATUS_UNSUCCESSFUL; - } - - if (NT_SUCCESS(status)) - { - // allocate the memory - buffer = (PGET_CONFIGURATION_HEADER)ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - size, - CDROM_TAG_FEATURE); - - if (buffer == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) - { - // send the first request down to just get the header - status = DeviceGetConfiguration(Device, - buffer, - size, - &returned, - StartingFeature, - RequestedType); - - if (!NT_SUCCESS(status)) - { - ExFreePool(buffer); - } - else if (returned > size) - { - ExFreePool(buffer); - status = STATUS_INTERNAL_ERROR; - } - } - - // command succeeded. - if (NT_SUCCESS(status)) - { - returned = buffer->DataLength[0] << 24 | - buffer->DataLength[1] << 16 | - buffer->DataLength[2] << 8 | - buffer->DataLength[3] << 0 ; - returned += 4*sizeof(UCHAR); - - if (returned <= size) - { - *Buffer = buffer; - *BytesReturned = returned; // amount of 'safe' memory - // succes, get out of loop. - status = STATUS_SUCCESS; - break; - } - else - { - // the data size is bigger than the buffer size, retry using new size.... - size = returned; - ExFreePool(buffer); - buffer = NULL; - } - } - } // end of for() loop - } - - if (!NT_SUCCESS(status)) - { - // it failed after a number of attempts, so just fail. - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DeviceGetConfigurationWithAlloc: Failed %d attempts to get all feature " - "information\n", i)); - } - - return status; -} - -_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 - ) -/*++ - -Routine Description: - - This function is used to get configuration data. - -Arguments: - - Device - device object - Buffer - buffer address to hold data. - BufferSize - size of the buffer - ValidBytes - valid data size in buffer - StartingFeature - the starting point of the feature list - RequestedType - - -Return Value: - - NTSTATUS - -NOTE: does not handle case where more than 64k bytes are returned, - which requires multiple calls with different starting feature - numbers. - ---*/ -{ - NTSTATUS status; - PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device); - SCSI_REQUEST_BLOCK srb; - PCDB cdb = (PCDB)srb.Cdb; - - PAGED_CODE(); - - NT_ASSERT(ValidBytes); - - // when system is low resources we can receive empty buffer - if (Buffer == NULL || BufferSize < sizeof(GET_CONFIGURATION_HEADER)) - { - return STATUS_BUFFER_TOO_SMALL; - } - - *ValidBytes = 0; - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - RtlZeroMemory(Buffer, BufferSize); - - if (TEST_FLAG(deviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_GET_CONFIG_SUPPORT)) - { - return STATUS_INVALID_DEVICE_REQUEST; - } - -#pragma warning(push) -#pragma warning(disable: 6386) // OACR will complain buffer overrun: the writable size is 'BufferSize' bytes, but '65532' - // bytes might be written, which is impossible because BufferSize > 0xFFFC. - - if (BufferSize > 0xFFFC) - { - // cannot request more than 0xFFFC bytes in one request - // Eventually will "stitch" together multiple requests if needed - // Today, no drive has anywhere close to 4k..... - return DeviceGetConfiguration(Device, - Buffer, - 0xFFFC, - ValidBytes, - StartingFeature, - RequestedType); - } -#pragma warning(pop) - - //Start real work - srb.TimeOutValue = CDROM_GET_CONFIGURATION_TIMEOUT; - srb.CdbLength = 10; - - cdb->GET_CONFIGURATION.OperationCode = SCSIOP_GET_CONFIGURATION; - cdb->GET_CONFIGURATION.RequestType = (UCHAR)RequestedType; - cdb->GET_CONFIGURATION.StartingFeature[0] = (UCHAR)(StartingFeature >> 8); - cdb->GET_CONFIGURATION.StartingFeature[1] = (UCHAR)(StartingFeature & 0xff); - cdb->GET_CONFIGURATION.AllocationLength[0] = (UCHAR)(BufferSize >> 8); - cdb->GET_CONFIGURATION.AllocationLength[1] = (UCHAR)(BufferSize & 0xff); - - status = DeviceSendSrbSynchronously(Device, - &srb, - Buffer, - BufferSize, - FALSE, - NULL); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, - "DeviceGetConfiguration: Status was %x\n", status)); - - if (NT_SUCCESS(status) || - (status == STATUS_BUFFER_OVERFLOW) || - (status == STATUS_DATA_OVERRUN)) - { - ULONG returned = srb.DataTransferLength; - PGET_CONFIGURATION_HEADER header = (PGET_CONFIGURATION_HEADER)Buffer; - ULONG available = (header->DataLength[0] << (8*3)) | - (header->DataLength[1] << (8*2)) | - (header->DataLength[2] << (8*1)) | - (header->DataLength[3] << (8*0)) ; - - available += RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength); - - _Analysis_assume_(srb.DataTransferLength <= BufferSize); - - // The true usable amount of data returned is the lesser of - // * the returned data per the srb.DataTransferLength field - // * the total size per the GET_CONFIGURATION_HEADER - // This is because ATAPI can't tell how many bytes really - // were transferred on success when using DMA. - if (available < returned) - { - returned = available; - } - - NT_ASSERT(returned <= BufferSize); - *ValidBytes = (ULONG)returned; - - //This is succeed case - status = STATUS_SUCCESS; - } - else - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, - "DeviceGetConfiguration: failed %x\n", status)); - } - - return status; -} - - -_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 - ) -/*++ - -Routine Description: - - This function will allocates configuration buffer and set the size. - -Arguments: - - Buffer - - BufferSize - size of the buffer - CurrentOnly - valid data size in buffer - Writable - the buffer is allocationed in non-paged pool. - validationSchema - the starting point of the feature list - BlockingFactor - - -Return Value: - - NTSTATUS - -NOTE: does not handle case where more than 64k bytes are returned, - which requires multiple calls with different starting feature - numbers. - ---*/ -{ - // - // this routine is used to check if the drive can currently (current==TRUE) - // or can ever (current==FALSE) write to media with the current CDROM.SYS - // driver. this check parses the GET_CONFIGURATION response data to search - // for the appropriate features and/or if they are current. - // - // this function should not allocate any resources, and thus may safely - // return from any point within the function. - // - PAGED_CODE(); - - *Writable = FALSE; - *ValidationSchema = 0; - *BlockingFactor = 1; - - // - // if the drive supports hardware defect management and random writes, that's - // sufficient to allow writes. - // - { - PFEATURE_HEADER defectHeader; - PFEATURE_HEADER writableHeader; - - defectHeader = MmcDataFindFeaturePage(Buffer, - BufferSize, - FeatureDefectManagement); - writableHeader = MmcDataFindFeaturePage(Buffer, - BufferSize, - FeatureRandomWritable); - - if (defectHeader == NULL || writableHeader == NULL) - { - // cannot write this way - } - else if (!CurrentOnly) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes supported (defect management)\n")); - *Writable = TRUE; - return; - } - else if (defectHeader->Current && writableHeader->Current) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes *allowed* (defect management)\n")); - *Writable = TRUE; - *ValidationSchema = FeatureDefectManagement; - return; - } - } - - // Certain validation schema require the blocking factor - // This is a best-effort attempt to ensure that illegal - // requests do not make it to drive - { - PFEATURE_HEADER header; - ULONG additionalLength; - - // Certain validation schema require the blocking factor - // This is a best-effort attempt to ensure that illegal - // requests do not make it to drive - additionalLength = RTL_SIZEOF_THROUGH_FIELD(FEATURE_DATA_RANDOM_READABLE, Blocking) - sizeof(FEATURE_HEADER); - - header = MmcDataFindFeaturePage(Buffer, - BufferSize, - FeatureRandomReadable); - - if ((header != NULL) && - (header->Current) && - (header->AdditionalLength >= additionalLength)) - { - PFEATURE_DATA_RANDOM_READABLE feature = (PFEATURE_DATA_RANDOM_READABLE)header; - *BlockingFactor = (feature->Blocking[0] << 8) | feature->Blocking[1]; - } - } - - // the majority of features to indicate write capability - // indicate this by a single feature existance/current bit. - // thus, can use a table-based method for the majority - // of the detection.... - { - typedef struct { - FEATURE_NUMBER FeatureToFind; // the ones allowed - FEATURE_NUMBER ValidationSchema; // and their related schema - } FEATURE_TO_WRITE_SCHEMA_MAP; - - static FEATURE_TO_WRITE_SCHEMA_MAP const FeaturesToAllowWritesWith[] = { - { FeatureRandomWritable, FeatureRandomWritable }, - { FeatureRigidRestrictedOverwrite, FeatureRigidRestrictedOverwrite }, - { FeatureRestrictedOverwrite, FeatureRestrictedOverwrite }, - { FeatureIncrementalStreamingWritable, FeatureIncrementalStreamingWritable }, - }; - - ULONG count; - for (count = 0; count < RTL_NUMBER_OF(FeaturesToAllowWritesWith); count++) - { - PFEATURE_HEADER header = MmcDataFindFeaturePage(Buffer, - BufferSize, - FeaturesToAllowWritesWith[count].FeatureToFind); - if (header == NULL) - { - // cannot write using this method - } - else if (!CurrentOnly) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes supported (feature %04x)\n", - FeaturesToAllowWritesWith[count].FeatureToFind - )); - *Writable = TRUE; - return; - } - else if (header->Current) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes *allowed* (feature %04x)\n", - FeaturesToAllowWritesWith[count].FeatureToFind - )); - *Writable = TRUE; - *ValidationSchema = FeaturesToAllowWritesWith[count].ValidationSchema; - return; - } - } // end count loop - } - - // unfortunately, DVD+R media doesn't require IncrementalStreamingWritable feature - // to be explicitly set AND it has a seperate bit in the feature to indicate - // being able to write to this media type. Thus, use a special case of the above code. - { - PFEATURE_DATA_DVD_PLUS_R header; - ULONG additionalLength = FIELD_OFFSET(FEATURE_DATA_DVD_PLUS_R, Reserved2[0]) - sizeof(FEATURE_HEADER); - header = MmcDataFindFeaturePage(Buffer, - BufferSize, - FeatureDvdPlusR); - - if (header == NULL || (header->Header.AdditionalLength < additionalLength) || (!header->Write)) - { - // cannot write this way - } - else if (!CurrentOnly) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes supported (feature %04x)\n", - FeatureDvdPlusR - )); - *Writable = TRUE; - return; - } - else if (header->Header.Current) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes *allowed* (feature %04x)\n", - FeatureDvdPlusR - )); - *Writable = TRUE; - *ValidationSchema = FeatureIncrementalStreamingWritable; - return; - } - } - - // unfortunately, DVD+R DL media doesn't require IncrementalStreamingWritable feature - // to be explicitly set AND it has a seperate bit in the feature to indicate - // being able to write to this media type. Thus, use a special case of the above code. - { - PFEATURE_DATA_DVD_PLUS_R_DUAL_LAYER header; - ULONG additionalLength = FIELD_OFFSET(FEATURE_DATA_DVD_PLUS_R_DUAL_LAYER, Reserved2[0]) - sizeof(FEATURE_HEADER); - header = MmcDataFindFeaturePage(Buffer, - BufferSize, - FeatureDvdPlusRDualLayer); - - if (header == NULL || (header->Header.AdditionalLength < additionalLength) || (!header->Write)) - { - // cannot write this way - } - else if (!CurrentOnly) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes supported (feature %04x)\n", - FeatureDvdPlusRDualLayer - )); - *Writable = TRUE; - return; - } - else if (header->Header.Current) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes *allowed* (feature %04x)\n", - FeatureDvdPlusRDualLayer - )); - *Writable = TRUE; - *ValidationSchema = FeatureIncrementalStreamingWritable; - return; - } - } - - // There are currently a number of drives on the market - // that fail to report: - // (a) FeatureIncrementalStreamingWritable as current - // for CD-R / DVD-R profile. - // (b) FeatureRestrictedOverwrite as current for CD-RW - // profile - // (c) FeatureRigidRestrictedOverwrite as current for - // DVD-RW profile - // - // Thus, use the profiles also. - { - PFEATURE_HEADER header; - header = MmcDataFindFeaturePage(Buffer, - BufferSize, - FeatureProfileList); - - if (header != NULL && header->Current) - { - // verify buffer bounds -- the below routine presumes full profile list provided - PUCHAR bufferEnd = ((PUCHAR)Buffer) + BufferSize; - PUCHAR headerEnd = ((PUCHAR)header) + header->AdditionalLength + RTL_SIZEOF_THROUGH_FIELD(FEATURE_HEADER, AdditionalLength); - if (bufferEnd >= headerEnd) // this _should_ never occurr, but.... - { - // Profiles don't contain any data other than current/not current. - // thus, can generically loop through them to see if any of the - // below (in order of preference) are current. - typedef struct { - FEATURE_PROFILE_TYPE ProfileToFind; // the ones allowed - FEATURE_NUMBER ValidationSchema; // and their related schema - } PROFILE_TO_WRITE_SCHEMA_MAP; - - static PROFILE_TO_WRITE_SCHEMA_MAP const ProfilesToAllowWritesWith[] = { - { ProfileDvdRewritable, FeatureRigidRestrictedOverwrite }, - { ProfileCdRewritable, FeatureRestrictedOverwrite }, - { ProfileDvdRecordable, FeatureIncrementalStreamingWritable }, - { ProfileCdRecordable, FeatureIncrementalStreamingWritable }, - }; - - ULONG count; - for (count = 0; count < RTL_NUMBER_OF(ProfilesToAllowWritesWith); count++) - { - BOOLEAN exists = FALSE; - MmcDataFindProfileInProfiles((PFEATURE_DATA_PROFILE_LIST)header, - ProfilesToAllowWritesWith[count].ProfileToFind, - CurrentOnly, - &exists); - if (exists) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, - "DeviceUpdateMmcWriteCapability => Writes %s (profile %04x)\n", - (CurrentOnly ? "*allowed*" : "supported"), - FeatureDvdPlusR - )); - - *Writable = TRUE; - *ValidationSchema = ProfilesToAllowWritesWith[count].ValidationSchema; - return; - } - } // end count loop - } // end if (bufferEnd >= headerEnd) - - } // end if (header != NULL && header->Current) - } - - // nothing matched to say it's writable..... - return; -} - -_IRQL_requires_max_(APC_LEVEL) -PVOID -MmcDataFindFeaturePage( - _In_reads_bytes_(Length) - PGET_CONFIGURATION_HEADER FeatureBuffer, - ULONG const Length, - FEATURE_NUMBER const Feature - ) -/*++ - -Routine Description: - - search the specific feature from feature list buffer - -Arguments: - - FeatureBuffer - buffer of feature list - Length - size of the buffer - Feature - feature wanted to find - -Return Value: - - PVOID - if found, pointer of starting address of the specific feature. - otherwise, NULL. - ---*/ -{ - PUCHAR buffer; - PUCHAR limit; - ULONG validLength; - - PAGED_CODE(); - - if (Length < sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER)) { - return NULL; - } - - // Calculate the length of valid data available in the - // capabilities buffer from the DataLength field - REVERSE_BYTES(&validLength, FeatureBuffer->DataLength); - validLength += RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength); - - // set limit to point to first illegal address - limit = (PUCHAR)FeatureBuffer; - limit += min(Length, validLength); - - // set buffer to point to first page - buffer = FeatureBuffer->Data; - - // loop through each page until we find the requested one, or - // until it's not safe to access the entire feature header - // (if equal, have exactly enough for the feature header) - while (buffer + sizeof(FEATURE_HEADER) <= limit) - { - PFEATURE_HEADER header = (PFEATURE_HEADER)buffer; - FEATURE_NUMBER thisFeature; - - thisFeature = (header->FeatureCode[0] << 8) | - (header->FeatureCode[1]); - - if (thisFeature == Feature) - { - PUCHAR temp; - - // if don't have enough memory to safely access all the feature - // information, return NULL - temp = buffer; - temp += sizeof(FEATURE_HEADER); - temp += header->AdditionalLength; - - if (temp > limit) - { - // this means the transfer was cut-off, an insufficiently - // small buffer was given, or other arbitrary error. since - // it's not safe to view the amount of data (even though - // the header is safe) in this feature, pretend it wasn't - // transferred at all... - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "Feature %x exists, but not safe to access all its " - "data. returning NULL\n", Feature)); - return NULL; - } - else - { - return buffer; - } - } - - if ((header->AdditionalLength % 4) && - !(Feature >= 0xff00 && Feature <= 0xffff)) - { - return NULL; - } - - buffer += sizeof(FEATURE_HEADER); - buffer += header->AdditionalLength; - - } - return NULL; -} - -_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 - ) -/*++ - -Routine Description: - - search the specific feature from feature list buffer - -Arguments: - - ProfileHeader - buffer of profile list - ProfileToFind - profile to be found - CurrentOnly - - -Return Value: - - Found - found or not - ---*/ -{ - FEATURE_DATA_PROFILE_LIST_EX const * profile; - ULONG numberOfProfiles; - ULONG i; - - PAGED_CODE(); - - // initialize output - *Found = FALSE; - - // sanity check - if (ProfileHeader->Header.AdditionalLength % 2 != 0) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "Profile total length %x is not integral multiple of 4\n", - ProfileHeader->Header.AdditionalLength)); - NT_ASSERT(FALSE); - return; - } - - // calculate number of profiles - numberOfProfiles = ProfileHeader->Header.AdditionalLength / 4; - profile = ProfileHeader->Profiles; // zero-sized array - - // loop through profiles - for (i = 0; i < numberOfProfiles; i++) - { - FEATURE_PROFILE_TYPE currentProfile; - - currentProfile = (profile->ProfileNumber[0] << 8) | - (profile->ProfileNumber[1] & 0xff); - - if (currentProfile == ProfileToFind) - { - if (profile->Current || (!CurrentOnly)) - { - *Found = TRUE; - } - } - - profile++; - } - - return; -} - -_IRQL_requires_max_(APC_LEVEL) -_Ret_range_(-1,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) -LONGLONG -DeviceRetryTimeGuessBasedOnProfile( - FEATURE_PROFILE_TYPE const Profile - ) -/*++ - -Routine Description: - - determine the retry time based on profile - -Arguments: - - Profile - - -Return Value: - - LONGLONG - retry time - ---*/ -{ - LONGLONG result = -1; // this means we have no idea - - PAGED_CODE(); - - switch (Profile) - { - case ProfileInvalid: // = 0x0000, - case ProfileNonRemovableDisk: // = 0x0001, - case ProfileRemovableDisk: // = 0x0002, - case ProfileMOErasable: // = 0x0003, - case ProfileMOWriteOnce: // = 0x0004, - case ProfileAS_MO: // = 0x0005, - // Reserved 0x0006 - 0x0007, - // Reserved 0x000b - 0x000f, - // Reserved 0x0017 - 0x0019 - // Reserved 0x001C - 001F - // Reserved 0x0023 - 0x0029 - // Reserved 0x002C - 0x003F - // Reserved 0x0044 - 0x004F - // Reserved 0x0053 - 0xfffe - case ProfileNonStandard: // = 0xffff - default: - { - NOTHING; // no default - break; - } - - case ProfileCdrom: // = 0x0008, - case ProfileCdRecordable: // = 0x0009, - case ProfileCdRewritable: // = 0x000a, - case ProfileDDCdrom: // = 0x0020, // obsolete - case ProfileDDCdRecordable: // = 0x0021, // obsolete - case ProfileDDCdRewritable: // = 0x0022, // obsolete - { - // 4x is ok as all CD drives have - // at least 64k*4 (256k) buffer - // and this is just a first-pass - // guess based only on profile - result = WRITE_RETRY_DELAY_CD_4x; - break; - } - case ProfileDvdRom: // = 0x0010, - case ProfileDvdRecordable: // = 0x0011, - case ProfileDvdRam: // = 0x0012, - case ProfileDvdRewritable: // = 0x0013, // restricted overwrite - case ProfileDvdRWSequential: // = 0x0014, - case ProfileDvdDashRLayerJump: // = 0x0016, - case ProfileDvdPlusRW: // = 0x001A, - case ProfileDvdPlusR: // = 0x001B, - { - result = WRITE_RETRY_DELAY_DVD_1x; - break; - } - case ProfileDvdDashRDualLayer: // = 0x0015, - case ProfileDvdPlusRWDualLayer: // = 0x002A, - case ProfileDvdPlusRDualLayer: // = 0x002B, - { - result = WRITE_RETRY_DELAY_DVD_1x; - break; - } - - case ProfileBDRom: // = 0x0040, - case ProfileBDRSequentialWritable: // = 0x0041, // BD-R 'SRM' - case ProfileBDRRandomWritable: // = 0x0042, // BD-R 'RRM' - case ProfileBDRewritable: // = 0x0043, - { - // I could not find specifications for the - // minimal 1x data rate for BD media. Use - // HDDVD values for now, since they are - // likely to be similar. Also, all media - // except for CD, DVD, and AS-MO should - // already fully support GET_CONFIG, so - // this guess is only used if we fail to - // get a performance descriptor.... - result = WRITE_RETRY_DELAY_HDDVD_1x; - break; - } - - case ProfileHDDVDRom: // = 0x0050, - case ProfileHDDVDRecordable: // = 0x0051, - case ProfileHDDVDRam: // = 0x0052, - { - // All HDDVD drives support GET_PERFORMANCE - // so this guess is fine at 1x.... - result = WRITE_RETRY_DELAY_HDDVD_1x; - break; - } - - // addition of any further profile types is not - // technically required as GET PERFORMANCE - // should succeed for all future drives. However, - // it is useful in case GET PERFORMANCE does - // fail for other reasons (i.e. bus resets, etc) - - } // end switch(Profile) - - return result; -} - -_IRQL_requires_max_(APC_LEVEL) -_Ret_range_(-1,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) -LONGLONG -DeviceRetryTimeDetectionBasedOnModePage2A( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - determine the retry time based on mode sense data - -Arguments: - - DeviceExtension - device context - -Return Value: - - LONGLONG - retry time - ---*/ -{ - NTSTATUS status; - ULONG transferSize = min(0xFFF0, DeviceExtension->ScratchContext.ScratchBufferSize); - CDB cdb; - LONGLONG result = -1; - - PAGED_CODE(); - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - cdb.MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; - cdb.MODE_SENSE10.Dbd = 1; - cdb.MODE_SENSE10.PageCode = MODE_PAGE_CAPABILITIES; - cdb.MODE_SENSE10.AllocationLength[0] = (UCHAR)(transferSize >> 8); - cdb.MODE_SENSE10.AllocationLength[1] = (UCHAR)(transferSize & 0xFF); - - status = ScratchBuffer_ExecuteCdb(DeviceExtension, NULL, transferSize, TRUE, &cdb, 10); - - // analyze the data on success.... - if (NT_SUCCESS(status)) - { - MODE_PARAMETER_HEADER10 const* header = DeviceExtension->ScratchContext.ScratchBuffer; - CDVD_CAPABILITIES_PAGE const* page = NULL; - ULONG dataLength = (header->ModeDataLength[0] << (8*1)) | - (header->ModeDataLength[1] << (8*0)) ; - - // no possible overflow - if (dataLength != 0) - { - dataLength += RTL_SIZEOF_THROUGH_FIELD(MODE_PARAMETER_HEADER10, ModeDataLength); - } - - // If it's not abundantly clear, we really don't trust the drive - // to be returning valid data. Get the page pointer and usable - // size of the page here... - if (dataLength < sizeof(MODE_PARAMETER_HEADER10)) - { - dataLength = 0; - } - else if (dataLength > DeviceExtension->ScratchContext.ScratchBufferSize) - { - dataLength = 0; - } - else if ((header->BlockDescriptorLength[1] == 0) && - (header->BlockDescriptorLength[0] == 0)) - { - dataLength -= sizeof(MODE_PARAMETER_HEADER10); - page = (CDVD_CAPABILITIES_PAGE const *)(header + 1); - } - else if ((header->BlockDescriptorLength[1] == 0) && - (header->BlockDescriptorLength[0] == sizeof(MODE_PARAMETER_BLOCK))) - { - dataLength -= sizeof(MODE_PARAMETER_HEADER10); - dataLength -= min(dataLength, sizeof(MODE_PARAMETER_BLOCK)); - page = (CDVD_CAPABILITIES_PAGE const *) - ( ((PUCHAR)header) + - sizeof(MODE_PARAMETER_HEADER10) + - sizeof(MODE_PARAMETER_BLOCK) - ); - } - - // Change dataLength from the size available per the header to - // the size available per the page itself. - if ((page != NULL) && - (dataLength >= RTL_SIZEOF_THROUGH_FIELD(CDVD_CAPABILITIES_PAGE, PageLength)) - ) - { - dataLength = min(dataLength, ((ULONG)(page->PageLength) + 2)); - } - - // Ignore the page if the fastest write speed field isn't available. - if ((page != NULL) && - (dataLength < RTL_SIZEOF_THROUGH_FIELD(CDVD_CAPABILITIES_PAGE, WriteSpeedMaximum)) - ) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "ModePage 2Ah was requested, but drive reported " - "only %x bytes (%x needed). Ignoring.\n", - dataLength, - RTL_SIZEOF_THROUGH_FIELD(CDVD_CAPABILITIES_PAGE, WriteSpeedMaximum) - )); - page = NULL; - } - - // Verify the page we requested is the one the drive actually provided - if ((page != NULL) && (page->PageCode != MODE_PAGE_CAPABILITIES)) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "ModePage 2Ah was requested, but drive reported " - "page %x\n", - page->PageCode - )); - page = NULL; - } - - // If _everything_ succeeded, then use the speed value in the page! - if (page != NULL) - { - ULONG temp = - (page->WriteSpeedMaximum[0] << (8*1)) | - (page->WriteSpeedMaximum[1] << (8*0)) ; - // stored as 1,000 byte increments... - temp *= 1000; - // typically stored at 2448 bytes/sector due to CD media - // error up to 20% high by presuming it returned 2048 data - // and convert to sectors/second - temp /= 2048; - // currently: sectors/sec - // ignore too-small or zero values - if (temp != 0) - { - result = ConvertSectorsPerSecondTo100nsUnitsFor64kWrite(temp); - } - } - } - - ScratchBuffer_EndUse(DeviceExtension); - - return result; -} - - -_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 - ) -/*++ - -Routine Description: - - determine the retry time based on get performance data - -Arguments: - - DeviceExtension - device context - UseLegacyNominalPerformance - - -Return Value: - - LONGLONG - retry time - ---*/ -{ - typedef struct _GET_PERFORMANCE_HEADER { - UCHAR TotalDataLength[4]; // not including this field - UCHAR Except : 1; - UCHAR Write : 1; - UCHAR Reserved0 : 6; - UCHAR Reserved1[3]; - } GET_PERFORMANCE_HEADER, *PGET_PERFORMANCE_HEADER; - C_ASSERT( sizeof(GET_PERFORMANCE_HEADER) == 8); - - typedef struct _GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR { - UCHAR StartLba[4]; - UCHAR StartPerformance[4]; - UCHAR EndLba[4]; - UCHAR EndPerformance[4]; - } GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR, *PGET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR; - C_ASSERT( sizeof(GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR) == 16); - - - typedef struct _GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR { - UCHAR MixedReadWrite : 1; - UCHAR GuaranteedForWholeMedia : 1; - UCHAR Reserved0_RDD : 1; - UCHAR WriteRotationControl : 2; - UCHAR Reserved1 : 3; - UCHAR Reserved2[3]; - - UCHAR MediaCapacity[4]; - UCHAR ReadSpeedKilobytesPerSecond[4]; - UCHAR WriteSpeedKilobytesPerSecond[4]; - } GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR, *PGET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR; - C_ASSERT( sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR) == 16); - - ////// - - NTSTATUS status; - LONGLONG result = -1; - - // transfer size -- descriptors + 8 byte header - // Note: this size is identical for both descriptor types - C_ASSERT( sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR) == sizeof(GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR)); - - ULONG const maxDescriptors = min(200, (DeviceExtension->ScratchContext.ScratchBufferSize-sizeof(GET_PERFORMANCE_HEADER))/sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR)); - ULONG validDescriptors = 0; - ULONG transferSize = sizeof(GET_PERFORMANCE_HEADER) + (maxDescriptors*sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR)); - CDB cdb; - - PAGED_CODE(); - - ScratchBuffer_BeginUse(DeviceExtension); - - RtlZeroMemory(&cdb, sizeof(CDB)); - // Set up the CDB - if (UseLegacyNominalPerformance) - { - cdb.GET_PERFORMANCE.OperationCode = SCSIOP_GET_PERFORMANCE; - cdb.GET_PERFORMANCE.Except = 0; - cdb.GET_PERFORMANCE.Write = 1; - cdb.GET_PERFORMANCE.Tolerance = 2; // only defined option - cdb.GET_PERFORMANCE.MaximumNumberOfDescriptors[1] = (UCHAR)maxDescriptors; - cdb.GET_PERFORMANCE.Type = 0; // legacy nominal descriptors - } - else - { - cdb.GET_PERFORMANCE.OperationCode = SCSIOP_GET_PERFORMANCE; - cdb.GET_PERFORMANCE.MaximumNumberOfDescriptors[1] = (UCHAR)maxDescriptors; - cdb.GET_PERFORMANCE.Type = 3; // write speed - } - - status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, NULL, transferSize, TRUE, &cdb, 12, CDROM_GET_PERFORMANCE_TIMEOUT); - - // determine how many valid descriptors there actually are - if (NT_SUCCESS(status)) - { - GET_PERFORMANCE_HEADER const* header = (GET_PERFORMANCE_HEADER const*)DeviceExtension->ScratchContext.ScratchBuffer; - ULONG temp1 = (header->TotalDataLength[0] << (8*3)) | - (header->TotalDataLength[1] << (8*2)) | - (header->TotalDataLength[2] << (8*1)) | - (header->TotalDataLength[3] << (8*0)) ; - - // adjust data size for header - if (temp1 + (ULONG)RTL_SIZEOF_THROUGH_FIELD(GET_PERFORMANCE_HEADER, TotalDataLength) < temp1) - { - temp1 = 0; - } - else if (temp1 != 0) - { - temp1 += RTL_SIZEOF_THROUGH_FIELD(GET_PERFORMANCE_HEADER, TotalDataLength); - } - - if (temp1 == 0) - { - // no data returned - } - else if (temp1 <= sizeof(GET_PERFORMANCE_HEADER)) - { - // only the header returned, no descriptors - } - else if (UseLegacyNominalPerformance && - ((header->Except != 0) || (header->Write == 0)) - ) - { - // bad data being returned -- ignore it - } - else if (!UseLegacyNominalPerformance && - ((header->Except != 0) || (header->Write != 0)) - ) - { - // returning Performance (Type 0) data, not requested Write Speed (Type 3) data - } - else if ( (temp1 - sizeof(GET_PERFORMANCE_HEADER)) % sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR) != 0) - { - // Note: this size is identical for both descriptor types - C_ASSERT( sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR) == sizeof(GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR)); - - // not returning valid data.... - } - else // save how many are usable - { - // Note: this size is identical for both descriptor types - C_ASSERT( sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR) == sizeof(GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR)); - - // take the smaller usable value - temp1 = min(temp1, DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength); - // then determine the usable descriptors - validDescriptors = (temp1 - sizeof(GET_PERFORMANCE_HEADER)) / sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR); - } - } - - // The drive likely supports this command. - // Verify the data makes sense. - if (NT_SUCCESS(status)) - { - ULONG i; - GET_PERFORMANCE_HEADER const* header = (GET_PERFORMANCE_HEADER const*)DeviceExtension->ScratchContext.ScratchBuffer; - GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR const* descriptor = (GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR const*)(header+1); // pointer math - - // NOTE: We could write this loop twice, once for each write descriptor type - // However, the only fields of interest are the writeKBps field (Type 3) and - // the EndPerformance field (Type 0), which both exist in the same exact - // location and have essentially the same meaning. So, just use the same - // loop/structure pointers for both of the to simplify the readability of - // this code. The C_ASSERT()s here verify this at compile-time. - - C_ASSERT( sizeof(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR) == sizeof(GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR)); - C_ASSERT( FIELD_OFFSET(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR, WriteSpeedKilobytesPerSecond) == - FIELD_OFFSET(GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR, EndPerformance) - ); - C_ASSERT( RTL_FIELD_SIZE(GET_PERFORMANCE_WRITE_SPEED_DESCRIPTOR, WriteSpeedKilobytesPerSecond) == - RTL_FIELD_SIZE(GET_PERFORMANCE_NOMINAL_PERFORMANCE_DESCRIPTOR, EndPerformance) - ); - - // loop through them all, and find the fastest listed write speed - for (i = 0; NT_SUCCESS(status) && (i <validDescriptors); descriptor++, i++) - { - ULONG const writeKBps = - (descriptor->WriteSpeedKilobytesPerSecond[0] << (8*3)) | - (descriptor->WriteSpeedKilobytesPerSecond[1] << (8*2)) | - (descriptor->WriteSpeedKilobytesPerSecond[2] << (8*1)) | - (descriptor->WriteSpeedKilobytesPerSecond[3] << (8*0)) ; - - // Avoid overflow and still have good estimates - // 0x1 0000 0000 / 1000 == 0x00418937 == maximum writeKBps to multiple first - ULONG const sectorsPerSecond = - (writeKBps > 0x00418937) ? // would overflow occur by multiplying by 1000? - ((writeKBps / 2048) * 1000) : // must divide first, minimal loss of accuracy - ((writeKBps * 1000) / 2048) ; // must multiply first, avoid loss of accuracy - - if (sectorsPerSecond <= 0) - { - break; // out of the loop -- no longer valid data (very defensive programming) - } - - // we have at least one valid result, so prevent returning -1 as our result - if (result == -1) { result = MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS; } - - // take the fastest speed (smallest wait time) we've found thus far - result = min(result, ConvertSectorsPerSecondTo100nsUnitsFor64kWrite(sectorsPerSecond)); - } - } - - ScratchBuffer_EndUse(DeviceExtension); - - return result; -} - -#pragma warning(pop) // un-sets any local warning changes diff --git a/storage/class/cdrom/src/mmc.h b/storage/class/cdrom/src/mmc.h deleted file mode 100644 index 51c03309..00000000 --- a/storage/class/cdrom/src/mmc.h +++ /dev/null @@ -1,122 +0,0 @@ -/*++ - -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__ diff --git a/storage/class/cdrom/src/pnppower.c b/storage/class/cdrom/src/pnppower.c deleted file mode 100644 index 56f239e4..00000000 --- a/storage/class/cdrom/src/pnppower.c +++ /dev/null @@ -1,684 +0,0 @@ -/*-- - -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 -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 -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 -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 -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 -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 - diff --git a/storage/class/cdrom/src/scratch.c b/storage/class/cdrom/src/scratch.c deleted file mode 100644 index fe82049a..00000000 --- a/storage/class/cdrom/src/scratch.c +++ /dev/null @@ -1,1463 +0,0 @@ -/*-- - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - scratch.c - -Abstract: - - Functions for using common scratch buffer - -Environment: - - kernel mode only - -Notes: - - -Revision History: - ---*/ - -#include "stddef.h" -#include "string.h" - -#include "ntddk.h" -#include "ntddstor.h" -#include "cdrom.h" -#include "ioctl.h" -#include "scratch.h" -#include "mmc.h" - -#ifdef DEBUG_USE_WPP -#include "scratch.tmh" -#endif - -// Forward declarations -EVT_WDF_REQUEST_COMPLETION_ROUTINE ScratchBuffer_ReadWriteCompletionRoutine; - -#ifdef ALLOC_PRAGMA - -#pragma alloc_text(PAGE, ScratchBuffer_Deallocate) -#pragma alloc_text(PAGE, ScratchBuffer_Allocate) -#pragma alloc_text(PAGE, ScratchBuffer_SetupSrb) -#pragma alloc_text(PAGE, ScratchBuffer_ExecuteCdbEx) - -#endif - -_IRQL_requires_max_(APC_LEVEL) -VOID -ScratchBuffer_Deallocate( - _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - release all resources allocated for scratch. - -Arguments: - - DeviceExtension - device extension - -Return Value: - - none - ---*/ -{ - PAGED_CODE (); - - NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse == 0); - - if (DeviceExtension->ScratchContext.ScratchHistory != NULL) - { - ExFreePool(DeviceExtension->ScratchContext.ScratchHistory); - DeviceExtension->ScratchContext.ScratchHistory = NULL; - } - if (DeviceExtension->ScratchContext.ScratchSense != NULL) - { - ExFreePool(DeviceExtension->ScratchContext.ScratchSense); - DeviceExtension->ScratchContext.ScratchSense = NULL; - } - if (DeviceExtension->ScratchContext.ScratchSrb != NULL) - { - ExFreePool(DeviceExtension->ScratchContext.ScratchSrb); - DeviceExtension->ScratchContext.ScratchSrb = NULL; - } - if (DeviceExtension->ScratchContext.ScratchBufferSize != 0) - { - DeviceExtension->ScratchContext.ScratchBufferSize = 0; - } - if (DeviceExtension->ScratchContext.ScratchBufferMdl != NULL) - { - IoFreeMdl(DeviceExtension->ScratchContext.ScratchBufferMdl); - DeviceExtension->ScratchContext.ScratchBufferMdl = NULL; - } - if (DeviceExtension->ScratchContext.ScratchBuffer != NULL) - { - ExFreePool(DeviceExtension->ScratchContext.ScratchBuffer); - DeviceExtension->ScratchContext.ScratchBuffer = NULL; - } - - if (DeviceExtension->ScratchContext.PartialMdl != NULL) - { - IoFreeMdl(DeviceExtension->ScratchContext.PartialMdl); - DeviceExtension->ScratchContext.PartialMdl = NULL; - } - - if (DeviceExtension->ScratchContext.ScratchRequest != NULL) - { - PIRP irp = WdfRequestWdmGetIrp(DeviceExtension->ScratchContext.ScratchRequest); - if (irp->MdlAddress) - { - irp->MdlAddress = NULL; - } - WdfObjectDelete(DeviceExtension->ScratchContext.ScratchRequest); - DeviceExtension->ScratchContext.ScratchRequest = NULL; - } - - return; -} - -_IRQL_requires_max_(APC_LEVEL) -BOOLEAN -ScratchBuffer_Allocate( - _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - allocate resources allocated for scratch. - -Arguments: - - DeviceExtension - device extension - -Return Value: - - none - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE (); - - NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse == 0); - - // quick-exit if already allocated - if ((DeviceExtension->ScratchContext.ScratchBuffer != NULL) && - (DeviceExtension->ScratchContext.ScratchBufferMdl != NULL) && - (DeviceExtension->ScratchContext.ScratchBufferSize != 0) && - (DeviceExtension->ScratchContext.ScratchRequest != NULL) && - (DeviceExtension->ScratchContext.ScratchSrb != NULL) && - (DeviceExtension->ScratchContext.ScratchHistory != NULL) && - (DeviceExtension->ScratchContext.PartialMdl != NULL) - ) - { - return TRUE; - } - - // validate max transfer already determined - NT_ASSERT(DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes != 0); - - // validate no partially-saved state - NT_ASSERT(DeviceExtension->ScratchContext.ScratchBuffer == NULL); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchBufferMdl == NULL); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchBufferSize == 0); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchRequest == NULL); - NT_ASSERT(DeviceExtension->ScratchContext.PartialMdl == NULL); - - // limit the scratch buffer to between 4k and 64k (so data length fits into USHORT -- req'd for many commands) - DeviceExtension->ScratchContext.ScratchBufferSize = min(DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes, (64*1024)); - - // allocate the buffer - if (NT_SUCCESS(status)) - { - DeviceExtension->ScratchContext.ScratchBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, - DeviceExtension->ScratchContext.ScratchBufferSize, - CDROM_TAG_SCRATCH); - if (DeviceExtension->ScratchContext.ScratchBuffer == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to allocate scratch buffer of %x bytes\n", - DeviceExtension->ScratchContext.ScratchBufferSize - )); - } - else if (BYTE_OFFSET(DeviceExtension->ScratchContext.ScratchBuffer) != 0) - { - status = STATUS_INTERNAL_ERROR; - TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT, - "Allocation of %x bytes non-paged pool was not " - "allocated on page boundary? STATUS_INTERNAL_ERROR\n", - DeviceExtension->ScratchContext.ScratchBufferSize - )); - } - } - - // allocate the MDL - if (NT_SUCCESS(status)) - { - DeviceExtension->ScratchContext.ScratchBufferMdl = IoAllocateMdl(DeviceExtension->ScratchContext.ScratchBuffer, - DeviceExtension->ScratchContext.ScratchBufferSize, - FALSE, FALSE, NULL); - if (DeviceExtension->ScratchContext.ScratchBufferMdl == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to allocate MDL for %x byte buffer\n", - DeviceExtension->ScratchContext.ScratchBufferSize - )); - } - else - { - MmBuildMdlForNonPagedPool(DeviceExtension->ScratchContext.ScratchBufferMdl); - } - } - - // create the request - if (NT_SUCCESS(status)) - { - WDF_OBJECT_ATTRIBUTES attributes; - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CDROM_REQUEST_CONTEXT); - - status = WdfRequestCreate(&attributes, - DeviceExtension->IoTarget, - &DeviceExtension->ScratchContext.ScratchRequest); - - if ((!NT_SUCCESS(status)) || - (DeviceExtension->ScratchContext.ScratchRequest == NULL)) - { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to allocate scratch MDL \n")); - } - } - - // allocate the srb - if (NT_SUCCESS(status)) - { - DeviceExtension->ScratchContext.ScratchSrb = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(SCSI_REQUEST_BLOCK), - CDROM_TAG_SCRATCH); - - if (DeviceExtension->ScratchContext.ScratchSrb == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to allocate scratch SRB\n")); - } - } - - // allocate the sense buffer - if (NT_SUCCESS(status)) - { - DeviceExtension->ScratchContext.ScratchSense = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(SENSE_DATA), - CDROM_TAG_SCRATCH); - - if (DeviceExtension->ScratchContext.ScratchSense == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to allocate scratch sense data\n" - )); - } - } - - // allocate the SRB history data - if (NT_SUCCESS(status)) - { - size_t allocationSize = sizeof(SRB_HISTORY) - sizeof(SRB_HISTORY_ITEM); - allocationSize += 20 * sizeof(SRB_HISTORY_ITEM); - - DeviceExtension->ScratchContext.ScratchHistory = ExAllocatePool2(POOL_FLAG_NON_PAGED, - allocationSize, - CDROM_TAG_SCRATCH); - if (DeviceExtension->ScratchContext.ScratchHistory == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to allocate scratch history buffer\n" - )); - } - else - { - // must be initialized here... - DeviceExtension->ScratchContext.ScratchHistory->TotalHistoryCount = 20; - } - } - - // allocate the MDL - if (NT_SUCCESS(status)) - { - ULONG transferLength = 0; - - status = RtlULongAdd(DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes, PAGE_SIZE, &transferLength); - if (NT_SUCCESS(status)) - { - DeviceExtension->ScratchContext.PartialMdlIsBuilt = FALSE; - DeviceExtension->ScratchContext.PartialMdl = IoAllocateMdl(NULL, - transferLength, - FALSE, - FALSE, - NULL); - if (DeviceExtension->ScratchContext.PartialMdl == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "Failed to allocate MDL for %x byte buffer\n", - DeviceExtension->ScratchContext.ScratchBufferSize - )); - } - else - { - NT_ASSERT(DeviceExtension->ScratchContext.PartialMdl->Size >= - (CSHORT)(sizeof(MDL) + BYTES_TO_PAGES(DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes) * sizeof(PFN_NUMBER))); - } - } - else - { - status = STATUS_INTEGER_OVERFLOW; - } - } - - // cleanup on failure - if (!NT_SUCCESS(status)) - { - ScratchBuffer_Deallocate(DeviceExtension); - } - - return NT_SUCCESS(status); -} - - -VOID -ScratchBuffer_ResetItems( - _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN ResetRequestHistory - ) -/*++ - -Routine Description: - - reset scratch items for reuse. - -Arguments: - - DeviceExtension - device extension - ResetRequestHistory - reset history fields or not - -Return Value: - - none - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - WDF_REQUEST_REUSE_PARAMS reuseParams; - PIRP irp = NULL; - - NT_ASSERT(DeviceExtension->ScratchContext.ScratchHistory != NULL); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchSense != NULL); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchSrb != NULL); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchRequest != NULL); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchBufferSize != 0); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchBuffer != NULL); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchBufferMdl != NULL); - NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse != 0); - - irp = WdfRequestWdmGetIrp(DeviceExtension->ScratchContext.ScratchRequest); - - if (ResetRequestHistory) - { - PSRB_HISTORY history = DeviceExtension->ScratchContext.ScratchHistory; - RtlZeroMemory(history->History, sizeof(SRB_HISTORY_ITEM) * history->TotalHistoryCount); - history->ClassDriverUse[0] = 0; - history->ClassDriverUse[1] = 0; - history->ClassDriverUse[2] = 0; - history->ClassDriverUse[3] = 0; - history->UsedHistoryCount = 0; - } - - // re-use the KMDF request object - - // deassign the MdlAddress, this is the value we assign explicitly. - // this is to prevent WdfRequestReuse to release the Mdl unexpectly. - if (irp->MdlAddress) - { - irp->MdlAddress = NULL; - } - - WDF_REQUEST_REUSE_PARAMS_INIT(&reuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED); - status = WdfRequestReuse(DeviceExtension->ScratchContext.ScratchRequest, &reuseParams); - // WDF request to format the request befor sending it - if (NT_SUCCESS(status)) - { - // clean up completion routine. - WdfRequestSetCompletionRoutine(DeviceExtension->ScratchContext.ScratchRequest, NULL, NULL); - - status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget, - DeviceExtension->ScratchContext.ScratchRequest, - IOCTL_SCSI_EXECUTE_IN, - NULL, NULL, - NULL, NULL, - NULL, NULL); - if (!NT_SUCCESS(status)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "ScratchBuffer_ResetItems: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n", - status)); - } - } - - RtlZeroMemory(DeviceExtension->ScratchContext.ScratchSense, sizeof(SENSE_DATA)); - RtlZeroMemory(DeviceExtension->ScratchContext.ScratchSrb, sizeof(SCSI_REQUEST_BLOCK)); - - return; -} - - -NTSTATUS -ScratchBuffer_PerformNextReadWrite( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN FirstTry - ) -/*++ - -Routine Description: - - This function asynchronously sends the next read/write SRB down the stack. - -Arguments: - - DeviceExtension - Device extension - -Return Value: - - none - ---*/ -{ - PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext = &DeviceExtension->ScratchContext.ScratchReadWriteContext; - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(DeviceExtension->ScratchContext.ScratchRequest); - WDFREQUEST originalRequest = requestContext->OriginalRequest; - NTSTATUS status = STATUS_SUCCESS; - - ULONG transferSize; - BOOLEAN usePartialMdl; - - transferSize = min((readWriteContext->EntireXferLen - readWriteContext->TransferedBytes), readWriteContext->MaxLength); - - if (FirstTry) - { - DeviceExtension->ScratchContext.NumRetries = 0; - } - - ScratchBuffer_ResetItems(DeviceExtension, FALSE); - - usePartialMdl = (readWriteContext->PacketsCount > 1 || readWriteContext->TransferedBytes > 0); - - ScratchBuffer_SetupReadWriteSrb(DeviceExtension, - originalRequest, - readWriteContext->StartingOffset, - transferSize, - readWriteContext->DataBuffer, - readWriteContext->IsRead, - usePartialMdl - ); - - WdfRequestSetCompletionRoutine(DeviceExtension->ScratchContext.ScratchRequest, - ScratchBuffer_ReadWriteCompletionRoutine, DeviceExtension); - - status = ScratchBuffer_SendSrb(DeviceExtension, FALSE, (FirstTry ? &readWriteContext->SrbHistoryItem : NULL)); - - return status; -} - - -VOID -ScratchBuffer_ReadWriteTimerRoutine( - struct _KDPC *Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2 - ) -/*++ - -Routine Description: - - Timer routine for retrying read and write requests. - -Arguments: - - Timer - WDF timer - -Return Value: - - none - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = NULL; - PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext = NULL; - WDFREQUEST originalRequest = NULL; - PCDROM_REQUEST_CONTEXT requestContext = NULL; - NTSTATUS status = STATUS_SUCCESS; - KIRQL oldIrql; - - UNREFERENCED_PARAMETER(Dpc); - UNREFERENCED_PARAMETER(SystemArgument1); - UNREFERENCED_PARAMETER(SystemArgument2); - - if (DeferredContext == NULL) - { - // This is impossible, but definition of KDEFERRED_ROUTINE allows optional argument, - // and thus OACR will complain. - - return; - } - - originalRequest = (WDFREQUEST) DeferredContext; - requestContext = RequestGetContext(originalRequest); - - KeAcquireSpinLock(&requestContext->ReadWriteCancelSpinLock, &oldIrql); - - if (!requestContext->ReadWriteIsCompleted) - { - // As the first step, unregister the cancellation routine - status = WdfRequestUnmarkCancelable(originalRequest); - } - else - { - status = STATUS_CANCELLED; - } - - KeReleaseSpinLock(&requestContext->ReadWriteCancelSpinLock, oldIrql); - - if (status != STATUS_CANCELLED) - { - deviceExtension = requestContext->DeviceExtension; - readWriteContext = &deviceExtension->ScratchContext.ScratchReadWriteContext; - - // We use timer only for retries, that's why the second parameter is always FALSE - status = ScratchBuffer_PerformNextReadWrite(deviceExtension, FALSE); - - if (!NT_SUCCESS(status)) - { - ScratchBuffer_EndUse(deviceExtension); - RequestCompletion(deviceExtension, originalRequest, status, readWriteContext->TransferedBytes); - } - } - - // - // Drop the extra reference - // - WdfObjectDereference(originalRequest); -} - - -EVT_WDF_REQUEST_CANCEL ScratchBuffer_ReadWriteEvtRequestCancel; - -VOID -ScratchBuffer_ReadWriteEvtRequestCancel( - _In_ WDFREQUEST Request - ) -/*++ - -Routine Description: - - Cancels a request waiting for the read/write timer to expire. This function does not - support cancellation of requests that have already been sent down. - -Arguments: - - Request - WDF request - -Return Value: - - none - ---*/ -{ - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - PCDROM_DEVICE_EXTENSION deviceExtension = requestContext->DeviceExtension; - PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext = &deviceExtension->ScratchContext.ScratchReadWriteContext; - KIRQL oldIrql; - - KeAcquireSpinLock(&requestContext->ReadWriteCancelSpinLock, &oldIrql); - - if (KeCancelTimer(&requestContext->ReadWriteTimer)) - { - // - // Timer is canceled, we own the request. Drop the reference we took before - // queueing the timer. - // - WdfObjectDereference(Request); - } - else - { - // - // Timer will run and drop the reference but it won't complete the request - // because we set IsCompleted to TRUE - // - } - - requestContext->ReadWriteIsCompleted = TRUE; - - KeReleaseSpinLock(&requestContext->ReadWriteCancelSpinLock, oldIrql); - - ScratchBuffer_EndUse(deviceExtension); - - // If WdfTimerStop returned TRUE, it means this request was scheduled for a retry - // and the retry has not happened yet. We just need to cancel it and release the scratch buffer. - RequestCompletion(deviceExtension, Request, STATUS_CANCELLED, readWriteContext->TransferedBytes); -} - -VOID -ScratchBuffer_ReadWriteCompletionRoutine( - _In_ WDFREQUEST Request, - _In_ WDFIOTARGET Target, - _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, - _In_ WDFCONTEXT Context - ) -/*++ - -Routine Description: - - Read/write request completion routine. - -Arguments: - Request - WDF request - Target - The IO target the request was completed by. - Params - the request completion parameters - Context - context - -Return Value: - - none - ---*/ -{ - PCDROM_DEVICE_EXTENSION deviceExtension = (PCDROM_DEVICE_EXTENSION) Context; - PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext = &deviceExtension->ScratchContext.ScratchReadWriteContext; - NTSTATUS status = STATUS_SUCCESS; - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(deviceExtension->ScratchContext.ScratchRequest); - WDFREQUEST originalRequest = requestContext->OriginalRequest; - - if (!NT_SUCCESS(WdfRequestGetStatus(Request))) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, - "WdfRequestSend: %lx\n", - WdfRequestGetStatus(Request) - )); - } - - UNREFERENCED_PARAMETER(Params); - UNREFERENCED_PARAMETER(Target); - - // We are not calling ScratchBuffer_BeginUse / ScratchBuffer_EndUse in this function, because we already own - // the scratch buffer if this function is being called. - - if ((deviceExtension->ScratchContext.ScratchSrb->SrbStatus == SRB_STATUS_ABORTED) && - (deviceExtension->ScratchContext.ScratchSrb->InternalStatus == STATUS_CANCELLED)) - { - // The request has been cancelled, just need to complete it - } - else if (SRB_STATUS(deviceExtension->ScratchContext.ScratchSrb->SrbStatus) != SRB_STATUS_SUCCESS) - { - // The SCSI command that we sent down has failed, retry it if necessary - BOOLEAN shouldRetry = TRUE; - LONGLONG retryIn100nsUnits = 0; - - shouldRetry = RequestSenseInfoInterpretForScratchBuffer(deviceExtension, - deviceExtension->ScratchContext.NumRetries, - &status, - &retryIn100nsUnits); - - if (shouldRetry) - { - deviceExtension->ScratchContext.NumRetries++; - - if (retryIn100nsUnits == 0) - { - // We take a shortcut here by calling ScratchBuffer_PerformNextReadWrite directly: - // this helps to avoid unnecessary context switch. - status = ScratchBuffer_PerformNextReadWrite(deviceExtension, FALSE); - - if (NT_SUCCESS(status)) - { - // We're not done with the request yet, no need to complete it now - return; - } - } - else - { - PCDROM_REQUEST_CONTEXT originalRequestContext = RequestGetContext(originalRequest); - KIRQL oldIrql; - - // - // Initialize the spin lock and timer local to the original request. - // - if (!originalRequestContext->ReadWriteRetryInitialized) - { - KeInitializeSpinLock(&originalRequestContext->ReadWriteCancelSpinLock); - KeInitializeTimer(&originalRequestContext->ReadWriteTimer); - KeInitializeDpc(&originalRequestContext->ReadWriteDpc, ScratchBuffer_ReadWriteTimerRoutine, originalRequest); - originalRequestContext->ReadWriteRetryInitialized = TRUE; - } - - KeAcquireSpinLock(&requestContext->ReadWriteCancelSpinLock, &oldIrql); - - status = WdfRequestMarkCancelableEx(originalRequest, ScratchBuffer_ReadWriteEvtRequestCancel); - - if (status == STATUS_CANCELLED) - { - requestContext->ReadWriteIsCompleted = TRUE; - - KeReleaseSpinLock(&requestContext->ReadWriteCancelSpinLock, oldIrql); - } - else - { - LARGE_INTEGER t; - - t.QuadPart = -retryIn100nsUnits; - - WdfObjectReference(originalRequest); - - // Use negative time to indicate that we want a relative delay - KeSetTimer(&originalRequestContext->ReadWriteTimer, - t, - &originalRequestContext->ReadWriteDpc - ); - - KeReleaseSpinLock(&requestContext->ReadWriteCancelSpinLock, oldIrql); - - return; - } - } - } - } - else - { - // The SCSI command has succeeded - readWriteContext->DataBuffer += deviceExtension->ScratchContext.ScratchSrb->DataTransferLength; - readWriteContext->StartingOffset.QuadPart += deviceExtension->ScratchContext.ScratchSrb->DataTransferLength; - readWriteContext->TransferedBytes += deviceExtension->ScratchContext.ScratchSrb->DataTransferLength; - readWriteContext->PacketsCount--; - - // Update the SRB history item - if (readWriteContext->SrbHistoryItem) - { - ULONG senseSize; - - // Query the tick count and store in the history - KeQueryTickCount(&readWriteContext->SrbHistoryItem->TickCountCompleted); - - // Copy the SRB Status... - readWriteContext->SrbHistoryItem->SrbStatus = deviceExtension->ScratchContext.ScratchSrb->SrbStatus; - - // Determine the amount of valid sense data - if (deviceExtension->ScratchContext.ScratchSrb->SenseInfoBufferLength >= - RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength)) - { - PSENSE_DATA sense = (PSENSE_DATA)deviceExtension->ScratchContext.ScratchSrb->SenseInfoBuffer; - senseSize = RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength) + - sense->AdditionalSenseLength; - senseSize = min(senseSize, sizeof(SENSE_DATA)); - } - else - { - senseSize = deviceExtension->ScratchContext.ScratchSrb->SenseInfoBufferLength; - } - - // Normalize the sense data copy in the history - RtlZeroMemory(&(readWriteContext->SrbHistoryItem->NormalizedSenseData), sizeof(SENSE_DATA)); - RtlCopyMemory(&(readWriteContext->SrbHistoryItem->NormalizedSenseData), - deviceExtension->ScratchContext.ScratchSrb->SenseInfoBuffer, senseSize); - } - - // Check whether we need to send more SCSI commands to complete the request - if (readWriteContext->PacketsCount > 0) - { - status = ScratchBuffer_PerformNextReadWrite(deviceExtension, TRUE); - - if (NT_SUCCESS(status)) - { - // We're not done with the request yet, no need to complete it now - return; - } - } - } - - ScratchBuffer_EndUse(deviceExtension); - - - RequestCompletion(deviceExtension, originalRequest, status, readWriteContext->TransferedBytes); -} - -_IRQL_requires_max_(APC_LEVEL) -VOID -ScratchBuffer_SetupSrb( - _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_opt_ WDFREQUEST OriginalRequest, - _In_ ULONG MaximumTransferLength, - _In_ BOOLEAN GetDataFromDevice - ) -/*++ - -Routine Description: - - setup scratch SRB for sending out. - -Arguments: - - DeviceExtension - device extension - OriginalRequest - original request delivered by WDF - MaximumTransferLength - transfer length - GetDataFromDevice - TRUE (get data from device); FALSE (send data to device) - -Return Value: - - none - ---*/ -{ - WDFREQUEST request = DeviceExtension->ScratchContext.ScratchRequest; - PIRP irp = WdfRequestWdmGetIrp(request); - PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb; - PIO_STACK_LOCATION irpStack = NULL; - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(request); - - PAGED_CODE (); - - requestContext->OriginalRequest = OriginalRequest; - - // set to use the full scratch buffer via the scratch SRB - irpStack = IoGetNextIrpStackLocation(irp); - irpStack->MajorFunction = IRP_MJ_SCSI; - if (MaximumTransferLength == 0) - { - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_NONE; - } - else if (GetDataFromDevice) - { - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; - } - else - { - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_OUT; - } - irpStack->Parameters.Scsi.Srb = srb; - - if (MaximumTransferLength > 0) - { - // the Irp must show the MDL's address for the transfer - irp->MdlAddress = DeviceExtension->ScratchContext.ScratchBufferMdl; - - srb->DataBuffer = DeviceExtension->ScratchContext.ScratchBuffer; - } - - // prepare the SRB with default values - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - srb->SrbStatus = 0; - srb->ScsiStatus = 0; - srb->NextSrb = NULL; - srb->OriginalRequest = irp; - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - srb->SenseInfoBuffer = DeviceExtension->ScratchContext.ScratchSense; - - srb->CdbLength = 16; // to cause failures if not set correctly -- CD devices limited to 12 bytes for now... - - srb->DataTransferLength = min(DeviceExtension->ScratchContext.ScratchBufferSize, MaximumTransferLength); - srb->TimeOutValue = DeviceExtension->TimeOutValue; - srb->SrbFlags = DeviceExtension->SrbFlags; - SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); - SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE); - - if (MaximumTransferLength == 0) - { - SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_DATA_TRANSFER); - } - else if (GetDataFromDevice) - { - SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_IN); - } - else - { - SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_OUT); - } -} - - -NTSTATUS -ScratchBuffer_SendSrb( - _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ BOOLEAN SynchronousSrb, - _When_(SynchronousSrb, _Pre_null_) - _When_(!SynchronousSrb, _In_opt_) - PSRB_HISTORY_ITEM *SrbHistoryItem - ) -/*++ - -Routine Description: - - Send the command from the scratch SRB to lower driver and retry if necessary. - -Arguments: - - DeviceExtension - device extension - SynchronousSrb - indicates whether the SRB needs to be sent synchronously or nor - SrbHistoryItem - storage for SRB history item, if this is an asynchronous request - -Return Value: - - none - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb; - PSRB_HISTORY history = DeviceExtension->ScratchContext.ScratchHistory; - PSRB_HISTORY_ITEM item = NULL; - BOOLEAN requestCancelled = FALSE; - - srb->InternalStatus = 0; - srb->SrbStatus = 0; - - // allocate/update history pre-command, if it is a synchronous request or we were supplied - // with a storage for the history item - if (SynchronousSrb || SrbHistoryItem != NULL) - { - // sending a packet implies a new history unit is to be used. - NT_ASSERT( history->UsedHistoryCount <= history->TotalHistoryCount ); - - // if already all used up, remove at least one history unit - if (history->UsedHistoryCount == history->TotalHistoryCount ) - { - CompressSrbHistoryData(history); - NT_ASSERT( history->UsedHistoryCount < history->TotalHistoryCount ); - } - - // thus, since we are about to increment the count, it must now be less... - NT_ASSERT( history->UsedHistoryCount < history->TotalHistoryCount ); - - // increment the number of history units in use - history->UsedHistoryCount++; - - // determine index to use - item = &( history->History[ history->UsedHistoryCount-1 ] ); - - if (SrbHistoryItem != NULL) - { - *SrbHistoryItem = item; - } - - // zero out the history item - RtlZeroMemory(item, sizeof(SRB_HISTORY_ITEM)); - - // Query the tick count and store in the history - KeQueryTickCount(&item->TickCountSent); - } - - // get cancellation status; - { - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(DeviceExtension->ScratchContext.ScratchRequest); - - if (requestContext->OriginalRequest != NULL) - { - requestCancelled = WdfRequestIsCanceled(requestContext->OriginalRequest); - } - } - - if (!requestCancelled) - { - status = RequestSend(DeviceExtension, - DeviceExtension->ScratchContext.ScratchRequest, - DeviceExtension->IoTarget, - SynchronousSrb ? WDF_REQUEST_SEND_OPTION_SYNCHRONOUS : 0, - NULL); - - // If this is a synchronous request, update the history item immediately, including "normalized" sense data - if (SynchronousSrb) - { - ULONG senseSize; - - // Query the tick count and store in the history - KeQueryTickCount(&item->TickCountCompleted); - - // Copy the SRB Status - item->SrbStatus = srb->SrbStatus; - - // Determine the amount of valid sense data - if (srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength)) - { - PSENSE_DATA sense = (PSENSE_DATA)srb->SenseInfoBuffer; - senseSize = RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength) + - sense->AdditionalSenseLength; - senseSize = min(senseSize, sizeof(SENSE_DATA)); - } - else - { - senseSize = srb->SenseInfoBufferLength; - } - - // Normalize the sense data copy in the history - RtlZeroMemory(&(item->NormalizedSenseData), sizeof(SENSE_DATA)); - RtlCopyMemory(&(item->NormalizedSenseData), srb->SenseInfoBuffer, senseSize); - } - } - else - { - DeviceExtension->ScratchContext.ScratchSrb->SrbStatus = SRB_STATUS_ABORTED; - DeviceExtension->ScratchContext.ScratchSrb->InternalStatus = (ULONG)STATUS_CANCELLED; - status = STATUS_CANCELLED; - } - - return status; -} - -VOID -CompressSrbHistoryData( - _Inout_ PSRB_HISTORY RequestHistory - ) -/*++ - -Routine Description: - - compress the SRB history data. - -Arguments: - - RequestHistory - SRB history data - -Return Value: - - RequestHistory - compressed history data - ---*/ -{ - ULONG i; - NT_ASSERT( RequestHistory->UsedHistoryCount == RequestHistory->TotalHistoryCount ); - ValidateSrbHistoryDataPresumptions(RequestHistory); - - for (i=0; i < RequestHistory->UsedHistoryCount; i++) - { - // for each item... - PSRB_HISTORY_ITEM toMatch = &( RequestHistory->History[i] ); - // hint: read const qualifiers backwards. i.e. srbstatus is a const UCHAR - // so, "UCHAR const * const x" is read "x is a const pointer to a const UCHAR" - // unfortunately, "const UCHAR" is equivalent to "UCHAR const", which causes - // people no end of confusion due to its widespread use. - UCHAR const srbStatus = toMatch->SrbStatus; - UCHAR const sense = toMatch->NormalizedSenseData.SenseKey; - UCHAR const asc = toMatch->NormalizedSenseData.AdditionalSenseCode; - UCHAR const ascq = toMatch->NormalizedSenseData.AdditionalSenseCodeQualifier; - ULONG j; - - // see if there are any at higher indices with identical Sense/ASC/ASCQ - for (j = i+1; (toMatch->ClassDriverUse != 0xFF) && (j < RequestHistory->UsedHistoryCount); j++) - { - PSRB_HISTORY_ITEM found = &( RequestHistory->History[j] ); - // close enough match? - if ((srbStatus == found->SrbStatus) && - (sense == found->NormalizedSenseData.SenseKey) && - (asc == found->NormalizedSenseData.AdditionalSenseCode) && - (ascq == found->NormalizedSenseData.AdditionalSenseCodeQualifier)) { - - // add the fields to keep reasonable track of delay times. - if (toMatch->MillisecondsDelayOnRetry + found->MillisecondsDelayOnRetry < toMatch->MillisecondsDelayOnRetry) { - toMatch->MillisecondsDelayOnRetry = MAXULONG; - } else { - toMatch->MillisecondsDelayOnRetry += found->MillisecondsDelayOnRetry; - } - - // this found item cannot contain any compressed entries because - // the first entry with a given set of sense/asc/ascq will always - // either be full (0xFF) or be the only partially-full entry with - // that sense/asc/ascq. - NT_ASSERT(found->ClassDriverUse == 0); - // add the counts so we still know how many retries total - toMatch->ClassDriverUse++; - - - // if not the last entry, need to move later entries earlier in the array - if (j != RequestHistory->UsedHistoryCount-1) { - // how many entries remain? - SIZE_T remainingBytes = RequestHistory->UsedHistoryCount - 1 - j; - remainingBytes *= sizeof(SRB_HISTORY_ITEM); - - // note that MOVE is required due to overlapping entries - RtlMoveMemory(found, found+1, remainingBytes); - - // Finally, decrement the number of used history count and - // decrement j to rescan the current location again - --RequestHistory->UsedHistoryCount; - --j; - } // end moving of array elements around - } // end of close enough match - } // end j loop - } // end i loop - - // unable to compress duplicate sense/asc/ascq, so just lose the most recent data - if (RequestHistory->UsedHistoryCount == RequestHistory->TotalHistoryCount) - { - PSRB_HISTORY_ITEM item = &( RequestHistory->History[ RequestHistory->TotalHistoryCount-1 ] ); - RequestHistory->ClassDriverUse[0] += item->ClassDriverUse; // how many did we "lose"? - RequestHistory->UsedHistoryCount--; - } - - // finally, zero any that are no longer in use - NT_ASSERT( RequestHistory->UsedHistoryCount != RequestHistory->TotalHistoryCount); - { - SIZE_T bytesToZero = RequestHistory->TotalHistoryCount - RequestHistory->UsedHistoryCount; - bytesToZero *= sizeof(SRB_HISTORY_ITEM); - RtlZeroMemory(&(RequestHistory->History[RequestHistory->UsedHistoryCount]), bytesToZero); - } - - ValidateSrbHistoryDataPresumptions(RequestHistory); - return; -} - -VOID -ValidateSrbHistoryDataPresumptions( - _In_ SRB_HISTORY const * RequestHistory - ) -{ -#if DBG - // validate that all fully-compressed items are before any non-fully-compressed items of any particular sense/asc/ascq - // validate that there is at most one partially-compressed item of any particular sense/asc/ascq - // validate that all items of any particular sense/asc/ascq that are uncompressed are at the end - // THUS: A(255) A(255) A( 40) A( 0) A( 0) is legal for all types with A as sense/asc/ascq - // A(0) B(255) A( 0) B( 17) B( 0) is also legal because A/B are different types of error - - ULONG i; - for (i = 0; i < RequestHistory->UsedHistoryCount; i++) - { - SRB_HISTORY_ITEM const * toMatch = &( RequestHistory->History[i] ); - UCHAR const srbStatus = toMatch->SrbStatus; - UCHAR const sense = toMatch->NormalizedSenseData.SenseKey; - UCHAR const asc = toMatch->NormalizedSenseData.AdditionalSenseCode; - UCHAR const ascq = toMatch->NormalizedSenseData.AdditionalSenseCodeQualifier; - ULONG j; - - BOOLEAN foundPartiallyCompressedItem = - (toMatch->ClassDriverUse != 0) && - (toMatch->ClassDriverUse != 0xFF) ; - BOOLEAN foundUncompressedItem = - (toMatch->ClassDriverUse == 0) ; - - for (j = i+1; j < RequestHistory->UsedHistoryCount; j++) - { - SRB_HISTORY_ITEM const * found = &( RequestHistory->History[j] ); - if ((srbStatus == found->SrbStatus) && - (sense == found->NormalizedSenseData.SenseKey) && - (asc == found->NormalizedSenseData.AdditionalSenseCode) && - (ascq == found->NormalizedSenseData.AdditionalSenseCodeQualifier) - ) - { - // found a matching type, so validate ordering rules - if (foundUncompressedItem && (found->ClassDriverUse != 0)) - { - DbgPrintEx(DPFLTR_CDROM_ID, DPFLTR_ERROR_LEVEL, - "History data has compressed history following uncompressed history " - "for srbstatus/sense/asc/ascq of %02x/%02x/%02x/%02x at indices %d (%08x) and %d (%08x)\n", - srbStatus, sense, asc, ascq, - i,i, j,j - ); - NT_ASSERT(FALSE); - } - else if (foundPartiallyCompressedItem && (found->ClassDriverUse == 0xFF)) - { - DbgPrintEx(DPFLTR_CDROM_ID, DPFLTR_ERROR_LEVEL, - "History data has fully compressed history following partially compressed history " - "for srbstatus/sense/asc/ascq of %02x/%02x/%02x/%02x at indices %d (%08x) and %d (%08x)\n", - srbStatus, sense, asc, ascq, - i,i, j,j - ); - NT_ASSERT(FALSE); - } - - // update if we have now found partially compressed and/or uncompressed items - if (found->ClassDriverUse == 0) - { - foundUncompressedItem = TRUE; - } - else if (found->ClassDriverUse != 0xFF) - { - foundPartiallyCompressedItem = TRUE; - } - } // end match of (toMatch,found) - } // end loop j - } // end loop i -#else - UNREFERENCED_PARAMETER(RequestHistory); -#endif - return; -} - -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 - ) -/*++ - -Routine Description: - - setup SRB for read/write request. - -Arguments: - - DeviceExtension - device extension - OriginalRequest - read/write request - StartingOffset - read/write starting offset - DataBuffer - buffer for read/write - IsReadRequest - TRUE (read); FALSE (write) - -Return Value: - - none - ---*/ -{ - //NOTE: R/W request not use the ScratchBuffer, instead, it uses the buffer associated with IRP. - - PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb; - PCDB cdb = (PCDB)srb->Cdb; - LARGE_INTEGER logicalBlockAddr; - ULONG numTransferBlocks; - - PIRP originalIrp = WdfRequestWdmGetIrp(OriginalRequest); - - PIRP irp = WdfRequestWdmGetIrp(DeviceExtension->ScratchContext.ScratchRequest); - PIO_STACK_LOCATION irpStack = NULL; - - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(DeviceExtension->ScratchContext.ScratchRequest); - - requestContext->OriginalRequest = OriginalRequest; - - - logicalBlockAddr.QuadPart = Int64ShrlMod32(StartingOffset.QuadPart, DeviceExtension->SectorShift); - numTransferBlocks = RequiredLength >> DeviceExtension->SectorShift; - - // set to use the full scratch buffer via the scratch SRB - irpStack = IoGetNextIrpStackLocation(irp); - irpStack->MajorFunction = IRP_MJ_SCSI; - if (IsReadRequest) - { - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; - } - else - { - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_OUT; - } - irpStack->Parameters.Scsi.Srb = srb; - - // prepare the SRB with default values - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - srb->SrbStatus = 0; - srb->ScsiStatus = 0; - srb->NextSrb = NULL; - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - srb->SenseInfoBuffer = DeviceExtension->ScratchContext.ScratchSense; - - srb->DataBuffer = DataBuffer; - srb->DataTransferLength = RequiredLength; - - srb->QueueSortKey = logicalBlockAddr.LowPart; - if (logicalBlockAddr.QuadPart > 0xFFFFFFFF) - { - // - // If the requested LBA is more than max ULONG set the - // QueueSortKey to the maximum value, so that these - // requests can be added towards the end of the queue. - // - srb->QueueSortKey = 0xFFFFFFFF; - } - - srb->OriginalRequest = irp; - srb->TimeOutValue = DeviceExtension->TimeOutValue; - - if (RequestIsRealtimeStreaming(OriginalRequest, IsReadRequest) && - !TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_STREAMING)) - { - if (IsReadRequest) - { - RtlZeroMemory(&cdb->READ12, sizeof(cdb->READ12)); - REVERSE_BYTES(&cdb->READ12.LogicalBlock, &logicalBlockAddr.LowPart); - REVERSE_BYTES(&cdb->READ12.TransferLength, &numTransferBlocks); - cdb->READ12.Streaming = 1; - cdb->READ12.OperationCode = SCSIOP_READ12; - srb->CdbLength = sizeof(cdb->READ12); - } - else - { - RtlZeroMemory(&cdb->WRITE12, sizeof(cdb->WRITE12)); - REVERSE_BYTES(&cdb->WRITE12.LogicalBlock, &logicalBlockAddr.LowPart); - REVERSE_BYTES(&cdb->WRITE12.TransferLength, &numTransferBlocks); - cdb->WRITE12.Streaming = 1; - cdb->WRITE12.OperationCode = SCSIOP_WRITE12; - srb->CdbLength = sizeof(cdb->WRITE12); - } - } - else - { - RtlZeroMemory(&cdb->CDB10, sizeof(cdb->CDB10)); - cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte3; - cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte2; - cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte1; - cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte0; - cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1; - cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0; - cdb->CDB10.OperationCode = (IsReadRequest) ? SCSIOP_READ : SCSIOP_WRITE; - srb->CdbLength = sizeof(cdb->CDB10); - } - - // Set SRB and IRP flags - srb->SrbFlags = DeviceExtension->SrbFlags; - if (TEST_FLAG(originalIrp->Flags, IRP_PAGING_IO) || - TEST_FLAG(originalIrp->Flags, IRP_SYNCHRONOUS_PAGING_IO)) - { - SET_FLAG(srb->SrbFlags, SRB_CLASS_FLAGS_PAGING); - } - - SET_FLAG(srb->SrbFlags, (IsReadRequest) ? SRB_FLAGS_DATA_IN : SRB_FLAGS_DATA_OUT); - SET_FLAG(srb->SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE); - - // - // If the request is not split, we can use the original IRP MDL. If the - // request needs to be split, we need to use a partial MDL. The partial MDL - // is needed because more than one driver might be mapping the same MDL - // and this causes problems. - // - if (UsePartialMdl == FALSE) - { - irp->MdlAddress = originalIrp->MdlAddress; - } - else - { - if (DeviceExtension->ScratchContext.PartialMdlIsBuilt != FALSE) - { - MmPrepareMdlForReuse(DeviceExtension->ScratchContext.PartialMdl); - } - - IoBuildPartialMdl(originalIrp->MdlAddress, DeviceExtension->ScratchContext.PartialMdl, srb->DataBuffer, srb->DataTransferLength); - DeviceExtension->ScratchContext.PartialMdlIsBuilt = TRUE; - irp->MdlAddress = DeviceExtension->ScratchContext.PartialMdl; - } - - //DBGLOGSENDPACKET(Pkt); - //HISTORYLOGSENDPACKET(Pkt); - - // - // Set the original irp here for SFIO. - // - srb->SrbExtension = (PVOID)(originalIrp); - - return; -} - -_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 - ) -/*++ - -Routine Description: - - Use Scratch buffer to send the Cdb, check error and retry if necessary. - -Arguments: - - DeviceExtension - device context - OriginalRequest - original request that requires this CDB operation - TransferSize - Data transfer size required - GetFromDevice - TRUE if getting data from device. - Cdb - SCSI command - OprationLength - SCSI command length: 6, 10 or 12 - TimeoutValue - if > 0, use it as timeout value for command - if 0, use the default device timeout value - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb; - PCDB cdb = (PCDB)(srb->Cdb); - - BOOLEAN shouldRetry = TRUE; - ULONG timesAlreadyRetried = 0; - LONGLONG retryIn100nsUnits = 0; - - PAGED_CODE (); - - while (shouldRetry) - { - ScratchBuffer_SetupSrb(DeviceExtension, OriginalRequest, TransferSize, GetDataFromDevice); - - // Set up the SRB/CDB - RtlCopyMemory(cdb, Cdb, sizeof(CDB)); - - srb->CdbLength = OprationLength; - - if (TimeoutValue > 0) - { - srb->TimeOutValue = TimeoutValue; - } - - ScratchBuffer_SendSrb(DeviceExtension, TRUE, NULL); - - if ((DeviceExtension->ScratchContext.ScratchSrb->SrbStatus == SRB_STATUS_ABORTED) && - (DeviceExtension->ScratchContext.ScratchSrb->InternalStatus == STATUS_CANCELLED)) - { - shouldRetry = FALSE; - status = STATUS_CANCELLED; - } - else - { - shouldRetry = RequestSenseInfoInterpretForScratchBuffer(DeviceExtension, - timesAlreadyRetried, - &status, - &retryIn100nsUnits); - if (shouldRetry) - { - LARGE_INTEGER t; - t.QuadPart = -retryIn100nsUnits; - timesAlreadyRetried++; - KeDelayExecutionThread(KernelMode, FALSE, &t); - // keep items clean - ScratchBuffer_ResetItems(DeviceExtension, FALSE); - } - } - } - - return status; -} - - diff --git a/storage/class/cdrom/src/scratch.h b/storage/class/cdrom/src/scratch.h deleted file mode 100644 index 92d75328..00000000 --- a/storage/class/cdrom/src/scratch.h +++ /dev/null @@ -1,187 +0,0 @@ -/*++ - -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__ diff --git a/storage/class/cdrom/src/sense.c b/storage/class/cdrom/src/sense.c deleted file mode 100644 index 7033c6ce..00000000 --- a/storage/class/cdrom/src/sense.c +++ /dev/null @@ -1,2600 +0,0 @@ -/*-- - -Copyright (C) Microsoft Corporation. All rights reserved. - -Module Name: - - sense.c - -Abstract: - - This file contains the methods needed to accurately - determine how to retry requests on CDROM device types. - -Environment: - - kernel mode only - -Revision History: - ---*/ - -#include "stddef.h" -#include "string.h" - -#include "ntddk.h" -#include "ntddstor.h" -#include "cdrom.h" -#include "ntstrsafe.h" - - -#ifdef DEBUG_USE_WPP -#include "sense.tmh" -#endif - -// Forward declarations -VOID -SenseInfoInterpretRefineByIoControl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG IoControlCode, - _In_ BOOLEAN OverrideVerifyVolume, - _Inout_ BOOLEAN* Retry, - _Inout_ NTSTATUS* Status - ); - - -#ifdef ALLOC_PRAGMA - -#pragma alloc_text(PAGE, SenseInfoInterpretRefineByIoControl) - -#endif - - -// -// FROM CLASSPNP\CLASSP.H -// 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 TOTAL_COUNT_RETRY_DEFAULT 4 -#define TOTAL_COUNT_RETRY_LOCK_MEDIA 1 -#define TOTAL_COUNT_RETRY_MODESENSE 1 -#define TOTAL_COUNT_RETRY_READ_CAPACITY 1 - - -#define TOTAL_SECONDS_RETRY_TIME_WRITE 160 -#define TOTAL_SECONDS_RETRY_TIME_MEDIUM_REMOVAL 120 - -typedef struct _ERROR_LOG_CONTEXT { - BOOLEAN LogError; - BOOLEAN ErrorUnhandled; - NTSTATUS ErrorCode; - ULONG UniqueErrorValue; - ULONG BadSector; -} ERROR_LOG_CONTEXT, *PERROR_LOG_CONTEXT; - -NTSTATUS -DeviceErrorHandlerForMmc( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _Inout_ PNTSTATUS Status, - _Inout_ PBOOLEAN Retry - ) -/*++ - -Routine Description: - - this routine will be used for error handler for all MMC devices. - it's invoked by DeviceErrorHandler()that invoked by SenseInfoInterpret() or GESN - - This routine just checks for media change sense/asc/ascq and - also for other events, such as bus resets. this is used to - determine if the device behaviour has changed, to allow for - read and write operations to be allowed and/or disallowed. - -Arguments: - - DeviceExtension - device context - Srb - SRB structure for analyze - -Return Value: - - NTSTATUS - Status - - Retry - - ---*/ -{ - BOOLEAN mediaChange = FALSE; - PCDB cdb = (PCDB)Srb->Cdb; - - if (TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID)) - { - PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; - - // the following sense keys could indicate a change in capabilities. - - // we used to expect this to be serialized, and only hit from our - // own routine. we now allow some requests to continue during our - // processing of the capabilities update in order to allow - // IoReadPartitionTable() to succeed. - switch (senseBuffer->SenseKey & 0xf) - { - - case SCSI_SENSE_NOT_READY: - { - if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE) - { - if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: media removed, writes will be " - "failed until new media detected\n")); - } - - // NOTE - REF #0002 - DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE; - } - else if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) - { - if (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_BECOMING_READY) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: media becoming ready, " - "SHOULD notify shell of change time by sending " - "GESN request immediately!\n")); - } - else if (((senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_OPERATION_IN_PROGRESS) || - (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS) - ) && - ((Srb->Cdb[0] == SCSIOP_READ) || - (Srb->Cdb[0] == SCSIOP_READ6) || - (Srb->Cdb[0] == SCSIOP_READ_CAPACITY) || - (Srb->Cdb[0] == SCSIOP_READ_CD) || - (Srb->Cdb[0] == SCSIOP_READ_CD_MSF) || - (Srb->Cdb[0] == SCSIOP_READ_TOC) || - (Srb->Cdb[0] == SCSIOP_WRITE) || - (Srb->Cdb[0] == SCSIOP_WRITE6) || - (Srb->Cdb[0] == SCSIOP_READ_TRACK_INFORMATION) || - (Srb->Cdb[0] == SCSIOP_READ_DISK_INFORMATION) - ) - ) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: LONG_WRITE or " - "OP_IN_PROGRESS for limited subset of cmds -- " - "setting retry to TRUE\n")); - *Retry = TRUE; - *Status = STATUS_DEVICE_BUSY; - } - } - break; - } // end SCSI_SENSE_NOT_READY - - case SCSI_SENSE_UNIT_ATTENTION: - { - switch (senseBuffer->AdditionalSenseCode) - { - case SCSI_ADSENSE_MEDIUM_CHANGED: - { - // always update if the medium may have changed - - // NOTE - REF #0002 - DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE; - DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: media change detected, need to " - "update drive capabilities\n")); - mediaChange = TRUE; - break; - - } // end SCSI_ADSENSE_MEDIUM_CHANGED - - case SCSI_ADSENSE_BUS_RESET: - { - // NOTE - REF #0002 - DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE; - DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: bus reset detected, need to " - "update drive capabilities\n")); - break; - - } // end SCSI_ADSENSE_BUS_RESET - - case SCSI_ADSENSE_OPERATOR_REQUEST: - { - - BOOLEAN b = FALSE; - - switch (senseBuffer->AdditionalSenseCodeQualifier) - { - case SCSI_SENSEQ_MEDIUM_REMOVAL: - { - // eject notification currently handled by classpnp - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: Eject requested by user\n")); - *Retry = TRUE; - *Status = STATUS_DEVICE_BUSY; - break; - } - - case SCSI_SENSEQ_WRITE_PROTECT_DISABLE: - b = TRUE; - case SCSI_SENSEQ_WRITE_PROTECT_ENABLE: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: Write protect %s requested " - "by user\n", - (b ? "disable" : "enable"))); - *Retry = TRUE; - *Status = STATUS_DEVICE_BUSY; - // NOTE - REF #0002 - DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE; - DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired; - - break; - } - - } // end of AdditionalSenseCodeQualifier switch - - - break; - - } // end SCSI_ADSENSE_OPERATOR_REQUEST - - default: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: Unit attention %02x/%02x\n", - senseBuffer->AdditionalSenseCode, - senseBuffer->AdditionalSenseCodeQualifier)); - break; - } - - } // end of AdditionSenseCode switch - break; - - } // end SCSI_SENSE_UNIT_ATTENTION - - case SCSI_SENSE_ILLEGAL_REQUEST: - { - if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_WRITE_PROTECT) - { - if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: media was writable, but " - "failed request with WRITE_PROTECT error...\n")); - } - // NOTE - REF #0002 - // do not update all the capabilities just because - // we can't write to the disc. - DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE; - } - break; - } // end SCSI_SENSE_ILLEGAL_REQUEST - - } // end of SenseKey switch - - // Check if we failed to set the DVD region key and send appropriate error - if (cdb->CDB16.OperationCode == SCSIOP_SEND_KEY) - { - if (cdb->SEND_KEY.KeyFormat == DvdSetRpcKey) - { - if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE) - { - // media of appropriate region required - *Status = STATUS_NO_MEDIA_IN_DEVICE; - *Retry = FALSE; - } - else if ((senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) && - (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_COPY_PROTECTION_FAILURE) && - (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT)) - { - // media of appropriate region required - *Status = STATUS_CSS_REGION_MISMATCH; - *Retry = FALSE; - } - else if ((senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) && - (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_INVALID_MEDIA) && - (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_INCOMPATIBLE_FORMAT)) - { - // media of appropriate region required - *Status = STATUS_CSS_REGION_MISMATCH; - *Retry = FALSE; - } - } - } - } // end of SRB_STATUS_AUTOSENSE_VALID - - // On media change, if device speed should be reset to default then - // queue a workitem to send the commands to the device. Do this on - // media arrival as some device will fail this command if no media - // is present. Ignore the fake media change from classpnp driver. - if ((mediaChange == TRUE) && (*Status != STATUS_MEDIA_CHANGED)) - { - if (DeviceExtension->DeviceAdditionalData.RestoreDefaults == TRUE) - { - NTSTATUS status = STATUS_SUCCESS; - WDF_OBJECT_ATTRIBUTES attributes; - WDF_WORKITEM_CONFIG workitemConfig; - WDFWORKITEM workItem; - - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = DeviceExtension->Device; - - WDF_WORKITEM_CONFIG_INIT(&workitemConfig, - DeviceRestoreDefaultSpeed); - - status = WdfWorkItemCreate(&workitemConfig, - &attributes, - &workItem); - if (!NT_SUCCESS(status)) - { - return STATUS_SUCCESS; - } - - WdfWorkItemEnqueue(workItem); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForMmc: Restore device default speed for %p\n", - DeviceExtension->DeviceObject)); - } - } - return STATUS_SUCCESS; -} - -NTSTATUS -DeviceErrorHandlerForHitachiGD2000( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _Inout_ PNTSTATUS Status, - _Inout_ PBOOLEAN Retry - ) -/*++ - -Routine Description: - - error handler for HITACHI CDR-1750S, CDR-3650/1650S - - This routine checks the type of error. If the error suggests that the - drive has spun down and cannot reinitialize itself, send a - START_UNIT or READ to the device. This will force the drive to spin - up. This drive also loses the AGIDs it has granted when it spins down, - which may result in playback failure the first time around. - -Arguments: - - DeviceExtension - the device object. - - Srb - Supplies a pointer to the failing Srb. - - Status - return the final status for this command? - - Retry - return if the command should be retried. - -Return Value: - - None. - ---*/ -{ - PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; - - if (!TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID)) - { - return STATUS_SUCCESS; //nobody cares about this return value yet. - } - - if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_HARDWARE_ERROR) && - (senseBuffer->AdditionalSenseCode == 0x44)) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "DeviceErrorHandlerForHitachiGD2000 (%p) => Internal Target " - "Failure Detected -- spinning up drive\n", DeviceExtension->Device)); - - // the request should be retried because the device isn't ready - *Retry = TRUE; - *Status = STATUS_DEVICE_NOT_READY; - - // send a START_STOP unit to spin up the drive - // NOTE: this temporarily violates the StartIo serialization - // mechanism, but the completion routine on this will NOT - // call StartNextPacket(), so it's a temporary disruption - // of the serialization only. - DeviceSendStartUnit(DeviceExtension->Device); - } - - return STATUS_SUCCESS; -} - - -VOID -SenseInfoRequestGetInformation( - _In_ WDFREQUEST Request, - _Out_ UCHAR* MajorFunctionCode, - _Out_ ULONG* IoControlCode, - _Out_ BOOLEAN* OverrideVerifyVolume, - _Out_ ULONGLONG* Total100nsSinceFirstSend - ) -{ - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - - *MajorFunctionCode = 0; - *IoControlCode = 0; - *OverrideVerifyVolume = FALSE; - *Total100nsSinceFirstSend = 0; - - if (requestContext->OriginalRequest != NULL) - { - PIO_STACK_LOCATION originalIrpStack = NULL; - - PIRP originalIrp = WdfRequestWdmGetIrp(requestContext->OriginalRequest); - - if (originalIrp != NULL) - { - originalIrpStack = IoGetCurrentIrpStackLocation(originalIrp); - } - - if (originalIrpStack != NULL) - { - *MajorFunctionCode = originalIrpStack->MajorFunction; - - if (*MajorFunctionCode == IRP_MJ_DEVICE_CONTROL) - { - *IoControlCode = originalIrpStack->Parameters.DeviceIoControl.IoControlCode; - } - - *OverrideVerifyVolume = TEST_FLAG(originalIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME); - } - } - - // Calculate time past since the request was first time sent. - if (requestContext->TimeSentDownFirstTime.QuadPart > 0) - { - LARGE_INTEGER tmp; - KeQueryTickCount(&tmp); - tmp.QuadPart -= requestContext->TimeSentDownFirstTime.QuadPart; - tmp.QuadPart *= KeQueryTimeIncrement(); - *Total100nsSinceFirstSend = tmp.QuadPart; - } - else - { - // set to -1 if field TimeSentDownFirstTime not set. - *Total100nsSinceFirstSend = (ULONGLONG) -1; - } - - return; -} - -BOOLEAN -SenseInfoInterpretByAdditionalSenseCode( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_ UCHAR AdditionalSenseCode, - _In_ UCHAR AdditionalSenseCodeQual, - _Inout_ NTSTATUS* Status, - _Inout_ BOOLEAN* Retry, - _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds, - _Inout_ PERROR_LOG_CONTEXT LogContext - ) -/* - This function will interpret error based on ASC/ASCQ. - - If the error code is not processed in this function, e.g. return value is TRUE, - caller needs to call SenseInfoInterpretBySenseKey() for further interpret. -*/ -{ - BOOLEAN needFurtherInterpret = TRUE; - PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; - - // set default values for retry fields. - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - *RetryIntervalInSeconds = 0; - - switch (AdditionalSenseCode) - { - case SCSI_ADSENSE_LUN_NOT_READY: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Lun not ready\n")); - - // - // Many non-WHQL certified drives (mostly CD-RW) return - // 2/4/0 when they have no media instead of the obvious choice of: - // - // SCSI_SENSE_NOT_READY/SCSI_ADSENSE_NO_MEDIA_IN_DEVICE - // - // These drives should not pass WHQL certification due to this discrepency. - // - // However, we have to retry on 2/4/0 (Not ready, LUN not ready, no info) - // and also 3/2/0 (no seek complete). - // - // These conditions occur when the shell tries to examine an - // injected CD (e.g. for autoplay) before the CD is spun up. - // - // The drive should be returning an ASCQ of SCSI_SENSEQ_BECOMING_READY - // (0x01) in order to comply with WHQL standards. - // - // The default retry timeout of one second is acceptable to balance - // these discrepencies. don't modify the status, though.... - // - - switch (AdditionalSenseCodeQual) - { - case SCSI_SENSEQ_OPERATION_IN_PROGRESS: - { - DEVICE_EVENT_BECOMING_READY notReady = {0}; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Operation In Progress\n")); - - needFurtherInterpret = FALSE; - - *Retry = TRUE; - *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL; - *Status = STATUS_DEVICE_NOT_READY; - - notReady.Version = 1; - notReady.Reason = 2; - notReady.Estimated100msToReady = *RetryIntervalInSeconds * 10; - DeviceSendNotification(DeviceExtension, - &GUID_IO_DEVICE_BECOMING_READY, - sizeof(DEVICE_EVENT_BECOMING_READY), - ¬Ready); - - break; - } - - case SCSI_SENSEQ_BECOMING_READY: - { - DEVICE_EVENT_BECOMING_READY notReady = {0}; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: In process of becoming ready\n")); - - needFurtherInterpret = FALSE; - - *Retry = TRUE; - *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL; - *Status = STATUS_DEVICE_NOT_READY; - - notReady.Version = 1; - notReady.Reason = 1; - notReady.Estimated100msToReady = *RetryIntervalInSeconds * 10; - DeviceSendNotification(DeviceExtension, - &GUID_IO_DEVICE_BECOMING_READY, - sizeof(DEVICE_EVENT_BECOMING_READY), - ¬Ready); - - break; - } - - case SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Long write in progress\n")); - - needFurtherInterpret = FALSE; - - // This has been seen as a transcient failure on some drives - *Status = STATUS_DEVICE_NOT_READY; - *Retry = TRUE; - // Set retry interval to be 0 as the drive can be ready at anytime. - *RetryIntervalInSeconds = 0; - - break; - } - - case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Manual intervention required\n")); - - needFurtherInterpret = FALSE; - - *Status = STATUS_NO_MEDIA_IN_DEVICE; - *Retry = FALSE; - *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL; - - break; - } - - case SCSI_SENSEQ_FORMAT_IN_PROGRESS: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Format in progress\n")); - - needFurtherInterpret = FALSE; - - *Status = STATUS_DEVICE_NOT_READY; - *Retry = FALSE; - *RetryIntervalInSeconds = NOT_READY_RETRY_INTERVAL; - - break; - } - - case SCSI_SENSEQ_CAUSE_NOT_REPORTABLE: - case SCSI_SENSEQ_INIT_COMMAND_REQUIRED: - default: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Initializing command required\n")); - - needFurtherInterpret = FALSE; - - *Status = STATUS_DEVICE_NOT_READY; - *Retry = TRUE; - *RetryIntervalInSeconds = 0; - - // This sense code/additional sense code combination may indicate - // that the device needs to be started. - if (TEST_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT) && - !TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_LOW_PRIORITY)) - { - DeviceSendStartUnit(DeviceExtension->Device); - } - - break; - } - } // end switch (AdditionalSenseCodeQual) - break; - - } // end case (SCSI_ADSENSE_LUN_NOT_READY) - - case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE: - { - TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: No Media in device.\n")); - - needFurtherInterpret = FALSE; - - *Status = STATUS_NO_MEDIA_IN_DEVICE; - *Retry = FALSE; - - if (AdditionalSenseCodeQual == 0xCC) - { - // The IMAPIv1 filter returns this ASCQ value while it is burning CD media, and we want - // to preserve this functionality for compatibility reasons. - // We want to indicate that the media is not present to most applications; - // but RSM has to know that the media is still in the drive (i.e. the drive is not free). - DeviceSetMediaChangeStateEx(DeviceExtension, MediaUnavailable, NULL); - } - else - { - DeviceSetMediaChangeStateEx(DeviceExtension, MediaNotPresent, NULL); - } - - break; - } // end case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE - - case SCSI_ADSENSE_INVALID_MEDIA: - { - switch (AdditionalSenseCodeQual) - { - - case SCSI_SENSEQ_UNKNOWN_FORMAT: - { - needFurtherInterpret = FALSE; - - // Log error only if this is a paging request - *Status = STATUS_UNRECOGNIZED_MEDIA; - *Retry = FALSE; - - LogContext->LogError = TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING); - LogContext->UniqueErrorValue = 256; - LogContext->ErrorCode = IO_ERR_BAD_BLOCK; - - break; - } - - case SCSI_SENSEQ_INCOMPATIBLE_FORMAT: - { - needFurtherInterpret = FALSE; - - *Status = STATUS_UNRECOGNIZED_MEDIA; - *Retry = FALSE; - - LogContext->LogError = FALSE; - - break; - } - - case SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED: - { - needFurtherInterpret = FALSE; - - *Status = STATUS_CLEANER_CARTRIDGE_INSTALLED; - *Retry = FALSE; - - LogContext->LogError = FALSE; - LogContext->UniqueErrorValue = 256; - LogContext->ErrorCode = IO_ERR_BAD_BLOCK; - break; - } - - default: - { - needFurtherInterpret = TRUE; - break; - } - } // end case AdditionalSenseCodeQual - - break; - } // end case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE - - case SCSI_ADSENSE_NO_SEEK_COMPLETE: - { - switch (AdditionalSenseCodeQual) - { - - case 0x00: - { - needFurtherInterpret = FALSE; - - *Status = STATUS_DEVICE_DATA_ERROR; - *Retry = TRUE; - *RetryIntervalInSeconds = 0; - LogContext->LogError = TRUE; - LogContext->UniqueErrorValue = 256; - LogContext->ErrorCode = IO_ERR_BAD_BLOCK; - break; - } - - default: - { - needFurtherInterpret = TRUE; - break; - } - } - - break; - } // end case SCSI_ADSENSE_NO_SEEK_COMPLETE - - case SCSI_ADSENSE_LUN_COMMUNICATION: - { - switch (AdditionalSenseCodeQual) - { - - case SCSI_SESNEQ_COMM_CRC_ERROR: - { - needFurtherInterpret = FALSE; - - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - *RetryIntervalInSeconds = 1; - LogContext->LogError = TRUE; - LogContext->UniqueErrorValue = 257; - LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR; - break; - } - - default: - { - needFurtherInterpret = TRUE; - break; - } - } - - break; - } // end case SCSI_ADSENSE_LUN_COMMUNICATION - - case SCSI_ADSENSE_ILLEGAL_BLOCK: - { - needFurtherInterpret = FALSE; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Illegal block address\n")); - *Status = STATUS_NONEXISTENT_SECTOR; - *Retry = FALSE; - break; - } - - case SCSI_ADSENSE_INVALID_LUN: - { - needFurtherInterpret = FALSE; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Invalid LUN\n")); - *Status = STATUS_NO_SUCH_DEVICE; - *Retry = FALSE; - break; - } - - case SCSI_ADSENSE_COPY_PROTECTION_FAILURE: - { - needFurtherInterpret = FALSE; - - *Retry = FALSE; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Key - Copy protection failure\n")); - - switch (AdditionalSenseCodeQual) - { - case SCSI_SENSEQ_AUTHENTICATION_FAILURE: - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Authentication failure\n")); - *Status = STATUS_CSS_AUTHENTICATION_FAILURE; - break; - case SCSI_SENSEQ_KEY_NOT_PRESENT: - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Key not present\n")); - *Status = STATUS_CSS_KEY_NOT_PRESENT; - break; - case SCSI_SENSEQ_KEY_NOT_ESTABLISHED: - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Key not established\n")); - *Status = STATUS_CSS_KEY_NOT_ESTABLISHED; - break; - case SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION: - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Read of scrambled sector w/o authentication\n")); - *Status = STATUS_CSS_SCRAMBLED_SECTOR; - break; - case SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT: - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Media region does not logical unit region\n")); - *Status = STATUS_CSS_REGION_MISMATCH; - break; - case SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR: - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Region set error -- region may be permanent\n")); - *Status = STATUS_CSS_RESETS_EXHAUSTED; - break; - - default: - *Status = STATUS_COPY_PROTECTION_FAILURE; - break; - } // end switch of ASCQ for COPY_PROTECTION_FAILURE - - break; - } - - case SCSI_ADSENSE_INVALID_CDB: - { - needFurtherInterpret = FALSE; - - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Key - Invalid CDB\n")); - - *Status = STATUS_INVALID_DEVICE_REQUEST; - *Retry = FALSE; - - // Note: the retry interval is not typically used. - // it is set here only because a ClassErrorHandler - // cannot set the RetryIntervalInSeconds, and the error may - // require a few commands to be sent to clear whatever - // caused this condition (i.e. disk clears the write - // cache, requiring at least two commands) - // - // hopefully, this shortcoming can be changed for blackcomb. - *RetryIntervalInSeconds = 3; - - break; - } - - case SCSI_ADSENSE_MEDIUM_CHANGED: - { - needFurtherInterpret = FALSE; - *RetryIntervalInSeconds = 0; - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "SenseInfoInterpretByAdditionalSenseCode: Media changed\n")); - - DeviceSetMediaChangeStateEx(DeviceExtension, MediaPresent, NULL); - - // special process for Media Change - if (IsVolumeMounted(DeviceExtension->DeviceObject)) - { - // Set bit to indicate that media may have changed and volume needs verification. - SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME); - - *Status = STATUS_VERIFY_REQUIRED; - *Retry = FALSE; - } - else - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - } - break; - } - - case SCSI_ADSENSE_OPERATOR_REQUEST: - { - switch (AdditionalSenseCodeQual) - { - case SCSI_SENSEQ_MEDIUM_REMOVAL: - { - needFurtherInterpret = FALSE; - *RetryIntervalInSeconds = 0; - - InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount); - - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Ejection request received!\n")); - //Send eject notification. - DeviceSendNotification(DeviceExtension, - &GUID_IO_MEDIA_EJECT_REQUEST, - 0, - NULL); - // special process for Media Change - if (IsVolumeMounted(DeviceExtension->DeviceObject)) - { - // Set bit to indicate that media may have changed and volume needs verification. - SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME); - - *Status = STATUS_VERIFY_REQUIRED; - *Retry = FALSE; - } - else - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - } - break; - } - default: - { - needFurtherInterpret = TRUE; - break; - } - } - break; - } - - case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED: - { - needFurtherInterpret = FALSE; - *RetryIntervalInSeconds = 5; - - InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount); - - // Device information has changed, we need to rescan the - // bus for changed information such as the capacity. - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Device information changed. Invalidate the bus\n")); - - IoInvalidateDeviceRelations(DeviceExtension->LowerPdo, BusRelations); - - // special process for Media Change - if (IsVolumeMounted(DeviceExtension->DeviceObject)) - { - // Set bit to indicate that media may have changed and volume needs verification. - SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME); - - *Status = STATUS_VERIFY_REQUIRED; - *Retry = FALSE; - } - else - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - } - break; - } //end Case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED - - - case SCSI_ADSENSE_REC_DATA_NOECC: - case SCSI_ADSENSE_REC_DATA_ECC: - { - needFurtherInterpret = FALSE; - - *Status = STATUS_SUCCESS; - *Retry = FALSE; - LogContext->LogError = TRUE; - LogContext->UniqueErrorValue = 258; - LogContext->ErrorCode = IO_RECOVERED_VIA_ECC; - - if (senseBuffer->IncorrectLength) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Incorrect length detected.\n")); - *Status = STATUS_INVALID_BLOCK_LENGTH ; - } - break; - } - - case SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED: - { - UCHAR wmiEventData[sizeof(ULONG)+sizeof(UCHAR)] = {0}; - - *((PULONG)wmiEventData) = sizeof(UCHAR); - wmiEventData[sizeof(ULONG)] = AdditionalSenseCodeQual; - - needFurtherInterpret = FALSE; - - // Don't log another eventlog if we have already logged once - // NOTE: this should have been interlocked, but the structure - // was publicly defined to use a BOOLEAN (char). Since - // media only reports these errors once per X minutes, - // the potential race condition is nearly non-existant. - // the worst case is duplicate log entries, so ignore. - - *Status = STATUS_SUCCESS; - *Retry = FALSE; - LogContext->UniqueErrorValue = 258; - LogContext->LogError = TRUE; - LogContext->ErrorCode = IO_WRN_FAILURE_PREDICTED; - - if (senseBuffer->IncorrectLength) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretByAdditionalSenseCode: Incorrect length detected.\n")); - *Status = STATUS_INVALID_BLOCK_LENGTH ; - } - break; - } - - case 0x57: - { - // UNABLE_TO_RECOVER_TABLE_OF_CONTENTS - // the Matshita CR-585 returns this for all read commands - // on blank CD-R and CD-RW media, and we need to handle - // this for READ_CD detection ability. - switch (AdditionalSenseCodeQual) - { - case 0x00: - { - needFurtherInterpret = FALSE; - - *Status = STATUS_UNRECOGNIZED_MEDIA; - *Retry = FALSE; - break; - } - default: - { - needFurtherInterpret = TRUE; - break; - } - } - break; - } //end case Matshita specific error 0x57 - - default: - { - needFurtherInterpret = TRUE; - break; - } - } - - return needFurtherInterpret; -} - -VOID -SenseInfoInterpretBySenseKey( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSENSE_DATA SenseData, - _In_ UCHAR SenseKey, - _Inout_ NTSTATUS* Status, - _Inout_ BOOLEAN* Retry, - _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds, - _Inout_ PERROR_LOG_CONTEXT LogContext - ) -{ - // set default values for retry fields. - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - *RetryIntervalInSeconds = 0; - - switch (SenseKey) - { - case SCSI_SENSE_NOT_READY: - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Key - Not Ready (bad block)\n")); - - *Status = STATUS_DEVICE_NOT_READY; - *Retry = TRUE; - - // for unprocessed "not ready" codes, retry the command immediately. - *RetryIntervalInSeconds = 0; - break; - } - - case SCSI_SENSE_DATA_PROTECT: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Key - Media write protected\n")); - *Status = STATUS_MEDIA_WRITE_PROTECTED; - *Retry = FALSE; - break; - } - - case SCSI_SENSE_MEDIUM_ERROR: - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Key - Medium Error (bad block)\n")); - - *Status = STATUS_DEVICE_DATA_ERROR; - *Retry = FALSE; - LogContext->LogError = TRUE; - LogContext->UniqueErrorValue = 256; - LogContext->ErrorCode = IO_ERR_BAD_BLOCK; - - break; - } // end SCSI_SENSE_MEDIUM_ERROR - - case SCSI_SENSE_HARDWARE_ERROR: - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Key - Hardware error\n")); - - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - LogContext->LogError = TRUE; - LogContext->UniqueErrorValue = 257; - LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR; - - break; - } // end SCSI_SENSE_HARDWARE_ERROR - - case SCSI_SENSE_ILLEGAL_REQUEST: - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Key - Illegal SCSI request\n")); - *Status = STATUS_INVALID_DEVICE_REQUEST; - *Retry = FALSE; - - break; - } // end SCSI_SENSE_ILLEGAL_REQUEST - - case SCSI_SENSE_UNIT_ATTENTION: - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Key - Unit Attention\n")); - - // A media change may have occured so increment the change - // count for the physical device - InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount); - - if (IsVolumeMounted(DeviceExtension->DeviceObject)) - { - // Set bit to indicate that media may have changed - // and volume needs verification. - SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME); - - *Status = STATUS_VERIFY_REQUIRED; - *Retry = FALSE; - } - else - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - } - - break; - - } // end SCSI_SENSE_UNIT_ATTENTION - - case SCSI_SENSE_ABORTED_COMMAND: - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Command aborted\n")); - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - *RetryIntervalInSeconds = 1; - break; - } // end SCSI_SENSE_ABORTED_COMMAND - - case SCSI_SENSE_BLANK_CHECK: - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Media blank check\n")); - *Retry = FALSE; - *Status = STATUS_NO_DATA_DETECTED; - break; - } // end SCSI_SENSE_BLANK_CHECK - - case SCSI_SENSE_RECOVERED_ERROR: - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Recovered error\n")); - *Status = STATUS_SUCCESS; - *Retry = FALSE; - LogContext->LogError = TRUE; - LogContext->UniqueErrorValue = 258; - LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR; - - if (SenseData->IncorrectLength) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Incorrect length detected.\n")); - *Status = STATUS_INVALID_BLOCK_LENGTH ; - } - - break; - } // end SCSI_SENSE_RECOVERED_ERROR - - case SCSI_SENSE_NO_SENSE: - { - // Check other indicators. - if (SenseData->IncorrectLength) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Incorrect length detected.\n")); - *Status = STATUS_INVALID_BLOCK_LENGTH ; - *Retry = FALSE; - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: No specific sense key\n")); - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - } - - break; - } // end SCSI_SENSE_NO_SENSE - - default: - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpretBySenseKey: Unrecognized sense code\n")); - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - *RetryIntervalInSeconds = 0; - - break; - } - - } // end switch (SenseKey) - - return; -} - -VOID -SenseInfoInterpretBySrbStatus( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_ ULONG RetriedCount, - _Inout_ NTSTATUS* Status, - _Inout_ BOOLEAN* Retry, - _Out_ _Deref_out_range_(0,100) ULONG* RetryIntervalInSeconds, - _Inout_ PERROR_LOG_CONTEXT LogContext - ) -{ - BOOLEAN incrementErrorCount = FALSE; - - // set default values for retry fields. - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - *RetryIntervalInSeconds = 0; - - switch (SRB_STATUS(Srb->SrbStatus)) - { - case SRB_STATUS_INVALID_LUN: - case SRB_STATUS_INVALID_TARGET_ID: - case SRB_STATUS_NO_DEVICE: - case SRB_STATUS_NO_HBA: - case SRB_STATUS_INVALID_PATH_ID: - { - *Status = STATUS_NO_SUCH_DEVICE; - *Retry = FALSE; - break; - } - - case SRB_STATUS_COMMAND_TIMEOUT: - case SRB_STATUS_TIMEOUT: - { - // Update the error count for the device. - *Status = STATUS_IO_TIMEOUT; - *Retry = TRUE; - *RetryIntervalInSeconds = 0; - incrementErrorCount = TRUE; - break; - } - - case SRB_STATUS_ABORTED: - { - // Update the error count for the device. - *Status = STATUS_IO_TIMEOUT; - *Retry = TRUE; - *RetryIntervalInSeconds = 1; - incrementErrorCount = TRUE; - break; - } - - case SRB_STATUS_SELECTION_TIMEOUT: - { - *Status = STATUS_DEVICE_NOT_CONNECTED; - *Retry = FALSE; - *RetryIntervalInSeconds = 2; - LogContext->LogError = TRUE; - LogContext->ErrorCode = IO_ERR_NOT_READY; - LogContext->UniqueErrorValue = 260; - break; - } - - case SRB_STATUS_DATA_OVERRUN: - { - *Status = STATUS_DATA_OVERRUN; - *Retry = FALSE; - break; - } - - case SRB_STATUS_PHASE_SEQUENCE_FAILURE: - { - // Update the error count for the device. - incrementErrorCount = TRUE; - *Status = STATUS_IO_DEVICE_ERROR; - - // If there was phase sequence error then limit the number of retries. - *Retry = (RetriedCount <= 1); - - break; - } - - case SRB_STATUS_REQUEST_FLUSHED: - { - // If the status needs verification bit is set. Then set - // the status to need verification and no retry; otherwise, - // just retry the request. - if (TEST_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME)) - { - *Status = STATUS_VERIFY_REQUIRED; - *Retry = FALSE; - } - else - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - } - - break; - } - - case SRB_STATUS_INVALID_REQUEST: - { - *Status = STATUS_INVALID_DEVICE_REQUEST; - *Retry = FALSE; - break; - } - - case SRB_STATUS_UNEXPECTED_BUS_FREE: - case SRB_STATUS_PARITY_ERROR: - // Update the error count for the device and fall through to below - incrementErrorCount = TRUE; - - case SRB_STATUS_BUS_RESET: - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - break; - } - - case SRB_STATUS_ERROR: - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - - if (Srb->ScsiStatus == 0) - { - // This is some strange return code. Update the error - // count for the device. - incrementErrorCount = TRUE; - } - - if (Srb->ScsiStatus == SCSISTAT_BUSY) - { - *Status = STATUS_DEVICE_NOT_READY; - } - - break; - } - - default: - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - LogContext->LogError = TRUE; - LogContext->ErrorCode = IO_ERR_CONTROLLER_ERROR; - LogContext->UniqueErrorValue = 259; - LogContext->ErrorUnhandled = TRUE; - break; - } - - } //end of (SRB_STATUS(Srb->SrbStatus)) - - if (incrementErrorCount) - { - // if any error count occurred, delay the retry of this io by - // at least one second, if caller supports it. - if (*RetryIntervalInSeconds == 0) - { - *RetryIntervalInSeconds = 1; - } - - DevicePerfIncrementErrorCount(DeviceExtension); - } - - return; -} - -VOID -SenseInfoLogError( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_ UCHAR MajorFunctionCode, - _In_ ULONG IoControlCode, - _In_ ULONG RetriedCount, - _In_ NTSTATUS* Status, - _In_ BOOLEAN* Retry, - _Inout_ PERROR_LOG_CONTEXT LogContext - ) -{ - // Always log the error in our internal log. - // If logError is set, also log the error in the system log. - PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; - ULONG totalSize = 0; - ULONG senseBufferSize = 0; - IO_ERROR_LOG_PACKET staticErrLogEntry = {0}; - CDROM_ERROR_LOG_DATA staticErrLogData = {0}; - - // Calculate the total size of the error log entry. - // add to totalSize in the order that they are used. - // the advantage to calculating all the sizes here is - // that we don't have to do a bunch of extraneous checks - // later on in this code path. - totalSize = sizeof(IO_ERROR_LOG_PACKET) // required - + sizeof(CDROM_ERROR_LOG_DATA); // struct for ease - - // also save any available extra sense data, up to the maximum errlog - // packet size . WMI should be used for real-time analysis. - // the event log should only be used for post-mortem debugging. - if (TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID)) - { - ULONG validSenseBytes; - BOOLEAN validSense; - - // make sure we can at least access the AdditionalSenseLength field - validSense = RTL_CONTAINS_FIELD(senseBuffer, - Srb->SenseInfoBufferLength, - AdditionalSenseLength); - if (validSense) - { - // if extra info exists, copy the maximum amount of available - // sense data that is safe into the the errlog. - validSenseBytes = senseBuffer->AdditionalSenseLength - + offsetof(SENSE_DATA, AdditionalSenseLength); - - // this is invalid because it causes overflow! - // whoever sent this type of request would cause - // a system crash. - NT_ASSERT(validSenseBytes < MAX_ADDITIONAL_SENSE_BYTES); - - // set to save the most sense buffer possible - senseBufferSize = max(validSenseBytes, sizeof(SENSE_DATA)); - senseBufferSize = min(senseBufferSize, Srb->SenseInfoBufferLength); - } - else - { - // it's smaller than required to read the total number of - // valid bytes, so just use the SenseInfoBufferLength field. - senseBufferSize = Srb->SenseInfoBufferLength; - } - - // Bump totalSize by the number of extra senseBuffer bytes - // (beyond the default sense buffer within CDROM_ERROR_LOG_DATA). - // Make sure to never allocate more than ERROR_LOG_MAXIMUM_SIZE. - if (senseBufferSize > sizeof(SENSE_DATA)) - { - totalSize += senseBufferSize-sizeof(SENSE_DATA); - if (totalSize > ERROR_LOG_MAXIMUM_SIZE) - { - senseBufferSize -= totalSize-ERROR_LOG_MAXIMUM_SIZE; - totalSize = ERROR_LOG_MAXIMUM_SIZE; - } - } - } - - // If we've used up all of our retry attempts, set the final status to - // reflect the appropriate result. - // - // ISSUE: the test below should also check RetriedCount to determine if we will actually retry, - // but there is no easy test because we'd have to consider the original retry count - // for the op; besides, InterpretTransferPacketError sometimes ignores the retry - // decision returned by this function. So just ErrorRetried to be true in the majority case. - // - if (*Retry) - { - staticErrLogEntry.FinalStatus = STATUS_SUCCESS; - staticErrLogData.ErrorRetried = TRUE; - } - else - { - staticErrLogEntry.FinalStatus = *Status; - } - - // Don't log generic IO_WARNING_PAGING_FAILURE message if either the - // I/O is retried, or it completed successfully. - if ((LogContext->ErrorCode == IO_WARNING_PAGING_FAILURE) && - (*Retry || NT_SUCCESS(*Status)) ) - { - LogContext->LogError = FALSE; - } - - if (TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING)) - { - staticErrLogData.ErrorPaging = TRUE; - } - - staticErrLogData.ErrorUnhandled = LogContext->ErrorUnhandled; - - // Calculate the device offset if there is a geometry. - staticErrLogEntry.DeviceOffset.QuadPart = (LONGLONG)LogContext->BadSector; - staticErrLogEntry.DeviceOffset.QuadPart *= (LONGLONG)DeviceExtension->DiskGeometry.BytesPerSector; - - if (LogContext->ErrorCode == -1) - { - staticErrLogEntry.ErrorCode = STATUS_IO_DEVICE_ERROR; - } - else - { - staticErrLogEntry.ErrorCode = LogContext->ErrorCode; - } - - // The dump data follows the IO_ERROR_LOG_PACKET - staticErrLogEntry.DumpDataSize = (USHORT)totalSize - sizeof(IO_ERROR_LOG_PACKET); - - staticErrLogEntry.SequenceNumber = 0; - staticErrLogEntry.MajorFunctionCode = MajorFunctionCode; - staticErrLogEntry.IoControlCode = IoControlCode; - staticErrLogEntry.RetryCount = (UCHAR)RetriedCount; - staticErrLogEntry.UniqueErrorValue = LogContext->UniqueErrorValue; - - KeQueryTickCount(&staticErrLogData.TickCount); - staticErrLogData.PortNumber = (ULONG)-1; - - // Save the entire contents of the SRB. - staticErrLogData.Srb = *Srb; - - // For our private log, save just the default length of the SENSE_DATA. - if (senseBufferSize != 0) - { - RtlCopyMemory(&staticErrLogData.SenseData, senseBuffer, min(senseBufferSize, sizeof(SENSE_DATA))); - } - - // Save the error log in our context. - // We only save the default sense buffer length. - { - KIRQL oldIrql; - KeAcquireSpinLock(&DeviceExtension->PrivateFdoData->SpinLock, &oldIrql); - DeviceExtension->PrivateFdoData->ErrorLogs[DeviceExtension->PrivateFdoData->ErrorLogNextIndex] = staticErrLogData; - DeviceExtension->PrivateFdoData->ErrorLogNextIndex++; - DeviceExtension->PrivateFdoData->ErrorLogNextIndex %= NUM_ERROR_LOG_ENTRIES; - KeReleaseSpinLock(&DeviceExtension->PrivateFdoData->SpinLock, oldIrql); - } - - // If logError is set, also save this log in the system's error log. - // But make sure we don't log TUR failures over and over - // (e.g. if an external drive was switched off and we're still sending TUR's to it every second). - if (LogContext->LogError) - { - // We do not want to log certain system events repetitively - switch (((PCDB)Srb->Cdb)->CDB10.OperationCode) - { - case SCSIOP_TEST_UNIT_READY: - { - if (DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO) - { - LogContext->LogError = FALSE; - } - else - { - DeviceExtension->PrivateFdoData->LoggedTURFailureSinceLastIO = TRUE; - } - - break; - } - - case SCSIOP_SYNCHRONIZE_CACHE: - { - if (DeviceExtension->PrivateFdoData->LoggedSYNCFailure) - { - LogContext->LogError = FALSE; - } - else - { - DeviceExtension->PrivateFdoData->LoggedSYNCFailure = TRUE; - } - - break; - } - } - - // Do not log 5/21/00 LOGICAL BLOCK ADDRESS OUT OF RANGE if the disc is blank, - // it is known to litter the Event Log with repetitive errors - // Do not log this error for READ, as it's known that File System mount process reads different sectors from media. - if (senseBufferSize > RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier) && - senseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST && - senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_BLOCK && - senseBuffer->AdditionalSenseCodeQualifier == 0 && - IS_SCSIOP_READ(((PCDB)Srb->Cdb)->CDB10.OperationCode)) - { - LogContext->LogError = FALSE; - } - } - - // Write the error log packet to the system error logging thread. - if (LogContext->LogError) - { - PIO_ERROR_LOG_PACKET errorLogEntry; - PCDROM_ERROR_LOG_DATA errlogData; - - errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DeviceExtension->DeviceObject, (UCHAR)totalSize); - if (errorLogEntry) - { - errlogData = (PCDROM_ERROR_LOG_DATA)errorLogEntry->DumpData; - - *errorLogEntry = staticErrLogEntry; - *errlogData = staticErrLogData; - - // For the system log, copy as much of the sense buffer as possible. - if (senseBufferSize != 0) - { - RtlCopyMemory(&errlogData->SenseData, senseBuffer, senseBufferSize); - } - - // errorLogEntry - It will be freed by the kernel. - IoWriteErrorLogEntry(errorLogEntry); - } - } - - return; -} - -VOID -SenseInfoInterpretRefineByScsiCommand( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_ ULONG RetriedCount, - _In_ LONGLONG Total100nsSinceFirstSend, - _In_ BOOLEAN OverrideVerifyVolume, - _Inout_ BOOLEAN* Retry, - _Inout_ NTSTATUS* Status, - _Inout_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) - LONGLONG* RetryIntervalIn100ns - ) -/*++ - -Routine Description: - - Based on SCSI command, modify the interpretion result. - -Arguments: - - DeviceExtension - device extension. - Srb - Supplies the scsi request block which failed. - RetriedCount - retried count. - Total100nsUnitsSinceFirstSend - time spent after the request was sent down first time. - OverrideVerifyVolume - should override verify volume request. - -Return Value: - - Retry - the reques should be retried or not. - Status - Returns the status for the request. - RetryInterval - waiting time (in 100ns) before the request should be retried. - Zero indicates the request should be immediately retried. - ---*/ -{ - UCHAR const opCode = Srb->Cdb[0]; - CDB const* cdb = (CDB const*)(Srb->Cdb); - PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; - - if (opCode == SCSIOP_MEDIUM_REMOVAL) - { - if (( cdb->AsByte[1] == 0) && - ( cdb->AsByte[2] == 0) && - ( cdb->AsByte[3] == 0) && - ((cdb->AsByte[4] & 0xFC) == 0) - ) - { - // byte[4] == 0x3 or byte[4] == 0x1 == UNLOCK OF MEDIA - if ((cdb->AsByte[4] & 0x01) == 0) - { - if (RetriedCount < TOTAL_COUNT_RETRY_DEFAULT) - { - // keep retrying unlock operation for several times - *Retry = TRUE; - } - } - else // LOCK REQUEST - { - // do not retry LOCK requests more than once (per CLASSPNP code) - if (RetriedCount > TOTAL_COUNT_RETRY_LOCK_MEDIA) - { - *Retry = FALSE; - } - } - } - - // want a minimum time to retry of 2 seconds - if ((*Status == STATUS_DEVICE_NOT_READY) && - (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)) - { - *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2)); - } - else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) - { - *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2)); - } - } - else if ((opCode == SCSIOP_MODE_SENSE) || (opCode == SCSIOP_MODE_SENSE10)) - { - // want a minimum time to retry of 2 seconds - if ((*Status == STATUS_DEVICE_NOT_READY) && - (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)) - { - *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2)); - } - else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) - { - *RetryIntervalIn100ns = max(*RetryIntervalIn100ns, SECONDS_TO_100NS_UNITS(2)); - } - - // Want to ignore a STATUS_VERIFY_REQUIRED error because it either - // doesn't make sense or is required to satisfy the VERIFY. - if (*Status == STATUS_VERIFY_REQUIRED) - { - *Retry = TRUE; - } - else if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) - { - /* - * This is a HACK. - * Atapi returns SRB_STATUS_DATA_OVERRUN when it really means - * underrun (i.e. success, and the buffer is longer than needed). - * So treat this as a success. - * When the caller of this function sees that the status was changed to success, - * it will add the transferred length to the original irp. - */ - *Status = STATUS_SUCCESS; - *Retry = FALSE; - } - - // limit the count of retries - if (RetriedCount > TOTAL_COUNT_RETRY_MODESENSE) - { - *Retry = FALSE; - } - } - else if ((opCode == SCSIOP_READ_CAPACITY) || (opCode == SCSIOP_READ_CAPACITY16)) - { - // Want to ignore a STATUS_VERIFY_REQUIRED error because it either - // doesn't make sense or is required to satisfy the VERIFY. - if (*Status == STATUS_VERIFY_REQUIRED) - { - *Retry = TRUE; - } - - if (RetriedCount > TOTAL_COUNT_RETRY_READ_CAPACITY) - { - *Retry = FALSE; - } - } - else if ((opCode == SCSIOP_RESERVE_UNIT) || (opCode == SCSIOP_RELEASE_UNIT)) - { - // The RESERVE(6) / RELEASE(6) commands are optional. - // So if they aren't supported, try the 10-byte equivalents - if (*Status == STATUS_INVALID_DEVICE_REQUEST) - { - PCDB tempCdb = (PCDB)Srb->Cdb; - - Srb->CdbLength = 10; - tempCdb->CDB10.OperationCode = (tempCdb->CDB6GENERIC.OperationCode == SCSIOP_RESERVE_UNIT) - ? SCSIOP_RESERVE_UNIT10 - : SCSIOP_RELEASE_UNIT10; - - SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6); - *Retry = TRUE; - } - } - else if (IS_SCSIOP_READWRITE(opCode)) - { - // Retry if still verifying a (possibly) reloaded disk/cdrom. - if (OverrideVerifyVolume && (*Status == STATUS_VERIFY_REQUIRED)) - { - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - } - - // Special case for streaming READ/WRITE commands - if (((opCode == SCSIOP_READ12) && (cdb->READ12.Streaming == 1)) || - ((opCode == SCSIOP_WRITE12) && (cdb->WRITE12.Streaming == 1))) - { - // We've got a failure while performing a streaming operation and now need to guess if - // it's likely to be a permanent error because the drive does not support streaming at all - // (in which case we're going to fall back to normal reads/writes), or a transient error - // (in which case we quickly fail the request but contrinue to use streaming). - // - // We analyze the sense information to make that decision. Bus resets and device timeouts - // are treated as permanent errors, because some non-compliant devices may even hang when - // they get a command that they do not expect. - - BOOLEAN disableStreaming = FALSE; - - if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_TIMEOUT || - SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_COMMAND_TIMEOUT || - SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT || - SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_BUS_RESET) - { - disableStreaming = TRUE; - } - else if ((senseBuffer->SenseKey &0xf) == SCSI_SENSE_UNIT_ATTENTION) - { - if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_BUS_RESET || - senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_INSUFFICIENT_TIME_FOR_OPERATION) - { - disableStreaming = TRUE; - } - } - else if ((senseBuffer->SenseKey &0xf) == SCSI_SENSE_ILLEGAL_REQUEST) - { - // LBA Out of Range is an exception, as it's more likely to be caused by - // upper layers attempting to read/write a wrong LBA. - if (senseBuffer->AdditionalSenseCode != SCSI_ADSENSE_ILLEGAL_BLOCK) - { - disableStreaming = TRUE; - } - } - - if (disableStreaming) - { - // if the failure looks permanent, we disable streaming for all future reads/writes - // and retry the command immediately - SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_STREAMING); - *Retry = TRUE; - *RetryIntervalIn100ns = 0; - } - else - { - // if the failure looks transient, we simply fail the current request without retries - // to minimize the time of processing - *Retry = FALSE; - } - } - - // Special-case handling of READ/WRITE commands. These commands now have a 120 second timeout, - // but the preferred behavior (and that taken by many drives) is to immediately report 2/4/x - // on OPC and similar commands. Thus, retries must occur for at least 160 seconds - // (120 seconds + four 10 second retries) as a conservative guess. - // Note: 160s retry time is also a result of discussion with OEMs for case of 2/4/7 and 2/4/8. - if (*Retry) - { - if ((Total100nsSinceFirstSend < 0) || - (((senseBuffer->SenseKey &0xf) == SCSI_SENSE_HARDWARE_ERROR) && (senseBuffer->AdditionalSenseCode == 0x09))) - { - // time information is not valid. use default retry count. - // or if it's SERVO FAILURE, use retry count instead of 160s retry. - *Retry = (RetriedCount <= TOTAL_COUNT_RETRY_DEFAULT); - } - else if (Total100nsSinceFirstSend > SECONDS_TO_100NS_UNITS(TOTAL_SECONDS_RETRY_TIME_WRITE)) - { - *Retry = FALSE; - } - - // How long should we request a delay for during writing? This depends entirely on - // the current write speed of the drive. If we request retries too quickly, - // we can overload the processor on the drive (resulting in garbage being written), - // but too slowly results in lesser performance. - // - *RetryIntervalIn100ns = DeviceExtension->DeviceAdditionalData.ReadWriteRetryDelay100nsUnits; - - } // end retry for 160 seconds modification - } - else if (opCode == SCSIOP_GET_PERFORMANCE) - { - if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) - { - // This is a HACK. - // Atapi returns SRB_STATUS_DATA_OVERRUN when it really means - // underrun (i.e. success, and the buffer is longer than needed). - // So treat this as a success. - // When the caller of this function sees that the status was changed to success, - // it will add the transferred length to the original irp. - *Status = STATUS_SUCCESS; - *Retry = FALSE; - } - - if ((Srb->SenseInfoBufferLength < RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA,AdditionalSenseCodeQualifier)) || - !TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID)) - { - // If get configuration command is failing and if the request type is TYPE ONE - // then most likely the device does not support this request type. Set the - // flag so that the TYPE ONE requests will be tried as TYPE ALL requets. - if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) && - (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_DATA_OVERRUN) && - (((PCDB)Srb->Cdb)->GET_CONFIGURATION.RequestType == SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE)) - { - - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "TYPE ONE GetConfiguration failed. Set hack flag and retry.\n")); - SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG); - *Retry = TRUE; - } - } - - // limit retries to GET_PERFORMANCE commands to default retry count - if (RetriedCount > TOTAL_COUNT_RETRY_DEFAULT) - { - *Retry = FALSE; - } - } - else // default handler -- checks for retry count only. - { - if (RetriedCount > TOTAL_COUNT_RETRY_DEFAULT) - { - *Retry = FALSE; - } - } - - return; -} - - -VOID -SenseInfoInterpretRefineByIoControl( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG IoControlCode, - _In_ BOOLEAN OverrideVerifyVolume, - _Inout_ BOOLEAN* Retry, - _Inout_ NTSTATUS* Status - ) -/*++ - -Routine Description: - - Based on IOCTL code, modify the interpretion result. - -Arguments: - - Device - Supplies the device object associated with this request. - OriginalRequest - the irp that error occurs on. - Srb - Supplies the scsi request block which failed. - MajorFunctionCode - Supplies the function code to be used for logging. - IoDeviceCode - Supplies the device code to be used for logging. - PreviousRetryCount - retried count. - RequestHistory_DoNotUse - the history list - -Return Value: - - BOOLEAN TRUE: Drivers should retry this request. - FALSE: Drivers should not retry this request. - Status - Returns the status for the request. - RetryInterval - Number of seconds before the request should be retried. - Zero indicates the request should be immediately retried. - ---*/ -{ - PAGED_CODE(); - - if ((IoControlCode == IOCTL_CDROM_GET_LAST_SESSION) || - (IoControlCode == IOCTL_CDROM_READ_TOC) || - (IoControlCode == IOCTL_CDROM_READ_TOC_EX) || - (IoControlCode == IOCTL_CDROM_GET_CONFIGURATION)|| - (IoControlCode == IOCTL_CDROM_GET_VOLUME)) - { - if (*Status == STATUS_DATA_OVERRUN) - { - *Status = STATUS_SUCCESS; - *Retry = FALSE; - } - } - - if (IoControlCode == IOCTL_CDROM_READ_Q_CHANNEL) - { - PLAY_ACTIVE(DeviceExtension) = FALSE; - } - - // If the status is verified required and the this request - // should bypass verify required then retry the request. - if (OverrideVerifyVolume && (*Status == STATUS_VERIFY_REQUIRED)) - { - // note: status gets overwritten here - *Status = STATUS_IO_DEVICE_ERROR; - *Retry = TRUE; - - if ((IoControlCode == IOCTL_CDROM_CHECK_VERIFY) || - (IoControlCode == IOCTL_STORAGE_CHECK_VERIFY) || - (IoControlCode == IOCTL_STORAGE_CHECK_VERIFY2) || - (IoControlCode == IOCTL_DISK_CHECK_VERIFY) - ) - { - // Update the geometry information, as the media could have changed. - (VOID) MediaReadCapacity(DeviceExtension->Device); - } // end of ioctls to update capacity - } - - if (!NT_SUCCESS(*Status) && (IoControlCode == IOCTL_CDROM_SET_SPEED)) - { - // If set speed request fails then we should disable the restore speed option. - // Otherwise we will try to restore to default speed on next media change, - // if requested by the caller. - DeviceExtension->DeviceAdditionalData.RestoreDefaults = FALSE; - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "Disable restore default\n")); - } - - return; -} - -BOOLEAN -SenseInfoInterpret( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_ ULONG RetriedCount, - _Out_ NTSTATUS* Status, - _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) - LONGLONG* RetryIntervalIn100ns - ) -/*++ - -SenseInfoInterpret() - -Routine Description: - - This routine interprets the data returned from the SCSI request sense. - It determines the status to return in the IRP - and whether this request can be retried. - -Arguments: - - Device - Supplies the device object associated with this request. - Srb - Supplies the scsi request block which failed. - MajorFunctionCode - Supplies the function code to be used for logging. - IoDeviceCode - Supplies the device code to be used for logging. - -Return Value: - - BOOLEAN TRUE: Drivers should retry this request. - FALSE: Drivers should not retry this request. - Status - Returns the status for the request. - RetryInterval - Number of seconds before the request should be retried. - Zero indicates the request should be immediately retried. - ---*/ -{ - ULONG retryIntervalInSeconds = 0; - BOOLEAN retry = TRUE; - PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; - ULONG readSector = 0; - ERROR_LOG_CONTEXT logContext; - - UCHAR majorFunctionCode = 0; - ULONG ioControlCode = 0; - BOOLEAN overrideVerifyVolume = FALSE; - ULONGLONG total100nsSinceFirstSend = 0; - PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo; - - // - *Status = STATUS_IO_DEVICE_ERROR; - - RtlZeroMemory(&logContext, sizeof(ERROR_LOG_CONTEXT)); - logContext.ErrorCode = -1; - - // Get Original Request related information - SenseInfoRequestGetInformation(Request, - &majorFunctionCode, - &ioControlCode, - &overrideVerifyVolume, - &total100nsSinceFirstSend); - - if(TEST_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING)) - { - // Log anything remotely incorrect about paging i/o - logContext.LogError = TRUE; - logContext.UniqueErrorValue = 301; - logContext.ErrorCode = IO_WARNING_PAGING_FAILURE; - } - - // must handle the SRB_STATUS_INTERNAL_ERROR case first, - // as it has all the flags set. - if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_INTERNAL_ERROR) - { - TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, - "SenseInfoInterpret: Internal Error code is %x\n", - Srb->InternalStatus)); - - retry = FALSE; - *Status = Srb->InternalStatus; - } - else if (Srb->ScsiStatus == SCSISTAT_RESERVATION_CONFLICT) - { - retry = FALSE; - *Status = STATUS_DEVICE_BUSY; - logContext.LogError = FALSE; - } - else if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) && - (Srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength))) - { - UCHAR senseKey = (UCHAR)(senseBuffer->SenseKey & 0x0f); - UCHAR additionalSenseCode = 0; - UCHAR additionalSenseCodeQual = 0; - - // Zero the additional sense code and additional sense code qualifier - // if they were not returned by the device. - readSector = senseBuffer->AdditionalSenseLength + offsetof(SENSE_DATA, AdditionalSenseLength); - if (readSector > Srb->SenseInfoBufferLength) - { - readSector = Srb->SenseInfoBufferLength; - } - - additionalSenseCode = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCode)) ? - senseBuffer->AdditionalSenseCode : 0; - additionalSenseCodeQual = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier)) ? - senseBuffer->AdditionalSenseCodeQualifier : 0; - - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "SCSI Error - \n" - "\tcdb: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n" - "\tsrb status: %X; sense: %02X/%02X/%02X; Retried count: %d\n\n", - Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5], - Srb->Cdb[6], Srb->Cdb[7], Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11], - Srb->Cdb[12], Srb->Cdb[13], Srb->Cdb[14], Srb->Cdb[15], - SRB_STATUS(Srb->SrbStatus), - senseKey, - additionalSenseCode, - additionalSenseCodeQual, - RetriedCount)); - - if (senseKey == SCSI_SENSE_UNIT_ATTENTION) - { - ULONG mediaChangeCount; - - // A media change may have occured so increment the change count for the physical device - mediaChangeCount = InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount); - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, - "SenseInfoInterpret: Media change count for device %d incremented to %#lx\n", - DeviceExtension->DeviceNumber, mediaChangeCount)); - } - - if ((zpoddInfo != NULL) && - (((PCDB)Srb->Cdb)->CDB6GENERIC.OperationCode == SCSIOP_TEST_UNIT_READY)) - { - // This sense code is in response to the Test Unit Ready sent during delayed power down - // request. Copy the sense data into the zpoddInfo structure for later processing. - zpoddInfo->SenseKey = senseKey; - zpoddInfo->AdditionalSenseCode = additionalSenseCode; - zpoddInfo->AdditionalSenseCodeQualifier = additionalSenseCodeQual; - } - - // Interpret error by specific ASC & ASCQ first, - // If the error is not handled, interpret using f - { - BOOLEAN notHandled = FALSE; - notHandled = SenseInfoInterpretByAdditionalSenseCode(DeviceExtension, - Srb, - additionalSenseCode, - additionalSenseCodeQual, - Status, - &retry, - &retryIntervalInSeconds, - &logContext); - - if (notHandled) - { - SenseInfoInterpretBySenseKey(DeviceExtension, - senseBuffer, - senseKey, - Status, - &retry, - &retryIntervalInSeconds, - &logContext); - } - } - - // Try to determine the bad sector from the inquiry data. - if ((IS_SCSIOP_READWRITE(((PCDB)Srb->Cdb)->CDB10.OperationCode)) || - (((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY) || - (((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY16)) - { - ULONG index; - readSector = 0; - - for (index = 0; index < 4; index++) - { - logContext.BadSector = (logContext.BadSector << 8) | senseBuffer->Information[index]; - } - - for (index = 0; index < 4; index++) - { - readSector = (readSector << 8) | Srb->Cdb[index+2]; - } - - index = (((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) | - ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb; - - // Make sure the bad sector is within the read sectors. - if (!(logContext.BadSector >= readSector && logContext.BadSector < (readSector + index))) - { - logContext.BadSector = readSector; - } - } - } - else - { - // Request sense buffer not valid. No sense information - // to pinpoint the error. Return general request fail. - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "SCSI Error - \n" - "\tcdb: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n" - "\tsrb status: %X; sense info not valid; Retried count: %d\n\n", - Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5], - Srb->Cdb[6], Srb->Cdb[7], Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11], - Srb->Cdb[12], Srb->Cdb[13], Srb->Cdb[14], Srb->Cdb[15], - SRB_STATUS(Srb->SrbStatus), - RetriedCount)); - - SenseInfoInterpretBySrbStatus(DeviceExtension, - Srb, - RetriedCount, - Status, - &retry, - &retryIntervalInSeconds, - &logContext); - } - - // all functions using unit - seconds for retry Interval already be called. - *RetryIntervalIn100ns = SECONDS_TO_100NS_UNITS(retryIntervalInSeconds); - - // call the device specific error handler if it has one. - // DeviceErrorHandlerForMmmc() for all MMC devices - // or DeviceErrorHandlerForHitachiGD2000() for HITACHI GD-2000, HITACHI DVD-ROM GD-2000 - if (DeviceExtension->DeviceAdditionalData.ErrorHandler) - { - DeviceExtension->DeviceAdditionalData.ErrorHandler(DeviceExtension, Srb, Status, &retry); - } - - // Refine retry based on SCSI command - SenseInfoInterpretRefineByScsiCommand(DeviceExtension, - Srb, - RetriedCount, - total100nsSinceFirstSend, - overrideVerifyVolume, - &retry, - Status, - RetryIntervalIn100ns); - - // Refine retry based on IOCTL code. - if (majorFunctionCode == IRP_MJ_DEVICE_CONTROL) - { - SenseInfoInterpretRefineByIoControl(DeviceExtension, - ioControlCode, - overrideVerifyVolume, - &retry, - Status); - } - - // LOG the error: - // Always log the error in our internal log. - // If logError is set, also log the error in the system log. - SenseInfoLogError(DeviceExtension, - Srb, - majorFunctionCode, - ioControlCode, - RetriedCount, - Status, - &retry, - &logContext); - - // all process about the error done. check if the irp was cancelled. - if ((!NT_SUCCESS(*Status)) && retry) - { - PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request); - - if ((requestContext->OriginalRequest != NULL) && - WdfRequestIsCanceled(requestContext->OriginalRequest) - ) - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "Request %p was cancelled when it would have been retried\n", - requestContext->OriginalRequest)); - - *Status = STATUS_CANCELLED; - retry = FALSE; - *RetryIntervalIn100ns = 0; - } - } - - // now, all decisions are made. display trace information. - if (retry) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "Command shall be retried in %2I64d.%03I64d seconds\n", - (*RetryIntervalIn100ns / UNIT_100NS_PER_SECOND), - (*RetryIntervalIn100ns / 10000) % 1000 - )); - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "Will not retry; Sense/ASC/ASCQ of %02x/%02x/%02x\n", - senseBuffer->SenseKey, - senseBuffer->AdditionalSenseCode, - senseBuffer->AdditionalSenseCodeQualifier - )); - } - - return retry; - -} // end SenseInfoInterpret() - - -BOOLEAN -SenseInfoInterpretForZPODD( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ PSCSI_REQUEST_BLOCK Srb, - _Out_ NTSTATUS* Status, - _Out_ _Out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) - LONGLONG* RetryIntervalIn100ns - ) -/*++ - -SenseInfoInterpretForZPODD() - -Routine Description: - - This routine interprets the data returned from the SCSI request sense. - It determines the status to return in the IRP - and whether this request can be retried. - -Arguments: - - Device - Supplies the device object associated with this request. - Srb - Supplies the scsi request block which failed. - -Return Value: - - BOOLEAN TRUE: Drivers should retry this request. - FALSE: Drivers should not retry this request. - Status - Returns the status for the request. - RetryInterval - Number of seconds before the request should be retried. - Zero indicates the request should be immediately retried. - ---*/ -{ - BOOLEAN retry = FALSE; - PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; - ULONG readSector = 0; - PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo; - - *Status = STATUS_IO_DEVICE_ERROR; - *RetryIntervalIn100ns = 0; - - if (zpoddInfo->RetryFirstCommand != FALSE) - { - // The first command to the logical unit after power resumed will be terminated - // with CHECK CONDITION Status, 6/29/00 POWER ON, RESET, OR BUS DEVICE RESET OCCURRED - - // We have observed some devices return a different sense code, and thus as long as - // the first command after power resume fails, we just retry one more time. - zpoddInfo->RetryFirstCommand = FALSE; - - retry = TRUE; - } - else if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) && - (Srb->SenseInfoBufferLength >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength))) - { - UCHAR senseKey = (UCHAR)(senseBuffer->SenseKey & 0x0f); - UCHAR additionalSenseCode = 0; - UCHAR additionalSenseCodeQual = 0; - - // Zero the additional sense code and additional sense code qualifier - // if they were not returned by the device. - readSector = senseBuffer->AdditionalSenseLength + offsetof(SENSE_DATA, AdditionalSenseLength); - if (readSector > Srb->SenseInfoBufferLength) - { - readSector = Srb->SenseInfoBufferLength; - } - - additionalSenseCode = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCode)) ? - senseBuffer->AdditionalSenseCode : 0; - additionalSenseCodeQual = (readSector >= RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseCodeQualifier)) ? - senseBuffer->AdditionalSenseCodeQualifier : 0; - - // If sense code is 2/4/1, device is becoming ready from ZPODD mode. According to Mt Fuji, device - // could take up to 800msec to be fully operational. - if ((senseKey == SCSI_SENSE_NOT_READY) && - (additionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) && - (additionalSenseCodeQual == SCSI_SENSEQ_BECOMING_READY)) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "SenseInfoInterpretForZPODD: In process of becoming ready\n")); - - zpoddInfo->BecomingReadyRetryCount--; - - if (zpoddInfo->BecomingReadyRetryCount > 0) - { - DEVICE_EVENT_BECOMING_READY notReady = {0}; - - retry = TRUE; - *Status = STATUS_DEVICE_NOT_READY; - *RetryIntervalIn100ns = BECOMING_READY_RETRY_INTERNVAL_IN_100NS; - - notReady.Version = 1; - notReady.Reason = 1; - notReady.Estimated100msToReady = (ULONG) *RetryIntervalIn100ns / (1000 * 1000); - DeviceSendNotification(DeviceExtension, - &GUID_IO_DEVICE_BECOMING_READY, - sizeof(DEVICE_EVENT_BECOMING_READY), - ¬Ready); - } - } - } - - // now, all decisions are made. display trace information. - if (retry) - { - TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, - "Command shall be retried in %2I64d.%03I64d seconds\n", - (*RetryIntervalIn100ns / UNIT_100NS_PER_SECOND), - (*RetryIntervalIn100ns / 10000) % 1000 - )); - } - else - { - TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, - "Will not retry; Sense/ASC/ASCQ of %02x/%02x/%02x\n", - senseBuffer->SenseKey, - senseBuffer->AdditionalSenseCode, - senseBuffer->AdditionalSenseCodeQualifier - )); - } - - return retry; - -} // end SenseInfoInterpret() - - -BOOLEAN -RequestSenseInfoInterpret( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ WDFREQUEST Request, - _In_ PSCSI_REQUEST_BLOCK Srb, - _In_ ULONG RetriedCount, - _Out_ NTSTATUS* Status, - _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) - LONGLONG* RetryIntervalIn100ns - ) -/*++ - -Routine Description: - -Interpret the error, process it. - 1. Release device queue if it's frozen. - 2. Interpret and process the error. - -Arguments: - - DeviceExtension - Supplies the device object associated with this request. - Request - the Request that error occurs on. - Srb - Supplies the scsi request block which failed. - RetriedCount - retried count. - -Return Value: - - BOOLEAN TRUE: Drivers should retry this request. - FALSE: Drivers should not retry this request. - Status - Returns the status for the request. - RetryIntervalIn100nsUnits - Number of 100ns before the request should be retried. - Zero indicates the request should be immediately retried. - ---*/ -{ - BOOLEAN retry = FALSE; - LONGLONG retryIntervalIn100ns = 0; - PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo; - - if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS) - { - // request succeeded. - if ((zpoddInfo != NULL) && - (zpoddInfo->BecomingReadyRetryCount > 0)) - { - zpoddInfo->BecomingReadyRetryCount = 0; - } - - *Status = STATUS_SUCCESS; - retry = FALSE; - } - else - { - // request failed. We need to process the error. - - // 1. Release the queue if it is frozen. - if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) - { - DeviceReleaseQueue(DeviceExtension->Device); - } - - if ((zpoddInfo != NULL) && - ((zpoddInfo->RetryFirstCommand != FALSE) || (zpoddInfo->BecomingReadyRetryCount > 0))) - { - retry = SenseInfoInterpretForZPODD(DeviceExtension, - Srb, - Status, - &retryIntervalIn100ns); - } - - if (retry == FALSE) - { - // 2. Error Processing - if ((zpoddInfo != NULL) && - (zpoddInfo->BecomingReadyRetryCount > 0)) - { - zpoddInfo->BecomingReadyRetryCount = 0; - } - - retry = SenseInfoInterpret(DeviceExtension, - Request, - Srb, - RetriedCount, - Status, - &retryIntervalIn100ns); - } - } - - if (RetryIntervalIn100ns != NULL) - { - *RetryIntervalIn100ns = retryIntervalIn100ns; - } - - return retry; -} - - -BOOLEAN -RequestSenseInfoInterpretForScratchBuffer( - _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, - _In_ ULONG RetriedCount, - _Out_ NTSTATUS* Status, - _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) - LONGLONG* RetryIntervalIn100ns - ) -/*++ - -Routine Description: - - to analyze the error occurred and set the status, retry interval and decide to retry or not. - -Arguments: - - DeviceExtension - device extension - RetriedCount - already retried count. - -Return Value: - - BOOLEAN - TRUE (should retry) - Status - NTSTATUS - RetryIntervalIn100nsUnits - retry interval - ---*/ -{ - NT_ASSERT(DeviceExtension->ScratchContext.ScratchInUse != 0); - - return RequestSenseInfoInterpret(DeviceExtension, - DeviceExtension->ScratchContext.ScratchRequest, - DeviceExtension->ScratchContext.ScratchSrb, - RetriedCount, - Status, - RetryIntervalIn100ns); -} - - diff --git a/storage/class/cdrom/src/zpodd.c b/storage/class/cdrom/src/zpodd.c deleted file mode 100644 index 9e729143..00000000 --- a/storage/class/cdrom/src/zpodd.c +++ /dev/null @@ -1,823 +0,0 @@ -/*++ - -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 = ExAllocatePool2(POOL_FLAG_NON_PAGED, - sizeof(ZERO_POWER_ODD_INFO), - CDROM_TAG_ZERO_POWER_ODD); - - if (zpoddInfo == NULL) - { - status = STATUS_INSUFFICIENT_RESOURCES; - - goto Cleanup; - } - - // - // 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, - ®istryKey); - - if (NT_SUCCESS(status)) - { - status = WdfRegistryQueryULong(registryKey, - ®istryValueName, - &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); - - // - // 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 - - diff --git a/storage/class/classpnp/classpnp.sln b/storage/class/classpnp/classpnp.sln index 8078e6e1..1c6e04ec 100644 --- a/storage/class/classpnp/classpnp.sln +++ b/storage/class/classpnp/classpnp.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0 @@ -7,16 +7,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "classpnp", "src\classpnp.vc EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|ARM64 = Debug|ARM64 + Release|ARM64 = Release|ARM64 Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CAE2DAC6-A407-41A6-A943-11156A103D14}.Debug|Win32.ActiveCfg = Debug|Win32 - {CAE2DAC6-A407-41A6-A943-11156A103D14}.Debug|Win32.Build.0 = Debug|Win32 - {CAE2DAC6-A407-41A6-A943-11156A103D14}.Release|Win32.ActiveCfg = Release|Win32 - {CAE2DAC6-A407-41A6-A943-11156A103D14}.Release|Win32.Build.0 = Release|Win32 + {CAE2DAC6-A407-41A6-A943-11156A103D14}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CAE2DAC6-A407-41A6-A943-11156A103D14}.Debug|ARM64.Build.0 = Debug|ARM64 + {CAE2DAC6-A407-41A6-A943-11156A103D14}.Release|ARM64.ActiveCfg = Release|ARM64 + {CAE2DAC6-A407-41A6-A943-11156A103D14}.Release|ARM64.Build.0 = Release|ARM64 {CAE2DAC6-A407-41A6-A943-11156A103D14}.Debug|x64.ActiveCfg = Debug|x64 {CAE2DAC6-A407-41A6-A943-11156A103D14}.Debug|x64.Build.0 = Debug|x64 {CAE2DAC6-A407-41A6-A943-11156A103D14}.Release|x64.ActiveCfg = Release|x64 diff --git a/storage/class/classpnp/src/classpnp.vcxproj b/storage/class/classpnp/src/classpnp.vcxproj index 2727ab87..2fc75493 100644 --- a/storage/class/classpnp/src/classpnp.vcxproj +++ b/storage/class/classpnp/src/classpnp.vcxproj @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> + <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> + <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> @@ -23,38 +23,38 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <SupportsPackaging>false</SupportsPackaging> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{58F97C0C-9D73-4882-B4FA-BBEAE3EA4E10}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>ExportDriver</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>ExportDriver</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>ExportDriver</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>ExportDriver</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> @@ -66,13 +66,13 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> <ItemGroup Label="WrappedTaskItems"> @@ -95,13 +95,13 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>classpnp</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetName>classpnp</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetName>classpnp</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>classpnp</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -135,7 +135,7 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS=512</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> @@ -166,7 +166,7 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS=512</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> @@ -197,7 +197,7 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS=512</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> @@ -247,7 +247,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ClCompile> <PreprocessorDefinitions Condition="!('$(UseDebugLibraries)'=='false')">%(PreprocessorDefinitions);DEBUG_USE_KDPRINT</PreprocessorDefinitions> <ExceptionHandling> @@ -266,7 +266,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> <PreprocessorDefinitions Condition="!('$(UseDebugLibraries)'=='false')">%(PreprocessorDefinitions);DEBUG_USE_KDPRINT</PreprocessorDefinitions> <ExceptionHandling> @@ -285,7 +285,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ClCompile> <PreprocessorDefinitions Condition="!('$(UseDebugLibraries)'=='false')">%(PreprocessorDefinitions);DEBUG_USE_KDPRINT</PreprocessorDefinitions> <ExceptionHandling> @@ -314,7 +314,7 @@ </ItemGroup> <Exec Command="if not exist "%(CustomBuildTarget0Input.Identity)" copy ".\%(CustomBuildTarget0Input.Filename)%(CustomBuildTarget0Input.Extension)" "%(CustomBuildTarget0Input.Identity)"" WorkingDirectory="$(MSBuildProjectDirectory)" /> <Exec Command="mofcomp -Amendment:ms_409 -MFL:$(IntDir)\MFL.MFL -MOF:$(IntDir)\MOF.MOF "%(CustomBuildTarget0Input.Identity)"" WorkingDirectory="$(MSBuildProjectDirectory)" /> - <Exec Command="wmimofck -y$(IntDir)\MOF.MOF -z$(IntDir)\MFL.MFL $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> + <Exec Command=""$(WmimofckToolPath)\wmimofck.exe" -y$(IntDir)\MOF.MOF -z$(IntDir)\MFL.MFL $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> <Exec Command="mofcomp -B:".\$(IntDir)\classlog.bmf" $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> </Target> <ItemGroup> diff --git a/storage/class/disk/disk.sln b/storage/class/disk/disk.sln index 26ff24dd..40743058 100644 --- a/storage/class/disk/disk.sln +++ b/storage/class/disk/disk.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0 @@ -7,16 +7,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "disk", "src\disk.vcxproj", EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|ARM64 = Debug|ARM64 + Release|ARM64 = Release|ARM64 Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Debug|Win32.ActiveCfg = Debug|Win32 - {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Debug|Win32.Build.0 = Debug|Win32 - {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Release|Win32.ActiveCfg = Release|Win32 - {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Release|Win32.Build.0 = Release|Win32 + {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Debug|ARM64.Build.0 = Debug|ARM64 + {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Release|ARM64.ActiveCfg = Release|ARM64 + {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Release|ARM64.Build.0 = Release|ARM64 {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Debug|x64.ActiveCfg = Debug|x64 {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Debug|x64.Build.0 = Debug|x64 {C4E8B1CC-0131-442C-8EB8-8E84F938878A}.Release|x64.ActiveCfg = Release|x64 diff --git a/storage/class/disk/src/disk.vcxproj b/storage/class/disk/src/disk.vcxproj index a1e3cf5d..7145df46 100644 --- a/storage/class/disk/src/disk.vcxproj +++ b/storage/class/disk/src/disk.vcxproj @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> + <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> + <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> @@ -23,7 +23,7 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <SupportsPackaging>false</SupportsPackaging> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{1257A10C-96B8-46FB-9FFD-6726981343C7}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> @@ -35,23 +35,23 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> + <UseDebugLibraries>False</UseDebugLibraries> <DriverTargetPlatform>Universal</DriverTargetPlatform> <DriverType>WDM</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> + <UseDebugLibraries>True</UseDebugLibraries> <DriverTargetPlatform>Universal</DriverTargetPlatform> <DriverType>WDM</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> <DriverTargetPlatform>Universal</DriverTargetPlatform> @@ -66,13 +66,13 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> <ItemGroup Label="WrappedTaskItems"> @@ -90,13 +90,13 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>disk</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetName>disk</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetName>disk</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>disk</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -121,7 +121,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\classpnp.lib</AdditionalDependencies> </Link> @@ -143,7 +143,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\classpnp.lib</AdditionalDependencies> </Link> @@ -165,7 +165,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\classpnp.lib</AdditionalDependencies> </Link> diff --git a/storage/class/disk/src/diskdev.inf b/storage/class/disk/src/diskdev.inf index 73a26b23..dd32c4e6 100644 --- a/storage/class/disk/src/diskdev.inf +++ b/storage/class/disk/src/diskdev.inf @@ -14,7 +14,8 @@ Provider=%ProviderName% ClassGUID={4d36e967-e325-11ce-bfc1-08002be10318} Class=DiskDrive DriverVer=08/27/1999,5.2.1425.0 -;CatalogFile=your_cat_here.cat ; Supply your own catalog file here. +CatalogFile=diskdev.cat ; Supply your own catalog file here. +PnpLockdown=1 [DestinationDirs] DefaultDestDir = 12 @@ -24,15 +25,7 @@ DefaultDestDir = 12 ; [Manufacturer] -%MfgName% = Standard.Mfg, NTx86, NTia64, NTamd64 - -[Standard.Mfg.NTx86] -%GenDisk.DeviceDesc% = disk, GenDisk -%GenOptical.DeviceDesc% = disk, GenOptical - -[Standard.Mfg.NTia64] -%GenDisk.DeviceDesc% = disk, GenDisk -%GenOptical.DeviceDesc% = disk, GenOptical +%MfgName% = Standard.Mfg, NTamd64 [Standard.Mfg.NTamd64] %GenDisk.DeviceDesc% = disk, GenDisk @@ -74,12 +67,6 @@ ServiceBinary = %12%\disk.sys ; Source file information ; -[SourceDisksNames.x86] -1 = %DiskId1%,,,\i386 - -[SourceDisksNames.ia64] -1 = %DiskId1%,,,\ia64 - [SourceDisksNames.amd64] 1 = %DiskId1%,,,\amd64 diff --git a/storage/filters/addfilter/README.md b/storage/filters/addfilter/README.md deleted file mode 100644 index 149922df..00000000 --- a/storage/filters/addfilter/README.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -page_type: sample -description: "A command-line application that adds and removes filter drivers for a given drive or volume." -languages: -- cpp -products: -- windows -- windows-wdk ---- - -# AddFilter Storage Filter Tool - -Addfilter is a command-line application that adds and removes filter drivers for a given drive or volume. This application demonstrates how to insert a filter driver into the driver stack of a device. The sample illustrates how to insert such a filter driver by using the SetupDi API. - -## Installation and Operation - -This initial sample does not check the filter for validity before it is added to the driver stack. If an invalid filter is added, the specified device might no longer be accessible. - -The minifilter identifies implicit locks when it sees a non-shared write open request on a volume object. In this scenario, the minifilter closes its metadata file and sets a trigger that corresponds to the volume in its instance object. Later, each close operation is examined to identify if the implicit lock on the volume is being released and, if so, a re-open of the minifilter's metadata file is triggered. - -> [!IMPORTANT] -> If you attempt to add a non-existing filter to a boot device and then restart, the system might show the INACCESSIBLE\_BOOT\_DEVICE error message. If this message appears, you will be unable to start the computer. To fix this problem, when the startup menu is displayed when the computer starts up, go to the Advanced Options screen and select **Use Last Known Good Profile**. - -The sample is intended for use with upper filter drivers only. - -When you add a filter to a device, that device needs to be restarted. Depending on the device, you might also need to restart your computer. The RestartDevice function (in *Addfilter.c*) stops the specified device and then restarts it. If the device has been stopped but not restarted, and the computer is restarted, the restart will not necessarily restart the device. You will need to call the RestartDevice function to restart your device. - -Because the sample currently enumerates only disk devices, the sample can operate only on devices of this class. To extend this sample code, you can add another command-line argument that handles other device types. - -The following is the command line usage for addfilter: - -`addfilter [/listdevices] [/device device_name] [/add filter] [/remove filter]` - -If the device name is not supplied, settings will apply to all devices. If there is no /add or /remove argument, a list of currently installed drivers will be printed. diff --git a/storage/filters/addfilter/addfilter.sln b/storage/filters/addfilter/addfilter.sln deleted file mode 100644 index f2c404f5..00000000 --- a/storage/filters/addfilter/addfilter.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0 -MinimumVisualStudioVersion = 12.0 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "addfilter", "src\addfilter.vcxproj", "{95C071C0-CBCC-4943-BB7D-90E2EDD17043}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {95C071C0-CBCC-4943-BB7D-90E2EDD17043}.Debug|Win32.ActiveCfg = Debug|Win32 - {95C071C0-CBCC-4943-BB7D-90E2EDD17043}.Debug|Win32.Build.0 = Debug|Win32 - {95C071C0-CBCC-4943-BB7D-90E2EDD17043}.Release|Win32.ActiveCfg = Release|Win32 - {95C071C0-CBCC-4943-BB7D-90E2EDD17043}.Release|Win32.Build.0 = Release|Win32 - {95C071C0-CBCC-4943-BB7D-90E2EDD17043}.Debug|x64.ActiveCfg = Debug|x64 - {95C071C0-CBCC-4943-BB7D-90E2EDD17043}.Debug|x64.Build.0 = Debug|x64 - {95C071C0-CBCC-4943-BB7D-90E2EDD17043}.Release|x64.ActiveCfg = Release|x64 - {95C071C0-CBCC-4943-BB7D-90E2EDD17043}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/storage/filters/addfilter/src/addfilter.c b/storage/filters/addfilter/src/addfilter.c deleted file mode 100644 index 5c319bf7..00000000 --- a/storage/filters/addfilter/src/addfilter.c +++ /dev/null @@ -1,1129 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, 1999 - 1999 - -Module Name: - - addfilter.c - -Abstract: - - This command line utility adds and removes upper filter drivers - for a given drive or volume - -Author: - - Benjamin Strautin (t-bensta) - -Environment: - - User mode only - -Notes: - - - the filter is not checked for validity before it is added to the driver - stack; if an invalid filter is added, the device may no longer be - accessible. - - all code works irrespective of character set (ANSI, Unicode, ...) - -Revision History: - - 05-24-99 : created - ---*/ - -#include <driverspecs.h> -_Analysis_mode_(_Analysis_code_type_user_code_); - -#include <windows.h> -#include <stdio.h> -#include <malloc.h> - -// defines GUID -#include <initguid.h> - -// the SetupDiXXX api (from the DDK) -#include <setupapi.h> - -// defines guids for device classes (GUID_DEVINTERFACE_DISK, etc) -#include <devioctl.h> -#include <ntddstor.h> - -// for all of the _t stuff (to allow compiling for both Unicode/Ansi) -#include <tchar.h> - -#include <strsafe.h> - -#if DBG -#include <assert.h> -#define ASSERT(condition) assert(condition) -#else -#define ASSERT(condition) -#endif - -BOOLEAN -AddFilterDriver( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - _In_ IN LPTSTR Filter, - IN BOOLEAN UpperFilter - ); - -BOOLEAN -RemoveFilterDriver( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - _In_ IN LPTSTR Filter, - IN BOOLEAN UpperFilter - ); - -void -PrintFilters( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - IN BOOLEAN UpperFilters - ); - -LPTSTR -GetFilters( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - IN BOOLEAN UpperFilters - ); - -void PrintDeviceName( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData - ); - -BOOLEAN -DeviceNameMatches( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - _In_ IN LPTSTR DeviceName - ); - -PBYTE -GetDeviceRegistryProperty( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - IN DWORD Property, - OUT PDWORD PropertyRegDataType - ); - -BOOLEAN -RestartDevice( - IN HDEVINFO DeviceInfoSet, - IN OUT PSP_DEVINFO_DATA DeviceInfoData - ); - -BOOLEAN -PrependSzToMultiSz( - _In_ LPTSTR SzToPrepend, - _Inout_ LPTSTR *MultiSz - ); - -size_t -MultiSzLength( - _In_ IN LPTSTR MultiSz - ); - -size_t -MultiSzSearchAndDeleteCaseInsensitive( - _In_ IN LPTSTR FindThis, - _In_ IN LPTSTR FindWithin, - OUT size_t *NewStringLength - ); - -void -PrintUsage(); - -// To add/remove filter drivers: -// - use SetupDiGetClassDevs to get a list of devices of the given interface -// class -// - use SetupDiEnumDeviceInfo to enumerate the items in that list and -// obtain a SP_DEVINFO_DATA -// - use SetupDiGetDeviceRegistryProperty to get the list of filter drivers -// - add/remove items in the filter list -// - use SetupDiSetDeviceRegistryProperty to put the list back in place -// To restart the device: -// - use SetupDiCallClassInstaller with DIF_PROPERTYCHANGE and DICS_STOP to -// stop the device -// - use SetupDiCallClassInstaller with DIF_PROPERTYCHANGE and DICS_START to -// restart the device - -int __cdecl _tmain(int argc, _In_reads_(argc) LPTSTR argv[]) -{ - // these two constants are used to help enumerate through the list of all - // disks and volumes on the system. Adding another GUID should "just work" - static const GUID * deviceGuids[] = { - &GUID_DEVINTERFACE_DISK, - &GUID_DEVINTERFACE_VOLUME, - &GUID_DEVINTERFACE_CDROM - }; - static const int numdeviceGuids = sizeof(deviceGuids) / sizeof(LPGUID); - - // structs needed to contain information about devices - HDEVINFO devInfo = INVALID_HANDLE_VALUE; - SP_DEVINFO_DATA devInfoData; - - // indices for stepping through devices, and device interface guids - int argIndex; - int devGuidIndex; - int deviceIndex; - - // variables used to deal with the command-line options of this program - BOOLEAN listDevices = FALSE; - BOOLEAN upperFilter = TRUE; - - LPTSTR deviceName = NULL; - LPTSTR filterToAdd = NULL; - LPTSTR filterToRemove = NULL; - - BOOLEAN keepGoing = TRUE; - BOOLEAN needReboot = FALSE; - BOOLEAN deviceMatch = FALSE; - - //////////////////////////////////////////////// - // parse arguments; nothing too exciting here // - //////////////////////////////////////////////// - - if( argc < 2 || _tcscmp(argv[1], _T("/?")) == 0 ) - { - PrintUsage(); - return (0); - } - - for (argIndex = 1; argIndex < argc; argIndex++) { - -#pragma prefast(suppress:6385, "Previously checked argIndex being less than argc. No buffer overflow.") - if( _tcscmp(argv[argIndex], _T("/listdevices")) == 0 ) { - - listDevices = TRUE; - - } else if( _tcscmp(argv[argIndex], _T("/lower")) == 0 ) { - - upperFilter = FALSE; - printf("Using Lower Filters\n"); - - } else if( _tcscmp(argv[argIndex], _T("/device")) == 0 ) { - - argIndex++; - - if( argIndex < argc ) { - deviceName = argv[argIndex]; - } else { - PrintUsage(); - return (0); - } - - } else if( _tcscmp(argv[argIndex], _T("/add")) == 0 ) { - - argIndex++; - - if( argIndex<argc ) { - filterToAdd = argv[argIndex]; - } else { - PrintUsage(); - return (0); - } - - } else if( _tcscmp(argv[argIndex], _T("/remove")) == 0 ) { - - argIndex++; - if( argIndex<argc ) { - filterToRemove = argv[argIndex]; - } else { - PrintUsage(); - return (0); - } - - } else { - PrintUsage(); - return (0); - } - - } - - ////////////////////////////////////////////////////// - // done parsing arguments, move onto the good stuff // - ////////////////////////////////////////////////////// - - // This outer loop steps through the array of device guid pointers that is - // defined above main(). It was just the easiest way to deal with both - // Disks and Volumes (and it is easy to add other types of devices) - - for(devGuidIndex = 0; devGuidIndex<numdeviceGuids; devGuidIndex++) { - - // get a list of devices which support the given interface - devInfo = SetupDiGetClassDevs( deviceGuids[devGuidIndex], - NULL, - NULL, - DIGCF_PROFILE | - DIGCF_DEVICEINTERFACE | - DIGCF_PRESENT ); - - if( devInfo == INVALID_HANDLE_VALUE ) { - printf("got INVALID_HANDLE_VALUE!\n"); - return (1); - } - - // as per DDK docs on SetupDiEnumDeviceInfo - devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - - // step through the list of devices for this handle - // get device info at index deviceIndex, the function returns FALSE - // when there is no device at the given index. - for( deviceIndex=0; - SetupDiEnumDeviceInfo( devInfo, deviceIndex, &devInfoData ); - deviceIndex++ ) { - - // setting this variable to FALSE will cause all of the if - // statements to fall through, cutting off processing for this - // device. - keepGoing = TRUE; - - // if a device name was specified, and it doesn't match this one, - // stop. If there is a match (or no name was specified), mark that - // there was a match. - if( deviceName != NULL && - !DeviceNameMatches( devInfo, &devInfoData, deviceName ) - ) { - - keepGoing = FALSE; - - } else { - - deviceMatch = TRUE; - - } - - // print the device name - if( keepGoing && listDevices ) { - - PrintDeviceName( devInfo, &devInfoData ); - - } - - // print the drivers, if we are not adding or removing one - if( keepGoing && filterToAdd == NULL && filterToRemove == NULL ) { - - PrintFilters( devInfo, &devInfoData, upperFilter ); - - } - - // add the filter, then try to restart the device - if( keepGoing && filterToAdd != NULL ) { - - if( !AddFilterDriver(devInfo, - &devInfoData, - filterToAdd, - upperFilter)) { - - printf("Unable to add filter!\n"); - - } else { - - if( !RestartDevice( devInfo, &devInfoData) ) { - needReboot = TRUE; - } - - } - } - - // remove the filter, then try to restart the device - if( keepGoing && filterToRemove != NULL ) { - - if( !RemoveFilterDriver(devInfo, - &devInfoData, - filterToRemove, - upperFilter)) { - - printf("Unable to remove filter!\n"); - - } else { - - if( !RestartDevice( devInfo, &devInfoData) ) { - needReboot = TRUE; - } - - } - - } - - if( listDevices ) - { - printf("\n"); - } - - // end of main processing loop - } - - // clean up the device list - if( devInfo != INVALID_HANDLE_VALUE ) { - - if( !SetupDiDestroyDeviceInfoList( devInfo ) ) { - printf("unable to delete device info list! error: %u\n", - GetLastError()); - } - - } - - } // loop for each GUID index - - if( !deviceMatch ) { - - printf("No devices matched that name\n"); - - } else { - - if( needReboot ) { - - printf("One or more devices could not be restarted. The machine " - "must be restarted\n" - "in order for settings to take effect\n"); - - } else { - - printf("Everything has completed normally.\n"); - return (2); - - } - - } - - return (0); -} - - -/* - * add the given filter driver to the list of upper filter drivers for the - * device. - * - * After the call, the device must be restarted in order for the new setting to - * take effect. This can be accomplished with a call to RestartDevice(), or by - * rebooting the machine. - * - * returns TRUE if successful, FALSE otherwise - * - * note: The filter is prepended to the list of drivers, which will put it at - * the bottom of the filter driver stack - * - * parameters: - * DeviceInfoSet - The device information set which contains DeviceInfoData - * DeviceInfoData - Information needed to deal with the given device - * Filter - the filter to add - */ -BOOLEAN -AddFilterDriver( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - _In_ IN LPTSTR Filter, - IN BOOLEAN UpperFilter - ) -{ - size_t length = 0; // character length - size_t size = 0; // buffer size - LPTSTR buffer = GetFilters( DeviceInfoSet, DeviceInfoData, UpperFilter ); - - ASSERT(DeviceInfoData != NULL); - ASSERT(Filter != NULL); - - if( buffer == NULL ) - { - // if there is no such value in the registry, then there are no upper - // filter drivers loaded, and we can just put one there - - // make room for the string, string null terminator, and multisz null - // terminator - length = _tcslen(Filter)+1; - size = (length+1)*sizeof(_TCHAR); - buffer = malloc( size ); - if( buffer == NULL ) - { - printf("in AddUpperFilterDriver(): unable to allocate memory!\n"); - return (FALSE); - } - memset(buffer, 0, size); - - // copy the string into the new buffer - - memcpy(buffer, Filter, length*sizeof(_TCHAR)); - - } - else - { - LPTSTR buffer2; - // remove all instances of filter from driver list - MultiSzSearchAndDeleteCaseInsensitive( Filter, buffer, &length ); - - // allocate a buffer large enough to add the new filter - // MultiSzLength already includes length of terminating NULL - - // determing the new length of the string - length = MultiSzLength(buffer) + _tcslen(Filter) + 1; - size = length*sizeof(_TCHAR); - - buffer2 = malloc( size ); - if (buffer2 == NULL) { - printf("Out of memory adding filter\n"); - return (0); - } - memset(buffer2, 0, size); - - // swap the buffers out - memcpy(buffer2, buffer, MultiSzLength(buffer)*sizeof(_TCHAR)); - free(buffer); - buffer = buffer2; - - // add the driver to the driver list - PrependSzToMultiSz(Filter, &buffer); - - } - - // set the new list of filters in place - if( !SetupDiSetDeviceRegistryProperty( DeviceInfoSet, - DeviceInfoData, - (UpperFilter ? SPDRP_UPPERFILTERS : SPDRP_LOWERFILTERS), - (PBYTE)buffer, - (DWORD)(MultiSzLength(buffer)*sizeof(_TCHAR)) ) - ) - { - printf("in AddUpperFilterDriver(): " - "couldn't set registry value! error: %u\n", GetLastError()); - free( buffer ); - return (FALSE); - } - - // no need for buffer anymore - free( buffer ); - - return (TRUE); -} - - -/* - * remove all instances of the given filter driver from the list of upper - * filter drivers for the device. - * - * After the call, the device must be restarted in order for the new setting to - * take effect. This can be accomplished with a call to RestartDevice(), or by - * rebooting the machine. - * - * returns TRUE if successful, FALSE otherwise - * - * parameters: - * DeviceInfoSet - The device information set which contains DeviceInfoData - * DeviceInfoData - Information needed to deal with the given device - * Filter - the filter to remove - */ -BOOLEAN -RemoveFilterDriver( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - _In_ IN LPTSTR Filter, - IN BOOLEAN UpperFilter - ) -{ - size_t length = 0; - size_t size = 0; - LPTSTR buffer = GetFilters( DeviceInfoSet, DeviceInfoData, UpperFilter ); - BOOL success = FALSE; - - ASSERT(DeviceInfoData != NULL); - ASSERT(Filter != NULL); - - if( buffer == NULL ) - { - // if there is no such value in the registry, then there are no upper - // filter drivers loaded, and we are done - return (TRUE); - } - else - { - // remove all instances of filter from driver list - MultiSzSearchAndDeleteCaseInsensitive( Filter, buffer, &length ); - } - - length = MultiSzLength(buffer); - - ASSERT ( length > 0 ); - - if( length == 1 ) - { - // if the length of the list is 1, the return value from - // MultiSzLength() was just accounting for the trailing '\0', so we can - // delete the registry key, by setting it to NULL. - success = SetupDiSetDeviceRegistryProperty( DeviceInfoSet, - DeviceInfoData, - (UpperFilter ? SPDRP_UPPERFILTERS : SPDRP_LOWERFILTERS), - NULL, - 0 ); - } - else - { - // set the new list of drivers into the registry - size = length*sizeof(_TCHAR); - success = SetupDiSetDeviceRegistryProperty( DeviceInfoSet, - DeviceInfoData, - (UpperFilter ? SPDRP_UPPERFILTERS : SPDRP_LOWERFILTERS), - (PBYTE)buffer, - (DWORD)size ); - } - - // no need for buffer anymore - free( buffer ); - - if( !success ) - { - printf("in RemoveUpperFilterDriver(): " - "couldn't set registry value! error: %u\n", GetLastError()); - return (FALSE); - } - - return (TRUE); -} - -/* - * print the list of upper filters for the given device - * - * parameters: - * DeviceInfoSet - The device information set which contains DeviceInfoData - * DeviceInfoData - Information needed to deal with the given device - */ -void -PrintFilters( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - IN BOOLEAN UpperFilters - ) -{ - // get the list of filters - LPTSTR buffer = GetFilters( DeviceInfoSet, DeviceInfoData, UpperFilters ); - LPTSTR filterName; - DWORD filterPosition; - - if( buffer == NULL ) - { - // if there is no such value in the registry, then there are no upper - // filter drivers loaded - printf("There are no upper filter drivers loaded for this device.\n"); - } - else - { - // go through the multisz and print out each driver - filterPosition=0; - filterName = buffer; - while( *filterName != _T('\0') ) - { - _tprintf(_T("%u: %s\n"), filterPosition, filterName); - filterName += _tcslen(filterName)+1; - filterPosition++; - } - - // no need for buffer anymore - free( buffer ); - } - - return; -} - -/* - * print the device name - * - * parameters: - * DeviceInfoSet - The device information set which contains DeviceInfoData - * DeviceInfoData - Information needed to deal with the given device - */ -void PrintDeviceName( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData - ) -{ - DWORD regDataType; - LPTSTR deviceName = - (LPTSTR) GetDeviceRegistryProperty( DeviceInfoSet, - DeviceInfoData, - SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, - ®DataType ); - - if( deviceName != NULL ) - { - // just to make sure we are getting the expected type of buffer - if( regDataType != REG_SZ ) - { - printf("in PrintDeviceName(): registry key is not an SZ!\n"); - } - else - { - // if the device name starts with \Device, cut that off (all - // devices will start with it, so it is redundant) - - if( _tcsncmp(deviceName, _T("\\Device"), 7) == 0 ) - { - memmove(deviceName, - deviceName+7, - (_tcslen(deviceName)-6)*sizeof(_TCHAR) ); - } - - _tprintf(_T("%s\n"), deviceName); - } - free( deviceName ); - } - else - { - printf("in PrintDeviceName(): registry key is NULL! error: %u\n", - GetLastError()); - } - - return; -} - -/* - * Returns a buffer containing the list of upper filters for the device. (NULL - * is returned if there is no buffer, or an error occurs) - * The buffer must be freed by the caller. - * - * parameters: - * DeviceInfoSet - The device information set which contains DeviceInfoData - * DeviceInfoData - Information needed to deal with the given device - */ -LPTSTR -GetFilters( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - IN BOOLEAN UpperFilters - ) -{ - DWORD regDataType; - LPTSTR buffer = (LPTSTR) GetDeviceRegistryProperty( DeviceInfoSet, - DeviceInfoData, - (UpperFilters ? SPDRP_UPPERFILTERS : SPDRP_LOWERFILTERS), - ®DataType ); - - // just to make sure we are getting the expected type of buffer - if( buffer != NULL && regDataType != REG_MULTI_SZ ) - { - printf("in GetUpperFilters(): " - "registry key is not a MULTI_SZ!\n"); - free( buffer ); - return (NULL); - } - - return (buffer); -} - -/* - * return true if DeviceName matches the name of the device specified by - * DeviceInfoData - * - * parameters: - * DeviceInfoSet - The device information set which contains DeviceInfoData - * DeviceInfoData - Information needed to deal with the given device - * DeviceName - the name to try to match - */ -BOOLEAN -DeviceNameMatches( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - _In_ IN LPTSTR DeviceName - ) -{ - BOOLEAN matching = FALSE; - DWORD regDataType; - - // get the device name - LPTSTR deviceName = - (LPTSTR) GetDeviceRegistryProperty( DeviceInfoSet, - DeviceInfoData, - SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, - ®DataType ); - - if( deviceName != NULL ) - { - // just to make sure we are getting the expected type of buffer - if( regDataType != REG_SZ ) - { - printf("in DeviceNameMatches(): registry key is not an SZ!\n"); - matching = FALSE; - } - else - { - // if the device name starts with \Device, cut that off (all - // devices will start with it, so it is redundant) - - if( _tcsncmp(deviceName, _T("\\Device"), 7) == 0 ) - { - memmove(deviceName, - deviceName+7, - (_tcslen(deviceName)-6)*sizeof(_TCHAR) ); - } - - // do the strings match? - matching = (_tcscmp(deviceName, DeviceName) == 0) ? TRUE : FALSE; - } - free( deviceName ); - } - else - { - printf("in DeviceNameMatches(): registry key is NULL!\n"); - matching = FALSE; - } - - return (matching); -} - -/* - * A wrapper around SetupDiGetDeviceRegistryProperty, so that I don't have to - * deal with memory allocation anywhere else - * - * parameters: - * DeviceInfoSet - The device information set which contains DeviceInfoData - * DeviceInfoData - Information needed to deal with the given device - * Property - which property to get (SPDRP_XXX) - * PropertyRegDataType - the type of registry property - */ -PBYTE -GetDeviceRegistryProperty( - IN HDEVINFO DeviceInfoSet, - IN PSP_DEVINFO_DATA DeviceInfoData, - IN DWORD Property, - OUT PDWORD PropertyRegDataType - ) -{ - DWORD length = 0; - PBYTE buffer = NULL; - - // get the required length of the buffer - if( SetupDiGetDeviceRegistryProperty( DeviceInfoSet, - DeviceInfoData, - Property, - NULL, // registry data type - NULL, // buffer - 0, // buffer size - &length // required size - ) ) - { - // we should not be successful at this point, so this call succeeding - // is an error condition - printf("in GetDeviceRegistryProperty(): " - "call SetupDiGetDeviceRegistryProperty did not fail? (%x)\n", - GetLastError()); - return (NULL); - } - - if( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) - { - // this means there are no upper filter drivers loaded, so we can just - // return. - return (NULL); - } - - // since we don't have a buffer yet, it is "insufficient"; we allocate - // one and try again. - buffer = malloc( length ); - if( buffer == NULL ) - { - printf("in GetDeviceRegistryProperty(): " - "unable to allocate memory!\n"); - return (NULL); - } - if( !SetupDiGetDeviceRegistryProperty( DeviceInfoSet, - DeviceInfoData, - Property, - PropertyRegDataType, - buffer, - length, - NULL // required size - ) ) - { - printf("in GetDeviceRegistryProperty(): " - "couldn't get registry property! error: %u\n", - GetLastError()); - free( buffer ); - return (NULL); - } - - // ok, we are finally done, and can return the buffer - return (buffer); -} - - -/* - * restarts the given device - * - * call CM_Query_And_Remove_Subtree (to unload the driver) - * call CM_Reenumerate_DevNode on the _parent_ (to reload the driver) - * - * parameters: - * DeviceInfoSet - The device information set which contains DeviceInfoData - * DeviceInfoData - Information needed to deal with the given device - */ -BOOLEAN -RestartDevice( - IN HDEVINFO DeviceInfoSet, - IN OUT PSP_DEVINFO_DATA DeviceInfoData - ) -{ - SP_PROPCHANGE_PARAMS params; - SP_DEVINSTALL_PARAMS installParams; - - // for future compatibility; this will zero out the entire struct, rather - // than just the fields which exist now - memset(¶ms, 0, sizeof(SP_PROPCHANGE_PARAMS)); - - // initialize the SP_CLASSINSTALL_HEADER struct at the beginning of the - // SP_PROPCHANGE_PARAMS struct, so that SetupDiSetClassInstallParams will - // work - params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); - params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; - - // initialize SP_PROPCHANGE_PARAMS such that the device will be stopped. - params.StateChange = DICS_STOP; - params.Scope = DICS_FLAG_CONFIGSPECIFIC; - params.HwProfile = 0; // current profile - - // prepare for the call to SetupDiCallClassInstaller (to stop the device) - if( !SetupDiSetClassInstallParams( DeviceInfoSet, - DeviceInfoData, - (PSP_CLASSINSTALL_HEADER) ¶ms, - sizeof(SP_PROPCHANGE_PARAMS) - ) ) - { - printf("in RestartDevice(): couldn't set the install parameters!"); - printf(" error: %u\n", GetLastError()); - return (FALSE); - } - - // stop the device - if( !SetupDiCallClassInstaller( DIF_PROPERTYCHANGE, - DeviceInfoSet, - DeviceInfoData ) - ) - { - printf("in RestartDevice(): call to class installer (STOP) failed!"); - printf(" error: %u\n", GetLastError() ); - return (FALSE); - } - - // restarting the device - params.StateChange = DICS_START; - - // prepare for the call to SetupDiCallClassInstaller (to stop the device) - if( !SetupDiSetClassInstallParams( DeviceInfoSet, - DeviceInfoData, - (PSP_CLASSINSTALL_HEADER) ¶ms, - sizeof(SP_PROPCHANGE_PARAMS) - ) ) - { - printf("in RestartDevice(): couldn't set the install parameters!"); - printf(" error: %u\n", GetLastError()); - return (FALSE); - } - - // restart the device - if( !SetupDiCallClassInstaller( DIF_PROPERTYCHANGE, - DeviceInfoSet, - DeviceInfoData ) - ) - { - printf("in RestartDevice(): call to class installer (START) failed!"); - printf(" error: %u\n", GetLastError()); - return (FALSE); - } - - installParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); - - // same as above, the call will succeed, but we still need to check status - if( !SetupDiGetDeviceInstallParams( DeviceInfoSet, - DeviceInfoData, - &installParams ) - ) - { - printf("in RestartDevice(): couldn't get the device install params!"); - printf(" error: %u\n", GetLastError() ); - return (FALSE); - } - - // to see if the machine needs to be rebooted - if( installParams.Flags & DI_NEEDREBOOT ) - { - return (FALSE); - } - - // if we get this far, then the device has been stopped and restarted - return (TRUE); -} - - -/* - * prepend the given string to a MultiSz - * - * returns true if successful, false if not (will only fail in memory - * allocation) - * - * note: This WILL allocate and free memory, so don't keep pointers to the - * MultiSz passed in. - * - * parameters: - * SzToPrepend - string to prepend - * MultiSz - pointer to a MultiSz which will be prepended-to - */ -BOOLEAN -PrependSzToMultiSz( - _In_ LPTSTR SzToPrepend, - _Inout_ LPTSTR *MultiSz - ) -{ - size_t szLen; - size_t multiSzLen; - LPTSTR newMultiSz = NULL; - - ASSERT(SzToPrepend != NULL); - ASSERT(MultiSz != NULL); - - if (SzToPrepend == NULL || MultiSz == NULL) { - return (FALSE); - } - - // get the size, in bytes, of the two buffers - szLen = (_tcslen(SzToPrepend)+1)*sizeof(_TCHAR); - multiSzLen = MultiSzLength(*MultiSz)*sizeof(_TCHAR); - newMultiSz = (LPTSTR)malloc( szLen+multiSzLen ); - - if( newMultiSz == NULL ) - { - return (FALSE); - } - - // recopy the old MultiSz into proper position into the new buffer. - // the (char*) cast is necessary, because newMultiSz may be a wchar*, and - // szLen is in bytes. - - memcpy( ((char*)newMultiSz) + szLen, *MultiSz, multiSzLen ); - - // copy in the new string - StringCbCopy( newMultiSz, szLen, SzToPrepend ); - - free( *MultiSz ); - *MultiSz = newMultiSz; - - return (TRUE); -} - - -/* - * returns the length (in characters) of the buffer required to hold this - * MultiSz, INCLUDING the trailing null. - * - * example: MultiSzLength("foo\0bar\0") returns 9 - * - * note: since MultiSz cannot be null, a number >= 1 will always be returned - * - * parameters: - * MultiSz - the MultiSz to get the length of - */ -size_t -MultiSzLength( - _In_ IN LPTSTR MultiSz - ) -{ - size_t len = 0; - size_t totalLen = 0; - - ASSERT( MultiSz != NULL ); - - // search for trailing null character - while( *MultiSz != _T('\0') ) - { - len = _tcslen(MultiSz)+1; - MultiSz += len; - totalLen += len; - } - - // add one for the trailing null character - return (totalLen+1); -} - - -/* - * Deletes all instances of a string from within a multi-sz. - * - * parameters: - * FindThis - the string to find and remove - * FindWithin - the string having the instances removed - * NewStringLength - the new string length - */ -size_t -MultiSzSearchAndDeleteCaseInsensitive( - _In_ IN LPTSTR FindThis, - _In_ IN LPTSTR FindWithin, - OUT size_t *NewLength - ) -{ - LPTSTR search; - size_t currentOffset; - DWORD instancesDeleted; - size_t searchLen; - - ASSERT(FindThis != NULL); - ASSERT(FindWithin != NULL); - ASSERT(NewLength != NULL); - - currentOffset = 0; - instancesDeleted = 0; - search = FindWithin; - - *NewLength = MultiSzLength(FindWithin); - - // loop while the multisz null terminator is not found - while ( *search != _T('\0') ) - { - // length of string + null char; used in more than a couple places - searchLen = _tcslen(search) + 1; - - // if this string matches the current one in the multisz... - if( _tcsicmp(search, FindThis) == 0 ) - { - // they match, shift the contents of the multisz, to overwrite the - // string (and terminating null), and update the length - instancesDeleted++; - *NewLength -= searchLen; - memmove( search, - search + searchLen, - (*NewLength - currentOffset) * sizeof(TCHAR) ); - } - else - { - // they don't mactch, so move pointers, increment counters - currentOffset += searchLen; - search += searchLen; - } - } - - return (instancesDeleted); -} - - -/* - * print usage - */ -void PrintUsage() -{ - printf("usage:\n\n" - "addfilter" - " [/listdevices]" - " [/device device_name]" - " [/add filter]" - " [/remove filter]" - " [/lower]" - "\n\n"); - printf("If device_name is not supplied, settings will apply " - "to all devices.\n"); - printf("If there is no /add or /remove argument, a list of currently" - " installed drivers\n" - "will be printed.\n"); - printf("The default is to process upper filters. Use the /lower switch" - " to process lower filters instead.\n"); - return; -} diff --git a/storage/filters/addfilter/src/addfilter.rc b/storage/filters/addfilter/src/addfilter.rc deleted file mode 100644 index 2568f031..00000000 --- a/storage/filters/addfilter/src/addfilter.rc +++ /dev/null @@ -1,21 +0,0 @@ -//+------------------------------------------------------------------------- -// -// Microsoft Windows -// -// Copyright (C) Microsoft Corporation, 1999 - 1999 -// -// File: addfilter.rc -// -//-------------------------------------------------------------------------- - -#include <windows.h> -#include <ntverp.h> - -#define VER_FILETYPE VFT_APP -#define VER_FILESUBTYPE VFT2_UNKNOWN -#define VER_FILEDESCRIPTION_STR "Microsoft add/remove filter drivers sample utility" - -#define VER_INTERNALNAME_STR "addfilter.exe" -#define VER_ORIGINALFILENAME_STR "addfilter.exe" - -#include <common.ver> diff --git a/storage/filters/addfilter/src/addfilter.vcxproj b/storage/filters/addfilter/src/addfilter.vcxproj deleted file mode 100644 index 1cb9300f..00000000 --- a/storage/filters/addfilter/src/addfilter.vcxproj +++ /dev/null @@ -1,191 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{95C071C0-CBCC-4943-BB7D-90E2EDD17043}</ProjectGuid> - <RootNamespace>$(MSBuildProjectName)</RootNamespace> - <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> - <SampleGuid>{E441786B-1740-49DB-ACB6-E800A4DB2D15}</SampleGuid> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>Application</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>Application</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>Application</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>Application</ConfigurationType> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <PropertyGroup> - <OutDir>$(IntDir)</OutDir> - </PropertyGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ItemGroup Label="WrappedTaskItems" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <TargetName>addfilter</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <TargetName>addfilter</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>addfilter</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>addfilter</TargetName> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - </Midl> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - </Midl> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - </Midl> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions> - </Midl> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="addfilter.c" /> - <ResourceCompile Include="addfilter.rc" /> - </ItemGroup> - <ItemGroup> - <Inf Exclude="@(Inf)" Include="*.inf" /> - <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> - </ItemGroup> - <ItemGroup> - <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> - <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> - <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> - </ItemGroup> - <ItemGroup> - <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project>
\ No newline at end of file diff --git a/storage/filters/addfilter/src/addfilter.vcxproj.Filters b/storage/filters/addfilter/src/addfilter.vcxproj.Filters deleted file mode 100644 index 9b5df5cf..00000000 --- a/storage/filters/addfilter/src/addfilter.vcxproj.Filters +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> - <UniqueIdentifier>{BFD7B380-2B08-4124-81F2-BD9E9E1E59BB}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files"> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - <UniqueIdentifier>{84770C65-A89D-40AC-BFB6-2D42A6ECD7C4}</UniqueIdentifier> - </Filter> - <Filter Include="Resource Files"> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> - <UniqueIdentifier>{E60018BB-F626-48CB-90FA-2817FC2C2C06}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="addfilter.c"> - <Filter>Source Files</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="addfilter.rc"> - <Filter>Resource Files</Filter> - </ResourceCompile> - </ItemGroup> -</Project>
\ No newline at end of file diff --git a/storage/iscsi/iscsi.sln b/storage/iscsi/iscsi.sln index 819e26da..9ec75219 100644 --- a/storage/iscsi/iscsi.sln +++ b/storage/iscsi/iscsi.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0 @@ -7,16 +7,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmptyProject", "src\EmptyPr EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|ARM64 = Debug|ARM64 + Release|ARM64 = Release|ARM64 Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Debug|Win32.ActiveCfg = Debug|Win32 - {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Debug|Win32.Build.0 = Debug|Win32 - {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Release|Win32.ActiveCfg = Release|Win32 - {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Release|Win32.Build.0 = Release|Win32 + {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Debug|ARM64.Build.0 = Debug|ARM64 + {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Release|ARM64.ActiveCfg = Release|ARM64 + {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Release|ARM64.Build.0 = Release|ARM64 {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Debug|x64.ActiveCfg = Debug|x64 {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Debug|x64.Build.0 = Debug|x64 {D522AB21-5E8C-4E3F-9934-AE9C8C23C7E6}.Release|x64.ActiveCfg = Release|x64 diff --git a/storage/iscsi/src/EmptyProject.vcxproj b/storage/iscsi/src/EmptyProject.vcxproj index 21c5ce69..51057d78 100644 --- a/storage/iscsi/src/EmptyProject.vcxproj +++ b/storage/iscsi/src/EmptyProject.vcxproj @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> + <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> + <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> @@ -23,7 +23,7 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <SupportsPackaging>false</SupportsPackaging> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{DDD40F41-C9A9-428F-8C00-862850DDBB19}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> @@ -35,23 +35,23 @@ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> + <UseDebugLibraries>False</UseDebugLibraries> <DriverTargetPlatform>Desktop</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> + <UseDebugLibraries>True</UseDebugLibraries> <DriverTargetPlatform>Desktop</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> <DriverTargetPlatform>Desktop</DriverTargetPlatform> @@ -66,26 +66,26 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>EmptyProject</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetName>EmptyProject</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetName>EmptyProject</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>EmptyProject</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -97,7 +97,7 @@ <NoEntryPoint>true</NoEntryPoint> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ClCompile> <ExceptionHandling> </ExceptionHandling> @@ -106,7 +106,7 @@ <NoEntryPoint>true</NoEntryPoint> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> <ExceptionHandling> </ExceptionHandling> @@ -115,7 +115,7 @@ <NoEntryPoint>true</NoEntryPoint> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ClCompile> <ExceptionHandling> </ExceptionHandling> diff --git a/storage/miniports/lsi_u3/lsi_u3.sln b/storage/miniports/lsi_u3/lsi_u3.sln index 94476382..621da2e2 100644 --- a/storage/miniports/lsi_u3/lsi_u3.sln +++ b/storage/miniports/lsi_u3/lsi_u3.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0 @@ -7,16 +7,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lsi_u3", "src\lsi_u3.vcxpro EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|ARM64 = Debug|ARM64 + Release|ARM64 = Release|ARM64 Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Debug|Win32.ActiveCfg = Debug|Win32 - {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Debug|Win32.Build.0 = Debug|Win32 - {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Release|Win32.ActiveCfg = Release|Win32 - {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Release|Win32.Build.0 = Release|Win32 + {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Debug|ARM64.Build.0 = Debug|ARM64 + {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Release|ARM64.ActiveCfg = Release|ARM64 + {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Release|ARM64.Build.0 = Release|ARM64 {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Debug|x64.ActiveCfg = Debug|x64 {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Debug|x64.Build.0 = Debug|x64 {75BE5762-0334-4CA9-9018-831B9DFFCB0A}.Release|x64.ActiveCfg = Release|x64 diff --git a/storage/miniports/lsi_u3/src/lsi_u3.inf b/storage/miniports/lsi_u3/src/lsi_u3.inf Binary files differindex 8d631d41..5a879f51 100644 --- a/storage/miniports/lsi_u3/src/lsi_u3.inf +++ b/storage/miniports/lsi_u3/src/lsi_u3.inf diff --git a/storage/miniports/lsi_u3/src/lsi_u3.vcxproj b/storage/miniports/lsi_u3/src/lsi_u3.vcxproj index 4c380734..c8344d93 100644 --- a/storage/miniports/lsi_u3/src/lsi_u3.vcxproj +++ b/storage/miniports/lsi_u3/src/lsi_u3.vcxproj @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> + <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> + <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> @@ -22,7 +22,7 @@ <ProjectGuid>{75BE5762-0334-4CA9-9018-831B9DFFCB0A}</ProjectGuid> <RootNamespace>$(MSBuildProjectName)</RootNamespace> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{A109C08F-5073-4F9A-9971-1DE62D52E8C7}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> @@ -34,23 +34,23 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> + <UseDebugLibraries>False</UseDebugLibraries> <DriverTargetPlatform>Universal</DriverTargetPlatform> <DriverType>Miniport</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> + <UseDebugLibraries>True</UseDebugLibraries> <DriverTargetPlatform>Universal</DriverTargetPlatform> <DriverType>Miniport</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> <DriverTargetPlatform>Universal</DriverTargetPlatform> @@ -65,26 +65,26 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>lsi_u3</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetName>lsi_u3</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetName>lsi_u3</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>lsi_u3</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -109,7 +109,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ClCompile> <AdditionalOptions>%(AdditionalOptions) /Ob1</AdditionalOptions> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> @@ -131,7 +131,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> <AdditionalOptions>%(AdditionalOptions) /Ob1</AdditionalOptions> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> @@ -153,7 +153,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ClCompile> <AdditionalOptions>%(AdditionalOptions) /Ob1</AdditionalOptions> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> diff --git a/storage/miniports/storahci/src/inbox/storahci.vcxproj b/storage/miniports/storahci/src/inbox/storahci.vcxproj index cd55b82a..746bed56 100644 --- a/storage/miniports/storahci/src/inbox/storahci.vcxproj +++ b/storage/miniports/storahci/src/inbox/storahci.vcxproj @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> + <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> + <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> @@ -23,38 +23,38 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <SupportsPackaging>false</SupportsPackaging> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{4DCDD06A-EB9F-4DF7-B94F-404879FE230C}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>Miniport</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>Miniport</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>Miniport</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType>Miniport</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> @@ -66,13 +66,13 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> <ItemGroup Label="WrappedTaskItems"> @@ -85,13 +85,13 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>storahci</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetName>storahci</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetName>storahci</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>storahci</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -99,7 +99,7 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> </ResourceCompile> <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(KIT_SHARED_INC_PATH_WDK)</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> <ExceptionHandling> @@ -115,12 +115,12 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> </ResourceCompile> <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(KIT_SHARED_INC_PATH_WDK)</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> <ExceptionHandling> @@ -136,12 +136,12 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> </ResourceCompile> <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(KIT_SHARED_INC_PATH_WDK)</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> <ExceptionHandling> @@ -157,12 +157,12 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> </ResourceCompile> <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(KIT_SHARED_INC_PATH_WDK)</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> <ExceptionHandling> diff --git a/storage/miniports/storahci/storahci.sln b/storage/miniports/storahci/storahci.sln index fd7aaea4..ea5d7569 100644 --- a/storage/miniports/storahci/storahci.sln +++ b/storage/miniports/storahci/storahci.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0 @@ -7,16 +7,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "storahci", "src\inbox\stora EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|ARM64 = Debug|ARM64 + Release|ARM64 = Release|ARM64 Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Debug|Win32.ActiveCfg = Debug|Win32 - {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Debug|Win32.Build.0 = Debug|Win32 - {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Release|Win32.ActiveCfg = Release|Win32 - {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Release|Win32.Build.0 = Release|Win32 + {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Debug|ARM64.Build.0 = Debug|ARM64 + {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Release|ARM64.ActiveCfg = Release|ARM64 + {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Release|ARM64.Build.0 = Release|ARM64 {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Debug|x64.ActiveCfg = Debug|x64 {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Debug|x64.Build.0 = Debug|x64 {1452B3C2-50A6-4F07-BF00-413B7A51E3A4}.Release|x64.ActiveCfg = Release|x64 diff --git a/storage/msdsm/msdsm.sln b/storage/msdsm/msdsm.sln index 26e0a90d..ecabf32c 100644 --- a/storage/msdsm/msdsm.sln +++ b/storage/msdsm/msdsm.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0 @@ -7,16 +7,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleDSM", "src\SampleDSM. EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|ARM64 = Debug|ARM64 + Release|ARM64 = Release|ARM64 Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Debug|Win32.ActiveCfg = Debug|Win32 - {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Debug|Win32.Build.0 = Debug|Win32 - {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Release|Win32.ActiveCfg = Release|Win32 - {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Release|Win32.Build.0 = Release|Win32 + {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Release|ARM64.ActiveCfg = Release|ARM64 {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Debug|x64.ActiveCfg = Debug|x64 {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Debug|x64.Build.0 = Debug|x64 {65A3C0DB-248E-4365-83D2-E4DE6E764C6C}.Release|x64.ActiveCfg = Release|x64 diff --git a/storage/msdsm/src/SampleDSM.inf b/storage/msdsm/src/SampleDSM.inf Binary files differindex 5617fa4e..a820c7ec 100644 --- a/storage/msdsm/src/SampleDSM.inf +++ b/storage/msdsm/src/SampleDSM.inf diff --git a/storage/msdsm/src/SampleDSM.vcxproj b/storage/msdsm/src/SampleDSM.vcxproj index 308353ca..c0301e5d 100644 --- a/storage/msdsm/src/SampleDSM.vcxproj +++ b/storage/msdsm/src/SampleDSM.vcxproj @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> + <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> + <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> @@ -23,38 +23,38 @@ <RootNamespace>$(MSBuildProjectName)</RootNamespace> <SupportsPackaging>false</SupportsPackaging> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{C7903CA3-734F-46C5-AECC-1824E8E189EE}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverTargetPlatform>Universal</DriverTargetPlatform> <DriverType>WDM</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> <DriverType>WDM</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> <DriverType>WDM</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverTargetPlatform>Universal</DriverTargetPlatform> <DriverType>WDM</DriverType> <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> @@ -66,13 +66,13 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> <ItemGroup Label="WrappedTaskItems"> @@ -142,19 +142,19 @@ <WarningLevel>Level4</WarningLevel> </ClCompile> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> </ClCompile> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> </ClCompile> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> @@ -163,13 +163,13 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>SampleDSM</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetName>SampleDSM</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetName>SampleDSM</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>SampleDSM</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -177,17 +177,17 @@ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\mpio.lib;$(DDK_LIB_PATH)\Rtlver.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\mpio.lib;$(DDK_LIB_PATH)\Rtlver.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\mpio.lib;$(DDK_LIB_PATH)\Rtlver.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\mpio.lib;$(DDK_LIB_PATH)\Rtlver.lib</AdditionalDependencies> </Link> @@ -211,7 +211,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN2K_COMPAT_SLIST_USAGE</PreprocessorDefinitions> @@ -230,7 +230,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN2K_COMPAT_SLIST_USAGE</PreprocessorDefinitions> @@ -249,7 +249,7 @@ <FileDigestAlgorithm>sha256</FileDigestAlgorithm> </DriverSign> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN2K_COMPAT_SLIST_USAGE</PreprocessorDefinitions> @@ -285,7 +285,7 @@ </ItemGroup> <Exec Command="if not exist "%(CustomBuildTarget0Input.Identity)" copy ".\%(CustomBuildTarget0Input.Filename)%(CustomBuildTarget0Input.Extension)" "%(CustomBuildTarget0Input.Identity)"" WorkingDirectory="$(MSBuildProjectDirectory)" /> <Exec Command="mofcomp -Amendment:ms_409 -MFL:$(IntDir)\MFL.MFL -MOF:$(IntDir)\MOF.MOF "%(CustomBuildTarget0Input.Identity)"" WorkingDirectory="$(MSBuildProjectDirectory)" /> - <Exec Command="wmimofck -y$(IntDir)\MOF.MOF -z$(IntDir)\MFL.MFL $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> + <Exec Command=""$(WmimofckToolPath)\wmimofck.exe" -y$(IntDir)\MOF.MOF -z$(IntDir)\MFL.MFL $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> <Exec Command="mofcomp -B:".\$(IntDir)\msdsm.bmf" $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> </Target> <Target Name="Custom Build Target 2" BeforeTargets="$(BuildGenerateSourcesTargets)"> @@ -294,7 +294,7 @@ </ItemGroup> <Exec Command="if not exist "%(CustomBuildTarget2Input.Identity)" copy ".\%(CustomBuildTarget2Input.Filename)%(CustomBuildTarget2Input.Extension)" "%(CustomBuildTarget2Input.Identity)"" WorkingDirectory="$(MSBuildProjectDirectory)" /> <Exec Command="mofcomp -Amendment:ms_409 -MFL:$(IntDir)\MFL.MFL -MOF:$(IntDir)\MOF.MOF "%(CustomBuildTarget2Input.Identity)"" WorkingDirectory="$(MSBuildProjectDirectory)" /> - <Exec Command="wmimofck -y$(IntDir)\MOF.MOF -z$(IntDir)\MFL.MFL $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> + <Exec Command=""$(WmimofckToolPath)\wmimofck.exe" -y$(IntDir)\MOF.MOF -z$(IntDir)\MFL.MFL $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> <Exec Command="mofcomp -B:".\$(IntDir)\msdsmdsm.bmf" $(IntDir)\MOFMFL.MOF" WorkingDirectory="$(MSBuildProjectDirectory)" /> </Target> <ItemGroup> diff --git a/storage/sfloppy/README.md b/storage/sfloppy/README.md deleted file mode 100644 index d05748df..00000000 --- a/storage/sfloppy/README.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -page_type: sample -description: "A sample class driver for Super Floppy disk drives." -languages: -- cpp -products: -- windows -- windows-wdk ---- - -# Super Floppy (sfloppy) Storage Class Driver - -The sfloppy sample is a super floppy driver. This driver is a class driver for Super Floppy disk drives. - -## Universal Windows Driver Compliant - -This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. - -## Installation and Operation - -This sample sits a level above the port driver (ATAPI, USB, and so on) in the driver stack and controls communication between the application level and the port driver. The floppy driver takes requests from file system drivers and then sends the appropriate [**SCSI\_REQUEST\_BLOCK**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/srb/ns-srb-_scsi_request_block) (SRB) to the port driver. - -For more information, see [Introduction to Storage Class Drivers](https://docs.microsoft.com/windows-hardware/drivers/storage/introduction-to-storage-class-drivers) in the storage technologies design guide. diff --git a/storage/sfloppy/sfloppy.sln b/storage/sfloppy/sfloppy.sln deleted file mode 100644 index ad9d60c3..00000000 --- a/storage/sfloppy/sfloppy.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0 -MinimumVisualStudioVersion = 12.0 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sfloppy", "src\sfloppy.vcxproj", "{97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}.Debug|Win32.ActiveCfg = Debug|Win32 - {97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}.Debug|Win32.Build.0 = Debug|Win32 - {97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}.Release|Win32.ActiveCfg = Release|Win32 - {97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}.Release|Win32.Build.0 = Release|Win32 - {97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}.Debug|x64.ActiveCfg = Debug|x64 - {97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}.Debug|x64.Build.0 = Debug|x64 - {97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}.Release|x64.ActiveCfg = Release|x64 - {97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/storage/sfloppy/src/floppy.c b/storage/sfloppy/src/floppy.c deleted file mode 100644 index 282885a6..00000000 --- a/storage/sfloppy/src/floppy.c +++ /dev/null @@ -1,3428 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, 1991 - 1999 - -Module Name: - - floppy.c - -Abstract: - - SCSI floppy class driver - -Author: - - Jeff Havens (jhavens) - -Environment: - - kernel mode only - -Notes: - -Revision History: -02/28/96 georgioc Merged this code with code developed by compaq in - parallel with microsoft, for 120MB floppy support. - -01/17/96 georgioc Made code PNP aware (uses the new \storage\classpnp/scsiport) - ---*/ - -#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int -#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union - -#include <stddef.h> -#include <ntddk.h> -#include <winerror.h> -#include <scsi.h> -#include <classpnp.h> -#include <initguid.h> -#include <ntddstor.h> - -#include <ntstrsafe.h> -#include <intsafe.h> - -#define MODE_DATA_SIZE 192 -#define SCSI_FLOPPY_TIMEOUT 20 -#define SFLOPPY_SRB_LIST_SIZE 4 -#define SFLOPPY_TAG 'poFS' -// -// Define all possible drive/media combinations, given drives listed above -// and media types in ntdddisk.h. -// -// These values are used to index the DriveMediaConstants table. -// - -#define NUMBER_OF_DRIVE_TYPES 7 -#define DRIVE_TYPE_120M 4 //120MB Floptical -#define DRIVE_TYPE_NONE NUMBER_OF_DRIVE_TYPES - -// -// This array describes all media types we support. -// It should be arranged in the increasing order of density -// -// For a given drive, we list all the mediatypes that will -// work with that drive. For instance, a 120MB drive will -// take 720KB media, 1.44MB media, and 120MB media. -// -// Note that, DriveMediaConstants given below is grouped -// as drive and media combination -// -typedef enum _DRIVE_MEDIA_TYPE { - Drive360Media160, // 5.25" 360k drive; 160k media - Drive360Media180, // 5.25" 360k drive; 180k media - Drive360Media320, // 5.25" 360k drive; 320k media - Drive360Media32X, // 5.25" 360k drive; 320k 1k secs - Drive360Media360, // 5.25" 360k drive; 360k media - Drive720Media720, // 3.5" 720k drive; 720k media - Drive120Media160, // 5.25" 1.2Mb drive; 160k media - Drive120Media180, // 5.25" 1.2Mb drive; 180k media - Drive120Media320, // 5.25" 1.2Mb drive; 320k media - Drive120Media32X, // 5.25" 1.2Mb drive; 320k 1k secs - Drive120Media360, // 5.25" 1.2Mb drive; 360k media - Drive120Media120, // 5.25" 1.2Mb drive; 1.2Mb media - Drive144Media720, // 3.5" 1.44Mb drive; 720k media - Drive144Media144, // 3.5" 1.44Mb drive; 1.44Mb media - Drive288Media720, // 3.5" 2.88Mb drive; 720k media - Drive288Media144, // 3.5" 2.88Mb drive; 1.44Mb media - Drive288Media288, // 3.5" 2.88Mb drive; 2.88Mb media - Drive2080Media720, // 3.5" 20.8Mb drive; 720k media - Drive2080Media144, // 3.5" 20.8Mb drive; 1.44Mb media - Drive2080Media2080, // 3.5" 20.8Mb drive; 20.8Mb media - Drive32MMedia32M, // 3.5" 32Mb drive; 32MB media - Drive120MMedia720, // 3.5" 120Mb drive; 720k media - Drive120MMedia144, // 3.5" 120Mb drive; 1.44Mb media - Drive120MMedia120M, // 3.5" 120Mb drive; 120Mb media - Drive240MMedia144M, // 3.5" 240Mb drive; 1.44Mb media - Drive240MMedia120M, // 3.5" 240Mb drive; 120Mb media - Drive240MMedia240M // 3.5" 240Mb drive; 240Mb media -} DRIVE_MEDIA_TYPE; - -// -// When we want to determine the media type in a drive, we will first -// guess that the media with highest possible density is in the drive, -// and keep trying lower densities until we can successfully read from -// the drive. -// -// These values are used to select a DRIVE_MEDIA_TYPE value. -// -// The following table defines ranges that apply to the DRIVE_MEDIA_TYPE -// enumerated values when trying media types for a particular drive type. -// Note that for this to work, the DRIVE_MEDIA_TYPE values must be sorted -// by ascending densities within drive types. Also, for maximum track -// size to be determined properly, the drive types must be in ascending -// order. -// - -typedef struct _DRIVE_MEDIA_LIMITS { - DRIVE_MEDIA_TYPE HighestDriveMediaType; - DRIVE_MEDIA_TYPE LowestDriveMediaType; -} DRIVE_MEDIA_LIMITS, *PDRIVE_MEDIA_LIMITS; - -#if 0 -DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = { - - { Drive360Media360, Drive360Media160 }, // DRIVE_TYPE_0360 - { Drive120Media120, Drive120Media160 }, // DRIVE_TYPE_1200 - { Drive720Media720, Drive720Media720 }, // DRIVE_TYPE_0720 - { Drive144Media144, Drive144Media720 }, // DRIVE_TYPE_1440 - { Drive288Media288, Drive288Media720 }, // DRIVE_TYPE_2880 - { Drive2080Media2080, Drive2080Media720 } -}; -#else -DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = { - - { Drive720Media720, Drive720Media720 }, // DRIVE_TYPE_0720 - { Drive144Media144, Drive144Media720}, // DRIVE_TYPE_1440 - { Drive288Media288, Drive288Media720}, // DRIVE_TYPE_2880 - { Drive2080Media2080, Drive2080Media720 }, - { Drive32MMedia32M, Drive32MMedia32M }, // DRIVE_TYPE_32M - { Drive120MMedia120M, Drive120MMedia720 }, // DRIVE_TYPE_120M - { Drive240MMedia240M, Drive240MMedia144M } // DRIVE_TYPE_240M -}; - -#endif -// -// For each drive/media combination, define important constants. -// - -typedef struct _DRIVE_MEDIA_CONSTANTS { - MEDIA_TYPE MediaType; - USHORT BytesPerSector; - UCHAR SectorsPerTrack; - USHORT MaximumTrack; - UCHAR NumberOfHeads; -} DRIVE_MEDIA_CONSTANTS, *PDRIVE_MEDIA_CONSTANTS; - -// -// Magic value to add to the SectorLengthCode to use it as a shift value -// to determine the sector size. -// - -#define SECTORLENGTHCODE_TO_BYTESHIFT 7 - -// -// The following values were gleaned from many different sources, which -// often disagreed with each other. Where numbers were in conflict, I -// chose the more conservative or most-often-selected value. -// - -DRIVE_MEDIA_CONSTANTS DriveMediaConstants[] = - { - - { F5_160_512, 0x200, 0x08, 0x27, 0x1 }, - { F5_180_512, 0x200, 0x09, 0x27, 0x1 }, - { F5_320_1024, 0x400, 0x04, 0x27, 0x2 }, - { F5_320_512, 0x200, 0x08, 0x27, 0x2 }, - { F5_360_512, 0x200, 0x09, 0x27, 0x2 }, - - { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, - - { F5_160_512, 0x200, 0x08, 0x27, 0x1 }, - { F5_180_512, 0x200, 0x09, 0x27, 0x1 }, - { F5_320_1024, 0x400, 0x04, 0x27, 0x2 }, - { F5_320_512, 0x200, 0x08, 0x27, 0x2 }, - { F5_360_512, 0x200, 0x09, 0x27, 0x2 }, - { F5_1Pt2_512, 0x200, 0x0f, 0x4f, 0x2 }, - - { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, - { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, - - { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, - { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, - { F3_2Pt88_512, 0x200, 0x24, 0x4f, 0x2 }, - - { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, - { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, - { F3_20Pt8_512, 0x200, 0x1b, 0xfa, 0x6 }, - - { F3_32M_512, 0x200, 0x20, 0x3ff,0x2}, - - { F3_720_512, 0x200, 0x09, 0x4f, 0x2 }, - { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, - { F3_120M_512, 0x200, 0x20, 0x3c2,0x8 }, - - { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 }, - { F3_120M_512, 0x200, 0x20, 0x3c2,0x8 }, - { F3_240M_512, 0x200, 0x38, 0x105,0x20} -}; - - -#define NUMBER_OF_DRIVE_MEDIA_COMBINATIONS sizeof(DriveMediaConstants)/sizeof(DRIVE_MEDIA_CONSTANTS) - -// -// floppy device data -// - -typedef struct _DISK_DATA { - ULONG DriveType; - BOOLEAN IsDMF; - // BOOLEAN EnableDMF; - UNICODE_STRING FloppyInterfaceString; -} DISK_DATA, *PDISK_DATA; - -// -// The FloppyCapacities and FloppyGeometries arrays are used by the -// USBFlopGetMediaTypes() and USBFlopFormatTracks() routines. - -// The FloppyCapacities and FloppyGeometries arrays must be kept in 1:1 sync, -// i.e. each FloppyGeometries[i] must correspond to each FloppyCapacities[i]. - -// Also, the arrays must be kept in sorted ascending order so that they -// are returned in sorted ascending order by IOCTL_DISK_GET_MEDIA_TYPES. -// - -typedef struct _FORMATTED_CAPACITY -{ - ULONG NumberOfBlocks; - - ULONG BlockLength; - - BOOLEAN CanFormat; // return for IOCTL_DISK_GET_MEDIA_TYPES ? - -} FORMATTED_CAPACITY, *PFORMATTED_CAPACITY; - - -FORMATTED_CAPACITY FloppyCapacities[] = -{ - // Blocks BlockLen CanFormat H T B/S S/T - {0x000500, 0x0200, TRUE}, // 2 80 512 8 640 KB F5_640_512 - {0x0005A0, 0x0200, TRUE}, // 2 80 512 9 720 KB F3_720_512 - {0x000960, 0x0200, TRUE}, // 2 80 512 15 1.20 MB F3_1Pt2_512 (Toshiba) - {0x0004D0, 0x0400, TRUE}, // 2 77 1024 8 1.23 MB F3_1Pt23_1024 (NEC) - {0x000B40, 0x0200, TRUE}, // 2 80 512 18 1.44 MB F3_1Pt44_512 - {0x000D20, 0x0200, FALSE}, // 2 80 512 21 1.70 MB DMF - {0x010000, 0x0200, TRUE}, // 2 1024 512 32 32 MB F3_32M_512 - {0x03C300, 0x0200, TRUE}, // 8 963 512 32 120 MB F3_120M_512 - {0x0600A4, 0x0200, TRUE}, // 13 890 512 34 200 MB F3_200Mb_512 (HiFD) - {0x072A00, 0x0200, TRUE} // 32 262 512 56 240 MB F3_240M_512 -}; - -DISK_GEOMETRY FloppyGeometries[] = -{ - // Cyl MediaType Trk/Cyl Sec/Trk Bytes/Sec - {{80,0}, F3_640_512, 2, 8, 512}, - {{80,0}, F3_720_512, 2, 9, 512}, - {{80,0}, F3_1Pt2_512, 2, 15, 512}, - {{77,0}, F3_1Pt23_1024, 2, 8, 1024}, - {{80,0}, F3_1Pt44_512, 2, 18, 512}, - {{80,0}, F3_1Pt44_512, 2, 21, 512}, // DMF -> F3_1Pt44_512 - {{1024,0}, F3_32M_512, 2, 32, 512}, - {{963,0}, F3_120M_512, 8, 32, 512}, - {{890,0}, F3_200Mb_512, 13, 34, 512}, - {{262,0}, F3_240M_512, 32, 56, 512} -}; - -#define FLOPPY_CAPACITIES (sizeof(FloppyCapacities)/sizeof(FloppyCapacities[0])) - -C_ASSERT((sizeof(FloppyGeometries)/sizeof(FloppyGeometries[0])) == FLOPPY_CAPACITIES); - -// -// The following structures are used by USBFlopFormatTracks() -// - -#pragma pack (push, 1) - -typedef struct _CDB12FORMAT -{ - UCHAR OperationCode; - UCHAR DefectListFormat : 3; - UCHAR CmpList : 1; - UCHAR FmtData : 1; - UCHAR LogicalUnitNumber : 3; - UCHAR TrackNumber; - UCHAR InterleaveMsb; - UCHAR InterleaveLsb; - UCHAR Reserved1[2]; - UCHAR ParameterListLengthMsb; - UCHAR ParameterListLengthLsb; - UCHAR Reserved2[3]; -} CDB12FORMAT, *PCDB12FORMAT; - - -typedef struct _DEFECT_LIST_HEADER -{ - UCHAR Reserved1; - UCHAR Side : 1; - UCHAR Immediate : 1; - UCHAR Reserved2 : 2; - UCHAR SingleTrack : 1; - UCHAR DisableCert : 1; - UCHAR Reserved3 : 1; - UCHAR FormatOptionsValid : 1; - UCHAR DefectListLengthMsb; - UCHAR DefectListLengthLsb; -} DEFECT_LIST_HEADER, *PDEFECT_LIST_HEADER; - -typedef struct _FORMAT_UNIT_PARAMETER_LIST -{ - DEFECT_LIST_HEADER DefectListHeader; - FORMATTED_CAPACITY_DESCRIPTOR FormatDescriptor; -} FORMAT_UNIT_PARAMETER_LIST, *PFORMAT_UNIT_PARAMETER_LIST; - -#pragma pack (pop) - -DRIVER_INITIALIZE DriverEntry; - -DRIVER_UNLOAD ScsiFlopUnload; - -DRIVER_ADD_DEVICE ScsiFlopAddDevice; - -NTSTATUS -ScsiFlopInitDevice( - IN PDEVICE_OBJECT Fdo - ); - -NTSTATUS -ScsiFlopStartDevice( - IN PDEVICE_OBJECT Fdo - ); - -NTSTATUS -ScsiFlopRemoveDevice( - IN PDEVICE_OBJECT Fdo, - IN UCHAR Type - ); - -NTSTATUS -ScsiFlopStopDevice( - IN PDEVICE_OBJECT Fdo, - IN UCHAR Type - ); - -BOOLEAN -FindScsiFlops( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath, - IN PCLASS_INIT_DATA InitializationData, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber - ); - -NTSTATUS -ScsiFlopReadWriteVerification( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -ScsiFlopDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -BOOLEAN -IsFloppyDevice( - PDEVICE_OBJECT DeviceObject - ); - -NTSTATUS -CreateFlopDeviceObject( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG DeviceCount - ); - -NTSTATUS -DetermineMediaType( - PDEVICE_OBJECT DeviceObject - ); - -ULONG -DetermineDriveType( - PDEVICE_OBJECT DeviceObject - ); - -BOOLEAN -FlCheckFormatParameters( - IN PDEVICE_OBJECT DeviceObject, - IN PFORMAT_PARAMETERS FormatParameters - ); - -NTSTATUS -FormatMedia( - PDEVICE_OBJECT DeviceObject, - MEDIA_TYPE MediaType - ); - -NTSTATUS -FlopticalFormatMedia( - PDEVICE_OBJECT DeviceObject, - PFORMAT_PARAMETERS Format - ); - -VOID -ScsiFlopProcessError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ); - -NTSTATUS -USBFlopGetMediaTypes( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -USBFlopFormatTracks( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(INIT, DriverEntry) - -#pragma alloc_text(PAGE, ScsiFlopUnload) -#pragma alloc_text(PAGE, ScsiFlopAddDevice) -#pragma alloc_text(PAGE, CreateFlopDeviceObject) -#pragma alloc_text(PAGE, ScsiFlopStartDevice) -#pragma alloc_text(PAGE, ScsiFlopRemoveDevice) -#pragma alloc_text(PAGE, IsFloppyDevice) -#pragma alloc_text(PAGE, DetermineMediaType) -#pragma alloc_text(PAGE, DetermineDriveType) -#pragma alloc_text(PAGE, FlCheckFormatParameters) -#pragma alloc_text(PAGE, FormatMedia) -#pragma alloc_text(PAGE, FlopticalFormatMedia) -#pragma alloc_text(PAGE, USBFlopGetMediaTypes) -#pragma alloc_text(PAGE, USBFlopFormatTracks) - -#endif - - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - - This is the system initialization routine for installable drivers. - It calls the SCSI class driver initialization routine. - -Arguments: - - DriverObject - Pointer to driver object created by system. - -Return Value: - - NTSTATUS - ---*/ - -{ - CLASS_INIT_DATA InitializationData; - - // - // Zero InitData - // - - RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA)); - - // - // Set sizes - // - - InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA); - InitializationData.FdoData.DeviceExtensionSize = - sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA); - - InitializationData.FdoData.DeviceType = FILE_DEVICE_DISK; - InitializationData.FdoData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE; - - // - // Set entry points - // - - InitializationData.FdoData.ClassInitDevice = ScsiFlopInitDevice; - InitializationData.FdoData.ClassStartDevice = ScsiFlopStartDevice; - InitializationData.FdoData.ClassStopDevice = ScsiFlopStopDevice; - InitializationData.FdoData.ClassRemoveDevice = ScsiFlopRemoveDevice; - - InitializationData.FdoData.ClassReadWriteVerification = ScsiFlopReadWriteVerification; - InitializationData.FdoData.ClassDeviceControl = ScsiFlopDeviceControl; - - InitializationData.FdoData.ClassShutdownFlush = NULL; - InitializationData.FdoData.ClassCreateClose = NULL; - InitializationData.FdoData.ClassError = ScsiFlopProcessError; - InitializationData.ClassStartIo = NULL; - - InitializationData.ClassAddDevice = ScsiFlopAddDevice; - InitializationData.ClassUnload = ScsiFlopUnload; - // - // Call the class init routine - // - - return ClassInitialize( DriverObject, RegistryPath, &InitializationData); - - -} // end DriverEntry() - -VOID -ScsiFlopUnload( - IN PDRIVER_OBJECT DriverObject - ) -{ - PAGED_CODE(); - UNREFERENCED_PARAMETER(DriverObject); - return; -} - -// -// AddDevice operation is performed in CreateFlopDeviceObject function which -// is called by ScsiFlopAddDevice (The AddDevice routine for sfloppy.sys). -// DO_DEVICE_INITIALIZING flag is cleard upon successfully processing AddDevice -// operation in CreateFlopDeviceObject. But PREFAST is currently unable to -// detect that DO_DEVICE_INITIALIZING is indeed cleard in CreateFlopDeviceObject -// and it raises Warning 28152 (The return from an AddDevice-like function -// unexpectedly did not clear DO_DEVICE_INITIALIZING). Suppress that warning -// using #pragma. -// -#pragma warning(push) -#pragma warning(disable:28152) - -NTSTATUS -ScsiFlopAddDevice ( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT Pdo - ) -/*++ - -Routine Description: - - This routine creates and initializes a new FDO for the corresponding - PDO. It may perform property queries on the FDO but cannot do any - media access operations. - -Arguments: - - DriverObject - Scsiscan class driver object. - - Pdo - the physical device object we are being added to - -Return Value: - - status - ---*/ -{ - NTSTATUS status; - ULONG floppyCount = IoGetConfigurationInformation()->FloppyCount; - - PAGED_CODE(); - - // - // Get the number of disks already initialized. - // - - status = CreateFlopDeviceObject(DriverObject, Pdo, floppyCount); - - if (NT_SUCCESS(status)) { - - // - // Increment system floppy device count. - // - - IoGetConfigurationInformation()->FloppyCount++; - } - - return status; -} - -NTSTATUS -CreateFlopDeviceObject( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT Pdo, - IN ULONG DeviceCount - ) - -/*++ - -Routine Description: - - This routine creates an object for the device and then calls the - SCSI port driver for media capacity and sector size. - -Arguments: - - DriverObject - Pointer to driver object created by system. - PortDeviceObject - to connect to SCSI port driver. - DeviceCount - Number of previously installed Floppys. - AdapterDescriptor - Pointer to structure returned by SCSI port - driver describing adapter capabilites (and limitations). - DeviceDescriptor - Pointer to configuration information for this device. - -Return Value: - ---*/ -{ - NTSTATUS status; - PDEVICE_OBJECT deviceObject = NULL; - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL; - PDISK_DATA diskData; - - PAGED_CODE(); - - DebugPrint((3,"CreateFlopDeviceObject: Enter routine\n")); - - // - // Try to claim the device. - // - - status = ClassClaimDevice(Pdo,FALSE); - - if (!NT_SUCCESS(status)) { - return(status); - } - - DeviceCount--; - - do { - UCHAR name[256]; - - // - // Create device object for this device. - // - - DeviceCount++; - - status = RtlStringCbPrintfA((PCCHAR) name, - sizeof(name), - "\\Device\\Floppy%u", - DeviceCount); - if (NT_SUCCESS(status)) { - - status = ClassCreateDeviceObject(DriverObject, - (PCCHAR) name, - Pdo, - TRUE, - &deviceObject); - } - } while ((status == STATUS_OBJECT_NAME_COLLISION) || - (status == STATUS_OBJECT_NAME_EXISTS)); - - if (!NT_SUCCESS(status)) { - DebugPrint((1,"CreateFlopDeviceObjects: Can not create device\n")); - goto CreateFlopDeviceObjectExit; - } - - // - // Indicate that IRPs should include MDLs. - // - - deviceObject->Flags |= DO_DIRECT_IO; - - fdoExtension = deviceObject->DeviceExtension; - - // - // Back pointer to device object. - // - - fdoExtension->CommonExtension.DeviceObject = deviceObject; - - // - // This is the physical device. - // - - fdoExtension->CommonExtension.PartitionZeroExtension = fdoExtension; - - // - // Reset the drive type. - // - - diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData; - diskData->DriveType = DRIVE_TYPE_NONE; - diskData->IsDMF = FALSE; - // diskData->EnableDMF = TRUE; - - // - // Initialize lock count to zero. The lock count is used to - // disable the ejection mechanism when media is mounted. - // - - fdoExtension->LockCount = 0; - - // - // Save system floppy number - // - - fdoExtension->DeviceNumber = DeviceCount; - - // - // Set the alignment requirements for the device based on the - // host adapter requirements - // - - if (Pdo->AlignmentRequirement > deviceObject->AlignmentRequirement) { - deviceObject->AlignmentRequirement = Pdo->AlignmentRequirement; - } - - // - // Clear the SrbFlags and disable synchronous transfers - // - - fdoExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // - // Finally, attach to the PDO - // - - fdoExtension->LowerPdo = Pdo; - - fdoExtension->CommonExtension.LowerDeviceObject = - IoAttachDeviceToDeviceStack(deviceObject, Pdo); - - if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) { - - status = STATUS_UNSUCCESSFUL; - goto CreateFlopDeviceObjectExit; - } - - deviceObject->StackSize++; - - // - // The device is initialized properly - mark it as such. - // - - deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - return STATUS_SUCCESS; - -CreateFlopDeviceObjectExit: - - if (deviceObject != NULL) { - IoDeleteDevice(deviceObject); - } - - return status; - -} // end CreateFlopDeviceObject() -#pragma warning(pop) - -NTSTATUS -ScsiFlopInitDevice( - IN PDEVICE_OBJECT Fdo - ) -{ - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; - PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; - PDISK_DATA diskData = commonExtension->DriverData; - - PVOID senseData = NULL; - ULONG timeOut; - - NTSTATUS status = STATUS_SUCCESS; - - // - // Allocate request sense buffer. - // - - senseData = ExAllocatePool2(POOL_FLAG_NON_PAGED | POOL_FLAG_CACHE_ALIGNED, - SENSE_BUFFER_SIZE, - SFLOPPY_TAG); - - if (senseData == NULL) { - - // - // The buffer cannot be allocated. - // - - status = STATUS_INSUFFICIENT_RESOURCES; - return status; - } - - // - // Set the sense data pointer in the device extension. - // - - fdoExtension->SenseData = senseData; - - // - // Build the lookaside list for srb's for this device. - // - - ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION)fdoExtension, - SFLOPPY_SRB_LIST_SIZE); - - // - // Register for media change notification - // - ClassInitializeMediaChangeDetection(fdoExtension, - (PUCHAR) "SFloppy"); - - // - // Set timeout value in seconds. - // - - timeOut = ClassQueryTimeOutRegistryValue(Fdo); - if (timeOut) { - fdoExtension->TimeOutValue = timeOut; - } else { - fdoExtension->TimeOutValue = SCSI_FLOPPY_TIMEOUT; - } - - // - // Floppies are not partitionable so starting offset is 0. - // - - fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)0; - -#if 0 - if (!IsFloppyDevice(Fdo) || - !(Fdo->Characteristics & FILE_REMOVABLE_MEDIA) || - (fdoExtension->DeviceDescriptor->DeviceType != DIRECT_ACCESS_DEVICE)) { - - ExFreePool(senseData); - status = STATUS_NO_SUCH_DEVICE; - return status; - } -#endif - - RtlZeroMemory(&(fdoExtension->DiskGeometry), - sizeof(DISK_GEOMETRY)); - - // - // Determine the media type if possible. Set the current media type to - // Unknown so that determine media type will check the media. - // - - fdoExtension->DiskGeometry.MediaType = Unknown; - - // - // Register interfaces for this device. - // - - { - UNICODE_STRING interfaceName; - - RtlInitUnicodeString(&interfaceName, NULL); - - status = IoRegisterDeviceInterface(fdoExtension->LowerPdo, - (LPGUID) &GUID_DEVINTERFACE_FLOPPY, - NULL, - &interfaceName); - - if(NT_SUCCESS(status)) { - diskData->FloppyInterfaceString = interfaceName; - } else { - RtlInitUnicodeString(&(diskData->FloppyInterfaceString), NULL); - DebugPrint((1, "ScsiFlopStartDevice: Unable to register device " - "interface for fdo %p [%08lx]\n", - Fdo, status)); - } - } - - return (STATUS_SUCCESS); -} - -#pragma warning(suppress:6262) // This function uses 1096 bytes of stack which exceed default value of 1024 bytes used by Code Analysis for flagging as warning -NTSTATUS ScsiFlopStartDevice( - IN PDEVICE_OBJECT Fdo - ) -{ - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; - PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; - - PIRP irp; - IO_STATUS_BLOCK ioStatus; - - SCSI_ADDRESS scsiAddress; - - WCHAR ntNameBuffer[256]; - UNICODE_STRING ntUnicodeString; - - WCHAR arcNameBuffer[256]; - UNICODE_STRING arcUnicodeString; - - KEVENT event; - - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE(); - - KeInitializeEvent(&event,SynchronizationEvent,FALSE); - - DetermineMediaType(Fdo); // ignore unsuccessful here - - // - // Create device object for this device. - // - - RtlStringCbPrintfW(ntNameBuffer, - sizeof(ntNameBuffer), - L"\\Device\\Floppy%u", - fdoExtension->DeviceNumber); - - // - // Create local copy of unicode string - // - RtlInitUnicodeString(&ntUnicodeString,ntNameBuffer); - - // - // Create a symbolic link from the disk name to the corresponding - // ARC name, to be used if we're booting off the disk. This will - // fail if it's not system initialization time; that's fine. The - // ARC name looks something like \ArcName\scsi(0)Flop(0)fdisk(0). - // In order to get the address, we need to send a IOCTL_SCSI_GET_ADDRESS... - // - - irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS, - Fdo, - NULL, - 0, - &scsiAddress, - sizeof(scsiAddress), - FALSE, - &event, - &ioStatus); - - if (irp == NULL) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - status = IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - // - // IOCTL_SCSI_GET_ADDRESS might not be supported by the port driver and - // hence may fail. But it is not a fatal error. Do not fail PnP start - // if this IOCTL fails. - // - if (NT_SUCCESS(status)) { - - RtlStringCbPrintfW(arcNameBuffer, - sizeof(arcNameBuffer), - L"\\ArcName\\scsi(%u)disk(%u)fdisk(%u)", - scsiAddress.PortNumber, - scsiAddress.TargetId, - scsiAddress.Lun); - - RtlInitUnicodeString(&arcUnicodeString, arcNameBuffer); - - IoAssignArcName(&arcUnicodeString, &ntUnicodeString); - } - - status = STATUS_SUCCESS; - - // - // Create the multi() arc name -- Create the "fake" - // name of multi(0)disk(0)fdisk(#) to handle the case where the - // SCSI floppy is the only floppy in the system. If this fails - // it doesn't matter because the previous scsi() based ArcName - // will work. This name is necessary for installation. - // - - RtlStringCbPrintfW(arcNameBuffer, - sizeof(arcNameBuffer), - L"\\ArcName\\multi(%u)disk(%u)fdisk(%u)", - 0, - 0, - fdoExtension->DeviceNumber); - - RtlInitUnicodeString(&arcUnicodeString, arcNameBuffer); - - IoAssignArcName(&arcUnicodeString, &ntUnicodeString); - - // - // Set our interface state. - // - - { - PDISK_DATA diskData = commonExtension->DriverData; - - if(diskData->FloppyInterfaceString.Buffer != NULL) { - - status = IoSetDeviceInterfaceState( - &(diskData->FloppyInterfaceString), - TRUE); - - if(!NT_SUCCESS(status)) { - DebugPrint((1, "ScsiFlopStartDevice: Unable to set device " - "interface state to TRUE for fdo %p " - "[%08lx]\n", - Fdo, status)); - } - } - } - - return STATUS_SUCCESS; -} - - -NTSTATUS -ScsiFlopReadWriteVerification( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - -Arguments: - -Return Value: - - NT Status - ---*/ - -{ - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp); - NTSTATUS status = STATUS_SUCCESS; - - // - // Make sure that the number of bytes to transfer is a multiple of the sector size - // - if ((irpSp->Parameters.Read.Length & (fdoExtension->DiskGeometry.BytesPerSector - 1)) != 0) - { - status = STATUS_INVALID_PARAMETER; - } - - Irp->IoStatus.Status = status; - - return status; -} - - -NTSTATUS -ScsiFlopDeviceControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ) - -/*++ - -Routine Description: - -Arguments: - -Return Value: - - Status is returned. - ---*/ - -{ - KIRQL currentIrql; - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; - PSCSI_REQUEST_BLOCK srb; - PCDB cdb; - NTSTATUS status; - PDISK_GEOMETRY outputBuffer; - ULONG outputBufferLength; - ULONG i; - DRIVE_MEDIA_TYPE lowestDriveMediaType; - DRIVE_MEDIA_TYPE highestDriveMediaType; - PFORMAT_PARAMETERS formatParameters; - PMODE_PARAMETER_HEADER modeData; - ULONG length; - - // - // Initialize the information field - // - Irp->IoStatus.Information = 0; - - srb = ExAllocatePool2(POOL_FLAG_NON_PAGED, - SCSI_REQUEST_BLOCK_SIZE, - SFLOPPY_TAG); - - if (srb == NULL) { - - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - if (IoIsErrorUserInduced(Irp->IoStatus.Status)) { - - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - } - - KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); - ClassReleaseRemoveLock(DeviceObject, Irp); - ClassCompleteRequest(DeviceObject, Irp, 0); - KeLowerIrql(currentIrql); - - return(STATUS_INSUFFICIENT_RESOURCES); - } - - // - // Write zeros to Srb. - // - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - cdb = (PCDB)srb->Cdb; - - switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { - - - case IOCTL_DISK_VERIFY: { - - PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer; - LARGE_INTEGER byteOffset; - ULONG sectorOffset; - USHORT sectorCount; - - // - // Validate buffer length. - // - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(VERIFY_INFORMATION)) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - // - // Perform a bounds check on the sector range - // - if ((verifyInfo->StartingOffset.QuadPart > fdoExtension->CommonExtension.PartitionLength.QuadPart) || - (verifyInfo->StartingOffset.QuadPart < 0)) - { - status = STATUS_NONEXISTENT_SECTOR; - break; - } - else - { - ULONGLONG bytesRemaining = fdoExtension->CommonExtension.PartitionLength.QuadPart - verifyInfo->StartingOffset.QuadPart; - - if ((ULONGLONG)verifyInfo->Length > bytesRemaining) - { - status = STATUS_NONEXISTENT_SECTOR; - break; - } - } - - // - // Verify sectors - // - - srb->CdbLength = 10; - - cdb->CDB10.OperationCode = SCSIOP_VERIFY; - - // - // Add disk offset to starting sector. - // - - byteOffset.QuadPart = fdoExtension->CommonExtension.StartingOffset.QuadPart + - verifyInfo->StartingOffset.QuadPart; - - // - // Convert byte offset to sector offset. - // - - sectorOffset = (ULONG)(byteOffset.QuadPart >> fdoExtension->SectorShift); - - // - // Convert ULONG byte count to USHORT sector count. - // - - sectorCount = (USHORT)(verifyInfo->Length >> fdoExtension->SectorShift); - - // - // Move little endian values into CDB in big endian format. - // - - cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)§orOffset)->Byte3; - cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)§orOffset)->Byte2; - cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)§orOffset)->Byte1; - cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)§orOffset)->Byte0; - - cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)§orCount)->Byte1; - cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)§orCount)->Byte0; - - // - // The verify command is used by the NT FORMAT utility and - // requests are sent down for 5% of the volume size. The - // request timeout value is calculated based on the number of - // sectors verified. - // - - srb->TimeOutValue = ((sectorCount + 0x7F) >> 7) * - fdoExtension->TimeOutValue; - - status = ClassSendSrbAsynchronous(DeviceObject, - srb, - Irp, - NULL, - 0, - FALSE); - return(status); - - } - - case IOCTL_DISK_GET_PARTITION_INFO: { - - if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) { - - USBFlopGetMediaTypes(DeviceObject, NULL); - - // Don't need to propagate any error if one occurs - // - status = STATUS_SUCCESS; - - } else { - - status = DetermineMediaType(DeviceObject); - } - - if (!NT_SUCCESS(status)) { - // so will propogate error - NOTHING; - } else if (fdoExtension->DiskGeometry.MediaType == F3_120M_512) { - //so that the format code will not try to partition it. - status = STATUS_INVALID_DEVICE_REQUEST; - } else { - // - // Free the Srb, since it is not needed. - // - - ExFreePool(srb); - - // - // Pass the request to the common device control routine. - // - - return(ClassDeviceControl(DeviceObject, Irp)); - } - break; - } - - case IOCTL_DISK_GET_DRIVE_GEOMETRY: { - - DebugPrint((3,"ScsiDeviceIoControl: Get drive geometry\n")); - - if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) - { - status = USBFlopGetMediaTypes(DeviceObject, - Irp); - break; - } - - // - // If there's not enough room to write the - // data, then fail the request. - // - - if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof( DISK_GEOMETRY ) ) { - - status = STATUS_INVALID_PARAMETER; - break; - } - - status = DetermineMediaType(DeviceObject); - - if (!NT_SUCCESS(status)) { - - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = status; - - } else { - - // - // Copy drive geometry information from device extension. - // - - RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, - &(fdoExtension->DiskGeometry), - sizeof(DISK_GEOMETRY)); - - Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); - status = STATUS_SUCCESS; - - } - - break; - } - - case IOCTL_DISK_GET_MEDIA_TYPES: { - - if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) - { - status = USBFlopGetMediaTypes(DeviceObject, - Irp); - break; - } - - i = DetermineDriveType(DeviceObject); - - if (i == DRIVE_TYPE_NONE) { - status = STATUS_UNRECOGNIZED_MEDIA; - break; - } - - lowestDriveMediaType = DriveMediaLimits[i].LowestDriveMediaType; - highestDriveMediaType = DriveMediaLimits[i].HighestDriveMediaType; - - outputBufferLength = - irpStack->Parameters.DeviceIoControl.OutputBufferLength; - - // - // Make sure that the input buffer has enough room to return - // at least one descriptions of a supported media type. - // - - if ( outputBufferLength < ( sizeof( DISK_GEOMETRY ) ) ) { - - status = STATUS_BUFFER_TOO_SMALL; - break; - } - - // - // Assume success, although we might modify it to a buffer - // overflow warning below (if the buffer isn't big enough - // to hold ALL of the media descriptions). - // - - status = STATUS_SUCCESS; - - if (outputBufferLength < ( sizeof( DISK_GEOMETRY ) * - ( highestDriveMediaType - lowestDriveMediaType + 1 ) ) ) { - - // - // The buffer is too small for all of the descriptions; - // calculate what CAN fit in the buffer. - // - - status = STATUS_BUFFER_OVERFLOW; - - highestDriveMediaType = (DRIVE_MEDIA_TYPE)( ( lowestDriveMediaType - 1 ) + - ( outputBufferLength / - sizeof( DISK_GEOMETRY ) ) ); - } - - outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer; - - for (i = (UCHAR)lowestDriveMediaType;i <= (UCHAR)highestDriveMediaType;i++ ) { - - outputBuffer->MediaType = DriveMediaConstants[i].MediaType; - outputBuffer->Cylinders.LowPart = - DriveMediaConstants[i].MaximumTrack + 1; - outputBuffer->Cylinders.HighPart = 0; - outputBuffer->TracksPerCylinder = - DriveMediaConstants[i].NumberOfHeads; - outputBuffer->SectorsPerTrack = - DriveMediaConstants[i].SectorsPerTrack; - outputBuffer->BytesPerSector = - DriveMediaConstants[i].BytesPerSector; - outputBuffer++; - - Irp->IoStatus.Information += sizeof( DISK_GEOMETRY ); - } - - break; - } - - case IOCTL_DISK_FORMAT_TRACKS: { - - if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) - { - status = USBFlopFormatTracks(DeviceObject, - Irp); - break; - } - - // - // Make sure that we got all the necessary format parameters. - // - - if ( irpStack->Parameters.DeviceIoControl.InputBufferLength <sizeof( FORMAT_PARAMETERS ) ) { - - status = STATUS_INVALID_PARAMETER; - break; - } - - formatParameters = (PFORMAT_PARAMETERS) Irp->AssociatedIrp.SystemBuffer; - - // - // Make sure the parameters we got are reasonable. - // - - if ( !FlCheckFormatParameters(DeviceObject, formatParameters)) { - - status = STATUS_INVALID_PARAMETER; - break; - } - - // - // If this request is for a 20.8 MB floppy then call a special - // floppy format routine. - // - - if (formatParameters->MediaType == F3_20Pt8_512) { - status = FlopticalFormatMedia(DeviceObject, - formatParameters - ); - - break; - } - - // - // All the work is done in the pass. If this is not the first pass, - // then complete the request and return; - // - - if (formatParameters->StartCylinderNumber != 0 || formatParameters->StartHeadNumber != 0) { - - status = STATUS_SUCCESS; - break; - } - - status = FormatMedia( DeviceObject, formatParameters->MediaType); - break; - } - - case IOCTL_DISK_IS_WRITABLE: { - - if ((fdoExtension->DiskGeometry.MediaType) == F3_32M_512) { - - // - // 32MB media is READ ONLY. Just return - // STATUS_MEDIA_WRITE_PROTECTED - // - - status = STATUS_MEDIA_WRITE_PROTECTED; - - break; - } - - // - // Determine if the device is writable. - // - - modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE); - - if (modeData == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - RtlZeroMemory(modeData, MODE_DATA_SIZE); - - length = ClassModeSense(DeviceObject, - (PCHAR) modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - // - // Retry the request in case of a check condition. - // - - length = ClassModeSense(DeviceObject, - (PCHAR) modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - status = STATUS_IO_DEVICE_ERROR; - ExFreePool(modeData); - break; - } - } - - if (modeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT) { - status = STATUS_MEDIA_WRITE_PROTECTED; - } else { - status = STATUS_SUCCESS; - } - - DebugPrint((2,"IOCTL_DISK_IS_WRITABLE returns %08X\n", status)); - - ExFreePool(modeData); - break; - } - - default: { - - DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n")); - - // - // Free the Srb, since it is not needed. - // - - ExFreePool(srb); - - // - // Pass the request to the common device control routine. - // - - return(ClassDeviceControl(DeviceObject, Irp)); - - break; - } - - } // end switch( ... - - // - // Check if SL_OVERRIDE_VERIFY_VOLUME flag is set in the IRP. - // If so, do not return STATUS_VERIFY_REQUIRED - // - if ((status == STATUS_VERIFY_REQUIRED) && - (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME))) { - - status = STATUS_IO_DEVICE_ERROR; - - } - - Irp->IoStatus.Status = status; - - if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { - - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - } - - KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); - ClassReleaseRemoveLock(DeviceObject, Irp); - ClassCompleteRequest(DeviceObject, Irp, 0); - KeLowerIrql(currentIrql); - - ExFreePool(srb); - - return status; - -} // end ScsiFlopDeviceControl() - -#if 0 - -BOOLEAN -IsFloppyDevice( - PDEVICE_OBJECT DeviceObject - ) -/*++ - -Routine Description: - - The routine performs the necessary funcitons to deterime if the device is - really a floppy rather than a harddisk. This is done by a mode sense - command. First a check is made to see if the medimum type is set. Second - a check is made for the flexible parameters mode page. - -Arguments: - - DeviceObject - Supplies the device object to be tested. - -Return Value: - - Return TRUE if the indicated device is a floppy. - ---*/ -{ - - PVOID modeData; - PUCHAR pageData; - ULONG length; - - modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE); - - if (modeData == NULL) { - return(FALSE); - } - - RtlZeroMemory(modeData, MODE_DATA_SIZE); - - length = ClassModeSense(DeviceObject, modeData, MODE_DATA_SIZE, MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - // - // Retry the request in case of a check condition. - // - - length = ClassModeSense(DeviceObject, - modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - ExFreePool(modeData); - return(FALSE); - - } - } - -#if 0 - // - // Some drives incorrectly report this. In particular the SONY RMO-S350 - // when in disk mode. - // - - if (((PMODE_PARAMETER_HEADER) modeData)->MediumType >= MODE_FD_SINGLE_SIDE - && ((PMODE_PARAMETER_HEADER) modeData)->MediumType <= MODE_FD_MAXIMUM_TYPE) { - - DebugPrint((1, "ScsiFlop: MediumType value %2x, This is a floppy.\n", ((PMODE_PARAMETER_HEADER) modeData)->MediumType)); - ExFreePool(modeData); - return(TRUE); - } - -#endif - - // - // If the length is greater than length indiated by the mode data reset - // the data to the mode data. - // - if (length > (ULONG)((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) { - length = (ULONG)((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1; - - } - - // - // Look for the flexible disk mode page. - // - - pageData = ClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE); - - if (pageData != NULL) { - - DebugPrint((1, "ScsiFlop: Flexible disk page found, This is a floppy.\n")); - - // - // As a special case for the floptical driver do a magic mode sense to - // enable the drive. - // - - ClassModeSense(DeviceObject, modeData, 0x2a, 0x2e); - - ExFreePool(modeData); - return(TRUE); - - } - - ExFreePool(modeData); - return(FALSE); - -} -#endif - - -NTSTATUS -DetermineMediaType( - PDEVICE_OBJECT DeviceObject - ) -/*++ - -Routine Description: - - This routine determines the floppy media type based on the size of the - device. The geometry information is set for the device object. - -Arguments: - - DeviceObject - Supplies the device object to be tested. - -Return Value: - - None - ---*/ -{ - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; - PDISK_GEOMETRY geometry; - LONG index; - NTSTATUS status; - - PAGED_CODE(); - - geometry = &(fdoExtension->DiskGeometry); - - // - // Issue ReadCapacity to update device extension - // with information for current media. - // - - status = ClassReadDriveCapacity(DeviceObject); - - if (!NT_SUCCESS(status)) { - - // - // Set the media type to unknow and zero the geometry information. - // - - geometry->MediaType = Unknown; - - return status; - - } - - // - // Look at the capcity of disk to determine its type. - // - - for (index = NUMBER_OF_DRIVE_MEDIA_COMBINATIONS - 1; index >= 0; index--) { - - // - // Walk the table backward untill the drive capacity holds all of the - // data and the bytes per setor are equal - // - - if ((ULONG) (DriveMediaConstants[index].NumberOfHeads * - (DriveMediaConstants[index].MaximumTrack + 1) * - DriveMediaConstants[index].SectorsPerTrack * - DriveMediaConstants[index].BytesPerSector) <= - fdoExtension->CommonExtension.PartitionLength.LowPart && - DriveMediaConstants[index].BytesPerSector == - geometry->BytesPerSector) { - - geometry->MediaType = DriveMediaConstants[index].MediaType; - geometry->TracksPerCylinder = DriveMediaConstants[index].NumberOfHeads; - geometry->SectorsPerTrack = DriveMediaConstants[index].SectorsPerTrack; - geometry->Cylinders.LowPart = DriveMediaConstants[index].MaximumTrack+1; - break; - } - } - - if (index == -1) { - - // - // Set the media type to unknow and zero the geometry information. - // - - geometry->MediaType = Unknown; - - - } else { - // - // DMF check breaks the insight SCSI floppy, so its disabled for that case - // - PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData; - - // if (diskData->EnableDMF == TRUE) { - - // - //check to see if DMF - // - - PSCSI_REQUEST_BLOCK srb; - PVOID readData; - - // - // Allocate a Srb for the read command. - // - - readData = ExAllocatePool(NonPagedPoolNx, geometry->BytesPerSector); - if (readData == NULL) { - return STATUS_NO_MEMORY; - } - - srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); - - if (srb == NULL) { - - ExFreePool(readData); - return STATUS_NO_MEMORY; - } - - RtlZeroMemory(readData, geometry->BytesPerSector); - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - srb->CdbLength = 10; - srb->Cdb[0] = SCSIOP_READ; - srb->Cdb[5] = 0; - srb->Cdb[8] = (UCHAR) 1; - - // - // Set timeout value. - // - - srb->TimeOutValue = fdoExtension->TimeOutValue; - - // - // Send the mode select data. - // - - status = ClassSendSrbSynchronous(DeviceObject, - srb, - readData, - geometry->BytesPerSector, - FALSE - ); - - if (NT_SUCCESS(status)) { - char *pchar = (char *)readData; - - pchar += 3; //skip 3 bytes jump code - - // If the MSDMF3. signature is there then mark it as DMF diskette - if (RtlCompareMemory(pchar, "MSDMF3.", 7) == 7) { - diskData->IsDMF = TRUE; - } - - } - ExFreePool(readData); - ExFreePool(srb); - // }// else - } - return status; -} - -ULONG -DetermineDriveType( - PDEVICE_OBJECT DeviceObject - ) -/*++ - -Routine Description: - - The routine determines the device type so that the supported medias can be - determined. It does a mode sense for the default parameters. This code - assumes that the returned values are for the maximum device size. - -Arguments: - - DeviceObject - Supplies the device object to be tested. - -Return Value: - - None - ---*/ -{ - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; - PVOID modeData; - PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData; - PMODE_FLEXIBLE_DISK_PAGE pageData; - ULONG length; - LONG index; - UCHAR numberOfHeads; - UCHAR sectorsPerTrack; - USHORT maximumTrack; - BOOLEAN applyFix = FALSE; - - PAGED_CODE(); - - if (diskData->DriveType != DRIVE_TYPE_NONE) { - return(diskData->DriveType); - } - - modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE); - - if (modeData == NULL) { - return(DRIVE_TYPE_NONE); - } - - RtlZeroMemory(modeData, MODE_DATA_SIZE); - - length = ClassModeSense(DeviceObject, - modeData, - MODE_DATA_SIZE, - MODE_PAGE_FLEXIBILE); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - // - // Retry the request one more time - // in case of a check condition. - // - length = ClassModeSense(DeviceObject, - modeData, - MODE_DATA_SIZE, - MODE_PAGE_FLEXIBILE); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - ExFreePool(modeData); - return(DRIVE_TYPE_NONE); - } - } - - // - // Look for the flexible disk mode page. - // - - pageData = ClassFindModePage( modeData, - length, - MODE_PAGE_FLEXIBILE, - TRUE); - - // - // Make sure the page is returned and is large enough. - // - - if ((pageData != NULL) && - (pageData->PageLength + 2 >= - (UCHAR)offsetof(MODE_FLEXIBLE_DISK_PAGE, StartWritePrecom))) { - - // - // Pull out the heads, cylinders, and sectors. - // - - numberOfHeads = pageData->NumberOfHeads; - maximumTrack = pageData->NumberOfCylinders[1]; - maximumTrack |= pageData->NumberOfCylinders[0] << 8; - sectorsPerTrack = pageData->SectorsPerTrack; - - - // - // Convert from number of cylinders to maximum track. - // - - maximumTrack--; - - // - // Search for the maximum supported media. Based on the number of heads, - // sectors per track and number of cylinders - // - for (index = 0; index < NUMBER_OF_DRIVE_MEDIA_COMBINATIONS; index++) { - - // - // Walk the table forward until the drive capacity holds all of the - // data and the bytes per setor are equal - // - - if (DriveMediaConstants[index].NumberOfHeads == numberOfHeads && - DriveMediaConstants[index].MaximumTrack == maximumTrack && - DriveMediaConstants[index].SectorsPerTrack ==sectorsPerTrack) { - - ExFreePool(modeData); - - // - // index is now a drive media combination. Compare this to - // the maximum drive media type in the drive media table. - // - - for (length = 0; length < NUMBER_OF_DRIVE_TYPES; length++) { - - if (DriveMediaLimits[length].HighestDriveMediaType == index) { - return(length); - } - } - return(DRIVE_TYPE_NONE); - } - } - - // If the maximum track is greater than 8 bits then divide the - // number of tracks by 3 and multiply the number of heads by 3. - // This is a special case for the 20.8 MB floppy. - // - - if (!applyFix && maximumTrack >= 0x0100) { - maximumTrack++; - maximumTrack /= 3; - maximumTrack--; - numberOfHeads *= 3; - } else { - ExFreePool(modeData); - return(DRIVE_TYPE_NONE); - } - - } - - ExFreePool(modeData); - return(DRIVE_TYPE_NONE); -} - - -BOOLEAN -FlCheckFormatParameters( - IN PDEVICE_OBJECT DeviceObject, - IN PFORMAT_PARAMETERS FormatParameters - ) - -/*++ - -Routine Description: - - This routine checks the supplied format parameters to make sure that - they'll work on the drive to be formatted. - -Arguments: - - DeviceObject - Pointer to the device object to be formated. - - FormatParameters - a pointer to the caller's parameters for the FORMAT. - -Return Value: - - TRUE if parameters are OK. - FALSE if the parameters are bad. - ---*/ - -{ - PDRIVE_MEDIA_CONSTANTS driveMediaConstants; - DRIVE_MEDIA_TYPE driveMediaType; - ULONG index; - - PAGED_CODE(); - - // - // Get the device type. - // - - index = DetermineDriveType(DeviceObject); - - if (index == DRIVE_TYPE_NONE) { - - // - // If the determine device type failed then just use the media type - // and try the parameters. - // - - driveMediaType = Drive360Media160; - - while (( DriveMediaConstants[driveMediaType].MediaType != - FormatParameters->MediaType ) && - ( driveMediaType < Drive288Media288) ) { - - driveMediaType++; - } - - } else { - - // - // Figure out which entry in the DriveMediaConstants table to use. - // - - driveMediaType = - DriveMediaLimits[index].HighestDriveMediaType; - - while ( ( DriveMediaConstants[driveMediaType].MediaType != - FormatParameters->MediaType ) && - ( driveMediaType > DriveMediaLimits[index]. - LowestDriveMediaType ) ) { - - driveMediaType--; - } - - } - - - // driveMediaType is bounded below by DriveMediaLimits[].LowestDriveMediaType -#pragma warning(push) -#pragma warning(disable:33010) // 33010: Enum used as array index may be negative - if ( DriveMediaConstants[driveMediaType].MediaType != - FormatParameters->MediaType ) { - return FALSE; - - } else { - - driveMediaConstants = &DriveMediaConstants[driveMediaType]; - - if ( ( FormatParameters->StartHeadNumber > - (ULONG)( driveMediaConstants->NumberOfHeads - 1 ) ) || - ( FormatParameters->EndHeadNumber > - (ULONG)( driveMediaConstants->NumberOfHeads - 1 ) ) || - ( FormatParameters->StartCylinderNumber > - driveMediaConstants->MaximumTrack ) || - ( FormatParameters->EndCylinderNumber > - driveMediaConstants->MaximumTrack ) || - ( FormatParameters->EndCylinderNumber < - FormatParameters->StartCylinderNumber ) ) { - - return FALSE; - - } else { - - return TRUE; - } - } -#pragma warning(pop) -} - -NTSTATUS -FormatMedia( - PDEVICE_OBJECT DeviceObject, - MEDIA_TYPE MediaType - ) -/*++ - -Routine Description: - - This routine formats the floppy disk. The entire floppy is formated in - one shot. - -Arguments: - - DeviceObject - Supplies the device object to be tested. - - Irp - Supplies a pointer to the requesting Irp. - - MediaType - Supplies the media type format the device for. - -Return Value: - - Returns a status for the operation. - ---*/ -{ - PVOID modeData; - PSCSI_REQUEST_BLOCK srb; - PMODE_FLEXIBLE_DISK_PAGE pageData; - DRIVE_MEDIA_TYPE driveMediaType; - PDRIVE_MEDIA_CONSTANTS driveMediaConstants; - ULONG length; - NTSTATUS status; - - PAGED_CODE(); - - modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE); - - if (modeData == NULL) { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - RtlZeroMemory(modeData, MODE_DATA_SIZE); - - length = ClassModeSense(DeviceObject, - modeData, - MODE_DATA_SIZE, - MODE_PAGE_FLEXIBILE); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - ExFreePool(modeData); - return(STATUS_INVALID_DEVICE_REQUEST); - } - - // - // Look for the flexible disk mode page. - // - - pageData = ClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE); - - // - // Make sure the page is returned and is large enough. - // - - if ((pageData == NULL) || - (pageData->PageLength + 2 < - (UCHAR)offsetof(MODE_FLEXIBLE_DISK_PAGE, StartWritePrecom))) { - - ExFreePool(modeData); - return(STATUS_INVALID_DEVICE_REQUEST); - - } - - // - // Look for a drive media type which matches the requested media type. - // - // - //start from Drive120MMedia120M instead of Drive2080Media2080 - // - for (driveMediaType = Drive120MMedia120M; - DriveMediaConstants[driveMediaType].MediaType != MediaType; - driveMediaType--) { - if (driveMediaType == Drive360Media160) { - - ExFreePool(modeData); - return(STATUS_INVALID_PARAMETER); - - } - } - - driveMediaConstants = &DriveMediaConstants[driveMediaType]; - - if ((pageData->NumberOfHeads != driveMediaConstants->NumberOfHeads) || - (pageData->SectorsPerTrack != driveMediaConstants->SectorsPerTrack) || - ((pageData->NumberOfCylinders[0] != (UCHAR)((driveMediaConstants->MaximumTrack+1) >> 8)) && - (pageData->NumberOfCylinders[1] != (UCHAR)driveMediaConstants->MaximumTrack+1)) || - (pageData->BytesPerSector[0] != driveMediaConstants->BytesPerSector >> 8 )) { - - // - // Update the flexible parameters page with the new parameters. - // - - pageData->NumberOfHeads = driveMediaConstants->NumberOfHeads; - pageData->SectorsPerTrack = driveMediaConstants->SectorsPerTrack; - pageData->NumberOfCylinders[0] = (UCHAR)((driveMediaConstants->MaximumTrack+1) >> 8); - pageData->NumberOfCylinders[1] = (UCHAR)driveMediaConstants->MaximumTrack+1; - pageData->BytesPerSector[0] = driveMediaConstants->BytesPerSector >> 8; - - // - // Clear the mode parameter header. - // - - RtlZeroMemory(modeData, sizeof(MODE_PARAMETER_HEADER)); - - // - // Set the length equal to the length returned for the flexible page. - // - - length = pageData->PageLength + 2; - - // - // Copy the page after the mode parameter header. - // - - RtlMoveMemory((PCHAR) modeData + sizeof(MODE_PARAMETER_HEADER), - pageData, - length - ); - length += sizeof(MODE_PARAMETER_HEADER); - - - // - // Allocate a Srb for the format command. - // - - srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); - - if (srb == NULL) { - - ExFreePool(modeData); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - srb->CdbLength = 6; - srb->Cdb[0] = SCSIOP_MODE_SELECT; - srb->Cdb[4] = (UCHAR) length; - - // - // Set the PF bit. - // - - srb->Cdb[1] |= 0x10; - - // - // Set timeout value. - // - - srb->TimeOutValue = 2; - - // - // Send the mode select data. - // - - status = ClassSendSrbSynchronous(DeviceObject, - srb, - modeData, - length, - TRUE - ); - - // - // The mode data not needed any more so free it. - // - - ExFreePool(modeData); - - if (!NT_SUCCESS(status)) { - ExFreePool(srb); - return(status); - } - - } else { - - // - // The mode data not needed any more so free it. - // - - ExFreePool(modeData); - - // - // Allocate a Srb for the format command. - // - - srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); - - if (srb == NULL) { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - } - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - srb->CdbLength = 6; - - srb->Cdb[0] = SCSIOP_FORMAT_UNIT; - - // - // Set timeout value. - // - - srb->TimeOutValue = 10 * 60; - - status = ClassSendSrbSynchronous(DeviceObject, - srb, - NULL, - 0, - FALSE - ); - ExFreePool(srb); - - return(status); - -} - -VOID -ScsiFlopProcessError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ) -/*++ - -Routine Description: - - This routine checks the type of error. If the error indicate the floppy - controller needs to be reinitialize a command is made to do it. - -Arguments: - - DeviceObject - Supplies a pointer to the device object. - - Srb - Supplies a pointer to the failing Srb. - - Status - Status with which the IRP will be completed. - - Retry - Indication of whether the request will be retried. - -Return Value: - - None. - ---*/ - -{ - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; - PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData; - PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; - PIO_STACK_LOCATION irpStack; - PIRP irp; - PSCSI_REQUEST_BLOCK srb; - LARGE_INTEGER largeInt; - PCOMPLETION_CONTEXT context; - PCDB cdb; - ULONG_PTR alignment; - ULONG majorFunction; - - UNREFERENCED_PARAMETER(Status); - UNREFERENCED_PARAMETER(Retry); - - largeInt.QuadPart = 1; - - // - // Check the status. The initialization command only needs to be sent - // if UNIT ATTENTION or LUN NOT READY is returned. - // - - if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) { - - // - // The drive does not require reinitialization. - // - - return; - } - - // - // Reset the drive type. - // - - diskData->DriveType = DRIVE_TYPE_NONE; - diskData->IsDMF = FALSE; - - fdoExtension->DiskGeometry.MediaType = Unknown; - - if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) { - - // FLPYDISK.SYS never returns a non-zero value for the ChangeCount - // on an IOCTL_DISK_CHECK_VERIFY. Some things seem to work better - // if we do the same. In particular, FatVerifyVolume() can exit between - // the IOCTL_DISK_CHECK_VERIFY and the IOCTL_DISK_GET_DRIVE_GEOMETRY - // if a non-zero ChangeCount is returned, and this appears to cause - // issues formatting unformatted media in some situations. - // - // This is something that should probably be revisited at some point. - // - fdoExtension->MediaChangeCount = 0; - - if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) && - (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_MEDIUM_CHANGED)) { - - struct _START_STOP *startStopCdb; - - DebugPrint((2,"Sending SCSIOP_START_STOP_UNIT\n")); - - context = ExAllocatePool(NonPagedPoolNx, - sizeof(COMPLETION_CONTEXT)); - - if (context == NULL) { - - return; - } -#if (NTDDI_VERSION >= NTDDI_WIN8) - srb = &context->Srb.Srb; -#else - srb = &context->Srb; -#endif - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - srb->SrbFlags = SRB_FLAGS_DISABLE_AUTOSENSE; - - srb->CdbLength = 6; - - startStopCdb = (struct _START_STOP *)srb->Cdb; - - startStopCdb->OperationCode = SCSIOP_START_STOP_UNIT; - startStopCdb->Start = 1; - - // A Start Stop Unit request has no transfer buffer. - // Set the request to IRP_MJ_FLUSH_BUFFERS when calling - // IoBuildAsynchronousFsdRequest() so that it ignores - // the buffer pointer and buffer length parameters. - // - majorFunction = IRP_MJ_FLUSH_BUFFERS; - - } else if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_MEDIUM_ERROR) { - - // Return ERROR_UNRECOGNIZED_MEDIA instead of - // STATUS_DEVICE_DATA_ERROR to make shell happy. - // - *Status = STATUS_UNRECOGNIZED_MEDIA; - return; - - } else { - - return; - } - - } else if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_NOT_READY) && - senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_INIT_COMMAND_REQUIRED || - (senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) { - - ULONG sizeNeeded; - ULONG tmpSize; - BOOLEAN overFlow; - - DebugPrint((1, "ScsiFlopProcessError: Reinitializing the floppy.\n")); - - // - // Send the special mode sense command to enable writes on the - // floptical drive. - // - - alignment = DeviceObject->AlignmentRequirement ? - DeviceObject->AlignmentRequirement : 1; - - sizeNeeded = 0; - overFlow = TRUE; - if (SUCCEEDED(ULongAdd(sizeof(COMPLETION_CONTEXT), 0x2a, &tmpSize))) { - - if (SUCCEEDED(ULongAdd(tmpSize, (ULONG) alignment, &sizeNeeded))) { - overFlow = FALSE; - } - } - - context = NULL; - - if (!overFlow) { - context = ExAllocatePool(NonPagedPoolNx, sizeNeeded); - } - - if (context == NULL) { - - // - // If there is not enough memory to fulfill this request, - // simply return. A subsequent retry will fail and another - // chance to start the unit. - // - - return; - } - -#if (NTDDI_VERSION >= NTDDI_WIN8) - srb = &context->Srb.Srb; -#else - srb = &context->Srb; -#endif - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - // - // Set the transfer length. - // - - srb->DataTransferLength = 0x2a; - srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // - // The data buffer must be aligned. - // - - srb->DataBuffer = (PVOID) (((ULONG_PTR) (context + 1) + (alignment - 1)) & - ~(alignment - 1)); - - - // - // Build the start unit CDB. - // - - srb->CdbLength = 6; - cdb = (PCDB)srb->Cdb; - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb->MODE_SENSE.PageCode = 0x2e; - cdb->MODE_SENSE.AllocationLength = 0x2a; - - majorFunction = IRP_MJ_READ; - - } else { - - return; - } - - context->DeviceObject = DeviceObject; - - // - // Write length to SRB. - // - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->TimeOutValue = fdoExtension->TimeOutValue; - - // - // Build the asynchronous request - // to be sent to the port driver. - // - - irp = IoBuildAsynchronousFsdRequest(majorFunction, - DeviceObject, - srb->DataBuffer, - srb->DataTransferLength, - &largeInt, - NULL); - - if(irp == NULL) { - ExFreePool(context); - return; - } - - - IoSetCompletionRoutine(irp, - (PIO_COMPLETION_ROUTINE)ClassAsynchronousCompletion, - context, - TRUE, - TRUE, - TRUE); - - ClassAcquireRemoveLock(DeviceObject, irp); - - irpStack = IoGetNextIrpStackLocation(irp); - - irpStack->MajorFunction = IRP_MJ_SCSI; - - srb->OriginalRequest = irp; - - // - // Save SRB address in next stack for port driver. - // - - irpStack->Parameters.Others.Argument1 = (PVOID)srb; - - // - // Can't release the remove lock yet - let ClassAsynchronousCompletion - // take care of that for us. - // - - (VOID)IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp); - - return; -} - -NTSTATUS -FlopticalFormatMedia( - PDEVICE_OBJECT DeviceObject, - PFORMAT_PARAMETERS Format - ) -/*++ - -Routine Description: - - This routine is used to do perform a format tracks for the 20.8 MB - floppy. Because the device does not support format tracks and the full - format takes a long time a write of zeros is done instead. - -Arguments: - - DeviceObject - Supplies the device object to be tested. - - Format - Supplies the format parameters. - -Return Value: - - Returns a status for the operation. - ---*/ -{ - IO_STATUS_BLOCK ioStatus; - PIRP irp; - KEVENT event; - LARGE_INTEGER offset; - ULONG length; - PVOID buffer; - PDRIVE_MEDIA_CONSTANTS driveMediaConstants; - NTSTATUS status; - - PAGED_CODE(); - - driveMediaConstants = &DriveMediaConstants[Drive2080Media2080]; - - // - // Calculate the length of the buffer. - // - - length = ((Format->EndCylinderNumber - Format->StartCylinderNumber) * - driveMediaConstants->NumberOfHeads + - Format->EndHeadNumber - Format->StartHeadNumber + 1) * - driveMediaConstants->SectorsPerTrack * - driveMediaConstants->BytesPerSector; - - buffer = ExAllocatePool(NonPagedPoolNxCacheAligned, length); - - if (buffer == NULL) { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - RtlZeroMemory(buffer, length); - - offset.QuadPart = - (Format->StartCylinderNumber * driveMediaConstants->NumberOfHeads + - Format->StartHeadNumber) * driveMediaConstants->SectorsPerTrack * - driveMediaConstants->BytesPerSector; - - // - // Set the event object to the unsignaled state. - // It will be used to signal request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Build the synchronous request with data transfer. - // - - irp = IoBuildSynchronousFsdRequest( - IRP_MJ_WRITE, - DeviceObject, - buffer, - length, - &offset, - &event, - &ioStatus); - - if (irp != NULL) { - status = IoCallDriver(DeviceObject, irp); - - if (status == STATUS_PENDING) { - - // - // Wait for the request to complete if necessary. - // - - KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); - } - - // - // If the call driver suceeded then set the status to the status block. - // - - if (NT_SUCCESS(status)) { - status = ioStatus.Status; - } - } else { - status = STATUS_INSUFFICIENT_RESOURCES; - } - - ExFreePool(buffer); - - return(status); - -} - - -NTSTATUS -ScsiFlopRemoveDevice( - IN PDEVICE_OBJECT DeviceObject, - IN UCHAR Type - ) -/*++ - -Routine Description: - - This routine is responsible for releasing any resources in use by the - sfloppy driver. This routine is called - when all outstanding requests have been completed and the driver has - disappeared - no requests may be issued to the lower drivers. - -Arguments: - - DeviceObject - the device object being removed - - Type - the type of remove operation (QUERY, REMOVE or CANCEL) - -Return Value: - - for a query - success if the device can be removed or a failure code - indiciating why not. - - for a remove or cancel - STATUS_SUCCESS - ---*/ - -{ - PFUNCTIONAL_DEVICE_EXTENSION deviceExtension = - DeviceObject->DeviceExtension; - PDISK_DATA diskData = deviceExtension->CommonExtension.DriverData; - NTSTATUS status; - - PAGED_CODE(); - - if((Type == IRP_MN_QUERY_REMOVE_DEVICE) || - (Type == IRP_MN_CANCEL_REMOVE_DEVICE)) { - return STATUS_SUCCESS; - } - - if (Type == IRP_MN_REMOVE_DEVICE){ - if(deviceExtension->DeviceDescriptor) { - ExFreePool(deviceExtension->DeviceDescriptor); - deviceExtension->DeviceDescriptor = NULL; - } - - if(deviceExtension->AdapterDescriptor) { - ExFreePool(deviceExtension->AdapterDescriptor); - deviceExtension->AdapterDescriptor = NULL; - } - - if(deviceExtension->SenseData) { - ExFreePool(deviceExtension->SenseData); - deviceExtension->SenseData = NULL; - } - - ClassDeleteSrbLookasideList(&deviceExtension->CommonExtension); - } - - if(diskData->FloppyInterfaceString.Buffer != NULL) { - - status = IoSetDeviceInterfaceState( - &(diskData->FloppyInterfaceString), - FALSE); - - if (!NT_SUCCESS(status)) { - // Failed to disable device interface during removal. Not a fatal error. - DebugPrint((1, "ScsiFlopRemoveDevice: Unable to set device " - "interface state to FALSE for fdo %p " - "[%08lx]\n", - DeviceObject, status)); - } - - RtlFreeUnicodeString(&(diskData->FloppyInterfaceString)); - RtlInitUnicodeString(&(diskData->FloppyInterfaceString), NULL); - } - - if(Type == IRP_MN_REMOVE_DEVICE) { - IoGetConfigurationInformation()->FloppyCount--; - } - - return STATUS_SUCCESS; -} - - -NTSTATUS -ScsiFlopStopDevice( - IN PDEVICE_OBJECT DeviceObject, - IN UCHAR Type - ) -{ - UNREFERENCED_PARAMETER(DeviceObject); - UNREFERENCED_PARAMETER(Type); - - return STATUS_SUCCESS; -} - - -NTSTATUS -USBFlopGetMediaTypes( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) -{ -/*++ - -Routine Description: - - This routines determines the current or default geometry of the drive - for IOCTL_DISK_GET_DRIVE_GEOMETRY, or all currently supported geometries - of the drive (which is determined by its currently inserted media) for - IOCTL_DISK_GET_MEDIA_TYPES. - - The returned geometries are determined by issuing a Read Format Capacities - request and then matching the returned {Number of Blocks, Block Length} - pairs in a table of known floppy geometries. - -Arguments: - - DeviceObject - Supplies the device object. - - Irp - A IOCTL_DISK_GET_DRIVE_GEOMETRY or a IOCTL_DISK_GET_MEDIA_TYPES Irp. - If NULL, the device geometry is updated with the current device - geometry. - -Return Value: - - Status is returned. - ---*/ - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension; - PIO_STACK_LOCATION irpStack; - ULONG ioControlCode; - PDISK_GEOMETRY outputBuffer; - PDISK_GEOMETRY outputBufferEnd; - ULONG outputBufferLength; - PSCSI_REQUEST_BLOCK srb; - PVOID dataBuffer; - ULONG dataTransferLength; - struct _READ_FORMATTED_CAPACITIES *cdb; - PFORMATTED_CAPACITY_LIST capList; - NTSTATUS status; - - PAGED_CODE(); - - fdoExtension = DeviceObject->DeviceExtension; - - if (Irp != NULL) { - - // Get the Irp parameters - // - irpStack = IoGetCurrentIrpStackLocation(Irp); - - ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; - - Irp->IoStatus.Information = 0; - - outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer; - - outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; - - if (outputBufferLength < sizeof(DISK_GEOMETRY)) - { - return STATUS_BUFFER_TOO_SMALL; - } - - // Pointer arithmetic to allow multiple DISK_GEOMETRY's to be returned. - // Rounds BufferEnd down to integral multiple of DISK_GEOMETRY structs. - // - outputBufferEnd = outputBuffer + - outputBufferLength / sizeof(DISK_GEOMETRY); - - } else { - - // No Irp to return the result in, just update the current geometry - // in the device extension. - // - ioControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY; - - outputBuffer = NULL; - - outputBufferEnd = NULL; - - outputBufferLength = 0; - } - - if (ioControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) { - - fdoExtension->DiskGeometry.MediaType = Unknown; - - status = ClassReadDriveCapacity(DeviceObject); - - if (!NT_SUCCESS(status)) - { - // If the media is not recongized, we want to return the default - // geometry so that the media can be formatted. Unrecognized media - // causes SCSI_SENSE_MEDIUM_ERROR, which gets reported as - // STATUS_DEVICE_DATA_ERROR. Ignore these errors, but return other - // errors, such as STATUS_NO_MEDIA_IN_DEVICE. - // - if (status != STATUS_UNRECOGNIZED_MEDIA) - { - DebugPrint((2,"IOCTL_DISK_GET_DRIVE_GEOMETRY returns %08X\n", status)); - - return status; - } - } - } - - // Allocate an SRB for the SCSIOP_READ_FORMATTED_CAPACITY request - // - srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); - - if (srb == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // Allocate a transfer buffer for the SCSIOP_READ_FORMATTED_CAPACITY request - // The length of the returned descriptor array is limited to a byte field - // in the capacity list header. - // - dataTransferLength = sizeof(FORMATTED_CAPACITY_LIST) + - 31 * sizeof(FORMATTED_CAPACITY_DESCRIPTOR); - - ASSERT(dataTransferLength < 0x100); - - dataBuffer = ExAllocatePool(NonPagedPoolNx, dataTransferLength); - - if (dataBuffer == NULL) - { - ExFreePool(srb); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // Initialize the SRB and CDB - // - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - RtlZeroMemory(dataBuffer, dataTransferLength); - - srb->CdbLength = sizeof(struct _READ_FORMATTED_CAPACITIES); - - srb->TimeOutValue = fdoExtension->TimeOutValue; - - cdb = (struct _READ_FORMATTED_CAPACITIES *)srb->Cdb; - - cdb->OperationCode = SCSIOP_READ_FORMATTED_CAPACITY; - cdb->AllocationLength[1] = (UCHAR)dataTransferLength; - - // - // Send down the SCSIOP_READ_FORMATTED_CAPACITY request - // - status = ClassSendSrbSynchronous(DeviceObject, - srb, - dataBuffer, - dataTransferLength, - FALSE); - - capList = (PFORMATTED_CAPACITY_LIST)dataBuffer; - - // If we don't get as much data as requested, it is not an error. - // - if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) - { - status = STATUS_SUCCESS; - } - - if (NT_SUCCESS(status) && - srb->DataTransferLength >= sizeof(FORMATTED_CAPACITY_LIST) && - capList->CapacityListLength && - capList->CapacityListLength % sizeof(FORMATTED_CAPACITY_DESCRIPTOR) == 0) - { - ULONG NumberOfBlocks; - ULONG BlockLength; - ULONG count; - ULONG i, j; - LONG currentGeometry; - BOOLEAN capacityMatches[FLOPPY_CAPACITIES]; - - // Subtract the size of the Capacity List Header to get - // just the size of the Capacity List Descriptor array. - // - srb->DataTransferLength -= sizeof(FORMATTED_CAPACITY_LIST); - - // Only look at the Capacity List Descriptors that were actually - // returned. - // - if (srb->DataTransferLength < capList->CapacityListLength) - { - count = srb->DataTransferLength / - sizeof(FORMATTED_CAPACITY_DESCRIPTOR); - } - else - { - count = capList->CapacityListLength / - sizeof(FORMATTED_CAPACITY_DESCRIPTOR); - } - - // Updated only if a match is found for the first Capacity List - // Descriptor returned by the device. - // - currentGeometry = -1; - - // Initialize the array of capacities that hit a match. - // - RtlZeroMemory(capacityMatches, sizeof(capacityMatches)); - - // Iterate over each Capacity List Descriptor returned from the device - // and record matching capacities in the capacity match array. - // - for (i = 0; i < count; i++) - { - NumberOfBlocks = (capList->Descriptors[i].NumberOfBlocks[0] << 24) + - (capList->Descriptors[i].NumberOfBlocks[1] << 16) + - (capList->Descriptors[i].NumberOfBlocks[2] << 8) + - (capList->Descriptors[i].NumberOfBlocks[3]); - - BlockLength = (capList->Descriptors[i].BlockLength[0] << 16) + - (capList->Descriptors[i].BlockLength[1] << 8) + - (capList->Descriptors[i].BlockLength[2]); - - // Given the {NumberOfBlocks, BlockLength} from this Capacity List - // Descriptor, find a matching entry in FloppyCapacities[]. - // - for (j = 0; j < FLOPPY_CAPACITIES; j++) - { - if (NumberOfBlocks == FloppyCapacities[j].NumberOfBlocks && - BlockLength == FloppyCapacities[j].BlockLength) - { - // A matching capacity was found, record it. - // - capacityMatches[j] = TRUE; - - // A match was found for the first Capacity List - // Descriptor returned by the device. - // - if (i == 0) - { - currentGeometry = j; - } - } else if ((capList->Descriptors[i].Valid) && - (BlockLength == FloppyCapacities[j].BlockLength)) { - - ULONG inx; - ULONG mediaInx; - - // - // Check if this is 32MB media type. 32MB media - // reports variable NumberOfBlocks. So we cannot - // use that to determine the drive type - // - inx = DetermineDriveType(DeviceObject); - if (inx != DRIVE_TYPE_NONE) { - mediaInx = DriveMediaLimits[inx].HighestDriveMediaType; - if ((DriveMediaConstants[mediaInx].MediaType) - == F3_32M_512) { - capacityMatches[j] = TRUE; - - if (i == 0) { - currentGeometry = j; - } - } - } - } - } - } - - // Default status is STATUS_UNRECOGNIZED_MEDIA, unless we return - // either STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW. - // - status = STATUS_UNRECOGNIZED_MEDIA; - - if (ioControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) { - - if (currentGeometry != -1) - { - // Update the current device geometry - // - fdoExtension->DiskGeometry = FloppyGeometries[currentGeometry]; - - // - // Calculate sector to byte shift. - // - - WHICH_BIT(fdoExtension->DiskGeometry.BytesPerSector, - fdoExtension->SectorShift); - - fdoExtension->CommonExtension.PartitionLength.QuadPart = - (LONGLONG)FloppyCapacities[currentGeometry].NumberOfBlocks * - FloppyCapacities[currentGeometry].BlockLength; - - DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n", - fdoExtension->DiskGeometry.Cylinders.LowPart, - fdoExtension->DiskGeometry.MediaType, - fdoExtension->DiskGeometry.TracksPerCylinder, - fdoExtension->DiskGeometry.SectorsPerTrack, - fdoExtension->DiskGeometry.BytesPerSector, - fdoExtension->SectorShift, - fdoExtension->CommonExtension.PartitionLength.LowPart)); - - // Return the current device geometry - // - if (Irp != NULL) - { - *outputBuffer = FloppyGeometries[currentGeometry]; - - Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); - } - - status = STATUS_SUCCESS; - } - - } else { - - // Iterate over the capacities and return the geometry - // corresponding to each matching Capacity List Descriptor - // returned from the device. - // - // The resulting list should be in sorted ascending order, - // assuming that the FloppyGeometries[] array is in sorted - // ascending order. - // - for (i = 0; i < FLOPPY_CAPACITIES; i++) - { - if (capacityMatches[i] && FloppyCapacities[i].CanFormat) - { - if (outputBuffer < outputBufferEnd) - { - *outputBuffer++ = FloppyGeometries[i]; - - Irp->IoStatus.Information += sizeof(DISK_GEOMETRY); - - DebugPrint((2,"geometry : %3d %2d %d %2d %4d\n", - FloppyGeometries[i].Cylinders.LowPart, - FloppyGeometries[i].MediaType, - FloppyGeometries[i].TracksPerCylinder, - FloppyGeometries[i].SectorsPerTrack, - FloppyGeometries[i].BytesPerSector)); - - status = STATUS_SUCCESS; - } - else - { - // We ran out of output buffer room before we ran out - // geometries to return. - // - status = STATUS_BUFFER_OVERFLOW; - } - } - } - } - } - else if (NT_SUCCESS(status)) - { - // The SCSIOP_READ_FORMATTED_CAPACITY request was successful, but - // returned data does not appear valid. - // - status = STATUS_UNSUCCESSFUL; - } - - ExFreePool(dataBuffer); - ExFreePool(srb); - - return status; -} - - -NTSTATUS -USBFlopFormatTracks( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) -{ -/*++ - -Routine Description: - - This routines formats the specified tracks. If multiple tracks are - specified, each is formatted with a separate Format Unit request. - -Arguments: - - DeviceObject - Supplies the device object. - - Irp - A IOCTL_DISK_FORMAT_TRACKS Irp. - -Return Value: - - Status is returned. - ---*/ - PFUNCTIONAL_DEVICE_EXTENSION fdoExtension; - PIO_STACK_LOCATION irpStack; - PFORMAT_PARAMETERS formatParameters; - PDISK_GEOMETRY geometry; - PFORMATTED_CAPACITY capacity; - PSCSI_REQUEST_BLOCK srb; - PFORMAT_UNIT_PARAMETER_LIST parameterList; - PCDB12FORMAT cdb; - ULONG i; - ULONG cylinder, head; - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE(); - - fdoExtension = DeviceObject->DeviceExtension; - - // Get the Irp parameters - // - irpStack = IoGetCurrentIrpStackLocation(Irp); - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(FORMAT_PARAMETERS)) - { - return STATUS_INVALID_PARAMETER; - } - - formatParameters = (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer; - - // Find the geometry / capacity entries corresponding to the format - // parameters MediaType - // - geometry = NULL; - capacity = NULL; - - for (i=0; i<FLOPPY_CAPACITIES; i++) - { - if (FloppyGeometries[i].MediaType == formatParameters->MediaType) - { - geometry = &FloppyGeometries[i]; - capacity = &FloppyCapacities[i]; - - break; - } - } - - if (geometry == NULL) - { - return STATUS_INVALID_PARAMETER; - } - - // Check if the format parameters are valid - // - if ((formatParameters->StartCylinderNumber > - geometry->Cylinders.LowPart - 1) || - - (formatParameters->EndCylinderNumber > - geometry->Cylinders.LowPart - 1) || - - (formatParameters->StartHeadNumber > - geometry->TracksPerCylinder - 1) || - - (formatParameters->EndHeadNumber > - geometry->TracksPerCylinder - 1) || - - (formatParameters->StartCylinderNumber > - formatParameters->EndCylinderNumber) || - - (formatParameters->StartHeadNumber > - formatParameters->EndHeadNumber)) - { - return STATUS_INVALID_PARAMETER; - } - - // Don't low level format LS-120 media, Imation says it's best to not - // do this. - // - if ((formatParameters->MediaType == F3_120M_512) || - (formatParameters->MediaType == F3_240M_512) || - (formatParameters->MediaType == F3_32M_512)) - { - return STATUS_SUCCESS; - } - - // Allocate an SRB for the SCSIOP_FORMAT_UNIT request - // - srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE); - - if (srb == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // Allocate a transfer buffer for the SCSIOP_FORMAT_UNIT parameter list - // - parameterList = ExAllocatePool(NonPagedPoolNx, - sizeof(FORMAT_UNIT_PARAMETER_LIST)); - - if (parameterList == NULL) - { - ExFreePool(srb); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // Initialize the parameter list - // - RtlZeroMemory(parameterList, sizeof(FORMAT_UNIT_PARAMETER_LIST)); - - parameterList->DefectListHeader.SingleTrack = 1; - parameterList->DefectListHeader.DisableCert = 1; // TEAC requires this set - parameterList->DefectListHeader.FormatOptionsValid = 1; - parameterList->DefectListHeader.DefectListLengthLsb = 8; - - parameterList->FormatDescriptor.NumberOfBlocks[0] = - (UCHAR)((capacity->NumberOfBlocks >> 24) & 0xFF); - - parameterList->FormatDescriptor.NumberOfBlocks[1] = - (UCHAR)((capacity->NumberOfBlocks >> 16) & 0xFF); - - parameterList->FormatDescriptor.NumberOfBlocks[2] = - (UCHAR)((capacity->NumberOfBlocks >> 8) & 0xFF); - - parameterList->FormatDescriptor.NumberOfBlocks[3] = - (UCHAR)(capacity->NumberOfBlocks & 0xFF); - - parameterList->FormatDescriptor.BlockLength[0] = - (UCHAR)((capacity->BlockLength >> 16) & 0xFF); - - parameterList->FormatDescriptor.BlockLength[1] = - (UCHAR)((capacity->BlockLength >> 8) & 0xFF); - - parameterList->FormatDescriptor.BlockLength[2] = - (UCHAR)(capacity->BlockLength & 0xFF); - - - for (cylinder = formatParameters->StartCylinderNumber; - cylinder <= formatParameters->EndCylinderNumber; - cylinder++) - { - for (head = formatParameters->StartHeadNumber; - head <= formatParameters->EndHeadNumber; - head++) - { - // Initialize the SRB and CDB - // - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - srb->CdbLength = sizeof(CDB12FORMAT); - - srb->TimeOutValue = fdoExtension->TimeOutValue; - - cdb = (PCDB12FORMAT)srb->Cdb; - - cdb->OperationCode = SCSIOP_FORMAT_UNIT; - cdb->DefectListFormat = 7; - cdb->FmtData = 1; - cdb->TrackNumber = (UCHAR)cylinder; - cdb->ParameterListLengthLsb = sizeof(FORMAT_UNIT_PARAMETER_LIST); - - parameterList->DefectListHeader.Side = (UCHAR)head; - - // - // Send down the SCSIOP_FORMAT_UNIT request - // - status = ClassSendSrbSynchronous(DeviceObject, - srb, - parameterList, - sizeof(FORMAT_UNIT_PARAMETER_LIST), - TRUE); - - if (!NT_SUCCESS(status)) - { - break; - } - } - if (!NT_SUCCESS(status)) - { - break; - } - } - - if (NT_SUCCESS(status) && formatParameters->StartCylinderNumber == 0) - { - // Update the device geometry - // - - DebugPrint((2,"geometry was: %3d %2d %d %2d %4d %2d %08X\n", - fdoExtension->DiskGeometry.Cylinders.LowPart, - fdoExtension->DiskGeometry.MediaType, - fdoExtension->DiskGeometry.TracksPerCylinder, - fdoExtension->DiskGeometry.SectorsPerTrack, - fdoExtension->DiskGeometry.BytesPerSector, - fdoExtension->SectorShift, - fdoExtension->CommonExtension.PartitionLength.LowPart)); - - fdoExtension->DiskGeometry = *geometry; - - // - // Calculate sector to byte shift. - // - - WHICH_BIT(fdoExtension->DiskGeometry.BytesPerSector, - fdoExtension->SectorShift); - - fdoExtension->CommonExtension.PartitionLength.QuadPart = - (LONGLONG)capacity->NumberOfBlocks * - capacity->BlockLength; - - DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n", - fdoExtension->DiskGeometry.Cylinders.LowPart, - fdoExtension->DiskGeometry.MediaType, - fdoExtension->DiskGeometry.TracksPerCylinder, - fdoExtension->DiskGeometry.SectorsPerTrack, - fdoExtension->DiskGeometry.BytesPerSector, - fdoExtension->SectorShift, - fdoExtension->CommonExtension.PartitionLength.LowPart)); - } - - // Free everything we allocated - // - ExFreePool(parameterList); - ExFreePool(srb); - - return status; -} diff --git a/storage/sfloppy/src/sfloppy.inf b/storage/sfloppy/src/sfloppy.inf deleted file mode 100644 index 5eb2f79a..00000000 --- a/storage/sfloppy/src/sfloppy.inf +++ /dev/null @@ -1,87 +0,0 @@ -; sfloppy.inf -; -; Installation inf for the Floppy Disk Driver (DDK Sample). -; -; (c) Copyright 2002 Microsoft -; -[Version] -Signature="$WINDOWS NT$" -Class=FloppyDisk -ClassGuid={4D36E980-E325-11CE-BFC1-08002BE10318} -Provider=%ProviderString% -CatalogFile=ddk_sample.cat -DriverVer=05/17/2002,5.2.3635.0 - -;You must specify which platform is supported by each SourceDisksNames section -;Valid platform identifiers include .x86, .ia64, .alpha, .axp64 -[SourceDisksNames] -12=%floppyClassName%,,, - -;You must also specify which platform is supported by each SourceDisksFiles section -;Valid platform identifiers include .x86, .ia64, .alpha, .axp64 -[SourceDisksFiles] -sfloppy.sys=12 - -[ControlFlags] -ExcludeFromSelect=* - -[DestinationDirs] -sfloppy_copyfiles=12 -DefaultDestDir=12 - -[Manufacturer] -%ManufacturerName%=floppy_device,NTx86,NTia64,NTamd64 - -[floppy_device.NTx86] -%sfloppy_devdesc%=sfloppy_install,GenSFloppy -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskMATSHITALS-120_COSM___04 -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskCOMPAQ__LS-120_VER5___AB -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskCOMPAQ__LS-120_HIMA___01 -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskMATSHITALS-120_VER5___00 - -[floppy_device.NTia64] -%sfloppy_devdesc%=sfloppy_install,GenSFloppy -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskMATSHITALS-120_COSM___04 -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskCOMPAQ__LS-120_VER5___AB -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskCOMPAQ__LS-120_HIMA___01 -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskMATSHITALS-120_VER5___00 - -[floppy_device.NTamd64] -%sfloppy_devdesc%=sfloppy_install,GenSFloppy -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskMATSHITALS-120_COSM___04 -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskCOMPAQ__LS-120_VER5___AB -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskCOMPAQ__LS-120_HIMA___01 -%sfloppy_devdesc%=sfloppy_install,SCSI\DiskMATSHITALS-120_VER5___00 - -;; -;; super floppy -;; -[sfloppy_install.NT] -CopyFiles=sfloppy_copyfiles - -[sfloppy_copyfiles] -sfloppy.sys - -[sfloppy_install.NT.Services] -AddService=sfloppy,2,sfloppy_ServiceInstallSection - -[sfloppy_ServiceInstallSection] -DisplayName=%sfloppy_devdesc% -ServiceType=1 -StartType=3 -ErrorControl=1 -ServiceBinary = %12%\sfloppy.sys - -[sfloppy_install.NT.HW] -AddReg=sfloppyEnable.RegHW - -[sfloppyEnable.RegHW] -HKR,,SuperFloppy,%REG_DWORD%,0x00000001 - -[Strings] -ProviderString="TODO-Set-Provider" -ManufacturerName="TODO-Set-Manufacturer" -floppyClassName="Floppy disk drives" -sfloppy_devdesc="High-Capacity Floppy Disk Drive" - -REG_DWORD=0x00010001 diff --git a/storage/sfloppy/src/sfloppy.rc b/storage/sfloppy/src/sfloppy.rc deleted file mode 100644 index efe6c05c..00000000 --- a/storage/sfloppy/src/sfloppy.rc +++ /dev/null @@ -1,23 +0,0 @@ -//+------------------------------------------------------------------------- -// -// Microsoft Windows -// -// Copyright (C) Microsoft Corporation, 1997 - 1999 -// -// File: sfloppy.rc -// -//-------------------------------------------------------------------------- - -#include <windows.h> - -#include <ntverp.h> - -#define VER_FILETYPE VFT_DRV -#define VER_FILESUBTYPE VFT2_DRV_SYSTEM -#define VER_FILEDESCRIPTION_STR "SCSI Floppy Driver" -#define VER_INTERNALNAME_STR "sfloppy.sys" -#define VER_ORIGINALFILENAME_STR "sfloppy.sys" -#define VER_LANGNEUTRAL - -#include "common.ver" - diff --git a/storage/sfloppy/src/sfloppy.vcxproj b/storage/sfloppy/src/sfloppy.vcxproj deleted file mode 100644 index abcc78d0..00000000 --- a/storage/sfloppy/src/sfloppy.vcxproj +++ /dev/null @@ -1,192 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{97D2E67D-8E5F-43CD-B8EB-C5DBB43C7EB7}</ProjectGuid> - <RootNamespace>$(MSBuildProjectName)</RootNamespace> - <SupportsPackaging>false</SupportsPackaging> - <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> - <SampleGuid>{6B097D1A-972A-41E8-A5C4-3691455FBB8B}</SampleGuid> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>WDM</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>WDM</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>WDM</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>WDM</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <PropertyGroup> - <OutDir>$(IntDir)</OutDir> - </PropertyGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> - <ItemGroup Label="WrappedTaskItems" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <TargetName>sfloppy</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <TargetName>sfloppy</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <TargetName>sfloppy</TargetName> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <TargetName>sfloppy</TargetName> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\classpnp.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\classpnp.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\classpnp.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\classpnp.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> - </Midl> - <DriverSign> - <FileDigestAlgorithm>sha256</FileDigestAlgorithm> - </DriverSign> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="floppy.c" /> - <ResourceCompile Include="sfloppy.rc" /> - </ItemGroup> - <ItemGroup> - <Inf Exclude="@(Inf)" Include="*.inf" /> - <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> - </ItemGroup> - <ItemGroup> - <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> - <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> - <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> - </ItemGroup> - <ItemGroup> - <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> -</Project>
\ No newline at end of file diff --git a/storage/sfloppy/src/sfloppy.vcxproj.Filters b/storage/sfloppy/src/sfloppy.vcxproj.Filters deleted file mode 100644 index c1d47f3d..00000000 --- a/storage/sfloppy/src/sfloppy.vcxproj.Filters +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> - <UniqueIdentifier>{4BC320E9-22F6-4E58-8E7B-B87F90A2226B}</UniqueIdentifier> - </Filter> - <Filter Include="Header Files"> - <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> - <UniqueIdentifier>{1B1144FD-B9FD-45E0-846D-0C0A89430459}</UniqueIdentifier> - </Filter> - <Filter Include="Resource Files"> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> - <UniqueIdentifier>{BC1B1BDB-FAE7-4C16-A4B2-EBDC273AB7BC}</UniqueIdentifier> - </Filter> - <Filter Include="Driver Files"> - <Extensions>inf;inv;inx;mof;mc;</Extensions> - <UniqueIdentifier>{3AF8BBF9-34B1-4CEA-8BC6-305FB857F626}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="floppy.c"> - <Filter>Source Files</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="sfloppy.rc"> - <Filter>Resource Files</Filter> - </ResourceCompile> - </ItemGroup> - <ItemGroup> - <Inf Include="*.inf"> - <Filter>Driver Files</Filter> - </Inf> - </ItemGroup> -</Project>
\ No newline at end of file diff --git a/storage/tools/spti/spti.sln b/storage/tools/spti/spti.sln index 3075d257..49e55a69 100644 --- a/storage/tools/spti/spti.sln +++ b/storage/tools/spti/spti.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0 @@ -7,16 +7,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spti", "src\spti.vcxproj", EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|ARM64 = Debug|ARM64 + Release|ARM64 = Release|ARM64 Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Debug|Win32.ActiveCfg = Debug|Win32 - {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Debug|Win32.Build.0 = Debug|Win32 - {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Release|Win32.ActiveCfg = Release|Win32 - {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Release|Win32.Build.0 = Release|Win32 + {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Debug|ARM64.Build.0 = Debug|ARM64 + {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Release|ARM64.ActiveCfg = Release|ARM64 + {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Release|ARM64.Build.0 = Release|ARM64 {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Debug|x64.ActiveCfg = Debug|x64 {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Debug|x64.Build.0 = Debug|x64 {DBA7C5E3-522A-4974-B0C3-543BBC1665FF}.Release|x64.ActiveCfg = Release|x64 diff --git a/storage/tools/spti/src/spti.vcxproj b/storage/tools/spti/src/spti.vcxproj index 25cb31d5..5dbc7a50 100644 --- a/storage/tools/spti/src/spti.vcxproj +++ b/storage/tools/spti/src/spti.vcxproj @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> + <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> + <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> - <Platform>Win32</Platform> + <Platform>ARM64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> @@ -22,38 +22,38 @@ <ProjectGuid>{DBA7C5E3-522A-4974-B0C3-543BBC1665FF}</ProjectGuid> <RootNamespace>$(MSBuildProjectName)</RootNamespace> <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> - <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <Platform Condition="'$(Platform)' == ''">x64</Platform> <SampleGuid>{2A05EF6E-AE10-41D1-B69C-7F7FA900C3AF}</SampleGuid> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>Application</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>Application</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>Application</ConfigurationType> </PropertyGroup> - <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> <DriverType /> <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>Application</ConfigurationType> @@ -65,26 +65,26 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>spti</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <TargetName>spti</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetName>spti</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <TargetName>spti</TargetName> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -102,7 +102,7 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> @@ -117,7 +117,7 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> @@ -132,7 +132,7 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\..\inc;$(DDK_INC_PATH)</AdditionalIncludeDirectories> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> <WarningLevel>Level4</WarningLevel> |
