ReactOS 0.4.15-dev-7958-gcd0bb1a
class.c
Go to the documentation of this file.
1/*++
2
3Copyright (C) Microsoft Corporation, 1991 - 2010
4
5Module Name:
6
7 class.c
8
9Abstract:
10
11 SCSI class driver routines
12
13Environment:
14
15 kernel mode only
16
17Notes:
18
19
20Revision History:
21
22--*/
23
24#define CLASS_INIT_GUID 1
25#define DEBUG_MAIN_SOURCE 1
26
27#include "classp.h"
28#include "debug.h"
29#include <process.h>
30#include <devpkey.h>
31#include <ntiologc.h>
32
33
34#ifdef DEBUG_USE_WPP
35#include "class.tmh"
36#endif
37
38#ifdef ALLOC_PRAGMA
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)
77#endif
78#endif
79
80#ifdef _MSC_VER
81#pragma prefast(disable:28159, "There are certain cases when we have to bugcheck...")
82#endif
83
84IO_COMPLETION_ROUTINE ClassCheckVerifyComplete;
85
86
89CONST LARGE_INTEGER Magic10000 = {{0xe219652c, 0xd1b71758}};
90GUID StoragePredictFailureDPSGuid = WDI_STORAGE_PREDICT_FAILURE_DPS_GUID;
91
92#define FirstDriveLetter 'C'
93#define LastDriveLetter 'Z'
94
96
97//
98// Keep track of whether security cookie is initialized or not. This is
99// required by SDL.
100//
101
103
104//
105// List Identifier for offload data transfer operations
106//
109
110//
111// List of FDOs that have enabled idle power management.
112//
115
116//
117// Handle used to register for power setting notifications.
118//
120
121//
122// Handle used to register for screen state setting notifications.
123//
125
126//
127// Disk idle timeout in milliseconds.
128// We default this to 0xFFFFFFFF as this is what the power manager considers
129// "never" and ensures we do not set a disk idle timeout until the power
130// manager calls us back with a different value.
131//
133
134
136{
137 DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_INFO_LEVEL, "classpnp.sys is now unloading\n");
138
140 PoUnregisterPowerSettingCallback(PowerSettingNotificationHandle);
142 }
143
145 PoUnregisterPowerSettingCallback(ScreenStateNotificationHandle);
147 }
148
149
150 return STATUS_SUCCESS;
151}
152
153
154/*++////////////////////////////////////////////////////////////////////////////
155
156DriverEntry()
157
158Routine Description:
159
160 Temporary entry point needed to initialize the class system dll.
161 It doesn't do anything.
162
163Arguments:
164
165 DriverObject - Pointer to the driver object created by the system.
166
167Return Value:
168
169 STATUS_SUCCESS
170
171--*/
173NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
177 )
178{
181
182 return STATUS_SUCCESS;
183}
184
185
186
187/*++////////////////////////////////////////////////////////////////////////////
188
189ClassInitialize()
190
191Routine Description:
192
193 This routine is called by a class driver during its
194 DriverEntry routine to initialize the driver.
195
196Arguments:
197
198 Argument1 - Driver Object.
199 Argument2 - Registry Path.
200 InitializationData - Device-specific driver's initialization data.
201
202Return Value:
203
204 A valid return code for a DriverEntry routine.
205
206--*/
209ULONG
210NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
211ClassInitialize(
215 )
216{
219
220 PCLASS_DRIVER_EXTENSION driverExtension;
221
223
224
225
226 PAGED_CODE();
227
228 //
229 // Initialize the security cookie if needed.
230 //
231#ifndef __REACTOS__
232 if (InitSecurityCookie == FALSE) {
235 }
236#endif
237
238
239 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "\n\nSCSI Class Driver\n"));
240
242
243 //
244 // Validate the length of this structure. This is effectively a
245 // version check.
246 //
247
248 if (InitializationData->InitializationDataSize != sizeof(CLASS_INIT_DATA)) {
249
250 //
251 // This DebugPrint is to help third-party driver writers
252 //
253
254 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassInitialize: Class driver wrong version\n"));
256 }
257
258 //
259 // Check that each required entry is not NULL. Note that Shutdown, Flush and Error
260 // are not required entry points.
261 //
262
263 if ((!InitializationData->FdoData.ClassDeviceControl) ||
264 (!((InitializationData->FdoData.ClassReadWriteVerification) ||
265 (InitializationData->ClassStartIo))) ||
266 (!InitializationData->ClassAddDevice) ||
267 (!InitializationData->FdoData.ClassStartDevice)) {
268
269 //
270 // This DebugPrint is to help third-party driver writers
271 //
272
273 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
274 "ClassInitialize: Class device-specific driver missing required "
275 "FDO entry\n"));
276
278 }
279
280 if ((InitializationData->ClassEnumerateDevice) &&
281 ((!InitializationData->PdoData.ClassDeviceControl) ||
282 (!InitializationData->PdoData.ClassStartDevice) ||
283 (!((InitializationData->PdoData.ClassReadWriteVerification) ||
284 (InitializationData->ClassStartIo))))) {
285
286 //
287 // This DebugPrint is to help third-party driver writers
288 //
289
290 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassInitialize: Class device-specific missing "
291 "required PDO entry\n"));
292
294 }
295
296 if((InitializationData->FdoData.ClassStopDevice == NULL) ||
297 ((InitializationData->ClassEnumerateDevice != NULL) &&
298 (InitializationData->PdoData.ClassStopDevice == NULL))) {
299
300 //
301 // This DebugPrint is to help third-party driver writers
302 //
303
304 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassInitialize: Class device-specific missing "
305 "required PDO entry\n"));
308 }
309
310 //
311 // Setup the default power handlers if the class driver didn't provide
312 // any.
313 //
314
315 if(InitializationData->FdoData.ClassPowerDevice == NULL) {
316 InitializationData->FdoData.ClassPowerDevice = ClassMinimalPowerHandler;
317 }
318
319 if((InitializationData->ClassEnumerateDevice != NULL) &&
320 (InitializationData->PdoData.ClassPowerDevice == NULL)) {
321 InitializationData->PdoData.ClassPowerDevice = ClassMinimalPowerHandler;
322 }
323
324 //
325 // warn that unload is not supported
326 //
327 // ISSUE-2000/02/03-peterwie
328 // We should think about making this a fatal error.
329 //
330
331 if(InitializationData->ClassUnload == NULL) {
332
333 //
334 // This DebugPrint is to help third-party driver writers
335 //
336
337 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassInitialize: driver does not support unload %wZ\n",
338 RegistryPath));
339 }
340
341 //
342 // Create an extension for the driver object
343 //
344#ifdef _MSC_VER
345#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
346#endif
348
349 if(NT_SUCCESS(status)) {
350
351 //
352 // Copy the registry path into the driver extension so we can use it later
353 //
354
355 driverExtension->RegistryPath.Length = RegistryPath->Length;
356 driverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength;
357
358 driverExtension->RegistryPath.Buffer =
360 RegistryPath->MaximumLength,
361 '1CcS');
362
363 if(driverExtension->RegistryPath.Buffer == NULL) {
364
366 return status;
367 }
368
370 &(driverExtension->RegistryPath),
372
373 //
374 // Copy the initialization data into the driver extension so we can reuse
375 // it during our add device routine
376 //
377
379 &(driverExtension->InitData),
381 sizeof(CLASS_INIT_DATA));
382
383 driverExtension->DeviceCount = 0;
384
385 ClassInitializeDispatchTables(driverExtension);
386
387 } else if (status == STATUS_OBJECT_NAME_COLLISION) {
388
389 //
390 // The extension already exists - get a pointer to it
391 //
392#ifdef _MSC_VER
393#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
394#endif
396
397 NT_ASSERT(driverExtension != NULL);
398
399 } else {
400
401 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassInitialize: Class driver extension could not be "
402 "allocated %lx\n", status));
403 return status;
404 }
405
406
407 //
408 // Update driver object with entry points.
409 //
410
411#ifdef _MSC_VER
412#pragma prefast(push)
413#pragma prefast(disable:28175, "Accessing DRIVER_OBJECT fileds is OK here since this function " \
414 "is supposed to be invoked from DriverEntry only")
415#endif
427
428 if (InitializationData->ClassStartIo) {
429 DriverObject->DriverStartIo = ClasspStartIo;
430 }
431
432 if ((InitializationData->ClassUnload) && (ClassPnpAllowUnload == TRUE)) {
433 DriverObject->DriverUnload = ClassUnload;
434 } else {
435 DriverObject->DriverUnload = NULL;
436 }
437
438 DriverObject->DriverExtension->AddDevice = ClassAddDevice;
439#ifdef _MSC_VER
440#pragma prefast(pop)
441#endif
442
443
444 //
445 // Register for event tracing
446 //
447 if (driverExtension->EtwHandle == 0) {
449 NULL,
450 NULL,
451 &driverExtension->EtwHandle);
452 if (!NT_SUCCESS(status)) {
453 driverExtension->EtwHandle = 0;
454 }
456 }
457
458
459 //
460 // Ensure these are only initialized once.
461 //
462 if (IdlePowerFDOList.Flink == NULL) {
465 }
466
468 return status;
469} // end ClassInitialize()
470
471/*++////////////////////////////////////////////////////////////////////////////
472
473ClassInitializeEx()
474
475Routine Description:
476
477 This routine is allows the caller to do any extra initialization or
478 setup that is not done in ClassInitialize. The operation is
479 controlled by the GUID that is passed and the contents of the Data
480 parameter is dependent upon the GUID.
481
482 This is the list of supported operations:
483
484 GUID_CLASSPNP_QUERY_REGINFOEX == CLASS_QUERY_WMI_REGINFO_EX_LIST
485
486 Initialized classpnp to callback a PCLASS_QUERY_WMI_REGINFO_EX
487 callback instead of a PCLASS_QUERY_WMI_REGINFO callback. The
488 former callback allows the driver to specify the name of the
489 mof resource.
490
491 GUID_CLASSPNP_SENSEINFO2 == CLASS_INTERPRET_SENSE_INFO2
492
493 Initialize classpnp to callback into class drive for interpretation
494 of all sense info, and to indicate the count of "history" to keep
495 for each packet.
496
497 GUID_CLASSPNP_WORKING_SET == CLASS_WORKING_SET
498
499 Allow class driver to override the min and max working set transfer
500 packet value used in classpnp.
501
502 GUID_CLASSPNP_SRB_SUPPORT == ULONG
503
504 Allow class driver to provide supported SRB types.
505
506Arguments:
507
508 DriverObject
509 Guid
510 Data
511
512Return Value:
513
514 Status Code
515
516--*/
519ULONG
520NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
521ClassInitializeEx(
525 )
526{
527 PCLASS_DRIVER_EXTENSION driverExtension;
528
530
531 PAGED_CODE();
532
533#ifdef _MSC_VER
534#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
535#endif
537
538 if (driverExtension == NULL)
539 {
542 }
543
545 {
547
548 //
549 // Indicate the device supports PCLASS_QUERY_REGINFO_EX
550 // callback instead of PCLASS_QUERY_REGINFO callback.
551 //
553
554 if (List->Size == sizeof(CLASS_QUERY_WMI_REGINFO_EX_LIST))
555 {
556 driverExtension->ClassFdoQueryWmiRegInfoEx = List->ClassFdoQueryWmiRegInfoEx;
557 driverExtension->ClassPdoQueryWmiRegInfoEx = List->ClassPdoQueryWmiRegInfoEx;
559 } else {
561 }
562 }
564 {
567
568 // only try to allocate memory for cached copy if size is correct
569 if (infoOriginal->Size != sizeof(CLASS_WORKING_SET))
570 {
571 // incorrect size -- client programming error
573 }
574 else
575 {
576 info = ExAllocatePoolWithTag(NonPagedPoolNx,
577 sizeof(CLASS_WORKING_SET),
579 );
580 if (info == NULL)
581 {
583 }
584 else
585 {
586 // cache the structure internally
587 RtlCopyMemory(info, infoOriginal, sizeof(CLASS_WORKING_SET));
589 }
590 }
591 // if we successfully cached a copy, validate all the data within
592 if (NT_SUCCESS(status))
593 {
594 if (info->Size != sizeof(CLASS_WORKING_SET))
595 {
596 // incorrect size -- client programming error
598 }
599 else if (info->XferPacketsWorkingSetMaximum > CLASS_WORKING_SET_MAXIMUM)
600 {
601 // too many requested in the working set
603 }
604 else if (info->XferPacketsWorkingSetMinimum > CLASS_WORKING_SET_MAXIMUM)
605 {
606 // too many requested in the working set
608 }
609 else if (driverExtension->InitData.FdoData.DeviceType != FILE_DEVICE_CD_ROM)
610 {
611 // classpnp developer wants to restrict this code path
612 // for now to CDROM devices only.
614 }
615 else if (driverExtension->WorkingSet != NULL)
616 {
617 // not allowed to change it once it is set for a driver
620 }
621 }
622 // save results or cleanup
623 if (NT_SUCCESS(status))
624 {
625 driverExtension->WorkingSet = info; info = NULL;
626 }
627 else
628 {
629 FREE_POOL( info );
630 }
631 }
633 {
636
637 // only try to allocate memory for cached copy if size is correct
638 if (infoOriginal->Size != sizeof(CLASS_INTERPRET_SENSE_INFO2))
639 {
640 // incorrect size -- client programming error
642 }
643 else
644 {
645 info = ExAllocatePoolWithTag(NonPagedPoolNx,
648 );
649 if (info == NULL)
650 {
652 }
653 else
654 {
655 // cache the structure internally
656 RtlCopyMemory(info, infoOriginal, sizeof(CLASS_INTERPRET_SENSE_INFO2));
658 }
659 }
660
661 // if we successfully cached a copy, validate all the data within
662 if (NT_SUCCESS(status))
663 {
664 if (info->Size != sizeof(CLASS_INTERPRET_SENSE_INFO2))
665 {
666 // incorrect size -- client programming error
668 }
670 {
671 // incorrect count -- client programming error
673 }
674 else if (info->Compress == NULL)
675 {
676 // Compression of the history is required to be supported
678 }
679 else if (info->HistoryCount == 0)
680 {
681 // History count cannot be zero
683 }
684 else if (info->Interpret == NULL)
685 {
686 // Updated interpret sense info function is required
688 }
689 else if (driverExtension->InitData.FdoData.DeviceType != FILE_DEVICE_CD_ROM)
690 {
691 // classpnp developer wants to restrict this code path
692 // for now to CDROM devices only.
694 }
695 else if (driverExtension->InterpretSenseInfo != NULL)
696 {
697 // not allowed to change it once it is set for a driver
700 }
701 }
702
703 // save results or cleanup
704 if (NT_SUCCESS(status))
705 {
706 driverExtension->InterpretSenseInfo = info; info = NULL;
707 }
708 else
709 {
710 FREE_POOL( info );
711 }
712 }
714 {
715 ULONG srbSupport = *((PULONG)Data);
716
717 //
718 // Validate that at least one of the supported bit flags is set. Assume
719 // all class drivers support SCSI_REQUEST_BLOCK as a class driver that
720 // supports only extended SRB is not feasible.
721 //
722 if ((srbSupport &
724 driverExtension->SrbSupport = srbSupport;
726
727 //
728 // Catch cases of a class driver reporting only extended SRB support
729 //
730 if ((driverExtension->SrbSupport & CLASS_SRB_SCSI_REQUEST_BLOCK) == 0) {
732 }
733 } else {
735 }
736 }
737 else
738 {
740 }
741
742 return status;
743
744} // end ClassInitializeEx()
745
746/*++////////////////////////////////////////////////////////////////////////////
747
748ClassUnload()
749
750Routine Description:
751
752 called when there are no more references to the driver. this allows
753 drivers to be updated without rebooting.
754
755Arguments:
756
757 DriverObject - a pointer to the driver object that is being unloaded
758
759Status:
760
761--*/
762VOID
763NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
766 )
767{
768 PCLASS_DRIVER_EXTENSION driverExtension;
769
770 PAGED_CODE();
771
772 NT_ASSERT( DriverObject->DeviceObject == NULL );
773
774#ifdef _MSC_VER
775#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
776#endif
778
779
780 if (driverExtension == NULL)
781 {
783 return;
784 }
785
786 NT_ASSERT(driverExtension->RegistryPath.Buffer != NULL);
787 NT_ASSERT(driverExtension->InitData.ClassUnload != NULL);
788
789 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClassUnload: driver unloading %wZ\n",
790 &driverExtension->RegistryPath));
791
792 //
793 // attempt to process the driver's unload routine first.
794 //
795
796 driverExtension->InitData.ClassUnload(DriverObject);
797
798 //
799 // free own allocated resources and return
800 //
801
802 FREE_POOL( driverExtension->WorkingSet );
803 FREE_POOL( driverExtension->InterpretSenseInfo );
804 FREE_POOL( driverExtension->RegistryPath.Buffer );
805 driverExtension->RegistryPath.Length = 0;
806 driverExtension->RegistryPath.MaximumLength = 0;
807
808
809 //
810 // Unregister ETW
811 //
812 if (driverExtension->EtwHandle != 0) {
813 EtwUnregister(driverExtension->EtwHandle);
814 driverExtension->EtwHandle = 0;
815
817 }
818
819
820 return;
821} // end ClassUnload()
822
823/*++////////////////////////////////////////////////////////////////////////////
824
825ClassAddDevice()
826
827Routine Description:
828
829 SCSI class driver add device routine. This is called by pnp when a new
830 physical device come into being.
831
832 This routine will call out to the class driver to verify that it should
833 own this device then will create and attach a device object and then hand
834 it to the driver to initialize and create symbolic links
835
836Arguments:
837
838 DriverObject - a pointer to the driver object that this is being created for
839 PhysicalDeviceObject - a pointer to the physical device object
840
841Status: STATUS_NO_SUCH_DEVICE if the class driver did not want this device
842 STATUS_SUCCESS if the creation and attachment was successful
843 status of device creation and initialization
844
845--*/
847#ifdef _MSC_VER
848#pragma prefast(suppress:28152, "We expect the class driver to clear the DO_DEVICE_INITIALIZING flag in its AddDevice routine.")
849#endif
850NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
854 )
855{
856#ifdef _MSC_VER
857#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
858#endif
860
862
863 PAGED_CODE();
864
865
866 status = driverExtension->InitData.ClassAddDevice(DriverObject,
868
869 return status;
870} // end ClassAddDevice()
871
872/*++////////////////////////////////////////////////////////////////////////////
873
874ClassDispatchPnp()
875
876Routine Description:
877
878 Storage class driver pnp routine. This is called by the io system when
879 a PNP request is sent to the device.
880
881Arguments:
882
883 DeviceObject - pointer to the device object
884
885 Irp - pointer to the io request packet
886
887Return Value:
888
889 status
890
891--*/
893NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
896 IN PIRP Irp
897 )
898{
899 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
900 BOOLEAN isFdo = commonExtension->IsFdo;
901
902 PCLASS_DRIVER_EXTENSION driverExtension;
903 PCLASS_INIT_DATA initData;
904 PCLASS_DEV_INFO devInfo;
905
907
908 NTSTATUS status = Irp->IoStatus.Status;
909 BOOLEAN completeRequest = TRUE;
910 BOOLEAN lockReleased = FALSE;
911
912
913 PAGED_CODE();
914
915 //
916 // Extract all the useful information out of the driver object
917 // extension
918 //
919
920#ifdef _MSC_VER
921#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
922#endif
924
925 if (driverExtension){
926
927 initData = &(driverExtension->InitData);
928
929 if(isFdo) {
930 devInfo = &(initData->FdoData);
931 } else {
932 devInfo = &(initData->PdoData);
933 }
934
936
937 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): minor code %#x for %s %p\n",
939 irpStack->MinorFunction,
940 isFdo ? "fdo" : "pdo",
941 DeviceObject));
942 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): previous %#x, current %#x\n",
944 commonExtension->PreviousState,
945 commonExtension->CurrentState));
946
947
948 switch(irpStack->MinorFunction) {
949
950 case IRP_MN_START_DEVICE: {
951
952 //
953 // if this is sent to the FDO we should forward it down the
954 // attachment chain before we start the FDO.
955 //
956
957 if (isFdo) {
958 status = ClassForwardIrpSynchronous(commonExtension, Irp);
959 }
960 else {
962 }
963
964 if (NT_SUCCESS(status)){
965 status = Irp->IoStatus.Status = ClassPnpStartDevice(DeviceObject);
966 }
967
968 break;
969 }
970
971
973
975 irpStack->Parameters.QueryDeviceRelations.Type;
976
977 PDEVICE_RELATIONS deviceRelations = NULL;
978
979
980 if(!isFdo) {
981
983
984 //
985 // Device relations has one entry built in to it's size.
986 //
987
989
990 deviceRelations = ExAllocatePoolWithTag(PagedPool,
991 sizeof(DEVICE_RELATIONS),
992 '2CcS');
993
994 if(deviceRelations != NULL) {
995
996 RtlZeroMemory(deviceRelations,
997 sizeof(DEVICE_RELATIONS));
998
999 Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
1000
1001 deviceRelations->Count = 1;
1002 deviceRelations->Objects[0] = DeviceObject;
1003 ObReferenceObject(deviceRelations->Objects[0]);
1004
1006 }
1007
1008 } else {
1009 //
1010 // PDO's just complete enumeration requests without altering
1011 // the status.
1012 //
1013
1014 status = Irp->IoStatus.Status;
1015 }
1016
1017 break;
1018
1019 } else if (type == BusRelations) {
1020
1021 NT_ASSERT(commonExtension->IsInitialized);
1022
1023 //
1024 // Make sure we support enumeration
1025 //
1026
1027 if(initData->ClassEnumerateDevice == NULL) {
1028
1029 //
1030 // Just send the request down to the lower driver. Perhaps
1031 // It can enumerate children.
1032 //
1033
1034 } else {
1035
1036 //
1037 // Re-enumerate the device
1038 //
1039
1041
1042 if(!NT_SUCCESS(status)) {
1043 completeRequest = TRUE;
1044 break;
1045 }
1046 }
1047 }
1048
1049
1052 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1053 completeRequest = FALSE;
1054
1055 break;
1056 }
1057
1058 case IRP_MN_QUERY_ID: {
1059
1060 BUS_QUERY_ID_TYPE idType = irpStack->Parameters.QueryId.IdType;
1061 UNICODE_STRING unicodeString;
1062
1063
1064 if(isFdo) {
1065
1066
1067 //
1068 // FDO's should just forward the query down to the lower
1069 // device objects
1070 //
1071
1074
1075 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1076 completeRequest = FALSE;
1077 break;
1078 }
1079
1080 //
1081 // PDO's need to give an answer - this is easy for now
1082 //
1083
1084 RtlInitUnicodeString(&unicodeString, NULL);
1085
1087 idType,
1088 &unicodeString);
1089
1091 //
1092 // The driver doesn't implement this ID (whatever it is).
1093 // Use the status out of the IRP so that we don't mangle a
1094 // response from someone else.
1095 //
1096
1097 status = Irp->IoStatus.Status;
1098 } else if(NT_SUCCESS(status)) {
1099 Irp->IoStatus.Information = (ULONG_PTR) unicodeString.Buffer;
1100 } else {
1101 Irp->IoStatus.Information = (ULONG_PTR) NULL;
1102 }
1103
1104 break;
1105 }
1106
1109
1110
1111 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Processing QUERY_%s irp\n",
1113 ((irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ?
1114 "STOP" : "REMOVE")));
1115
1116 //
1117 // If this device is in use for some reason (paging, etc...)
1118 // then we need to fail the request.
1119 //
1120
1121 if(commonExtension->PagingPathCount != 0) {
1122
1123 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): device is in paging "
1124 "path and cannot be removed\n",
1125 DeviceObject, Irp));
1127 break;
1128 }
1129
1130
1131 //
1132 // Check with the class driver to see if the query operation
1133 // can succeed.
1134 //
1135
1136 if(irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) {
1138 irpStack->MinorFunction);
1139 } else {
1141 irpStack->MinorFunction);
1142 }
1143
1144 if(NT_SUCCESS(status)) {
1145
1146 //
1147 // ASSERT that we never get two queries in a row, as
1148 // this will severly mess up the state machine
1149 //
1150 NT_ASSERT(commonExtension->CurrentState != irpStack->MinorFunction);
1151 commonExtension->PreviousState = commonExtension->CurrentState;
1152 commonExtension->CurrentState = irpStack->MinorFunction;
1153
1154 if(isFdo) {
1155 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Forwarding QUERY_"
1156 "%s irp\n", DeviceObject, Irp,
1157 ((irpStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ?
1158 "STOP" : "REMOVE")));
1159 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1160 }
1161 }
1162
1163
1164 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Final status == %x\n",
1166
1167 break;
1168 }
1169
1172
1173
1174 //
1175 // Check with the class driver to see if the query or cancel
1176 // operation can succeed.
1177 //
1178
1179 if(irpStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) {
1181 irpStack->MinorFunction);
1182 NT_ASSERTMSG("ClassDispatchPnp !! CANCEL_STOP_DEVICE should never be failed\n", NT_SUCCESS(status));
1183 } else {
1185 irpStack->MinorFunction);
1186 NT_ASSERTMSG("ClassDispatchPnp !! CANCEL_REMOVE_DEVICE should never be failed\n", NT_SUCCESS(status));
1187 }
1188
1189 Irp->IoStatus.Status = status;
1190
1191 //
1192 // We got a CANCEL - roll back to the previous state only
1193 // if the current state is the respective QUERY state.
1194 //
1195
1196 if(((irpStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) &&
1197 (commonExtension->CurrentState == IRP_MN_QUERY_STOP_DEVICE)
1198 ) ||
1200 (commonExtension->CurrentState == IRP_MN_QUERY_REMOVE_DEVICE)
1201 )
1202 ) {
1203
1204 commonExtension->CurrentState =
1205 commonExtension->PreviousState;
1206 commonExtension->PreviousState = 0xff;
1207
1208 }
1209
1210
1211 if(isFdo) {
1212
1213
1216 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1217 completeRequest = FALSE;
1218 } else {
1220 }
1221
1222 break;
1223 }
1224
1225 case IRP_MN_STOP_DEVICE: {
1226
1227
1228 //
1229 // These all mean nothing to the class driver currently. The
1230 // port driver will handle all queueing when necessary.
1231 //
1232
1233 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): got stop request for %s\n",
1235 (isFdo ? "fdo" : "pdo")
1236 ));
1237
1238 NT_ASSERT(commonExtension->PagingPathCount == 0);
1239
1240 //
1241 // ISSUE-2000/02/03-peterwie
1242 // if we stop the timer here then it means no class driver can
1243 // do i/o in its ClassStopDevice routine. This is because the
1244 // retry (among other things) is tied into the tick handler
1245 // and disabling retries could cause the class driver to deadlock.
1246 // Currently no class driver we're aware of issues i/o in its
1247 // Stop routine but this is a case we may want to defend ourself
1248 // against.
1249 //
1250
1252
1253
1255
1256 NT_ASSERTMSG("ClassDispatchPnp !! STOP_DEVICE should never be failed\n", NT_SUCCESS(status));
1257
1258 if(isFdo) {
1259 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1260 }
1261
1262 if(NT_SUCCESS(status)) {
1263 commonExtension->CurrentState = irpStack->MinorFunction;
1264 commonExtension->PreviousState = 0xff;
1265 }
1266
1267
1268 break;
1269 }
1270
1273 UCHAR removeType = irpStack->MinorFunction;
1274
1275 //
1276 // Log a sytem event when non-removable disks are surprise-removed.
1277 //
1278 if (isFdo &&
1279 (removeType == IRP_MN_SURPRISE_REMOVAL)) {
1280
1281 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1282 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
1283 BOOLEAN logSurpriseRemove = TRUE;
1284 STORAGE_BUS_TYPE busType = fdoExtension->DeviceDescriptor->BusType;
1285
1286 //
1287 // Don't log an event for VHDs
1288 //
1289 if (busType == BusTypeFileBackedVirtual) {
1290 logSurpriseRemove = FALSE;
1291
1292 } else if (fdoData->HotplugInfo.MediaRemovable) {
1293 logSurpriseRemove = FALSE;
1294
1295 } else if (fdoData->HotplugInfo.DeviceHotplug && ( busType == BusTypeUsb || busType == BusType1394)) {
1296
1297 /*
1298 This device is reported as DeviceHotplug but since the busType is Usb or 1394, don't log an event
1299 Note that some storage arrays may report DeviceHotplug and we would like to log an event in those cases
1300 */
1301
1302 logSurpriseRemove = FALSE;
1303 }
1304
1305 if (logSurpriseRemove) {
1306
1308 }
1309
1310 }
1311
1312 if (commonExtension->PagingPathCount != 0) {
1313 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): paging device is getting removed!", DeviceObject, Irp));
1314 }
1315
1316 //
1317 // Release the lock for this IRP before calling in.
1318 //
1320 lockReleased = TRUE;
1321
1322 /*
1323 * Set IsRemoved before propagating the REMOVE down the stack.
1324 * This keeps class-initiated I/O (e.g. the MCN irp) from getting sent
1325 * after we propagate the remove.
1326 */
1327 commonExtension->IsRemoved = REMOVE_PENDING;
1328
1329 /*
1330 * If a timer was started on the device, stop it.
1331 */
1333
1334 /*
1335 * "Fire-and-forget" the remove irp to the lower stack.
1336 * Don't touch the irp (or the irp stack!) after this.
1337 */
1338 if (isFdo) {
1339
1340
1342 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1344 completeRequest = FALSE;
1345 }
1346 else {
1348 }
1349
1350 /*
1351 * Do our own cleanup and call the class driver's remove
1352 * cleanup routine.
1353 * For IRP_MN_REMOVE_DEVICE, this also deletes our device object,
1354 * so don't touch the extension after this.
1355 */
1356 commonExtension->PreviousState = commonExtension->CurrentState;
1357 commonExtension->CurrentState = removeType;
1358 ClassRemoveDevice(DeviceObject, removeType);
1359
1360 break;
1361 }
1362
1364
1366 BOOLEAN setPagable;
1367
1368
1369 switch(type) {
1370
1371 case DeviceUsageTypePaging: {
1372
1373 if ((irpStack->Parameters.UsageNotification.InPath) &&
1374 (commonExtension->CurrentState != IRP_MN_START_DEVICE)) {
1375
1376 //
1377 // Device isn't started. Don't allow adding a
1378 // paging file, but allow a removal of one.
1379 //
1380
1382 break;
1383 }
1384
1385 NT_ASSERT(commonExtension->IsInitialized);
1386
1387 /*
1388 * Ensure that this user thread is not suspended while we are holding the PathCountEvent.
1389 */
1391
1392 (VOID)KeWaitForSingleObject(&commonExtension->PathCountEvent,
1394 FALSE, NULL);
1396
1397 //
1398 // If the volume is removable we should try to lock it in
1399 // place or unlock it once per paging path count
1400 //
1401
1402 if (commonExtension->IsFdo){
1405 Irp,
1407 (BOOLEAN)irpStack->Parameters.UsageNotification.InPath);
1408 }
1409
1410 if (!NT_SUCCESS(status)){
1411 KeSetEvent(&commonExtension->PathCountEvent, IO_NO_INCREMENT, FALSE);
1413 break;
1414 }
1415
1416 //
1417 // if removing last paging device, need to set DO_POWER_PAGABLE
1418 // bit here, and possible re-set it below on failure.
1419 //
1420
1421 setPagable = FALSE;
1422
1423 if ((!irpStack->Parameters.UsageNotification.InPath) &&
1424 (commonExtension->PagingPathCount == 1)) {
1425
1426 //
1427 // removing last paging file
1428 // must have DO_POWER_PAGABLE bits set, but only
1429 // if none set the DO_POWER_INRUSH bit and no other special files
1430 //
1431
1432 if (TEST_FLAG(DeviceObject->Flags, DO_POWER_INRUSH)) {
1433 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1434 "paging file removed, but "
1435 "DO_POWER_INRUSH was set, so NOT "
1436 "setting DO_POWER_PAGABLE\n",
1437 DeviceObject, Irp));
1438 } else if ((commonExtension->HibernationPathCount == 0) &&
1439 (commonExtension->DumpPathCount == 0)) {
1440 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1441 "paging file removed, "
1442 "setting DO_POWER_PAGABLE\n",
1443 DeviceObject, Irp));
1445 setPagable = TRUE;
1446 }
1447
1448 }
1449
1450 //
1451 // forward the irp before finishing handling the
1452 // special cases
1453 //
1454
1455 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1456
1457 //
1458 // now deal with the failure and success cases.
1459 // note that we are not allowed to fail the irp
1460 // once it is sent to the lower drivers.
1461 //
1462
1463 if (NT_SUCCESS(status)) {
1464
1466 (volatile LONG *)&commonExtension->PagingPathCount,
1467 irpStack->Parameters.UsageNotification.InPath);
1468
1469 if (irpStack->Parameters.UsageNotification.InPath) {
1470 if (commonExtension->PagingPathCount == 1) {
1471 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): "
1472 "Clearing PAGABLE bit\n",
1473 DeviceObject, Irp));
1475
1476
1477 }
1478
1479 }
1480
1481 } else {
1482
1483 //
1484 // cleanup the changes done above
1485 //
1486
1487 if (setPagable == TRUE) {
1488 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Unsetting "
1489 "PAGABLE bit due to irp failure\n",
1490 DeviceObject, Irp));
1492 setPagable = FALSE;
1493 }
1494
1495 //
1496 // relock or unlock the media if needed.
1497 //
1498
1499 if (commonExtension->IsFdo) {
1500
1503 Irp,
1505 (BOOLEAN)!irpStack->Parameters.UsageNotification.InPath);
1506 }
1507 }
1508
1509 //
1510 // set the event so the next one can occur.
1511 //
1512
1513 KeSetEvent(&commonExtension->PathCountEvent,
1516 break;
1517 }
1518
1520
1521 //
1522 // if removing last hiber device, need to set DO_POWER_PAGABLE
1523 // bit here, and possible re-set it below on failure.
1524 //
1525
1526 setPagable = FALSE;
1527
1528 if ((!irpStack->Parameters.UsageNotification.InPath) &&
1529 (commonExtension->HibernationPathCount == 1)) {
1530
1531 //
1532 // removing last hiber file
1533 // must have DO_POWER_PAGABLE bits set, but only
1534 // if none set the DO_POWER_INRUSH bit and no other special files
1535 //
1536
1537 if (TEST_FLAG(DeviceObject->Flags, DO_POWER_INRUSH)) {
1538 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1539 "hiber file removed, but "
1540 "DO_POWER_INRUSH was set, so NOT "
1541 "setting DO_POWER_PAGABLE\n",
1542 DeviceObject, Irp));
1543 } else if ((commonExtension->PagingPathCount == 0) &&
1544 (commonExtension->DumpPathCount == 0)) {
1545 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1546 "hiber file removed, "
1547 "setting DO_POWER_PAGABLE\n",
1548 DeviceObject, Irp));
1550 setPagable = TRUE;
1551 }
1552
1553 }
1554
1555 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1556 if (!NT_SUCCESS(status)) {
1557
1558 if (setPagable == TRUE) {
1559 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Unsetting "
1560 "PAGABLE bit due to irp failure\n",
1561 DeviceObject, Irp));
1563 setPagable = FALSE;
1564 }
1565
1566 } else {
1567
1569 (volatile LONG *)&commonExtension->HibernationPathCount,
1570 irpStack->Parameters.UsageNotification.InPath
1571 );
1572
1573 if ((irpStack->Parameters.UsageNotification.InPath) &&
1574 (commonExtension->HibernationPathCount == 1)) {
1575 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): "
1576 "Clearing PAGABLE bit\n",
1577 DeviceObject, Irp));
1579 }
1580 }
1581
1582 break;
1583 }
1584
1586
1587 //
1588 // if removing last dump device, need to set DO_POWER_PAGABLE
1589 // bit here, and possible re-set it below on failure.
1590 //
1591
1592 setPagable = FALSE;
1593
1594 if ((!irpStack->Parameters.UsageNotification.InPath) &&
1595 (commonExtension->DumpPathCount == 1)) {
1596
1597 //
1598 // removing last dump file
1599 // must have DO_POWER_PAGABLE bits set, but only
1600 // if none set the DO_POWER_INRUSH bit and no other special files
1601 //
1602
1603 if (TEST_FLAG(DeviceObject->Flags, DO_POWER_INRUSH)) {
1604 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1605 "dump file removed, but "
1606 "DO_POWER_INRUSH was set, so NOT "
1607 "setting DO_POWER_PAGABLE\n",
1608 DeviceObject, Irp));
1609 } else if ((commonExtension->PagingPathCount == 0) &&
1610 (commonExtension->HibernationPathCount == 0)) {
1611 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Last "
1612 "dump file removed, "
1613 "setting DO_POWER_PAGABLE\n",
1614 DeviceObject, Irp));
1616 setPagable = TRUE;
1617 }
1618
1619 }
1620
1621 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1622 if (!NT_SUCCESS(status)) {
1623
1624 if (setPagable == TRUE) {
1625 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): Unsetting "
1626 "PAGABLE bit due to irp failure\n",
1627 DeviceObject, Irp));
1629 setPagable = FALSE;
1630 }
1631
1632 } else {
1633
1635 (volatile LONG *)&commonExtension->DumpPathCount,
1636 irpStack->Parameters.UsageNotification.InPath
1637 );
1638
1639 if ((irpStack->Parameters.UsageNotification.InPath) &&
1640 (commonExtension->DumpPathCount == 1)) {
1641 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): "
1642 "Clearing PAGABLE bit\n",
1643 DeviceObject, Irp));
1645 }
1646 }
1647
1648 break;
1649 }
1650
1651 case DeviceUsageTypeBoot: {
1652
1653 if (isFdo) {
1655
1656 fdoData = ((PFUNCTIONAL_DEVICE_EXTENSION)(DeviceObject->DeviceExtension))->PrivateFdoData;
1657
1658
1659 //
1660 // If boot disk has removal policy as RemovalPolicyExpectSurpriseRemoval (e.g. disk is hotplug-able),
1661 // change the removal policy to RemovalPolicyExpectOrderlyRemoval.
1662 // This will cause the write cache of disk to be enabled on subsequent start Fdo (next boot).
1663 //
1664 if ((fdoData != NULL) &&
1665 fdoData->HotplugInfo.DeviceHotplug) {
1666
1667 fdoData->HotplugInfo.DeviceHotplug = FALSE;
1668 fdoData->HotplugInfo.MediaRemovable = FALSE;
1669
1670 ClassSetDeviceParameter((PFUNCTIONAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension,
1674 }
1675 }
1676
1677 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1678 break;
1679 }
1680
1681 default: {
1683 break;
1684 }
1685 }
1686 break;
1687 }
1688
1690
1691 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): QueryCapabilities\n",
1692 DeviceObject, Irp));
1693
1694 if(!isFdo) {
1695
1698 irpStack->Parameters.DeviceCapabilities.Capabilities
1699 );
1700
1701 break;
1702
1703 } else {
1704
1705 PDEVICE_CAPABILITIES deviceCapabilities;
1706 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
1708
1709 fdoExtension = DeviceObject->DeviceExtension;
1710 fdoData = fdoExtension->PrivateFdoData;
1711 deviceCapabilities =
1712 irpStack->Parameters.DeviceCapabilities.Capabilities;
1713
1714 //
1715 // forward the irp before handling the special cases
1716 //
1717
1718 status = ClassForwardIrpSynchronous(commonExtension, Irp);
1719 if (!NT_SUCCESS(status)) {
1720 break;
1721 }
1722
1723 //
1724 // we generally want to remove the device from the hotplug
1725 // applet, which requires the SR-OK bit to be set.
1726 // only when the user specifies that they are capable of
1727 // safely removing things do we want to clear this bit
1728 // (saved in WriteCacheEnableOverride)
1729 //
1730 // setting of this bit is done either above, or by the
1731 // lower driver.
1732 //
1733 // note: may not be started, so check we have FDO data first.
1734 //
1735
1736 if (fdoData &&
1738 if (deviceCapabilities->SurpriseRemovalOK) {
1739 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "Classpnp: Clearing SR-OK bit in "
1740 "device capabilities due to hotplug "
1741 "device or media\n"));
1742 }
1743 deviceCapabilities->SurpriseRemovalOK = FALSE;
1744 }
1745 break;
1746
1747 } // end QUERY_CAPABILITIES for FDOs
1748
1749 break;
1750
1751
1752 } // end QUERY_CAPABILITIES
1753
1754 default: {
1755
1756 if (isFdo){
1757
1758
1760
1762 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
1763
1764 completeRequest = FALSE;
1765 }
1766
1767 break;
1768 }
1769 }
1770 }
1771 else {
1772 NT_ASSERT(driverExtension);
1774 }
1775
1776 if (completeRequest){
1777 Irp->IoStatus.Status = status;
1778
1779 if (!lockReleased){
1781 }
1782
1784
1785 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): leaving with previous %#x, current %#x.", DeviceObject, Irp, commonExtension->PreviousState, commonExtension->CurrentState));
1786 }
1787 else {
1788 /*
1789 * The irp is already completed so don't touch it.
1790 * This may be a remove so don't touch the device extension.
1791 */
1792 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "ClassDispatchPnp (%p,%p): leaving.", DeviceObject, Irp));
1793 }
1794
1795 return status;
1796} // end ClassDispatchPnp()
1797
1798
1799/*++////////////////////////////////////////////////////////////////////////////
1800
1801ClassPnpStartDevice()
1802
1803Routine Description:
1804
1805 Storage class driver routine for IRP_MN_START_DEVICE requests.
1806 This routine kicks off any device specific initialization
1807
1808Arguments:
1809
1810 DeviceObject - a pointer to the device object
1811
1812 Irp - a pointer to the io request packet
1813
1814Return Value:
1815
1816 none
1817
1818--*/
1820{
1821 PCLASS_DRIVER_EXTENSION driverExtension;
1822 PCLASS_INIT_DATA initData;
1823
1824 PCLASS_DEV_INFO devInfo;
1825
1826 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
1827 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1828 BOOLEAN isFdo = commonExtension->IsFdo;
1829
1830 BOOLEAN isMountedDevice = TRUE;
1831 BOOLEAN isPortable = FALSE;
1832
1834 PDEVICE_POWER_DESCRIPTOR powerDescriptor = NULL;
1835
1836
1837 PAGED_CODE();
1838
1839#ifdef _MSC_VER
1840#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
1841#endif
1842 driverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, CLASS_DRIVER_EXTENSION_KEY);
1843
1844 initData = &(driverExtension->InitData);
1845 if(isFdo) {
1846 devInfo = &(initData->FdoData);
1847 } else {
1848 devInfo = &(initData->PdoData);
1849 }
1850
1851 NT_ASSERT(devInfo->ClassInitDevice != NULL);
1852 NT_ASSERT(devInfo->ClassStartDevice != NULL);
1853
1854 if (!commonExtension->IsInitialized){
1855
1856 //
1857 // perform FDO/PDO specific initialization
1858 //
1859
1860 if (isFdo){
1861 STORAGE_PROPERTY_ID propertyId;
1862
1863 //
1864 // allocate a private extension for class data
1865 //
1866
1867 if (fdoExtension->PrivateFdoData == NULL) {
1868 fdoExtension->PrivateFdoData = ExAllocatePoolWithTag(NonPagedPoolNx,
1869 sizeof(CLASS_PRIVATE_FDO_DATA),
1871 );
1872 }
1873
1874 if (fdoExtension->PrivateFdoData == NULL) {
1875 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate for private fdo data\n"));
1877 }
1878
1879 RtlZeroMemory(fdoExtension->PrivateFdoData, sizeof(CLASS_PRIVATE_FDO_DATA));
1880
1881
1882#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1883 //
1884 // Allocate a structure to hold more data than what we can put in FUNCTIONAL_DEVICE_EXTENSION.
1885 // This structure's memory is managed by classpnp, so it is more extensible.
1886 //
1887 if (fdoExtension->AdditionalFdoData == NULL) {
1888 fdoExtension->AdditionalFdoData = ExAllocatePoolWithTag(NonPagedPoolNx,
1889 sizeof(ADDITIONAL_FDO_DATA),
1891 );
1892 }
1893
1894 if (fdoExtension->AdditionalFdoData == NULL) {
1895 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate memory for the additional data structure.\n"));
1897 }
1898
1899 RtlZeroMemory(fdoExtension->AdditionalFdoData, sizeof(ADDITIONAL_FDO_DATA));
1900#endif
1901
1902 status = ClasspInitializeTimer(fdoExtension);
1903 if (NT_SUCCESS(status) == FALSE) {
1904 FREE_POOL(fdoExtension->PrivateFdoData);
1905#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1906 FREE_POOL(fdoExtension->AdditionalFdoData);
1907#endif
1908 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Failed to initialize tick timer\n"));
1910 }
1911
1912 //
1913 // allocate LowerLayerSupport for class data
1914 //
1915
1916 if (fdoExtension->FunctionSupportInfo == NULL) {
1917 fdoExtension->FunctionSupportInfo = (PCLASS_FUNCTION_SUPPORT_INFO)ExAllocatePoolWithTag(NonPagedPoolNx,
1919 '3BcS'
1920 );
1921 }
1922
1923 if (fdoExtension->FunctionSupportInfo == NULL) {
1924 ClasspDeleteTimer(fdoExtension);
1925 FREE_POOL(fdoExtension->PrivateFdoData);
1926#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1927 FREE_POOL(fdoExtension->AdditionalFdoData);
1928#endif
1929 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate for FunctionSupportInfo\n"));
1931 }
1932
1933 //
1934 // initialize the struct's various fields.
1935 //
1936 RtlZeroMemory(fdoExtension->FunctionSupportInfo, sizeof(CLASS_FUNCTION_SUPPORT_INFO));
1937 KeInitializeSpinLock(&fdoExtension->FunctionSupportInfo->SyncLock);
1938
1939 //
1940 // intialize the CommandStatus to -1 indicates that no effort made yet to retrieve the info.
1941 // Possible values of CommandStatus (data type: NTSTATUS):
1942 // -1: It's not attempted yet to retrieve the information.
1943 // success: Command sent and succeeded, information cached in FdoExtension.
1944 // failed/warning: Command is either not supported or failed by device or lower level driver.
1945 // The command should not be attempted again.
1946 //
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;
1952
1953
1954 KeInitializeTimer(&fdoExtension->PrivateFdoData->Retry.Timer);
1955 KeInitializeDpc(&fdoExtension->PrivateFdoData->Retry.Dpc,
1957 DeviceObject);
1958 KeInitializeSpinLock(&fdoExtension->PrivateFdoData->Retry.Lock);
1959 fdoExtension->PrivateFdoData->Retry.Granularity = KeQueryTimeIncrement();
1960 commonExtension->Reserved4 = (ULONG_PTR)(' GPH'); // debug aid
1961 InitializeListHead(&fdoExtension->PrivateFdoData->DeferredClientIrpList);
1962
1963 KeInitializeSpinLock(&fdoExtension->PrivateFdoData->SpinLock);
1964
1965 //
1966 // keep a pointer to the senseinfo2 stuff locally also (used in every read/write).
1967 //
1968 fdoExtension->PrivateFdoData->InterpretSenseInfo = driverExtension->InterpretSenseInfo;
1969
1970 fdoExtension->PrivateFdoData->MaxNumberOfIoRetries = NUM_IO_RETRIES;
1971
1972 //
1973 // Initialize release queue extended SRB
1974 //
1975 status = InitializeStorageRequestBlock(&(fdoExtension->PrivateFdoData->ReleaseQueueSrb.SrbEx),
1977 sizeof(fdoExtension->PrivateFdoData->ReleaseQueueSrb.ReleaseQueueSrbBuffer),
1978 0);
1979 if (!NT_SUCCESS(status)) {
1981 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
1982 "ClassPnpStartDevice: fail to initialize release queue extended SRB 0x%x\n", status));
1983 return status;
1984 }
1985
1986
1987 /*
1988 * Anchor the FDO in our static list.
1989 * Pnp is synchronized, so we shouldn't need any synchronization here.
1990 */
1991 InsertTailList(&AllFdosList, &fdoExtension->PrivateFdoData->AllFdosListEntry);
1992
1993 //
1994 // NOTE: the old interface allowed the class driver to allocate
1995 // this. this was unsafe for low-memory conditions. allocate one
1996 // unconditionally now, and modify our internal functions to use
1997 // our own exclusively as it is the only safe way to do this.
1998 //
1999
2000 status = ClasspAllocateReleaseQueueIrp(fdoExtension);
2001 if (!NT_SUCCESS(status)) {
2002 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate the private release queue irp\n"));
2003 return status;
2004 }
2005
2006 status = ClasspAllocatePowerProcessIrp(fdoExtension);
2007 if (!NT_SUCCESS(status)) {
2008 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate the power process irp\n"));
2009 return status;
2010 }
2011
2012 //
2013 // Call port driver to get miniport properties for disk devices
2014 // It's ok for this call to fail
2015 //
2016
2017 if ((DeviceObject->DeviceType == FILE_DEVICE_DISK) &&
2018 (!TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE))) {
2019
2020 propertyId = StorageMiniportProperty;
2021
2022 status = ClassGetDescriptor(fdoExtension->CommonExtension.LowerDeviceObject,
2023 &propertyId,
2024 (PVOID *)&fdoExtension->MiniportDescriptor);
2025
2026 //
2027 // function ClassGetDescriptor returns succeed with buffer "fdoExtension->MiniportDescriptor" allocated.
2028 //
2029 if ( NT_SUCCESS(status) &&
2030 (fdoExtension->MiniportDescriptor->Portdriver != StoragePortCodeSetStorport &&
2031 fdoExtension->MiniportDescriptor->Portdriver != StoragePortCodeSetUSBport) ) {
2032 //
2033 // field "IoTimeoutValue" supported for either Storport or USBStor
2034 //
2035 fdoExtension->MiniportDescriptor->IoTimeoutValue = 0;
2036 }
2037
2038
2039
2040 }
2041
2042 //
2043 // Call port driver to get adapter capabilities.
2044 //
2045
2046 propertyId = StorageAdapterProperty;
2047
2048 status = ClassGetDescriptor(
2049 commonExtension->LowerDeviceObject,
2050 &propertyId,
2051 (PVOID *)&fdoExtension->AdapterDescriptor);
2052 if (!NT_SUCCESS(status)) {
2053 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: ClassGetDescriptor [ADAPTER] failed %lx\n", status));
2054 return status;
2055 }
2056
2057 //
2058 // Call port driver to get device descriptor.
2059 //
2060
2061 propertyId = StorageDeviceProperty;
2062
2063 status = ClassGetDescriptor(
2064 commonExtension->LowerDeviceObject,
2065 &propertyId,
2066 (PVOID *)&fdoExtension->DeviceDescriptor);
2067 if (NT_SUCCESS(status)){
2068
2069 ClasspScanForSpecialInRegistry(fdoExtension);
2070 ClassScanForSpecial(fdoExtension, ClassBadItems, ClasspScanForClassHacks);
2071
2072 //
2073 // allow perf to be re-enabled after a given number of failed IOs
2074 // require this number to be at least CLASS_PERF_RESTORE_MINIMUM
2075 //
2076
2077 {
2079
2080 ClassGetDeviceParameter(fdoExtension,
2083 &t);
2085 fdoExtension->PrivateFdoData->Perf.ReEnableThreshhold = t;
2086 }
2087 }
2088
2089 //
2090 // compatibility comes first. writable cd media will not
2091 // get a SYNCH_CACHE on power down.
2092 //
2093 if (fdoExtension->DeviceObject->DeviceType != FILE_DEVICE_DISK) {
2094 SET_FLAG(fdoExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_SYNC_CACHE);
2095 }
2096
2097
2098 //
2099 // Test if the device is portable and updated the characteristics if so
2100 //
2101 status = ClasspIsPortable(fdoExtension,
2102 &isPortable);
2103
2104 if (NT_SUCCESS(status) && (isPortable == TRUE)) {
2105 DeviceObject->Characteristics |= FILE_PORTABLE_DEVICE;
2106 }
2107
2108 //
2109 // initialize the hotplug information only after the ScanForSpecial
2110 // routines, as it relies upon the hack flags.
2111 //
2112 status = ClasspInitializeHotplugInfo(fdoExtension);
2113 if (NT_SUCCESS(status)){
2114 /*
2115 * Allocate/initialize TRANSFER_PACKETs and related resources.
2116 */
2118 }
2119 else {
2120 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClassPnpStartDevice: Could not initialize hotplug information %lx\n", status));
2122 }
2123 else {
2124 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: ClassGetDescriptor [DEVICE] failed %lx\n", status));
2125 return status;
2126 }
2127
2128
2129 if (NT_SUCCESS(status)) {
2130
2131 //
2132 // Retrieve info on whether async notification is supported by port drivers
2133 //
2134 propertyId = StorageDevicePowerProperty;
2135
2136 status = ClassGetDescriptor(fdoExtension->CommonExtension.LowerDeviceObject,
2137 &propertyId,
2138 (PVOID *)&powerDescriptor);
2139 if (NT_SUCCESS(status) && (powerDescriptor != NULL)) {
2140 fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported = powerDescriptor->AsynchronousNotificationSupported;
2141 fdoExtension->FunctionSupportInfo->IdlePower.D3ColdSupported = powerDescriptor->D3ColdSupported;
2142 fdoExtension->FunctionSupportInfo->IdlePower.NoVerifyDuringIdlePower = powerDescriptor->NoVerifyDuringIdlePower;
2143 FREE_POOL(powerDescriptor);
2144 } else {
2145 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: ClassGetDescriptor [DevicePower] failed %lx\n", status));
2146
2147 //
2148 // Ignore error as device power property is optional
2149 //
2151 }
2152 }
2153 }
2154
2155 //
2156 // ISSUE - drivers need to disable write caching on the media
2157 // if hotplug and !useroverride. perhaps we should
2158 // allow registration of a callback to enable/disable
2159 // write cache instead.
2160 //
2161
2162 if (NT_SUCCESS(status)){
2164 }
2165
2166 if (commonExtension->IsFdo) {
2167 fdoExtension->PrivateFdoData->Perf.OriginalSrbFlags = fdoExtension->SrbFlags;
2168
2169 //
2170 // initialization for disk device
2171 //
2172 if ((DeviceObject->DeviceType == FILE_DEVICE_DISK) &&
2173 (!TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE))) {
2174
2175 ULONG accessAlignmentNotSupported = 0;
2176 ULONG qerrOverrideMode = QERR_SET_ZERO_ODX_OR_TP_ONLY;
2177 ULONG legacyErrorHandling = FALSE;
2178
2179 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP,
2180 "ClassPnpStartDevice: Enabling idle timer for %p\n", DeviceObject));
2181 // Initialize idle timer for disk devices
2182 ClasspInitializeIdleTimer(fdoExtension);
2183
2184 if (ClasspIsObsoletePortDriver(fdoExtension) == FALSE) {
2185 // get INQUIRY VPD support information. It's safe to send command as everything is ready in ClassInitDevice().
2186 ClasspGetInquiryVpdSupportInfo(fdoExtension);
2187
2188 // Query and cache away Logical Block Provisioning info in the FDO extension.
2189 // The cached information will be used in responding to some IOCTLs
2190 ClasspGetLBProvisioningInfo(fdoExtension);
2191
2192 //
2193 // Query and cache away Block Device ROD Limits info in the FDO extension.
2194 //
2195 if (fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits) {
2196 ClassDetermineTokenOperationCommandSupport(DeviceObject);
2197 }
2198
2199 //
2200 // See if the user has specified a particular QERR override
2201 // mode. "Override" meaning setting QERR = 0 via Mode Select.
2202 // 0 = Only when ODX or Thin Provisioning are supported (default)
2203 // 1 = Always
2204 // 2 = Never (or any value >= 2)
2205 //
2206 ClassGetDeviceParameter(fdoExtension,
2209 &qerrOverrideMode);
2210
2211 //
2212 // If this device is thinly provisioned or supports ODX, we
2213 // may need to force QERR to zero. The user may have also
2214 // specified that we should always or never do this.
2215 //
2216 if (qerrOverrideMode == QERR_SET_ZERO_ALWAYS ||
2217 (qerrOverrideMode == QERR_SET_ZERO_ODX_OR_TP_ONLY &&
2218 (ClasspIsThinProvisioned(fdoExtension->FunctionSupportInfo) ||
2219 NT_SUCCESS(ClasspValidateOffloadSupported(DeviceObject, NULL))))) {
2220
2222 }
2223
2224 } else {
2225
2226 //
2227 // Since this device has been exposed by a legacy miniport (e.g. SCSIPort miniport)
2228 // set its LB Provisioning command status to an error status that will be surfaced
2229 // up to the caller of a TRIM/Unmap command.
2230 //
2231 fdoExtension->FunctionSupportInfo->LBProvisioningData.CommandStatus = STATUS_UNSUCCESSFUL;
2232 fdoExtension->FunctionSupportInfo->BlockLimitsData.CommandStatus = STATUS_UNSUCCESSFUL;
2233 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus = STATUS_UNSUCCESSFUL;
2234 }
2235
2236 // Get registry setting of failing the IOCTL for AccessAlignment Property.
2237 ClassGetDeviceParameter(fdoExtension,
2240 &accessAlignmentNotSupported);
2241
2242 if (accessAlignmentNotSupported > 0) {
2243 fdoExtension->FunctionSupportInfo->RegAccessAlignmentQueryNotSupported = TRUE;
2244 }
2245
2246#if (NTDDI_VERSION >= NTDDI_WINBLUE)
2247
2248
2249 //
2250 // See if the user has specified legacy error handling.
2251 //
2252 ClassGetDeviceParameter(fdoExtension,
2255 &legacyErrorHandling);
2256
2257 if (legacyErrorHandling) {
2258 //
2259 // Legacy error handling means that the maximum number of
2260 // retries allowd for an IO request is 8 instead of 4.
2261 //
2262 fdoExtension->PrivateFdoData->MaxNumberOfIoRetries = LEGACY_NUM_IO_RETRIES;
2263 fdoExtension->PrivateFdoData->LegacyErrorHandling = TRUE;
2264 }
2265#else
2266 UNREFERENCED_PARAMETER(legacyErrorHandling);
2267#endif
2268
2269
2270 //
2271 // Get the copy offload max target duration value.
2272 // This function will set the default value if one hasn't been
2273 // specified in the registry.
2274 //
2275 ClasspGetCopyOffloadMaxDuration(DeviceObject,
2277 &(fdoExtension->PrivateFdoData->CopyOffloadMaxTargetDuration));
2278
2279 }
2280
2281 }
2282 }
2283
2284 if (!NT_SUCCESS(status)){
2285
2286 //
2287 // Just bail out - the remove that comes down will clean up the
2288 // initialized scraps.
2289 //
2290
2291 return status;
2292 } else {
2293 commonExtension->IsInitialized = TRUE;
2294 }
2295
2296 //
2297 // If device requests autorun functionality or a once a second callback
2298 // then enable the once per second timer. Exception is if media change
2299 // detection is desired but device supports async notification.
2300 //
2301 // NOTE: This assumes that ClassInitializeMediaChangeDetection is always
2302 // called in the context of the ClassInitDevice callback. If called
2303 // after then this check will have already been made and the
2304 // once a second timer will not have been enabled.
2305 //
2306 if ((isFdo) &&
2307 ((initData->ClassTick != NULL) ||
2308 ((fdoExtension->MediaChangeDetectionInfo != NULL) &&
2309 (fdoExtension->FunctionSupportInfo != NULL) &&
2310 (fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported == FALSE)) ||
2311 ((fdoExtension->FailurePredictionInfo != NULL) &&
2312 (fdoExtension->FailurePredictionInfo->Method != FailurePredictionNone))))
2313 {
2314 ClasspEnableTimer(fdoExtension);
2315
2316 //
2317 // In addition, we may change our polling behavior when the screen is
2318 // off so register for screen state notification if we haven't already
2319 // done so.
2320 //
2323 &GUID_CONSOLE_DISPLAY_STATE,
2325 NULL,
2327 }
2328 }
2329
2330 //
2331 // NOTE: the timer looks at commonExtension->CurrentState now
2332 // to prevent Media Change Notification code from running
2333 // until the device is started, but allows the device
2334 // specific tick handler to run. therefore it is imperative
2335 // that commonExtension->CurrentState not be updated until
2336 // the device specific startdevice handler has finished.
2337 //
2338
2340
2341 if (NT_SUCCESS(status)){
2342 commonExtension->CurrentState = IRP_MN_START_DEVICE;
2343
2344 if((isFdo) && (initData->ClassEnumerateDevice != NULL)) {
2345 isMountedDevice = FALSE;
2346 }
2347
2348 if (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM) {
2349
2350 isMountedDevice = FALSE;
2351 }
2352
2353 //
2354 // Register for mounted device interface if this is a
2355 // sfloppy device.
2356 //
2357 if ((DeviceObject->DeviceType == FILE_DEVICE_DISK) &&
2358 (TEST_FLAG(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE))) {
2359
2360 isMountedDevice = TRUE;
2361 }
2362
2363 if(isMountedDevice) {
2365 }
2366
2367 if(commonExtension->IsFdo) {
2369
2370 //
2371 // Tell Storport (Usbstor or SD) to enable idle power management for this
2372 // device, assuming the user hasn't turned it off in the registry.
2373 //
2374 if (fdoExtension->FunctionSupportInfo != NULL &&
2375 fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled == FALSE &&
2376 fdoExtension->MiniportDescriptor != NULL &&
2377 (fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetStorport ||
2378 fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetSDport ||
2379 fdoExtension->MiniportDescriptor->Portdriver == StoragePortCodeSetUSBport)) {
2380 ULONG disableIdlePower= 0;
2381 ClassGetDeviceParameter(fdoExtension,
2384 &disableIdlePower);
2385
2386 if (!disableIdlePower) {
2388 }
2389 }
2390 }
2391 }
2392 else {
2393 ClasspDisableTimer(fdoExtension);
2394 }
2395
2396
2397 return status;
2398}
2399
2400
2401/*++////////////////////////////////////////////////////////////////////////////
2402
2403ClassReadWrite()
2404
2405Routine Description:
2406
2407 This is the system entry point for read and write requests. The
2408 device-specific handler is invoked to perform any validation necessary.
2409
2410 If the device object is a PDO (partition object) then the request will
2411 simply be adjusted for Partition0 and issued to the lower device driver.
2412
2413 IF the device object is an FDO (paritition 0 object), the number of bytes
2414 in the request are checked against the maximum byte counts that the adapter
2415 supports and requests are broken up into
2416 smaller sizes if necessary.
2417
2418Arguments:
2419
2420 DeviceObject - a pointer to the device object for this request
2421
2422 Irp - IO request
2423
2424Return Value:
2425
2426 NT Status
2427
2428--*/
2430NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2432{
2433 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
2434 PDEVICE_OBJECT lowerDeviceObject = commonExtension->LowerDeviceObject;
2436 ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
2437 ULONG isRemoved;
2439
2440 /*
2441 * Grab the remove lock. If we can't acquire it, bail out.
2442 */
2444 if (isRemoved) {
2445 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
2446 Irp->IoStatus.Information = 0;
2450 }
2451 else if (TEST_FLAG(DeviceObject->Flags, DO_VERIFY_VOLUME) &&
2452 (currentIrpStack->MinorFunction != CLASSP_VOLUME_VERIFY_CHECKED) &&
2453 !TEST_FLAG(currentIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME)){
2454
2455 /*
2456 * DO_VERIFY_VOLUME is set for the device object,
2457 * but this request is not itself a verify request.
2458 * So fail this request.
2459 */
2460 if (Irp->Tail.Overlay.Thread != NULL) {
2462 }
2463 Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
2464 Irp->IoStatus.Information = 0;
2468 }
2469 else {
2470
2471 /*
2472 * Since we've bypassed the verify-required tests we don't need to repeat
2473 * them with this IRP - in particular we don't want to worry about
2474 * hitting them at the partition 0 level if the request has come through
2475 * a non-zero partition.
2476 */
2478
2479 /*
2480 * Call the miniport driver's pre-pass filter to check if we
2481 * should continue with this transfer.
2482 */
2483 NT_ASSERT(commonExtension->DevInfo->ClassReadWriteVerification);
2485 // Code Analysis cannot analyze the code paths specific to clients.
2487 if (!NT_SUCCESS(status)){
2488 NT_ASSERT(Irp->IoStatus.Status == status);
2489 Irp->IoStatus.Information = 0;
2492 }
2493 else if (status == STATUS_PENDING){
2494 /*
2495 * ClassReadWriteVerification queued this request.
2496 * So don't touch the irp anymore.
2497 */
2498 }
2499 else {
2500
2501 if (transferByteCount == 0) {
2502 /*
2503 * Several parts of the code turn 0 into 0xffffffff,
2504 * so don't process a zero-length request any further.
2505 */
2506 Irp->IoStatus.Status = STATUS_SUCCESS;
2507 Irp->IoStatus.Information = 0;
2511 }
2512 else {
2513 /*
2514 * If the driver has its own StartIo routine, call it.
2515 */
2516 if (commonExtension->DriverExtension->InitData.ClassStartIo) {
2520 }
2521 else {
2522 /*
2523 * The driver does not have its own StartIo routine.
2524 * So process this request ourselves.
2525 */
2526
2527 /*
2528 * Add partition byte offset to make starting byte relative to
2529 * beginning of disk.
2530 */
2531 currentIrpStack->Parameters.Read.ByteOffset.QuadPart +=
2532 commonExtension->StartingOffset.QuadPart;
2533
2534 if (commonExtension->IsFdo){
2535
2536 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
2537 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
2538
2539 /*
2540 * Add in any skew for the disk manager software.
2541 */
2542 currentIrpStack->Parameters.Read.ByteOffset.QuadPart +=
2543 commonExtension->PartitionZeroExtension->DMByteSkew;
2544
2545 //
2546 // In case DEV_USE_16BYTE_CDB flag is not set, R/W request will be translated into READ/WRITE 10 SCSI command.
2547 // These SCSI commands have 4 bytes in "Starting LBA" field.
2548 // Requests cannot be represented in these SCSI commands should be failed.
2549 //
2550 if (!TEST_FLAG(fdoExtension->DeviceFlags, DEV_USE_16BYTE_CDB)) {
2551 LARGE_INTEGER startingLba;
2552
2553 startingLba.QuadPart = currentIrpStack->Parameters.Read.ByteOffset.QuadPart >> fdoExtension->SectorShift;
2554
2555 if (startingLba.QuadPart > MAXULONG) {
2556 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2557 Irp->IoStatus.Information = 0;
2561 goto Exit;
2562 }
2563 }
2564
2565#if DBG
2566 //
2567 // Record the caller if:
2568 // 1. the disk is currently off
2569 // 2. the operation is a read, (likely resulting in disk spinnage)
2570 // 3. the operation is marked WT (likely resulting in disk spinnage)
2571 //
2572 if((fdoExtension->DevicePowerState == PowerDeviceD3) && // disk is off
2573 ((currentIrpStack->MajorFunction == IRP_MJ_READ) || // It's a read.
2574 (TEST_FLAG(currentIrpStack->Flags, SL_WRITE_THROUGH))) ) { // they *really* want it to go to disk.
2575
2577 }
2578#endif
2579
2580 /*
2581 * Perform the actual transfer(s) on the hardware
2582 * to service this request.
2583 */
2584 if (ClasspIsIdleRequestSupported(fdoData, Irp)) {
2587 } else {
2588 UCHAR uniqueAddr = 0;
2589
2590 //
2591 // Since we're touching fdoData after servicing the transfer packet, this opens us up to
2592 // a potential window, where the device may be removed between the time that
2593 // ServiceTransferPacket completes and we've had a chance to access fdoData. In order
2594 // to guard against this, we acquire the removelock an additional time here. This
2595 // acquire is guaranteed to succeed otherwise we wouldn't be here (because of the
2596 // outer acquire).
2597 // The sequence of events we're guarding against with this remLock acquire is:
2598 // 1. This UL IRP acquired the lock.
2599 // 2. Device gets surprised removed, then gets IRP_MN_REMOVE_DEVICE; ClassRemoveDevice
2600 // waits for the above RemoveLock.
2601 // 3. ServiceTransferRequest breaks the UL IRP into DL IRPs.
2602 // 4. DL IRPs complete with STATUS_NO_SUCH_DEVICE and TransferPktComplete completes the UL
2603 // IRP with STATUS_NO_SUCH_DEVICE; releases the RemoveLock.
2604 // 5. ClassRemoveDevice is now unblocked, continues running and frees resources (including
2605 // fdoData).
2606 // 6. Finally ClassReadWrite gets to run again and accesses a freed fdoData when trying to
2607 // check/update idle-related fields.
2608 //
2610
2613 if (fdoData->IdlePrioritySupported == TRUE) {
2615 }
2616
2618 }
2619 }
2620 else {
2621 /*
2622 * This is a child PDO enumerated for our FDO by e.g. disk.sys
2623 * and owned by e.g. partmgr. Send it down to the next device
2624 * and the same irp will come back to us for the FDO.
2625 */
2628 status = IoCallDriver(lowerDeviceObject, Irp);
2629 }
2630 }
2631 }
2632 }
2633 }
2634
2635Exit:
2636 return status;
2637}
2638
2639
2641{
2642 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
2643 ULONG cylinderSize;
2644 ULONG bytesPerSector;
2645 LARGE_INTEGER lastSector;
2646 LARGE_INTEGER largeInt;
2647
2648 bytesPerSector = ClasspCalculateLogicalSectorSize(Fdo, ReadCapacityData->BytesPerBlock);
2649
2650 fdoExt->DiskGeometry.BytesPerSector = bytesPerSector;
2652
2653 /*
2654 * LogicalBlockAddress is the last sector of the logical drive, in big-endian.
2655 * It tells us the size of the drive (#sectors is lastSector+1).
2656 */
2657
2658 largeInt = ReadCapacityData->LogicalBlockAddress;
2659 REVERSE_BYTES_QUAD(&lastSector, &largeInt);
2660
2661 if (fdoExt->DMActive){
2662 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassReadDriveCapacity: reducing number of sectors by %d\n", fdoExt->DMSkew));
2663 lastSector.QuadPart -= fdoExt->DMSkew;
2664 }
2665
2666 /*
2667 * Check to see if we have a geometry we should be using already.
2668 * If not, we set part of the disk geometry to garbage values that will be filled in by the caller (e.g. disk.sys).
2669 *
2670 * So the first call to ClassReadDriveCapacity always sets a meaningless geometry.
2671 * TracksPerCylinder and SectorsPerTrack are kind of meaningless anyway wrt I/O,
2672 * because I/O is always targeted to a logical sector number.
2673 * All that really matters is BytesPerSector and the number of sectors.
2674 */
2675 cylinderSize = fdoExt->DiskGeometry.TracksPerCylinder * fdoExt->DiskGeometry.SectorsPerTrack;
2676 if (cylinderSize == 0){
2677 fdoExt->DiskGeometry.TracksPerCylinder = 0xff;
2678 fdoExt->DiskGeometry.SectorsPerTrack = 0x3f;
2679 cylinderSize = fdoExt->DiskGeometry.TracksPerCylinder * fdoExt->DiskGeometry.SectorsPerTrack;
2680 }
2681
2682 /*
2683 * Calculate number of cylinders.
2684 * If there are zero cylinders, then the device lied AND it's
2685 * smaller than 0xff*0x3f (about 16k sectors, usually 8 meg)
2686 * this can fit into a single LONGLONG, so create another usable
2687 * geometry, even if it's unusual looking.
2688 * This allows small, non-standard devices, such as Sony's Memory Stick, to show up as having a partition.
2689 */
2690 fdoExt->DiskGeometry.Cylinders.QuadPart = (LONGLONG)((lastSector.QuadPart + 1)/cylinderSize);
2691 if (fdoExt->DiskGeometry.Cylinders.QuadPart == (LONGLONG)0) {
2692 fdoExt->DiskGeometry.SectorsPerTrack = 1;
2693 fdoExt->DiskGeometry.TracksPerCylinder = 1;
2694 fdoExt->DiskGeometry.Cylinders.QuadPart = lastSector.QuadPart + 1;
2695 }
2696
2697 /*
2698 * Calculate media capacity in bytes.
2699 * For this purpose we treat the entire LUN as is if it is one partition. Disk will deal with actual partitioning.
2700 */
2702 ((LONGLONG)(lastSector.QuadPart + 1)) << fdoExt->SectorShift;
2703
2704 /*
2705 * Is this removable or fixed media
2706 */
2707 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)){
2709 }
2710 else {
2712 }
2713
2714}
2715
2716/*++////////////////////////////////////////////////////////////////////////////
2717
2718ClassReadDriveCapacity()
2719
2720Routine Description:
2721
2722 This routine sends a READ CAPACITY to the requested device, updates
2723 the geometry information in the device object and returns
2724 when it is complete. This routine is synchronous.
2725
2726 This routine must be called with the remove lock held or some other
2727 assurance that the Fdo will not be removed while processing.
2728
2729Arguments:
2730
2731 DeviceObject - Supplies a pointer to the device object that represents
2732 the device whose capacity is to be read.
2733
2734Return Value:
2735
2736 Status is returned.
2737
2738--*/
2741NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2743{
2744 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
2745 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
2746 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
2747 READ_CAPACITY_DATA_EX PTRALIGN readCapacityData = {0};
2748 PTRANSFER_PACKET pkt;
2750 PMDL driveCapMdl = NULL;
2751 KEVENT event;
2752 IRP pseudoIrp = {0};
2753 ULONG readCapacityDataSize;
2754 BOOLEAN use16ByteCdb;
2755 BOOLEAN match = TRUE;
2756
2757 use16ByteCdb = TEST_FLAG(fdoExt->DeviceFlags, DEV_USE_16BYTE_CDB);
2758
2760
2761 if (use16ByteCdb) {
2762 readCapacityDataSize = sizeof(READ_CAPACITY_DATA_EX);
2763 } else {
2764 readCapacityDataSize = sizeof(READ_CAPACITY_DATA);
2765 }
2766
2767 if (driveCapMdl != NULL) {
2768 FreeDeviceInputMdl(driveCapMdl);
2769 driveCapMdl = NULL;
2770 }
2771
2772 //
2773 // Allocate the MDL based on the Read Capacity command.
2774 //
2775 driveCapMdl = BuildDeviceInputMdl(&readCapacityData, readCapacityDataSize);
2776 if (driveCapMdl == NULL) {
2778 goto SafeExit;
2779 }
2780
2782 if (pkt == NULL) {
2784 goto SafeExit;
2785 }
2786
2787 //
2788 // Our engine needs an "original irp" to write the status back to
2789 // and to count down packets (one in this case).
2790 // Just use a pretend irp for this.
2791 //
2792
2793 pseudoIrp.Tail.Overlay.DriverContext[0] = LongToPtr(1);
2794 pseudoIrp.IoStatus.Status = STATUS_SUCCESS;
2795 pseudoIrp.IoStatus.Information = 0;
2796 pseudoIrp.MdlAddress = driveCapMdl;
2797
2798 //
2799 // Set this up as a SYNCHRONOUS transfer, submit it,
2800 // and wait for the packet to complete. The result
2801 // status will be written to the original irp.
2802 //
2803
2806 &readCapacityData,
2807 readCapacityDataSize,
2808 &event,
2809 &pseudoIrp,
2810 use16ByteCdb);
2813
2814 status = pseudoIrp.IoStatus.Status;
2815
2816 //
2817 // If we got an UNDERRUN, retry exactly once.
2818 // (The transfer_packet engine didn't retry because the result
2819 // status was success).
2820 //
2821
2822 if (NT_SUCCESS(status) &&
2823 (pseudoIrp.IoStatus.Information < readCapacityDataSize)) {
2824
2825 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassReadDriveCapacity: read len (%xh) < %xh, retrying ...",
2826 (ULONG)pseudoIrp.IoStatus.Information, readCapacityDataSize));
2827
2829 if (pkt) {
2830 pseudoIrp.Tail.Overlay.DriverContext[0] = LongToPtr(1);
2831 pseudoIrp.IoStatus.Status = STATUS_SUCCESS;
2832 pseudoIrp.IoStatus.Information = 0;
2835 &readCapacityData,
2836 readCapacityDataSize,
2837 &event,
2838 &pseudoIrp,
2839 use16ByteCdb);
2842 status = pseudoIrp.IoStatus.Status;
2843 if (pseudoIrp.IoStatus.Information < readCapacityDataSize){
2845 }
2846 } else {
2848 }
2849 }
2850
2851 if (NT_SUCCESS(status)) {
2852 //
2853 // The request succeeded. Check for 8 byte LBA support.
2854 //
2855
2856 if (use16ByteCdb == FALSE) {
2857
2858 PREAD_CAPACITY_DATA readCapacity;
2859
2860 //
2861 // Check whether the device supports 8 byte LBA. If the device supports
2862 // it then retry the request using 16 byte CDB.
2863 //
2864
2865 readCapacity = (PREAD_CAPACITY_DATA) &readCapacityData;
2866
2867 if (readCapacity->LogicalBlockAddress == 0xFFFFFFFF) {
2868 //
2869 // Device returned max size for last LBA. Need to send
2870 // 16 byte request to get the size.
2871 //
2872 use16ByteCdb = TRUE;
2873 goto RetryRequest;
2874
2875 } else {
2876 //
2877 // Convert the 4 byte LBA (READ_CAPACITY_DATA) to 8 byte LBA (READ_CAPACITY_DATA_EX)
2878 // format for ease of use. This is the only format stored in the device extension.
2879 //
2880
2881 RtlMoveMemory((PUCHAR)(&readCapacityData) + sizeof(ULONG), readCapacity, sizeof(READ_CAPACITY_DATA));
2882 RtlZeroMemory((PUCHAR)(&readCapacityData), sizeof(ULONG));
2883
2884 }
2885 } else {
2886 //
2887 // Device completed 16 byte command successfully, it supports 8-byte LBA.
2888 //
2889
2891 }
2892
2893 //
2894 // Read out and store the drive information.
2895 //
2896
2897 InterpretCapacityData(Fdo, &readCapacityData);
2898
2899 //
2900 // Before caching the new drive capacity, compare it with the
2901 // cached capacity for any change.
2902 //
2903
2904 if (fdoData->IsCachedDriveCapDataValid == TRUE) {
2905
2907 &readCapacityData, sizeof(READ_CAPACITY_DATA_EX));
2908 }
2909
2910 //
2911 // Store the readCapacityData in private FDO data.
2912 // This is so that runtime memory failures don't cause disk.sys to put
2913 // the paging disk in an error state. Also this is used in
2914 // IOCTL_STORAGE_READ_CAPACITY.
2915 //
2916 fdoData->LastKnownDriveCapacityData = readCapacityData;
2918
2919 if (match == FALSE) {
2920 if (commonExtension->CurrentState != IRP_MN_START_DEVICE)
2921 {
2922 //
2923 // This can happen if a disk reports Parameters Changed / Capacity Data Changed sense data.
2924 // NT_ASSERT(!"Drive capacity has changed while the device wasn't started!");
2925 //
2926 } else {
2927 //
2928 // state of (commonExtension->CurrentState == IRP_MN_START_DEVICE) indicates that the device has been started.
2929 // UpdateDiskPropertiesWorkItemActive is used as a flag to ensure we only have one work item updating the disk
2930 // properties at a time.
2931 //
2932 if (InterlockedCompareExchange((volatile LONG *)&fdoData->UpdateDiskPropertiesWorkItemActive, 1, 0) == 0)
2933 {
2934 PIO_WORKITEM workItem;
2935
2936 workItem = IoAllocateWorkItem(Fdo);
2937
2938 if (workItem) {
2939 //
2940 // The disk capacity has changed, send notification to the disk driver.
2941 // Start a work item to notify the disk class driver asynchronously.
2942 //
2944 } else {
2946 }
2947 }
2948 }
2949 }
2950
2951 } else {
2952 //
2953 // The request failed.
2954 //
2955
2956 //
2957 // ISSUE - 2000/02/04 - henrygab - non-512-byte sector sizes and failed geometry update
2958 // what happens when the disk's sector size is bigger than
2959 // 512 bytes and we hit this code path? this is untested.
2960 //
2961 // If the read capacity fails, set the geometry to reasonable parameter
2962 // so things don't fail at unexpected places. Zero the geometry
2963 // except for the bytes per sector and sector shift.
2964 //
2965
2966 //
2967 // This request can sometimes fail legitimately
2968 // (e.g. when a SCSI device is attached but turned off)
2969 // so this is not necessarily a device/driver bug.
2970 //
2971
2972 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassReadDriveCapacity on Fdo %p failed with status %ul.", Fdo, status));
2973
2974 //
2975 // Write in a default disk geometry which we HOPE is right (??).
2976 //
2977
2978 RtlZeroMemory(&fdoExt->DiskGeometry, sizeof(DISK_GEOMETRY));
2979 fdoExt->DiskGeometry.BytesPerSector = 512;
2980 fdoExt->SectorShift = 9;
2982
2983 //
2984 // Is this removable or fixed media
2985 //
2986
2987 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)){
2989 } else {
2991 }
2992 }
2993
2994SafeExit:
2995
2996
2997 //
2998 // In case DEV_USE_16BYTE_CDB flag is not set, classpnp translates R/W request into READ/WRITE 10 SCSI command.
2999 // These SCSI commands have 2 bytes in "Transfer Blocks" field.
3000 // Make sure this max length (0xFFFF * sector size) is respected during request split.
3001 //
3002 if (!TEST_FLAG(fdoExt->DeviceFlags, DEV_USE_16BYTE_CDB)) {
3003 ULONG cdb10MaxBlocks = ((ULONG)USHORT_MAX) << fdoExt->SectorShift;
3004
3005 fdoData->HwMaxXferLen = min(cdb10MaxBlocks, fdoData->HwMaxXferLen);
3006 }
3007
3008 if (driveCapMdl != NULL) {
3009 FreeDeviceInputMdl(driveCapMdl);
3010 }
3011
3012 //
3013 // If the request failed for some reason then invalidate the cached
3014 // capacity data for removable devices. So that we won't return
3015 // wrong capacity in IOCTL_STORAGE_READ_CAPACITY
3016 //
3017
3018 if (!NT_SUCCESS(status) && (fdoExt->DiskGeometry.MediaType == RemovableMedia)) {
3020 }
3021
3022 //
3023 // Don't let memory failures (either here or in the port driver) in the ReadDriveCapacity call
3024 // put the paging disk in an error state such that paging fails.
3025 // Return the last known drive capacity (which may possibly be slightly out of date, even on
3026 // fixed media, e.g. for storage cabinets that can grow a logical disk).
3027 //
3029 (fdoData->IsCachedDriveCapDataValid) &&
3030 (fdoExt->DiskGeometry.MediaType == FixedMedia)) {
3031 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassReadDriveCapacity: defaulting to cached DriveCapacity data"));
3034 }
3035
3036 return status;
3037}
3038
3039
3040/*++////////////////////////////////////////////////////////////////////////////
3041
3042ClassSendStartUnit()
3043
3044Routine Description:
3045
3046 Send command to SCSI unit to start or power up.
3047 Because this command is issued asynchronounsly, that is, without
3048 waiting on it to complete, the IMMEDIATE flag is not set. This
3049 means that the CDB will not return until the drive has powered up.
3050 This should keep subsequent requests from being submitted to the
3051 device before it has completely spun up.
3052
3053 This routine is called from the InterpretSense routine, when a
3054 request sense returns data indicating that a drive must be
3055 powered up.
3056
3057 This routine may also be called from a class driver's error handler,
3058 or anytime a non-critical start device should be sent to the device.
3059
3060Arguments:
3061
3062 Fdo - The functional device object for the stopped device.
3063
3064Return Value:
3065
3066 None.
3067
3068--*/
3069VOID
3070NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3073 )
3074{
3075 PIO_STACK_LOCATION irpStack;
3076 PIRP irp;
3077 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
3080 PCDB cdb;
3083
3084 //
3085 // Allocate Srb from nonpaged pool.
3086 //
3087
3088 context = ExAllocatePoolWithTag(NonPagedPoolNx,
3089 sizeof(COMPLETION_CONTEXT),
3090 '6CcS');
3091
3092 if (context == NULL) {
3093
3094 //
3095 // ISSUE-2000/02/03-peterwie
3096 // This code path was inheritted from the NT 4.0 class2.sys driver.
3097 // It needs to be changed to survive low-memory conditions.
3098 //
3099
3100 KeBugCheck(SCSI_DISK_DRIVER_INTERNAL);
3101 }
3102
3103 //
3104 // Save the device object in the context for use by the completion
3105 // routine.
3106 //
3107
3108 context->DeviceObject = Fdo;
3109
3110 srb = &context->Srb.Srb;
3111 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
3112 srbEx = &context->Srb.SrbEx;
3115 sizeof(context->Srb.SrbExBuffer),
3116 1,
3118 if (!NT_SUCCESS(status)) {
3121 return;
3122 }
3123
3124 srbEx->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
3125
3126 } else {
3127
3128 //
3129 // Zero out srb.
3130 //
3131
3132 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
3133
3134 //
3135 // Write length to SRB.
3136 //
3137
3138 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
3139
3141 }
3142
3143 //
3144 // Set timeout value large enough for drive to spin up.
3145 //
3146
3148
3149 //
3150 // Set the transfer length.
3151 //
3152
3157
3158 //
3159 // Build the start unit CDB.
3160 //
3161
3162 SrbSetCdbLength(srb, 6);
3163 cdb = SrbGetCdb(srb);
3164
3165 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
3166 cdb->START_STOP.Start = 1;
3167 cdb->START_STOP.Immediate = 0;
3168 cdb->START_STOP.LogicalUnitNumber = srb->Lun;
3169
3170 //
3171 // Build the asynchronous request to be sent to the port driver.
3172 // Since this routine is called from a DPC the IRP should always be
3173 // available.
3174 //
3175
3176 irp = IoAllocateIrp(Fdo->StackSize, FALSE);
3177
3178 if (irp == NULL) {
3179
3180 //
3181 // ISSUE-2000/02/03-peterwie
3182 // This code path was inheritted from the NT 4.0 class2.sys driver.
3183 // It needs to be changed to survive low-memory conditions.
3184 //
3185
3186 KeBugCheck(SCSI_DISK_DRIVER_INTERNAL);
3187
3188 }
3189
3191
3194 context,
3195 TRUE,
3196 TRUE,
3197 TRUE);
3198
3199 irpStack = IoGetNextIrpStackLocation(irp);
3200 irpStack->MajorFunction = IRP_MJ_SCSI;
3202
3203 //
3204 // Store the SRB address in next stack for port driver.
3205 //
3206
3207 irpStack->Parameters.Scsi.Srb = srb;
3208
3209 //
3210 // Call the port driver with the IRP.
3211 //
3212
3214
3215 return;
3216
3217} // end StartUnit()
3218
3219/*++////////////////////////////////////////////////////////////////////////////
3220
3221ClassAsynchronousCompletion() ISSUE-2000/02/18-henrygab - why public?!
3222
3223Routine Description:
3224
3225 This routine is called when an asynchronous I/O request
3226 which was issused by the class driver completes. Examples of such requests
3227 are release queue or START UNIT. This routine releases the queue if
3228 necessary. It then frees the context and the IRP.
3229
3230Arguments:
3231
3232 DeviceObject - The device object for the logical unit; however since this
3233 is the top stack location the value is NULL.
3234
3235 Irp - Supplies a pointer to the Irp to be processed.
3236
3237 Context - Supplies the context to be used to process this request.
3238
3239Return Value:
3240
3241 None.
3242
3243--*/
3245NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3248 PIRP Irp,
3250 )
3251{
3254 ULONG srbFunction;
3255 ULONG srbFlags;
3256
3257 if (context == NULL) {
3259 }
3260
3261 if (DeviceObject == NULL) {
3262
3263 DeviceObject = context->DeviceObject;
3264 }
3265
3266 srb = &context->Srb.Srb;
3267
3269 srbFunction = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction;
3270 srbFlags = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFlags;
3271 } else {
3272 srbFunction = srb->Function;
3273 srbFlags = srb->SrbFlags;
3274 }
3275
3276 //
3277 // If this is an execute srb, then check the return status and make sure.
3278 // the queue is not frozen.
3279 //
3280
3281 if (srbFunction == SRB_FUNCTION_EXECUTE_SCSI) {
3282
3283 //
3284 // Check for a frozen queue.
3285 //
3286
3288
3289 //
3290 // Unfreeze the queue getting the device object from the context.
3291 //
3292
3293 ClassReleaseQueue(context->DeviceObject);
3294 }
3295 }
3296
3297 { // free port-allocated sense buffer if we can detect
3298
3299 if (((PCOMMON_DEVICE_EXTENSION)(DeviceObject->DeviceExtension))->IsFdo) {
3300
3301 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
3302 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3303 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
3304 }
3305
3306 } else {
3307
3309
3310 }
3311 }
3312
3313
3314 //
3315 // Free the context and the Irp.
3316 //
3317
3318 if (Irp->MdlAddress != NULL) {
3319 MmUnlockPages(Irp->MdlAddress);
3320 IoFreeMdl(Irp->MdlAddress);
3321
3322 Irp->MdlAddress = NULL;
3323 }
3324
3326
3328
3329 IoFreeIrp(Irp);
3330
3331 //
3332 // Indicate the I/O system should stop processing the Irp completion.
3333 //
3334
3336
3337} // end ClassAsynchronousCompletion()
3338
3339
3343 PIRP Irp,
3344 BOOLEAN PostToDpc
3345 )
3346
3347/*++
3348
3349Routine description:
3350
3351 This routine processes Io requests, splitting them if they
3352 are larger than what the hardware can handle at a time. If
3353 there isn't enough memory available, the request is placed
3354 in a queue, to be processed at a later time
3355
3356 If this is a high priority paging request, all regular Io
3357 are throttled to provide Mm with better thoroughput
3358
3359Arguments:
3360
3361 Fdo - The functional device object processing the request
3362 Irp - The Io request to be processed
3363 PostToDpc - Flag that indicates that this IRP must be posted to a DPC
3364
3365Return Value:
3366
3367 STATUS_SUCCESS if successful, an error code otherwise
3368
3369--*/
3370
3371{
3372 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
3373 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
3374 PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExtension->PartitionZeroExtension->AdapterDescriptor;
3375 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
3377 BOOLEAN deferClientIrp = FALSE;
3378 BOOLEAN driverUsesStartIO = (commonExtension->DriverExtension->InitData.ClassStartIo != NULL);
3379 KIRQL oldIrql;
3382
3383 /*
3384 * Initialize IRP status for the master IRP to
3385 * - STATUS_FT_READ_FROM_COPY if it's a copy-specific read
3386 * - STATUS_SUCCESS otherwise.
3387 *
3388 * This is required. When Classpnp determines the status for the master IRP
3389 * when completing child IRPs, the call to IoSetMasterIrpStatus
3390 * will be functioning properly (See TransferPktComplete function)
3391 *
3392 * Note:
3393 * If the IRP is a copy-specific read, File System already initialized the IRP status
3394 * to be STATUS_FT_READ_FROM_COPY. However, this can be changed when the IRP arrives
3395 * at Classpnp. It's possible that other drivers in the stack may initialize the
3396 * IRP status field to other values before forwarding the IRP down the stack.
3397 * To be defensive, we initialize the IRP status to either STATUS_FT_READ_FROM_COPY
3398 * if it's a copy-specific read, or STATUS_SUCCESS otherwise.
3399 */
3400 if (currentIrpStack->MajorFunction == IRP_MJ_READ &&
3401 TEST_FLAG(currentIrpStack->Flags, SL_KEY_SPECIFIED) &&
3402 IsKeyReadCopyNumber(currentIrpStack->Parameters.Read.Key)) {
3403 Irp->IoStatus.Status = STATUS_FT_READ_FROM_COPY;
3404 } else {
3405 Irp->IoStatus.Status = STATUS_SUCCESS;
3406 }
3407
3408 //
3409 // If this is a high priority request, hold off all other Io requests
3410 //
3411
3413 {
3414 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
3415
3416 if (fdoData->NumHighPriorityPagingIo == 0)
3417 {
3418 //
3419 // Entering throttle mode
3420 //
3421
3423 }
3424
3425 fdoData->NumHighPriorityPagingIo++;
3427
3428 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
3429 }
3430 else
3431 {
3432 if (fdoData->NumHighPriorityPagingIo != 0)
3433 {
3434 //
3435 // This request wasn't flagged as critical and atleast one critical request
3436 // is currently outstanding. Queue this request until all of those are done
3437 // but only if the interleave threshold has been reached
3438 //
3439
3440 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
3441
3442 if (fdoData->NumHighPriorityPagingIo != 0)
3443 {
3444 if (fdoData->MaxInterleavedNormalIo == 0)
3445 {
3446 deferClientIrp = TRUE;
3447 }
3448 else
3449 {
3450 fdoData->MaxInterleavedNormalIo--;
3451 }
3452 }
3453
3454 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
3455 }
3456 }
3457
3458 if (!deferClientIrp)
3459 {
3461 ULONG entireXferLen = currentSp->Parameters.Read.Length;
3462 PUCHAR bufPtr = MmGetMdlVirtualAddress(Irp->MdlAddress);
3463 LARGE_INTEGER targetLocation = currentSp->Parameters.Read.ByteOffset;
3464 PTRANSFER_PACKET pkt;
3465 SINGLE_LIST_ENTRY pktList;
3466 PSINGLE_LIST_ENTRY slistEntry;
3467 ULONG hwMaxXferLen;
3468 ULONG numPackets;
3469 ULONG i;
3470
3471
3472 /*
3473 * We precomputed fdoData->HwMaxXferLen using (MaximumPhysicalPages-1).
3474 * If the buffer is page-aligned, that's one less page crossing so we can add the page back in.
3475 * Note: adapters that return MaximumPhysicalPages=0x10 depend on this to
3476 * transfer aligned 64K requests in one piece.
3477 * Also note: make sure adding PAGE_SIZE back in doesn't wrap to zero.
3478 */
3479 if (((ULONG_PTR)bufPtr & (PAGE_SIZE-1)) || (fdoData->HwMaxXferLen > 0xffffffff-PAGE_SIZE)){
3480 hwMaxXferLen = fdoData->HwMaxXferLen;
3481 }
3482 else {
3484 hwMaxXferLen = min(fdoData->HwMaxXferLen+PAGE_SIZE, adapterDesc->MaximumTransferLength);
3485 }
3486
3487 /*
3488 * Compute the number of hw xfers we'll have to do.
3489 * Calculate this without allowing for an overflow condition.
3490 */
3491 NT_ASSERT(hwMaxXferLen >= PAGE_SIZE);
3492 numPackets = entireXferLen/hwMaxXferLen;
3493 if (entireXferLen % hwMaxXferLen){
3494 numPackets++;
3495 }
3496
3497 /*
3498 * Use our 'simple' slist functions since we don't need interlocked.
3499 */
3500 SimpleInitSlistHdr(&pktList);
3501
3502 if (driverUsesStartIO) {
3503 /*
3504 * special case: StartIO-based writing must stay serialized, so just
3505 * re-use one packet.
3506 */
3508 if (pkt) {
3510 i = 1;
3511 } else {
3512 i = 0;
3513 }
3514 } else {
3515 /*
3516 * First get all the TRANSFER_PACKETs that we'll need at once.
3517 */
3518 for (i = 0; i < numPackets; i++){
3520 if (pkt){
3522 }
3523 else {
3524 break;
3525 }
3526 }
3527 }
3528
3529
3530 if ((i == numPackets) &&
3531 (!driverUsesStartIO)) {
3532 NTSTATUS pktStat;
3533
3534 /*
3535 * The IoStatus.Information field will be incremented to the
3536 * transfer length as the pieces complete.
3537 */
3538 Irp->IoStatus.Information = 0;
3539
3540 /*
3541 * Store the number of transfer pieces inside the original IRP.
3542 * It will be used to count down the pieces as they complete.
3543 */
3544 Irp->Tail.Overlay.DriverContext[0] = LongToPtr(numPackets);
3545
3546 /*
3547 * For the common 1-packet case, we want to allow for an optimization by BlkCache
3548 * (and also potentially synchronous storage drivers) which may complete the
3549 * downward request synchronously.
3550 * In that synchronous completion case, we want to _not_ mark the original irp pending
3551 * and thereby save on the top-level APC.
3552 * It's critical to coordinate this with the completion routine so that we mark the original irp
3553 * pending if-and-only-if we return STATUS_PENDING for it.
3554 */
3555 if (numPackets > 1){
3558 }
3559 else {
3561 }
3562
3563 /*
3564 * Transmit the pieces of the transfer.
3565 */
3566 while (entireXferLen > 0){
3567 ULONG thisPieceLen = MIN(hwMaxXferLen, entireXferLen);
3568
3569 /*
3570 * Set up a TRANSFER_PACKET for this piece and send it.
3571 */
3572 slistEntry = SimplePopSlist(&pktList);
3573 NT_ASSERT(slistEntry);
3574 pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
3576 bufPtr,
3577 thisPieceLen,
3578 targetLocation,
3579 Irp);
3580
3581 //
3582 // If the IRP needs to be split, then we need to use a partial MDL.
3583 // This prevents problems if the same MDL is mapped multiple times.
3584 //
3585 if (numPackets > 1) {
3586 pkt->UsePartialMdl = TRUE;
3587 }
3588
3589 /*
3590 * When an IRP is completed, the completion routine checks to see if there
3591 * is a deferred IRP ready to sent down (assuming that there are no non-idle
3592 * requests waiting to be serviced). If such a deferred IRP is available, it
3593 * is sent down using this routine. However, if the lower driver completes
3594 * the request inline, there is a potential for multiple deferred IRPs being
3595 * sent down in the context of the same completion thread, thus exhausting
3596 * the call stack.
3597 * In order to prevent this from happening, we need to ensure that deferred
3598 * IRPs that are dequeued in the context of a request's completion routine
3599 * get posted to a DPC.
3600 */
3601 if (PostToDpc) {
3602
3603 pkt->RetryIn100nsUnits = 0;
3606
3607 } else {
3608
3609 pktStat = SubmitTransferPacket(pkt);
3610
3611 /*
3612 * If any of the packets completes with pending, we MUST return pending.
3613 * Also, if a packet completes with an error, return pending; this is because
3614 * in the completion routine we mark the original irp pending if the packet failed
3615 * (since we may retry, thereby switching threads).
3616 */
3617 if (pktStat != STATUS_SUCCESS){
3619 }
3620 }
3621
3622 entireXferLen -= thisPieceLen;
3623 bufPtr += thisPieceLen;
3624 targetLocation.QuadPart += thisPieceLen;
3625 }
3626 NT_ASSERT(SimpleIsSlistEmpty(&pktList));
3627 }
3628 else if (i >= 1){
3629 /*
3630 * We were unable to get all the TRANSFER_PACKETs we need,
3631 * but we did get at least one.
3632 * That means that we are in extreme low-memory stress.
3633 * We'll try doing this transfer using a single packet.
3634 * The port driver is certainly also in stress, so use one-page
3635 * transfers.
3636 */
3637
3638 /*
3639 * Free all but one of the TRANSFER_PACKETs.
3640 */
3641 while (i-- > 1){
3642 slistEntry = SimplePopSlist(&pktList);
3643 NT_ASSERT(slistEntry);
3644 pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
3646 }
3647
3648 /*
3649 * Get the single TRANSFER_PACKET that we'll be using.
3650 */
3651 slistEntry = SimplePopSlist(&pktList);
3652 NT_ASSERT(slistEntry);
3653 NT_ASSERT(SimpleIsSlistEmpty(&pktList));
3654 pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
3655
3656 if (!driverUsesStartIO) {
3657 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Insufficient packets available in ServiceTransferRequest - entering lowMemRetry with pkt=%p.", pkt));
3658 }
3659
3660 /*
3661 * Set the number of transfer packets (one)
3662 * inside the original irp.
3663 */
3664 Irp->IoStatus.Information = 0;
3665 Irp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
3667
3668 /*
3669 * Set up the TRANSFER_PACKET for a lowMem transfer and launch.
3670 */
3672 bufPtr,
3673 entireXferLen,
3674 targetLocation,
3675 Irp);
3676
3677 InitLowMemRetry(pkt, bufPtr, entireXferLen, targetLocation);
3678 StepLowMemRetry(pkt);
3680 }
3681 else {
3682 /*
3683 * We were unable to get ANY TRANSFER_PACKETs.
3684 * Defer this client irp until some TRANSFER_PACKETs free up.
3685 */
3686 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "No packets available in ServiceTransferRequest - deferring transfer (Irp=%p)...", Irp));
3687
3689 {
3690 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
3691
3693 {
3694 fdoData->MaxInterleavedNormalIo = 0;
3695 }
3696 else
3697 {
3699 }
3700
3701 fdoData->NumHighPriorityPagingIo--;
3702
3703 if (fdoData->NumHighPriorityPagingIo == 0)
3704 {
3705 LARGE_INTEGER period;
3706
3707 //
3708 // Exiting throttle mode
3709 //
3710
3712
3713 period.QuadPart = fdoData->ThrottleStopTime.QuadPart - fdoData->ThrottleStartTime.QuadPart;
3715 }
3716
3717 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
3718 }
3719
3720 deferClientIrp = TRUE;
3721 }
3722 }
3723 _Analysis_assume_(deferClientIrp);
3724 if (deferClientIrp)
3725 {
3729 }
3730
3732
3733 return status;
3734}
3735
3736
3737/*++////////////////////////////////////////////////////////////////////////////
3738
3739ClassIoComplete()
3740
3741Routine Description:
3742
3743 This routine executes when the port driver has completed a request.
3744 It looks at the SRB status in the completing SRB and if not success
3745 it checks for valid request sense buffer information. If valid, the
3746 info is used to update status with more precise message of type of
3747 error. This routine deallocates the SRB.
3748
3749 This routine should only be placed on the stack location for a class
3750 driver FDO.
3751
3752Arguments:
3753
3754 Fdo - Supplies the device object which represents the logical
3755 unit.
3756
3757 Irp - Supplies the Irp which has completed.
3758
3759 Context - Supplies a pointer to the SRB.
3760
3761Return Value:
3762
3763 NT status
3764
3765--*/
3767NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3770 IN PIRP Irp,
3772 )
3773{
3776 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
3777 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
3779 BOOLEAN retry;
3780 BOOLEAN callStartNextPacket;
3781 ULONG srbFlags;
3782 ULONG srbFunction;
3783
3784 NT_ASSERT(fdoExtension->CommonExtension.IsFdo);
3785
3787 srbFlags = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFlags;
3788 srbFunction = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction;
3789 } else {
3790 srbFlags = srb->SrbFlags;
3791 srbFunction = srb->Function;
3792 }
3793
3794 #if DBG
3795 if (srbFunction == SRB_FUNCTION_FLUSH) {
3796 DBGLOGFLUSHINFO(fdoData, FALSE, FALSE, TRUE);
3797 }
3798 #endif
3799
3800 //
3801 // Check SRB status for success of completing request.
3802 //
3803
3805 LONGLONG retryInterval;
3806
3807 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoComplete: IRP %p, SRB %p\n", Irp, srb));
3808
3809 //
3810 // Release the queue if it is frozen.
3811 //
3812
3815 }
3817 Fdo,
3818 Irp,
3819 srb,
3820 irpStack->MajorFunction,
3821 ((irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) ?
3822 irpStack->Parameters.DeviceIoControl.IoControlCode :
3823 0),
3825 ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
3826 &status,
3827 &retryInterval);
3828
3829 //
3830 // For Persistent Reserve requests, make sure user gets back partial data.
3831 //
3832
3833 if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
3837
3839 retry = FALSE;
3840 }
3841
3842 //
3843 // If the status is verified required and the this request
3844 // should bypass verify required then retry the request.
3845 //
3846
3847 if (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
3849
3851 retry = TRUE;
3852 }
3853
3854#ifndef __REACTOS__
3855#pragma warning(suppress:4213) // okay to cast Arg4 as a ulong for this use case
3856 if (retry && ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4)--) {
3857#else
3858 if (retry && (*(ULONG *)&irpStack->Parameters.Others.Argument4)--) {
3859#endif
3860
3861
3862 //
3863 // Retry request.
3864 //
3865
3866 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "Retry request %p\n", Irp));
3867
3868 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3869 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
3870 }
3871
3872 RetryRequest(Fdo, Irp, srb, FALSE, retryInterval);
3874 }
3875
3876 } else {
3877
3878 //
3879 // Set status for successful request
3880 //
3882 ClasspPerfIncrementSuccessfulIo(fdoExtension);
3884 } // end if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS)
3885
3886
3887 //
3888 // ensure we have returned some info, and it matches what the
3889 // original request wanted for PAGING operations only
3890 //
3891
3892 if ((NT_SUCCESS(status)) && TEST_FLAG(Irp->Flags, IRP_PAGING_IO)) {
3893 NT_ASSERT(Irp->IoStatus.Information != 0);
3894 NT_ASSERT(irpStack->Parameters.Read.Length == Irp->IoStatus.Information);
3895 }
3896
3897 //
3898 // remember if the caller wanted to skip calling IoStartNextPacket.
3899 // for legacy reasons, we cannot call IoStartNextPacket for IoDeviceControl
3900 // calls. this setting only affects device objects with StartIo routines.
3901 //
3902
3903 callStartNextPacket = !TEST_FLAG(srbFlags, SRB_FLAGS_DONT_START_NEXT_PACKET);
3904 if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
3905 callStartNextPacket = FALSE;
3906 }
3907
3908 //
3909 // Free MDL if allocated.
3910 //
3911
3912 if (TEST_FLAG(srbFlags, SRB_CLASS_FLAGS_FREE_MDL)) {
3914 IoFreeMdl(Irp->MdlAddress);
3915 Irp->MdlAddress = NULL;
3916 }
3917
3918
3919 //
3920 // Free the srb
3921 //
3922
3923 if (!TEST_FLAG(srbFlags, SRB_CLASS_FLAGS_PERSISTANT)) {
3924
3925 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3926 FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
3927 }
3928
3930 ClassFreeOrReuseSrb(fdoExtension, srb);
3931 }
3932 else {
3933 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoComplete is freeing an SRB (possibly) on behalf of another driver."));
3934 FREE_POOL(srb);
3935 }
3936
3937 } else {
3938
3939 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoComplete: Not Freeing srb @ %p because "
3940 "SRB_CLASS_FLAGS_PERSISTANT set\n", srb));
3941 if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
3942 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassIoComplete: Not Freeing sensebuffer @ %p "
3943 " because SRB_CLASS_FLAGS_PERSISTANT set\n",
3944 srb->SenseInfoBuffer));
3945 }
3946
3947 }
3948
3949 //
3950 // Set status in completing IRP.
3951 //
3952
3953 Irp->IoStatus.Status = status;
3954
3955 //
3956 // Set the hard error if necessary.
3957 //
3958
3959 if (!NT_SUCCESS(status) &&
3961 (Irp->Tail.Overlay.Thread != NULL)
3962 ) {
3963
3964 //
3965 // Store DeviceObject for filesystem, and clear
3966 // in IoStatus.Information field.
3967 //
3968
3970 Irp->IoStatus.Information = 0;
3971 }
3972
3973 //
3974 // If disk firmware update succeeded, log a system event.
3975 //
3976
3977 if (NT_SUCCESS(status) &&
3978 (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) &&
3979 (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_FIRMWARE_ACTIVATE)) {
3980
3982 }
3983
3984 //
3985 // If pending has be returned for this irp then mark the current stack as
3986 // pending.
3987 //
3988
3989 if (Irp->PendingReturned) {
3991 }
3992
3994 if (callStartNextPacket) {
3995 KIRQL oldIrql;
3996 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
3997 IoStartNextPacket(Fdo, TRUE); // Yes, some IO must now be cancellable.
3998 KeLowerIrql(oldIrql);
3999 }
4000 }
4001
4003
4004 return status;
4005
4006} // end ClassIoComplete()
4007
4008
4009/*++////////////////////////////////////////////////////////////////////////////
4010
4011ClassSendSrbSynchronous()
4012
4013Routine Description:
4014
4015 This routine is called by SCSI device controls to complete an
4016 SRB and send it to the port driver synchronously (ie wait for
4017 completion). The CDB is already completed along with the SRB CDB
4018 size and request timeout value.
4019
4020Arguments:
4021
4022 Fdo - Supplies the functional device object which represents the target.
4023
4024 Srb - Supplies a partially initialized SRB. The SRB cannot come from zone.
4025
4026 BufferAddress - Supplies the address of the buffer.
4027
4028 BufferLength - Supplies the length in bytes of the buffer.
4029
4030 WriteToDevice - Indicates the data should be transfer to the device.
4031
4032Return Value:
4033
4034 NTSTATUS indicating the final results of the operation.
4035
4036 If NT_SUCCESS(), then the amount of usable data is contained in the field
4037 Srb->DataTransferLength
4038
4039--*/
4041NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
4048 )
4049{
4050
4051 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
4052 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
4053 IO_STATUS_BLOCK ioStatus = {0};
4054 PIRP irp;
4055 PIO_STACK_LOCATION irpStack;
4056 KEVENT event;
4058 ULONG senseInfoBufferLength = SENSE_BUFFER_SIZE_EX;
4059 ULONG retryCount = MAXIMUM_RETRIES;
4061 BOOLEAN retry;
4063
4064 //
4065 // NOTE: This code is only pagable because we are not freezing
4066 // the queue. Allowing the queue to be frozen from a pagable
4067 // routine could leave the queue frozen as we try to page in
4068 // the code to unfreeze the queue. The result would be a nice
4069 // case of deadlock. Therefore, since we are unfreezing the
4070 // queue regardless of the result, just set the NO_FREEZE_QUEUE
4071 // flag in the SRB.
4072 //
4073
4075 NT_ASSERT(fdoExtension->CommonExtension.IsFdo);
4076
4078 //
4079 // Write length to SRB.
4080 //
4081
4082 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
4083
4084 //
4085 // Set SCSI bus address.
4086 //
4087
4089 }
4090
4091 //
4092 // The Srb->Function should have been set corresponding to SrbType.
4093 //
4094
4097
4098
4099 //
4100 // Sense buffer is in aligned nonpaged pool.
4101 //
4102
4103#if defined(_ARM_) || defined(_ARM64_)
4104
4105 //
4106 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
4107 // based platforms. We are taking the conservative approach here.
4108 //
4109 senseInfoBufferLength = ALIGN_UP_BY(senseInfoBufferLength,KeGetRecommendedSharedDataAlignment());
4110
4111#endif
4112
4113 senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
4114 senseInfoBufferLength,
4115 '7CcS');
4116
4117 if (senseInfoBuffer == NULL) {
4118
4119 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous: Can't allocate request sense "
4120 "buffer\n"));
4122 }
4123
4124
4125 //
4126 // Enable auto request sense.
4127 //
4130
4132
4133
4134 //
4135 // Start retries here.
4136 //
4137
4138retry:
4139
4140 //
4141 // use fdoextension's flags by default.
4142 // do not move out of loop, as the flag may change due to errors
4143 // sending this command.
4144 //
4145
4146 SrbAssignSrbFlags(Srb, fdoExtension->SrbFlags);
4147
4148 if (BufferAddress != NULL) {
4149 if (WriteToDevice) {
4151 } else {
4153 }
4154 }
4155
4156
4157 //
4158 // Initialize the QueueAction field.
4159 //
4160
4162
4163 //
4164 // Disable synchronous transfer for these requests.
4165 //
4167
4168 //
4169 // Set the event object to the unsignaled state.
4170 // It will be used to signal request completion.
4171 //
4172
4174
4175 //
4176 // Build device I/O control request with METHOD_NEITHER data transfer.
4177 // We'll queue a completion routine to cleanup the MDL's and such ourself.
4178 //
4179
4181 (CCHAR) (fdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1),
4182 FALSE);
4183
4184 if (irp == NULL) {
4188 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous: Can't allocate Irp\n"));
4190 }
4191
4192 //
4193 // Get next stack location.
4194 //
4195
4196 irpStack = IoGetNextIrpStackLocation(irp);
4197
4198 //
4199 // Set up SRB for execute scsi request. Save SRB address in next stack
4200 // for the port driver.
4201 //
4202
4203 irpStack->MajorFunction = IRP_MJ_SCSI;
4204 irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)Srb;
4205
4208 Srb,
4209 TRUE,
4210 TRUE,
4211 TRUE);
4212
4213 irp->UserIosb = &ioStatus;
4214 irp->UserEvent = &event;
4215
4216 if (BufferAddress) {
4217 //
4218 // Build an MDL for the data buffer and stick it into the irp. The
4219 // completion routine will unlock the pages and free the MDL.
4220 //
4221
4222 irp->MdlAddress = IoAllocateMdl( BufferAddress,
4224 FALSE,
4225 FALSE,
4226 irp );
4227 if (irp->MdlAddress == NULL) {
4231 IoFreeIrp( irp );
4232 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous: Can't allocate MDL\n"));
4234 }
4235
4236 _SEH2_TRY {
4237
4238 //
4239 // the io manager unlocks these pages upon completion
4240 //
4241
4242 MmProbeAndLockPages( irp->MdlAddress,
4243 KernelMode,
4245 IoWriteAccess));
4246
4247#ifdef _MSC_VER
4248 #pragma warning(suppress: 6320) // We want to handle any exception that MmProbeAndLockPages might throw
4249#endif
4252
4256 IoFreeMdl(irp->MdlAddress);
4257 IoFreeIrp(irp);
4258
4259 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous: Exception %lx "
4260 "locking buffer\n", status));
4261 _SEH2_YIELD(return status);
4262 } _SEH2_END;
4263 }
4264
4265 //
4266 // Set the transfer length.
4267 //
4268
4270
4271 //
4272 // Zero out status.
4273 //
4274
4276 Srb->SrbStatus = 0;
4278
4279 //
4280 // Set up IRP Address.
4281 //
4282
4284
4285 //
4286 // Call the port driver with the request and wait for it to complete.
4287 //
4288
4290
4291 if (status == STATUS_PENDING) {
4293 status = ioStatus.Status;
4294 }
4295
4296// NT_ASSERT(SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_PENDING);
4299
4300 //
4301 // Clear the IRP address in SRB as IRP has been freed at this time
4302 // and don't want to leave any references that may be accessed.
4303 //
4304
4306
4307 //
4308 // Check that request completed without error.
4309 //
4310
4312
4313 LONGLONG retryInterval;
4314
4315 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendSrbSynchronous - srb %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)", Srb,
4321
4322 //
4323 // assert that the queue is not frozen
4324 //
4325
4327
4328 //
4329 // Update status and determine if request should be retried.
4330 //
4331
4333 NULL, // no valid irp exists
4336 0,
4337 MAXIMUM_RETRIES - retryCount,
4338 &status,
4339 &retryInterval);
4340
4341 if (retry) {
4342
4345
4347
4348 validSense = ScsiGetSenseKeyAndCodes(senseInfoBuffer,
4351 NULL,
4353 NULL);
4354 }
4355
4358
4359 LARGE_INTEGER delay;
4360
4361 //
4362 // Delay for at least 2 seconds.
4363 //
4364
4365 if (retryInterval < 2*1000*1000*10) {
4366 retryInterval = 2*1000*1000*10;
4367 }
4368
4369 delay.QuadPart = -retryInterval;
4370
4371 //
4372 // Stall for a while to let the device become ready
4373 //
4374
4376
4377 }
4378
4379
4380 //
4381 // If retries are not exhausted then retry this operation.
4382 //
4383
4384 if (retryCount--) {
4385
4386 if (PORT_ALLOCATED_SENSE_EX(fdoExtension, Srb)) {
4388 }
4389
4390 goto retry;
4391 }
4392 }
4393
4394
4395 } else {
4398 }
4399
4400 //
4401 // required even though we allocated our own, since the port driver may
4402 // have allocated one also
4403 //
4404
4405 if (PORT_ALLOCATED_SENSE_EX(fdoExtension, Srb)) {
4407 }
4408
4412
4413 return status;
4414}
4415
4416
4417/*++////////////////////////////////////////////////////////////////////////////
4418
4419ClassInterpretSenseInfo()
4420
4421Routine Description:
4422
4423 This routine interprets the data returned from the SCSI
4424 request sense. It determines the status to return in the
4425 IRP and whether this request can be retried.
4426
4427Arguments:
4428
4429 Fdo - Supplies the device object associated with this request.
4430
4431 Srb - Supplies the scsi request block which failed.
4432
4433 MajorFunctionCode - Supplies the function code to be used for logging.
4434
4435 IoDeviceCode - Supplies the device code to be used for logging.
4436
4437 RetryCount - Number of times that the request has been retried.
4438
4439 Status - Returns the status for the request.
4440
4441 RetryInterval - Number of seconds before the request should be retried.
4442 Zero indicates the request should be immediately retried.
4443
4444Return Value:
4445
4446 BOOLEAN TRUE: Drivers should retry this request.
4447 FALSE: Drivers should not retry this request.
4448
4449--*/
4450BOOLEAN
4451NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
4457 _In_ ULONG RetryCount,
4459 _Out_opt_ _Deref_out_range_(0,100) ULONG *RetryInterval
4460 )
4461{
4462 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
4463 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
4465 PVOID senseBuffer = SrbGetSenseInfoBuffer(Srb);
4466 BOOLEAN retry = TRUE;
4467 BOOLEAN logError = FALSE;
4468 BOOLEAN unhandledError = FALSE;
4469 BOOLEAN incrementErrorCount = FALSE;
4470
4471 //
4472 // NOTE: This flag must be used only for read/write requests that
4473 // fail with a unexpected retryable error.
4474 //
4475 BOOLEAN logRetryableError = TRUE;
4476
4477 //
4478 // Indicates if we should log this error in our internal log.
4479 //
4480 BOOLEAN logErrorInternal = TRUE;
4481
4482 ULONGLONG badSector = 0;
4483 ULONG uniqueId = 0;
4484
4485 NTSTATUS logStatus;
4486
4487 ULONGLONG readSector;
4488 ULONG index;
4489
4490 ULONG retryInterval = 0;
4491 KIRQL oldIrql;
4492 PCDB cdb = SrbGetCdb(Srb);
4493 UCHAR cdbOpcode = 0;
4494 ULONG cdbLength = SrbGetCdbLength(Srb);
4495
4496#if DBG
4497 BOOLEAN isReservationConflict = FALSE;
4498#endif
4499
4500 if (cdb) {
4501 cdbOpcode = cdb->CDB6GENERIC.OperationCode;
4502 }
4503
4505 logStatus = -1;
4506
4508
4509 //
4510 // Log anything remotely incorrect about paging i/o
4511 //
4512
4513 logError = TRUE;
4514 uniqueId = 301;
4515 logStatus = IO_WARNING_PAGING_FAILURE;
4516 }
4517
4518 //
4519 // Check that request sense buffer is valid.
4520 //
4521
4522 NT_ASSERT(fdoExtension->CommonExtension.IsFdo);
4523
4524
4525 //
4526 // must handle the SRB_STATUS_INTERNAL_ERROR case first,
4527 // as it has all the flags set.
4528 //
4529
4531
4532 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
4533 "ClassInterpretSenseInfo: Internal Error code is %x\n",
4535
4536 retry = FALSE;
4538
4540
4541 //
4542 // Need to reserve STATUS_DEVICE_BUSY to convey reservation conflict
4543 // for read/write requests as there are upper level components that
4544 // have built-in assumptions that STATUS_DEVICE_BUSY implies reservation
4545 // conflict.
4546 //
4548 retry = FALSE;
4549 logError = FALSE;
4550#if DBG
4551 isReservationConflict = TRUE;
4552#endif
4553
4554 } else {
4555
4557
4558 if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) && senseBuffer) {
4559
4560 UCHAR errorCode = 0;
4561 UCHAR senseKey = 0;
4562 UCHAR addlSenseCode = 0;
4563 UCHAR addlSenseCodeQual = 0;
4564 BOOLEAN isIncorrectLengthValid = FALSE;
4565 BOOLEAN incorrectLength = FALSE;
4566 BOOLEAN isInformationValid = FALSE;
4568
4569
4570 validSense = ScsiGetSenseKeyAndCodes(senseBuffer,
4573 &senseKey,
4574 &addlSenseCode,
4575 &addlSenseCodeQual);
4576
4577 if (!validSense && !IsSenseDataFormatValueValid(senseBuffer)) {
4578
4580
4581 validSense = ScsiGetFixedSenseKeyAndCodes(senseBuffer,
4583 &senseKey,
4584 &addlSenseCode,
4585 &addlSenseCodeQual);
4586 }
4587
4588 if (!validSense) {
4589 goto __ClassInterpretSenseInfo_ProcessingInvalidSenseBuffer;
4590 }
4591
4592 errorCode = ScsiGetSenseErrorCode(senseBuffer);
4593
4594 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: Error code is %x\n", errorCode));
4595 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: Sense key is %x\n", senseKey));
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));
4598
4599 if (IsDescriptorSenseDataFormat(senseBuffer)) {
4600
4601 //
4602 // Sense data in Descriptor format
4603 //
4604
4605 PVOID startBuffer = NULL;
4606 UCHAR startBufferLength = 0;
4607
4608
4609 if (ScsiGetSenseDescriptor(senseBuffer,
4611 &startBuffer,
4612 &startBufferLength)) {
4613 UCHAR outType;
4615 UCHAR outBufferLength = 0;
4616 BOOLEAN foundBlockCommandType = FALSE;
4617 BOOLEAN foundInformationType = FALSE;
4619
4622
4623 while ((!foundBlockCommandType || !foundInformationType) &&
4624 ScsiGetNextSenseDescriptorByType(startBuffer,
4625 startBufferLength,
4626 typeList,
4627 ARRAYSIZE(typeList),
4628 &outType,
4629 &outBuffer,
4630 &outBufferLength)) {
4631
4633
4634 if (outBufferLength < descriptorLength) {
4635
4636 // Descriptor data is truncated.
4637 // Complete searching descriptors. Exit the loop now.
4638 break;
4639 }
4640
4642
4643 //
4644 // Block Command type
4645 //
4646
4647 if (!foundBlockCommandType) {
4648
4649 foundBlockCommandType = TRUE;
4650
4651 if (ScsiValidateBlockCommandSenseDescriptor(outBuffer, outBufferLength)) {
4652 incorrectLength = ((PSCSI_SENSE_DESCRIPTOR_BLOCK_COMMAND)outBuffer)->IncorrectLength;
4653 isIncorrectLengthValid = TRUE;
4654 }
4655 } else {
4656
4657 //
4658 // A Block Command descriptor is already found earlier.
4659 //
4660 // T10 SPC specification only allows one descriptor for Block Command Descriptor type.
4661 // Assert here to catch devices that violate this rule. Ignore this descriptor.
4662 //
4664 }
4665
4666 } else if (outType == SCSI_SENSE_DESCRIPTOR_TYPE_INFORMATION) {
4667
4668 //
4669 // Information type
4670 //
4671
4672 if (!foundInformationType) {
4673
4674 foundInformationType = TRUE;
4675
4676 if (ScsiValidateInformationSenseDescriptor(outBuffer, outBufferLength)) {
4678 isInformationValid = TRUE;
4679 }
4680 } else {
4681
4682 //
4683 // A Information descriptor is already found earlier.
4684 //
4685 // T10 SPC specification only allows one descriptor for Information Descriptor type.
4686 // Assert here to catch devices that violate this rule. Ignore this descriptor.
4687 //
4689 }
4690
4691 } else {
4692
4693 //
4694 // ScsiGetNextDescriptorByType should only return a type that is specified by us.
4695 //
4697 break;
4698 }
4699
4700 //
4701 // Advance to start address of next descriptor
4702 //
4703 startBuffer = (PUCHAR)outBuffer + descriptorLength;
4704 startBufferLength = outBufferLength - descriptorLength;
4705 }
4706 }
4707 } else {
4708
4709 //
4710 // Sense data in Fixed format
4711 //
4712
4713 incorrectLength = ((PFIXED_SENSE_DATA)(senseBuffer))->IncorrectLength;
4715 isInformationValid = TRUE;
4716 isIncorrectLengthValid = TRUE;
4717 }
4718
4719
4720 switch (senseKey) {
4721
4722 case SCSI_SENSE_NO_SENSE: {
4723
4724 //
4725 // Check other indicators.
4726 //
4727
4728 if (isIncorrectLengthValid && incorrectLength) {
4729
4730 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4731 "Incorrect length detected.\n"));
4733 retry = FALSE;
4734
4735 } else {
4736
4737 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4738 "No specific sense key\n"));
4740 retry = TRUE;
4741 }
4742
4743 break;
4744 } // end SCSI_SENSE_NO_SENSE
4745
4747
4748 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4749 "Recovered error\n"));
4751 retry = FALSE;
4752 logError = TRUE;
4753 uniqueId = 258;
4754
4755 switch(addlSenseCode) {
4758 logStatus = IO_ERR_SEEK_ERROR;
4759 break;
4760 }
4761
4764 logStatus = IO_RECOVERED_VIA_ECC;
4765 break;
4766 }
4767
4769
4770 UCHAR wmiEventData[sizeof(ULONG)+sizeof(UCHAR)] = {0};
4771
4772 *((PULONG)wmiEventData) = sizeof(UCHAR);
4773 wmiEventData[sizeof(ULONG)] = addlSenseCodeQual;
4774
4775 //
4776 // Don't log another eventlog if we have already logged once
4777 // NOTE: this should have been interlocked, but the structure
4778 // was publicly defined to use a BOOLEAN (char). Since
4779 // media only reports these errors once per X minutes,
4780 // the potential race condition is nearly non-existant.
4781 // the worst case is duplicate log entries, so ignore.
4782 //
4783
4784 logError = FALSE;
4785 if (fdoExtension->FailurePredicted == 0) {
4786 logError = TRUE;
4787 }
4788 fdoExtension->FailureReason = addlSenseCodeQual;
4789 logStatus = IO_WRN_FAILURE_PREDICTED;
4790
4791 ClassNotifyFailurePredicted(fdoExtension,
4792 (PUCHAR)wmiEventData,
4793 sizeof(wmiEventData),
4794 FALSE, // do not log error
4795 4, // unique error value
4798 SrbGetLun(Srb));
4799
4800 fdoExtension->FailurePredicted = TRUE;
4801 break;
4802 }
4803
4804 default: {
4805 logStatus = IO_ERR_CONTROLLER_ERROR;
4806 break;
4807 }
4808
4809 } // end switch(addlSenseCode)
4810
4811 if (isIncorrectLengthValid && incorrectLength) {
4812
4813 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4814 "Incorrect length detected.\n"));
4816 }
4817
4818
4819 break;
4820 } // end SCSI_SENSE_RECOVERED_ERROR
4821
4822 case SCSI_SENSE_NOT_READY: {
4823
4824 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4825 "Device not ready\n"));
4827
4828 switch (addlSenseCode) {
4829
4831
4832 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4833 "Lun not ready\n"));
4834
4835 retryInterval = NOT_READY_RETRY_INTERVAL;
4836
4837 switch (addlSenseCodeQual) {
4838
4840 DEVICE_EVENT_BECOMING_READY notReady = {0};
4841
4842 logRetryableError = FALSE;
4843 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4844 "In process of becoming ready\n"));
4845
4846 notReady.Version = 1;
4847 notReady.Reason = 1;
4848 notReady.Estimated100msToReady = retryInterval * 10;
4849 ClassSendNotification(fdoExtension,
4850 &GUID_IO_DEVICE_BECOMING_READY,
4852 &notReady);
4853 break;
4854 }
4855
4857 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4858 "Manual intervention required\n"));
4860 retry = FALSE;
4861 break;
4862 }
4863
4865 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4866 "Format in progress\n"));
4867 retry = FALSE;
4868 break;
4869 }
4870
4872 DEVICE_EVENT_BECOMING_READY notReady = {0};
4873
4874 logRetryableError = FALSE;
4875 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4876 "Operation In Progress\n"));
4877
4878 notReady.Version = 1;
4879 notReady.Reason = 2;
4880 notReady.Estimated100msToReady = retryInterval * 10;
4881 ClassSendNotification(fdoExtension,
4882 &GUID_IO_DEVICE_BECOMING_READY,
4884 &notReady);
4885
4886 break;
4887 }
4888
4890 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4891 "Long write in progress\n"));
4892 //
4893 // This has been seen as a transcient failure on some cdrom
4894 // drives. The cdrom class driver is going to override this
4895 // setting but has no way of dropping the retry interval
4896 //
4897 retry = FALSE;
4898 retryInterval = 1;
4899 break;
4900 }
4901
4903 logRetryableError = FALSE;
4904 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4905 "The device (%p) is busy allocating space.\n",
4906 Fdo));
4907
4908 //
4909 // This indicates that a thinly-provisioned device has hit
4910 // a temporary resource exhaustion and is busy allocating
4911 // more space. We need to retry the request as the device
4912 // will eventually be able to service it.
4913 //
4915 retry = TRUE;
4916
4917 break;
4918 }
4919
4921
4922 if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
4924
4925 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
4926 "ClassInterpretSenseInfo: "
4927 "not ready, cause unknown\n"));
4928 /*
4929 Many non-WHQL certified drives (mostly CD-RW) return
4930 this when they have no media instead of the obvious
4931 choice of:
4932
4933 SCSI_SENSE_NOT_READY/SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
4934
4935 These drives should not pass WHQL certification due
4936 to this discrepency.
4937
4938 */
4939 retry = FALSE;
4940 break;
4941
4942 } else {
4943
4944 //
4945 // Treat this as init command required and fall through.
4946 //
4947 }
4948 }
4949
4951 default: {
4952 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4953 "Initializing command required\n"));
4954 retryInterval = 0; // go back to default
4955 logRetryableError = FALSE;
4956
4957 //
4958 // This sense code/additional sense code
4959 // combination may indicate that the device
4960 // needs to be started. Send an start unit if this
4961 // is a disk device.
4962 //
4963 if (TEST_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT) &&
4965
4967 }
4968 break;
4969 }
4970
4971 } // end switch (addlSenseCodeQual)
4972 break;
4973 }
4974
4976 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4977 "No Media in device.\n"));
4979 retry = FALSE;
4980
4981 //
4982 // signal MCN that there isn't any media in the device
4983 //
4984 if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
4985 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
4986 "No Media in a non-removable device %p\n",
4987 Fdo));
4988 }
4989
4990 if (addlSenseCodeQual == 0xCC){
4991 /*
4992 * The IMAPI filter returns this ASCQ value when it is burning CD-R media.
4993 * We want to indicate that the media is not present to most applications;
4994 * but RSM has to know that the media is still in the drive (i.e. the drive is not free).
4995 */
4996 ClassSetMediaChangeState(fdoExtension, MediaUnavailable, FALSE);
4997 }
4998 else {
4999 ClassSetMediaChangeState(fdoExtension, MediaNotPresent, FALSE);
5000 }
5001
5002 break;
5003 }
5004 } // end switch (addlSenseCode)
5005
5006 break;
5007 } // end SCSI_SENSE_NOT_READY
5008
5010 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5011 "Medium Error (bad block)\n"));
5013
5014 retry = FALSE;
5015 logError = TRUE;
5016 uniqueId = 256;
5017 logStatus = IO_ERR_BAD_BLOCK;
5018
5019 //
5020 // Check if this error is due to unknown format
5021 //
5022 if (addlSenseCode == SCSI_ADSENSE_INVALID_MEDIA) {
5023
5024 switch (addlSenseCodeQual) {
5025
5027
5029
5030 //
5031 // Log error only if this is a paging request
5032 //
5034 logError = FALSE;
5035 }
5036 break;
5037 }
5038
5040
5042 logError = FALSE;
5043 break;
5044
5045 }
5046 default: {
5047 break;
5048 }
5049 } // end switch addlSenseCodeQual
5050
5051 } // end SCSI_ADSENSE_INVALID_MEDIA
5052
5053 break;
5054
5055 } // end SCSI_SENSE_MEDIUM_ERROR
5056
5058 BOOLEAN logHardwareError = TRUE;
5059
5060 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5061 "Hardware error\n"));
5062
5063 if (fdoData->LegacyErrorHandling == FALSE) {
5064 //
5065 // Hardware errors indicate something has seriously gone
5066 // wrong with the device and retries are very unlikely to
5067 // succeed so fail this request back immediately.
5068 //
5069 retry = FALSE;
5071 logError = FALSE;
5072
5073 } else {
5074 //
5075 // Revert to legacy behavior. That is, retry everything by default.
5076 //
5077 retry = TRUE;
5079 logError = TRUE;
5080 uniqueId = 257;
5081 logStatus = IO_ERR_CONTROLLER_ERROR;
5082 logHardwareError = FALSE;
5083
5084 //
5085 // This indicates the possibility of a dropped FC packet.
5086 //
5087 if ((addlSenseCode == SCSI_ADSENSE_LOGICAL_UNIT_ERROR && addlSenseCodeQual == SCSI_SENSEQ_TIMEOUT_ON_LOGICAL_UNIT) ||
5088 (addlSenseCode == SCSI_ADSENSE_DATA_TRANSFER_ERROR && addlSenseCodeQual == SCSI_SENSEQ_INITIATOR_RESPONSE_TIMEOUT)) {
5089 //
5090 // Fail requests that report this error back to the application.
5091 //
5092 retry = FALSE;
5093
5094 //
5095 // Log a more descriptive error and avoid a second
5096 // error message (IO_ERR_CONTROLLER_ERROR) being logged.
5097 //
5098 logHardwareError = TRUE;
5099 logError = FALSE;
5100 }
5101 }
5102
5103 //
5104 // If CRC error was returned, retry after a slight delay.
5105 //
5106 if (addlSenseCode == SCSI_ADSENSE_LUN_COMMUNICATION &&
5107 addlSenseCodeQual == SCSI_SESNEQ_COMM_CRC_ERROR) {
5108 retry = TRUE;
5109 retryInterval = 1;
5110 logHardwareError = FALSE;
5111 logError = FALSE;
5112 }
5113
5114 //
5115 // Hardware errors warrant a more descriptive error.
5116 // Specifically, we need to ensure this disk is easily
5117 // identifiable.
5118 //
5119 if (logHardwareError) {
5120 UCHAR senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb);
5121 UCHAR senseBufferSize = 0;
5122
5123 if (ScsiGetTotalSenseByteCountIndicated(senseBuffer,
5124 senseInfoBufferLength,
5125 &senseBufferSize)) {
5126
5127 senseBufferSize = min(senseBufferSize, senseInfoBufferLength);
5128
5129 } else {
5130 //
5131 // it's smaller than required to read the total number of
5132 // valid bytes, so just use the SenseInfoBufferLength field.
5133 //
5134 senseBufferSize = senseInfoBufferLength;
5135 }
5136
5138 senseBufferSize,
5139 senseBuffer,
5143 cdbLength,
5144 cdb,
5145 NULL);
5146 }
5147
5148 break;
5149 } // end SCSI_SENSE_HARDWARE_ERROR
5150
5152
5153 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5154 "Illegal SCSI request\n"));
5156 retry = FALSE;
5157
5158 switch (addlSenseCode) {
5159
5160 case SCSI_ADSENSE_NO_SENSE: {
5161
5162 switch (addlSenseCodeQual) {
5163
5164 //
5165 // 1. Duplicate List Identifier
5166 //
5168
5169 //
5170 // XCOPY, READ BUFFER and CHANGE ALIASES return this sense combination under
5171 // certain conditions. Since these commands aren't sent down natively by the
5172 // Windows OS, return the default error for them and only handle this sense
5173 // combination for offload data transfer commands.
5174 //
5176
5177 TracePrint((TRACE_LEVEL_ERROR,
5178 TRACE_FLAG_IOCTL,
5179 "ClassInterpretSenseInfo (%p): Duplicate List Identifier (command %x, parameter field offset 0x%016llx)\n",
5180 Fdo,
5181 cdbOpcode,
5182 information));
5183
5184 NT_ASSERTMSG("Duplicate list identifier specified", FALSE);
5185
5186 //
5187 // The host should ensure that it uses unique list id for each TokenOperation request.
5188 //
5190 }
5191 break;
5192 }
5193 }
5194 break;
5195 }
5196
5198
5199 switch (addlSenseCodeQual) {
5200
5201 //
5202 // 1. Source/Destination pairing can't communicate with each other or the copy manager.
5203 //
5205
5206 TracePrint((TRACE_LEVEL_ERROR,
5207 TRACE_FLAG_IOCTL,
5208 "ClassInterpretSenseInfo (%p): Source-Destination LUNs can't communicate (command %x)\n",
5209 Fdo,
5210 cdbOpcode));
5211
5213 break;
5214 }
5215 }
5216 break;
5217 }
5218
5220
5221 switch (addlSenseCodeQual) {
5222
5223 //
5224 // 1. Sum of logical block fields in all block device range descriptors is greater than number
5225 // of logical blocks in the ROD minus block offset into ROD
5226 //
5228
5229 TracePrint((TRACE_LEVEL_ERROR,
5230 TRACE_FLAG_IOCTL,
5231 "ClassInterpretSenseInfo (%p): Host specified a transfer length greater than what is represented by the token (considering the offset) [command %x]\n",
5232 Fdo,
5233 cdbOpcode));
5234
5235 NT_ASSERTMSG("Host specified blocks to write beyond what is represented by the token", FALSE);
5236
5238 break;
5239 }
5240 }
5241 break;
5242 }
5243
5244 //
5245 // 1. Parameter data truncation (e.g. last descriptor was not fully specified)
5246 //
5248
5249 TracePrint((TRACE_LEVEL_ERROR,
5250 TRACE_FLAG_IOCTL,
5251 "ClassInterpretSenseInfo (%p): Target truncated the block device range descriptors in the parameter list (command %x)\n",
5252 Fdo,
5253 cdbOpcode));
5254
5255 NT_ASSERTMSG("Parameter data truncation", FALSE);
5256
5258 break;
5259 }
5260
5262 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5263 "Illegal command\n"));
5264 break;
5265 }
5266
5268
5269 LARGE_INTEGER logicalBlockAddr;
5270 LARGE_INTEGER lastLBA;
5271 ULONG numTransferBlocks = 0;
5272
5273 logicalBlockAddr.QuadPart = 0;
5274
5275 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: Illegal block address\n"));
5276
5278
5279 if (Fdo->DeviceType == FILE_DEVICE_DISK) {
5280
5281 if (IS_SCSIOP_READWRITE(cdbOpcode) && cdb) {
5282
5283 if (TEST_FLAG(fdoExtension->DeviceFlags, DEV_USE_16BYTE_CDB)) {
5284 REVERSE_BYTES_QUAD(&logicalBlockAddr, &cdb->CDB16.LogicalBlock);
5285 REVERSE_BYTES(&numTransferBlocks, &cdb->CDB16.TransferLength);
5286 } else {
5287 REVERSE_BYTES(&logicalBlockAddr.LowPart, &cdb->CDB10.LogicalBlockByte0);
5288 REVERSE_BYTES_SHORT((PUSHORT)&numTransferBlocks, &cdb->CDB10.TransferBlocksMsb);
5289 }
5290
5292
5293 if ((logicalBlockAddr.QuadPart > lastLBA.QuadPart) ||
5294 ((logicalBlockAddr.QuadPart + numTransferBlocks - 1) > lastLBA.QuadPart)) {
5295
5296 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5297 "Request beyond boundary. Last LBA: 0x%I64X Read LBA: 0x%I64X Length: 0x%X\n",
5298 (__int64) lastLBA.QuadPart, (__int64) logicalBlockAddr.QuadPart, numTransferBlocks));
5299 } else {
5300 //
5301 // Should only retry these if the request was
5302 // truly within our expected size.
5303 //
5304 // Fujitsu IDE drives have been observed to
5305 // return this error transiently for a legal LBA;
5306 // manual retry in the debugger then works, so
5307 // there is a good chance that a programmed retry
5308 // will also work.
5309 //
5310
5311 retry = TRUE;
5312 retryInterval = 5;
5313 }
5314 } else if (ClasspIsOffloadDataTransferCommand(cdb)) {
5315
5316 //
5317 // 1. Number of logical blocks of block device range descriptor exceeds capacity of the medium
5318 //
5319 TracePrint((TRACE_LEVEL_ERROR,
5320 TRACE_FLAG_IOCTL,
5321 "ClassInterpretSenseInfo (%p): LBA out of range (command %x, parameter field offset 0x%016llx)\n",
5322 Fdo,
5323 cdbOpcode,
5324 information));
5325
5326 NT_ASSERTMSG("Number of blocks specified exceeds LUN capacity", FALSE);
5327 }
5328 }
5329 break;
5330 }
5331
5332 //
5333 // 1. Generic error - cause not reportable
5334 // 2. Insufficient resources to create ROD
5335 // 3. Insufficient resources to create Token
5336 // 4. Max number of tokens exceeded
5337 // 5. Remote Token creation not supported
5338 // 6. Token expired
5339 // 7. Token unknown
5340 // 8. Unsupported Token type
5341 // 9. Token corrupt
5342 // 10. Token revoked
5343 // 11. Token cancelled
5344 // 12. Remote Token usage not supported
5345 //
5347
5348 TracePrint((TRACE_LEVEL_ERROR,
5349 TRACE_FLAG_IOCTL,
5350 "ClassInterpretSenseInfo (%p): Invalid/Expired/Modified token specified (command %x, parameter field offset 0x%016llx)\n",
5351 Fdo,
5352 cdbOpcode,
5353 information));
5354
5356 break;
5357 }
5358
5361
5362 //
5363 // 1. Mismatched I_T nexus and list identifier
5364 //
5365 TracePrint((TRACE_LEVEL_ERROR,
5366 TRACE_FLAG_IOCTL,
5367 "ClassInterpretSenseInfo (%p): Incorrect I_T nexus likely used (command %x)\n",
5368 Fdo,
5369 cdbOpcode));
5370
5371 //
5372 // The host should ensure that it sends TokenOperation and ReceiveTokenInformation for the same
5373 // list Id using the same I_T nexus.
5374 //
5376
5377 } else {
5378
5379 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5380 "Invalid CDB\n"));
5381
5382 //
5383 // Note: the retry interval is not typically used.
5384 // it is set here only because a ClassErrorHandler
5385 // cannot set the retryInterval, and the error may
5386 // require a few commands to be sent to clear whatever
5387 // caused this condition (i.e. disk clears the write
5388 // cache, requiring at least two commands)
5389 //
5390 // hopefully, this shortcoming can be changed for
5391 // blackcomb.
5392 //
5393
5394 retryInterval = 3;
5395 }
5396 break;
5397 }
5398
5400 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5401 "Invalid LUN\n"));
5403 break;
5404 }
5405
5407
5408 switch (addlSenseCodeQual) {
5409
5410 //
5411 // 1. Alignment violation (e.g. copy manager is unable to copy because destination offset is NOT aligned to LUN's granularity/alignment)
5412 //
5414
5415 TracePrint((TRACE_LEVEL_ERROR,
5416 TRACE_FLAG_IOCTL,
5417 "ClassInterpretSenseInfo (%p): Alignment violation for command %x.\n",
5418 Fdo,
5419 cdbOpcode));
5420
5421 NT_ASSERTMSG("Specified offset is not aligned to LUN's granularity", FALSE);
5422
5424 break;
5425 }
5426
5427 //
5428 // 1. Number of block device range descriptors is greater than maximum range descriptors
5429 //
5431
5432 TracePrint((TRACE_LEVEL_ERROR,
5433 TRACE_FLAG_IOCTL,
5434 "ClassInterpretSenseInfo (%p): Too many descriptors in parameter list for command %x (parameter field offset 0x%016llx)\n",
5435 Fdo,
5436 cdbOpcode,
5437 information));
5438
5439 NT_ASSERTMSG("Too many descriptors specified", FALSE);
5440
5442 break;
5443 }
5444
5445 default: {
5446
5448
5449 //
5450 // 1. (Various) Invalid parameter length
5451 // 2. Requested inactivity timeout is greater than maximum inactivity timeout
5452 // 3. Same LBA is included in more than one block device range descriptor (overlapping LBAs)
5453 // 4. Total number of logical blocks of all block range descriptors is greater than the maximum transfer size
5454 // 5. Total number of logical blocks of all block range descriptors is greater than maximum token transfer size
5455 // (e.g. WriteUsingToken descriptors specify a cumulative total block count that exceeds the PopulateToken that created the token)
5456 // 6. Block offset into ROD specified an offset that is greater than or equal to the number of logical blocks in the ROD
5457 // 7. Number of logical blocks in a block device range descriptor is greater than maximum transfer length in blocks
5458 //
5459 TracePrint((TRACE_LEVEL_ERROR,
5460 TRACE_FLAG_IOCTL,
5461 "ClassInterpretSenseInfo (%p): Illegal field in parameter list for command %x (parameter field offset 0x%016llx) [AddSense %x, AddSenseQ %x]\n",
5462 Fdo,
5463 cdbOpcode,
5465 addlSenseCode,
5466 addlSenseCodeQual));
5467
5468 NT_ASSERTMSG("Invalid field in parameter list", FALSE);
5469
5471 }
5472
5473 break;
5474 }
5475 }
5476 break;
5477 }
5478
5480 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5481 "Copy protection failure\n"));
5482
5484
5485 switch (addlSenseCodeQual) {
5487 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5488 "ClassInterpretSenseInfo: "
5489 "Authentication failure\n"));
5491 break;
5493 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5494 "ClassInterpretSenseInfo: "
5495 "Key not present\n"));
5497 break;
5499 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5500 "ClassInterpretSenseInfo: "
5501 "Key not established\n"));
5503 break;
5505 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5506 "ClassInterpretSenseInfo: "
5507 "Read of scrambled sector w/o "
5508 "authentication\n"));
5510 break;
5512 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5513 "ClassInterpretSenseInfo: "
5514 "Media region does not logical unit "
5515 "region\n"));
5517 break;
5519 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
5520 "ClassInterpretSenseInfo: "
5521 "Region set error -- region may "
5522 "be permanent\n"));
5524 break;
5525 } // end switch of ASCQ for COPY_PROTECTION_FAILURE
5526
5527 break;
5528 }
5529
5531 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5532 "Music area\n"));
5533 break;
5534 }
5535
5537 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5538 "Data area\n"));
5539 break;
5540 }
5541
5543 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5544 "Volume overflow\n"));
5545 break;
5546 }
5547
5548 } // end switch (addlSenseCode)
5549
5550 break;
5551 } // end SCSI_SENSE_ILLEGAL_REQUEST
5552
5554
5555 ULONG count;
5556
5557 //
5558 // A media change may have occured so increment the change
5559 // count for the physical device
5560 //
5561
5562 count = InterlockedIncrement((volatile LONG *)&fdoExtension->MediaChangeCount);
5563 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassInterpretSenseInfo: "
5564 "Media change count for device %d incremented to %#lx\n",
5565 fdoExtension->DeviceNumber, count));
5566
5567
5568 switch (addlSenseCode) {
5570 logRetryableError = FALSE;
5571 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassInterpretSenseInfo: "
5572 "Media changed\n"));
5573
5574 if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
5575 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_MCN, "ClassInterpretSenseInfo: "
5576 "Media Changed on non-removable device %p\n",
5577 Fdo));
5578 }
5579 ClassSetMediaChangeState(fdoExtension, MediaPresent, FALSE);
5580 break;
5581 }
5582
5584 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5585 "Bus reset\n"));
5586 break;
5587 }
5588
5590 logRetryableError = FALSE;
5591 if (addlSenseCodeQual == SCSI_SENSEQ_CAPACITY_DATA_CHANGED) {
5592 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5593 "Device capacity changed (e.g. thinly provisioned LUN). Retry the request.\n"));
5594
5596
5597 //
5598 // Retry with 1 second delay as ClassQueueCapacityChangedEventWorker may trigger a couple of commands sent to disk.
5599 //
5600 retryInterval = 1;
5601 retry = TRUE;
5602 }
5603 break;
5604 }
5605
5607
5608 switch (addlSenseCodeQual) {
5609
5611
5612 logRetryableError = FALSE;
5613 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5614 "Device (%p) has hit a soft threshold.\n",
5615 Fdo));
5616
5617 //
5618 // This indicates that a resource provisioned or thinly
5619 // provisioned device has hit a soft threshold. Queue a
5620 // worker thread to log a system event and then retry the
5621 // original request.
5622 //
5624 break;
5625 }
5626 default: {
5627 retry = FALSE;
5628 break;
5629 }
5630
5631 } // end switch (addlSenseCodeQual)
5632 break;
5633 }
5634
5636
5637 if (addlSenseCodeQual == SCSI_SENSEQ_MICROCODE_CHANGED) {
5638 //
5639 // Device firmware has been changed. Retry the request.
5640 //
5641 logRetryableError = TRUE;
5642 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5643 "Device firmware has been changed.\n"));
5644
5645 retryInterval = 1;
5646 retry = TRUE;
5647 } else {
5648 //
5649 // Device information has changed, we need to rescan the
5650 // bus for changed information such as the capacity.
5651 //
5652 logRetryableError = FALSE;
5653 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5654 "Device information changed. Invalidate the bus\n"));
5655
5656 if (addlSenseCodeQual == SCSI_SENSEQ_INQUIRY_DATA_CHANGED) {
5657
5659 }
5660
5661 if (addlSenseCodeQual == SCSI_SENSEQ_INQUIRY_DATA_CHANGED ||
5662 addlSenseCodeQual == SCSI_SENSEQ_OPERATING_DEFINITION_CHANGED) {
5663
5664 //
5665 // Since either the LB provisioning type changed, or the block/slab size
5666 // changed, next time anyone trying to query the FunctionSupportInfo, we
5667 // will requery the device.
5668 //
5669 InterlockedIncrement((volatile LONG *)&fdoExtension->FunctionSupportInfo->ChangeRequestCount);
5670 }
5671
5673 retryInterval = 5;
5674 }
5675 break;
5676 }
5677
5679 switch (addlSenseCodeQual) {
5680
5682 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5683 "Ejection request received!\n"));
5684 ClassSendEjectionNotification(fdoExtension);
5685 break;
5686 }
5687
5689 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5690 "Operator selected write permit?! "
5691 "(unsupported!)\n"));
5692 break;
5693 }
5694
5696 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5697 "Operator selected write protect?! "
5698 "(unsupported!)\n"));
5699 break;
5700 }
5701 }
5702 }
5703
5705
5706 UCHAR wmiEventData[sizeof(ULONG)+sizeof(UCHAR)] = {0};
5707
5708 *((PULONG)wmiEventData) = sizeof(UCHAR);
5709 wmiEventData[sizeof(ULONG)] = addlSenseCodeQual;
5710
5711 //
5712 // Don't log another eventlog if we have already logged once
5713 // NOTE: this should have been interlocked, but the structure
5714 // was publicly defined to use a BOOLEAN (char). Since
5715 // media only reports these errors once per X minutes,
5716 // the potential race condition is nearly non-existant.
5717 // the worst case is duplicate log entries, so ignore.
5718 //
5719
5720 logError = FALSE;
5721 if (fdoExtension->FailurePredicted == 0) {
5722 logError = TRUE;
5723 }
5724 fdoExtension->FailureReason = addlSenseCodeQual;
5725 logStatus = IO_WRN_FAILURE_PREDICTED;
5726
5727 ClassNotifyFailurePredicted(fdoExtension,
5728 (PUCHAR)wmiEventData,
5729 sizeof(wmiEventData),
5730 FALSE, // do not log error
5731 4, // unique error value
5734 SrbGetLun(Srb));
5735
5736 fdoExtension->FailurePredicted = TRUE;
5737
5738 //
5739 // Since this is a Unit Attention we need to make
5740 // sure we retry this request.
5741 //
5742 retry = TRUE;
5743
5744 break;
5745 }
5746
5747 default: {
5748 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5749 "Unit attention\n"));
5750 break;
5751 }
5752
5753 } // end switch (addlSenseCode)
5754
5755 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA))
5756 {
5757
5758 if ((ClassGetVpb(Fdo) != NULL) && (ClassGetVpb(Fdo)->Flags & VPB_MOUNTED))
5759 {
5760 //
5761 // Set bit to indicate that media may have changed
5762 // and volume needs verification.
5763 //
5764
5765 SET_FLAG(Fdo->Flags, DO_VERIFY_VOLUME);
5766
5768 retry = FALSE;
5769 }
5770 else {
5772 }
5773 }
5774 else
5775 {
5777 }
5778
5779 break;
5780
5781 } // end SCSI_SENSE_UNIT_ATTENTION
5782
5784
5785 retry = FALSE;
5786
5787 if (addlSenseCode == SCSI_ADSENSE_WRITE_PROTECT)
5788 {
5789 switch (addlSenseCodeQual) {
5790
5792
5793 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5794 "Device's (%p) resources are exhausted.\n",
5795 Fdo));
5796
5798
5799 //
5800 // This indicates that a thinly-provisioned device has
5801 // hit a permanent resource exhaustion. We need to
5802 // return this status code so that patmgr can take the
5803 // disk offline.
5804 //
5806 break;
5807 }
5808 default:
5809 {
5810 break;
5811 }
5812
5813 } // end switch addlSenseCodeQual
5814 }
5815 else
5816 {
5817 if (IS_SCSIOP_WRITE(cdbOpcode)) {
5818 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5819 "Media write protected\n"));
5821 } else {
5822 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5823 "Access denied\n"));
5825 }
5826 }
5827 break;
5828 } // end SCSI_SENSE_DATA_PROTECT
5829
5831 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5832 "Media blank check\n"));
5833 retry = FALSE;
5835 break;
5836 } // end SCSI_SENSE_BLANK_CHECK
5837
5839
5840 switch (addlSenseCode) {
5841
5843
5844 switch (addlSenseCodeQual) {
5845
5846 //
5847 // 1. Target truncated the data transfer.
5848 //
5850
5851 TracePrint((TRACE_LEVEL_WARNING,
5852 TRACE_FLAG_IOCTL,
5853 "ClassInterpretSenseInfo (%p): Data transfer was truncated (command %x)\n",
5854 Fdo,
5855 cdbOpcode));
5856
5858 retry = FALSE;
5859 break;
5860 }
5861 }
5862 break;
5863 }
5864 }
5865 break;
5866 }
5867
5870
5871 switch (addlSenseCode) {
5872
5874
5875 switch (addlSenseCodeQual) {
5876
5877 //
5878 // 1. Target truncated the data transfer.
5879 //
5881
5882 TracePrint((TRACE_LEVEL_WARNING,
5883 TRACE_FLAG_IOCTL,
5884 "ClassInterpretSenseInfo (%p): Target has truncated the data transfer (command %x)\n",
5885 Fdo,
5886 cdbOpcode));
5887
5889 retry = FALSE;
5890 break;
5891 }
5892 }
5893 break;
5894 }
5895
5897
5898 switch (addlSenseCodeQual) {
5899
5900 //
5901 // 1. Copy manager wasn't able to finish the operation because of insuffient resources
5902 // (e.g. microsnapshot failure on read, no space on write, etc.)
5903 //
5905
5906 TracePrint((TRACE_LEVEL_ERROR,
5907 TRACE_FLAG_IOCTL,
5908 "ClassInterpretSenseInfo (%p): Target has insufficient resources (command %x)\n",
5909 Fdo,
5910 cdb->CDB6GENERIC.OperationCode));
5911
5913 retry = FALSE;
5914 break;
5915 }
5916 }
5917 break;
5918 }
5919 }
5920 } else {
5921 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5922 "Command aborted\n"));
5924 retryInterval = 1;
5925 }
5926 break;
5927 } // end SCSI_SENSE_ABORTED_COMMAND
5928
5929 default: {
5930 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5931 "Unrecognized sense code\n"));
5933 break;
5934 }
5935
5936 } // end switch (senseKey)
5937
5938
5939
5940 //
5941 // Try to determine bad sector information from sense data
5942 //
5943
5944 if (((IS_SCSIOP_READWRITE(cdbOpcode)) ||
5945 (cdbOpcode == SCSIOP_VERIFY) ||
5946 (cdbOpcode == SCSIOP_VERIFY16)) && cdb) {
5947
5948 if (isInformationValid)
5949 {
5950 readSector = 0;
5951 badSector = information;
5952
5953 if (cdbOpcode == SCSIOP_READ16 || cdbOpcode == SCSIOP_WRITE16 || cdbOpcode == SCSIOP_VERIFY16) {
5954 REVERSE_BYTES_QUAD(&readSector, &(cdb->AsByte[2]));
5955 } else {
5956 REVERSE_BYTES(&readSector, &(cdb->AsByte[2]));
5957 }
5958
5959 if (cdbOpcode == SCSIOP_READ || cdbOpcode == SCSIOP_WRITE || cdbOpcode == SCSIOP_VERIFY) {
5960 REVERSE_BYTES_SHORT(&index, &(cdb->CDB10.TransferBlocksMsb));
5961 } else if (cdbOpcode == SCSIOP_READ6 || cdbOpcode == SCSIOP_WRITE6) {
5962 index = cdb->CDB6READWRITE.TransferBlocks;
5963 } else if(cdbOpcode == SCSIOP_READ12 || cdbOpcode == SCSIOP_WRITE12) {
5964 REVERSE_BYTES(&index, &(cdb->CDB12.TransferLength));
5965 } else {
5966 REVERSE_BYTES(&index, &(cdb->CDB16.TransferLength));
5967 }
5968
5969 //
5970 // Make sure the bad sector is within the read sectors.
5971 //
5972
5973 if (!(badSector >= readSector && badSector < readSector + index)) {
5974 badSector = readSector;
5975 }
5976 }
5977 }
5978 }
5979
5980__ClassInterpretSenseInfo_ProcessingInvalidSenseBuffer:
5981
5982 if (!validSense) {
5983
5984 //
5985 // Request sense buffer not valid. No sense information
5986 // to pinpoint the error. Return general request fail.
5987 //
5988
5989 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassInterpretSenseInfo: "
5990 "Request sense info not valid. SrbStatus %2x\n",
5992 retry = TRUE;
5993
5994
5995 switch (SRB_STATUS(Srb->SrbStatus)) {
5996 case SRB_STATUS_ABORTED: {
5997
5998 //
5999 // Update the error count for the device.
6000 //
6001
6002 incrementErrorCount = TRUE;
6004 retryInterval = 1;
6005 retry = TRUE;
6006 break;
6007 }
6008
6009 case SRB_STATUS_ERROR: {
6010
6013
6014 //
6015 // This is some strange return code. Update the error
6016 // count for the device.
6017 //
6018
6019 incrementErrorCount = TRUE;
6020
6021 } else if (SrbGetScsiStatus(Srb) == SCSISTAT_BUSY) {
6022
6024 logRetryableError = FALSE;
6025 }
6026
6027 break;
6028 }
6029
6032 retry = FALSE;
6033 break;
6034 }
6035
6038 case SRB_STATUS_NO_HBA:
6042 retry = FALSE;
6043 break;
6044 }
6045
6047 logError = TRUE;
6048 logStatus = IO_ERR_NOT_READY;
6049 uniqueId = 260;
6051 retry = FALSE;
6052 break;
6053 }
6054
6055 case SRB_STATUS_TIMEOUT:
6057
6058 //
6059 // Update the error count for the device.
6060 //
6061 incrementErrorCount = TRUE;
6063 break;
6064 }
6065
6068
6069 //
6070 // Update the error count for the device
6071 // and fall through to below
6072 //
6073 incrementErrorCount = TRUE;
6074
6075 case SRB_STATUS_BUS_RESET: {
6076
6078 logRetryableError = FALSE;
6079 break;
6080 }
6081
6083
6085 retry = FALSE;
6086
6087 //
6088 // For some commands, we allocate a buffer that may be
6089 // larger than necessary. In these cases, the SRB may be
6090 // returned with SRB_STATUS_DATA_OVERRUN to indicate a
6091 // buffer *underrun*. However, the command was still
6092 // successful so we ensure STATUS_SUCCESS is returned.
6093 // We will also prevent these errors from causing noise in
6094 // the error logs.
6095 //
6096 if ((cdbOpcode == SCSIOP_MODE_SENSE && SrbGetDataTransferLength(Srb) <= cdb->MODE_SENSE.AllocationLength) ||
6097 (cdbOpcode == SCSIOP_INQUIRY && SrbGetDataTransferLength(Srb) <= cdb->CDB6INQUIRY.AllocationLength)) {
6099 logErrorInternal = FALSE;
6100 logError = FALSE;
6101 } else if (cdbOpcode == SCSIOP_MODE_SENSE10) {
6102 USHORT allocationLength;
6103 REVERSE_BYTES_SHORT(&(cdb->MODE_SENSE10.AllocationLength), &allocationLength);
6104 if (SrbGetDataTransferLength(Srb) <= allocationLength) {
6106 logErrorInternal = FALSE;
6107 logError = FALSE;
6108 }
6109 } else if (ClasspIsReceiveTokenInformation(cdb)) {
6110 ULONG allocationLength;
6111 REVERSE_BYTES(&(cdb->RECEIVE_TOKEN_INFORMATION.AllocationLength), &allocationLength);
6112 if (SrbGetDataTransferLength(Srb) <= allocationLength) {
6114 logErrorInternal = FALSE;
6115 logError = FALSE;
6116 }
6117 }
6118
6119 break;
6120 }
6121
6123
6124 //
6125 // Update the error count for the device.
6126 //
6127
6128 incrementErrorCount = TRUE;
6130
6131 //
6132 // If there was phase sequence error then limit the number of
6133 // retries.
6134 //
6135
6136 if (RetryCount > 1 ) {
6137 retry = FALSE;
6138 }
6139
6140 break;
6141 }
6142
6144
6145 //
6146 // If the status needs verification bit is set. Then set
6147 // the status to need verification and no retry; otherwise,
6148 // just retry the request.
6149 //
6150
6151 if (TEST_FLAG(Fdo->Flags, DO_VERIFY_VOLUME)) {
6152
6154 retry = FALSE;
6155
6156 } else {
6158 logRetryableError = FALSE;
6159 }
6160
6161 break;
6162 }
6163
6164
6165 default: {
6166 logError = TRUE;
6167 logStatus = IO_ERR_CONTROLLER_ERROR;
6168 uniqueId = 259;
6170 unhandledError = TRUE;
6171 logRetryableError = FALSE;
6172 break;
6173 }
6174 }
6175
6176
6177 //
6178 // NTRAID #183546 - if we support GESN subtype NOT_READY events, and
6179 // we know from a previous poll when the device will be ready (ETA)
6180 // we should delay the retry more appropriately than just guessing.
6181 //
6182 /*
6183 if (fdoExtension->MediaChangeDetectionInfo &&
6184 fdoExtension->MediaChangeDetectionInfo->Gesn.Supported &&
6185 TEST_FLAG(fdoExtension->MediaChangeDetectionInfo->Gesn.EventMask,
6186 NOTIFICATION_DEVICE_BUSY_CLASS_MASK)
6187 ) {
6188 // check if Gesn.ReadyTime if greater than current tick count
6189 // if so, delay that long (from 1 to 30 seconds max?)
6190 // else, leave the guess of time alone.
6191 }
6192 */
6193
6194 }
6195
6196 }
6197
6198 if (incrementErrorCount) {
6199
6200 //
6201 // if any error count occurred, delay the retry of this io by
6202 // at least one second, if caller supports it.
6203 //
6204
6205 if (retryInterval == 0) {
6206 retryInterval = 1;
6207 }
6208 ClasspPerfIncrementErrorCount(fdoExtension);
6209 }
6210
6211 //
6212 // If there is a class specific error handler call it.
6213 //
6214
6215 if (fdoExtension->CommonExtension.DevInfo->ClassError != NULL) {
6216
6217 SCSI_REQUEST_BLOCK tempSrb = {0};
6219
6220 //
6221 // If class driver does not support extended SRB and this is
6222 // an extended SRB, convert to legacy SRB and pass to class
6223 // driver.
6224 //
6226 ((fdoExtension->CommonExtension.DriverExtension->SrbSupport &
6229 srbPtr = &tempSrb;
6230 }
6231
6232 fdoExtension->CommonExtension.DevInfo->ClassError(Fdo,
6233 srbPtr,
6234 Status,
6235 &retry);
6236 }
6237
6238 //
6239 // If the caller wants to know the suggested retry interval tell them.
6240 //
6241
6242 if (ARGUMENT_PRESENT(RetryInterval)) {
6243 *RetryInterval = retryInterval;
6244 }
6245
6246 //
6247 // The RESERVE(6) / RELEASE(6) commands are optional. So
6248 // if they aren't supported, try the 10-byte equivalents
6249 //
6250
6251 cdb = SrbGetCdb(Srb);
6252 if (cdb) {
6253 cdbOpcode = cdb->CDB6GENERIC.OperationCode;
6254 }
6255
6256 if ((cdbOpcode == SCSIOP_RESERVE_UNIT ||
6257 cdbOpcode == SCSIOP_RELEASE_UNIT) && cdb)
6258 {
6260 {
6261 SrbSetCdbLength(Srb, 10);
6262 cdb->CDB10.OperationCode = (cdb->CDB6GENERIC.OperationCode == SCSIOP_RESERVE_UNIT) ? SCSIOP_RESERVE_UNIT10 : SCSIOP_RELEASE_UNIT10;
6263
6264 SET_FLAG(fdoExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6);
6265 retry = TRUE;
6266 }
6267 }
6268
6269#if DBG
6270
6271 //
6272 // Ensure that for read/write requests, only return STATUS_DEVICE_BUSY if
6273 // reservation conflict.
6274 //
6275 if (IS_SCSIOP_READWRITE(cdbOpcode) && (*Status == STATUS_DEVICE_BUSY)) {
6276 NT_ASSERT(isReservationConflict == TRUE);
6277 }
6278
6279#endif
6280
6281 /*
6282 * LOG the error:
6283 * If logErrorInternal is set, log the error in our internal log.
6284 * If logError is set, also log the error in the system log.
6285 */
6286 if (logErrorInternal || logError) {
6287 ULONG totalSize;
6288 ULONG senseBufferSize = 0;
6289 IO_ERROR_LOG_PACKET staticErrLogEntry = {0};
6290 CLASS_ERROR_LOG_DATA staticErrLogData = {0};
6291 SENSE_DATA convertedSenseBuffer = {0};
6292 UCHAR convertedSenseBufferLength = 0;
6293 BOOLEAN senseDataConverted = FALSE;
6294
6295 //
6296 // Logic below assumes that IO_ERROR_LOG_PACKET + CLASS_ERROR_LOG_DATA
6297 // is less than ERROR_LOG_MAXIMUM_SIZE which is not true for extended SRB.
6298 // Given that classpnp currently does not use >16 byte CDB, we'll convert
6299 // an extended SRB to SCSI_REQUEST_BLOCK instead of changing this code.
6300 // More changes will need to be made when classpnp starts using >16 byte
6301 // CDBs.
6302 //
6303
6304 //
6305 // Calculate the total size of the error log entry.
6306 // add to totalSize in the order that they are used.
6307 // the advantage to calculating all the sizes here is
6308 // that we don't have to do a bunch of extraneous checks
6309 // later on in this code path.
6310 //
6311 totalSize = sizeof(IO_ERROR_LOG_PACKET) // required
6312 + sizeof(CLASS_ERROR_LOG_DATA);// struct for ease
6313
6314 //
6315 // also save any available extra sense data, up to the maximum errlog
6316 // packet size . WMI should be used for real-time analysis.
6317 // the event log should only be used for post-mortem debugging.
6318 //
6319 if ((TEST_FLAG(Srb->SrbStatus, SRB_STATUS_AUTOSENSE_VALID)) && senseBuffer) {
6320
6321 UCHAR validSenseBytes = 0;
6322 UCHAR senseInfoBufferLength = 0;
6323
6324 senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb);
6325
6326 //
6327 // If sense data is in Descriptor format, convert it to Fixed format
6328 // for the private log.
6329 //
6330
6331 if (IsDescriptorSenseDataFormat(senseBuffer)) {
6332
6333 convertedSenseBufferLength = sizeof(convertedSenseBuffer);
6334
6335 senseDataConverted = ScsiConvertToFixedSenseFormat(senseBuffer,
6336 senseInfoBufferLength,
6337 (PVOID)&convertedSenseBuffer,
6338 convertedSenseBufferLength);
6339 }
6340
6341 //
6342 // For System Log, copy the maximum amount of available sense data
6343 //
6344
6345 if (ScsiGetTotalSenseByteCountIndicated(senseBuffer,
6346 senseInfoBufferLength,
6347 &validSenseBytes)) {
6348
6349 //
6350 // If it is able to determine number of valid bytes,
6351 // copy the maximum amount of available
6352 // sense data that can be saved into the the errlog.
6353 //
6354
6355 //
6356 // set to save the most sense buffer possible
6357 //
6358
6359 senseBufferSize = max(validSenseBytes, sizeof(staticErrLogData.SenseData));
6360 senseBufferSize = min(senseBufferSize, senseInfoBufferLength);
6361
6362 } else {
6363 //
6364 // it's smaller than required to read the total number of
6365 // valid bytes, so just use the SenseInfoBufferLength field.
6366 //
6367 senseBufferSize = senseInfoBufferLength;
6368 }
6369
6370 /*
6371 * Bump totalSize by the number of extra senseBuffer bytes
6372 * (beyond the default sense buffer within CLASS_ERROR_LOG_DATA).
6373 * Make sure to never allocate more than ERROR_LOG_MAXIMUM_SIZE.
6374 */
6375 if (senseBufferSize > sizeof(staticErrLogData.SenseData)){
6376 totalSize += senseBufferSize-sizeof(staticErrLogData.SenseData);
6377 if (totalSize > ERROR_LOG_MAXIMUM_SIZE){
6378 senseBufferSize -= totalSize-ERROR_LOG_MAXIMUM_SIZE;
6379 totalSize = ERROR_LOG_MAXIMUM_SIZE;
6380 }
6381 }
6382 }
6383
6384 //
6385 // If we've used up all of our retry attempts, set the final status to
6386 // reflect the appropriate result.
6387 //
6388 // ISSUE: the test below should also check RetryCount to determine if we will actually retry,
6389 // but there is no easy test because we'd have to consider the original retry count
6390 // for the op; besides, InterpretTransferPacketError sometimes ignores the retry
6391 // decision returned by this function. So just ErrorRetried to be true in the majority case.
6392 //
6393 if (retry){
6394 staticErrLogEntry.FinalStatus = STATUS_SUCCESS;
6395 staticErrLogData.ErrorRetried = TRUE;
6396 } else {
6397 staticErrLogEntry.FinalStatus = *Status;
6398 }
6399
6400 //
6401 // Don't log generic IO_WARNING_PAGING_FAILURE message if either the
6402 // I/O is retried, or it completed successfully.
6403 //
6404 if (logStatus == IO_WARNING_PAGING_FAILURE &&
6405 (retry || NT_SUCCESS(*Status)) ) {
6406 logError = FALSE;
6407 }
6408
6410 staticErrLogData.ErrorPaging = TRUE;
6411 }
6412 if (unhandledError) {
6413 staticErrLogData.ErrorUnhandled = TRUE;
6414 }
6415
6416 //
6417 // Calculate the device offset if there is a geometry.
6418 //
6419 staticErrLogEntry.DeviceOffset.QuadPart = (LONGLONG)badSector;
6420 staticErrLogEntry.DeviceOffset.QuadPart *= (LONGLONG)fdoExtension->DiskGeometry.BytesPerSector;
6421 if (logStatus == -1){
6422 staticErrLogEntry.ErrorCode = STATUS_IO_DEVICE_ERROR;
6423 } else {
6424 staticErrLogEntry.ErrorCode = logStatus;
6425 }
6426
6427 /*
6428 * The dump data follows the IO_ERROR_LOG_PACKET
6429 */
6430 staticErrLogEntry.DumpDataSize = (USHORT)totalSize - sizeof(IO_ERROR_LOG_PACKET);
6431
6432 staticErrLogEntry.SequenceNumber = 0;
6433 staticErrLogEntry.MajorFunctionCode = MajorFunctionCode;
6434 staticErrLogEntry.IoControlCode = IoDeviceCode;
6435 staticErrLogEntry.RetryCount = (UCHAR) RetryCount;
6436 staticErrLogEntry.UniqueErrorValue = uniqueId;
6437
6438 KeQueryTickCount(&staticErrLogData.TickCount);
6439 staticErrLogData.PortNumber = (ULONG)-1;
6440
6441 /*
6442 * Save the entire contents of the SRB.
6443 */
6446 } else {
6447 staticErrLogData.Srb = *(PSCSI_REQUEST_BLOCK)Srb;
6448 }
6449
6450 /*
6451 * For our private log, save just the default length of the SENSE_DATA.
6452 */
6453
6454 if ((senseBufferSize != 0) && senseBuffer) {
6455
6456 //
6457 // If sense buffer is in Fixed format, put it in the private log
6458 //
6459 // If sense buffer is in Descriptor format, put it in the private log if conversion to Fixed format
6460 // succeeded. Otherwise, do not put it in the private log.
6461 //
6462 // If sense buffer is in unknown format, the device or the driver probably does not populate
6463 // the first byte of sense data, we probably still want to log error in this case assuming
6464 // it's fixed format, so that its sense key, its additional sense code, and its additional sense code
6465 // qualifier would be shown in the debugger extension output. By doing so, it minimizes any potential
6466 // negative impacts to our ability to diagnose issue.
6467 //
6468 if (IsDescriptorSenseDataFormat(senseBuffer)) {
6469 if (senseDataConverted) {
6470 RtlCopyMemory(&staticErrLogData.SenseData, &convertedSenseBuffer, min(convertedSenseBufferLength, sizeof(staticErrLogData.SenseData)));
6471 }
6472 } else {
6473 RtlCopyMemory(&staticErrLogData.SenseData, senseBuffer, min(senseBufferSize, sizeof(staticErrLogData.SenseData)));
6474 }
6475 }
6476
6477 /*
6478 * Save the error log in our context.
6479 * We only save the default sense buffer length.
6480 */
6481 if (logErrorInternal) {
6482 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
6483 fdoData->ErrorLogs[fdoData->ErrorLogNextIndex] = staticErrLogData;
6484 fdoData->ErrorLogNextIndex++;
6486 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
6487 }
6488
6489 /*
6490 * Log an event if an IO is being retried for reasons that may indicate
6491 * a transient/permanent problem with the I_T_L nexus. But log the event
6492 * only once per retried IO.
6493 */
6494 if (!IS_SCSIOP_READWRITE(cdbOpcode) ||
6495 !retry ||
6496 (RetryCount != 0)) {
6497
6498 logRetryableError = FALSE;
6499 }
6500
6501 if (logRetryableError) {
6502
6503 logError = TRUE;
6504 }
6505
6506 /*
6507 * If logError is set, also save this log in the system's error log.
6508 * But make sure we don't log TUR failures over and over
6509 * (e.g. if an external drive was switched off and we're still sending TUR's to it every second).
6510 */
6511
6512 if (logError)
6513 {
6514 //
6515 // We do not want to log certain system events repetitively
6516 //
6517
6518 cdb = SrbGetCdb(Srb);
6519 if (cdb) {
6520 switch (cdb->CDB10.OperationCode)
6521 {
6523 {
6524 if (fdoData->LoggedTURFailureSinceLastIO)
6525 {
6526 logError = FALSE;
6527 }
6528 else
6529 {
6531 }
6532
6533 break;
6534 }
6535
6537 {
6538 if (fdoData->LoggedSYNCFailure)
6539 {
6540 logError = FALSE;
6541 }
6542 else
6543 {
6544 fdoData->LoggedSYNCFailure = TRUE;
6545 }
6546
6547 break;
6548 }
6549 }
6550 }
6551 }
6552
6553 if (logError){
6554
6555 if (logRetryableError) {
6556
6557 NT_ASSERT(IS_SCSIOP_READWRITE(cdbOpcode));
6558
6559 //
6560 // A large Disk TimeOutValue (like 60 seconds) results in giving a command a
6561 // large window to complete in. However, if the target returns a retryable error
6562 // just prior to the command timing out, and if multiple retries kick in, it may
6563 // take a significantly long time for the request to complete back to the
6564 // application, leading to a user perception of a hung system. So log an event
6565 // for retried IO so that an admin can help explain the reason for this behavior.
6566 //
6568 senseBufferSize,
6569 senseBuffer,
6573 cdbLength,
6574 cdb,
6575 NULL);
6576
6577 } else {
6578
6579 PIO_ERROR_LOG_PACKET errorLogEntry;
6580 PCLASS_ERROR_LOG_DATA errlogData;
6581
6582 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(Fdo, (UCHAR)totalSize);
6583 if (errorLogEntry){
6584 errlogData = (PCLASS_ERROR_LOG_DATA)errorLogEntry->DumpData;
6585
6586 *errorLogEntry = staticErrLogEntry;
6587 *errlogData = staticErrLogData;
6588
6589 /*
6590 * For the system log, copy as much of the sense buffer as possible.
6591 */
6592 if ((senseBufferSize != 0) && senseBuffer) {
6593 RtlCopyMemory(&errlogData->SenseData, senseBuffer, senseBufferSize);
6594 }
6595
6596 /*
6597 * Write the error log packet to the system error logging thread.
6598 * It will be freed by the kernel.
6599 */
6600 IoWriteErrorLogEntry(errorLogEntry);
6601 }
6602 }
6603 }
6604 }
6605
6606 return retry;
6607
6608} // end ClassInterpretSenseInfo()
6609
6610
6611/*++////////////////////////////////////////////////////////////////////////////
6612
6613ClassModeSense()
6614
6615Routine Description:
6616
6617 This routine sends a mode sense command to a target ID and returns
6618 when it is complete.
6619
6620Arguments:
6621
6622 Fdo - Supplies the functional device object associated with this request.
6623
6624 ModeSenseBuffer - Supplies a buffer to store the sense data.
6625
6626 Length - Supplies the length in bytes of the mode sense buffer.
6627
6628 PageMode - Supplies the page or pages of mode sense data to be retrived.
6629
6630Return Value:
6631
6632 Length of the transferred data is returned.
6633
6634--*/
6635ULONG
6636NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
6639 _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
6642 )
6643{
6644 PAGED_CODE();
6645
6646 return ClasspModeSense(Fdo,
6647 ModeSenseBuffer,
6648 Length,
6649 PageMode,
6651}
6652
6653
6654ULONG
6655NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
6658 _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
6662 )
6663{
6664 PAGED_CODE();
6665#if (NTDDI_VERSION >= NTDDI_WINBLUE)
6666 return ClasspModeSense(Fdo,
6667 ModeSenseBuffer,
6668 Length,
6669 PageMode,
6670 PageControl);
6671#else
6673 UNREFERENCED_PARAMETER(ModeSenseBuffer);
6677 return 0;
6678#endif
6679}
6680
6683 _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
6687 )
6688/*
6689Routine Description:
6690
6691 This routine sends a mode sense command to a target ID and returns
6692 when it is complete.
6693
6694Arguments:
6695
6696 Fdo - Supplies the functional device object associated with this request.
6697
6698 ModeSenseBuffer - Supplies a buffer to store the sense data.
6699
6700 Length - Supplies the length in bytes of the mode sense buffer.
6701
6702 PageMode - Supplies the page or pages of mode sense data to be retrived.
6703
6704 PageControl - Supplies the page control value of the request, which is
6705 one of the following:
6706 MODE_SENSE_CURRENT_VALUES
6707 MODE_SENSE_CHANGEABLE_VALUES
6708 MODE_SENSE_DEFAULT_VAULES
6709 MODE_SENSE_SAVED_VALUES
6710
6711Return Value:
6712
6713 Length of the transferred data is returned.
6714
6715--*/
6716{
6717 ULONG lengthTransferred = 0;
6718 PMDL senseBufferMdl;
6719
6720 PAGED_CODE();
6721
6722 senseBufferMdl = BuildDeviceInputMdl(ModeSenseBuffer, Length);
6723 if (senseBufferMdl){
6724
6726 if (pkt){
6727 KEVENT event;
6728 IRP pseudoIrp = {0};
6729
6730 /*
6731 * Store the number of packets servicing the irp (one)
6732 * inside the original IRP. It will be used to counted down
6733 * to zero when the packet completes.
6734 * Initialize the original IRP's status to success.
6735 * If the packet fails, we will set it to the error status.
6736 */
6737 pseudoIrp.Tail.Overlay.DriverContext[0] = LongToPtr(1);
6738 pseudoIrp.IoStatus.Status = STATUS_SUCCESS;
6739 pseudoIrp.IoStatus.Information = 0;
6740 pseudoIrp.MdlAddress = senseBufferMdl;
6741
6742 /*
6743 * Set this up as a SYNCHRONOUS transfer, submit it,
6744 * and wait for the packet to complete. The result
6745 * status will be written to the original irp.
6746 */
6747 NT_ASSERT(Length <= 0x0ff);
6749 SetupModeSenseTransferPacket(pkt, &event, ModeSenseBuffer, (UCHAR)Length, PageMode, 0, &pseudoIrp, PageControl);
6752
6753 if (NT_SUCCESS(pseudoIrp.IoStatus.Status)){
6754 lengthTransferred = (ULONG)pseudoIrp.IoStatus.Information;
6755 }
6756 else {
6757 /*
6758 * This request can sometimes fail legitimately
6759 * (e.g. when a SCSI device is attached but turned off)
6760 * so this is not necessarily a device/driver bug.
6761 */
6762 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClasspModeSense on Fdo %ph failed with status %xh.", Fdo, pseudoIrp.IoStatus.Status));
6763 }
6764 }
6765
6766 FreeDeviceInputMdl(senseBufferMdl);
6767 }
6768
6769 return lengthTransferred;
6770}
6771
6772/*++////////////////////////////////////////////////////////////////////////////
6773
6774ClassFindModePage()
6775
6776Routine Description:
6777
6778 This routine scans through the mode sense data and finds the requested
6779 mode sense page code.
6780
6781Arguments:
6782 ModeSenseBuffer - Supplies a pointer to the mode sense data.
6783
6784 Length - Indicates the length of valid data.
6785
6786 PageMode - Supplies the page mode to be searched for.
6787
6788 Use6Byte - Indicates whether 6 or 10 byte mode sense was used.
6789
6790Return Value:
6791
6792 A pointer to the the requested mode page. If the mode page was not found
6793 then NULL is return.
6794
6795--*/
6796PVOID
6797NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
6799 _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
6803 )
6804{
6805 PUCHAR limit;
6806 ULONG parameterHeaderLength;
6807 PVOID result = NULL;
6808
6809 limit = (PUCHAR)ModeSenseBuffer + Length;
6810 parameterHeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10);
6811
6812 if (Length >= parameterHeaderLength) {
6813
6814 PMODE_PARAMETER_HEADER10 modeParam10;
6815 ULONG blockDescriptorLength;
6816
6817 /*
6818 * Skip the mode select header and block descriptors.
6819 */
6820 if (Use6Byte){
6821 blockDescriptorLength = ((PMODE_PARAMETER_HEADER) ModeSenseBuffer)->BlockDescriptorLength;
6822 }
6823 else {
6824 modeParam10 = (PMODE_PARAMETER_HEADER10) ModeSenseBuffer;
6825 blockDescriptorLength = modeParam10->BlockDescriptorLength[1];
6826 }
6827
6828 ModeSenseBuffer += parameterHeaderLength + blockDescriptorLength;
6829
6830 //
6831 // ModeSenseBuffer now points at pages. Walk the pages looking for the
6832 // requested page until the limit is reached.
6833 //
6834
6835 while (ModeSenseBuffer +
6837
6838 if (((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageCode == PageMode) {
6839
6840 /*
6841 * found the mode page. make sure it's safe to touch it all
6842 * before returning the pointer to caller
6843 */
6844
6845 if (ModeSenseBuffer + ((PMODE_DISCONNECT_PAGE)ModeSenseBuffer)->PageLength > (PCHAR)limit) {
6846 /*
6847 * Return NULL since the page is not safe to access in full
6848 */
6849 result = NULL;
6850 }
6851 else {
6852 result = ModeSenseBuffer;
6853 }
6854 break;
6855 }
6856
6857 //
6858 // Advance to the next page which is 4-byte-aligned offset after this page.
6859 //
6860 ModeSenseBuffer +=
6861 ((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageLength +
6863
6864 }
6865 }
6866
6867 return result;
6868} // end ClassFindModePage()
6869
6870
6872NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
6875 _In_reads_bytes_(Length) PCHAR ModeSelectBuffer,
6877 _In_ BOOLEAN SavePages
6878 )
6879{
6880#if (NTDDI_VERSION >= NTDDI_WINBLUE)
6881 return ClasspModeSelect(Fdo,
6882 ModeSelectBuffer,
6883 Length,
6884 SavePages);
6885#else
6887 UNREFERENCED_PARAMETER(ModeSelectBuffer);
6889 UNREFERENCED_PARAMETER(SavePages);
6890 return STATUS_NOT_SUPPORTED;
6891#endif
6892}
6893
6894/*++
6895ClasspModeSelect()
6896
6897Routine Description:
6898
6899 This routine sends a mode select command to a target ID and returns
6900 when it is complete.
6901
6902Arguments:
6903
6904 Fdo - Supplies the functional device object associated with this request.
6905
6906 ModeSelectBuffer - Supplies a buffer to the select data.
6907
6908 Length - Supplies the length in bytes of the mode select buffer.
6909
6910 SavePages - Specifies the value of the save pages (SP) bit in the mode
6911 select command.
6912
6913Return Value:
6914
6915 NTSTATUS code of the request.
6916
6917--*/
6921 _In_reads_bytes_(Length) PCHAR ModeSelectBuffer,
6923 _In_ BOOLEAN SavePages
6924 )
6925{
6926
6927 PMDL senseBufferMdl;
6929
6930 senseBufferMdl = BuildDeviceInputMdl(ModeSelectBuffer, Length);
6931 if (senseBufferMdl) {
6932
6934 if (pkt){
6935 KEVENT event;
6936 IRP pseudoIrp = {0};
6937
6938 /*
6939 * Store the number of packets servicing the irp (one)
6940 * inside the original IRP. It will be used to counted down
6941 * to zero when the packet completes.
6942 * Initialize the original IRP's status to success.
6943 * If the packet fails, we will set it to the error status.
6944 */
6945 pseudoIrp.Tail.Overlay.DriverContext[0] = LongToPtr(1);
6946 pseudoIrp.IoStatus.Status = STATUS_SUCCESS;
6947 pseudoIrp.IoStatus.Information = 0;
6948 pseudoIrp.MdlAddress = senseBufferMdl;
6949
6950 /*
6951 * Set this up as a SYNCHRONOUS transfer, submit it,
6952 * and wait for the packet to complete. The result
6953 * status will be written to the original irp.
6954 */
6955 NT_ASSERT(Length <= 0x0ff);
6957 SetupModeSelectTransferPacket(pkt, &event, ModeSelectBuffer, (UCHAR)Length, SavePages, &pseudoIrp);
6960
6961 if (!NT_SUCCESS(pseudoIrp.IoStatus.Status)){
6962 /*
6963 * This request can sometimes fail legitimately
6964 * (e.g. when a SCSI device is attached but turned off)
6965 * so this is not necessarily a device/driver bug.
6966 */
6967 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "ClassModeSelect on Fdo %ph failed with status %xh.", Fdo, pseudoIrp.IoStatus.Status));
6968 }
6969
6970 status = pseudoIrp.IoStatus.Status;
6971 }
6972
6973 FreeDeviceInputMdl(senseBufferMdl);
6974 } else {
6976 }
6977
6978 return status;
6979}
6980
6981/*++////////////////////////////////////////////////////////////////////////////
6982
6983ClassSendSrbAsynchronous()
6984
6985Routine Description:
6986
6987 This routine takes a partially built Srb and an Irp and sends it down to
6988 the port driver.
6989
6990 This routine must be called with the remove lock held for the specified
6991 Irp.
6992
6993Arguments:
6994
6995 Fdo - Supplies the functional device object for the orginal request.
6996
6997 Srb - Supplies a paritally build ScsiRequestBlock. In particular, the
6998 CDB and the SRB timeout value must be filled in. The SRB must not be
6999 allocated from zone.
7000
7001 Irp - Supplies the requesting Irp.
7002
7003 BufferAddress - Supplies a pointer to the buffer to be transfered.
7004
7005 BufferLength - Supplies the length of data transfer.
7006
7007 WriteToDevice - Indicates the data transfer will be from system memory to
7008 device.
7009
7010Return Value:
7011
7012 Returns STATUS_PENDING if the request is dispatched (since the
7013 completion routine may change the irp's status value we cannot simply
7014 return the value of the dispatch)
7015
7016 or returns a status value to indicate why it failed.
7017
7018--*/
7021NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
7025 _In_ PIRP Irp,
7029 )
7030{
7031
7032 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
7033 PIO_STACK_LOCATION irpStack;
7035
7036 ULONG savedFlags;
7037
7039 //
7040 // Write length to SRB.
7041 //
7042
7043 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
7044
7045 //
7046 // Set SCSI bus address.
7047 //
7048
7050 }
7051
7052 //
7053 // This is a violation of the SCSI spec but it is required for
7054 // some targets.
7055 //
7056
7057 // Srb->Cdb[1] |= deviceExtension->Lun << 5;
7058
7059 //
7060 // Indicate auto request sense by specifying buffer and size.
7061 //
7062
7063 SrbSetSenseInfoBuffer(Srb, fdoExtension->SenseData);
7065
7067
7068 //
7069 // Set the transfer length.
7070 //
7072
7073 //
7074 // Save the class driver specific flags away.
7075 //
7076
7078
7079 //
7080 // Allow the caller to specify that they do not wish
7081 // IoStartNextPacket() to be called in the completion routine.
7082 //
7083
7085
7086 //
7087 // If caller wants to this request to be tagged, save this fact.
7088 //
7089
7094
7098 }
7099 }
7100
7101 if (BufferAddress != NULL) {
7102
7103 //
7104 // Build Mdl if necessary.
7105 //
7106
7107 if (Irp->MdlAddress == NULL) {
7108
7109 PMDL mdl;
7110
7113 FALSE,
7114 FALSE,
7115 Irp);
7116
7117 if ((mdl == NULL) || (Irp->MdlAddress == NULL)) {
7118
7119 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
7120
7121 //
7122 // ClassIoComplete() would have free'd the srb
7123 //
7124
7125 if (PORT_ALLOCATED_SENSE_EX(fdoExtension, Srb)) {
7127 }
7131
7133 }
7134
7136
7137 MmBuildMdlForNonPagedPool(Irp->MdlAddress);
7138
7139 } else {
7140
7141 //
7142 // Make sure the buffer requested matches the MDL.
7143 //
7144
7146 }
7147
7148 //
7149 // Set read flag.
7150 //
7151
7153
7154 } else {
7155
7156 //
7157 // Clear flags.
7158 //
7159
7161 }
7162
7163 //
7164 // Restore saved flags.
7165 //
7166
7167 SrbSetSrbFlags(Srb, savedFlags);
7168
7169 //
7170 // Disable synchronous transfer for these requests.
7171 //
7172
7174
7175 //
7176 // Zero out status.
7177 //
7178
7180 Srb->SrbStatus = 0;
7181
7183
7184 //
7185 // Save a few parameters in the current stack location.
7186 //
7187
7189
7190 //
7191 // Save retry count in current Irp stack.
7192 //
7193
7194 irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
7195
7196 //
7197 // Set up IoCompletion routine address.
7198 //
7199
7201
7202 //
7203 // Get next stack location and
7204 // set major function code.
7205 //
7206
7207 irpStack = IoGetNextIrpStackLocation(Irp);
7208
7209 irpStack->MajorFunction = IRP_MJ_SCSI;
7210
7211 //
7212 // Save SRB address in next stack for port driver.
7213 //
7214
7215 irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)Srb;
7216
7217 //
7218 // Set up Irp Address.
7219 //
7220
7222
7223 //
7224 // Call the port driver to process the request.
7225 //
7226
7228
7230
7231 return STATUS_PENDING;
7232
7233} // end ClassSendSrbAsynchronous()
7234
7235/*++////////////////////////////////////////////////////////////////////////////
7236
7237ClassDeviceControlDispatch()
7238
7239Routine Description:
7240
7241 The routine is the common class driver device control dispatch entry point.
7242 This routine is invokes the device-specific drivers DeviceControl routine,
7243 (which may call the Class driver's common DeviceControl routine).
7244
7245Arguments:
7246
7247 DeviceObject - Supplies a pointer to the device object for this request.
7248
7249 Irp - Supplies the Irp making the request.
7250
7251Return Value:
7252
7253 Returns the status returned from the device-specific driver.
7254
7255--*/
7257NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
7260 PIRP Irp
7261 )
7262{
7263
7264 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
7265 ULONG isRemoved;
7266
7268 _Analysis_assume_(isRemoved);
7269 if(isRemoved) {
7270
7272
7273 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
7276 }
7277
7278 //
7279 // Call the class specific driver DeviceControl routine.
7280 // If it doesn't handle it, it will call back into ClassDeviceControl.
7281 //
7282
7283 NT_ASSERT(commonExtension->DevInfo->ClassDeviceControl);
7284
7285 return commonExtension->DevInfo->ClassDeviceControl(DeviceObject,Irp);
7286} // end ClassDeviceControlDispatch()
7287
7288
7289/*++////////////////////////////////////////////////////////////////////////////
7290
7291ClassDeviceControl()
7292
7293Routine Description:
7294
7295 The routine is the common class driver device control dispatch function.
7296 This routine is called by a class driver when it get an unrecognized
7297 device control request. This routine will perform the correct action for
7298 common requests such as lock media. If the device request is unknown it
7299 passed down to the next level.
7300
7301 This routine must be called with the remove lock held for the specified
7302 irp.
7303
7304Arguments:
7305
7306 DeviceObject - Supplies a pointer to the device object for this request.
7307
7308 Irp - Supplies the Irp making the request.
7309
7310Return Value:
7311
7312 Returns back a STATUS_PENDING or a completion status.
7313
7314--*/
7316NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
7320 )
7321{
7322 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
7323
7325 PIO_STACK_LOCATION nextStack = NULL;
7326
7327 ULONG controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
7328
7330 PCDB cdb = NULL;
7331
7333 ULONG modifiedIoControlCode = 0;
7334 GUID activityId = {0};
7335
7336
7337 //
7338 // If this is a pass through I/O control, set the minor function code
7339 // and device address and pass it to the port driver.
7340 //
7341
7342 if ( (controlCode == IOCTL_SCSI_PASS_THROUGH) ||
7343 (controlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) ||
7344 (controlCode == IOCTL_SCSI_PASS_THROUGH_EX) ||
7345 (controlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT_EX) ) {
7346
7347
7348
7349 //
7350 // Validiate the user buffer for SCSI pass through.
7351 // For pass through EX: as the handler will validate the size anyway,
7352 // do not apply the similar check and leave the work to the handler.
7353 //
7354 if ( (controlCode == IOCTL_SCSI_PASS_THROUGH) ||
7355 (controlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) ) {
7356
7357 #if BUILD_WOW64_ENABLED && defined(_WIN64)
7358
7359 if (IoIs32bitProcess(Irp)) {
7360
7361 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32)){
7362
7363 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
7364
7367
7369 goto SetStatusAndReturn;
7370 }
7371 }
7372 else
7373
7374 #endif
7375
7376 {
7377 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
7378 sizeof(SCSI_PASS_THROUGH)) {
7379
7380 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
7381
7384
7386 goto SetStatusAndReturn;
7387 }
7388 }
7389 }
7390
7391
7393
7394 nextStack = IoGetNextIrpStackLocation(Irp);
7395 nextStack->MinorFunction = 1;
7396
7398
7399 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
7400 goto SetStatusAndReturn;
7401
7402 }
7403
7404 Irp->IoStatus.Information = 0;
7405
7406
7407 switch (controlCode) {
7408
7410
7411 PMOUNTDEV_UNIQUE_ID uniqueId;
7412
7413 if (!commonExtension->MountedDeviceInterfaceName.Buffer) {
7415 break;
7416 }
7417
7418 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7419 sizeof(MOUNTDEV_UNIQUE_ID)) {
7420
7422 Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
7423 break;
7424 }
7425
7426 uniqueId = Irp->AssociatedIrp.SystemBuffer;
7427 RtlZeroMemory(uniqueId, sizeof(MOUNTDEV_UNIQUE_ID));
7428 uniqueId->UniqueIdLength =
7429 commonExtension->MountedDeviceInterfaceName.Length;
7430
7431 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7432 sizeof(USHORT) + uniqueId->UniqueIdLength) {
7433
7435 Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
7436 break;
7437 }
7438
7439 RtlCopyMemory(uniqueId->UniqueId,
7440 commonExtension->MountedDeviceInterfaceName.Buffer,
7441 uniqueId->UniqueIdLength);
7442
7444 Irp->IoStatus.Information = sizeof(USHORT) +
7445 uniqueId->UniqueIdLength;
7446 break;
7447 }
7448
7450
7452
7453 NT_ASSERT(commonExtension->DeviceName.Buffer);
7454
7455 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7456 sizeof(MOUNTDEV_NAME)) {
7457
7459 Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
7460 break;
7461 }
7462
7463 name = Irp->AssociatedIrp.SystemBuffer;
7465 name->NameLength = commonExtension->DeviceName.Length;
7466
7467 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7468 sizeof(USHORT) + name->NameLength) {
7469
7471 Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
7472 break;
7473 }
7474
7475 RtlCopyMemory(name->Name, commonExtension->DeviceName.Buffer,
7476 name->NameLength);
7477
7479 Irp->IoStatus.Information = sizeof(USHORT) + name->NameLength;
7480 break;
7481 }
7482
7484
7485 PMOUNTDEV_SUGGESTED_LINK_NAME suggestedName;
7486 WCHAR driveLetterNameBuffer[10] = {0};
7487 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0};
7488 PWSTR valueName;
7489 UNICODE_STRING driveLetterName;
7490
7491 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7493
7495 Irp->IoStatus.Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
7496 break;
7497 }
7498
7499 valueName = ExAllocatePoolWithTag(
7500 PagedPool,
7501 commonExtension->DeviceName.Length + sizeof(WCHAR),
7502 '8CcS');
7503
7504 if (!valueName) {
7506 break;
7507 }
7508
7509 RtlCopyMemory(valueName, commonExtension->DeviceName.Buffer,
7510 commonExtension->DeviceName.Length);
7511 valueName[commonExtension->DeviceName.Length/sizeof(WCHAR)] = 0;
7512
7513 driveLetterName.Buffer = driveLetterNameBuffer;
7514 driveLetterName.MaximumLength = sizeof(driveLetterNameBuffer);
7515 driveLetterName.Length = 0;
7516
7517 queryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
7520 queryTable[0].Name = valueName;
7521 queryTable[0].EntryContext = &driveLetterName;
7523
7525 L"\\Registry\\Machine\\System\\DISK",
7526 queryTable, NULL, NULL);
7527
7528 if (!NT_SUCCESS(status)) {
7529 FREE_POOL(valueName);
7530 break;
7531 }
7532
7533 if (driveLetterName.Length == 4 &&
7534 driveLetterName.Buffer[0] == '%' &&
7535 driveLetterName.Buffer[1] == ':') {
7536
7537 driveLetterName.Buffer[0] = 0xFF;
7538
7539 } else if (driveLetterName.Length != 4 ||
7540 driveLetterName.Buffer[0] < FirstDriveLetter ||
7541 driveLetterName.Buffer[0] > LastDriveLetter ||
7542 driveLetterName.Buffer[1] != ':') {
7543
7545 FREE_POOL(valueName);
7546 break;
7547 }
7548
7549 suggestedName = Irp->AssociatedIrp.SystemBuffer;
7550 RtlZeroMemory(suggestedName, sizeof(MOUNTDEV_SUGGESTED_LINK_NAME));
7551 suggestedName->UseOnlyIfThereAreNoOtherLinks = TRUE;
7552 suggestedName->NameLength = 28;
7553
7554 Irp->IoStatus.Information =
7556
7557 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7558 Irp->IoStatus.Information) {
7559
7560 Irp->IoStatus.Information =
7563 FREE_POOL(valueName);
7564 break;
7565 }
7566
7568 L"\\Registry\\Machine\\System\\DISK",
7569 valueName);
7570
7571 FREE_POOL(valueName);
7572
7573 RtlCopyMemory(suggestedName->Name, L"\\DosDevices\\", 24);
7574 suggestedName->Name[12] = driveLetterName.Buffer[0];
7575 suggestedName->Name[13] = ':';
7576
7577 //
7578 // NT_SUCCESS(status) based on RtlQueryRegistryValues
7579 //
7581
7582 break;
7583 }
7584
7585 default:
7587 break;
7588 }
7589
7590 if (status != STATUS_PENDING) {
7592 Irp->IoStatus.Status = status;
7593
7594
7596 return status;
7597 }
7598
7599 if (commonExtension->IsFdo){
7600
7601 PULONG_PTR function;
7602 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)commonExtension;
7603 size_t sizeNeeded;
7604
7605 //
7606 // Allocate a SCSI SRB for handling various IOCTLs.
7607 // NOTE - there is a case where an IOCTL is sent to classpnp before AdapterDescriptor
7608 // is initialized. In this case, default to legacy SRB.
7609 //
7610 if ((fdoExtension->AdapterDescriptor != NULL) &&
7611 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
7613 } else {
7614 sizeNeeded = sizeof(SCSI_REQUEST_BLOCK);
7615 }
7616
7617 srb = ExAllocatePoolWithTag(NonPagedPoolNx,
7618 sizeNeeded +
7619 (sizeof(ULONG_PTR) * 2),
7620 '9CcS');
7621
7622 if (srb == NULL) {
7623
7624 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
7628 goto SetStatusAndReturn;
7629 }
7630
7631 if ((fdoExtension->AdapterDescriptor != NULL) &&
7632 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
7636 1,
7638 if (NT_SUCCESS(status)) {
7640 function = (PULONG_PTR)((PCHAR)srb + sizeNeeded);
7641 } else {
7642 //
7643 // Should not occur.
7644 //
7646 goto SetStatusAndReturn;
7647 }
7648 } else {
7649 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
7650 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
7652 function = (PULONG_PTR) ((PSCSI_REQUEST_BLOCK) (srb + 1));
7653 }
7654
7655 //
7656 // Save the function code and the device object in the memory after
7657 // the SRB.
7658 //
7659
7660 *function = (ULONG_PTR) DeviceObject;
7661 function++;
7662 *function = (ULONG_PTR) controlCode;
7663
7664 } else {
7665 srb = NULL;
7666 }
7667
7668 //
7669 // Change the device type to storage for the switch statement, but only
7670 // if from a legacy device type
7671 //
7672
7673 if (((controlCode & 0xffff0000) == (IOCTL_DISK_BASE << 16)) ||
7674 ((controlCode & 0xffff0000) == (IOCTL_TAPE_BASE << 16)) ||
7675 ((controlCode & 0xffff0000) == (IOCTL_CDROM_BASE << 16))
7676 ) {
7677
7678 modifiedIoControlCode = (controlCode & ~0xffff0000);
7679 modifiedIoControlCode |= (IOCTL_STORAGE_BASE << 16);
7680
7681 } else {
7682
7683 modifiedIoControlCode = controlCode;
7684
7685 }
7686
7687 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL, "> ioctl %xh (%s)", modifiedIoControlCode, DBGGETIOCTLSTR(modifiedIoControlCode)));
7688
7689
7690 switch (modifiedIoControlCode) {
7691
7693
7694 FREE_POOL(srb);
7695
7696 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7697 sizeof(STORAGE_HOTPLUG_INFO)) {
7698
7699 //
7700 // Indicate unsuccessful status and no data transferred.
7701 //
7702
7703 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
7704 Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO);
7705
7709
7710 } else if (!commonExtension->IsFdo) {
7711
7712
7713 //
7714 // Just forward this down and return
7715 //
7716
7718
7720 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
7721
7722 } else {
7723
7724 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
7726
7727 fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)commonExtension;
7728 info = Irp->AssociatedIrp.SystemBuffer;
7729
7730 *info = fdoExtension->PrivateFdoData->HotplugInfo;
7731 Irp->IoStatus.Status = STATUS_SUCCESS;
7732 Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO);
7736 }
7737 break;
7738 }
7739
7741
7742 FREE_POOL(srb);
7743
7744 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
7745 sizeof(STORAGE_HOTPLUG_INFO)) {
7746
7747 //
7748 // Indicate unsuccessful status and no data transferred.
7749 //
7750
7751 Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH;
7752
7756 goto SetStatusAndReturn;
7757
7758 }
7759
7760 if (!commonExtension->IsFdo) {
7761
7762
7763 //
7764 // Just forward this down and return
7765 //
7766
7768
7770 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
7771
7772 } else {
7773
7774 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)commonExtension;
7775 PSTORAGE_HOTPLUG_INFO info = Irp->AssociatedIrp.SystemBuffer;
7776
7778
7779 if (info->Size != fdoExtension->PrivateFdoData->HotplugInfo.Size)
7780 {
7782 }
7783
7784 if (info->MediaRemovable != fdoExtension->PrivateFdoData->HotplugInfo.MediaRemovable)
7785 {
7787 }
7788
7789 if (info->MediaHotplug != fdoExtension->PrivateFdoData->HotplugInfo.MediaHotplug)
7790 {
7792 }
7793
7794 if (NT_SUCCESS(status))
7795 {
7796 if (info->WriteCacheEnableOverride != fdoExtension->PrivateFdoData->HotplugInfo.WriteCacheEnableOverride)
7797 {
7798 fdoExtension->PrivateFdoData->HotplugInfo.WriteCacheEnableOverride = info->WriteCacheEnableOverride;
7799
7800 //
7801 // Store the user-defined override in the registry
7802 //
7803
7804 ClassSetDeviceParameter(fdoExtension,
7807 info->WriteCacheEnableOverride);
7808 }
7809
7810 fdoExtension->PrivateFdoData->HotplugInfo.DeviceHotplug = info->DeviceHotplug;
7811
7812 //
7813 // Store the user-defined override in the registry
7814 //
7815
7816 ClassSetDeviceParameter(fdoExtension,
7820 }
7821
7822 Irp->IoStatus.Status = status;
7823
7826 }
7827
7828 break;
7829 }
7830
7833
7834 PIRP irp2 = NULL;
7835 PIO_STACK_LOCATION newStack;
7836
7837 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
7838
7839 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DeviceIoControl: Check verify\n"));
7840
7841 //
7842 // If a buffer for a media change count was provided, make sure it's
7843 // big enough to hold the result
7844 //
7845
7846 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
7847
7848 //
7849 // If the buffer is too small to hold the media change count
7850 // then return an error to the caller
7851 //
7852
7853 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
7854 sizeof(ULONG)) {
7855
7856 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "DeviceIoControl: media count "
7857 "buffer too small\n"));
7858
7859 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
7860 Irp->IoStatus.Information = sizeof(ULONG);
7861
7862 FREE_POOL(srb);
7863
7866
7868 goto SetStatusAndReturn;
7869 }
7870 }
7871
7872 if (!commonExtension->IsFdo) {
7873
7874
7875 //
7876 // If this is a PDO then we should just forward the request down
7877 //
7878 NT_ASSERT(!srb);
7879
7881
7883
7884 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
7885
7886 goto SetStatusAndReturn;
7887
7888 } else {
7889
7890 fdoExtension = DeviceObject->DeviceExtension;
7891
7892 }
7893
7894 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
7895
7896 //
7897 // The caller has provided a valid buffer. Allocate an additional
7898 // irp and stick the CheckVerify completion routine on it. We will
7899 // then send this down to the port driver instead of the irp the
7900 // caller sent in
7901 //
7902
7903 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DeviceIoControl: Check verify wants "
7904 "media count\n"));
7905
7906 //
7907 // Allocate a new irp to send the TestUnitReady to the port driver
7908 //
7909
7910 irp2 = IoAllocateIrp((CCHAR) (DeviceObject->StackSize + 3), FALSE);
7911
7912 if (irp2 == NULL) {
7913 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
7914 Irp->IoStatus.Information = 0;
7915 FREE_POOL(srb);
7919 goto SetStatusAndReturn;
7920
7921 break;
7922 }
7923
7924 //
7925 // Make sure to acquire the lock for the new irp.
7926 //
7927
7929
7930 irp2->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
7932
7933 //
7934 // Set the top stack location and shove the master Irp into the
7935 // top location
7936 //
7937
7938 newStack = IoGetCurrentIrpStackLocation(irp2);
7939 newStack->Parameters.Others.Argument1 = Irp;
7940 newStack->DeviceObject = DeviceObject;
7941
7942 //
7943 // Stick the check verify completion routine onto the stack
7944 // and prepare the irp for the port driver
7945 //
7946
7949 NULL,
7950 TRUE,
7951 TRUE,
7952 TRUE);
7953
7955 newStack = IoGetCurrentIrpStackLocation(irp2);
7956 newStack->DeviceObject = DeviceObject;
7957 newStack->MajorFunction = irpStack->MajorFunction;
7958 newStack->MinorFunction = irpStack->MinorFunction;
7959 newStack->Flags = irpStack->Flags;
7960
7961
7962 //
7963 // Mark the master irp as pending - whether the lower level
7964 // driver completes it immediately or not this should allow it
7965 // to go all the way back up.
7966 //
7967
7969
7970 Irp = irp2;
7971
7972 }
7973
7974 //
7975 // Test Unit Ready
7976 //
7977
7978 SrbSetCdbLength(srb, 6);
7979 cdb = SrbGetCdb(srb);
7980 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
7981
7982 //
7983 // Set timeout value.
7984 //
7985
7986 SrbSetTimeOutValue(srb, fdoExtension->TimeOutValue);
7987
7988 //
7989 // If this was a CV2 then mark the request as low-priority so we don't
7990 // spin up the drive just to satisfy it.
7991 //
7992
7993 if (controlCode == IOCTL_STORAGE_CHECK_VERIFY2) {
7995 }
7996
7997 //
7998 // Since this routine will always hand the request to the
7999 // port driver if there isn't a data transfer to be done
8000 // we don't have to worry about completing the request here
8001 // on an error
8002 //
8003
8004 //
8005 // This routine uses a completion routine so we don't want to release
8006 // the remove lock until then.
8007 //
8008
8010 srb,
8011 Irp,
8012 NULL,
8013 0,
8014 FALSE);
8015
8016 break;
8017 }
8018
8021
8022 PPREVENT_MEDIA_REMOVAL mediaRemoval = Irp->AssociatedIrp.SystemBuffer;
8023
8024 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DiskIoControl: ejection control\n"));
8025
8026 FREE_POOL(srb);
8027
8028 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
8029 sizeof(PREVENT_MEDIA_REMOVAL)) {
8030
8031 //
8032 // Indicate unsuccessful status and no data transferred.
8033 //
8034
8035 Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH;
8036
8040 goto SetStatusAndReturn;
8041 }
8042
8043 if (!commonExtension->IsFdo) {
8044
8045
8046 //
8047 // Just forward this down and return
8048 //
8049
8051
8053 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8054 }
8055 else {
8056
8057 // i don't believe this assertion is valid. this is a request
8058 // from user-mode, so they could request this for any device
8059 // they want? also, we handle it properly.
8060 // NT_ASSERT(TEST_FLAG(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA));
8063 Irp,
8064 ((modifiedIoControlCode ==
8067 mediaRemoval->PreventMediaRemoval);
8068
8069 Irp->IoStatus.Status = status;
8072 }
8073
8074 break;
8075 }
8076
8078
8079 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DiskIoControl: MCN control\n"));
8080
8081 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
8082 sizeof(PREVENT_MEDIA_REMOVAL)) {
8083
8084 //
8085 // Indicate unsuccessful status and no data transferred.
8086 //
8087
8088 Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH;
8089 Irp->IoStatus.Information = 0;
8090
8091 FREE_POOL(srb);
8092
8096 goto SetStatusAndReturn;
8097 }
8098
8099 if (!commonExtension->IsFdo) {
8100
8101
8102 //
8103 // Just forward this down and return
8104 //
8105
8106 FREE_POOL(srb);
8107
8109
8111 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8112
8113 } else {
8114
8115 //
8116 // Call to the FDO - handle the ejection control.
8117 //
8118
8119 status = ClasspMcnControl(DeviceObject->DeviceExtension,
8120 Irp,
8121 srb);
8122 }
8123 goto SetStatusAndReturn;
8124 }
8125
8127 case IOCTL_STORAGE_RELEASE: {
8128
8129 //
8130 // Reserve logical unit.
8131 //
8132
8133 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
8134
8135 if (!commonExtension->IsFdo) {
8136
8137
8139
8141 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8142 goto SetStatusAndReturn;
8143
8144 } else {
8145 fdoExtension = DeviceObject->DeviceExtension;
8146 }
8147
8148 if (TEST_FLAG(fdoExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6))
8149 {
8150 SrbSetCdbLength(srb, 10);
8151 cdb = SrbGetCdb(srb);
8152 cdb->CDB10.OperationCode = (modifiedIoControlCode == IOCTL_STORAGE_RESERVE) ? SCSIOP_RESERVE_UNIT10 : SCSIOP_RELEASE_UNIT10;
8153 }
8154 else
8155 {
8156 SrbSetCdbLength(srb, 6);
8157 cdb = SrbGetCdb(srb);
8158 cdb->CDB6GENERIC.OperationCode = (modifiedIoControlCode == IOCTL_STORAGE_RESERVE) ? SCSIOP_RESERVE_UNIT : SCSIOP_RELEASE_UNIT;
8159 }
8160
8161 //
8162 // Set timeout value.
8163 //
8164
8165 SrbSetTimeOutValue(srb, fdoExtension->TimeOutValue);
8166
8167 //
8168 // Send reserves as tagged requests.
8169 //
8170
8171 if ( IOCTL_STORAGE_RESERVE == modifiedIoControlCode ) {
8174 }
8175
8177 srb,
8178 Irp,
8179 NULL,
8180 0,
8181 FALSE);
8182
8183 break;
8184 }
8185
8188
8189 if (!commonExtension->IsFdo) {
8190
8192
8194 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8195 goto SetStatusAndReturn;
8196 }
8197
8198 //
8199 // Process Persistent Reserve
8200 //
8201
8203
8204 break;
8205
8206 }
8207
8211
8212 //
8213 // Eject media.
8214 //
8215
8216 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
8217
8218 if (!commonExtension->IsFdo) {
8219
8220
8222
8224
8225 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8226 goto SetStatusAndReturn;
8227 } else {
8228 fdoExtension = DeviceObject->DeviceExtension;
8229 }
8230
8231 if (commonExtension->PagingPathCount != 0) {
8232
8233 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClassDeviceControl: call to eject paging device - "
8234 "failure\n"));
8235
8237 Irp->IoStatus.Status = status;
8238
8239 Irp->IoStatus.Information = 0;
8240
8241 FREE_POOL(srb);
8242
8245 goto SetStatusAndReturn;
8246 }
8247
8248 //
8249 // Synchronize with ejection control and ejection cleanup code as
8250 // well as other eject/load requests.
8251 //
8252
8256 KernelMode,
8257 FALSE,
8258 NULL);
8259
8260 if (fdoExtension->ProtectedLockCount != 0) {
8261
8262 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClassDeviceControl: call to eject protected locked "
8263 "device - failure\n"));
8264
8266 Irp->IoStatus.Status = status;
8267 Irp->IoStatus.Information = 0;
8268
8269 FREE_POOL(srb);
8270
8273
8276 FALSE);
8278
8279 goto SetStatusAndReturn;
8280 }
8281
8282 SrbSetCdbLength(srb, 6);
8283 cdb = SrbGetCdb(srb);
8284
8285 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
8286 cdb->START_STOP.LoadEject = 1;
8287
8288 if (modifiedIoControlCode == IOCTL_STORAGE_EJECT_MEDIA) {
8289 cdb->START_STOP.Start = 0;
8290 } else {
8291 cdb->START_STOP.Start = 1;
8292 }
8293
8294 //
8295 // Set timeout value.
8296 //
8297
8298 SrbSetTimeOutValue(srb, fdoExtension->TimeOutValue);
8300 srb,
8301 Irp,
8302 NULL,
8303 0,
8304 FALSE);
8305
8308
8309 break;
8310 }
8311
8313
8314 FREE_POOL(srb);
8315
8316 if (commonExtension->IsFdo) {
8317
8319 ((PFUNCTIONAL_DEVICE_EXTENSION) commonExtension)->LowerPdo,
8320 BusRelations);
8321
8323 Irp->IoStatus.Status = status;
8324
8327 }
8328 else {
8329
8330
8332
8334 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8335 }
8336 break;
8337 }
8338
8340
8341 FREE_POOL(srb);
8342
8343 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >=
8344 sizeof(STORAGE_DEVICE_NUMBER)) {
8345
8346 PSTORAGE_DEVICE_NUMBER deviceNumber =
8347 Irp->AssociatedIrp.SystemBuffer;
8348 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
8349 commonExtension->PartitionZeroExtension;
8350
8351 deviceNumber->DeviceType = fdoExtension->CommonExtension.DeviceObject->DeviceType;
8352 deviceNumber->DeviceNumber = fdoExtension->DeviceNumber;
8353 deviceNumber->PartitionNumber = commonExtension->PartitionNumber;
8354
8356 Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
8357
8358 } else {
8360 Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
8361 }
8362
8363 Irp->IoStatus.Status = status;
8366
8367 break;
8368 }
8369
8370
8372
8373 FREE_POOL(srb);
8374
8375 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
8376 sizeof(STORAGE_READ_CAPACITY)) {
8377
8378 //
8379 // Indicate unsuccessful status and no data transferred.
8380 //
8381
8382 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
8383 Irp->IoStatus.Information = sizeof(STORAGE_READ_CAPACITY);
8384
8388 break;
8389 }
8390
8391 if (!commonExtension->IsFdo) {
8392
8393
8394 //
8395 // Just forward this down and return
8396 //
8397
8399
8401 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8402 }
8403 else {
8404
8405 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = DeviceObject->DeviceExtension;
8406 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
8407 PSTORAGE_READ_CAPACITY readCapacity = Irp->AssociatedIrp.SystemBuffer;
8408 LARGE_INTEGER diskLength;
8409
8411 if (NT_SUCCESS(status) && fdoData->IsCachedDriveCapDataValid) {
8412
8413 readCapacity->Version = sizeof(STORAGE_READ_CAPACITY);
8414 readCapacity->Size = sizeof(STORAGE_READ_CAPACITY);
8415
8416 REVERSE_BYTES(&readCapacity->BlockLength,
8418 REVERSE_BYTES_QUAD(&readCapacity->NumberOfBlocks,
8420 readCapacity->NumberOfBlocks.QuadPart++;
8421
8422 readCapacity->DiskLength = fdoExt->CommonExtension.PartitionLength;
8423
8424 //
8425 // Make sure the lengths are equal.
8426 // Remove this after testing.
8427 //
8428 diskLength.QuadPart = readCapacity->NumberOfBlocks.QuadPart *
8429 readCapacity->BlockLength;
8430
8431 Irp->IoStatus.Status = STATUS_SUCCESS;
8432 Irp->IoStatus.Information = sizeof(STORAGE_READ_CAPACITY);
8433
8434 } else {
8435 //
8436 // Read capacity request failed.
8437 //
8438 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "ClassDeviceControl: ClassReadDriveCapacity failed: 0x%X IsCachedDriveCapDataValid: %d\n",
8440 Irp->IoStatus.Status = status;
8441 Irp->IoStatus.Information = 0;
8442 }
8445 }
8446
8447 break;
8448 }
8449
8451
8452 PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
8453
8454 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_PROPERTY_QUERY)) {
8455
8457 Irp->IoStatus.Status = status;
8460 FREE_POOL(srb);
8461 break;
8462 }
8463
8464 if (!commonExtension->IsFdo) {
8465
8466
8468
8470 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8471 FREE_POOL(srb);
8472 break;
8473 }
8474
8475 //
8476 // Determine PropertyId type and either call appropriate routine
8477 // or pass request to lower drivers.
8478 //
8479
8480 switch ( query->PropertyId ) {
8481
8483
8485 break;
8486 }
8487
8489
8491 break;
8492 }
8493
8494 // these propertyId has been implemented in some port driver and filter drivers.
8495 // to keep the backwards compatibility, classpnp will send the request down if it's supported by lower layer.
8496 // otherwise, classpnp sends SCSI command and then interprets the result.
8498
8500 break;
8501 }
8502
8504
8506 break;
8507 }
8508
8510
8512 break;
8513 }
8514
8516
8518 break;
8519 }
8520
8522
8523 status = ClasspDeviceCopyOffloadProperty(DeviceObject, Irp, srb);
8524 break;
8525 }
8526
8528
8530 break;
8531 }
8532
8533 default: {
8534
8535 //
8536 // Copy the Irp stack parameters to the next stack location.
8537 //
8538
8540
8542 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8543 break;
8544 }
8545 } // end switch
8546
8547 FREE_POOL(srb);
8548 break;
8549 }
8550
8552
8553 FREE_POOL(srb);
8554
8555 if (!commonExtension->IsFdo) {
8556
8557
8559
8561 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8562 break;
8563 }
8564
8565 //
8566 // Process priority hit request
8567 //
8568
8570 break;
8571 }
8572
8574
8575 PDEVICE_MANAGE_DATA_SET_ATTRIBUTES dsmAttributes = Irp->AssociatedIrp.SystemBuffer;
8576
8577 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES)) {
8578
8580 Irp->IoStatus.Status = status;
8583 FREE_POOL(srb);
8584 break;
8585 }
8586
8587 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
8588 (sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES) + dsmAttributes->ParameterBlockLength + dsmAttributes->DataSetRangesLength)) {
8589
8591 Irp->IoStatus.Status = status;
8594 FREE_POOL(srb);
8595 break;
8596 }
8597
8598 if (!commonExtension->IsFdo) {
8599
8600
8602
8604 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8605 FREE_POOL(srb);
8606 break;
8607 }
8608
8609 switch(dsmAttributes->Action) {
8610
8611 // only process Trim action in class layer if possible.
8612 case DeviceDsmAction_Trim: {
8613 status = ClasspDeviceTrimProcess(DeviceObject, Irp, &activityId, srb);
8614 break;
8615 }
8616
8618 status = ClassDeviceProcessOffloadRead(DeviceObject, Irp, srb);
8619 break;
8620 }
8621
8623 status = ClassDeviceProcessOffloadWrite(DeviceObject, Irp, srb);
8624 break;
8625 }
8626
8629 break;
8630 }
8631
8632
8633 default: {
8634
8635
8636 //
8637 // Copy the Irp stack parameters to the next stack location.
8638 //
8639
8641
8643 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8644 break;
8645 }
8646 } // end switch
8647
8648 FREE_POOL(srb);
8649 break;
8650 }
8651
8653
8654 if (commonExtension->IsFdo) {
8655
8657
8658 } else {
8659
8661
8663 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8664 }
8665
8666 FREE_POOL(srb);
8667
8668 break;
8669 }
8670
8672
8673 FREE_POOL(srb);
8674
8676 break;
8677 }
8678
8679#if (NTDDI_VERSION >= NTDDI_WINTRHESHOLD)
8681 FREE_POOL(srb);
8682
8684 break;
8685 }
8686
8688 if (!commonExtension->IsFdo) {
8689
8691
8693 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8694 goto SetStatusAndReturn;
8695 }
8696
8698 break;
8699 }
8700
8702 if (!commonExtension->IsFdo) {
8703
8705
8707 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8708 goto SetStatusAndReturn;
8709 }
8710
8712 break;
8713 }
8714#endif
8715
8716
8717 default: {
8718
8719 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "IoDeviceControl: Unsupported device IOCTL %x for %p\n",
8720 controlCode, DeviceObject));
8721
8722
8723 //
8724 // Pass the device control to the next driver.
8725 //
8726
8727 FREE_POOL(srb);
8728
8729 //
8730 // Copy the Irp stack parameters to the next stack location.
8731 //
8732
8734
8736 status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
8737 break;
8738 }
8739
8740 } // end switch( ...
8741
8742SetStatusAndReturn:
8743
8744 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "< ioctl %xh (%s): status %xh.", modifiedIoControlCode, DBGGETIOCTLSTR(modifiedIoControlCode), status));
8745
8746 return status;
8747} // end ClassDeviceControl()
8748
8749/*++////////////////////////////////////////////////////////////////////////////
8750
8751ClassShutdownFlush()
8752
8753Routine Description:
8754
8755 This routine is called for a shutdown and flush IRPs. These are sent by the
8756 system before it actually shuts down or when the file system does a flush.
8757 If it exists, the device-specific driver's routine will be invoked. If there
8758 wasn't one specified, the Irp will be completed with an Invalid device request.
8759
8760Arguments:
8761
8762 DriverObject - Pointer to device object to being shutdown by system.
8763
8764 Irp - IRP involved.
8765
8766Return Value:
8767
8768 NT Status
8769
8770--*/
8772NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
8775 IN PIRP Irp
8776 )
8777{
8778 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
8779
8780 ULONG isRemoved;
8781
8783 _Analysis_assume_(isRemoved);
8784 if(isRemoved) {
8785
8787
8788 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
8789
8791
8793 }
8794
8795 if (commonExtension->DevInfo->ClassShutdownFlush) {
8796
8797 //
8798 // Call the device-specific driver's routine.
8799 //
8800
8801 return commonExtension->DevInfo->ClassShutdownFlush(DeviceObject, Irp);
8802 }
8803
8804 //
8805 // Device-specific driver doesn't support this.
8806 //
8807
8808 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
8809
8812
8814} // end ClassShutdownFlush()
8815
8816/*++////////////////////////////////////////////////////////////////////////////
8817
8818ClasspIsPortable()
8819
8820Routine Description:
8821
8822 This routine is called during start device to determine whether the PDO
8823 for a stack reports itself as portable.
8824
8825Arguments:
8826
8827 FdoExtension - Pointer to FDO whose PDO we check for portability.
8828
8829 IsPortable - Boolean pointer in which to store result.
8830
8831Return Value:
8832
8833 NT Status
8834
8835--*/
8839 _Out_ PBOOLEAN IsPortable
8840 )
8841{
8842 DEVPROP_BOOLEAN isInternal = DEVPROP_FALSE;
8843 BOOLEAN isPortable = FALSE;
8844 ULONG size = 0;
8847
8848 PAGED_CODE();
8849
8850 *IsPortable = FALSE;
8851
8852 //
8853 // Check to see if the underlying device
8854 // object is in local machine container
8855 //
8856
8857 status = IoGetDevicePropertyData(FdoExtension->LowerPdo,
8858 &DEVPKEY_Device_InLocalMachineContainer,
8859 0,
8860 0,
8861 sizeof(isInternal),
8862 &isInternal,
8863 &size,
8864 &type);
8865
8866 if (!NT_SUCCESS(status)) {
8867 goto cleanup;
8868 }
8869
8870 NT_ASSERT(size == sizeof(isInternal));
8872
8873 //
8874 // Volume is hot-pluggable if the disk pdo
8875 // container id differs from that of root device
8876 //
8877
8878 if (isInternal == DEVPROP_TRUE) {
8879 goto cleanup;
8880 }
8881
8882 isPortable = TRUE;
8883
8884 //
8885 // Examine the bus type to ensure
8886 // that this really is a fixed disk
8887 //
8888
8889 if (FdoExtension->DeviceDescriptor->BusType == BusTypeFibre ||
8890 FdoExtension->DeviceDescriptor->BusType == BusTypeiScsi ||
8891 FdoExtension->DeviceDescriptor->BusType == BusTypeRAID) {
8892
8893 isPortable = FALSE;
8894 }
8895
8896 *IsPortable = isPortable;
8897
8898cleanup:
8899
8900 return status;
8901}
8902
8903/*++////////////////////////////////////////////////////////////////////////////
8904
8905ClassCreateDeviceObject()
8906
8907Routine Description:
8908
8909 This routine creates an object for the physical device specified and
8910 sets up the deviceExtension's function pointers for each entry point
8911 in the device-specific driver.
8912
8913Arguments:
8914
8915 DriverObject - Pointer to driver object created by system.
8916
8917 ObjectNameBuffer - Dir. name of the object to create.
8918
8919 LowerDeviceObject - Pointer to the lower device object
8920
8921 IsFdo - should this be an fdo or a pdo
8922
8923 DeviceObject - Pointer to the device object pointer we will return.
8924
8925Return Value:
8926
8927 NTSTATUS
8928
8929--*/
8930
8933_Post_satisfies_(return <= 0)
8936NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
8937ClassCreateDeviceObject(
8939 _In_z_ PCCHAR ObjectNameBuffer,
8940 _In_ PDEVICE_OBJECT LowerDevice,
8945 )
8946{
8947 BOOLEAN isPartitionable;
8948 STRING ntNameString;
8949 UNICODE_STRING ntUnicodeString;
8952
8953 ULONG characteristics;
8955 PCHAR rundownAddr = NULL;
8956 ULONG devExtSize;
8957
8958#ifdef _MSC_VER
8959#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
8960#endif
8962
8963 PCLASS_DEV_INFO devInfo;
8964
8965 PAGED_CODE();
8966
8967 _Analysis_assume_(driverExtension != NULL);
8968
8969 *DeviceObject = NULL;
8970 RtlInitUnicodeString(&ntUnicodeString, NULL);
8971
8972 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClassCreateFdo: Create device object\n"));
8973
8974 NT_ASSERT(LowerDevice);
8975
8976 //
8977 // Make sure that if we're making PDO's we have an enumeration routine
8978 //
8979
8980 isPartitionable = (driverExtension->InitData.ClassEnumerateDevice != NULL);
8981
8982 NT_ASSERT(IsFdo || isPartitionable);
8983
8984 //
8985 // Grab the correct dev-info structure out of the init data
8986 //
8987
8988 if (IsFdo) {
8989 devInfo = &(driverExtension->InitData.FdoData);
8990 } else {
8991 devInfo = &(driverExtension->InitData.PdoData);
8992 }
8993
8994 characteristics = devInfo->DeviceCharacteristics;
8995
8997 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClassCreateFdo: Name is %s\n", ObjectNameBuffer));
8998
8999 RtlInitString(&ntNameString, ObjectNameBuffer);
9000
9001 status = RtlAnsiStringToUnicodeString(&ntUnicodeString, &ntNameString, TRUE);
9002
9003 if (!NT_SUCCESS(status)) {
9004
9005 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
9006 "ClassCreateFdo: Cannot convert string %s\n",
9008
9009 ntUnicodeString.Buffer = NULL;
9010 return status;
9011 }
9012 } else {
9013 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClassCreateFdo: Object will be unnamed\n"));
9014
9015 if (IsFdo == FALSE) {
9016
9017 //
9018 // PDO's have to have some sort of name.
9019 //
9020
9021 SET_FLAG(characteristics, FILE_AUTOGENERATED_DEVICE_NAME);
9022 }
9023
9024 RtlInitUnicodeString(&ntUnicodeString, NULL);
9025 }
9026
9027 devExtSize = devInfo->DeviceExtensionSize +
9028 (ULONG)sizeof(CLASS_PRIVATE_COMMON_DATA) + (ULONG)rundownSize;
9030 devExtSize,
9031 &ntUnicodeString,
9032 devInfo->DeviceType,
9033 characteristics,
9034 FALSE,
9035 &deviceObject);
9036
9037 if (!NT_SUCCESS(status)) {
9038
9039 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassCreateFdo: Can not create device object %lx\n",
9040 status));
9042
9043 //
9044 // buffer is not used any longer here.
9045 //
9046
9047 if (ntUnicodeString.Buffer != NULL) {
9048 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassCreateFdo: Freeing unicode name buffer\n"));
9049 FREE_POOL(ntUnicodeString.Buffer);
9050 RtlInitUnicodeString(&ntUnicodeString, NULL);
9051 }
9052
9053 } else {
9054
9055 PCOMMON_DEVICE_EXTENSION commonExtension = deviceObject->DeviceExtension;
9056
9058 deviceObject->DeviceExtension,
9059 devExtSize);
9060
9061 //
9062 // Setup version code
9063 //
9064
9065 commonExtension->Version = 0x03;
9066
9067 //
9068 // Setup the remove lock and event
9069 //
9070
9071 commonExtension->IsRemoved = NO_REMOVE;
9072
9073#if DBG
9074
9075 commonExtension->RemoveLock = 0;
9076
9077#endif
9078
9079 KeInitializeEvent(&commonExtension->RemoveEvent,
9081 FALSE);
9082
9083
9085
9086 //
9087 // Initialize the PrivateCommonData
9088 //
9089
9091 ((PCHAR)deviceObject->DeviceExtension + devInfo->DeviceExtensionSize);
9092 rundownAddr = (PCHAR)commonExtension->PrivateCommonData + sizeof(CLASS_PRIVATE_COMMON_DATA);
9094 commonExtension->PrivateCommonData->RemoveLockFailAcquire = 0;
9095
9096 //
9097 // Acquire the lock once. This reference will be released when the
9098 // remove IRP has been received.
9099 //
9100
9102
9103 //
9104 // Store a pointer to the driver extension so we don't have to do
9105 // lookups to get it.
9106 //
9107
9108 commonExtension->DriverExtension = driverExtension;
9109
9110 //
9111 // Fill in entry points
9112 //
9113
9114 commonExtension->DevInfo = devInfo;
9115
9116 //
9117 // Initialize some of the common values in the structure
9118 //
9119
9120 commonExtension->DeviceObject = deviceObject;
9121
9122 commonExtension->LowerDeviceObject = NULL;
9123
9124 commonExtension->DispatchTable = driverExtension->DeviceMajorFunctionTable;
9125
9126 if(IsFdo) {
9127
9128 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = (PVOID) commonExtension;
9129
9130 commonExtension->PartitionZeroExtension = deviceObject->DeviceExtension;
9131
9132 //
9133 // Set the initial device object flags.
9134 //
9135
9137 //
9138 // Clear the PDO list
9139 //
9140
9141 commonExtension->ChildList = NULL;
9142
9143 commonExtension->DriverData =
9144 ((PFUNCTIONAL_DEVICE_EXTENSION) deviceObject->DeviceExtension + 1);
9145
9146 //
9147 // The disk class driver creates only FDO. The partition number
9148 // for the FDO must be 0.
9149 //
9150
9151 if ((isPartitionable == TRUE) ||
9152 (devInfo->DeviceType == FILE_DEVICE_DISK)) {
9153
9154 commonExtension->PartitionNumber = 0;
9155 } else {
9156 commonExtension->PartitionNumber = (ULONG) (-1L);
9157 }
9158
9159 fdoExtension->DevicePowerState = PowerDeviceD0;
9160
9163 TRUE);
9164
9165 KeInitializeEvent(&fdoExtension->ChildLock,
9167 TRUE);
9168
9170
9171 if(!NT_SUCCESS(status)) {
9173 *DeviceObject = NULL;
9174
9175 if (ntUnicodeString.Buffer != NULL) {
9176 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClassCreateFdo: Freeing unicode name buffer\n"));
9177 FREE_POOL(ntUnicodeString.Buffer);
9178 RtlInitUnicodeString(&ntUnicodeString, NULL);
9179 }
9180
9181 return status;
9182 }
9183
9184 } else {
9185
9186 PPHYSICAL_DEVICE_EXTENSION pdoExtension =
9187 deviceObject->DeviceExtension;
9188
9189 PFUNCTIONAL_DEVICE_EXTENSION p0Extension =
9190 LowerDevice->DeviceExtension;
9191
9193
9194 commonExtension->PartitionZeroExtension = p0Extension;
9195
9196 //
9197 // Stick this onto the PDO list
9198 //
9199
9200 ClassAddChild(p0Extension, pdoExtension, TRUE);
9201
9202 commonExtension->DriverData = (PVOID) (pdoExtension + 1);
9203
9204 //
9205 // Get the top of stack for the lower device - this allows
9206 // filters to get stuck in between the partitions and the
9207 // physical disk.
9208 //
9209
9210 commonExtension->LowerDeviceObject =
9211 IoGetAttachedDeviceReference(LowerDevice);
9212
9213 //
9214 // Pnp will keep a reference to the lower device object long
9215 // after this partition has been deleted. Dereference now so
9216 // we don't have to deal with it later.
9217 //
9218
9219 ObDereferenceObject(commonExtension->LowerDeviceObject);
9220 }
9221
9223
9224 commonExtension->IsFdo = IsFdo;
9225
9226 commonExtension->DeviceName = ntUnicodeString;
9227
9228 commonExtension->PreviousState = 0xff;
9229
9230 InitializeDictionary(&(commonExtension->FileObjectDictionary));
9231
9232 commonExtension->CurrentState = IRP_MN_STOP_DEVICE;
9233
9234 if (commonExtension->DriverExtension->InitData.ClassStartIo) {
9236 }
9237 }
9238
9240
9241 return status;
9242} // end ClassCreateDeviceObject()
9243
9244/*++////////////////////////////////////////////////////////////////////////////
9245
9246ClassClaimDevice()
9247
9248Routine Description:
9249
9250 This function claims a device in the port driver. The port driver object
9251 is updated with the correct driver object if the device is successfully
9252 claimed.
9253
9254Arguments:
9255
9256 LowerDeviceObject - Supplies the base port device object.
9257
9258 Release - Indicates the logical unit should be released rather than claimed.
9259
9260Return Value:
9261
9262 Returns a status indicating success or failure of the operation.
9263
9264--*/
9267NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
9268ClassClaimDevice(
9271 )
9272{
9273 IO_STATUS_BLOCK ioStatus;
9274 PIRP irp;
9275 PIO_STACK_LOCATION irpStack;
9276 KEVENT event;
9278 SCSI_REQUEST_BLOCK srb = {0};
9279
9280 PAGED_CODE();
9281
9282 //
9283 // WORK ITEM - MPIO related. Need to think about how to handle.
9284 //
9285
9286 srb.Length = sizeof(SCSI_REQUEST_BLOCK);
9287
9290
9291 //
9292 // Set the event object to the unsignaled state.
9293 // It will be used to signal request completion
9294 //
9295
9297
9298 //
9299 // Build synchronous request with no transfer.
9300 //
9301
9304 NULL,
9305 0,
9306 NULL,
9307 0,
9308 TRUE,
9309 &event,
9310 &ioStatus);
9311
9312 if (irp == NULL) {
9313 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClassClaimDevice: Can't allocate Irp\n"));
9315 }
9316
9317 irpStack = IoGetNextIrpStackLocation(irp);
9318
9319 //
9320 // Save SRB address in next stack for port driver.
9321 //
9322
9323 irpStack->Parameters.Scsi.Srb = &srb;
9324
9325 //
9326 // Set up IRP Address.
9327 //
9328
9329 srb.OriginalRequest = irp;
9330
9331 //
9332 // Call the port driver with the request and wait for it to complete.
9333 //
9334
9336 if (status == STATUS_PENDING) {
9337
9339 status = ioStatus.Status;
9340 }
9341
9342 //
9343 // If this is a release request, then just decrement the reference count
9344 // and return. The status does not matter.
9345 //
9346
9347 if (Release) {
9348
9349 // ObDereferenceObject(LowerDeviceObject);
9350 return STATUS_SUCCESS;
9351 }
9352
9353 if (!NT_SUCCESS(status)) {
9354 return status;
9355 }
9356
9357 NT_ASSERT(srb.DataBuffer != NULL);
9359
9360 return status;
9361} // end ClassClaimDevice()
9362
9363/*++////////////////////////////////////////////////////////////////////////////
9364
9365ClassInternalIoControl()
9366
9367Routine Description:
9368
9369 This routine passes internal device controls to the port driver.
9370 Internal device controls are used by higher level drivers both for ioctls
9371 and to pass through scsi requests.
9372
9373 If the IoControlCode does not match any of the handled ioctls and is
9374 a valid system address then the request will be treated as an SRB and
9375 passed down to the lower driver. If the IoControlCode is not a valid
9376 system address the ioctl will be failed.
9377
9378 Callers must therefore be extremely cautious to pass correct, initialized
9379 values to this function.
9380
9381Arguments:
9382
9383 DeviceObject - Supplies a pointer to the device object for this request.
9384
9385 Irp - Supplies the Irp making the request.
9386
9387Return Value:
9388
9389 Returns back a STATUS_PENDING or a completion status.
9390
9391--*/
9393NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
9396 IN PIRP Irp
9397 )
9398{
9399 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
9400
9403
9404 ULONG isRemoved;
9405
9407
9409 _Analysis_assume_(isRemoved);
9410 if(isRemoved) {
9411
9412 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
9413
9415
9417
9419 }
9420
9421 //
9422 // Get a pointer to the SRB.
9423 //
9424
9425 srb = irpStack->Parameters.Scsi.Srb;
9426
9427 //
9428 // Set the parameters in the next stack location.
9429 //
9430
9431 if(commonExtension->IsFdo) {
9432 nextStack->Parameters.Scsi.Srb = srb;
9433 nextStack->MajorFunction = IRP_MJ_SCSI;
9434 nextStack->MinorFunction = IRP_MN_SCSI_CLASS;
9435
9436 } else {
9437
9439 }
9440
9442
9443 return IoCallDriver(commonExtension->LowerDeviceObject, Irp);
9444} // end ClassInternalIoControl()
9445
9446/*++////////////////////////////////////////////////////////////////////////////
9447
9448ClassQueryTimeOutRegistryValue()
9449
9450Routine Description:
9451
9452 This routine determines whether a reg key for a user-specified timeout
9453 value exists. This should be called at initialization time.
9454
9455Arguments:
9456
9457 DeviceObject - Pointer to the device object we are retrieving the timeout
9458 value for
9459
9460Return Value:
9461
9462 None, but it sets a new default timeout for a class of devices.
9463
9464--*/
9466ULONG
9467NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
9468ClassQueryTimeOutRegistryValue(
9470 )
9471{
9472 //
9473 // Find the appropriate reg. key
9474 //
9475
9476#ifdef _MSC_VER
9477#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
9478#endif
9480
9481 PUNICODE_STRING registryPath = &(driverExtension->RegistryPath);
9482
9483 PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
9484 PWSTR path;
9486 LONG timeOut = 0;
9487 ULONG zero = 0;
9488 ULONG size;
9489
9490 PAGED_CODE();
9491
9492 if (!registryPath) {
9493 return 0;
9494 }
9495
9496 parameters = ExAllocatePoolWithTag(NonPagedPoolNx,
9497 sizeof(RTL_QUERY_REGISTRY_TABLE)*2,
9498 '1BcS');
9499
9500 if (!parameters) {
9501 return 0;
9502 }
9503
9504 size = registryPath->MaximumLength + sizeof(WCHAR);
9505 path = ExAllocatePoolWithTag(NonPagedPoolNx, size, '2BcS');
9506
9507 if (!path) {
9508 FREE_POOL(parameters);
9509 return 0;
9510 }
9511
9513 RtlCopyMemory(path, registryPath->Buffer, size - sizeof(WCHAR));
9514
9515
9516 //
9517 // Check for the Timeout value.
9518 //
9519
9520 RtlZeroMemory(parameters,
9521 (sizeof(RTL_QUERY_REGISTRY_TABLE)*2));
9522
9524 parameters[0].Name = L"TimeOutValue";
9525 parameters[0].EntryContext = &timeOut;
9527 parameters[0].DefaultData = &zero;
9528 parameters[0].DefaultLength = sizeof(ULONG);
9529
9531 path,
9532 parameters,
9533 NULL,
9534 NULL);
9535
9536 if (!(NT_SUCCESS(status))) {
9537 timeOut = 0;
9538 }
9539
9540 FREE_POOL(parameters);
9541 FREE_POOL(path);
9542
9543 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
9544 "ClassQueryTimeOutRegistryValue: Timeout value %d\n",
9545 timeOut));
9546
9547
9548 return timeOut;
9549
9550} // end ClassQueryTimeOutRegistryValue()
9551
9552
9553/*++////////////////////////////////////////////////////////////////////////////
9554
9555ClassCheckVerifyComplete() ISSUE-2000/02/18-henrygab - why public?!
9556
9557Routine Description:
9558
9559 This routine executes when the port driver has completed a check verify
9560 ioctl. It will set the status of the master Irp, copy the media change
9561 count and complete the request.
9562
9563Arguments:
9564
9565 Fdo - Supplies the functional device object which represents the logical unit.
9566
9567 Irp - Supplies the Irp which has completed.
9568
9569 Context - NULL
9570
9571Return Value:
9572
9573 NT status
9574
9575--*/
9577NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
9580 IN PIRP Irp,
9582 )
9583{
9585 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
9586
9587 PIRP originalIrp;
9588
9590
9591 ASSERT_FDO(Fdo);
9592
9593 originalIrp = irpStack->Parameters.Others.Argument1;
9594
9595 //
9596 // Copy the media change count and status
9597 //
9598
9599 *((PULONG) (originalIrp->AssociatedIrp.SystemBuffer)) =
9600 fdoExtension->MediaChangeCount;
9601
9602 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClassCheckVerifyComplete - Media change count for"
9603 "device %d is %lx - saved as %lx\n",
9604 fdoExtension->DeviceNumber,
9605 fdoExtension->MediaChangeCount,
9606 *((PULONG) originalIrp->AssociatedIrp.SystemBuffer)));
9607
9608 originalIrp->IoStatus.Status = Irp->IoStatus.Status;
9609 originalIrp->IoStatus.Information = sizeof(ULONG);
9610
9611 ClassReleaseRemoveLock(Fdo, originalIrp);
9613
9614 IoFreeIrp(Irp);
9615
9617
9618} // end ClassCheckVerifyComplete()
9619
9620
9621/*++////////////////////////////////////////////////////////////////////////////
9622
9623ClassGetDescriptor()
9624
9625Routine Description:
9626
9627 This routine will perform a query for the specified property id and will
9628 allocate a non-paged buffer to store the data in. It is the responsibility
9629 of the caller to ensure that this buffer is freed.
9630
9631 This routine must be run at IRQL_PASSIVE_LEVEL
9632
9633Arguments:
9634
9635 DeviceObject - the device to query
9636 DeviceInfo - a location to store a pointer to the buffer we allocate
9637
9638Return Value:
9639
9640 status
9641 if status is unsuccessful *DeviceInfo will be set to NULL, else the
9642 buffer allocated on behalf of the caller.
9643
9644--*/
9647NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
9648ClassGetDescriptor(
9652 )
9653{
9655 IO_STATUS_BLOCK ioStatus;
9656
9658 ULONG length;
9659
9660 PAGED_CODE();
9661
9662 //
9663 // Set the passed-in descriptor pointer to NULL as default
9664 //
9665
9666 *Descriptor = NULL;
9667
9668 query.PropertyId = *PropertyId;
9669 query.QueryType = PropertyStandardQuery;
9670
9671 //
9672 // On the first pass we just want to get the first few
9673 // bytes of the descriptor so we can read it's size
9674 //
9675
9677
9678 NT_ASSERT(sizeof(STORAGE_PROPERTY_QUERY) >= (sizeof(ULONG)*2));
9679
9683 &query,
9684 sizeof(STORAGE_PROPERTY_QUERY),
9685 sizeof(ULONG) * 2,
9686 FALSE,
9687 &ioStatus
9688 );
9689
9690 if(!NT_SUCCESS(ioStatus.Status)) {
9691
9692 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassGetDescriptor: error %lx trying to "
9693 "query properties #1\n", ioStatus.Status));
9694 return ioStatus.Status;
9695 }
9696
9697 if (descriptor->Size == 0) {
9698
9699 //
9700 // This DebugPrint is to help third-party driver writers
9701 //
9702
9703 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassGetDescriptor: size returned was zero?! (status "
9704 "%x\n", ioStatus.Status));
9705 return STATUS_UNSUCCESSFUL;
9706
9707 }
9708
9709 //
9710 // This time we know how much data there is so we can
9711 // allocate a buffer of the correct size
9712 //
9713
9714 length = descriptor->Size;
9717
9718 descriptor = ExAllocatePoolWithTag(NonPagedPoolNx, length, '4BcS');
9719
9720 if(descriptor == NULL) {
9721
9722 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassGetDescriptor: unable to memory for descriptor "
9723 "(%d bytes)\n", length));
9725 }
9726
9727 //
9728 // setup the query again, as it was overwritten above
9729 //
9730
9732 query.PropertyId = *PropertyId;
9733 query.QueryType = PropertyStandardQuery;
9734
9735 //
9736 // copy the input to the new outputbuffer
9737 //
9738
9740
9742 &query,
9744 );
9745
9749 descriptor,
9750 sizeof(STORAGE_PROPERTY_QUERY),
9751 length,
9752 FALSE,
9753 &ioStatus
9754 );
9755
9756 if(!NT_SUCCESS(ioStatus.Status)) {
9757
9758 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "ClassGetDescriptor: error %lx trying to "
9759 "query properties #1\n", ioStatus.Status));
9761 return ioStatus.Status;
9762 }
9763
9764 //
9765 // return the memory we've allocated to the caller
9766 //
9767
9769 return ioStatus.Status;
9770} // end ClassGetDescriptor()
9771
9772
9773/*++////////////////////////////////////////////////////////////////////////////
9774
9775ClassSignalCompletion()
9776
9777Routine Description:
9778
9779 This completion routine will signal the event given as context and then
9780 return STATUS_MORE_PROCESSING_REQUIRED to stop event completion. It is
9781 the responsibility of the routine waiting on the event to complete the
9782 request and free the event.
9783
9784Arguments:
9785
9786 DeviceObject - a pointer to the device object
9787
9788 Irp - a pointer to the irp
9789
9790 Event - a pointer to the event to signal
9791
9792Return Value:
9793
9794 STATUS_MORE_PROCESSING_REQUIRED
9795
9796--*/
9798NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
9801 IN PIRP Irp,
9803 )
9804{
9806
9809
9810 if (Context == NULL) {
9813 }
9814
9816
9818} // end ClassSignalCompletion()
9819
9820/*++////////////////////////////////////////////////////////////////////////////
9821
9822ClassPnpQueryFdoRelations()
9823
9824Routine Description:
9825
9826 This routine will call the driver's enumeration routine to update the
9827 list of PDO's. It will then build a response to the
9828 IRP_MN_QUERY_DEVICE_RELATIONS and place it into the information field in
9829 the irp.
9830
9831Arguments:
9832
9833 Fdo - a pointer to the functional device object we are enumerating
9834
9835 Irp - a pointer to the enumeration request
9836
9837Return Value:
9838
9839 status
9840
9841--*/
9845 IN PIRP Irp
9846 )
9847{
9848 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
9849#ifdef _MSC_VER
9850#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
9851#endif
9853
9854 PAGED_CODE();
9855
9856 _Analysis_assume_(driverExtension != NULL);
9857
9858 //
9859 // If there's already an enumeration in progress then don't start another
9860 // one.
9861 //
9862
9863 if(InterlockedIncrement((volatile LONG *)&(fdoExtension->EnumerationInterlock)) == 1) {
9864 driverExtension->InitData.ClassEnumerateDevice(Fdo);
9865 }
9866
9867 Irp->IoStatus.Status = ClassRetrieveDeviceRelations(
9868 Fdo,
9870 (PDEVICE_RELATIONS *) &Irp->IoStatus.Information);
9871 InterlockedDecrement((volatile LONG *)&(fdoExtension->EnumerationInterlock));
9872
9873 return Irp->IoStatus.Status;
9874} // end ClassPnpQueryFdoRelations()
9875
9876/*++////////////////////////////////////////////////////////////////////////////
9877
9878ClassMarkChildrenMissing()
9879
9880Routine Description:
9881
9882 This routine will call ClassMarkChildMissing() for all children.
9883 It acquires the ChildLock before calling ClassMarkChildMissing().
9884
9885Arguments:
9886
9887 Fdo - the "bus's" device object, such as the disk FDO for non-removable
9888 disks with multiple partitions.
9889
9890Return Value:
9891
9892 None
9893
9894--*/
9896VOID
9897NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
9898ClassMarkChildrenMissing(
9900 )
9901{
9902 PCOMMON_DEVICE_EXTENSION commonExtension = &(Fdo->CommonExtension);
9903 PPHYSICAL_DEVICE_EXTENSION nextChild = commonExtension->ChildList;
9904
9905 PAGED_CODE();
9906
9907 ClassAcquireChildLock(Fdo);
9908
9909 while (nextChild){
9911
9912 /*
9913 * ClassMarkChildMissing will also dequeue the child extension.
9914 * So get the next pointer before calling ClassMarkChildMissing.
9915 */
9916 tmpChild = nextChild;
9917 nextChild = tmpChild->CommonExtension.ChildList;
9918 ClassMarkChildMissing(tmpChild, FALSE);
9919 }
9921 return;
9922} // end ClassMarkChildrenMissing()
9923
9924/*++////////////////////////////////////////////////////////////////////////////
9925
9926ClassMarkChildMissing()
9927
9928Routine Description:
9929
9930 This routine will make an active child "missing." If the device has never
9931 been enumerated then it will be deleted on the spot. If the device has
9932 not been enumerated then it will be marked as missing so that we can
9933 not report it in the next device enumeration.
9934
9935Arguments:
9936
9937 Child - the child device to be marked as missing.
9938
9939 AcquireChildLock - TRUE if the child lock should be acquired before removing
9940 the missing child. FALSE if the child lock is already
9941 acquired by this thread.
9942
9943Return Value:
9944
9945 returns whether or not the child device object has previously been reported
9946 to PNP.
9947
9948--*/
9950BOOLEAN
9951NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
9952ClassMarkChildMissing(
9955 )
9956{
9957 BOOLEAN returnValue = Child->IsEnumerated;
9958
9959 PAGED_CODE();
9960 ASSERT_PDO(Child->DeviceObject);
9961
9962 Child->IsMissing = TRUE;
9963
9964 //
9965 // Make sure this child is not in the active list.
9966 //
9967
9968 ClassRemoveChild(Child->CommonExtension.PartitionZeroExtension,
9969 Child,
9971
9972 if(Child->IsEnumerated == FALSE) {
9974 commonExtension->IsRemoved = REMOVE_PENDING;
9975 ClassRemoveDevice(Child->DeviceObject, IRP_MN_REMOVE_DEVICE);
9976 }
9977
9978 return returnValue;
9979} // end ClassMarkChildMissing()
9980
9981/*++////////////////////////////////////////////////////////////////////////////
9982
9983ClassRetrieveDeviceRelations()
9984
9985Routine Description:
9986
9987 This routine will allocate a buffer to hold the specified list of
9988 relations. It will then fill in the list with referenced device pointers
9989 and will return the request.
9990
9991Arguments:
9992
9993 Fdo - pointer to the FDO being queried
9994
9995 RelationType - what type of relations are being queried
9996
9997 DeviceRelations - a location to store a pointer to the response
9998
9999Return Value:
10000
10001 status
10002
10003--*/
10008 OUT PDEVICE_RELATIONS *DeviceRelations
10009 )
10010{
10011 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
10012
10013 ULONG count = 0;
10014 ULONG i;
10015
10017
10018 ULONG relationsSize;
10019 PDEVICE_RELATIONS deviceRelations = NULL;
10020 PDEVICE_RELATIONS oldRelations = *DeviceRelations;
10021
10023
10025
10026 PAGED_CODE();
10027
10028 ClassAcquireChildLock(fdoExtension);
10029
10030 nextChild = fdoExtension->CommonExtension.ChildList;
10031
10032 //
10033 // Count the number of PDO's attached to this disk
10034 //
10035
10036 while (nextChild != NULL) {
10037 PCOMMON_DEVICE_EXTENSION commonExtension;
10038
10039 commonExtension = &(nextChild->CommonExtension);
10040
10041 NT_ASSERTMSG("ClassPnp internal error: missing child on active list\n",
10042 (nextChild->IsMissing == FALSE));
10043
10044 nextChild = commonExtension->ChildList;
10045
10046 count++;
10047 };
10048
10049 //
10050 // If relations already exist in the QDR, adjust the current count
10051 // to include the previous list.
10052 //
10053
10054 if (oldRelations) {
10055 count += oldRelations->Count;
10056 }
10057
10058 relationsSize = (sizeof(DEVICE_RELATIONS) +
10059 (count * sizeof(PDEVICE_OBJECT)));
10060
10061 deviceRelations = ExAllocatePoolWithTag(PagedPool, relationsSize, '5BcS');
10062
10063 if (deviceRelations == NULL) {
10064
10065 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_ENUM, "ClassRetrieveDeviceRelations: unable to allocate "
10066 "%d bytes for device relations\n", relationsSize));
10067
10068 ClassReleaseChildLock(fdoExtension);
10069
10071 }
10072
10073 RtlZeroMemory(deviceRelations, relationsSize);
10074
10075 if (oldRelations) {
10076
10077 //
10078 // Copy the old relations to the new list and free the old list.
10079 //
10080
10081 for (i = 0; i < oldRelations->Count; i++) {
10082 deviceRelations->Objects[i] = oldRelations->Objects[i];
10083 }
10084
10085 FREE_POOL(oldRelations);
10086 }
10087
10088 nextChild = fdoExtension->CommonExtension.ChildList;
10089 i = count;
10090
10091 while (nextChild != NULL) {
10092 PCOMMON_DEVICE_EXTENSION commonExtension;
10093
10094 commonExtension = &(nextChild->CommonExtension);
10095
10096 NT_ASSERTMSG("ClassPnp internal error: missing child on active list\n",
10097 (nextChild->IsMissing == FALSE));
10098
10099 _Analysis_assume_(i >= 1);
10100 deviceRelations->Objects[--i] = nextChild->DeviceObject;
10101
10103 nextChild->DeviceObject,
10104 0,
10105 NULL,
10106 KernelMode);
10107 if (!NT_SUCCESS(status)) {
10108 NT_ASSERT(!"Error referencing child device by pointer");
10109 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_ENUM,
10110 "ClassRetrieveDeviceRelations: Error referencing child "
10111 "device %p by pointer\n", nextChild->DeviceObject));
10112
10113 }
10114 nextChild->IsEnumerated = TRUE;
10115 nextChild = commonExtension->ChildList;
10116 }
10117
10118 NT_ASSERTMSG("Child list has changed: ", i == 0);
10119
10120 deviceRelations->Count = count;
10121 *DeviceRelations = deviceRelations;
10122
10123 ClassReleaseChildLock(fdoExtension);
10124 return STATUS_SUCCESS;
10125} // end ClassRetrieveDeviceRelations()
10126
10127/*++////////////////////////////////////////////////////////////////////////////
10128
10129ClassGetPdoId()
10130
10131Routine Description:
10132
10133 This routine will call into the driver to retrieve a copy of one of it's
10134 id strings.
10135
10136Arguments:
10137
10138 Pdo - a pointer to the pdo being queried
10139
10140 IdType - which type of id string is being queried
10141
10142 IdString - an allocated unicode string structure which the driver
10143 can fill in.
10144
10145Return Value:
10146
10147 status
10148
10149--*/
10155 )
10156{
10157#ifdef _MSC_VER
10158#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
10159#endif
10161
10162 _Analysis_assume_(driverExtension != NULL);
10163
10164 ASSERT_PDO(Pdo);
10165 NT_ASSERT(driverExtension->InitData.ClassQueryId);
10166
10167 PAGED_CODE();
10168
10169 return driverExtension->InitData.ClassQueryId( Pdo, IdType, IdString);
10170} // end ClassGetPdoId()
10171
10172/*++////////////////////////////////////////////////////////////////////////////
10173
10174ClassQueryPnpCapabilities()
10175
10176Routine Description:
10177
10178 This routine will call into the class driver to retrieve it's pnp
10179 capabilities.
10180
10181Arguments:
10182
10183 PhysicalDeviceObject - The physical device object to retrieve properties
10184 for.
10185
10186Return Value:
10187
10188 status
10189
10190--*/
10195 )
10196{
10197 PCLASS_DRIVER_EXTENSION driverExtension =
10198 ClassGetDriverExtension(DeviceObject->DriverObject);
10199 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
10200
10201 PCLASS_QUERY_PNP_CAPABILITIES queryRoutine = NULL;
10202
10203 PAGED_CODE();
10204
10207
10208 if(commonExtension->IsFdo) {
10209 queryRoutine = driverExtension->InitData.FdoData.ClassQueryPnpCapabilities;
10210 } else {
10211 queryRoutine = driverExtension->InitData.PdoData.ClassQueryPnpCapabilities;
10212 }
10213
10214 if(queryRoutine) {
10215 return queryRoutine(DeviceObject,
10216 Capabilities);
10217 } else {
10219 }
10220} // end ClassQueryPnpCapabilities()
10221
10222/*++////////////////////////////////////////////////////////////////////////////
10223
10224ClassInvalidateBusRelations()
10225
10226Routine Description:
10227
10228 This routine re-enumerates the devices on the "bus". It will call into
10229 the driver's ClassEnumerate routine to update the device objects
10230 immediately. It will then schedule a bus re-enumeration for pnp by calling
10231 IoInvalidateDeviceRelations.
10232
10233Arguments:
10234
10235 Fdo - a pointer to the functional device object for this bus
10236
10237Return Value:
10238
10239 none
10240
10241--*/
10243VOID
10244NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
10245ClassInvalidateBusRelations(
10247 )
10248{
10249 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
10250#ifdef _MSC_VER
10251#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
10252#endif
10254
10256
10257 PAGED_CODE();
10258
10259 _Analysis_assume_(driverExtension != NULL);
10260
10261 ASSERT_FDO(Fdo);
10262 NT_ASSERT(driverExtension->InitData.ClassEnumerateDevice != NULL);
10263
10264 if(InterlockedIncrement((volatile LONG *)&(fdoExtension->EnumerationInterlock)) == 1) {
10265 status = driverExtension->InitData.ClassEnumerateDevice(Fdo);
10266 }
10267 InterlockedDecrement((volatile LONG *)&(fdoExtension->EnumerationInterlock));
10268
10269 if(!NT_SUCCESS(status)) {
10270
10271 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_ENUM, "ClassInvalidateBusRelations: EnumerateDevice routine "
10272 "returned %lx\n", status));
10273 }
10274
10276
10277 return;
10278} // end ClassInvalidateBusRelations()
10279
10280/*++////////////////////////////////////////////////////////////////////////////
10281
10282ClassRemoveDevice() ISSUE-2000/02/18-henrygab - why public?!
10283
10284Routine Description:
10285
10286 This routine is called to handle the "removal" of a device. It will
10287 forward the request downwards if necesssary, call into the driver
10288 to release any necessary resources (memory, events, etc) and then
10289 will delete the device object.
10290
10291Arguments:
10292
10293 DeviceObject - a pointer to the device object being removed
10294
10295 RemoveType - indicates what type of remove this is (regular or surprise).
10296
10297Return Value:
10298
10299 status
10300
10301--*/
10304NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
10305ClassRemoveDevice(
10308 )
10309{
10310#ifdef _MSC_VER
10311#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
10312#endif
10314 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
10315 PDEVICE_OBJECT lowerDeviceObject = commonExtension->LowerDeviceObject;
10316 BOOLEAN proceedWithRemove = TRUE;
10318 PEX_RUNDOWN_REF_CACHE_AWARE removeLockRundown = NULL;
10319
10320
10321 PAGED_CODE();
10322
10323 _Analysis_assume_(driverExtension != NULL);
10324
10325 /*
10326 * Deregister from WMI.
10327 */
10328 if (commonExtension->IsFdo ||
10329 driverExtension->InitData.PdoData.ClassWmiInfo.GuidRegInfo) {
10331 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "ClassRemoveDevice: IoWMIRegistrationControl(%p, WMI_ACTION_DEREGISTER) --> %lx", DeviceObject, status));
10332 }
10333
10334 /*
10335 * If we exposed a "shingle" (a named device interface openable by CreateFile)
10336 * then delete it now.
10337 */
10338 if (commonExtension->MountedDeviceInterfaceName.Buffer){
10342 }
10343
10344 //
10345 // If this is a surprise removal we leave the device around - which means
10346 // we don't have to (or want to) drop the remove lock and wait for pending
10347 // requests to complete.
10348 //
10349
10351
10352 //
10353 // Release the lock we acquired when the device object was created.
10354 //
10355
10357
10358 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClasspRemoveDevice - Reference count is now %d\n",
10359 commonExtension->RemoveLock));
10360
10361 //
10362 // The RemoveLockRundown allows fast protection of the device object
10363 // structure that is torn down by a single thread. While in the rundown process (the call to
10364 // ExWaitForRundownProtectionReleaseCacheAware returns), the rundown object becomes
10365 // invalid and the subsequent calls to ExAcquireRundownProtectionCacheAware will return FALSE.
10366 // ExReInitializeRundownProtectionCacheAware needs to be called to re-initialize the
10367 // RemoveLockRundown protection.
10368 //
10369
10370 removeLockRundown = (PEX_RUNDOWN_REF_CACHE_AWARE)
10371 ((PCHAR)commonExtension->PrivateCommonData +
10374
10375 KeSetEvent(&commonExtension->RemoveEvent,
10377 FALSE);
10378
10379 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClasspRemoveDevice - removing device %p\n", DeviceObject));
10380
10381 if (commonExtension->IsFdo) {
10382
10383 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClasspRemoveDevice - FDO %p has received a "
10384 "remove request.\n", DeviceObject));
10385
10386 } else {
10387 PPHYSICAL_DEVICE_EXTENSION pdoExtension = DeviceObject->DeviceExtension;
10388
10389 if (pdoExtension->IsMissing) {
10390 /*
10391 * The child partition PDO is missing, so we are going to go ahead
10392 * and delete it for the remove.
10393 */
10394 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClasspRemoveDevice - PDO %p is missing and will be removed", DeviceObject));
10395 } else {
10396 /*
10397 * We got a remove for a child partition PDO which is not actually missing.
10398 * So we will NOT actually delete it.
10399 */
10400 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "ClasspRemoveDevice - PDO %p still exists and will be removed when it disappears", DeviceObject));
10401
10403
10404 //
10405 // Reacquire the remove lock for the next time this comes around.
10406 //
10407
10409
10410 //
10411 // the device wasn't missing so it's not really been removed.
10412 //
10413
10414 commonExtension->IsRemoved = NO_REMOVE;
10415
10417 commonExtension->PartitionZeroExtension->LowerPdo,
10418 BusRelations);
10419
10420 proceedWithRemove = FALSE;
10421 }
10422 }
10423 }
10424
10425
10426 if (proceedWithRemove) {
10427
10428 /*
10429 * Call the class driver's remove handler.
10430 * All this is supposed to do is clean up its data and device interfaces.
10431 */
10432 NT_ASSERT(commonExtension->DevInfo->ClassRemoveDevice);
10436 UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
10437
10438 if (commonExtension->IsFdo) {
10439 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
10440
10441 ClasspDisableTimer(fdoExtension);
10442
10444
10446
10447 //
10448 // If this FDO is idle power managed, remove it from the
10449 // list of idle power managed FDOs.
10450 //
10451 if (fdoExtension->FunctionSupportInfo &&
10452 fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled) {
10454
10457 while ((PLIST_ENTRY)fdoEntry != &IdlePowerFDOList) {
10459 if (fdoEntry->Fdo == DeviceObject) {
10460 RemoveEntryList(&(fdoEntry->ListEntry));
10461 ExFreePool(fdoEntry);
10462 break;
10463 }
10464 fdoEntry = nextEntry;
10465 }
10467 }
10468
10469 //
10470 // Cleanup the media detection resources now that the class driver
10471 // has stopped it's timer (if any) and we can be sure they won't
10472 // call us to do detection again.
10473 //
10474
10475 ClassCleanupMediaChangeDetection(fdoExtension);
10476
10477 //
10478 // Cleanup any Failure Prediction stuff
10479 //
10480 FREE_POOL(fdoExtension->FailurePredictionInfo);
10481
10482 /*
10483 * Ordinarily all child PDOs will be removed by the time
10484 * that the parent gets the REMOVE_DEVICE.
10485 * However, if a child PDO has been created but has not
10486 * been announced in a QueryDeviceRelations, then it is
10487 * just a private data structure unknown to pnp, and we have
10488 * to delete it ourselves.
10489 */
10490 ClassAcquireChildLock(fdoExtension);
10491 child = ClassRemoveChild(fdoExtension, NULL, FALSE);
10492 while (child) {
10493 PCOMMON_DEVICE_EXTENSION childCommonExtension = child->DeviceObject->DeviceExtension;
10494
10495 //
10496 // Yank the pdo. This routine will unlink the device from the
10497 // pdo list so NextPdo will point to the next one when it's
10498 // complete.
10499 //
10500 child->IsMissing = TRUE;
10501 childCommonExtension->IsRemoved = REMOVE_PENDING;
10502 ClassRemoveDevice(child->DeviceObject, IRP_MN_REMOVE_DEVICE);
10503 child = ClassRemoveChild(fdoExtension, NULL, FALSE);
10504 }
10505 ClassReleaseChildLock(fdoExtension);
10506 }
10508 /*
10509 * This is a surprise-remove on the parent FDO.
10510 * We will mark the child PDOs as missing so that they
10511 * will actually get deleted when they get a REMOVE_DEVICE.
10512 */
10513 ClassMarkChildrenMissing(fdoExtension);
10514 }
10515
10517
10519
10520 //
10521 // Free FDO-specific data structs
10522 //
10523 if (fdoExtension->PrivateFdoData) {
10524 //
10525 // Only remove the entry if the list has been initialized, or
10526 // else we will access invalid memory.
10527 //
10528 PLIST_ENTRY allFdosListEntry = &fdoExtension->PrivateFdoData->AllFdosListEntry;
10529 if (allFdosListEntry->Flink && allFdosListEntry->Blink) {
10530 //
10531 // Remove the FDO from the static list.
10532 // Pnp is synchronized so this shouldn't need any synchronization.
10533 //
10534 RemoveEntryList(allFdosListEntry);
10535 }
10536 InitializeListHead(allFdosListEntry);
10537
10539
10540 //
10541 // Delete the tick timer now.
10542 //
10543 ClasspDeleteTimer(fdoExtension);
10544
10545
10546 FREE_POOL(fdoExtension->PrivateFdoData->PowerProcessIrp);
10547 FREE_POOL(fdoExtension->PrivateFdoData->FreeTransferPacketsLists);
10548 FREE_POOL(fdoExtension->PrivateFdoData);
10549 }
10550
10551#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
10552 FREE_POOL(fdoExtension->AdditionalFdoData);
10553#endif
10554
10555 if (commonExtension->DeviceName.Buffer) {
10556 FREE_POOL(commonExtension->DeviceName.Buffer);
10557 RtlInitUnicodeString(&commonExtension->DeviceName, NULL);
10558 }
10559
10560#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
10561 if (fdoExtension->FunctionSupportInfo != NULL) {
10562 FREE_POOL(fdoExtension->FunctionSupportInfo->HwFirmwareInfo);
10563 }
10564#endif
10565 FREE_POOL(fdoExtension->FunctionSupportInfo);
10566
10567 FREE_POOL(fdoExtension->MiniportDescriptor);
10568
10569 FREE_POOL(fdoExtension->AdapterDescriptor);
10570
10571 FREE_POOL(fdoExtension->DeviceDescriptor);
10572
10573 //
10574 // Detach our device object from the stack - there's no reason
10575 // to hold off our cleanup any longer.
10576 //
10577
10578 IoDetachDevice(lowerDeviceObject);
10579 }
10580 }
10581 else {
10582 /*
10583 * This is a child partition PDO.
10584 * We have already determined that it was previously marked
10585 * as missing. So if this is a REMOVE_DEVICE, we will actually
10586 * delete it.
10587 */
10589 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = commonExtension->PartitionZeroExtension;
10590 PPHYSICAL_DEVICE_EXTENSION pdoExtension = (PPHYSICAL_DEVICE_EXTENSION)commonExtension;
10591
10592 //
10593 // See if this device is in the child list (if this was a suprise
10594 // removal it might be) and remove it.
10595 //
10596 ClassRemoveChild(fdoExtension, pdoExtension, TRUE);
10597 }
10598 }
10599
10600 commonExtension->PartitionLength.QuadPart = 0;
10601
10603
10605
10607 }
10608 }
10609
10610 return STATUS_SUCCESS;
10611} // end ClassRemoveDevice()
10612
10613/*++////////////////////////////////////////////////////////////////////////////
10614
10615ClassGetDriverExtension()
10616
10617Routine Description:
10618
10619 This routine will return the classpnp's driver extension.
10620
10621Arguments:
10622
10623 DriverObject - the driver object for which to get classpnp's extension
10624
10625Return Value:
10626
10627 Either NULL if none, or a pointer to the driver extension
10628
10629--*/
10633NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
10634ClassGetDriverExtension(
10636 )
10637{
10638#ifdef _MSC_VER
10639#pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
10640#endif
10642} // end ClassGetDriverExtension()
10643
10644/*++////////////////////////////////////////////////////////////////////////////
10645
10646ClasspStartIo()
10647
10648Routine Description:
10649
10650 This routine wraps the class driver's start io routine. If the device
10651 is being removed it will complete any requests with
10652 STATUS_DEVICE_DOES_NOT_EXIST and fire up the next packet.
10653
10654Arguments:
10655
10656Return Value:
10657
10658 none
10659
10660--*/
10661VOID
10662NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
10665 IN PIRP Irp
10666 )
10667{
10668 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
10669
10670 //
10671 // We're already holding the remove lock so just check the variable and
10672 // see what's going on.
10673 //
10674
10675 if(commonExtension->IsRemoved) {
10676
10677 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
10678
10679#ifdef _MSC_VER
10680#pragma warning(suppress:4054) // okay to type cast function pointer to PIRP for this use case
10681#endif
10683
10686 IoStartNextPacket(DeviceObject, TRUE); // Some IO is cancellable
10687
10688#ifdef _MSC_VER
10689#pragma warning(suppress:4054) // okay to type cast function pointer to PIRP for this use case
10690#endif
10692
10693 return;
10694 }
10695
10696 commonExtension->DriverExtension->InitData.ClassStartIo(
10698 Irp);
10699
10700 return;
10701} // ClasspStartIo()
10702
10703/*++////////////////////////////////////////////////////////////////////////////
10704
10705ClassUpdateInformationInRegistry()
10706
10707Routine Description:
10708
10709 This routine has knowledge about the layout of the device map information
10710 in the registry. It will update this information to include a value
10711 entry specifying the dos device name that is assumed to get assigned
10712 to this NT device name. For more information on this assigning of the
10713 dos device name look in the drive support routine in the hal that assigns
10714 all dos names.
10715
10716 Since some versions of some device's firmware did not work and some
10717 vendors did not bother to follow the specification, the entire inquiry
10718 information must also be stored in the registry so than someone can
10719 figure out the firmware version.
10720
10721Arguments:
10722
10723 DeviceObject - A pointer to the device object for the tape device.
10724
10725Return Value:
10726
10727 None
10728
10729--*/
10731VOID
10732NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
10733ClassUpdateInformationInRegistry(
10739 )
10740{
10742 SCSI_ADDRESS scsiAddress = {0};
10743 OBJECT_ATTRIBUTES objectAttributes = {0};
10744 STRING string;
10745 UNICODE_STRING unicodeName = {0};
10746 UNICODE_STRING unicodeRegistryPath = {0};
10747 UNICODE_STRING unicodeData = {0};
10748 HANDLE targetKey;
10749 IO_STATUS_BLOCK ioStatus;
10750 UCHAR buffer[256] = {0};
10751
10752 PAGED_CODE();
10753
10755 targetKey = NULL;
10756
10757 _SEH2_TRY {
10758
10759 //
10760 // Issue GET_ADDRESS Ioctl to determine path, target, and lun information.
10761 //
10762
10765 Fdo,
10766 &scsiAddress,
10767 0,
10768 sizeof(SCSI_ADDRESS),
10769 FALSE,
10770 &ioStatus
10771 );
10772
10773 if (!NT_SUCCESS(ioStatus.Status)) {
10774
10775 status = ioStatus.Status;
10776 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
10777 "UpdateInformationInRegistry: Get Address failed %lx\n",
10778 status));
10780
10781 } else {
10782
10783 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
10784 "GetAddress: Port %x, Path %x, Target %x, Lun %x\n",
10785 scsiAddress.PortNumber,
10786 scsiAddress.PathId,
10787 scsiAddress.TargetId,
10788 scsiAddress.Lun));
10789
10790 }
10791
10793 sizeof(buffer)-1,
10794 "\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi\\Scsi Port %d\\Scsi Bus %d\\Target Id %d\\Logical Unit Id %d",
10795 scsiAddress.PortNumber,
10796 scsiAddress.PathId,
10797 scsiAddress.TargetId,
10798 scsiAddress.Lun);
10799
10800 if (!NT_SUCCESS(status)) {
10802 }
10803
10804 RtlInitString(&string, (PCSZ)buffer);
10805
10806 status = RtlAnsiStringToUnicodeString(&unicodeRegistryPath,
10807 &string,
10808 TRUE);
10809
10810 if (!NT_SUCCESS(status)) {
10812 }
10813
10814 //
10815 // Open the registry key for the scsi information for this
10816 // scsibus, target, lun.
10817 //
10818
10819 InitializeObjectAttributes(&objectAttributes,
10820 &unicodeRegistryPath,
10822 NULL,
10823 NULL);
10824
10825 status = ZwOpenKey(&targetKey,
10827 &objectAttributes);
10828
10829 if (!NT_SUCCESS(status)) {
10831 }
10832
10833 //
10834 // Now construct and attempt to create the registry value
10835 // specifying the device name in the appropriate place in the
10836 // device map.
10837 //
10838
10839 RtlInitUnicodeString(&unicodeName, L"DeviceName");
10840
10842 if (!NT_SUCCESS(status)) {
10844 }
10845
10846 RtlInitString(&string, (PCSZ)buffer);
10847 status = RtlAnsiStringToUnicodeString(&unicodeData,
10848 &string,
10849 TRUE);
10850 if (NT_SUCCESS(status)) {
10851 status = ZwSetValueKey(targetKey,
10852 &unicodeName,
10853 0,
10854 REG_SZ,
10855 unicodeData.Buffer,
10856 unicodeData.Length);
10857 }
10858
10859 //
10860 // if they sent in data, update the registry
10861 //
10862
10864
10865 NT_ASSERT(InquiryData);
10866
10867 RtlInitUnicodeString(&unicodeName, L"InquiryData");
10868 status = ZwSetValueKey(targetKey,
10869 &unicodeName,
10870 0,
10871 REG_BINARY,
10872 InquiryData,
10874 }
10875
10876 // that's all, except to clean up.
10877
10878 } _SEH2_FINALLY {
10879
10880 if (!NT_SUCCESS(status)) {
10881 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
10882 "Failure to update information in registry: %08x\n",
10883 status
10884 ));
10885 }
10886
10887 if (unicodeData.Buffer) {
10888 RtlFreeUnicodeString(&unicodeData);
10889 }
10890 if (unicodeRegistryPath.Buffer) {
10891 RtlFreeUnicodeString(&unicodeRegistryPath);
10892 }
10893 if (targetKey) {
10894 ZwClose(targetKey);
10895 }
10896
10897 } _SEH2_END;
10898
10899} // end ClassUpdateInformationInRegistry()
10900
10901/*++////////////////////////////////////////////////////////////////////////////
10902
10903ClasspSendSynchronousCompletion()
10904
10905Routine Description:
10906
10907 This completion routine will set the user event in the irp after
10908 freeing the irp and the associated MDL (if any).
10909
10910Arguments:
10911
10912 DeviceObject - the device object which requested the completion routine
10913
10914 Irp - the irp being completed
10915
10916 Context - unused
10917
10918Return Value:
10919
10920 STATUS_MORE_PROCESSING_REQUIRED
10921
10922--*/
10924NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
10927 IN PIRP Irp,
10929 )
10930{
10931 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClasspSendSynchronousCompletion: %p %p %p\n",
10933 //
10934 // First set the status and information fields in the io status block
10935 // provided by the caller.
10936 //
10937
10938 *(Irp->UserIosb) = Irp->IoStatus;
10939
10940 //
10941 // Unlock the pages for the data buffer.
10942 //
10943
10944 if(Irp->MdlAddress) {
10945 MmUnlockPages(Irp->MdlAddress);
10946 IoFreeMdl(Irp->MdlAddress);
10947 }
10948
10949 //
10950 // Signal the caller's event.
10951 //
10952
10953 KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);
10954
10955 //
10956 // Free the MDL and the IRP.
10957 //
10958
10959 IoFreeIrp(Irp);
10960
10962} // end ClasspSendSynchronousCompletion()
10963
10964/*++
10965
10966 ISSUE-2000/02/20-henrygab Not documented ClasspRegisterMountedDeviceInterface
10967
10968--*/
10969VOID
10972 )
10973{
10974
10975 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
10976 BOOLEAN isFdo = commonExtension->IsFdo;
10977 PDEVICE_OBJECT pdo;
10978 UNICODE_STRING interfaceName;
10979
10981
10982 PAGED_CODE();
10983
10984 if(isFdo) {
10985
10986 PFUNCTIONAL_DEVICE_EXTENSION functionalExtension;
10987
10988 functionalExtension =
10989 (PFUNCTIONAL_DEVICE_EXTENSION) commonExtension;
10990 pdo = functionalExtension->LowerPdo;
10991 } else {
10992 pdo = DeviceObject;
10993 }
10994
10995#ifdef _MSC_VER
10996#pragma prefast(suppress:6014, "The allocated memory that interfaceName points to will be freed in ClassRemoveDevice().")
10997#endif
10999 pdo,
11000 &MOUNTDEV_MOUNTED_DEVICE_GUID,
11001 NULL,
11002 &interfaceName
11003 );
11004
11005 if(NT_SUCCESS(status)) {
11006
11007 //
11008 // Copy the interface name before setting the interface state - the
11009 // name is needed by the components we notify.
11010 //
11011
11012 commonExtension->MountedDeviceInterfaceName = interfaceName;
11013 status = IoSetDeviceInterfaceState(&interfaceName, TRUE);
11014
11015 if(!NT_SUCCESS(status)) {
11016 RtlFreeUnicodeString(&interfaceName);
11017 }
11018 }
11019
11020 if(!NT_SUCCESS(status)) {
11022 NULL);
11023 }
11024 return;
11025} // end ClasspRegisterMountedDeviceInterface()
11026
11027/*++////////////////////////////////////////////////////////////////////////////
11028
11029ClassSendDeviceIoControlSynchronous()
11030
11031Routine Description:
11032
11033 This routine is based upon IoBuildDeviceIoControlRequest(). It has been
11034 modified to reduce code and memory by not double-buffering the io, using
11035 the same buffer for both input and output, allocating and deallocating
11036 the mdl on behalf of the caller, and waiting for the io to complete.
11037
11038 This routine also works around the rare cases in which APC's are disabled.
11039 Since IoBuildDeviceIoControl() used APC's to signal completion, this had
11040 led to a number of difficult-to-detect hangs, where the irp was completed,
11041 but the event passed to IoBuild..() was still being waited upon by the
11042 caller.
11043
11044Arguments:
11045
11046 IoControlCode - the IOCTL to send
11047
11048 TargetDeviceObject - the device object that should handle the ioctl
11049
11050 Buffer - the input and output buffer, or NULL if no input/output
11051
11052 InputBufferLength - the number of bytes prepared for the IOCTL in Buffer
11053
11054 OutputBufferLength - the number of bytes to be filled in upon success
11055
11056 InternalDeviceIoControl - if TRUE, uses IRP_MJ_INTERNAL_DEVICE_CONTROL
11057
11058 IoStatus - the status block that contains the results of the operation
11059
11060Return Value:
11061
11062--*/
11063VOID
11064NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
11073 )
11074{
11075 PIRP irp;
11077 ULONG method;
11078
11079 PAGED_CODE();
11080
11081 irp = NULL;
11082 method = IoControlCode & 3;
11083
11084 #if DBG // Begin Argument Checking (nop in fre version)
11085
11087
11088 if ((InputBufferLength != 0) || (OutputBufferLength != 0)) {
11090 }
11091 else {
11093 }
11094 #endif
11095
11096 //
11097 // Begin by allocating the IRP for this request. Do not charge quota to
11098 // the current process for this IRP.
11099 //
11100
11102 if (!irp) {
11103 IoStatus->Information = 0;
11105 return;
11106 }
11107
11108 //
11109 // Get a pointer to the stack location of the first driver which will be
11110 // invoked. This is where the function codes and the parameters are set.
11111 //
11112
11114
11115 //
11116 // Set the major function code based on the type of device I/O control
11117 // function the caller has specified.
11118 //
11119
11121 irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
11122 } else {
11123 irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
11124 }
11125
11126 //
11127 // Copy the caller's parameters to the service-specific portion of the
11128 // IRP for those parameters that are the same for all four methods.
11129 //
11130
11131 irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
11132 irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
11133 irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
11134
11135 //
11136 // Get the method bits from the I/O control code to determine how the
11137 // buffers are to be passed to the driver.
11138 //
11139
11140 switch (method)
11141 {
11142 //
11143 // case 0
11144 //
11145 case METHOD_BUFFERED:
11146 {
11147 if ((InputBufferLength != 0) || (OutputBufferLength != 0))
11148 {
11149 irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
11152 if (irp->AssociatedIrp.SystemBuffer == NULL)
11153 {
11154 IoFreeIrp(irp);
11155
11156 IoStatus->Information = 0;
11158 return;
11159 }
11160
11161 if (InputBufferLength != 0)
11162 {
11163 RtlCopyMemory(irp->AssociatedIrp.SystemBuffer, Buffer, InputBufferLength);
11164 }
11165 }
11166
11167 irp->UserBuffer = Buffer;
11168
11169 break;
11170 }
11171
11172 //
11173 // case 1, case 2
11174 //
11175 case METHOD_IN_DIRECT:
11176 case METHOD_OUT_DIRECT:
11177 {
11178 if (InputBufferLength != 0)
11179 {
11180 irp->AssociatedIrp.SystemBuffer = Buffer;
11181 }
11182
11183 if (OutputBufferLength != 0)
11184 {
11185 irp->MdlAddress = IoAllocateMdl(Buffer,
11187 FALSE,
11188 FALSE,
11189 (PIRP) NULL);
11190 if (irp->MdlAddress == NULL)
11191 {
11192 IoFreeIrp(irp);
11193
11194 IoStatus->Information = 0;
11196 return;
11197 }
11198
11199 _SEH2_TRY
11200 {
11201 MmProbeAndLockPages(irp->MdlAddress,
11202 KernelMode,
11204 }
11205#ifdef _MSC_VER
11206 #pragma warning(suppress: 6320) // We want to handle any exception that MmProbeAndLockPages might throw
11207#endif
11209 {
11210 IoFreeMdl(irp->MdlAddress);
11211 IoFreeIrp(irp);
11212
11213 IoStatus->Information = 0;
11214 IoStatus->Status = _SEH2_GetExceptionCode();
11215 _SEH2_YIELD(return);
11216 } _SEH2_END;
11217 }
11218
11219 break;
11220 }
11221
11222 //
11223 // case 3
11224 //
11225 case METHOD_NEITHER:
11226 {
11227 NT_ASSERT(!"ClassSendDeviceIoControlSynchronous does not support METHOD_NEITHER Ioctls");
11228
11229 IoFreeIrp(irp);
11230
11231 IoStatus->Information = 0;
11233 return;
11234 }
11235 }
11236
11237 irp->Tail.Overlay.Thread = PsGetCurrentThread();
11238
11239 //
11240 // send the irp synchronously
11241 //
11242
11244
11245 //
11246 // copy the iostatus block for the caller
11247 //
11248
11249 *IoStatus = irp->IoStatus;
11250
11251 //
11252 // free any allocated resources
11253 //
11254
11255 switch (method) {
11256 case METHOD_BUFFERED: {
11257
11258 NT_ASSERT(irp->UserBuffer == Buffer);
11259
11260 //
11261 // first copy the buffered result, if any
11262 // Note that there are no security implications in
11263 // not checking for success since only drivers can
11264 // call into this routine anyways...
11265 //
11266
11267 if (OutputBufferLength != 0) {
11268#ifdef _MSC_VER
11269 #pragma warning(suppress: 6386) // Buffer's size is max(InputBufferLength, OutputBufferLength)
11270#endif
11271 RtlCopyMemory(Buffer, // irp->UserBuffer
11272 irp->AssociatedIrp.SystemBuffer,
11274 );
11275 }
11276
11277 //
11278 // then free the memory allocated to buffer the io
11279 //
11280
11281 if ((InputBufferLength !=0) || (OutputBufferLength != 0)) {
11282 FREE_POOL(irp->AssociatedIrp.SystemBuffer);
11283 }
11284 break;
11285 }
11286
11287 case METHOD_IN_DIRECT:
11288 case METHOD_OUT_DIRECT: {
11289
11290 //
11291 // we alloc a mdl if there is an output buffer specified
11292 // free it here after unlocking the pages
11293 //
11294
11295 if (OutputBufferLength != 0) {
11296 NT_ASSERT(irp->MdlAddress != NULL);
11297 MmUnlockPages(irp->MdlAddress);
11298 IoFreeMdl(irp->MdlAddress);
11299 irp->MdlAddress = (PMDL) NULL;
11300 }
11301 break;
11302 }
11303
11304 case METHOD_NEITHER: {
11305 NT_ASSERT(!"Code is out of date");
11306 break;
11307 }
11308 }
11309
11310 //
11311 // we always have allocated an irp. free it here.
11312 //
11313
11314 IoFreeIrp(irp);
11315 irp = (PIRP) NULL;
11316
11317 //
11318 // return the io status block's status to the caller
11319 //
11320
11321 return;
11322} // end ClassSendDeviceIoControlSynchronous()
11323
11324/*++////////////////////////////////////////////////////////////////////////////
11325
11326ClassForwardIrpSynchronous()
11327
11328Routine Description:
11329
11330 Forwards a given irp to the next lower device object.
11331
11332Arguments:
11333
11334 CommonExtension - the common class extension
11335
11336 Irp - the request to forward down the stack
11337
11338Return Value:
11339
11340--*/
11342NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
11344 _In_ PCOMMON_DEVICE_EXTENSION CommonExtension,
11345 _In_ PIRP Irp
11346 )
11347{
11349 return ClassSendIrpSynchronous(CommonExtension->LowerDeviceObject, Irp);
11350} // end ClassForwardIrpSynchronous()
11351
11352/*++////////////////////////////////////////////////////////////////////////////
11353
11354ClassSendIrpSynchronous()
11355
11356Routine Description:
11357
11358 This routine sends the given irp to the given device object, and waits for
11359 it to complete. On debug versions, will print out a debug message and
11360 optionally assert for "lost" irps based upon classpnp's globals
11361
11362Arguments:
11363
11364 TargetDeviceObject - the device object to handle this irp
11365
11366 Irp - the request to be sent
11367
11368Return Value:
11369
11370--*/
11372NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
11375 _In_ PIRP Irp
11376 )
11377{
11378 KEVENT event;
11380
11383 NT_ASSERT(Irp != NULL);
11384 NT_ASSERT(Irp->StackCount >= TargetDeviceObject->StackSize);
11385
11386 //
11387 // ISSUE-2000/02/20-henrygab What if APCs are disabled?
11388 // May need to enter critical section before IoCallDriver()
11389 // until the event is hit?
11390 //
11391
11394 TRUE, TRUE, TRUE);
11395
11398 if (status == STATUS_PENDING) {
11399
11400 #if DBG
11402
11403 timeout.QuadPart = (LONGLONG)(-1 * 10 * 1000 * (LONGLONG)1000 *
11404 ClasspnpGlobals.SecondsToWaitForIrps);
11405
11406 do {
11408 Executive,
11409 KernelMode,
11410 FALSE,
11411 &timeout);
11412
11413
11414 if (status == STATUS_TIMEOUT) {
11415
11416 //
11417 // This DebugPrint should almost always be investigated by the
11418 // party who sent the irp and/or the current owner of the irp.
11419 // Synchronous Irps should not take this long (currently 30
11420 // seconds) without good reason. This points to a potentially
11421 // serious problem in the underlying device stack.
11422 //
11423
11424 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassSendIrpSynchronous: (%p) irp %p did not "
11425 "complete within %x seconds\n",
11427 ClasspnpGlobals.SecondsToWaitForIrps
11428 ));
11429
11430 if (ClasspnpGlobals.BreakOnLostIrps != 0) {
11431 NT_ASSERT(!" - Irp failed to complete within 30 seconds - ");
11432 }
11433 }
11434
11435
11436 } while (status==STATUS_TIMEOUT);
11437 #else
11439 Executive,
11440 KernelMode,
11441 FALSE,
11442 NULL);
11443 #endif
11444
11445 status = Irp->IoStatus.Status;
11446 }
11447
11448 return status;
11449} // end ClassSendIrpSynchronous()
11450
11451/*++////////////////////////////////////////////////////////////////////////////
11452
11453ClassGetVpb()
11454
11455Routine Description:
11456
11457 This routine returns the current VPB (Volume Parameter Block) for the
11458 given device object.
11459 The Vpb field is only visible in the ntddk.h (not the wdm.h) definition
11460 of DEVICE_OBJECT; hence this exported function.
11461
11462Arguments:
11463
11464 DeviceObject - the device to get the VPB for
11465
11466Return Value:
11467
11468 the VPB, or NULL if none.
11469
11470--*/
11471PVPB
11472NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
11475 )
11476{
11477#ifdef _MSC_VER
11478#pragma prefast(suppress:28175)
11479#endif
11480 return DeviceObject->Vpb;
11481} // end ClassGetVpb()
11482
11483/*++
11484
11485 ISSUE-2000/02/20-henrygab Not documented ClasspAllocateReleaseRequest
11486
11487--*/
11491 )
11492{
11493 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
11494
11495 PAGED_CODE();
11496
11498
11499 fdoExtension->ReleaseQueueNeeded = FALSE;
11500 fdoExtension->ReleaseQueueInProgress = FALSE;
11501 fdoExtension->ReleaseQueueIrpFromPool = FALSE;
11502
11503 //
11504 // The class driver is responsible for allocating a properly sized irp,
11505 // or ClassReleaseQueue will attempt to do it on the first error.
11506 //
11507
11508 fdoExtension->ReleaseQueueIrp = NULL;
11509
11510 //
11511 // Write length to SRB.
11512 //
11513
11514 fdoExtension->ReleaseQueueSrb.Length = sizeof(SCSI_REQUEST_BLOCK);
11515
11516 return STATUS_SUCCESS;
11517} // end ClasspAllocateReleaseRequest()
11518
11519/*++
11520
11521 ISSUE-2000/02/20-henrygab Not documented ClasspFreeReleaseRequest
11522
11523--*/
11524VOID
11527 )
11528{
11529 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
11530
11531 PAGED_CODE();
11532
11533 //KIRQL oldIrql;
11534
11535 NT_ASSERT(fdoExtension->CommonExtension.IsRemoved != NO_REMOVE);
11536
11537 //
11538 // free anything the driver allocated
11539 //
11540
11541 if (fdoExtension->ReleaseQueueIrp) {
11542 if (fdoExtension->ReleaseQueueIrpFromPool) {
11543 FREE_POOL(fdoExtension->ReleaseQueueIrp);
11544 } else {
11545 IoFreeIrp(fdoExtension->ReleaseQueueIrp);
11546 }
11547 fdoExtension->ReleaseQueueIrp = NULL;
11548 }
11549
11550 //
11551 // free anything that we allocated
11552 //
11553
11554 if ((fdoExtension->PrivateFdoData) &&
11555 (fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated)) {
11556
11557 FREE_POOL(fdoExtension->PrivateFdoData->ReleaseQueueIrp);
11558 fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated = FALSE;
11559 }
11560
11561 return;
11562} // end ClasspFreeReleaseRequest()
11563
11564/*++////////////////////////////////////////////////////////////////////////////
11565
11566ClassReleaseQueue()
11567
11568Routine Description:
11569
11570 This routine issues an internal device control command
11571 to the port driver to release a frozen queue. The call
11572 is issued asynchronously as ClassReleaseQueue will be invoked
11573 from the IO completion DPC (and will have no context to
11574 wait for a synchronous call to complete).
11575
11576 This routine must be called with the remove lock held.
11577
11578Arguments:
11579
11580 Fdo - The functional device object for the device with the frozen queue.
11581
11582Return Value:
11583
11584 None.
11585
11586--*/
11587VOID
11588NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
11591 )
11592{
11594 return;
11595} // end ClassReleaseQueue()
11596
11597/*++////////////////////////////////////////////////////////////////////////////
11598
11599ClasspAllocateReleaseQueueIrp()
11600
11601Routine Description:
11602
11603 This routine allocates the release queue irp held in classpnp's private
11604 extension. This was added to allow no-memory conditions to be more
11605 survivable.
11606
11607Return Value:
11608
11609 NT_SUCCESS value.
11610
11611Notes:
11612
11613 Does not grab the spinlock. Should only be called from StartDevice()
11614 routine. May be called elsewhere for poorly-behaved drivers that cause
11615 the queue to lockup before the device is started. This should *never*
11616 occur, since it's illegal to send a request to a non-started PDO. This
11617 condition is checked for in ClasspReleaseQueue().
11618
11619--*/
11623 )
11624{
11625 UCHAR lowerStackSize;
11626
11627 //
11628 // do an initial check w/o the spinlock
11629 //
11630
11631 if (FdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated) {
11632 return STATUS_SUCCESS;
11633 }
11634
11635
11636 lowerStackSize = FdoExtension->CommonExtension.LowerDeviceObject->StackSize;
11637
11638 //
11639 // don't allocate one if one is in progress! this means whoever called
11640 // this routine didn't check if one was in progress.
11641 //
11642
11643 NT_ASSERT(!(FdoExtension->ReleaseQueueInProgress));
11644
11645 FdoExtension->PrivateFdoData->ReleaseQueueIrp =
11646 ExAllocatePoolWithTag(NonPagedPoolNx,
11647 IoSizeOfIrp(lowerStackSize),
11649 );
11650
11651 if (FdoExtension->PrivateFdoData->ReleaseQueueIrp == NULL) {
11652 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "ClassPnpStartDevice: Cannot allocate for "
11653 "release queue irp\n"));
11655 }
11656 IoInitializeIrp(FdoExtension->PrivateFdoData->ReleaseQueueIrp,
11657 IoSizeOfIrp(lowerStackSize),
11658 lowerStackSize);
11659 FdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated = TRUE;
11660
11661 return STATUS_SUCCESS;
11662}
11663
11664/*++////////////////////////////////////////////////////////////////////////////
11665
11666ClasspAllocatePowerProcessIrp()
11667
11668Routine Description:
11669
11670 This routine allocates the power process irp.
11671 This routine should be called after PrivateFdoData is allocated.
11672
11673Return Value:
11674
11675 NTSTATUS value.
11676
11677Notes:
11678
11679 Should only be called from StartDevice()
11680
11681--*/
11685 )
11686{
11687 UCHAR stackSize;
11688
11689 NT_ASSERT(FdoExtension->PrivateFdoData != NULL);
11690
11691 stackSize = FdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1;
11692
11693 FdoExtension->PrivateFdoData->PowerProcessIrp = ExAllocatePoolWithTag(NonPagedPoolNx,
11694 IoSizeOfIrp(stackSize),
11696 );
11697
11698 if (FdoExtension->PrivateFdoData->PowerProcessIrp == NULL) {
11699
11701 } else {
11702
11703 IoInitializeIrp(FdoExtension->PrivateFdoData->PowerProcessIrp,
11704 IoSizeOfIrp(stackSize),
11705 stackSize);
11706
11707 return STATUS_SUCCESS;
11708 }
11709}
11710
11711
11712/*++////////////////////////////////////////////////////////////////////////////
11713
11714ClasspReleaseQueue()
11715
11716Routine Description:
11717
11718 This routine issues an internal device control command
11719 to the port driver to release a frozen queue. The call
11720 is issued asynchronously as ClassReleaseQueue will be invoked
11721 from the IO completion DPC (and will have no context to
11722 wait for a synchronous call to complete).
11723
11724 This routine must be called with the remove lock held.
11725
11726Arguments:
11727
11728 Fdo - The functional device object for the device with the frozen queue.
11729
11730 ReleaseQueueIrp - If this irp is supplied then the test to determine whether
11731 a release queue request is in progress will be ignored.
11732 The irp provided must be the IRP originally allocated
11733 for release queue requests (so this parameter can only
11734 really be provided by the release queue completion
11735 routine.)
11736
11737Return Value:
11738
11739 None.
11740
11741--*/
11742VOID
11745 IN PIRP ReleaseQueueIrp OPTIONAL
11746 )
11747{
11748 PIO_STACK_LOCATION irpStack;
11749 PIRP irp;
11750 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
11751 PDEVICE_OBJECT lowerDevice;
11753 KIRQL currentIrql;
11754 ULONG function;
11755
11756 lowerDevice = fdoExtension->CommonExtension.LowerDeviceObject;
11757
11758 //
11759 // we raise irql seperately so we're not swapped out or suspended
11760 // while holding the release queue irp in this routine. this lets
11761 // us release the spin lock before lowering irql.
11762 //
11763
11764 KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
11765
11767
11768 //
11769 // make sure that if they passed us an irp, it matches our allocated irp.
11770 //
11771
11772 NT_ASSERT((ReleaseQueueIrp == NULL) ||
11773 (ReleaseQueueIrp == fdoExtension->PrivateFdoData->ReleaseQueueIrp));
11774
11775 //
11776 // ASSERT that we've already allocated this. (should not occur)
11777 // try to allocate it anyways, then finally bugcheck if
11778 // there's still no memory...
11779 //
11780
11781 NT_ASSERT(fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated);
11782 if (!fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated) {
11783 ClasspAllocateReleaseQueueIrp(fdoExtension);
11784 }
11785 if (!fdoExtension->PrivateFdoData->ReleaseQueueIrpAllocated) {
11786 KeBugCheckEx(SCSI_DISK_DRIVER_INTERNAL, 0x12, (ULONG_PTR)Fdo, 0x0, 0x0);
11787 }
11788
11789 if ((fdoExtension->ReleaseQueueInProgress) && (ReleaseQueueIrp == NULL)) {
11790
11791 //
11792 // Someone is already using the irp - just set the flag to indicate that
11793 // we need to release the queue again.
11794 //
11795
11796 fdoExtension->ReleaseQueueNeeded = TRUE;
11798 KeLowerIrql(currentIrql);
11799 return;
11800
11801 }
11802
11803 //
11804 // Mark that there is a release queue in progress and drop the spinlock.
11805 //
11806
11807 fdoExtension->ReleaseQueueInProgress = TRUE;
11808 if (ReleaseQueueIrp) {
11809 irp = ReleaseQueueIrp;
11810 } else {
11811 irp = fdoExtension->PrivateFdoData->ReleaseQueueIrp;
11812 }
11813
11814 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
11815 srb = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->PrivateFdoData->ReleaseQueueSrb.SrbEx);
11816 } else {
11817 srb = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->ReleaseQueueSrb);
11818 }
11819
11821
11822 NT_ASSERT(irp != NULL);
11823
11824 irpStack = IoGetNextIrpStackLocation(irp);
11825
11826 irpStack->MajorFunction = IRP_MJ_SCSI;
11827
11829
11830 //
11831 // Store the SRB address in next stack for port driver.
11832 //
11833
11834 irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srb;
11835
11836 //
11837 // If this device is removable then flush the queue. This will also
11838 // release it.
11839 //
11840
11841 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)){
11842 function = SRB_FUNCTION_FLUSH_QUEUE;
11843 }
11844 else {
11845 function = SRB_FUNCTION_RELEASE_QUEUE;
11846 }
11847
11848 if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
11849 ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction = function;
11850 } else {
11851 srb->Function = (UCHAR)function;
11852 }
11853
11855
11858 Fdo,
11859 TRUE,
11860 TRUE,
11861 TRUE);
11862
11863 IoCallDriver(lowerDevice, irp);
11864
11865 KeLowerIrql(currentIrql);
11866
11867 return;
11868
11869} // end ClassReleaseQueue()
11870
11871/*++////////////////////////////////////////////////////////////////////////////
11872
11873ClassReleaseQueueCompletion()
11874
11875Routine Description:
11876
11877 This routine is called when an asynchronous I/O request
11878 which was issused by the class driver completes. Examples of such requests
11879 are release queue or START UNIT. This routine releases the queue if
11880 necessary. It then frees the context and the IRP.
11881
11882Arguments:
11883
11884 DeviceObject - The device object for the logical unit; however since this
11885 is the top stack location the value is NULL.
11886
11887 Irp - Supplies a pointer to the Irp to be processed.
11888
11889 Context - Supplies the context to be used to process this request.
11890
11891Return Value:
11892
11893 None.
11894
11895--*/
11897NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
11900 PIRP Irp,
11902 )
11903{
11904 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
11905 KIRQL oldIrql;
11906
11907 BOOLEAN releaseQueueNeeded;
11908
11909 if (Context == NULL) {
11912 }
11913
11915
11916 fdoExtension = DeviceObject->DeviceExtension;
11917
11919
11920 //
11921 // Grab the spinlock and clear the release queue in progress flag so others
11922 // can run. Save (and clear) the state of the release queue needed flag
11923 // so that we can issue a new release queue outside the spinlock.
11924 //
11925
11926 KeAcquireSpinLock(&(fdoExtension->ReleaseQueueSpinLock), &oldIrql);
11927
11928 releaseQueueNeeded = fdoExtension->ReleaseQueueNeeded;
11929
11930 fdoExtension->ReleaseQueueNeeded = FALSE;
11931 fdoExtension->ReleaseQueueInProgress = FALSE;
11932
11933 KeReleaseSpinLock(&(fdoExtension->ReleaseQueueSpinLock), oldIrql);
11934
11935 //
11936 // If we need a release queue then issue one now. Another processor may
11937 // have already started one in which case we'll try to issue this one after
11938 // it is done - but we should never recurse more than one deep.
11939 //
11940
11941 if(releaseQueueNeeded) {
11943 }
11944
11945 //
11946 // Indicate the I/O system should stop processing the Irp completion.
11947 //
11948
11950
11951} // ClassAsynchronousCompletion()
11952
11953
11954/*++////////////////////////////////////////////////////////////////////////////
11955
11956ClassAcquireChildLock()
11957
11958Routine Description:
11959
11960 This routine acquires the lock protecting children PDOs. It may be
11961 acquired recursively by the same thread, but must be release by the
11962 thread once for each acquisition.
11963
11964Arguments:
11965
11966 FdoExtension - the device whose child list is protected.
11967
11968Return Value:
11969
11970 None
11971
11972--*/
11974VOID
11975NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
11976ClassAcquireChildLock(
11978 )
11979{
11980 PAGED_CODE();
11981
11982 if(FdoExtension->ChildLockOwner != KeGetCurrentThread()) {
11985 FALSE, NULL);
11986
11987 NT_ASSERT(FdoExtension->ChildLockOwner == NULL);
11988 NT_ASSERT(FdoExtension->ChildLockAcquisitionCount == 0);
11989
11990 FdoExtension->ChildLockOwner = KeGetCurrentThread();
11991 } else {
11992 NT_ASSERT(FdoExtension->ChildLockAcquisitionCount != 0);
11993 }
11994
11995 FdoExtension->ChildLockAcquisitionCount++;
11996 return;
11997}
11998
11999/*++////////////////////////////////////////////////////////////////////////////
12000
12001ClassReleaseChildLock() ISSUE-2000/02/18-henrygab - not documented
12002
12003Routine Description:
12004
12005 This routine releases the lock protecting children PDOs. It must be
12006 called once for each time ClassAcquireChildLock was called.
12007
12008Arguments:
12009
12010 FdoExtension - the device whose child list is protected
12011
12012Return Value:
12013
12014 None.
12015
12016--*/
12017VOID
12018NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
12021 )
12022{
12023 NT_ASSERT(FdoExtension->ChildLockOwner == KeGetCurrentThread());
12024 NT_ASSERT(FdoExtension->ChildLockAcquisitionCount != 0);
12025
12026 FdoExtension->ChildLockAcquisitionCount -= 1;
12027
12028 if(FdoExtension->ChildLockAcquisitionCount == 0) {
12029 FdoExtension->ChildLockOwner = NULL;
12031 }
12032
12033 return;
12034} // end ClassReleaseChildLock(
12035
12036/*++////////////////////////////////////////////////////////////////////////////
12037
12038ClassAddChild()
12039
12040Routine Description:
12041
12042 This routine will insert a new child into the head of the child list.
12043
12044Arguments:
12045
12046 Parent - the child's parent (contains the head of the list)
12047 Child - the child to be inserted.
12048 AcquireLock - whether the child lock should be acquired (TRUE) or whether
12049 it's already been acquired by or on behalf of the caller
12050 (FALSE).
12051
12052Return Value:
12053
12054 None.
12055
12056--*/
12057VOID
12062 )
12063{
12064 if(AcquireLock) {
12065 ClassAcquireChildLock(Parent);
12066 }
12067
12068 #if DBG
12069 //
12070 // Make sure this child's not already in the list.
12071 //
12072 {
12074
12075 for (testChild = Parent->CommonExtension.ChildList;
12076 testChild != NULL;
12077 testChild = testChild->CommonExtension.ChildList) {
12078
12079 NT_ASSERT(testChild != Child);
12080 }
12081 }
12082 #endif
12083
12084 Child->CommonExtension.ChildList = Parent->CommonExtension.ChildList;
12085 Parent->CommonExtension.ChildList = Child;
12086
12087 if(AcquireLock) {
12089 }
12090 return;
12091} // end ClassAddChild()
12092
12093/*++////////////////////////////////////////////////////////////////////////////
12094
12095ClassRemoveChild()
12096
12097Routine Description:
12098
12099 This routine will remove a child from the child list.
12100
12101Arguments:
12102
12103 Parent - the parent to be removed from.
12104
12105 Child - the child to be removed or NULL if the first child should be
12106 removed.
12107
12108 AcquireLock - whether the child lock should be acquired (TRUE) or whether
12109 it's already been acquired by or on behalf of the caller
12110 (FALSE).
12111
12112Return Value:
12113
12114 A pointer to the child which was removed or NULL if no such child could
12115 be found in the list (or if Child was NULL but the list is empty).
12116
12117--*/
12123 )
12124{
12125 if(AcquireLock) {
12126 ClassAcquireChildLock(Parent);
12127 }
12128
12129 TRY {
12130 PCOMMON_DEVICE_EXTENSION previousChild = &Parent->CommonExtension;
12131
12132 //
12133 // If the list is empty then bail out now.
12134 //
12135
12136 if(Parent->CommonExtension.ChildList == NULL) {
12137 Child = NULL;
12138 LEAVE;
12139 }
12140
12141 //
12142 // If the caller specified a child then find the child object before
12143 // it. If none was specified then the FDO is the child object before
12144 // the one we want to remove.
12145 //
12146
12147 if(Child != NULL) {
12148
12149 //
12150 // Scan through the child list to find the entry which points to
12151 // this one.
12152 //
12153
12154 do {
12155 NT_ASSERT(previousChild != &Child->CommonExtension);
12156
12157 if(previousChild->ChildList == Child) {
12158 break;
12159 }
12160
12161 previousChild = &previousChild->ChildList->CommonExtension;
12162 } while(previousChild != NULL);
12163
12164 if(previousChild == NULL) {
12165 Child = NULL;
12166 LEAVE;
12167 }
12168 }
12169
12170 //
12171 // Save the next child away then unlink it from the list.
12172 //
12173
12174 Child = previousChild->ChildList;
12175 previousChild->ChildList = Child->CommonExtension.ChildList;
12176 Child->CommonExtension.ChildList = NULL;
12177
12178 } FINALLY {
12179 if(AcquireLock) {
12181 }
12182 }
12183 return Child;
12184} // end ClassRemoveChild()
12185
12186
12187/*++
12188
12189 ISSUE-2000/02/20-henrygab Not documented ClasspRetryRequestDpc
12190
12191--*/
12192VOID
12193NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
12195 IN PKDPC Dpc,
12197 IN PVOID Arg1,
12198 IN PVOID Arg2
12199 )
12200{
12201 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
12202 PCOMMON_DEVICE_EXTENSION commonExtension;
12204 PCLASS_RETRY_INFO retryList;
12205 KIRQL irql;
12207
12211
12212 if (DeferredContext == NULL) {
12214 return;
12215 }
12216
12217 commonExtension = DeviceObject->DeviceExtension;
12218 NT_ASSERT(commonExtension->IsFdo);
12219 fdoExtension = DeviceObject->DeviceExtension;
12220 fdoData = fdoExtension->PrivateFdoData;
12221
12222
12223 KeAcquireSpinLock(&fdoData->Retry.Lock, &irql);
12224 {
12227
12228 //
12229 // if CurrentTick is less than now
12230 // fire another DPC
12231 // else
12232 // retry entire list
12233 // endif
12234 //
12235
12236 if (now.QuadPart < fdoData->Retry.Tick.QuadPart) {
12237
12238 ClasspRetryDpcTimer(fdoData);
12239 retryList = NULL;
12240
12241 } else {
12242
12243 retryList = fdoData->Retry.ListHead;
12244 fdoData->Retry.ListHead = NULL;
12245 fdoData->Retry.Delta.QuadPart = (LONGLONG)0;
12246 fdoData->Retry.Tick.QuadPart = (LONGLONG)0;
12247
12248 }
12249 }
12250 KeReleaseSpinLock(&fdoData->Retry.Lock, irql);
12251
12252 while (retryList != NULL) {
12253
12254 PIRP irp;
12255
12256
12257 irp = CONTAINING_RECORD(retryList, IRP, Tail.Overlay.DriverContext[0]);
12258 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassRetry: -- %p\n", irp));
12259 retryList = retryList->Next;
12260 #if DBG
12261 irp->Tail.Overlay.DriverContext[0] = ULongToPtr(0xdddddddd); // invalidate data
12262 irp->Tail.Overlay.DriverContext[1] = ULongToPtr(0xdddddddd); // invalidate data
12263 irp->Tail.Overlay.DriverContext[2] = ULongToPtr(0xdddddddd); // invalidate data
12264 irp->Tail.Overlay.DriverContext[3] = ULongToPtr(0xdddddddd); // invalidate data
12265 #endif
12266
12267
12268 if (NO_REMOVE == InterlockedCompareExchange((volatile LONG *)&commonExtension->IsRemoved, REMOVE_PENDING, REMOVE_PENDING)) {
12269
12270 IoCallDriver(commonExtension->LowerDeviceObject, irp);
12271
12272 } else {
12273
12274 PIO_STACK_LOCATION irpStack;
12275
12276 //
12277 // Ensure that we don't skip a completion routine (equivalent of sending down a request
12278 // to a device after it has received a remove and it completes the request. We need to
12279 // mimic that behavior here).
12280 //
12282
12284
12285 if (irpStack->MajorFunction == IRP_MJ_SCSI) {
12286
12287 PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
12288
12289 if (srb) {
12291 }
12292 }
12293
12294 //
12295 // Ensure that no retries will take place. This takes care of requests that are either
12296 // not IRP_MJ_SCSI or for ones where the SRB was passed in to the completion routine
12297 // as a context as opposed to an argument on the IRP stack location.
12298 //
12299 irpStack->Parameters.Others.Argument4 = (PVOID)0;
12300
12301 irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
12302 irp->IoStatus.Information = 0;
12304 }
12305
12306 }
12307 return;
12308
12309} // end ClasspRetryRequestDpc()
12310
12311/*++
12312
12313 ISSUE-2000/02/20-henrygab Not documented ClassRetryRequest
12314
12315--*/
12316VOID
12318 IN PDEVICE_OBJECT SelfDeviceObject,
12319 IN PIRP Irp,
12320 _In_ _In_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) // 100 seconds; already an assert on this...
12321 IN LONGLONG TimeDelta100ns // in 100ns units
12322 )
12323{
12324 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
12326 PCLASS_RETRY_INFO retryInfo;
12327 LARGE_INTEGER delta;
12328 KIRQL irql;
12329
12330 //
12331 // this checks we aren't destroying irps
12332 //
12333 NT_ASSERT(sizeof(CLASS_RETRY_INFO) <= (4*sizeof(PVOID)));
12334
12335 fdoExtension = SelfDeviceObject->DeviceExtension;
12336
12337 if (!fdoExtension->CommonExtension.IsFdo) {
12338
12339 //
12340 // this debug print/assertion should ALWAYS be investigated.
12341 // ClassRetryRequest can currently only be used by FDO's
12342 //
12343
12344 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "ClassRetryRequestEx: LOST IRP %p\n", Irp));
12345 NT_ASSERT(!"ClassRetryRequestEx Called From PDO? LOST IRP");
12346 return;
12347
12348 }
12349
12350 fdoData = fdoExtension->PrivateFdoData;
12351
12352 if (TimeDelta100ns < 0) {
12353 NT_ASSERT(!"ClassRetryRequest - must use positive delay");
12354 TimeDelta100ns *= -1;
12355 }
12356
12357 /*
12358 * We are going to queue the irp and send it down in a timer DPC.
12359 * This means that we may be causing the irp to complete on a different thread than the issuing thread.
12360 * So mark the irp pending.
12361 */
12363
12364 //
12365 // prepare what we can out of the loop
12366 //
12367
12368 retryInfo = (PCLASS_RETRY_INFO)(&Irp->Tail.Overlay.DriverContext[0]);
12369 RtlZeroMemory(retryInfo, sizeof(CLASS_RETRY_INFO));
12370
12371 delta.QuadPart = (TimeDelta100ns / fdoData->Retry.Granularity);
12372 if (TimeDelta100ns % fdoData->Retry.Granularity) {
12373 delta.QuadPart ++; // round up to next tick
12374 }
12375 if (delta.QuadPart == (LONGLONG)0) {
12377 }
12378
12379 //
12380 // now determine if we should fire another DPC or not
12381 //
12382
12383 KeAcquireSpinLock(&fdoData->Retry.Lock, &irql);
12384
12385 //
12386 // always add request to the list
12387 //
12388
12389 retryInfo->Next = fdoData->Retry.ListHead;
12390 fdoData->Retry.ListHead = retryInfo;
12391
12392 if (fdoData->Retry.Delta.QuadPart == (LONGLONG)0) {
12393
12394 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassRetry: +++ %p\n", Irp));
12395
12396 //
12397 // must be exactly one item on list
12398 //
12399
12400 NT_ASSERT(fdoData->Retry.ListHead != NULL);
12401 NT_ASSERT(fdoData->Retry.ListHead->Next == NULL);
12402
12403 //
12404 // if currentDelta is zero, always fire a DPC
12405 //
12406
12407 KeQueryTickCount(&fdoData->Retry.Tick);
12408 fdoData->Retry.Tick.QuadPart += delta.QuadPart;
12409 fdoData->Retry.Delta.QuadPart = delta.QuadPart;
12410 ClasspRetryDpcTimer(fdoData);
12411
12412 } else if (delta.QuadPart > fdoData->Retry.Delta.QuadPart) {
12413
12414 //
12415 // if delta is greater than the list's current delta,
12416 // increase the DPC handling time by difference
12417 // and update the delta to new larger value
12418 // allow the DPC to re-fire itself if needed
12419 //
12420
12421 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassRetry: ++ %p\n", Irp));
12422
12423 //
12424 // must be at least two items on list
12425 //
12426
12427 NT_ASSERT(fdoData->Retry.ListHead != NULL);
12428 NT_ASSERT(fdoData->Retry.ListHead->Next != NULL);
12429
12430 fdoData->Retry.Tick.QuadPart -= fdoData->Retry.Delta.QuadPart;
12431 fdoData->Retry.Tick.QuadPart += delta.QuadPart;
12432
12433 fdoData->Retry.Delta.QuadPart = delta.QuadPart;
12434
12435 } else {
12436
12437 //
12438 // just inserting it on the list was enough
12439 //
12440
12441 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "ClassRetry: ++ %p\n", Irp));
12442
12443 }
12444
12445
12446 KeReleaseSpinLock(&fdoData->Retry.Lock, irql);
12447
12448
12449} // end ClassRetryRequest()
12450
12451/*++
12452
12453 ISSUE-2000/02/20-henrygab Not documented ClasspRetryDpcTimer
12454
12455--*/
12456VOID
12459 )
12460{
12461 LARGE_INTEGER fire;
12462
12463 NT_ASSERT(FdoData->Retry.Tick.QuadPart != (LONGLONG)0);
12464 NT_ASSERT(FdoData->Retry.ListHead != NULL); // never fire an empty list
12465
12466 //
12467 // fire == (CurrentTick - now) * (100ns per tick)
12468 //
12469 // NOTE: Overflow is nearly impossible and is ignored here
12470 //
12471
12472 KeQueryTickCount(&fire);
12473 fire.QuadPart = FdoData->Retry.Tick.QuadPart - fire.QuadPart;
12474 fire.QuadPart *= FdoData->Retry.Granularity;
12475
12476 //
12477 // fire is now multiples of 100ns until should fire the timer.
12478 // if timer should already have expired, or would fire too quickly,
12479 // fire it in some arbitrary number of ticks to prevent infinitely
12480 // recursing.
12481 //
12482
12483 if (fire.QuadPart < MINIMUM_RETRY_UNITS) {
12485 }
12486
12487 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
12488 "ClassRetry: ======= %I64x ticks\n",
12489 fire.QuadPart));
12490
12491 //
12492 // must use negative to specify relative time to fire
12493 //
12494
12495 fire.QuadPart = fire.QuadPart * ((LONGLONG)-1);
12496
12497 //
12498 // set the timer, since this is the first addition
12499 //
12500
12501 KeSetTimerEx(&FdoData->Retry.Timer, fire, 0, &FdoData->Retry.Dpc);
12502
12503 return;
12504} // end ClasspRetryDpcTimer()
12505
12509 )
12510{
12511 PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
12512 DEVICE_REMOVAL_POLICY deviceRemovalPolicy = 0;
12514 ULONG resultLength = 0;
12515 ULONG writeCacheOverride;
12516
12517 PAGED_CODE();
12518
12519 //
12520 // start with some default settings
12521 //
12522 RtlZeroMemory(&(fdoData->HotplugInfo), sizeof(STORAGE_HOTPLUG_INFO));
12523
12524 //
12525 // set the size (aka version)
12526 //
12527
12528 fdoData->HotplugInfo.Size = sizeof(STORAGE_HOTPLUG_INFO);
12529
12530 //
12531 // set if the device has removable media
12532 //
12533
12534 if (FdoExtension->DeviceDescriptor->RemovableMedia) {
12535 fdoData->HotplugInfo.MediaRemovable = TRUE;
12536 } else {
12537 fdoData->HotplugInfo.MediaRemovable = FALSE;
12538 }
12539
12540 //
12541 // this refers to devices which, for reasons not yet understood,
12542 // do not fail PREVENT_MEDIA_REMOVAL requests even though they
12543 // have no way to lock the media into the drive. this allows
12544 // the filesystems to turn off delayed-write caching for these
12545 // devices as well.
12546 //
12547
12548 if (TEST_FLAG(FdoExtension->PrivateFdoData->HackFlags,
12550 fdoData->HotplugInfo.MediaHotplug = TRUE;
12551 } else {
12552 fdoData->HotplugInfo.MediaHotplug = FALSE;
12553 }
12554
12555 //
12556 // Query the default removal policy from the kernel
12557 //
12558
12561 sizeof(DEVICE_REMOVAL_POLICY),
12562 (PVOID)&deviceRemovalPolicy,
12563 &resultLength);
12564 if (!NT_SUCCESS(status)) {
12565 return status;
12566 }
12567
12568 if (resultLength != sizeof(DEVICE_REMOVAL_POLICY)) {
12569 return STATUS_UNSUCCESSFUL;
12570 }
12571
12572 //
12573 // Look into the registry to see if the user has chosen
12574 // to override the default setting for the removal policy.
12575 // User can override only if the default removal policy is
12576 // orderly or suprise removal.
12577
12578 if ((deviceRemovalPolicy == RemovalPolicyExpectOrderlyRemoval) ||
12579 (deviceRemovalPolicy == RemovalPolicyExpectSurpriseRemoval)) {
12580
12581 DEVICE_REMOVAL_POLICY userRemovalPolicy = 0;
12582
12583 ClassGetDeviceParameter(FdoExtension,
12586 (PULONG)&userRemovalPolicy);
12587
12588 //
12589 // Validate the override value and use it only if it is an
12590 // allowed value.
12591 //
12592 if ((userRemovalPolicy == RemovalPolicyExpectOrderlyRemoval) ||
12593 (userRemovalPolicy == RemovalPolicyExpectSurpriseRemoval)) {
12594 deviceRemovalPolicy = userRemovalPolicy;
12595 }
12596 }
12597
12598 //
12599 // use this info to set the DeviceHotplug setting
12600 // don't rely on DeviceCapabilities, since it can't properly
12601 // determine device relations, etc. let the kernel figure this
12602 // stuff out instead.
12603 //
12604
12605 if (deviceRemovalPolicy == RemovalPolicyExpectSurpriseRemoval) {
12606 fdoData->HotplugInfo.DeviceHotplug = TRUE;
12607 } else {
12608 fdoData->HotplugInfo.DeviceHotplug = FALSE;
12609 }
12610
12611 //
12612 // this refers to the *filesystem* caching, but has to be included
12613 // here since it's a per-device setting. this may change to be
12614 // stored by the system in the future.
12615 //
12616
12617 writeCacheOverride = FALSE;
12618 ClassGetDeviceParameter(FdoExtension,
12621 &writeCacheOverride);
12622
12623 if (writeCacheOverride) {
12625 } else {
12627 }
12628
12629 return STATUS_SUCCESS;
12630}
12631
12632VOID
12633NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
12637 )
12638{
12639 PAGED_CODE();
12640
12641 //
12642 // remove invalid flags and save
12643 //
12644
12646 SET_FLAG(FdoExtension->PrivateFdoData->HackFlags, Data);
12647 return;
12648}
12649
12650VOID
12653 )
12654{
12655 HANDLE deviceParameterHandle; // device instance key
12656 HANDLE classParameterHandle; // classpnp subkey
12657 OBJECT_ATTRIBUTES objectAttributes = {0};
12658 UNICODE_STRING subkeyName;
12660
12661 //
12662 // seeded in the ENUM tree by ClassInstaller
12663 //
12664 ULONG deviceHacks;
12665 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0}; // null terminated array
12666
12667 PAGED_CODE();
12668
12669 deviceParameterHandle = NULL;
12670 classParameterHandle = NULL;
12671 deviceHacks = 0;
12672
12675 KEY_WRITE,
12676 &deviceParameterHandle
12677 );
12678
12679 if (!NT_SUCCESS(status)) {
12680 goto cleanupScanForSpecial;
12681 }
12682
12684 InitializeObjectAttributes(&objectAttributes,
12685 &subkeyName,
12687 deviceParameterHandle,
12688 NULL
12689 );
12690
12691 status = ZwOpenKey( &classParameterHandle,
12692 KEY_READ,
12693 &objectAttributes
12694 );
12695
12696 if (!NT_SUCCESS(status)) {
12697 goto cleanupScanForSpecial;
12698 }
12699
12700 //
12701 // Setup the structure to read
12702 //
12703
12705 queryTable[0].Name = CLASSP_REG_HACK_VALUE_NAME;
12706 queryTable[0].EntryContext = &deviceHacks;
12708 queryTable[0].DefaultData = &deviceHacks;
12709 queryTable[0].DefaultLength = 0;
12710
12711 //
12712 // read values
12713 //
12714
12716 (PWSTR)classParameterHandle,
12717 &queryTable[0],
12718 NULL,
12719 NULL
12720 );
12721 if (!NT_SUCCESS(status)) {
12722 goto cleanupScanForSpecial;
12723 }
12724
12725 //
12726 // remove unknown values and save...
12727 //
12728
12729 CLEAR_FLAG(deviceHacks, FDO_HACK_INVALID_FLAGS);
12730 SET_FLAG(FdoExtension->PrivateFdoData->HackFlags, deviceHacks);
12731
12732
12733cleanupScanForSpecial:
12734
12735 if (deviceParameterHandle) {
12736 ZwClose(deviceParameterHandle);
12737 }
12738
12739 if (classParameterHandle) {
12740 ZwClose(classParameterHandle);
12741 }
12742
12743 //
12744 // we should modify the system hive to include another key for us to grab
12745 // settings from. in this case: Classpnp\HackFlags
12746 //
12747 // the use of a DWORD value for the HackFlags allows 32 hacks w/o
12748 // significant use of the registry, and also reduces OEM exposure.
12749 //
12750 // definition of bit flags:
12751 // 0x00000001 -- Device succeeds PREVENT_MEDIUM_REMOVAL, but
12752 // cannot actually prevent removal.
12753 // 0x00000002 -- Device hard-hangs or times out for GESN requests.
12754 // 0xfffffffc -- Currently reserved, may be used later.
12755 //
12756
12757 return;
12758}
12759
12760/*++////////////////////////////////////////////////////////////////////////////
12761
12762ClasspUpdateDiskProperties()
12763
12764Routine Description:
12765
12766 This routine will send IOCTL_DISK_UPDATE_PROPERTIES to top of stack - Partition Manager
12767 to invalidate the cached geometry.
12768
12769Arguments:
12770
12771 Fdo - The device object whose capacity needs to be verified.
12772
12773Return Value:
12774
12775 NTSTATUS
12776
12777--*/
12778
12779VOID
12780NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
12784 )
12785{
12786 PDEVICE_OBJECT topOfStack;
12787 IO_STATUS_BLOCK ioStatus;
12789 KEVENT event;
12790 PIRP irp = NULL;
12791 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
12792 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
12794
12796
12797 topOfStack = IoGetAttachedDeviceReference(Fdo);
12798
12799 //
12800 // Send down irp to update properties
12801 //
12802
12805 topOfStack,
12806 NULL,
12807 0,
12808 NULL,
12809 0,
12810 FALSE,
12811 &event,
12812 &ioStatus);
12813
12814 if (irp != NULL) {
12815
12816
12817 status = IoCallDriver(topOfStack, irp);
12818 if (status == STATUS_PENDING) {
12820 status = ioStatus.Status;
12821 }
12822
12823 } else {
12825 }
12826
12828
12829 if (!NT_SUCCESS(status)) {
12830 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT, "ClasspUpdateDiskProperties: Disk property update for fdo %p failed with status 0x%X.\n", Fdo, status));
12831 } else {
12832 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspUpdateDiskProperties: Drive capacity has changed for %p.\n", Fdo));
12833 }
12834 ObDereferenceObject(topOfStack);
12835
12836 if (WorkItem != NULL) {
12838 }
12839
12840 return;
12841}
12842
12843BOOLEAN
12853 LONGLONG * RetryIn100nsUnits
12854 )
12855{
12856 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
12857 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
12858 LONGLONG tmpRetry = 0;
12859 BOOLEAN retry = FALSE;
12860
12861 if (fdoData->InterpretSenseInfo != NULL)
12862 {
12863 SCSI_REQUEST_BLOCK tempSrb = {0};
12864 PSCSI_REQUEST_BLOCK srbPtr = Srb;
12865
12866 // SAL annotations and ClassInitializeEx() both validate this
12868
12869 //
12870 // If class driver does not support extended SRB and this is
12871 // an extended SRB, convert to legacy SRB and pass to class
12872 // driver.
12873 //
12875 ((fdoExtension->CommonExtension.DriverExtension->SrbSupport &
12878 srbPtr = &tempSrb;
12879 }
12880
12881 retry = fdoData->InterpretSenseInfo->Interpret(Fdo,
12883 srbPtr,
12887 NULL,
12888 Status,
12889 &tmpRetry);
12890 }
12891 else
12892 {
12893 ULONG seconds = 0;
12894
12896 Srb,
12900 Status,
12901 &seconds);
12902 tmpRetry = ((LONGLONG)seconds) * 1000 * 1000 * 10;
12903 }
12904
12905
12906 if (RetryIn100nsUnits != NULL)
12907 {
12908 *RetryIn100nsUnits = tmpRetry;
12909 }
12910 return retry;
12911}
12912
12913VOID
12916 )
12917{
12920 SCSI_REQUEST_BLOCK srb = {0};
12921 PCDB cdb;
12922 PVPD_SUPPORTED_PAGES_PAGE supportedPages = NULL;
12924 ULONG allocationBufferLength = bufferLength;
12925 UCHAR srbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE] = {0};
12927
12928#if defined(_ARM_) || defined(_ARM64_)
12929 //
12930 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
12931 // based platforms. We are taking the conservative approach here.
12932 //
12933 allocationBufferLength = ALIGN_UP_BY(allocationBufferLength,KeGetRecommendedSharedDataAlignment());
12934 supportedPages = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
12935 allocationBufferLength,
12936 '3CcS'
12937 );
12938
12939#else
12940 supportedPages = ExAllocatePoolWithTag(NonPagedPoolNx,
12942 '3CcS'
12943 );
12944#endif
12945
12946 if (supportedPages == NULL) {
12947 // memory allocation failure.
12948 return;
12949 }
12950
12951 RtlZeroMemory(supportedPages, allocationBufferLength);
12952
12953 // prepare the Srb
12954 if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
12955
12956#ifdef _MSC_VER
12957 #pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded")
12958#endif
12961 sizeof(srbExBuffer),
12962 1,
12964
12965 if (!NT_SUCCESS(status)) {
12966 //
12967 // Should not happen. Revert to legacy SRB.
12971 srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&srb;
12972 } else {
12973 ((PSTORAGE_REQUEST_BLOCK)srbExBuffer)->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
12974 srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)srbExBuffer;
12975 }
12976
12977 } else {
12980 srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&srb;
12981 }
12982
12983 SrbSetTimeOutValue(srbHeader, FdoExtension->TimeOutValue);
12984 SrbSetRequestTag(srbHeader, SP_UNTAGGED);
12986 SrbAssignSrbFlags(srbHeader, FdoExtension->SrbFlags);
12987 SrbSetCdbLength(srbHeader, 6);
12988
12989 cdb = SrbGetCdb(srbHeader);
12990 cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
12991 cdb->CDB6INQUIRY3.EnableVitalProductData = 1; //EVPD bit
12992 cdb->CDB6INQUIRY3.PageCode = VPD_SUPPORTED_PAGES;
12993 cdb->CDB6INQUIRY3.AllocationLength = bufferLength; //AllocationLength field in CDB6INQUIRY3 is only one byte.
12994
12995 status = ClassSendSrbSynchronous(commonExtension->DeviceObject,
12996 (PSCSI_REQUEST_BLOCK)srbHeader,
12997 supportedPages,
12998 allocationBufferLength,
12999 FALSE);
13000
13001 //
13002 // Handle the case where we get back STATUS_DATA_OVERRUN b/c the input
13003 // buffer was larger than necessary.
13004 //
13006 {
13008 }
13009
13010 if ( NT_SUCCESS(status) &&
13011 (supportedPages->PageLength > 0) &&
13012 (supportedPages->SupportedPageList[0] > 0) ) {
13013 // ataport treats all INQUIRY command as standard INQUIRY command, thus fills invalid info
13014 // If VPD INQUIRY is supported, the first page reported (additional length field for standard INQUIRY data) should be '00'
13016 }
13017
13018 if (NT_SUCCESS(status)) {
13019 int i;
13020
13021 for (i = 0; i < supportedPages->PageLength; i++) {
13022 if ( (i > 0) && (supportedPages->SupportedPageList[i] <= supportedPages->SupportedPageList[i - 1]) ) {
13023 // shall be in ascending order beginning with page code 00h.
13024 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = FALSE;
13025 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits = FALSE;
13026 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceCharacteristics = FALSE;
13027 FdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning = FALSE;
13028
13029
13030 break;
13031 }
13032 switch (supportedPages->SupportedPageList[i]) {
13034 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = TRUE;
13035 break;
13036
13037 case VPD_BLOCK_LIMITS:
13038 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits = TRUE;
13039 break;
13040
13042 FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceCharacteristics = TRUE;
13043 break;
13044
13046 FdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning = TRUE;
13047 break;
13048
13049 }
13050 }
13051 }
13052
13053 ExFreePool(supportedPages);
13054
13055 return;
13056}
13057
13058//
13059// ClasspGetLBProvisioningInfo
13060//
13061// Description: This function does the work to get Logical Block Provisioning
13062// (LBP) info for a given LUN, including UNMAP support and parameters. It
13063// will attempt to get both the Logical Block Provisioning (0xB2) VPD page
13064// and the Block Limits (0xB0) VPD page and cache the relevant values in
13065// the given FDO extension.
13066//
13067// After calling this function, you can use the ClasspIsThinProvisioned()
13068// function to determine if the device is thinly provisioned and the
13069// ClasspSupportsUnmap() function to determine if the device supports the
13070// UNMAP command.
13071//
13072// Arguments:
13073// - FdoExtension: The FDO extension associated with the LUN for which Thin
13074// Provisioning info is desired. The Thin Provisioning info is stored
13075// in the FunctionSupportInfo member of this FDO extension.
13076//
13077// Returns:
13078// - STATUS_INVALID_PARAMETER if the given FDO extension has not been
13079// allocated properly.
13080// - STATUS_INSUFFICIENT_RESOURCES if this function was unable to allocate
13081// an SRB used to get the necessary VPD pages.
13082// - STATUS_SUCCESS in all other cases. If any of the incidental functions
13083// don't return STATUS_SUCCESS this function will just assume Thin
13084// Provisioning is not enabled and return STATUS_SUCCESS.
13085//
13089 )
13090{
13092 ULONG srbSize = 0;
13093
13094 //
13095 // Make sure we actually have data structures to work with.
13096 //
13097 if (FdoExtension == NULL ||
13098 FdoExtension->FunctionSupportInfo == NULL) {
13100 }
13101
13102 //
13103 // Allocate an SRB for querying the device for LBP-related info if either
13104 // the Logical Block Provisioning (0xB2) or Block Limits (0xB0) VPD page
13105 // exists.
13106 //
13107 if ((FdoExtension->FunctionSupportInfo->ValidInquiryPages.LBProvisioning == TRUE) ||
13108 (FdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockLimits == TRUE)) {
13109
13110 if ((FdoExtension->AdapterDescriptor != NULL) &&
13111 (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
13113 } else {
13114 srbSize = sizeof(SCSI_REQUEST_BLOCK);
13115 }
13116
13117 srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, '0DcS');
13118
13119 if (srb == NULL) {
13121 }
13122 }
13123
13124 //
13125 // Get the Logical Block Provisioning VPD page (0xB2). This function will
13126 // set some default values if the LBP VPD page is not supported.
13127 //
13129
13130
13131 //
13132 // Get the Block Limits VPD page (0xB0), which may override the default
13133 // UNMAP parameter values set above.
13134 //
13136 srb,
13137 srbSize,
13138 &FdoExtension->FunctionSupportInfo->BlockLimitsData);
13139
13140 FREE_POOL(srb);
13141
13142 return STATUS_SUCCESS;
13143}
13144
13145
13146
13150ClassDetermineTokenOperationCommandSupport(
13152 )
13153
13154/*++
13155
13156Routine Description:
13157
13158 This routine determines if Token Operation and Receive ROD Token Information commands
13159 are supported by this device and updates the internal structures to reflect this.
13160 In addition, it also queries the registry to determine the maximum listIdentifier
13161 to use for TokenOperation commands.
13162
13163 This function must be called at IRQL == PASSIVE_LEVEL.
13164
13165Arguments:
13166
13167 DeviceObject - The device object for which we want to determine command support.
13168
13169Return Value:
13170
13171 Nothing
13172
13173--*/
13174
13175{
13177
13178 PAGED_CODE();
13179
13180 TracePrint((TRACE_LEVEL_VERBOSE,
13181 TRACE_FLAG_PNP,
13182 "ClassDetermineTokenOperationCommandSupport (%p): Entering function.\n",
13183 DeviceObject));
13184
13185 //
13186 // Send down Inquiry for VPD_THIRD_PARTY_COPY_PAGE and cache away the device parameters
13187 // from WINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR.
13188 //
13190
13191 if (NT_SUCCESS(status)) {
13192
13193 ULONG maxListIdentifier = MaxTokenOperationListIdentifier;
13194
13195 //
13196 // Query the maximum list identifier to use for TokenOperation commands.
13197 //
13198 if (NT_SUCCESS(ClasspGetMaximumTokenListIdentifier(DeviceObject, REG_DISK_CLASS_CONTROL, &maxListIdentifier))) {
13199 if (maxListIdentifier >= MIN_TOKEN_LIST_IDENTIFIERS) {
13200
13201 NT_ASSERT(maxListIdentifier <= MAX_TOKEN_LIST_IDENTIFIERS);
13202 MaxTokenOperationListIdentifier = maxListIdentifier;
13203 }
13204 }
13205
13206 }
13207
13208 TracePrint((TRACE_LEVEL_VERBOSE,
13209 TRACE_FLAG_PNP,
13210 "ClassDetermineTokenOperationCommandSupport (%p): Exiting function with status %x.\n",
13212 status));
13213
13214 return status;
13215}
13216
13217
13222 )
13223
13224/*++
13225
13226Routine Description:
13227
13228 This routine does the work to get the Block Device Token Limits info for a given LUN.
13229 This is done by sending Inquiry for the Third Party Copy VPD page.
13230
13231Arguments:
13232
13233 DeviceObject - The FDO associated with the LUN for which Block Device Token
13234 limits info is desired.
13235
13236Return Value:
13237
13238 STATUS_DEVICE_FEATURE_NOT_SUPPORTED if either the Inquiry fails or validations fail.
13239 STATUS_SUCCESS otherwise.
13240
13241--*/
13242
13243{
13244 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
13247 ULONG srbSize = 0;
13248 USHORT pageLength = 0;
13252 ULONG allocationBufferLength = bufferLength;
13253 PCDB cdb;
13254 ULONG dataTransferLength = 0;
13255 PVPD_THIRD_PARTY_COPY_PAGE operatingParameters = NULL;
13256 PWINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR blockDeviceTokenLimits = NULL;
13257
13258 TracePrint((TRACE_LEVEL_VERBOSE,
13259 TRACE_FLAG_PNP,
13260 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Entering function.\n",
13261 DeviceObject));
13262
13263 //
13264 // Allocate an SRB for querying the device for LBP-related info.
13265 //
13266 if ((fdoExtension->AdapterDescriptor != NULL) &&
13267 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
13269 } else {
13270 srbSize = sizeof(SCSI_REQUEST_BLOCK);
13271 }
13272
13273 srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, CLASSPNP_POOL_TAG_SRB);
13274
13275 if (!srb) {
13276
13277 TracePrint((TRACE_LEVEL_ERROR,
13278 TRACE_FLAG_PNP,
13279 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Couldn't allocate SRB.\n",
13280 DeviceObject));
13281
13283 goto __ClasspGetBlockDeviceTokenLimitsInfo_Exit;
13284 }
13285
13286#if defined(_ARM_) || defined(_ARM64_)
13287 //
13288 // ARM has specific alignment requirements, although this will not have a functional impact on x86 or amd64
13289 // based platforms. We are taking the conservative approach here.
13290 //
13291 allocationBufferLength = ALIGN_UP_BY(allocationBufferLength, KeGetRecommendedSharedDataAlignment());
13292 dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationBufferLength, CLASSPNP_POOL_TAG_VPD);
13293#else
13295#endif
13296
13297 if (!dataBuffer) {
13298
13299 TracePrint((TRACE_LEVEL_ERROR,
13300 TRACE_FLAG_PNP,
13301 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Couldn't allocate dataBuffer.\n",
13302 DeviceObject));
13303
13305 goto __ClasspGetBlockDeviceTokenLimitsInfo_Exit;
13306 }
13307
13308 operatingParameters = (PVPD_THIRD_PARTY_COPY_PAGE)dataBuffer;
13309
13310 RtlZeroMemory(dataBuffer, allocationBufferLength);
13311
13312 if ((fdoExtension->AdapterDescriptor != NULL) &&
13313 (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
13317 1,
13319 if (NT_SUCCESS(status)) {
13320
13322
13323 } else {
13324
13325 //
13326 // Should not occur. Revert to legacy SRB.
13327 //
13329
13330 TracePrint((TRACE_LEVEL_WARNING,
13331 TRACE_FLAG_PNP,
13332 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Falling back to using SRB (instead of SRB_EX).\n",
13333 DeviceObject));
13334
13335 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
13336 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
13337 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
13338 }
13339 } else {
13340
13341 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
13342 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
13344 }
13345
13346 SrbSetTimeOutValue(srb, fdoExtension->TimeOutValue);
13349 SrbAssignSrbFlags(srb, fdoExtension->SrbFlags);
13350
13351 SrbSetCdbLength(srb, 6);
13352
13353 cdb = SrbGetCdb(srb);
13354 cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY;
13355 cdb->CDB6INQUIRY3.EnableVitalProductData = 1;
13356 cdb->CDB6INQUIRY3.PageCode = VPD_THIRD_PARTY_COPY;
13357 cdb->CDB6INQUIRY3.AllocationLength = bufferLength;
13358
13360 srb,
13361 dataBuffer,
13362 allocationBufferLength,
13363 FALSE);
13364
13365 //
13366 // Handle the case where we get back STATUS_DATA_OVERRUN because the input
13367 // buffer was larger than necessary.
13368 //
13369 dataTransferLength = SrbGetDataTransferLength(srb);
13370
13371 if (status == STATUS_DATA_OVERRUN && dataTransferLength < bufferLength) {
13372
13374 }
13375
13376 if (NT_SUCCESS(status)) {
13377
13378 REVERSE_BYTES_SHORT(&pageLength, &operatingParameters->PageLength);
13379
13380 } else {
13381 TracePrint((TRACE_LEVEL_ERROR,
13382 TRACE_FLAG_PNP,
13383 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Inquiry for TPC VPD failed with %x.\n",
13385 status));
13386 }
13387
13388 if ((NT_SUCCESS(status)) &&
13389 (pageLength >= sizeof(WINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR))) {
13390
13391 USHORT descriptorType;
13392
13393 blockDeviceTokenLimits = (PWINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR)operatingParameters->ThirdPartyCopyDescriptors;
13394 REVERSE_BYTES_SHORT(&descriptorType, &blockDeviceTokenLimits->DescriptorType);
13395 REVERSE_BYTES_SHORT(&descriptorLength, &blockDeviceTokenLimits->DescriptorLength);
13396
13397 if ((descriptorType == BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR_TYPE_WINDOWS) &&
13399
13400 fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = TRUE;
13401
13402 REVERSE_BYTES_SHORT(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumRangeDescriptors, &blockDeviceTokenLimits->MaximumRangeDescriptors);
13403 REVERSE_BYTES(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer, &blockDeviceTokenLimits->MaximumInactivityTimer);
13404 REVERSE_BYTES(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.DefaultInactivityTimer, &blockDeviceTokenLimits->DefaultInactivityTimer);
13405 REVERSE_BYTES_QUAD(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize, &blockDeviceTokenLimits->MaximumTokenTransferSize);
13406 REVERSE_BYTES_QUAD(&fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount, &blockDeviceTokenLimits->OptimalTransferCount);
13407
13408 TracePrint((TRACE_LEVEL_INFORMATION,
13409 TRACE_FLAG_PNP,
13410 "ClasspGetBlockDeviceTokenLimitsInfo (%p): %s %s (rev %s) reported following parameters: \
13411 \n\t\t\tMaxRangeDescriptors: %u\n\t\t\tMaxIAT: %u\n\t\t\tDefaultIAT: %u \
13412 \n\t\t\tMaxTokenTransferSize: %I64u\n\t\t\tOptimalTransferCount: %I64u\n\t\t\tOptimalTransferLengthGranularity: %u \
13413 \n\t\t\tOptimalTransferLength: %u\n\t\t\tMaxTransferLength: %u\n",
13415 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->VendorIdOffset),
13416 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->ProductIdOffset),
13417 (PCSZ)(((PUCHAR)fdoExtension->DeviceDescriptor) + fdoExtension->DeviceDescriptor->ProductRevisionOffset),
13418 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumRangeDescriptors,
13419 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer,
13420 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.DefaultInactivityTimer,
13421 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize,
13422 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount,
13423 fdoExtension->FunctionSupportInfo->BlockLimitsData.OptimalTransferLengthGranularity,
13424 fdoExtension->FunctionSupportInfo->BlockLimitsData.OptimalTransferLength,
13425 fdoExtension->FunctionSupportInfo->BlockLimitsData.MaximumTransferLength));
13426 } else {
13427
13428 TracePrint((TRACE_LEVEL_WARNING,
13429 TRACE_FLAG_PNP,
13430 "ClasspGetBlockDeviceTokenLimitsInfo (%p): ThirdPartyCopy VPD data doesn't have Windows OffloadDataTransfer descriptor.\n",
13431 DeviceObject));
13432
13433 fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = FALSE;
13435 }
13436 } else {
13437
13438 TracePrint((TRACE_LEVEL_WARNING,
13439 TRACE_FLAG_PNP,
13440 "ClasspGetBlockDeviceTokenLimitsInfo (%p): TPC VPD data didn't return TPC descriptors of interest.\n",
13441 DeviceObject));
13442
13443 fdoExtension->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits = FALSE;
13445 }
13446
13447__ClasspGetBlockDeviceTokenLimitsInfo_Exit:
13448
13450 FREE_POOL(srb);
13451 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus = status;
13452
13453 TracePrint((TRACE_LEVEL_VERBOSE,
13454 TRACE_FLAG_PNP,
13455 "ClasspGetBlockDeviceTokenLimitsInfo (%p): Exiting function with status %x.\n",
13457 status));
13458
13459 return status;
13460}
13461
13462
13467ClassDeviceProcessOffloadRead(
13469 _In_ PIRP Irp,
13471 )
13472
13473/*++
13474
13475Routine Description:
13476
13477 This routine services IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES for CopyOffload
13478 Read. If the device supports copy offload, it performs the translation of the
13479 IOCTL into the appropriate SCSI commands to complete the operation.
13480
13481 This function must be called at IRQL < DISPATCH_LEVEL.
13482
13483Arguments:
13484
13485 DeviceObject - Supplies the device object associated with this request
13486 Irp - The IRP to be processed
13487 Srb - An SRB that can be optimally used to process this request
13488
13489Return Value:
13490
13491 NTSTATUS code
13492
13493--*/
13494
13495{
13496 PIO_STACK_LOCATION irpStack;
13499 PDEVICE_DSM_OFFLOAD_READ_PARAMETERS offloadReadParameters;
13500 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
13501
13503
13504 //
13505 // This function must be called at less than dispatch level.
13506 // Fail if IRQL >= DISPATCH_LEVEL.
13507 //
13508 PAGED_CODE();
13509
13510 TracePrint((TRACE_LEVEL_VERBOSE,
13511 TRACE_FLAG_IOCTL,
13512 "ClassDeviceProcessOffloadRead (%p): Entering function. Irp %p\n",
13514 Irp));
13515
13516
13517 irpStack = IoGetCurrentIrpStackLocation (Irp);
13518
13519 //
13520 // Validations
13521 //
13522 status = ClasspValidateOffloadSupported(DeviceObject, Irp);
13523 if (!NT_SUCCESS(status)) {
13524 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13525 }
13526
13528
13530 TracePrint((TRACE_LEVEL_ERROR,
13531 TRACE_FLAG_IOCTL,
13532 "ClassDeviceProcessOffloadRead (%p): Called at raised IRQL.\n",
13533 DeviceObject));
13534
13536 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13537 }
13538
13539 //
13540 // Ensure that this DSM IOCTL was generated in kernel
13541 //
13542 if (Irp->RequestorMode != KernelMode) {
13543
13544 TracePrint((TRACE_LEVEL_ERROR,
13545 TRACE_FLAG_IOCTL,
13546 "ClassDeviceProcessOffloadRead (%p): Called from user mode.\n",
13547 DeviceObject));
13548
13550 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13551 }
13552
13553 status = ClasspValidateOffloadInputParameters(DeviceObject, Irp);
13554 if (!NT_SUCCESS(status)) {
13555 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13556 }
13557
13558 dsmAttributes = Irp->AssociatedIrp.SystemBuffer;
13559
13560 //
13561 // Validate that we were passed in correct sized parameter block.
13562 //
13563 if (dsmAttributes->ParameterBlockLength < sizeof(DEVICE_DSM_OFFLOAD_READ_PARAMETERS)) {
13564
13565 TracePrint((TRACE_LEVEL_ERROR,
13566 TRACE_FLAG_IOCTL,
13567 "ClassDeviceProcessOffloadRead (%p): Parameter block size (%u) too small. Required %u.\n",
13569 dsmAttributes->ParameterBlockLength,
13571
13573 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13574 }
13575
13576 offloadReadParameters = Add2Ptr(dsmAttributes, dsmAttributes->ParameterBlockOffset);
13577
13578 fdoExtension = DeviceObject->DeviceExtension;
13579
13580 //
13581 // If the request TTL is greater than the max supported by this storage, the target will
13582 // end up failing this command, so might as well do the check up front.
13583 //
13584 if ((fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer > 0) &&
13585 (offloadReadParameters->TimeToLive > fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer)) {
13586
13587 TracePrint((TRACE_LEVEL_ERROR,
13588 TRACE_FLAG_IOCTL,
13589 "ClassDeviceProcessOffloadRead (%p): Requested TTL (%u) greater than max supported (%u).\n",
13591 offloadReadParameters->TimeToLive,
13592 fdoExtension->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumInactivityTimer));
13593
13595 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13596 }
13597
13598 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_OFFLOAD_READ_OUTPUT)) {
13599
13600 TracePrint((TRACE_LEVEL_ERROR,
13601 TRACE_FLAG_IOCTL,
13602 "ClassDeviceProcessOffloadRead (%p): Output buffer size (%u) too small.\n",
13604 irpStack->Parameters.DeviceIoControl.OutputBufferLength));
13605
13607 goto __ClassDeviceProcessOffloadRead_CompleteAndExit;
13608 }
13609
13610
13611
13612 status = ClasspServicePopulateTokenTransferRequest(DeviceObject, Irp);
13613
13614 if (status == STATUS_PENDING) {
13615 goto __ClassDeviceProcessOffloadRead_Exit;
13616 }
13617
13618__ClassDeviceProcessOffloadRead_CompleteAndExit:
13620__ClassDeviceProcessOffloadRead_Exit:
13621 TracePrint((TRACE_LEVEL_VERBOSE,
13622 TRACE_FLAG_IOCTL,
13623 "ClassDeviceProcessOffloadRead (%p): Exiting function Irp %p with status %x.\n",
13625 Irp,
13626 status));
13627
13628 return status;
13629}
13630
13631VOID
13634 _In_ PIRP Irp,
13635 _In_ NTSTATUS CompletionStatus)
13636{
13637 NTSTATUS status = CompletionStatus;
13638
13639
13640 Irp->IoStatus.Status = status;
13641
13644
13645 return;
13646}
13647
13648
13653ClassDeviceProcessOffloadWrite(
13655 _In_ PIRP Irp,
13657 )
13658
13659/*++
13660
13661Routine Description:
13662
13663 This routine services IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES for CopyOffload
13664 Write. If the device supports copy offload, it performs the translation of the
13665 IOCTL into the appropriate SCSI commands to complete the operation.
13666
13667 This function must be called at IRQL < DISPATCH_LEVEL.
13668
13669Arguments:
13670
13671 DeviceObject - Supplies the device object associated with this request
13672 Irp - The IRP to be processed
13673 Srb - An SRB that can be optinally used to process this request
13674
13675Return Value:
13676
13677 NTSTATUS code
13678
13679--*/
13680
13681{
13682 PIO_STACK_LOCATION irpStack;
13685
13687
13688 //
13689 // This function must be called at less than dispatch level.
13690 //
13691 PAGED_CODE();
13692
13693 TracePrint((TRACE_LEVEL_VERBOSE,
13694 TRACE_FLAG_IOCTL,
13695 "ClassDeviceProcessOffloadWrite (%p): Entering function. Irp %p\n",
13697 Irp));
13698
13699
13701
13702 //
13703 // Validations
13704 //
13705 status = ClasspValidateOffloadSupported(DeviceObject, Irp);
13706 if (!NT_SUCCESS(status)) {
13707 goto __ClassDeviceProcessOffloadWrite_CompleteAndExit;
13708 }
13709
13711
13713 TracePrint((TRACE_LEVEL_ERROR,
13714 TRACE_FLAG_IOCTL,
13715 "ClassDeviceProcessOffloadWrite (%p): Called at raised IRQL.\n",
13716 DeviceObject));
13717
13719 goto __ClassDeviceProcessOffloadWrite_CompleteAndExit;
13720 }
13721
13722 //
13723 // Ensure that this DSM IOCTL was generated in kernel
13724 //
13725 if (Irp->RequestorMode != KernelMode) {
13726
13727 TracePrint((TRACE_LEVEL_ERROR,
13728 TRACE_FLAG_IOCTL,
13729 "ClassDeviceProcessOffloadWrite (%p): Called from user mode.\n",
13730 DeviceObject));
13731
13733 goto __ClassDeviceProcessOffloadWrite_CompleteAndExit;
13734 }
13735
13736 status = ClasspValidateOffloadInputParameters(DeviceObject, Irp);
13737 if (!NT_SUCCESS(status)) {
13738 goto __ClassDeviceProcessOffloadWrite_CompleteAndExit;
13739 }
13740
13741 dsmAttributes = Irp->AssociatedIrp.SystemBuffer;
13742
13743 //
13744 // Validate that we were passed in correct sized parameter block.
13745 //
13746 if (dsmAttributes->ParameterBlockLength < sizeof(DEVICE_DSM_OFFLOAD_WRITE_PARAMETERS)) {
13747
13748 TracePrint((TRACE_LEVEL_ERROR,
13749 TRACE_FLAG_IOCTL,
13750 "ClassDeviceProcessOffloadWrite (%p): Parameter block size (%u) too small. Required %u.\n",
13752 dsmAttributes->ParameterBlockLength,
13754
13756 goto __ClassDeviceProcessOffloadWrite_CompleteAndExit;
13757 }
13758
13759 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_OFFLOAD_WRITE_OUTPUT)) {
13760
13761 TracePrint((TRACE_LEVEL_ERROR,
13762 TRACE_FLAG_IOCTL,
13763 "ClassDeviceProcessOffloadWrite (%p): Output buffer size (%u) too small.\n",
13765 irpStack->Parameters.DeviceIoControl.OutputBufferLength));
13766
13768 goto __ClassDeviceProcessOffloadWrite_CompleteAndExit;
13769 }
13770
13771
13772
13773 status = ClasspServiceWriteUsingTokenTransferRequest(DeviceObject, Irp);
13774
13775 if (status == STATUS_PENDING) {
13776 goto __ClassDeviceProcessOffloadWrite_Exit;
13777 }
13778
13779__ClassDeviceProcessOffloadWrite_CompleteAndExit:
13781__ClassDeviceProcessOffloadWrite_Exit:
13782 TracePrint((TRACE_LEVEL_VERBOSE,
13783 TRACE_FLAG_IOCTL,
13784 "ClassDeviceProcessOffloadWrite (%p): Exiting function Irp %p with status %x\n",
13786 Irp,
13787 status));
13788
13789 return status;
13790}
13791
13792
13797ClasspServicePopulateTokenTransferRequest(
13799 _In_ PIRP Irp
13800 )
13801
13802/*++
13803
13804Routine description:
13805
13806 This routine processes offload read requests by building the SRB
13807 for PopulateToken and its result (i.e. token).
13808
13809Arguments:
13810
13811 Fdo - The functional device object processing the request
13812 Irp - The Io request to be processed
13813
13814Return Value:
13815
13816 STATUS_SUCCESS if successful, an error code otherwise
13817
13818--*/
13819
13820{
13821 BOOLEAN allDataSetRangeFullyConverted;
13822 UINT32 allocationSize;
13823 ULONG blockDescrIndex;
13824 PBLOCK_DEVICE_RANGE_DESCRIPTOR blockDescrPointer;
13825 PVOID buffer;
13827 ULONG dataSetRangeIndex;
13828 PDEVICE_DATA_SET_RANGE dataSetRanges;
13829 ULONG dataSetRangesCount;
13831 ULONGLONG entireXferLen;
13833 ULONG i;
13834 ULONG lbaCount;
13835 ULONG listIdentifier;
13836 ULONG maxBlockDescrCount;
13837 ULONGLONG maxLbaCount;
13838 POFFLOAD_READ_CONTEXT offloadReadContext;
13839 PDEVICE_DSM_OFFLOAD_READ_PARAMETERS offloadReadParameters;
13840 PTRANSFER_PACKET pkt;
13841 USHORT populateTokenDataLength;
13842 USHORT populateTokenDescriptorsLength;
13843 PMDL populateTokenMdl;
13844 PIRP pseudoIrp;
13845 ULONG receiveTokenInformationBufferLength;
13847 DEVICE_DATA_SET_RANGE tempDataSetRange;
13848 BOOLEAN tempDataSetRangeFullyConverted;
13849 PUCHAR token;
13850 ULONG tokenLength;
13851 ULONG tokenOperationBufferLength;
13852 ULONGLONG totalSectorCount;
13853 ULONGLONG totalSectorsToProcess;
13854 ULONG transferSize;
13855
13856 PAGED_CODE();
13857
13858 TracePrint((TRACE_LEVEL_VERBOSE,
13859 TRACE_FLAG_IOCTL,
13860 "ClasspServicePopulateTokenTransferRequest (%p): Entering function. Irp %p\n",
13861 Fdo,
13862 Irp));
13863
13864 fdoExt = Fdo->DeviceExtension;
13866 dsmAttributes = Irp->AssociatedIrp.SystemBuffer;
13867 buffer = NULL;
13868 pkt = NULL;
13869 populateTokenMdl = NULL;
13870 offloadReadParameters = Add2Ptr(dsmAttributes, dsmAttributes->ParameterBlockOffset);
13871 dataSetRanges = Add2Ptr(dsmAttributes, dsmAttributes->DataSetRangesOffset);
13872 dataSetRangesCount = dsmAttributes->DataSetRangesLength / sizeof(DEVICE_DATA_SET_RANGE);
13873 totalSectorsToProcess = 0;
13874 token = NULL;
13875 tokenLength = 0;
13876 bufferLength = 0;
13877 offloadReadContext = NULL;
13878
13879 NT_ASSERT(fdoExt->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits &&
13880 NT_SUCCESS(fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus));
13881
13882
13883 for (i = 0, entireXferLen = 0; i < dataSetRangesCount; i++) {
13884 entireXferLen += dataSetRanges[i].LengthInBytes;
13885 }
13886
13887 //
13888 // We need to truncate the read request based on the following hardware limitations:
13889 // 1. The size of the data buffer containing the TokenOperation command's parameters must
13890 // not exceed the MaximumTransferLength (and max physical pages) of the underlying
13891 // adapter.
13892 // 2. The number of descriptors specified in the TokenOperation command must not exceed
13893 // the MaximumRangeDescriptors.
13894 // 3. The cumulative total of the number of transfer blocks in all the descriptors in
13895 // the TokenOperation command must not exceed the MaximumTokenTransferSize.
13896 // 4. If the TTL has been set to the 0 (i.e. indicates the use of the default TLT),
13897 // limit the cumulative total of the number of transfer blocks in all the descriptors
13898 // in the TokenOperation command to the OptimalTransferCount.
13899 // NOTE: only a TTL of 0 has an implicit indication that the initiator of the
13900 // request would like the storage stack to be smart about the amount of data
13901 // transfer.
13902 //
13903 // In addition to the above, we need to ensure that for each of the descriptors in the
13904 // TokenOperation command:
13905 // 1. The number of blocks specified is an exact multiple of the OptimalTransferLengthGranularity.
13906 // 2. The number of blocks specified is limited to the MaximumTransferLength. (We shall
13907 // however, limit the number of blocks specified in each descriptor to be a maximum of
13908 // OptimalTransferLength or MaximumTransferLength, whichever is lesser).
13909 //
13910 // Finally, we shall always send down the PopulateToken command using IMMED = 0 for this
13911 // release. This makes it simpler to handle multi-initiator scenarios since we won't need
13912 // to deal with the PopulateToken (with IMMED = 1) succeeding but ReceiveRODTokenInformation
13913 // failing due to the path/node failing, thus making it impossible to retrieve the token.
13914 //
13915 // The LBA ranges is in DEVICE_DATA_SET_RANGE format, it needs to be converted into
13916 // WINDOWS_RANGE_DESCRIPTOR Block Descriptors.
13917 //
13918
13921 &bufferLength,
13922 &tokenOperationBufferLength,
13923 &receiveTokenInformationBufferLength);
13924
13925 allocationSize = sizeof(OFFLOAD_READ_CONTEXT) + bufferLength;
13926
13927 offloadReadContext = ExAllocatePoolWithTag(
13928 NonPagedPoolNx,
13929 allocationSize,
13931
13932 if (!offloadReadContext) {
13933
13934 TracePrint((TRACE_LEVEL_ERROR,
13935 TRACE_FLAG_IOCTL,
13936 "ClasspServicePopulateTokenTransferRequest (%p): Failed to allocate buffer for PopulateToken operations.\n",
13937 Fdo));
13938
13940 goto __ClasspServicePopulateTokenTransferRequest_ErrorExit;
13941 }
13942
13943 RtlZeroMemory(offloadReadContext, allocationSize);
13944
13945 offloadReadContext->Fdo = Fdo;
13946 offloadReadContext->OffloadReadDsmIrp = Irp;
13947
13948 //
13949 // The buffer for the commands is after the offloadReadContext.
13950 //
13951 buffer = (offloadReadContext + 1);
13952
13953 //
13954 // No matter how large the offload read request, we'll be sending it down in one shot.
13955 // So we need only one transfer packet.
13956 //
13958 if (!pkt){
13959
13960 TracePrint((TRACE_LEVEL_ERROR,
13961 TRACE_FLAG_IOCTL,
13962 "ClasspServicePopulateTokenTransferRequest (%p): Failed to retrieve transfer packet for TokenOperation (PopulateToken) operation.\n",
13963 Fdo));
13964
13966 goto __ClasspServicePopulateTokenTransferRequest_ErrorExit;
13967 }
13968
13969 offloadReadContext->Pkt = pkt;
13970
13973 tokenOperationBufferLength,
13974 &maxBlockDescrCount,
13975 &maxLbaCount);
13976
13977 //
13978 // We will limit the maximum data transfer in an offload read operation to:
13979 // - OTC if TTL was specified as 0
13980 // - MaximumTransferTransferSize if lesser than above, or if TTL was specified was non-zero
13981 //
13982 if ((offloadReadParameters->TimeToLive == 0) && (fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount > 0)) {
13983
13984 maxLbaCount = MIN(maxLbaCount, fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount);
13985 }
13986
13987 //
13988 // Since we do not want very fragmented files to end up causing the PopulateToken command to take
13989 // too long (and potentially timeout), we will limit the max number of descriptors sent down in a
13990 // command.
13991 //
13992 maxBlockDescrCount = MIN(maxBlockDescrCount, MAX_NUMBER_BLOCK_DEVICE_DESCRIPTORS);
13993
13994 TracePrint((TRACE_LEVEL_INFORMATION,
13995 TRACE_FLAG_IOCTL,
13996 "ClasspServicePopulateTokenTransferRequest (%p): Using MaxBlockDescrCount %u and MaxLbaCount %I64u.\n",
13997 Fdo,
13998 maxBlockDescrCount,
13999 maxLbaCount));
14000
14001 allDataSetRangeFullyConverted = FALSE;
14002 tempDataSetRangeFullyConverted = TRUE;
14003 dataSetRangeIndex = (ULONG)-1;
14004
14005 blockDescrPointer = (PBLOCK_DEVICE_RANGE_DESCRIPTOR)
14006 &((PPOPULATE_TOKEN_HEADER)buffer)->BlockDeviceRangeDescriptor[0];
14007
14008 RtlZeroMemory(&tempDataSetRange, sizeof(tempDataSetRange));
14009
14010 blockDescrIndex = 0;
14011 lbaCount = 0;
14012
14013 //
14014 // Send PopulateToken command when the buffer is full or all input entries are converted.
14015 //
14016 while (!((blockDescrIndex == maxBlockDescrCount) || // buffer full or block descriptor count reached
14017 (lbaCount == maxLbaCount) || // block LBA count reached
14018 (allDataSetRangeFullyConverted))) { // all DataSetRanges have been converted
14019
14020 //
14021 // If the previous entry conversion completed, continue the next one;
14022 // Otherwise, still process the left part of the un-completed entry.
14023 //
14024 if (tempDataSetRangeFullyConverted) {
14025 dataSetRangeIndex++;
14026 tempDataSetRange.StartingOffset = dataSetRanges[dataSetRangeIndex].StartingOffset;
14027 tempDataSetRange.LengthInBytes = dataSetRanges[dataSetRangeIndex].LengthInBytes;
14028 }
14029
14030 totalSectorCount = 0;
14031
14032 ClasspConvertDataSetRangeToBlockDescr(Fdo,
14033 blockDescrPointer,
14034 &blockDescrIndex,
14035 maxBlockDescrCount,
14036 &lbaCount,
14037 maxLbaCount,
14038 &tempDataSetRange,
14039 &totalSectorCount);
14040
14041 tempDataSetRangeFullyConverted = (tempDataSetRange.LengthInBytes == 0) ? TRUE : FALSE;
14042
14043 allDataSetRangeFullyConverted = tempDataSetRangeFullyConverted && ((dataSetRangeIndex + 1) == dataSetRangesCount);
14044
14045 totalSectorsToProcess += totalSectorCount;
14046 }
14047
14048 //
14049 // Calculate transfer size, including the header
14050 //
14051 transferSize = (blockDescrIndex * sizeof(BLOCK_DEVICE_RANGE_DESCRIPTOR)) + FIELD_OFFSET(POPULATE_TOKEN_HEADER, BlockDeviceRangeDescriptor);
14052
14054
14055 populateTokenDataLength = (USHORT)transferSize - RTL_SIZEOF_THROUGH_FIELD(POPULATE_TOKEN_HEADER, PopulateTokenDataLength);
14056 REVERSE_BYTES_SHORT(((PPOPULATE_TOKEN_HEADER)buffer)->PopulateTokenDataLength, &populateTokenDataLength);
14057
14058 ((PPOPULATE_TOKEN_HEADER)buffer)->Immediate = 0;
14059
14060 REVERSE_BYTES(((PPOPULATE_TOKEN_HEADER)buffer)->InactivityTimeout, &offloadReadParameters->TimeToLive);
14061
14062 populateTokenDescriptorsLength = (USHORT)transferSize - FIELD_OFFSET(POPULATE_TOKEN_HEADER, BlockDeviceRangeDescriptor);
14063 REVERSE_BYTES_SHORT(((PPOPULATE_TOKEN_HEADER)buffer)->BlockDeviceRangeDescriptorListLength, &populateTokenDescriptorsLength);
14064
14065 //
14066 // Reuse a single buffer for both TokenOperation and ReceiveTokenInformation. This has the one disadvantage
14067 // that we'll be marking the page(s) as IoWriteAccess even though we only need read access for token
14068 // operation command. However, the advantage is that we eliminate the possibility of any potential failures
14069 // when trying to allocate an MDL for the ReceiveTokenInformation later on.
14070 //
14071 bufferLength = max(transferSize, receiveTokenInformationBufferLength);
14072
14073 populateTokenMdl = ClasspBuildDeviceMdl(buffer, bufferLength, FALSE);
14074 if (!populateTokenMdl) {
14075
14076 TracePrint((TRACE_LEVEL_ERROR,
14077 TRACE_FLAG_IOCTL,
14078 "ClasspServicePopulateTokenTransferRequest (%p): Failed to allocate MDL for PopulateToken operations.\n",
14079 Fdo));
14080
14082 goto __ClasspServicePopulateTokenTransferRequest_ErrorExit;
14083 }
14084
14085 offloadReadContext->PopulateTokenMdl = populateTokenMdl;
14086
14087 pseudoIrp = &offloadReadContext->PseudoIrp;
14088
14089
14090 pseudoIrp->IoStatus.Status = STATUS_SUCCESS;
14091 pseudoIrp->IoStatus.Information = 0;
14092 pseudoIrp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
14093 pseudoIrp->MdlAddress = populateTokenMdl;
14094
14096 listIdentifier = InterlockedIncrement((volatile LONG *)&TokenOperationListIdentifier);
14097
14098 ClasspSetupPopulateTokenTransferPacket(
14099 offloadReadContext,
14100 pkt,
14101 transferSize,
14102 (PUCHAR)buffer,
14103 pseudoIrp,
14104 listIdentifier);
14105
14106 TracePrint((TRACE_LEVEL_INFORMATION,
14107 TRACE_FLAG_IOCTL,
14108 "ClasspServicePopulateTokenTransferRequest (%p): Generate token for %I64u bytes (versus %I64u) [via %u descriptors]. \
14109 \n\t\t\tDataLength: %u, DescriptorsLength: %u. Pkt %p (list id %x). Requested TTL: %u secs.\n",
14110 Fdo,
14111 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector,
14112 entireXferLen,
14113 blockDescrIndex,
14114 populateTokenDataLength,
14115 populateTokenDescriptorsLength,
14116 pkt,
14117 listIdentifier,
14118 offloadReadParameters->TimeToLive));
14119
14120 //
14121 // Save (into the offloadReadContext) any remaining things that
14122 // ClasspPopulateTokenTransferPacketDone() will need.
14123 //
14124
14125 offloadReadContext->ListIdentifier = listIdentifier;
14126 offloadReadContext->BufferLength = bufferLength;
14127 offloadReadContext->ReceiveTokenInformationBufferLength = receiveTokenInformationBufferLength;
14128 offloadReadContext->TotalSectorsToProcess = totalSectorsToProcess; // so far
14129 offloadReadContext->EntireXferLen = entireXferLen;
14130
14131 NT_ASSERT(status == STATUS_SUCCESS); // so far.
14132
14135
14137 goto __ClasspServicePopulateTokenTransferRequest_Exit;
14138
14139 //
14140 // Error cleanup label only - not used in success case:
14141 //
14142
14143__ClasspServicePopulateTokenTransferRequest_ErrorExit:
14144
14146
14147 if (offloadReadContext != NULL) {
14148 ClasspCleanupOffloadReadContext(offloadReadContext);
14149 offloadReadContext = NULL;
14150 }
14151
14152__ClasspServicePopulateTokenTransferRequest_Exit:
14153
14154 TracePrint((TRACE_LEVEL_VERBOSE,
14155 TRACE_FLAG_IOCTL,
14156 "ClasspServicePopulateTokenTransferRequest (%p): Exiting function (Irp %p) with status %x.\n",
14157 Fdo,
14158 Irp,
14159 status));
14160
14161 return status;
14162}
14163
14164
14165VOID
14168 )
14169
14170/*++
14171
14172Routine description:
14173
14174 This routine continues an offload read operation on completion of the
14175 populate token transfer packet.
14176
14177 This function is responsible for continuing or completing the offload read
14178 operation.
14179
14180Arguments:
14181
14182 Context - Pointer to the OFFLOAD_READ_CONTEXT for the offload read
14183 operation.
14184
14185Return Value:
14186
14187 None.
14188
14189--*/
14190
14191{
14192 PDEVICE_OBJECT fdo;
14193 ULONG listIdentifier;
14194 POFFLOAD_READ_CONTEXT offloadReadContext;
14195 PTRANSFER_PACKET pkt;
14196 PIRP pseudoIrp;
14198
14199 offloadReadContext = Context;
14200 pseudoIrp = &offloadReadContext->PseudoIrp;
14201 pkt = offloadReadContext->Pkt;
14202 fdo = offloadReadContext->Fdo;
14203 listIdentifier = offloadReadContext->ListIdentifier;
14204
14205 offloadReadContext->Pkt = NULL;
14206
14207
14208 status = pseudoIrp->IoStatus.Status;
14210
14211 if (!NT_SUCCESS(status)) {
14212 TracePrint((TRACE_LEVEL_ERROR,
14213 TRACE_FLAG_IOCTL,
14214 "ClasspPopulateTokenTransferPacketDone (%p): Generate token for list Id %x failed with %x (Pkt %p).\n",
14215 fdo,
14216 listIdentifier,
14217 status,
14218 pkt));
14219 goto __ClasspPopulateTokenTransferPacketDone_ErrorExit;
14220 }
14221
14222 //
14223 // If a token was successfully generated, it is now time to retrieve the token.
14224 // The called function is responsible for completing the offload read DSM IRP.
14225 //
14226 ClasspReceivePopulateTokenInformation(offloadReadContext);
14227
14228 //
14229 // ClasspReceivePopulateTokenInformation() takes care of completing the IRP,
14230 // so this function is done regardless of success or failure in
14231 // ClasspReceivePopulateTokenInformation().
14232 //
14233
14234 return;
14235
14236 //
14237 // Error cleanup label only - not used in success case:
14238 //
14239
14240__ClasspPopulateTokenTransferPacketDone_ErrorExit:
14241
14243
14244 //
14245 // ClasspCompleteOffloadRead also cleans up offloadReadContext.
14246 //
14247
14248 ClasspCompleteOffloadRead(offloadReadContext, status);
14249
14250 return;
14251}
14252
14253
14254VOID
14256 _In_ POFFLOAD_READ_CONTEXT OffloadReadContext,
14257 _In_ NTSTATUS CompletionStatus
14258 )
14259
14260/*++
14261
14262Routine description:
14263
14264 This routine completes an offload read operation with given status, and
14265 cleans up the OFFLOAD_READ_CONTEXT.
14266
14267Arguments:
14268
14269 OffloadReadContext - Pointer to the OFFLOAD_READ_CONTEXT for the offload
14270 read operation.
14271
14272 CompletionStatus - The completion status for the offload read operation.
14273
14274Return Value:
14275
14276 None.
14277
14278--*/
14279
14280{
14282 ULONGLONG entireXferLen;
14283 PDEVICE_OBJECT fdo;
14285 PIRP irp;
14287 PUCHAR token;
14288 ULONGLONG totalSectorsProcessed;
14289
14290 status = CompletionStatus;
14291 dsmAttributes = OffloadReadContext->OffloadReadDsmIrp->AssociatedIrp.SystemBuffer;
14292 totalSectorsProcessed = OffloadReadContext->TotalSectorsProcessed;
14293 fdoExt = OffloadReadContext->Fdo->DeviceExtension;
14294 entireXferLen = OffloadReadContext->EntireXferLen;
14295 token = OffloadReadContext->Token;
14296 irp = OffloadReadContext->OffloadReadDsmIrp;
14297 fdo = OffloadReadContext->Fdo;
14298
14299 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->OffloadReadFlags = 0;
14300 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->Reserved = 0;
14301
14302 if (NT_SUCCESS(status)) {
14303 ULONGLONG totalBytesProcessed = totalSectorsProcessed * fdoExt->DiskGeometry.BytesPerSector;
14304
14305 TracePrint((totalBytesProcessed == entireXferLen ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_WARNING,
14306 TRACE_FLAG_IOCTL,
14307 "ClasspCompleteOffloadRead (%p): Successfully populated token with %I64u (out of %I64u) bytes (list Id %x).\n",
14308 fdo,
14309 totalBytesProcessed,
14310 entireXferLen,
14311 OffloadReadContext->ListIdentifier));
14312
14313 if (totalBytesProcessed < entireXferLen) {
14315 }
14316 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->LengthProtected = totalBytesProcessed;
14317 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->TokenLength = STORAGE_OFFLOAD_MAX_TOKEN_LENGTH;
14319 } else {
14320 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->LengthProtected = 0;
14321 ((PSTORAGE_OFFLOAD_READ_OUTPUT)dsmAttributes)->TokenLength = 0;
14322 }
14323
14324 irp->IoStatus.Information = sizeof(STORAGE_OFFLOAD_READ_OUTPUT);
14325
14327 ClasspCleanupOffloadReadContext(OffloadReadContext);
14328 OffloadReadContext = NULL;
14329
14330 return;
14331}
14332
14333
14334VOID
14336 _In_ __drv_freesMem(mem) POFFLOAD_READ_CONTEXT OffloadReadContext
14337 )
14338
14339/*++
14340
14341Routine description:
14342
14343 This routine cleans up an OFFLOAD_READ_CONTEXT.
14344
14345Arguments:
14346
14347 OffloadReadContext - Pointer to the OFFLOAD_READ_CONTEXT for the offload
14348 read operation.
14349
14350Return Value:
14351
14352 None.
14353
14354--*/
14355
14356{
14357 PMDL populateTokenMdl;
14358
14359 populateTokenMdl = OffloadReadContext->PopulateTokenMdl;
14360
14361 NT_ASSERT(OffloadReadContext != NULL);
14362
14363 if (populateTokenMdl) {
14364 ClasspFreeDeviceMdl(populateTokenMdl);
14365 }
14366 FREE_POOL(OffloadReadContext);
14367
14368 return;
14369}
14370
14371
14373VOID
14375 _In_ POFFLOAD_READ_CONTEXT OffloadReadContext
14376 )
14377
14378/*++
14379
14380Routine description:
14381
14382 This routine retrieves the token after a PopulateToken command
14383 has been sent down.
14384
14385 Can also be called repeatedly for a single offload op when a previous
14386 RECEIVE ROD TOKEN INFORMATION for that op indicated that the operation was
14387 not yet complete.
14388
14389 This function is responsible for continuing or completing the offload read
14390 operation.
14391
14392Arguments:
14393
14394 OffloadReadContext - Pointer to the OFFLOAD_READ_CONTEXT for the offload
14395 read operation.
14396
14397Return Value:
14398
14399 None.
14400
14401--*/
14402
14403{
14404 PVOID buffer;
14406 ULONG cdbLength;
14407 PDEVICE_OBJECT fdo;
14408 PIRP irp;
14409 ULONG listIdentifier;
14410 PTRANSFER_PACKET pkt;
14411 PIRP pseudoIrp;
14412 ULONG receiveTokenInformationBufferLength;
14415 ULONG tempSizeUlong;
14416 PULONGLONG totalSectorsProcessed;
14417
14418 totalSectorsProcessed = &OffloadReadContext->TotalSectorsProcessed;
14419 buffer = OffloadReadContext + 1;
14420 bufferLength = OffloadReadContext->BufferLength;
14421 fdo = OffloadReadContext->Fdo;
14422 irp = OffloadReadContext->OffloadReadDsmIrp;
14423 receiveTokenInformationBufferLength = OffloadReadContext->ReceiveTokenInformationBufferLength;
14424 listIdentifier = OffloadReadContext->ListIdentifier;
14425
14426 TracePrint((TRACE_LEVEL_VERBOSE,
14427 TRACE_FLAG_IOCTL,
14428 "ClasspReceivePopulateTokenInformation (%p): Entering function. Irp %p\n",
14429 fdo,
14430 irp));
14431
14432 srb = &OffloadReadContext->Srb;
14433 *totalSectorsProcessed = 0;
14434
14435 pkt = DequeueFreeTransferPacket(fdo, TRUE);
14436 if (!pkt){
14437
14438 TracePrint((TRACE_LEVEL_ERROR,
14439 TRACE_FLAG_IOCTL,
14440 "ClasspReceivePopulateTokenInformation (%p): Failed to retrieve transfer packet for ReceiveTokenInformation (PopulateToken) operation.\n",
14441 fdo));
14442
14444 goto __ClasspReceivePopulateTokenInformation_ErrorExit;
14445 }
14446
14447 OffloadReadContext->Pkt = pkt;
14448
14450
14451 tempSizeUlong = receiveTokenInformationBufferLength - 4;
14452 REVERSE_BYTES(((PRECEIVE_TOKEN_INFORMATION_HEADER)buffer)->AvailableData, &tempSizeUlong);
14453
14454 pseudoIrp = &OffloadReadContext->PseudoIrp;
14455 RtlZeroMemory(pseudoIrp, sizeof(IRP));
14456
14457
14458 pseudoIrp->IoStatus.Status = STATUS_SUCCESS;
14459 pseudoIrp->IoStatus.Information = 0;
14460 pseudoIrp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
14461 pseudoIrp->MdlAddress = OffloadReadContext->PopulateTokenMdl;
14462
14463 ClasspSetupReceivePopulateTokenInformationTransferPacket(
14464 OffloadReadContext,
14465 pkt,
14466 receiveTokenInformationBufferLength,
14467 (PUCHAR)buffer,
14468 pseudoIrp,
14469 listIdentifier);
14470
14471 //
14472 // Cache away the CDB as it may be required for forwarded sense data
14473 // after this command completes.
14474 //
14475 RtlZeroMemory(srb, sizeof(*srb));
14476 cdbLength = SrbGetCdbLength(pkt->Srb);
14477 if (cdbLength <= 16) {
14478 RtlCopyMemory(&srb->Cdb, SrbGetCdb(pkt->Srb), cdbLength);
14479 }
14480
14482
14483 return;
14484
14485 //
14486 // Error cleanup label only - not used in success case:
14487 //
14488
14489__ClasspReceivePopulateTokenInformation_ErrorExit:
14490
14492
14493 //
14494 // ClasspCompleteOffloadRead also cleans up offloadReadContext.
14495 //
14496
14497 ClasspCompleteOffloadRead(OffloadReadContext, status);
14498
14499 return;
14500}
14501
14502
14503VOID
14506 )
14507
14508/*++
14509
14510Routine description:
14511
14512 This routine continues an offload read operation on completion of the
14513 RECEIVE ROD TOKEN INFORMATION transfer packet.
14514
14515 This routine is responsible for continuing or completing the offload read
14516 operation.
14517
14518Arguments:
14519
14520 Context - Pointer to the OFFLOAD_READ_CONTEXT for the offload read
14521 operation.
14522
14523Return Value:
14524
14525 None.
14526
14527--*/
14528
14529{
14530 ULONG availableData;
14531 PVOID buffer;
14532 UCHAR completionStatus;
14533 ULONG estimatedRetryInterval;
14534 PDEVICE_OBJECT fdo;
14536 PIRP irp;
14537 ULONG listIdentifier;
14538 POFFLOAD_READ_CONTEXT offloadReadContext;
14539 BOOLEAN operationCompleted;
14540 UCHAR operationStatus;
14541 PIRP pseudoIrp;
14542 USHORT segmentsProcessed;
14543 PSENSE_DATA senseData;
14544 ULONG senseDataFieldLength;
14545 UCHAR senseDataLength;
14548 PUCHAR token;
14549 PVOID tokenAscii;
14550 PBLOCK_DEVICE_TOKEN_DESCRIPTOR tokenDescriptor;
14551 ULONG tokenDescriptorLength;
14552 PRECEIVE_TOKEN_INFORMATION_HEADER tokenInformationResults;
14553 PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER tokenInformationResultsResponse;
14554 ULONG tokenLength;
14555 ULONG tokenSize;
14556 PULONGLONG totalSectorsProcessed;
14557 ULONGLONG totalSectorsToProcess;
14558 ULONGLONG transferBlockCount;
14559
14560 offloadReadContext = Context;
14561 fdo = offloadReadContext->Fdo;
14562 fdoExt = fdo->DeviceExtension;
14563 buffer = offloadReadContext + 1;
14564 listIdentifier = offloadReadContext->ListIdentifier;
14565 irp = offloadReadContext->OffloadReadDsmIrp;
14566 totalSectorsToProcess = offloadReadContext->TotalSectorsToProcess;
14567 totalSectorsProcessed = &offloadReadContext->TotalSectorsProcessed;
14568 srb = &offloadReadContext->Srb;
14569 tokenAscii = NULL;
14570 tokenSize = BLOCK_DEVICE_TOKEN_SIZE;
14571 tokenInformationResults = (PRECEIVE_TOKEN_INFORMATION_HEADER)buffer;
14572 senseData = (PSENSE_DATA)((PUCHAR)tokenInformationResults + FIELD_OFFSET(RECEIVE_TOKEN_INFORMATION_HEADER, SenseData));
14573 transferBlockCount = 0;
14574 tokenInformationResultsResponse = NULL;
14575 tokenDescriptor = NULL;
14576 operationCompleted = FALSE;
14577 tokenDescriptorLength = 0;
14578 tokenLength = 0;
14579 token = NULL;
14580 pseudoIrp = &offloadReadContext->PseudoIrp;
14581
14582 status = pseudoIrp->IoStatus.Status;
14584
14585 //
14586 // The buffer we hand allows for the max sizes for all the fields whereas the returned
14587 // data may be lesser (e.g. sense data info will almost never be MAX_SENSE_BUFFER_SIZE, etc.
14588 // so handle underrun "error"
14589 //
14590 if (status == STATUS_DATA_OVERRUN) {
14591
14593 }
14594
14595 if (!NT_SUCCESS(status)) {
14596 TracePrint((TRACE_LEVEL_ERROR,
14597 TRACE_FLAG_IOCTL,
14598 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Token retrieval failed for list Id %x with %x.\n",
14599 fdo,
14600 listIdentifier,
14601 status));
14602 goto __ClasspReceivePopulateTokenInformationTransferPacketDone_Exit;
14603 }
14604
14605 REVERSE_BYTES(&availableData, &tokenInformationResults->AvailableData);
14606
14609
14611
14612 operationStatus = tokenInformationResults->OperationStatus;
14613 operationCompleted = ClasspIsTokenOperationComplete(operationStatus);
14614 NT_ASSERT(operationCompleted);
14615
14616 REVERSE_BYTES(&estimatedRetryInterval, &tokenInformationResults->EstimatedStatusUpdateDelay);
14617
14618 completionStatus = tokenInformationResults->CompletionStatus;
14619
14621 REVERSE_BYTES_QUAD(&transferBlockCount, &tokenInformationResults->TransferCount);
14622
14623 REVERSE_BYTES_SHORT(&segmentsProcessed, &tokenInformationResults->SegmentsProcessed);
14624 NT_ASSERT(segmentsProcessed == 0);
14625
14626 if (operationCompleted) {
14627
14628 if (transferBlockCount > totalSectorsToProcess) {
14629
14630 //
14631 // Buggy or hostile target. Don't let it claim more was procesed
14632 // than was requested. Since this is likely a bug and it's unknown
14633 // how much was actually transferred, assume no data was
14634 // transferred.
14635 //
14636
14637 NT_ASSERT(transferBlockCount <= totalSectorsToProcess);
14638 transferBlockCount = 0;
14639 }
14640
14641 if (operationStatus != OPERATION_COMPLETED_WITH_SUCCESS &&
14642 operationStatus != OPERATION_COMPLETED_WITH_RESIDUAL_DATA) {
14643
14644 //
14645 // Assert on buggy response from target, but in any case, make sure not
14646 // to claim that any data was written.
14647 //
14648
14649 NT_ASSERT(transferBlockCount == 0);
14650 transferBlockCount = 0;
14651 }
14652
14653 //
14654 // Since the TokenOperation was sent down synchronously, the operation is complete as soon as the command returns.
14655 //
14656
14657 senseDataFieldLength = tokenInformationResults->SenseDataFieldLength;
14658 senseDataLength = tokenInformationResults->SenseDataLength;
14659 NT_ASSERT(senseDataFieldLength >= senseDataLength);
14660
14661 tokenInformationResultsResponse = (PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER)((PUCHAR)tokenInformationResults +
14663 tokenInformationResults->SenseDataFieldLength);
14664
14665 REVERSE_BYTES(&tokenDescriptorLength, &tokenInformationResultsResponse->TokenDescriptorsLength);
14666
14667 if (tokenDescriptorLength > 0) {
14668
14669 NT_ASSERT(tokenDescriptorLength == sizeof(BLOCK_DEVICE_TOKEN_DESCRIPTOR));
14670
14671 if (tokenDescriptorLength != sizeof(BLOCK_DEVICE_TOKEN_DESCRIPTOR)) {
14672
14673 TracePrint((TRACE_LEVEL_ERROR,
14674 TRACE_FLAG_IOCTL,
14675 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Bad firmware, token descriptor length %u.\n",
14676 fdo,
14677 tokenDescriptorLength));
14678
14679 NT_ASSERT((*totalSectorsProcessed) == 0);
14680 NT_ASSERT(tokenLength == 0);
14681
14682 } else {
14683
14684 USHORT restrictedId;
14685
14686 tokenDescriptor = (PBLOCK_DEVICE_TOKEN_DESCRIPTOR)tokenInformationResultsResponse->TokenDescriptor;
14687
14688 REVERSE_BYTES_SHORT(&restrictedId, &tokenDescriptor->TokenIdentifier);
14689 NT_ASSERT(restrictedId == 0);
14690
14691 tokenLength = BLOCK_DEVICE_TOKEN_SIZE;
14692 token = tokenDescriptor->Token;
14693
14694 *totalSectorsProcessed = transferBlockCount;
14695
14696 if (transferBlockCount < totalSectorsToProcess) {
14697
14699 operationStatus == OPERATION_COMPLETED_WITH_ERROR ||
14700 operationStatus == OPERATION_TERMINATED);
14701
14702 if (transferBlockCount == 0) {
14703 //
14704 // Treat the same as not getting a token.
14705 //
14706
14707 tokenLength = 0;
14708 }
14709
14710 } else {
14711
14712 NT_ASSERT(operationStatus == OPERATION_COMPLETED_WITH_SUCCESS);
14713 NT_ASSERT(transferBlockCount == totalSectorsToProcess);
14714 }
14715
14716 //
14717 // Need to convert to ascii.
14718 //
14719 tokenAscii = ClasspBinaryToAscii((PUCHAR)token,
14720 tokenSize,
14721 &tokenSize);
14722
14723 TracePrint((transferBlockCount == totalSectorsToProcess ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_WARNING,
14724 TRACE_FLAG_IOCTL,
14725 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): %wsToken %s generated successfully for list Id %x for data size %I64u bytes.\n",
14726 fdo,
14727 transferBlockCount == totalSectorsToProcess ? L"" : L"Target truncated read. ",
14728 (tokenAscii == NULL) ? "" : tokenAscii,
14729 listIdentifier,
14730 (*totalSectorsProcessed) * fdoExt->DiskGeometry.BytesPerSector));
14731
14732 FREE_POOL(tokenAscii);
14733 }
14734 } else {
14735
14736 TracePrint((TRACE_LEVEL_ERROR,
14737 TRACE_FLAG_IOCTL,
14738 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Target failed to generate a token for list Id %x for data size %I64u bytes (requested %I64u bytes).\n",
14739 fdo,
14740 listIdentifier,
14741 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector,
14742 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector));
14743
14744 *totalSectorsProcessed = 0;
14745
14746 NT_ASSERT(operationStatus == OPERATION_COMPLETED_WITH_ERROR);
14747 }
14748
14749 //
14750 // Operation that completes with success can have sense data (for target to pass on some extra info)
14751 // but we don't care about such sense info.
14752 // Operation that complete but not with success, may not have sense data associated, but may
14753 // have valid CompletionStatus.
14754 //
14755 // The "status" may be overriden by ClassInterpretSenseInfo(). Final
14756 // status is determined a bit later - this is just the default status
14757 // when ClassInterpretSenseInfo() doesn't get to run here.
14758 //
14760 if (operationStatus == OPERATION_COMPLETED_WITH_ERROR ||
14761 operationStatus == OPERATION_COMPLETED_WITH_RESIDUAL_DATA ||
14762 operationStatus == OPERATION_TERMINATED) {
14763
14764 SrbSetScsiStatus((PSTORAGE_REQUEST_BLOCK_HEADER)srb, completionStatus);
14765
14766 if (senseDataLength) {
14767
14768 ULONG retryInterval;
14769
14770 NT_ASSERT(senseDataLength <= sizeof(SENSE_DATA));
14771
14772 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
14773
14777
14779 srb,
14781 0,
14782 0,
14783 &status,
14784 &retryInterval);
14785
14786 TracePrint((TRACE_LEVEL_WARNING,
14787 TRACE_FLAG_IOCTL,
14788 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Reason for truncation/failure: %x - for list Id %x for data size %I64u bytes.\n",
14789 fdo,
14790 status,
14791 listIdentifier,
14792 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector));
14793 } else {
14794
14795 TracePrint((TRACE_LEVEL_WARNING,
14796 TRACE_FLAG_IOCTL,
14797 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): No sense data available but reason for truncation/failure, possibly: %x - for list Id %x for data size %I64u bytes.\n",
14798 fdo,
14799 completionStatus,
14800 listIdentifier,
14801 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector));
14802 }
14803 }
14804
14805 if (tokenLength > 0) {
14806
14807 offloadReadContext->Token = token;
14808
14809 //
14810 // Even if target returned an error, from the OS upper layers' perspective,
14811 // it is a success (with truncation) if any data at all was read.
14812 //
14814
14815 } else {
14816
14817 if (NT_SUCCESS(status)) {
14818 //
14819 // Make sure status is a failing status, without throwing away an
14820 // already-failing status obtained from sense data.
14821 //
14823 }
14824 }
14825
14826 //
14827 // Done with the operation.
14828 //
14829
14831 goto __ClasspReceivePopulateTokenInformationTransferPacketDone_Exit;
14832
14833 } else {
14834
14836
14837 TracePrint((TRACE_LEVEL_ERROR,
14838 TRACE_FLAG_IOCTL,
14839 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Token retrieval failed for list Id %x with %x.\n",
14840 fdo,
14841 listIdentifier,
14842 status));
14843
14844 NT_ASSERT(*totalSectorsProcessed == 0);
14845 goto __ClasspReceivePopulateTokenInformationTransferPacketDone_Exit;
14846 }
14847
14848__ClasspReceivePopulateTokenInformationTransferPacketDone_Exit:
14849
14850 if (status != STATUS_PENDING) {
14851
14852 //
14853 // The "status" value can be success or failure at this point, as
14854 // appropriate.
14855 //
14856
14857 ClasspCompleteOffloadRead(offloadReadContext, status);
14858 }
14859
14860 //
14861 // Due to tracing a potentially freed pointer value "Irp", this trace could
14862 // be delayed beyond another offload op picking up the same pointer value
14863 // for its Irp. This function exits after the operation is complete when
14864 // status != STATUS_PENDING.
14865 //
14866
14867 TracePrint((TRACE_LEVEL_VERBOSE,
14868 TRACE_FLAG_IOCTL,
14869 "ClasspReceivePopulateTokenInformationTransferPacketDone (%p): Exiting function (Irp %p) with internal status %x.\n",
14870 fdo,
14871 irp,
14872 status));
14873
14874 return;
14875}
14876
14877
14882ClasspServiceWriteUsingTokenTransferRequest(
14884 _In_ PIRP Irp
14885 )
14886
14887/*++
14888
14889Routine description:
14890
14891 This routine processes offload write requests by building the SRB
14892 for WriteUsingToken.
14893
14894Arguments:
14895
14896 Fdo - The functional device object processing the request
14897 Irp - The Io request to be processed
14898
14899Return Value:
14900
14901 STATUS_SUCCESS if successful, an error code otherwise
14902
14903--*/
14904
14905{
14906 ULONG allocationSize;
14907 PVOID buffer;
14909 PDEVICE_DATA_SET_RANGE dataSetRanges;
14910 ULONG dataSetRangesCount;
14912 ULONGLONG entireXferLen;
14914 ULONG i;
14915 ULONGLONG logicalBlockOffset;
14916 ULONG maxBlockDescrCount;
14917 ULONGLONG maxLbaCount;
14918 POFFLOAD_WRITE_CONTEXT offloadWriteContext;
14919 PDEVICE_DSM_OFFLOAD_WRITE_PARAMETERS offloadWriteParameters;
14920 ULONG receiveTokenInformationBufferLength;
14922 NTSTATUS tempStatus;
14923 BOOLEAN tokenInvalidated;
14924 ULONG tokenOperationBufferLength;
14925 PMDL writeUsingTokenMdl;
14926
14927 PAGED_CODE();
14928
14929 TracePrint((TRACE_LEVEL_VERBOSE,
14930 TRACE_FLAG_IOCTL,
14931 "ClasspServiceWriteUsingTokenTransferRequest (%p): Entering function. Irp %p.\n",
14932 Fdo,
14933 Irp));
14934
14935 fdoExt = Fdo->DeviceExtension;
14937 tempStatus = STATUS_SUCCESS;
14938 dsmAttributes = Irp->AssociatedIrp.SystemBuffer;
14939 buffer = NULL;
14940 writeUsingTokenMdl = NULL;
14941 offloadWriteParameters = Add2Ptr(dsmAttributes, dsmAttributes->ParameterBlockOffset);
14942 dataSetRanges = Add2Ptr(dsmAttributes, dsmAttributes->DataSetRangesOffset);
14943 dataSetRangesCount = dsmAttributes->DataSetRangesLength / sizeof(DEVICE_DATA_SET_RANGE);
14944 logicalBlockOffset = offloadWriteParameters->TokenOffset / fdoExt->DiskGeometry.BytesPerSector;
14945 tokenInvalidated = FALSE;
14946 bufferLength = 0;
14947
14948
14949 NT_ASSERT(fdoExt->FunctionSupportInfo->ValidInquiryPages.BlockDeviceRODLimits &&
14950 NT_SUCCESS(fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.CommandStatus));
14951
14952 for (i = 0, entireXferLen = 0; i < dataSetRangesCount; i++) {
14953 entireXferLen += dataSetRanges[i].LengthInBytes;
14954 }
14955
14956 //
14957 // We need to split the write request based on the following hardware limitations:
14958 // 1. The size of the data buffer containing the TokenOperation command's parameters must
14959 // not exceed the MaximumTransferLength (and max physical pages) of the underlying
14960 // adapter.
14961 // 2. The number of descriptors specified in the TokenOperation command must not exceed
14962 // the MaximumRangeDescriptors.
14963 // 3. The cumulative total of the number of transfer blocks in all the descriptors in
14964 // the TokenOperation command must not exceed the MaximumTokenTransferSize.
14965 //
14966 // In addition to the above, we need to ensure that for each of the descriptors in the
14967 // TokenOperation command:
14968 // 1. The number of blocks specified is an exact multiple of the OptimalTransferLengthGranularity.
14969 // 2. The number of blocks specified is limited to the MaximumTransferLength. (We shall
14970 // however, limit the number of blocks specified in each descriptor to be a maximum of
14971 // OptimalTransferLength or MaximumTransferLength, whichever is lesser).
14972 //
14973 // Finally, we shall always send down the WriteUsingToken command using IMMED = 0 for this
14974 // release. This makes it simpler to handle multi-initiator scenarios since we won't need
14975 // to deal with the WriteUsingToken (with IMMED = 1) succeeding but ReceiveRODTokenInformation
14976 // failing due to the path/node failing, thus making it impossible to retrieve results of
14977 // the data transfer operation, or to cancel the data transfer via CopyOperationAbort.
14978 // Since a write data transfer of a large amount of data may take a long time when sent
14979 // down IMMED = 0, we shall limit the size to a maximum of 256MB even if it means truncating
14980 // the original requested size to this capped size. The application is expected to deal with
14981 // this truncation.
14982 // (NOTE: the cap of 256MB is chosen to match with the Copy Engine's chunk size).
14983 //
14984 // The LBA ranges is in DEVICE_DATA_SET_RANGE format, it needs to be converted into
14985 // WINDOWS_BLOCK_DEVICE_RANGE_DESCRIPTOR Block Descriptors.
14986 //
14987
14990 &bufferLength,
14991 &tokenOperationBufferLength,
14992 &receiveTokenInformationBufferLength);
14993
14994 allocationSize = sizeof(OFFLOAD_WRITE_CONTEXT) + bufferLength;
14995
14996 offloadWriteContext = ExAllocatePoolWithTag(
14997 NonPagedPoolNx,
14998 allocationSize,
15000
15001 if (!offloadWriteContext) {
15002
15003 TracePrint((TRACE_LEVEL_ERROR,
15004 TRACE_FLAG_IOCTL,
15005 "ClasspServiceWriteUsingTokenTransferRequest (%p): Failed to allocate buffer for WriteUsingToken operations.\n",
15006 Fdo));
15007
15009 goto __ClasspServiceWriteUsingTokenTransferRequest_ErrorExit;
15010 }
15011
15012 //
15013 // Only zero the context portion here. The buffer portion is zeroed for
15014 // each sub-request.
15015 //
15016 RtlZeroMemory(offloadWriteContext, sizeof(OFFLOAD_WRITE_CONTEXT));
15017
15018 offloadWriteContext->Fdo = Fdo;
15019 offloadWriteContext->OffloadWriteDsmIrp = Irp;
15020 offloadWriteContext->OperationStartTime = KeQueryInterruptTime();
15021
15022 //
15023 // The buffer for the commands is after the offloadWriteContext.
15024 //
15025 buffer = (offloadWriteContext + 1);
15026
15027 //
15028 // Set up fields that allow iterating through whole request, by issuing sub-
15029 // requests which each do some of the writing. Because of truncation by the
15030 // target, it's not known exactly how many bytes will be written by the
15031 // target in each sub-request (can be less than requested), so the
15032 // progress through the outer request must only commit the move through the
15033 // upper DSM ranges when a lower request is done and the number of written
15034 // sectors is known.
15035 //
15036
15037 NT_ASSERT(offloadWriteContext->TotalSectorsProcessedSuccessfully == 0);
15038 offloadWriteContext->TotalRequestSizeSectors = entireXferLen / fdoExt->DiskGeometry.BytesPerSector;
15039 NT_ASSERT(offloadWriteContext->DataSetRangeIndex == 0);
15040 NT_ASSERT(offloadWriteContext->DataSetRangeByteOffset == 0);
15041 offloadWriteContext->DataSetRangesCount = dataSetRangesCount;
15042
15043 offloadWriteContext->DsmAttributes = dsmAttributes;
15044 offloadWriteContext->OffloadWriteParameters = offloadWriteParameters;
15045 offloadWriteContext->DataSetRanges = dataSetRanges;
15046 offloadWriteContext->LogicalBlockOffset = logicalBlockOffset;
15047
15050 tokenOperationBufferLength,
15051 &maxBlockDescrCount,
15052 &maxLbaCount);
15053
15054 if (fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount && fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize) {
15055
15056 NT_ASSERT(fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount <= fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.MaximumTokenTransferSize);
15057 }
15058
15059 //
15060 // We will limit the maximum data transfer in an offload write operation to:
15061 // - 64MB if OptimalTransferCount = 0
15062 // - OptimalTransferCount if < 256MB
15063 // - 256MB if OptimalTransferCount >= 256MB
15064 // - MaximumTokenTransferSize if lesser than above chosen size
15065 //
15066 if (0 == fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount) {
15067
15069
15070 } else if (fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount < (MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN / (ULONGLONG)fdoExt->DiskGeometry.BytesPerSector)) {
15071
15072 maxLbaCount = MIN(maxLbaCount, fdoExt->FunctionSupportInfo->BlockDeviceRODLimitsData.OptimalTransferCount);
15073
15074 } else {
15075
15077 }
15078
15079 //
15080 // Since we do not want very fragmented files to end up causing the WriteUsingToken command to take
15081 // too long (and potentially timeout), we will limit the max number of descriptors sent down in a
15082 // command.
15083 //
15084 maxBlockDescrCount = MIN(maxBlockDescrCount, MAX_NUMBER_BLOCK_DEVICE_DESCRIPTORS);
15085
15086 TracePrint((TRACE_LEVEL_INFORMATION,
15087 TRACE_FLAG_IOCTL,
15088 "ClasspServiceWriteUsingTokenTransferRequest (%p): Using MaxBlockDescrCount %u and MaxLbaCount %I64u.\n",
15089 Fdo,
15090 maxBlockDescrCount,
15091 maxLbaCount));
15092
15093 offloadWriteContext->MaxBlockDescrCount = maxBlockDescrCount;
15094 offloadWriteContext->MaxLbaCount = maxLbaCount;
15095
15096 //
15097 // Reuse a single buffer for both TokenOperation and ReceiveTokenInformation. This has the one disadvantage
15098 // that we'll be marking the page(s) as IoWriteAccess even though we only need read access for token
15099 // operation command and we may not even need to send down a ReceiveTokenInformation (in case of a successful
15100 // synchronous transfer). However, the advantage is that we eliminate the possibility of any potential
15101 // failures when trying to allocate an MDL for the ReceiveTokenInformation later on if we need to send it.
15102 //
15103 writeUsingTokenMdl = ClasspBuildDeviceMdl(buffer, bufferLength, FALSE);
15104 if (!writeUsingTokenMdl) {
15105
15106 TracePrint((TRACE_LEVEL_ERROR,
15107 TRACE_FLAG_IOCTL,
15108 "ClasspServiceWriteUsingTokenTransferRequest (%p): Failed to allocate MDL for WriteUsingToken operations.\n",
15109 Fdo));
15110
15112 goto __ClasspServiceWriteUsingTokenTransferRequest_ErrorExit;
15113 }
15114
15115 offloadWriteContext->WriteUsingTokenMdl = writeUsingTokenMdl;
15116
15117 //
15118 // There are potentially two approaches that we can take:
15119 // 1. Determine how many transfer packets we need (in case we need to split the request), get
15120 // them all up-front and then send down all the split WriteUsingToken commands in parallel.
15121 // The benefit of this approach is that the performance will be improved in the success case.
15122 // But error case handling becomes very complex to handle, since if one of the intermediate
15123 // write fails, there is no way to cancel the remaining writes that were sent. Waiting for
15124 // such requests to complete in geo-distributed source and target cases can be very time
15125 // consuming. The complexity gets worse in the case that the target succeeds only a partial
15126 // amount of data for one the of intermediate split commands.
15127 // [OR]
15128 // 2. Until the entire data set range is processed, build the command for as much of the range as
15129 // possible, send down a packet, and once it completes, repeat sequentially in a loop.
15130 // The advantage of this approach is its simplistic nature. In the success case, it will
15131 // be less performant as compared to the previous approach, but since the gain of offload
15132 // copy is so significant compared to native buffered-copy, the tradeoff is acceptable.
15133 // In the failure case the simplicity offers the following benefit - if any command fails,
15134 // there is no further processing that is needed. And the cumulative total bytes that succeeded
15135 // (until the failing split WriteUsingToken command) is easily tracked.
15136 //
15137 // Given the above, we're going with the second approach.
15138 //
15139
15140 NT_ASSERT(status == STATUS_SUCCESS); // so far
15141
15142 //
15143 // Save (into the offloadReadContext) any remaining things that
15144 // ClasspPopulateTokenTransferPacketDone() will need.
15145 //
15146
15147 offloadWriteContext->BufferLength = bufferLength;
15148 offloadWriteContext->ReceiveTokenInformationBufferLength = receiveTokenInformationBufferLength;
15149 offloadWriteContext->EntireXferLen = entireXferLen;
15150
15152 ClasspContinueOffloadWrite(offloadWriteContext);
15153
15155 goto __ClasspServiceWriteUsingTokenTransferRequest_Exit;
15156
15157 //
15158 // Error label only - not used in success case:
15159 //
15160
15161__ClasspServiceWriteUsingTokenTransferRequest_ErrorExit:
15162
15164
15165 if (offloadWriteContext != NULL) {
15166 ClasspCleanupOffloadWriteContext(offloadWriteContext);
15167 offloadWriteContext = NULL;
15168 }
15169
15170__ClasspServiceWriteUsingTokenTransferRequest_Exit:
15171
15172 TracePrint((TRACE_LEVEL_VERBOSE,
15173 TRACE_FLAG_IOCTL,
15174 "ClasspServiceWriteUsingTokenTransferRequest (%p): Exiting function (Irp %p) with status %x.\n",
15175 Fdo,
15176 Irp,
15177 status));
15178
15179 return status;
15180}
15181
15182
15183VOID
15184#ifdef _MSC_VER
15185#pragma warning(suppress: 28194) // This function will either alias or free OffloadWriteContext
15186#endif
15188 _In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext
15189 )
15190
15191/*++
15192
15193Routine description:
15194
15195 This routine continues an offload write operation. This routine expects the
15196 offload write operation to be set up and ready to start a WRITE USING TOKEN,
15197 but with no WRITE USING TOKEN currently in flight.
15198
15199 This routine is responsible for continuing or completing the offload write
15200 operation.
15201
15202Arguments:
15203
15204 OffloadWriteContext - Pointer to the OFFLOAD_WRITE_CONTEXT for the offload
15205 write operation.
15206
15207Return Value:
15208
15209 None.
15210
15211--*/
15212
15213{
15214 BOOLEAN allDataSetRangeFullyConverted;
15215 ULONG blockDescrIndex;
15216 PBLOCK_DEVICE_RANGE_DESCRIPTOR blockDescrPointer;
15217 PVOID buffer;
15219 ULONGLONG dataSetRangeByteOffset;
15220 ULONG dataSetRangeIndex;
15221 PDEVICE_DATA_SET_RANGE dataSetRanges;
15222 ULONG dataSetRangesCount;
15223 ULONGLONG entireXferLen;
15224 PDEVICE_OBJECT fdo;
15226 PIRP irp;
15227 ULONG lbaCount;
15228 ULONG listIdentifier;
15229 ULONGLONG logicalBlockOffset;
15230 ULONG maxBlockDescrCount;
15231 ULONGLONG maxLbaCount;
15232 PDEVICE_DSM_OFFLOAD_WRITE_PARAMETERS offloadWriteParameters;
15233 PTRANSFER_PACKET pkt;
15234 PIRP pseudoIrp;
15236 DEVICE_DATA_SET_RANGE tempDataSetRange;
15237 BOOLEAN tempDataSetRangeFullyConverted;
15238 PVOID tokenAscii;
15239 ULONG tokenSize;
15240 ULONGLONG totalSectorCount;
15241 ULONGLONG totalSectorsProcessedSuccessfully;
15242 ULONGLONG totalSectorsToProcess;
15243 ULONG transferSize;
15244 USHORT writeUsingTokenDataLength;
15245 USHORT writeUsingTokenDescriptorsLength;
15246 PMDL writeUsingTokenMdl;
15247
15248 tokenAscii = NULL;
15249 tokenSize = BLOCK_DEVICE_TOKEN_SIZE;
15250 tempDataSetRangeFullyConverted = FALSE;
15251 allDataSetRangeFullyConverted = FALSE;
15252 fdo = OffloadWriteContext->Fdo;
15253 fdoExt = fdo->DeviceExtension;
15254 irp = OffloadWriteContext->OffloadWriteDsmIrp;
15255 buffer = OffloadWriteContext + 1;
15256 bufferLength = OffloadWriteContext->BufferLength;
15257 dataSetRanges = OffloadWriteContext->DataSetRanges;
15258 offloadWriteParameters = OffloadWriteContext->OffloadWriteParameters;
15259 pseudoIrp = &OffloadWriteContext->PseudoIrp;
15260 writeUsingTokenMdl = OffloadWriteContext->WriteUsingTokenMdl;
15261 entireXferLen = OffloadWriteContext->EntireXferLen;
15262
15264
15265 pkt = DequeueFreeTransferPacket(fdo, TRUE);
15266 if (!pkt){
15267
15268 TracePrint((TRACE_LEVEL_ERROR,
15269 TRACE_FLAG_IOCTL,
15270 "ClasspContinueOffloadWrite (%p): Failed to retrieve transfer packet for TokenOperation (WriteUsingToken) operation.\n",
15271 fdo));
15272
15274 goto __ClasspContinueOffloadWrite_ErrorExit;
15275 }
15276
15277 OffloadWriteContext->Pkt = pkt;
15278
15279 blockDescrPointer = (PBLOCK_DEVICE_RANGE_DESCRIPTOR)
15280 &((PWRITE_USING_TOKEN_HEADER)buffer)->BlockDeviceRangeDescriptor[0];
15281
15282 blockDescrIndex = 0;
15283 lbaCount = 0;
15284
15285 totalSectorsToProcess = 0;
15286
15287 maxBlockDescrCount = OffloadWriteContext->MaxBlockDescrCount;
15288 maxLbaCount = OffloadWriteContext->MaxLbaCount;
15289
15290 //
15291 // The OffloadWriteContext->DataSetRangeIndex, DataSetRangeByteOffset, and
15292 // TotalSectorsProcessedSuccessfully don't move forward until RRTI has
15293 // reported the actual amount written.
15294 //
15295 // For that reason, this function only updates
15296 // OffloadWriteContext->TotalSectorsProcessed, which tracks the number of
15297 // sectors requested to be written by the current WRITE USING TOKEN command
15298 // (not all will necessarily be written).
15299 //
15300
15301 dataSetRangeIndex = OffloadWriteContext->DataSetRangeIndex;
15302 dataSetRangesCount = OffloadWriteContext->DataSetRangesCount;
15303 dataSetRangeByteOffset = OffloadWriteContext->DataSetRangeByteOffset;
15304 totalSectorsProcessedSuccessfully = OffloadWriteContext->TotalSectorsProcessedSuccessfully;
15305
15306 //
15307 // Send WriteUsingToken commands when the buffer is full or all input entries are converted.
15308 //
15309 while (!((blockDescrIndex == maxBlockDescrCount) || // buffer full or block descriptor count reached
15310 (lbaCount == maxLbaCount) || // block LBA count reached
15311 (allDataSetRangeFullyConverted))) { // all DataSetRanges have been converted
15312
15313 NT_ASSERT(dataSetRangeIndex < dataSetRangesCount);
15314 NT_ASSERT(dataSetRangeByteOffset < dataSetRanges[dataSetRangeIndex].LengthInBytes);
15315
15316 tempDataSetRange.StartingOffset = dataSetRanges[dataSetRangeIndex].StartingOffset + dataSetRangeByteOffset;
15317 tempDataSetRange.LengthInBytes = dataSetRanges[dataSetRangeIndex].LengthInBytes - dataSetRangeByteOffset;
15318
15319 totalSectorCount = 0;
15320
15321 ClasspConvertDataSetRangeToBlockDescr(fdo,
15322 blockDescrPointer,
15323 &blockDescrIndex,
15324 maxBlockDescrCount,
15325 &lbaCount,
15326 maxLbaCount,
15327 &tempDataSetRange,
15328 &totalSectorCount);
15329
15330 tempDataSetRangeFullyConverted = (tempDataSetRange.LengthInBytes == 0) ? TRUE : FALSE;
15331
15332 allDataSetRangeFullyConverted = tempDataSetRangeFullyConverted && ((dataSetRangeIndex + 1) == dataSetRangesCount);
15333
15334 if (tempDataSetRangeFullyConverted) {
15335 dataSetRangeIndex += 1;
15336 dataSetRangeByteOffset = 0;
15337 NT_ASSERT(dataSetRangeIndex <= dataSetRangesCount);
15338 } else {
15339 dataSetRangeByteOffset += totalSectorCount * fdoExt->DiskGeometry.BytesPerSector;
15340 NT_ASSERT(dataSetRangeByteOffset < dataSetRanges[dataSetRangeIndex].LengthInBytes);
15341 }
15342
15343 totalSectorsToProcess += totalSectorCount;
15344 }
15345
15346 //
15347 // Save the number of sectors being attempted in this WRITE USING TOKEN
15348 // command, so that a success return from the command will know how much
15349 // was written, without needing to issue a RECEIVE ROD TOKEN INFORMATION
15350 // command.
15351 //
15352 OffloadWriteContext->TotalSectorsToProcess = totalSectorsToProcess;
15353 OffloadWriteContext->TotalSectorsProcessed = 0;
15354
15355 //
15356 // Calculate transfer size, including the header
15357 //
15358 transferSize = (blockDescrIndex * sizeof(BLOCK_DEVICE_RANGE_DESCRIPTOR)) + FIELD_OFFSET(WRITE_USING_TOKEN_HEADER, BlockDeviceRangeDescriptor);
15359
15361
15362 writeUsingTokenDataLength = (USHORT)transferSize - RTL_SIZEOF_THROUGH_FIELD(WRITE_USING_TOKEN_HEADER, WriteUsingTokenDataLength);
15363 REVERSE_BYTES_SHORT(((PWRITE_USING_TOKEN_HEADER)buffer)->WriteUsingTokenDataLength, &writeUsingTokenDataLength);
15364
15365 ((PWRITE_USING_TOKEN_HEADER)buffer)->Immediate = 0;
15366
15367 logicalBlockOffset = OffloadWriteContext->LogicalBlockOffset + totalSectorsProcessedSuccessfully;
15368 REVERSE_BYTES_QUAD(((PWRITE_USING_TOKEN_HEADER)buffer)->BlockOffsetIntoToken, &logicalBlockOffset);
15369
15371 &offloadWriteParameters->Token,
15373
15374 writeUsingTokenDescriptorsLength = (USHORT)transferSize - FIELD_OFFSET(WRITE_USING_TOKEN_HEADER, BlockDeviceRangeDescriptor);
15375 REVERSE_BYTES_SHORT(((PWRITE_USING_TOKEN_HEADER)buffer)->BlockDeviceRangeDescriptorListLength, &writeUsingTokenDescriptorsLength);
15376
15377 RtlZeroMemory(pseudoIrp, sizeof(IRP));
15378
15379 pseudoIrp->IoStatus.Status = STATUS_SUCCESS;
15380 pseudoIrp->IoStatus.Information = 0;
15381 pseudoIrp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
15382 pseudoIrp->MdlAddress = writeUsingTokenMdl;
15383
15385 listIdentifier = InterlockedIncrement((volatile LONG *)&TokenOperationListIdentifier);
15386
15387 ClasspSetupWriteUsingTokenTransferPacket(
15388 OffloadWriteContext,
15389 pkt,
15390 transferSize,
15391 (PUCHAR)buffer,
15392 pseudoIrp,
15393 listIdentifier);
15394
15396 tokenSize,
15397 &tokenSize);
15398
15399 TracePrint((TRACE_LEVEL_INFORMATION,
15400 TRACE_FLAG_IOCTL,
15401 "ClasspContinueOffloadWrite (%p): Offloading write for %I64u bytes (versus %I64u) [via %u descriptors]. \
15402 \n\t\t\tDataLength: %u, DescriptorsLength: %u. Pkt %p (list id %x) [Token: %s]\n",
15403 fdo,
15404 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector,
15405 entireXferLen,
15406 blockDescrIndex,
15407 writeUsingTokenDataLength,
15408 writeUsingTokenDescriptorsLength,
15409 pkt,
15410 listIdentifier,
15411 (tokenAscii == NULL) ? "" : tokenAscii));
15412
15413 FREE_POOL(tokenAscii);
15414
15415 OffloadWriteContext->ListIdentifier = listIdentifier;
15416
15418
15419 //
15420 // ClasspWriteUsingTokenTransferPacketDone() takes care of completing the
15421 // IRP, so this function is done.
15422 //
15423
15424 return;
15425
15426 //
15427 // Error cleaup label only - not used in success case:
15428 //
15429
15430__ClasspContinueOffloadWrite_ErrorExit:
15431
15433
15434 //
15435 // ClasspCompleteOffloadWrite also cleans up offloadWriteContext.
15436 //
15437
15438 ClasspCompleteOffloadWrite(OffloadWriteContext, status);
15439
15440 return;
15441}
15442
15443
15444VOID
15446 _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
15447 _In_ ULONGLONG SectorsToAdvance
15448 )
15449
15450/*++
15451
15452Routine description:
15453
15454 After the target has responded to WRITE USING TOKEN with success, or RRTI
15455 with a specific TRANSFER COUNT, this routine is used to update the relative
15456 position within the overall offload write request. This position includes
15457 the TotalSectorsProcessedSuccessfully, the DataSetRangeIndex, and the
15458 DataSetRangeByteOffset.
15459
15460 The caller is responsible for continuing or completing the offload write
15461 operation (this routine doesn't do that).
15462
15463Arguments:
15464
15465 OffloadWriteContext - Pointer to the OFFLOAD_WRITE_CONTEXT for the offload
15466 write operation.
15467
15468 SectorsToAdvance - The number of sectors which were just written
15469 successfully (not the total for the offload write operation overall,
15470 just the number done by the most recent WRITE USING TOKEN).
15471
15472Return Value:
15473
15474 None.
15475
15476--*/
15477
15478{
15479 ULONGLONG bytesToAdvance;
15480 ULONGLONG bytesToDo;
15481 PULONGLONG dataSetRangeByteOffset;
15482 PULONG dataSetRangeIndex;
15483 PDEVICE_DATA_SET_RANGE dataSetRanges;
15484 PDEVICE_OBJECT fdo;
15486 PULONGLONG totalSectorsProcessedSuccessfully;
15487
15488 fdo = OffloadWriteContext->Fdo;
15489 fdoExt = fdo->DeviceExtension;
15490 dataSetRanges = OffloadWriteContext->DataSetRanges;
15491 dataSetRangeByteOffset = &OffloadWriteContext->DataSetRangeByteOffset;
15492 dataSetRangeIndex = &OffloadWriteContext->DataSetRangeIndex;
15493 totalSectorsProcessedSuccessfully = &OffloadWriteContext->TotalSectorsProcessedSuccessfully;
15494 bytesToAdvance = SectorsToAdvance * fdoExt->DiskGeometry.BytesPerSector;
15495
15496 (*totalSectorsProcessedSuccessfully) += SectorsToAdvance;
15497 NT_ASSERT((*totalSectorsProcessedSuccessfully) <= OffloadWriteContext->TotalRequestSizeSectors);
15498
15499 while (bytesToAdvance != 0) {
15500 bytesToDo = dataSetRanges[*dataSetRangeIndex].LengthInBytes - *dataSetRangeByteOffset;
15501 if (bytesToDo > bytesToAdvance) {
15502 bytesToDo = bytesToAdvance;
15503 }
15504 (*dataSetRangeByteOffset) += bytesToDo;
15505 bytesToAdvance -= bytesToDo;
15506 if ((*dataSetRangeByteOffset) == dataSetRanges[*dataSetRangeIndex].LengthInBytes) {
15507 (*dataSetRangeIndex) += 1;
15508 (*dataSetRangeByteOffset) = 0;
15509 }
15510 }
15511
15512 NT_ASSERT((*dataSetRangeIndex) <= OffloadWriteContext->DataSetRangesCount);
15513
15514 return;
15515}
15516
15517
15518VOID
15521 )
15522
15523/*++
15524
15525Routine description:
15526
15527 This routine continues an offload write operation when the WRITE USING
15528 TOKEN transfer packet completes.
15529
15530 This routine may be able to determine that all requested sectors were
15531 written if the WRITE USING TOKEN completed with success, or may need to
15532 issue a RECEIVE ROD TOKEN INFORMATION if the WRITE USING TOKEN indicated
15533 check condition.
15534
15535 This routine is responsible for continuing or completing the offload write
15536 operation.
15537
15538Arguments:
15539
15540 Context - Pointer to the OFFLOAD_WRITE_CONTEXT for the offload write
15541 operation.
15542
15543Return Value:
15544
15545 None.
15546
15547--*/
15548
15549{
15550 ULONGLONG entireXferLen;
15551 PDEVICE_OBJECT fdo;
15553 ULONG listIdentifier;
15554 POFFLOAD_WRITE_CONTEXT offloadWriteContext;
15555 PTRANSFER_PACKET pkt;
15556 PIRP pseudoIrp;
15558 PBOOLEAN tokenInvalidated;
15559 ULONGLONG totalSectorsToProcess;
15560
15561 offloadWriteContext = Context;
15562 pseudoIrp = &offloadWriteContext->PseudoIrp;
15563 fdo = offloadWriteContext->Fdo;
15564 fdoExt = fdo->DeviceExtension;
15565 listIdentifier = offloadWriteContext->ListIdentifier;
15566 totalSectorsToProcess = offloadWriteContext->TotalSectorsToProcess;
15567 entireXferLen = offloadWriteContext->EntireXferLen;
15568 tokenInvalidated = &offloadWriteContext->TokenInvalidated;
15569 pkt = offloadWriteContext->Pkt;
15570
15571 offloadWriteContext->Pkt = NULL;
15572
15573
15574 status = pseudoIrp->IoStatus.Status;
15576
15577 //
15578 // If the request failed with any of the following errors, then it is meaningless to send
15579 // down a ReceiveTokenInformation (regardless of whether the transfer was requested as sync
15580 // or async), since the target has no saved information about the command:
15581 // - STATUS_INVALID_TOKEN
15582 // - STATUS_INVALID_PARAMETER
15583 //
15586
15587 TracePrint((TRACE_LEVEL_ERROR,
15588 TRACE_FLAG_IOCTL,
15589 "ClasspWriteUsingTokenTransferPacketDone (%p): Write failed with %x (list id %x).\n",
15590 fdo,
15591 status,
15592 listIdentifier));
15593
15594 //
15595 // If the token isn't valid any longer, we should let the upper layers know so that
15596 // they don't waste time retrying the write with the same token.
15597 //
15599
15600 *tokenInvalidated = TRUE;
15601 }
15602
15604 goto __ClasspWriteUsingTokenTransferPacketDone_Exit;
15605
15606 } else if ((NT_SUCCESS(status)) &&
15607 (pkt->Srb->SrbStatus == SRB_STATUS_SUCCESS || pkt->TransferCount != 0)) {
15608
15609 //
15610 // If the TokenOperation command was sent to the target requesting synchronous data
15611 // transfer, a success indicates that the command is complete.
15612 // This could either be because of a successful completion of the entire transfer
15613 // or because of a partial transfer due to target truncation. If it is the latter,
15614 // and the information field of the sense data has returned the TransferCount, we
15615 // can avoid sending down an RRTI.
15616 //
15617 if (pkt->Srb->SrbStatus == SRB_STATUS_SUCCESS) {
15618
15619 //
15620 // The entire transfer has completed successfully.
15621 //
15622 offloadWriteContext->TotalSectorsProcessed = totalSectorsToProcess;
15623 TracePrint((TRACE_LEVEL_INFORMATION,
15624 TRACE_FLAG_IOCTL,
15625 "ClasspWriteUsingTokenTransferPacketDone (%p): Successfully wrote using token %I64u (out of %I64u) bytes (list Id %x).\n",
15626 fdo,
15627 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector,
15628 entireXferLen,
15629 listIdentifier));
15630 } else {
15631
15632 //
15633 // The target has returned how much data it transferred in the response to the
15634 // WUT command itself, allowing us to optimize by removing the necessaity for
15635 // sending down an RRTI to query the TransferCount.
15636 //
15638
15639 offloadWriteContext->TotalSectorsProcessed = totalSectorsToProcess = pkt->TransferCount;
15640 TracePrint((TRACE_LEVEL_INFORMATION,
15641 TRACE_FLAG_IOCTL,
15642 "ClasspWriteUsingTokenTransferPacketDone (%p): Target truncated write using token %I64u (out of %I64u) bytes (list Id %x).\n",
15643 fdo,
15644 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector,
15645 entireXferLen,
15646 listIdentifier));
15647 }
15648
15649 ClasspAdvanceOffloadWritePosition(offloadWriteContext, totalSectorsToProcess);
15650
15652
15653 //
15654 // ClasspReceiveWriteUsingTokenInformationDone() takes care of
15655 // completing the operation (eventually), so pending from point of view
15656 // of this function.
15657 //
15658
15661
15662 goto __ClasspWriteUsingTokenTransferPacketDone_Exit;
15663
15664 } else {
15665
15666 //
15667 // Since the TokenOperation was failed (or the target truncated the transfer but
15668 // didn't indicate the amount), we need to send down ReceiveTokenInformation.
15669 //
15670 TracePrint((TRACE_LEVEL_ERROR,
15671 TRACE_FLAG_IOCTL,
15672 "ClasspWriteUsingTokenTransferPacketDone (%p): Write failed with status %x, %x (list id %x).\n",
15673 fdo,
15674 status,
15675 pkt->Srb->SrbStatus,
15676 listIdentifier));
15677
15678 ClasspReceiveWriteUsingTokenInformation(offloadWriteContext);
15679
15681 goto __ClasspWriteUsingTokenTransferPacketDone_Exit;
15682 }
15683
15684__ClasspWriteUsingTokenTransferPacketDone_Exit:
15685
15686 if (status != STATUS_PENDING) {
15687 ClasspCompleteOffloadWrite(offloadWriteContext, status);
15688 }
15689
15690 return;
15691}
15692
15693
15694VOID
15696 _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
15697 _In_ NTSTATUS CompletionCausingStatus
15698 )
15699
15700/*++
15701
15702Routine description:
15703
15704 This routine continues an offload write operation when a WRITE USING TOKEN
15705 and possible associated RECEIVE ROD TOKEN INFORMATION have both fully
15706 completed and the RRTI has indicated completion of the WUT.
15707
15708 This routine checks to see if the total sectors written is already equal to
15709 the overall total requested sector count, and if so, completes the offload
15710 write operation. If not, this routine continues the operation by issuing
15711 another WUT.
15712
15713 This routine is responsible for continuing or completing the offload write
15714 operation.
15715
15716Arguments:
15717
15718 OffloadWriteContext - Pointer to the OFFLOAD_WRITE_CONTEXT for the offload
15719 write operation.
15720
15721Return Value:
15722
15723 None.
15724
15725--*/
15726
15727{
15728 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = OffloadWriteContext->Fdo->DeviceExtension;
15729 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
15730
15731 //
15732 // Time taken in 100ns units.
15733 //
15734 ULONGLONG durationIn100ns = (KeQueryInterruptTime() - OffloadWriteContext->OperationStartTime);
15735 ULONGLONG maxTargetDuration = fdoData->CopyOffloadMaxTargetDuration * 10ULL * 1000 * 1000;
15736
15737 NT_ASSERT(
15738 OffloadWriteContext->TotalSectorsProcessedSuccessfully <=
15739 OffloadWriteContext->TotalRequestSizeSectors);
15740
15741
15742 if (OffloadWriteContext->TotalSectorsProcessedSuccessfully == OffloadWriteContext->TotalRequestSizeSectors) {
15743
15744 ClasspCompleteOffloadWrite(OffloadWriteContext, CompletionCausingStatus);
15745
15746 goto __ClasspReceiveWriteUsingTokenInformationDone_Exit;
15747 }
15748
15749 //
15750 // Since we don't want a layered timeout mechanism (e.g. guest and parent OS in Hyper-V scenarios)
15751 // to cause a SCSI timeout for the higher layer token operations.
15752 //
15753 if (maxTargetDuration <= durationIn100ns) {
15754
15755 TracePrint((TRACE_LEVEL_WARNING,
15756 TRACE_FLAG_IOCTL,
15757 "ClasspReceiveWriteUsingTokenInformationDone (%p): Truncating write (list id %x) because of max-duration-rule.\n",
15758 OffloadWriteContext->Fdo,
15759 OffloadWriteContext->ListIdentifier));
15760
15761 //
15762 // We could technically pass in STATUS_IO_OPERATION_TIMEOUT, but ClasspCompleteOffloadWrite
15763 // won't end up doing anything (useful) with this status, since some bytes would already
15764 // have been transferred.
15765 //
15766 ClasspCompleteOffloadWrite(OffloadWriteContext, STATUS_UNSUCCESSFUL);
15767
15768 goto __ClasspReceiveWriteUsingTokenInformationDone_Exit;
15769 }
15770
15771 NT_ASSERT(
15772 OffloadWriteContext->TotalSectorsProcessedSuccessfully <
15773 OffloadWriteContext->TotalRequestSizeSectors);
15774
15775 //
15776 // Keep going with the next sub-request.
15777 //
15778
15779 ClasspContinueOffloadWrite(OffloadWriteContext);
15780
15781__ClasspReceiveWriteUsingTokenInformationDone_Exit:
15782
15783 return;
15784}
15785
15786
15787VOID
15789 _In_ __drv_freesMem(Mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
15790 _In_ NTSTATUS CompletionCausingStatus
15791 )
15792
15793/*++
15794
15795Routine description:
15796
15797 This routine is used to complete an offload write operation.
15798
15799 The input CompletionCausingStatus doesn't necessarily drive the completion
15800 status of the offload write operation overall, if the offload write
15801 operation overall has previously written some sectors successfully.
15802
15803 This routine completes the offload write operation.
15804
15805Arguments:
15806
15807 OffloadWriteContext - Pointer to the OFFLOAD_WRITE_CONTEXT for the offload
15808 write operation.
15809
15810 CompletionCausingStatus - Status code indicating a reason that the offload
15811 write operation is completing. For success this will be STATUS_SUCCESS,
15812 but for a failure, this status will indicate what failure occurred.
15813 This status doesn't directly propagate to the completion status of the
15814 overall offload write operation if this status is failure and the
15815 overall offload write operation has already previously written some
15816 sectors successfully.
15817
15818Return Value:
15819
15820 None.
15821
15822--*/
15823
15824{
15825 PDEVICE_OBJECT fdo;
15828 PULONGLONG totalSectorsProcessedSuccessfully;
15829 ULONGLONG entireXferLen;
15830 PIRP irp;
15831 PBOOLEAN tokenInvalidated;
15832 ULONG listIdentifier;
15833 ULONGLONG totalSectorsProcessed;
15835 ULONGLONG totalBytesProcessed;
15836
15837 fdo = OffloadWriteContext->Fdo;
15838 fdoExt = fdo->DeviceExtension;
15839 dsmAttributes = OffloadWriteContext->DsmAttributes;
15840 totalSectorsProcessedSuccessfully = &OffloadWriteContext->TotalSectorsProcessedSuccessfully;
15841 entireXferLen = OffloadWriteContext->EntireXferLen;
15842 irp = OffloadWriteContext->OffloadWriteDsmIrp;
15843 tokenInvalidated = &OffloadWriteContext->TokenInvalidated;
15844 listIdentifier = OffloadWriteContext->ListIdentifier;
15845 totalSectorsProcessed = OffloadWriteContext->TotalSectorsProcessed;
15846 status = CompletionCausingStatus;
15847
15848 ((PSTORAGE_OFFLOAD_WRITE_OUTPUT)dsmAttributes)->OffloadWriteFlags = 0;
15849 ((PSTORAGE_OFFLOAD_WRITE_OUTPUT)dsmAttributes)->Reserved = 0;
15850
15851 totalBytesProcessed = (*totalSectorsProcessedSuccessfully) * fdoExt->DiskGeometry.BytesPerSector;
15852
15853 TracePrint((totalBytesProcessed == entireXferLen ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_WARNING,
15854 TRACE_FLAG_IOCTL,
15855 "ClasspCompleteOffloadWrite (%p): %ws wrote using token %I64u (out of %I64u) bytes (Irp %p).\n",
15856 fdo,
15857 NT_SUCCESS(status) ? L"Successful" : L"Failed",
15858 totalBytesProcessed,
15859 entireXferLen,
15860 irp));
15861
15862 if (totalBytesProcessed > 0 && totalBytesProcessed < entireXferLen) {
15864 }
15865 if (*tokenInvalidated) {
15866 SET_FLAG(((PSTORAGE_OFFLOAD_WRITE_OUTPUT)dsmAttributes)->OffloadWriteFlags, STORAGE_OFFLOAD_TOKEN_INVALID);
15867 }
15868 ((PSTORAGE_OFFLOAD_WRITE_OUTPUT)dsmAttributes)->LengthCopied = totalBytesProcessed;
15869
15870
15871 if (!NT_SUCCESS(status)) {
15872
15873 TracePrint((TRACE_LEVEL_WARNING,
15874 TRACE_FLAG_IOCTL,
15875 "ClasspCompleteOffloadWrite (%p): TokenOperation for WriteUsingToken (list Id %u) completed with %x writing %I64u blocks (currentTotal %I64u blocks).\n",
15876 fdo,
15877 listIdentifier,
15878 status,
15879 totalSectorsProcessed,
15880 *totalSectorsProcessedSuccessfully));
15881
15882 //
15883 // Even if target returned an error, from the OS upper layers' perspective,
15884 // it is a success (with truncation) if any data at all was written.
15885 //
15886 if (*totalSectorsProcessedSuccessfully) {
15888 }
15889 }
15890
15891 irp->IoStatus.Information = sizeof(STORAGE_OFFLOAD_WRITE_OUTPUT);
15892
15894 ClasspCleanupOffloadWriteContext(OffloadWriteContext);
15895 OffloadWriteContext = NULL;
15896
15897 return;
15898}
15899
15900
15901VOID
15903 _In_ __drv_freesMem(mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext
15904 )
15905
15906/*++
15907
15908Routine description:
15909
15910 This routine cleans up an offload write context.
15911
15912Arguments:
15913
15914 OffloadWriteContext - Pointer to the OFFLOAD_WRITE_CONTEXT for the offload
15915 write operation.
15916
15917Return Value:
15918
15919 None.
15920
15921--*/
15922
15923{
15924 PMDL writeUsingTokenMdl = OffloadWriteContext->WriteUsingTokenMdl;
15925
15926 if (writeUsingTokenMdl) {
15927 ClasspFreeDeviceMdl(writeUsingTokenMdl);
15928 }
15929 FREE_POOL(OffloadWriteContext);
15930
15931 return;
15932}
15933
15934
15936VOID
15938 _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext
15939 )
15940
15941/*++
15942
15943Routine description:
15944
15945 This routine retrieves the token after a WriteUsingToken command
15946 has been sent down in case of an error or if there is a need to
15947 poll for the result.
15948
15949 This routine is responsible for continuing or completing the offload write
15950 operation.
15951
15952Arguments:
15953
15954 OffloadWriteContext - Pointer to the OFFLOAD_WRITE_CONTEXT for the offload
15955 write operation.
15956
15957Return Value:
15958
15959 None.
15960
15961--*/
15962
15963{
15964 PVOID buffer;
15966 ULONG cdbLength;
15967 PDEVICE_OBJECT fdo;
15968 PIRP irp;
15969 ULONG listIdentifier;
15970 PTRANSFER_PACKET pkt;
15971 PIRP pseudoIrp;
15972 ULONG receiveTokenInformationBufferLength;
15975 ULONG tempSizeUlong;
15976 PMDL writeUsingTokenMdl;
15977
15978 fdo = OffloadWriteContext->Fdo;
15979 irp = OffloadWriteContext->OffloadWriteDsmIrp;
15980 pseudoIrp = &OffloadWriteContext->PseudoIrp;
15981 buffer = OffloadWriteContext + 1;
15982 bufferLength = OffloadWriteContext->BufferLength;
15983 receiveTokenInformationBufferLength = OffloadWriteContext->ReceiveTokenInformationBufferLength;
15984 writeUsingTokenMdl = OffloadWriteContext->WriteUsingTokenMdl;
15985 listIdentifier = OffloadWriteContext->ListIdentifier;
15986 srb = &OffloadWriteContext->Srb;
15988
15989 TracePrint((TRACE_LEVEL_VERBOSE,
15990 TRACE_FLAG_IOCTL,
15991 "ClasspReceiveWriteUsingTokenInformation (%p): Entering function. Irp %p\n",
15992 fdo,
15993 irp));
15994
15995 //
15996 // The WRITE USING TOKEN wasn't immediately fully successful, so that means
15997 // the only way to find out how many sectors were processed by the WRITE
15998 // USING TOKEN is to get a successful RECEIVE ROD TOKEN INFORMATION that
15999 // indicates the operation is complete.
16000 //
16001
16002 NT_ASSERT(OffloadWriteContext->TotalSectorsProcessed == 0);
16003
16004 pkt = DequeueFreeTransferPacket(fdo, TRUE);
16005
16006 if (!pkt) {
16007
16008 TracePrint((TRACE_LEVEL_ERROR,
16009 TRACE_FLAG_IOCTL,
16010 "ClasspReceiveWriteUsingTokenInformation (%p): Failed to retrieve transfer packet for ReceiveTokenInformation (WriteUsingToken) operation.\n",
16011 fdo));
16012
16014
16015 goto __ClasspReceiveWriteUsingTokenInformation_ErrorExit;
16016 }
16017
16019
16020 tempSizeUlong = receiveTokenInformationBufferLength - 4;
16021 REVERSE_BYTES(((PRECEIVE_TOKEN_INFORMATION_HEADER)buffer)->AvailableData, &tempSizeUlong);
16022
16023 RtlZeroMemory(pseudoIrp, sizeof(IRP));
16024
16025 pseudoIrp->IoStatus.Status = STATUS_SUCCESS;
16026 pseudoIrp->IoStatus.Information = 0;
16027 pseudoIrp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
16028 pseudoIrp->MdlAddress = writeUsingTokenMdl;
16029
16030 ClasspSetupReceiveWriteUsingTokenInformationTransferPacket(
16031 OffloadWriteContext,
16032 pkt,
16034 (PUCHAR)buffer,
16035 pseudoIrp,
16036 listIdentifier);
16037
16038 //
16039 // Cache away the CDB as it may be required for forwarded sense data
16040 // after this command completes.
16041 //
16042 RtlZeroMemory(srb, sizeof(*srb));
16043 cdbLength = SrbGetCdbLength(pkt->Srb);
16044 if (cdbLength <= 16) {
16045 RtlCopyMemory(&srb->Cdb, SrbGetCdb(pkt->Srb), cdbLength);
16046 }
16047
16049
16050 return;
16051
16052 //
16053 // Error label only - not used by success cases:
16054 //
16055
16056__ClasspReceiveWriteUsingTokenInformation_ErrorExit:
16057
16059
16060 //
16061 // ClasspCompleteOffloadWrite also cleans up OffloadWriteContext.
16062 //
16063
16064 ClasspCompleteOffloadWrite(OffloadWriteContext, status);
16065
16066 return;
16067}
16068
16069
16070VOID
16072 _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext
16073 )
16074
16075/*++
16076
16077Routine description:
16078
16079 This routine continues an offload write operation when a RECEIVE ROD TOKEN
16080 INFORMATION transfer packet is done.
16081
16082 This routine may need to send another RRTI, or it may be able to indicate
16083 that this WUT is done via call to
16084 ClasspReceiveWriteUsingTokenInformationDone().
16085
16086 This routine is responsible for continuing or completing the offload write
16087 operation.
16088
16089Arguments:
16090
16091 OffloadWriteContext - Pointer to the OFFLOAD_WRITE_CONTEXT for the offload
16092 write operation.
16093
16094Return Value:
16095
16096 None.
16097
16098--*/
16099
16100{
16101 ULONG availableData;
16102 PVOID buffer;
16103 UCHAR completionStatus;
16104 ULONG estimatedRetryInterval;
16105 PDEVICE_OBJECT fdo;
16107 PIRP irp;
16108 ULONG listIdentifier;
16109 BOOLEAN operationCompleted;
16110 UCHAR operationStatus;
16111 PIRP pseudoIrp;
16112 USHORT segmentsProcessed;
16113 PSENSE_DATA senseData;
16114 ULONG senseDataFieldLength;
16115 UCHAR senseDataLength;
16118 ULONG tokenDescriptorLength;
16119 PRECEIVE_TOKEN_INFORMATION_HEADER tokenInformationResults;
16120 PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER tokenInformationResponsePadding;
16121 PBOOLEAN tokenInvalidated;
16122 PULONGLONG totalSectorsProcessed;
16123 ULONGLONG totalSectorsToProcess;
16124 ULONGLONG transferBlockCount;
16125
16126 fdo = OffloadWriteContext->Fdo;
16127 fdoExt = fdo->DeviceExtension;
16128 listIdentifier = OffloadWriteContext->ListIdentifier;
16129 totalSectorsProcessed = &OffloadWriteContext->TotalSectorsProcessed;
16130 totalSectorsToProcess = OffloadWriteContext->TotalSectorsToProcess;
16131 irp = OffloadWriteContext->OffloadWriteDsmIrp;
16132 pseudoIrp = &OffloadWriteContext->PseudoIrp;
16133 tokenInvalidated = &OffloadWriteContext->TokenInvalidated;
16134 srb = &OffloadWriteContext->Srb;
16135 operationCompleted = FALSE;
16136 buffer = OffloadWriteContext + 1;
16137 tokenInformationResults = (PRECEIVE_TOKEN_INFORMATION_HEADER)buffer;
16138 senseData = (PSENSE_DATA)((PUCHAR)tokenInformationResults + FIELD_OFFSET(RECEIVE_TOKEN_INFORMATION_HEADER, SenseData));
16139 transferBlockCount = 0;
16140 tokenInformationResponsePadding = NULL;
16141 tokenDescriptorLength = 0;
16142
16143 NT_ASSERT((*totalSectorsProcessed) == 0);
16144
16145 OffloadWriteContext->Pkt = NULL;
16146
16147
16148 status = pseudoIrp->IoStatus.Status;
16150
16151 //
16152 // The buffer we hand allows for the max sizes for all the fields whereas the returned
16153 // data may be lesser (e.g. sense data info will almost never be MAX_SENSE_BUFFER_SIZE, etc.
16154 // so handle underrun "error"
16155 //
16156 if (status == STATUS_DATA_OVERRUN) {
16157
16159 }
16160
16161 if (!NT_SUCCESS(status)) {
16162 TracePrint((TRACE_LEVEL_ERROR,
16163 TRACE_FLAG_IOCTL,
16164 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): Failed with %x to retrieve write results for list Id %x for data size %I64u bytes.\n",
16165 fdo,
16166 status,
16167 listIdentifier,
16168 totalSectorsToProcess * fdoExt->DiskGeometry.BytesPerSector));
16169
16170 NT_ASSERT((*totalSectorsProcessed) == 0);
16171
16172 goto __ClasspReceiveWriteUsingTokenInformationTransferPacketDone_ErrorExit;
16173 }
16174
16175 REVERSE_BYTES(&availableData, &tokenInformationResults->AvailableData);
16176
16178
16180
16181 operationStatus = tokenInformationResults->OperationStatus;
16182 operationCompleted = ClasspIsTokenOperationComplete(operationStatus);
16183 NT_ASSERT(operationCompleted);
16184
16185 REVERSE_BYTES(&estimatedRetryInterval, &tokenInformationResults->EstimatedStatusUpdateDelay);
16186
16187 completionStatus = tokenInformationResults->CompletionStatus;
16188
16189 senseDataFieldLength = tokenInformationResults->SenseDataFieldLength;
16190 senseDataLength = tokenInformationResults->SenseDataLength;
16191 NT_ASSERT(senseDataFieldLength >= senseDataLength);
16192
16193 tokenInformationResponsePadding = (PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER)((PUCHAR)tokenInformationResults +
16195 tokenInformationResults->SenseDataFieldLength);
16196
16197 REVERSE_BYTES(&tokenDescriptorLength, &tokenInformationResponsePadding->TokenDescriptorsLength);
16198 NT_ASSERT(tokenDescriptorLength == 0);
16199
16201 REVERSE_BYTES_QUAD(&transferBlockCount, &tokenInformationResults->TransferCount);
16202
16203 REVERSE_BYTES_SHORT(&segmentsProcessed, &tokenInformationResults->SegmentsProcessed);
16204 NT_ASSERT(segmentsProcessed == 0);
16205
16206 if (operationCompleted) {
16207
16208 if (transferBlockCount > totalSectorsToProcess) {
16209
16210 //
16211 // Buggy or hostile target. Don't let it claim more was procesed
16212 // than was requested. Since this is likely a bug and it's unknown
16213 // how much was actually transferred, assume no data was
16214 // transferred.
16215 //
16216
16217 NT_ASSERT(transferBlockCount <= totalSectorsToProcess);
16218 transferBlockCount = 0;
16219 }
16220
16221 if (operationStatus != OPERATION_COMPLETED_WITH_SUCCESS &&
16222 operationStatus != OPERATION_COMPLETED_WITH_RESIDUAL_DATA) {
16223
16224 //
16225 // Assert on buggy response from target, but in any case, make sure not
16226 // to claim that any data was written.
16227 //
16228
16229 NT_ASSERT(transferBlockCount == 0);
16230 transferBlockCount = 0;
16231 }
16232
16233 //
16234 // Since the TokenOperation was sent down synchronously but failed, the operation is complete as soon as the
16235 // ReceiveTokenInformation command returns.
16236 //
16237
16238 NT_ASSERT((*totalSectorsProcessed) == 0);
16239 *totalSectorsProcessed = transferBlockCount;
16240 ClasspAdvanceOffloadWritePosition(OffloadWriteContext, transferBlockCount);
16241
16242 if (transferBlockCount < totalSectorsToProcess) {
16243
16245 operationStatus == OPERATION_COMPLETED_WITH_ERROR ||
16246 operationStatus == OPERATION_TERMINATED);
16247
16248 } else {
16249
16250 NT_ASSERT(operationStatus == OPERATION_COMPLETED_WITH_SUCCESS);
16251 }
16252
16253 TracePrint((transferBlockCount == totalSectorsToProcess ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_WARNING,
16254 TRACE_FLAG_IOCTL,
16255 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): %wsSuccessfully wrote (for list Id %x) for data size %I64u bytes\n",
16256 fdo,
16257 transferBlockCount == totalSectorsToProcess ? L"" : L"Target truncated write. ",
16258 listIdentifier,
16259 (*totalSectorsProcessed) * fdoExt->DiskGeometry.BytesPerSector));
16260
16261 //
16262 // Operation that completes with success can have sense data (for target to pass on some extra info)
16263 // but we don't care about such sense info.
16264 // Operation that complete but not with success, may not have sense data associated, but may
16265 // have valid CompletionStatus.
16266 //
16267 // The "status" may be overriden by ClassInterpretSenseInfo(). Final
16268 // status is determined a bit later - this is just the default status
16269 // when ClassInterpretSenseInfo() doesn't get to run here.
16270 //
16272 if (operationStatus == OPERATION_COMPLETED_WITH_ERROR ||
16273 operationStatus == OPERATION_COMPLETED_WITH_RESIDUAL_DATA ||
16274 operationStatus == OPERATION_TERMINATED) {
16275
16276 SrbSetScsiStatus((PSTORAGE_REQUEST_BLOCK_HEADER)srb, completionStatus);
16277
16278 if (senseDataLength) {
16279
16280 ULONG retryInterval;
16281
16282 NT_ASSERT(senseDataLength <= sizeof(SENSE_DATA));
16283
16284 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
16285
16289
16291 srb,
16293 0,
16294 0,
16295 &status,
16296 &retryInterval);
16297
16298 TracePrint((TRACE_LEVEL_WARNING,
16299 TRACE_FLAG_IOCTL,
16300 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): Reason for truncation/failure: %x - for list Id %x for data size %I64u bytes.\n",
16301 fdo,
16302 status,
16303 listIdentifier,
16304 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector));
16305
16306 //
16307 // If the token isn't valid any longer, we should let the upper layers know so that
16308 // they don't waste time retrying the write with the same token.
16309 //
16311
16312 *tokenInvalidated = TRUE;
16313 }
16314 } else {
16315
16316 TracePrint((TRACE_LEVEL_WARNING,
16317 TRACE_FLAG_IOCTL,
16318 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): No sense data available but reason for truncation/failure, possibly: %x - for list Id %x for data size %I64u bytes.\n",
16319 fdo,
16320 completionStatus,
16321 listIdentifier,
16322 transferBlockCount * fdoExt->DiskGeometry.BytesPerSector));
16323 }
16324 }
16325
16326 //
16327 // Initialize status. Upper layer needs to know if command failed because it
16328 // timed out without doing any writing. ClasspCompleteOffloadWrite() will
16329 // force status to success if any data was written, so it's this function's
16330 // job to set the status appropriately based on the outcome of this
16331 // WRITE USING TOKEN command, and then ClasspCompleteOffloadWrite()
16332 // can override with success if previos WRITE USING TOKEN commands
16333 // issued for the same upper request were able to write some data.
16334 //
16335 if (transferBlockCount != 0) {
16337 } else {
16338
16339 if (NT_SUCCESS(status)) {
16340 //
16341 // Make sure status is a failing status, without throwing away an
16342 // already-failing status obtained from sense data.
16343 //
16345 }
16346 }
16347
16349
16350 if (!NT_SUCCESS(status)) {
16351 goto __ClasspReceiveWriteUsingTokenInformationTransferPacketDone_ErrorExit;
16352 }
16353
16356 goto __ClasspReceiveWriteUsingTokenInformationTransferPacketDone_Exit;
16357
16358 } else {
16359
16361
16362 goto __ClasspReceiveWriteUsingTokenInformationTransferPacketDone_ErrorExit;
16363 }
16364
16365 //
16366 // Error label only - not used in success case:
16367 //
16368
16369__ClasspReceiveWriteUsingTokenInformationTransferPacketDone_ErrorExit:
16370
16372
16373 ClasspCompleteOffloadWrite(OffloadWriteContext, status);
16374
16375__ClasspReceiveWriteUsingTokenInformationTransferPacketDone_Exit:
16376
16377 //
16378 // Due to tracing a potentially freed pointer value "Irp", this trace could
16379 // be delayed beyond another offload op picking up the same pointer value
16380 // for its Irp.
16381 //
16382
16383 TracePrint((TRACE_LEVEL_VERBOSE,
16384 TRACE_FLAG_IOCTL,
16385 "ClasspReceiveWriteUsingTokenInformationTransferPacketDone (%p): Exiting function (Irp %p) with status %x.\n",
16386 fdo,
16387 irp,
16388 status));
16389
16390 return;
16391}
16392
16393
16397 _In_ BOOLEAN ForceQuery
16398 )
16399/*
16400Routine Description:
16401
16402 This function is to update various properties described in FDO extension's
16403 CLASS_FUNCTION_SUPPORT_INFO structure by requerying the device's VPD pages.
16404 Although this function is capable of updating any properties in the
16405 CLASS_FUNCTION_SUPPORT_INFO structure, it will initially support only
16406 a small number of proporties in the block limit data
16407
16408Arguments:
16409
16410 FdoExtension : FDO extension
16411
16412 ForceQuery : TRUE if the caller wants to force a query of the device's
16413 VPD pages. Otherwise, the function may use cached data.
16414
16415Return Value:
16416
16417 STATUS_SUCCESS or an error status
16418
16419--*/
16420{
16423 ULONG srbSize;
16424 CLASS_VPD_B0_DATA blockLimitsDataNew;
16425 PCLASS_VPD_B0_DATA blockLimitsDataOriginal;
16426 KLOCK_QUEUE_HANDLE lockHandle;
16427 ULONG generationCount;
16428 ULONG changeRequestCount;
16429
16430 //
16431 // ChangeRequestCount is incremented every time we get an unit attention with
16432 // SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED. GenerationCount will be set to
16433 // ChangeRequestCount after CLASS_FUNCTION_SUPPORT_INFO is refreshed with the latest
16434 // VPD data. i.e. if both values are the same, data in
16435 // CLASS_FUNCTION_SUPPORT_INFO is current
16436 //
16437
16438 generationCount = FdoExtension->FunctionSupportInfo->GenerationCount;
16439 changeRequestCount = FdoExtension->FunctionSupportInfo->ChangeRequestCount;
16440 if (!ForceQuery && generationCount == changeRequestCount) {
16441 return STATUS_SUCCESS;
16442 }
16443
16444 //
16445 // Allocate an SRB for querying the device for LBP-related info if either
16446 // the Logical Block Provisioning (0xB2) or Block Limits (0xB0) VPD page
16447 // exists.
16448 //
16449 if ((FdoExtension->AdapterDescriptor != NULL) &&
16450 (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)) {
16452 } else {
16453 srbSize = sizeof(SCSI_REQUEST_BLOCK);
16454 }
16455
16456 srb = ExAllocatePoolWithTag(NonPagedPoolNx, srbSize, '1DcS');
16457 if (srb == NULL) {
16459 }
16460
16462 srb,
16463 srbSize,
16464 &blockLimitsDataNew);
16465
16466 if (NT_SUCCESS(status)) {
16467
16468 KeAcquireInStackQueuedSpinLock(&FdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
16469
16470 //
16471 // If the generationCount didn't change since we looked at it last time, it means
16472 // no one has tried to update the CLASS_FUNCTION_SUPPORT_INFO data; otherwise, someone
16473 // else has beat us to it.
16474 //
16475 if (generationCount == FdoExtension->FunctionSupportInfo->GenerationCount) {
16476
16477 blockLimitsDataOriginal = &FdoExtension->FunctionSupportInfo->BlockLimitsData;
16478 if (blockLimitsDataOriginal->CommandStatus == -1) {
16479 //
16480 // CommandStatus == -1 means this is the first time we have
16481 // gotten the block limits data.
16482 //
16483 *blockLimitsDataOriginal = blockLimitsDataNew;
16484 } else {
16485 //
16486 // We only expect the Optimal Unmap Granularity (and alignment)
16487 // to change, so those are the only parameters we update.
16488 //
16489 blockLimitsDataOriginal->UGAVALID = blockLimitsDataNew.UGAVALID;
16490 blockLimitsDataOriginal->UnmapGranularityAlignment = blockLimitsDataNew.UnmapGranularityAlignment;
16491 blockLimitsDataOriginal->OptimalUnmapGranularity = blockLimitsDataNew.OptimalUnmapGranularity;
16492 }
16493 FdoExtension->FunctionSupportInfo->GenerationCount = changeRequestCount;
16494 }
16495
16496 KeReleaseInStackQueuedSpinLock(&lockHandle);
16497 }
16498
16499 FREE_POOL(srb);
16500 return status;
16501}
16502
16506 _In_ BOOLEAN ForceQuery,
16507 _Out_ PCLASS_VPD_B0_DATA BlockLimitsData,
16508 _Out_ PULONG GenerationCount
16509 )
16510/*
16511Routine Description:
16512
16513 This function is to get a copy of the latest block limits data.
16514
16515 When this function is called multiple times, GenerationCount can change (value always goes up)
16516 while BlockLimitsData stays the same. In this case, the caller should assume BlockLimitsData
16517 has changed to different values and eventually changed back to the same state when the first
16518 call to this function was made.
16519
16520Arguments:
16521
16522 FdoExtension : FDO extension
16523
16524 ForceQuery : TRUE if the caller wants to force a query of the device's
16525 VPD pages. Otherwise, the function may use cached data.
16526
16527 BlockLimitsData : pointer to memory that will receive the block limits data
16528
16529 GenerationCount : generation count of the block limit data.
16530
16531 DataIsOutdated: set to TRUE if the BlockLimitsData is old but this function fails to
16532 query the latest data from the device due to insufficient resources
16533
16534Return Value:
16535
16536 STATUS_SUCCESS or an error status
16537
16538--*/
16539{
16541 KLOCK_QUEUE_HANDLE lockHandle;
16542
16544
16545 KeAcquireInStackQueuedSpinLock(&FdoExtension->FunctionSupportInfo->SyncLock, &lockHandle);
16546 *BlockLimitsData = FdoExtension->FunctionSupportInfo->BlockLimitsData;
16547 *GenerationCount = FdoExtension->FunctionSupportInfo->GenerationCount;
16548 KeReleaseInStackQueuedSpinLock(&lockHandle);
16549
16550 return status;
16551}
16552
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
struct _IRP * PIRP
#define PAGED_CODE()
#define ALIGN_UP_BY(size, align)
unsigned char BOOLEAN
unsigned int UINT32
#define VOID
Definition: acefi.h:82
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define MIN(x, y)
Definition: rdesktop.h:171
#define index(s, c)
Definition: various.h:29
#define ULongToPtr(ul)
Definition: basetsd.h:92
#define LongToPtr(l)
Definition: basetsd.h:91
#define __int64
Definition: basetyps.h:16
#define __drv_aliasesMem
Definition: btrfs_drv.h:203
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430
LPCTSTR registryPath
Definition: butterflies.c:17
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
_In_ size_t _In_ UCHAR _In_ BOOLEAN Use6Byte
Definition: cdrom.h:1328
FORCEINLINE BOOLEAN PORT_ALLOCATED_SENSE(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: cdrom.h:826
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
_In_ size_t _In_ UCHAR PageMode
Definition: cdrom.h:1326
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define START_UNIT_TIMEOUT
Definition: cdrom.h:132
FORCEINLINE VOID FREE_PORT_ALLOCATED_SENSE_BUFFER(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: cdrom.h:839
#define IS_SCSIOP_READWRITE(opCode)
Definition: cdrom.h:803
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID BufferAddress
Definition: cdrom.h:990
_In_ PSTORAGE_PROPERTY_ID PropertyId
Definition: cdrom.h:932
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN _In_opt_ WDFREQUEST OriginalRequest
Definition: cdrom.h:994
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: cdrom.h:162
_In_ BOOLEAN Release
Definition: cdrom.h:920
#define MAXIMUM_RETRIES
Definition: cdrom.h:124
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:992
#define IS_SCSIOP_WRITE(opCode)
Definition: cdrom.h:797
_In_ ULONG _In_ UCHAR PageCode
Definition: cdrom.h:1317
#define SRB_CLASS_FLAGS_PAGING
Definition: cdrom.h:165
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
_In_ ULONG _In_ UCHAR _In_ UCHAR PageControl
Definition: cdrom.h:1319
#define FDO_HACK_NO_RESERVE6
Definition: cdromp.h:135
#define CLASS_PERF_RESTORE_MINIMUM
Definition: cdromp.h:129
#define MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS
Definition: cdromp.h:50
#define CLASSP_REG_HACK_VALUE_NAME
Definition: cdromp.h:122
#define CLASSP_REG_PERF_RESTORE_VALUE_NAME
Definition: cdromp.h:125
#define NUM_ERROR_LOG_ENTRIES
Definition: cdromp.h:323
#define PTRALIGN
Definition: cdromp.h:44
@ MediaPresent
Definition: cdromp.h:82
@ MediaNotPresent
Definition: cdromp.h:83
@ MediaUnavailable
Definition: cdromp.h:84
#define CLASSP_REG_WRITE_CACHE_VALUE_NAME
Definition: cdromp.h:124
#define FDO_HACK_INVALID_FLAGS
Definition: cdromp.h:141
#define FDO_HACK_CANNOT_LOCK_MEDIA
Definition: cdromp.h:133
@ SimpleMediaLock
Definition: cdromp.h:289
@ InternalMediaLock
Definition: cdromp.h:291
@ SecureMediaLock
Definition: cdromp.h:290
#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME
Definition: cdromp.h:126
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
#define SCSI_ADSENSE_ILLEGAL_BLOCK
Definition: cdrw_hw.h:1264
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSI_SENSEQ_INVALID_RELEASE_OF_PERSISTENT_RESERVATION
Definition: cdrw_hw.h:1362
#define SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED
Definition: cdrw_hw.h:1315
#define SCSI_SENSE_NO_SENSE
Definition: cdrw_hw.h:1187
#define SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED
Definition: cdrw_hw.h:1324
struct _READ_CAPACITY_DATA * PREAD_CAPACITY_DATA
#define SCSI_SENSEQ_OPERATION_IN_PROGRESS
Definition: cdrw_hw.h:1317
#define SCSISTAT_RESERVATION_CONFLICT
Definition: cdrw_hw.h:1084
#define SCSI_SENSEQ_AUTHENTICATION_FAILURE
Definition: cdrw_hw.h:1390
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
#define SCSISTAT_GOOD
Definition: cdrw_hw.h:1078
#define SCSI_ADSENSE_SEEK_ERROR
Definition: cdrw_hw.h:1232
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
struct _READ_CAPACITY_DATA READ_CAPACITY_DATA
#define SCSI_ADSENSE_REC_DATA_NOECC
Definition: cdrw_hw.h:1211
#define SCSI_SENSE_COPY_ABORTED
Definition: cdrw_hw.h:1197
#define SCSI_ADSENSE_INVALID_LUN
Definition: cdrw_hw.h:1266
#define SCSI_SENSE_DATA_PROTECT
Definition: cdrw_hw.h:1194
#define SCSI_ADSENSE_INVALID_CDB
Definition: cdrw_hw.h:1265
#define SCSI_ADSENSE_WRITE_PROTECT
Definition: cdrw_hw.h:1268
#define SCSIOP_WRITE6
Definition: cdrw_hw.h:876
#define SCSI_ADSENSE_MUSIC_AREA
Definition: cdrw_hw.h:1282
#define SCSI_ADSENSE_TRACK_ERROR
Definition: cdrw_hw.h:1231
#define SCSIOP_RELEASE_UNIT
Definition: cdrw_hw.h:893
#define SCSI_SENSEQ_KEY_NOT_ESTABLISHED
Definition: cdrw_hw.h:1392
#define SCSI_SENSE_MEDIUM_ERROR
Definition: cdrw_hw.h:1190
struct _MODE_PARAMETER_HEADER10 MODE_PARAMETER_HEADER10
#define SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION
Definition: cdrw_hw.h:1393
struct _SENSE_DATA * PSENSE_DATA
#define SCSI_ADSENSE_ILLEGAL_COMMAND
Definition: cdrw_hw.h:1263
#define SCSI_SENSEQ_UNKNOWN_FORMAT
Definition: cdrw_hw.h:1322
struct _MODE_PARAMETER_HEADER10 * PMODE_PARAMETER_HEADER10
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
#define SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT
Definition: cdrw_hw.h:1394
#define SCSI_SENSEQ_CAUSE_NOT_REPORTABLE
Definition: cdrw_hw.h:1312
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
#define SCSI_SENSEQ_KEY_NOT_PRESENT
Definition: cdrw_hw.h:1391
#define SCSIOP_READ6
Definition: cdrw_hw.h:874
#define SCSIOP_RESERVE_UNIT
Definition: cdrw_hw.h:892
#define SCSI_ADSENSE_REC_DATA_ECC
Definition: cdrw_hw.h:1212
#define IOCTL_SCSI_EXECUTE_NONE
Definition: cdrw_hw.h:1453
#define NOT_READY_RETRY_INTERVAL
Definition: cdrw_hw.h:1094
#define SCSI_SENSEQ_BECOMING_READY
Definition: cdrw_hw.h:1313
#define MODE_SENSE_CURRENT_VALUES
Definition: cdrw_hw.h:859
#define SCSI_ADSENSE_INVALID_MEDIA
Definition: cdrw_hw.h:1220
#define SCSIOP_READ12
Definition: cdrw_hw.h:956
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
#define SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR
Definition: cdrw_hw.h:1395
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define SCSI_ADSENSE_NO_SENSE
Definition: cdrw_hw.h:1207
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SCSIOP_WRITE12
Definition: cdrw_hw.h:957
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED
Definition: cdrw_hw.h:1314
#define SCSI_ADSENSE_DATA_AREA
Definition: cdrw_hw.h:1283
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
#define SCSI_SENSE_BLANK_CHECK
Definition: cdrw_hw.h:1195
#define SCSI_SENSE_HARDWARE_ERROR
Definition: cdrw_hw.h:1191
#define SCSI_ADSENSE_VOLUME_OVERFLOW
Definition: cdrw_hw.h:1284
struct _MODE_PARAMETER_HEADER * PMODE_PARAMETER_HEADER
#define SCSI_SENSE_RECOVERED_ERROR
Definition: cdrw_hw.h:1188
#define SCSIOP_READ
Definition: cdrw_hw.h:905
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define SCSI_SENSE_ABORTED_COMMAND
Definition: cdrw_hw.h:1198
#define SCSI_ADSENSE_BUS_RESET
Definition: cdrw_hw.h:1289
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
#define SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
Definition: cdrw_hw.h:1318
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
Definition: bufpool.h:45
VOID ClassQueueResourceExhaustionEventWorker(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:5528
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
NTSTATUS ClasspDeviceLBProvisioningProperty(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2894
GUID ClassGuidSrbSupport
Definition: data.c:218
_IRQL_requires_same_ NTSTATUS ClasspGetTokenOperationDescriptorLimits(_In_ PDEVICE_OBJECT Fdo, _In_ ULONG ServiceAction, _In_ ULONG MaxParameterBufferLength, _Out_ PULONG MaxBlockDescriptorsCount, _Out_ PULONGLONG MaxBlockDescriptorsLength)
Definition: utils.c:7472
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt)
Definition: retry.c:706
FORCEINLINE VOID ClasspMarkIrpAsIdle(PIRP Irp, BOOLEAN Idle)
Definition: classp.h:1251
#define MAX_TOKEN_OPERATION_PARAMETER_DATA_LENGTH
Definition: classp.h:207
#define REG_DISK_CLASS_CONTROL
Definition: classp.h:218
FORCEINLINE BOOLEAN ClasspIsTokenOperationComplete(_In_ ULONG CurrentStatus)
Definition: classp.h:2023
NTSTATUS ClasspWriteCacheProperty(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:1199
NTSTATUS ClasspDeviceTrimProcess(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PGUID ActivityId, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:3476
struct _CLASS_RETRY_INFO * PCLASS_RETRY_INFO
VOID ClasspZeroQERR(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:7938
VOID ClassQueueCapacityChangedEventWorker(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:5637
VOID ClasspQueueLogIOEventWithContextWorker(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG SenseBufferSize, _In_ PVOID SenseData, _In_ UCHAR SrbStatus, _In_ UCHAR ScsiStatus, _In_ ULONG ErrorCode, _In_ ULONG CdbLength, _In_opt_ PCDB Cdb, _In_opt_ PTRANSFER_PACKET Pkt)
Definition: utils.c:6010
#define CLASSPNP_POOL_TAG_VPD
Definition: classp.h:195
struct _OFFLOAD_WRITE_CONTEXT OFFLOAD_WRITE_CONTEXT
_IRQL_requires_same_ NTSTATUS ClasspStorageEventNotification(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: utils.c:7826
VOID ClasspFreeDeviceMdl(PMDL Mdl)
Definition: utils.c:615
#define CLASS_MAX_INTERLEAVE_PER_CRITICAL_IO
Definition: classp.h:133
FORCEINLINE VOID SimpleInitSlistHdr(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1211
NTSTATUS ClassDeviceHwFirmwareDownloadProcess(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:8541
NTSTATUS NTAPI ClassMinimalPowerHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: power.c:1890
NTSTATUS ClasspDeviceGetLBAStatus(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:3861
VOID SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, UCHAR SubPage, PIRP OriginalIrp, UCHAR PageControl)
Definition: xferpkt.c:1365
FORCEINLINE BOOLEAN ClasspIsOffloadDataTransferCommand(_In_ PCDB Cdb)
Definition: classp.h:2087
#define DEFAULT_MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN
Definition: classp.h:212
struct _OFFLOAD_READ_CONTEXT OFFLOAD_READ_CONTEXT
#define CLASSP_REG_ACCESS_ALIGNMENT_NOT_SUPPORTED
Definition: classp.h:122
CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[]
Definition: data.c:43
FORCEINLINE LARGE_INTEGER ClasspGetCurrentTime(VOID)
Definition: classp.h:1280
VOID FreeDeviceInputMdl(PMDL Mdl)
Definition: utils.c:622
#define CLASSPNP_POOL_TAG_SRB
Definition: classp.h:194
NTSTATUS ClasspPersistentReserve(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:6211
#define CLASS_TAG_SENSE2
Definition: classp.h:190
FORCEINLINE SINGLE_LIST_ENTRY * SimplePopSlist(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1220
ULONG ClasspCalculateLogicalSectorSize(_In_ PDEVICE_OBJECT Fdo, _In_ ULONG BytesPerBlockInBigEndian)
Definition: utils.c:1483
VOID RetryRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, PSCSI_REQUEST_BLOCK Srb, BOOLEAN Associated, LONGLONG TimeDelta100ns)
Definition: obsolete.c:359
VOID ClasspInitializeIdleTimer(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: clntirp.c:175
_IRQL_requires_same_ PUCHAR ClasspBinaryToAscii(_In_reads_(Length) PUCHAR HexBuffer, _In_ ULONG Length, _Inout_ PULONG UpdateLength)
Definition: utils.c:7717
VOID ClasspPerfIncrementSuccessfulIo(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: utils.c:486
#define VPD_PAGE_HEADER_SIZE
Definition: classp.h:221
NTSTATUS ClasspDuidQueryProperty(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: utils.c:997
#define CLASSP_REG_QERR_OVERRIDE_MODE
Definition: classp.h:126
LIST_ENTRY AllFdosList
Definition: data.c:29
VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, __drv_aliasesMem PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:529
DRIVER_STARTIO ClasspStartIo
Definition: classp.h:1454
NTSTATUS ClasspLogSystemEventWithDeviceNumber(_In_ PDEVICE_OBJECT DeviceObject, _In_ NTSTATUS IoErrorCode)
Definition: utils.c:5354
VOID InitializeDictionary(IN PDICTIONARY Dictionary)
Definition: dictlib.c:58
NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:45
#define CLASSPNP_POOL_TAG_TOKEN_OPERATION
Definition: classp.h:193
NTSTATUS ClasspAccessAlignmentProperty(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:1700
IO_COMPLETION_ROUTINE ClassReleaseQueueCompletion
Definition: classp.h:1586
PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
Definition: xferpkt.c:656
VOID ClasspUninitializeRemoveTracking(_In_ PDEVICE_OBJECT DeviceObject)
Definition: lock.c:529
DRIVER_UNLOAD ClassUnload
Definition: classp.h:1356
#define NUM_IO_RETRIES
Definition: classp.h:169
GUID ClassGuidSenseInfo2
Definition: data.c:216
GUID ClassGuidWorkingSet
Definition: data.c:217
#define CLASSPNP_POOL_TAG_ADDITIONAL_DATA
Definition: classp.h:197
GUID ClassGuidQueryRegInfoEx
Definition: data.c:215
FORCEINLINE BOOLEAN SimpleIsSlistEmpty(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1229
VOID SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp, BOOLEAN Use16ByteCdb)
Definition: xferpkt.c:1480
FORCEINLINE BOOLEAN ClasspIsObsoletePortDriver(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classp.h:1335
_IRQL_requires_same_ NTSTATUS ClasspGetTokenOperationCommandBufferLength(_In_ PDEVICE_OBJECT Fdo, _In_ ULONG ServiceAction, _Inout_ PULONG CommandBufferLength, _Out_opt_ PULONG TokenOperationBufferLength, _Out_opt_ PULONG ReceiveTokenInformationBufferLength)
Definition: utils.c:7356
#define FDO_HACK_NO_SYNC_CACHE
Definition: classp.h:137
VOID DestroyAllTransferPackets(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:288
#define QERR_SET_ZERO_ODX_OR_TP_ONLY
Definition: classp.h:1185
#define QERR_SET_ZERO_ALWAYS
Definition: classp.h:1186
PMDL ClasspBuildDeviceMdl(PVOID Buffer, ULONG BufferLen, BOOLEAN WriteToDevice)
Definition: utils.c:582
FORCEINLINE VOID SimplePushSlist(SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
Definition: classp.h:1215
VOID EnqueueDeferredClientIrp(PDEVICE_OBJECT Fdo, PIRP Irp)
Definition: clntirp.c:78
NTSTATUS ClasspDeviceGetLBProvisioningVPDPage(_In_ PDEVICE_OBJECT DeviceObject, _Inout_opt_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2350
VOID SetupModeSelectTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSelectBuffer, UCHAR ModeSelectBufferLen, BOOLEAN SavePages, PIRP OriginalIrp)
Definition: xferpkt.c:1425
FORCEINLINE BOOLEAN ClasspIsThinProvisioned(_In_ PCLASS_FUNCTION_SUPPORT_INFO SupportInfo)
Definition: classp.h:1317
NTSTATUS ClassDeviceHwFirmwareGetInfoProcess(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
Definition: utils.c:8366
NTSTATUS ClasspPriorityHint(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: utils.c:6480
NTSTATUS ClasspDeviceSeekPenaltyProperty(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2172
KDEFERRED_ROUTINE ClasspRetryRequestDpc
Definition: classp.h:1644
NTSTATUS SubmitTransferPacket(PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:850
NTSTATUS ClasspDeviceTrimProperty(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:2730
FORCEINLINE BOOLEAN ClasspIsReceiveTokenInformation(_In_ PCDB Cdb)
Definition: classp.h:2066
FORCEINLINE BOOLEAN ClasspIsIdleRequestSupported(PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp)
Definition: classp.h:1236
#define CLASS_TAG_WORKING_SET
Definition: classp.h:191
NTSTATUS ClasspEjectionControl(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN MEDIA_LOCK_TYPE LockType, IN BOOLEAN Lock)
Definition: create.c:474
PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen)
Definition: utils.c:609
#define CLASSP_REG_LEGACY_ERROR_HANDLING
Definition: classp.h:127
VOID ClasspInitializeRemoveTracking(_In_ PDEVICE_OBJECT DeviceObject)
Definition: lock.c:500
FORCEINLINE BOOLEAN PORT_ALLOCATED_SENSE_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2547
VOID TransferPacketQueueRetryDpc(PTRANSFER_PACKET Pkt)
Definition: retry.c:604
VOID ClassFreeOrReuseSrb(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN __drv_freesMem(mem) PSCSI_REQUEST_BLOCK Srb)
Definition: obsolete.c:882
_IRQL_requires_same_ NTSTATUS ClasspEnableIdlePower(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2550
VOID ClassQueueThresholdEventWorker(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:5471
VOID InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation)
Definition: retry.c:670
#define MAX_TOKEN_LIST_IDENTIFIERS
Definition: classp.h:215
#define CLASS_TAG_PRIVATE_DATA
Definition: classp.h:189
struct _IDLE_POWER_FDO_LIST_ENTRY * PIDLE_POWER_FDO_LIST_ENTRY
#define MINIMUM_RETRY_UNITS
Definition: classp.h:1195
#define CLASSP_REG_DISBALE_IDLE_POWER_NAME
Definition: classp.h:123
#define MIN_TOKEN_LIST_IDENTIFIERS
Definition: classp.h:214
NTSTATUS ClasspDeviceGetBlockLimitsVPDPage(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Inout_bytecount_(SrbSize) PSCSI_REQUEST_BLOCK Srb, _In_ ULONG SrbSize, _Out_ PCLASS_VPD_B0_DATA BlockLimitsData)
Definition: utils.c:2521
#define LEGACY_NUM_IO_RETRIES
Definition: classp.h:170
VOID SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp)
Definition: xferpkt.c:718
IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties
Definition: classp.h:1714
VOID ClassQueueProvisioningTypeChangedEventWorker(_In_ PDEVICE_OBJECT DeviceObject)
Definition: utils.c:5726
struct _CLASS_ERROR_LOG_DATA * PCLASS_ERROR_LOG_DATA
FORCEINLINE VOID FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2560
NTSTATUS ClassDeviceGetLBProvisioningResources(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:5087
NTSTATUS ClasspEnqueueIdleRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: clntirp.c:576
NTSTATUS ClassDeviceHwFirmwareActivateProcess(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:8902
VOID ClasspPerfIncrementErrorCount(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: utils.c:432
IO_COMPLETION_ROUTINE ClasspSendSynchronousCompletion
Definition: classp.h:1410
#define MAX_NUMBER_BLOCK_DEVICE_DESCRIPTORS
Definition: classp.h:216
VOID ClassInitializeDispatchTables(PCLASS_DRIVER_EXTENSION DriverExtension)
Definition: dispatch.c:38
VOID ClasspConvertToScsiRequestBlock(_Out_ PSCSI_REQUEST_BLOCK Srb, _In_ PSTORAGE_REQUEST_BLOCK SrbEx)
Definition: utils.c:6559
#define MAX_NUMBER_BYTES_PER_SYNC_WRITE_USING_TOKEN
Definition: classp.h:213
#define CLASSP_VOLUME_VERIFY_CHECKED
Definition: classp.h:187
NTSTATUS ClasspDeviceMediaTypeProperty(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: utils.c:1917
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
NTSTATUS ClasspInitializeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3737
NTSTATUS ClasspMcnControl(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb)
Definition: autorun.c:3276
VOID ClasspEnableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3857
VOID ClassSendEjectionNotification(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:155
VOID ClasspDeleteTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3798
VOID ClasspDisableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3956
#define SRB_CLASS_FLAGS_FREE_MDL
Definition: classpnp.h:22
#define FINALLY
Definition: classpnp.h:116
IO_COMPLETION_ROUTINE ClassSignalCompletion
Definition: classpnp.h:1330
struct _CLASS_PRIVATE_COMMON_DATA * PCLASS_PRIVATE_COMMON_DATA
Definition: classpnp.h:285
_In_ BUS_QUERY_ID_TYPE IdType
Definition: classpnp.h:374
#define LEAVE
Definition: classpnp.h:115
struct _CLASS_PRIVATE_COMMON_DATA CLASS_PRIVATE_COMMON_DATA
Definition: classpnp.h:285
_In_ PVOID _In_ PCLASS_INIT_DATA InitializationData
Definition: classpnp.h:722
FORCEINLINE UCHAR GET_FDO_EXTENSON_SENSE_DATA_LENGTH(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classpnp.h:1437
#define CLASS_WORKING_SET_MAXIMUM
Definition: classpnp.h:161
_In_z_ PCCHAR _In_ PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:983
_In_ PVOID Argument2
Definition: classpnp.h:721
struct _CLASS_INTERPRET_SENSE_INFO2 * PCLASS_INTERPRET_SENSE_INFO2
_In_z_ PCCHAR _In_ PDEVICE_OBJECT _In_ BOOLEAN IsFdo
Definition: classpnp.h:984
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
_In_ UCHAR RemoveType
Definition: classpnp.h:1343
_In_ PCHAR _In_ ULONG _In_ ULONG InquiryDataLength
Definition: classpnp.h:1232
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR MajorFunctionCode
Definition: classpnp.h:484
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
struct _CLASS_WORKING_SET * PCLASS_WORKING_SET
#define CLASS_SRB_SCSI_REQUEST_BLOCK
Definition: classpnp.h:572
struct _CLASS_FUNCTION_SUPPORT_INFO * PCLASS_FUNCTION_SUPPORT_INFO
_In_ BOOLEAN AcquireChildLock
Definition: classpnp.h:1182
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
_In_ BUS_QUERY_ID_TYPE _In_ PUNICODE_STRING IdString
Definition: classpnp.h:375
#define DEV_USE_16BYTE_CDB
Definition: classpnp.h:183
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1230
#define CLASS_SRB_STORAGE_REQUEST_BLOCK
Definition: classpnp.h:573
struct _CLASS_QUERY_WMI_REGINFO_EX_LIST * PCLASS_QUERY_WMI_REGINFO_EX_LIST
struct _PHYSICAL_DEVICE_EXTENSION * PPHYSICAL_DEVICE_EXTENSION
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR _In_ ULONG IoDeviceCode
Definition: classpnp.h:485
#define CLASS_TAG_DEVICE_CONTROL
Definition: classpnp.h:85
SCSIPORT_API NTSTATUS NTAPI ClassSendSrbAsynchronous(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp, _In_reads_bytes_opt_(BufferLength) __drv_aliasesMem PVOID BufferAddress, _In_ ULONG BufferLength, _In_ BOOLEAN WriteToDevice)
#define NO_REMOVE
Definition: classpnp.h:96
_In_z_ PCCHAR ObjectNameBuffer
Definition: classpnp.h:982
#define REMOVE_PENDING
Definition: classpnp.h:97
#define CLASS_INTERPRET_SENSE_INFO2_MAXIMUM_HISTORY_COUNT
Definition: classpnp.h:163
@ FailurePredictionNone
Definition: classpnp.h:234
#define CLASS_DRIVER_EXTENSION_KEY
Definition: classpnp.h:94
_In_opt_ PIRP _In_ PSCSI_REQUEST_BLOCK _In_ UCHAR _In_ ULONG _In_ ULONG PreviousRetryCount
Definition: classpnp.h:486
#define SRB_CLASS_FLAGS_PERSISTANT
Definition: classpnp.h:20
#define CLASS_TAG_RELEASE_QUEUE
Definition: classpnp.h:81
_In_ PIRP Irp
Definition: csq.h:116
static PDB_INFORMATION information
Definition: db.cpp:178
#define DEVPROP_FALSE
Definition: devpropdef.h:67
ULONG DEVPROPTYPE
Definition: devpropdef.h:24
CHAR DEVPROP_BOOLEAN
Definition: devpropdef.h:64
#define DEVPROP_TYPE_EMPTY
Definition: devpropdef.h:29
#define DEVPROP_TYPE_BOOLEAN
Definition: devpropdef.h:46
#define DEVPROP_TRUE
Definition: devpropdef.h:66
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
static void cleanup(void)
Definition: main.c:1335
ULONG NTAPI DllUnload()
Definition: dll.cpp:28
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
@ DPFLTR_CLASSPNP_ID
Definition: dpfilter.h:36
method
Definition: dragdrop.c:54
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
struct _COMMON_DEVICE_EXTENSION * PCOMMON_DEVICE_EXTENSION
#define ASSERT_FDO(x)
Definition: pci.h:37
#define ASSERT_PDO(x)
Definition: pci.h:38
KIRQL irql
Definition: wave.h:1
#define WPP_INIT_TRACING(a, b)
Definition: kdebugprint.h:56
#define WPP_CLEANUP(a)
Definition: kdebugprint.h:57
PVOID NTAPI ClassFindModePage(_In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ BOOLEAN Use6Byte)
Definition: class.c:6798
NTSTATUS NTAPI ClassIoComplete(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN PVOID Context)
Definition: class.c:3768
ULONG ClassPnpAllowUnload
Definition: class.c:87
VOID NTAPI ClasspScanForClassHacks(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN ULONG_PTR Data)
Definition: class.c:12634
ULONG NTAPI ClassModeSense(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode)
Definition: class.c:6637
_IRQL_requires_same_ VOID ClasspReceiveWriteUsingTokenInformation(_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
Definition: class.c:15937
NTSTATUS ClassPnpStartDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: class.c:1819
NTSTATUS NTAPI ClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: class.c:9394
NTSTATUS ClassGetPdoId(IN PDEVICE_OBJECT Pdo, IN BUS_QUERY_ID_TYPE IdType, IN PUNICODE_STRING IdString)
Definition: class.c:10151
VOID ClasspContinueOffloadWrite(_In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
Definition: class.c:15187
NTSTATUS NTAPI ClassReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: class.c:2431
NTSTATUS NTAPI ClassDeviceControlDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: class.c:7258
VOID ClasspReleaseQueue(IN PDEVICE_OBJECT Fdo, IN PIRP ReleaseQueueIrp OPTIONAL)
Definition: class.c:11743
VOID ClasspAdvanceOffloadWritePosition(_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ ULONGLONG SectorsToAdvance)
Definition: class.c:15445
NTSTATUS ClasspRefreshFunctionSupportInfo(_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ BOOLEAN ForceQuery)
Definition: class.c:16395
NTSTATUS NTAPI ClassSendSrbSynchronous(_In_ PDEVICE_OBJECT Fdo, _Inout_ PSCSI_REQUEST_BLOCK _Srb, _In_reads_bytes_opt_(BufferLength) PVOID BufferAddress, _In_ ULONG BufferLength, _In_ BOOLEAN WriteToDevice)
Definition: class.c:4042
VOID ClasspFreeReleaseRequest(IN PDEVICE_OBJECT Fdo)
Definition: class.c:11525
NTSTATUS ClasspBlockLimitsDataSnapshot(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ BOOLEAN ForceQuery, _Out_ PCLASS_VPD_B0_DATA BlockLimitsData, _Out_ PULONG GenerationCount)
Definition: class.c:16504
VOID ClasspCompleteOffloadRead(_In_ POFFLOAD_READ_CONTEXT OffloadReadContext, _In_ NTSTATUS CompletionStatus)
Definition: class.c:14255
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
PVOID ScreenStateNotificationHandle
Definition: class.c:124
VOID ClasspCompleteOffloadWrite(_In_ __drv_freesMem(Mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ NTSTATUS CompletionCausingStatus)
Definition: class.c:15788
BOOLEAN InitSecurityCookie
Definition: class.c:102
NTSTATUS NTAPI ClassModeSelect(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, _In_ ULONG Length, _In_ BOOLEAN SavePages)
Definition: class.c:6873
NTSTATUS ClasspAllocateReleaseRequest(IN PDEVICE_OBJECT Fdo)
Definition: class.c:11489
ULONG MaxTokenOperationListIdentifier
Definition: class.c:107
IO_COMPLETION_ROUTINE ClassCheckVerifyComplete
Definition: class.c:84
VOID ClasspReceiveWriteUsingTokenInformationDone(_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext, _In_ NTSTATUS CompletionCausingStatus)
Definition: class.c:15695
VOID ClasspReceiveWriteUsingTokenInformationTransferPacketDone(_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
Definition: class.c:16071
NTSTATUS ClasspModeSelect(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSelectBuffer, _In_ ULONG Length, _In_ BOOLEAN SavePages)
Definition: class.c:6919
#define LastDriveLetter
Definition: class.c:93
ULONG ClassMaxInterleavePerCriticalIo
Definition: class.c:88
VOID ClasspGetInquiryVpdSupportInfo(_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:12914
VOID NTAPI ClassReleaseChildLock(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:12019
ULONG ClasspModeSense(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ UCHAR PageControl)
Definition: class.c:6681
BOOLEAN UseQPCTime
Definition: class.c:95
VOID ClasspScanForSpecialInRegistry(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:12651
NTSTATUS ClasspAllocateReleaseQueueIrp(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:11621
KGUARDED_MUTEX IdlePowerFDOListMutex
Definition: class.c:114
NTSTATUS ClassQueryPnpCapabilities(IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_CAPABILITIES Capabilities)
Definition: class.c:10192
NTSTATUS ClasspGetLBProvisioningInfo(_Inout_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:13087
VOID ClassRetryRequest(IN PDEVICE_OBJECT SelfDeviceObject, IN PIRP Irp, _In_ _In_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) IN LONGLONG TimeDelta100ns)
Definition: class.c:12317
_IRQL_requires_same_ VOID ClasspReceivePopulateTokenInformation(_In_ POFFLOAD_READ_CONTEXT OffloadReadContext)
Definition: class.c:14374
VOID ClasspWriteUsingTokenTransferPacketDone(_In_ PVOID Context)
Definition: class.c:15519
VOID NTAPI ClassSendStartUnit(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:3071
VOID ClassAddChild(_In_ PFUNCTIONAL_DEVICE_EXTENSION Parent, _In_ PPHYSICAL_DEVICE_EXTENSION Child, _In_ BOOLEAN AcquireLock)
Definition: class.c:12058
NTSTATUS ClasspIsPortable(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _Out_ PBOOLEAN IsPortable)
Definition: class.c:8837
_IRQL_requires_same_ NTSTATUS ClasspGetBlockDeviceTokenLimitsInfo(_Inout_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:13220
ULONG DiskIdleTimeoutInMS
Definition: class.c:132
NTSTATUS NTAPI ClassAsynchronousCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: class.c:3246
VOID NTAPI ClassSendDeviceIoControlSynchronous(_In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT TargetDeviceObject, _Inout_updates_opt_(_Inexpressible_(max(InputBufferLength, OutputBufferLength))) PVOID Buffer, _In_ ULONG InputBufferLength, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl, _Out_ PIO_STATUS_BLOCK IoStatus)
Definition: class.c:11065
VOID ClasspRegisterMountedDeviceInterface(IN PDEVICE_OBJECT DeviceObject)
Definition: class.c:10970
NTSTATUS ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp, BOOLEAN PostToDpc)
Definition: class.c:3341
NTSTATUS ClasspAllocatePowerProcessIrp(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:11683
VOID ClasspReceivePopulateTokenInformationTransferPacketDone(_In_ PVOID Context)
Definition: class.c:14504
NTSTATUS ClassPnpQueryFdoRelations(IN PDEVICE_OBJECT Fdo, IN PIRP Irp)
Definition: class.c:9843
GUID StoragePredictFailureDPSGuid
Definition: class.c:90
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
NTSTATUS NTAPI ClassDispatchPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: class.c:894
CONST LARGE_INTEGER Magic10000
Definition: class.c:89
VOID NTAPI ClassReleaseQueue(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:11589
PPHYSICAL_DEVICE_EXTENSION ClassRemoveChild(IN PFUNCTIONAL_DEVICE_EXTENSION Parent, IN PPHYSICAL_DEVICE_EXTENSION Child, IN BOOLEAN AcquireLock)
Definition: class.c:12119
VOID ClasspRetryDpcTimer(IN PCLASS_PRIVATE_FDO_DATA FdoData)
Definition: class.c:12457
VOID ClasspCompleteOffloadRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ NTSTATUS CompletionStatus)
Definition: class.c:13632
ULONG NTAPI ClassModeSenseEx(_In_ PDEVICE_OBJECT Fdo, _In_reads_bytes_(Length) PCHAR ModeSenseBuffer, _In_ ULONG Length, _In_ UCHAR PageMode, _In_ UCHAR PageControl)
Definition: class.c:6656
VOID ClasspPopulateTokenTransferPacketDone(_In_ PVOID Context)
Definition: class.c:14166
volatile ULONG TokenOperationListIdentifier
Definition: class.c:108
VOID ClasspCleanupOffloadWriteContext(_In_ __drv_freesMem(mem) POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
Definition: class.c:15902
BOOLEAN NTAPI ClassInterpretSenseInfo(_In_ PDEVICE_OBJECT Fdo, _In_ PSCSI_REQUEST_BLOCK _Srb, _In_ UCHAR MajorFunctionCode, _In_ ULONG IoDeviceCode, _In_ ULONG RetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, 100) ULONG *RetryInterval)
Definition: class.c:4452
#define FirstDriveLetter
Definition: class.c:92
NTSTATUS NTAPI ClassSendIrpSynchronous(_In_ PDEVICE_OBJECT TargetDeviceObject, _In_ PIRP Irp)
Definition: class.c:11373
VOID InterpretCapacityData(PDEVICE_OBJECT Fdo, PREAD_CAPACITY_DATA_EX ReadCapacityData)
Definition: class.c:2640
NTSTATUS ClassRetrieveDeviceRelations(IN PDEVICE_OBJECT Fdo, IN DEVICE_RELATION_TYPE RelationType, OUT PDEVICE_RELATIONS *DeviceRelations)
Definition: class.c:10005
PVOID PowerSettingNotificationHandle
Definition: class.c:119
BOOLEAN InterpretSenseInfoWithoutHistory(_In_ PDEVICE_OBJECT Fdo, _In_opt_ PIRP OriginalRequest, _In_ PSCSI_REQUEST_BLOCK Srb, UCHAR MajorFunctionCode, ULONG IoDeviceCode, ULONG PreviousRetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIn100nsUnits)
Definition: class.c:12844
NTSTATUS ClasspInitializeHotplugInfo(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:12507
VOID ClasspCleanupOffloadReadContext(_In_ __drv_freesMem(mem) POFFLOAD_READ_CONTEXT OffloadReadContext)
Definition: class.c:14335
NTSTATUS NTAPI ClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: class.c:8773
NTSTATUS NTAPI ClassForwardIrpSynchronous(_In_ PCOMMON_DEVICE_EXTENSION CommonExtension, _In_ PIRP Irp)
Definition: class.c:11343
LIST_ENTRY IdlePowerFDOList
Definition: class.c:113
#define DBGGETSCSIOPSTR(_pSrb)
Definition: debug.h:26
#define DBGLOGFLUSHINFO(_fdoData, _isIO, _isFUA, _isFlush)
Definition: debug.h:129
#define DBGGETADSENSECODESTR(_pSrb)
Definition: debug.h:29
#define ClasspInitializeDebugGlobals()
Definition: debug.h:123
#define DBGGETADSENSEQUALIFIERSTR(_pSrb)
Definition: debug.h:30
#define DBGGETSRBSTATUSSTR(_pSrb)
Definition: debug.h:27
#define DBGGETSENSECODESTR(_pSrb)
Definition: debug.h:28
#define SnapDiskStartup()
Definition: debug.h:124
#define DBGGETIOCTLSTR(_ioctl)
Definition: debug.h:25
NTSTATUS NTAPI ClassGlobalDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: dispatch.c:73
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
#define CLASS_TAG_POWER
Definition: power.c:37
#define ULONG_PTR
Definition: config.h:101
#define SCSIOP_READ16
Definition: scsi.h:914
#define SCSIOP_VERIFY16
Definition: scsi.h:916
#define SCSIOP_WRITE16
Definition: scsi.h:915
#define SRB_STATUS_INVALID_LUN
Definition: srb.h:362
#define SRB_STATUS_REQUEST_FLUSHED
Definition: srb.h:361
#define SRB_STATUS_PHASE_SEQUENCE_FAILURE
Definition: srb.h:359
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_STATUS_NO_HBA
Definition: srb.h:356
#define SRB_FUNCTION_RELEASE_DEVICE
Definition: srb.h:321
#define SCSI_REQUEST_BLOCK_SIZE
Definition: srb.h:282
#define SRB_STATUS_BUS_RESET
Definition: srb.h:353
#define SRB_STATUS_INVALID_TARGET_ID
Definition: srb.h:363
#define SRB_FUNCTION_CLAIM_DEVICE
Definition: srb.h:316
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:406
#define SRB_STATUS_UNEXPECTED_BUS_FREE
Definition: srb.h:358
#define SP_UNTAGGED
Definition: srb.h:233
#define SRB_FLAGS_CLASS_DRIVER_RESERVED
Definition: srb.h:418
#define SRB_FUNCTION_RELEASE_QUEUE
Definition: srb.h:319
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FLAGS_DONT_START_NEXT_PACKET
Definition: srb.h:415
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_STATUS_ABORTED
Definition: srb.h:342
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:402
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:423
#define SRB_STATUS_INVALID_PATH_ID
Definition: srb.h:347
#define SRB_ORDERED_QUEUE_TAG_REQUEST
Definition: srb.h:425
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_FUNCTION_FLUSH
Definition: srb.h:323
#define SRB_FUNCTION_FLUSH_QUEUE
Definition: srb.h:329
#define SRB_STATUS_TIMEOUT
Definition: srb.h:349
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:399
#define SRB_HEAD_OF_QUEUE_TAG_REQUEST
Definition: srb.h:424
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_INTERNAL_ERROR
Definition: srb.h:373
#define SRB_STATUS_COMMAND_TIMEOUT
Definition: srb.h:351
#define SRB_STATUS_PARITY_ERROR
Definition: srb.h:354
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
@ FdoExtension
Definition: precomp.h:48
#define _IRQL_requires_same_
Definition: driverspecs.h:232
#define __drv_freesMem(kind)
Definition: driverspecs.h:272
#define _IRQL_requires_min_(irql)
Definition: driverspecs.h:231
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define __drv_allocatesMem(kind)
Definition: driverspecs.h:257
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define PKEVENT
Definition: env_spec_w32.h:70
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
IN OUT PVCB IN PDEVICE_OBJECT TargetDeviceObject
Definition: fatprocs.h:1674
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
#define IOCTL_STORAGE_LOAD_MEDIA2
Definition: ntddk_ex.h:210
time_t now
Definition: finger.c:65
std::wstring STRING
Definition: fontsub.cpp:33
MxDeviceObject deviceObject
pPkgPnp m_DeviceInterfaceLock AcquireLock(pFxDriverGlobals)
MDL * mdl
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
PVOID dataBuffer
FxIrp * irp
Status
Definition: gdiplustypes.h:25
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble t
Definition: gl.h:2047
GLsizeiptr size
Definition: glext.h:5919
struct _cl_event * event
Definition: glext.h:7739
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLint limit
Definition: glext.h:10326
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166
#define KeGetCurrentThread
Definition: hal.h:55
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR)
#define FILE_PORTABLE_DEVICE
Definition: winternl.h:1855
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define USHORT_MAX
Definition: intsafe.h:147
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
#define Add2Ptr(PTR, INC)
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
static DRIVER_DISPATCH ClassDeviceControl
Definition: kbdclass.c:22
static DRIVER_ADD_DEVICE ClassAddDevice
Definition: kbdclass.c:24
#define RtlEqualMemory(a, b, c)
Definition: kdvm.h:18
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
#define PCHAR
Definition: match.c:90
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
char string[160]
Definition: util.h:11
struct _MOUNTDEV_NAME MOUNTDEV_NAME
struct _MOUNTDEV_UNIQUE_ID MOUNTDEV_UNIQUE_ID
struct _STORAGE_HOTPLUG_INFO STORAGE_HOTPLUG_INFO
#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
struct _MOUNTDEV_SUGGESTED_LINK_NAME MOUNTDEV_SUGGESTED_LINK_NAME
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static HWND child
Definition: cursoricon.c:298
static int priority
Definition: timer.c:163
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_opt_
Definition: ms_sal.h:346
#define _Success_(expr)
Definition: ms_sal.h:259
#define _In_reads_bytes_(size)
Definition: ms_sal.h:321
#define _Inout_
Definition: ms_sal.h:378
#define _In_z_
Definition: ms_sal.h:313
#define _Outptr_
Definition: ms_sal.h:427
#define _Deref_out_range_(lb, ub)
Definition: ms_sal.h:575
#define _At_(target, annos)
Definition: ms_sal.h:244
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_reads_bytes_opt_(size)
Definition: ms_sal.h:322
#define _In_opt_
Definition: ms_sal.h:309
#define _Inout_updates_opt_(size)
Definition: ms_sal.h:388
#define __on_failure(annotes)
Definition: ms_sal.h:2882
#define _Post_satisfies_(cond)
Definition: ms_sal.h:588
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
#define _In_range_(lb, ub)
Definition: ms_sal.h:571
#define _Outptr_result_nullonfailure_
Definition: ms_sal.h:441
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define KernelMode
Definition: asm.h:34
#define FILE_AUTOGENERATED_DEVICE_NAME
Definition: iotypes.h:138
#define DPFLTR_INFO_LEVEL
Definition: kdtypes.h:33
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI ULONG __cdecl DbgPrintEx(_In_ ULONG ComponentId, _In_ ULONG Level, _In_z_ _Printf_format_string_ PCSTR Format,...)
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define METHOD_NEITHER
Definition: nt_native.h:597
#define REG_BINARY
Definition: nt_native.h:1496
NTSYSAPI VOID NTAPI RtlInitString(PSTRING DestinationString, PCSZ SourceString)
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define METHOD_OUT_DIRECT
Definition: nt_native.h:596
#define METHOD_BUFFERED
Definition: nt_native.h:594
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define KEY_WRITE
Definition: nt_native.h:1031
#define REG_NONE
Definition: nt_native.h:1492
#define RTL_REGISTRY_OPTIONAL
Definition: nt_native.h:169
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define METHOD_IN_DIRECT
Definition: nt_native.h:595
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
@ RemovableMedia
Definition: ntdddisk.h:387
@ FixedMedia
Definition: ntdddisk.h:388
#define IOCTL_DISK_BASE
Definition: ntdddisk.h:44
#define IOCTL_DISK_UPDATE_PROPERTIES
Definition: ntdddisk.h:242
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
#define STORAGE_OFFLOAD_WRITE_RANGE_TRUNCATED
Definition: ntddstor.h:1051
* PSTORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
#define IOCTL_STORAGE_RELEASE
Definition: ntddstor.h:119
enum _STORAGE_PROPERTY_ID STORAGE_PROPERTY_ID
#define DeviceDsmAction_OffloadRead
Definition: ntddstor.h:278
#define STORAGE_OFFLOAD_MAX_TOKEN_LENGTH
Definition: ntddstor.h:986
STORAGE_READ_CAPACITY
Definition: ntddstor.h:861
#define IOCTL_STORAGE_EVENT_NOTIFICATION
Definition: ntddstor.h:226
#define DeviceDsmAction_Allocation
Definition: ntddstor.h:280
struct _STORAGE_DEVICE_NUMBER STORAGE_DEVICE_NUMBER
#define IOCTL_STORAGE_SET_HOTPLUG_INFO
Definition: ntddstor.h:157
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_STORAGE_FIRMWARE_ACTIVATE
Definition: ntddstor.h:211
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define IOCTL_STORAGE_READ_CAPACITY
Definition: ntddstor.h:175
#define IsKeyReadCopyNumber(_k)
Definition: ntddstor.h:1072
#define IOCTL_STORAGE_FIRMWARE_DOWNLOAD
Definition: ntddstor.h:208
#define DeviceDsmAction_OffloadWrite
Definition: ntddstor.h:279
@ BusTypeiScsi
Definition: ntddstor.h:447
@ BusTypeFileBackedVirtual
Definition: ntddstor.h:453
@ BusTypeUsb
Definition: ntddstor.h:445
@ BusTypeRAID
Definition: ntddstor.h:446
@ BusTypeFibre
Definition: ntddstor.h:444
@ BusType1394
Definition: ntddstor.h:442
#define STORAGE_OFFLOAD_TOKEN_INVALID
Definition: ntddstor.h:1052
#define IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
Definition: ntddstor.h:181
#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
struct _STORAGE_OFFLOAD_WRITE_OUTPUT * PSTORAGE_OFFLOAD_WRITE_OUTPUT
#define IOCTL_STORAGE_RESERVE
Definition: ntddstor.h:116
struct _STORAGE_OFFLOAD_READ_OUTPUT * PSTORAGE_OFFLOAD_READ_OUTPUT
@ StorageMiniportProperty
Definition: ntddstor.h:517
@ StorageDeviceUniqueIdProperty
Definition: ntddstor.h:515
@ StorageDeviceMediumProductType
Definition: ntddstor.h:527
@ StorageDeviceSeekPenaltyProperty
Definition: ntddstor.h:519
@ StorageDeviceLBProvisioningProperty
Definition: ntddstor.h:523
@ StorageDeviceWriteCacheProperty
Definition: ntddstor.h:516
@ StorageAdapterProperty
Definition: ntddstor.h:513
@ StorageDeviceTrimProperty
Definition: ntddstor.h:520
@ StorageDevicePowerProperty
Definition: ntddstor.h:524
@ StorageDeviceCopyOffloadProperty
Definition: ntddstor.h:525
@ StorageAccessAlignmentProperty
Definition: ntddstor.h:518
@ StorageDeviceProperty
Definition: ntddstor.h:512
#define STORAGE_OFFLOAD_READ_RANGE_TRUNCATED
Definition: ntddstor.h:1026
#define IOCTL_STORAGE_FIRMWARE_GET_INFO
Definition: ntddstor.h:205
#define IOCTL_STORAGE_GET_LB_PROVISIONING_MAP_RESOURCES
Definition: ntddstor.h:184
enum _STORAGE_BUS_TYPE STORAGE_BUS_TYPE
@ PropertyStandardQuery
Definition: ntddstor.h:505
#define IOCTL_STORAGE_FIND_NEW_DEVICES
Definition: ntddstor.h:122
struct _STORAGE_OFFLOAD_WRITE_OUTPUT STORAGE_OFFLOAD_WRITE_OUTPUT
struct _STORAGE_OFFLOAD_READ_OUTPUT STORAGE_OFFLOAD_READ_OUTPUT
enum _STORAGE_PROPERTY_ID * PSTORAGE_PROPERTY_ID
#define IOCTL_STORAGE_BASE
Definition: ntddstor.h:96
#define IOCTL_STORAGE_MCN_CONTROL
Definition: ntddstor.h:128
@ StoragePortCodeSetStorport
Definition: ntddstor.h:619
@ StoragePortCodeSetUSBport
Definition: ntddstor.h:623
@ StoragePortCodeSetSDport
Definition: ntddstor.h:625
#define IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT
Definition: ntddstor.h:196
#define DeviceDsmAction_Trim
Definition: ntddstor.h:276
struct _DEVICE_DATA_SET_RANGE DEVICE_DATA_SET_RANGE
#define IOCTL_STORAGE_EJECT_MEDIA
Definition: ntddstor.h:107
#define IOCTL_STORAGE_EJECTION_CONTROL
Definition: ntddstor.h:125
#define IOCTL_STORAGE_MEDIA_REMOVAL
Definition: ntddstor.h:104
* PSTORAGE_ADAPTER_DESCRIPTOR
Definition: ntddstor.h:599
* PSTORAGE_READ_CAPACITY
Definition: ntddstor.h:861
#define IOCTL_TAPE_BASE
Definition: ntddtape.h:35
#define ARGUMENT_PRESENT(ArgumentPointer)
@ NotificationEvent
@ SynchronizationEvent
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
#define IO_ERR_NOT_READY
Definition: ntiologc.h:42
#define IO_ERR_SEEK_ERROR
Definition: ntiologc.h:33
#define IO_WRN_FAILURE_PREDICTED
Definition: ntiologc.h:78
#define IO_WARNING_DISK_SURPRISE_REMOVED
Definition: ntiologc.h:118
#define IO_WARNING_PAGING_FAILURE
Definition: ntiologc.h:77
#define IO_ERR_CONTROLLER_ERROR
Definition: ntiologc.h:38
#define IO_WARNING_DISK_FIRMWARE_UPDATED
Definition: ntiologc.h:120
#define IO_WARNING_IO_OPERATION_RETRIED
Definition: ntiologc.h:114
#define IO_ERROR_IO_HARDWARE_ERROR
Definition: ntiologc.h:115
#define IO_RECOVERED_VIA_ECC
Definition: ntiologc.h:60
#define IO_ERR_BAD_BLOCK
Definition: ntiologc.h:34
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
VOID NTAPI IoStartPacket(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PULONG Key, IN PDRIVER_CANCEL CancelFunction)
Definition: device.c:1876
VOID NTAPI IoDetachDevice(IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:1296
VOID NTAPI IoSetStartIoAttributes(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN DeferredStartIo, IN BOOLEAN NonCancelable)
Definition: device.c:1798
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: device.c:1847
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:955
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1311
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1904
NTSTATUS NTAPI IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress, IN ULONG DriverObjectExtensionSize, OUT PVOID *DriverObjectExtension)
Definition: driver.c:1826
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
VOID NTAPI IoInitializeIrp(IN PIRP Irp, IN USHORT PacketSize, IN CCHAR StackSize)
Definition: irp.c:1854
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
IO_PAGING_PRIORITY FASTCALL IoGetPagingIoPriority(IN PIRP Irp)
Definition: irp.c:1748
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:710
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
NTSTATUS NTAPI IoWMIRegistrationControl(IN PDEVICE_OBJECT DeviceObject, IN ULONG Action)
Definition: wmi.c:68
@ PowerDeviceD0
Definition: ntpoapi.h:49
@ PowerDeviceD3
Definition: ntpoapi.h:52
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_CLEANER_CARTRIDGE_INSTALLED
Definition: ntstatus.h:218
#define STATUS_CSS_AUTHENTICATION_FAILURE
Definition: ntstatus.h:882
#define STATUS_COPY_PROTECTION_FAILURE
Definition: ntstatus.h:881
#define STATUS_DISK_RESOURCES_EXHAUSTED
Definition: ntstatus.h:983
#define STATUS_FT_READ_FROM_COPY
Definition: ntstatus.h:167
#define STATUS_CSS_REGION_MISMATCH
Definition: ntstatus.h:886
#define STATUS_INVALID_INITIATOR_TARGET_PATH
Definition: ntstatus.h:1005
#define STATUS_CSS_KEY_NOT_ESTABLISHED
Definition: ntstatus.h:884
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_DEVICE_FEATURE_NOT_SUPPORTED
Definition: ntstatus.h:985
#define STATUS_CSS_SCRAMBLED_SECTOR
Definition: ntstatus.h:885
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define STATUS_TOO_MANY_SEGMENT_DESCRIPTORS
Definition: ntstatus.h:1001
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_CSS_KEY_NOT_PRESENT
Definition: ntstatus.h:883
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_INVALID_OFFSET_ALIGNMENT
Definition: ntstatus.h:1002
#define STATUS_INVALID_TOKEN
Definition: ntstatus.h:987
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
#define STATUS_DEVICE_UNREACHABLE
Definition: ntstatus.h:986
#define STATUS_OPERATION_IN_PROGRESS
Definition: ntstatus.h:1004
#define STATUS_DEVICE_HARDWARE_ERROR
Definition: ntstatus.h:1017
#define STATUS_INVALID_FIELD_IN_PARAMETER_LIST
Definition: ntstatus.h:1003
#define STATUS_INVALID_PARAMETER_3
Definition: ntstatus.h:477
#define STATUS_FILES_OPEN
Definition: ntstatus.h:499
#define STATUS_CSS_RESETS_EXHAUSTED
Definition: ntstatus.h:887
#define STATUS_REVISION_MISMATCH
Definition: ntstatus.h:325
NTSTRSAFEVAPI RtlStringCchPrintfA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1085
_Null_terminated_ char * NTSTRSAFE_PSTR
Definition: ntstrsafe.h:56
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObReferenceObjectByPointer(IN PVOID Object, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode)
Definition: obref.c:381
#define CONST
Definition: pedump.c:81
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS NTAPI IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
Definition: pnpmgr.c:1621
NTSTATUS NTAPI IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_REGISTRY_PROPERTY DeviceProperty, IN ULONG BufferLength, OUT PVOID PropertyBuffer, OUT PULONG ResultLength)
Definition: pnpmgr.c:1382
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
NTKRNLVISTAAPI NTSTATUS NTAPI PoRegisterPowerSettingCallback(_In_opt_ PDEVICE_OBJECT DeviceObject, _In_ LPCGUID SettingGuid, _In_ PPOWER_SETTING_CALLBACK Callback, _In_opt_ PVOID Context, _Outptr_opt_ PVOID *Handle)
Definition: po.c:14
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:108
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
VOID NTAPI ExInitializeRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, IN SIZE_T Size)
Definition: rundown.c:667
SIZE_T NTAPI ExSizeOfRundownProtectionCacheAware(VOID)
Definition: rundown.c:725
#define IOCTL_SCSI_PASS_THROUGH
Definition: scsi_port.h:47
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define SCSIPORT_API
Definition: scsi_port.h:177
#define IOCTL_SCSI_PASS_THROUGH_DIRECT
Definition: scsi_port.h:51
#define CLASS_SPECIAL_CAUSE_NOT_REPORTABLE_HACK
Definition: scsi_port.h:175
#define REG_DWORD
Definition: sdbapi.c:596
void __cdecl __security_init_cookie(void)
Definition: gs_support.c:55
#define SCSI_ADSENSE_INVALID_FIELD_PARAMETER_LIST
Definition: scsi.h:672
#define SCSIOP_RELEASE_UNIT10
Definition: scsi.h:322
#define VPD_BLOCK_DEVICE_CHARACTERISTICS
Definition: scsi.h:2417
#define VPD_MAX_BUFFER_SIZE
Definition: scsi.h:2402
struct _READ_CAPACITY_DATA_EX READ_CAPACITY_DATA_EX
UCHAR additionalSenseCode
Definition: scsi.h:4020
#define ScsiGetSenseDescriptorLength(DescriptorBuffer)
Definition: scsi.h:3678
#define VPD_LOGICAL_BLOCK_PROVISIONING
Definition: scsi.h:2418
#define SCSI_ADSENSE_COPY_PROTECTION_FAILURE
Definition: scsi.h:694
#define SCSI_ADSENSE_INVALID_TOKEN
Definition: scsi.h:669
#define SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED
Definition: scsi.h:692
#define SCSI_SENSEQ_TOO_MANY_SEGMENT_DESCRIPTORS
Definition: scsi.h:799
#define SCSI_ADSENSE_LB_PROVISIONING
Definition: scsi.h:680
struct BLOCK_DEVICE_TOKEN_DESCRIPTOR * PBLOCK_DEVICE_TOKEN_DESCRIPTOR
struct POPULATE_TOKEN_HEADER * PPOPULATE_TOKEN_HEADER
#define BLOCK_DEVICE_TOKEN_SIZE
Definition: scsi.h:3584
#define SCSI_SENSEQ_OPERATION_IS_IN_PROGRESS
Definition: scsi.h:712
#define SCSI_SENSEQ_OPERATING_DEFINITION_CHANGED
Definition: scsi.h:842
struct _VPD_THIRD_PARTY_COPY_PAGE * PVPD_THIRD_PARTY_COPY_PAGE
#define SCSI_SENSEQ_INSUFFICIENT_RESOURCES
Definition: scsi.h:874
struct BLOCK_DEVICE_RANGE_DESCRIPTOR * PBLOCK_DEVICE_RANGE_DESCRIPTOR
#define SCSIOP_RESERVE_UNIT10
Definition: scsi.h:320
struct WRITE_USING_TOKEN_HEADER * PWRITE_USING_TOKEN_HEADER
#define SCSI_SENSE_DESCRIPTOR_TYPE_INFORMATION
Definition: scsi.h:630
#define SCSI_SENSEQ_INITIATOR_RESPONSE_TIMEOUT
Definition: scsi.h:867
#define SERVICE_ACTION_POPULATE_TOKEN
Definition: scsi.h:442
#define SCSI_SENSEQ_INQUIRY_DATA_CHANGED
Definition: scsi.h:843
#define SCSI_SENSEQ_SPACE_ALLOC_IN_PROGRESS
Definition: scsi.h:731
#define SCSI_ADSENSE_RESOURCE_FAILURE
Definition: scsi.h:690
descriptor
Definition: scsi.h:3951
#define SCSI_SESNEQ_COMM_CRC_ERROR
Definition: scsi.h:738
#define SCSI_SENSEQ_SOFT_THRESHOLD_REACHED
Definition: scsi.h:828
#define SCSI_ADSENSE_LUN_COMMUNICATION
Definition: scsi.h:653
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3839
#define SCSI_SENSEQ_TIMEOUT_ON_LOGICAL_UNIT
Definition: scsi.h:834
#define BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR_TYPE_WINDOWS
Definition: scsi.h:2523
#define IsSenseDataFormatValueValid(SenseInfoBuffer)
Definition: scsi.h:3697
UCHAR descriptorLength
Definition: scsi.h:4078
#define VPD_SUPPORTED_PAGES
Definition: scsi.h:2404
#define SCSI_SENSE_DESCRIPTOR_TYPE_BLOCK_COMMAND
Definition: scsi.h:635
#define SCSI_SENSEQ_WRITE_PROTECT_DISABLE
Definition: scsi.h:881
struct _MODE_DISCONNECT_PAGE * PMODE_DISCONNECT_PAGE
#define VPD_BLOCK_LIMITS
Definition: scsi.h:2416
#define REVERSE_BYTES_QUAD(Destination, Source)
Definition: scsi.h:3452
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
struct RECEIVE_TOKEN_INFORMATION_HEADER * PRECEIVE_TOKEN_INFORMATION_HEADER
#define SCSI_SENSEQ_MICROCODE_CHANGED
Definition: scsi.h:841
#define SCSI_ADSENSE_PARAMETERS_CHANGED
Definition: scsi.h:676
struct _WINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR * PWINDOWS_BLOCK_DEVICE_TOKEN_LIMITS_DESCRIPTOR
#define SCSI_SENSEQ_UNREACHABLE_TARGET
Definition: scsi.h:739
UCHAR senseKey
Definition: scsi.h:4019
#define SCSI_SENSEQ_MEDIUM_REMOVAL
Definition: scsi.h:879
PFIXED_SENSE_DATA senseInfoBuffer
Definition: scsi.h:3710
struct _SENSE_DATA * PFIXED_SENSE_DATA
Definition: scsi.h:2723
#define ScsiGetSenseErrorCode(SenseInfoBuffer)
Definition: scsi.h:3676
@ OPERATION_COMPLETED_WITH_SUCCESS
Definition: scsi.h:3652
@ OPERATION_COMPLETED_WITH_ERROR
Definition: scsi.h:3653
@ OPERATION_COMPLETED_WITH_RESIDUAL_DATA
Definition: scsi.h:3654
@ OPERATION_TERMINATED
Definition: scsi.h:3657
#define SCSI_SENSEQ_CAPACITY_DATA_CHANGED
Definition: scsi.h:807
#define SCSI_ADSENSE_OPERATOR_REQUEST
Definition: scsi.h:691
#define SCSI_ADSENSE_COPY_TARGET_DEVICE_ERROR
Definition: scsi.h:657
#define SERVICE_ACTION_WRITE_USING_TOKEN
Definition: scsi.h:443
#define SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED
Definition: scsi.h:684
#define SCSI_ADSENSE_DATA_TRANSFER_ERROR
Definition: scsi.h:688
struct RECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER * PRECEIVE_TOKEN_INFORMATION_RESPONSE_HEADER
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
#define VPD_THIRD_PARTY_COPY
Definition: scsi.h:2415
#define SCSI_SENSEQ_DATA_UNDERRUN
Definition: scsi.h:761
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
PFIXED_SENSE_DATA outBuffer
Definition: scsi.h:4022
struct _SCSI_SENSE_DESCRIPTOR_BLOCK_COMMAND * PSCSI_SENSE_DESCRIPTOR_BLOCK_COMMAND
#define SCSI_ADSENSE_PARAMETER_LIST_LENGTH
Definition: scsi.h:664
@ TRANSFER_COUNT_UNITS_NUMBER_BLOCKS
Definition: scsi.h:3668
#define SCSI_ADSENSE_LOGICAL_UNIT_ERROR
Definition: scsi.h:683
#define MAX_SENSE_BUFFER_SIZE
Definition: scsi.h:598
#define SCSI_SENSEQ_WRITE_PROTECT_ENABLE
Definition: scsi.h:880
#define SCSI_SENSEQ_SPACE_ALLOC_FAILED_WRITE_PROTECT
Definition: scsi.h:803
#define SCSI_SENSE_OPTIONS_NONE
Definition: scsi.h:3838
BOOLEAN validSense
Definition: scsi.h:4018
#define IsDescriptorSenseDataFormat(SenseInfoBuffer)
Definition: scsi.h:3685
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:664
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:108
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:666
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:661
#define SRB_TYPE_SCSI_REQUEST_BLOCK
Definition: srb.h:663
@ SrbExDataTypeScsiCdb16
Definition: srb.h:459
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
#define IOCTL_SCSI_PASS_THROUGH_DIRECT_EX
Definition: ntddscsi.h:38
#define IOCTL_SCSI_PASS_THROUGH_EX
Definition: ntddscsi.h:37
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
#define KeQueryInterruptTime()
Definition: ke.h:37
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
int zero
Definition: sehframes.cpp:29
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
static void Exit(void)
Definition: sock.c:1330
FORCEINLINE UCHAR SrbGetCdbLength(_In_ PVOID Srb)
Definition: srbhelper.h:1074
FORCEINLINE VOID SrbSetSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:964
FORCEINLINE VOID SrbSetRequestAttribute(_In_ PVOID Srb, _In_ UCHAR RequestAttribute)
Definition: srbhelper.h:1131
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
FORCEINLINE VOID SrbSetDataTransferLength(_In_ PVOID Srb, _In_ ULONG DataTransferLength)
Definition: srbhelper.h:784
FORCEINLINE UCHAR SrbGetTargetId(_In_ PVOID Srb)
Definition: srbhelper.h:1184
FORCEINLINE VOID SrbSetNextSrb(_In_ PVOID Srb, _In_opt_ PVOID NextSrb)
Definition: srbhelper.h:909
FORCEINLINE UCHAR SrbGetLun(_In_ PVOID Srb)
Definition: srbhelper.h:1217
FORCEINLINE VOID SrbSetOriginalRequest(_In_ PVOID Srb, _In_opt_ PVOID OriginalRequest)
Definition: srbhelper.h:710
FORCEINLINE UCHAR SrbGetPathId(_In_ PVOID Srb)
Definition: srbhelper.h:1151
FORCEINLINE VOID SrbClearSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:982
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
FORCEINLINE UCHAR SrbGetScsiStatus(_In_ PVOID Srb)
Definition: srbhelper.h:1037
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
FORCEINLINE ULONG SrbGetSrbFlags(_In_ PVOID Srb)
Definition: srbhelper.h:927
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
FORCEINLINE ULONG SrbGetRequestAttribute(_In_ PVOID Srb)
Definition: srbhelper.h:1111
FORCEINLINE VOID SrbSetDataBuffer(_In_ PVOID Srb, _In_opt_ __drv_aliasesMem PVOID DataBuffer)
Definition: srbhelper.h:747
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
FORCEINLINE ULONG SrbGetSystemStatus(_In_ PVOID Srb)
Definition: srbhelper.h:1000
#define SrbSetRequestTag
Definition: srbhelper.h:869
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
FORCEINLINE ULONG SrbGetDataTransferLength(_In_ PVOID Srb)
Definition: srbhelper.h:765
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
#define WHICH_BIT(Data, Bit)
Definition: tools.h:80
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
UCHAR Token[BLOCK_DEVICE_TOKEN_SIZE]
Definition: scsi.h:3648
UCHAR TokenDescriptor[ANYSIZE_ARRAY]
Definition: scsi.h:3642
ULONG DeviceCharacteristics
Definition: classpnp.h:521
PCLASS_INIT_DEVICE ClassInitDevice
Definition: classpnp.h:527
PCLASS_QUERY_PNP_CAPABILITIES ClassQueryPnpCapabilities
Definition: classpnp.h:532
PCLASS_SHUTDOWN_FLUSH ClassShutdownFlush
Definition: classpnp.h:525
PCLASS_READ_WRITE ClassReadWriteVerification
Definition: classpnp.h:523
DEVICE_TYPE DeviceType
Definition: classpnp.h:519
ULONG DeviceExtensionSize
Definition: classpnp.h:518
PCLASS_REMOVE_DEVICE ClassRemoveDevice
Definition: classpnp.h:531
PCLASS_START_DEVICE ClassStartDevice
Definition: classpnp.h:528
PCLASS_DEVICE_CONTROL ClassDeviceControl
Definition: classpnp.h:524
PCLASS_STOP_DEVICE ClassStopDevice
Definition: classpnp.h:530
PCLASS_ERROR ClassError
Definition: classpnp.h:522
CLASS_WMI_INFO ClassWmiInfo
Definition: classpnp.h:533
PCLASS_WORKING_SET WorkingSet
Definition: classpnp.h:588
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
PCLASS_QUERY_WMI_REGINFO_EX ClassFdoQueryWmiRegInfoEx
Definition: classpnp.h:580
PCLASS_QUERY_WMI_REGINFO_EX ClassPdoQueryWmiRegInfoEx
Definition: classpnp.h:581
UNICODE_STRING RegistryPath
Definition: kbdclass.h:25
PDRIVER_DISPATCH DeviceMajorFunctionTable[IRP_MJ_MAXIMUM_FUNCTION+1]
Definition: classpnp.h:585
PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo
Definition: classpnp.h:587
SENSE_DATA SenseData
Definition: classp.h:479
LARGE_INTEGER TickCount
Definition: classp.h:461
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:471
PDRIVER_STARTIO ClassStartIo
Definition: classpnp.h:543
CLASS_DEV_INFO FdoData
Definition: classpnp.h:538
PCLASS_QUERY_ID ClassQueryId
Definition: classpnp.h:542
CLASS_DEV_INFO PdoData
Definition: classpnp.h:539
PCLASS_UNLOAD ClassUnload
Definition: classpnp.h:544
PCLASS_ENUM_DEVICE ClassEnumerateDevice
Definition: classpnp.h:541
PCLASS_ADD_DEVICE ClassAddDevice
Definition: classpnp.h:540
PCLASS_TICK ClassTick
Definition: classpnp.h:545
__callback PCLASS_INTERPRET_SENSE_INFO Interpret
Definition: classpnp.h:566
BOOLEAN IsCachedDriveCapDataValid
Definition: classp.h:803
BOOLEAN IdlePrioritySupported
Definition: classp.h:808
ULONG MaxInterleavedNormalIo
Definition: classp.h:831
ULONG UpdateDiskPropertiesWorkItemActive
Definition: classp.h:704
STORAGE_HOTPLUG_INFO HotplugInfo
Definition: classp.h:739
BOOLEAN LegacyErrorHandling
Definition: classp.h:971
LARGE_INTEGER LongestThrottlePeriod
Definition: classp.h:846
PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo
Definition: classp.h:958
READ_CAPACITY_DATA_EX LastKnownDriveCapacityData
Definition: classp.h:802
ULONG CopyOffloadMaxTargetDuration
Definition: classp.h:665
LARGE_INTEGER ThrottleStartTime
Definition: classp.h:836
ULONG NumHighPriorityPagingIo
Definition: classp.h:826
BOOLEAN LoggedSYNCFailure
Definition: classp.h:754
KSPIN_LOCK SpinLock
Definition: classp.h:795
LARGE_INTEGER LastNonIdleIoTime
Definition: classp.h:935
LARGE_INTEGER ThrottleStopTime
Definition: classp.h:841
BOOLEAN LoggedTURFailureSinceLastIO
Definition: classp.h:753
CLASS_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES]
Definition: classp.h:821
struct _CLASS_PRIVATE_FDO_DATA::@1053 Retry
struct _CLASS_RETRY_INFO * Next
Definition: classp.h:408
BOOLEAN UGAVALID
Definition: classpnp.h:754
ULONG UnmapGranularityAlignment
Definition: classpnp.h:753
ULONG OptimalUnmapGranularity
Definition: classpnp.h:752
NTSTATUS CommandStatus
Definition: classpnp.h:749
PGUIDREGINFO GuidRegInfo
Definition: classpnp.h:508
LARGE_INTEGER StartingOffset
Definition: classpnp.h:619
PDEVICE_OBJECT DeviceObject
Definition: pci.h:46
DICTIONARY FileObjectDictionary
Definition: classpnp.h:631
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
struct _PHYSICAL_DEVICE_EXTENSION * ChildList
Definition: classpnp.h:616
UNICODE_STRING DeviceName
Definition: classpnp.h:615
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
BOOLEAN IsSrbLookasideListInitialized
Definition: classpnp.h:610
UNICODE_STRING MountedDeviceInterfaceName
Definition: classpnp.h:628
PCLASS_DEV_INFO DevInfo
Definition: classpnp.h:620
LARGE_INTEGER PartitionLength
Definition: classpnp.h:618
PCLASS_PRIVATE_COMMON_DATA PrivateCommonData
Definition: classpnp.h:633
PDRIVER_DISPATCH * DispatchTable
Definition: classpnp.h:638
ULONGLONG LengthInBytes
Definition: ntddstor.h:768
LONGLONG StartingOffset
Definition: ntddstor.h:767
STORAGE_OFFLOAD_TOKEN Token
Definition: ntddstor.h:1048
DEVICE_DATA_MANAGEMENT_SET_ACTION Action
Definition: ntddstor.h:773
PVOID DeviceExtension
Definition: env_spec_w32.h:418
BOOLEAN NoVerifyDuringIdlePower
Definition: ntddstor.h:671
BOOLEAN AsynchronousNotificationSupported
Definition: ntddstor.h:667
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:405
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
ULONG BytesPerSector
Definition: ntdddisk.h:409
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
KSPIN_LOCK ReleaseQueueSpinLock
Definition: classpnp.h:911
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
PDEVICE_OBJECT LowerPdo
Definition: classpnp.h:875
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
SCSI_REQUEST_BLOCK ReleaseQueueSrb
Definition: classpnp.h:913
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: classpnp.h:876
Definition: classp.h:1033
LIST_ENTRY ListEntry
Definition: classp.h:1034
PDEVICE_OBJECT Fdo
Definition: classp.h:1035
LARGE_INTEGER DeviceOffset
Definition: iotypes.h:2012
NTSTATUS ErrorCode
Definition: iotypes.h:2007
NTSTATUS FinalStatus
Definition: iotypes.h:2009
struct _IO_STACK_LOCATION::@1564::@1565 DeviceIoControl
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
struct _IO_STACK_LOCATION::@3978::@4017 Others
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@4003 QueryDeviceRelations
struct _IO_STACK_LOCATION::@3978::@4000 Scsi
struct _IO_STACK_LOCATION::@3978::@4005 DeviceCapabilities
struct _IO_STACK_LOCATION::@3978::@3982 Read
struct _IO_STACK_LOCATION::@3978::@4009 QueryId
struct _IO_STACK_LOCATION::@3978::@4011 UsageNotification
PVOID SystemBuffer
IO_STATUS_BLOCK IoStatus
union _IRP::@1566 AssociatedIrp
Definition: ketypes.h:699
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
UCHAR BlockDescriptorLength[2]
Definition: cdrw_hw.h:2516
USHORT UniqueIdLength
Definition: imports.h:138
UCHAR UniqueId[1]
Definition: imports.h:139
ULONG ReceiveTokenInformationBufferLength
Definition: classp.h:1074
PTRANSFER_PACKET Pkt
Definition: classp.h:1066
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:1098
ULONGLONG TotalSectorsToProcess
Definition: classp.h:1080
ULONGLONG TotalSectorsProcessed
Definition: classp.h:1086
ULONGLONG EntireXferLen
Definition: classp.h:1092
PDEVICE_OBJECT Fdo
Definition: classp.h:1040
ULONGLONG OperationStartTime
Definition: classp.h:1162
PDEVICE_MANAGE_DATA_SET_ATTRIBUTES DsmAttributes
Definition: classp.h:1124
ULONGLONG TotalRequestSizeSectors
Definition: classp.h:1120
ULONGLONG DataSetRangeByteOffset
Definition: classp.h:1141
ULONGLONG TotalSectorsProcessedSuccessfully
Definition: classp.h:1139
PDEVICE_DATA_SET_RANGE DataSetRanges
Definition: classp.h:1125
ULONGLONG EntireXferLen
Definition: classp.h:1119
BOOLEAN TokenInvalidated
Definition: classp.h:1154
ULONGLONG LogicalBlockOffset
Definition: classp.h:1127
ULONG ReceiveTokenInformationBufferLength
Definition: classp.h:1133
PDEVICE_DSM_OFFLOAD_WRITE_PARAMETERS OffloadWriteParameters
Definition: classp.h:1126
PDEVICE_OBJECT Fdo
Definition: classp.h:1115
ULONGLONG MaxLbaCount
Definition: classp.h:1130
PTRANSFER_PACKET Pkt
Definition: classp.h:1143
ULONGLONG TotalSectorsToProcess
Definition: classp.h:1149
ULONGLONG TotalSectorsProcessed
Definition: classp.h:1150
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:652
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:650
BOOLEAN PreventMediaRemoval
Definition: ntddstor.h:343
LARGE_INTEGER LogicalBlockAddress
Definition: scsi.h:2749
ULONG LogicalBlockAddress
Definition: cdrw_hw.h:1471
UCHAR PathId
Definition: scsi_port.h:149
UCHAR TargetId
Definition: scsi_port.h:150
UCHAR PortNumber
Definition: scsi_port.h:148
PVOID OriginalRequest
Definition: srb.h:266
PVOID DataBuffer
Definition: srb.h:263
UCHAR Cdb[16]
Definition: srb.h:279
PVOID SenseInfoBuffer
Definition: srb.h:264
UCHAR Function
Definition: srb.h:250
ULONG SrbFlags
Definition: srb.h:260
USHORT Length
Definition: srb.h:249
UCHAR SrbStatus
Definition: srb.h:251
Definition: ntbasedef.h:628
DEVICE_TYPE DeviceType
Definition: ntddstor.h:324
BOOLEAN WriteCacheEnableOverride
Definition: imports.h:249
BOOLEAN MediaRemovable
Definition: imports.h:246
BOOLEAN DeviceHotplug
Definition: imports.h:248
BOOLEAN MediaHotplug
Definition: imports.h:247
PSTORAGE_REQUEST_BLOCK_HEADER Srb
Definition: classp.h:580
SLIST_ENTRY SlistEntry
Definition: classp.h:500
BOOLEAN UsePartialMdl
Definition: classp.h:595
ULONGLONG TransferCount
Definition: classp.h:610
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: iotypes.h:189
UCHAR SupportedPageList[0]
Definition: scsi.h:2633
UCHAR ThirdPartyCopyDescriptors[ANYSIZE_ARRAY]
Definition: scsi.h:2508
Definition: http.c:7252
Definition: match.c:28
Definition: mem.c:156
Definition: name.c:39
Definition: ps.c:97
Definition: dhcpd.h:245
#define max(a, b)
Definition: svc.c:63
BOOLEAN NTAPI KeSetTimerEx(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN LONG Period, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:294
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG_PTR
Definition: typedefs.h:65
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
char CCHAR
Definition: typedefs.h:51
char * PCHAR
Definition: typedefs.h:51
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_RETRY
Definition: udferr_usr.h:182
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_UNRECOGNIZED_MEDIA
Definition: udferr_usr.h:142
#define STATUS_INVALID_BLOCK_LENGTH
Definition: udferr_usr.h:175
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_NONEXISTENT_SECTOR
Definition: udferr_usr.h:143
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_NO_DATA_DETECTED
Definition: udferr_usr.h:131
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_DEVICE_DATA_ERROR
Definition: udferr_usr.h:159
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
CONST char * PCSZ
Definition: umtypes.h:125
Definition: cdrw_hw.h:28
struct _CDB::_CDB10 CDB10
UCHAR AsByte[16]
Definition: scsi.h:1988
struct _CDB::_CDB6INQUIRY3 CDB6INQUIRY3
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _CDB::_MODE_SENSE10 MODE_SENSE10
struct _CDB::_CDB12 CDB12
struct _CDB::_CDB6INQUIRY CDB6INQUIRY
struct _CDB::_START_STOP START_STOP
struct _CDB::_MODE_SENSE MODE_SENSE
struct _CDB::_RECEIVE_TOKEN_INFORMATION RECEIVE_TOKEN_INFORMATION
struct _CDB::_CDB16 CDB16
struct _CDB::_CDB6READWRITE CDB6READWRITE
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
PVOID PMDL
Definition: usb.h:39
#define SrbGetCdb(srb)
Definition: usbstor.h:18
#define IOCTL_CDROM_BASE
Definition: vcdcli.c:21
#define TRY(sps, bps)
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ DEVICE_RELATION_TYPE RelationType
Definition: wdfdevice.h:1059
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_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
_In_opt_ PVOID _In_ ULONG bufferLength
Definition: wdfdriver.h:109
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
_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
WDF_EXTERN_C_START typedef _Must_inspect_result_ _In_ WDFDRIVER _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ PDEVICE_OBJECT _In_opt_ PDEVICE_OBJECT _In_opt_ PDEVICE_OBJECT Pdo
Definition: wdfminiport.h:72
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_IRQL_requires_same_ _In_opt_ PVOID Argument1
Definition: cmtypes.h:696
NTKERNELAPI VOID FASTCALL ExReInitializeRundownProtectionCacheAware(_Inout_ PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware)
NTKERNELAPI VOID FASTCALL ExWaitForRundownProtectionReleaseCacheAware(IN OUT PEX_RUNDOWN_REF_CACHE_AWARE RunRef)
struct _EX_RUNDOWN_REF_CACHE_AWARE * PEX_RUNDOWN_REF_CACHE_AWARE
Definition: extypes.h:186
@ DelayedWorkQueue
Definition: extypes.h:190
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
#define IoAdjustPagingPathCount(_Count, _Increment)
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2680
#define IoSizeOfIrp(_StackSize)
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID _In_ ULONG _In_ BOOLEAN InternalDeviceIoControl
Definition: iofuncs.h:720
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2786
irpSp
Definition: iofuncs.h:2719
#define IRP_MJ_SCSI
#define IRP_MN_CANCEL_STOP_DEVICE
@ BusRelations
Definition: iotypes.h:2152
@ TargetDeviceRelation
Definition: iotypes.h:2156
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
enum _IO_PAGING_PRIORITY IO_PAGING_PRIORITY
#define ERROR_LOG_MAXIMUM_SIZE
Definition: iotypes.h:2042
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define SL_KEY_SPECIFIED
Definition: iotypes.h:1822
enum _BUS_QUERY_ID_TYPE BUS_QUERY_ID_TYPE
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_PAGING_IO
#define IRP_MN_START_DEVICE
@ IoPagingPriorityHigh
Definition: iotypes.h:2822
@ IoPagingPriorityInvalid
Definition: iotypes.h:2820
enum _DEVICE_REMOVAL_POLICY DEVICE_REMOVAL_POLICY
#define IRP_MN_DEVICE_USAGE_NOTIFICATION
#define WMIREG_ACTION_REGISTER
#define IRP_MN_QUERY_ID
IO_COMPLETION_ROUTINE * PIO_COMPLETION_ROUTINE
Definition: iotypes.h:2835
#define IRP_MN_REMOVE_DEVICE
@ DevicePropertyRemovalPolicy
Definition: iotypes.h:1214
#define WMIREG_ACTION_DEREGISTER
#define IRP_MN_QUERY_DEVICE_RELATIONS
#define DO_POWER_PAGABLE
#define IRP_MN_QUERY_STOP_DEVICE
#define IRP_MJ_SYSTEM_CONTROL
struct _IO_WORKITEM * PIO_WORKITEM
Definition: iotypes.h:506
struct _IO_ERROR_LOG_PACKET * PIO_ERROR_LOG_PACKET
#define IRP_MN_QUERY_CAPABILITIES
#define IRP_MJ_FLUSH_BUFFERS
* PDEVICE_CAPABILITIES
Definition: iotypes.h:965
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
struct _DEVICE_RELATIONS DEVICE_RELATIONS
#define DO_POWER_INRUSH
#define IRP_MN_CANCEL_REMOVE_DEVICE
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
#define IRP_MN_STOP_DEVICE
#define IRP_MJ_SHUTDOWN
#define SL_WRITE_THROUGH
Definition: iotypes.h:1824
#define IRP_MJ_POWER
enum _DEVICE_RELATION_TYPE DEVICE_RELATION_TYPE
#define IRP_MN_SCSI_CLASS
enum _DEVICE_USAGE_NOTIFICATION_TYPE DEVICE_USAGE_NOTIFICATION_TYPE
struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET
@ RemovalPolicyExpectSurpriseRemoval
Definition: iotypes.h:842
@ RemovalPolicyExpectOrderlyRemoval
Definition: iotypes.h:841
@ DeviceUsageTypeHibernation
Definition: iotypes.h:1171
@ DeviceUsageTypeBoot
Definition: iotypes.h:1173
@ DeviceUsageTypeDumpFile
Definition: iotypes.h:1172
@ DeviceUsageTypePaging
Definition: iotypes.h:1170
#define IRP_MN_QUERY_REMOVE_DEVICE
@ UserRequest
Definition: ketypes.h:421
@ Executive
Definition: ketypes.h:415
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
#define MmGetMdlVirtualAddress(_Mdl)
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define NT_ASSERTMSG
Definition: rtlfuncs.h:3311
#define RTL_QUERY_REGISTRY_TYPECHECK
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180