/*--
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 = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
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,