ReactOS 0.4.15-dev-7842-g558ab78
init.c
Go to the documentation of this file.
1/*--
2
3Copyright (C) Microsoft Corporation. All rights reserved.
4
5Module Name:
6
7 init.c
8
9Abstract:
10
11 Initialization routines for CDROM
12
13Environment:
14
15 kernel mode only
16
17Notes:
18
19
20Revision History:
21
22--*/
23
24
25#include "ntddk.h"
26#include "ntddstor.h"
27#include "ntstrsafe.h"
28#include "devpkey.h"
29
30#include "cdrom.h"
31#include "scratch.h"
32#include "mmc.h"
33
34#ifdef DEBUG_USE_WPP
35#include "init.tmh"
36#endif
37
40DeviceInitAllocateBuffers(
41 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
42 );
43
46DeviceRetrieveScsiAddress(
47 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
48 _In_ PSCSI_ADDRESS ScsiAddress
49 );
50
53DeviceRetrieveDescriptorsAndTransferLength(
54 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
55 );
56
58VOID
59DeviceScanSpecialDevices(
60 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
61 );
62
65DeviceInitMmcContext(
66 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
67 );
68
71DeviceGetMmcSupportInfo(
72 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
73 _Out_ PBOOLEAN IsMmcDevice
74 );
75
76#if (NTDDI_VERSION >= NTDDI_WIN8)
79DeviceIsPortable(
80 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
81 _Out_ PBOOLEAN IsPortable
82 );
83#endif
84
85
86#ifdef ALLOC_PRAGMA
87
88#pragma alloc_text(PAGE, DeviceClaimRelease)
89#pragma alloc_text(PAGE, DeviceEvtSelfManagedIoInit)
90
91#pragma alloc_text(PAGE, DeviceInitReleaseQueueContext)
92#pragma alloc_text(PAGE, DeviceInitAllocateBuffers)
93#pragma alloc_text(PAGE, DeviceInitPowerContext)
94#pragma alloc_text(PAGE, DeviceCreateWellKnownName)
95#pragma alloc_text(PAGE, DeviceRetrieveScsiAddress)
96#pragma alloc_text(PAGE, DeviceRetrieveDescriptorsAndTransferLength)
97#pragma alloc_text(PAGE, DeviceInitializeHotplugInfo)
98#pragma alloc_text(PAGE, DeviceScanSpecialDevices)
99#pragma alloc_text(PAGE, DeviceGetTimeOutValueFromRegistry)
100#pragma alloc_text(PAGE, DeviceGetMmcSupportInfo)
101#pragma alloc_text(PAGE, DeviceRetrieveDescriptor)
102#pragma alloc_text(PAGE, DeviceRetrieveHackFlagsFromRegistry)
103#pragma alloc_text(PAGE, DeviceScanForSpecial)
104#pragma alloc_text(PAGE, DeviceHackFlagsScan)
105#pragma alloc_text(PAGE, DeviceInitMmcContext)
106#pragma alloc_text(PAGE, ScanForSpecialHandler)
107#pragma alloc_text(PAGE, DeviceSetRawReadInfo)
108#pragma alloc_text(PAGE, DeviceInitializeDvd)
109#pragma alloc_text(PAGE, DeviceCacheDeviceInquiryData)
110
111#if (NTDDI_VERSION >= NTDDI_WIN8)
112#pragma alloc_text(PAGE, DeviceIsPortable)
113#endif
114
115#endif
116
117#pragma warning(push)
118#pragma warning(disable:4152) // nonstandard extension, function/data pointer conversion in expression
119#pragma warning(disable:26000) // read overflow reported because of pointer type conversion
120
123DeviceClaimRelease(
124 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
126 )
127/*++
128
129Routine Description:
130
131 This function claims a device in the port driver. The port driver object
132 is updated with the correct driver object if the device is successfully
133 claimed.
134
135Arguments:
136
137 Device - The WDFDEVICE that needs to be claimed or released.
138
139 Release - Indicates the logical unit should be released rather than claimed.
140
141Return Value:
142
143 Returns a status indicating success or failure of the operation.
144
145--*/
146{
148 SCSI_REQUEST_BLOCK srb = {0};
150 WDFREQUEST request;
151 WDF_OBJECT_ATTRIBUTES attributes;
152
153 PAGED_CODE();
154
155 //Create a request
158
159 status = WdfRequestCreate(&attributes,
160 DeviceExtension->IoTarget,
161 &request);
162
163 if (NT_SUCCESS(status))
164 {
165 //fill up srb structure
166 srb.OriginalRequest = WdfRequestWdmGetIrp(request);
168
169 srb.Length = sizeof(SCSI_REQUEST_BLOCK);
170
171 srb.Function = Release
174
175
177 &srb,
178 sizeof(srb));
179
180 status = WdfIoTargetSendInternalIoctlOthersSynchronously(DeviceExtension->IoTarget,
181 request,
183 &descriptor,
184 NULL,
185 NULL,
186 NULL,
187 NULL);
188
190
191 // The request should be deleted.
192 WdfObjectDelete(request);
193
194 if (!NT_SUCCESS(status))
195 {
196 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
197 "DeviceClaimRelease: Failed to %s device, status: 0x%X\n",
198 Release ? "Release" : "Claim",
199 status));
200 }
201 }
202 else
203 {
204 TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
205 "DeviceClaimRelease: Failed to create request, status: 0x%X\n",
206 status));
207 }
208
209 if (Release)
210 {
211 // We only release the device when we don't want to manage it.
212 // The failure status does not matter.
214 }
215
216 return status;
217} // end DeviceClaimRelease()
218
219
221NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
223 _In_ WDFDEVICE Device
224 )
225/*++
226
227Routine Description:
228
229 This routine is called only once after the device is added in system, so it's used to do
230 hardware-dependent device initialization work and resource allocation.
231 If this routine fails, DeviceEvtSelfManagedIoCleanup will be invoked by the framework.
232
233Arguments:
234
235 Device - Handle to device object
236
237Return Value:
238
239 NTSTATUS
240
241--*/
242{
244 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
245
246 PAGED_CODE();
247
248 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP,
249 "DeviceEvtSelfManagedIoInit: WDFDEVICE %p is being started.\n",
250 Device));
251
252 deviceExtension = DeviceGetExtension(Device);
253
254 // 1. Set/retrieve basic information, some of the following operations may depend on it
255 if (NT_SUCCESS(status))
256 {
257 // We do not care if this function fails, SCSI address is mainly for debugging/tracing purposes.
258 (VOID) DeviceRetrieveScsiAddress(deviceExtension, &deviceExtension->ScsiAddress);
259 }
260
261 if (NT_SUCCESS(status))
262 {
263 status = DeviceRetrieveDescriptorsAndTransferLength(deviceExtension);
264 }
265
266 if (NT_SUCCESS(status))
267 {
268 // This function should be called after DeviceRetrieveDescriptorsAndTransferLength()
269 // It depends on MaxTransferLenth fields.
270 status = DeviceInitAllocateBuffers(deviceExtension);
271 }
272
273 // 2. The following functions depend on the allocated buffers.
274
275 // perf re-enable after failing. Q: Is this one used by cdrom.sys?
276 if (NT_SUCCESS(status))
277 {
278 // allow perf to be re-enabled after a given number of failed IOs
279 // require this number to be at least CLASS_PERF_RESTORE_MINIMUM
281
282 DeviceGetParameter(deviceExtension,
285 &t);
287 {
288 deviceExtension->PrivateFdoData->Perf.ReEnableThreshhold = t;
289 }
290 }
291
292 // 3. Retrieve information about special devices and hack flags.
293 if (NT_SUCCESS(status))
294 {
295 DeviceRetrieveHackFlagsFromRegistry(deviceExtension);
296 // scan for bad items.
297 DeviceScanForSpecial(deviceExtension, CdRomBadItems, DeviceHackFlagsScan);
298 // Check to see if it's a special device that needs special error process.
299 DeviceScanSpecialDevices(deviceExtension); // may send command to device
300 }
301
302 // 4. Initialize the hotplug information only after the ScanForSpecial routines,
303 // as it relies upon the hack flags - deviceExtension->PrivateFdoData->HackFlags.
304 if (NT_SUCCESS(status))
305 {
306 status = DeviceInitializeHotplugInfo(deviceExtension);
307 }
308
309 if (NT_SUCCESS(status))
310 {
311 // cache the device's inquiry data
312 status = DeviceCacheDeviceInquiryData(deviceExtension);
313 if (!NT_SUCCESS(status))
314 {
315 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
316 "Failed to cache the device's inquiry data, failng %!STATUS!\n",
317 status
318 ));
319 }
320 }
321
322 // 5. Initialize MMC context, media change notification stuff and read media capacity
323 if (NT_SUCCESS(status))
324 {
325 status = DeviceInitializeMediaChangeDetection(deviceExtension);
326 }
327 if (NT_SUCCESS(status))
328 {
329 status = DeviceInitMmcContext(deviceExtension);
330 }
331 if (NT_SUCCESS(status))
332 {
333 status = DeviceInitializeZPODD(deviceExtension);
334 }
335 if (NT_SUCCESS(status))
336 {
337 // Do READ CAPACITY. This SCSI command returns the last sector address
338 // on the device and the bytes per sector. These are used to calculate
339 // the drive capacity in bytes.
340 status = MediaReadCapacity(Device);
341
342 // If READ CAPACITY succeeded, we can safely conclude that there is a media present
343 if (NT_SUCCESS(status))
344 {
345 DeviceSetMediaChangeStateEx(deviceExtension,
347 NULL);
348 }
349
350 // READ CAPACITY is not critical for init, ignore all errors occuring during its execution
352 }
353
354 // 6. Perform DVD-specific initialization
355 if (NT_SUCCESS(status))
356 {
357 status = DeviceInitializeDvd(Device);
358 }
359
360 // 7. Miscellaneous initialization actions
361 if (NT_SUCCESS(status))
362 {
363 if (deviceExtension->PrivateFdoData != NULL)
364 {
365 deviceExtension->PrivateFdoData->Perf.OriginalSrbFlags = deviceExtension->SrbFlags;
366 }
367
368 if (deviceExtension->DeviceAdditionalData.Mmc.IsWriter)
369 {
370 // OPC can really take this long per IMAPIv1 timeout....
371 deviceExtension->TimeOutValue = max(deviceExtension->TimeOutValue, SCSI_CDROM_OPC_TIMEOUT);
372 }
373 }
374
375 // 8. Enable the main timer, create ARC name as needed
376 if (NT_SUCCESS(status))
377 {
378 // Device successfully added and initialized, increase CdRomCount.
380
381 deviceExtension->IsInitialized = TRUE;
382
383 DeviceEnableMainTimer(deviceExtension);
384
385 }
386
387#if (NTDDI_VERSION >= NTDDI_WIN8)
388 // 9. Set volume interface properties
389 if (NT_SUCCESS(status))
390 {
391 BOOLEAN isCritical = FALSE;
392 BOOLEAN isPortable = FALSE;
393 BOOLEAN isRemovable = TEST_FLAG(deviceExtension->DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA);
394 DEVPROP_BOOLEAN propCritical = DEVPROP_FALSE;
395 DEVPROP_BOOLEAN propPortable = DEVPROP_FALSE;
396 DEVPROP_BOOLEAN propRemovable = DEVPROP_FALSE;
397
398 status = DeviceIsPortable(deviceExtension, &isPortable);
399
400 if (NT_SUCCESS(status))
401 {
402 if (isPortable) {
403 SET_FLAG(deviceExtension->DeviceObject->Characteristics, FILE_PORTABLE_DEVICE);
404 }
405
406 propPortable = isPortable ? DEVPROP_TRUE : DEVPROP_FALSE;
407
408 status = IoSetDeviceInterfacePropertyData(&deviceExtension->MountedDeviceInterfaceName,
409 &DEVPKEY_Storage_Portable,
410 0,
411 0,
413 sizeof(DEVPROP_BOOLEAN),
414 &propPortable);
415 }
416
417 if (NT_SUCCESS(status))
418 {
419 propRemovable = isRemovable ? DEVPROP_TRUE : DEVPROP_FALSE;
420
421 status = IoSetDeviceInterfacePropertyData(&deviceExtension->MountedDeviceInterfaceName,
422 &DEVPKEY_Storage_Removable_Media,
423 0,
424 0,
426 sizeof(DEVPROP_BOOLEAN),
427 &propRemovable);
428 }
429
430 if (NT_SUCCESS(status))
431 {
432 isCritical = TEST_FLAG(deviceExtension->DeviceObject->Flags,
436
437 propCritical = isCritical ? DEVPROP_TRUE : DEVPROP_FALSE;
438
439 status = IoSetDeviceInterfacePropertyData(&deviceExtension->MountedDeviceInterfaceName,
440 &DEVPKEY_Storage_System_Critical,
441 0,
442 0,
444 sizeof(DEVPROP_BOOLEAN),
445 &propCritical);
446 }
447
448 }
449#endif
450
451 return status;
452}
453
454
457DeviceInitReleaseQueueContext(
458 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
459 )
460/*++
461
462Routine Description:
463
464 Part of device initialize routine. Initialize ReleaseQueue related stuff.
465
466Arguments:
467
468 DeviceExtension - device extension of WDFDEVICE.
469
470Return Value:
471
472 NTSTATUS
473
474--*/
475{
477 WDF_OBJECT_ATTRIBUTES attributes;
478
479 PAGED_CODE();
480
483 attributes.ParentObject = DeviceExtension->Device;
484
485 status = WdfRequestCreate(&attributes,
486 DeviceExtension->IoTarget,
487 &(DeviceExtension->ReleaseQueueRequest));
488
489 if (!NT_SUCCESS(status))
490 {
491 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Cannot create the release queue request\n"));
492
493 return status;
494 }
495
496 // Initialize ReleaseQueueInputMemory, a wrapper around ReleaseQueueSrb
497 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
498 attributes.ParentObject = DeviceExtension->ReleaseQueueRequest;
499
500 status = WdfMemoryCreatePreallocated(&attributes,
501 &DeviceExtension->ReleaseQueueSrb,
502 sizeof(SCSI_REQUEST_BLOCK),
503 &DeviceExtension->ReleaseQueueInputMemory);
504 if (!NT_SUCCESS(status))
505 {
506 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Failed to allocate ReleaseQueueSrb.\n"));
507
508 return status;
509 }
510
511 // Preformat the release queue request here to ensure that this call will never
512 // fail during an actual release of the queue.
513 if (NT_SUCCESS(status))
514 {
515 status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget,
516 DeviceExtension->ReleaseQueueRequest,
518 DeviceExtension->ReleaseQueueInputMemory,
519 NULL,
520 NULL,
521 NULL,
522 NULL,
523 NULL);
524 }
525
526 // Set a CompletionRoutine callback function for ReleaseQueueRequest.
527 if (NT_SUCCESS(status))
528 {
529 WdfRequestSetCompletionRoutine(DeviceExtension->ReleaseQueueRequest,
531 DeviceExtension->Device);
532 }
533
534 // Create a spinlock for ReleaseQueueRequest
535 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
536 attributes.ParentObject = DeviceExtension->Device;
537
538 status = WdfSpinLockCreate(&attributes,
539 &(DeviceExtension->ReleaseQueueSpinLock));
540
541 if (!NT_SUCCESS(status))
542 {
543 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP,
544 "DeviceInitReleaseQueueContext: Cannot create the release queue spinlock\n"));
545
546 return status;
547 }
548
549 // Initialize miscellaneous ReleaseQueue related fields
550 DeviceExtension->ReleaseQueueNeeded = FALSE;
551 DeviceExtension->ReleaseQueueInProgress = FALSE;
552 DeviceExtension->ReleaseQueueSrb.Length = sizeof(SCSI_REQUEST_BLOCK);
553
554 return status;
555}
556
559DeviceInitPowerContext(
560 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
561 )
562/*++
563
564Routine Description:
565
566 Part of device initialize routine. Initialize PowerContext related stuff.
567
568Arguments:
569
570 DeviceExtension - device extension of WDFDEVICE.
571
572Return Value:
573
574 NTSTATUS
575
576--*/
577{
579 WDF_OBJECT_ATTRIBUTES attributes;
580
581 PAGED_CODE();
582
583 // create request object for Power operations
584
587 attributes.ParentObject = DeviceExtension->Device;
588
589 status = WdfRequestCreate(&attributes,
590 DeviceExtension->IoTarget,
591 &(DeviceExtension->PowerContext.PowerRequest) );
592
593 if (!NT_SUCCESS(status))
594 {
595 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Cannot create the power request object.\n"));
596
597 return status;
598 }
599
600 // Preformat the power request. With this being done, we never need to worry about
601 // WdfIoTargetFormatRequestForInternalIoctlOthers ever failing later.
602 status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget,
603 DeviceExtension->PowerContext.PowerRequest,
605 NULL, NULL,
606 NULL, NULL,
607 NULL, NULL);
608 return status;
609}
610
613DeviceCreateWellKnownName(
614 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
615 )
616/*++
617
618Routine Description:
619
620 This routine creates a symbolic link to the cdrom device object
621 under \dosdevices. The number of the cdrom device does not neccessarily
622 match between \dosdevices and \device, but usually will be the same.
623
624 Saves the buffer
625
626Arguments:
627
628 DeviceObject -
629
630Return Value:
631
632 NTSTATUS
633
634--*/
635{
637 UNICODE_STRING unicodeLinkName = {0};
638 WCHAR wideLinkName[64] = {0};
639 PWCHAR savedName;
640
641 LONG cdromNumber = DeviceExtension->DeviceNumber;
642
643 PAGED_CODE();
644
645 // if already linked, assert then return
646 if (DeviceExtension->DeviceAdditionalData.WellKnownName.Buffer != NULL)
647 {
648
649 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
650 "DeviceCreateWellKnownName: link already exists %p\n",
651 DeviceExtension->DeviceAdditionalData.WellKnownName.Buffer));
652
654
655 return STATUS_UNSUCCESSFUL;
656 }
657
658 // find an unused CdRomNN to link to.
659 // It's doing this way because the same might be used for other device in another driver.
660 do
661 {
663 RTL_NUMBER_OF(wideLinkName),
664 L"\\DosDevices\\CdRom%d",
665 cdromNumber);
666 if (!NT_SUCCESS(status))
667 {
668 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
669 "DeviceCreateWellKnownName: Format symbolic link failed with error: 0x%X\n", status));
670 return status;
671 }
672
673 RtlInitUnicodeString(&unicodeLinkName, wideLinkName);
674
675 status = WdfDeviceCreateSymbolicLink(DeviceExtension->Device,
676 &unicodeLinkName);
677
678 cdromNumber++;
679
682
683 if (!NT_SUCCESS(status))
684 {
685 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT,
686 "DeviceCreateWellKnownName: Error %lx linking %wZ to "
687 "device %wZ\n",
688 status,
689 &unicodeLinkName,
690 &(DeviceExtension->DeviceName)));
691 return status;
692 }
693
694 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
695 "DeviceCreateWellKnownName: successfully linked %wZ "
696 "to device %wZ\n",
697 &unicodeLinkName,
698 &(DeviceExtension->DeviceName)));
699
700 // Save away the symbolic link name in the driver data block. We need
701 // it so we can delete the link when the device is removed.
703 unicodeLinkName.MaximumLength,
705
706 if (savedName == NULL)
707 {
708 // Test Note: test path should excise here to see if the symbolic is deleted by framework.
709 // IoDeleteSymbolicLink(&unicodeLinkName);
710 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
711 "DeviceCreateWellKnownName: unable to allocate memory.\n"));
712
714 }
715
716 RtlZeroMemory(savedName, unicodeLinkName.MaximumLength);
717 RtlCopyMemory(savedName, unicodeLinkName.Buffer, unicodeLinkName.MaximumLength);
718
719 RtlInitUnicodeString(&(DeviceExtension->DeviceAdditionalData.WellKnownName), savedName);
720
721 // the name was saved and the link created
722
723 return STATUS_SUCCESS;
724}
725
728DeviceRetrieveScsiAddress(
729 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
730 _In_ PSCSI_ADDRESS ScsiAddress
731 )
732/*++
733
734Routine Description:
735
736 retrieve SCSI address information and put into device extension
737
738Arguments:
739
740 DeviceExtension - device context.
741 ScsiAddress - the buffer to put the scsi address info.
742
743Return Value:
744
745 NTSTATUS
746
747--*/
748{
750 WDF_MEMORY_DESCRIPTOR outputDescriptor;
751
752 PAGED_CODE();
753
754 if ((DeviceExtension == NULL) ||
755 (ScsiAddress == NULL))
756 {
758 }
759
760 //Get IOTARGET for sending request to port driver.
761 WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor,
762 (PVOID)ScsiAddress,
763 sizeof(SCSI_ADDRESS));
764
765 status = WdfIoTargetSendIoctlSynchronously(DeviceExtension->IoTarget,
766 NULL,
768 NULL,
769 &outputDescriptor,
770 NULL,
771 NULL);
772
773 if (!NT_SUCCESS(status))
774 {
775 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
776 "DeviceRetrieveScsiAddress: Get Address failed %lx\n",
777 status));
778 }
779 else
780 {
781 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
782 "GetAddress: Port %x, Path %x, Target %x, Lun %x\n",
783 ScsiAddress->PortNumber,
784 ScsiAddress->PathId,
785 ScsiAddress->TargetId,
786 ScsiAddress->Lun));
787 }
788
789 return status;
790}
791
794DeviceInitAllocateBuffers(
795 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
796 )
797/*++
798
799Routine Description:
800
801 Part of device initialize routine.
802 Allocate all buffers in Device Extension.
803
804Arguments:
805
806 DeviceExtension - device extension of WDFDEVICE.
807
808Return Value:
809
810 NTSTATUS
811
812--*/
813{
815 PVOID senseData = NULL;
816
817 PAGED_CODE();
818
819 // allocate a private extension for class data
820 if (DeviceExtension->PrivateFdoData == NULL)
821 {
822 DeviceExtension->PrivateFdoData = ExAllocatePoolWithTag(NonPagedPoolNx,
825 }
826
827 if (DeviceExtension->PrivateFdoData == NULL)
828 {
830 }
831 else
832 {
833 // initialize the struct's various fields.
834 RtlZeroMemory(DeviceExtension->PrivateFdoData, sizeof(CDROM_PRIVATE_FDO_DATA));
835 }
836
837 // Allocate request sense buffer.
838 senseData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
841
842 if (senseData == NULL)
843 {
844 // The buffer cannot be allocated.
846 }
847 else
848 {
849 // Set the sense data pointer in the device extension.
850 DeviceExtension->SenseData = senseData;
851 }
852
853 // Allocate scratch buffer -- Must occur after determining
854 // max transfer size, but before other CD specific detection
855 // (which relies upon this buffer).
856 if (!ScratchBuffer_Allocate(DeviceExtension))
857 {
859 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
860 "Failed to allocate scratch buffer, failing %!STATUS!\n",
861 status
862 ));
863 }
864
865 return status;
866}
867
870DeviceRetrieveDescriptorsAndTransferLength(
871 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
872 )
873/*++
874
875Routine Description:
876
877 Part of device initialize routine.
878 Retrieve Device Descriptor and Adaptor Descriptor.
879
880Arguments:
881
882 DeviceExtension - device extension of WDFDEVICE.
883
884Return Value:
885
886 NTSTATUS
887
888--*/
889{
891 STORAGE_PROPERTY_ID propertyId;
892
893 PAGED_CODE();
894
895 if (NT_SUCCESS(status))
896 {
897 // Call port driver to get adapter capabilities.
898 propertyId = StorageAdapterProperty;
899
900 status = DeviceRetrieveDescriptor(DeviceExtension->Device,
901 &propertyId,
902 (PSTORAGE_DESCRIPTOR_HEADER*)&DeviceExtension->AdapterDescriptor);
903 }
904 if (NT_SUCCESS(status))
905 {
906 // Call port driver to get device descriptor.
907 propertyId = StorageDeviceProperty;
908
909 status = DeviceRetrieveDescriptor(DeviceExtension->Device,
910 &propertyId,
911 (PSTORAGE_DESCRIPTOR_HEADER*)&DeviceExtension->DeviceDescriptor);
912 }
913 if (NT_SUCCESS(status))
914 {
915 // Call port driver to get device power property.
916 // Not all port drivers support this property, and it's not fatal if this query fails.
917 propertyId = StorageDevicePowerProperty;
918
919 (void) DeviceRetrieveDescriptor(DeviceExtension->Device,
920 &propertyId,
921 (PSTORAGE_DESCRIPTOR_HEADER*)&DeviceExtension->PowerDescriptor);
922 }
923
924 if (NT_SUCCESS(status))
925 {
926 // Determine the maximum page-aligned and non-page-aligned transfer
927 // lengths here, so we needn't do this in common READ/WRITE code paths
928
929 // start with the number of pages the adapter can support
930 ULONG maxAlignedTransfer = DeviceExtension->AdapterDescriptor->MaximumPhysicalPages;
931 ULONG maxUnalignedTransfer = DeviceExtension->AdapterDescriptor->MaximumPhysicalPages;
932
933
934 // Unaligned buffers could cross a page boundary.
935 if (maxUnalignedTransfer > 1)
936 {
937 maxUnalignedTransfer--;
938 }
939
940 // if we'd overflow multiplying by page size, just max out the
941 // transfer length allowed by the number of pages limit.
942 if (maxAlignedTransfer >= (((ULONG)-1) / PAGE_SIZE))
943 {
944 maxAlignedTransfer = (ULONG)-1;
945 }
946 else
947 {
948 maxAlignedTransfer *= PAGE_SIZE;
949 }
950
951 if (maxUnalignedTransfer >= (((ULONG)-1) / PAGE_SIZE))
952 {
953 maxUnalignedTransfer = (ULONG)-1;
954 }
955 else
956 {
957 maxUnalignedTransfer *= PAGE_SIZE;
958 }
959
960 // finally, take the smaller of the above and the adapter's
961 // reported maximum number of bytes per transfer.
962 maxAlignedTransfer = min(maxAlignedTransfer, DeviceExtension->AdapterDescriptor->MaximumTransferLength);
963 maxUnalignedTransfer = min(maxUnalignedTransfer, DeviceExtension->AdapterDescriptor->MaximumTransferLength);
964
965 // Make sure the values are reasonable and not zero.
966 maxAlignedTransfer = max(maxAlignedTransfer, PAGE_SIZE);
967 maxUnalignedTransfer = max(maxUnalignedTransfer, PAGE_SIZE);
968
969 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
970 "Device %p Max aligned/unaligned transfer size is %x/%x\n",
971 DeviceExtension->Device,
972 maxAlignedTransfer,
973 maxUnalignedTransfer
974 ));
975 DeviceExtension->DeviceAdditionalData.MaxPageAlignedTransferBytes = maxAlignedTransfer;
976 DeviceExtension->DeviceAdditionalData.MaxUnalignedTransferBytes = maxUnalignedTransfer;
977 }
978 else
979 {
980 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DeviceRetrieveDescriptorsAndTransferLength failed %lx\n", status));
981 }
982
983 return status;
984}
985
986
989DeviceRetrieveDescriptor(
990 _In_ WDFDEVICE Device,
993 )
994/*++
995
996Routine Description:
997
998 This routine will perform a query for the specified property id and will
999 allocate a non-paged buffer to store the data in. It is the responsibility
1000 of the caller to ensure that this buffer is freed.
1001
1002 This routine must be run at IRQL_PASSIVE_LEVEL
1003
1004Arguments:
1005
1006 Device - the device object
1007 PropertyId - type of property to retrieve
1008 Descriptor - buffer allocated in this function to hold the descriptor data
1009
1010Return Value:
1011
1012 status
1013
1014--*/
1015{
1017 WDF_MEMORY_DESCRIPTOR memoryDescriptor;
1018
1020 ULONG bufferLength = 0;
1021
1023 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
1024
1025 PAGED_CODE();
1026
1027 // Set the passed-in descriptor pointer to NULL as default
1028 *Descriptor = NULL;
1029
1030 // On the first pass we just want to get the first few
1031 // bytes of the descriptor so we can read it's size
1032 query.PropertyId = *PropertyId;
1033 query.QueryType = PropertyStandardQuery;
1034
1036
1037 NT_ASSERT(sizeof(STORAGE_PROPERTY_QUERY) >= (sizeof(ULONG)*2));
1038
1039 WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor,
1040 (PVOID)&query,
1041 sizeof(STORAGE_PROPERTY_QUERY));
1042
1043 status = WdfIoTargetSendIoctlSynchronously(deviceExtension->IoTarget,
1044 NULL,
1046 &memoryDescriptor,
1047 &memoryDescriptor,
1048 NULL,
1049 NULL);
1050
1051 if(!NT_SUCCESS(status))
1052 {
1053 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "DeviceRetrieveDescriptor: error %lx trying to "
1054 "query properties #1\n", status));
1055 return status;
1056 }
1057
1058 if (descriptor->Size == 0)
1059 {
1060 // This DebugPrint is to help third-party driver writers
1061 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "DeviceRetrieveDescriptor: size returned was zero?! (status "
1062 "%x\n", status));
1063 return STATUS_UNSUCCESSFUL;
1064 }
1065
1066 // This time we know how much data there is so we can
1067 // allocate a buffer of the correct size
1068 bufferLength = descriptor->Size;
1071
1073
1074 if(descriptor == NULL)
1075 {
1076 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "DeviceRetrieveDescriptor: unable to memory for descriptor "
1077 "(%d bytes)\n", bufferLength));
1079 }
1080
1081 // setup the query again, as it was overwritten above
1083 query.PropertyId = *PropertyId;
1084 query.QueryType = PropertyStandardQuery;
1085
1086 // copy the input to the new outputbuffer
1088 &query,
1089 sizeof(STORAGE_PROPERTY_QUERY));
1090
1091 WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor,
1093 bufferLength);
1094
1095 status = WdfIoTargetSendIoctlSynchronously(deviceExtension->IoTarget,
1096 NULL,
1098 &memoryDescriptor,
1099 &memoryDescriptor,
1100 NULL,
1101 NULL);
1102
1103 if(!NT_SUCCESS(status))
1104 {
1105 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "DeviceRetrieveDescriptor: error %lx trying to "
1106 "query properties #1\n", status));
1108
1109 return status;
1110 }
1111
1112 // return the memory we've allocated to the caller
1114
1115 return status;
1116} // end DeviceRetrieveDescriptor()
1117
1119VOID
1120DeviceRetrieveHackFlagsFromRegistry(
1121 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1122 )
1123/*++
1124
1125Routine Description:
1126
1127 try to retrieve hack flages from registry and put the information in
1128 device extension.
1129
1130Arguments:
1131
1132 DeviceExtension - the device context
1133
1134Return Value:
1135
1136 none
1137
1138--*/
1139{
1141 WDFKEY hardwareKey = NULL;
1142 WDFKEY subKey = NULL;
1143 ULONG deviceHacks = 0;
1144
1147
1148 PAGED_CODE();
1149
1150 status = WdfDeviceOpenRegistryKey(DeviceExtension->Device,
1152 KEY_READ,
1154 &hardwareKey);
1155 if (NT_SUCCESS(status))
1156 {
1157 status = WdfRegistryOpenKey(hardwareKey,
1158 &subKeyName,
1159 KEY_READ,
1161 &subKey);
1162
1163 if (NT_SUCCESS(status))
1164 {
1165 status = WdfRegistryQueryULong(subKey,
1166 &valueName,
1167 &deviceHacks);
1168 if (NT_SUCCESS(status))
1169 {
1170 // remove unknown values and save...
1171 CLEAR_FLAG(deviceHacks, FDO_HACK_INVALID_FLAGS);
1172 SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, deviceHacks);
1173 }
1174
1175 WdfRegistryClose(subKey);
1176 }
1177
1178 WdfRegistryClose(hardwareKey);
1179 }
1180
1181
1182 //
1183 // we should modify the system hive to include another key for us to grab
1184 // settings from. in this case: Classpnp\HackFlags
1185 //
1186 // the use of a DWORD value for the HackFlags allows 32 hacks w/o
1187 // significant use of the registry, and also reduces OEM exposure.
1188 //
1189 // definition of bit flags:
1190 // 0x00000001 -- Device succeeds PREVENT_MEDIUM_REMOVAL, but
1191 // cannot actually prevent removal.
1192 // 0x00000002 -- Device hard-hangs or times out for GESN requests.
1193 // 0x00000008 -- Device does not support RESERVE(6) and RELEASE(6).
1194 // 0x00000010 -- Device may incorrecly report operational changes in GESN.
1195 // 0x00000020 -- Device does not support streaming READ(12) / WRITE(12).
1196 // 0x00000040 -- Device does not support asynchronous notification.
1197 // 0xffffff80 -- Currently reserved, may be used later.
1198 //
1199
1200 return;
1201}
1202
1204VOID DeviceScanForSpecial(
1205 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1208/*++
1209
1210Routine Description:
1211
1212 scan the list of devices that should be hacked or not supported.
1213
1214Arguments:
1215
1216 DeviceExtension - the device context
1217 DeviceList - the device list
1218 Function - function used to scan from the list.
1219
1220Return Value:
1221
1222 none
1223
1224--*/
1225{
1226 PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
1227 PUCHAR vendorId;
1228 PUCHAR productId;
1229 PUCHAR productRevision;
1230 UCHAR nullString[] = "";
1231
1232 PAGED_CODE();
1235
1236 if (DeviceList == NULL)
1237 {
1238 return;
1239 }
1240 if (Function == NULL)
1241 {
1242 return;
1243 }
1244
1245 deviceDescriptor = DeviceExtension->DeviceDescriptor;
1246
1247 // SCSI sets offsets to -1, ATAPI sets to 0. check for both.
1248 if (deviceDescriptor->VendorIdOffset != 0 &&
1249 deviceDescriptor->VendorIdOffset != -1)
1250 {
1251 vendorId = ((PUCHAR)deviceDescriptor);
1252 vendorId += deviceDescriptor->VendorIdOffset;
1253 }
1254 else
1255 {
1256 vendorId = nullString;
1257 }
1258
1259 if (deviceDescriptor->ProductIdOffset != 0 &&
1260 deviceDescriptor->ProductIdOffset != -1)
1261 {
1262 productId = ((PUCHAR)deviceDescriptor);
1263 productId += deviceDescriptor->ProductIdOffset;
1264 }
1265 else
1266 {
1267 productId = nullString;
1268 }
1269
1270 if (deviceDescriptor->ProductRevisionOffset != 0 &&
1271 deviceDescriptor->ProductRevisionOffset != -1)
1272 {
1273 productRevision = ((PUCHAR)deviceDescriptor);
1274 productRevision += deviceDescriptor->ProductRevisionOffset;
1275 }
1276 else
1277 {
1278 productRevision = nullString;
1279 }
1280
1281 // loop while the device list is valid (not null-filled)
1282 for (;(DeviceList->VendorId != NULL ||
1283 DeviceList->ProductId != NULL ||
1284 DeviceList->ProductRevision != NULL); DeviceList++)
1285 {
1286 if (StringsAreMatched(DeviceList->VendorId, (LPSTR)vendorId) &&
1287 StringsAreMatched(DeviceList->ProductId, (LPSTR)productId) &&
1288 StringsAreMatched(DeviceList->ProductRevision, (LPSTR)productRevision)
1289 )
1290 {
1291
1292 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "DeviceScanForSpecial: Found matching "
1293 "controller Ven: %s Prod: %s Rev: %s\n",
1294 (LPCSTR)vendorId, (LPCSTR)productId, (LPCSTR)productRevision));
1295
1296 // pass the context to the call back routine and exit
1297 (Function)(DeviceExtension, DeviceList->Data);
1298
1299 // for CHK builds, try to prevent wierd stacks by having a debug
1300 // print here. it's a hack, but i know of no other way to prevent
1301 // the stack from being wrong.
1302 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "DeviceScanForSpecial: "
1303 "completed callback\n"));
1304 return;
1305
1306 } // else the strings did not match
1307
1308 } // none of the devices matched.
1309
1310 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "DeviceScanForSpecial: no match found for %p\n",
1311 DeviceExtension->DeviceObject));
1312 return;
1313
1314} // end DeviceScanForSpecial()
1315
1317VOID
1318DeviceHackFlagsScan(
1319 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1321 )
1322{
1323 PAGED_CODE();
1324
1325 // remove invalid flags and save
1327 SET_FLAG(DeviceExtension->PrivateFdoData->HackFlags, Data);
1328
1329 return;
1330}
1331
1332
1335DeviceInitializeHotplugInfo(
1336 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1337 )
1338/*++
1339
1340Routine Description:
1341
1342 Retrieve information into struc STORAGE_HOTPLUG_INFO in DeviceExtension
1343 initialize the hotplug information only after the ScanForSpecial routines,
1344 as it relies upon the hack flags - DeviceExtension->PrivateFdoData->HackFlags.
1345
1346Arguments:
1347
1348 DeviceExtension - the device context
1349
1350Return Value:
1351
1352 NTSTATUS
1353
1354--*/
1355{
1357 PCDROM_PRIVATE_FDO_DATA fdoData = DeviceExtension->PrivateFdoData;
1358 DEVICE_REMOVAL_POLICY deviceRemovalPolicy = 0;
1359 ULONG resultLength = 0;
1360 ULONG writeCacheOverride;
1361
1362 PAGED_CODE();
1363
1364 // start with some default settings
1365 RtlZeroMemory(&(fdoData->HotplugInfo), sizeof(STORAGE_HOTPLUG_INFO));
1366
1367 // set the size (aka version)
1368 fdoData->HotplugInfo.Size = sizeof(STORAGE_HOTPLUG_INFO);
1369
1370 // set if the device has removable media
1371 if (DeviceExtension->DeviceDescriptor->RemovableMedia)
1372 {
1373 fdoData->HotplugInfo.MediaRemovable = TRUE;
1374 }
1375 else
1376 {
1377 fdoData->HotplugInfo.MediaRemovable = FALSE;
1378 }
1379
1380 //
1381 // this refers to devices which, for reasons not yet understood,
1382 // do not fail PREVENT_MEDIA_REMOVAL requests even though they
1383 // have no way to lock the media into the drive. this allows
1384 // the filesystems to turn off delayed-write caching for these
1385 // devices as well.
1386 //
1387
1388 if (TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_CANNOT_LOCK_MEDIA))
1389 {
1390 fdoData->HotplugInfo.MediaHotplug = TRUE;
1391 }
1392 else
1393 {
1394 fdoData->HotplugInfo.MediaHotplug = FALSE;
1395 }
1396
1397 // Query the default removal policy from the kernel
1398 status = WdfDeviceQueryProperty(DeviceExtension->Device,
1400 sizeof(DEVICE_REMOVAL_POLICY),
1401 (PVOID)&deviceRemovalPolicy,
1402 &resultLength);
1403 if (NT_SUCCESS(status))
1404 {
1405 if (resultLength != sizeof(DEVICE_REMOVAL_POLICY))
1406 {
1408 }
1409 }
1410
1411 if (NT_SUCCESS(status))
1412 {
1413 // Look into the registry to see if the user has chosen
1414 // to override the default setting for the removal policy.
1415 // User can override only if the default removal policy is
1416 // orderly or suprise removal.
1417
1418 if ((deviceRemovalPolicy == RemovalPolicyExpectOrderlyRemoval) ||
1419 (deviceRemovalPolicy == RemovalPolicyExpectSurpriseRemoval))
1420 {
1421 DEVICE_REMOVAL_POLICY userRemovalPolicy = 0;
1422
1423 DeviceGetParameter(DeviceExtension,
1426 (PULONG)&userRemovalPolicy);
1427
1428 // Validate the override value and use it only if it is an
1429 // allowed value.
1430 if ((userRemovalPolicy == RemovalPolicyExpectOrderlyRemoval) ||
1431 (userRemovalPolicy == RemovalPolicyExpectSurpriseRemoval))
1432 {
1433 deviceRemovalPolicy = userRemovalPolicy;
1434 }
1435 }
1436
1437 // use this info to set the DeviceHotplug setting
1438 // don't rely on DeviceCapabilities, since it can't properly
1439 // determine device relations, etc. let the kernel figure this
1440 // stuff out instead.
1441 if (deviceRemovalPolicy == RemovalPolicyExpectSurpriseRemoval)
1442 {
1443 fdoData->HotplugInfo.DeviceHotplug = TRUE;
1444 }
1445 else
1446 {
1447 fdoData->HotplugInfo.DeviceHotplug = FALSE;
1448 }
1449
1450 // this refers to the *filesystem* caching, but has to be included
1451 // here since it's a per-device setting. this may change to be
1452 // stored by the system in the future.
1453 writeCacheOverride = FALSE;
1454 DeviceGetParameter(DeviceExtension,
1457 &writeCacheOverride);
1458
1459 if (writeCacheOverride)
1460 {
1462 }
1463 else
1464 {
1466 }
1467 }
1468
1469 if (!NT_SUCCESS(status))
1470 {
1471 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_INIT, "Could not initialize hotplug information %lx\n", status));
1472 }
1473
1474 return status;
1475}
1476
1477
1480DeviceInitMmcContext(
1481 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1482 )
1483/*++
1484
1485Routine Description:
1486
1487 This routine initializes and populates the internal data structures that are
1488 used to discover various MMC-defined capabilities of the device.
1489
1490 This routine will not clean up allocate resources if it fails - that
1491 is left for device stop/removal routines
1492
1493Arguments:
1494
1495 DeviceExtension - device extension
1496
1497Return Value:
1498
1499 NTSTATUS
1500
1501--*/
1502{
1504
1505 PAGED_CODE();
1506
1507 DeviceExtension->DeviceAdditionalData.Mmc.IsMmc = FALSE;
1508 DeviceExtension->DeviceAdditionalData.Mmc.IsAACS = FALSE;
1509 DeviceExtension->DeviceAdditionalData.Mmc.IsWriter = FALSE;
1510 DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed = FALSE;
1511 DeviceExtension->DeviceAdditionalData.Mmc.IsCssDvd = FALSE;
1512 DeviceExtension->DeviceAdditionalData.DriveDeviceType = FILE_DEVICE_CD_ROM;
1513
1514 // Determine if the drive is MMC-Capable
1515 if (NT_SUCCESS(status))
1516 {
1517 status = DeviceGetMmcSupportInfo(DeviceExtension,
1518 &DeviceExtension->DeviceAdditionalData.Mmc.IsMmc);
1519
1520 if (!NT_SUCCESS(status))
1521 {
1522 //Currently, only low resource error comes here.
1523 //That is a success case for unsupporting this command.
1524 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
1525 "DeviceInitMmcContext: Failed to get the support info for GET CONFIGURATION "
1526 "command, failng %!STATUS!\n", status
1527 ));
1528
1529 DeviceExtension->DeviceAdditionalData.Mmc.IsMmc = FALSE;
1531 }
1532 }
1533
1534 if (NT_SUCCESS(status) && DeviceExtension->DeviceAdditionalData.Mmc.IsMmc)
1535 {
1536 // the drive supports at least a subset of MMC commands
1537 // (and therefore supports READ_CD, etc...)
1538
1539 // allocate a buffer for all the capabilities and such
1540 status = DeviceAllocateMmcResources(DeviceExtension->Device);
1541 }
1542
1543 if (NT_SUCCESS(status) && DeviceExtension->DeviceAdditionalData.Mmc.IsMmc)
1544 {
1546 FEATURE_NUMBER validationSchema;
1547 ULONG blockingFactor;
1548
1549 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1550 "DeviceInitMmcContext: FDO %p GET CONFIGURATION buffer %p\n",
1551 DeviceExtension->Device,
1552 DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer
1553 ));
1554
1555 // Update several properties using the retrieved Configuration Data.
1556
1557 // print all the feature pages (DBG only)
1558 DevicePrintAllFeaturePages(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer,
1559 DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize);
1560
1561 // if AACS feature exists, enable AACS flag in the driver
1562 header = DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer,
1563 DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize,
1564 FeatureAACS);
1565 if (header)
1566 {
1567 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1568 "DeviceInitMmcContext: Reporting AACS support for device due to "
1569 "GET CONFIGURATION showing support\n"
1570 ));
1571 DeviceExtension->DeviceAdditionalData.Mmc.IsAACS = TRUE;
1572 }
1573
1574#ifdef ENABLE_AACS_TESTING
1575 DeviceExtension->DeviceAdditionalData.Mmc.IsAACS = TRUE; // just force it true for testing
1576#endif // ENABLE_AACS_TESTING
1577
1578 // Check if it's a DVD device
1579 header = DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer,
1580 DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize,
1582 if (header != NULL)
1583 {
1584 DeviceExtension->DeviceAdditionalData.DriveDeviceType = FILE_DEVICE_DVD;
1585 }
1586
1587 // check if drive is writer
1588 DeviceUpdateMmcWriteCapability(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer,
1589 DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize,
1590 FALSE, //Check if the drive has the ability to write.
1591 (PBOOLEAN)&(DeviceExtension->DeviceAdditionalData.Mmc.IsWriter),
1592 &validationSchema,
1593 &blockingFactor);
1594
1595 // check if there is a CSS protected DVD or CPPM-protected DVDAudio media in drive.
1596 header = DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer,
1597 DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize,
1599
1600 DeviceExtension->DeviceAdditionalData.Mmc.IsCssDvd = (header != NULL) && (header->Current);
1601
1602 // Flag the StartIo routine to update its state and hook in the error handler
1603 DeviceExtension->DeviceAdditionalData.Mmc.UpdateState = CdromMmcUpdateRequired;
1604 DeviceExtension->DeviceAdditionalData.ErrorHandler = DeviceErrorHandlerForMmc;
1605
1606 SET_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT);
1607
1608 // Read the CDROM mode sense page to get additional info for raw read requests.
1609 // only valid for MMC devices
1610 DeviceSetRawReadInfo(DeviceExtension);
1611 }
1612
1613 // Set Read-Only device flag for non-MMC device.
1614 if (!(DeviceExtension->DeviceAdditionalData.Mmc.IsMmc))
1615 {
1616 ULONG deviceCharacteristics = WdfDeviceGetCharacteristics(DeviceExtension->Device);
1617
1618 deviceCharacteristics |= FILE_READ_ONLY_DEVICE;
1619
1620 WdfDeviceSetCharacteristics(DeviceExtension->Device, deviceCharacteristics);
1621
1622 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1623 "DeviceInitMmcContext: FDO %p Device is not an MMC compliant device, so setting "
1624 "to read-only (legacy) mode",
1625 DeviceExtension->Device
1626 ));
1627 }
1628
1629 // Set DEV_SAFE_START_UNIT flag for newer devices.
1630 if (DeviceExtension->DeviceAdditionalData.DriveDeviceType == FILE_DEVICE_DVD)
1631 {
1632 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1633 "DeviceInitMmcContext: DVD Devices require START UNIT\n"));
1634 SET_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT);
1635
1636 }
1637 else if ((DeviceExtension->DeviceDescriptor->BusType != BusTypeScsi) &&
1638 (DeviceExtension->DeviceDescriptor->BusType != BusTypeAtapi) &&
1639 (DeviceExtension->DeviceDescriptor->BusType != BusTypeUnknown)
1640 )
1641 {
1642 // devices on the newer busses require START_UNIT
1643 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1644 "DeviceInitMmcContext: Devices for newer buses require START UNIT\n"));
1645 SET_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT);
1646 }
1647
1648 return status;
1649}
1650
1651
1653ULONG
1654DeviceGetTimeOutValueFromRegistry()
1655/*++
1656
1657Routine Description:
1658
1659 get the device time out value from registry
1660
1661Arguments:
1662
1663 None
1664
1665Return Value:
1666
1667 ULONG - value of timeout
1668
1669--*/
1670{
1672 WDFKEY registryKey = NULL;
1673 ULONG timeOutValue = 0;
1674
1675 DECLARE_CONST_UNICODE_STRING(registryValueName, L"TimeOutValue");
1676
1677 PAGED_CODE();
1678
1679 // open the service key.
1680 status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(),
1681 KEY_READ,
1683 &registryKey);
1684
1685 if (NT_SUCCESS(status))
1686 {
1687 status = WdfRegistryQueryULong(registryKey,
1688 &registryValueName,
1689 &timeOutValue);
1690
1691 WdfRegistryClose(registryKey);
1692 }
1693
1694 if (!NT_SUCCESS(status))
1695 {
1696 timeOutValue = 0;
1697 }
1698
1699 return timeOutValue;
1700
1701} // end DeviceGetTimeOutValueFromRegistry()
1702
1703
1705VOID
1706DeviceScanSpecialDevices(
1707 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1708 )
1709/*++
1710
1711Routine Description:
1712
1713 This function checks to see if an SCSI logical unit requires an special
1714 initialization or error processing.
1715
1716Arguments:
1717
1718 Device - device object.
1719
1720Return Value:
1721
1722 None.
1723
1724--*/
1725{
1726
1727 PAGED_CODE();
1728
1729 // set our hack flags
1730 DeviceScanForSpecial(DeviceExtension, CdromHackItems, ScanForSpecialHandler);
1731
1732 //
1733 // All CDRom's can ignore the queue lock failure for power operations
1734 // and do not require handling the SpinUp case (unknown result of sending
1735 // a cdrom a START_UNIT command -- may eject disks?)
1736 //
1737 // We send the stop command mostly to stop outstanding asynch operations
1738 // (like audio playback) from running when the system is powered off.
1739 // Because of this and the unlikely chance that a PLAY command will be
1740 // sent in the window between the STOP and the time the machine powers down
1741 // we don't require queue locks. This is important because without them
1742 // classpnp's power routines will send the START_STOP_UNIT command to the
1743 // device whether or not it supports locking (atapi does not support locking
1744 // and if we requested them we would end up not stopping audio on atapi
1745 // devices).
1746// SET_FLAG(deviceExtension->ScanForSpecialFlags, CDROM_SPECIAL_DISABLE_SPIN_UP);
1747// SET_FLAG(deviceExtension->ScanForSpecialFlags, CDROM_SPECIAL_NO_QUEUE_LOCK);
1748
1749 if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_TOSHIBA_SD_W1101))
1750 {
1751 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1752 "DeviceScanSpecialDevices: Found Toshiba SD-W1101 DVD-RAM "
1753 "-- This drive will *NOT* support DVD-ROM playback.\n"));
1754 }
1755 else if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_HITACHI_GD_2000))
1756 {
1757 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1758 "DeviceScanSpecialDevices: Found Hitachi GD-2000\n"));
1759
1760 // Setup an error handler to spin up the drive when it idles out
1761 // since it seems to like to fail to spin itself back up on its
1762 // own for a REPORT_KEY command. It may also lose the AGIDs that
1763 // it has given, which will result in DVD playback failures.
1764 // This routine will just do what it can...
1765 DeviceExtension->DeviceAdditionalData.ErrorHandler = DeviceErrorHandlerForHitachiGD2000;
1766
1767 // this drive may require START_UNIT commands to spin
1768 // the drive up when it's spun itself down.
1769 SET_FLAG(DeviceExtension->DeviceFlags, DEV_SAFE_START_UNIT);
1770 }
1771 else if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_FUJITSU_FMCD_10x))
1772 {
1773 // When Read command is issued to FMCD-101 or FMCD-102 and there is a music
1774 // cd in it. It takes longer time than SCSI_CDROM_TIMEOUT before returning
1775 // error status.
1776 DeviceExtension->TimeOutValue = 20;
1777 }
1778 else if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_DEC_RRD))
1779 {
1781 PMODE_PARM_READ_WRITE_DATA modeParameters;
1782 SCSI_REQUEST_BLOCK srb = {0};
1783 PCDB cdb;
1784
1785 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1786 "DeviceScanSpecialDevices: Found DEC RRD.\n"));
1787
1788 DeviceExtension->DeviceAdditionalData.IsDecRrd = TRUE;
1789
1790 // Setup an error handler to reinitialize the cd rom after it is reset?
1791 //
1792 //DeviceExtension->DevInfo->ClassError = DecRrdProcessError;
1793
1794 // Found a DEC RRD cd-rom. These devices do not pass MS HCT
1795 // multi-media tests because the DEC firmware modifieds the block
1796 // from the PC-standard 2K to 512. Change the block transfer size
1797 // back to the PC-standard 2K by using a mode select command.
1798
1799 modeParameters = ExAllocatePoolWithTag(NonPagedPoolNx,
1802 if (modeParameters == NULL)
1803 {
1804 return;
1805 }
1806
1807 RtlZeroMemory(modeParameters, sizeof(MODE_PARM_READ_WRITE_DATA));
1808 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
1809
1810 // Set the block length to 2K.
1812
1813 // Set block length to 2K (0x0800) in Parameter Block.
1814 modeParameters->ParameterListBlock.BlockLength[0] = 0x00; //MSB
1815 modeParameters->ParameterListBlock.BlockLength[1] = 0x08;
1816 modeParameters->ParameterListBlock.BlockLength[2] = 0x00; //LSB
1817
1818 // Build the mode select CDB.
1819 srb.CdbLength = 6;
1820 srb.TimeOutValue = DeviceExtension->TimeOutValue;
1821
1822 cdb = (PCDB)srb.Cdb;
1823 cdb->MODE_SELECT.PFBit = 1;
1824 cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1825 cdb->MODE_SELECT.ParameterListLength = HITACHI_MODE_DATA_SIZE;
1826
1827 // Send the request to the device.
1828 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
1829 &srb,
1830 modeParameters,
1832 TRUE,
1833 NULL);
1834
1835 if (!NT_SUCCESS(status))
1836 {
1837 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
1838 "DeviceScanSpecialDevices: Setting DEC RRD to 2K block"
1839 "size failed [%x]\n", status));
1840 }
1841
1842 ExFreePool(modeParameters);
1843 }
1844
1845 return;
1846}
1847
1849VOID
1850ScanForSpecialHandler(
1851 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1853 )
1854{
1855 PAGED_CODE();
1856
1858
1859 DeviceExtension->DeviceAdditionalData.HackFlags = HackFlags;
1860
1861 return;
1862}
1863
1864
1867DeviceCacheDeviceInquiryData(
1868 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1869 )
1870/*++
1871
1872Routine Description:
1873
1874 get inquiry data from device and cache it into device extension
1875 The first INQUIRY command sent is with 0x24 bytes required data,
1876 as ATAport driver always sends this to enumerate devices and 0x24
1877 bytes is the minimum data device should return by spec.
1878
1879Arguments:
1880
1881 DeviceExtension - device extension.
1882
1883Return Value:
1884
1885 NTSTATUS.
1886
1887--*/
1888{
1890 SCSI_REQUEST_BLOCK srb = {0};
1891 PCDB cdb = (PCDB)(&srb.Cdb);
1892 PINQUIRYDATA tmpInquiry = NULL;
1893
1894 // by spec, device should return at least 36 bytes.
1895 ULONG requestedInquiryTransferBytes = MINIMUM_CDROM_INQUIRY_SIZE;
1896 BOOLEAN needResendCommand = TRUE;
1897 BOOLEAN portDriverHack = FALSE;
1898
1899 // this ensures that the strings vendorID, productID, and firmwareRevision
1900 // are all available in the inquiry data. In addition, MMC spec requires
1901 // all type 5 devices to have minimum 36 bytes of inquiry.
1902 static const UCHAR minInquiryAdditionalLength =
1904 RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, AdditionalLength);
1905
1906 C_ASSERT( RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, AdditionalLength) <= 8 );
1908
1909 PAGED_CODE();
1910
1911 // short-circuit here for if already cached for this device
1912 // required to avoid use of scratch buffer after initialization
1913 // of MCN code.
1914 if (DeviceExtension->DeviceAdditionalData.CachedInquiryData != NULL)
1915 {
1916 NT_ASSERT(DeviceExtension->DeviceAdditionalData.CachedInquiryDataByteCount != 0);
1917 return STATUS_SUCCESS;
1918 }
1919
1920 // 1. retrieve the inquiry data length
1921
1922 // 1.1 allocate inquiry data buffer
1923 tmpInquiry = ExAllocatePoolWithTag(NonPagedPoolNx,
1924 requestedInquiryTransferBytes,
1926 if (tmpInquiry == NULL)
1927 {
1929 }
1930
1931 // 1.2 send INQUIRY command
1932 if (NT_SUCCESS(status))
1933 {
1934 srb.CdbLength = 6;
1935 cdb->AsByte[0] = SCSIOP_INQUIRY;
1936 cdb->AsByte[3] = (UCHAR)( requestedInquiryTransferBytes >> (8*1) );
1937 cdb->AsByte[4] = (UCHAR)( requestedInquiryTransferBytes >> (8*0) );
1938
1939 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
1940 &srb,
1941 tmpInquiry,
1942 requestedInquiryTransferBytes,
1943 FALSE,
1944 NULL);
1945 }
1946
1947 // 1.3 get required data length
1948 if (NT_SUCCESS(status))
1949 {
1950 if ((requestedInquiryTransferBytes == srb.DataTransferLength) &&
1951 (requestedInquiryTransferBytes == (tmpInquiry->AdditionalLength +
1952 RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, AdditionalLength))) )
1953 {
1954 // device has only 36 bytes of INQUIRY data. do not need to resend the command.
1955 needResendCommand = FALSE;
1956 }
1957 else
1958 {
1959 // workaround an ATAPI.SYS bug where additional length field is set to zero
1960 if (tmpInquiry->AdditionalLength == 0)
1961 {
1962 tmpInquiry->AdditionalLength = minInquiryAdditionalLength;
1963 portDriverHack = TRUE;
1964 }
1965
1966 requestedInquiryTransferBytes =
1967 tmpInquiry->AdditionalLength +
1968 RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, AdditionalLength);
1969
1970 if (requestedInquiryTransferBytes >= MINIMUM_CDROM_INQUIRY_SIZE)
1971 {
1972 needResendCommand = TRUE;
1973 }
1974 else
1975 {
1976 needResendCommand = FALSE;
1977 //Length is small than minimum length, error out.
1979 }
1980 }
1981 }
1982
1983 // 2. retrieve the inquiry data if still needed.
1984
1985 // 2.1 Clean up.
1986 if (NT_SUCCESS(status) && needResendCommand)
1987 {
1988 FREE_POOL(tmpInquiry);
1989 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
1990
1991 tmpInquiry = ExAllocatePoolWithTag(NonPagedPoolNx,
1992 requestedInquiryTransferBytes,
1994 if (tmpInquiry == NULL)
1995 {
1997 }
1998 }
1999
2000 // 2.2 resend INQUIRY command
2001 if (NT_SUCCESS(status) && needResendCommand)
2002 {
2003 srb.CdbLength = 6;
2004 cdb->AsByte[0] = SCSIOP_INQUIRY;
2005 cdb->AsByte[3] = (UCHAR)( requestedInquiryTransferBytes >> (8*1) );
2006 cdb->AsByte[4] = (UCHAR)( requestedInquiryTransferBytes >> (8*0) );
2007
2008 status = DeviceSendSrbSynchronously( DeviceExtension->Device,
2009 &srb,
2010 tmpInquiry,
2011 requestedInquiryTransferBytes,
2012 FALSE,
2013 NULL);
2014
2015 if (!NT_SUCCESS(status))
2016 {
2017 // Workaround for drive reports that it has more INQUIRY data than reality.
2018 if ((srb.SrbStatus == SRB_STATUS_DATA_OVERRUN) &&
2019 (srb.DataTransferLength < requestedInquiryTransferBytes) &&
2021 {
2022 //Port driver says buffer size mismatch (buffer underrun),
2023 //retry with the real buffer size it could return.
2024 requestedInquiryTransferBytes = srb.DataTransferLength;
2025
2026 FREE_POOL(tmpInquiry);
2027 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
2028
2029 tmpInquiry = ExAllocatePoolWithTag(NonPagedPoolNx,
2030 requestedInquiryTransferBytes,
2032 if (tmpInquiry == NULL)
2033 {
2035 }
2036 else
2037 {
2038 srb.CdbLength = 6;
2039 cdb->AsByte[0] = SCSIOP_INQUIRY;
2040 cdb->AsByte[3] = (UCHAR)( requestedInquiryTransferBytes >> (8*1) );
2041 cdb->AsByte[4] = (UCHAR)( requestedInquiryTransferBytes >> (8*0) );
2042
2043 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
2044 &srb,
2045 tmpInquiry,
2046 requestedInquiryTransferBytes,
2047 FALSE,
2048 NULL);
2049 }
2050 }
2051 }
2052
2053 //Check the transferred data length for safe.
2054 if (NT_SUCCESS(status))
2055 {
2056 requestedInquiryTransferBytes = srb.DataTransferLength;
2057
2058 if (requestedInquiryTransferBytes < MINIMUM_CDROM_INQUIRY_SIZE)
2059 {
2060 // should never occur
2062 }
2063 }
2064
2065 // ensure we got some non-zero data....
2066 // This is done so we don't accidentally work around the
2067 // ATAPI.SYS bug when no data was transferred.
2068 if (NT_SUCCESS(status) && portDriverHack)
2069 {
2070 PULONG tmp = (PULONG)tmpInquiry;
2072 C_ASSERT( RTL_SIZEOF_THROUGH_FIELD(INQUIRYDATA, ProductRevisionLevel) % sizeof(ULONG) == 0 );
2073
2074 // wouldn't you know it -- there is no RtlIsMemoryZero() function; Make one up.
2075 for ( ; i != 0; i--)
2076 {
2077 if (*tmp != 0)
2078 {
2079 break; // out of this inner FOR loop -- guarantees 'i != 0'
2080 }
2081 tmp++;
2082 }
2083
2084 if (i == 0) // all loop'd successfully
2085 {
2086 // should never occur to successfully get all zero'd data
2088 }
2089 }
2090 }
2091
2092 // if everything succeeded, then (and only then) modify the device extension
2093 if (NT_SUCCESS(status))
2094 {
2095 DeviceExtension->DeviceAdditionalData.CachedInquiryData = tmpInquiry;
2096 DeviceExtension->DeviceAdditionalData.CachedInquiryDataByteCount = requestedInquiryTransferBytes;
2097 }
2098 else
2099 {
2100 FREE_POOL(tmpInquiry);
2101 }
2102
2103 return status;
2104}
2105
2108DeviceGetMmcSupportInfo(
2109 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2110 _Out_ PBOOLEAN IsMmcDevice
2111 )
2112/*++
2113
2114Routine Description:
2115
2116 check if the device is MMC capable.
2117
2118Arguments:
2119
2120 DeviceExtension - device extension.
2121
2122Return Value:
2123
2124 NTSTATUS.
2125 IsMmcDevice - TRUE (MMC capable); FALSE (not MMC device)
2126
2127--*/
2128{
2130 ULONG size;
2131 ULONG previouslyFailed;
2132
2133 PAGED_CODE();
2134
2135 *IsMmcDevice = FALSE;
2136
2137 // read the registry in case the drive failed previously,
2138 // and a timeout is occurring.
2139 previouslyFailed = FALSE;
2140 DeviceGetParameter(DeviceExtension,
2143 &previouslyFailed);
2144
2145 if (previouslyFailed)
2146 {
2147 SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_GET_CONFIG_SUPPORT);
2148 }
2149
2150 // read from the registry in case the drive reports bad profile lengths
2151 previouslyFailed = FALSE;
2152 DeviceGetParameter(DeviceExtension,
2155 &previouslyFailed);
2156
2157 if (previouslyFailed)
2158 {
2159 SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_VENDOR_PROFILES);
2160 }
2161
2162 // check for the ProfileList feature to determine if the drive is MMC compliant
2163 // and set the "size" local variable to total GetConfig data size available.
2164 // NOTE: This will exit this function in some error paths.
2165 {
2166 GET_CONFIGURATION_HEADER localHeader = {0};
2167 ULONG usable = 0;
2168
2169 status = DeviceGetConfiguration(DeviceExtension->Device,
2170 &localHeader,
2172 &usable,
2175
2180 {
2181 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2182 "GetConfiguration Failed (%x), device %p not mmc-compliant\n",
2183 status, DeviceExtension->DeviceObject
2184 ));
2185
2186 previouslyFailed = TRUE;
2187 DeviceSetParameter( DeviceExtension,
2190 previouslyFailed);
2191
2192 return STATUS_SUCCESS;
2193 }
2194 else if (!NT_SUCCESS(status))
2195 {
2196 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2197 "GetConfiguration Failed, status %x -- defaulting to -ROM\n",
2198 status));
2199
2200 return STATUS_SUCCESS;
2201 }
2202 else if (usable < sizeof(GET_CONFIGURATION_HEADER))
2203 {
2204 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2205 "GetConfiguration Failed, returned only %x bytes!\n", usable));
2206 previouslyFailed = TRUE;
2207 DeviceSetParameter( DeviceExtension,
2210 previouslyFailed);
2211
2212 return STATUS_SUCCESS;
2213 }
2214
2215 size = (localHeader.DataLength[0] << 24) |
2216 (localHeader.DataLength[1] << 16) |
2217 (localHeader.DataLength[2] << 8) |
2218 (localHeader.DataLength[3] << 0) ;
2219
2220
2221 if ((size <= 4) || (size + 4 < size))
2222 {
2223 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2224 "GetConfiguration Failed, claims MMC support but doesn't "
2225 "correctly return config length! (%x)\n",
2226 size
2227 ));
2228 previouslyFailed = TRUE;
2229 DeviceSetParameter( DeviceExtension,
2232 previouslyFailed);
2233
2234 return STATUS_SUCCESS;
2235 }
2236 else if ((size % 4) != 0)
2237 {
2238 if ((size % 2) != 0)
2239 {
2240 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2241 "GetConfiguration Failed, returned odd number of bytes %x!\n",
2242 size
2243 ));
2244 previouslyFailed = TRUE;
2245 DeviceSetParameter( DeviceExtension,
2248 previouslyFailed);
2249
2250 return STATUS_SUCCESS;
2251 }
2252 else
2253 {
2254 if (TEST_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_VENDOR_PROFILES))
2255 {
2256 // we've already caught this and ASSERT'd once, so don't do it again
2257 }
2258 else
2259 {
2260 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2261 "GetConfiguration returned a size that is not per spec (%x bytes), this is probably because of a vendor specific data header with a size not divisible by 4.\n",
2262 size
2263 ));
2264 previouslyFailed = TRUE;
2265 DeviceSetParameter(DeviceExtension,
2268 previouslyFailed);
2269 }
2270 }
2271 }
2272
2273 size += 4; // sizeof the datalength fields
2274 }
2275
2276 *IsMmcDevice = TRUE;
2277
2278 // This code doesn't handle total get config size over 64k
2279 NT_ASSERT( size <= MAXUSHORT );
2280
2281 // Check for SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE support in the device.
2282 // NOTE: This will exit this function in some error paths.
2283 {
2284 ULONG featureSize = sizeof(GET_CONFIGURATION_HEADER)+sizeof(FEATURE_HEADER);
2285 ULONG usable = 0;
2286
2288 NonPagedPoolNx,
2289 featureSize,
2291
2292 if (configBuffer == NULL)
2293 {
2295 }
2296
2297 // read the registry in case the drive failed previously,
2298 // and a timeout is occurring.
2299 previouslyFailed = FALSE;
2300 DeviceGetParameter( DeviceExtension,
2303 &previouslyFailed);
2304
2305 if (previouslyFailed)
2306 {
2307 SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG);
2308 FREE_POOL(configBuffer);
2309 return STATUS_SUCCESS;
2310 }
2311
2312 // Get only the config and feature header
2313 status = DeviceGetConfiguration(DeviceExtension->Device,
2314 configBuffer,
2315 featureSize,
2316 &usable,
2319
2320 if (!NT_SUCCESS(status) || (usable < featureSize))
2321 {
2322 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2323 "Type One GetConfiguration Failed. Usable buffer size: %d\n", usable));
2324 previouslyFailed = TRUE;
2325 }
2326 else
2327 {
2328 PFEATURE_HEADER featureHeader;
2329 ULONG totalAvailableBytes = 0;
2330 ULONG expectedAvailableBytes = 0;
2331
2332 REVERSE_BYTES(&totalAvailableBytes, configBuffer->DataLength);
2334
2335 featureHeader = (PFEATURE_HEADER) ((PUCHAR)configBuffer + sizeof(GET_CONFIGURATION_HEADER));
2336 expectedAvailableBytes = sizeof(GET_CONFIGURATION_HEADER) +
2337 sizeof(FEATURE_HEADER) +
2338 featureHeader->AdditionalLength;
2339
2340 if (totalAvailableBytes > expectedAvailableBytes)
2341 {
2342 // Device is returning more than required size. Most likely the device
2343 // is returning TYPE ALL data. Set the flag to use TYPE ALL for TYPE ONE
2344 // requets
2345 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2346 "Type One GetConfiguration Failed. "
2347 "Device returned %d bytes instead of %d bytes\n",
2348 size, featureSize));
2349
2350 previouslyFailed = TRUE;
2351 }
2352 }
2353
2354 FREE_POOL(configBuffer);
2355
2356 if (previouslyFailed == TRUE)
2357 {
2358 DeviceSetParameter( DeviceExtension,
2361 previouslyFailed);
2362
2363 SET_FLAG(DeviceExtension->DeviceAdditionalData.HackFlags, CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG);
2364 }
2365 }
2366
2367 return status;
2368}
2369
2370
2373DeviceSetRawReadInfo(
2374 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
2375 )
2376/*++
2377
2378Routine Description:
2379
2380 This routine reads the CDROM capabilities mode page and save information
2381 in the device extension needed for raw reads.
2382 NOTE: this function is only valid for MMC device
2383
2384Arguments:
2385
2386 DeviceExtension - device context
2387
2388Return Value:
2389
2390 NTSTATUS
2391
2392--*/
2393{
2395 PUCHAR buffer = NULL;
2396 ULONG count = 0;
2397
2398 PAGED_CODE();
2399
2400 // Check whether the device can return C2 error flag bits and the block
2401 // error byte. If so, save this info and fill in appropriate flag during
2402 // raw read requests.
2403
2404 // Start by checking the GET_CONFIGURATION data
2405 {
2406 PFEATURE_DATA_CD_READ cdReadHeader = NULL;
2408
2409 cdReadHeader = DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer,
2410 DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize,
2412
2413 if ((cdReadHeader != NULL) &&
2414 (cdReadHeader->Header.AdditionalLength >= additionalLength) &&
2415 (cdReadHeader->C2ErrorData)
2416 )
2417 {
2418 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2419 "DeviceSetRawReadInfo: FDO %p GET_CONFIG shows ability to read C2 error bits\n",
2420 DeviceExtension->DeviceObject
2421 ));
2422 DeviceExtension->DeviceAdditionalData.Mmc.ReadCdC2Pointers = TRUE; // Device returns C2 error info.
2423 }
2424 }
2425
2426 // Unfortunately, the only way to check for the ability to read R-W subcode
2427 // information is via MODE_SENSE. Do so here, and check the C2 bit as well
2428 // in case the drive has a firmware bug where it fails to report this ability
2429 // in GET_CONFIG (which some drives do).
2430 for (count = 0; count < 6; count++)
2431 {
2432 SCSI_REQUEST_BLOCK srb = {0};
2433 PCDB cdb = (PCDB)srb.Cdb;
2434 ULONG bufferLength = 0;
2435
2436 // Build the MODE SENSE CDB. Try 10-byte CDB first.
2437 if ((count/3) == 0)
2438 {
2440 sizeof(MODE_PARAMETER_HEADER10) +
2441 sizeof(MODE_PARAMETER_BLOCK);
2442
2443 cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
2444 cdb->MODE_SENSE10.Dbd = 1;
2445 cdb->MODE_SENSE10.PageCode = MODE_PAGE_CAPABILITIES;
2446 cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(bufferLength >> 8);
2447 cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(bufferLength >> 0);
2448 srb.CdbLength = 10;
2449 }
2450 else
2451 {
2453 sizeof(MODE_PARAMETER_HEADER) +
2454 sizeof(MODE_PARAMETER_BLOCK);
2455
2456 cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
2457 cdb->MODE_SENSE.Dbd = 1;
2458 cdb->MODE_SENSE.PageCode = MODE_PAGE_CAPABILITIES;
2459 cdb->MODE_SENSE.AllocationLength = (UCHAR)bufferLength;
2460 srb.CdbLength = 6;
2461 }
2462
2463 // Set timeout value from device extension.
2464 srb.TimeOutValue = DeviceExtension->TimeOutValue;
2465
2467
2468 if (buffer == NULL)
2469 {
2470 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
2471 "DeviceSetRawReadInfo: cannot allocate "
2472 "buffer, so not setting raw read info for FDO %p\n",
2473 DeviceExtension->DeviceObject
2474 ));
2476 goto FnExit;
2477 }
2478
2480
2481 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
2482 &srb,
2483 buffer,
2485 FALSE,
2486 NULL);
2487
2488 if (NT_SUCCESS(status) ||
2491 {
2492 PCDVD_CAPABILITIES_PAGE capabilities = NULL;
2493
2494 // determine where the capabilities page really is
2495 if ((count/3) == 0)
2496 {
2498 capabilities = (PCDVD_CAPABILITIES_PAGE)(buffer +
2499 sizeof(MODE_PARAMETER_HEADER10) +
2500 (p->BlockDescriptorLength[0] * 256) +
2501 p->BlockDescriptorLength[1]);
2502 }
2503 else
2504 {
2506 capabilities = (PCDVD_CAPABILITIES_PAGE)(buffer +
2507 sizeof(MODE_PARAMETER_HEADER) +
2508 p->BlockDescriptorLength);
2509 }
2510
2511 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2512 "DeviceSetRawReadInfo: FDO %p CDVD Capabilities buffer %p\n",
2513 DeviceExtension->DeviceObject,
2514 buffer
2515 ));
2516
2517 if (capabilities->PageCode == MODE_PAGE_CAPABILITIES)
2518 {
2519 if (capabilities->C2Pointers)
2520 {
2521 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2522 "DeviceSetRawReadInfo: FDO %p supports C2 error bits in READ_CD command\n",
2523 DeviceExtension->DeviceObject
2524 ));
2525 DeviceExtension->DeviceAdditionalData.Mmc.ReadCdC2Pointers = TRUE;
2526 }
2527
2528 if (capabilities->RWSupported)
2529 {
2530 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2531 "DeviceSetRawReadInfo: FDO %p supports raw subcode in READ_CD command\n",
2532 DeviceExtension->DeviceObject
2533 ));
2534 DeviceExtension->DeviceAdditionalData.Mmc.ReadCdSubCode = TRUE;
2535 }
2536
2537 break;
2538 }
2539 }
2540
2541 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2542 "DeviceSetRawReadInfo: FDO %p failed %x byte mode sense, status %x\n",
2543 DeviceExtension->DeviceObject,
2544 (((count/3) == 0) ? 10 : 6),
2545 status
2546 ));
2547
2549 }
2550
2551 if (count == 6)
2552 {
2553 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2554 "DeviceSetRawReadInfo: FDO %p couldn't get mode sense data\n",
2555 DeviceExtension->DeviceObject
2556 ));
2557 }
2558
2559FnExit:
2560
2561 if (buffer)
2562 {
2564 }
2565
2566 return status;
2567}
2568
2569
2572DeviceInitializeDvd(
2573 _In_ WDFDEVICE Device
2574 )
2575/*++
2576
2577Routine Description:
2578
2579 This routine sets the region of DVD drive
2580 NOTE: this routine uses ScratchBuffer, it must be called after ScratchBuffer allocated.
2581
2582Arguments:
2583
2584 Device - device object
2585
2586Return Value:
2587
2588 NTSTATUS
2589
2590--*/
2591
2592{
2594 PCDROM_DEVICE_EXTENSION deviceExtension;
2595 PDVD_COPY_PROTECT_KEY copyProtectKey = NULL;
2596 PDVD_RPC_KEY rpcKey = NULL;
2597 ULONG bufferLen = 0;
2598 size_t bytesReturned;
2599
2600 PAGED_CODE();
2601
2602 deviceExtension = DeviceGetExtension(Device);
2603
2604 // check to see if we have a DVD device
2606 {
2607 return STATUS_SUCCESS;
2608 }
2609
2610 // we got a DVD drive.
2611 bufferLen = DVD_RPC_KEY_LENGTH;
2613 bufferLen,
2615
2616 if (copyProtectKey == NULL)
2617 {
2619 }
2620
2621 // get the device region
2622 RtlZeroMemory (copyProtectKey, bufferLen);
2623 copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH;
2624 copyProtectKey->KeyType = DvdGetRpcKey;
2625
2626 // perform IOCTL_DVD_READ_KEY
2627 status = DvdStartSessionReadKey(deviceExtension,
2629 NULL,
2630 copyProtectKey,
2632 copyProtectKey,
2634 &bytesReturned);
2635
2636 if (NT_SUCCESS(status))
2637 {
2638 rpcKey = (PDVD_RPC_KEY)copyProtectKey->KeyData;
2639
2640 // TypeCode of zero means that no region has been set.
2641 if (rpcKey->TypeCode == 0)
2642 {
2643 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP,
2644 "DVD Initialize (%p): must choose DVD region\n",
2645 Device));
2646 deviceExtension->DeviceAdditionalData.PickDvdRegion = 1;
2647
2648 // set the device region code to be the same as region code on media.
2649 if (deviceExtension->DeviceAdditionalData.Mmc.IsCssDvd)
2650 {
2651 DevicePickDvdRegion(Device);
2652 }
2653 }
2654 }
2655
2656 FREE_POOL(copyProtectKey);
2657
2658 // return status of IOCTL_DVD_READ_KEY will be ignored.
2659 return STATUS_SUCCESS;
2660}
2661
2662
2663#if (NTDDI_VERSION >= NTDDI_WIN8)
2666DeviceIsPortable(
2667 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2668 _Out_ PBOOLEAN IsPortable
2669 )
2670/*++
2671
2672Routine Description:
2673
2674 This routine checks if the volume is on a portable storage device.
2675
2676Arguments:
2677
2678 DeviceExtension - device context
2679 IsPortable - device is portable
2680
2681Return Value:
2682
2683 NTSTATUS.
2684
2685--*/
2686
2687{
2688 DEVPROP_BOOLEAN isInternal = DEVPROP_FALSE;
2689 BOOLEAN isPortable = FALSE;
2690 ULONG size = 0;
2693
2694 PAGED_CODE();
2695
2696 *IsPortable = FALSE;
2697
2698 // Check to see if the underlying device object is in local machine container
2699 status = IoGetDevicePropertyData(DeviceExtension->LowerPdo,
2700 &DEVPKEY_Device_InLocalMachineContainer,
2701 0,
2702 0,
2703 sizeof(isInternal),
2704 &isInternal,
2705 &size,
2706 &type);
2707
2708 if (!NT_SUCCESS(status))
2709 {
2710 goto Cleanup;
2711 }
2712
2713 NT_ASSERT(size == sizeof(isInternal));
2715
2716 // Volume is hot-pluggable if the disk pdo container id differs from that of root device
2717 if (isInternal == DEVPROP_TRUE)
2718 {
2719 goto Cleanup;
2720 }
2721
2722 isPortable = TRUE;
2723
2724 // Examine the bus type to ensure that this really is a fixed device
2725 if (DeviceExtension->DeviceDescriptor->BusType == BusTypeFibre ||
2726 DeviceExtension->DeviceDescriptor->BusType == BusTypeiScsi ||
2727 DeviceExtension->DeviceDescriptor->BusType == BusTypeRAID)
2728 {
2729 isPortable = FALSE;
2730 }
2731
2732 *IsPortable = isPortable;
2733
2734Cleanup:
2735
2736 return status;
2737}
2738#endif
2739
2740
2741#pragma warning(pop) // un-sets any local warning changes
2742
#define PAGED_CODE()
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
VOID DeviceSetMediaChangeStateEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
Definition: autorun.c:751
NTSTATUS DeviceErrorHandlerForMmc(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Inout_ PNTSTATUS Status, _Inout_ PBOOLEAN Retry)
Definition: sense.c:87
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
VOID(* PCDROM_SCAN_FOR_SPECIAL_HANDLER)(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG_PTR Data)
Definition: cdrom.h:775
#define CDROM_HACK_INVALID_FLAGS
Definition: cdrom.h:105
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG
Definition: cdrom.h:99
#define CdromMmcUpdateRequired
Definition: cdrom.h:242
#define CDROM_TAG_GET_CONFIG
Definition: cdrom.h:728
#define CDROM_HACK_BAD_GET_CONFIG_SUPPORT
Definition: cdrom.h:96
#define CDROM_TYPE_ONE_GET_CONFIG_NAME
Definition: cdrom.h:757
_In_ PSTORAGE_PROPERTY_ID PropertyId
Definition: cdrom.h:932
#define CDROM_HACK_HITACHI_GD_2000
Definition: cdrom.h:91
#define CDROM_HACK_TOSHIBA_SD_W1101
Definition: cdrom.h:92
_In_ BOOLEAN Release
Definition: cdrom.h:920
#define CDROM_HACK_FUJITSU_FMCD_10x
Definition: cdrom.h:89
#define CDROM_HACK_DEC_RRD
Definition: cdrom.h:88
CDROM_SCAN_FOR_SPECIAL_INFO CdromHackItems[]
Definition: data.c:44
#define CDROM_HACK_BAD_VENDOR_PROFILES
Definition: cdrom.h:100
EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT DeviceEvtSelfManagedIoInit
Definition: cdrom.h:874
#define DVD_TAG_RPC2_CHECK
Definition: cdrom.h:748
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
EVT_WDF_REQUEST_COMPLETION_ROUTINE DeviceReleaseQueueCompletion
Definition: cdrom.h:1052
#define CDROM_TAG_INQUIRY
Definition: cdrom.h:736
#define CDROM_NON_MMC_DRIVE_NAME
Definition: cdrom.h:756
#define CDROM_TAG_MODE_DATA
Definition: cdrom.h:737
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
#define SCSI_CDROM_OPC_TIMEOUT
Definition: cdrom.h:688
#define CDROM_NON_MMC_VENDOR_SPECIFIC_PROFILE
Definition: cdrom.h:758
#define HITACHI_MODE_DATA_SIZE
Definition: cdrom.h:690
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define CDROM_SUBKEY_NAME
Definition: cdrom.h:754
#define CDROM_TAG_STRINGS
Definition: cdrom.h:743
_In_ ULONG_PTR HackFlags
Definition: cdrom.h:983
#define CDROM_TAG_DESCRIPTOR
Definition: cdrom.h:730
NTSTATUS DeviceErrorHandlerForHitachiGD2000(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _Inout_ PNTSTATUS Status, _Inout_ PBOOLEAN Retry)
Definition: sense.c:361
#define CDROM_TAG_SENSE_INFO
Definition: cdrom.h:735
#define CLASS_PERF_RESTORE_MINIMUM
Definition: cdromp.h:129
#define CLASSP_REG_HACK_VALUE_NAME
Definition: cdromp.h:122
#define CLASSP_REG_PERF_RESTORE_VALUE_NAME
Definition: cdromp.h:125
#define CDROM_TAG_PRIVATE_DATA
Definition: cdromp.h:173
@ MediaPresent
Definition: cdromp.h:82
#define CLASSP_REG_WRITE_CACHE_VALUE_NAME
Definition: cdromp.h:124
#define FDO_HACK_INVALID_FLAGS
Definition: cdromp.h:141
CDROM_SCAN_FOR_SPECIAL_INFO CdRomBadItems[]
Definition: data.c:100
#define FDO_HACK_CANNOT_LOCK_MEDIA
Definition: cdromp.h:133
#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME
Definition: cdromp.h:126
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
struct _MODE_PARAMETER_HEADER10 * PMODE_PARAMETER_HEADER10
#define IOCTL_SCSI_EXECUTE_NONE
Definition: cdrw_hw.h:1453
#define SENSE_BUFFER_SIZE
Definition: cdrw_hw.h:1183
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
union _CDB * PCDB
struct _MODE_PARAMETER_BLOCK MODE_PARAMETER_BLOCK
struct _MODE_PARAMETER_HEADER * PMODE_PARAMETER_HEADER
#define SCSIOP_MODE_SELECT
Definition: cdrw_hw.h:891
#define MODE_PAGE_CAPABILITIES
Definition: cdrw_hw.h:854
#define IOCTL_DVD_READ_KEY
Definition: cdrw_usr.h:160
#define DVD_RPC_KEY_LENGTH
Definition: cdrw_usr.h:1597
#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
PDEVICE_LIST DeviceList
Definition: utils.c:27
static const WCHAR Cleanup[]
Definition: register.c:80
struct _DVD_RPC_KEY * PDVD_RPC_KEY
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_FUNCTION_RELEASE_DEVICE
Definition: srb.h:321
#define SRB_FUNCTION_CLAIM_DEVICE
Definition: srb.h:316
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:406
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define DO_SYSTEM_BOOT_PARTITION
Definition: env_spec_w32.h:400
#define PagedPool
Definition: env_spec_w32.h:308
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
GLuint buffer
Definition: glext.h:5915
GLfloat GLfloat p
Definition: glext.h:8902
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
#define FILE_PORTABLE_DEVICE
Definition: winternl.h:1855
#define C_ASSERT(e)
Definition: intsafe.h:73
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
if(dx< 0)
Definition: linetemp.h:194
struct _STORAGE_HOTPLUG_INFO STORAGE_HOTPLUG_INFO
#define min(a, b)
Definition: monoChain.cc:55
#define _Outptr_
Definition: ms_sal.h:427
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FILE_READ_ONLY_DEVICE
Definition: nt_native.h:808
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
#define MINIMUM_CDROM_INQUIRY_SIZE
Definition: ntddcdrm.h:128
struct _FEATURE_HEADER * PFEATURE_HEADER
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE
Definition: ntddmmc.h:17
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL
Definition: ntddmmc.h:15
enum _FEATURE_NUMBER FEATURE_NUMBER
@ FeatureAACS
Definition: ntddmmc.h:127
@ FeatureCdRead
Definition: ntddmmc.h:82
@ FeatureProfileList
Definition: ntddmmc.h:75
@ FeatureDvdCSS
Definition: ntddmmc.h:120
@ FeatureDvdRead
Definition: ntddmmc.h:83
struct _GET_CONFIGURATION_HEADER GET_CONFIGURATION_HEADER
struct _FEATURE_DATA_CD_READ FEATURE_DATA_CD_READ
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
* PSTORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
enum _STORAGE_PROPERTY_ID STORAGE_PROPERTY_ID
@ BusTypeScsi
Definition: ntddstor.h:439
@ BusTypeiScsi
Definition: ntddstor.h:447
@ BusTypeRAID
Definition: ntddstor.h:446
@ BusTypeFibre
Definition: ntddstor.h:444
@ BusTypeAtapi
Definition: ntddstor.h:440
@ BusTypeUnknown
Definition: ntddstor.h:438
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:576
@ StorageAdapterProperty
Definition: ntddstor.h:513
@ StorageDevicePowerProperty
Definition: ntddstor.h:524
@ StorageDeviceProperty
Definition: ntddstor.h:512
@ PropertyStandardQuery
Definition: ntddstor.h:505
enum _STORAGE_PROPERTY_ID * PSTORAGE_PROPERTY_ID
#define STATUS_DEVICE_PROTOCOL_ERROR
Definition: ntstatus.h:623
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
_Null_terminated_ wchar_t * NTSTRSAFE_PWSTR
Definition: ntstrsafe.h:58
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
@ DvdGetRpcKey
Definition: ntddcdvd.h:170
struct _DVD_COPY_PROTECT_KEY * PDVD_COPY_PROTECT_KEY
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:108
#define FILE_DEVICE_DVD
Definition: winioctl.h:157
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
descriptor
Definition: scsi.h:3951
struct _CDVD_CAPABILITIES_PAGE * PCDVD_CAPABILITIES_PAGE
UCHAR additionalLength
Definition: scsi.h:3943
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
struct _CDVD_CAPABILITIES_PAGE CDVD_CAPABILITIES_PAGE
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_FATAL
Definition: storswtr.h:26
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
CDROM_MMC_EXTENSION Mmc
Definition: cdrom.h:341
DEVICE_TYPE DriveDeviceType
Definition: cdrom.h:388
ULONG PickDvdRegion
Definition: cdrom.h:354
WDFIOTARGET IoTarget
Definition: cdrom.h:476
PDEVICE_OBJECT DeviceObject
Definition: cdrom.h:493
PCDROM_PRIVATE_FDO_DATA PrivateFdoData
Definition: cdrom.h:605
BOOLEAN IsInitialized
Definition: cdrom.h:464
UNICODE_STRING MountedDeviceInterfaceName
Definition: cdrom.h:536
SCSI_ADDRESS ScsiAddress
Definition: cdrom.h:521
CDROM_DATA DeviceAdditionalData
Definition: cdrom.h:598
BOOLEAN IsCssDvd
Definition: cdrom.h:252
BOOLEAN IsWriter
Definition: cdrom.h:249
struct _CDROM_PRIVATE_FDO_DATA::@1046 Perf
STORAGE_HOTPLUG_INFO HotplugInfo
Definition: cdromp.h:343
DVD_KEY_TYPE KeyType
Definition: ntddcdvd.h:178
UCHAR TypeCode
Definition: scsi.h:2925
FEATURE_HEADER Header
Definition: ntddmmc.h:197
UCHAR AdditionalLength
Definition: ntddmmc.h:34
UCHAR AdditionalLength
Definition: cdrw_hw.h:1122
UCHAR BlockLength[3]
Definition: cdrw_hw.h:2531
MODE_PARAMETER_HEADER ParameterListHeader
Definition: cdrw_hw.h:2536
MODE_PARAMETER_BLOCK ParameterListBlock
Definition: cdrw_hw.h:2537
ULONG TimeOutValue
Definition: srb.h:262
PVOID OriginalRequest
Definition: srb.h:266
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
UCHAR Function
Definition: srb.h:250
ULONG DataTransferLength
Definition: srb.h:261
ULONG SrbFlags
Definition: srb.h:260
USHORT Length
Definition: srb.h:249
UCHAR SrbStatus
Definition: srb.h:251
BOOLEAN WriteCacheEnableOverride
Definition: imports.h:249
BOOLEAN MediaRemovable
Definition: imports.h:246
BOOLEAN DeviceHotplug
Definition: imports.h:248
BOOLEAN MediaHotplug
Definition: imports.h:247
USHORT MaximumLength
Definition: env_spec_w32.h:370
WDFOBJECT ParentObject
Definition: wdfobject.h:130
Definition: tftpd.h:86
Definition: ps.c:97
#define max(a, b)
Definition: svc.c:63
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#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_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: cdrw_hw.h:28
struct _CDB::_MODE_SELECT MODE_SELECT
UCHAR AsByte[16]
Definition: scsi.h:1988
struct _CDB::_MODE_SENSE10 MODE_SENSE10
struct _CDB::_MODE_SENSE MODE_SENSE
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
#define DECLARE_CONST_UNICODE_STRING(_variablename, _string)
Definition: wdfcore.h:161
FORCEINLINE WDFDRIVER WdfGetDriver(VOID)
Definition: wdfdriver.h:194
_In_opt_ PVOID _In_ ULONG bufferLength
Definition: wdfdriver.h:109
FORCEINLINE VOID WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(_Out_ PWDF_MEMORY_DESCRIPTOR Descriptor, _In_ PVOID Buffer, _In_ ULONG BufferLength)
Definition: wdfmemory.h:102
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
#define WDF_NO_OBJECT_ATTRIBUTES
Definition: wdftypes.h:105
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2786
enum _DEVICE_REMOVAL_POLICY DEVICE_REMOVAL_POLICY
#define DO_SYSTEM_CRITICAL_PARTITION
@ DevicePropertyRemovalPolicy
Definition: iotypes.h:1214
#define DO_SYSTEM_SYSTEM_PARTITION
@ RemovalPolicyExpectSurpriseRemoval
Definition: iotypes.h:842
@ RemovalPolicyExpectOrderlyRemoval
Definition: iotypes.h:841
#define NT_ASSERT
Definition: rtlfuncs.h:3310
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180