ReactOS 0.4.15-dev-7918-g2a2556c
cdrom.c File Reference
#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"
Include dependency graph for cdrom.c:

Go to the source code of this file.

Macros

#define DEBUG_MAIN_SOURCE   1
 

Functions

BOOLEAN BootEnvironmentIsWinPE (VOID)
 
NTSTATUS NTAPI DriverEntry (_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
 
VOID NTAPI DriverEvtCleanup (_In_ WDFOBJECT Driver)
 
NTSTATUS NTAPI DriverEvtDeviceAdd (_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
 
VOID NTAPI DeviceEvtCleanup (_In_ WDFOBJECT Device)
 
VOID NTAPI DeviceEvtSelfManagedIoCleanup (_In_ WDFDEVICE Device)
 
NTSTATUS NTAPI DeviceEvtD0Entry (_In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE PreviousState)
 
NTSTATUS NTAPI DeviceEvtD0Exit (_In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE TargetState)
 
VOID NTAPI DeviceEvtSurpriseRemoval (_In_ WDFDEVICE Device)
 
VOID NTAPI CreateQueueEvtIoDefault (_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request)
 
VOID NTAPI DeviceEvtFileClose (_In_ WDFFILEOBJECT FileObject)
 
 _IRQL_requires_max_ (PASSIVE_LEVEL)
 
 _IRQL_requires_max_ (APC_LEVEL)
 
VOID NormalizeIoctl (_Inout_ PWDF_REQUEST_PARAMETERS requestParameters)
 
VOID NTAPI DeviceEvtIoInCallerContext (_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
 
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)
 
VOID RequestProcessInternalDeviceControl (_In_ WDFREQUEST Request, _In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
 
VOID NTAPI SequentialQueueEvtIoReadWrite (_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length)
 
VOID NTAPI ReadWriteWorkItemRoutine (_In_ WDFWORKITEM WorkItem)
 
VOID NTAPI SequentialQueueEvtIoDeviceControl (_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode)
 
VOID NTAPI IoctlWorkItemRoutine (_In_ WDFWORKITEM WorkItem)
 
VOID NTAPI SequentialQueueEvtCanceledOnQueue (_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request)
 
NTSTATUS RequestSynchronizeProcessWithSerialQueue (_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
 
NTSTATUS RequestIsIoctlBlockedByExclusiveAccess (_In_ WDFREQUEST Request, _Out_ PBOOLEAN IsBlocked)
 
BOOLEAN DeviceIsMmcUpdateRequired (_In_ WDFDEVICE Device)
 
VOID NTAPI RequestEvtCleanup (_In_ WDFOBJECT Request)
 

Macro Definition Documentation

◆ DEBUG_MAIN_SOURCE

#define DEBUG_MAIN_SOURCE   1

Definition at line 26 of file cdrom.c.

Function Documentation

◆ _IRQL_requires_max_() [1/2]

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 1473 of file cdrom.c.

1496{
1497 PAGED_CODE();
1498
1499 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1500 "CleanupDisableMcn called for WDFDEVICE %p, WDFFILEOBJECT %p, locked %d times.\n",
1501 DeviceExtension->Device, FileObjectContext->FileObject, FileObjectContext->McnDisableCount));
1502
1503 // For each secure lock on this handle decrement the secured lock count
1504 // for the FDO. Keep track of the new value.
1506 {
1507 DeviceEnableMediaChangeDetection(DeviceExtension, FileObjectContext, TRUE);
1508 }
1509
1510 return STATUS_SUCCESS;
1511}
#define PAGED_CODE()
_In_ PFILE_OBJECT_CONTEXT FileObjectContext
Definition: cdrom.h:1212
#define TRUE
Definition: types.h:120
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
ULONG McnDisableCount
Definition: cdromp.h:367
WDFFILEOBJECT FileObject
Definition: cdromp.h:364

◆ _IRQL_requires_max_() [2/2]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 1389 of file cdrom.c.

1412{
1414
1415 PAGED_CODE();
1416
1417 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1418 "CleanupProtectedLocks called for WDFDEVICE %p, WDFFILEOBJECT %p, locked %d times.\n",
1419 DeviceExtension->Device, FileObjectContext->FileObject, FileObjectContext->LockCount));
1420
1421 // Synchronize with ejection and ejection control requests.
1422 WdfWaitLockAcquire(DeviceExtension->EjectSynchronizationLock, NULL);
1423
1424 // For each secure lock on this handle decrement the secured lock count
1425 // for the FDO. Keep track of the new value.
1426 if (FileObjectContext->LockCount != 0)
1427 {
1428 DeviceExtension->ProtectedLockCount -= FileObjectContext->LockCount;
1430
1431 // If the new lock count has been dropped to zero then issue a lock
1432 // command to the device.
1433 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1434 "FDO secured lock count = %d "
1435 "lock count = %d\n",
1436 DeviceExtension->ProtectedLockCount,
1437 DeviceExtension->LockCount));
1438
1439 if ((DeviceExtension->ProtectedLockCount == 0) && (DeviceExtension->LockCount == 0))
1440 {
1441 SCSI_REQUEST_BLOCK srb = {0};
1442 PCDB cdb = (PCDB) &(srb.Cdb);
1443
1444 srb.CdbLength = 6;
1445
1446 cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
1447
1448 // TRUE - prevent media removal.
1449 // FALSE - allow media removal.
1450 cdb->MEDIA_REMOVAL.Prevent = FALSE;
1451
1452 // Set timeout value.
1453 srb.TimeOutValue = DeviceExtension->TimeOutValue;
1454 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
1455 &srb,
1456 NULL,
1457 0,
1458 FALSE,
1459 NULL);
1460
1461 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1462 "Allow media removal (unlock) request to drive returned %!STATUS!\n",
1463 status));
1464 }
1465 }
1466
1467 WdfWaitLockRelease(DeviceExtension->EjectSynchronizationLock);
1468
1469 return status;
1470}
LONG NTSTATUS
Definition: precomp.h:26
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
union _CDB * PCDB
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
ULONG TimeOutValue
Definition: srb.h:262
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
Definition: ps.c:97
Definition: cdrw_hw.h:28
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL
_Must_inspect_result_ FORCEINLINE NTSTATUS WdfWaitLockAcquire(_In_ _Requires_lock_not_held_(_Curr_) WDFWAITLOCK Lock, _In_opt_ PLONGLONG Timeout)
Definition: wdfsync.h:173

◆ BootEnvironmentIsWinPE()

BOOLEAN BootEnvironmentIsWinPE ( VOID  )

Definition at line 158 of file cdrom.c.

176{
178 WDFKEY registryKey = NULL;
179
181
182 PAGED_CODE();
183
184 status = WdfRegistryOpenKey(NULL,
185 &registryKeyName,
186 KEY_READ,
188 &registryKey);
189
190 if (!NT_SUCCESS(status))
191 {
192 return FALSE;
193 }
194
195 WdfRegistryClose(registryKey);
196 return TRUE;
197} // end BootEnvironmentIsWinPE()
#define WINPE_REG_KEY_NAME
Definition: cdromp.h:127
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define KEY_READ
Definition: nt_native.h:1023
#define DECLARE_CONST_UNICODE_STRING(_variablename, _string)
Definition: wdfcore.h:161
#define WDF_NO_OBJECT_ATTRIBUTES
Definition: wdftypes.h:105

Referenced by DriverEntry().

◆ CreateQueueEvtIoDefault()

VOID NTAPI CreateQueueEvtIoDefault ( _In_ WDFQUEUE  Queue,
_In_ WDFREQUEST  Request 
)

Definition at line 1266 of file cdrom.c.

1288{
1289 WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request);
1290 WDFDEVICE device = WdfIoQueueGetDevice(Queue);
1292 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
1293 PFILE_OBJECT_CONTEXT fileObjectContext = NULL;
1294
1295 PAGED_CODE();
1296
1297 if (fileObject == NULL) {
1298
1299 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_QUEUE,
1300 "Error: received a file create request with file object set to NULL\n"));
1301
1302 RequestCompletion(deviceExtension, Request, STATUS_INTERNAL_ERROR, 0);
1303 return;
1304 }
1305
1306 fileObjectContext = FileObjectGetContext(fileObject);
1307
1308 // Initialize this WDFFILEOBJECT's context
1309 fileObjectContext->DeviceObject = device;
1310 fileObjectContext->FileObject = fileObject;
1311 fileObjectContext->LockCount = 0;
1312 fileObjectContext->McnDisableCount = 0;
1313 fileObjectContext->EnforceStreamingRead = FALSE;
1314 fileObjectContext->EnforceStreamingWrite = FALSE;
1315
1316 // send down the create synchronously
1317 status = DeviceSendRequestSynchronously(device, Request, FALSE);
1318
1319 // Need to complete the request in this routine.
1320 RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
1321
1322 return;
1323}
VOID RequestCompletion(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG_PTR Information)
Definition: common.c:3439
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
BOOLEAN EnforceStreamingRead
Definition: cdromp.h:368
BOOLEAN EnforceStreamingWrite
Definition: cdromp.h:369
WDFDEVICE DeviceObject
Definition: cdromp.h:365
Definition: devices.h:37
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2225
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547

◆ DeviceEvtCleanup()

VOID NTAPI DeviceEvtCleanup ( _In_ WDFOBJECT  Device)

Definition at line 856 of file cdrom.c.

873{
874 WDFDEVICE device = (WDFDEVICE)Device;
875 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
876
877 PAGED_CODE ();
878
879 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
880 "WDFDEVICE %p cleanup: The device is about to be destroyed.\n",
881 device));
882
883 deviceExtension = DeviceGetExtension(device);
884
885 FREE_POOL(deviceExtension->DeviceName.Buffer);
886 RtlInitUnicodeString(&deviceExtension->DeviceName, NULL);
887
888 if (deviceExtension->DeviceAdditionalData.WellKnownName.Buffer != NULL)
889 {
891 }
892
895
896 return;
897}
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
UNICODE_STRING WellKnownName
Definition: cdrom.h:357
UNICODE_STRING DeviceName
Definition: cdrom.h:502
CDROM_DATA DeviceAdditionalData
Definition: cdrom.h:598
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474

◆ DeviceEvtD0Entry()

NTSTATUS NTAPI DeviceEvtD0Entry ( _In_ WDFDEVICE  Device,
_In_ WDF_POWER_DEVICE_STATE  PreviousState 
)

Definition at line 993 of file cdrom.c.

1014{
1015 PCDROM_DEVICE_EXTENSION deviceExtension;
1017 PZERO_POWER_ODD_INFO zpoddInfo = NULL;
1018 STORAGE_IDLE_POWERUP_REASON powerupReason = {0};
1019
1021 deviceExtension = DeviceGetExtension(Device);
1022
1023 // Make certain not to do anything before properly initialized
1024 if (deviceExtension->IsInitialized)
1025 {
1026 zpoddInfo = deviceExtension->ZeroPowerODDInfo;
1027
1028 if (zpoddInfo != NULL)
1029 {
1030 if (zpoddInfo->InZeroPowerState != FALSE)
1031 {
1032 // We just woke up from Zero Power state
1033 zpoddInfo->InZeroPowerState = FALSE;
1034 zpoddInfo->RetryFirstCommand = TRUE;
1036
1037 status = DeviceZPODDGetPowerupReason(deviceExtension, &powerupReason);
1038
1039 if (NT_SUCCESS(status) &&
1041 {
1042 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
1043 "DeviceEvtD0Entry: Device has left zero power state due to eject button pressed\n"
1044 ));
1045
1046 // This wake-up is caused by user pressing the eject button.
1047 // In case of drawer type, we need to soft eject the tray to emulate the effect.
1048 // Note that the first command to the device after power resumed will
1049 // be terminated with CHECK CONDITION status with sense code 6/29/00,
1050 // but we already have a retry logic to handle this.
1051 if ((zpoddInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) && (zpoddInfo->Load == 0)) // Drawer
1052 {
1053 DeviceSendIoctlAsynchronously(deviceExtension, IOCTL_STORAGE_EJECT_MEDIA, deviceExtension->DeviceObject);
1054 }
1055 }
1056 else
1057 {
1058 // This wake-up is caused by non-cached CDB received or a 3rd-party driver
1059 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
1060 "DeviceEvtD0Entry: Device has left zero power state due to IO received\n"
1061 ));
1062
1063 }
1064 }
1065 }
1066
1067 DeviceEnableMainTimer(deviceExtension);
1068 }
1069
1070 return STATUS_SUCCESS;
1071}
NTSTATUS DeviceZPODDGetPowerupReason(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _Out_ PSTORAGE_IDLE_POWERUP_REASON PowerupReason)
Definition: zpodd.c:608
VOID DeviceSendIoctlAsynchronously(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT TargetDeviceObject)
Definition: common.c:1030
#define BECOMING_READY_RETRY_COUNT
Definition: cdromp.h:261
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
@ StoragePowerupDeviceAttention
Definition: ntddstor.h:1095
#define IOCTL_STORAGE_EJECT_MEDIA
Definition: ntddstor.h:107
#define LOADING_MECHANISM_TRAY
Definition: scsi.h:972
PDEVICE_OBJECT DeviceObject
Definition: cdrom.h:493
PZERO_POWER_ODD_INFO ZeroPowerODDInfo
Definition: cdrom.h:566
BOOLEAN IsInitialized
Definition: cdrom.h:464
STORAGE_POWERUP_REASON_TYPE PowerupReason
Definition: ntddstor.h:1102
BOOLEAN RetryFirstCommand
Definition: cdromp.h:273
ULONG BecomingReadyRetryCount
Definition: cdromp.h:277
UCHAR LoadingMechanism
Definition: cdromp.h:266
BOOLEAN InZeroPowerState
Definition: cdromp.h:272
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829

◆ DeviceEvtD0Exit()

NTSTATUS NTAPI DeviceEvtD0Exit ( _In_ WDFDEVICE  Device,
_In_ WDF_POWER_DEVICE_STATE  TargetState 
)

Definition at line 1075 of file cdrom.c.

