ReactOS 0.4.15-dev-8058-ga7cbb60
ioctl.c
Go to the documentation of this file.
1/*--
2
3Copyright (C) Microsoft Corporation. All rights reserved.
4
5Module Name:
6
7 ioctl.c
8
9Abstract:
10
11 Include all funtions for processing IOCTLs
12
13Environment:
14
15 kernel mode only
16
17Notes:
18
19
20Revision History:
21
22--*/
23
24#include "stddef.h"
25#include "string.h"
26
27#include "ntddk.h"
28#include "ntddstor.h"
29#include "cdrom.h"
30#include "ioctl.h"
31#include "scratch.h"
32#include "mmc.h"
33
34
35#ifdef DEBUG_USE_WPP
36#include "ioctl.tmh"
37#endif
38
39
40#define FirstDriveLetter 'C'
41#define LastDriveLetter 'Z'
42
43#if DBG
44 LPCSTR READ_DVD_STRUCTURE_FORMAT_STRINGS[DvdMaxDescriptor+1] = {
45 "Physical",
46 "Copyright",
47 "DiskKey",
48 "BCA",
49 "Manufacturer",
50 "Unknown"
51 };
52#endif // DBG
53
55VOID
56GetConfigurationDataConversionTypeAllToTypeOne(
57 _In_ FEATURE_NUMBER RequestedFeature,
59 _Out_ size_t * DataLength
60 );
61
63VOID
64GetConfigurationDataSynthesize(
65 _In_reads_bytes_(InputBufferSize) PVOID InputBuffer,
66 _In_ ULONG InputBufferSize,
67 _Out_writes_bytes_(OutputBufferSize) PVOID OutputBuffer,
68 _In_ size_t OutputBufferSize,
71 _Out_ size_t * DataLength
72 );
73
75PCDB
76RequestGetScsiPassThroughCdb(
78 );
79
80#ifdef ALLOC_PRAGMA
81
82#pragma alloc_text(PAGE, DeviceIsPlayActive)
83#pragma alloc_text(PAGE, RequestHandleGetDvdRegion)
84#pragma alloc_text(PAGE, RequestHandleReadTOC)
85#pragma alloc_text(PAGE, RequestHandleReadTocEx)
86#pragma alloc_text(PAGE, RequestHandleGetConfiguration)
87#pragma alloc_text(PAGE, RequestHandleGetDriveGeometry)
88#pragma alloc_text(PAGE, RequestHandleDiskVerify)
89#pragma alloc_text(PAGE, RequestHandleCheckVerify)
90#pragma alloc_text(PAGE, RequestHandleFakePartitionInfo)
91#pragma alloc_text(PAGE, RequestHandleEjectionControl)
92#pragma alloc_text(PAGE, RequestHandleEnableStreaming)
93#pragma alloc_text(PAGE, RequestHandleSendOpcInformation)
94#pragma alloc_text(PAGE, RequestHandleGetPerformance)
95#pragma alloc_text(PAGE, RequestHandleMcnSyncFakeIoctl)
96#pragma alloc_text(PAGE, RequestHandleLoadEjectMedia)
97#pragma alloc_text(PAGE, RequestHandleReserveRelease)
98#pragma alloc_text(PAGE, RequestHandlePersistentReserve)
99#pragma alloc_text(PAGE, DeviceHandleRawRead)
100#pragma alloc_text(PAGE, DeviceHandlePlayAudioMsf)
101#pragma alloc_text(PAGE, DeviceHandleReadQChannel)
102#pragma alloc_text(PAGE, ReadQChannel)
103#pragma alloc_text(PAGE, DeviceHandlePauseAudio)
104#pragma alloc_text(PAGE, DeviceHandleResumeAudio)
105#pragma alloc_text(PAGE, DeviceHandleSeekAudioMsf)
106#pragma alloc_text(PAGE, DeviceHandleStopAudio)
107#pragma alloc_text(PAGE, DeviceHandleGetSetVolume)
108#pragma alloc_text(PAGE, DeviceHandleReadDvdStructure)
109#pragma alloc_text(PAGE, ReadDvdStructure)
110#pragma alloc_text(PAGE, DeviceHandleDvdEndSession)
111#pragma alloc_text(PAGE, DeviceHandleDvdStartSessionReadKey)
112#pragma alloc_text(PAGE, DvdStartSessionReadKey)
113#pragma alloc_text(PAGE, DeviceHandleDvdSendKey)
114#pragma alloc_text(PAGE, DvdSendKey)
115#pragma alloc_text(PAGE, DeviceHandleSetReadAhead)
116#pragma alloc_text(PAGE, DeviceHandleSetSpeed)
117#pragma alloc_text(PAGE, RequestHandleExclusiveAccessQueryLockState)
118#pragma alloc_text(PAGE, RequestHandleExclusiveAccessLockDevice)
119#pragma alloc_text(PAGE, RequestHandleExclusiveAccessUnlockDevice)
120#pragma alloc_text(PAGE, RequestHandleScsiPassThrough)
121#pragma alloc_text(PAGE, RequestGetScsiPassThroughCdb)
122#pragma alloc_text(PAGE, GetConfigurationDataConversionTypeAllToTypeOne)
123#pragma alloc_text(PAGE, GetConfigurationDataSynthesize)
124
125#endif
126
129 _In_ WDFDEVICE Device,
130 _In_ WDFREQUEST Request
131 )
132/*++
133
134Routine Description:
135
136 All unknown IOCTLs will be forward to lower level driver.
137
138Arguments:
139
140 Device - device object
141 Request - request to be handled
142
143Return Value:
144
145 NTSTATUS
146
147--*/
148{
150 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
151 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
152 BOOLEAN syncRequired = requestContext->SyncRequired;
153
154 ULONG sendOptionsFlags = 0;
155 BOOLEAN requestSent = FALSE;
156
157 WdfRequestFormatRequestUsingCurrentType(Request);
158
159 if (syncRequired)
160 {
161 sendOptionsFlags = WDF_REQUEST_SEND_OPTION_SYNCHRONOUS;
162 }
163 else
164 {
165 WdfRequestSetCompletionRoutine(Request, RequestDummyCompletionRoutine, NULL);
166 }
167
168 status = RequestSend(deviceExtension,
169 Request,
170 deviceExtension->IoTarget,
171 sendOptionsFlags,
172 &requestSent);
173
174 if (requestSent)
175 {
176 if (syncRequired)
177 {
178 // the request needs to be completed here.
179 RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
180 }
181 }
182 else
183 {
184 // failed to send the request to IoTarget
185 RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
186 }
187
188 return status;
189}
190
193DeviceIsPlayActive(
194 _In_ WDFDEVICE Device
195 )
196/*++
197
198Routine Description:
199
200 This routine determines if the cd is currently playing music.
201
202Arguments:
203
204 Device - Device object.
205
206Return Value:
207
208 BOOLEAN - TRUE if the device is playing music.
209
210--*/
211{
213 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
214 PSUB_Q_CURRENT_POSITION currentBuffer;
215 size_t bytesRead = 0;
216
217 PAGED_CODE ();
218
219 // if we don't think it is playing audio, don't bother checking.
220 if (!deviceExtension->DeviceAdditionalData.PlayActive)
221 {
222 return FALSE;
223 }
224
225 // Allocate the required memory
227 currentBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
230 if (currentBuffer == NULL)
231 {
232 return FALSE;
233 }
234
235 // set the options in the output buffer format
236 ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Format = IOCTL_CDROM_CURRENT_POSITION;
237 ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Track = 0;
238
239 // Send SCSI command to read Q Channel information.
240 status = ReadQChannel(deviceExtension,
241 NULL,
242 currentBuffer,
244 currentBuffer,
246 &bytesRead);
247
248 if (!NT_SUCCESS(status))
249 {
250 ExFreePool(currentBuffer);
251 return FALSE;
252 }
253
254 // update the playactive flag appropriately
255 if (currentBuffer->Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS)
256 {
257 deviceExtension->DeviceAdditionalData.PlayActive = TRUE;
258 }
259 else
260 {
261 deviceExtension->DeviceAdditionalData.PlayActive = FALSE;
262 }
263
264 ExFreePool(currentBuffer);
265
266 return deviceExtension->DeviceAdditionalData.PlayActive;
267}
268
271 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
272 _In_ WDFREQUEST Request,
274 _Out_ size_t * DataLength)
275/*++
276
277Routine Description:
278
279 Handler for IOCTL_CDROM_GET_INQUIRY_DATA
280
281Arguments:
282
283 DeviceExtension - device context
284 Request - request to be handled
285 RequestParameters - request parameter
286 DataLength - transferred data length
287
288Return Value:
289
290 NTSTATUS
291
292--*/
293{
295 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
296
297 *DataLength = 0;
298
299 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength == 0)
300 {
302 }
303 else
304 {
305 PVOID outputBuffer = NULL;
306
308 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength);
309
310 status = WdfRequestRetrieveOutputBuffer(Request,
312 &outputBuffer,
313 NULL);
314
315 if (NT_SUCCESS(status) &&
316 (outputBuffer != NULL))
317 {
318 // Always copy as much data as possible
319 RtlCopyMemory(outputBuffer,
320 cdData->CachedInquiryData,
321 *DataLength);
322 }
323
324 // and finally decide between two possible status values
326 {
328 }
329 }
330
331 return status;
332}
333
334
337 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
338 _In_ WDFREQUEST Request,
339 _Out_ size_t * DataLength
340 )
341/*++
342
343Routine Description:
344
345 Handler for IOCTL_STORAGE_GET_MEDIA_TYPES_EX
346
347Arguments:
348
349 DeviceExtension - device context
350 Request - request to be handled
351 DataLength - transferred data length
352
353Return Value:
354
355 NTSTATUS
356
357--*/
358{
360 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
361
362 PGET_MEDIA_TYPES mediaTypes = NULL;
363 PDEVICE_MEDIA_INFO mediaInfo = NULL; //&mediaTypes->MediaInfo[0];
364 ULONG sizeNeeded = 0;
365 PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
366
367 *DataLength = 0;
368
369 // Must run below dispatch level.
371 {
374 }
375
376 sizeNeeded = sizeof(GET_MEDIA_TYPES);
377
378 // IsMmc is static...
379 if (cdData->Mmc.IsMmc)
380 {
381 sizeNeeded += sizeof(DEVICE_MEDIA_INFO) * 1; // return two media types
382 }
383
384 status = WdfRequestRetrieveOutputBuffer(Request,
385 sizeNeeded,
386 (PVOID*)&mediaTypes,
387 NULL);
388
389 if (NT_SUCCESS(status) &&
390 (mediaTypes != NULL))
391 {
392 mediaInfo = &mediaTypes->MediaInfo[0];
393
394 RtlZeroMemory(mediaTypes, sizeNeeded);
395
396 // ISSUE-2000/5/11-henrygab - need to update GET_MEDIA_TYPES_EX
397
398 mediaTypes->DeviceType = cdData->DriveDeviceType;
399
400 mediaTypes->MediaInfoCount = 1;
401 mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = CD_ROM;
402 mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1;
403 mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_READ_ONLY;
404 mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = DeviceExtension->DiskGeometry.Cylinders.QuadPart;
405 mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = DeviceExtension->DiskGeometry.TracksPerCylinder;
406 mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = DeviceExtension->DiskGeometry.SectorsPerTrack;
407 mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = DeviceExtension->DiskGeometry.BytesPerSector;
408
409 if (cdData->Mmc.IsMmc)
410 {
411 // also report a removable disk
412 mediaTypes->MediaInfoCount += 1;
413
414 mediaInfo++;
415 mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = RemovableMedia;
416 mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1;
417 mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_READ_WRITE;
418 mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = DeviceExtension->DiskGeometry.Cylinders.QuadPart;
419 mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = DeviceExtension->DiskGeometry.TracksPerCylinder;
420 mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = DeviceExtension->DiskGeometry.SectorsPerTrack;
421 mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = DeviceExtension->DiskGeometry.BytesPerSector;
422 mediaInfo--;
423
424 }
425
426 // Status will either be success, if media is present, or no media.
427 // It would be optimal to base from density code and medium type, but not all devices
428 // have values for these fields.
429
430 // Send a TUR to determine if media is present, only if the device is not in ZPODD mode.
431 if ((!EXCLUSIVE_MODE(cdData) ||
432 EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request))) &&
433 ((zpoddInfo == NULL) ||
434 (zpoddInfo->InZeroPowerState == FALSE)))
435 {
437 PCDB cdb = (PCDB)srb.Cdb;
438
439 RtlZeroMemory(&srb,sizeof(SCSI_REQUEST_BLOCK));
440
441 srb.CdbLength = 6;
442 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
443
445
446 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
447 &srb,
448 NULL,
449 0,
450 FALSE,
451 Request);
452
453 if (NT_SUCCESS(status))
454 {
455 // set the disk's media as current if we can write to it.
456 if (cdData->Mmc.IsMmc && cdData->Mmc.WriteAllowed)
457 {
458 mediaInfo++;
459 SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics,
461 mediaInfo--;
462 }
463 else
464 {
465 SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics,
467 }
468 }
469 else
470 {
471 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
472 "RequestHandleGetMediaTypeEx: GET_MEDIA_TYPES status of TUR - %lx\n", status));
473 }
474 }
475
476 // per legacy cdrom behavior, always return success
478 }
479
480 *DataLength = sizeNeeded;
481
482 return status;
483}
484
487RequestHandleGetDvdRegion(
488 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
489 _In_ WDFREQUEST Request,
490 _Out_ size_t * DataLength
491 )
492/*++
493
494Routine Description:
495
496 Handler for IOCTL_DVD_GET_REGION
497
498Arguments:
499
500 DeviceExtension - device context
501 Request - request to be handled
502 DataLength - transferred data length
503
504Return Value:
505
506 NTSTATUS
507
508--*/
509{
511
512 PVOID outputBuffer = NULL;
513 size_t bytesReturned = 0;
514
515 PDVD_COPY_PROTECT_KEY copyProtectKey = NULL;
516 ULONG keyLength = 0;
517 PDVD_DESCRIPTOR_HEADER dvdHeader;
518 PDVD_COPYRIGHT_DESCRIPTOR copyRightDescriptor;
519 PDVD_REGION dvdRegion = NULL;
520 PDVD_READ_STRUCTURE readStructure = NULL;
521 PDVD_RPC_KEY rpcKey;
522
523 PAGED_CODE ();
524
525 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
526 "RequestHandleGetDvdRegion: [%p] IOCTL_DVD_GET_REGION\n", Request));
527
528 *DataLength = 0;
529
530 // reject the request if it's not a DVD device.
531 if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD)
532 {
534 }
535
536 if (NT_SUCCESS(status))
537 {
538 status = WdfRequestRetrieveOutputBuffer(Request,
539 sizeof(DVD_REGION),
540 &outputBuffer,
541 NULL);
542 }
543
544 if (NT_SUCCESS(status))
545 {
546 // figure out how much data buffer we need
547 keyLength = max((sizeof(DVD_DESCRIPTOR_HEADER) + sizeof(DVD_COPYRIGHT_DESCRIPTOR)),
548 sizeof(DVD_READ_STRUCTURE));
549 keyLength = max(keyLength,
551
552 // round the size to nearest ULONGLONG -- why?
553 // could this be to deal with device alignment issues?
554 keyLength += sizeof(ULONGLONG) - (keyLength & (sizeof(ULONGLONG) - 1));
555
556 readStructure = ExAllocatePoolWithTag(NonPagedPoolNx,
557 keyLength,
559 if (readStructure == NULL)
560 {
562 }
563 }
564
565 if (NT_SUCCESS(status))
566 {
567 RtlZeroMemory (readStructure, keyLength);
568 readStructure->Format = DvdCopyrightDescriptor;
569
570 // use READ_STRUCTURE to read copyright descriptor
571 status = ReadDvdStructure(DeviceExtension,
572 Request,
573 readStructure,
574 keyLength,
575 readStructure,
577 &bytesReturned);
578 }
579
580 if (NT_SUCCESS(status))
581 {
582 // we got the copyright descriptor, so now get the region if possible
583 dvdHeader = (PDVD_DESCRIPTOR_HEADER) readStructure;
584 copyRightDescriptor = (PDVD_COPYRIGHT_DESCRIPTOR) dvdHeader->Data;
585
586 // the original irp's systembuffer has a copy of the info that
587 // should be passed down in the request
588 dvdRegion = outputBuffer;
589
590 dvdRegion->CopySystem = copyRightDescriptor->CopyrightProtectionType;
591 dvdRegion->RegionData = copyRightDescriptor->RegionManagementInformation;
592
593 // now reuse the buffer to request the copy protection info
594 copyProtectKey = (PDVD_COPY_PROTECT_KEY) readStructure;
595 RtlZeroMemory (copyProtectKey, DVD_RPC_KEY_LENGTH);
596 copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH;
597 copyProtectKey->KeyType = DvdGetRpcKey;
598
599 // send a request for READ_KEY
600 status = DvdStartSessionReadKey(DeviceExtension,
602 Request,
603 copyProtectKey,
605 copyProtectKey,
607 &bytesReturned);
608 }
609
610 if (NT_SUCCESS(status))
611 {
612 // the request succeeded. if a supported scheme is returned,
613 // then return the information to the caller
614 rpcKey = (PDVD_RPC_KEY) copyProtectKey->KeyData;
615
616 if (rpcKey->RpcScheme == 1)
617 {
618 if (rpcKey->TypeCode)
619 {
620 dvdRegion->SystemRegion = ~rpcKey->RegionMask;
621 dvdRegion->ResetCount = rpcKey->UserResetsAvailable;
622 }
623 else
624 {
625 // the drive has not been set for any region
626 dvdRegion->SystemRegion = 0;
627 dvdRegion->ResetCount = rpcKey->UserResetsAvailable;
628 }
629
630 *DataLength = sizeof(DVD_REGION);
631 }
632 else
633 {
634 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
635 "RequestHandleGetDvdRegion => rpcKey->RpcScheme != 1\n"));
637 }
638 }
639
640 // Clean up
641 if (readStructure != NULL)
642 {
643 ExFreePool(readStructure);
644 }
645
646 return status;
647}
648
651 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
652 _In_ WDFREQUEST Request,
654 _Out_ size_t * DataLength
655 )
656/*++
657
658Routine Description:
659
660 Validate request of IOCTL_CDROM_RAW_READ
661
662Arguments:
663
664 DeviceExtension - device context
665 Request - request to be handled
666 RequestParameters - request parameter
667 DataLength - transferred data length
668
669Return Value:
670
671 NTSTATUS
672
673--*/
674{
676 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
677
678 PVOID inputBuffer = NULL;
679 PIRP irp = NULL;
680 PIO_STACK_LOCATION currentStack = NULL;
681
682 LARGE_INTEGER startingOffset = {0};
683 ULONGLONG transferBytes = 0;
684 ULONGLONG endOffset;
685 ULONGLONG mdlBytes;
686 RAW_READ_INFO rawReadInfo = {0};
687
688 *DataLength = 0;
689
690 irp = WdfRequestWdmGetIrp(Request);
691 currentStack = IoGetCurrentIrpStackLocation(irp);
692
693 status = WdfRequestRetrieveInputBuffer(Request,
695 &inputBuffer,
696 NULL);
697
698 // Check that ending sector is on disc and buffers are there and of
699 // correct size.
700 if (NT_SUCCESS(status) &&
701 (RequestParameters.Parameters.DeviceIoControl.Type3InputBuffer == NULL))
702 {
703 // This is a call from user space. This is the only time that we need to validate parameters.
704 // Validate the input and get the input buffer into Type3InputBuffer
705 // so the rest of the code will be uniform.
706 if (inputBuffer != NULL)
707 {
708 currentStack->Parameters.DeviceIoControl.Type3InputBuffer = inputBuffer;
709 RequestParameters.Parameters.DeviceIoControl.Type3InputBuffer = inputBuffer;
710
711 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(RAW_READ_INFO))
712 {
713 *DataLength = sizeof(RAW_READ_INFO);
715 }
716 }
717 else
718 {
720 }
721 }
722
723 if (NT_SUCCESS(status))
724 {
725 // Since this ioctl is METHOD_OUT_DIRECT, we need to copy away the input buffer before interpreting it.
726 // This prevents a malicious app from messing with the input buffer while we are interpreting it.
727 rawReadInfo = *(PRAW_READ_INFO)RequestParameters.Parameters.DeviceIoControl.Type3InputBuffer;
728
729 startingOffset.QuadPart = rawReadInfo.DiskOffset.QuadPart;
730
731 if ((rawReadInfo.TrackMode == CDDA) ||
732 (rawReadInfo.TrackMode == YellowMode2) ||
733 (rawReadInfo.TrackMode == XAForm2) )
734 {
735 transferBytes = (ULONGLONG)rawReadInfo.SectorCount * RAW_SECTOR_SIZE;
736 }
737 else if (rawReadInfo.TrackMode == RawWithSubCode)
738 {
739 transferBytes = (ULONGLONG)rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_SUBCODE_SIZE;
740 }
741 else if (rawReadInfo.TrackMode == RawWithC2)
742 {
743 transferBytes = (ULONGLONG)rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_C2_SIZE;
744 }
745 else if (rawReadInfo.TrackMode == RawWithC2AndSubCode)
746 {
747 transferBytes = (ULONGLONG)rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_C2_AND_SUBCODE_SIZE;
748 }
749 else
750 {
751 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
752 "RequestValidateRawRead: Invalid TrackMode type %x for XA read\n",
753 rawReadInfo.TrackMode
754 ));
755 }
756
757 endOffset = (ULONGLONG)rawReadInfo.SectorCount * COOKED_SECTOR_SIZE;
758 endOffset += startingOffset.QuadPart;
759
760 // check for overflows....
761 if (rawReadInfo.SectorCount == 0)
762 {
763 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
764 "RequestValidateRawRead: Invalid I/O parameters for XA "
765 "Read (zero sectors requested)\n"));
767 }
768 else if (transferBytes < (ULONGLONG)(rawReadInfo.SectorCount))
769 {
770 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
771 "RequestValidateRawRead: Invalid I/O parameters for XA "
772 "Read (TransferBytes Overflow)\n"));
774 }
775 else if (endOffset < (ULONGLONG)startingOffset.QuadPart)
776 {
777 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
778 "RequestValidateRawRead: Invalid I/O parameters for XA "
779 "Read (EndingOffset Overflow)\n"));
781 }
782 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < transferBytes)
783 {
784 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
785 "RequestValidateRawRead: Invalid I/O parameters for XA "
786 "Read (Bad buffer size)\n"));
788 }
789 else if (endOffset > (ULONGLONG)DeviceExtension->PartitionLength.QuadPart)
790 {
791 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
792 "RequestValidateRawRead: Invalid I/O parameters for XA "
793 "Read (Request Out of Bounds)\n"));
795 }
796 }
797
798 if (NT_SUCCESS(status))
799 {
800 // cannot validate the MdlAddress, since it is not included in any
801 // other location per the DDK and file system calls.
802
803 // validate the mdl describes at least the number of bytes
804 // requested from us.
805 mdlBytes = (ULONGLONG)MmGetMdlByteCount(irp->MdlAddress);
806 if (mdlBytes < transferBytes)
807 {
808 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
809 "RequestValidateRawRead: Invalid MDL %s, Irp %p\n",
810 "size (5)", irp));
812 }
813 }
814
815 if (NT_SUCCESS(status))
816 {
817 // check the buffer for alignment
818 // This is important for x86 as some busses (ie ATAPI)
819 // require word-aligned buffers.
820 if ( ((ULONG_PTR)MmGetMdlVirtualAddress(irp->MdlAddress)) &
821 DeviceExtension->AdapterDescriptor->AlignmentMask )
822 {
823 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
824 "RequestValidateRawRead: Invalid I/O parameters for "
825 "XA Read (Buffer %p not aligned with mask %x\n",
827 DeviceExtension->AdapterDescriptor->AlignmentMask));
829 }
830 }
831
832 if (NT_SUCCESS(status))
833 {
834 // Validate the request is not too large for the adapter
835 BOOLEAN bufferIsPageAligned = FALSE;
836 ULONG maxLength = 0;
837
838 // if buffer is not page-aligned, then subtract one as the
839 // transfer could cross a page boundary.
840 if ((((ULONG_PTR)MmGetMdlVirtualAddress(irp->MdlAddress)) & (PAGE_SIZE-1)) == 0)
841 {
842 bufferIsPageAligned = TRUE;
843 }
844
845 if (bufferIsPageAligned)
846 {
848 }
849 else
850 {
852 }
853
854 if (transferBytes > maxLength)
855 {
856 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
857 "RequestValidateRawRead: The XA Read (type %x) would require %I64x bytes, "
858 "but the adapter can only handle %x bytes (for a%saligned buffer)\n",
859 rawReadInfo.TrackMode,
860 transferBytes,
861 maxLength,
862 (bufferIsPageAligned ? " " : "n un")
863 ));
865 }
866 }
867
868 if (NT_SUCCESS(status))
869 {
870 //
871 // HACKHACK - REF #0001
872 // The retry count will be in this irp's IRP_MN function,
873 // as the new irp was freed, and we therefore cannot use
874 // this irp's next stack location for this function.
875 // This may be a good location to store this info for
876 // when we remove RAW_READ (mode switching), as we will
877 // no longer have the nextIrpStackLocation to play with
878 // when that occurs
879 //
880 currentStack->MinorFunction = MAXIMUM_RETRIES; // HACKHACK - REF #0001
881 }
882
883 return status;
884}
885
888 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
889 _In_ WDFREQUEST Request,
891 _Out_ size_t * DataLength
892 )
893/*++
894
895Routine Description:
896
897 Validate request of IOCTL_CDROM_READ_TOC_EX
898
899Arguments:
900
901 DeviceExtension - device context
902 Request - request to be handled
903 RequestParameters - request parameter
904 DataLength - transferred data length
905
906Return Value:
907
908 NTSTATUS
909
910--*/
911{
913
914 PCDROM_READ_TOC_EX inputBuffer = NULL;
915
916 *DataLength = 0;
917
918 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
919 sizeof(CDROM_READ_TOC_EX))
920 {
922 }
923 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
925 {
928 }
929 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >
930 ((USHORT)-1))
931 {
933 }
934 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength &
935 DeviceExtension->AdapterDescriptor->AlignmentMask)
936 {
938 }
939
940 if (NT_SUCCESS(status))
941 {
942 status = WdfRequestRetrieveInputBuffer(Request,
944 &inputBuffer,
945 NULL);
946 }
947
948 if (NT_SUCCESS(status))
949 {
950 if ((inputBuffer->Reserved1 != 0) ||
951 (inputBuffer->Reserved2 != 0) ||
952 (inputBuffer->Reserved3 != 0))
953 {
955 }
956 // NOTE: when adding new formats, ensure that first two bytes
957 // specify the amount of additional data available.
958 else if ((inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_TOC ) ||
959 (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_FULL_TOC) ||
960 (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_CDTEXT ))
961 {
962 // SessionTrack field is used
963 }
964 else if ((inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_SESSION) ||
965 (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_PMA) ||
966 (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_ATIP))
967 {
968 // SessionTrack field is reserved
969 if (inputBuffer->SessionTrack != 0)
970 {
972 }
973 }
974 else
975 {
977 }
978 }
979
980 return status;
981}
982
985 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
987 _Out_ size_t * DataLength
988 )
989/*++
990
991Routine Description:
992
993 Validate request of IOCTL_CDROM_READ_TOC
994
995Arguments:
996
997 DeviceExtension - device context
998 RequestParameters - request parameter
999 DataLength - transferred data length
1000
1001Return Value:
1002
1003 NTSTATUS
1004
1005--*/
1006{
1008
1009 *DataLength = 0;
1010
1011 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1012 sizeof(CDROM_TOC))
1013 {
1014 // they didn't request the entire TOC -- use _EX version
1015 // for partial transfers and such.
1017 *DataLength = sizeof(CDROM_TOC);
1018 }
1019 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength &
1020 DeviceExtension->AdapterDescriptor->AlignmentMask)
1021 {
1023 }
1024
1025 return status;
1026}
1027
1030 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1032 _Out_ size_t * DataLength
1033 )
1034/*++
1035
1036Routine Description:
1037
1038 Validate request of IOCTL_CDROM_GET_LAST_SESSION
1039
1040Arguments:
1041
1042 DeviceExtension - device context
1043 RequestParameters - request parameter
1044 DataLength - transferred data length
1045
1046Return Value:
1047
1048 NTSTATUS
1049
1050--*/
1051{
1053
1054 *DataLength = 0;
1055
1056 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1057 sizeof(CDROM_TOC_SESSION_DATA))
1058 {
1061 }
1062 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength &
1063 DeviceExtension->AdapterDescriptor->AlignmentMask)
1064 {
1066 }
1067
1068 return status;
1069}
1070
1073 _In_ WDFREQUEST Request,
1075 _Out_ size_t * DataLength
1076 )
1077/*++
1078
1079Routine Description:
1080
1081 Validate request of IOCTL_CDROM_READ_Q_CHANNEL
1082
1083Arguments:
1084
1085 Request - request to be handled
1086 RequestParameters - request parameter
1087 DataLength - transferred data length
1088
1089Return Value:
1090
1091 NTSTATUS
1092
1093--*/
1094{
1096 PCDROM_SUB_Q_DATA_FORMAT inputBuffer = NULL;
1097 ULONG transferByteCount = 0;
1098
1099 *DataLength = 0;
1100
1101 if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
1103 {
1105 }
1106
1107 if (NT_SUCCESS(status))
1108 {
1109 status = WdfRequestRetrieveInputBuffer(Request,
1111 &inputBuffer,
1112 NULL);
1113 }
1114
1115 if (NT_SUCCESS(status))
1116 {
1117 // check for all valid types of request
1118 if (inputBuffer->Format == IOCTL_CDROM_CURRENT_POSITION)
1119 {
1120 transferByteCount = sizeof(SUB_Q_CURRENT_POSITION);
1121 }
1122 else if (inputBuffer->Format == IOCTL_CDROM_MEDIA_CATALOG)
1123 {
1124 transferByteCount = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER);
1125 }
1126 else if (inputBuffer->Format == IOCTL_CDROM_TRACK_ISRC)
1127 {
1128 transferByteCount = sizeof(SUB_Q_TRACK_ISRC);
1129 }
1130 else
1131 {
1132 // Format not valid
1134 }
1135 }
1136
1137 if (NT_SUCCESS(status))
1138 {
1139 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1140 transferByteCount)
1141 {
1143 *DataLength = transferByteCount;
1144 }
1145 }
1146
1147 return status;
1148}
1149
1152 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1154 _Out_ size_t * DataLength
1155 )
1156/*++
1157
1158Routine Description:
1159
1160 Validate request of IOCTL_DVD_READ_STRUCTURE
1161
1162Arguments:
1163
1164 DeviceExtension - device context
1165 RequestParameters - request parameter
1166 DataLength - transferred data length
1167
1168Return Value:
1169
1170 NTSTATUS
1171
1172--*/
1173{
1175
1176 *DataLength = 0;
1177
1178 if (NT_SUCCESS(status))
1179 {
1180 if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
1181 sizeof(DVD_READ_STRUCTURE))
1182 {
1183 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
1184 "RequestValidateDvdReadStructure - input buffer "
1185 "length too small (was %d should be %d)\n",
1186 (int)RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
1187 sizeof(DVD_READ_STRUCTURE)));
1189 }
1190 else if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1192 {
1193
1194 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
1195 "RequestValidateDvdReadStructure - output buffer "
1196 "cannot hold header information\n"));
1199 }
1200 else if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >
1201 MAXUSHORT)
1202 {
1203 // key length must fit in two bytes
1204 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
1205 "RequestValidateDvdReadStructure - output buffer "
1206 "too large\n"));
1208 }
1209 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength &
1210 DeviceExtension->AdapterDescriptor->AlignmentMask)
1211 {
1213 }
1214 else if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD)
1215 {
1216 // reject the request if it's not a DVD device.
1218 }
1219 }
1220
1221 return status;
1222}
1223
1226 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1228 _Out_ size_t * DataLength
1229 )
1230/*++
1231
1232Routine Description:
1233
1234 Validate request of IOCTL_DVD_START_SESSION
1235
1236Arguments:
1237
1238 DeviceExtension - device context
1239 RequestParameters - request parameter
1240 DataLength - transferred data length
1241
1242Return Value:
1243
1244 NTSTATUS
1245
1246--*/
1247{
1249
1250 *DataLength = 0;
1251
1252 if (NT_SUCCESS(status))
1253 {
1254 if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1255 sizeof(DVD_SESSION_ID))
1256 {
1257 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
1258 "RequestValidateDvdStartSession: DVD_START_SESSION - output "
1259 "buffer too small\n"));
1261 *DataLength = sizeof(DVD_SESSION_ID);
1262 }
1263 else if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD)
1264 {
1265 // reject the request if it's not a DVD device.
1267 }
1268 }
1269
1270 return status;
1271}
1272
1275 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1276 _In_ WDFREQUEST Request,
1278 _Out_ size_t * DataLength
1279 )
1280/*++
1281
1282Routine Description:
1283
1284 Validate request of IOCTL_DVD_SEND_KEY, IOCTL_DVD_SEND_KEY2
1285
1286Arguments:
1287
1288 DeviceExtension - device context
1289 Request - request to be handled
1290 RequestParameters - request parameter
1291 DataLength - transferred data length
1292
1293Return Value:
1294
1295 NTSTATUS
1296
1297--*/
1298{
1301
1302 *DataLength = 0;
1303
1304 status = WdfRequestRetrieveInputBuffer(Request,
1306 &key,
1307 NULL);
1308
1309 if (NT_SUCCESS(status))
1310 {
1311 if((RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(DVD_COPY_PROTECT_KEY)) ||
1312 (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != key->KeyLength))
1313 {
1314
1315 //
1316 // Key is too small to have a header or the key length doesn't
1317 // match the input buffer length. Key must be invalid
1318 //
1319
1320 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
1321 "RequestValidateDvdSendKey: [%p] IOCTL_DVD_SEND_KEY - "
1322 "key is too small or does not match KeyLength\n",
1323 Request));
1325 }
1326 }
1327
1328 if (NT_SUCCESS(status))
1329 {
1330 // allow only certain key type (non-destructive) to go through
1331 // IOCTL_DVD_SEND_KEY (which only requires READ access to the device)
1333 {
1334 if ((key->KeyType != DvdChallengeKey) &&
1335 (key->KeyType != DvdBusKey2) &&
1336 (key->KeyType != DvdInvalidateAGID))
1337 {
1339 }
1340 }
1341 else if ((key->KeyType != DvdChallengeKey) &&
1342 (key->KeyType != DvdBusKey1) &&
1343 (key->KeyType != DvdBusKey2) &&
1344 (key->KeyType != DvdTitleKey) &&
1345 (key->KeyType != DvdAsf) &&
1346 (key->KeyType != DvdSetRpcKey) &&
1347 (key->KeyType != DvdGetRpcKey) &&
1348 (key->KeyType != DvdDiskKey) &&
1349 (key->KeyType != DvdInvalidateAGID))
1350 {
1352 }
1353 else if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD)
1354 {
1355 // reject the request if it's not a DVD device.
1357 }
1358 }
1359
1360 return status;
1361}
1362
1365 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1366 _In_ WDFREQUEST Request,
1368 _Out_ size_t * DataLength
1369 )
1370/*++
1371
1372Routine Description:
1373
1374 Validate request of IOCTL_CDROM_GET_CONFIGURATION
1375
1376Arguments:
1377
1378 DeviceExtension - device context
1379 Request - request to be handled
1380 RequestParameters - request parameter
1381 DataLength - transferred data length
1382
1383Return Value:
1384
1385 NTSTATUS
1386
1387--*/
1388{
1390
1391 *DataLength = 0;
1392
1393 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1395 {
1398 }
1399 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > 0xffff)
1400 {
1401 // output buffer is too large
1403 }
1404 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength &
1405 DeviceExtension->AdapterDescriptor->AlignmentMask)
1406 {
1407 // buffer is not proper size multiple
1409 }
1410
1411 if (NT_SUCCESS(status))
1412 {
1413
1414#if BUILD_WOW64_ENABLED && defined(_WIN64)
1415
1416 if (WdfRequestIsFrom32BitProcess(Request))
1417 {
1418 PGET_CONFIGURATION_IOCTL_INPUT32 inputBuffer = NULL;
1419
1420 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
1421 sizeof(GET_CONFIGURATION_IOCTL_INPUT32))
1422 {
1424 }
1425
1426 //
1427 // also verify the arguments are reasonable.
1428 //
1429 if (NT_SUCCESS(status))
1430 {
1431 status = WdfRequestRetrieveInputBuffer(Request,
1433 &inputBuffer,
1434 NULL);
1435 }
1436
1437 if (NT_SUCCESS(status))
1438 {
1439 if (inputBuffer->Feature > 0xffff)
1440 {
1442 }
1443 else if ((inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) &&
1444 (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT) &&
1445 (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL))
1446 {
1448 }
1449 else if (inputBuffer->Reserved[0] || inputBuffer->Reserved[1])
1450 {
1452 }
1453 }
1454 }
1455 else
1456
1457#endif
1458
1459 {
1461
1462 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
1464 {
1466 }
1467
1468 // also verify the arguments are reasonable.
1469 if (NT_SUCCESS(status))
1470 {
1471 status = WdfRequestRetrieveInputBuffer(Request,
1473 &inputBuffer,
1474 NULL);
1475 }
1476
1477 if (NT_SUCCESS(status))
1478 {
1479 if (inputBuffer->Feature > 0xffff)
1480 {
1482 }
1483 else if ((inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) &&
1486 {
1488 }
1489 else if (inputBuffer->Reserved[0] || inputBuffer->Reserved[1])
1490 {
1492 }
1493 }
1494 }
1495 }
1496
1497 return status;
1498}
1499
1502 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1503 _In_ WDFREQUEST Request,
1505 _Out_ size_t * DataLength
1506 )
1507/*++
1508
1509Routine Description:
1510
1511 Validate request of IOCTL_CDROM_SET_SPEED
1512
1513Arguments:
1514
1515 DeviceExtension - device context
1516 Request - request to be handled
1517 RequestParameters - request parameter
1518 DataLength - transferred data length
1519
1520Return Value:
1521
1522 NTSTATUS
1523
1524--*/
1525{
1527 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
1528 PCDROM_SET_SPEED inputBuffer = NULL;
1529 ULONG requiredLength = 0;
1530
1531 *DataLength = 0;
1532
1533 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(CDROM_SET_SPEED))
1534 {
1536 }
1537
1538 if (NT_SUCCESS(status))
1539 {
1540 // Get the request type using CDROM_SET_SPEED structure
1541 status = WdfRequestRetrieveInputBuffer(Request,
1542 sizeof(CDROM_SET_SPEED),
1543 &inputBuffer,
1544 NULL);
1545
1546 }
1547
1548 if (NT_SUCCESS(status))
1549 {
1550 if (inputBuffer->RequestType > CdromSetStreaming)
1551 {
1552 // Unknown request type.
1554 }
1555 else if (inputBuffer->RequestType == CdromSetSpeed)
1556 {
1557 requiredLength = sizeof(CDROM_SET_SPEED);
1558 }
1559 else
1560 {
1561 // Don't send SET STREAMING command if this is not a MMC compliant device
1562 if (cdData->Mmc.IsMmc == FALSE)
1563 {
1565 }
1566
1567 requiredLength = sizeof(CDROM_SET_STREAMING);
1568 }
1569 }
1570
1571 if (NT_SUCCESS(status))
1572 {
1573 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < requiredLength)
1574 {
1575 // Input buffer too small
1577 }
1578 }
1579
1580 return status;
1581}
1582
1585 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1586 _In_ WDFREQUEST Request,
1588 _Out_ size_t * DataLength
1589 )
1590/*++
1591
1592Routine Description:
1593
1594 Validate request of IOCTL_AACS_READ_MEDIA_KEY_BLOCK
1595
1596Arguments:
1597
1598 DeviceExtension - device context
1599 Request - request to be handled
1600 RequestParameters - request parameter
1601 DataLength - transferred data length
1602
1603Return Value:
1604
1605 NTSTATUS
1606
1607--*/
1608{
1610 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
1611 PAACS_LAYER_NUMBER layerNumber = NULL;
1612
1613 *DataLength = 0;
1614
1615 if (!cdData->Mmc.IsAACS)
1616 {
1618 }
1619 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(AACS_LAYER_NUMBER))
1620 {
1622 }
1623 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < 8)
1624 {
1625 // This is a variable-length structure, but we're pretty sure
1626 // it can never be less than eight bytes...
1627 *DataLength = 8;
1629 }
1630
1631 if (NT_SUCCESS(status))
1632 {
1633 status = WdfRequestRetrieveInputBuffer(Request,
1635 &layerNumber,
1636 NULL);
1637 }
1638
1639 if (NT_SUCCESS(status))
1640 {
1641 if (*layerNumber > 255)
1642 {
1644 }
1645 }
1646
1647 return status;
1648}
1649
1652 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1654 _Out_ size_t * DataLength
1655 )
1656/*++
1657
1658Routine Description:
1659
1660 Validate request of IOCTL_AACS_START_SESSION
1661
1662Arguments:
1663
1664 DeviceExtension - device context
1665 RequestParameters - request parameter
1666 DataLength - transferred data length
1667
1668Return Value:
1669
1670 NTSTATUS
1671
1672--*/
1673{
1675 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
1676
1677 *DataLength = 0;
1678
1679 if (!cdData->Mmc.IsAACS)
1680 {
1682 }
1683 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(DVD_SESSION_ID))
1684 {
1685 *DataLength = sizeof(DVD_SESSION_ID);
1687 }
1688 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(DVD_SESSION_ID))
1689 {
1691 }
1692
1693 return status;
1694}
1695
1698 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1699 _In_ WDFREQUEST Request,
1701 _Out_ size_t * DataLength
1702 )
1703/*++
1704
1705Routine Description:
1706
1707 Validate request of IOCTL_AACS_SEND_CERTIFICATE
1708
1709Arguments:
1710
1711 DeviceExtension - device context
1712 Request - request to be handled
1713 RequestParameters - request parameter
1714 DataLength - transferred data length
1715
1716Return Value:
1717
1718 NTSTATUS
1719
1720--*/
1721{
1723 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
1724 PAACS_SEND_CERTIFICATE inputBuffer = NULL;
1725
1726 *DataLength = 0;
1727
1728 if (!cdData->Mmc.IsAACS)
1729 {
1731 }
1732 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(AACS_SEND_CERTIFICATE))
1733 {
1735 }
1736
1737 if (NT_SUCCESS(status))
1738 {
1739 status = WdfRequestRetrieveInputBuffer(Request,
1741 &inputBuffer,
1742 NULL);
1743 }
1744
1745 if (NT_SUCCESS(status))
1746 {
1747 if (inputBuffer->SessionId > MAX_COPY_PROTECT_AGID)
1748 {
1750 }
1751 }
1752
1753 return status;
1754}
1755
1758 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1759 _In_ WDFREQUEST Request,
1761 _Out_ size_t * DataLength
1762 )
1763/*++
1764
1765Routine Description:
1766
1767 Validate request of IOCTL_AACS_GET_CERTIFICATE
1768
1769Arguments:
1770
1771 DeviceExtension - device context
1772 Request - request to be handled
1773 RequestParameters - request parameter
1774 DataLength - transferred data length
1775
1776Return Value:
1777
1778 NTSTATUS
1779
1780--*/
1781{
1783 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
1784 PDVD_SESSION_ID sessionId = NULL;
1785
1786 *DataLength = 0;
1787
1788 if (!cdData->Mmc.IsAACS)
1789 {
1791 }
1792 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID))
1793 {
1795 }
1796 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_CERTIFICATE))
1797 {
1798 *DataLength = sizeof(AACS_CERTIFICATE);
1800 }
1801 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_CERTIFICATE))
1802 {
1804 }
1805
1806 if (NT_SUCCESS(status))
1807 {
1808 status = WdfRequestRetrieveInputBuffer(Request,
1810 &sessionId,
1811 NULL);
1812 }
1813
1814 if (NT_SUCCESS(status))
1815 {
1816 if (*sessionId > MAX_COPY_PROTECT_AGID)
1817 {
1819 }
1820 }
1821
1822 return status;
1823}
1824
1827 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1828 _In_ WDFREQUEST Request,
1830 _Out_ size_t * DataLength
1831 )
1832/*++
1833
1834Routine Description:
1835
1836 Validate request of IOCTL_AACS_GET_CHALLENGE_KEY
1837
1838Arguments:
1839
1840 DeviceExtension - device context
1841 Request - request to be handled
1842 RequestParameters - request parameter
1843 DataLength - transferred data length
1844
1845Return Value:
1846
1847 NTSTATUS
1848
1849--*/
1850{
1852 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
1853 PDVD_SESSION_ID sessionId = NULL;
1854
1855 *DataLength = 0;
1856
1857 if (!cdData->Mmc.IsAACS)
1858 {
1860 }
1861 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID))
1862 {
1864 }
1865 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_CHALLENGE_KEY))
1866 {
1867 *DataLength = sizeof(AACS_CHALLENGE_KEY);
1869 }
1870 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_CHALLENGE_KEY))
1871 {
1873 }
1874
1875 if (NT_SUCCESS(status))
1876 {
1877 status = WdfRequestRetrieveInputBuffer(Request,
1879 &sessionId,
1880 NULL);
1881 }
1882
1883 if (NT_SUCCESS(status))
1884 {
1885 if (*sessionId > MAX_COPY_PROTECT_AGID)
1886 {
1888 }
1889 }
1890
1891 return status;
1892}
1893
1896 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1897 _In_ WDFREQUEST Request,
1899 _Out_ size_t * DataLength
1900 )
1901/*++
1902
1903Routine Description:
1904
1905 Validate request of IOCTL_AACS_SEND_CHALLENGE_KEY
1906
1907Arguments:
1908
1909 DeviceExtension - device context
1910 Request - request to be handled
1911 RequestParameters - request parameter
1912 DataLength - transferred data length
1913
1914Return Value:
1915
1916 NTSTATUS
1917
1918--*/
1919{
1921 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
1922 PAACS_SEND_CHALLENGE_KEY inputBuffer = NULL;
1923
1924 *DataLength = 0;
1925
1926 if (!cdData->Mmc.IsAACS)
1927 {
1929 }
1930 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(AACS_SEND_CHALLENGE_KEY))
1931 {
1933 }
1934
1935 if (NT_SUCCESS(status))
1936 {
1937 status = WdfRequestRetrieveInputBuffer(Request,
1939 &inputBuffer,
1940 NULL);
1941 }
1942
1943 if (NT_SUCCESS(status))
1944 {
1945 if (inputBuffer->SessionId > MAX_COPY_PROTECT_AGID)
1946 {
1948 }
1949 }
1950
1951 return status;
1952}
1953
1956 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1957 _In_ WDFREQUEST Request,
1959 _Out_ size_t * DataLength
1960 )
1961/*++
1962
1963Routine Description:
1964
1965 Validate request of IOCTL_AACS_READ_VOLUME_ID
1966
1967Arguments:
1968
1969 DeviceExtension - device context
1970 Request - request to be handled
1971 RequestParameters - request parameter
1972 DataLength - transferred data length
1973
1974Return Value:
1975
1976 NTSTATUS
1977
1978--*/
1979{
1981 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
1982 PDVD_SESSION_ID sessionId = NULL;
1983
1984 *DataLength = 0;
1985
1986 if (!cdData->Mmc.IsAACS)
1987 {
1989 }
1990 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID))
1991 {
1993 }
1994 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_VOLUME_ID))
1995 {
1996 *DataLength = sizeof(AACS_VOLUME_ID);
1998 }
1999 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_VOLUME_ID))
2000 {
2002 }
2003
2004 if (NT_SUCCESS(status))
2005 {
2006 status = WdfRequestRetrieveInputBuffer(Request,
2008 &sessionId,
2009 NULL);
2010 }
2011
2012 if (NT_SUCCESS(status))
2013 {
2014 if (*sessionId > MAX_COPY_PROTECT_AGID)
2015 {
2017 }
2018 }
2019
2020 return status;
2021}
2022
2025 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2026 _In_ WDFREQUEST Request,
2028 _Out_ size_t * DataLength
2029 )
2030/*++
2031
2032Routine Description:
2033
2034 Validate request of IOCTL_AACS_READ_SERIAL_NUMBER
2035
2036Arguments:
2037
2038 DeviceExtension - device context
2039 Request - request to be handled
2040 RequestParameters - request parameter
2041 DataLength - transferred data length
2042
2043Return Value:
2044
2045 NTSTATUS
2046
2047--*/
2048{
2050 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
2051 PDVD_SESSION_ID sessionId = NULL;
2052
2053 *DataLength = 0;
2054
2055 if (!cdData->Mmc.IsAACS)
2056 {
2058 }
2059 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID))
2060 {
2062 }
2063 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_SERIAL_NUMBER))
2064 {
2065 *DataLength = sizeof(AACS_SERIAL_NUMBER);
2067 }
2068 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_SERIAL_NUMBER))
2069 {
2071 }
2072
2073 if (NT_SUCCESS(status))
2074 {
2075 status = WdfRequestRetrieveInputBuffer(Request,
2077 &sessionId,
2078 NULL);
2079 }
2080
2081 if (NT_SUCCESS(status))
2082 {
2083 if (*sessionId > MAX_COPY_PROTECT_AGID)
2084 {
2086 }
2087 }
2088
2089 return status;
2090}
2091
2094 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2095 _In_ WDFREQUEST Request,
2097 _Out_ size_t * DataLength
2098 )
2099/*++
2100
2101Routine Description:
2102
2103 Validate request of IOCTL_AACS_READ_MEDIA_ID
2104
2105Arguments:
2106
2107 DeviceExtension - device context
2108 Request - request to be handled
2109 RequestParameters - request parameter
2110 DataLength - transferred data length
2111
2112Return Value:
2113
2114 NTSTATUS
2115
2116--*/
2117{
2119 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
2120 PDVD_SESSION_ID sessionId = NULL;
2121
2122 *DataLength = 0;
2123
2124 if (!cdData->Mmc.IsAACS)
2125 {
2127 }
2128 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID))
2129 {
2131 }
2132 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_MEDIA_ID))
2133 {
2134 *DataLength = sizeof(AACS_MEDIA_ID);
2136 }
2137 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_MEDIA_ID))
2138 {
2140 }
2141
2142 if (NT_SUCCESS(status))
2143 {
2144 status = WdfRequestRetrieveInputBuffer(Request,
2146 &sessionId,
2147 NULL);
2148 }
2149
2150 if (NT_SUCCESS(status))
2151 {
2152 if (*sessionId > MAX_COPY_PROTECT_AGID)
2153 {
2155 }
2156 }
2157
2158 return status;
2159}
2160
2163 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2164 _In_ WDFREQUEST Request,
2166 _Out_ size_t * DataLength
2167 )
2168/*++
2169
2170Routine Description:
2171
2172 Validate request of IOCTL_AACS_READ_BINDING_NONCE
2173 IOCTL_AACS_GENERATE_BINDING_NONCE
2174
2175Arguments:
2176
2177 DeviceExtension - device context
2178 Request - request to be handled
2179 RequestParameters - request parameter
2180 DataLength - transferred data length
2181
2182Return Value:
2183
2184 NTSTATUS
2185
2186--*/
2187{
2189 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
2190 PAACS_READ_BINDING_NONCE inputBuffer = NULL;
2191
2192 *DataLength = 0;
2193
2194 if (!cdData->Mmc.IsAACS)
2195 {
2197 }
2198 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(AACS_READ_BINDING_NONCE))
2199 {
2201 }
2202 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(AACS_BINDING_NONCE))
2203 {
2204 *DataLength = sizeof(AACS_BINDING_NONCE);
2206 }
2207 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > sizeof(AACS_BINDING_NONCE))
2208 {
2210 }
2211
2212 if (NT_SUCCESS(status))
2213 {
2214 status = WdfRequestRetrieveInputBuffer(Request,
2216 &inputBuffer,
2217 NULL);
2218 }
2219
2220 if (NT_SUCCESS(status))
2221 {
2222 if (inputBuffer->SessionId > MAX_COPY_PROTECT_AGID)
2223 {
2225 }
2226 else if (inputBuffer->NumberOfSectors > 255)
2227 {
2229 }
2230 else if (inputBuffer->StartLba > MAXULONG)
2231 {
2233 }
2234 }
2235
2236 return status;
2237}
2238
2241 _In_ WDFREQUEST Request,
2243 _Out_ size_t * DataLength
2244 )
2245/*++
2246
2247Routine Description:
2248
2249 Validate request of IOCTL_CDROM_EXCLUSIVE_ACCESS
2250
2251Arguments:
2252
2253 Request - request to be handled
2254 RequestParameters - request parameter
2255 DataLength - transferred data length
2256
2257Return Value:
2258
2259 NTSTATUS
2260
2261--*/
2262{
2264 PCDROM_EXCLUSIVE_ACCESS exclusiveAccess = NULL;
2265
2266 *DataLength = 0;
2267
2269 {
2270 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: IOCTL must be called at passive level.\n"));
2272 }
2273 else if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(CDROM_EXCLUSIVE_ACCESS))
2274 {
2275
2276 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: Input buffer too small\n"));
2278 }
2279
2280 if (NT_SUCCESS(status))
2281 {
2282 status = WdfRequestRetrieveInputBuffer(Request,
2284 &exclusiveAccess,
2285 NULL);
2286 }
2287
2288 if (NT_SUCCESS(status))
2289 {
2290 switch (exclusiveAccess->RequestType)
2291 {
2293 {
2294 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2296 {
2297 //
2298 // Output buffer too small.
2299 //
2300 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: Output buffer too small\n"));
2303 }
2304 break;
2305 }
2306
2308 {
2309 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2310 sizeof(CDROM_EXCLUSIVE_LOCK))
2311 {
2312 //
2313 // Input buffer too small
2314 //
2315 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: Input buffer too small\n"));
2317 }
2318 break;
2319 }
2321 {
2322 //
2323 // Nothing to check
2324 //
2325 break;
2326 }
2327
2328 default:
2329 {
2330 //
2331 // Unknown request type.
2332 //
2333 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "RequestValidateExclusiveAccess: Invalid request type\n"));
2335 }
2336 }
2337 }
2338
2339 return status;
2340}
2341
2344RequestHandleExclusiveAccessQueryLockState(
2345 _In_ WDFDEVICE Device,
2346 _In_ WDFREQUEST Request
2347 )
2348/*++
2349
2350Routine Description:
2351
2352 Handle request of IOCTL_CDROM_EXCLUSIVE_ACCESS with ExclusiveAccessQueryState
2353
2354Arguments:
2355
2356 DeviceExtension - device context
2357 Request - request to be handled
2358 RequestParameters - request parameter
2359 DataLength - transferred data length
2360
2361Return Value:
2362
2363 NTSTATUS
2364
2365--*/
2366{
2368 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2369 PCDROM_DATA cdData = &deviceExtension->DeviceAdditionalData;
2370 PCDROM_EXCLUSIVE_LOCK_STATE exclusiveLockState = NULL;
2371
2372 PAGED_CODE();
2373
2374 status = WdfRequestRetrieveOutputBuffer(Request,
2376 &exclusiveLockState,
2377 NULL);
2379
2380 RtlZeroMemory(exclusiveLockState, sizeof(CDROM_EXCLUSIVE_LOCK_STATE));
2381
2382 if (EXCLUSIVE_MODE(cdData))
2383 {
2384 // Device is locked for exclusive use
2385 exclusiveLockState->LockState = TRUE;
2386
2387 RtlCopyMemory(&exclusiveLockState->CallerName,
2388 &cdData->CallerName,
2390
2391 }
2392 else
2393 {
2394 // Device is not locked
2395 exclusiveLockState->LockState = FALSE;
2396 }
2397
2398 RequestCompletion(deviceExtension, Request, status, sizeof(CDROM_EXCLUSIVE_LOCK_STATE));
2399
2400 return status;
2401}
2402
2405RequestHandleExclusiveAccessLockDevice(
2406 _In_ WDFDEVICE Device,
2407 _In_ WDFREQUEST Request
2408 )
2409/*++
2410
2411Routine Description:
2412
2413 Handle request of IOCTL_CDROM_EXCLUSIVE_ACCESS with ExclusiveAccessLockDevice
2414
2415Arguments:
2416
2417 DeviceExtension - device context
2418 Request - request to be handled
2419 RequestParameters - request parameter
2420 DataLength - transferred data length
2421
2422Return Value:
2423
2424 NTSTATUS
2425
2426--*/
2427{
2429 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2430 PCDROM_DATA cdData = &deviceExtension->DeviceAdditionalData;
2431 PCDROM_EXCLUSIVE_LOCK exclusiveLock = NULL;
2432 PIO_ERROR_LOG_PACKET logEntry;
2433
2434 WDFFILEOBJECT fileObject = NULL;
2435 ULONG idx = 0;
2436 ULONG nameLength = 0;
2437
2438 PAGED_CODE();
2439
2440 fileObject = WdfRequestGetFileObject(Request);
2441
2442 if (fileObject == NULL)
2443 {
2445
2446 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
2447 "RequestHandleExclusiveAccessLockDevice: FileObject is NULL, cannot grant exclusive access\n"));
2448 }
2449
2450 if (NT_SUCCESS(status))
2451 {
2452 status = WdfRequestRetrieveInputBuffer(Request,
2453 sizeof(CDROM_EXCLUSIVE_LOCK),
2454 &exclusiveLock,
2455 NULL);
2456 }
2457
2458 if (NT_SUCCESS(status))
2459 {
2460 // Validate the caller name string
2461 for (idx = 0; (idx < CDROM_EXCLUSIVE_CALLER_LENGTH) && (exclusiveLock->CallerName[idx] != '\0'); idx++)
2462 {
2463 if (!ValidChar(exclusiveLock->CallerName[idx]))
2464 {
2465 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
2466 "RequestHandleExclusiveAccessLockDevice: Invalid characters in caller name\n"));
2467 // error out
2469 break;
2470 }
2471 }
2472 }
2473
2474 if (NT_SUCCESS(status))
2475 {
2476 if ((idx == 0) || (idx >= CDROM_EXCLUSIVE_CALLER_LENGTH))
2477 {
2478
2479 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
2480 "RequestHandleExclusiveAccessLockDevice: Not a valid null terminated string.\n"));
2481 //error out
2483 }
2484 else
2485 {
2486 nameLength = idx+1; // Add 1 for the NULL character
2488 }
2489 }
2490
2491 // If the file system is still mounted on this device fail the request,
2492 // unless the force lock flag is set.
2493 if (NT_SUCCESS(status))
2494 {
2495 if ((TEST_FLAG(exclusiveLock->Access.Flags, CDROM_LOCK_IGNORE_VOLUME) == FALSE) &&
2496 IsVolumeMounted(deviceExtension->DeviceObject))
2497 {
2498 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
2499 "RequestHandleExclusiveAccessLockDevice: Unable to lock device, file system mounted\n"));
2501 }
2502 }
2503
2504 // Lock the device for exclusive access if the device is not already locked
2505 if (NT_SUCCESS(status))
2506 {
2507 if (InterlockedCompareExchangePointer((PVOID)&cdData->ExclusiveOwner, (PVOID)fileObject, NULL) == NULL)
2508 {
2509 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2510 "RequestHandleExclusiveAccessLockDevice: Entering exclusive mode! Device locked by file object %p\n", fileObject));
2511
2512 // Zero out the CallerName before storing it in the extension
2514 RtlCopyMemory(&cdData->CallerName,
2515 &exclusiveLock->CallerName,
2516 nameLength);
2517
2518 // Send Exclusive Lock notification
2519 DeviceSendNotification(deviceExtension,
2520 &GUID_IO_CDROM_EXCLUSIVE_LOCK,
2521 0,
2522 NULL);
2523
2524 // Log an informational event with the caller name
2525 logEntry = IoAllocateErrorLogEntry(
2526 deviceExtension->DeviceObject,
2528
2529 if (logEntry != NULL)
2530 {
2531 PUCHAR dumpDataPtr = (PUCHAR) logEntry->DumpData;
2532
2533 logEntry->FinalStatus = STATUS_SUCCESS;
2535 logEntry->SequenceNumber = 0;
2538 logEntry->RetryCount = 0;
2539 logEntry->UniqueErrorValue = 0x1;
2541
2542 RtlCopyMemory(dumpDataPtr,
2543 (PUCHAR)&cdData->CallerName,
2545
2546 // Write the error log packet.
2547 IoWriteErrorLogEntry(logEntry);
2548 }
2549
2550 }
2551 else
2552 {
2553 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
2554 "RequestHandleExclusiveAccessLockDevice: Unable to lock device, device already locked.\n"));
2555
2557 }
2558 }
2559
2560 RequestCompletion(deviceExtension, Request, status, 0);
2561
2562 return status;
2563}
2564
2567RequestHandleExclusiveAccessUnlockDevice(
2568 _In_ WDFDEVICE Device,
2569 _In_ WDFREQUEST Request
2570 )
2571/*++
2572
2573Routine Description:
2574
2575 Handle request of IOCTL_CDROM_EXCLUSIVE_ACCESS with ExclusiveAccessUnlockDevice
2576
2577Arguments:
2578
2579 Device - device handle
2580 Request - request to be handled
2581
2582Return Value:
2583
2584 NTSTATUS
2585
2586--*/
2587{
2589 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2590 PCDROM_EXCLUSIVE_ACCESS exclusiveAccess = NULL;
2591 WDFFILEOBJECT fileObject = NULL;
2592
2593 PAGED_CODE();
2594
2595 fileObject = WdfRequestGetFileObject(Request);
2596
2597 if (fileObject == NULL)
2598 {
2599 // The device can be unlocked from exclusive mode only via the file object which locked it.
2601
2602 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
2603 "RequestHandleExclusiveAccessUnlockDevice: FileObject is NULL, cannot release exclusive access\n"));
2604 }
2605
2606 if (NT_SUCCESS(status))
2607 {
2608 status = WdfRequestRetrieveInputBuffer(Request,
2610 &exclusiveAccess,
2611 NULL);
2612 }
2613
2614 if (NT_SUCCESS(status))
2615 {
2616 status = DeviceUnlockExclusive(deviceExtension, fileObject,
2617 TEST_FLAG(exclusiveAccess->Flags, CDROM_NO_MEDIA_NOTIFICATIONS));
2618
2619 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "RequestHandleExclusiveAccessUnlockDevice: Device unlocked\n"));
2620 }
2621
2622 RequestCompletion(deviceExtension, Request, status, 0);
2623
2624 return status;
2625}
2626
2629 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2630 _In_ WDFREQUEST Request,
2632 _Out_ size_t * DataLength
2633 )
2634/*++
2635
2636Routine Description:
2637
2638 Handle request of IOCTL_STORAGE_QUERY_PROPERTY when the required data is cached.
2639
2640Arguments:
2641
2642 DeviceExtension - device context
2643 Request - request to be handled
2644 RequestParameters - request parameter
2645 DataLength - transferred data length
2646
2647Return Value:
2648
2649 NTSTATUS
2650
2651--*/
2652{
2654 PSTORAGE_PROPERTY_QUERY inputBuffer = NULL;
2655
2656 *DataLength = 0;
2657
2658 status = WdfRequestRetrieveInputBuffer(Request,
2660 &inputBuffer,
2661 NULL);
2662
2663 if (NT_SUCCESS(status))
2664 {
2665 if (inputBuffer->PropertyId == StorageDeviceProperty)
2666 {
2667 // check output buffer length
2668 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength == 0)
2669 {
2670 // According to MSDN, an output buffer of size 0 can be used to determine if a property exists
2671 // so this must be a success case with no data transferred
2672 *DataLength = 0;
2674 }
2675 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_DESCRIPTOR_HEADER))
2676 {
2677 // Buffer too small
2678 *DataLength = DeviceExtension->DeviceDescriptor->Size;
2680 }
2681 else
2682 {
2683 PSTORAGE_DEVICE_DESCRIPTOR outputDescriptor = NULL;
2684 CHAR* localDescriptorBuffer = (CHAR*)DeviceExtension->DeviceDescriptor;
2685
2686 status = WdfRequestRetrieveOutputBuffer(Request,
2687 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
2688 &outputDescriptor,
2689 NULL);
2690
2691 if (NT_SUCCESS(status))
2692 {
2693 // transfer as much data out as the buffer will allow
2695 DeviceExtension->DeviceDescriptor->Size);
2696
2697 RtlCopyMemory(outputDescriptor,
2698 DeviceExtension->DeviceDescriptor,
2699 *DataLength);
2700
2701 // walk through and update offset variables to reflect data that didn't make it into the output buffer
2703 (DeviceExtension->DeviceDescriptor->VendorIdOffset != 0) &&
2704 (DeviceExtension->DeviceDescriptor->VendorIdOffset != 0xFFFFFFFF))
2705 {
2706 // set VendorIdOffset appropriately
2707 if (*DataLength <
2708 (DeviceExtension->DeviceDescriptor->VendorIdOffset + strlen(localDescriptorBuffer + DeviceExtension->DeviceDescriptor->VendorIdOffset)))
2709 {
2710 outputDescriptor->VendorIdOffset = 0;
2711 }
2712 }
2713
2715 (DeviceExtension->DeviceDescriptor->ProductIdOffset != 0) &&
2716 (DeviceExtension->DeviceDescriptor->ProductIdOffset != 0xFFFFFFFF))
2717 {
2718 // set ProductIdOffset appropriately
2719 if (*DataLength <
2720 (DeviceExtension->DeviceDescriptor->ProductIdOffset + strlen(localDescriptorBuffer + DeviceExtension->DeviceDescriptor->ProductIdOffset)))
2721 {
2722 outputDescriptor->ProductIdOffset = 0;
2723 }
2724 }
2725
2726 if ((*DataLength >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_DEVICE_DESCRIPTOR, ProductRevisionOffset)) &&
2727 (DeviceExtension->DeviceDescriptor->ProductRevisionOffset != 0) &&
2728 (DeviceExtension->DeviceDescriptor->ProductRevisionOffset != 0xFFFFFFFF))
2729 {
2730 // set ProductRevisionOffset appropriately
2731 if (*DataLength <
2732 (DeviceExtension->DeviceDescriptor->ProductRevisionOffset + strlen(localDescriptorBuffer + DeviceExtension->DeviceDescriptor->ProductRevisionOffset)))
2733 {
2734 outputDescriptor->ProductRevisionOffset = 0;
2735 }
2736 }
2737
2738 if ((*DataLength >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_DEVICE_DESCRIPTOR, SerialNumberOffset)) &&
2739 (DeviceExtension->DeviceDescriptor->SerialNumberOffset != 0) &&
2740 (DeviceExtension->DeviceDescriptor->SerialNumberOffset != 0xFFFFFFFF))
2741 {
2742 // set SerialNumberOffset appropriately
2743 if (*DataLength <
2744 (DeviceExtension->DeviceDescriptor->SerialNumberOffset + strlen(localDescriptorBuffer + DeviceExtension->DeviceDescriptor->SerialNumberOffset)))
2745 {
2746 // NOTE: setting this to 0 since that is what most port drivers do
2747 // [this could cause issues with SCSI port devices whose clients expect -1 in this field]
2748 outputDescriptor->SerialNumberOffset = 0;
2749 }
2750 }
2752 }
2753 }
2754 } //end of StorageDeviceProperty
2755 else if (inputBuffer->PropertyId == StorageAdapterProperty)
2756 {
2757 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength == 0)
2758 {
2759 // According to MSDN, an output buffer of size 0 can be used to determine if a property exists
2760 // so this must be a success case with no data transferred
2761 *DataLength = 0;
2763 }
2764 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_DESCRIPTOR_HEADER))
2765 {
2766 // Buffer too small
2767 *DataLength = DeviceExtension->AdapterDescriptor->Size;
2769 }
2770 else
2771 {
2772 PSTORAGE_ADAPTER_DESCRIPTOR outputDescriptor = NULL;
2773
2774 status = WdfRequestRetrieveOutputBuffer(Request,
2775 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
2776 &outputDescriptor,
2777 NULL);
2778 if (NT_SUCCESS(status))
2779 {
2780 // copy as much data out as the buffer will allow
2782 DeviceExtension->AdapterDescriptor->Size);
2783
2784 RtlCopyMemory(outputDescriptor,
2785 DeviceExtension->AdapterDescriptor,
2786 *DataLength);
2787
2788 // set status
2790 }
2791 }
2792 }
2793 }
2794
2795 return status;
2796}
2797
2800 _In_ WDFDEVICE Device,
2801 _In_ WDFREQUEST Request
2802 )
2803/*++
2804
2805Routine Description:
2806
2807 Handle request of IOCTL_STORAGE_QUERY_PROPERTY with StorageDeviceUniqueIdProperty.
2808
2809Arguments:
2810
2811 DeviceExtension - device context
2812 Request - request to be handled
2813 RequestParameters - request parameter
2814 DataLength - transferred data length
2815
2816Return Value:
2817
2818 NTSTATUS
2819
2820--*/
2821{
2823 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2824 PSTORAGE_PROPERTY_QUERY inputBuffer = NULL;
2825 PSTORAGE_DESCRIPTOR_HEADER descHeader = NULL;
2826 size_t outLength = 0;
2827 WDF_REQUEST_PARAMETERS requestParameters;
2828
2829 // Get the Request parameters
2830 WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
2831 WdfRequestGetParameters(Request, &requestParameters);
2832
2833 status = WdfRequestRetrieveInputBuffer(Request,
2834 requestParameters.Parameters.DeviceIoControl.InputBufferLength,
2835 &inputBuffer,
2836 NULL);
2837
2838 if (NT_SUCCESS(status))
2839 {
2840 BOOLEAN overflow = FALSE;
2841 BOOLEAN infoFound = FALSE;
2842
2843 // Must run at less then dispatch.
2845 {
2847 outLength = 0;
2849 }
2850 else if (inputBuffer->QueryType == PropertyExistsQuery)
2851 {
2852 outLength = 0;
2854 }
2855 else if (inputBuffer->QueryType != PropertyStandardQuery)
2856 {
2857 outLength = 0;
2859 }
2860 else
2861 {
2862 // Check AdditionalParameters validity.
2863 if (inputBuffer->AdditionalParameters[0] == DUID_INCLUDE_SOFTWARE_IDS)
2864 {
2865 // Do nothing
2866 }
2867 else if (inputBuffer->AdditionalParameters[0] == DUID_HARDWARE_IDS_ONLY)
2868 {
2869 // Do nothing
2870 }
2871 else
2872 {
2873 outLength = 0;
2875 }
2876
2877 if (NT_SUCCESS(status) &&
2878 (outLength < sizeof(STORAGE_DESCRIPTOR_HEADER)))
2879 {
2880 outLength = 0;
2882 }
2883 }
2884
2885 // From this point forward the status depends on the overflow
2886 // and infoFound flags.
2887 if (NT_SUCCESS(status))
2888 {
2889 outLength = requestParameters.Parameters.DeviceIoControl.OutputBufferLength;
2890 status = WdfRequestRetrieveOutputBuffer(Request,
2891 requestParameters.Parameters.DeviceIoControl.OutputBufferLength,
2892 &descHeader,
2893 NULL);
2894 }
2895
2896 if (NT_SUCCESS(status))
2897 {
2898 RtlZeroMemory(descHeader, outLength);
2899
2900 descHeader->Version = DUID_VERSION_1;
2901 descHeader->Size = sizeof(STORAGE_DEVICE_UNIQUE_IDENTIFIER);
2902
2903 // Try to build device unique id from StorageDeviceIdProperty.
2904 status = RequestDuidGetDeviceIdProperty(deviceExtension,
2905 Request,
2906 requestParameters,
2907 &outLength);
2908
2910 {
2911 overflow = TRUE;
2912 }
2913
2914 if (NT_SUCCESS(status))
2915 {
2916 infoFound = TRUE;
2917 }
2918
2919 // Try to build device unique id from StorageDeviceProperty.
2920 status = RequestDuidGetDeviceProperty(deviceExtension,
2921 Request,
2922 requestParameters,
2923 &outLength);
2924
2926 {
2927 overflow = TRUE;
2928 }
2929
2930 if (NT_SUCCESS(status))
2931 {
2932 infoFound = TRUE;
2933 }
2934
2935 // Return overflow, success, or a generic error.
2936 if (overflow)
2937 {
2938 // If output buffer is STORAGE_DESCRIPTOR_HEADER, then return
2939 // success to the user. Otherwise, send an error so the user
2940 // knows a larger buffer is required.
2941 if (outLength == sizeof(STORAGE_DESCRIPTOR_HEADER))
2942 {
2944 }
2945 else
2946 {
2947 outLength = (ULONG)WdfRequestGetInformation(Request);
2949 }
2950
2951 }
2952 else if (infoFound)
2953 {
2955
2956 // Exercise the compare routine. This should always succeed.
2959
2960 }
2961 else
2962 {
2964 }
2965 }
2966 }
2967
2968 RequestCompletion(deviceExtension, Request, status, outLength);
2969
2970 return status;
2971}
2972
2975 _In_ WDFDEVICE Device,
2976 _In_ WDFREQUEST Request
2977 )
2978/*++
2979
2980Routine Description:
2981
2982 Handle request of IOCTL_STORAGE_QUERY_PROPERTY with StorageDeviceWriteCacheProperty.
2983
2984Arguments:
2985
2986 DeviceExtension - device context
2987 Request - request to be handled
2988
2989Return Value:
2990
2991 NTSTATUS
2992
2993--*/
2994{
2996 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2999 PMODE_PARAMETER_HEADER modeData = NULL;
3000 PMODE_CACHING_PAGE pageData = NULL;
3001 size_t length = 0;
3002 ULONG information = 0;
3004 WDF_REQUEST_PARAMETERS requestParameters;
3005
3006 // Get the Request parameters
3007 WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
3008 WdfRequestGetParameters(Request, &requestParameters);
3009
3010 status = WdfRequestRetrieveInputBuffer(Request,
3011 requestParameters.Parameters.DeviceIoControl.InputBufferLength,
3012 &query,
3013 NULL);
3014
3015 if (NT_SUCCESS(status))
3016 {
3017
3018 // Must run at less then dispatch.
3020 {
3023 }
3024 else if (query->QueryType == PropertyExistsQuery)
3025 {
3026 information = 0;
3028 }
3029 else if (query->QueryType != PropertyStandardQuery)
3030 {
3032 }
3033 }
3034
3035 if (NT_SUCCESS(status))
3036 {
3037 length = requestParameters.Parameters.DeviceIoControl.OutputBufferLength;
3038
3039 if (length < sizeof(STORAGE_DESCRIPTOR_HEADER))
3040 {
3042 }
3043 }
3044
3045 if (NT_SUCCESS(status))
3046 {
3047 status = WdfRequestRetrieveOutputBuffer(Request,
3048 requestParameters.Parameters.DeviceIoControl.OutputBufferLength,
3049 &writeCache,
3050 NULL);
3051 }
3052
3053 if (NT_SUCCESS(status))
3054 {
3055 RtlZeroMemory(writeCache, length);
3056
3057 // Set version and required size.
3058 writeCache->Version = sizeof(STORAGE_WRITE_CACHE_PROPERTY);
3059 writeCache->Size = sizeof(STORAGE_WRITE_CACHE_PROPERTY);
3060
3062 {
3063 // caller only wants header information, bail out.
3066
3067 RequestCompletion(deviceExtension, Request, status, information);
3068 return status;
3069 }
3070 }
3071
3072 if (NT_SUCCESS(status))
3073 {
3074 srb = ExAllocatePoolWithTag(NonPagedPoolNx,
3075 sizeof(SCSI_REQUEST_BLOCK) +
3076 (sizeof(ULONG_PTR) * 2),
3078
3079 if (srb == NULL)
3080 {
3082 }
3083 }
3084
3085 if (NT_SUCCESS(status))
3086 {
3087 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
3088
3089 // Set known values
3090 writeCache->NVCacheEnabled = FALSE;
3091 writeCache->UserDefinedPowerProtection = TEST_FLAG(deviceExtension->DeviceFlags, DEV_POWER_PROTECTED);
3092
3093 // Check for flush cache support by sending a sync cache command
3094 // to the device.
3095
3096 // Set timeout value and mark the request as not being a tagged request.
3098 srb->TimeOutValue = TimeOutValueGetCapValue(deviceExtension->TimeOutValue, 4);
3099 srb->QueueTag = SP_UNTAGGED;
3101 srb->SrbFlags = deviceExtension->SrbFlags;
3102
3104 srb->CdbLength = 10;
3105
3106 srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
3107
3108 status = DeviceSendSrbSynchronously(Device,
3109 srb,
3110 NULL,
3111 0,
3112 TRUE, //flush drive cache
3113 Request);
3114
3115 if (NT_SUCCESS(status))
3116 {
3117 writeCache->FlushCacheSupported = TRUE;
3118 }
3119 else
3120 {
3121 // Device does not support sync cache
3122 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
3123 "RequestHandleQueryPropertyWriteCache: Synchronize cache failed with status 0x%X\n", status));
3124 writeCache->FlushCacheSupported = FALSE;
3125
3126 // Reset the status if there was any failure
3128 }
3129
3130 modeData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
3133
3134 if (modeData == NULL)
3135 {
3136 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
3137 "RequestHandleQueryPropertyWriteCache: Unable to allocate mode data buffer\n"));
3139 }
3140 }
3141
3142 if (NT_SUCCESS(status))
3143 {
3145
3146 length = DeviceRetrieveModeSenseUsingScratch(deviceExtension,
3147 (PCHAR)modeData,
3151
3152 if (length < sizeof(MODE_PARAMETER_HEADER))
3153 {
3154 // Retry the request in case of a check condition.
3155 length = DeviceRetrieveModeSenseUsingScratch(deviceExtension,
3156 (PCHAR)modeData,
3160
3161 if (length < sizeof(MODE_PARAMETER_HEADER))
3162 {
3163 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "RequestHandleQueryPropertyWriteCache: Mode Sense failed\n"));
3165 }
3166 }
3167 }
3168
3169 if (NT_SUCCESS(status))
3170 {
3171 // If the length is greater than length indicated by the mode data reset
3172 // the data to the mode data.
3173 if (length > (ULONG) (modeData->ModeDataLength + 1))
3174 {
3175 length = modeData->ModeDataLength + 1;
3176 }
3177
3178 // Look for caching page in the returned mode page data.
3179 pageData = ModeSenseFindSpecificPage((PCHAR)modeData,
3180 length,
3182 TRUE);
3183
3184 // Check if valid caching page exists.
3185 if (pageData == NULL)
3186 {
3187 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "RequestHandleQueryPropertyWriteCache: Unable to find caching mode page.\n"));
3188
3189 // Set write cache value as unknown.
3190 writeCache->WriteCacheEnabled = WriteCacheEnableUnknown;
3191 writeCache->WriteCacheType = WriteCacheTypeUnknown;
3192 }
3193 else
3194 {
3195 writeCache->WriteCacheEnabled = pageData->WriteCacheEnable
3198
3199 writeCache->WriteCacheType = pageData->WriteCacheEnable
3202 }
3203
3204 // Check write through support.
3205 if (modeData->DeviceSpecificParameter & MODE_DSP_FUA_SUPPORTED)
3206 {
3207 writeCache->WriteThroughSupported = WriteThroughSupported;
3208 }
3209 else
3210 {
3211 writeCache->WriteThroughSupported = WriteThroughNotSupported;
3212 }
3213
3214 // Get the changeable caching mode page and check write cache is changeable.
3216
3217 length = DeviceRetrieveModeSenseUsingScratch(deviceExtension,
3218 (PCHAR) modeData,
3222
3223 if (length < sizeof(MODE_PARAMETER_HEADER))
3224 {
3225 // Retry the request in case of a check condition.
3226 length = DeviceRetrieveModeSenseUsingScratch(deviceExtension,
3227 (PCHAR) modeData,
3231
3232 if (length < sizeof(MODE_PARAMETER_HEADER))
3233 {
3234 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "RequestHandleQueryPropertyWriteCache: Mode Sense failed\n"));
3235
3236 // If the device fails to return changeable pages, then
3237 // set the write cache changeable value to unknown.
3238 writeCache->WriteCacheChangeable = WriteCacheChangeUnknown;
3240 }
3241 }
3242 }
3243
3244 if (NT_SUCCESS(status))
3245 {
3246 // If the length is greater than length indicated by the mode data reset
3247 // the data to the mode data.
3248 if (length > (ULONG) (modeData->ModeDataLength + 1))
3249 {
3250 length = modeData->ModeDataLength + 1;
3251 }
3252
3253 // Look for caching page in the returned mode page data.
3254 pageData = ModeSenseFindSpecificPage((PCHAR)modeData,
3255 length,
3257 TRUE);
3258 // Check if valid caching page exists.
3259 if (pageData == NULL)
3260 {
3261 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "RequestHandleQueryPropertyWriteCache: Unable to find caching mode page.\n"));
3262
3263 // Set write cache changeable value to unknown.
3264 writeCache->WriteCacheChangeable = WriteCacheChangeUnknown;
3265 }
3266 else
3267 {
3268 writeCache->WriteCacheChangeable = pageData->WriteCacheEnable
3271 }
3272
3274
3275 }
3276
3277 FREE_POOL(srb);
3278 FREE_POOL(modeData);
3279
3280 RequestCompletion(deviceExtension, Request, status, information);
3281
3282 return status;
3283}
3284
3287 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3288 _In_ WDFREQUEST Request,
3290 _Out_ size_t * DataLength
3291 )
3292/*++
3293
3294Routine Description:
3295
3296 Validate request of IOCTL_DVD_READ_KEY
3297
3298Arguments:
3299
3300 DeviceExtension - device context
3301 Request - request to be handled
3302 RequestParameters - request parameter
3303 DataLength - transferred data length
3304
3305Return Value:
3306
3307 NTSTATUS
3308
3309--*/
3310{
3312 PDVD_COPY_PROTECT_KEY keyParameters = NULL;
3313 ULONG keyLength = 0;
3314
3315 *DataLength = 0;
3316
3317 status = WdfRequestRetrieveInputBuffer(Request,
3319 &keyParameters,
3320 NULL);
3321
3322 if (NT_SUCCESS(status))
3323 {
3325 {
3326 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3327 "DvdDeviceControl: EstablishDriveKey - challenge "
3328 "key buffer too small\n"));
3330 }
3331 }
3332
3333 if (NT_SUCCESS(status))
3334 {
3335 switch(keyParameters->KeyType)
3336 {
3337
3338 case DvdChallengeKey:
3339 {
3341 keyLength = DVD_CHALLENGE_KEY_LENGTH;
3342 break;
3343 }
3344 case DvdBusKey1:
3345 case DvdBusKey2:
3346 {
3348 keyLength = DVD_BUS_KEY_LENGTH;
3349 break;
3350 }
3351 case DvdTitleKey:
3352 {
3354 keyLength = DVD_TITLE_KEY_LENGTH;
3355 break;
3356 }
3357 case DvdAsf:
3358 {
3360 keyLength = DVD_ASF_LENGTH;
3361 break;
3362 }
3363 case DvdDiskKey:
3364 {
3366 keyLength = DVD_DISK_KEY_LENGTH;
3367 break;
3368 }
3369 case DvdGetRpcKey:
3370 {
3372 keyLength = DVD_RPC_KEY_LENGTH;
3373 break;
3374 }
3375 default:
3376 {
3377 keyLength = sizeof(DVD_COPY_PROTECT_KEY);
3378 break;
3379 }
3380 }
3381
3382 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < keyLength)
3383 {
3384
3385 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3386 "DvdDeviceControl: EstablishDriveKey - output "
3387 "buffer too small\n"));
3389 *DataLength = keyLength;
3390 }
3391 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength &
3392 DeviceExtension->AdapterDescriptor->AlignmentMask)
3393 {
3395 }
3396 else if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD)
3397 {
3398 // reject the request if it's not a DVD device.
3400 }
3401 }
3402
3403 return status;
3404}
3405
3406
3409 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3410 _In_ WDFREQUEST Request,
3412 _Out_ size_t * DataLength
3413 )
3414/*++
3415
3416Routine Description:
3417
3418 Handle request of IOCTL_DVD_END_SESSION
3419
3420Arguments:
3421
3422 DeviceExtension - device context
3423 Request - request to be handled
3424 RequestParameters - request parameter
3425 DataLength - transferred data length
3426
3427Return Value:
3428
3429 NTSTATUS
3430
3431--*/
3432{
3434 PDVD_SESSION_ID sessionId = NULL;
3435
3436 UNREFERENCED_PARAMETER(DeviceExtension);
3437
3438 *DataLength = 0;
3439
3440 status = WdfRequestRetrieveInputBuffer(Request,
3442 &sessionId,
3443 NULL);
3444
3445 if (NT_SUCCESS(status))
3446 {
3447 if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
3448 sizeof(DVD_SESSION_ID))
3449 {
3450 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3451 "DvdDeviceControl: EndSession - input buffer too "
3452 "small\n"));
3454 }
3455 }
3456
3457 return status;
3458}
3459
3460
3463 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3464 _In_ WDFREQUEST Request,
3466 _Out_ size_t * DataLength
3467 )
3468/*++
3469
3470Routine Description:
3471
3472 Validate request of IOCTL_AACS_END_SESSION
3473
3474Arguments:
3475
3476 DeviceExtension - device context
3477 Request - request to be handled
3478 RequestParameters - request parameter
3479 DataLength - transferred data length
3480
3481Return Value:
3482
3483 NTSTATUS
3484
3485--*/
3486{
3488 PDVD_SESSION_ID sessionId = NULL;
3489 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
3490
3491 *DataLength = 0;
3492
3493 status = WdfRequestRetrieveInputBuffer(Request,
3495 &sessionId,
3496 NULL);
3497
3498 if (NT_SUCCESS(status))
3499 {
3500 if (!cdData->Mmc.IsAACS)
3501 {
3503 }
3504 else if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_SESSION_ID))
3505 {
3507 }
3508 }
3509
3510 return status;
3511}
3512
3513
3516 _In_ WDFREQUEST Request,
3518 _Out_ size_t * DataLength
3519 )
3520/*++
3521
3522Routine Description:
3523
3524 Validates an IOCTL_CDROM_ENABLE_STREAMING request
3525
3526Arguments:
3527
3528 Request - request to be handled
3529 RequestParameters - request parameters
3530 DataLength - transferred data length
3531
3532Return Value:
3533
3534 NTSTATUS
3535
3536--*/
3537{
3539
3540 PCDROM_STREAMING_CONTROL inputBuffer = NULL;
3541
3542 *DataLength = 0;
3543
3544 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
3546 {
3548 }
3549
3550 if (NT_SUCCESS(status))
3551 {
3552 // Get the request type using CDROM_STREAMING_CONTROL structure
3553 status = WdfRequestRetrieveInputBuffer(Request,
3555 &inputBuffer,
3556 NULL);
3557 }
3558
3559 if (NT_SUCCESS(status))
3560 {
3561 if (inputBuffer->RequestType != CdromStreamingDisable &&
3565 {
3566 // Unknown request type
3568 }
3569 }
3570
3571 return status;
3572}
3573
3574
3577 _In_ WDFREQUEST Request,
3579 _Out_ size_t * DataLength
3580 )
3581/*++
3582
3583Routine Description:
3584
3585 Validates an IOCTL_CDROM_SEND_OPC_INFORMATION request
3586
3587Arguments:
3588
3589 Request - request to be handled
3590 RequestParameters - request parameters
3591 DataLength - transferred data length
3592
3593Return Value:
3594
3595 NTSTATUS
3596
3597--*/
3598{
3600
3601 PCDROM_SIMPLE_OPC_INFO inputBuffer = NULL;
3602
3603 *DataLength = 0;
3604
3605 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
3606 sizeof(CDROM_SIMPLE_OPC_INFO))
3607 {
3609 }
3610
3611 if (NT_SUCCESS(status))
3612 {
3613 // Get the request type using CDROM_SIMPLE_OPC_INFO structure
3614 status = WdfRequestRetrieveInputBuffer(Request,
3615 sizeof(CDROM_SIMPLE_OPC_INFO),
3616 &inputBuffer,
3617 NULL);
3618 }
3619
3620 if (NT_SUCCESS(status))
3621 {
3622 if (inputBuffer->RequestType != SimpleOpcInfo)
3623 {
3624 // Unknown request type
3626 }
3627 }
3628
3629 return status;
3630}
3631
3632
3635 _In_ WDFREQUEST Request,
3637 _Out_ size_t * DataLength
3638 )
3639/*++
3640
3641Routine Description:
3642
3643 Validates an IOCTL_CDROM_GET_PERFORMANCE request
3644
3645Arguments:
3646
3647 Request - request to be handled
3648 RequestParameters - request parameter
3649 DataLength - transferred data length
3650
3651Return Value:
3652
3653 NTSTATUS
3654
3655--*/
3656{
3658 PCDROM_WRITE_SPEED_REQUEST writeSpeedRequest = NULL;
3659 PCDROM_PERFORMANCE_REQUEST performanceRequest = NULL;
3660
3661 *DataLength = 0;
3662
3663 // CDROM_WRITE_SPEED_REQUEST is the smallest performance request that we support.
3664 // We use it to retrieve request type and then check input length more carefully
3665 // on a per request type basis.
3666 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
3668 {
3670 }
3671
3672 if (NT_SUCCESS(status))
3673 {
3674 status = WdfRequestRetrieveInputBuffer(Request,
3676 (PVOID*)&writeSpeedRequest,
3677 NULL);
3678 }
3679
3680 if (NT_SUCCESS(status))
3681 {
3682 if (writeSpeedRequest->RequestType == CdromPerformanceRequest)
3683 {
3684 // CDROM_PERFORMANCE_REQUEST is bigger than CDROM_WRITE_SPEED_REQUEST,
3685 // so we perform more checks and retrieve more bytes through WDF.
3686 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
3688 {
3690 }
3691 if (NT_SUCCESS(status))
3692 {
3693 status = WdfRequestRetrieveInputBuffer(Request,
3695 &performanceRequest,
3696 NULL);
3697 }
3698
3699 if (!NT_SUCCESS(status))
3700 {
3701 // just pass the status code from above
3702 }
3703 // validate all enum-type fields of CDROM_PERFORMANCE_REQUEST
3704 else if (performanceRequest->PerformanceType != CdromReadPerformance &&
3705 performanceRequest->PerformanceType != CdromWritePerformance)
3706 {
3708 }
3709 else if (performanceRequest->Exceptions != CdromNominalPerformance &&
3710 performanceRequest->Exceptions != CdromEntirePerformanceList &&
3711 performanceRequest->Exceptions != CdromPerformanceExceptionsOnly)
3712 {
3714 }
3715 else if (performanceRequest->Tolerance != Cdrom10Nominal20Exceptions)
3716 {
3718 }
3719 }
3720 else if (writeSpeedRequest->RequestType == CdromWriteSpeedRequest)
3721 {
3722 // No additional checks here: all remaining fields are ignored
3723 // if RequestType == CdromWriteSpeedRequest.
3724 }
3725 else
3726 {
3728 }
3729 }
3730
3731 // finally, check output buffer length
3732 if (NT_SUCCESS(status))
3733 {
3734 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
3736 {
3739 }
3740 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >
3741 ((USHORT)-1))
3742 {
3744 }
3745 }
3746
3747 return status;
3748}
3749
3750
3752PCDB
3753RequestGetScsiPassThroughCdb(
3754 _In_ PIRP Irp
3755 )
3756/*++
3757
3758Routine Description:
3759
3760 Get the CDB structure from the SCSI pass through
3761
3762Arguments:
3763
3764 Irp - request to be handled
3765
3766Return Value:
3767
3768 PCDB
3769
3770--*/
3771{
3772 PCDB cdb = NULL;
3774 ULONG inputBufferLength = 0;
3775 PVOID inputBuffer = NULL;
3776 BOOLEAN legacyPassThrough = FALSE;
3777
3778 PAGED_CODE();
3779
3780 if (((currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH) ||
3781 (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) ||
3782 (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_EX) ||
3783 (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT_EX)) &&
3784 (Irp->AssociatedIrp.SystemBuffer != NULL))
3785 {
3786 inputBufferLength = currentIrpStack->Parameters.DeviceIoControl.InputBufferLength;
3787 inputBuffer = Irp->AssociatedIrp.SystemBuffer;
3788 legacyPassThrough = TRUE;
3789
3790 if ((currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_EX) ||
3791 (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT_EX))
3792 {
3793 legacyPassThrough = FALSE;
3794 }
3795
3796 //
3797 // If this is a 32 bit application running on 64 bit then thunk the
3798 // input structures to grab the cdb.
3799 //
3800
3801#if BUILD_WOW64_ENABLED && defined(_WIN64)
3802
3803 if (IoIs32bitProcess(Irp))
3804 {
3805 if (legacyPassThrough)
3806 {
3807 if (inputBufferLength >= sizeof(SCSI_PASS_THROUGH32))
3808 {
3809 cdb = (PCDB)((PSCSI_PASS_THROUGH32)inputBuffer)->Cdb;
3810 }
3811 }
3812 else
3813 {
3814 if (inputBufferLength >= sizeof(SCSI_PASS_THROUGH32_EX))
3815 {
3816 cdb = (PCDB)((PSCSI_PASS_THROUGH32_EX)inputBuffer)->Cdb;
3817 }
3818 }
3819
3820 }
3821 else
3822
3823#endif
3824
3825 {
3826 if (legacyPassThrough)
3827 {
3828 if (inputBufferLength >= sizeof(SCSI_PASS_THROUGH))
3829 {
3830 cdb = (PCDB)((PSCSI_PASS_THROUGH)inputBuffer)->Cdb;
3831 }
3832 }
3833 else
3834 {
3835 if (inputBufferLength >= sizeof(SCSI_PASS_THROUGH_EX))
3836 {
3837 cdb = (PCDB)((PSCSI_PASS_THROUGH_EX)inputBuffer)->Cdb;
3838 }
3839 }
3840 }
3841 }
3842
3843 return cdb;
3844}
3845
3848RequestHandleScsiPassThrough(
3849 _In_ WDFDEVICE Device,
3850 _In_ WDFREQUEST Request
3851 )
3852/*++
3853
3854Routine Description:
3855
3856 Handle request of IOCTL_SCSI_PASS_THROUGH
3857 IOCTL_SCSI_PASS_THROUGH_DIRECT
3858
3859 The function sets the MinorFunction field of irpStack,
3860 and pass the request to lower level driver.
3861
3862Arguments:
3863
3864 Device - device object
3865 Request - request to be handled
3866
3867Return Value:
3868
3869 NTSTATUS
3870
3871--*/
3872{
3874 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
3875 PIRP irp = WdfRequestWdmGetIrp(Request);
3876 PZERO_POWER_ODD_INFO zpoddInfo = deviceExtension->ZeroPowerODDInfo;
3877 PCDB cdb = NULL;
3878 BOOLEAN isSoftEject = FALSE;
3879
3880#if DBG
3881 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
3882#endif
3883
3884
3885 PAGED_CODE();
3886
3887#if DBG
3888 // SPTI is always processed in sync manner.
3889 NT_ASSERT(requestContext->SyncRequired);
3890#endif
3891
3892 if ((zpoddInfo != NULL) &&
3893 (zpoddInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) &&
3894 (zpoddInfo->Load == 0)) // Drawer
3895 {
3896 cdb = RequestGetScsiPassThroughCdb(irp);
3897
3898 if ((cdb != NULL) &&
3899 (cdb->AsByte[0] == SCSIOP_START_STOP_UNIT) &&
3900 (cdb->START_STOP.LoadEject == 1) &&
3901 (cdb->START_STOP.Start == 0))
3902 {
3903 isSoftEject = TRUE;
3904 }
3905 }
3906
3907 WdfRequestFormatRequestUsingCurrentType(Request);
3908
3909 // Special for SPTI, set the MinorFunction.
3910 {
3912
3913 nextStack->MinorFunction = 1;
3914 }
3915
3916
3917 status = RequestSend(deviceExtension,
3918 Request,
3919 deviceExtension->IoTarget,
3921 NULL);
3922
3923
3924 if (!NT_SUCCESS(status) &&
3925 (isSoftEject != FALSE))
3926 {
3927 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
3928 "RequestHandleScsiPassThrough: soft eject detected, device marked as active\n"));
3929
3930 DeviceMarkActive(deviceExtension, TRUE, FALSE);
3931 }
3932
3933 RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
3934
3935 return status;
3936}
3937
3940 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3941 _In_ WDFREQUEST Request,
3943 _Out_ size_t * DataLength
3944 )
3945/*++
3946
3947Routine Description:
3948
3949 Handle request of IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
3950
3951Arguments:
3952
3953 DeviceExtension - device context
3954 Request - request to be handled
3955 RequestParameters - request parameter
3956 DataLength - transferred data length
3957
3958Return Value:
3959
3960 NTSTATUS
3961
3962--*/
3963{
3965 PMOUNTDEV_UNIQUE_ID uniqueId = NULL;
3966
3967 *DataLength = 0;
3968
3969 if (!DeviceExtension->MountedDeviceInterfaceName.Buffer)
3970 {
3972 }
3973 else if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_UNIQUE_ID))
3974 {
3975 *DataLength = sizeof(MOUNTDEV_UNIQUE_ID);
3977 }
3978
3979 if (NT_SUCCESS(status))
3980 {
3981 status = WdfRequestRetrieveOutputBuffer(Request,
3982 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
3983 &uniqueId,
3984 NULL);
3985 }
3986
3987 if (NT_SUCCESS(status))
3988 {
3989 RtlZeroMemory(uniqueId, RequestParameters.Parameters.DeviceIoControl.OutputBufferLength);
3990
3991 uniqueId->UniqueIdLength = DeviceExtension->MountedDeviceInterfaceName.Length;
3992
3993 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
3994 (sizeof(USHORT) + DeviceExtension->MountedDeviceInterfaceName.Length))
3995 {
3996 *DataLength = sizeof(MOUNTDEV_UNIQUE_ID);
3998 }
3999 }
4000
4001 if (NT_SUCCESS(status))
4002 {
4003 RtlCopyMemory(uniqueId->UniqueId,
4004 DeviceExtension->MountedDeviceInterfaceName.Buffer,
4005 uniqueId->UniqueIdLength);
4006
4007 *DataLength = sizeof(USHORT) + uniqueId->UniqueIdLength;
4009 }
4010
4011 return status;
4012}
4013
4016 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
4017 _In_ WDFREQUEST Request,
4019 _Out_ size_t * DataLength
4020 )
4021/*++
4022
4023Routine Description:
4024
4025 Handle request of IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
4026
4027Arguments:
4028
4029 DeviceExtension - device context
4030 Request - request to be handled
4031 RequestParameters - request parameter
4032 DataLength - transferred data length
4033
4034Return Value:
4035
4036 NTSTATUS
4037
4038--*/
4039{
4042
4043 *DataLength = 0;
4044
4045 NT_ASSERT(DeviceExtension->DeviceName.Buffer);
4046
4047 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME))
4048 {
4050 *DataLength = sizeof(MOUNTDEV_NAME);
4051 }
4052
4053 if (NT_SUCCESS(status))
4054 {
4055 status = WdfRequestRetrieveOutputBuffer(Request,
4056 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
4057 &name,
4058 NULL);
4059 }
4060
4061 if (NT_SUCCESS(status))
4062 {
4064 name->NameLength = DeviceExtension->DeviceName.Length;
4065
4066 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
4067 (sizeof(USHORT) + DeviceExtension->DeviceName.Length))
4068 {
4070 *DataLength = sizeof(MOUNTDEV_NAME);
4071 }
4072 }
4073
4074 if (NT_SUCCESS(status))
4075 {
4076 RtlCopyMemory(name->Name,
4077 DeviceExtension->DeviceName.Buffer,
4078 name->NameLength);
4079
4081 *DataLength = sizeof(USHORT) + name->NameLength;
4082 }
4083
4084 return status;
4085}
4086
4089 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
4090 _In_ WDFREQUEST Request,
4092 _Out_ size_t * DataLength
4093 )
4094/*++
4095
4096Routine Description:
4097
4098 Handle request of IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
4099
4100Arguments:
4101
4102 DeviceExtension - device context
4103 Request - request to be handled
4104 RequestParameters - request parameter
4105 DataLength - transferred data length
4106
4107Return Value:
4108
4109 NTSTATUS
4110
4111--*/
4112{
4114
4115 PMOUNTDEV_SUGGESTED_LINK_NAME suggestedName = NULL;
4116
4117 WCHAR driveLetterNameBuffer[10] = {0};
4118 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0};
4119 PWSTR valueName = NULL;
4120 UNICODE_STRING driveLetterName = {0};
4121
4122 *DataLength = 0;
4123
4124 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
4126 {
4129 }
4130
4131 if (NT_SUCCESS(status))
4132 {
4133 valueName = ExAllocatePoolWithTag(PagedPool,
4134 DeviceExtension->DeviceName.Length + sizeof(WCHAR),
4136 if (valueName == NULL)
4137 {
4139 }
4140 }
4141
4142 if (NT_SUCCESS(status))
4143 {
4144 RtlCopyMemory(valueName,
4145 DeviceExtension->DeviceName.Buffer,
4146 DeviceExtension->DeviceName.Length);
4147 valueName[DeviceExtension->DeviceName.Length/sizeof(WCHAR)] = 0;
4148
4149 driveLetterName.Buffer = driveLetterNameBuffer;
4150 driveLetterName.MaximumLength = sizeof(driveLetterNameBuffer);
4151 driveLetterName.Length = 0;
4152
4154 queryTable[0].Name = valueName;
4155 queryTable[0].EntryContext = &driveLetterName;
4157
4159 L"\\Registry\\Machine\\System\\DISK", // why hard coded?
4160 queryTable, NULL, NULL);
4161 }
4162
4163 if (NT_SUCCESS(status))
4164 {
4165 if ((driveLetterName.Length == 4) &&
4166 (driveLetterName.Buffer[0] == '%') &&
4167 (driveLetterName.Buffer[1] == ':'))
4168 {
4169 driveLetterName.Buffer[0] = 0xFF;
4170 }
4171 else if ((driveLetterName.Length != 4) ||
4172 (driveLetterName.Buffer[0] < FirstDriveLetter) ||
4173 (driveLetterName.Buffer[0] > LastDriveLetter) ||
4174 (driveLetterName.Buffer[1] != ':'))
4175 {
4177 }
4178 }
4179
4180 if (NT_SUCCESS(status))
4181 {
4182 status = WdfRequestRetrieveOutputBuffer(Request,
4183 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
4184 &suggestedName,
4185 NULL);
4186 }
4187
4188 if (NT_SUCCESS(status))
4189 {
4190 RtlZeroMemory(suggestedName, RequestParameters.Parameters.DeviceIoControl.OutputBufferLength);
4191 suggestedName->UseOnlyIfThereAreNoOtherLinks = TRUE;
4192 suggestedName->NameLength = 28;
4193
4195
4196 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < *DataLength)
4197 {
4200 }
4201 }
4202
4203 if (NT_SUCCESS(status))
4204 {
4206 L"\\Registry\\Machine\\System\\DISK",
4207 valueName);
4208
4209 RtlCopyMemory(suggestedName->Name, L"\\DosDevices\\", 24);
4210 suggestedName->Name[12] = driveLetterName.Buffer[0];
4211 suggestedName->Name[13] = ':';
4212 }
4213
4214 FREE_POOL(valueName);
4215
4216 return status;
4217}
4218
4221RequestHandleReadTOC(
4222 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
4223 _In_ WDFREQUEST Request,
4225 _Out_ size_t * DataLength
4226 )
4227/*++
4228
4229Routine Description:
4230
4231 Handle request of IOCTL_CDROM_READ_TOC
4232 IOCTL_CDROM_GET_LAST_SESSION
4233
4234Arguments:
4235
4236 DeviceExtension - device context
4237 Request - request to be handled
4238 RequestParameters - request parameter
4239 DataLength - transferred data length
4240
4241Return Value:
4242
4243 NTSTATUS
4244
4245--*/
4246{
4248 VOID* outputBuffer = NULL;
4249
4250 PAGED_CODE ();
4251
4252 *DataLength = 0;
4253
4254 if (DeviceIsPlayActive(DeviceExtension->Device))
4255 {
4257 }
4258
4259 if (NT_SUCCESS(status))
4260 {
4261 status = WdfRequestRetrieveOutputBuffer(Request,
4262 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
4263 &outputBuffer,
4264 NULL);
4265 }
4266
4267 // handle the request
4268 if (NT_SUCCESS(status))
4269 {
4270 size_t transferSize;
4271 CDB cdb;
4272
4273 transferSize = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, sizeof(CDROM_TOC));
4274
4275 RtlZeroMemory(outputBuffer, transferSize);
4276
4277 ScratchBuffer_BeginUse(DeviceExtension);
4278
4279 RtlZeroMemory(&cdb, sizeof(CDB));
4280 // Set up the CDB
4282 {
4283 // Set format to return first and last session numbers.
4285 }
4286 else
4287 {
4288 // Use MSF addressing
4289 cdb.READ_TOC.Msf = 1;
4290 }
4291
4292 cdb.READ_TOC.OperationCode = SCSIOP_READ_TOC;
4293 cdb.READ_TOC.AllocationLength[0] = (UCHAR)(transferSize >> 8);
4294 cdb.READ_TOC.AllocationLength[1] = (UCHAR)(transferSize & 0xFF);
4295
4296 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, (ULONG)transferSize, TRUE, &cdb, 10);
4297
4298 if (NT_SUCCESS(status))
4299 {
4300 *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength;
4301 RtlCopyMemory(outputBuffer,
4302 DeviceExtension->ScratchContext.ScratchBuffer,
4303 *DataLength);
4304 }
4305
4306 ScratchBuffer_EndUse(DeviceExtension);
4307 }
4308
4309 return status;
4310}
4311
4314RequestHandleReadTocEx(
4315 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
4316 _In_ WDFREQUEST Request,
4318 _Out_ size_t * DataLength
4319 )
4320/*++
4321
4322Routine Description:
4323
4324 Handle request of IOCTL_CDROM_READ_TOC_EX
4325
4326Arguments:
4327
4328 DeviceExtension - device context
4329 Request - request to be handled
4330 RequestParameters - request parameter
4331 DataLength - transferred data length
4332
4333Return Value:
4334
4335 NTSTATUS
4336
4337--*/
4338{
4340 PCDROM_READ_TOC_EX inputBuffer = NULL;
4341 VOID* outputBuffer = NULL;
4342
4343 PAGED_CODE ();
4344
4345 *DataLength = 0;
4346
4347 if (DeviceIsPlayActive(DeviceExtension->Device))
4348 {
4350 }
4351
4352 if (NT_SUCCESS(status))
4353 {
4354 status = WdfRequestRetrieveInputBuffer(Request,
4356 &inputBuffer,
4357 NULL);
4358 }
4359
4360 if (NT_SUCCESS(status))
4361 {
4362 status = WdfRequestRetrieveOutputBuffer(Request,
4363 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
4364 &outputBuffer,
4365 NULL);
4366 }
4367
4368 // handle the request
4369 if (NT_SUCCESS(status))
4370 {
4371 size_t transferSize;
4372 CDB cdb;
4373
4374 transferSize = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, MAXUSHORT);
4375 ScratchBuffer_BeginUse(DeviceExtension);
4376
4377 RtlZeroMemory(&cdb, sizeof(CDB));
4378 // Set up the CDB
4379 cdb.READ_TOC.OperationCode = SCSIOP_READ_TOC;
4380 cdb.READ_TOC.Msf = inputBuffer->Msf;
4381 cdb.READ_TOC.Format2 = inputBuffer->Format;
4382 cdb.READ_TOC.StartingTrack = inputBuffer->SessionTrack;
4383 cdb.READ_TOC.AllocationLength[0] = (UCHAR)(transferSize >> 8);
4384 cdb.READ_TOC.AllocationLength[1] = (UCHAR)(transferSize & 0xFF);
4385
4386 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, (ULONG)transferSize, TRUE, &cdb, 10);
4387
4388 if (NT_SUCCESS(status))
4389 {
4390 if (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength < MINIMUM_CDROM_READ_TOC_EX_SIZE)
4391 {
4392 *DataLength = 0;
4394 }
4395 else
4396 {
4397 *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength;
4398 RtlCopyMemory(outputBuffer,
4399 DeviceExtension->ScratchContext.ScratchBuffer,
4400 *DataLength);
4401 }
4402 }
4403
4404 ScratchBuffer_EndUse(DeviceExtension);
4405 }
4406
4407 return status;
4408}
4409
4410
4412VOID
4413GetConfigurationDataConversionTypeAllToTypeOne(
4414 _In_ FEATURE_NUMBER RequestedFeature,
4416 _Out_ size_t * DataLength
4417 )
4418/*++
4419
4420Routine Description:
4421
4422 Some CDROM devices do not handle the GET CONFIGURATION commands with
4423 TYPE ONE request. The command will time out causing a bus reset.
4424 To avoid this problem we set a device flag during start device if the device
4425 fails a TYPE ONE request. If this flag is set the TYPE ONE requests will be
4426 tried as TYPE ALL request and the data will be converted to TYPE ONE format
4427 in this routine.
4428
4429Arguments:
4430
4431 RequestedFeature - device context
4432 Srb - request to be handled
4433 DataLength - transfer data length
4434
4435Return Value:
4436
4437 NTSTATUS
4438
4439--*/
4440{
4441 PFEATURE_HEADER featureHeader = NULL;
4442 FEATURE_NUMBER thisFeature;
4443 ULONG totalLength = 0;
4444 ULONG featureLength = 0;
4445 ULONG headerLength = 0;
4446
4448
4449 PAGED_CODE ();
4450
4451 *DataLength = 0;
4452
4454 {
4455 // do not have valid data.
4456 return;
4457 }
4458
4459 // Calculate the length of valid data available in the
4460 // capabilities buffer from the DataLength field
4462 REVERSE_BYTES(&totalLength, header->DataLength);
4463
4465
4466 // Make sure the we have enough data in the SRB
4467 totalLength = min(totalLength, Srb->DataTransferLength);
4468
4469 // If we have received enough data from the device
4470 // check for the given feature.
4471 if (totalLength >= (sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER)))
4472 {
4473 // Feature information is present. Verify the feature.
4474 featureHeader = (PFEATURE_HEADER)((PUCHAR)Srb->DataBuffer + sizeof(GET_CONFIGURATION_HEADER));
4475
4476 thisFeature = (featureHeader->FeatureCode[0] << 8) | (featureHeader->FeatureCode[1]);
4477
4478 if (thisFeature == RequestedFeature)
4479 {
4480 // Calculate the feature length
4481 featureLength = sizeof(FEATURE_HEADER) + featureHeader->AdditionalLength;
4482 }
4483 }
4484
4485 // Calculate the total size
4486 totalLength = sizeof(GET_CONFIGURATION_HEADER) + featureLength;
4487
4488 headerLength = totalLength -
4490
4491 REVERSE_BYTES(header->DataLength, &headerLength);
4492
4493 *DataLength = totalLength;
4494
4495 return;
4496}
4497
4499VOID
4500GetConfigurationDataSynthesize(
4501 _In_reads_bytes_(InputBufferSize) PVOID InputBuffer,
4502 _In_ ULONG InputBufferSize,
4503 _Out_writes_bytes_(OutputBufferSize) PVOID OutputBuffer,
4504 _In_ size_t OutputBufferSize,
4507 _Out_ size_t * DataLength
4508 )
4509/*++
4510
4511Routine Description:
4512
4513 Get Configuration is a frequently used command, and we don't want it to wake
4514 up the device in case it is in Zero Power state. Before entering Zero Power state,
4515 the complete response of the command is saved in cache, and since the response
4516 is always the same in case there is no media, we can synthesize the response
4517 based on the user request.
4518
4519Arguments:
4520
4521 InputBuffer - buffer containing cached command response
4522 InputBufferSize - size of above buffer
4523 OutputBuffer - buffer to fill in result
4524 OutputBufferSize - size of above buffer
4525 StartingFeature - requested Starting Feature Number
4526 RequestType - requested Request Type
4527 DataLength - transfer data length
4528
4529Return Value:
4530
4531--*/
4532{
4533 PFEATURE_HEADER featureHeader = NULL;
4534 ULONG validLength = 0;
4535 ULONG featureLength = 0;
4536 ULONG headerLength = 0;
4537 PUCHAR buffer = NULL;
4538 ULONG bytesRemaining = 0;
4539 FEATURE_NUMBER featureCode = 0;
4540 BOOLEAN shouldCopy = FALSE;
4541 size_t copyLength = 0;
4542 size_t transferedLength = 0;
4543 size_t requiredLength = 0;
4544
4546
4547 PAGED_CODE ();
4548
4549 if (InputBufferSize < sizeof (GET_CONFIGURATION_HEADER))
4550 {
4551 // do not have valid data.
4552 *DataLength = 0;
4553
4554 return;
4555 }
4556
4557 // Calculate the length of valid data available in the
4558 // capabilities buffer from the DataLength field
4560 REVERSE_BYTES(&validLength, header->DataLength);
4561
4563
4564 // Make sure we have enough data
4565 validLength = min(validLength, InputBufferSize);
4566
4567 // Copy the header first
4568 copyLength = min(OutputBufferSize, sizeof (GET_CONFIGURATION_HEADER));
4569
4572 copyLength);
4573
4574 transferedLength = copyLength;
4575 requiredLength = sizeof (GET_CONFIGURATION_HEADER);
4576
4577 if (validLength > sizeof (GET_CONFIGURATION_HEADER))
4578 {
4579 buffer = header->Data;
4580 bytesRemaining = validLength - sizeof (GET_CONFIGURATION_HEADER);
4581
4582 // Ignore incomplete feature descriptor
4583 while (bytesRemaining >= sizeof (FEATURE_HEADER))
4584 {
4585 featureHeader = (PFEATURE_HEADER) buffer;
4586 shouldCopy = FALSE;
4587
4588 featureCode = (featureHeader->FeatureCode[0] << 8) | (featureHeader->FeatureCode[1]);
4589 featureLength = sizeof (FEATURE_HEADER) + featureHeader->AdditionalLength;
4590
4591 if (featureCode >= StartingFeature)
4592 {
4593 switch (RequestType) {
4594
4596
4597 shouldCopy = TRUE;
4598 break;
4599
4601
4602 if (featureHeader->Current)
4603 {
4604 shouldCopy = TRUE;
4605 }
4606 break;
4607
4609
4610 if (featureCode == StartingFeature)
4611 {
4612 shouldCopy = TRUE;
4613 }
4614 break;
4615
4616 default:
4617
4618 break;
4619 }
4620 }
4621
4622 if (shouldCopy != FALSE)
4623 {
4624 copyLength = min(featureLength, bytesRemaining);
4625 copyLength = min(copyLength, OutputBufferSize - transferedLength);
4626
4627 RtlMoveMemory((PUCHAR) OutputBuffer + transferedLength,
4628 buffer,
4629 copyLength);
4630
4631 transferedLength += copyLength;
4632 requiredLength += featureLength;
4633 }
4634
4635 buffer += min(featureLength, bytesRemaining);
4636 bytesRemaining -= min(featureLength, bytesRemaining);
4637 }
4638 }
4639
4640 // Adjust Data Length field in header
4642 {
4643 headerLength = (ULONG) requiredLength - RTL_SIZEOF_THROUGH_FIELD(GET_CONFIGURATION_HEADER, DataLength);
4644
4646 REVERSE_BYTES(header->DataLength, &headerLength);
4647 }
4648
4649 *DataLength = transferedLength;
4650
4651 return;
4652}
4653
4654
4657RequestHandleGetConfiguration(
4658 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
4659 _In_ WDFREQUEST Request,
4661 _Out_ size_t * DataLength
4662 )
4663/*++
4664
4665Routine Description:
4666
4667 Handle request of IOCTL_CDROM_GET_CONFIGURATION
4668
4669Arguments:
4670
4671 DeviceExtension - device context
4672 Request - request to be handled
4673 RequestParameters - request parameter
4674 DataLength - transferred data length
4675
4676Return Value:
4677
4678 NTSTATUS
4679
4680--*/
4681{
4683 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
4685 VOID* outputBuffer = NULL;
4686 size_t transferByteCount = 0;
4687 PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
4688 BOOLEAN inZeroPowerState = FALSE;
4689
4690 PAGED_CODE ();
4691
4692 *DataLength = 0;
4693
4694 //
4695 if (!cdData->Mmc.IsMmc)
4696 {
4698 }
4699 else
4700 {
4701 status = WdfRequestRetrieveInputBuffer(Request,
4703 &inputBuffer,
4704 NULL);
4705 }
4706
4707 if (NT_SUCCESS(status))
4708 {
4709 status = WdfRequestRetrieveOutputBuffer(Request,
4710 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
4711 &outputBuffer,
4712 NULL);
4713 }
4714
4715 if (NT_SUCCESS(status))
4716 {
4717 // If device is Zero Power state, there should be no media in device, thus we can synthesize the response
4718 // from our cache. Avoid waking up the device in this case.
4719 if ((zpoddInfo != NULL) &&
4720 (zpoddInfo->InZeroPowerState != FALSE))
4721 {
4722 inZeroPowerState = TRUE;
4723 }
4724
4725 if ((inZeroPowerState == FALSE) ||
4726 (zpoddInfo->GetConfigurationBuffer == NULL))
4727 {
4728 CDB cdb;
4729
4730 //The maximum number of bytes that a Drive may return
4731 //to describe its Features in one GET CONFIGURATION Command is 65,534
4732 transferByteCount = min(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength, (MAXUSHORT - 1));
4733
4734 // If this is a TYPE ONE request and if this device can't handle this
4735 // request, then we need to send TYPE ALL request to the device and
4736 // convert the data in the completion routine. If required allocate a big
4737 // buffer to get both configuration and feature header.
4740 {
4741 transferByteCount = max(transferByteCount,
4742 sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER));
4743 }
4744
4745 ScratchBuffer_BeginUse(DeviceExtension);
4746
4747 RtlZeroMemory(&cdb, sizeof(CDB));
4748 // Set up the CDB
4749 cdb.GET_CONFIGURATION.OperationCode = SCSIOP_GET_CONFIGURATION;
4750 cdb.GET_CONFIGURATION.AllocationLength[0] = (UCHAR)(transferByteCount >> 8);
4751 cdb.GET_CONFIGURATION.AllocationLength[1] = (UCHAR)(transferByteCount & 0xff);
4752
4753 cdb.GET_CONFIGURATION.StartingFeature[0] = (UCHAR)(inputBuffer->Feature >> 8);
4754 cdb.GET_CONFIGURATION.StartingFeature[1] = (UCHAR)(inputBuffer->Feature & 0xff);
4755 cdb.GET_CONFIGURATION.RequestType = (UCHAR)(inputBuffer->RequestType);
4756
4757 // If the device does not support TYPE ONE get configuration commands
4758 // then change the request type to TYPE ALL. Convert the returned data to
4759 // TYPE ONE format in the completion routine.
4762 {
4763
4764 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
4765 "DeviceHandleGetConfiguration: Changing TYPE_ONE Get Config to TYPE_ALL\n"));
4767 }
4768
4769 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, (ULONG)transferByteCount, TRUE, &cdb, 12);
4770
4771 if (NT_SUCCESS(status))
4772 {
4775 {
4776
4777 if (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength < sizeof(GET_CONFIGURATION_HEADER))
4778 {
4779 // Not enough data to calculate the data length.
4780 // So assume feature is not present
4781 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL, "DeviceHandleGetConfiguration: No get config header!\n"));
4782 *DataLength = 0;
4784 }
4785 else
4786 {
4787 //Some CDROM devices do not handle the GET CONFIGURATION commands with
4788 //TYPE ONE request. The command will time out causing a bus reset.
4789 //To avoid this problem we set a device flag during start device if the device
4790 //fails a TYPE ONE request. If this flag is set the TYPE ONE requests will be
4791 //tried as TYPE ALL request and the data will be converted to TYPE ONE format
4792 //in this routine.
4793 GetConfigurationDataConversionTypeAllToTypeOne(inputBuffer->Feature, DeviceExtension->ScratchContext.ScratchSrb, DataLength);
4795 }
4796 }
4797 else
4798 {
4799 *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength;
4800 }
4801
4802 // copy data to output buffer
4803 if (NT_SUCCESS(status))
4804 {
4805 RtlMoveMemory(outputBuffer,
4806 DeviceExtension->ScratchContext.ScratchBuffer,
4807 *DataLength);
4808 }
4809 }
4810
4811 ScratchBuffer_EndUse(DeviceExtension);
4812 }
4813 else
4814 {
4815 // We are in Zero Power state, and our cached response is available.
4816 // Synthesize the requested data.
4817 GetConfigurationDataSynthesize(zpoddInfo->GetConfigurationBuffer,
4818 zpoddInfo->GetConfigurationBufferSize,
4819 outputBuffer,
4820 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
4821 inputBuffer->Feature,
4822 inputBuffer->RequestType,
4824 );
4825 }
4826 }
4827
4828 return status;
4829}
4830
4833RequestHandleGetDriveGeometry(
4834 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
4835 _In_ WDFREQUEST Request,
4837 _Out_ size_t * DataLength
4838 )
4839/*++
4840
4841Routine Description:
4842
4843 Handle request of IOCTL_DISK_GET_LENGTH_INFO
4844 IOCTL_DISK_GET_DRIVE_GEOMETRY
4845 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
4846 IOCTL_CDROM_GET_DRIVE_GEOMETRY
4847 IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX
4848 IOCTL_STORAGE_READ_CAPACITY
4849
4850Arguments:
4851
4852 DeviceExtension - device context
4853 Request - request to be handled
4854 RequestParameters - request parameter
4855 DataLength - transferred data length
4856
4857Return Value:
4858
4859 NTSTATUS
4860
4861--*/
4862{
4864 VOID* outputBuffer = NULL;
4865
4866 PAGED_CODE ();
4867
4868 *DataLength = 0;
4869
4870 status = WdfRequestRetrieveOutputBuffer(Request,
4871 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
4872 &outputBuffer,
4873 NULL);
4874
4875 // Issue ReadCapacity to update device extension
4876 // with information for current media.
4877 if (NT_SUCCESS(status))
4878 {
4879 status = MediaReadCapacity(DeviceExtension->Device);
4880 }
4881
4882 if (NT_SUCCESS(status))
4883 {
4884 switch(RequestParameters.Parameters.DeviceIoControl.IoControlCode)
4885 {
4887 {
4888 PGET_LENGTH_INFORMATION lengthInfo = (PGET_LENGTH_INFORMATION)outputBuffer;
4889
4890 lengthInfo->Length = DeviceExtension->PartitionLength;
4892 break;
4893 }
4896 {
4897 PDISK_GEOMETRY geometry = (PDISK_GEOMETRY)outputBuffer;
4898
4899 *geometry = DeviceExtension->DiskGeometry;
4900 *DataLength = sizeof(DISK_GEOMETRY);
4901 break;
4902 }
4905 {
4906 PDISK_GEOMETRY_EX geometryEx = (PDISK_GEOMETRY_EX)outputBuffer;
4907
4908 geometryEx->DiskSize = DeviceExtension->PartitionLength;
4909 geometryEx->Geometry = DeviceExtension->DiskGeometry;
4911 break;
4912 }
4914 {
4915 PSTORAGE_READ_CAPACITY readCapacity = (PSTORAGE_READ_CAPACITY)outputBuffer;
4916
4917 readCapacity->Version = sizeof(STORAGE_READ_CAPACITY);
4918 readCapacity->Size = sizeof(STORAGE_READ_CAPACITY);
4919
4920 readCapacity->BlockLength = DeviceExtension->DiskGeometry.BytesPerSector;
4921 if (readCapacity->BlockLength > 0)
4922 {
4923 readCapacity->NumberOfBlocks.QuadPart = DeviceExtension->PartitionLength.QuadPart/readCapacity->BlockLength;
4924 }
4925 else
4926 {
4927 readCapacity->NumberOfBlocks.QuadPart = 0;
4928 }
4929
4930 readCapacity->DiskLength = DeviceExtension->PartitionLength;
4931
4933 break;
4934 }
4935 default:
4936 {
4938 break;
4939 }
4940 } // end of switch()
4941 }
4942
4943 return status;
4944}
4945
4948RequestHandleDiskVerify(
4949 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
4950 _In_ WDFREQUEST Request,
4952 _Out_ size_t * DataLength
4953 )
4954/*++
4955
4956Routine Description:
4957
4958 Handle request of IOCTL_DISK_VERIFY
4959
4960Arguments:
4961
4962 DeviceExtension - device context
4963 Request - request to be handled
4964 RequestParameters - request parameter
4965 DataLength - transferred data length
4966
4967Return Value:
4968
4969 NTSTATUS
4970
4971--*/
4972{
4974 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
4975 PVERIFY_INFORMATION verifyInfo = NULL;
4976
4977 PAGED_CODE ();
4978
4979 *DataLength = 0;
4980
4981 if (!cdData->Mmc.WriteAllowed)
4982 {
4984 }
4985
4986 if (NT_SUCCESS(status))
4987 {
4988 status = WdfRequestRetrieveInputBuffer(Request,
4990 &verifyInfo,
4991 NULL);
4992 }
4993
4994 // handle the request
4995 if (NT_SUCCESS(status))
4996 {
4997 LARGE_INTEGER byteOffset = {0};
4998
4999 // Add disk offset to starting sector.
5000 byteOffset.QuadPart = DeviceExtension->StartingOffset.QuadPart +
5001 verifyInfo->StartingOffset.QuadPart;
5002
5003 // prevent overflow returning success but only validating small area
5004 if (((DeviceExtension->StartingOffset.QuadPart + verifyInfo->StartingOffset.QuadPart) < DeviceExtension->StartingOffset.QuadPart) ||
5005 ((verifyInfo->Length >> DeviceExtension->SectorShift) > MAXUSHORT) ||
5006 ((byteOffset.QuadPart >> DeviceExtension->SectorShift) > MAXULONG) )
5007 {
5009 }
5010 else
5011 {
5012 ULONG transferSize = 0;
5013 ULONG timeoutValue = 0;
5014 CDB cdb;
5015 ULONG sectorOffset;
5017
5018 ScratchBuffer_BeginUse(DeviceExtension);
5019
5020 // Convert byte offset to sector offset.
5021 sectorOffset = (ULONG)(byteOffset.QuadPart >> DeviceExtension->SectorShift);
5022
5023 // Convert ULONG byte count to USHORT sector count.
5024 sectorCount = (USHORT)(verifyInfo->Length >> DeviceExtension->SectorShift);
5025
5026 RtlZeroMemory(&cdb, sizeof(CDB));
5027 // Set up the CDB
5028 cdb.CDB10.OperationCode = SCSIOP_VERIFY;
5029
5030 // Move little endian values into CDB in big endian format.
5031 cdb.CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&sectorOffset)->Byte3;
5032 cdb.CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&sectorOffset)->Byte2;
5033 cdb.CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&sectorOffset)->Byte1;
5034 cdb.CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&sectorOffset)->Byte0;
5035
5036 cdb.CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&sectorCount)->Byte1;
5037 cdb.CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&sectorCount)->Byte0;
5038
5039 // The verify command is used by the NT FORMAT utility and
5040 // requests are sent down for 5% of the volume size. The
5041 // request timeout value is calculated based on the number of
5042 // sectors verified.
5043 if (sectorCount != 0)
5044 {
5045 // sectorCount is a USHORT, so no overflow here...
5046 timeoutValue = TimeOutValueGetCapValue(DeviceExtension->TimeOutValue, ((sectorCount + 128) / 128));
5047 }
5048
5049 status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, Request, transferSize, FALSE, &cdb, 10, timeoutValue);
5050
5051 // nothing to do after the command finishes.
5052 ScratchBuffer_EndUse(DeviceExtension);
5053 }
5054 }
5055
5056 return status;
5057}
5058
5059
5062RequestHandleCheckVerify(
5063 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5064 _In_ WDFREQUEST Request,
5066 _Out_ size_t * DataLength
5067 )
5068/*++
5069
5070Routine Description:
5071
5072 Handle request of IOCTL_STORAGE_CHECK_VERIFY2
5073 IOCTL_STORAGE_CHECK_VERIFY
5074
5075Arguments:
5076
5077 DeviceExtension - device context
5078 Request - request to be handled
5079 RequestParameters - request parameter
5080 DataLength - transferred data length
5081
5082Return Value:
5083
5084 NTSTATUS
5085
5086--*/
5087{
5089
5090 PAGED_CODE ();
5091
5092 *DataLength = 0;
5093
5094 if (NT_SUCCESS(status))
5095 {
5096 ULONG transferSize = 0;
5097 CDB cdb;
5098
5099 ScratchBuffer_BeginUse(DeviceExtension);
5100
5101 RtlZeroMemory(&cdb, sizeof(CDB));
5102 // Set up the CDB
5103 cdb.CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
5104
5105 status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, Request, transferSize, FALSE, &cdb, 6, CDROM_TEST_UNIT_READY_TIMEOUT);
5106
5107 if (NT_SUCCESS(status))
5108 {
5110 (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength))
5111 {
5112 PULONG outputBuffer = NULL;
5113 status = WdfRequestRetrieveOutputBuffer(Request,
5114 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
5115 &outputBuffer,
5116 NULL);
5117
5118 if (outputBuffer != NULL)
5119 {
5120 *outputBuffer = DeviceExtension->MediaChangeCount;
5121 *DataLength = sizeof(ULONG);
5122 }
5123 }
5124 else
5125 {
5126 *DataLength = 0;
5127 }
5128 }
5129
5130 // nothing to do after the command finishes.
5131 ScratchBuffer_EndUse(DeviceExtension);
5132 }
5133
5134 return status;
5135}
5136
5137
5140RequestHandleFakePartitionInfo(
5141 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5142 _In_ WDFREQUEST Request,
5144 _Out_ size_t * DataLength
5145 )
5146/*++
5147
5148Routine Description:
5149
5150 Handle request of IOCTL_DISK_GET_DRIVE_LAYOUT
5151 IOCTL_DISK_GET_DRIVE_LAYOUT_EX
5152 IOCTL_DISK_GET_PARTITION_INFO
5153 IOCTL_DISK_GET_PARTITION_INFO_EX
5154
5155Arguments:
5156
5157 DeviceExtension - device context
5158 Request - request to be handled
5159 RequestParameters - request parameter
5160 DataLength - transferred data length
5161
5162Return Value:
5163
5164 NTSTATUS
5165
5166--*/
5167{
5169 VOID* outputBuffer = NULL;
5171
5172 PAGED_CODE ();
5173
5174 *DataLength = 0;
5175
5176 if (NT_SUCCESS(status))
5177 {
5182 {
5184 }
5185 }
5186
5187 if (NT_SUCCESS(status))
5188 {
5189 status = WdfRequestRetrieveOutputBuffer(Request,
5190 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
5191 &outputBuffer,
5192 NULL);
5193 }
5194
5195 // handle the request
5196 if (NT_SUCCESS(status))
5197 {
5198 switch (ioctl)
5199 {
5201 *DataLength = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]);
5202 RtlZeroMemory(outputBuffer, *DataLength);
5203 break;
5205 *DataLength = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]);
5206 RtlZeroMemory(outputBuffer, *DataLength);
5207 break;
5210 RtlZeroMemory(outputBuffer, *DataLength);
5211 break;
5214 RtlZeroMemory(outputBuffer, *DataLength);
5215 break;
5216 default:
5217 NT_ASSERT(!"Invalid ioctl should not have reached this point\n");
5218 break;
5219 }
5220
5221 // if we are getting the drive layout, then we need to start by
5222 // adding some of the non-partition stuff that says we have
5223 // exactly one partition available.
5225 {
5227 layout = (PDRIVE_LAYOUT_INFORMATION)outputBuffer;
5228 layout->PartitionCount = 1;
5229 layout->Signature = 1;
5230 outputBuffer = (PVOID)(layout->PartitionEntry);
5232 }
5234 {
5235 PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
5236 layoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)outputBuffer;
5237 layoutEx->PartitionStyle = PARTITION_STYLE_MBR;
5238 layoutEx->PartitionCount = 1;
5239 layoutEx->Mbr.Signature = 1;
5240 outputBuffer = (PVOID)(layoutEx->PartitionEntry);
5242 }
5243
5244 // NOTE: the local var 'ioctl' is now modified to either EX or
5245 // non-EX version. the local var 'systemBuffer' is now pointing
5246 // to the partition information structure.
5248 {
5249 PPARTITION_INFORMATION partitionInfo;
5250 partitionInfo = (PPARTITION_INFORMATION)outputBuffer;
5251 partitionInfo->RewritePartition = FALSE;
5252 partitionInfo->RecognizedPartition = TRUE;
5253 partitionInfo->PartitionType = PARTITION_FAT32;
5254 partitionInfo->BootIndicator = FALSE;
5255 partitionInfo->HiddenSectors = 0;
5256 partitionInfo->StartingOffset.QuadPart = 0;
5257 partitionInfo->PartitionLength = DeviceExtension->PartitionLength;
5258 partitionInfo->PartitionNumber = 0;
5259 }
5260 else
5261 {
5262 PPARTITION_INFORMATION_EX partitionInfo;
5263 partitionInfo = (PPARTITION_INFORMATION_EX)outputBuffer;
5264 partitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
5265 partitionInfo->RewritePartition = FALSE;
5266 partitionInfo->Mbr.RecognizedPartition = TRUE;
5267 partitionInfo->Mbr.PartitionType = PARTITION_FAT32;
5268 partitionInfo->Mbr.BootIndicator = FALSE;
5269 partitionInfo->Mbr.HiddenSectors = 0;
5270 partitionInfo->StartingOffset.QuadPart = 0;
5271 partitionInfo->PartitionLength = DeviceExtension->PartitionLength;
5272 partitionInfo->PartitionNumber = 0;
5273 }
5274 }
5275
5276 return status;
5277}
5278
5281 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5282 _In_ WDFREQUEST Request,
5284 _Out_ size_t * DataLength
5285 )
5286/*++
5287
5288Routine Description:
5289
5290 Handle request of IOCTL_STORAGE_GET_DEVICE_NUMBER
5291
5292Arguments:
5293
5294 DeviceExtension - device context
5295 Request - request to be handled
5296 RequestParameters - request parameter
5297 DataLength - transferred data length
5298
5299Return Value:
5300
5301 NTSTATUS
5302
5303--*/
5304{
5306
5307 *DataLength = 0;
5308
5309 if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >=
5310 sizeof(STORAGE_DEVICE_NUMBER))
5311 {
5312 PSTORAGE_DEVICE_NUMBER deviceNumber = NULL;
5313 status = WdfRequestRetrieveOutputBuffer(Request,
5314 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
5315 &deviceNumber,
5316 NULL);
5317 if (NT_SUCCESS(status))
5318 {
5319 deviceNumber->DeviceType = DeviceExtension->DeviceObject->DeviceType;
5320 deviceNumber->DeviceNumber = DeviceExtension->DeviceNumber;
5321 deviceNumber->PartitionNumber = (ULONG)-1; // legacy reason, return (-1) for this IOCTL.
5322
5325 }
5326 }
5327 else
5328 {
5331 }
5332
5333 return status;
5334}
5335
5338 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5339 _In_ WDFREQUEST Request,
5341 _Out_ size_t * DataLength
5342 )
5343/*++
5344
5345Routine Description:
5346
5347 Handle request of IOCTL_STORAGE_GET_HOTPLUG_INFO
5348
5349Arguments:
5350
5351 DeviceExtension - device context
5352 Request - request to be handled
5353 RequestParameters - request parameter
5354 DataLength - transferred data length
5355
5356Return Value:
5357
5358 NTSTATUS
5359
5360--*/
5361{
5363
5364 *DataLength = 0;
5365
5366 if(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >=
5367 sizeof(STORAGE_HOTPLUG_INFO))
5368 {
5370 status = WdfRequestRetrieveOutputBuffer(Request,
5371 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
5372 &info,
5373 NULL);
5374 if (NT_SUCCESS(status))
5375 {
5376 *info = DeviceExtension->PrivateFdoData->HotplugInfo;
5377
5380 }
5381 }
5382 else
5383 {
5386 }
5387
5388 return status;
5389}
5390
5393 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5394 _In_ WDFREQUEST Request,
5396 _Out_ size_t * DataLength
5397 )
5398/*++
5399
5400Routine Description:
5401
5402 Handle request of IOCTL_STORAGE_SET_HOTPLUG_INFO
5403
5404Arguments:
5405
5406 DeviceExtension - device context
5407 Request - request to be handled
5408 RequestParameters - request parameter
5409 DataLength - transferred data length
5410
5411Return Value:
5412
5413 NTSTATUS
5414
5415--*/
5416{
5419
5420 *DataLength = 0;
5421
5422 if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
5423 sizeof(STORAGE_HOTPLUG_INFO))
5424 {
5425 // Indicate unsuccessful status and no data transferred.
5427 }
5428
5429 if (NT_SUCCESS(status))
5430 {
5431 status = WdfRequestRetrieveInputBuffer(Request,
5433 &info,
5434 NULL);
5435 }
5436
5437 if (NT_SUCCESS(status))
5438 {
5439 if (info->Size != DeviceExtension->PrivateFdoData->HotplugInfo.Size)
5440 {
5442 }
5443
5444 if (info->MediaRemovable != DeviceExtension->PrivateFdoData->HotplugInfo.MediaRemovable)
5445 {
5447 }
5448
5449 if (info->MediaHotplug != DeviceExtension->PrivateFdoData->HotplugInfo.MediaHotplug)
5450 {
5452 }
5453
5454 if (info->WriteCacheEnableOverride != DeviceExtension->PrivateFdoData->HotplugInfo.WriteCacheEnableOverride)
5455 {
5457 }
5458 }
5459
5460 if (NT_SUCCESS(status))
5461 {
5462 DeviceExtension->PrivateFdoData->HotplugInfo.DeviceHotplug = info->DeviceHotplug;
5463
5464 // Store the user-defined override in the registry
5465 DeviceSetParameter(DeviceExtension,
5469 }
5470
5471 return status;
5472}
5473
5476RequestHandleEventNotification(
5477 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5478 _In_opt_ WDFREQUEST Request,
5480 _Out_ size_t * DataLength
5481 )
5482/*++
5483
5484Routine Description:
5485
5486 This routine handles the process of IOCTL_STORAGE_EVENT_NOTIFICATION
5487
5488Arguments:
5489
5490 DeviceExtension - device context
5491
5492 Request - request to be handled
5493
5494 RequestParameters - request parameter
5495
5496 DataLength - data transferred
5497
5498Return Value:
5499 NTSTATUS
5500
5501--*/
5502{
5505 LONG requestInUse;
5506 PSTORAGE_EVENT_NOTIFICATION eventBuffer = NULL;
5507
5508 *DataLength = 0;
5509
5510 info = DeviceExtension->MediaChangeDetectionInfo;
5511
5512 // Since AN is ASYNCHRONOUS and can happen at any time,
5513 // make certain not to do anything before properly initialized.
5514 if ((!DeviceExtension->IsInitialized) || (info == NULL))
5515 {
5517 }
5518
5519 if (NT_SUCCESS(status) && (Request != NULL) && (RequestParameters != NULL)) {
5520
5521 //
5522 // Validate IOCTL parameters
5523 //
5524 if (RequestParameters->Parameters.DeviceIoControl.InputBufferLength <
5527 }
5528
5529 //
5530 // Check for an supported event
5531 //
5532 if (NT_SUCCESS(status)) {
5533 status = WdfRequestRetrieveInputBuffer(Request,
5534 RequestParameters->Parameters.DeviceIoControl.InputBufferLength,
5535 &eventBuffer,
5536 NULL);
5537 if (NT_SUCCESS(status)) {
5538 if ((eventBuffer->Version != STORAGE_EVENT_NOTIFICATION_VERSION_V1) ||
5539 (eventBuffer->Size != sizeof(STORAGE_EVENT_NOTIFICATION))) {
5541 } else if ((eventBuffer->Events &
5544 }
5545 }
5546 }
5547
5548 }
5549
5550 if (NT_SUCCESS(status))
5551 {
5552 if (info->MediaChangeDetectionDisableCount != 0)
5553 {
5554 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN,
5555 "RequestHandleEventNotification: device %p has detection disabled \n",
5556 DeviceExtension->DeviceObject));
5558 }
5559 }
5560
5561 if (NT_SUCCESS(status))
5562 {
5563 // if the request is not in use, mark it as such.
5564 requestInUse = InterlockedCompareExchange((PLONG)&info->MediaChangeRequestInUse, 1, 0);
5565
5566 if (requestInUse != 0)
5567 {
5569 }
5570 }
5571
5572 if (NT_SUCCESS(status))
5573 {
5574 // The last MCN finished. ok to issue the new one.
5575 RequestSetupMcnSyncIrp(DeviceExtension);
5576
5577 // The irp will go into KMDF framework and a request will be created there to represent it.
5578 IoCallDriver(DeviceExtension->DeviceObject, info->MediaChangeSyncIrp);
5579 }
5580
5581 return status;
5582}
5583
5584
5587RequestHandleEjectionControl(
5588 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5589 _In_ WDFREQUEST Request,
5591 _Out_ size_t * DataLength
5592 )
5593/*++
5594
5595Routine Description:
5596
5597 Handle request of IOCTL_STORAGE_MEDIA_REMOVAL
5598 IOCTL_STORAGE_EJECTION_CONTROL
5599
5600Arguments:
5601
5602 DeviceExtension - device context
5603 Request - request to be handled
5604 RequestParameters - request parameter
5605 DataLength - transferred data length
5606
5607Return Value:
5608
5609 NTSTATUS
5610
5611--*/
5612{
5614 PPREVENT_MEDIA_REMOVAL mediaRemoval = NULL;
5615
5616 PAGED_CODE ();
5617
5618 *DataLength = 0;
5619
5620 if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
5621 sizeof(PREVENT_MEDIA_REMOVAL))
5622 {
5624 }
5625 else
5626 {
5627 status = WdfRequestRetrieveInputBuffer(Request,
5629 &mediaRemoval,
5630 NULL);
5631 }
5632
5633 if (NT_SUCCESS(status))
5634 {
5635 status = PerformEjectionControl(DeviceExtension,
5636 Request,
5639 : SimpleMediaLock),
5640 mediaRemoval->PreventMediaRemoval);
5641 }
5642
5643 return status;
5644}
5645
5646
5649RequestHandleEnableStreaming(
5650 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5651 _In_ WDFREQUEST Request,
5652 _Out_ size_t * DataLength
5653 )
5654/*++
5655
5656Routine Description:
5657
5658 Handles an IOCTL_CDROM_ENABLE_STREAMING request
5659
5660Arguments:
5661
5662 DeviceExtension - device context
5663 Request - request to be handled
5664 DataLength - transferred data length
5665
5666Notes:
5667
5668 This IOCTL is serialized because it changes read/write
5669 behavior and we want to make sure that all previous
5670 reads/writes have been completed before we change the
5671 behavior.
5672
5673Return Value:
5674
5675 NTSTATUS
5676
5677--*/
5678{
5679 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
5680 PCDROM_PRIVATE_FDO_DATA fdoData = DeviceExtension->PrivateFdoData;
5681
5682 WDFFILEOBJECT fileObject = NULL;
5683 PFILE_OBJECT_CONTEXT fileObjectContext = NULL;
5684
5686 PCDROM_STREAMING_CONTROL inputBuffer = NULL;
5687
5688 BOOLEAN enforceStreamingRead = FALSE;
5689 BOOLEAN enforceStreamingWrite = FALSE;
5690 BOOLEAN streamingReadSupported, streamingWriteSupported;
5691
5692 PAGED_CODE ();
5693
5694 *DataLength = 0;
5695
5696 status = WdfRequestRetrieveInputBuffer(Request,
5698 &inputBuffer,
5699 NULL);
5700
5701 if (NT_SUCCESS(status))
5702 {
5703 // get file object context
5704 fileObject = WdfRequestGetFileObject(Request);
5705 if (fileObject != NULL) {
5706 fileObjectContext = FileObjectGetContext(fileObject);
5707 }
5708 NT_ASSERT(fileObjectContext != NULL);
5709
5710 if (fileObjectContext == NULL)
5711 {
5712 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
5713 "RequestHandleEnableStreaming: cannot find file object context\n"));
5715 }
5716 }
5717
5718 if (NT_SUCCESS(status))
5719 {
5720 if (inputBuffer->RequestType == CdromStreamingDisable)
5721 {
5722 enforceStreamingRead = FALSE;
5723 enforceStreamingWrite = FALSE;
5724 }
5725 else if (inputBuffer->RequestType == CdromStreamingEnableForReadOnly)
5726 {
5727 enforceStreamingRead = TRUE;
5728 enforceStreamingWrite = FALSE;
5729 }
5730 else if (inputBuffer->RequestType == CdromStreamingEnableForWriteOnly)
5731 {
5732 enforceStreamingRead = FALSE;
5733 enforceStreamingWrite = TRUE;
5734 }
5735 else if (inputBuffer->RequestType == CdromStreamingEnableForReadWrite)
5736 {
5737 enforceStreamingRead = TRUE;
5738 enforceStreamingWrite = TRUE;
5739 }
5740
5741 streamingReadSupported = cdData->Mmc.StreamingReadSupported && !TEST_FLAG(fdoData->HackFlags, FDO_HACK_NO_STREAMING);
5742 streamingWriteSupported = cdData->Mmc.StreamingWriteSupported && !TEST_FLAG(fdoData->HackFlags, FDO_HACK_NO_STREAMING);
5743 if ((enforceStreamingRead && !streamingReadSupported) ||
5744 (enforceStreamingWrite && !streamingWriteSupported))
5745 {
5746 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
5747 "RequestHandleEnableStreaming: requested Streaming mode is not supported\n"));
5749 }
5750 else
5751 {
5752 fileObjectContext->EnforceStreamingRead = enforceStreamingRead;
5753 fileObjectContext->EnforceStreamingWrite = enforceStreamingWrite;
5754 }
5755 }
5756
5757 return status;
5758}
5759
5760
5763RequestHandleSendOpcInformation(
5764 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5765 _In_ WDFREQUEST Request,
5766 _Out_ size_t * DataLength
5767 )
5768/*++
5769
5770Routine Description:
5771
5772 Handles an IOCTL_CDROM_SEND_OPC_INFORMATION request
5773
5774Arguments:
5775
5776 DeviceExtension - device context
5777 Request - request to be handled
5778 DataLength - transferred data length
5779
5780Return Value:
5781
5782 NTSTATUS
5783
5784--*/
5785{
5787 PCDROM_SIMPLE_OPC_INFO inputBuffer = NULL;
5788
5789 PAGED_CODE ();
5790
5791 *DataLength = 0;
5792
5793 status = WdfRequestRetrieveInputBuffer(Request,
5794 sizeof(CDROM_SIMPLE_OPC_INFO),
5795 (PVOID*)&inputBuffer,
5796 NULL);
5797
5798 if (NT_SUCCESS(status))
5799 {
5800 CDB cdb;
5801
5802 ScratchBuffer_BeginUse(DeviceExtension);
5803
5804 RtlZeroMemory(&cdb, sizeof(CDB));
5805
5806 // we support only the simplest version for now
5808 cdb.SEND_OPC_INFORMATION.DoOpc = 1;
5809 cdb.SEND_OPC_INFORMATION.Exclude0 = (inputBuffer->Exclude0 ? 1 : 0);
5810 cdb.SEND_OPC_INFORMATION.Exclude1 = (inputBuffer->Exclude1 ? 1 : 0);
5811
5812 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, 0, FALSE, &cdb, sizeof(cdb.SEND_OPC_INFORMATION));
5813
5814 // nothing to do after the command finishes
5815 ScratchBuffer_EndUse(DeviceExtension);
5816 }
5817
5818 return status;
5819}
5820
5821
5824RequestHandleGetPerformance(
5825 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5826 _In_ WDFREQUEST Request,
5828 _Out_ size_t * DataLength
5829 )
5830/*++
5831
5832Routine Description:
5833
5834 Handles an IOCTL_CDROM_GET_PERFORMANCE request
5835
5836Arguments:
5837
5838 DeviceExtension - device context
5839 Request - request to be handled
5840 RequestParameters - request parameter
5841 DataLength - transferred data length
5842
5843Return Value:
5844
5845 NTSTATUS
5846
5847--*/
5848{
5850 PCDROM_PERFORMANCE_REQUEST inputBuffer = NULL;
5851 PVOID outputBuffer = NULL;
5852
5853 PAGED_CODE ();
5854
5855 *DataLength = 0;
5856
5857 // Retrieve pointers to input/output data. The size has been validated earlier
5858 // in RequestValidateGetPerformance, so we do not check it again.
5859 if (NT_SUCCESS(status))
5860 {
5861 status = WdfRequestRetrieveInputBuffer(Request,
5863 (PVOID*)&inputBuffer,
5864 NULL);
5865 }
5866 if (NT_SUCCESS(status))
5867 {
5868 status = WdfRequestRetrieveOutputBuffer(Request,
5869 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
5870 &outputBuffer,
5871 NULL);
5872 }
5873
5874 if (NT_SUCCESS(status))
5875 {
5876 USHORT descriptorSize = 0;
5877 USHORT descriptorCount = 0;
5878 size_t transferSize = 0;
5879 CDB cdb;
5880
5881 ScratchBuffer_BeginUse(DeviceExtension);
5882
5883 // Set up the CDB
5884 RtlZeroMemory(&cdb, sizeof(CDB));
5885
5886 if (inputBuffer->RequestType == CdromPerformanceRequest)
5887 {
5888 cdb.GET_PERFORMANCE.Type = 0;
5889
5890 // 10b is the only defined tolerance in MMCr6
5891 cdb.GET_PERFORMANCE.Tolerance = 2;
5892
5893 switch (inputBuffer->Exceptions) {
5895 cdb.GET_PERFORMANCE.Except = 0;
5896 descriptorSize = sizeof(CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR);
5897 break;
5899 cdb.GET_PERFORMANCE.Except = 1;
5900 descriptorSize = sizeof(CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR);
5901 break;
5903 cdb.GET_PERFORMANCE.Except = 2;
5904 descriptorSize = sizeof(CDROM_EXCEPTION_PERFORMANCE_DESCRIPTOR);
5905 break;
5906 }
5907
5908 switch (inputBuffer->PerformanceType) {
5910 cdb.GET_PERFORMANCE.Write = 0; break;
5912 cdb.GET_PERFORMANCE.Write = 1; break;
5913 }
5914
5915 REVERSE_BYTES(&cdb.GET_PERFORMANCE.StartingLBA, &inputBuffer->StaringLba);
5916 }
5917 else if (inputBuffer->RequestType == CdromWriteSpeedRequest)
5918 {
5919 cdb.GET_PERFORMANCE.Type = 3;
5920 descriptorSize = sizeof(CDROM_WRITE_SPEED_DESCRIPTOR);
5921 }
5922
5923 cdb.GET_PERFORMANCE.OperationCode = SCSIOP_GET_PERFORMANCE;
5924
5925 // calculate how many descriptors can fit into the output buffer
5926 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength >=
5927 sizeof(CDROM_PERFORMANCE_HEADER) &&
5928 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <=
5929 MAXUSHORT &&
5930 descriptorSize > 0)
5931 {
5932 descriptorCount = (USHORT)(RequestParameters.Parameters.DeviceIoControl.OutputBufferLength - sizeof(CDROM_PERFORMANCE_HEADER));
5933 descriptorCount /= descriptorSize;
5934 }
5935 else
5936 {
5938 }
5939
5940 REVERSE_BYTES_SHORT(&cdb.GET_PERFORMANCE.MaximumNumberOfDescriptors, &descriptorCount);
5941
5942 // Calculate transfer size. We round it up to meet adapter requirements.
5943 // Extra bytes are discarded later, when we copy data to the output buffer.
5944 transferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength;
5945 transferSize += DeviceExtension->AdapterDescriptor->AlignmentMask;
5946 transferSize &= ~DeviceExtension->AdapterDescriptor->AlignmentMask;
5947
5948 if (NT_SUCCESS(status))
5949 {
5950 status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, Request, (ULONG)transferSize, TRUE, &cdb, sizeof(cdb.GET_PERFORMANCE), CDROM_GET_PERFORMANCE_TIMEOUT);
5951 }
5952
5953 if (NT_SUCCESS(status))
5954 {
5955 if (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength < sizeof(CDROM_PERFORMANCE_HEADER))
5956 {
5957 *DataLength = 0;
5959 }
5960 else
5961 {
5963 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength);
5964 RtlCopyMemory(outputBuffer,
5965 DeviceExtension->ScratchContext.ScratchBuffer,
5966 *DataLength);
5967 }
5968 }
5969
5970 ScratchBuffer_EndUse(DeviceExtension);
5971 }
5972
5973 return status;
5974}
5975
5978RequestHandleMcnSyncFakeIoctl(
5979 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
5980 _Out_ size_t * DataLength
5981 )
5982/*++
5983
5984Routine Description:
5985
5986 Handles an IOCTL_MCN_SYNC_FAKE_IOCTL request
5987
5988Arguments:
5989
5990 DeviceExtension - device context
5991 DataLength - transferred data length
5992
5993Return Value:
5994
5995 NTSTATUS
5996
5997--*/
5998{
6000 PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo;
6001 BOOLEAN shouldRetry = TRUE;
6002 BOOLEAN requestSent = FALSE;
6003
6004 PAGED_CODE ();
6005
6006 *DataLength = 0;
6007
6008 //
6009 // Try to acquire the media change event. If we can't do it immediately
6010 // then bail out and assume the caller will try again later.
6011 //
6012 while (shouldRetry)
6013 {
6014
6015 status = RequestSetupMcnRequest(DeviceExtension,
6016 info->Gesn.Supported);
6017
6018 if (!NT_SUCCESS(status))
6019 {
6020 shouldRetry = FALSE;
6021 }
6022
6023 if (NT_SUCCESS(status))
6024 {
6025 requestSent = RequestSendMcnRequest(DeviceExtension);
6026
6027 if (requestSent)
6028 {
6029 shouldRetry = RequestPostWorkMcnRequest(DeviceExtension);
6030 }
6031 else
6032 {
6033 shouldRetry = FALSE;
6034 }
6035 }
6036 }
6037
6038 // If there were any media change notifications that were not delivered
6039 // for some reason, make an attempt to do so at this time.
6040 DeviceSendDelayedMediaChangeNotifications(DeviceExtension);
6041
6042 // Set the status and then complete the original request.
6043 // The timer handler will be able to send the next request.
6045
6046 return status;
6047}
6048
6049BOOLEAN
6051 _In_ WDFREQUEST Request,
6052 _In_ BOOLEAN IsReadRequest
6053 )
6054/*++
6055
6056Routine Description:
6057
6058 Checks whether a given read/write request should
6059 be performed in Real-Time Streaming mode.
6060
6061Arguments:
6062
6063 Request - request to be checked
6064 IsReadRequest - TRUE = read request; FALSE = write request
6065
6066Return Value:
6067
6068 TRUE - a Real-Time Streaming operation has to be performed
6069 FALSE - a normal (non-Streaming) operation has to be performed
6070
6071--*/
6072{
6073 BOOLEAN useStreaming = FALSE;
6074
6075 if (!useStreaming) {
6076 //
6077 // Check if we're required to use Streaming via I/O Stack Location flags
6078 //
6079 UCHAR currentStackLocationFlags = 0;
6080 currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
6081
6082 useStreaming = TEST_FLAG(currentStackLocationFlags, SL_REALTIME_STREAM);
6083 }
6084
6085 if (!useStreaming) {
6086 //
6087 // Check if we were previously requested to enforce Streaming for
6088 // the file handle through which this request was sent.
6089 //
6090
6091 WDFFILEOBJECT fileObject;
6092 PFILE_OBJECT_CONTEXT fileObjectContext;
6093
6094 fileObject = WdfRequestGetFileObject(Request);
6095
6096 if (fileObject != NULL) {
6097 fileObjectContext = FileObjectGetContext(fileObject);
6098 NT_ASSERT(fileObjectContext != NULL);
6099
6100 if (IsReadRequest && fileObjectContext->EnforceStreamingRead)
6101 {
6102 useStreaming = TRUE;
6103 }
6104
6105 if (!IsReadRequest && fileObjectContext->EnforceStreamingWrite)
6106 {
6107 useStreaming = TRUE;
6108 }
6109 }
6110 }
6111
6112 return useStreaming;
6113}
6114
6115
6118 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
6119 _In_ WDFREQUEST Request,
6121 )
6122/*++
6123
6124Routine Description:
6125
6126 Validate Read/Write request
6127
6128Arguments:
6129
6130 DeviceExtension - device context
6131 Request - request to be handled
6132 RequestParameters - request parameter
6133
6134Return Value:
6135
6136 NTSTATUS
6137
6138--*/
6139{
6141 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
6142
6143 BOOLEAN isValid = TRUE;
6144 LONGLONG startingOffset = 0;
6145 size_t transferByteCount = 0;
6146 PIRP irp = NULL;
6147 PIO_STACK_LOCATION currentStack = NULL;
6148
6149 irp = WdfRequestWdmGetIrp(Request);
6150 currentStack = IoGetCurrentIrpStackLocation(irp);
6151
6152 if (TEST_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME) &&
6153 (currentStack->MinorFunction != CDROM_VOLUME_VERIFY_CHECKED) &&
6154 !TEST_FLAG(currentStack->Flags, SL_OVERRIDE_VERIFY_VOLUME))
6155 {
6156 // DO_VERIFY_VOLUME is set for the device object,
6157 // but this request is not itself a verify request.
6158 // So fail this request.
6159
6160 //set the status for volume verification.
6162 }
6163
6164 if (NT_SUCCESS(status))
6165 {
6166 if (PLAY_ACTIVE(DeviceExtension))
6167 {
6169 }
6170 }
6171
6172 if (NT_SUCCESS(status))
6173 {
6174 // If the device is in exclusive mode, check whether the request is from
6175 // the handle that locked the device.
6176 if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
6177 {
6178 // This request is not from the owner. We can't let the operation go.
6179 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "RequestValidateReadWrite: Access Denied! Device in exclusive mode.\n"));
6180
6182 }
6183 }
6184
6185 // Validate the request alignment.
6186 if (NT_SUCCESS(status))
6187 {
6189 {
6190 startingOffset = RequestParameters.Parameters.Read.DeviceOffset;
6191 transferByteCount = RequestParameters.Parameters.Read.Length;
6192 }
6193 else
6194 {
6195 startingOffset = RequestParameters.Parameters.Write.DeviceOffset;
6196 transferByteCount = RequestParameters.Parameters.Write.Length;
6197 }
6198
6199 if (!DeviceExtension->DiskGeometry.BytesPerSector)
6200 {
6201 DeviceExtension->DiskGeometry.BytesPerSector = 2048;
6202 }
6203
6204 if (!DeviceExtension->SectorShift)
6205 {
6206 DeviceExtension->SectorShift = 11;
6207 }
6208
6209 // Perform some basic validation up front
6210 if (TEST_FLAG(startingOffset, DeviceExtension->DiskGeometry.BytesPerSector - 1) ||
6211 TEST_FLAG(transferByteCount, DeviceExtension->DiskGeometry.BytesPerSector - 1))
6212 {
6214 }
6215 }
6216
6217 // validate the request against the current mmc schema
6218 if (NT_SUCCESS(status))
6219 {
6221
6222 // We validate read requests according to the RandomWritable schema, except in the
6223 // case of IncrementalStreamingWritable, wherein the drive is responsible for all
6224 // of the verification
6226 {
6227 if (!cdData->Mmc.WriteAllowed)
6228 {
6229 // standard legacy validation of read irps
6230 // if writing is not allowed on the media
6232 }
6234 {
6235 // standard legacy validation of read irps
6236 // if not using streaming writes on writable media
6238 }
6239 }
6240
6241 // Fail write requests to read-only media
6243 !(cdData->Mmc.WriteAllowed))
6244 {
6245 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "RequestValidateReadWrite: Write request to read-only media\n"));
6246 isValid = FALSE;
6247 }
6248
6249 if (isValid)
6250 {
6251 switch (schema)
6252 {
6255 // Ensure that the request is within bounds for ROM drives.
6256 // Writer drives do not need to have bounds as outbounds request should not damage the drive.
6257 if(!cdData->Mmc.IsWriter)
6258 {
6259 if ((startingOffset >= DeviceExtension->PartitionLength.QuadPart) ||
6260 startingOffset < 0)
6261 {
6262 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "RequestValidateReadWrite: Request is out of bounds\n"));
6263 isValid = FALSE;
6264
6265 }
6266 else
6267 {
6268 ULONGLONG bytesRemaining = DeviceExtension->PartitionLength.QuadPart - startingOffset;
6269
6270 if ((ULONGLONG)transferByteCount > bytesRemaining)
6271 {
6272 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "RequestValidateReadWrite: Request is out of bounds\n"));
6273 isValid = FALSE;
6274 }
6275 }
6276 }
6277 break;
6278
6280 // Ensure that the number of blocks is a multiple of the blocking size
6281 if (((transferByteCount >> DeviceExtension->SectorShift) % cdData->Mmc.Blocking) != 0)
6282 {
6283 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW,
6284 "RequestValidateReadWrite: Number of blocks is not a multiple of the blocking size (%x)\n",
6285 cdData->Mmc.Blocking));
6286
6287 isValid = FALSE;
6288 }
6289 // Fall through
6291 // Ensure that the request begins on a blocking boundary
6292 if ((Int64ShrlMod32(startingOffset, DeviceExtension->SectorShift) % cdData->Mmc.Blocking) != 0)
6293 {
6294 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW,
6295 "RequestValidateReadWrite: Starting block is not a multiple of the blocking size (%x)\n",
6296 cdData->Mmc.Blocking));
6297
6298 isValid = FALSE;
6299 }
6300 break;
6301
6303 // Let the drive handle the verification
6304 break;
6305
6306 default:
6307 // Unknown schema. Fail the request
6308 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW,
6309 "RequestValidateReadWrite: Unknown validation schema (%x)\n",
6310 schema));
6311
6312 isValid = FALSE;
6313 break;
6314 } //end of switch (schema)
6315 } // end of if (isValid)
6316
6317 if (!isValid)
6318 {
6320 }
6321 } // end of mmc schema validation
6322
6323 // validate that the Real-Time Streaming requests meet device capabilties
6324 if (NT_SUCCESS(status))
6325 {
6326 // We do not check for FDO_HACK_NO_STREAMING in DeviceExtension->PrivateFdoData->HackFlags here,
6327 // because we're going to hide device failures related to streaming reads/writes from the sender
6328 // of the request. FDO_HACK_NO_STREAMING is going to be taken into account later during actual
6329 // processing of the request.
6331 {
6333 {
6334 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW,
6335 "RequestValidateReadWrite: Streaming reads are not supported.\n"));
6336
6338 }
6340 {
6341 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW,
6342 "RequestValidateReadWrite: Streaming writes are not supported.\n"));
6343
6345 }
6346 }
6347 }
6348
6349 return status;
6350}
6351
6354 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
6355 _In_ WDFREQUEST Request,
6357 )
6358/*++
6359
6360Routine Description:
6361
6362 Handle a read/write request
6363
6364Arguments:
6365
6366 DeviceExtension - device context
6367 Request - request to be handled
6368 RequestParameters - request parameter
6369
6370Return Value:
6371
6372 NTSTATUS
6373
6374--*/
6375{
6377 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
6378
6379 size_t transferByteCount = 0;
6380 PIRP irp = NULL;
6381 PIO_STACK_LOCATION currentStack = NULL;
6382
6384
6385
6386 irp = WdfRequestWdmGetIrp(Request);
6387 currentStack = IoGetCurrentIrpStackLocation(irp);
6388 dataBuffer = MmGetMdlVirtualAddress(irp->MdlAddress);
6389
6390 if (NT_SUCCESS(status))
6391 {
6393 {
6394 transferByteCount = RequestParameters.Parameters.Read.Length;
6395 }
6396 else
6397 {
6398 transferByteCount = RequestParameters.Parameters.Write.Length;
6399 }
6400
6401 if (transferByteCount == 0)
6402 {
6403 // Several parts of the code turn 0 into 0xffffffff,
6404 // so don't process a zero-length request any further.
6406 RequestCompletion(DeviceExtension, Request, status, 0);
6407 return status;
6408 }
6409
6410 // Add partition byte offset to make starting byte relative to
6411 // beginning of disk.
6412 currentStack->Parameters.Read.ByteOffset.QuadPart += (DeviceExtension->StartingOffset.QuadPart);
6413
6414 //not very necessary as the starting offset for CD/DVD device is always 0.
6416 {
6417 RequestParameters.Parameters.Read.DeviceOffset = currentStack->Parameters.Read.ByteOffset.QuadPart;
6418 }
6419 else
6420 {
6421 RequestParameters.Parameters.Write.DeviceOffset = currentStack->Parameters.Write.ByteOffset.QuadPart;
6422 }
6423 }
6424
6425 if (NT_SUCCESS(status))
6426 {
6427 ULONG entireXferLen = currentStack->Parameters.Read.Length;
6428 ULONG maxLength = 0;
6429 ULONG packetsCount = 0;
6430
6431 PCDROM_SCRATCH_READ_WRITE_CONTEXT readWriteContext;
6432 PCDROM_REQUEST_CONTEXT requestContext;
6433 PCDROM_REQUEST_CONTEXT originalRequestContext;
6434
6435 // get the count of packets we need to send.
6436 if ((((ULONG_PTR)dataBuffer) & (PAGE_SIZE-1)) == 0)
6437 {
6439 }
6440 else
6441 {
6443 }
6444
6445 packetsCount = entireXferLen / maxLength;
6446
6447 if (entireXferLen % maxLength != 0)
6448 {
6449 packetsCount++;
6450 }
6451
6452 originalRequestContext = RequestGetContext(Request);
6453
6454
6455 ScratchBuffer_BeginUse(DeviceExtension);
6456
6457 readWriteContext = &DeviceExtension->ScratchContext.ScratchReadWriteContext;
6458 requestContext = RequestGetContext(DeviceExtension->ScratchContext.ScratchRequest);
6459
6460 readWriteContext->PacketsCount = packetsCount;
6461 readWriteContext->EntireXferLen = entireXferLen;
6462 readWriteContext->MaxLength = maxLength;
6463 readWriteContext->StartingOffset = currentStack->Parameters.Read.ByteOffset;
6464 readWriteContext->DataBuffer = dataBuffer;
6465 readWriteContext->TransferedBytes = 0;
6466 readWriteContext->IsRead = (RequestParameters.Type == WdfRequestTypeRead);
6467
6468 requestContext->OriginalRequest = Request;
6469 requestContext->DeviceExtension = DeviceExtension;
6470
6471 //
6472 // Setup the READ/WRITE fields in the original request which is what
6473 // we use to properly synchronize cancellation logic between the
6474 // cancel callback and the timer routine.
6475 //
6476
6477 originalRequestContext->ReadWriteIsCompleted = FALSE;
6478 originalRequestContext->ReadWriteRetryInitialized = FALSE;
6479 originalRequestContext->DeviceExtension = DeviceExtension;
6480
6482
6483 // We do not call ScratchBuffer_EndUse here, because we're not releasing the scratch SRB.
6484 // It will be released in the completion routine.
6485 }
6486
6487 return status;
6488}
6489
6492RequestHandleLoadEjectMedia(
6493 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
6494 _In_ WDFREQUEST Request,
6496 _Out_ size_t * DataLength
6497 )
6498/*++
6499
6500Routine Description:
6501
6502 Handle request of IOCTL_STORAGE_EJECT_MEDIA
6503 IOCTL_STORAGE_LOAD_MEDIA
6504 IOCTL_STORAGE_LOAD_MEDIA2
6505
6506Arguments:
6507
6508 DeviceExtension - device context
6509 Request - request to be handled
6510 RequestParameters - request parameter
6511 DataLength - transferred data length
6512
6513Return Value:
6514
6515 NTSTATUS
6516
6517--*/
6518{
6520 PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
6521
6522 PAGED_CODE ();
6523
6524 *DataLength = 0;
6525
6526 if (NT_SUCCESS(status))
6527 {
6528 // Synchronize with ejection control and ejection cleanup code as
6529 // well as other eject/load requests.
6530 WdfWaitLockAcquire(DeviceExtension->EjectSynchronizationLock, NULL);
6531
6532 if(DeviceExtension->ProtectedLockCount != 0)
6533 {
6534 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "RequestHandleLoadEjectMedia: call to eject protected locked "
6535 "device - failure\n"));
6537 }
6538
6539 if (NT_SUCCESS(status))
6540 {
6542 PCDB cdb = (PCDB)srb.Cdb;
6543
6544 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
6545
6546 srb.CdbLength = 6;
6547
6548 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
6549 cdb->START_STOP.LoadEject = 1;
6550
6552 {
6553 cdb->START_STOP.Start = 0;
6554
6555 // We are sending down a soft eject, and in this case we should take an active ref
6556 // if the command succeeds.
6557 if ((zpoddInfo != NULL) &&
6558 (zpoddInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) &&
6559 (zpoddInfo->Load == 0)) // Drawer
6560 {
6561 zpoddInfo->MonitorStartStopUnit = TRUE;
6562 }
6563 }
6564 else
6565 {
6566 cdb->START_STOP.Start = 1;
6567 }
6568
6569 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
6570 &srb,
6571 NULL,
6572 0,
6573 FALSE,
6574 Request);
6575
6576 if (zpoddInfo != NULL)
6577 {
6578 zpoddInfo->MonitorStartStopUnit = FALSE;
6579 }
6580 }
6581
6582 WdfWaitLockRelease(DeviceExtension->EjectSynchronizationLock);
6583 }
6584
6585 return status;
6586}
6587
6588
6591RequestHandleReserveRelease(
6592 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
6593 _In_ WDFREQUEST Request,
6595 _Out_ size_t * DataLength
6596 )
6597/*++
6598
6599Routine Description:
6600
6601 Handle request of IOCTL_STORAGE_RESERVE
6602 IOCTL_STORAGE_RELEASE
6603
6604Arguments:
6605
6606 DeviceExtension - device context
6607 Request - request to be handled
6608 RequestParameters - request parameter
6609 DataLength - transferred data length
6610
6611Return Value:
6612
6613 NTSTATUS
6614
6615--*/
6616{
6619 PCDB cdb = NULL;
6620 ULONG ioctlCode = 0;
6621
6622 PAGED_CODE ();
6623
6624 *DataLength = 0;
6625
6626 srb = ExAllocatePoolWithTag(NonPagedPoolNx,
6627 sizeof(SCSI_REQUEST_BLOCK) +
6628 (sizeof(ULONG_PTR) * 2),
6630
6631 if (srb == NULL)
6632 {
6634 }
6635
6636 if (NT_SUCCESS(status))
6637 {
6638 ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
6639 cdb = (PCDB)srb->Cdb;
6640 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
6641
6642 if (TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_RESERVE6))
6643 {
6644 srb->CdbLength = 10;
6645 cdb->CDB10.OperationCode = (ioctlCode == IOCTL_STORAGE_RESERVE) ? SCSIOP_RESERVE_UNIT10 : SCSIOP_RELEASE_UNIT10;
6646 }
6647 else
6648 {
6649 srb->CdbLength = 6;
6650 cdb->CDB6GENERIC.OperationCode = (ioctlCode == IOCTL_STORAGE_RESERVE) ? SCSIOP_RESERVE_UNIT : SCSIOP_RELEASE_UNIT;
6651 }
6652
6653 // Set timeout value.
6654 srb->TimeOutValue = DeviceExtension->TimeOutValue;
6655
6656 // Send reserves as tagged requests.
6657 if (ioctlCode == IOCTL_STORAGE_RESERVE)
6658 {
6661 }
6662
6663 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
6664 srb,
6665 NULL,
6666 0,
6667 FALSE,
6668 Request);
6669 // no data transfer.
6670 *DataLength = 0;
6671
6672 FREE_POOL(srb);
6673 }
6674
6675 return status;
6676} // end RequestHandleReserveRelease()
6677
6678static // __REACTOS__
6679BOOLEAN
6681 UCHAR Scope)
6682{
6683 switch (Scope) {
6686
6687 return TRUE;
6688
6689 default:
6690
6691 return FALSE;
6692 }
6693}
6694
6695static // __REACTOS__
6696BOOLEAN
6698 UCHAR Type)
6699{
6700 switch (Type) {
6705
6706 return TRUE;
6707
6708 default:
6709
6710 return FALSE;
6711 }
6712}
6713
6716 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
6717 _In_ WDFREQUEST Request,
6719 _Out_ size_t * DataLength
6720 )
6721/*++
6722
6723Routine Description:
6724
6725 Validate request of IOCTL_STORAGE_PERSISTENT_RESERVE_IN
6726 IOCTL_STORAGE_PERSISTENT_RESERVE_OUT
6727
6728Arguments:
6729
6730 DeviceExtension - device context
6731 Request - request to be handled
6732 RequestParameters - request parameter
6733 DataLength - transferred data length
6734
6735Return Value:
6736
6737 NTSTATUS
6738
6739--*/
6740{
6742 ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
6743
6744 PPERSISTENT_RESERVE_COMMAND reserveCommand = NULL;
6745
6746 *DataLength = 0;
6747
6748 status = WdfRequestRetrieveInputBuffer(Request,
6750 (PVOID*)&reserveCommand,
6751 NULL);
6752 if (NT_SUCCESS(status))
6753 {
6754 if ((RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(PERSISTENT_RESERVE_COMMAND)) ||
6755 (reserveCommand->Size < sizeof(PERSISTENT_RESERVE_COMMAND)))
6756 {
6757 *DataLength = 0;
6759 }
6760 else if ((ULONG_PTR)reserveCommand & DeviceExtension->AdapterDescriptor->AlignmentMask)
6761 {
6762 // Check buffer alignment. Only an issue if another kernel mode component
6763 // (not the I/O manager) allocates the buffer.
6764 *DataLength = 0;
6766 }
6767 }
6768
6769 if (NT_SUCCESS(status))
6770 {
6771 if (ioctlCode == IOCTL_STORAGE_PERSISTENT_RESERVE_IN)
6772 {
6773 if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < reserveCommand->PR_IN.AllocationLength)
6774 {
6775 *DataLength = 0;
6777 }
6778 else
6779 {
6780 switch (reserveCommand->PR_IN.ServiceAction)
6781 {
6783 if (reserveCommand->PR_IN.AllocationLength < sizeof(PRI_REGISTRATION_LIST))
6784 {
6785 *DataLength = 0;
6787 }
6788 break;
6789
6791 if (reserveCommand->PR_IN.AllocationLength < sizeof(PRI_RESERVATION_LIST))
6792 {
6793 *DataLength = 0;
6795 }
6796 break;
6797
6798 default:
6799 *DataLength = 0;
6801 break;
6802 }
6803 }
6804 }
6805 else // case of IOCTL_STORAGE_PERSISTENT_RESERVE_OUT
6806 {
6807 // Verify ServiceAction, Scope, and Type
6808 switch (reserveCommand->PR_OUT.ServiceAction)
6809 {
6813 // Scope and type ignored.
6814 break;
6815
6820 if (!ValidPersistentReserveScope(reserveCommand->PR_OUT.Scope) ||
6821 !ValidPersistentReserveType(reserveCommand->PR_OUT.Type))
6822 {
6823 *DataLength = 0;
6825 }
6826 break;
6827
6828 default:
6829 *DataLength = 0;
6831 break;
6832 }
6833
6834 // Check input buffer for PR Out.
6835 // Caller must include the PR parameter list.
6836 if (NT_SUCCESS(status))
6837 {
6838 if ((RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
6839 (sizeof(PERSISTENT_RESERVE_COMMAND) + sizeof(PRO_PARAMETER_LIST))) ||
6840 (reserveCommand->Size < RequestParameters.Parameters.DeviceIoControl.InputBufferLength))
6841 {
6842 *DataLength = 0;
6844 }
6845 }
6846 } // end of validation for IOCTL_STORAGE_PERSISTENT_RESERVE_OUT
6847 }
6848
6849 return status;
6850} // end RequestValidatePersistentReserve()
6851
6852
6855RequestHandlePersistentReserve(
6856 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
6857 _In_ WDFREQUEST Request,
6859 _Out_ size_t * DataLength
6860 )
6861/*++
6862
6863Routine Description:
6864
6865 Handle request of IOCTL_STORAGE_PERSISTENT_RESERVE_IN
6866 IOCTL_STORAGE_PERSISTENT_RESERVE_OUT
6867
6868Arguments:
6869
6870 DeviceExtension - device context
6871 Request - request to be handled
6872 RequestParameters - request parameter
6873 DataLength - transferred data length
6874
6875Return Value:
6876
6877 NTSTATUS
6878
6879--*/
6880{
6882 ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
6884 PCDB cdb = NULL;
6885 BOOLEAN writeToDevice;
6886
6887 PPERSISTENT_RESERVE_COMMAND reserveCommand = NULL;
6888
6889 PAGED_CODE ();
6890
6891 *DataLength = 0;
6892
6893 status = WdfRequestRetrieveInputBuffer(Request,
6895 (PVOID*)&reserveCommand,
6896 NULL);
6897 if (NT_SUCCESS(status))
6898 {
6899 srb = ExAllocatePoolWithTag(NonPagedPoolNx,
6900 sizeof(SCSI_REQUEST_BLOCK) +
6901 (sizeof(ULONG_PTR) * 2),
6903
6904 if (srb == NULL)
6905 {
6907 }
6908 else
6909 {
6910 cdb = (PCDB)srb->Cdb;
6911 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
6912 }
6913 }
6914
6915 if (NT_SUCCESS(status))
6916 {
6917 size_t dataBufLen = 0;
6918
6919 // Fill in the CDB.
6920 if (ioctlCode == IOCTL_STORAGE_PERSISTENT_RESERVE_IN)
6921 {
6923 cdb->PERSISTENT_RESERVE_IN.ServiceAction = reserveCommand->PR_IN.ServiceAction;
6924
6925 REVERSE_BYTES_SHORT(&(cdb->PERSISTENT_RESERVE_IN.AllocationLength),
6926 &(reserveCommand->PR_IN.AllocationLength));
6927
6928 dataBufLen = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength;
6929 writeToDevice = FALSE;
6930 }
6931 else
6932 {
6934 cdb->PERSISTENT_RESERVE_OUT.ServiceAction = reserveCommand->PR_OUT.ServiceAction;
6935 cdb->PERSISTENT_RESERVE_OUT.Scope = reserveCommand->PR_OUT.Scope;
6936 cdb->PERSISTENT_RESERVE_OUT.Type = reserveCommand->PR_OUT.Type;
6937
6938 cdb->PERSISTENT_RESERVE_OUT.ParameterListLength[1] = (UCHAR)sizeof(PRO_PARAMETER_LIST);
6939
6940 // Move the parameter list to the beginning of the data buffer (so it is aligned
6941 // correctly and that the MDL describes it correctly).
6942 RtlMoveMemory(reserveCommand,
6943 reserveCommand->PR_OUT.ParameterList,
6944 sizeof(PRO_PARAMETER_LIST));
6945
6946 dataBufLen = sizeof(PRO_PARAMETER_LIST);
6947 writeToDevice = TRUE;
6948 }
6949
6950 srb->CdbLength = 10;
6952
6953 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
6954 srb,
6955 reserveCommand,
6956 (ULONG) dataBufLen,
6957 writeToDevice,
6958 Request);
6959
6960 FREE_POOL(srb);
6961 }
6962
6963 return status;
6964}
6965
6966#if (NTDDI_VERSION >= NTDDI_WIN8)
6969RequestHandleAreVolumesReady(
6970 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
6971 _In_ WDFREQUEST Request,
6973 _Out_ size_t * DataLength
6974 )
6975/*++
6976
6977Routine Description:
6978
6979 Handle request of IOCTL_DISK_ARE_VOLUMES_READY
6980
6981Arguments:
6982
6983 DeviceExtension - device context
6984 Request - request to be handled
6985 RequestParameters - request parameter
6986 DataLength - transferred data length
6987
6988Return Value:
6989
6990 NTSTATUS
6991
6992--*/
6993{
6994 BOOLEAN completeRequest = TRUE;
6996
6998
6999 *DataLength = 0;
7000
7001 if (DeviceExtension->IsVolumeOnlinePending == FALSE)
7002 {
7004 goto Cleanup;
7005 }
7006
7007 //
7008 // Add to the volume ready queue. No worries about request cancellation,
7009 // since KMDF will automatically handle that while request is in queue.
7010 //
7011 status = WdfRequestForwardToIoQueue(Request,
7012 DeviceExtension->ManualVolumeReadyQueue
7013 );
7014
7015 if(!NT_SUCCESS(status))
7016 {
7017 goto Cleanup;
7018 }
7019
7021 completeRequest = FALSE;
7022
7023Cleanup:
7024
7025 if (completeRequest)
7026 {
7027 RequestCompletion(DeviceExtension, Request, status, 0);
7028 }
7029
7030 return status;
7031}
7032
7035RequestHandleVolumeOnline(
7036 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7037 _In_ WDFREQUEST Request,
7039 _Out_ size_t * DataLength
7040 )
7041/*++
7042
7043Routine Description:
7044
7045 Handle request of IOCTL_VOLUME_ONLINE / IOCTL_VOLUME_POST_ONLINE
7046
7047Arguments:
7048
7049 DeviceExtension - device context
7050 Request - request to be handled
7051 RequestParameters - request parameter
7052 DataLength - transferred data length
7053
7054Return Value:
7055
7056 NTSTATUS
7057
7058--*/
7059{
7061 WDFREQUEST request;
7062 PIRP irp = NULL;
7063 PIO_STACK_LOCATION nextStack = NULL;
7064
7066
7067 *DataLength = 0;
7068
7069 DeviceExtension->IsVolumeOnlinePending = FALSE;
7070
7071 // Complete all parked volume ready requests.
7072 for (;;)
7073 {
7074 status = WdfIoQueueRetrieveNextRequest(DeviceExtension->ManualVolumeReadyQueue,
7075 &request);
7076
7077 if (!NT_SUCCESS(status))
7078 {
7079 break;
7080 }
7081
7082 RequestCompletion(DeviceExtension, request, STATUS_SUCCESS, 0);
7083 }
7084
7085 // Change the IOCTL code to IOCTL_DISK_VOLUMES_ARE_READY, and forward the request down,
7086 // so that if the underlying port driver will also know that volume is ready.
7087 WdfRequestFormatRequestUsingCurrentType(Request);
7088 irp = WdfRequestWdmGetIrp(Request);
7089 nextStack = IoGetNextIrpStackLocation(irp);
7090
7091 irp->AssociatedIrp.SystemBuffer = &DeviceExtension->DeviceNumber;
7092 nextStack->Parameters.DeviceIoControl.OutputBufferLength = 0;
7093 nextStack->Parameters.DeviceIoControl.InputBufferLength = sizeof (DeviceExtension->DeviceNumber);
7094 nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_DISK_VOLUMES_ARE_READY;
7095
7096 // Send the request straight down (synchronously).
7097 RequestSend(DeviceExtension,
7098 Request,
7099 DeviceExtension->IoTarget,
7101 NULL);
7102
7103 return STATUS_SUCCESS;
7104}
7105#endif
7106
7109DeviceHandleRawRead(
7110 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7111 _In_ WDFREQUEST Request,
7113 _Out_ size_t * DataLength
7114 )
7115/*++
7116
7117Routine Description:
7118
7119 Handle request of IOCTL_CDROM_RAW_READ
7120
7121Arguments:
7122
7123 DeviceExtension - device context
7124 Request - request to be handled
7125 RequestParameters - request parameter
7126 DataLength - transferred data length
7127
7128Return Value:
7129
7130 NTSTATUS
7131
7132--*/
7133{
7134 // Determine whether the drive is currently in raw or cooked mode,
7135 // and which command to use to read the data.
7136
7138 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
7139 RAW_READ_INFO rawReadInfo = {0};
7140 PVOID outputVirtAddr = NULL;
7141 ULONG startingSector;
7142
7143 PIRP irp = WdfRequestWdmGetIrp(Request);
7145
7146 VOID* outputBuffer = NULL;
7147
7148 PAGED_CODE ();
7149
7150 *DataLength = 0;
7151
7152 if (TEST_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME) &&
7153 (currentIrpStack->MinorFunction != CDROM_VOLUME_VERIFY_CHECKED) &&
7154 !TEST_FLAG(currentIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME))
7155 {
7156 // DO_VERIFY_VOLUME is set for the device object,
7157 // but this request is not itself a verify request.
7158 // So fail this request.
7159 (VOID) MediaReadCapacity(DeviceExtension->Device);
7160
7161 *DataLength = 0;
7162 //set the status for volume verification.
7164 }
7165
7166 if (NT_SUCCESS(status))
7167 {
7168 // Since this ioctl is METHOD_OUT_DIRECT, we need to copy away
7169 // the input buffer before interpreting it. This prevents a
7170 // malicious app from messing with the input buffer while we
7171 // are interpreting it. This is done in dispacth.
7172 //
7173 // Here, we are going to get the input buffer out of saved place.
7174 rawReadInfo = *(PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
7175
7176 if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength > 0)
7177 {
7178 // Make sure that any user buffer that we pass down to
7179 // the hardware is properly aligned
7180 NT_ASSERT(irp->MdlAddress);
7181 outputVirtAddr = MmGetMdlVirtualAddress(irp->MdlAddress);
7182 if ((ULONG_PTR)outputVirtAddr & DeviceExtension->AdapterDescriptor->AlignmentMask)
7183 {
7184 NT_ASSERT(!((ULONG_PTR)outputVirtAddr & DeviceExtension->AdapterDescriptor->AlignmentMask));
7185 *DataLength = 0;
7187 }
7188 }
7189 else
7190 {
7192 }
7193 }
7194
7195 if (NT_SUCCESS(status))
7196 {
7197 status = WdfRequestRetrieveOutputBuffer(Request,
7198 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
7199 &outputBuffer,
7200 NULL);
7201 }
7202
7203 if (NT_SUCCESS(status))
7204 {
7205 switch (rawReadInfo.TrackMode)
7206 {
7207 case CDDA:
7208 case YellowMode2:
7209 case XAForm2:
7210 // no check needed.
7211 break;
7212
7214 if (!cdData->Mmc.ReadCdC2Pointers || !cdData->Mmc.ReadCdSubCode)
7215 {
7216 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
7217 "Request to read C2 & Subcode rejected. "
7218 "Is C2 supported: %d Is Subcode supported: %d\n",
7219 cdData->Mmc.ReadCdC2Pointers,
7220 cdData->Mmc.ReadCdSubCode
7221 ));
7222 *DataLength = 0;
7224 }
7225 break;
7226 case RawWithC2:
7227 if (!cdData->Mmc.ReadCdC2Pointers)
7228 {
7229 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
7230 "Request to read C2 rejected because drive does not "
7231 "report support for C2 pointers\n"
7232 ));
7233 *DataLength = 0;
7235 }
7236 break;
7237 case RawWithSubCode:
7238
7239 if (!cdData->Mmc.ReadCdSubCode)
7240 {
7241 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
7242 "Request to read subcode rejected because drive does "
7243 "not report support for reading the subcode data\n"
7244 ));
7245 *DataLength = 0;
7247 }
7248 break;
7249
7250 default:
7251 *DataLength = 0;
7253 break;
7254 }
7255 }
7256
7257 if (NT_SUCCESS(status))
7258 {
7259 PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb;
7260 PCDB cdb = (PCDB)(srb->Cdb);
7261
7262 size_t transferByteCount;
7263 BOOLEAN shouldRetry = TRUE;
7264 ULONG timesAlreadyRetried = 0;
7265 LONGLONG retryIn100nsUnits = 0;
7266
7267 transferByteCount = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength;
7268
7269 ScratchBuffer_BeginUse(DeviceExtension);
7270
7271 while (shouldRetry)
7272 {
7273 // Setup cdb depending upon the sector type we want.
7274 switch (rawReadInfo.TrackMode)
7275 {
7276 case CDDA:
7277 transferByteCount = rawReadInfo.SectorCount * RAW_SECTOR_SIZE;
7278 cdb->READ_CD.ExpectedSectorType = CD_DA_SECTOR;
7279 cdb->READ_CD.IncludeUserData = 1;
7280 cdb->READ_CD.HeaderCode = 3;
7281 cdb->READ_CD.IncludeSyncData = 1;
7282 break;
7283
7284 case YellowMode2:
7285 transferByteCount = rawReadInfo.SectorCount * RAW_SECTOR_SIZE;
7286 cdb->READ_CD.ExpectedSectorType = YELLOW_MODE2_SECTOR;
7287 cdb->READ_CD.IncludeUserData = 1;
7288 cdb->READ_CD.HeaderCode = 1;
7289 cdb->READ_CD.IncludeSyncData = 1;
7290 break;
7291
7292 case XAForm2:
7293 transferByteCount = rawReadInfo.SectorCount * RAW_SECTOR_SIZE;
7294 cdb->READ_CD.ExpectedSectorType = FORM2_MODE2_SECTOR;
7295 cdb->READ_CD.IncludeUserData = 1;
7296 cdb->READ_CD.HeaderCode = 3;
7297 cdb->READ_CD.IncludeSyncData = 1;
7298 break;
7299
7301 transferByteCount = rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_C2_AND_SUBCODE_SIZE;
7302 cdb->READ_CD.ExpectedSectorType = 0; // Any sector type
7303 cdb->READ_CD.IncludeUserData = 1;
7304 cdb->READ_CD.HeaderCode = 3; // Header and subheader returned
7305 cdb->READ_CD.IncludeSyncData = 1;
7306 cdb->READ_CD.ErrorFlags = 2; // C2 and block error
7307 cdb->READ_CD.SubChannelSelection = 1; // raw subchannel data
7308 break;
7309
7310 case RawWithC2:
7311 transferByteCount = rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_C2_SIZE;
7312 cdb->READ_CD.ExpectedSectorType = 0; // Any sector type
7313 cdb->READ_CD.IncludeUserData = 1;
7314 cdb->READ_CD.HeaderCode = 3; // Header and subheader returned
7315 cdb->READ_CD.IncludeSyncData = 1;
7316 cdb->READ_CD.ErrorFlags = 2; // C2 and block error
7317 break;
7318
7319 case RawWithSubCode:
7320 transferByteCount = rawReadInfo.SectorCount * CD_RAW_SECTOR_WITH_SUBCODE_SIZE;
7321 cdb->READ_CD.ExpectedSectorType = 0; // Any sector type
7322 cdb->READ_CD.IncludeUserData = 1;
7323 cdb->READ_CD.HeaderCode = 3; // Header and subheader returned
7324 cdb->READ_CD.IncludeSyncData = 1;
7325 cdb->READ_CD.SubChannelSelection = 1; // raw subchannel data
7326 break;
7327
7328 default:
7329 // should already checked before coming in loop.
7331 break;
7332 }
7333
7334 ScratchBuffer_SetupSrb(DeviceExtension, Request, (ULONG)transferByteCount, TRUE);
7335 // Restore the buffer, buffer size and MdlAddress. They got changed but we don't want to use the scratch buffer.
7336 {
7337 PIRP scratchIrp = WdfRequestWdmGetIrp(DeviceExtension->ScratchContext.ScratchRequest);
7338 scratchIrp->MdlAddress = irp->MdlAddress;
7339 srb->DataBuffer = outputVirtAddr;
7340 srb->DataTransferLength = (ULONG)transferByteCount;
7341 }
7342 // Calculate starting offset.
7343 startingSector = (ULONG)(rawReadInfo.DiskOffset.QuadPart >> DeviceExtension->SectorShift);
7344
7345 // Fill in CDB fields.
7346 srb->CdbLength = 12;
7347
7348 cdb->READ_CD.OperationCode = SCSIOP_READ_CD;
7349 cdb->READ_CD.TransferBlocks[2] = (UCHAR) (rawReadInfo.SectorCount & 0xFF);
7350 cdb->READ_CD.TransferBlocks[1] = (UCHAR) (rawReadInfo.SectorCount >> 8 );
7351 cdb->READ_CD.TransferBlocks[0] = (UCHAR) (rawReadInfo.SectorCount >> 16);
7352
7353 cdb->READ_CD.StartingLBA[3] = (UCHAR) (startingSector & 0xFF);
7354 cdb->READ_CD.StartingLBA[2] = (UCHAR) ((startingSector >> 8));
7355 cdb->READ_CD.StartingLBA[1] = (UCHAR) ((startingSector >> 16));
7356 cdb->READ_CD.StartingLBA[0] = (UCHAR) ((startingSector >> 24));
7357
7358 ScratchBuffer_SendSrb(DeviceExtension, TRUE, NULL);
7359
7360 if ((DeviceExtension->ScratchContext.ScratchSrb->SrbStatus == SRB_STATUS_ABORTED) &&
7361 (DeviceExtension->ScratchContext.ScratchSrb->InternalStatus == STATUS_CANCELLED))
7362 {
7363 shouldRetry = FALSE;
7365 }
7366 else
7367 {
7368 shouldRetry = RequestSenseInfoInterpretForScratchBuffer(DeviceExtension,
7369 timesAlreadyRetried,
7370 &status,
7371 &retryIn100nsUnits);
7372 if (shouldRetry)
7373 {
7375 t.QuadPart = -retryIn100nsUnits;
7376 timesAlreadyRetried++;
7378 // keep items clean
7379 ScratchBuffer_ResetItems(DeviceExtension, FALSE);
7380 }
7381 }
7382 }
7383
7384 if (NT_SUCCESS(status))
7385 {
7387 }
7388
7389 ScratchBuffer_EndUse(DeviceExtension);
7390 }
7391
7392 return status;
7393}
7394
7397DeviceHandlePlayAudioMsf(
7398 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7399 _In_ WDFREQUEST Request,
7401 _Out_ size_t * DataLength
7402 )
7403/*++
7404
7405Routine Description:
7406
7407 Handle request of IOCTL_CDROM_PLAY_AUDIO_MSF
7408
7409Arguments:
7410
7411 DeviceExtension - device context
7412 Request - request to be handled
7413 RequestParameters - request parameter
7414 DataLength - transferred data length
7415
7416Return Value:
7417
7418 NTSTATUS
7419
7420--*/
7421{
7423 PCDROM_PLAY_AUDIO_MSF inputBuffer = NULL;
7424
7425 PAGED_CODE ();
7426
7427 *DataLength = 0;
7428
7429 status = WdfRequestRetrieveInputBuffer(Request,
7431 (PVOID*)&inputBuffer,
7432 NULL);
7433
7434
7435 if (NT_SUCCESS(status))
7436 {
7437 ULONG transferSize = 0;
7438 CDB cdb;
7439
7440 ScratchBuffer_BeginUse(DeviceExtension);
7441
7442 RtlZeroMemory(&cdb, sizeof(CDB));
7443 // Set up the CDB
7444 cdb.PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF;
7445
7446 cdb.PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM;
7447 cdb.PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS;
7448 cdb.PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF;
7449
7450 cdb.PLAY_AUDIO_MSF.EndingM = inputBuffer->EndingM;
7451 cdb.PLAY_AUDIO_MSF.EndingS = inputBuffer->EndingS;
7452 cdb.PLAY_AUDIO_MSF.EndingF = inputBuffer->EndingF;
7453
7454 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 10);
7455
7456 if (NT_SUCCESS(status))
7457 {
7458 PLAY_ACTIVE(DeviceExtension) = TRUE;
7459 *DataLength = 0;
7460 }
7461
7462 // nothing to do after the command finishes.
7463 ScratchBuffer_EndUse(DeviceExtension);
7464 }
7465
7466 return status;
7467}
7468
7471DeviceHandleReadQChannel(
7472 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7473 _In_ WDFREQUEST Request,
7475 _Out_ size_t * DataLength
7476 )
7477/*++
7478
7479Routine Description:
7480
7481 Handle request of IOCTL_CDROM_READ_Q_CHANNEL
7482
7483Arguments:
7484
7485 DeviceExtension - device context
7486 Request - request to be handled
7487 RequestParameters - request parameter
7488 DataLength - transferred data length
7489
7490Return Value:
7491
7492 NTSTATUS
7493
7494--*/
7495{
7497 PVOID inputBuffer = NULL;
7498 PVOID outputBuffer = NULL;
7499
7500 PAGED_CODE ();
7501
7502 *DataLength = 0;
7503
7504 status = WdfRequestRetrieveInputBuffer(Request,
7506 &inputBuffer,
7507 NULL);
7508
7509 if (NT_SUCCESS(status))
7510 {
7511 status = WdfRequestRetrieveOutputBuffer(Request,
7512 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
7513 &outputBuffer,
7514 NULL);
7515 }
7516
7517 if (NT_SUCCESS(status))
7518 {
7519 status = ReadQChannel(DeviceExtension,
7520 Request,
7521 inputBuffer,
7523 outputBuffer,
7524 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
7525 DataLength);
7526 }
7527
7528 return status;
7529}
7530
7533ReadQChannel(
7534 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7535 _In_opt_ WDFREQUEST OriginalRequest,
7537 _In_ size_t InputBufferLength,
7539 _In_ size_t OutputBufferLength,
7540 _Out_ size_t * DataLength
7541 )
7542/*++
7543
7544Routine Description:
7545
7546 base function to handle request of IOCTL_CDROM_READ_Q_CHANNEL
7547
7548Arguments:
7549
7550 DeviceExtension - device context
7551 OriginalRequest - original request to be handled
7552 InputBuffer - input buffer
7553 InputBufferLength - length of input buffer
7554 OutputBuffer - output buffer
7555 OutputBufferLength - length of output buffer
7556
7557Return Value:
7558
7559 NTSTATUS
7560 DataLength - returned data length
7561
7562--*/
7563{
7565 ULONG transferByteCount = 0;
7566 CDB cdb;
7569
7570 PAGED_CODE ();
7571
7573
7574 *DataLength = 0;
7575
7576 // Set size of channel data -- however, this is dependent on
7577 // what information we are requesting (which Format)
7578 switch( inputBuffer->Format )
7579 {
7581 transferByteCount = sizeof(SUB_Q_CURRENT_POSITION);
7582 break;
7583
7585 transferByteCount = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER);
7586 break;
7587
7589 transferByteCount = sizeof(SUB_Q_TRACK_ISRC);
7590 break;
7591 }
7592
7593 ScratchBuffer_BeginUse(DeviceExtension);
7594
7595 RtlZeroMemory(&cdb, sizeof(CDB));
7596 // Set up the CDB
7597 // Always logical unit 0, but only use MSF addressing
7598 // for IOCTL_CDROM_CURRENT_POSITION
7599 if (inputBuffer->Format==IOCTL_CDROM_CURRENT_POSITION)
7600 {
7601 cdb.SUBCHANNEL.Msf = CDB_USE_MSF;
7602 }
7603
7604 // Return subchannel data
7606
7607 // Specify format of informatin to return
7608 cdb.SUBCHANNEL.Format = inputBuffer->Format;
7609
7610 // Specify which track to access (only used by Track ISRC reads)
7611 if (inputBuffer->Format==IOCTL_CDROM_TRACK_ISRC)
7612 {
7613 cdb.SUBCHANNEL.TrackNumber = inputBuffer->Track;
7614 }
7615
7616 cdb.SUBCHANNEL.AllocationLength[0] = (UCHAR) (transferByteCount >> 8);
7617 cdb.SUBCHANNEL.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF);
7618 cdb.SUBCHANNEL.OperationCode = SCSIOP_READ_SUB_CHANNEL;
7619
7620 status = ScratchBuffer_ExecuteCdb(DeviceExtension, OriginalRequest, transferByteCount, TRUE, &cdb, 10);
7621
7622 if (NT_SUCCESS(status))
7623 {
7624 PSUB_Q_CHANNEL_DATA subQPtr = DeviceExtension->ScratchContext.ScratchSrb->DataBuffer;
7625
7626#if DBG
7627 switch( inputBuffer->Format )
7628 {
7630 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Audio Status is %u\n", subQPtr->CurrentPosition.Header.AudioStatus ));
7631 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: ADR = 0x%x\n", subQPtr->CurrentPosition.ADR ));
7632 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Control = 0x%x\n", subQPtr->CurrentPosition.Control ));
7633 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Track = %u\n", subQPtr->CurrentPosition.TrackNumber ));
7634 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Index = %u\n", subQPtr->CurrentPosition.IndexNumber ));
7635 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Absolute Address = %x\n", *((PULONG)subQPtr->CurrentPosition.AbsoluteAddress) ));
7636 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Relative Address = %x\n", *((PULONG)subQPtr->CurrentPosition.TrackRelativeAddress) ));
7637 break;
7638
7640 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Audio Status is %u\n", subQPtr->MediaCatalog.Header.AudioStatus ));
7641 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Mcval is %u\n", subQPtr->MediaCatalog.Mcval ));
7642 break;
7643
7645 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Audio Status is %u\n", subQPtr->TrackIsrc.Header.AudioStatus ));
7646 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,"ReadQChannel: Tcval is %u\n", subQPtr->TrackIsrc.Tcval ));
7647 break;
7648 }
7649#endif
7650
7651 // Update the play active status.
7653 {
7654 PLAY_ACTIVE(DeviceExtension) = TRUE;
7655 }
7656 else
7657 {
7658 PLAY_ACTIVE(DeviceExtension) = FALSE;
7659 }
7660
7661 // Check if output buffer is large enough to contain
7662 // the data.
7663 if (OutputBufferLength < DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength)
7664 {
7665 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength = (ULONG)OutputBufferLength;
7666 }
7667
7668 // Copy our buffer into users.
7669 RtlMoveMemory(userChannelData,
7670 subQPtr,
7671 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength);
7672
7673 *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength;
7674 }
7675
7676 // nothing to do after the command finishes.
7677 ScratchBuffer_EndUse(DeviceExtension);
7678
7679 return status;
7680}
7681
7682
7685DeviceHandlePauseAudio(
7686 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7687 _In_ WDFREQUEST Request,
7688 _Out_ size_t * DataLength
7689 )
7690/*++
7691
7692Routine Description:
7693
7694 Handle request of IOCTL_CDROM_PAUSE_AUDIO
7695
7696Arguments:
7697
7698 DeviceExtension - device context
7699 Request - request to be handled
7700 DataLength - transferred data length
7701
7702Return Value:
7703
7704 NTSTATUS
7705
7706--*/
7707{
7709
7710 PAGED_CODE ();
7711
7712 *DataLength = 0;
7713
7714 if (NT_SUCCESS(status))
7715 {
7716 ULONG transferSize = 0;
7717 CDB cdb;
7718
7719 ScratchBuffer_BeginUse(DeviceExtension);
7720
7721 RtlZeroMemory(&cdb, sizeof(CDB));
7722 // Set up the CDB
7723 cdb.PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
7724 cdb.PAUSE_RESUME.Action = CDB_AUDIO_PAUSE;
7725
7726 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 10);
7727
7728 if (NT_SUCCESS(status))
7729 {
7730 PLAY_ACTIVE(DeviceExtension) = FALSE;
7731 *DataLength = 0;
7732 }
7733
7734 // nothing to do after the command finishes.
7735 ScratchBuffer_EndUse(DeviceExtension);
7736 }
7737
7738 return status;
7739}
7740
7743DeviceHandleResumeAudio(
7744 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7745 _In_ WDFREQUEST Request,
7746 _Out_ size_t * DataLength
7747 )
7748/*++
7749
7750Routine Description:
7751
7752 Handle request of IOCTL_CDROM_RESUME_AUDIO
7753
7754Arguments:
7755
7756 DeviceExtension - device context
7757 Request - request to be handled
7758 DataLength - transferred data length
7759
7760Return Value:
7761
7762 NTSTATUS
7763
7764--*/
7765{
7767
7768 PAGED_CODE ();
7769
7770 *DataLength = 0;
7771
7772 if (NT_SUCCESS(status))
7773 {
7774 ULONG transferSize = 0;
7775 CDB cdb;
7776
7777 ScratchBuffer_BeginUse(DeviceExtension);
7778
7779 RtlZeroMemory(&cdb, sizeof(CDB));
7780 // Set up the CDB
7781 cdb.PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
7782 cdb.PAUSE_RESUME.Action = CDB_AUDIO_RESUME;
7783
7784 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 10);
7785
7786 if (NT_SUCCESS(status))
7787 {
7788 PLAY_ACTIVE(DeviceExtension) = TRUE; //not in original code. But we should set it.
7789 *DataLength = 0;
7790 }
7791
7792 // nothing to do after the command finishes.
7793 ScratchBuffer_EndUse(DeviceExtension);
7794 }
7795
7796 return status;
7797}
7798
7801DeviceHandleSeekAudioMsf(
7802 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7803 _In_ WDFREQUEST Request,
7805 _Out_ size_t * DataLength
7806 )
7807/*++
7808
7809Routine Description:
7810
7811 Handle request of IOCTL_CDROM_SEEK_AUDIO_MSF
7812
7813Arguments:
7814
7815 DeviceExtension - device context
7816 Request - request to be handled
7817 RequestParameters - request parameter
7818 DataLength - transferred data length
7819
7820Return Value:
7821
7822 NTSTATUS
7823
7824--*/
7825{
7827 PCDROM_SEEK_AUDIO_MSF inputBuffer = NULL;
7828
7829 PAGED_CODE ();
7830
7831 *DataLength = 0;
7832
7833 status = WdfRequestRetrieveInputBuffer(Request,
7835 (PVOID*)&inputBuffer,
7836 NULL);
7837
7838 if (NT_SUCCESS(status))
7839 {
7840 ULONG transferSize = 0;
7841 CDB cdb;
7842 ULONG logicalBlockAddress;
7843
7844 logicalBlockAddress = MSF_TO_LBA(inputBuffer->M, inputBuffer->S, inputBuffer->F);
7845
7846 ScratchBuffer_BeginUse(DeviceExtension);
7847
7848 RtlZeroMemory(&cdb, sizeof(CDB));
7849 // Set up the CDB
7850 cdb.SEEK.OperationCode = SCSIOP_SEEK;
7851 cdb.SEEK.LogicalBlockAddress[0] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
7852 cdb.SEEK.LogicalBlockAddress[1] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
7853 cdb.SEEK.LogicalBlockAddress[2] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
7854 cdb.SEEK.LogicalBlockAddress[3] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;
7855
7856 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 10);
7857
7858 if (NT_SUCCESS(status))
7859 {
7860 *DataLength = 0;
7861 }
7862
7863 // nothing to do after the command finishes.
7864
7865 ScratchBuffer_EndUse(DeviceExtension);
7866 }
7867
7868 return status;
7869}
7870
7873DeviceHandleStopAudio(
7874 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7875 _In_ WDFREQUEST Request,
7876 _Out_ size_t * DataLength
7877 )
7878{
7880
7881 PAGED_CODE ();
7882
7883 *DataLength = 0;
7884
7885 if (NT_SUCCESS(status))
7886 {
7887 ULONG transferSize = 0;
7888 CDB cdb;
7889
7890 ScratchBuffer_BeginUse(DeviceExtension);
7891
7892 RtlZeroMemory(&cdb, sizeof(CDB));
7893 // Set up the CDB
7894 cdb.START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
7895 cdb.START_STOP.Immediate = 1;
7896 cdb.START_STOP.Start = 0;
7897 cdb.START_STOP.LoadEject = 0;
7898
7899 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 6);
7900
7901 if (NT_SUCCESS(status))
7902 {
7903 PLAY_ACTIVE(DeviceExtension) = FALSE;
7904 *DataLength = 0;
7905 }
7906
7907 // nothing to do after the command finishes.
7908 ScratchBuffer_EndUse(DeviceExtension);
7909 }
7910
7911 return status;
7912}
7913
7916DeviceHandleGetSetVolume(
7917 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
7918 _In_ WDFREQUEST Request,
7920 _Out_ size_t * DataLength
7921 )
7922/*++
7923
7924Routine Description:
7925
7926 Handle request of IOCTL_CDROM_GET_VOLUME
7927 IOCTL_CDROM_SET_VOLUME
7928
7929Arguments:
7930
7931 DeviceExtension - device context
7932 Request - request to be handled
7933 RequestParameters - request parameter
7934 DataLength - transferred data length
7935
7936Return Value:
7937
7938 NTSTATUS
7939
7940--*/
7941{
7943
7944 PAGED_CODE ();
7945
7946 *DataLength = 0;
7947
7948 if (NT_SUCCESS(status))
7949 {
7950 ULONG transferSize = MODE_DATA_SIZE;
7951 CDB cdb;
7952
7953 ScratchBuffer_BeginUse(DeviceExtension);
7954
7955 RtlZeroMemory(&cdb, sizeof(CDB));
7956 // Set up the CDB
7957 cdb.MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
7959 cdb.MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8);
7960 cdb.MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF);
7961
7962 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, TRUE, &cdb, 10);
7963
7964 if (NT_SUCCESS(status))
7965 {
7967 {
7968 PAUDIO_OUTPUT audioOutput;
7969 PVOLUME_CONTROL volumeControl;
7970 ULONG bytesTransferred;
7971
7972 status = WdfRequestRetrieveOutputBuffer(Request,
7973 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
7974 (PVOID*)&volumeControl,
7975 NULL);
7976 if (NT_SUCCESS(status))
7977 {
7978 audioOutput = ModeSenseFindSpecificPage((PCHAR)DeviceExtension->ScratchContext.ScratchSrb->DataBuffer,
7979 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength,
7981 FALSE);
7982
7983 // Verify the page is as big as expected.
7984 bytesTransferred = (ULONG)((PCHAR)audioOutput - (PCHAR)DeviceExtension->ScratchContext.ScratchSrb->DataBuffer) +
7985 sizeof(AUDIO_OUTPUT);
7986
7987 if ((audioOutput != NULL) &&
7988 (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength >= bytesTransferred))
7989 {
7990 ULONG i;
7991 for (i=0; i<4; i++)
7992 {
7993 volumeControl->PortVolume[i] = audioOutput->PortOutput[i].Volume;
7994 }
7995
7996 // Set bytes transferred in IRP.
7997 *DataLength = sizeof(VOLUME_CONTROL);
7998
7999 }
8000 else
8001 {
8002 *DataLength = 0;
8004 }
8005 }
8006 }
8007 else //IOCTL_CDROM_SET_VOLUME
8008 {
8009 PAUDIO_OUTPUT audioInput = NULL;
8010 PAUDIO_OUTPUT audioOutput = NULL;
8011 PVOLUME_CONTROL volumeControl = NULL;
8012 ULONG i,bytesTransferred,headerLength;
8013
8014 status = WdfRequestRetrieveInputBuffer(Request,
8016 (PVOID*)&volumeControl,
8017 NULL);
8018
8019 if (NT_SUCCESS(status))
8020 {
8021 audioInput = ModeSenseFindSpecificPage((PCHAR)DeviceExtension->ScratchContext.ScratchSrb->DataBuffer,
8022 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength,
8024 FALSE);
8025
8026 // Check to make sure the mode sense data is valid before we go on
8027 if(audioInput == NULL)
8028 {
8029 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
8030 "Mode Sense Page %d not found\n",
8032
8033 *DataLength = 0;
8035 }
8036 }
8037
8038 if (NT_SUCCESS(status))
8039 {
8040 // keep items clean; clear the command history
8041 ScratchBuffer_ResetItems(DeviceExtension, TRUE);
8042
8043 headerLength = sizeof(MODE_PARAMETER_HEADER10);
8044 bytesTransferred = sizeof(AUDIO_OUTPUT) + headerLength;
8045
8046 // use the scratch buffer as input buffer.
8047 // the content of this buffer will not be changed in the following loop.
8048 audioOutput = (PAUDIO_OUTPUT)((PCHAR)DeviceExtension->ScratchContext.ScratchBuffer + headerLength);
8049
8050 for (i=0; i<4; i++)
8051 {
8052 audioOutput->PortOutput[i].Volume = volumeControl->PortVolume[i];
8053 audioOutput->PortOutput[i].ChannelSelection = audioInput->PortOutput[i].ChannelSelection;
8054 }
8055
8056 audioOutput->CodePage = CDROM_AUDIO_CONTROL_PAGE;
8057 audioOutput->ParameterLength = sizeof(AUDIO_OUTPUT) - 2;
8058 audioOutput->Immediate = MODE_SELECT_IMMEDIATE;
8059
8060 RtlZeroMemory(&cdb, sizeof(CDB));
8061 // Set up the CDB
8062 cdb.MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
8063 cdb.MODE_SELECT10.ParameterListLength[0] = (UCHAR) (bytesTransferred >> 8);
8064 cdb.MODE_SELECT10.ParameterListLength[1] = (UCHAR) (bytesTransferred & 0xFF);
8065 cdb.MODE_SELECT10.PFBit = 1;
8066
8067 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, bytesTransferred, FALSE, &cdb, 10);
8068
8069 }
8070 *DataLength = 0;
8071 }
8072 }
8073
8074 // nothing to do after the command finishes.
8075 ScratchBuffer_EndUse(DeviceExtension);
8076 }
8077
8078 return status;
8079}
8080
8083DeviceHandleReadDvdStructure(
8084 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
8085 _In_ WDFREQUEST Request,
8087 _Out_ size_t * DataLength
8088 )
8089/*++
8090
8091Routine Description:
8092
8093 Handle request of IOCTL_DVD_READ_STRUCTURE
8094
8095Arguments:
8096
8097 DeviceExtension - device context
8098 Request - request to be handled
8099 RequestParameters - request parameter
8100 DataLength - transferred data length
8101
8102Return Value:
8103
8104 NTSTATUS
8105
8106--*/
8107{
8109 PVOID inputBuffer = NULL;
8110 PVOID outputBuffer = NULL;
8111
8112 PAGED_CODE ();
8113
8114 *DataLength = 0;
8115
8116 status = WdfRequestRetrieveInputBuffer(Request,
8118 &inputBuffer,
8119 NULL);
8120
8121 if (NT_SUCCESS(status))
8122 {
8123 status = WdfRequestRetrieveOutputBuffer(Request,
8124 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
8125 &outputBuffer,
8126 NULL);
8127 }
8128
8129 if (NT_SUCCESS(status))
8130 {
8131 status = ReadDvdStructure(DeviceExtension,
8132 Request,
8133 inputBuffer,
8135 outputBuffer,
8136 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
8137 DataLength);
8138 }
8139
8140 return status;
8141}
8142
8145ReadDvdStructure(
8146 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
8147 _In_opt_ WDFREQUEST OriginalRequest,
8149 _In_ size_t InputBufferLength,
8151 _In_ size_t OutputBufferLength,
8152 _Out_ size_t * DataLength
8153 )
8154/*++
8155
8156Routine Description:
8157
8158 base function to handle request of IOCTL_DVD_START_SESSION
8159 IOCTL_DVD_READ_KEY
8160
8161Arguments:
8162
8163 DeviceExtension - device context
8164 OriginalRequest - original request to be handled
8165 InputBuffer - input buffer
8166 InputBufferLength - length of input buffer
8167 OutputBuffer - output buffer
8168 OutputBufferLength - length of output buffer
8169
8170Return Value:
8171
8172 NTSTATUS
8173 DataLength - returned data length
8174
8175--*/
8176{
8180 CDB cdb;
8181
8183 ULONG blockNumber;
8184 PFOUR_BYTE fourByte;
8185
8186 PAGED_CODE ();
8187
8189
8190 if (DeviceExtension->DeviceAdditionalData.DriveDeviceType != FILE_DEVICE_DVD)
8191 {
8192 *DataLength = 0;
8194 }
8195
8197 blockNumber = (ULONG)(request->BlockByteOffset.QuadPart >> DeviceExtension->SectorShift);
8198 fourByte = (PFOUR_BYTE)&blockNumber;
8199
8200 ScratchBuffer_BeginUse(DeviceExtension);
8201
8202 RtlZeroMemory(&cdb, sizeof(CDB));
8203 // Set up the CDB
8205 cdb.READ_DVD_STRUCTURE.RMDBlockNumber[0] = fourByte->Byte3;
8206 cdb.READ_DVD_STRUCTURE.RMDBlockNumber[1] = fourByte->Byte2;
8207 cdb.READ_DVD_STRUCTURE.RMDBlockNumber[2] = fourByte->Byte1;
8208 cdb.READ_DVD_STRUCTURE.RMDBlockNumber[3] = fourByte->Byte0;
8209 cdb.READ_DVD_STRUCTURE.LayerNumber = request->LayerNumber;
8210 cdb.READ_DVD_STRUCTURE.Format = (UCHAR)request->Format;
8211
8212#if DBG
8213 {
8214 if ((UCHAR)request->Format > DvdMaxDescriptor)
8215 {
8216 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
8217 "READ_DVD_STRUCTURE format %x = %s (%x bytes)\n",
8218 (UCHAR)request->Format,
8219 READ_DVD_STRUCTURE_FORMAT_STRINGS[DvdMaxDescriptor],
8221 ));
8222 }
8223 else
8224 {
8225 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
8226 "READ_DVD_STRUCTURE format %x = %s (%x bytes)\n",
8227 (UCHAR)request->Format,
8228 READ_DVD_STRUCTURE_FORMAT_STRINGS[(UCHAR)request->Format],
8230 ));
8231 }
8232 }
8233#endif // DBG
8234
8235 if (request->Format == DvdDiskKeyDescriptor)
8236 {
8237 cdb.READ_DVD_STRUCTURE.AGID = (UCHAR)request->SessionId;
8238 }
8239
8240 cdb.READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataLength >> 8);
8241 cdb.READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataLength & 0xff);
8242
8243 status = ScratchBuffer_ExecuteCdb(DeviceExtension, OriginalRequest, dataLength, TRUE, &cdb, 12);
8244
8245 if (NT_SUCCESS(status))
8246 {
8247 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
8248 "DvdDCCompletion - READ_STRUCTURE: descriptor format of %d\n", request->Format));
8249
8251 DeviceExtension->ScratchContext.ScratchSrb->DataBuffer,
8252 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength);
8253
8254 // Cook the data. There are a number of fields that really
8255 // should be byte-swapped for the caller.
8256 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
8257 "DvdDCCompletion - READ_STRUCTURE:\n"
8258 "\tHeader at %p\n"
8259 "\tDvdDCCompletion - READ_STRUCTURE: data at %p\n"
8260 "\tDataBuffer was at %p\n"
8261 "\tDataTransferLength was %lx\n",
8262 header,
8263 header->Data,
8264 DeviceExtension->ScratchContext.ScratchSrb->DataBuffer,
8265 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength));
8266
8267 // First the fields in the header
8268 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "READ_STRUCTURE: header->Length %lx -> ",
8269 header->Length));
8270
8271 REVERSE_SHORT(&header->Length);
8272
8273 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "%lx\n", header->Length));
8274
8275 // Now the fields in the descriptor
8276 if(request->Format == DvdPhysicalDescriptor)
8277 {
8278 ULONG tempLength = (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength > (ULONG)FIELD_OFFSET(DVD_DESCRIPTOR_HEADER, Data))
8279 ? (DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength - FIELD_OFFSET(DVD_DESCRIPTOR_HEADER, Data))
8280 : 0;
8281
8283
8284 // Make sure the buffer size is good for swapping bytes.
8285 if (tempLength >= RTL_SIZEOF_THROUGH_FIELD(DVD_LAYER_DESCRIPTOR, StartingDataSector))
8286 {
8287 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "READ_STRUCTURE: StartingDataSector %lx -> ",
8288 layer->StartingDataSector));
8289 REVERSE_LONG(&(layer->StartingDataSector));
8290 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "%lx\n", layer->StartingDataSector));
8291 }
8292 if (tempLength >= RTL_SIZEOF_THROUGH_FIELD(DVD_LAYER_DESCRIPTOR, EndDataSector))
8293 {
8294 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "READ_STRUCTURE: EndDataSector %lx -> ",
8295 layer->EndDataSector));
8296 REVERSE_LONG(&(layer->EndDataSector));
8297 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "%lx\n", layer->EndDataSector));
8298 }
8299 if (tempLength >= RTL_SIZEOF_THROUGH_FIELD(DVD_LAYER_DESCRIPTOR, EndLayerZeroSector))
8300 {
8301 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "READ_STRUCTURE: EndLayerZeroSector %lx -> ",
8302 layer->EndLayerZeroSector));
8303 REVERSE_LONG(&(layer->EndLayerZeroSector));
8304 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "%lx\n", layer->EndLayerZeroSector));
8305 }
8306 }
8307
8308 if (!NT_SUCCESS(status))
8309 {
8310 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "Status is %lx\n", status));
8311 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DvdDeviceControlCompletion - "
8312 "IOCTL_DVD_READ_STRUCTURE: data transfer length of %d\n",
8313 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength));
8314 }
8315
8316 *DataLength = DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength;
8317 }
8318
8319 ScratchBuffer_EndUse(DeviceExtension);
8320
8321 return status;
8322}
8323
8326DeviceHandleDvdEndSession(
8327 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
8328 _In_ WDFREQUEST Request,
8330 _Out_ size_t * DataLength
8331 )
8332/*++
8333
8334Routine Description:
8335
8336 Handle request of IOCTL_DVD_END_SESSION
8337
8338Arguments:
8339
8340 DeviceExtension - device context
8341 Request - request to be handled
8342 RequestParameters - request parameter
8343 DataLength - transferred data length
8344
8345Return Value:
8346
8347 NTSTATUS
8348
8349--*/
8350{
8352 PDVD_SESSION_ID sessionId = NULL;
8353
8354 PAGED_CODE ();
8355
8356 *DataLength = 0;
8357
8358 status = WdfRequestRetrieveInputBuffer(Request,
8360 (PVOID*)&sessionId,
8361 NULL);
8362
8363 if (NT_SUCCESS(status))
8364 {
8365 ULONG transferSize = 0;
8366 CDB cdb;
8367 DVD_SESSION_ID currentSession = 0;
8368 DVD_SESSION_ID limitSession = 0;
8369
8370 if(*sessionId == DVD_END_ALL_SESSIONS)
8371 {
8372 currentSession = 0;
8373 limitSession = MAX_COPY_PROTECT_AGID - 1;
8374 }
8375 else
8376 {
8377 currentSession = *sessionId;
8378 limitSession = *sessionId;
8379 }
8380
8381 ScratchBuffer_BeginUse(DeviceExtension);
8382
8383 do
8384 {
8385 RtlZeroMemory(&cdb, sizeof(CDB));
8386 // Set up the CDB
8387 cdb.SEND_KEY.OperationCode = SCSIOP_SEND_KEY;
8388 cdb.SEND_KEY.AGID = (UCHAR)(currentSession);
8389 cdb.SEND_KEY.KeyFormat = DVD_INVALIDATE_AGID;
8390
8391 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 12);
8392
8393 currentSession++;
8394 } while ((currentSession <= limitSession) && NT_SUCCESS(status));
8395
8396 // nothing to do after the command finishes.
8397 ScratchBuffer_EndUse(DeviceExtension);
8398 }
8399
8400 return status;
8401}
8402
8405DeviceHandleDvdStartSessionReadKey(
8406 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
8407 _In_ WDFREQUEST Request,
8409 _Out_ size_t * DataLength
8410 )
8411/*++
8412
8413Routine Description:
8414
8415 Handle request of IOCTL_DVD_START_SESSION
8416 IOCTL_DVD_READ_KEY
8417
8418Arguments:
8419
8420 DeviceExtension - device context
8421 Request - request to be handled
8422 RequestParameters - request parameter
8423 DataLength - transferred data length
8424
8425Return Value:
8426
8427 NTSTATUS
8428
8429--*/
8430{
8432 PDVD_COPY_PROTECT_KEY keyParameters = NULL;
8433 PVOID outputBuffer = NULL;
8434
8435 PAGED_CODE ();
8436
8437 if (NT_SUCCESS(status))
8438 {
8439 status = WdfRequestRetrieveOutputBuffer(Request,
8440 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
8441 &outputBuffer,
8442 NULL);
8443 }
8444
8446 {
8447 status = WdfRequestRetrieveInputBuffer(Request,
8449 (PVOID*)&keyParameters,
8450 NULL);
8451 }
8452
8453 if (NT_SUCCESS(status))
8454 {
8455 status = DvdStartSessionReadKey(DeviceExtension,
8457 Request,
8458 keyParameters,
8460 outputBuffer,
8461 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
8462 DataLength);
8463 }
8464
8465 return status;
8466}
8467
8470DvdStartSessionReadKey(
8471 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
8473 _In_opt_ WDFREQUEST OriginalRequest,
8475 _In_ size_t InputBufferLength,
8477 _In_ size_t OutputBufferLength,
8478 _Out_ size_t * DataLength
8479 )
8480/*++
8481
8482Routine Description:
8483
8484 base function to handle request of IOCTL_DVD_START_SESSION
8485 IOCTL_DVD_READ_KEY
8486
8487Arguments:
8488
8489 DeviceExtension - device context
8490 IoControlCode - IOCTL_DVD_READ_KEY or IOCTL_DVD_START_SESSION
8491 OriginalRequest - original request to be handled
8492 InputBuffer - input buffer
8493 InputBufferLength - length of input buffer
8494 OutputBuffer - output buffer
8495 OutputBufferLength - length of output buffer
8496
8497Return Value:
8498
8499 NTSTATUS
8500 DataLength - returned data length
8501
8502--*/
8503{
8505 ULONG keyLength = 0;
8506 ULONG result = 0;
8507 ULONG allocationLength;
8508 PFOUR_BYTE fourByte;
8510
8511 PAGED_CODE ();
8512
8514
8515 *DataLength = 0;
8516
8517 fourByte = (PFOUR_BYTE)&allocationLength;
8518
8520 {
8521 if (keyParameters == NULL)
8522 {
8524 }
8525
8526 // First of all, initialize the DVD region of the drive, if it has not been set yet
8527 if (NT_SUCCESS(status) &&
8528 (keyParameters->KeyType == DvdGetRpcKey) &&
8529 DeviceExtension->DeviceAdditionalData.Mmc.IsCssDvd)
8530 {
8531 DevicePickDvdRegion(DeviceExtension->Device);
8532 }
8533
8534 if (NT_SUCCESS(status) &&
8535 (keyParameters->KeyType == DvdDiskKey))
8536 {
8537 // Special case - need to use READ DVD STRUCTURE command to get the disk key.
8538 PDVD_COPY_PROTECT_KEY keyHeader = NULL;
8539 PDVD_READ_STRUCTURE readStructureRequest = (PDVD_READ_STRUCTURE)keyParameters;
8540
8541 // save the key header so we can restore the interesting parts later
8542 keyHeader = ExAllocatePoolWithTag(NonPagedPoolNx,
8543 sizeof(DVD_COPY_PROTECT_KEY),
8545
8546 if(keyHeader == NULL)
8547 {
8548 // Can't save the context so return an error
8549 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
8550 "DvdDeviceControl - READ_KEY: unable to allocate context\n"));
8552 }
8553
8554 if (NT_SUCCESS(status))
8555 {
8558
8559 // save input parameters
8560 RtlCopyMemory(keyHeader,
8562 sizeof(DVD_COPY_PROTECT_KEY));
8563
8564 readStructureRequest->Format = DvdDiskKeyDescriptor;
8565 readStructureRequest->BlockByteOffset.QuadPart = 0;
8566 readStructureRequest->LayerNumber = 0;
8567 readStructureRequest->SessionId = keyHeader->SessionId;
8568
8569 status = ReadDvdStructure(DeviceExtension,
8572 sizeof(DVD_READ_STRUCTURE),
8575 DataLength);
8576
8577 // fill the output buffer, it's not touched in DeviceHandleReadDvdStructure()
8578 // for this specific request type: DvdDiskKeyDescriptor
8579 if (NT_SUCCESS(status))
8580 {
8581 // Shift the data down to its new position.
8582 RtlMoveMemory(outputKey->KeyData,
8583 rawKey->Data,
8584 sizeof(DVD_DISK_KEY_DESCRIPTOR));
8585
8586 RtlCopyMemory(outputKey,
8587 keyHeader,
8588 sizeof(DVD_COPY_PROTECT_KEY));
8589
8590 outputKey->KeyLength = DVD_DISK_KEY_LENGTH;
8591
8593 }
8594 else
8595 {
8596 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
8597 "StartSessionReadKey Failed with status %x, %xI64 (%x) bytes\n",
8598 status,
8599 (unsigned int)*DataLength,
8600 ((rawKey->Length[0] << 16) | rawKey->Length[1]) ));
8601 }
8602
8603 FREE_POOL(keyHeader);
8604 }
8605
8606 // special process finished. return from here.
8607 return status;
8608 }
8609
8610 if (NT_SUCCESS(status))
8611 {
8612 status = RtlULongSub((ULONG)OutputBufferLength,
8613 (ULONG)sizeof(DVD_COPY_PROTECT_KEY), &result);
8614 }
8615
8616 if (NT_SUCCESS(status))
8617 {
8618 status = RtlULongAdd(result, sizeof(CDVD_KEY_HEADER), &keyLength);
8619 }
8620
8621 if (NT_SUCCESS(status))
8622 {
8623 //The data length field of REPORT KEY Command occupies two bytes
8624 keyLength = min(keyLength, MAXUSHORT);
8625 }
8626 }
8627 else //IOCTL_DVD_START_SESSION
8628 {
8629 keyParameters = NULL;
8630 keyLength = sizeof(CDVD_KEY_HEADER) + sizeof(CDVD_REPORT_AGID_DATA);
8632 }
8633
8634 if (NT_SUCCESS(status))
8635 {
8636 CDB cdb;
8637
8638 allocationLength = keyLength;
8639
8640 // Defensive coding. Prefix cannot recognize this usage.
8641 UNREFERENCED_PARAMETER(allocationLength);
8642
8643 ScratchBuffer_BeginUse(DeviceExtension);
8644
8645 RtlZeroMemory(&cdb, sizeof(CDB));
8646 // Set up the CDB
8647 cdb.REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY;
8648 cdb.REPORT_KEY.AllocationLength[0] = fourByte->Byte1;
8649 cdb.REPORT_KEY.AllocationLength[1] = fourByte->Byte0;
8650
8651 // set the specific parameters....
8653 {
8654 if(keyParameters->KeyType == DvdTitleKey)
8655 {
8656 ULONG logicalBlockAddress;
8657
8658 logicalBlockAddress = (ULONG)(keyParameters->Parameters.TitleOffset.QuadPart >>
8659 DeviceExtension->SectorShift);
8660
8661 fourByte = (PFOUR_BYTE)&(logicalBlockAddress);
8662
8663 cdb.REPORT_KEY.LogicalBlockAddress[0] = fourByte->Byte3;
8664 cdb.REPORT_KEY.LogicalBlockAddress[1] = fourByte->Byte2;
8665 cdb.REPORT_KEY.LogicalBlockAddress[2] = fourByte->Byte1;
8666 cdb.REPORT_KEY.LogicalBlockAddress[3] = fourByte->Byte0;
8667 }
8668
8669 cdb.REPORT_KEY.KeyFormat = (UCHAR)keyParameters->KeyType;
8670 cdb.REPORT_KEY.AGID = (UCHAR)keyParameters->SessionId;
8671 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
8672 "DvdStartSessionReadKey => sending irp %p (%s)\n",
8673 OriginalRequest, "READ_KEY"));
8674 }
8675 else
8676 {
8677 cdb.REPORT_KEY.KeyFormat = DVD_REPORT_AGID;
8678 cdb.REPORT_KEY.AGID = 0;
8679 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
8680 "DvdStartSessionReadKey => sending irp %p (%s)\n",
8681 OriginalRequest, "START_SESSION"));
8682 }
8683
8684 status = ScratchBuffer_ExecuteCdb(DeviceExtension, OriginalRequest, keyLength, TRUE, &cdb, 12);
8685
8686 if (NT_SUCCESS(status))
8687 {
8689 {
8690 NTSTATUS tempStatus;
8692 PCDVD_KEY_HEADER keyHeader = DeviceExtension->ScratchContext.ScratchSrb->DataBuffer;
8694 ULONG transferLength;
8695
8696 tempStatus = RtlULongSub(DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength,
8698 &transferLength);
8699
8700 dataLength = (keyHeader->DataLength[0] << 8) + keyHeader->DataLength[1];
8701
8702 if (NT_SUCCESS(tempStatus) && (dataLength >= 2))
8703 {
8704 // Adjust the data length to ignore the two reserved bytes in the
8705 // header.
8706 dataLength -= 2;
8707
8708 // take the minimum of the transferred length and the
8709 // length as specified in the header.
8710 if(dataLength < transferLength)
8711 {
8712 transferLength = dataLength;
8713 }
8714
8715 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
8716 "DvdDeviceControlCompletion: [%p] - READ_KEY with "
8717 "transfer length of (%d or %d) bytes\n",
8719 dataLength,
8720 DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength - 2));
8721
8722 // Copy the key data into the return buffer
8723 if(copyProtectKey->KeyType == DvdTitleKey)
8724 {
8725 RtlMoveMemory(copyProtectKey->KeyData,
8726 keyHeader->Data + 1,
8727 transferLength - 1);
8728
8729 copyProtectKey->KeyData[transferLength - 1] = 0;
8730
8731 // If this is a title key then we need to copy the CGMS flags
8732 // as well.
8733 copyProtectKey->KeyFlags = *(keyHeader->Data);
8734
8735 }
8736 else
8737 {
8738 RtlMoveMemory(copyProtectKey->KeyData,
8739 keyHeader->Data,
8740 transferLength);
8741 }
8742
8743 copyProtectKey->KeyLength = sizeof(DVD_COPY_PROTECT_KEY);
8744 copyProtectKey->KeyLength += transferLength;
8745
8746 *DataLength = copyProtectKey->KeyLength;
8747 }
8748 else
8749 {
8750 //There is no valid data from drive.
8751 //This may happen when Key Format = 0x3f that does not require data back from drive.
8753 *DataLength = 0;
8754 }
8755 }
8756 else
8757 {
8759 PCDVD_KEY_HEADER keyHeader = DeviceExtension->ScratchContext.ScratchSrb->DataBuffer;
8761
8762 *sessionId = keyData->AGID;
8763
8764 *DataLength = sizeof(DVD_SESSION_ID);
8765 }
8766 }
8767
8768 // nothing to do after the command finishes.
8769 ScratchBuffer_EndUse(DeviceExtension);
8770 }
8771
8772 return status;
8773}
8774
8775
8778DeviceHandleDvdSendKey(
8779 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
8780 _In_ WDFREQUEST Request,
8782 _Out_ size_t * DataLength
8783 )
8784/*++
8785
8786Routine Description:
8787
8788 Handle request of IOCTL_DVD_SEND_KEY
8789 IOCTL_DVD_SEND_KEY2
8790
8791Arguments:
8792
8793 DeviceExtension - device context
8794 Request - request to be handled
8795 RequestParameters - request parameter
8796 DataLength - transferred data length
8797
8798Return Value:
8799
8800 NTSTATUS
8801
8802--*/
8803{
8805 PVOID inputBuffer = NULL;
8806
8807 PAGED_CODE ();
8808
8809 *DataLength = 0;
8810
8811 status = WdfRequestRetrieveInputBuffer(Request,
8813 &inputBuffer,
8814 NULL);
8815
8816 if (NT_SUCCESS(status))
8817 {
8818 status = DvdSendKey(DeviceExtension,
8819 Request,
8820 inputBuffer,
8822 DataLength);
8823 }
8824
8825 return status;
8826}
8827
8830DvdSendKey(
8831 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
8832 _In_opt_ WDFREQUEST OriginalRequest,
8834 _In_ size_t InputBufferLength,
8835 _Out_ size_t * DataLength
8836 )
8837/*++
8838
8839Routine Description:
8840
8841 base function to handle request of IOCTL_DVD_SEND_KEY(2)
8842 NOTE: cdrom does not process this IOCTL if the input buffer length is bigger than Port transfer length.
8843
8844Arguments:
8845
8846 DeviceExtension - device context
8847 OriginalRequest - original request to be handled
8848 InputBuffer - input buffer
8849 InputBufferLength - length of input buffer
8850
8851Return Value:
8852
8853 NTSTATUS
8854 DataLength - returned data length
8855
8856--*/
8857{
8860
8861 ULONG keyLength = 0;
8862 ULONG result = 0;
8863 PFOUR_BYTE fourByte;
8864
8865 PAGED_CODE ();
8866
8868
8869 *DataLength = 0;
8870
8871 if (NT_SUCCESS(status))
8872 {
8873 if ((key->KeyLength < sizeof(DVD_COPY_PROTECT_KEY)) ||
8874 ((key->KeyLength - sizeof(DVD_COPY_PROTECT_KEY)) > DeviceExtension->ScratchContext.ScratchBufferSize))
8875 {
8878 }
8879 }
8880
8881 if (NT_SUCCESS(status))
8882 {
8883 status = RtlULongSub(key->KeyLength, sizeof(DVD_COPY_PROTECT_KEY), &result);
8884 }
8885
8886 if (NT_SUCCESS(status))
8887 {
8888 status = RtlULongAdd(result, sizeof(CDVD_KEY_HEADER), &keyLength);
8889 }
8890
8891 if (NT_SUCCESS(status))
8892 {
8893 keyLength = min(keyLength, DeviceExtension->ScratchContext.ScratchBufferSize);
8894
8895 if (keyLength < 2)
8896 {
8898 }
8899 }
8900
8901 if (NT_SUCCESS(status))
8902 {
8903 PCDVD_KEY_HEADER keyBuffer = NULL;
8904 CDB cdb;
8905
8906 ScratchBuffer_BeginUse(DeviceExtension);
8907
8908 // prepare the input buffer
8909 keyBuffer = (PCDVD_KEY_HEADER)DeviceExtension->ScratchContext.ScratchBuffer;
8910
8911 // keylength is decremented here by two because the
8912 // datalength does not include the header, which is two
8913 // bytes. keylength is immediately incremented later
8914 // by the same amount.
8915 keyLength -= 2;
8916 fourByte = (PFOUR_BYTE)&keyLength;
8917 keyBuffer->DataLength[0] = fourByte->Byte1;
8918 keyBuffer->DataLength[1] = fourByte->Byte0;
8919 keyLength += 2;
8920
8921 RtlMoveMemory(keyBuffer->Data,
8922 key->KeyData,
8923 key->KeyLength - sizeof(DVD_COPY_PROTECT_KEY));
8924
8925 RtlZeroMemory(&cdb, sizeof(CDB));
8926 // Set up the CDB
8927 cdb.REPORT_KEY.OperationCode = SCSIOP_SEND_KEY;
8928
8929 cdb.SEND_KEY.ParameterListLength[0] = fourByte->Byte1;
8930 cdb.SEND_KEY.ParameterListLength[1] = fourByte->Byte0;
8931 cdb.SEND_KEY.KeyFormat = (UCHAR)key->KeyType;
8932 cdb.SEND_KEY.AGID = (UCHAR)key->SessionId;
8933
8934 status = ScratchBuffer_ExecuteCdb(DeviceExtension, OriginalRequest, keyLength, FALSE, &cdb, 12);
8935
8936 // nothing to do after the command finishes.
8937 ScratchBuffer_EndUse(DeviceExtension);
8938 }
8939
8940 return status;
8941}
8942
8943
8946DeviceHandleSetReadAhead(
8947 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
8948 _In_ WDFREQUEST Request,
8950 _Out_ size_t * DataLength
8951 )
8952/*++
8953
8954Routine Description:
8955
8956 Handle request of IOCTL_STORAGE_SET_READ_AHEAD
8957
8958Arguments:
8959
8960 DeviceExtension - device context
8961 Request - request to be handled
8962 RequestParameters - request parameter
8963 DataLength - transferred data length
8964
8965Return Value:
8966
8967 NTSTATUS
8968
8969--*/
8970{
8972 PSTORAGE_SET_READ_AHEAD readAhead = NULL;
8973
8974 PAGED_CODE ();
8975
8976 *DataLength = 0;
8977
8978 status = WdfRequestRetrieveInputBuffer(Request,
8980 (PVOID*)&readAhead,
8981 NULL);
8982
8983 if (NT_SUCCESS(status))
8984 {
8985 ULONG transferSize = 0;
8986 CDB cdb;
8987 ULONG blockAddress;
8988 PFOUR_BYTE fourByte = (PFOUR_BYTE)&blockAddress;
8989
8990 ScratchBuffer_BeginUse(DeviceExtension);
8991
8992 RtlZeroMemory(&cdb, sizeof(CDB));
8993 // Set up the CDB
8994 cdb.SET_READ_AHEAD.OperationCode = SCSIOP_SET_READ_AHEAD;
8995
8996 blockAddress = (ULONG)(readAhead->TriggerAddress.QuadPart >>
8997 DeviceExtension->SectorShift);
8998
8999 // Defensive coding. Prefix cannot recognize this usage.
9000 UNREFERENCED_PARAMETER(blockAddress);
9001
9002 cdb.SET_READ_AHEAD.TriggerLBA[0] = fourByte->Byte3;
9003 cdb.SET_READ_AHEAD.TriggerLBA[1] = fourByte->Byte2;
9004 cdb.SET_READ_AHEAD.TriggerLBA[2] = fourByte->Byte1;
9005 cdb.SET_READ_AHEAD.TriggerLBA[3] = fourByte->Byte0;
9006
9007 blockAddress = (ULONG)(readAhead->TargetAddress.QuadPart >>
9008 DeviceExtension->SectorShift);
9009
9010 cdb.SET_READ_AHEAD.ReadAheadLBA[0] = fourByte->Byte3;
9011 cdb.SET_READ_AHEAD.ReadAheadLBA[1] = fourByte->Byte2;
9012 cdb.SET_READ_AHEAD.ReadAheadLBA[2] = fourByte->Byte1;
9013 cdb.SET_READ_AHEAD.ReadAheadLBA[3] = fourByte->Byte0;
9014
9015 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 12);
9016
9017 if (NT_SUCCESS(status))
9018 {
9019 *DataLength = 0;
9020 }
9021
9022 // nothing to do after the command finishes.
9023 ScratchBuffer_EndUse(DeviceExtension);
9024 }
9025
9026 return status;
9027}
9028
9031DeviceHandleSetSpeed(
9032 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
9033 _In_ WDFREQUEST Request,
9035 _Out_ size_t * DataLength
9036 )
9037/*++
9038
9039Routine Description:
9040
9041 Handle request of IOCTL_CDROM_SET_SPEED
9042
9043Arguments:
9044
9045 DeviceExtension - device context
9046 Request - request to be handled
9047 RequestParameters - request parameter
9048 DataLength - transferred data length
9049
9050Return Value:
9051
9052 NTSTATUS
9053
9054--*/
9055{
9057 PCDROM_DATA cdData = &(DeviceExtension->DeviceAdditionalData);
9058 PCDROM_SET_SPEED inputBuffer = NULL;
9059
9060 PAGED_CODE ();
9061
9062 *DataLength = 0;
9063
9064 status = WdfRequestRetrieveInputBuffer(Request,
9066 (PVOID*)&inputBuffer,
9067 NULL);
9068
9069 if (NT_SUCCESS(status))
9070 {
9071 ULONG transferSize = 0;
9072 CDB cdb;
9073 CDROM_SPEED_REQUEST requestType = inputBuffer->RequestType;
9074
9075 ScratchBuffer_BeginUse(DeviceExtension);
9076
9077 RtlZeroMemory(&cdb, sizeof(CDB));
9078 // Set up the CDB
9079 if (requestType == CdromSetSpeed)
9080 {
9081 PCDROM_SET_SPEED speed = inputBuffer;
9082
9083 cdb.SET_CD_SPEED.OperationCode = SCSIOP_SET_CD_SPEED;
9084 cdb.SET_CD_SPEED.RotationControl = speed->RotationControl;
9085 REVERSE_BYTES_SHORT(&cdb.SET_CD_SPEED.ReadSpeed, &speed->ReadSpeed);
9086 REVERSE_BYTES_SHORT(&cdb.SET_CD_SPEED.WriteSpeed, &speed->WriteSpeed);
9087 }
9088 else
9089 {
9091 PPERFORMANCE_DESCRIPTOR perfDescriptor;
9092
9093 transferSize = sizeof(PERFORMANCE_DESCRIPTOR);
9094
9095 perfDescriptor = DeviceExtension->ScratchContext.ScratchBuffer;
9096 RtlZeroMemory(perfDescriptor, transferSize);
9097
9098 perfDescriptor->RandomAccess = stream->RandomAccess;
9099 perfDescriptor->Exact = stream->SetExact;
9100 perfDescriptor->RestoreDefaults = stream->RestoreDefaults;
9101 perfDescriptor->WriteRotationControl = stream->RotationControl;
9102
9103 REVERSE_BYTES(&perfDescriptor->StartLba, &stream->StartLba);
9104 REVERSE_BYTES(&perfDescriptor->EndLba, &stream->EndLba);
9105 REVERSE_BYTES(&perfDescriptor->ReadSize, &stream->ReadSize);
9106 REVERSE_BYTES(&perfDescriptor->ReadTime, &stream->ReadTime);
9107 REVERSE_BYTES(&perfDescriptor->WriteSize, &stream->WriteSize);
9108 REVERSE_BYTES(&perfDescriptor->WriteTime, &stream->WriteTime);
9109
9110 cdb.SET_STREAMING.OperationCode = SCSIOP_SET_STREAMING;
9111 REVERSE_BYTES_SHORT(&cdb.SET_STREAMING.ParameterListLength, &transferSize);
9112
9113 // set value in extension by user inputs.
9114 cdData->RestoreDefaults = stream->Persistent ? FALSE : TRUE;
9115
9116 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DeviceHandleSetSpeed: Restore default speed on media change set to %s\n",
9117 cdData->RestoreDefaults ? "true" : "false"));
9118 }
9119
9120 status = ScratchBuffer_ExecuteCdb(DeviceExtension, Request, transferSize, FALSE, &cdb, 12);
9121
9122 if (NT_SUCCESS(status))
9123 {
9124 *DataLength = 0;
9125 }
9126
9127 // nothing to do after the command finishes.
9128 ScratchBuffer_EndUse(DeviceExtension);
9129 }
9130
9131 return status;
9132}
9133
9134
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
Type
Definition: Type.h:7
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
#define PARTITION_FAT32
Definition: disk.h:95
VOID RequestSetupMcnSyncIrp(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: autorun.c:2749
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
#define PLAY_ACTIVE(x)
Definition: cdrom.h:698
FORCEINLINE BOOLEAN ValidChar(UCHAR Ch)
Definition: cdrom.h:812
#define MODE_DATA_SIZE
Definition: cdrom.h:691
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG
Definition: cdrom.h:99
#define FORM2_MODE2_SECTOR
Definition: cdrom.h:710
BOOLEAN RequestSenseInfoInterpretForScratchBuffer(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2564
#define CDROM_TAG_PLAY_ACTIVE
Definition: cdrom.h:740
#define DVD_TAG_READ_KEY
Definition: cdrom.h:747
#define DEV_POWER_PROTECTED
Definition: cdrom.h:143
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN _In_opt_ WDFREQUEST OriginalRequest
Definition: cdrom.h:994
FORCEINLINE BOOLEAN IsVolumeMounted(_In_ PDEVICE_OBJECT DeviceObject)
Definition: cdrom.h:1514
#define MAXIMUM_RETRIES
Definition: cdrom.h:124
#define CDROM_TEST_UNIT_READY_TIMEOUT
Definition: cdrom.h:128
NTSTATUS RequestSend(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDFIOTARGET IoTarget, _In_ ULONG Flags, _Out_opt_ PBOOLEAN RequestSent)
Definition: common.c:3793
NTSTATUS RequestDuidGetDeviceIdProperty(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: common.c:2797
FORCEINLINE UCHAR RequestGetCurrentStackLocationFlags(_In_ WDFREQUEST Request)
Definition: cdrom.h:1554
#define EXCLUSIVE_OWNER(_CdData, _FileObject)
Definition: cdrom.h:789
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestDummyCompletionRoutine
Definition: cdrom.h:1608
#define MAX_COPY_PROTECT_AGID
Definition: cdrom.h:712
VOID RequestCompletion(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG_PTR Information)
Definition: common.c:3439
#define CD_DA_SECTOR
Definition: cdrom.h:706
#define CDROM_TAG_MODE_DATA
Definition: cdrom.h:737
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
NTSTATUS RequestDuidGetDeviceProperty(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: common.c:2888
#define EXCLUSIVE_MODE(_CdData)
Definition: cdrom.h:788
#define CDROM_TAG_SRB
Definition: cdrom.h:742
#define CDROM_GET_PERFORMANCE_TIMEOUT
Definition: cdrom.h:129
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define CDROM_TAG_STRINGS
Definition: cdrom.h:743
#define YELLOW_MODE2_SECTOR
Definition: cdrom.h:708
FORCEINLINE ULONG TimeOutValueGetCapValue(_In_ ULONG TimeOutValue, _In_ ULONG Times)
Definition: cdrom.h:1569
#define COOKED_SECTOR_SIZE
Definition: cdrom.h:694
#define FDO_HACK_NO_RESERVE6
Definition: cdromp.h:135
#define FDO_HACK_NO_STREAMING
Definition: cdromp.h:137
#define MODE_PAGE_DATA_SIZE
Definition: cdromp.h:376
#define CDROM_VOLUME_VERIFY_CHECKED
Definition: cdromp.h:171
@ SimpleMediaLock
Definition: cdromp.h:289
@ 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 SCSIOP_MODE_SENSE10
Definition: cdrw_hw.h:946
#define SCSIOP_READ_CD
Definition: cdrw_hw.h:967
struct _CDVD_KEY_HEADER * PCDVD_KEY_HEADER
#define SCSIOP_PLAY_AUDIO_MSF
Definition: cdrw_hw.h:931
#define SCSIOP_READ_SUB_CHANNEL
Definition: cdrw_hw.h:926
#define SCSIOP_SEEK
Definition: cdrw_hw.h:908
#define MODE_DSP_FUA_SUPPORTED
Definition: cdrw_hw.h:2522
#define SCSIOP_GET_CONFIGURATION
Definition: cdrw_hw.h:930
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
#define SCSIOP_READ_TOC
Definition: cdrw_hw.h:927
#define SCSIOP_RELEASE_UNIT
Definition: cdrw_hw.h:893
#define SCSIOP_GET_PERFORMANCE
Definition: cdrw_hw.h:959
#define SCSIOP_SET_READ_AHEAD
Definition: cdrw_hw.h:955
#define MODE_SENSE_CHANGEABLE_VALUES
Definition: cdrw_hw.h:860
struct _MODE_PARAMETER_HEADER10 MODE_PARAMETER_HEADER10
#define SCSIOP_PAUSE_RESUME
Definition: cdrw_hw.h:935
#define MODE_PAGE_CACHING
Definition: cdrw_hw.h:846
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
struct _CDVD_REPORT_AGID_DATA * PCDVD_REPORT_AGID_DATA
#define SCSIOP_RESERVE_UNIT
Definition: cdrw_hw.h:892
#define MODE_SENSE_CURRENT_VALUES
Definition: cdrw_hw.h:859
#define SCSIOP_SEND_KEY
Definition: cdrw_hw.h:951
#define SCSIOP_REPORT_KEY
Definition: cdrw_hw.h:952
#define SCSIOP_READ_DVD_STRUCTURE
Definition: cdrw_hw.h:960
union _CDB * PCDB
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
#define CDB_USE_MSF
Definition: cdrw_hw.h:3156
#define SCSIOP_SET_CD_SPEED
Definition: cdrw_hw.h:965
#define SCSIOP_SET_STREAMING
Definition: cdrw_hw.h:963
#define SCSIOP_MODE_SELECT10
Definition: cdrw_hw.h:943
struct _CDVD_KEY_HEADER CDVD_KEY_HEADER
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
ULONG DVD_SESSION_ID
Definition: cdrw_usr.h:1544
#define IOCTL_CDROM_CURRENT_POSITION
Definition: cdrw_usr.h:1354
#define DVD_TITLE_KEY_LENGTH
Definition: cdrw_usr.h:1595
#define DVD_BUS_KEY_LENGTH
Definition: cdrw_usr.h:1594
#define IOCTL_DVD_SEND_KEY
Definition: cdrw_usr.h:161
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define IOCTL_CDROM_MEDIA_CATALOG
Definition: cdrw_usr.h:1355
ULONG * PDVD_SESSION_ID
Definition: cdrw_usr.h:1544
#define DVD_CHALLENGE_KEY_LENGTH
Definition: cdrw_usr.h:1593
#define DVD_DISK_KEY_LENGTH
Definition: cdrw_usr.h:1596
#define IOCTL_CDROM_TRACK_ISRC
Definition: cdrw_usr.h:1356
#define DVD_ASF_LENGTH
Definition: cdrw_usr.h:1599
#define IOCTL_DVD_READ_KEY
Definition: cdrw_usr.h:160
@ CD_ROM
Definition: cdrw_usr.h:240
#define DVD_RPC_KEY_LENGTH
Definition: cdrw_usr.h:1597
_In_ PIRP Irp
Definition: csq.h:116
static PDB_INFORMATION information
Definition: db.cpp:178
UINT sectorCount[1]
Definition: diskio.c:16
#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
unsigned int idx
Definition: utils.c:41
#define RAW_SECTOR_SIZE
Definition: mcicda.c:50
static const WCHAR Cleanup[]
Definition: register.c:80
NTSTATUS RequestHandleGetHotPlugInfo(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5337
NTSTATUS RequestValidateReadToc(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:984
NTSTATUS RequestHandleGetMediaTypeEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _Out_ size_t *DataLength)
Definition: ioctl.c:336
NTSTATUS RequestHandleMountQuerySuggestedLinkName(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:4088
NTSTATUS RequestHandleQueryPropertyWriteCache(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: ioctl.c:2974
NTSTATUS RequestValidateAacsGetChallengeKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1826
NTSTATUS RequestHandleGetInquiryData(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:270
NTSTATUS RequestValidateSetSpeed(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1501
NTSTATUS RequestHandleSetHotPlugInfo(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5392
NTSTATUS RequestValidateRawRead(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:650
NTSTATUS RequestValidateSendOpcInformation(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3576
NTSTATUS RequestHandleGetDeviceNumber(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5280
NTSTATUS RequestValidateAacsReadMediaKeyBlock(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1584
NTSTATUS RequestValidateAacsReadVolumeId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1955
NTSTATUS RequestValidateGetPerformance(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3634
NTSTATUS RequestValidateReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: ioctl.c:6117
NTSTATUS RequestHandleMountQueryUniqueId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3939
#define LastDriveLetter
Definition: ioctl.c:41
NTSTATUS RequestHandleQueryPropertyDeviceUniqueId(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: ioctl.c:2799
NTSTATUS RequestValidateAacsStartSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1651
NTSTATUS RequestValidateDvdStartSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1225
static BOOLEAN ValidPersistentReserveScope(UCHAR Scope)
Definition: ioctl.c:6680
NTSTATUS RequestValidateAacsReadMediaId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2093
static BOOLEAN ValidPersistentReserveType(UCHAR Type)
Definition: ioctl.c:6697
NTSTATUS RequestValidateGetLastSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1029
NTSTATUS RequestValidateReadQChannel(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1072
NTSTATUS RequestHandleMountQueryDeviceName(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:4015
NTSTATUS RequestValidateGetConfiguration(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1364
NTSTATUS RequestValidateReadTocEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:887
NTSTATUS RequestValidateAacsSendCertificate(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1697
NTSTATUS RequestValidateAacsSendChallengeKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1895
NTSTATUS RequestValidateDvdEndSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3408
NTSTATUS RequestValidateDvdReadStructure(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1151
NTSTATUS RequestValidatePersistentReserve(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:6715
NTSTATUS RequestValidateAacsEndSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3462
NTSTATUS RequestValidateAacsGetCertificate(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1757
NTSTATUS RequestValidateDvdSendKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1274
#define FirstDriveLetter
Definition: ioctl.c:40
NTSTATUS RequestHandleQueryPropertyRetrieveCachedData(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2628
NTSTATUS RequestHandleReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: ioctl.c:6353
NTSTATUS RequestValidateExclusiveAccess(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2240
NTSTATUS RequestValidateDvdReadKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3286
NTSTATUS RequestValidateAacsReadSerialNumber(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2024
NTSTATUS RequestValidateAacsBindingNonce(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2162
NTSTATUS RequestValidateEnableStreaming(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3515
BOOLEAN RequestIsRealtimeStreaming(_In_ WDFREQUEST Request, _In_ BOOLEAN IsReadRequest)
Definition: ioctl.c:6050
_In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_PARAMETERS RequestParameters
Definition: ioctl.h:138
NTSTATUS RequestHandleUnknownIoctl(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
struct _DVD_DESCRIPTOR_HEADER * PDVD_DESCRIPTOR_HEADER
struct _DVD_RPC_KEY * PDVD_RPC_KEY
struct _DVD_LAYER_DESCRIPTOR * PDVD_LAYER_DESCRIPTOR
struct _DVD_COPYRIGHT_DESCRIPTOR * PDVD_COPYRIGHT_DESCRIPTOR
#define SCSI_REQUEST_BLOCK_SIZE
Definition: srb.h:282
#define SP_UNTAGGED
Definition: srb.h:233
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_STATUS_ABORTED
Definition: srb.h:342
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:423
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#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 DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define PagedPool
Definition: env_spec_w32.h:308
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
struct _FOUR_BYTE * PFOUR_BYTE
#define MSF_TO_LBA(Minutes, Seconds, Frames)
Definition: tools.h:269
PVOID dataBuffer
FxIrp * irp
GLdouble GLdouble t
Definition: gl.h:2047
GLuint buffer
Definition: glext.h:5915
GLsizei maxLength
Definition: glext.h:6877
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum GLuint GLint GLint layer
Definition: glext.h:7007
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
NTSYSAPI NTSTATUS WINAPI RtlDeleteRegistryValue(ULONG, PCWSTR, PCWSTR)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define C_ASSERT(e)
Definition: intsafe.h:73
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
const WCHAR * schema
#define MEDIA_CURRENTLY_MOUNTED
Definition: minitape.h:36
#define MEDIA_READ_WRITE
Definition: minitape.h:34
#define MEDIA_READ_ONLY
Definition: minitape.h:33
#define PCHAR
Definition: match.c:90
_Outptr_result_bytebuffer_all_ BytesReturned PGET_CONFIGURATION_HEADER _Out_ PULONG FEATURE_NUMBER const StartingFeature
Definition: mmc.h:54
struct _MOUNTDEV_NAME MOUNTDEV_NAME
struct _GET_LENGTH_INFORMATION * PGET_LENGTH_INFORMATION
struct _MOUNTDEV_UNIQUE_ID MOUNTDEV_UNIQUE_ID
struct _STORAGE_HOTPLUG_INFO STORAGE_HOTPLUG_INFO
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
struct _PARTITION_INFORMATION_EX * PPARTITION_INFORMATION_EX
@ PARTITION_STYLE_MBR
Definition: imports.h:201
struct _MOUNTDEV_SUGGESTED_LINK_NAME MOUNTDEV_SUGGESTED_LINK_NAME
static DWORD layout
Definition: bitmap.c:46
#define min(a, b)
Definition: monoChain.cc:55
#define DBG(x)
Definition: moztest.c:12
#define _In_reads_bytes_(size)
Definition: ms_sal.h:321
#define _Out_writes_bytes_(size)
Definition: ms_sal.h:350
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define KernelMode
Definition: asm.h:34
#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 REG_NONE
Definition: nt_native.h:1492
#define Int64ShrlMod32(a, b)
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
struct _CDROM_EXCEPTION_PERFORMANCE_DESCRIPTOR CDROM_EXCEPTION_PERFORMANCE_DESCRIPTOR
#define CD_RAW_SECTOR_WITH_C2_AND_SUBCODE_SIZE
Definition: ntddcdrm.h:391
struct _VOLUME_CONTROL VOLUME_CONTROL
#define AUDIO_STATUS_IN_PROGRESS
Definition: ntddcdrm.h:314
#define CDROM_READ_TOC_EX_FORMAT_SESSION
Definition: ntddcdrm.h:163
#define CDROM_LOCK_IGNORE_VOLUME
Definition: ntddcdrm.h:404
@ XAForm2
Definition: ntddcdrm.h:380
@ CDDA
Definition: ntddcdrm.h:381
@ RawWithC2AndSubCode
Definition: ntddcdrm.h:382
@ YellowMode2
Definition: ntddcdrm.h:379
@ RawWithSubCode
Definition: ntddcdrm.h:384
@ RawWithC2
Definition: ntddcdrm.h:383
@ CdromNominalPerformance
Definition: ntddcdrm.h:521
@ CdromEntirePerformanceList
Definition: ntddcdrm.h:522
@ CdromPerformanceExceptionsOnly
Definition: ntddcdrm.h:523
struct _CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR CDROM_NOMINAL_PERFORMANCE_DESCRIPTOR
#define CDROM_EXCLUSIVE_CALLER_LENGTH
Definition: ntddcdrm.h:402
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX
Definition: ntddcdrm.h:76
struct _CDROM_PERFORMANCE_HEADER CDROM_PERFORMANCE_HEADER
struct _CDROM_SET_STREAMING * PCDROM_SET_STREAMING
struct _CDROM_EXCLUSIVE_LOCK_STATE CDROM_EXCLUSIVE_LOCK_STATE
#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC
Definition: ntddcdrm.h:164
@ ExclusiveAccessQueryState
Definition: ntddcdrm.h:412
@ ExclusiveAccessLockDevice
Definition: ntddcdrm.h:413
@ ExclusiveAccessUnlockDevice
Definition: ntddcdrm.h:414
struct __RAW_READ_INFO RAW_READ_INFO
#define IOCTL_CDROM_GET_VOLUME
Definition: ntddcdrm.h:49
struct _SUB_Q_MEDIA_CATALOG_NUMBER SUB_Q_MEDIA_CATALOG_NUMBER
#define CDROM_READ_TOC_EX_FORMAT_PMA
Definition: ntddcdrm.h:165
@ Cdrom10Nominal20Exceptions
Definition: ntddcdrm.h:528
@ CdromReadPerformance
Definition: ntddcdrm.h:515
@ CdromWritePerformance
Definition: ntddcdrm.h:516
@ CdromStreamingDisable
Definition: ntddcdrm.h:479
@ CdromStreamingEnableForWriteOnly
Definition: ntddcdrm.h:481
@ CdromStreamingEnableForReadOnly
Definition: ntddcdrm.h:480
@ CdromStreamingEnableForReadWrite
Definition: ntddcdrm.h:482
#define CD_RAW_SECTOR_WITH_C2_SIZE
Definition: ntddcdrm.h:389
@ CdromPerformanceRequest
Definition: ntddcdrm.h:509
@ CdromWriteSpeedRequest
Definition: ntddcdrm.h:510
struct _CDROM_WRITE_SPEED_DESCRIPTOR CDROM_WRITE_SPEED_DESCRIPTOR
struct _CDROM_SET_STREAMING CDROM_SET_STREAMING
#define CDROM_READ_TOC_EX_FORMAT_TOC
Definition: ntddcdrm.h:162
#define CDROM_READ_TOC_EX_FORMAT_ATIP
Definition: ntddcdrm.h:166
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY
Definition: ntddcdrm.h:73
struct _SUB_Q_CURRENT_POSITION SUB_Q_CURRENT_POSITION
struct _CDROM_TOC_SESSION_DATA CDROM_TOC_SESSION_DATA
enum _CDROM_SPEED_REQUEST CDROM_SPEED_REQUEST
#define IOCTL_CDROM_EXCLUSIVE_ACCESS
Definition: ntddcdrm.h:85
#define CDROM_NO_MEDIA_NOTIFICATIONS
Definition: ntddcdrm.h:405
@ CdromSetSpeed
Definition: ntddcdrm.h:440
@ CdromSetStreaming
Definition: ntddcdrm.h:441
union _SUB_Q_CHANNEL_DATA * PSUB_Q_CHANNEL_DATA
struct _CDROM_TOC CDROM_TOC
#define CD_RAW_SECTOR_WITH_SUBCODE_SIZE
Definition: ntddcdrm.h:390
#define MINIMUM_CDROM_READ_TOC_EX_SIZE
Definition: ntddcdrm.h:133
@ SimpleOpcInfo
Definition: ntddcdrm.h:494
struct _CDROM_SUB_Q_DATA_FORMAT * PCDROM_SUB_Q_DATA_FORMAT
struct _CDROM_SET_SPEED CDROM_SET_SPEED
#define CDROM_READ_TOC_EX_FORMAT_CDTEXT
Definition: ntddcdrm.h:167
struct __RAW_READ_INFO * PRAW_READ_INFO
struct _SUB_Q_TRACK_ISRC SUB_Q_TRACK_ISRC
struct _DRIVE_LAYOUT_INFORMATION * PDRIVE_LAYOUT_INFORMATION
#define IOCTL_DISK_VOLUMES_ARE_READY
Definition: ntdddisk.h:248
struct _DISK_GEOMETRY DISK_GEOMETRY
#define IOCTL_DISK_GET_DRIVE_LAYOUT
Definition: ntdddisk.h:91
struct _PARTITION_INFORMATION PARTITION_INFORMATION
@ RemovableMedia
Definition: ntdddisk.h:387
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
struct _PARTITION_INFORMATION * PPARTITION_INFORMATION
struct _DISK_GEOMETRY * PDISK_GEOMETRY
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
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT
Definition: ntddmmc.h:16
enum _FEATURE_NUMBER FEATURE_NUMBER
struct _GET_CONFIGURATION_HEADER * PGET_CONFIGURATION_HEADER
@ FeatureRestrictedOverwrite
Definition: ntddmmc.h:90
@ FeatureIncrementalStreamingWritable
Definition: ntddmmc.h:85
@ FeatureRandomWritable
Definition: ntddmmc.h:84
@ FeatureDefectManagement
Definition: ntddmmc.h:88
@ FeatureRigidRestrictedOverwrite
Definition: ntddmmc.h:96
struct _GET_CONFIGURATION_HEADER GET_CONFIGURATION_HEADER
struct _FEATURE_HEADER FEATURE_HEADER
@ WriteThroughSupported
Definition: ntddstor.h:885
@ WriteThroughNotSupported
Definition: ntddstor.h:884
* PSTORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
STORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
#define STORAGE_EVENT_NOTIFICATION_VERSION_V1
Definition: ntddstor.h:979
STORAGE_READ_CAPACITY
Definition: ntddstor.h:861
struct _STORAGE_DEVICE_NUMBER STORAGE_DEVICE_NUMBER
* PSTORAGE_WRITE_CACHE_PROPERTY
Definition: ntddstor.h:898
@ WriteCacheChangeUnknown
Definition: ntddstor.h:877
@ WriteCacheChangeable
Definition: ntddstor.h:879
@ WriteCacheNotChangeable
Definition: ntddstor.h:878
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define IOCTL_STORAGE_READ_CAPACITY
Definition: ntddstor.h:175
@ WriteCacheTypeWriteBack
Definition: ntddstor.h:866
@ WriteCacheTypeUnknown
Definition: ntddstor.h:864
#define IOCTL_STORAGE_PERSISTENT_RESERVE_IN
Definition: ntddstor.h:169
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:576
#define IOCTL_STORAGE_RESERVE
Definition: ntddstor.h:116
@ StorageAdapterProperty
Definition: ntddstor.h:513
@ StorageDeviceProperty
Definition: ntddstor.h:512
#define STORAGE_EVENT_MEDIA_STATUS
Definition: ntddstor.h:981
@ WriteCacheEnableUnknown
Definition: ntddstor.h:871
@ WriteCacheDisabled
Definition: ntddstor.h:872
@ WriteCacheEnabled
Definition: ntddstor.h:873
STORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:576
@ PropertyExistsQuery
Definition: ntddstor.h:506
@ PropertyStandardQuery
Definition: ntddstor.h:505
struct _DEVICE_MEDIA_INFO DEVICE_MEDIA_INFO
STORAGE_WRITE_CACHE_PROPERTY
Definition: ntddstor.h:898
#define IOCTL_STORAGE_EJECT_MEDIA
Definition: ntddstor.h:107
#define IOCTL_STORAGE_EJECTION_CONTROL
Definition: ntddstor.h:125
#define STORAGE_EVENT_DEVICE_OPERATION
Definition: ntddstor.h:983
#define STORAGE_EVENT_DEVICE_STATUS
Definition: ntddstor.h:982
* PSTORAGE_ADAPTER_DESCRIPTOR
Definition: ntddstor.h:599
* PSTORAGE_READ_CAPACITY
Definition: ntddstor.h:861
struct _GET_MEDIA_TYPES GET_MEDIA_TYPES
#define IO_CDROM_EXCLUSIVE_LOCK
Definition: ntiologc.h:94
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:628
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:528
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define STATUS_INVALID_BUFFER_SIZE
Definition: ntstatus.h:650
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#define STATUS_INVALID_PARAMETER_3
Definition: ntstatus.h:477
#define STATUS_INVALID_PARAMETER_5
Definition: ntstatus.h:479
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
@ DvdAsf
Definition: ntddcdvd.h:168
@ DvdDiskKey
Definition: ntddcdvd.h:171
@ DvdInvalidateAGID
Definition: ntddcdvd.h:172
@ DvdTitleKey
Definition: ntddcdvd.h:167
@ DvdSetRpcKey
Definition: ntddcdvd.h:169
@ DvdBusKey1
Definition: ntddcdvd.h:165
@ DvdBusKey2
Definition: ntddcdvd.h:166
@ DvdChallengeKey
Definition: ntddcdvd.h:164
@ DvdGetRpcKey
Definition: ntddcdvd.h:170
@ DvdPhysicalDescriptor
Definition: ntddcdvd.h:109
@ DvdMaxDescriptor
Definition: ntddcdvd.h:114
@ DvdCopyrightDescriptor
Definition: ntddcdvd.h:110
@ DvdDiskKeyDescriptor
Definition: ntddcdvd.h:111
struct _DVD_COPY_PROTECT_KEY DVD_COPY_PROTECT_KEY
struct DVD_READ_STRUCTURE * PDVD_READ_STRUCTURE
struct _AACS_SERIAL_NUMBER AACS_SERIAL_NUMBER
struct _AACS_BINDING_NONCE AACS_BINDING_NONCE
struct _AACS_MEDIA_ID AACS_MEDIA_ID
* PAACS_LAYER_NUMBER
Definition: ntddcdvd.h:255
#define DVD_END_ALL_SESSIONS
Definition: ntddcdvd.h:195
struct _AACS_VOLUME_ID AACS_VOLUME_ID
struct _AACS_CERTIFICATE AACS_CERTIFICATE
struct _AACS_CHALLENGE_KEY AACS_CHALLENGE_KEY
struct _DVD_REGION DVD_REGION
struct _DVD_COPY_PROTECT_KEY * PDVD_COPY_PROTECT_KEY
#define FILE_DEVICE_DVD
Definition: winioctl.h:157
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
struct _DISK_GEOMETRY_EX * PDISK_GEOMETRY_EX
VOID ScratchBuffer_ResetItems(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN ResetRequestHistory)
Definition: scratch.c:343
NTSTATUS ScratchBuffer_SendSrb(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN SynchronousSrb, _When_(SynchronousSrb, _Pre_null_) _When_(!SynchronousSrb, _In_opt_) PSRB_HISTORY_ITEM *SrbHistoryItem)
Definition: scratch.c:906
NTSTATUS ScratchBuffer_PerformNextReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN FirstTry)
Definition: scratch.c:429
FORCEINLINE VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: scratch.h:104
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB Cdb
Definition: scratch.h:159
#define ScratchBuffer_BeginUse(context)
Definition: scratch.h:87
#define IOCTL_SCSI_PASS_THROUGH
Definition: scsi_port.h:47
#define IOCTL_SCSI_PASS_THROUGH_DIRECT
Definition: scsi_port.h:51
#define SCSIOP_RELEASE_UNIT10
Definition: scsi.h:322
#define CDROM_AUDIO_CONTROL_PAGE
Definition: scsi.h:991
#define CDB_AUDIO_RESUME
Definition: scsi.h:983
#define RESERVATION_ACTION_REGISTER
Definition: scsi.h:579
#define RESERVATION_SCOPE_ELEMENT
Definition: scsi.h:588
#define RESERVATION_SCOPE_LU
Definition: scsi.h:587
#define RESERVATION_ACTION_RESERVE
Definition: scsi.h:580
#define SCSIOP_SEND_OPC_INFORMATION
Definition: scsi.h:318
#define RESERVATION_ACTION_RELEASE
Definition: scsi.h:581
struct _PERFORMANCE_DESCRIPTOR PERFORMANCE_DESCRIPTOR
#define RESERVATION_ACTION_REGISTER_IGNORE_EXISTING
Definition: scsi.h:585
#define SCSIOP_RESERVE_UNIT10
Definition: scsi.h:320
#define DVD_REPORT_AGID
Definition: scsi.h:129
#define RESERVATION_TYPE_WRITE_EXCLUSIVE
Definition: scsi.h:590
#define RESERVATION_ACTION_READ_KEYS
Definition: scsi.h:576
#define RESERVATION_ACTION_PREEMPT_ABORT
Definition: scsi.h:584
#define RESERVATION_ACTION_CLEAR
Definition: scsi.h:582
#define CDB_SUBCHANNEL_BLOCK
Definition: scsi.h:989
#define CDB_AUDIO_PAUSE
Definition: scsi.h:982
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
struct _AUDIO_OUTPUT AUDIO_OUTPUT
struct _READ_DVD_STRUCTURES_HEADER READ_DVD_STRUCTURES_HEADER
#define REVERSE_SHORT(Short)
Definition: scsi.h:3481
#define SCSIOP_PERSISTENT_RESERVE_IN
Definition: scsi.h:329
#define DVD_INVALIDATE_AGID
Definition: scsi.h:135
#define RESERVATION_ACTION_PREEMPT
Definition: scsi.h:583
#define LOADING_MECHANISM_TRAY
Definition: scsi.h:972
struct _PRO_PARAMETER_LIST PRO_PARAMETER_LIST
#define RESERVATION_TYPE_EXCLUSIVE_REGISTRANTS
Definition: scsi.h:593
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define SCSIOP_PERSISTENT_RESERVE_OUT
Definition: scsi.h:330
#define MODE_SELECT_IMMEDIATE
Definition: scsi.h:992
#define RESERVATION_TYPE_EXCLUSIVE
Definition: scsi.h:591
struct _AUDIO_OUTPUT * PAUDIO_OUTPUT
ULONG dataLength
Definition: scsi.h:3751
#define REVERSE_LONG(Long)
Definition: scsi.h:3489
#define RESERVATION_ACTION_READ_RESERVATIONS
Definition: scsi.h:577
#define RESERVATION_TYPE_WRITE_EXCLUSIVE_REGISTRANTS
Definition: scsi.h:592
#define IOCTL_SCSI_PASS_THROUGH_DIRECT_EX
Definition: ntddscsi.h:38
#define IOCTL_SCSI_PASS_THROUGH_EX
Definition: ntddscsi.h:37
#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
FORCEINLINE DUID_MATCH_STATUS CompareStorageDuids(_In_ PSTORAGE_DEVICE_UNIQUE_IDENTIFIER Duid1, _In_ PSTORAGE_DEVICE_UNIQUE_IDENTIFIER Duid2)
Definition: storduid.h:56
struct _STORAGE_DEVICE_UNIQUE_IDENTIFIER STORAGE_DEVICE_UNIQUE_IDENTIFIER
#define DUID_INCLUDE_SOFTWARE_IDS
Definition: storduid.h:23
#define DUID_VERSION_1
Definition: storduid.h:20
@ DuidExactMatch
Definition: storduid.h:6
#define DUID_HARDWARE_IDS_ONLY
Definition: storduid.h:22
#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
LARGE_INTEGER BlockByteOffset
Definition: ntddcdvd.h:119
DVD_SESSION_ID SessionId
Definition: ntddcdvd.h:121
DVD_STRUCTURE_FORMAT Format
Definition: ntddcdvd.h:120
DVD_SESSION_ID SessionId
Definition: ntddcdvd.h:322
DVD_SESSION_ID SessionId
Definition: ntddcdvd.h:300
DVD_SESSION_ID SessionId
Definition: ntddcdvd.h:307
UCHAR ParameterLength
Definition: scsi.h:3194
UCHAR CodePage
Definition: scsi.h:3193
UCHAR Immediate
Definition: scsi.h:3195
PORT_OUTPUT PortOutput[4]
Definition: scsi.h:3199
ULONG_PTR HackFlags
Definition: cdrom.h:344
CDROM_MMC_EXTENSION Mmc
Definition: cdrom.h:341
DEVICE_TYPE DriveDeviceType
Definition: cdrom.h:388
BOOLEAN PlayActive
Definition: cdrom.h:351
ULONG MaxPageAlignedTransferBytes
Definition: cdrom.h:360
ULONG MaxUnalignedTransferBytes
Definition: cdrom.h:361
ULONG CachedInquiryDataByteCount
Definition: cdrom.h:392
UCHAR CallerName[CDROM_EXCLUSIVE_CALLER_LENGTH]
Definition: cdrom.h:376
BOOLEAN RestoreDefaults
Definition: cdrom.h:380
WDFFILEOBJECT ExclusiveOwner
Definition: cdrom.h:373
WDFIOTARGET IoTarget
Definition: cdrom.h:476
PDEVICE_OBJECT DeviceObject
Definition: cdrom.h:493
PZERO_POWER_ODD_INFO ZeroPowerODDInfo
Definition: cdrom.h:566
CDROM_DATA DeviceAdditionalData
Definition: cdrom.h:598
EXCLUSIVE_ACCESS_REQUEST_TYPE RequestType
Definition: ntddcdrm.h:419
UCHAR CallerName[CDROM_EXCLUSIVE_CALLER_LENGTH]
Definition: ntddcdrm.h:432
UCHAR CallerName[CDROM_EXCLUSIVE_CALLER_LENGTH]
Definition: ntddcdrm.h:426
CDROM_EXCLUSIVE_ACCESS Access
Definition: ntddcdrm.h:425
BOOLEAN ReadCdSubCode
Definition: cdrom.h:273
BOOLEAN WriteAllowed
Definition: cdrom.h:250
FEATURE_NUMBER ValidationSchema
Definition: cdrom.h:260
BOOLEAN ReadCdC2Pointers
Definition: cdrom.h:272
BOOLEAN StreamingReadSupported
Definition: cdrom.h:253
BOOLEAN StreamingWriteSupported
Definition: cdrom.h:254
BOOLEAN IsWriter
Definition: cdrom.h:249
BOOLEAN IsAACS
Definition: cdrom.h:248
CDROM_PERFORMANCE_TYPE PerformanceType
Definition: ntddcdrm.h:534
CDROM_PERFORMANCE_EXCEPTION_TYPE Exceptions
Definition: ntddcdrm.h:535
CDROM_PERFORMANCE_REQUEST_TYPE RequestType
Definition: ntddcdrm.h:533
CDROM_PERFORMANCE_TOLERANCE_TYPE Tolerance
Definition: ntddcdrm.h:536
ULONG_PTR HackFlags
Definition: cdromp.h:341
WDFREQUEST OriginalRequest
Definition: cdrom.h:633
PCDROM_DEVICE_EXTENSION DeviceExtension
Definition: cdrom.h:631
BOOLEAN SyncRequired
Definition: cdrom.h:643
BOOLEAN ReadWriteIsCompleted
Definition: cdrom.h:665
BOOLEAN ReadWriteRetryInitialized
Definition: cdrom.h:666
LARGE_INTEGER StartingOffset
Definition: cdrom.h:285
WRITE_ROTATION RotationControl
Definition: ntddcdrm.h:455
USHORT WriteSpeed
Definition: ntddcdrm.h:454
CDROM_SPEED_REQUEST RequestType
Definition: ntddcdrm.h:452
USHORT ReadSpeed
Definition: ntddcdrm.h:453
CDROM_OPC_INFO_TYPE RequestType
Definition: ntddcdrm.h:499
STREAMING_CONTROL_REQUEST_TYPE RequestType
Definition: ntddcdrm.h:486
CDROM_PERFORMANCE_REQUEST_TYPE RequestType
Definition: ntddcdrm.h:542
UCHAR Data[0]
Definition: scsi.h:2066
UCHAR DataLength[2]
Definition: cdrw_hw.h:3581
union _DEVICE_MEDIA_INFO::@3172 DeviceSpecific
struct _DEVICE_MEDIA_INFO::@3172::@3174 RemovableDiskInfo
DISK_GEOMETRY Geometry
Definition: winioctl.h:330
LARGE_INTEGER DiskSize
Definition: winioctl.h:331
DVD_SESSION_ID SessionId
Definition: ntddcdvd.h:177
LARGE_INTEGER TitleOffset
Definition: ntddcdvd.h:182
DVD_KEY_TYPE KeyType
Definition: ntddcdvd.h:178
union _DVD_COPY_PROTECT_KEY::@3165 Parameters
UCHAR ResetCount
Definition: ntddcdvd.h:246
UCHAR CopySystem
Definition: ntddcdvd.h:243
UCHAR RegionData
Definition: ntddcdvd.h:244
UCHAR SystemRegion
Definition: ntddcdvd.h:245
UCHAR UserResetsAvailable
Definition: scsi.h:2923
UCHAR TypeCode
Definition: scsi.h:2925
UCHAR RpcScheme
Definition: scsi.h:2927
UCHAR AdditionalLength
Definition: ntddmmc.h:34
UCHAR FeatureCode[2]
Definition: ntddmmc.h:29
UCHAR Current
Definition: ntddmmc.h:30
BOOLEAN EnforceStreamingRead
Definition: cdromp.h:368
BOOLEAN EnforceStreamingWrite
Definition: cdromp.h:369
UCHAR Byte0
Definition: tools.h:16
UCHAR Byte1
Definition: tools.h:17
UCHAR Byte2
Definition: tools.h:18
UCHAR Byte3
Definition: tools.h:19
LARGE_INTEGER Length
Definition: imports.h:232
ULONG DeviceType
Definition: ntddstor.h:494
DEVICE_MEDIA_INFO MediaInfo[1]
Definition: ntddstor.h:496
ULONG MediaInfoCount
Definition: ntddstor.h:495
NTSTATUS ErrorCode
Definition: iotypes.h:2007
NTSTATUS FinalStatus
Definition: iotypes.h:2009
union _IO_STACK_LOCATION::@1565 Parameters
struct _IO_STACK_LOCATION::@1565::@1566 DeviceIoControl
struct _IO_STACK_LOCATION::@3980::@3985 Write
struct _IO_STACK_LOCATION::@3980::@3984 Read
UCHAR WriteCacheEnable
Definition: cdrw_hw.h:2779
USHORT UniqueIdLength
Definition: imports.h:138
UCHAR UniqueId[1]
Definition: imports.h:139
LARGE_INTEGER StartingOffset
Definition: imports.h:221
PARTITION_STYLE PartitionStyle
Definition: imports.h:220
PARTITION_INFORMATION_MBR Mbr
Definition: imports.h:226
LARGE_INTEGER PartitionLength
Definition: imports.h:222
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:413
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:414
BOOLEAN RecognizedPartition
Definition: ntdddisk.h:419
BOOLEAN RewritePartition
Definition: ntdddisk.h:420
UCHAR WriteRotationControl
Definition: scsi.h:2293
UCHAR WriteSize[4]
Definition: scsi.h:2300
UCHAR WriteTime[4]
Definition: scsi.h:2301
struct _PERSISTENT_RESERVE_COMMAND::@3178::@3180 PR_OUT
struct _PERSISTENT_RESERVE_COMMAND::@3178::@3179 PR_IN
UCHAR ChannelSelection
Definition: scsi.h:3188
UCHAR Volume
Definition: scsi.h:3189
BOOLEAN PreventMediaRemoval
Definition: ntddstor.h:343
UCHAR QueueTag
Definition: srb.h:256
ULONG TimeOutValue
Definition: srb.h:262
PVOID DataBuffer
Definition: srb.h:263
UCHAR QueueAction
Definition: srb.h:257
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
DEVICE_TYPE DeviceType
Definition: ntddstor.h:324
STORAGE_QUERY_TYPE QueryType
Definition: ntddstor.h:553
UCHAR AdditionalParameters[1]
Definition: ntddstor.h:554
STORAGE_PROPERTY_ID PropertyId
Definition: ntddstor.h:552
LARGE_INTEGER TriggerAddress
Definition: ntddcdvd.h:104
LARGE_INTEGER TargetAddress
Definition: ntddcdvd.h:105
UCHAR TrackRelativeAddress[4]
Definition: ntddcdrm.h:354
UCHAR AbsoluteAddress[4]
Definition: ntddcdrm.h:353
SUB_Q_HEADER Header
Definition: ntddcdrm.h:347
UCHAR AudioStatus
Definition: ntddcdrm.h:322
SUB_Q_HEADER Header
Definition: ntddcdrm.h:336
USHORT MaximumLength
Definition: env_spec_w32.h:370
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:656
UCHAR PortVolume[4]
Definition: ntddcdrm.h:375
WDF_REQUEST_TYPE Type
Definition: wdfrequest.h:142
union _WDF_REQUEST_PARAMETERS::@3883 Parameters
struct _WDF_REQUEST_PARAMETERS::@3883::@3885 Read
struct _WDF_REQUEST_PARAMETERS::@3883::@3887 DeviceIoControl
struct _WDF_REQUEST_PARAMETERS::@3883::@3886 Write
ULONG GetConfigurationBufferSize
Definition: cdromp.h:284
BOOLEAN MonitorStartStopUnit
Definition: cdromp.h:274
PGET_CONFIGURATION_HEADER GetConfigurationBuffer
Definition: cdromp.h:283
UCHAR LoadingMechanism
Definition: cdromp.h:266
BOOLEAN InZeroPowerState
Definition: cdromp.h:272
TRACK_MODE_TYPE TrackMode
Definition: ntddcdrm.h:396
ULONG SectorCount
Definition: ntddcdrm.h:395
LARGE_INTEGER DiskOffset
Definition: ntddcdrm.h:394
Definition: copy.c:22
Definition: name.c:39
Definition: tftpd.h:86
Definition: ps.c:97
Definition: parse.h:23
#define max(a, b)
Definition: svc.c:63
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int64_t LONGLONG
Definition: typedefs.h:68
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
int32_t * PLONG
Definition: typedefs.h:58
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
char * PCHAR
Definition: typedefs.h:51
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
Definition: cdrw_hw.h:28
struct _CDB::_CDB10 CDB10
struct _CDB::_PERSISTENT_RESERVE_OUT PERSISTENT_RESERVE_OUT
struct _CDB::_PERSISTENT_RESERVE_IN PERSISTENT_RESERVE_IN
struct _CDB::_SUBCHANNEL SUBCHANNEL
UCHAR AsByte[16]
Definition: scsi.h:1988
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _CDB::_READ_DVD_STRUCTURE READ_DVD_STRUCTURE
struct _CDB::_MODE_SENSE10 MODE_SENSE10
struct _CDB::_SEND_OPC_INFORMATION SEND_OPC_INFORMATION
struct _CDB::_READ_CD READ_CD
struct _CDB::_SET_READ_AHEAD SET_READ_AHEAD
struct _CDB::_SEND_KEY SEND_KEY
struct _CDB::_GET_CONFIGURATION GET_CONFIGURATION
struct _CDB::_START_STOP START_STOP
struct _CDB::_SET_CD_SPEED SET_CD_SPEED
struct _CDB::_REPORT_KEY REPORT_KEY
struct _CDB::_MODE_SELECT10 MODE_SELECT10
struct _CDB::_PAUSE_RESUME PAUSE_RESUME
struct _CDB::_SEEK SEEK
struct _CDB::_PLAY_AUDIO_MSF PLAY_AUDIO_MSF
struct _CDB::_GET_PERFORMANCE GET_PERFORMANCE
struct _CDB::_SET_STREAMING SET_STREAMING
struct _CDB::_READ_TOC READ_TOC
LONGLONG QuadPart
Definition: typedefs.h:114
SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog
Definition: ntddcdrm.h:359
SUB_Q_TRACK_ISRC TrackIsrc
Definition: ntddcdrm.h:360
SUB_Q_CURRENT_POSITION CurrentPosition
Definition: ntddcdrm.h:358
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
@ WdfRequestTypeWrite
Definition: wdfdevice.h:507
@ WdfRequestTypeRead
Definition: wdfdevice.h:506
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFQUEUE _In_ _Strict_type_match_ WDF_REQUEST_TYPE RequestType
Definition: wdfdevice.h:4233
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_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
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
@ WDF_REQUEST_SEND_OPTION_SYNCHRONOUS
Definition: wdfrequest.h:109
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
Definition: wdfrequest.h:211
_Must_inspect_result_ FORCEINLINE NTSTATUS WdfWaitLockAcquire(_In_ _Requires_lock_not_held_(_Curr_) WDFWAITLOCK Lock, _In_opt_ PLONGLONG Timeout)
Definition: wdfsync.h:173
#define ioctl
Definition: wintirpc.h:60
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define SL_REALTIME_STREAM
Definition: iotypes.h:1827
@ RemovalPolicyExpectSurpriseRemoval
Definition: iotypes.h:842
@ RemovalPolicyExpectOrderlyRemoval
Definition: iotypes.h:841
#define MmGetMdlByteCount(_Mdl)
#define MmGetMdlVirtualAddress(_Mdl)
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define RTL_QUERY_REGISTRY_TYPECHECK
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
const char * LPCSTR
Definition: xmlstorage.h:183
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175