24#define CLASS_INIT_GUID 1
25#define DEBUG_MAIN_SOURCE 1
39 #pragma alloc_text(INIT, DriverEntry)
40 #pragma alloc_text(PAGE, ClassAddDevice)
41 #pragma alloc_text(PAGE, ClassClaimDevice)
42 #pragma alloc_text(PAGE, ClassCreateDeviceObject)
43 #pragma alloc_text(PAGE, ClassDispatchPnp)
44 #pragma alloc_text(PAGE, ClassGetDescriptor)
45 #pragma alloc_text(PAGE, ClassGetPdoId)
46 #pragma alloc_text(PAGE, ClassInitialize)
47 #pragma alloc_text(PAGE, ClassInitializeEx)
48 #pragma alloc_text(PAGE, ClassInvalidateBusRelations)
49 #pragma alloc_text(PAGE, ClassMarkChildMissing)
50 #pragma alloc_text(PAGE, ClassMarkChildrenMissing)
51 #pragma alloc_text(PAGE, ClassModeSense)
52 #pragma alloc_text(PAGE, ClassPnpQueryFdoRelations)
53 #pragma alloc_text(PAGE, ClassPnpStartDevice)
54 #pragma alloc_text(PAGE, ClassQueryPnpCapabilities)
55 #pragma alloc_text(PAGE, ClassQueryTimeOutRegistryValue)
56 #pragma alloc_text(PAGE, ClassRemoveDevice)
57 #pragma alloc_text(PAGE, ClassRetrieveDeviceRelations)
58 #pragma alloc_text(PAGE, ClassUpdateInformationInRegistry)
59 #pragma alloc_text(PAGE, ClassSendDeviceIoControlSynchronous)
60 #pragma alloc_text(PAGE, ClassUnload)
61 #pragma alloc_text(PAGE, ClasspAllocateReleaseRequest)
62 #pragma alloc_text(PAGE, ClasspFreeReleaseRequest)
63 #pragma alloc_text(PAGE, ClasspInitializeHotplugInfo)
64 #pragma alloc_text(PAGE, ClasspRegisterMountedDeviceInterface)
65 #pragma alloc_text(PAGE, ClasspScanForClassHacks)
66 #pragma alloc_text(PAGE, ClasspScanForSpecialInRegistry)
67 #pragma alloc_text(PAGE, ClasspModeSense)
68 #pragma alloc_text(PAGE, ClasspIsPortable)
69 #pragma alloc_text(PAGE, ClassAcquireChildLock)
70 #pragma alloc_text(PAGE, ClassDetermineTokenOperationCommandSupport)
71 #pragma alloc_text(PAGE, ClassDeviceProcessOffloadRead)
72 #pragma alloc_text(PAGE, ClassDeviceProcessOffloadWrite)
73 #pragma alloc_text(PAGE, ClasspServicePopulateTokenTransferRequest)
74 #pragma alloc_text(PAGE, ClasspServiceWriteUsingTokenTransferRequest)
75#if (NTDDI_VERSION >= NTDDI_WINBLUE)
76 #pragma alloc_text(PAGE, ClassModeSenseEx)
81#pragma prefast(disable:28159, "There are certain cases when we have to bugcheck...")
92#define FirstDriveLetter 'C'
93#define LastDriveLetter 'Z'
254 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
"ClassInitialize: Class driver wrong version\n"));
274 "ClassInitialize: Class device-specific driver missing required "
290 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
"ClassInitialize: Class device-specific missing "
291 "required PDO entry\n"));
304 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
"ClassInitialize: Class device-specific missing "
305 "required PDO entry\n"));
337 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
"ClassInitialize: driver does not support unload %wZ\n",
345#pragma warning(suppress:4054)
393#pragma warning(suppress:4054)
401 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
"ClassInitialize: Class driver extension could not be "
402 "allocated %lx\n",
status));
413#pragma prefast(disable:28175, "Accessing DRIVER_OBJECT fileds is OK here since this function " \
414 "is supposed to be invoked from DriverEntry only")
534#pragma warning(suppress:4054)
538 if (driverExtension ==
NULL)
679 else if (
info->HistoryCount == 0)
775#pragma warning(suppress:4054)
780 if (driverExtension ==
NULL)
813 EtwUnregister(driverExtension->
EtwHandle);
848#pragma prefast(suppress:28152, "We expect the class driver to clear the DO_DEVICE_INITIALIZING flag in its AddDevice routine.")
857#pragma warning(suppress:4054)
921#pragma warning(suppress:4054)
925 if (driverExtension){
927 initData = &(driverExtension->
InitData);
930 devInfo = &(initData->
FdoData);
932 devInfo = &(initData->
PdoData);
940 isFdo ?
"fdo" :
"pdo",
994 if(deviceRelations !=
NULL) {
999 Irp->IoStatus.Information = (
ULONG_PTR) deviceRelations;
1001 deviceRelations->
Count = 1;
1043 completeRequest =
TRUE;
1053 completeRequest =
FALSE;
1076 completeRequest =
FALSE;
1114 "STOP" :
"REMOVE")));
1123 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_PNP,
"ClassDispatchPnp (%p,%p): device is in paging "
1124 "path and cannot be removed\n",
1158 "STOP" :
"REMOVE")));
1217 completeRequest =
FALSE;
1235 (isFdo ?
"fdo" :
"pdo")
1264 commonExtension->PreviousState = 0xff;
1290 logSurpriseRemove =
FALSE;
1293 logSurpriseRemove =
FALSE;
1302 logSurpriseRemove =
FALSE;
1305 if (logSurpriseRemove) {
1320 lockReleased =
TRUE;
1344 completeRequest =
FALSE;
1356 commonExtension->PreviousState = commonExtension->CurrentState;
1357 commonExtension->CurrentState = removeType;
1402 if (commonExtension->
IsFdo){
1434 "paging file removed, but "
1435 "DO_POWER_INRUSH was set, so NOT "
1436 "setting DO_POWER_PAGABLE\n",
1441 "paging file removed, "
1442 "setting DO_POWER_PAGABLE\n",
1472 "Clearing PAGABLE bit\n",
1487 if (setPagable ==
TRUE) {
1489 "PAGABLE bit due to irp failure\n",
1499 if (commonExtension->
IsFdo) {
1539 "hiber file removed, but "
1540 "DO_POWER_INRUSH was set, so NOT "
1541 "setting DO_POWER_PAGABLE\n",
1546 "hiber file removed, "
1547 "setting DO_POWER_PAGABLE\n",
1558 if (setPagable ==
TRUE) {
1560 "PAGABLE bit due to irp failure\n",
1576 "Clearing PAGABLE bit\n",
1605 "dump file removed, but "
1606 "DO_POWER_INRUSH was set, so NOT "
1607 "setting DO_POWER_PAGABLE\n",
1612 "dump file removed, "
1613 "setting DO_POWER_PAGABLE\n",
1624 if (setPagable ==
TRUE) {
1626 "PAGABLE bit due to irp failure\n",
1642 "Clearing PAGABLE bit\n",
1664 if ((fdoData !=
NULL) &&
1710 fdoData = fdoExtension->PrivateFdoData;
1711 deviceCapabilities =
1738 if (deviceCapabilities->SurpriseRemovalOK) {
1740 "device capabilities due to hotplug "
1741 "device or media\n"));
1743 deviceCapabilities->SurpriseRemovalOK =
FALSE;
1764 completeRequest =
FALSE;
1776 if (completeRequest){
1840#pragma warning(suppress:4054)
1844 initData = &(driverExtension->
InitData);
1846 devInfo = &(initData->
FdoData);
1848 devInfo = &(initData->
PdoData);
1867 if (fdoExtension->PrivateFdoData ==
NULL) {
1874 if (fdoExtension->PrivateFdoData ==
NULL) {
1875 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: Cannot allocate for private fdo data\n"));
1882#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1887 if (fdoExtension->AdditionalFdoData ==
NULL) {
1889 sizeof(ADDITIONAL_FDO_DATA),
1894 if (fdoExtension->AdditionalFdoData ==
NULL) {
1895 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: Cannot allocate memory for the additional data structure.\n"));
1899 RtlZeroMemory(fdoExtension->AdditionalFdoData,
sizeof(ADDITIONAL_FDO_DATA));
1904 FREE_POOL(fdoExtension->PrivateFdoData);
1905#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1906 FREE_POOL(fdoExtension->AdditionalFdoData);
1908 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: Failed to initialize tick timer\n"));
1916 if (fdoExtension->FunctionSupportInfo ==
NULL) {
1923 if (fdoExtension->FunctionSupportInfo ==
NULL) {
1925 FREE_POOL(fdoExtension->PrivateFdoData);
1926#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1927 FREE_POOL(fdoExtension->AdditionalFdoData);
1929 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: Cannot allocate for FunctionSupportInfo\n"));
1947 fdoExtension->FunctionSupportInfo->BlockLimitsData.CommandStatus = -1;
1948 fdoExtension->FunctionSupportInfo->DeviceCharacteristicsData.CommandStatus = -1;
1949 fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus = -1;
1950 fdoExtension->FunctionSupportInfo->ReadCapacity16Data.CommandStatus = -1;
1951 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus = -1;
1968 fdoExtension->PrivateFdoData->InterpretSenseInfo = driverExtension->
InterpretSenseInfo;
1970 fdoExtension->PrivateFdoData->MaxNumberOfIoRetries =
NUM_IO_RETRIES;
1977 sizeof(fdoExtension->PrivateFdoData->
ReleaseQueueSrb.ReleaseQueueSrbBuffer),
1982 "ClassPnpStartDevice: fail to initialize release queue extended SRB 0x%x\n",
status));
2002 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: Cannot allocate the private release queue irp\n"));
2008 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: Cannot allocate the power process irp\n"));
2024 (
PVOID *)&fdoExtension->MiniportDescriptor);
2035 fdoExtension->MiniportDescriptor->IoTimeoutValue = 0;
2048 status = ClassGetDescriptor(
2053 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: ClassGetDescriptor [ADAPTER] failed %lx\n",
status));
2063 status = ClassGetDescriptor(
2080 ClassGetDeviceParameter(fdoExtension,
2085 fdoExtension->PrivateFdoData->Perf.ReEnableThreshhold =
t;
2120 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_PNP,
"ClassPnpStartDevice: Could not initialize hotplug information %lx\n",
status));
2124 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: ClassGetDescriptor [DEVICE] failed %lx\n",
status));
2138 (
PVOID *)&powerDescriptor);
2141 fdoExtension->FunctionSupportInfo->IdlePower.D3ColdSupported = powerDescriptor->
D3ColdSupported;
2142 fdoExtension->FunctionSupportInfo->IdlePower.NoVerifyDuringIdlePower = powerDescriptor->
NoVerifyDuringIdlePower;
2145 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
"ClassPnpStartDevice: ClassGetDescriptor [DevicePower] failed %lx\n",
status));
2166 if (commonExtension->
IsFdo) {
2167 fdoExtension->PrivateFdoData->Perf.OriginalSrbFlags = fdoExtension->
SrbFlags;
2175 ULONG accessAlignmentNotSupported = 0;
2180 "ClassPnpStartDevice: Enabling idle timer for %p\n",
DeviceObject));
2195 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits) {
2196 ClassDetermineTokenOperationCommandSupport(
DeviceObject);
2206 ClassGetDeviceParameter(fdoExtension,
2231 fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus =
STATUS_UNSUCCESSFUL;
2233 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus =
STATUS_UNSUCCESSFUL;
2237 ClassGetDeviceParameter(fdoExtension,
2240 &accessAlignmentNotSupported);
2242 if (accessAlignmentNotSupported > 0) {
2243 fdoExtension->FunctionSupportInfo->RegAccessAlignmentQueryNotSupported =
TRUE;
2246#if (NTDDI_VERSION >= NTDDI_WINBLUE)
2252 ClassGetDeviceParameter(fdoExtension,
2255 &legacyErrorHandling);
2257 if (legacyErrorHandling) {
2263 fdoExtension->PrivateFdoData->LegacyErrorHandling =
TRUE;
2277 &(fdoExtension->PrivateFdoData->CopyOffloadMaxTargetDuration));
2309 (fdoExtension->FunctionSupportInfo !=
NULL) &&
2310 (fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported ==
FALSE)) ||
2323 &GUID_CONSOLE_DISPLAY_STATE,
2345 isMountedDevice =
FALSE;
2350 isMountedDevice =
FALSE;
2360 isMountedDevice =
TRUE;
2363 if(isMountedDevice) {
2367 if(commonExtension->
IsFdo) {
2374 if (fdoExtension->FunctionSupportInfo !=
NULL &&
2375 fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled ==
FALSE &&
2376 fdoExtension->MiniportDescriptor !=
NULL &&
2380 ULONG disableIdlePower= 0;
2381 ClassGetDeviceParameter(fdoExtension,
2386 if (!disableIdlePower) {
2446 Irp->IoStatus.Information = 0;
2460 if (
Irp->Tail.Overlay.Thread !=
NULL) {
2464 Irp->IoStatus.Information = 0;
2489 Irp->IoStatus.Information = 0;
2501 if (transferByteCount == 0) {
2507 Irp->IoStatus.Information = 0;
2534 if (commonExtension->
IsFdo){
2557 Irp->IoStatus.Information = 0;
2588 UCHAR uniqueAddr = 0;
2644 ULONG bytesPerSector;
2662 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
"ClassReadDriveCapacity: reducing number of sectors by %d\n", fdoExt->
DMSkew));
2676 if (cylinderSize == 0){
2752 IRP pseudoIrp = {0};
2753 ULONG readCapacityDataSize;
2767 if (driveCapMdl !=
NULL) {
2776 if (driveCapMdl ==
NULL) {
2793 pseudoIrp.Tail.Overlay.DriverContext[0] =
LongToPtr(1);
2796 pseudoIrp.MdlAddress = driveCapMdl;
2807 readCapacityDataSize,
2825 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
"ClassReadDriveCapacity: read len (%xh) < %xh, retrying ...",
2830 pseudoIrp.Tail.Overlay.DriverContext[0] =
LongToPtr(1);
2836 readCapacityDataSize,
2856 if (use16ByteCdb ==
FALSE) {
2872 use16ByteCdb =
TRUE;
3008 if (driveCapMdl !=
NULL) {
3031 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
"ClassReadDriveCapacity: defaulting to cached DriveCapacity data"));
3115 sizeof(
context->Srb.SrbExBuffer),
3318 if (
Irp->MdlAddress !=
NULL) {
3446 deferClientIrp =
TRUE;
3458 if (!deferClientIrp)
3492 numPackets = entireXferLen/hwMaxXferLen;
3493 if (entireXferLen % hwMaxXferLen){
3502 if (driverUsesStartIO) {
3518 for (
i = 0;
i < numPackets;
i++){
3530 if ((
i == numPackets) &&
3531 (!driverUsesStartIO)) {
3538 Irp->IoStatus.Information = 0;
3544 Irp->Tail.Overlay.DriverContext[0] =
LongToPtr(numPackets);
3555 if (numPackets > 1){
3566 while (entireXferLen > 0){
3567 ULONG thisPieceLen =
MIN(hwMaxXferLen, entireXferLen);
3585 if (numPackets > 1) {
3603 pkt->RetryIn100nsUnits = 0;
3622 entireXferLen -= thisPieceLen;
3623 bufPtr += thisPieceLen;
3624 targetLocation.
QuadPart += thisPieceLen;
3656 if (!driverUsesStartIO) {
3657 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_RW,
"Insufficient packets available in ServiceTransferRequest - entering lowMemRetry with pkt=%p.", pkt));
3664 Irp->IoStatus.Information = 0;
3686 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_RW,
"No packets available in ServiceTransferRequest - deferring transfer (Irp=%p)...",
Irp));
3720 deferClientIrp =
TRUE;
3855#pragma warning(suppress:4213)
3905 callStartNextPacket =
FALSE;
3933 TracePrint((
TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
"ClassIoComplete is freeing an SRB (possibly) on behalf of another driver."));
3940 "SRB_CLASS_FLAGS_PERSISTANT set\n", srb));
3943 " because SRB_CLASS_FLAGS_PERSISTANT set\n",
3961 (
Irp->Tail.Overlay.Thread !=
NULL)
3970 Irp->IoStatus.Information = 0;
3989 if (
Irp->PendingReturned) {
3994 if (callStartNextPacket) {
4103#if defined(_ARM_) || defined(_ARM64_)
4114 senseInfoBufferLength,
4119 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClassSendSrbSynchronous: Can't allocate request sense "
4188 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClassSendSrbSynchronous: Can't allocate Irp\n"));
4213 irp->UserIosb = &ioStatus;
4227 if (
irp->MdlAddress ==
NULL) {
4232 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClassSendSrbSynchronous: Can't allocate MDL\n"));
4248 #pragma warning(suppress: 6320)
4259 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClassSendSrbSynchronous: Exception %lx "
4260 "locking buffer\n",
status));
4315 TracePrint((
TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
"ClassSendSrbSynchronous - srb %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)",
Srb,
4365 if (retryInterval < 2*1000*1000*10) {
4366 retryInterval = 2*1000*1000*10;
4490 ULONG retryInterval = 0;
4493 UCHAR cdbOpcode = 0;
4533 "ClassInterpretSenseInfo: Internal Error code is %x\n",
4551 isReservationConflict =
TRUE;
4560 UCHAR errorCode = 0;
4562 UCHAR addlSenseCode = 0;
4563 UCHAR addlSenseCodeQual = 0;
4570 validSense = ScsiGetSenseKeyAndCodes(senseBuffer,
4575 &addlSenseCodeQual);
4581 validSense = ScsiGetFixedSenseKeyAndCodes(senseBuffer,
4585 &addlSenseCodeQual);
4589 goto __ClassInterpretSenseInfo_ProcessingInvalidSenseBuffer;
4594 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
"ClassInterpretSenseInfo: Error code is %x\n", errorCode));
4596 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
"ClassInterpretSenseInfo: Additional sense code is %x\n", addlSenseCode));
4597 TracePrint((
TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
"ClassInterpretSenseInfo: Additional sense code qualifier is %x\n", addlSenseCodeQual));
4606 UCHAR startBufferLength = 0;
4609 if (ScsiGetSenseDescriptor(senseBuffer,
4612 &startBufferLength)) {
4615 UCHAR outBufferLength = 0;
4623 while ((!foundBlockCommandType || !foundInformationType) &&
4624 ScsiGetNextSenseDescriptorByType(startBuffer,
4630 &outBufferLength)) {
4647 if (!foundBlockCommandType) {
4649 foundBlockCommandType =
TRUE;
4651 if (ScsiValidateBlockCommandSenseDescriptor(
outBuffer, outBufferLength)) {
4653 isIncorrectLengthValid =
TRUE;
4672 if (!foundInformationType) {
4674 foundInformationType =
TRUE;
4676 if (ScsiValidateInformationSenseDescriptor(
outBuffer, outBufferLength)) {
4678 isInformationValid =
TRUE;
4715 isInformationValid =
TRUE;
4716 isIncorrectLengthValid =
TRUE;
4728 if (isIncorrectLengthValid && incorrectLength) {
4731 "Incorrect length detected.\n"));
4738 "No specific sense key\n"));
4749 "Recovered error\n"));
4755 switch(addlSenseCode) {
4773 wmiEventData[
sizeof(
ULONG)] = addlSenseCodeQual;
4791 ClassNotifyFailurePredicted(fdoExtension,
4793 sizeof(wmiEventData),
4811 if (isIncorrectLengthValid && incorrectLength) {
4814 "Incorrect length detected.\n"));
4825 "Device not ready\n"));
4828 switch (addlSenseCode) {
4833 "Lun not ready\n"));
4837 switch (addlSenseCodeQual) {
4842 logRetryableError =
FALSE;
4844 "In process of becoming ready\n"));
4849 ClassSendNotification(fdoExtension,
4850 &GUID_IO_DEVICE_BECOMING_READY,
4858 "Manual intervention required\n"));
4866 "Format in progress\n"));
4874 logRetryableError =
FALSE;
4876 "Operation In Progress\n"));
4881 ClassSendNotification(fdoExtension,
4882 &GUID_IO_DEVICE_BECOMING_READY,
4891 "Long write in progress\n"));
4903 logRetryableError =
FALSE;
4905 "The device (%p) is busy allocating space.\n",
4926 "ClassInterpretSenseInfo: "
4927 "not ready, cause unknown\n"));
4953 "Initializing command required\n"));
4955 logRetryableError =
FALSE;
4977 "No Media in device.\n"));
4986 "No Media in a non-removable device %p\n",
4990 if (addlSenseCodeQual == 0xCC){
5011 "Medium Error (bad block)\n"));