1097{
1099 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
1100 PZERO_POWER_ODD_INFO zpoddInfo = NULL;
1101
1102 PAGED_CODE ();
1103
1104 deviceExtension = DeviceGetExtension(Device);
1105 zpoddInfo = deviceExtension->ZeroPowerODDInfo;
1106
1107 // we only process the situation that the device is going into D3.
1108 if ((TargetState != WdfPowerDeviceD3) &&
1110 {
1111 return STATUS_SUCCESS;
1112 }
1113
1114 // Stop the main timer
1115 DeviceDisableMainTimer(deviceExtension);
1116
1117 // note: do not stop CreateQueue as the create request can be handled by port driver even the device is in D3 status.
1118
1119 // If initialization was not finished or the device was removed, we cannot interact
1120 // with it device, so we have to exit
1121 if ((!deviceExtension->IsInitialized) || deviceExtension->SurpriseRemoved)
1122 {
1123 return STATUS_SUCCESS;
1124 }
1125
1126
1127#ifdef DBG
1128 #if (WINVER >= 0x0601)
1129 // this API is introduced in Windows7
1130 {
1131 ULONG secondsRemaining = 0;
1132 BOOLEAN watchdogTimeSupported = FALSE;
1133
1134 watchdogTimeSupported = PoQueryWatchdogTime(deviceExtension->LowerPdo, &secondsRemaining);
1135 UNREFERENCED_PARAMETER(watchdogTimeSupported);
1136 }
1137 #endif
1138#endif
1139
1140 deviceExtension->PowerDownInProgress = TRUE;
1141
1142 status = PowerContextBeginUse(deviceExtension);
1143
1144 deviceExtension->PowerContext.Options.PowerDown = TRUE;
1145
1146 // Step 1. LOCK QUEUE
1147 if (NT_SUCCESS(status) &&
1149 {
1150 status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL);
1151
1152 if (NT_SUCCESS(status))
1153 {
1154 deviceExtension->PowerContext.Options.LockQueue = TRUE;
1155 }
1156
1157 // Ignore failure.
1159 }
1160
1161 deviceExtension->PowerContext.PowerChangeState.PowerDown++;
1162
1163 // Step 2. QUIESCE QUEUE
1164 if (NT_SUCCESS(status) &&
1166 {
1167 status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL);
1169 // We don't care about the status.
1171 }
1172
1173 deviceExtension->PowerContext.PowerChangeState.PowerDown++;
1174
1175 // Step 3. SYNC CACHE command should be sent to drive if the media is currently writable.
1176 if (NT_SUCCESS(status) &&
1177 deviceExtension->DeviceAdditionalData.Mmc.WriteAllowed)
1178 {
1179 status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL);
1182 }
1183
1184 deviceExtension->PowerContext.PowerChangeState.PowerDown++;
1185
1186 // Step 4. STOP UNIT
1187 if (NT_SUCCESS(status) &&
1189 {
1190 status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL);
1193 }
1194
1196 {
1197 // We're done with the power context.
1198 PowerContextEndUse(deviceExtension);
1199 }
1200
1201 // Bumping the media change count will force the file system to verify the volume when we resume
1202 SET_FLAG(deviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
1203 InterlockedIncrement((PLONG)&deviceExtension->MediaChangeCount);
1204
1205 // If this power down is caused by Zero Power ODD, we should mark the device as in ZPODD mode.
1206 if (zpoddInfo != NULL)
1207 {
1208 zpoddInfo->InZeroPowerState = TRUE;
1209
1210 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
1211 "Device has entered zero power state\n"
1212 ));
1213 }
1214
1215 deviceExtension->PowerDownInProgress = FALSE;
1216
1217 return STATUS_SUCCESS;
1218}
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define CDROM_SPECIAL_DISABLE_SPIN_DOWN
Definition: cdrom.h:149
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
CDROM_MMC_EXTENSION Mmc
Definition: cdrom.h:341
ULONG ScanForSpecialFlags
Definition: cdrom.h:512
CDROM_POWER_CONTEXT PowerContext
Definition: cdrom.h:586
PDEVICE_OBJECT LowerPdo
Definition: cdrom.h:496
BOOLEAN PowerDownInProgress
Definition: cdrom.h:587
BOOLEAN SurpriseRemoved
Definition: cdrom.h:470
BOOLEAN WriteAllowed
Definition: cdrom.h:250
union _CDROM_POWER_CONTEXT::@1045 PowerChangeState
CDROM_POWER_OPTIONS Options
Definition: cdrom.h:442
CDROM_POWER_DOWN_STATE PowerDown
Definition: cdrom.h:438
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
@ WdfPowerDeviceD3Final
Definition: wdfdevice.h:427
@ WdfPowerDeviceD3
Definition: wdfdevice.h:426
_In_ WDF_POWER_DEVICE_STATE TargetState
Definition: wdfdevice.h:859

◆ DeviceEvtFileClose()

VOID NTAPI DeviceEvtFileClose ( _In_ WDFFILEOBJECT  FileObject)

Definition at line 1327 of file cdrom.c.

1346{
1348
1349 PAGED_CODE();
1350
1351 if (FileObject != NULL)
1352 {
1353 WDFDEVICE device = WdfFileObjectGetDevice(FileObject);
1354 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
1355 PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
1356 PFILE_OBJECT_CONTEXT fileObjectContext = FileObjectGetContext(FileObject);
1357
1358 // cleanup locked media tray
1359 status = DeviceCleanupProtectedLocks(deviceExtension, fileObjectContext);
1360 if (!NT_SUCCESS(status))
1361 {
1362 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1363 "Failed to cleanup protected locks for WDFDEVICE %p, %!STATUS!\n", device, status));
1364 }
1365
1366 // cleanup disabled MCN
1367 status = DeviceCleanupDisableMcn(deviceExtension, fileObjectContext);
1368 if (!NT_SUCCESS(status))
1369 {
1370 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1371 "Failed to disable MCN for WDFDEVICE %p, %!STATUS!\n", device, status));
1372 }
1373
1374 // cleanup exclusive access
1375 if (EXCLUSIVE_MODE(cdData) && EXCLUSIVE_OWNER(cdData, FileObject))
1376 {
1377 status = DeviceUnlockExclusive(deviceExtension, FileObject, FALSE);
1378 if (!NT_SUCCESS(status))
1379 {
1380 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1381 "Failed to release exclusive lock for WDFDEVICE %p, %!STATUS!\n", device, status));
1382 }
1383 }
1384 }
1385
1386 return;
1387}
#define EXCLUSIVE_OWNER(_CdData, _FileObject)
Definition: cdrom.h:789
#define EXCLUSIVE_MODE(_CdData)
Definition: cdrom.h:788
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550

◆ DeviceEvtIoInCallerContext()

VOID NTAPI DeviceEvtIoInCallerContext ( _In_ WDFDEVICE  Device,
_In_ WDFREQUEST  Request 
)

Definition at line 1554 of file cdrom.c.

1575{
1577 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
1578 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
1579 WDF_REQUEST_PARAMETERS requestParameters;
1580
1581 requestContext->DeviceExtension = deviceExtension;
1582
1583 // set the received time
1585
1586 // get the request parameters
1587 WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
1588 WdfRequestGetParameters(Request, &requestParameters);
1589
1590 if (requestParameters.Type == WdfRequestTypeDeviceControl)
1591 {
1593 PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
1595
1596 if (requestParameters.Parameters.DeviceIoControl.IoControlCode != IOCTL_MCN_SYNC_FAKE_IOCTL)
1597 {
1598 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
1599 "Receiving IOCTL: %lx\n",
1600 requestParameters.Parameters.DeviceIoControl.IoControlCode));
1601 }
1602 else
1603 {
1604 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
1605 "Receiving IOCTL: %lx\n",
1606 requestParameters.Parameters.DeviceIoControl.IoControlCode));
1607 }
1608
1609 // If the device is in exclusive mode, check whether the request is from
1610 // the handle that locked the device.
1611 if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
1612 {
1613 BOOLEAN isBlocked = FALSE;
1614
1616 UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning.
1617
1618 if (isBlocked)
1619 {
1620 if ((requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_EVENT_NOTIFICATION) &&
1621 (info != NULL) && (info->AsynchronousNotificationSupported != FALSE))
1622 {
1623 // If AN is supported and we receive a signal but we can't send down GESN
1624 // due to exclusive lock, we should save it and fire a GESN when it's unlocked.
1625 // We just need true/false here and don't need count because we will keep sending
1626 // GESN until we deplete all events.
1627 info->ANSignalPendingDueToExclusiveLock = TRUE;
1628 }
1629
1630 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
1631 "Access Denied! Device in exclusive mode.Failing Ioctl %lx\n",
1632 requestParameters.Parameters.DeviceIoControl.IoControlCode));
1633 RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0);
1634
1635 return;
1636 }
1637 }
1638
1639 NormalizeIoctl(&requestParameters);
1640
1641 // 1. All requests that don't need to access device can be processed immediately
1642 if (!processed)
1643 {
1645 }
1646
1647 // 2. Requests that should be put in sequential queue.
1648 if (!processed)
1649 {
1651 }
1652
1653 // 3. Requests that need to be processed sequentially and in caller's context.
1654 if (!processed)
1655 {
1657 }
1658
1659 // 4. Special requests that needs different process in different cases.
1660 if (!processed)
1661 {
1663 }
1664
1665 // 5. This is default behavior for unknown IOCTLs. To pass it to lower level.
1666 if (!processed)
1667 {
1669 }
1670
1671 // All requests should be processed already.
1673 UNREFERENCED_PARAMETER(processed); //defensive coding, avoid PREFAST warning.
1674 }
1675 else if (requestParameters.Type == WdfRequestTypeDeviceControlInternal)
1676 {
1678 }
1679 else
1680 {
1681 // Requests other than IOCTLs will be forwarded to default queue.
1682 status = WdfDeviceEnqueueRequest(Device, Request);
1683 if (!NT_SUCCESS(status))
1684 {
1685 RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
1686 }
1687 }
1688
1689 return;
1690}
BOOLEAN RequestDispatchToSequentialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:1855
BOOLEAN RequestDispatchUnknownRequests(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:3093
NTSTATUS RequestIsIoctlBlockedByExclusiveAccess(_In_ WDFREQUEST Request, _Out_ PBOOLEAN IsBlocked)
Definition: cdrom.c:4058
VOID RequestProcessInternalDeviceControl(_In_ WDFREQUEST Request, _In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: cdrom.c:3154
VOID NormalizeIoctl(_Inout_ PWDF_REQUEST_PARAMETERS requestParameters)
Definition: cdrom.c:1514
BOOLEAN RequestDispatchSyncWithSequentialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:2717
BOOLEAN RequestDispatchProcessDirectly(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:1694
BOOLEAN RequestDispatchSpecialIoctls(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:2849
#define IOCTL_MCN_SYNC_FAKE_IOCTL
Definition: cdrom.h:181
VOID RequestSetReceivedTime(_In_ WDFREQUEST Request)
Definition: common.c:64
#define IOCTL_STORAGE_EVENT_NOTIFICATION
Definition: ntddstor.h:226
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: cdrom.h:563
PCDROM_DEVICE_EXTENSION DeviceExtension
Definition: cdrom.h:631
WDF_REQUEST_TYPE Type
Definition: wdfrequest.h:142
struct _WDF_REQUEST_PARAMETERS::@3881::@3885 DeviceIoControl
union _WDF_REQUEST_PARAMETERS::@3881 Parameters
static int processed(const type_t *type)
Definition: typegen.c:2254
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
@ WdfRequestTypeDeviceControlInternal
Definition: wdfdevice.h:518
@ WdfRequestTypeDeviceControl
Definition: wdfdevice.h:517
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
Definition: wdfrequest.h:211
#define NT_ASSERT
Definition: rtlfuncs.h:3310

◆ DeviceEvtSelfManagedIoCleanup()

VOID NTAPI DeviceEvtSelfManagedIoCleanup ( _In_ WDFDEVICE  Device)

Definition at line 902 of file cdrom.c.

921{
923 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
924
925 PAGED_CODE ();
926
927 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP,
928 "DeviceEvtSelfManagedIoCleanup: WDFDEVICE %p is being stopped.\n",
929 Device));
930
931 // extract the device and driver extensions
932 deviceExtension = DeviceGetExtension(Device);
933
934 // Purge unprocessed requests, stop the IO queues.
935 // Incoming request will be completed with STATUS_INVALID_DEVICE_STATE status.
936 WdfIoQueuePurge(deviceExtension->SerialIOQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);
937 WdfIoQueuePurge(deviceExtension->CreateQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);
938
939 // Close the IoTarget so that we are sure there are no outstanding I/Os in the stack.
940 if (deviceExtension->IoTarget)
941 {
942 WdfIoTargetClose(deviceExtension->IoTarget);
943 }
944
945 // Release the device
946 if (!deviceExtension->SurpriseRemoved)
947 {
948 status = DeviceClaimRelease(deviceExtension, TRUE); //status is mainly for debugging. we don't really care.
949 UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning.
950 }
951
952 // Be sure to flush the DPCs as the READ/WRITE timer routine may still be running
953 // during device removal. This call may take a while to complete.
955
956 // Release all the memory that we have allocated.
957
958 DeviceDeallocateMmcResources(Device);
959 ScratchBuffer_Deallocate(deviceExtension);
960 RtlZeroMemory(&(deviceExtension->DeviceAdditionalData.Mmc), sizeof(CDROM_MMC_EXTENSION));
961
962 FREE_POOL(deviceExtension->DeviceDescriptor);
963 FREE_POOL(deviceExtension->AdapterDescriptor);
964 FREE_POOL(deviceExtension->PowerDescriptor);
965 FREE_POOL(deviceExtension->SenseData);
966
967 if (deviceExtension->DeviceAdditionalData.CachedInquiryData != NULL)
968 {
969 FREE_POOL(deviceExtension->DeviceAdditionalData.CachedInquiryData);
971 }
972
973 FREE_POOL(deviceExtension->PrivateFdoData);
974
975 DeviceReleaseMcnResources(deviceExtension);
976
977 DeviceReleaseZPODDResources(deviceExtension);
978
979 // Keep the system-wide CDROM count accurate, as programs use this info to
980 // know when they have found all the cdroms in a system.
982
983 deviceExtension->PartitionLength.QuadPart = 0;
984
985 // All WDF objects related to Device will be automatically released
986 // when the root object is deleted. No need to release them manually.
987
988 return;
989}
VOID NTAPI KeFlushQueuedDpcs(VOID)
Definition: dpc.c:919
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
ULONG CachedInquiryDataByteCount
Definition: cdrom.h:392
WDFIOTARGET IoTarget
Definition: cdrom.h:476
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: cdrom.h:542
PCDROM_PRIVATE_FDO_DATA PrivateFdoData
Definition: cdrom.h:605
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: cdrom.h:539
WDFQUEUE CreateQueue
Definition: cdrom.h:483
WDFQUEUE SerialIOQueue
Definition: cdrom.h:479
LARGE_INTEGER PartitionLength
Definition: cdrom.h:530
PSENSE_DATA SenseData
Definition: cdrom.h:548
PDEVICE_POWER_DESCRIPTOR PowerDescriptor
Definition: cdrom.h:545
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
LONGLONG QuadPart
Definition: typedefs.h:114
#define WDF_NO_EVENT_CALLBACK
Definition: wdftypes.h:106
#define WDF_NO_CONTEXT
Definition: wdftypes.h:108

◆ DeviceEvtSurpriseRemoval()

VOID NTAPI DeviceEvtSurpriseRemoval ( _In_ WDFDEVICE  Device)

Definition at line 1223 of file cdrom.c.

1242{
1243 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
1244
1245 PAGED_CODE();
1246
1247 deviceExtension = DeviceGetExtension(Device);
1248
1249 deviceExtension->SurpriseRemoved = TRUE;
1250
1251 // Stop the main timer
1252 DeviceDisableMainTimer(deviceExtension);
1253
1254 // legacy behavior to set partition length to be 0.
1255 deviceExtension->PartitionLength.QuadPart = 0;
1256
1257 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1258 "Surprisely remove a WDFDEVICE %p\n", Device));
1259
1260 return;
1261}

◆ DeviceIsMmcUpdateRequired()

BOOLEAN DeviceIsMmcUpdateRequired ( _In_ WDFDEVICE  Device)

Definition at line 4180 of file cdrom.c.

4197{
4198 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
4199 PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
4200
4201 if ((cdData->Mmc.IsMmc) &&
4203 {
4204 return TRUE;
4205 }
4206 else
4207 {
4208 // no update required: just proceed
4209 return FALSE;
4210 }
4211}
#define CdromMmcUpdateRequired
Definition: cdrom.h:242

Referenced by IoctlWorkItemRoutine(), ReadWriteWorkItemRoutine(), and SequentialQueueEvtIoReadWrite().

◆ DriverEntry()

NTSTATUS NTAPI DriverEntry ( _In_ PDRIVER_OBJECT  DriverObject,
_In_ PUNICODE_STRING  RegistryPath 
)

Definition at line 75 of file cdrom.c.

99{
102 WDF_OBJECT_ATTRIBUTES attributes;
103 WDFDRIVER driverObject = NULL;
104
105 PAGED_CODE();
106
107 // Initialize WPP Tracing
109
110 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
111 "CDROM.SYS DriverObject %p loading\n",
112 DriverObject));
113
114 // Register DeviceAdd and DriverEvtCleanup callback.
115 // WPP_CLEANUP will be called in DriverEvtCleanup
118
120
121 status = WdfDriverCreate(DriverObject,
123 &attributes,
124 &config,
125 &driverObject);
126
127 if (!NT_SUCCESS(status))
128 {
129 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT,
130 "WdfDriverCreate failed. %x\n",
131 status));
132
133 // Cleanup tracing here because DriverUnload will not be called
134 // as we have failed to create WDFDRIVER object itself.
136
137 }
138 else
139 {
140 PCDROM_DRIVER_EXTENSION driverExtension = DriverGetExtension(driverObject);
141
142 // Copy the registry path into the driver extension so we can use it later
143 driverExtension->Version = 0x01;
144 driverExtension->DriverObject = DriverObject;
145
147
148 SET_FLAG(driverExtension->Flags, CDROM_FLAG_WINPE_MODE);
149 }
150
151 }
152
153 return status;
154}
BOOLEAN BootEnvironmentIsWinPE(VOID)
Definition: cdrom.c:158
EVT_WDF_DRIVER_DEVICE_ADD DriverEvtDeviceAdd
Definition: cdrom.h:862
EVT_WDF_OBJECT_CONTEXT_CLEANUP DriverEvtCleanup
Definition: cdrom.h:864
#define CDROM_FLAG_WINPE_MODE
Definition: cdrom.h:237
struct config_s config
#define WPP_INIT_TRACING(a, b)
Definition: kdebugprint.h:56
#define WPP_CLEANUP(a)
Definition: kdebugprint.h:57
#define TRACE_LEVEL_FATAL
Definition: storswtr.h:26
PDRIVER_OBJECT DriverObject
Definition: cdrom.h:232
PFN_WDF_OBJECT_CONTEXT_CLEANUP EvtCleanupCallback
Definition: wdfobject.h:109
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
FORCEINLINE VOID WDF_DRIVER_CONFIG_INIT(_Out_ PWDF_DRIVER_CONFIG Config, _In_opt_ PFN_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd)
Definition: wdfdriver.h:148
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170

◆ DriverEvtCleanup()

VOID NTAPI DriverEvtCleanup ( _In_ WDFOBJECT  Driver)

Definition at line 202 of file cdrom.c.

219{
220 WDFDRIVER driver = (WDFDRIVER)Driver;
221
222 PAGED_CODE ();
223
224 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
225 "CDROM.SYS DriverObject %p cleanup. Will be unloaded soon\n",
226 driver));
227
228 // Stop WPP Tracing
229 WPP_CLEANUP( WdfDriverWdmGetDriverObject(driver) );
230
231
232 return;
233}
struct @1669::@1670 driver
_Must_inspect_result_ _In_ WDFDRIVER Driver
Definition: wdfcontrol.h:83

◆ DriverEvtDeviceAdd()

NTSTATUS NTAPI DriverEvtDeviceAdd ( _In_ WDFDRIVER  Driver,
_Inout_ PWDFDEVICE_INIT  DeviceInit 
)

Definition at line 238 of file cdrom.c.

261{
263 PCDROM_DRIVER_EXTENSION driverExtension = NULL;
264 WDFDEVICE device = NULL;
265 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
266 BOOLEAN deviceClaimed = FALSE;
267
268 WDF_OBJECT_ATTRIBUTES attributes;
269 WDF_FILEOBJECT_CONFIG fileObjectConfig;
270 WDF_IO_TARGET_OPEN_PARAMS ioTargetOpenParams;
271 WDF_IO_QUEUE_CONFIG queueConfig;
272 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
273 WDF_REMOVE_LOCK_OPTIONS removeLockOptions;
274 PWCHAR wideDeviceName = NULL;
275 UNICODE_STRING unicodeDeviceName;
276 PDEVICE_OBJECT lowerPdo = NULL;
277 ULONG deviceNumber = 0;
278 ULONG devicePropertySessionId = INVALID_SESSION;
279 ULONG devicePropertySize = 0;
280 DEVPROPTYPE devicePropertyType = DEVPROP_TYPE_EMPTY;
281
282 PAGED_CODE();
283
284 driverExtension = DriverGetExtension(Driver);
285
286 // 0. Initialize the objects that we're going to use
287 RtlInitUnicodeString(&unicodeDeviceName, NULL);
288
289 // 1. Register PnP&Power callbacks for any we are interested in.
290 // If a callback isn't set, Framework will take the default action by itself.
291 {
292 // Zero out the PnpPowerCallbacks structure.
293 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
294
295 // Use this callback to init resources that are used by the device and only needs to be called once.
297
298 // Use this callback to prepare device for coming back from a lower power mode to D0.
299 pnpPowerCallbacks.EvtDeviceD0Entry = DeviceEvtD0Entry;
300
301 // Use this callback to prepare device for entering into a lower power mode.
302 pnpPowerCallbacks.EvtDeviceD0Exit = DeviceEvtD0Exit;
303
304 // Use this callback to free any resources used by device and will be called when the device is
305 // powered down.
307
309
310 // Register the PnP and power callbacks.
311 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
312 }
313
314 // 2. Register the EvtIoInCallerContext to deal with IOCTLs that need to stay in original context.
315 WdfDeviceInitSetIoInCallerContextCallback(DeviceInit,
317
318 // 3. Register PreprocessCallback for IRP_MJ_POWER, IRP_MJ_FLUSH_BUFFERS and IRP_MJ_SHUTDOWN
319 {
320 UCHAR minorFunctions[1];
321
322 minorFunctions[0] = IRP_MN_SET_POWER;
323
324 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
327 minorFunctions,
328 RTL_NUMBER_OF(minorFunctions));
329 if (!NT_SUCCESS(status))
330 {
331 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
332 "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_POWER failed, "
333 "status: 0x%X\n", status));
334
335 goto Exit;
336 }
337
338 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
341 NULL,
342 0);
343 if (!NT_SUCCESS(status))
344 {
345 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
346 "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_FLUSH_BUFFERS failed, "
347 "status: 0x%X\n", status));
348
349 goto Exit;
350 }
351
352 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
355 NULL,
356 0);
357 if (!NT_SUCCESS(status))
358 {
359 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
360 "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_SHUTDOWN failed, "
361 "status: 0x%X\n", status));
362
363 goto Exit;
364 }
365 }
366
367 // 4. Set attributes to create Request Context area.
368 {
369 //Reuse this structure.
373
374 WdfDeviceInitSetRequestAttributes(DeviceInit,
375 &attributes);
376 }
377
378 // 5. Register FileObject related callbacks
379 {
380 // Add FILE_OBJECT_EXTENSION as the context to the file object.
382
383 // Set Entry points for Create and Close..
384
385 // The framework doesn't sync the file create requests with pnp/power
386 // state. Re-direct all the file create requests to a dedicated
387 // queue, which will be purged manually during removal.
388 WDF_FILEOBJECT_CONFIG_INIT(&fileObjectConfig,
389 NULL, //CreateQueueEvtIoDefault,
391 WDF_NO_EVENT_CALLBACK); // No callback for Cleanup
392
394
395 // Since we are registering file events and fowarding create request
396 // ourself, we must also set AutoForwardCleanupClose so that cleanup
397 // and close can also get forwarded.
398 fileObjectConfig.AutoForwardCleanupClose = WdfTrue;
401
402 // Indicate that file object is optional.
404
405 WdfDeviceInitSetFileObjectConfig(DeviceInit,
406 &fileObjectConfig,
407 &attributes);
408 }
409
410 // 6. Initialize device-wide attributes
411 {
412 // Declare ourselves as NOT owning power policy.
413 // The power policy owner in storage stack is port driver.
414 WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE);
415
416 // Set other DeviceInit attributes.
417 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
418 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CD_ROM);
419 WdfDeviceInitSetCharacteristics(DeviceInit, FILE_REMOVABLE_MEDIA, FALSE);
420 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
421 WdfDeviceInitSetPowerPageable(DeviceInit);
422
423 // We require the framework to acquire a remove lock before delivering all IRP types
424 WDF_REMOVE_LOCK_OPTIONS_INIT(&removeLockOptions,
426
427 WdfDeviceInitSetRemoveLockOptions(DeviceInit, &removeLockOptions);
428
429 // save the PDO for later reference
430 lowerPdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
431
434
435 // We have a parallel queue, so WdfSynchronizationScopeNone is our only choice.
438
439 // Provide a cleanup callback which will release memory allocated with ExAllocatePool*
441 }
442
443 // 7. Now, the device can be created.
444 {
445 wideDeviceName = ExAllocatePoolWithTag(NonPagedPoolNx,
446 64 * sizeof(WCHAR),
448
449 if (wideDeviceName == NULL)
450 {
452 goto Exit;
453 }
454
455 // Find the lowest device number currently available.
456 do {
458 64,
459 L"\\Device\\CdRom%d",
460 deviceNumber);
461
462 if (!NT_SUCCESS(status)) {
463 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
464 "DriverEvtDeviceAdd: Format device name failed with error: 0x%X\n", status));
465
466 goto Exit;
467 }
468
469 RtlInitUnicodeString(&unicodeDeviceName, wideDeviceName);
470
471 status = WdfDeviceInitAssignName(DeviceInit, &unicodeDeviceName);
472 if (!NT_SUCCESS(status))
473 {
474 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
475 "DriverEvtDeviceAdd: WdfDeviceInitAssignName() failed with error: 0x%X\n", status));
476
477 goto Exit;
478 }
479
480 status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
481
482 deviceNumber++;
483
485
486 // When this loop exits the count is inflated by one - fix that.
487 deviceNumber--;
488
489 if (!NT_SUCCESS(status))
490 {
491 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
492 "DriverEvtDeviceAdd: Can not create a new device, status: 0x%X\n",
493 status));
494
495 goto Exit;
496 }
497 }
498
499 // 8. Fill up basic Device Extension settings and create a remote I/O target for the next-lower driver.
500 // The reason why we do not use the local I/O target is because we want to be able to close the
501 // I/O target on surprise removal.
502 {
503 deviceExtension = DeviceGetExtension(device);
504
505 deviceExtension->Version = 0x01;
506 deviceExtension->Size = sizeof(CDROM_DEVICE_EXTENSION);
507
508 deviceExtension->DeviceObject = WdfDeviceWdmGetDeviceObject(device);
509 deviceExtension->Device = device;
510 deviceExtension->DriverExtension = driverExtension;
511
512 deviceExtension->LowerPdo = lowerPdo;
513
514 deviceExtension->DeviceType = FILE_DEVICE_CD_ROM; //Always a FILE_DEVICE_CD_ROM for all device it manages.
515 deviceExtension->DeviceName = unicodeDeviceName;
516
517 deviceExtension->DeviceNumber = deviceNumber;
518 }
519 {
520 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
521 attributes.ParentObject = deviceExtension->Device;
522
523 status = WdfIoTargetCreate(deviceExtension->Device,
524 &attributes,
525 &deviceExtension->IoTarget);
526
527 if (!NT_SUCCESS(status))
528 {
529 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
530 "DriverEvtDeviceAdd: Can not create a remote I/O target object, status: 0x%X\n",
531 status));
532 goto Exit;
533 }
534
536 WdfDeviceWdmGetAttachedDevice(deviceExtension->Device));
537
538 status = WdfIoTargetOpen(deviceExtension->IoTarget,
539 &ioTargetOpenParams);
540 if (!NT_SUCCESS(status))
541 {
542 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
543 "DriverEvtDeviceAdd: Can not open a remote I/O target for the next-lower device, status: 0x%X\n",
544 status));
545
546 WdfObjectDelete(deviceExtension->IoTarget);
547 deviceExtension->IoTarget = NULL;
548
549 goto Exit;
550 }
551 }
552
553 // 9. Claim the device, so that port driver will only accept the commands from CDROM.SYS for this device.
554 // NOTE: The I/O should be issued after the device is started. But we would like to claim
555 // the device as soon as possible, so this legacy behavior is kept.
556 status = DeviceClaimRelease(deviceExtension, FALSE);
557
558 if (!NT_SUCCESS(status))
559 {
560 // Someone already had this device - we're in trouble
561 goto Exit;
562 }
563 else
564 {
565 deviceClaimed = TRUE;
566 }
567
568 //
569 // CDROM Queueing Structure
570 //
571 // a. EvtIoInCallerContext (prior to queueing):
572 // This event will be used ONLY to forward down IOCTLs that come in at PASSIVE LEVEL
573 // and need to be forwarded down the stack in the original context.
574 //
575 // b. Main input queue: serial queue for main dispatching
576 // This queue will be used to do all dispatching of requests to serialize
577 // access to the device. Any request that was previously completed in
578 // the Dispatch routines will be completed here. Anything requiring device
579 // I/O will be sent through the serial I/O queue.
580 //
581 // 10. Set up IO queues after device being created.
582 //
583 {
586
587 queueConfig.PowerManaged = WdfFalse;
588
589#pragma prefast(push)
590#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")
591#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")
594#pragma prefast(pop)
595
598
599 status = WdfIoQueueCreate(device,
600 &queueConfig,
602 &(deviceExtension->SerialIOQueue));
603 if (!NT_SUCCESS(status))
604 {
605 goto Exit;
606 }
607
608 // this queue is dedicated for file create requests.
610
611 queueConfig.PowerManaged = WdfFalse;
613
614 //Reuse this structure.
617
620
621 status = WdfIoQueueCreate(device,
622 &queueConfig,
623 &attributes,
624 &(deviceExtension->CreateQueue));
625
626 if (!NT_SUCCESS(status))
627 {
628 goto Exit;
629 }
630
631 // Configure the device to use driver created queue for dispatching create.
632 status = WdfDeviceConfigureRequestDispatching(device,
633 deviceExtension->CreateQueue,
635
636 if (!NT_SUCCESS(status))
637 {
638 goto Exit;
639 }
640 }
641
642 // 11. Set the alignment requirements for the device based on the host adapter requirements.
643 //
644 // NOTE: this should have been set when device is attached on device stack,
645 // by keeping this legacy code, we could avoid issue that this value was not correctly set at that time.
646 if (deviceExtension->LowerPdo->AlignmentRequirement > deviceExtension->DeviceObject->AlignmentRequirement)
647 {
648 WdfDeviceSetAlignmentRequirement(deviceExtension->Device,
649 deviceExtension->LowerPdo->AlignmentRequirement);
650 }
651
652 // 12. Initialization of miscellaneous internal properties
653
654 // CDROMs are not partitionable so starting offset is 0.
655 deviceExtension->StartingOffset.LowPart = 0;
656 deviceExtension->StartingOffset.HighPart = 0;
657
658 // Set the default geometry for the cdrom to match what NT 4 used.
659 // these values will be used to compute the cylinder count rather
660 // than using it's NT 5.0 defaults.
661 deviceExtension->DiskGeometry.MediaType = RemovableMedia;
662 deviceExtension->DiskGeometry.TracksPerCylinder = 0x40;
663 deviceExtension->DiskGeometry.SectorsPerTrack = 0x20;
664
666
667 // Clear the SrbFlags and disable synchronous transfers
669
670 // Set timeout value in seconds.
671 deviceExtension->TimeOutValue = DeviceGetTimeOutValueFromRegistry();
672 if ((deviceExtension->TimeOutValue > 30 * 60) || // longer than 30 minutes
673 (deviceExtension->TimeOutValue == 0))
674 {
675 deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
676 }
677
678 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
679 "DriverEvtDeviceAdd: device timeout is set to %x seconds",
680 deviceExtension->TimeOutValue
681 ));
682
683#if (NTDDI_VERSION >= NTDDI_WIN8)
684 deviceExtension->IsVolumeOnlinePending = TRUE;
685
687
688 queueConfig.PowerManaged = WdfFalse;
689
690 status = WdfIoQueueCreate(device,
691 &queueConfig,
693 &deviceExtension->ManualVolumeReadyQueue);
694
695 if (!NT_SUCCESS(status))
696 {
697 goto Exit;
698 }
699#endif
700
701 // 13. Initialize the stuff related to media locking
702 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
703 attributes.ParentObject = deviceExtension->Device;
704 status = WdfWaitLockCreate(&attributes,
705 &deviceExtension->EjectSynchronizationLock);
706
707 deviceExtension->LockCount = 0;
708
709 // 14. Initialize context structures needed for asynchronous release queue and power requests
710
711 if (NT_SUCCESS(status))
712 {
713 status = DeviceInitReleaseQueueContext(deviceExtension);
714 }
715
716 if (NT_SUCCESS(status))
717 {
718 status = DeviceInitPowerContext(deviceExtension);
719 }
720
721 // 15. Create external access points other than device name.
722 if (NT_SUCCESS(status))
723 {
724 status = DeviceCreateWellKnownName(deviceExtension);
725 }
726
727 // 16. Query session id from the PDO.
728 if (NT_SUCCESS(status))
729 {
730 status = IoGetDevicePropertyData(deviceExtension->LowerPdo,
731 &DEVPKEY_Device_SessionId,
732 0,
733 0,
734 sizeof(devicePropertySessionId),
735 &devicePropertySessionId,
736 &devicePropertySize,
737 &devicePropertyType);
738
739 if (!NT_SUCCESS(status))
740 {
741 // The device is global.
742 devicePropertySessionId = INVALID_SESSION;
744 }
745 }
746
747 // 17. Register interfaces for this device.
748 if (NT_SUCCESS(status))
749 {
750 status = DeviceRegisterInterface(deviceExtension, CdRomDeviceInterface);
751 }
752
753 if (NT_SUCCESS(status))
754 {
755 // If this is a per-session DO, don't register for mount interface so that
756 // mountmgr will not automatically assign a drive letter.
757 if (devicePropertySessionId == INVALID_SESSION)
758 {
759 status = DeviceRegisterInterface(deviceExtension, MountedDeviceInterface);
760 }
761 }
762
763 // 18. Initialize the shutdown/flush lock
764 if (NT_SUCCESS(status))
765 {
766 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
767 attributes.ParentObject = deviceExtension->Device;
768
769 status = WdfWaitLockCreate(&attributes, &deviceExtension->ShutdownFlushWaitLock);
770 if (!NT_SUCCESS(status))
771 {
772 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
773 "DriverEvtDeviceAdd: Cannot create shutdown/flush waitlock, status: 0x%X\n",
774 status));
775 }
776 }
777
778 // 19. Initialize the work item that is used to initiate asynchronous reads/writes
779 if (NT_SUCCESS(status))
780 {
781 WDF_WORKITEM_CONFIG workItemConfig;
782 WDF_OBJECT_ATTRIBUTES workItemAttributes;
783
784 WDF_WORKITEM_CONFIG_INIT(&workItemConfig,
786 );
787
788 WDF_OBJECT_ATTRIBUTES_INIT(&workItemAttributes);
789 workItemAttributes.ParentObject = deviceExtension->Device;
790
791 status = WdfWorkItemCreate(&workItemConfig,
792 &workItemAttributes,
793 &deviceExtension->ReadWriteWorkItem
794 );
795
796 if (!NT_SUCCESS(status))
797 {
798 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT,
799 "DriverEvtDeviceAdd: Cannot create read/write work item, status: 0x%X\n",
800 status));
801 }
802 }
803
804 // 20. Initialize the work item that is used to process most IOCTLs at PASSIVE_LEVEL.
805 if (NT_SUCCESS(status))
806 {
807 WDF_WORKITEM_CONFIG workItemConfig;
808 WDF_OBJECT_ATTRIBUTES workItemAttributes;
809
810 WDF_WORKITEM_CONFIG_INIT(&workItemConfig,
812 );
813
814 WDF_OBJECT_ATTRIBUTES_INIT(&workItemAttributes);
815 workItemAttributes.ParentObject = deviceExtension->Device;
816
817 status = WdfWorkItemCreate(&workItemConfig,
818 &workItemAttributes,
819 &deviceExtension->IoctlWorkItem
820 );
821
822 if (!NT_SUCCESS(status))
823 {
824 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT,
825 "DriverEvtDeviceAdd: Cannot create ioctl work item, status: 0x%X\n",
826 status));
827 }
828 }
829
830
831Exit:
832
833 if (!NT_SUCCESS(status))
834 {
835 FREE_POOL(wideDeviceName);
836
837 if (deviceExtension != NULL)
838 {
839 RtlInitUnicodeString(&deviceExtension->DeviceName, NULL);
840 }
841
842 // Release the device with the port driver, if it was claimed
843 if ((deviceExtension != NULL) && deviceClaimed)
844 {
845 DeviceClaimRelease(deviceExtension, TRUE);
846 }
847 deviceClaimed = FALSE;
848 }
849
850 return status;
851}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
VOID NTAPI SequentialQueueEvtIoReadWrite(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length)
Definition: cdrom.c:3215
EVT_WDF_IO_QUEUE_IO_DEFAULT CreateQueueEvtIoDefault
Definition: cdrom.h:886
#define WRITE_RETRY_DELAY_DVD_1x
Definition: cdrom.h:118
EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessSetPower
Definition: cdrom.h:910
EVT_WDF_WORKITEM IoctlWorkItemRoutine
Definition: cdrom.h:1616
EVT_WDF_WORKITEM ReadWriteWorkItemRoutine
Definition: cdrom.h:1618
EVT_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP DeviceEvtSelfManagedIoCleanup
Definition: cdrom.h:876
EVT_WDF_FILE_CLOSE DeviceEvtFileClose
Definition: cdrom.h:870
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SequentialQueueEvtIoDeviceControl
Definition: cdrom.h:900
EVT_WDF_OBJECT_CONTEXT_CLEANUP DeviceEvtCleanup
Definition: cdrom.h:868
EVT_WDF_DEVICE_D0_ENTRY DeviceEvtD0Entry
Definition: cdrom.h:878
EVT_WDF_OBJECT_CONTEXT_CLEANUP RequestEvtCleanup
Definition: cdrom.h:906
EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT DeviceEvtSelfManagedIoInit
Definition: cdrom.h:874
#define SCSI_CDROM_TIMEOUT
Definition: cdrom.h:680
EVT_WDF_IO_IN_CALLER_CONTEXT DeviceEvtIoInCallerContext
Definition: cdrom.h:872
EVT_WDF_DEVICE_SURPRISE_REMOVAL DeviceEvtSurpriseRemoval
Definition: cdrom.h:882
EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE SequentialQueueEvtCanceledOnQueue
Definition: cdrom.h:902
struct _CDROM_DEVICE_EXTENSION CDROM_DEVICE_EXTENSION
Definition: cdrom.h:216
#define CDROM_TAG_STRINGS
Definition: cdrom.h:743
EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessShutdownFlush
Definition: cdrom.h:908
@ CdRomDeviceInterface
Definition: cdrom.h:768
@ MountedDeviceInterface
Definition: cdrom.h:769
EVT_WDF_DEVICE_D0_EXIT DeviceEvtD0Exit
Definition: cdrom.h:880
#define INVALID_SESSION
Definition: cdromp.h:381
ULONG DEVPROPTYPE
Definition: devpropdef.h:24
#define DEVPROP_TYPE_EMPTY
Definition: devpropdef.h:29
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
@ RemovableMedia
Definition: ntdddisk.h:387
_Null_terminated_ wchar_t * NTSTRSAFE_PWSTR
Definition: ntstrsafe.h:58
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
#define L(x)
Definition: ntvdm.h:50
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:108
static void Exit(void)
Definition: sock.c:1330
LONGLONG ReadWriteRetryDelay100nsUnits
Definition: cdrom.h:384
WDFWAITLOCK EjectSynchronizationLock
Definition: cdrom.h:559
WDFWORKITEM IoctlWorkItem
Definition: cdrom.h:613
WDFQUEUE ManualVolumeReadyQueue
Definition: cdrom.h:591
WDFWORKITEM ReadWriteWorkItem
Definition: cdrom.h:608
LARGE_INTEGER StartingOffset
Definition: cdrom.h:533
DEVICE_TYPE DeviceType
Definition: cdrom.h:499
DISK_GEOMETRY DiskGeometry
Definition: cdrom.h:524
WDFWAITLOCK ShutdownFlushWaitLock
Definition: cdrom.h:595
BOOLEAN IsVolumeOnlinePending
Definition: cdrom.h:590
WDFDEVICE Device
Definition: cdrom.h:473
PCDROM_DRIVER_EXTENSION DriverExtension
Definition: cdrom.h:490
ULONG AlignmentRequirement
Definition: env_spec_w32.h:420
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
WDF_TRI_STATE AutoForwardCleanupClose
Definition: wdfdevice.h:612
WDF_FILEOBJECT_CLASS FileObjectClass
Definition: wdfdevice.h:619
PFN_WDF_IO_QUEUE_IO_DEFAULT EvtIoDefault
Definition: wdfio.h:399
PFN_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl
Definition: wdfio.h:405
WDF_TRI_STATE PowerManaged
Definition: wdfio.h:393
PFN_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE EvtIoCanceledOnQueue
Definition: wdfio.h:413
PFN_WDF_IO_QUEUE_IO_READ EvtIoRead
Definition: wdfio.h:401
PFN_WDF_IO_QUEUE_IO_WRITE EvtIoWrite
Definition: wdfio.h:403
WDFOBJECT ParentObject
Definition: wdfobject.h:130
WDF_EXECUTION_LEVEL ExecutionLevel
Definition: wdfobject.h:120
WDF_SYNCHRONIZATION_SCOPE SynchronizationScope
Definition: wdfobject.h:125
PFN_WDF_DEVICE_D0_ENTRY EvtDeviceD0Entry
Definition: wdfdevice.h:1164
PFN_WDF_DEVICE_SELF_MANAGED_IO_INIT EvtDeviceSelfManagedIoInit
Definition: wdfdevice.h:1172
PFN_WDF_DEVICE_D0_EXIT EvtDeviceD0Exit
Definition: wdfdevice.h:1166
PFN_WDF_DEVICE_SURPRISE_REMOVAL EvtDeviceSurpriseRemoval
Definition: wdfdevice.h:1175
PFN_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP EvtDeviceSelfManagedIoCleanup
Definition: wdfdevice.h:1170
uint16_t * PWCHAR
Definition: typedefs.h:56
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
ULONG LowPart
Definition: typedefs.h:106
_In_ PWDFDEVICE_INIT DeviceInit
Definition: wdfcontrol.h:113
@ WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO
Definition: wdfdevice.h:1639
FORCEINLINE VOID WDF_PNPPOWER_EVENT_CALLBACKS_INIT(_Out_ PWDF_PNPPOWER_EVENT_CALLBACKS Callbacks)
Definition: wdfdevice.h:1214
@ WdfRequestTypeCreate
Definition: wdfdevice.h:503
@ WdfFileObjectWdfCannotUseFsContexts
Definition: wdfdevice.h:463
@ WdfFileObjectCanBeOptional
Definition: wdfdevice.h:464
@ WdfDeviceIoDirect
Definition: wdfdevice.h:453
FORCEINLINE VOID WDF_REMOVE_LOCK_OPTIONS_INIT(_Out_ PWDF_REMOVE_LOCK_OPTIONS RemoveLockOptions, _In_ ULONG Flags)
Definition: wdfdevice.h:1661
FORCEINLINE VOID WDF_FILEOBJECT_CONFIG_INIT(_Out_ PWDF_FILEOBJECT_CONFIG FileEventCallbacks, _In_opt_ PFN_WDF_DEVICE_FILE_CREATE EvtDeviceFileCreate, _In_opt_ PFN_WDF_FILE_CLOSE EvtFileClose, _In_opt_ PFN_WDF_FILE_CLEANUP EvtFileCleanup)
Definition: wdfdevice.h:625
FORCEINLINE VOID WDF_IO_QUEUE_CONFIG_INIT(_Out_ PWDF_IO_QUEUE_CONFIG Config, _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType)
Definition: wdfio.h:426
FORCEINLINE VOID WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(_Out_ PWDF_IO_QUEUE_CONFIG Config, _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType)
Definition: wdfio.h:443
@ WdfIoQueueDispatchSequential
Definition: wdfio.h:78
@ WdfIoQueueDispatchParallel
Definition: wdfio.h:79
@ WdfIoQueueDispatchManual
Definition: wdfio.h:80
FORCEINLINE VOID WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(_Out_ PWDF_IO_TARGET_OPEN_PARAMS Params, _In_ PDEVICE_OBJECT DeviceObject)
Definition: wdfiotarget.h:287
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
@ WdfSynchronizationScopeNone
Definition: wdfobject.h:66
@ WdfExecutionLevelPassive
Definition: wdfobject.h:54
@ WdfExecutionLevelDispatch
Definition: wdfobject.h:55
@ WdfTrue
Definition: wdftypes.h:88
@ WdfFalse
Definition: wdftypes.h:87
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
#define IRP_MN_SET_POWER
#define IRP_MJ_FLUSH_BUFFERS
#define IRP_MJ_SHUTDOWN
#define IRP_MJ_POWER
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ IoctlWorkItemRoutine()

VOID NTAPI IoctlWorkItemRoutine ( _In_ WDFWORKITEM  WorkItem)

Definition at line 3503 of file cdrom.c.

3523{
3524 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
3525
3526 PAGED_CODE ();
3527
3528 deviceExtension = WdfObjectGetTypedContext(WdfWorkItemGetParentObject(WorkItem), CDROM_DEVICE_EXTENSION);
3529
3530 if (DeviceIsMmcUpdateRequired(deviceExtension->Device))
3531 {
3532 // Issue command to update the drive capabilities.
3533 // The failure of MMC update is not considered critical,
3534 // so that we'll continue to process I/O even MMC update fails.
3535 DeviceUpdateMmcCapabilities(deviceExtension->Device);
3536 }
3537
3538 RequestProcessSerializedIoctl(deviceExtension, deviceExtension->IoctlWorkItemContext.OriginalRequest);
3539}
BOOLEAN DeviceIsMmcUpdateRequired(_In_ WDFDEVICE Device)
Definition: cdrom.c:4180
CDROM_IOCTL_CONTEXT IoctlWorkItemContext
Definition: cdrom.h:614
WDFREQUEST OriginalRequest
Definition: cdrom.h:328
#define WdfObjectGetTypedContext(handle, type)
Definition: wdfobject.h:404
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115

◆ NormalizeIoctl()

VOID NormalizeIoctl ( _Inout_ PWDF_REQUEST_PARAMETERS  requestParameters)

Definition at line 1514 of file cdrom.c.

1517{
1518 ULONG ioctlCode;
1519 ULONG baseCode;
1520 ULONG functionCode;
1521
1522 // if this is a class driver ioctl then we need to change the base code
1523 // to IOCTL_STORAGE_BASE so that the switch statement can handle it.
1524 //
1525 // WARNING - currently the scsi class ioctl function codes are between
1526 // 0x200 & 0x300. this routine depends on that fact
1527 ioctlCode = requestParameters->Parameters.DeviceIoControl.IoControlCode;
1528 baseCode = DEVICE_TYPE_FROM_CTL_CODE(ioctlCode);
1529 functionCode = (ioctlCode & (~0xffffc003)) >> 2;
1530
1531 if ((baseCode == IOCTL_SCSI_BASE) ||
1532 (baseCode == IOCTL_DISK_BASE) ||
1533 (baseCode == IOCTL_TAPE_BASE) ||
1534 (baseCode == IOCTL_DVD_BASE) ||
1535 (baseCode == IOCTL_CDROM_BASE))
1536 //IOCTL_STORAGE_BASE does not need to be converted.
1537 {
1538 if((functionCode >= 0x200) && (functionCode <= 0x300))
1539 {
1540 ioctlCode = (ioctlCode & 0x0000ffff) | CTL_CODE(IOCTL_STORAGE_BASE, 0, 0, 0);
1541
1542 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
1543 "IOCTL code recalibrate, New ioctl code is %lx\n",
1544 ioctlCode));
1545
1546 // Set the code into request parameters, then "requestParameters" needs to be used for dispatch functions.
1547 requestParameters->Parameters.DeviceIoControl.IoControlCode = ioctlCode;
1548 }
1549 }
1550}
#define CTL_CODE(DeviceType, Function, Method, Access)
Definition: nt_native.h:586
#define IOCTL_DISK_BASE
Definition: ntdddisk.h:44
#define IOCTL_STORAGE_BASE
Definition: ntddstor.h:96
#define IOCTL_TAPE_BASE
Definition: ntddtape.h:35
#define IOCTL_DVD_BASE
Definition: ntddcdvd.h:32
#define DEVICE_TYPE_FROM_CTL_CODE(c)
Definition: winioctl.h:205
#define IOCTL_SCSI_BASE
Definition: scsi_port.h:37
#define IOCTL_CDROM_BASE
Definition: vcdcli.c:21

Referenced by DeviceEvtIoInCallerContext().

◆ ReadWriteWorkItemRoutine()

VOID NTAPI ReadWriteWorkItemRoutine ( _In_ WDFWORKITEM  WorkItem)

Definition at line 3345 of file cdrom.c.

3365{
3366 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
3367 WDFREQUEST readWriteRequest = NULL;
3368 WDF_REQUEST_PARAMETERS readWriteRequestParameters;
3370
3371 PAGED_CODE ();
3372
3373 deviceExtension = WdfObjectGetTypedContext(WdfWorkItemGetParentObject(WorkItem), CDROM_DEVICE_EXTENSION);
3374 readWriteRequest = deviceExtension->ReadWriteWorkItemContext.OriginalRequest;
3376
3377 WDF_REQUEST_PARAMETERS_INIT(&readWriteRequestParameters);
3378 WdfRequestGetParameters(readWriteRequest, &readWriteRequestParameters);
3379
3380 if (DeviceIsMmcUpdateRequired(deviceExtension->Device))
3381 {
3382 // Issue command to update the drive capabilities.
3383 // The failure of MMC update is not considered critical, so we'll
3384 // continue to process the request even if MMC update fails.
3385 (VOID) DeviceUpdateMmcCapabilities(deviceExtension->Device);
3386 }
3387
3388 // Now verify and process the request
3389 if (NT_SUCCESS(status))
3390 {
3391 status = RequestValidateReadWrite(deviceExtension, readWriteRequest, readWriteRequestParameters);
3392 }
3393 if (NT_SUCCESS(status))
3394 {
3395 status = RequestHandleReadWrite(deviceExtension, readWriteRequest, readWriteRequestParameters);
3396 }
3397
3398 // Complete the request immediately on failure
3399 if (!NT_SUCCESS(status))
3400 {
3401 RequestCompletion(deviceExtension, readWriteRequest, status, 0);
3402 }
3403}
#define VOID
Definition: acefi.h:82
NTSTATUS RequestValidateReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: ioctl.c:6117
NTSTATUS RequestHandleReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: ioctl.c:6353
CDROM_READ_WRITE_CONTEXT ReadWriteWorkItemContext
Definition: cdrom.h:609
WDFREQUEST OriginalRequest
Definition: cdrom.h:335

◆ RequestDispatchProcessDirectly()

BOOLEAN RequestDispatchProcessDirectly ( _In_ WDFDEVICE  Device,
_In_ WDFREQUEST  Request,
_In_ WDF_REQUEST_PARAMETERS  RequestParameters 
)

Definition at line 1694 of file cdrom.c.

1717{
1720 size_t dataLength = 0;
1721
1722 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
1723 ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
1724
1725 switch (ioctlCode)
1726 {
1727
1729 {
1731
1732 processed = TRUE;
1733 break; // complete the irp
1734 }
1735
1737 {
1739
1740 processed = TRUE;
1741 break; // complete the irp
1742 }
1743
1745 {
1747
1748 processed = TRUE;
1749 break; // complete the irp
1750 }
1751
1753 {
1755
1756 processed = TRUE;
1757 break; // complete the irp
1758 }
1759
1761 {
1763
1764 processed = TRUE;
1765 break; // complete the irp
1766 }
1767
1769 {
1771
1772 processed = TRUE;
1773 break; // complete the irp
1774 }
1775
1777 {
1779
1780 processed = TRUE;
1781 break; // complete the irp
1782 }
1783
1785 {
1787
1788 processed = TRUE;
1789 break; // complete the irp
1790 }
1791
1793 {
1794 status = RequestHandleEventNotification(deviceExtension, Request, &RequestParameters, &dataLength);
1795
1796 processed = TRUE;
1797 break; // complete the irp
1798 }
1799
1800#if (NTDDI_VERSION >= NTDDI_WIN8)
1802 {
1803 //
1804 // Mount manager and volume manager will
1805 // follow this online with a post online
1806 // but other callers may not. In those
1807 // cases, we process this request right
1808 // away. We approximate that these other
1809 // callers are from user mode
1810 //
1811
1812 if (WdfRequestGetRequestorMode(Request) == KernelMode)
1813 {
1814 processed = TRUE;
1815 }
1816 break;
1817 }
1818#endif
1819
1820 default:
1821 {
1822 processed = FALSE;
1823 break;
1824 }
1825
1826 } //end of switch (ioctlCode)
1827
1828 if (processed)
1829 {
1830 UCHAR currentStackLocationFlags = 0;
1831 currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
1832
1833 if ((status == STATUS_VERIFY_REQUIRED) &&
1834 (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME))
1835 {
1836 // If the status is verified required and this request
1837 // should bypass verify required then retry the request.
1839 UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
1840
1842 }
1843 else
1844 {
1845 // Complete the request after processing it.
1846 RequestCompletion(deviceExtension, Request, status, dataLength);
1847 }
1848 }
1849
1850 return processed;
1851}
FORCEINLINE UCHAR RequestGetCurrentStackLocationFlags(_In_ WDFREQUEST Request)
Definition: cdrom.h:1554
#define IOCTL_STORAGE_GET_MEDIA_TYPES_EX
Definition: cdrw_usr.h:190
NTSTATUS RequestHandleGetHotPlugInfo(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5337
NTSTATUS RequestHandleGetMediaTypeEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _Out_ size_t *DataLength)
Definition: ioctl.c:336
NTSTATUS RequestHandleMountQuerySuggestedLinkName(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:4088
NTSTATUS RequestHandleGetInquiryData(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:270
NTSTATUS RequestHandleSetHotPlugInfo(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5392
NTSTATUS RequestHandleGetDeviceNumber(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5280
NTSTATUS RequestHandleMountQueryUniqueId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3939
NTSTATUS RequestHandleMountQueryDeviceName(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:4015
_In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_PARAMETERS RequestParameters
Definition: ioctl.h:138
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
#define IOCTL_STORAGE_GET_HOTPLUG_INFO
Definition: imports.h:238
#define KernelMode
Definition: asm.h:34
#define IOCTL_CDROM_GET_INQUIRY_DATA
Definition: ntddcdrm.h:91
#define IOCTL_STORAGE_SET_HOTPLUG_INFO
Definition: ntddstor.h:157
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_VOLUME_ONLINE
Definition: ntddvol.h:62
ULONG dataLength
Definition: scsi.h:3751
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823

Referenced by DeviceEvtIoInCallerContext(), and RequestDispatchProcessDirectly().

◆ RequestDispatchSpecialIoctls()

BOOLEAN RequestDispatchSpecialIoctls ( _In_ WDFDEVICE  Device,
_In_ WDFREQUEST  Request,
_In_ WDF_REQUEST_PARAMETERS  RequestParameters 
)

Definition at line 2849 of file cdrom.c.

2872{
2875 size_t dataLength = 0;
2876 BOOLEAN requestCompleted = FALSE;
2877
2878 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2879 PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
2880 ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
2881
2882 switch (ioctlCode)
2883 {
2888 {
2889 // SPTI is considered special case as we need to set the MinorFunction before pass to low level.
2890
2891#if defined (_WIN64)
2892 if (WdfRequestIsFrom32BitProcess(Request))
2893 {
2894 if ((ioctlCode == IOCTL_SCSI_PASS_THROUGH) || (ioctlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT))
2895 {
2896 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32))
2897 {
2899 }
2900 }
2901 else
2902 {
2903 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32_EX))
2904 {
2906 }
2907 }
2908 }
2909 else
2910#endif
2911 {
2912 if ((ioctlCode == IOCTL_SCSI_PASS_THROUGH) || (ioctlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT))
2913 {
2914 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH))
2915 {
2917 }
2918 }
2919 else
2920 {
2921 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH_EX))
2922 {
2924 }
2925 }
2926 }
2927
2928 if (!NT_SUCCESS(status))
2929 {
2930 // validation failed.
2931 RequestCompletion(deviceExtension, Request, status, dataLength);
2932 }
2933 else
2934 {
2935 // keep the request in serialized manner and stay in user's context.
2936 status = RequestSetContextFields(Request, RequestHandleScsiPassThrough);
2937
2938 if (NT_SUCCESS(status))
2939 {
2941 }
2942 else
2943 {
2944 RequestCompletion(deviceExtension, Request, status, 0);
2945 }
2946 }
2947
2948 requestCompleted = TRUE;
2949 processed = TRUE;
2950 break;
2951 }
2952
2954 {
2956 {
2958 }
2959 else
2960 {
2961 PSTORAGE_PROPERTY_QUERY inputBuffer = NULL;
2962
2963 status = WdfRequestRetrieveInputBuffer(Request,
2965 &inputBuffer,
2966 NULL);
2967
2968 if (NT_SUCCESS(status))
2969 {
2970 if (!EXCLUSIVE_MODE(cdData) || // not locked
2971 EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)) || // request is from lock owner
2972 (inputBuffer->QueryType == PropertyExistsQuery)) // request not access device
2973 {
2974 if (inputBuffer->PropertyId == StorageDeviceUniqueIdProperty)
2975 {
2976 // previously handled in classpnp
2977 // keep the request in serialized manner and stay in user's context.
2979
2980 if (NT_SUCCESS(status))
2981 {
2983 // remeber that the request has been completed.
2984 requestCompleted = TRUE;
2985 }
2986 }
2987 else if (inputBuffer->PropertyId == StorageDeviceWriteCacheProperty)
2988 {
2989 // previously handled in classpnp
2990 // keep the request in serialized manner and stay in user's context.
2992
2993 if (NT_SUCCESS(status))
2994 {
2996 // remeber that the request has been completed.
2997 requestCompleted = TRUE;
2998 }
2999 }
3000 else
3001 {
3002 // Pass to port driver for handling
3004
3005 // remeber that the request has been completed.
3006 requestCompleted = TRUE;
3007 }
3008 }
3009 else
3010 {
3011 // If cached data exists, return cached data. Otherwise, fail the request.
3012 if ((inputBuffer->QueryType == PropertyStandardQuery) &&
3013 ((inputBuffer->PropertyId == StorageDeviceProperty) || (inputBuffer->PropertyId == StorageAdapterProperty)) )
3014 {
3016 }
3017 else
3018 {
3020 }
3021 }
3022 }
3023 }
3024
3025 processed = TRUE;
3026 break;
3027 }
3028
3029 // this IOCTL is a fake one, used for MCN process sync-ed with serial queue.
3031 {
3032 PIRP irp = WdfRequestWdmGetIrp(Request);
3033
3034 if ((deviceExtension->MediaChangeDetectionInfo != NULL) &&
3035 (irp == deviceExtension->MediaChangeDetectionInfo->MediaChangeSyncIrp) &&
3036 (WdfRequestGetRequestorMode(Request) == KernelMode) &&
3040 {
3041 // This is the requset we use to sync Media Change Detection with sequential queue.
3042 status = WdfDeviceEnqueueRequest(Device, Request);
3043
3044 if (!NT_SUCCESS(status))
3045 {
3046 RequestCompletion(deviceExtension, Request, status, dataLength);
3047 }
3048
3049 requestCompleted = TRUE;
3050 processed = TRUE;
3051 }
3052 else
3053 {
3054 // process as an unknown request.
3055 processed = FALSE;
3056 }
3057 break;
3058 }
3059
3060 default:
3061 {
3062 processed = FALSE;
3063 break;
3064 }
3065 } //end of switch (ioctlCode)
3066
3067 if (processed && !requestCompleted)
3068 {
3069 UCHAR currentStackLocationFlags = 0;
3070 currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
3071
3072 if ((status == STATUS_VERIFY_REQUIRED) &&
3073 (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME))
3074 {
3075 // If the status is verified required and this request
3076 // should bypass verify required then retry the request.
3078 UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
3079
3081 }
3082 else
3083 {
3084 RequestCompletion(deviceExtension, Request, status, dataLength);
3085 }
3086 }
3087
3088 return processed;
3089}
VOID RequestSetupMcnSyncIrp(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: autorun.c:2749
NTSTATUS RequestSynchronizeProcessWithSerialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: cdrom.c:3893
NTSTATUS RequestSetContextFields(_In_ WDFREQUEST Request, _In_ PSYNC_HANDLER Handler)
Definition: common.c:2748
NTSTATUS RequestHandleQueryPropertyWriteCache(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: ioctl.c:2974
NTSTATUS RequestHandleQueryPropertyDeviceUniqueId(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: ioctl.c:2799
NTSTATUS RequestHandleQueryPropertyRetrieveCachedData(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2628
FxIrp * irp
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
@ StorageDeviceUniqueIdProperty
Definition: ntddstor.h:515
@ StorageDeviceWriteCacheProperty
Definition: ntddstor.h:516
@ StorageAdapterProperty
Definition: ntddstor.h:513
@ StorageDeviceProperty
Definition: ntddstor.h:512
@ PropertyExistsQuery
Definition: ntddstor.h:506
@ PropertyStandardQuery
Definition: ntddstor.h:505
#define IOCTL_SCSI_PASS_THROUGH
Definition: scsi_port.h:47
#define IOCTL_SCSI_PASS_THROUGH_DIRECT
Definition: scsi_port.h:51
#define IOCTL_SCSI_PASS_THROUGH_DIRECT_EX
Definition: ntddscsi.h:38
#define IOCTL_SCSI_PASS_THROUGH_EX
Definition: ntddscsi.h:37
STORAGE_QUERY_TYPE QueryType
Definition: ntddstor.h:553
STORAGE_PROPERTY_ID PropertyId
Definition: ntddstor.h:552
struct _WDF_REQUEST_PARAMETERS::@3881::@3886 Others
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133

Referenced by DeviceEvtIoInCallerContext(), and RequestDispatchSpecialIoctls().

◆ RequestDispatchSyncWithSequentialQueue()

BOOLEAN RequestDispatchSyncWithSequentialQueue ( _In_ WDFDEVICE  Device,
_In_ WDFREQUEST  Request,
_In_ WDF_REQUEST_PARAMETERS  RequestParameters 
)

Definition at line 2717 of file cdrom.c.

2740{
2743 size_t dataLength = 0;
2744
2745 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2746 ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
2747
2748 switch (ioctlCode)
2749 {
2750
2752 {
2753 //1. Validate
2755
2756 //2. keep the request in serialized manner and stay in user's context.
2757 if (NT_SUCCESS(status))
2758 {
2759 PCDROM_EXCLUSIVE_ACCESS exclusiveAccess = NULL;
2760
2761 status = WdfRequestRetrieveInputBuffer(Request,
2763 &exclusiveAccess,
2764 NULL);
2765
2766 if (NT_SUCCESS(status))
2767 {
2768 // do not need to check "status" as it passed validation and cannot fail in WdfRequestRetrieveInputBuffer()
2769 switch (exclusiveAccess->RequestType)
2770 {
2771
2773 {
2774 status = RequestSetContextFields(Request, RequestHandleExclusiveAccessQueryLockState);
2775 break;
2776 }
2777
2779 {
2780 status = RequestSetContextFields(Request, RequestHandleExclusiveAccessLockDevice);
2781 break;
2782 }
2783
2785 {
2786 status = RequestSetContextFields(Request, RequestHandleExclusiveAccessUnlockDevice);
2787 break;
2788 }
2789 default:
2790 {
2791 // already valicated in RequestValidateExclusiveAccess()
2793 break;
2794 }
2795 }
2796 }
2797
2798 if (NT_SUCCESS(status))
2799 {
2800 // now, put the special synchronization information into the context
2802
2803 // "status" is used for debugging in above statement, reset to success to avoid further work in this function.
2805 }
2806 }
2807
2808 processed = TRUE;
2809 break; // complete the irp
2810 }
2811
2812 default:
2813 {
2814 processed = FALSE;
2815 break;
2816 }
2817 } //end of switch (ioctlCode)
2818
2819 // Following process is only valid if the request is not really processed. (failed in validation)
2820 if (processed && !NT_SUCCESS(status))
2821 {
2822 UCHAR currentStackLocationFlags = 0;
2823 currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
2824
2825 if ((status == STATUS_VERIFY_REQUIRED) &&
2826 (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME))
2827 {
2828 //
2829 // If the status is verified required and this request
2830 // should bypass verify required then retry the request.
2831 //
2833 UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
2834
2836 }
2837 else
2838 {
2839 // Validation failed / forward failed, complete the request.
2840 RequestCompletion(deviceExtension, Request, status, dataLength);
2841 }
2842 }
2843
2844 return processed;
2845}
NTSTATUS RequestValidateExclusiveAccess(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2240
@ ExclusiveAccessQueryState
Definition: ntddcdrm.h:412
@ ExclusiveAccessLockDevice
Definition: ntddcdrm.h:413
@ ExclusiveAccessUnlockDevice
Definition: ntddcdrm.h:414
#define IOCTL_CDROM_EXCLUSIVE_ACCESS
Definition: ntddcdrm.h:85
EXCLUSIVE_ACCESS_REQUEST_TYPE RequestType
Definition: ntddcdrm.h:419

Referenced by DeviceEvtIoInCallerContext(), and RequestDispatchSyncWithSequentialQueue().

◆ RequestDispatchToSequentialQueue()

BOOLEAN RequestDispatchToSequentialQueue ( _In_ WDFDEVICE  Device,
_In_ WDFREQUEST  Request,
_In_ WDF_REQUEST_PARAMETERS  RequestParameters 
)

Definition at line 1855 of file cdrom.c.

1878{
1881 size_t dataLength = 0;
1882 BOOLEAN inZeroPowerState = FALSE;
1883
1884 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
1885 ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
1886 PZERO_POWER_ODD_INFO zpoddInfo = deviceExtension->ZeroPowerODDInfo;
1887
1888 if ((zpoddInfo != NULL) &&
1889 (zpoddInfo->InZeroPowerState != FALSE))
1890 {
1891 inZeroPowerState = TRUE;
1892 }
1893
1894 switch (ioctlCode)
1895 {
1896
1898 {
1900
1901 processed = TRUE;
1902 break;
1903 }
1904
1907 {
1908 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
1909 "RequestDispatchToSequentialQueue: Get drive geometryEx\n"));
1910 if ( RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1912 {
1915 }
1916 else if (inZeroPowerState != FALSE)
1917 {
1919 }
1920 else
1921 {
1923 }
1924
1925 processed = TRUE;
1926 break;
1927 }
1928
1931 {
1932 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
1933 "RequestDispatchToSequentialQueue: Get drive geometry\n"));
1934 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1935 sizeof(DISK_GEOMETRY))
1936 {
1938 dataLength = sizeof(DISK_GEOMETRY);
1939 }
1940 else if (inZeroPowerState != FALSE)
1941 {
1943 }
1944 else
1945 {
1947 }
1948
1949 processed = TRUE;
1950 break;
1951 }
1952
1954 {
1956
1957 if (inZeroPowerState != FALSE)
1958 {
1960 }
1961
1962 processed = TRUE;
1963 break;
1964 }
1965
1967 {
1969
1970 if (inZeroPowerState != FALSE)
1971 {
1973 }
1974
1975 processed = TRUE;
1976 break;
1977 }
1978
1980 {
1982
1983 processed = TRUE;
1984 break;
1985 }
1986
1988 {
1989 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
1990 "RequestDispatchToSequentialQueue: Play audio MSF\n"));
1991
1992 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
1993 sizeof(CDROM_PLAY_AUDIO_MSF))
1994 {
1996 }
1997 else
1998 {
2000 }
2001
2002 processed = TRUE;
2003 break;
2004 }
2005
2007 {
2008 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2009 "RequestDispatchToSequentialQueue: Seek audio MSF\n"));
2010
2011 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2012 sizeof(CDROM_SEEK_AUDIO_MSF))
2013 {
2015 }
2016 else
2017 {
2019 }
2020
2021 processed = TRUE;
2022 break;
2023 }
2024
2026 {
2027 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2028 "RequestDispatchToSequentialQueue: Pause audio\n"));
2029
2031 processed = TRUE;
2032 break;
2033 }
2034
2036 {
2037 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2038 "RequestDispatchToSequentialQueue: Resume audio\n"));
2039
2041 processed = TRUE;
2042 break;
2043 }
2044
2046 {
2048
2049 processed = TRUE;
2050 break;
2051 }
2052
2054 {
2055 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2056 "RequestDispatchToSequentialQueue: Get volume control\n"));
2057
2058 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2059 sizeof(VOLUME_CONTROL))
2060 {
2062 dataLength = sizeof(VOLUME_CONTROL);
2063 }
2064 else
2065 {
2067 }
2068
2069 processed = TRUE;
2070 break;
2071 }
2072
2074 {
2075 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2076 "RequestDispatchToSequentialQueue: Set volume control\n"));
2077
2078 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2079 sizeof(VOLUME_CONTROL))
2080 {
2082 }
2083 else
2084 {
2086 }
2087
2088 processed = TRUE;
2089 break;
2090 }
2091
2093 {
2094 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2095 "RequestDispatchToSequentialQueue: Stop audio\n"));
2096
2098 processed = TRUE;
2099 break;
2100 }
2101
2104 {
2105 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2106 "RequestDispatchToSequentialQueue: [%p] Check Verify\n", Request));
2107
2108 // Following check will let the condition "OutputBufferLength == 0" pass.
2109 // Since it's legacy behavior in classpnp, we need to keep it.
2110 if ((RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > 0) &&
2111 (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)))
2112 {
2114 dataLength = sizeof(ULONG);
2115 }
2116 else if (inZeroPowerState != FALSE)
2117 {
2119 }
2120 else
2121 {
2123 }
2124
2125 processed = TRUE;
2126 break;
2127 }
2128
2130 {
2131 // validation will be done when process it.
2133 processed = TRUE;
2134 break;
2135 }
2136
2138 {
2139 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2140 "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_READ_STRUCTURE\n", Request));
2141
2143
2144 processed = TRUE;
2145 break;
2146 }
2147
2148 case IOCTL_DVD_READ_KEY:
2149 {
2150 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2151 "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_READ_KEY\n", Request));
2152
2154
2155 processed = TRUE;
2156 break;
2157 }
2158
2160 {
2161 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2162 "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_START_SESSION\n", Request));
2163
2165
2166 processed = TRUE;
2167 break;
2168 }
2169
2170 case IOCTL_DVD_SEND_KEY:
2172 {
2173 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2174 "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_SEND_KEY\n", Request));
2175
2177
2178 processed = TRUE;
2179 break;
2180 }
2181
2183 {
2184 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2185 "RequestDispatchToSequentialQueue: [%p] SetReadAhead\n", Request));
2186
2187 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2188 sizeof(STORAGE_SET_READ_AHEAD))
2189 {
2191 }
2192 else
2193 {
2195 }
2196
2197 processed = TRUE;
2198 break;
2199 }
2200
2202 {
2204
2205 processed = TRUE;
2206 break;
2207 }
2208
2210 {
2211 ULONG requiredSize = 0;
2212
2213 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2214 "RequestDispatchToSequentialQueue: Get drive layout\n"));
2215
2216 requiredSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]);
2217
2218 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2219 requiredSize)
2220 {
2222 dataLength = requiredSize;
2223 }
2224 else
2225 {
2227 }
2228
2229 processed = TRUE;
2230 break;
2231 }
2232
2234 {
2235 ULONG requiredSize = 0;
2236
2237 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2238 "RequestDispatchToSequentialQueue: Get drive layoutEx\n"));
2239
2240 requiredSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]);
2241
2242 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2243 requiredSize)
2244 {
2246 dataLength = requiredSize;
2247 }
2248 else
2249 {
2251 }
2252
2253 processed = TRUE;
2254 break;
2255 }
2256
2258 {
2259 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2260 "RequestDispatchToSequentialQueue: Get Partition Info\n"));
2261
2262 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2263 sizeof(PARTITION_INFORMATION))
2264 {
2267 }
2268 else
2269 {
2271 }
2272
2273 processed = TRUE;
2274 break;
2275 }
2276
2278 {
2279 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2280 "RequestDispatchToSequentialQueue: Get Partition InfoEx\n"));
2281
2282 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2284 {
2287 }
2288 else
2289 {
2291 }
2292
2293 processed = TRUE;
2294 break;
2295 }
2296
2297 case IOCTL_DISK_VERIFY:
2298 {
2299 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2300 "RequestDispatchToSequentialQueue: IOCTL_DISK_VERIFY to device %p through request %p\n",
2301 Device,
2302 Request));
2303
2304 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2305 sizeof(VERIFY_INFORMATION))
2306 {
2308 }
2309 else
2310 {
2312 }
2313
2314 processed = TRUE;
2315 break;
2316 }
2317
2319 {
2320 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2321 "RequestDispatchToSequentialQueue: Disk Get Length InfoEx\n"));
2322
2323 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2324 sizeof(GET_LENGTH_INFORMATION))
2325 {
2328 }
2329 else if (inZeroPowerState != FALSE)
2330 {
2332 }
2333 else
2334 {
2336 }
2337
2338 processed = TRUE;
2339 break;
2340 }
2341
2343 {
2344 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2345 "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_GET_CONFIGURATION\n", Request));
2346
2348
2349 processed = TRUE;
2350 break;
2351 }
2352
2354 {
2355 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2356 "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_SET_SPEED\n", Request));
2357
2359
2360 processed = TRUE;
2361 break;
2362 }
2363
2365 {
2366 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2367 "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_END_SESSION\n", Request));
2368
2370
2371 processed = TRUE;
2372 break;
2373 }
2374
2376 {
2377 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2378 "RequestDispatchToSequentialQueue: [%p] IOCTL_AACS_END_SESSION\n", Request));
2379
2381
2382 processed = TRUE;
2383 break;
2384 }
2385
2387 {
2388 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2389 "AACS: Querying full MKB with bufferSize of %x bytes\n",
2390 (int)RequestParameters.Parameters.DeviceIoControl.OutputBufferLength
2391 ));
2392
2394
2395 processed = TRUE;
2396 break;
2397 }
2398
2400 {
2401 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2402 "AACS: Requesting AGID\n"
2403 ));
2404
2406
2407 processed = TRUE;
2408 break;
2409 }
2410
2412 {
2413 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2414 "AACS: Sending host certificate to drive\n"
2415 ));
2416
2418
2419 processed = TRUE;
2420 break;
2421 }
2422
2424 {
2425 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2426 "AACS: Querying drive certificate\n"
2427 ));
2428
2430
2431 processed = TRUE;
2432 break;
2433 }
2434
2436 {
2437 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2438 "AACS: Querying drive challenge key\n"
2439 ));
2440
2442
2443 processed = TRUE;
2444 break;
2445 }
2446
2448 {
2449 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2450 "AACS: Sending drive challenge key\n"
2451 ));
2452
2454
2455 processed = TRUE;
2456 break;
2457 }
2458
2460 {
2461 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2462 "AACS: Reading volume ID\n"
2463 ));
2464
2466
2467 processed = TRUE;
2468 break;
2469 }
2470
2472 {
2473 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2474 "AACS: Reading Serial Number\n"
2475 ));
2476
2478
2479 processed = TRUE;
2480 break;
2481 }
2482
2484 {
2485 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2486 "AACS: Reading media ID\n"
2487 ));
2488
2490
2491 processed = TRUE;
2492 break;
2493 }
2494
2497 {
2498 if (ioctlCode == IOCTL_AACS_GENERATE_BINDING_NONCE)
2499 {
2500 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2501 "AACS: Generating new binding nonce\n"
2502 ));
2503 }
2504 else
2505 {
2506 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2507 "AACS: Reading existing binding nonce\n"
2508 ));
2509 }
2510
2512
2513 processed = TRUE;
2514 break;
2515 }
2516
2518 {
2519 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2520 "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_ENABLE_STREAMING\n", Request));
2521
2523
2524 processed = TRUE;
2525 break;
2526 }
2527
2529 {
2530 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2531 "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_SEND_OPC_INFORMATION\n", Request));
2532
2534
2535 processed = TRUE;
2536 break;
2537 }
2538
2540 {
2541 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2542 "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_GET_PERFORMANCE\n", Request));
2543
2545
2546 processed = TRUE;
2547 break;
2548 }
2549
2552 {
2553 if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2554 sizeof(PREVENT_MEDIA_REMOVAL))
2555 {
2557 }
2558 else
2559 {
2561 }
2562
2563 processed = TRUE;
2564 break; // complete the irp
2565 }
2566
2568 {
2569 if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2570 sizeof(PREVENT_MEDIA_REMOVAL))
2571 {
2573 }
2574 else
2575 {
2577 }
2578
2579 processed = TRUE;
2580 break; // complete the irp
2581 }
2582
2585 {
2586 // there is no validate check currently.
2588 processed = TRUE;
2589 break;
2590 }
2591
2594 {
2596
2597 processed = TRUE;
2598 break;
2599 }
2600
2604 {
2606
2607 processed = TRUE;
2608 break; // complete the irp
2609 }
2610
2612 {
2613 // process it.
2615
2617
2618 processed = TRUE;
2619 break; // complete the irp
2620 }
2621
2623 {
2624 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_READ_CAPACITY))
2625 {
2628 }
2629 else if (inZeroPowerState != FALSE)
2630 {
2632 }
2633 else
2634 {
2636 }
2637
2638 processed = TRUE;
2639 break; // complete the irp
2640 }
2641
2643 {
2644 // for disk.sys only in original classpnp
2646
2647 processed = TRUE;
2648 break; // complete the irp
2649 }
2650
2651#if (NTDDI_VERSION >= NTDDI_WIN8)
2653 {
2654 // this request doesn't access device at all, so seemingly it can be processed
2655 // directly; however, in case volume online is not received, we will need to
2656 // park these requests in a queue, and the only way a request can be queued is
2657 // if the request came out of another queue.
2659
2660 processed = TRUE;
2661 break;
2662 }
2663
2666 {
2668
2669 processed = TRUE;
2670 break;
2671 }
2672#endif
2673
2674 default:
2675 {
2676 processed = FALSE;
2677 break;
2678 }
2679 } //end of switch (ioctlCode)
2680
2681 if (processed)
2682 {
2683 UCHAR currentStackLocationFlags = 0;
2684 currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
2685
2686 if ((status == STATUS_VERIFY_REQUIRED) &&
2687 (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME))
2688 {
2689 // If the status is verified required and this request
2690 // should bypass verify required then retry the request.
2692 UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
2693
2695 }
2696 else
2697 {
2698 if (NT_SUCCESS(status))
2699 {
2700 // Forward the request to serialized queue.
2701 status = WdfDeviceEnqueueRequest(Device, Request);
2702 }
2703
2704 if (!NT_SUCCESS(status))
2705 {
2706 // Validation failed / forward failed, complete the request.
2707 RequestCompletion(deviceExtension, Request, status, dataLength);
2708 }
2709 }
2710 }
2711
2712 return processed;
2713}
#define IOCTL_DVD_SEND_KEY
Definition: cdrw_usr.h:161
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define IOCTL_DVD_END_SESSION
Definition: cdrw_usr.h:162
#define IOCTL_STORAGE_SET_READ_AHEAD
Definition: cdrw_usr.h:186
#define IOCTL_DVD_SEND_KEY2
Definition: cdrw_usr.h:165
#define IOCTL_DVD_GET_REGION
Definition: cdrw_usr.h:164
#define IOCTL_DISK_VERIFY
Definition: cdrw_usr.h:170
#define IOCTL_DVD_READ_KEY
Definition: cdrw_usr.h:160
#define IOCTL_DVD_START_SESSION
Definition: cdrw_usr.h:159
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
#define IOCTL_DVD_READ_STRUCTURE
Definition: cdrw_usr.h:157
#define IOCTL_VOLUME_POST_ONLINE
Definition: volume.c:26
NTSTATUS RequestValidateReadToc(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:984
NTSTATUS RequestValidateAacsGetChallengeKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1826
NTSTATUS RequestValidateSetSpeed(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1501
NTSTATUS RequestValidateRawRead(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:650
NTSTATUS RequestValidateSendOpcInformation(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3576
NTSTATUS RequestValidateAacsReadMediaKeyBlock(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1584
NTSTATUS RequestValidateAacsReadVolumeId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1955
NTSTATUS RequestValidateGetPerformance(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3634
NTSTATUS RequestValidateAacsStartSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1651
NTSTATUS RequestValidateDvdStartSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1225
NTSTATUS RequestValidateAacsReadMediaId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2093
NTSTATUS RequestValidateGetLastSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1029
NTSTATUS RequestValidateReadQChannel(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1072
NTSTATUS RequestValidateGetConfiguration(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1364
NTSTATUS RequestValidateReadTocEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:887
NTSTATUS RequestValidateAacsSendCertificate(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1697
NTSTATUS RequestValidateAacsSendChallengeKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1895
NTSTATUS RequestValidateDvdEndSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3408
NTSTATUS RequestValidateDvdReadStructure(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1151
NTSTATUS RequestValidatePersistentReserve(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:6715
NTSTATUS RequestValidateAacsEndSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3462
NTSTATUS RequestValidateAacsGetCertificate(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1757
NTSTATUS RequestValidateDvdSendKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1274
NTSTATUS RequestValidateDvdReadKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3286
NTSTATUS RequestValidateAacsReadSerialNumber(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2024
NTSTATUS RequestValidateAacsBindingNonce(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2162
NTSTATUS RequestValidateEnableStreaming(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3515
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
#define IOCTL_STORAGE_LOAD_MEDIA2
Definition: ntddk_ex.h:210
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define IOCTL_CDROM_ENABLE_STREAMING
Definition: ntddcdrm.h:94
struct _VOLUME_CONTROL VOLUME_CONTROL
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX
Definition: ntddcdrm.h:76
#define IOCTL_CDROM_SEEK_AUDIO_MSF
Definition: ntddcdrm.h:37
#define IOCTL_CDROM_READ_TOC_EX
Definition: ntddcdrm.h:79
#define IOCTL_CDROM_GET_VOLUME
Definition: ntddcdrm.h:49
#define IOCTL_CDROM_PAUSE_AUDIO
Definition: ntddcdrm.h:43
#define IOCTL_CDROM_SET_VOLUME
Definition: ntddcdrm.h:55
#define IOCTL_CDROM_STOP_AUDIO
Definition: ntddcdrm.h:40
#define IOCTL_CDROM_READ_Q_CHANNEL
Definition: ntddcdrm.h:58
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY
Definition: ntddcdrm.h:73
#define IOCTL_CDROM_SET_SPEED
Definition: ntddcdrm.h:88
#define IOCTL_CDROM_GET_CONFIGURATION
Definition: ntddcdrm.h:82
#define IOCTL_CDROM_PLAY_AUDIO_MSF
Definition: ntddcdrm.h:52
#define IOCTL_CDROM_RESUME_AUDIO
Definition: ntddcdrm.h:46
#define IOCTL_CDROM_SEND_OPC_INFORMATION
Definition: ntddcdrm.h:97
#define IOCTL_CDROM_READ_TOC
Definition: ntddcdrm.h:34
#define IOCTL_CDROM_RAW_READ
Definition: ntddcdrm.h:67
#define IOCTL_CDROM_GET_PERFORMANCE
Definition: ntddcdrm.h:100
struct _DISK_GEOMETRY DISK_GEOMETRY
#define IOCTL_DISK_GET_DRIVE_LAYOUT
Definition: ntdddisk.h:91
#define IOCTL_DISK_ARE_VOLUMES_READY
Definition: ntdddisk.h:46
struct _PARTITION_INFORMATION PARTITION_INFORMATION
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
#define IOCTL_STORAGE_RELEASE
Definition: ntddstor.h:119
STORAGE_READ_CAPACITY
Definition: ntddstor.h:861
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define IOCTL_STORAGE_READ_CAPACITY
Definition: ntddstor.h:175
#define IOCTL_STORAGE_PERSISTENT_RESERVE_IN
Definition: ntddstor.h:169
#define IOCTL_STORAGE_PERSISTENT_RESERVE_OUT
Definition: ntddstor.h:172
#define IOCTL_STORAGE_LOAD_MEDIA
Definition: ntddstor.h:110
#define IOCTL_STORAGE_RESERVE
Definition: ntddstor.h:116
#define IOCTL_STORAGE_FIND_NEW_DEVICES
Definition: ntddstor.h:122
#define IOCTL_STORAGE_MCN_CONTROL
Definition: ntddstor.h:128
#define IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT
Definition: ntddstor.h:196
#define IOCTL_STORAGE_EJECTION_CONTROL
Definition: ntddstor.h:125
#define IOCTL_STORAGE_MEDIA_REMOVAL
Definition: ntddstor.h:104
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK
Definition: ntddcdvd.h:61
#define IOCTL_AACS_START_SESSION
Definition: ntddcdvd.h:64
#define IOCTL_AACS_READ_BINDING_NONCE
Definition: ntddcdvd.h:91
#define IOCTL_AACS_SEND_CHALLENGE_KEY
Definition: ntddcdvd.h:79
#define IOCTL_AACS_READ_VOLUME_ID
Definition: ntddcdvd.h:82
#define IOCTL_AACS_END_SESSION
Definition: ntddcdvd.h:67
#define IOCTL_AACS_GET_CHALLENGE_KEY
Definition: ntddcdvd.h:76
#define IOCTL_AACS_SEND_CERTIFICATE
Definition: ntddcdvd.h:70
#define IOCTL_AACS_GENERATE_BINDING_NONCE
Definition: ntddcdvd.h:94
#define IOCTL_AACS_GET_CERTIFICATE
Definition: ntddcdvd.h:73
#define IOCTL_AACS_READ_SERIAL_NUMBER
Definition: ntddcdvd.h:85
#define IOCTL_AACS_READ_MEDIA_ID
Definition: ntddcdvd.h:88
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
@ BusRelations
Definition: iotypes.h:2152

Referenced by DeviceEvtIoInCallerContext(), and RequestDispatchToSequentialQueue().

◆ RequestDispatchUnknownRequests()

BOOLEAN RequestDispatchUnknownRequests ( _In_ WDFDEVICE  Device,
_In_ WDFREQUEST  Request,
_In_ WDF_REQUEST_PARAMETERS  RequestParameters 
)

Definition at line 3093 of file cdrom.c.

3118{
3120 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
3121
3123
3124 if ((KeGetCurrentIrql() != PASSIVE_LEVEL) ||
3125 (baseCode == FILE_DEVICE_ACPI))
3126 {
3127 // 1. When IRQL is higher than PASSIVE_LEVEL,
3128 // 2. ataport sends IOCTL_ACPI_ASYNC_EVAL_METHOD before queue starts,
3129 // send request directly to lower driver.
3131 }
3132 else
3133 {
3134 // keep the request in serialized manner and stay in user's context.
3136
3137 if (NT_SUCCESS(status))
3138 {
3140 }
3141 else
3142 {
3143 RequestCompletion(deviceExtension, Request, status, 0);
3144 }
3145 }
3146
3147 UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning.
3148
3149 // All unknown IOCTLs are processed in this function.
3150 return TRUE; //processed
3151}
NTSTATUS RequestHandleUnknownIoctl(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define FILE_DEVICE_ACPI
Definition: winioctl.h:156
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132

Referenced by DeviceEvtIoInCallerContext(), and RequestDispatchSpecialIoctls().

◆ RequestEvtCleanup()

VOID NTAPI RequestEvtCleanup ( _In_ WDFOBJECT  Request)

Definition at line 4215 of file cdrom.c.

4232{
4233 WDFREQUEST request = (WDFREQUEST)Request;
4234 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(request);
4235
4236 if (requestContext->SyncRequired)
4237 {
4238 // the event should have been signaled, just check that
4239 NT_ASSERT(KeReadStateEvent(requestContext->SyncEvent) != 0);
4240 }
4241}
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:120
BOOLEAN SyncRequired
Definition: cdrom.h:643
Definition: tftpd.h:86

◆ RequestIsIoctlBlockedByExclusiveAccess()

NTSTATUS RequestIsIoctlBlockedByExclusiveAccess ( _In_ WDFREQUEST  Request,
_Out_ PBOOLEAN  IsBlocked 
)

Definition at line 4058 of file cdrom.c.

4079{
4081 ULONG ioctlCode = 0;
4082 ULONG baseCode = 0;
4083 WDF_REQUEST_PARAMETERS requestParameters;
4084
4085 // Get the Request parameters
4086 WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
4087 WdfRequestGetParameters(Request, &requestParameters);
4088
4089 // check and initialize parameter
4090 if (IsBlocked == NULL)
4091 {
4092 //This is an internal function and this parameter must be supplied.
4094
4096 }
4097 else
4098 {
4099 *IsBlocked = FALSE;
4100 }
4101
4102 // check if this is an IOCTL
4103 if ((requestParameters.Type == WdfRequestTypeDeviceControl) ||
4104 (requestParameters.Type == WdfRequestTypeDeviceControlInternal))
4105 {
4106 //
4107 // Allow minimum set of commands that are required for the disk manager
4108 // to show the CD device, while in exclusive mode.
4109 // Note: These commands should not generate any requests to the device,
4110 // and thus must be handled directly in StartIO during exclusive
4111 // access (except for the exclusive owner, of course).
4112 //
4113 ioctlCode = requestParameters.Parameters.DeviceIoControl.IoControlCode;
4114 baseCode = DEVICE_TYPE_FROM_CTL_CODE(ioctlCode);
4115
4116 if (ioctlCode == IOCTL_SCSI_GET_ADDRESS ||
4117 ioctlCode == IOCTL_STORAGE_GET_HOTPLUG_INFO ||
4118 ioctlCode == IOCTL_STORAGE_GET_DEVICE_NUMBER ||
4119 ioctlCode == IOCTL_STORAGE_GET_MEDIA_TYPES_EX ||
4120 ioctlCode == IOCTL_CDROM_EXCLUSIVE_ACCESS ||
4121 ioctlCode == IOCTL_CDROM_GET_INQUIRY_DATA
4122 )
4123 {
4124 *IsBlocked = FALSE;
4125 }
4126
4127 //
4128 // Handle IOCTL_STORAGE_QUERY_PROPERTY special because:
4129 // (1) PropertyExistsQuery should not generate device i/o
4130 // (2) Queries for StorageDeviceProperty and StorageAdapterDescriptor
4131 // will return cache'd data
4132 else if (ioctlCode == IOCTL_STORAGE_QUERY_PROPERTY)
4133 {
4135 status = WdfRequestRetrieveInputBuffer(Request,
4136 requestParameters.Parameters.DeviceIoControl.InputBufferLength,
4137 (PVOID*)&query,
4138 NULL);
4139
4140 if (NT_SUCCESS(status))
4141 {
4142 if (query != NULL)
4143 {
4144 if (query->QueryType == PropertyExistsQuery)
4145 {
4146 *IsBlocked = FALSE;
4147 }
4148 else if ((query->QueryType == PropertyStandardQuery) &&
4149 ((query->PropertyId == StorageDeviceProperty) ||
4150 (query->PropertyId == StorageAdapterProperty)))
4151 {
4152 *IsBlocked = FALSE;
4153 }
4154 }
4155 }
4156 }
4157
4158 // Return TRUE for unknown IOCTLs with STORAGE bases
4159 else if (baseCode == IOCTL_SCSI_BASE ||
4160 baseCode == IOCTL_DISK_BASE ||
4161 baseCode == IOCTL_CDROM_BASE ||
4162 baseCode == IOCTL_STORAGE_BASE ||
4163 baseCode == IOCTL_DVD_BASE )
4164 {
4165 *IsBlocked = TRUE;
4166 }
4167 }
4168 else
4169 {
4170 // this should only be called with an IOCTL
4172
4174 }
4175
4176 return status;
4177}
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52

Referenced by DeviceEvtIoInCallerContext(), RequestSynchronizeProcessWithSerialQueue(), and SequentialQueueEvtIoDeviceControl().

◆ RequestProcessInternalDeviceControl()

VOID RequestProcessInternalDeviceControl ( _In_ WDFREQUEST  Request,
_In_ PCDROM_DEVICE_EXTENSION  DeviceExtension 
)

Definition at line 3154 of file cdrom.c.

3173{
3175 PIRP irp = NULL;
3176 PIO_STACK_LOCATION irpStack = NULL;
3177 PIO_STACK_LOCATION nextStack = NULL;
3178 BOOLEAN requestSent = FALSE;
3179
3180 irp = WdfRequestWdmGetIrp(Request);
3182 nextStack = IoGetNextIrpStackLocation(irp);
3183
3184 // Set the parameters in the next stack location.
3185 nextStack->Parameters.Scsi.Srb = irpStack->Parameters.Scsi.Srb;
3186 nextStack->MajorFunction = IRP_MJ_SCSI;
3187 nextStack->MinorFunction = IRP_MN_SCSI_CLASS;
3188
3189 WdfRequestSetCompletionRoutine(Request, RequestDummyCompletionRoutine, NULL);
3190
3191 status = RequestSend(DeviceExtension,
3192 Request,
3193 DeviceExtension->IoTarget,
3194 0,
3195 &requestSent);
3196
3197 // send the request straight down (asynchronously)
3198 if (!requestSent)
3199 {
3200 // fail the request
3201 RequestCompletion(DeviceExtension, Request, status, WdfRequestGetInformation(Request));
3202 }
3203
3204 return;
3205}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
NTSTATUS RequestSend(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDFIOTARGET IoTarget, _In_ ULONG Flags, _Out_opt_ PBOOLEAN RequestSent)
Definition: common.c:3793
EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestDummyCompletionRoutine
Definition: cdrom.h:1608
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@4000 Scsi
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IRP_MJ_SCSI
#define IRP_MN_SCSI_CLASS

Referenced by DeviceEvtIoInCallerContext().

◆ RequestSynchronizeProcessWithSerialQueue()

NTSTATUS RequestSynchronizeProcessWithSerialQueue ( _In_ WDFDEVICE  Device,
_In_ WDFREQUEST  Request 
)

Definition at line 3893 of file cdrom.c.

3916{
3918 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
3919 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
3920 PKEVENT bufferToFree = requestContext->SyncEvent;
3921
3923 // cannot block at or above DISPATCH_LEVEL
3924 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3925 "RequestSynchronousProcessWithSerialQueue called at DISPATCH_LEVEL or above"));
3927 RequestCompletion(deviceExtension, Request, STATUS_INVALID_LEVEL, 0);
3928 return STATUS_INVALID_LEVEL;
3929 }
3930
3931 // init the synchronization event
3933
3934 // do we still need to do something like this?
3935 // SET_FLAG(nextStack->Flags, SL_OVERRIDE_VERIFY_VOLUME);
3936
3937 // NOTE: this mechanism relies on that KMDF will not complete request by itself.
3938 // Doing that will cause the syncEvent not fired thus this thread will stuck.
3939 // This should not really happen: our EvtCanceledOnQueue callbacks should be
3940 // called even if queues are purged for some reason. The only case when these
3941 // callbacks are not called is when a request is owned by the driver (i.e. has
3942 // already been passed to one of the registered handlers). In this case, it is
3943 // our responsibility to cancel such requests properly.
3944 status = WdfDeviceEnqueueRequest(Device, Request);
3945
3946 if (!NT_SUCCESS(status))
3947 {
3948 // Failed to forward request! Pretend the sync event already occured, otherwise we'll hit
3949 // an assert in RequestEvtCleanup.
3950 KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE);
3951 RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
3952 }
3953 else
3954 {
3955 NTSTATUS waitStatus = STATUS_UNSUCCESSFUL;
3956 PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
3957 BOOLEAN fCallSyncCallback = FALSE;
3958 PIRP irp = WdfRequestWdmGetIrp(Request);
3959
3960 // ok, now wait on the event
3961 while (waitStatus != STATUS_SUCCESS)
3962 {
3963 waitStatus = KeWaitForSingleObject(requestContext->SyncEvent, Executive, KernelMode, TRUE, NULL);
3964 if (waitStatus == STATUS_SUCCESS) // must check equality -- STATUS_ALERTED is success code
3965 {
3966 // do nothing
3967 }
3968 else if (waitStatus != STATUS_ALERTED)
3969 {
3970 // do nothing
3971 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_IOCTL,
3972 "Request %p on device object %p had a non-alert, non-success result from wait (%!HRESULT!)\n",
3973 Request, Device, waitStatus));
3975 }
3977 {
3978 // the thread was alerted and is terminating, so cancel the irp
3979 // this will cause EvtIoCanceledOnQueue to be called, which will signal the event,
3980 // so we will get out of the while loop and eventually complete the request.
3981 if (IoCancelIrp(irp))
3982 {
3983 // cancellation routine was called
3984 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
3985 "Sychronize Ioctl: request %p cancelled from device %p\n",
3986 Request, Device));
3987 }
3988 else
3989 {
3990 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
3991 "Sychronize Ioctl: request %p could not be cancelled from device %p\n",
3992 Request, Device));
3993 }
3994 }
3995 else
3996 {
3997 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
3998 "SPURIOUS ALERT waiting for Request %p on device %p (%!STATUS!)\n",
3999 Request, Device, status));
4000 }
4001 } // end of wait loop on the event
4002
4003 // because we've waited an unknown amount of time, should check
4004 // the cancelled flag to immediately fail the irp as appropriate
4005 if (WdfRequestIsCanceled(Request))
4006 {
4007 // the request was cancelled, thus we should always stop
4008 // processing here if possible.
4010 RequestCompletion(deviceExtension, Request, status, 0);
4011 }
4012 else if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
4013 {
4014 WDF_REQUEST_PARAMETERS requestParameters;
4015 BOOLEAN isBlocked = FALSE;
4016
4017 // get the request parameters
4018 WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
4019 WdfRequestGetParameters(Request, &requestParameters);
4020
4022 if (isBlocked)
4023 {
4024 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
4025 "Access Denied! Device in exclusive mode.Failing Ioctl %lx\n",
4026 requestParameters.Parameters.DeviceIoControl.IoControlCode));
4027 RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0);
4028 }
4029 else
4030 {
4031 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
4032 "Ioctl %lx not blocked by cdrom being in exclusive mode\n",
4033 requestParameters.Parameters.DeviceIoControl.IoControlCode));
4034 fCallSyncCallback = TRUE;
4035 }
4036 }
4037 else
4038 {
4039 fCallSyncCallback = TRUE;
4040 }
4041
4042 if (fCallSyncCallback)
4043 {
4044 // Synchronization completed successfully. Call the requested routine
4045 status = requestContext->SyncCallback(Device, Request);
4046 }
4047 }
4048
4049 // The next SequentialQueue evt routine will not be triggered until the current request is completed.
4050
4051 // clean up the request context setting.
4052 FREE_POOL(bufferToFree);
4053
4054 return status;
4055}
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
@ NotificationEvent
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
Definition: irp.c:1101
BOOLEAN NTAPI PsIsThreadTerminating(IN PETHREAD Thread)
Definition: thread.c:868
#define STATUS_ALERTED
Definition: ntstatus.h:80
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
PSYNC_HANDLER SyncCallback
Definition: cdrom.h:645
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define IO_CD_ROM_INCREMENT
Definition: iotypes.h:599
@ Executive
Definition: ketypes.h:415

Referenced by RequestDispatchSpecialIoctls(), RequestDispatchSyncWithSequentialQueue(), and RequestDispatchUnknownRequests().

◆ SequentialQueueEvtCanceledOnQueue()

VOID NTAPI SequentialQueueEvtCanceledOnQueue ( _In_ WDFQUEUE  Queue,
_In_ WDFREQUEST  Request 
)

Definition at line 3848 of file cdrom.c.

3870{
3871 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
3872
3873 if (requestContext->SyncRequired)
3874 {
3875 KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE);
3876 }
3877 else
3878 {
3879 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
3880 WDFDEVICE device = WdfIoQueueGetDevice(Queue);
3881
3882 deviceExtension = DeviceGetExtension(device);
3883
3884 RequestCompletion(deviceExtension, Request, STATUS_CANCELLED, 0);
3885
3886 }
3887
3888 return;
3889}

◆ SequentialQueueEvtIoDeviceControl()

VOID NTAPI SequentialQueueEvtIoDeviceControl ( _In_ WDFQUEUE  Queue,
_In_ WDFREQUEST  Request,
_In_ size_t  OutputBufferLength,
_In_ size_t  InputBufferLength,
_In_ ULONG  IoControlCode 
)

Definition at line 3408 of file cdrom.c.

3431{
3433 WDFDEVICE device = WdfIoQueueGetDevice(Queue);
3434 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
3435 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
3436 PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
3437 WDF_REQUEST_PARAMETERS requestParameters;
3438
3442
3443 // get the request parameters
3444 WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
3445 WdfRequestGetParameters(Request, &requestParameters);
3446
3447 // If the device is in exclusive mode, check whether the request is from
3448 // the handle that locked the device
3449 if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
3450 {
3451 BOOLEAN isBlocked = FALSE;
3452
3454 if (NT_SUCCESS(status) && isBlocked)
3455 {
3456 if (requestContext->SyncRequired)
3457 {
3458 // set the following event, so RequestSynchronizeProcessWithSerialQueue() can contintue run to process the real request.
3459 // this function will wait for the request process finishes.
3460 KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE);
3461 }
3462 else
3463 {
3464 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3465 "DeviceEvtIoInCallerContext: Access Denied! Device in exclusive mode.Failing Ioctl %lx\n",
3466 requestParameters.Parameters.DeviceIoControl.IoControlCode));
3467 RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0);
3468 }
3469
3470 return;
3471 }
3472 }
3473
3474 if (!cdData->Mmc.WriteAllowed &&
3475 ((requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_IS_WRITABLE) ||
3476 (requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_VERIFY)))
3477 {
3479 }
3480
3481 // check if this is a synchronized ioctl
3482 if (requestContext->SyncRequired)
3483 {
3484 // set the following event, so RequestSynchronizeProcessWithSerialQueue() can contintue run to process the real request.
3485 // this function will wait for the request process finishes.
3486 KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE);
3487 }
3488 else
3489 {
3490 deviceExtension->IoctlWorkItemContext.OriginalRequest = Request;
3491
3492 // all other IOCTL processing is currently processed via a
3493 // work item running at PASSIVE_LEVEL.
3494 WdfWorkItemEnqueue(deviceExtension->IoctlWorkItem);
3495 }
3496
3497 return;
3498}
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:325
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:320
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
Definition: wdfio.h:322

◆ SequentialQueueEvtIoReadWrite()

VOID NTAPI SequentialQueueEvtIoReadWrite ( _In_ WDFQUEUE  Queue,
_In_ WDFREQUEST  Request,
_In_ size_t  Length 
)

Definition at line 3215 of file cdrom.c.

3238{
3240 WDFDEVICE device = WdfIoQueueGetDevice(Queue);
3241 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
3242 WDF_REQUEST_PARAMETERS requestParameters;
3243 PIRP wdmIrp = WdfRequestWdmGetIrp(Request);
3244 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(wdmIrp);
3245 PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
3246
3247 // Get the request parameters
3248 WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
3249 WdfRequestGetParameters(Request, &requestParameters);
3250
3251 if (requestParameters.Type == WdfRequestTypeRead)
3252 {
3253 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
3254 "Receiving READ, Length %Ix\n", (ULONG) Length));
3255 }
3256 else
3257 {
3258 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
3259 "Receiving WRITE, Length %Ix\n", (ULONG) Length));
3260 }
3261
3262 // Check if a verify is required before a READ/WRITE
3263 if (TEST_FLAG(deviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME) &&
3264 (requestParameters.MinorFunction != CDROM_VOLUME_VERIFY_CHECKED) &&
3265 !TEST_FLAG(currentIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME))
3266 {
3267 // DO_VERIFY_VOLUME is set for the device object,
3268 // but this request is not itself a verify request.
3269 // So fail this request.
3270 RequestCompletion(deviceExtension, Request, STATUS_VERIFY_REQUIRED, 0);
3271 }
3272 else
3273 {
3274 // Since we've bypassed the verify-required tests we don't need to repeat
3275 // them with this IRP - in particular we don't want to worry about
3276 // hitting them at the partition 0 level if the request has come through
3277 // a non-zero partition.
3278 currentIrpStack->MinorFunction = CDROM_VOLUME_VERIFY_CHECKED;
3279
3280 // Fail READ/WRITE requests when music is playing
3281 if (deviceExtension->DeviceAdditionalData.PlayActive)
3282 {
3283 RequestCompletion(deviceExtension, Request, STATUS_DEVICE_BUSY, 0);
3284
3285 return;
3286 }
3287
3288 // Fail READ/WRITE requests from non-owners if the drive is locked
3289 if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
3290 {
3291 RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0);
3292
3293 return;
3294 }
3295
3296 // Succeed READ/WRITE requests of length 0
3297 if (Length == 0)
3298 {
3299 // Several parts of the code turn 0 into 0xffffffff,
3300 // so don't process a zero-length request any further.
3301 RequestCompletion(deviceExtension, Request, STATUS_SUCCESS, Length);
3302
3303 return;
3304 }
3305
3306 // If there is an unexpected write request, we want to rediscover MMC capabilities
3307 if (!deviceExtension->DeviceAdditionalData.Mmc.WriteAllowed &&
3308 (requestParameters.Type == WdfRequestTypeWrite))
3309 {
3310 // Schedule MMC capabilities update now, but perform it later in a work item
3312 }
3313
3314 // If MMC capabilities update is required, we create a separate work item to avoid blocking
3315 // the current thread; otherwise, we initiate an async read/write in the current thread.
3316 if (DeviceIsMmcUpdateRequired(deviceExtension->Device))
3317 {
3319 WdfWorkItemEnqueue(deviceExtension->ReadWriteWorkItem);
3320
3322 }
3323 else
3324 {
3325 status = RequestValidateReadWrite(deviceExtension, Request, requestParameters);
3326
3327 if (NT_SUCCESS(status))
3328 {
3329 status = RequestHandleReadWrite(deviceExtension, Request, requestParameters);
3330 }
3331 }
3332
3333 if (!NT_SUCCESS(status))
3334 {
3335 RequestCompletion(deviceExtension, Request, status, 0);
3336 }
3337 }
3338
3339 return;
3340}
#define CDROM_VOLUME_VERIFY_CHECKED
Definition: cdromp.h:171
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
BOOLEAN PlayActive
Definition: cdrom.h:351
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
@ WdfRequestTypeWrite
Definition: wdfdevice.h:507
@ WdfRequestTypeRead
Definition: wdfdevice.h:506

Referenced by DriverEvtDeviceAdd().