ReactOS 0.4.16-dev-336-gb667d82
common.c
Go to the documentation of this file.
1/*++
2
3Copyright (C) Microsoft Corporation. All rights reserved.
4
5Module Name:
6
7 common.c
8
9Abstract:
10
11 shared private routines for cdrom.sys
12
13Environment:
14
15 kernel mode only
16
17Notes:
18
19
20Revision History:
21
22--*/
23
24
25#include "ntddk.h"
26#include "ntddstor.h"
27#include "ntstrsafe.h"
28
29#include "cdrom.h"
30#include "scratch.h"
31
32
33#ifdef DEBUG_USE_WPP
34#include "common.tmh"
35#endif
36
37#ifdef ALLOC_PRAGMA
38
39#pragma alloc_text(PAGE, DeviceGetParameter)
40#pragma alloc_text(PAGE, DeviceSetParameter)
41#pragma alloc_text(PAGE, DeviceSendSrbSynchronously)
42#pragma alloc_text(PAGE, DevicePickDvdRegion)
43#pragma alloc_text(PAGE, StringsAreMatched)
44#pragma alloc_text(PAGE, PerformEjectionControl)
45#pragma alloc_text(PAGE, DeviceFindFeaturePage)
46#pragma alloc_text(PAGE, DevicePrintAllFeaturePages)
47#pragma alloc_text(PAGE, DeviceRegisterInterface)
48#pragma alloc_text(PAGE, DeviceRestoreDefaultSpeed)
49#pragma alloc_text(PAGE, DeviceSendRequestSynchronously)
50#pragma alloc_text(PAGE, MediaReadCapacity)
51#pragma alloc_text(PAGE, MediaReadCapacityDataInterpret)
52#pragma alloc_text(PAGE, DeviceRetrieveModeSenseUsingScratch)
53#pragma alloc_text(PAGE, ModeSenseFindSpecificPage)
54#pragma alloc_text(PAGE, DeviceUnlockExclusive)
55
56#endif
57
58LPCSTR LockTypeStrings[] = {"Simple",
59 "Secure",
60 "Internal"
61 };
62
63VOID
65 _In_ WDFREQUEST Request
66 )
67{
68 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
70
72
73 requestContext->TimeReceived = temp;
74
75 return;
76}
77
78VOID
80 _In_ WDFREQUEST Request
81 )
82{
83 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
85
87
88 if (requestContext->TimeSentDownFirstTime.QuadPart == 0)
89 {
90 requestContext->TimeSentDownFirstTime = temp;
91 }
92
93 requestContext->TimeSentDownLasttTime = temp;
94
95 if (requestContext->OriginalRequest != NULL)
96 {
97 PCDROM_REQUEST_CONTEXT originalRequestContext = RequestGetContext(requestContext->OriginalRequest);
98
99 if (originalRequestContext->TimeSentDownFirstTime.QuadPart == 0)
100 {
101 originalRequestContext->TimeSentDownFirstTime = temp;
102 }
103
104 originalRequestContext->TimeSentDownLasttTime = temp;
105 }
106
107 return;
108}
109
110VOID
112 _In_ WDFREQUEST Request
113 )
114/*
115Routine Description:
116
117 This function is used to clean SentTime fields in reusable request context.
118
119Arguments:
120 Request -
121
122Return Value:
123 N/A
124
125*/
126{
127 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
128
129 requestContext->TimeSentDownFirstTime.QuadPart = 0;
130 requestContext->TimeSentDownLasttTime.QuadPart = 0;
131
132 return;
133}
134
136VOID
137DeviceGetParameter(
138 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
141 _Inout_ PULONG ParameterValue // also default value
142 )
143/*++
144Routine Description:
145
146 retrieve device parameter from registry.
147
148Arguments:
149
150 DeviceExtension - device context.
151
152 SubkeyName - name of subkey
153
154 ParameterName - the registry parameter to be retrieved
155
156Return Value:
157
158 ParameterValue - registry value retrieved
159
160--*/
161{
163 WDFKEY rootKey = NULL;
164 WDFKEY subKey = NULL;
165 UNICODE_STRING registrySubKeyName;
166 UNICODE_STRING registryValueName;
167 ULONG defaultParameterValue;
168
169 PAGED_CODE();
170
171 RtlInitUnicodeString(&registryValueName, ParameterName);
172
173 if (SubkeyName != NULL)
174 {
175 RtlInitUnicodeString(&registrySubKeyName, SubkeyName);
176 }
177
178 // open the hardware key
179 status = WdfDeviceOpenRegistryKey(DeviceExtension->Device,
181 KEY_READ,
183 &rootKey);
184
185 // open the sub key
186 if (NT_SUCCESS(status) && (SubkeyName != NULL))
187 {
188 status = WdfRegistryOpenKey(rootKey,
189 &registrySubKeyName,
190 KEY_READ,
192 &subKey);
193
194 if (!NT_SUCCESS(status))
195 {
196 WdfRegistryClose(rootKey);
197 rootKey = NULL;
198 }
199 }
200
201 if (NT_SUCCESS(status) && (rootKey != NULL))
202 {
203 defaultParameterValue = *ParameterValue;
204
205 status = WdfRegistryQueryULong((subKey != NULL) ? subKey : rootKey,
206 &registryValueName,
208
209 if (!NT_SUCCESS(status))
210 {
211 *ParameterValue = defaultParameterValue; // use default value
212 }
213 }
214
215 // close what we open
216 if (subKey != NULL)
217 {
218 WdfRegistryClose(subKey);
219 subKey = NULL;
220 }
221
222 if (rootKey != NULL)
223 {
224 WdfRegistryClose(rootKey);
225 rootKey = NULL;
226 }
227
228 // Windows 2000 SP3 uses the driver-specific key, so look in there
229 if (!NT_SUCCESS(status))
230 {
231 // open the software key
232 status = WdfDeviceOpenRegistryKey(DeviceExtension->Device,
234 KEY_READ,
236 &rootKey);
237
238 // open the sub key
239 if (NT_SUCCESS(status) && (SubkeyName != NULL))
240 {
241 status = WdfRegistryOpenKey(rootKey,
242 &registrySubKeyName,
243 KEY_READ,
245 &subKey);
246
247 if (!NT_SUCCESS(status))
248 {
249 WdfRegistryClose(rootKey);
250 rootKey = NULL;
251 }
252 }
253
254 if (NT_SUCCESS(status) && (rootKey != NULL))
255 {
256 defaultParameterValue = *ParameterValue;
257
258 status = WdfRegistryQueryULong((subKey != NULL) ? subKey : rootKey,
259 &registryValueName,
261
262 if (!NT_SUCCESS(status))
263 {
264 *ParameterValue = defaultParameterValue; // use default value
265 }
266 else
267 {
268 // Migrate the value over to the device-specific key
269 DeviceSetParameter(DeviceExtension, SubkeyName, ParameterName, *ParameterValue);
270 }
271 }
272
273 // close what we open
274 if (subKey != NULL)
275 {
276 WdfRegistryClose(subKey);
277 subKey = NULL;
278 }
279
280 if (rootKey != NULL)
281 {
282 WdfRegistryClose(rootKey);
283 rootKey = NULL;
284 }
285 }
286
287 return;
288
289} // end DeviceetParameter()
290
291
294DeviceSetParameter(
295 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
299 )
300/*++
301Routine Description:
302
303 set parameter to registry.
304
305Arguments:
306
307 DeviceExtension - device context.
308
309 SubkeyName - name of subkey
310
311 ParameterName - the registry parameter to be retrieved
312
313 ParameterValue - registry value to be set
314
315Return Value:
316 NTSTATUS
317
318--*/
319{
321 WDFKEY rootKey = NULL;
322 WDFKEY subKey = NULL;
323 UNICODE_STRING registrySubKeyName;
324 UNICODE_STRING registryValueName;
325
326 PAGED_CODE();
327
328 RtlInitUnicodeString(&registryValueName, ParameterName);
329
330 if (SubkeyName != NULL)
331 {
332 RtlInitUnicodeString(&registrySubKeyName, SubkeyName);
333 }
334
335 // open the hardware key
336 status = WdfDeviceOpenRegistryKey(DeviceExtension->Device,
340 &rootKey);
341
342 // open the sub key
343 if (NT_SUCCESS(status) && (SubkeyName != NULL))
344 {
345 status = WdfRegistryOpenKey(rootKey,
346 &registrySubKeyName,
349 &subKey);
350
351 if (!NT_SUCCESS(status))
352 {
353 WdfRegistryClose(rootKey);
354 rootKey = NULL;
355 }
356 }
357
358 if (NT_SUCCESS(status) && (rootKey != NULL))
359 {
360 status = WdfRegistryAssignULong((subKey != NULL) ? subKey : rootKey,
361 &registryValueName,
363 }
364
365 // close what we open
366 if (subKey != NULL)
367 {
368 WdfRegistryClose(subKey);
369 subKey = NULL;
370 }
371
372 if (rootKey != NULL)
373 {
374 WdfRegistryClose(rootKey);
375 rootKey = NULL;
376 }
377
378 return status;
379
380} // end DeviceSetParameter()
381
382
385DeviceSendRequestSynchronously(
386 _In_ WDFDEVICE Device,
387 _In_ WDFREQUEST Request,
389 )
390/*++
391Routine Description:
392
393 send a request to lower driver synchronously.
394
395Arguments:
396
397 Device - device object.
398
399 Request - request object
400
401 RequestFormated - if the request is already formatted, will no do it in this function
402
403Return Value:
404 NTSTATUS
405
406--*/
407{
409 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
410 BOOLEAN requestCancelled = FALSE;
411 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
412
413 PAGED_CODE();
414
415 if (!RequestFormated)
416 {
417 // set request up for sending down
418 WdfRequestFormatRequestUsingCurrentType(Request);
419 }
420
421 // get cancellation status for the original request
422 if (requestContext->OriginalRequest != NULL)
423 {
424 requestCancelled = WdfRequestIsCanceled(requestContext->OriginalRequest);
425 }
426
427 if (!requestCancelled)
428 {
429 status = RequestSend(deviceExtension,
430 Request,
431 deviceExtension->IoTarget,
433 NULL);
434 }
435 else
436 {
438 }
439
440 return status;
441}
442
443
446DeviceSendSrbSynchronously(
447 _In_ WDFDEVICE Device,
452 _In_opt_ WDFREQUEST OriginalRequest
453 )
454/*++
455Routine Description:
456
457 Send a SRB structure to lower driver synchronously.
458
459 Process of this function:
460 1. Allocate SenseBuffer; Create Request; Allocate MDL
461 2. Do following loop if necessary
462 2.1 Reuse Request
463 2.2 Format Srb, Irp
464 2.3 Send Request
465 2.4 Error Intepret and retry decision making.
466 3. Release all allocated resosurces.
467
468Arguments:
469
470 Device - device object.
471
472 Request - request object
473
474 RequestFormated - if the request is already formatted, will no do it in this function
475
476Return Value:
477 NTSTATUS
478
479NOTE:
480The caller needs to setup following fields before calling this routine.
481 srb.CdbLength
482 srb.TimeOutValue
483 cdb
484
485BufferLength and WriteToDevice to control the data direction of the device
486 BufferLength = 0: No data transfer
487 BufferLenth != 0 && !WriteToDevice: get data from device
488 BufferLenth != 0 && WriteToDevice: send data to device
489--*/
490{
492 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
493 PCDROM_PRIVATE_FDO_DATA fdoData = deviceExtension->PrivateFdoData;
495 ULONG retryCount = 0;
496 BOOLEAN retry = FALSE;
497 ULONG ioctlCode = 0;
498 WDFREQUEST request = NULL;
499 PIRP irp = NULL;
500 PIO_STACK_LOCATION nextStack = NULL;
501 PMDL mdlAddress = NULL;
502 BOOLEAN memoryLocked = FALSE;
503 WDF_OBJECT_ATTRIBUTES attributes;
504 PZERO_POWER_ODD_INFO zpoddInfo = deviceExtension->ZeroPowerODDInfo;
505
506 PAGED_CODE();
507
508 // NOTE: This code is only pagable because we are not freezing
509 // the queue. Allowing the queue to be frozen from a pagable
510 // routine could leave the queue frozen as we try to page in
511 // the code to unfreeze the queue. The result would be a nice
512 // case of deadlock. Therefore, since we are unfreezing the
513 // queue regardless of the result, just set the NO_FREEZE_QUEUE
514 // flag in the SRB.
516
517 //1. allocate SenseBuffer and initiate Srb common fields
518 // these fields will not be changed by lower driver.
519 {
520 // Write length to SRB.
521 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
524
525 // Sense buffer is in aligned nonpaged pool.
526 senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
529
530 if (senseInfoBuffer == NULL)
531 {
533
534 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
535 "DeviceSendSrbSynchronously: Can't allocate MDL\n"));
536
537 goto Exit;
538 }
539
542
543 // set timeout value to default value if it's not specifically set by caller.
544 if (Srb->TimeOutValue == 0)
545 {
546 Srb->TimeOutValue = deviceExtension->TimeOutValue;
547 }
548 }
549
550 //2. Create Request object
551 {
554
555 status = WdfRequestCreate(&attributes,
556 deviceExtension->IoTarget,
557 &request);
558
559 if (!NT_SUCCESS(status))
560 {
561 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
562 "DeviceSendSrbSynchronously: Can't create request: %lx\n",
563 status));
564
565 goto Exit;
566 }
567
568 irp = WdfRequestWdmGetIrp(request);
569 }
570
571 // 3. Build an MDL for the data buffer and stick it into the irp.
572 if (BufferAddress != NULL)
573 {
574 mdlAddress = IoAllocateMdl( BufferAddress,
576 FALSE,
577 FALSE,
578 irp );
579 if (mdlAddress == NULL)
580 {
582
583 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
584 "DeviceSendSrbSynchronously: Can't allocate MDL\n"));
585
586 goto Exit;
587 }
588
590 {
591 MmProbeAndLockPages(mdlAddress,
594 }
596 {
598
599 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
600 "DeviceSendSrbSynchronously: Exception %lx locking buffer\n", status));
601
602 _SEH2_YIELD(goto Exit);
603 }
604 _SEH2_END;
605
606 memoryLocked = TRUE;
607 }
608
609 // 4. Format Srb, Irp; Send request and retry when necessary
610 do
611 {
612 // clear the control variable.
613 retry = FALSE;
614
615 // 4.1 reuse the request object; set originalRequest field.
616 {
618 PCDROM_REQUEST_CONTEXT requestContext = NULL;
619
620 // deassign the MdlAddress, this is the value we assign explicitly.
621 // doing this can prevent WdfRequestReuse to release the Mdl unexpectly.
622 if (irp->MdlAddress)
623 {
624 irp->MdlAddress = NULL;
625 }
626
630
631 status = WdfRequestReuse(request, &params);
632
633 if (!NT_SUCCESS(status))
634 {
635 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
636 "DeviceSendSrbSynchronously: WdfRequestReuse failed, %!STATUS!\n",
637 status));
638 // exit the loop.
639 break;
640 }
641
642 // WDF requests to format the request befor sending it
643 status = WdfIoTargetFormatRequestForInternalIoctlOthers(deviceExtension->IoTarget,
644 request,
645 ioctlCode,
646 NULL, NULL,
647 NULL, NULL,
648 NULL, NULL);
649
650 if (!NT_SUCCESS(status))
651 {
652 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
653 "DeviceSendSrbSynchronously: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n",
654 status));
655 // exit the loop.
656 break;
657 }
658
659 requestContext = RequestGetContext(request);
660 requestContext->OriginalRequest = OriginalRequest;
661 }
662
663 // 4.2 Format Srb and Irp
664 {
668 Srb->SrbFlags = deviceExtension->SrbFlags;
669
670 // Disable synchronous transfer for these requests.
673
674 if (BufferAddress != NULL)
675 {
676 if (WriteToDevice)
677 {
679 ioctlCode = IOCTL_SCSI_EXECUTE_OUT;
680 }
681 else
682 {
684 ioctlCode = IOCTL_SCSI_EXECUTE_IN;
685 }
686 }
687 else
688 {
689 ioctlCode = IOCTL_SCSI_EXECUTE_NONE;
690 }
691
692
693 // Zero out status.
694 Srb->ScsiStatus = 0;
695 Srb->SrbStatus = 0;
696 Srb->NextSrb = NULL;
697
698 // irp related fields
699 irp->MdlAddress = mdlAddress;
700
701 nextStack = IoGetNextIrpStackLocation(irp);
702
703 nextStack->MajorFunction = IRP_MJ_SCSI;
704 nextStack->Parameters.DeviceIoControl.IoControlCode = ioctlCode;
705 nextStack->Parameters.Scsi.Srb = Srb;
706 }
707
708 // 4.3 send Request to lower driver.
709 status = DeviceSendRequestSynchronously(Device, request, TRUE);
710
712 {
716
717 // 4.4 error process.
719 {
720 LONGLONG retryIntervalIn100ns = 0;
721
722 // Update status and determine if request should be retried.
723 retry = RequestSenseInfoInterpret(deviceExtension,
724 request,
725 Srb,
726 retryCount,
727 &status,
728 &retryIntervalIn100ns);
729
730 if (retry)
731 {
733 t.QuadPart = -retryIntervalIn100ns;
734 retryCount++;
736 }
737 }
738 else
739 {
740 // Request succeeded.
743 retry = FALSE;
744 }
745 }
746 } while(retry);
747
748 if ((zpoddInfo != NULL) &&
749 (zpoddInfo->MonitorStartStopUnit != FALSE) &&
751 {
752 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
753 "DeviceSendSrbSynchronously: soft eject detected, device marked as active\n"));
754
755 DeviceMarkActive(deviceExtension, TRUE, FALSE);
756 }
757
758 // 5. Release all allocated resources.
759
760 // required even though we allocated our own, since the port driver may
761 // have allocated one also
762 if (PORT_ALLOCATED_SENSE(deviceExtension, Srb))
763 {
764 FREE_PORT_ALLOCATED_SENSE_BUFFER(deviceExtension, Srb);
765 }
766
767Exit:
768
769 if (senseInfoBuffer != NULL)
770 {
772 }
773
776
777 if (mdlAddress)
778 {
779 if (memoryLocked)
780 {
781 MmUnlockPages(mdlAddress);
782 memoryLocked = FALSE;
783 }
784
785 IoFreeMdl(mdlAddress);
786 irp->MdlAddress = NULL;
787 }
788
789 if (request)
790 {
791 WdfObjectDelete(request);
792 }
793
794 return status;
795}
796
797
798VOID
800 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
801 _In_ const GUID* Guid,
803 _In_opt_ PVOID ExtraData
804 )
805/*++
806Routine Description:
807
808 send notification to other components
809
810Arguments:
811
812 DeviceExtension - device context.
813
814 Guid - GUID for the notification
815
816 ExtraDataSize - data size along with notification
817
818 ExtraData - data buffer send with notification
819
820Return Value:
821 None
822
823--*/
824{
826 ULONG requiredSize;
828
829 status = RtlULongAdd((sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION) - sizeof(UCHAR)),
831 &requiredSize);
832
833 if (!(NT_SUCCESS(status)) || (requiredSize > 0x0000ffff))
834 {
835 // MAX_USHORT, max total size for these events!
836 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
837 "Error sending event: size too large! (%x)\n",
838 requiredSize));
839 return;
840 }
841
842 notification = ExAllocatePoolWithTag(NonPagedPoolNx,
843 requiredSize,
845
846 // if none allocated, exit
847 if (notification == NULL)
848 {
849 return;
850 }
851
852 // Prepare and send the request!
853 RtlZeroMemory(notification, requiredSize);
854 notification->Version = 1;
855 notification->Size = (USHORT)(requiredSize);
856 notification->FileObject = NULL;
857 notification->NameBufferOffset = -1;
858 notification->Event = *Guid;
859
860 if (ExtraData != NULL)
861 {
862 RtlCopyMemory(notification->CustomDataBuffer, ExtraData, ExtraDataSize);
863 }
864
865 IoReportTargetDeviceChangeAsynchronous(DeviceExtension->LowerPdo,
867 NULL,
868 NULL);
869
871
872 return;
873}
874
875
876VOID
878 _In_ WDFDEVICE Device
879 )
880/*++
881
882Routine Description:
883
884 Send command to SCSI unit to start or power up.
885 Because this command is issued asynchronounsly, that is, without
886 waiting on it to complete, the IMMEDIATE flag is not set. This
887 means that the CDB will not return until the drive has powered up.
888 This should keep subsequent requests from being submitted to the
889 device before it has completely spun up.
890
891 This routine is called from the InterpretSense routine, when a
892 request sense returns data indicating that a drive must be
893 powered up.
894
895 This routine may also be called from a class driver's error handler,
896 or anytime a non-critical start device should be sent to the device.
897
898Arguments:
899
900 Device - The device object.
901
902Return Value:
903
904 None.
905
906--*/
907{
909 PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
910 WDF_OBJECT_ATTRIBUTES attributes;
911 WDFREQUEST startUnitRequest = NULL;
912 WDFMEMORY inputMemory = NULL;
913
916 PCDB cdb = NULL;
917
918 deviceExtension = DeviceGetExtension(Device);
919
920 if (NT_SUCCESS(status))
921 {
922 // Allocate Srb from nonpaged pool.
923 context = ExAllocatePoolWithTag(NonPagedPoolNx,
924 sizeof(COMPLETION_CONTEXT),
926
927 if (context == NULL)
928 {
929 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
930 "DeviceSendStartUnit: Failed to allocate completion context\n"));
931
933 }
934 }
935
936 if (NT_SUCCESS(status))
937 {
938 // Save the device object in the context for use by the completion
939 // routine.
940 context->Device = Device;
941 srb = &context->Srb;
942
943 // Zero out srb.
944 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
945
946 // setup SRB structure.
947 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
950
953
954 // setup CDB
955 srb->CdbLength = 6;
956 cdb = (PCDB)srb->Cdb;
957
958 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
959 cdb->START_STOP.Start = 1;
960 cdb->START_STOP.Immediate = 0;
961 cdb->START_STOP.LogicalUnitNumber = srb->Lun;
962
963 //Create Request for sending down to port driver
966 attributes.ParentObject = deviceExtension->IoTarget;
967
968 status = WdfRequestCreate(&attributes,
969 deviceExtension->IoTarget,
970 &startUnitRequest);
971 }
972
973 if (NT_SUCCESS(status))
974 {
975 srb->OriginalRequest = WdfRequestWdmGetIrp(startUnitRequest);
977
978 //Prepare the request
979 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
980 attributes.ParentObject = startUnitRequest;
981
982 status = WdfMemoryCreatePreallocated(&attributes,
983 (PVOID)srb,
984 sizeof(SCSI_REQUEST_BLOCK),
985 &inputMemory);
986 }
987
988 if (NT_SUCCESS(status))
989 {
990 status = WdfIoTargetFormatRequestForInternalIoctlOthers(deviceExtension->IoTarget,
991 startUnitRequest,
993 inputMemory,
994 NULL,
995 NULL,
996 NULL,
997 NULL,
998 NULL);
999 }
1000
1001 if (NT_SUCCESS(status))
1002 {
1003 // Set a CompletionRoutine callback function.
1004 WdfRequestSetCompletionRoutine(startUnitRequest,
1006 context);
1007
1008 status = RequestSend(deviceExtension,
1009 startUnitRequest,
1010 deviceExtension->IoTarget,
1011 0,
1012 NULL);
1013 }
1014
1015 // release resources when failed.
1016 if (!NT_SUCCESS(status))
1017 {
1019 if (startUnitRequest != NULL)
1020 {
1021 WdfObjectDelete(startUnitRequest);
1022 }
1023 }
1024
1025 return;
1026} // end StartUnit()
1027
1028
1029VOID
1031 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1034 )
1035/*++
1036
1037Routine Description:
1038
1039 Send an IOCTL asynchronously
1040
1041Arguments:
1042
1043 DeviceExtension - device context.
1044 IoControlCode - IOCTL code.
1045 TargetDeviceObject - target device object.
1046
1047Return Value:
1048
1049 None.
1050
1051--*/
1052{
1053 PIRP irp = NULL;
1054 PIO_STACK_LOCATION nextIrpStack = NULL;
1055
1056 irp = IoAllocateIrp(DeviceExtension->DeviceObject->StackSize, FALSE);
1057
1058 if (irp != NULL)
1059 {
1060 nextIrpStack = IoGetNextIrpStackLocation(irp);
1061
1062 nextIrpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
1063
1064 nextIrpStack->Parameters.DeviceIoControl.OutputBufferLength = 0;
1065 nextIrpStack->Parameters.DeviceIoControl.InputBufferLength = 0;
1066 nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
1067 nextIrpStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
1068
1071 DeviceExtension,
1072 TRUE,
1073 TRUE,
1074 TRUE);
1075
1077 }
1078}
1079
1081NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1084 _In_ PIRP Irp,
1085 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context
1086 )
1087/*++
1088
1089Routine Description:
1090
1091 Free the Irp.
1092
1093Arguments:
1094
1095 DeviceObject - device that the completion routine fires on.
1096
1097 Irp - The irp to be completed.
1098
1099 Context - IRP context
1100
1101Return Value:
1102 NTSTATUS
1103
1104--*/
1105{
1108
1109 IoFreeIrp(Irp);
1110
1112}
1113
1114VOID
1115NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1117 _In_ WDFREQUEST Request,
1118 _In_ WDFIOTARGET Target,
1121 )
1122/*++
1123
1124Routine Description:
1125
1126 This routine is called when an asynchronous I/O request
1127 which was issused by the class driver completes. Examples of such requests
1128 are release queue or START UNIT. This routine releases the queue if
1129 necessary. It then frees the context and the IRP.
1130
1131Arguments:
1132
1133 DeviceObject - The device object for the logical unit; however since this
1134 is the top stack location the value is NULL.
1135
1136 Irp - Supplies a pointer to the Irp to be processed.
1137
1138 Context - Supplies the context to be used to process this request.
1139
1140Return Value:
1141
1142 None.
1143
1144--*/
1145{
1147 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(context->Device);
1148
1151
1152 // If this is an execute srb, then check the return status and make sure.
1153 // the queue is not frozen.
1154 if (context->Srb.Function == SRB_FUNCTION_EXECUTE_SCSI)
1155 {
1156 // Check for a frozen queue.
1157 if (context->Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN)
1158 {
1159 // Unfreeze the queue getting the device object from the context.
1160 DeviceReleaseQueue(context->Device);
1161 }
1162 }
1163
1164 // free port-allocated sense buffer if we can detect
1165 //
1166 if (PORT_ALLOCATED_SENSE(deviceExtension, &context->Srb))
1167 {
1168 FREE_PORT_ALLOCATED_SENSE_BUFFER(deviceExtension, &context->Srb);
1169 }
1170
1172
1173 WdfObjectDelete(Request);
1174
1175} // end DeviceAsynchronousCompletion()
1176
1177
1178VOID
1180 _In_ WDFDEVICE Device
1181 )
1182/*++
1183
1184Routine Description:
1185
1186 This routine issues an internal device control command
1187 to the port driver to release a frozen queue. The call
1188 is issued asynchronously as DeviceReleaseQueue will be invoked
1189 from the IO completion DPC (and will have no context to
1190 wait for a synchronous call to complete).
1191
1192 This routine must be called with the remove lock held.
1193
1194Arguments:
1195
1196 Device - The functional device object for the device with the frozen queue.
1197
1198Return Value:
1199
1200 None.
1201
1202--*/
1203{
1204 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
1206 KIRQL currentIrql;
1207
1208 // we raise irql seperately so we're not swapped out or suspended
1209 // while holding the release queue irp in this routine. this lets
1210 // us release the spin lock before lowering irql.
1211 KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
1212
1213 WdfSpinLockAcquire(deviceExtension->ReleaseQueueSpinLock);
1214
1215 if (deviceExtension->ReleaseQueueInProgress)
1216 {
1217 // Someone is already doing this work - just set the flag to indicate that
1218 // we need to release the queue again.
1219 deviceExtension->ReleaseQueueNeeded = TRUE;
1220 WdfSpinLockRelease(deviceExtension->ReleaseQueueSpinLock);
1221 KeLowerIrql(currentIrql);
1222
1223 return;
1224 }
1225
1226 // Mark that there is a release queue in progress and drop the spinlock.
1227 deviceExtension->ReleaseQueueInProgress = TRUE;
1228
1229 WdfSpinLockRelease(deviceExtension->ReleaseQueueSpinLock);
1230
1231 srb = &(deviceExtension->ReleaseQueueSrb);
1232
1233 // Optical media are removable, so we just flush the queue. This will also release it.
1235
1236 srb->OriginalRequest = WdfRequestWdmGetIrp(deviceExtension->ReleaseQueueRequest);
1237
1238 // Set a CompletionRoutine callback function.
1239 WdfRequestSetCompletionRoutine(deviceExtension->ReleaseQueueRequest,
1241 Device);
1242 // Send the request. If an error occurs, complete the request.
1243 RequestSend(deviceExtension,
1244 deviceExtension->ReleaseQueueRequest,
1245 deviceExtension->IoTarget,
1247 NULL);
1248
1249 KeLowerIrql(currentIrql);
1250
1251 return;
1252
1253} // end DeviceReleaseQueue()
1254
1255VOID
1256NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1258 _In_ WDFREQUEST Request,
1259 _In_ WDFIOTARGET Target,
1262 )
1263/*++
1264
1265Routine Description:
1266
1267 This routine is called when an asynchronous release queue request which
1268 was issused in DeviceReleaseQueue completes. This routine prepares for
1269 the next release queue request and resends it if necessary.
1270
1271Arguments:
1272
1273 Request - The completed request.
1274
1275 Target - IoTarget object
1276
1277 Params - Completion parameters
1278
1279 Context - WDFDEVICE object handle.
1280
1281Return Value:
1282
1283 None.
1284
1285--*/
1286{
1288 WDFDEVICE device = Context;
1289 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
1290
1291 BOOLEAN releaseQueueNeeded = FALSE;
1293
1296
1300
1301 // Grab the spinlock and clear the release queue in progress flag so others
1302 // can run. Save (and clear) the state of the release queue needed flag
1303 // so that we can issue a new release queue outside the spinlock.
1304 WdfSpinLockAcquire(deviceExtension->ReleaseQueueSpinLock);
1305
1306 releaseQueueNeeded = deviceExtension->ReleaseQueueNeeded;
1307
1308 deviceExtension->ReleaseQueueNeeded = FALSE;
1309 deviceExtension->ReleaseQueueInProgress = FALSE;
1310
1311 // Reuse the ReleaseQueueRequest for the next time.
1312 status = WdfRequestReuse(Request,&params);
1313
1314 if (NT_SUCCESS(status))
1315 {
1316 // Preformat the ReleaseQueueRequest for the next time.
1317 // This should always succeed because it was already preformatted once during device initialization
1318 status = WdfIoTargetFormatRequestForInternalIoctlOthers(deviceExtension->IoTarget,
1319 Request,
1321 deviceExtension->ReleaseQueueInputMemory,
1322 NULL,
1323 NULL,
1324 NULL,
1325 NULL,
1326 NULL);
1327 }
1328
1329 if (!NT_SUCCESS(status))
1330 {
1331 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1332 "DeviceReleaseQueueCompletion: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n",
1333 status));
1334 }
1335
1337
1338 WdfSpinLockRelease(deviceExtension->ReleaseQueueSpinLock);
1339
1340 // If we need a release queue then issue one now. Another processor may
1341 // have already started one in which case we'll try to issue this one after
1342 // it is done - but we should never recurse more than one deep.
1343 if (releaseQueueNeeded)
1344 {
1346 }
1347
1348 return;
1349
1350} // DeviceReleaseQueueCompletion()
1351
1352
1353//
1354// In order to provide better performance without the need to reboot,
1355// we need to implement a self-adjusting method to set and clear the
1356// srb flags based upon current performance.
1357//
1358// whenever there is an error, immediately grab the spin lock. the
1359// MP perf hit here is acceptable, since we're in an error path. this
1360// is also neccessary because we are guaranteed to be modifying the
1361// SRB flags here, setting SuccessfulIO to zero, and incrementing the
1362// actual error count (which is always done within this spinlock).
1363//
1364// whenever there is no error, increment a counter. if there have been
1365// errors on the device, and we've enabled dynamic perf, *and* we've
1366// just crossed the perf threshhold, then grab the spin lock and
1367// double check that the threshhold has, indeed been hit(*). then
1368// decrement the error count, and if it's dropped sufficiently, undo
1369// some of the safety changes made in the SRB flags due to the errors.
1370//
1371// * this works in all cases. even if lots of ios occur after the
1372// previous guy went in and cleared the successfulio counter, that
1373// just means that we've hit the threshhold again, and so it's proper
1374// to run the inner loop again.
1375//
1376
1377VOID
1379 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1380 )
1381{
1382 PCDROM_PRIVATE_FDO_DATA fdoData = DeviceExtension->PrivateFdoData;
1383 KIRQL oldIrql;
1384 ULONG errors;
1385
1386 KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
1387
1388 fdoData->Perf.SuccessfulIO = 0; // implicit interlock
1389 errors = InterlockedIncrement((PLONG)&DeviceExtension->ErrorCount);
1390
1391 if (errors >= CLASS_ERROR_LEVEL_1)
1392 {
1393 // If the error count has exceeded the error limit, then disable
1394 // any tagged queuing, multiple requests per lu queueing
1395 // and sychronous data transfers.
1396 //
1397 // Clearing the no queue freeze flag prevents the port driver
1398 // from sending multiple requests per logical unit.
1399 CLEAR_FLAG(DeviceExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
1400 CLEAR_FLAG(DeviceExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
1401
1402 SET_FLAG(DeviceExtension->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
1403
1404 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1405 "PerfIncrementErrorCount: Too many errors; disabling tagged queuing and "
1406 "synchronous data tranfers.\n"));
1407 }
1408
1409 if (errors >= CLASS_ERROR_LEVEL_2)
1410 {
1411 // If a second threshold is reached, disable disconnects.
1412 SET_FLAG(DeviceExtension->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
1413 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
1414 "PerfIncrementErrorCount: Too many errors; disabling disconnects.\n"));
1415 }
1416
1417 KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
1418 return;
1419}
1420
1421
1423PVOID
1424DeviceFindFeaturePage(
1426 _In_ ULONG const Length,
1428 )
1429/*++
1430Routine Description:
1431
1432 find the specific feature page in the buffer
1433
1434Arguments:
1435
1436 FeatureBuffer - buffer contains the device feature set.
1437
1438 Length - buffer length
1439
1440 Feature - the feature number looking for.
1441
1442Return Value:
1443
1444 PVOID - pointer to the starting location of the specific feature in buffer.
1445
1446--*/
1447{
1448 PUCHAR buffer;
1449 PUCHAR limit;
1450 ULONG validLength;
1451
1452 PAGED_CODE();
1453
1454 if (Length < sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER))
1455 {
1456 return NULL;
1457 }
1458
1459 // Calculate the length of valid data available in the
1460 // capabilities buffer from the DataLength field
1461 REVERSE_BYTES(&validLength, FeatureBuffer->DataLength);
1462
1464
1465 // set limit to point to first illegal address
1466 limit = (PUCHAR)FeatureBuffer;
1467 limit += min(Length, validLength);
1468
1469 // set buffer to point to first page
1470 buffer = FeatureBuffer->Data;
1471
1472 // loop through each page until we find the requested one, or
1473 // until it's not safe to access the entire feature header
1474 // (if equal, have exactly enough for the feature header)
1475 while (buffer + sizeof(FEATURE_HEADER) <= limit)
1476 {
1478 FEATURE_NUMBER thisFeature;
1479
1480 thisFeature = (header->FeatureCode[0] << 8) |
1481 (header->FeatureCode[1]);
1482
1483 if (thisFeature == Feature)
1484 {
1485 PUCHAR temp;
1486
1487 // if don't have enough memory to safely access all the feature
1488 // information, return NULL
1489 temp = buffer;
1490 temp += sizeof(FEATURE_HEADER);
1491 temp += header->AdditionalLength;
1492
1493 if (temp > limit)
1494 {
1495 // this means the transfer was cut-off, an insufficiently
1496 // small buffer was given, or other arbitrary error. since
1497 // it's not safe to view the amount of data (even though
1498 // the header is safe) in this feature, pretend it wasn't
1499 // transferred at all...
1500 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
1501 "Feature %x exists, but not safe to access all its data. returning NULL\n",
1502 Feature));
1503 return NULL;
1504 }
1505 else
1506 {
1507 return buffer;
1508 }
1509 }
1510
1511 if ((header->AdditionalLength % 4) &&
1512 !(Feature >= 0xff00 && Feature <= 0xffff))
1513 {
1514 return NULL;
1515 }
1516
1517 buffer += sizeof(FEATURE_HEADER);
1518 buffer += header->AdditionalLength;
1519 }
1520
1521 return NULL;
1522}
1523
1524
1526VOID
1527DevicePrintAllFeaturePages(
1529 _In_ ULONG const Usable
1530 )
1531/*++
1532Routine Description:
1533
1534 print out all feature pages in the buffer
1535
1536Arguments:
1537
1538 Buffer - buffer contains the device feature set.
1539
1540 Usable -
1541
1542Return Value:
1543
1544 none
1545
1546--*/
1547{
1548#if DBG
1550
1551 PAGED_CODE();
1552
1554 // items expected to ALWAYS be current if they exist
1556
1557 header = DeviceFindFeaturePage(Buffer, Usable, FeatureProfileList);
1558 if (header != NULL) {
1559 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1560 "CdromGetConfiguration: CurrentProfile %x "
1561 "with %x bytes of data at %p\n",
1562 Buffer->CurrentProfile[0] << 8 |
1563 Buffer->CurrentProfile[1],
1564 Usable, Buffer));
1565 }
1566
1567 header = DeviceFindFeaturePage(Buffer, Usable, FeatureCore);
1568 if (header) {
1569 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1570 "CdromGetConfiguration: %s %s\n",
1571 (header->Current ?
1572 "Currently supports" : "Is able to support"),
1573 "CORE Features"
1574 ));
1575 }
1576
1577 header = DeviceFindFeaturePage(Buffer, Usable, FeatureMorphing);
1578 if (header) {
1579 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1580 "CdromGetConfiguration: %s %s\n",
1581 (header->Current ?
1582 "Currently supports" : "Is able to support"),
1583 "Morphing"
1584 ));
1585 }
1586
1587 header = DeviceFindFeaturePage(Buffer, Usable, FeatureRemovableMedium);
1588 if (header) {
1589 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1590 "CdromGetConfiguration: %s %s\n",
1591 (header->Current ?
1592 "Currently supports" : "Is able to support"),
1593 "Removable Medium"
1594 ));
1595 }
1596
1597 header = DeviceFindFeaturePage(Buffer, Usable, FeaturePowerManagement);
1598 if (header) {
1599 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1600 "CdromGetConfiguration: %s %s\n",
1601 (header->Current ?
1602 "Currently supports" : "Is able to support"),
1603 "Power Management"
1604 ));
1605 }
1606
1607 header = DeviceFindFeaturePage(Buffer, Usable, FeatureEmbeddedChanger);
1608 if (header) {
1609 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1610 "CdromGetConfiguration: %s %s\n",
1611 (header->Current ?
1612 "Currently supports" : "Is able to support"),
1613 "Embedded Changer"
1614 ));
1615 }
1616
1617 header = DeviceFindFeaturePage(Buffer, Usable, FeatureMicrocodeUpgrade);
1618 if (header) {
1619 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1620 "CdromGetConfiguration: %s %s\n",
1621 (header->Current ?
1622 "Currently supports" : "Is able to support"),
1623 "Microcode Update"
1624 ));
1625 }
1626
1627 header = DeviceFindFeaturePage(Buffer, Usable, FeatureTimeout);
1628 if (header) {
1629 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1630 "CdromGetConfiguration: %s %s\n",
1631 (header->Current ?
1632 "Currently supports" : "Is able to support"),
1633 "Timeouts"
1634 ));
1635 }
1636
1637 header = DeviceFindFeaturePage(Buffer, Usable, FeatureLogicalUnitSerialNumber);
1638 if (header) {
1639 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1640 "CdromGetConfiguration: %s %s\n",
1641 (header->Current ?
1642 "Currently supports" : "Is able to support"),
1643 "LUN Serial Number"
1644 ));
1645 }
1646
1647 header = DeviceFindFeaturePage(Buffer, Usable, FeatureFirmwareDate);
1648 if (header) {
1649
1650 ULONG featureSize = header->AdditionalLength;
1651 featureSize += RTL_SIZEOF_THROUGH_FIELD(FEATURE_HEADER, AdditionalLength);
1652
1653 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1654 "CdromGetConfiguration: %s %s\n",
1655 (header->Current ?
1656 "Currently supports" : "Is able to support"),
1657 "Firmware Date"
1658 ));
1659
1660 if (featureSize >= RTL_SIZEOF_THROUGH_FIELD(FEATURE_DATA_FIRMWARE_DATE, Minute))
1661 {
1663 // show date as "YYYY/MM/DD hh:mm", which is 18 chars (17+NULL)
1664 UCHAR dateString[18] = { 0 };
1665 dateString[ 0] = date->Year[0];
1666 dateString[ 1] = date->Year[1];
1667 dateString[ 2] = date->Year[2];
1668 dateString[ 3] = date->Year[3];
1669 dateString[ 4] = '/';
1670 dateString[ 5] = date->Month[0];
1671 dateString[ 6] = date->Month[1];
1672 dateString[ 7] = '/';
1673 dateString[ 8] = date->Day[0];
1674 dateString[ 9] = date->Day[1];
1675 dateString[10] = ' ';
1676 dateString[11] = ' ';
1677 dateString[12] = date->Hour[0];
1678 dateString[13] = date->Hour[1];
1679 dateString[14] = ':';
1680 dateString[15] = date->Minute[0];
1681 dateString[16] = date->Minute[1];
1682 dateString[17] = 0;
1683 // SECONDS IS NOT AVAILABLE ON EARLY IMPLEMENTATIONS -- ignore it
1684 //dateString[17] = ':';
1685 //dateString[18] = date->Seconds[0];
1686 //dateString[19] = date->Seconds[1];
1687 //dateString[20] = 0;
1688 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1689 "CdromGetConfiguration: Firmware Date/Time %s (UTC)\n",
1690 (PCSTR)dateString
1691 ));
1692 }
1693 }
1694
1696// items expected not to always be current
1698
1699
1700 header = DeviceFindFeaturePage(Buffer, Usable, FeatureWriteProtect);
1701 if (header) {
1702 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
1703 "CdromGetConfiguration: %s %s\n",
1704 (header->Current ?
1705 "Currently supports" : "Is able to support"),
1706 "Software Write Protect"
1707 ));
1708 }
1709
1710 header = DeviceFindFeaturePage(Buffer, Usable, FeatureRandomReadable);
1711 if (header) {
1712 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1713 "CdromGetConfiguration: %s %s\n",
1714 (header->Current ?
1715 "Currently supports" : "Is able to support"),
1716 "Random Reads"
1717 ));
1718 }
1719
1720 header = DeviceFindFeaturePage(Buffer, Usable, FeatureMultiRead);
1721 if (header) {
1722 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1723 "CdromGetConfiguration: %s %s\n",
1724 (header->Current ?
1725 "Currently supports" : "Is able to support"),
1726 "Multi-Read"
1727 ));
1728 }
1729
1730 header = DeviceFindFeaturePage(Buffer, Usable, FeatureCdRead);
1731 if (header) {
1732 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1733 "CdromGetConfiguration: %s %s\n",
1734 (header->Current ?
1735 "Currently supports" : "Is able to support"),
1736 "reading from CD-ROM/R/RW"
1737 ));
1738 }
1739
1740 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdRead);
1741 if (header) {
1742 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1743 "CdromGetConfiguration: %s %s\n",
1744 (header->Current ?
1745 "Currently supports" : "Is able to support"),
1746 "DVD Structure Reads"
1747 ));
1748 }
1749
1750 header = DeviceFindFeaturePage(Buffer, Usable, FeatureRandomWritable);
1751 if (header) {
1752 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1753 "CdromGetConfiguration: %s %s\n",
1754 (header->Current ?
1755 "Currently supports" : "Is able to support"),
1756 "Random Writes"
1757 ));
1758 }
1759
1760 header = DeviceFindFeaturePage(Buffer, Usable, FeatureIncrementalStreamingWritable);
1761 if (header) {
1762 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1763 "CdromGetConfiguration: %s %s\n",
1764 (header->Current ?
1765 "Currently supports" : "Is able to support"),
1766 "Incremental Streaming Writing"
1767 ));
1768 }
1769
1770 header = DeviceFindFeaturePage(Buffer, Usable, FeatureSectorErasable);
1771 if (header) {
1772 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1773 "CdromGetConfiguration: %s %s\n",
1774 (header->Current ?
1775 "Currently supports" : "Is able to support"),
1776 "Sector Erasable Media"
1777 ));
1778 }
1779
1780 header = DeviceFindFeaturePage(Buffer, Usable, FeatureFormattable);
1781 if (header) {
1782 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1783 "CdromGetConfiguration: %s %s\n",
1784 (header->Current ?
1785 "Currently supports" : "Is able to support"),
1786 "Formatting"
1787 ));
1788 }
1789
1790 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDefectManagement);
1791 if (header) {
1792 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1793 "CdromGetConfiguration: %s %s\n",
1794 (header->Current ?
1795 "Currently supports" : "Is able to support"),
1796 "defect management"
1797 ));
1798 }
1799
1800 header = DeviceFindFeaturePage(Buffer, Usable, FeatureWriteOnce);
1801 if (header) {
1802 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1803 "CdromGetConfiguration: %s %s\n",
1804 (header->Current ?
1805 "Currently supports" : "Is able to support"),
1806 "Write Once Media"
1807 ));
1808 }
1809
1810 header = DeviceFindFeaturePage(Buffer, Usable, FeatureRestrictedOverwrite);
1811 if (header) {
1812 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1813 "CdromGetConfiguration: %s %s\n",
1814 (header->Current ?
1815 "Currently supports" : "Is able to support"),
1816 "Restricted Overwrites"
1817 ));
1818 }
1819
1820 header = DeviceFindFeaturePage(Buffer, Usable, FeatureCdrwCAVWrite);
1821 if (header) {
1822 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1823 "CdromGetConfiguration: %s %s\n",
1824 (header->Current ?
1825 "Currently supports" : "Is able to support"),
1826 "CD-RW CAV recording"
1827 ));
1828 }
1829
1830 header = DeviceFindFeaturePage(Buffer, Usable, FeatureMrw);
1831 if (header) {
1832 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1833 "CdromGetConfiguration: %s %s\n",
1834 (header->Current ?
1835 "Currently supports" : "Is able to support"),
1836 "Mount Rainier media"
1837 ));
1838 }
1839
1840 header = DeviceFindFeaturePage(Buffer, Usable, FeatureEnhancedDefectReporting);
1841 if (header) {
1842 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1843 "CdromGetConfiguration: %s %s\n",
1844 (header->Current ?
1845 "Currently supports" : "Is able to support"),
1846 "Enhanced Defect Reporting"
1847 ));
1848 }
1849
1850 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdPlusRW);
1851 if (header) {
1852 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1853 "CdromGetConfiguration: %s %s\n",
1854 (header->Current ?
1855 "Currently supports" : "Is able to support"),
1856 "DVD+RW media"
1857 ));
1858 }
1859
1860 header = DeviceFindFeaturePage(Buffer, Usable, FeatureRigidRestrictedOverwrite);
1861 if (header) {
1862 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1863 "CdromGetConfiguration: %s %s\n",
1864 (header->Current ?
1865 "Currently supports" : "Is able to support"),
1866 "Rigid Restricted Overwrite"
1867 ));
1868 }
1869
1870 header = DeviceFindFeaturePage(Buffer, Usable, FeatureCdTrackAtOnce);
1871 if (header) {
1872 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1873 "CdromGetConfiguration: %s %s\n",
1874 (header->Current ?
1875 "Currently supports" : "Is able to support"),
1876 "CD Recording (Track At Once)"
1877 ));
1878 }
1879
1880 header = DeviceFindFeaturePage(Buffer, Usable, FeatureCdMastering);
1881 if (header) {
1882 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1883 "CdromGetConfiguration: %s %s\n",
1884 (header->Current ?
1885 "Currently supports" : "Is able to support"),
1886 "CD Recording (Mastering)"
1887 ));
1888 }
1889
1890 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdRecordableWrite);
1891 if (header) {
1892 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1893 "CdromGetConfiguration: %s %s\n",
1894 (header->Current ?
1895 "Currently supports" : "Is able to support"),
1896 "DVD Recording (Mastering)"
1897 ));
1898 }
1899
1900 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDDCDRead);
1901 if (header) {
1902 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1903 "CdromGetConfiguration: %s %s\n",
1904 (header->Current ?
1905 "Currently supports" : "Is able to support"),
1906 "DD CD Reading"
1907 ));
1908 }
1909
1910 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDDCDRWrite);
1911 if (header) {
1912 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1913 "CdromGetConfiguration: %s %s\n",
1914 (header->Current ?
1915 "Currently supports" : "Is able to support"),
1916 "DD CD-R Writing"
1917 ));
1918 }
1919
1920 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDDCDRWWrite);
1921 if (header) {
1922 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1923 "CdromGetConfiguration: %s %s\n",
1924 (header->Current ?
1925 "Currently supports" : "Is able to support"),
1926 "DD CD-RW Writing"
1927 ));
1928 }
1929
1930 header = DeviceFindFeaturePage(Buffer, Usable, FeatureLayerJumpRecording);
1931 if (header) {
1932 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1933 "CdromGetConfiguration: %s %s\n",
1934 (header->Current ?
1935 "Currently supports" : "Is able to support"),
1936 "Layer Jump Recording"
1937 ));
1938 }
1939
1940 header = DeviceFindFeaturePage(Buffer, Usable, FeatureHDDVDRead);
1941 if (header) {
1942 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1943 "CdromGetConfiguration: %s %s\n",
1944 (header->Current ?
1945 "Currently supports" : "Is able to support"),
1946 "HD-DVD Reading"
1947 ));
1948 }
1949
1950 header = DeviceFindFeaturePage(Buffer, Usable, FeatureHDDVDWrite);
1951 if (header) {
1952 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1953 "CdromGetConfiguration: %s %s\n",
1954 (header->Current ?
1955 "Currently supports" : "Is able to support"),
1956 "HD-DVD Writing"
1957 ));
1958 }
1959
1960
1961 header = DeviceFindFeaturePage(Buffer, Usable, FeatureSMART);
1962 if (header) {
1963 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1964 "CdromGetConfiguration: %s %s\n",
1965 (header->Current ?
1966 "Currently supports" : "Is able to support"),
1967 "S.M.A.R.T."
1968 ));
1969 }
1970
1971 header = DeviceFindFeaturePage(Buffer, Usable, FeatureCDAudioAnalogPlay);
1972 if (header) {
1973 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1974 "CdromGetConfiguration: %s %s\n",
1975 (header->Current ?
1976 "Currently supports" : "Is able to support"),
1977 "Analogue CD Audio Operations"
1978 ));
1979 }
1980
1981 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdCSS);
1982 if (header) {
1983 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1984 "CdromGetConfiguration: %s %s\n",
1985 (header->Current ?
1986 "Currently supports" : "Is able to support"),
1987 "DVD CSS"
1988 ));
1989 }
1990
1991 header = DeviceFindFeaturePage(Buffer, Usable, FeatureRealTimeStreaming);
1992 if (header) {
1993 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1994 "CdromGetConfiguration: %s %s\n",
1995 (header->Current ?
1996 "Currently supports" : "Is able to support"),
1997 "Real-time Streaming Reads"
1998 ));
1999 }
2000
2001 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDiscControlBlocks);
2002 if (header) {
2003 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
2004 "CdromGetConfiguration: %s %s\n",
2005 (header->Current ?
2006 "Currently supports" : "Is able to support"),
2007 "DVD Disc Control Blocks"
2008 ));
2009 }
2010
2011 header = DeviceFindFeaturePage(Buffer, Usable, FeatureDvdCPRM);
2012 if (header) {
2013 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
2014 "CdromGetConfiguration: %s %s\n",
2015 (header->Current ?
2016 "Currently supports" : "Is able to support"),
2017 "DVD CPRM"
2018 ));
2019 }
2020
2021 header = DeviceFindFeaturePage(Buffer, Usable, FeatureAACS);
2022 if (header) {
2023 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
2024 "CdromGetConfiguration: %s %s\n",
2025 (header->Current ?
2026 "Currently supports" : "Is able to support"),
2027 "AACS"
2028 ));
2029 }
2030
2031#else
2032 PAGED_CODE();
2033
2036
2037#endif // DBG
2038 return;
2039}
2040
2041
2044MediaReadCapacity(
2045 _In_ WDFDEVICE Device
2046 )
2047/*++
2048Routine Description:
2049
2050 Get media capacity
2051
2052Arguments:
2053
2054 Device - the device that owns the media
2055
2056Return Value:
2057
2058 NTSTATUS
2059
2060--*/
2061{
2064 PCDB cdb = NULL;
2065 READ_CAPACITY_DATA capacityData;
2066
2067 PAGED_CODE();
2068
2069 RtlZeroMemory(&srb, sizeof(srb));
2070 RtlZeroMemory(&capacityData, sizeof(capacityData));
2071
2072 cdb = (PCDB)(&srb.Cdb);
2073
2074 //Prepare SCSI command fields
2075 srb.CdbLength = 10;
2077 cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
2078
2079 status = DeviceSendSrbSynchronously(Device,
2080 &srb,
2081 &capacityData,
2082 sizeof(READ_CAPACITY_DATA),
2083 FALSE,
2084 NULL);
2085
2086 //Remember the result
2087 if (!NT_SUCCESS(status))
2088 {
2089 //Set the BytesPerBlock to zero, this is for safe as if error happens this field should stay zero (no change).
2090 //it will be treated as error case in MediaReadCapacityDataInterpret()
2091 capacityData.BytesPerBlock = 0;
2092 }
2093
2094 MediaReadCapacityDataInterpret(Device, &capacityData);
2095
2096 return status;
2097}
2098
2099
2101VOID
2102MediaReadCapacityDataInterpret(
2103 _In_ WDFDEVICE Device,
2105 )
2106/*++
2107Routine Description:
2108
2109 Interpret media capacity and set corresponding fields in device context
2110
2111Arguments:
2112
2113 Device - the device that owns the media
2114
2115 ReadCapacityBuffer - data buffer of capacity
2116
2117Return Value:
2118
2119 none
2120
2121--*/
2122{
2123 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2124 ULONG lastSector = 0;
2125 ULONG bps = 0;
2126 ULONG lastBit = 0;
2127 ULONG bytesPerBlock = 0;
2128 BOOLEAN errorHappened = FALSE;
2129
2130 PAGED_CODE();
2131
2133
2134 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2135 "MediaReadCapacityDataInterpret: Entering\n"));
2136
2137 // Swizzle bytes from Read Capacity and translate into
2138 // the necessary geometry information in the device extension.
2139 bytesPerBlock = ReadCapacityBuffer->BytesPerBlock;
2140
2141 ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&bytesPerBlock)->Byte3;
2142 ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&bytesPerBlock)->Byte2;
2143 ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&bytesPerBlock)->Byte1;
2144 ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&bytesPerBlock)->Byte0;
2145
2146 // Insure that bps is a power of 2.
2147 // This corrects a problem with the HP 4020i CDR where it
2148 // returns an incorrect number for bytes per sector.
2149 if (!bps)
2150 {
2151 // Set disk geometry to default values (per ISO 9660).
2152 bps = 2048;
2153 errorHappened = TRUE;
2154 }
2155 else
2156 {
2157 lastBit = (ULONG)(-1);
2158 while (bps)
2159 {
2160 lastBit++;
2161 bps = (bps >> 1);
2162 }
2163 bps = (1 << lastBit);
2164 }
2165
2166 deviceExtension->DiskGeometry.BytesPerSector = bps;
2167
2168 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2169 "MediaReadCapacityDataInterpret: Calculated bps %#x\n",
2170 deviceExtension->DiskGeometry.BytesPerSector));
2171
2172 // Copy last sector in reverse byte order.
2173 bytesPerBlock = ReadCapacityBuffer->LogicalBlockAddress;
2174
2175 ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&bytesPerBlock)->Byte3;
2176 ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&bytesPerBlock)->Byte2;
2177 ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&bytesPerBlock)->Byte1;
2178 ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&bytesPerBlock)->Byte0;
2179
2180 // Calculate sector to byte shift.
2181 WHICH_BIT(bps, deviceExtension->SectorShift);
2182
2183 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
2184 "MediaReadCapacityDataInterpret: Sector size is %d\n",
2185 deviceExtension->DiskGeometry.BytesPerSector));
2186
2187 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
2188 "MediaReadCapacityDataInterpret: Number of Sectors is %d\n",
2189 lastSector + 1));
2190
2191 // Calculate media capacity in bytes.
2192 if (errorHappened)
2193 {
2194 // Set disk geometry to default values (per ISO 9660).
2195 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff);
2196 }
2197 else
2198 {
2199 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
2200 deviceExtension->PartitionLength.QuadPart =
2201 (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
2202 }
2203
2204 // we've defaulted to 32/64 forever. don't want to change this now...
2205 deviceExtension->DiskGeometry.TracksPerCylinder = 0x40;
2206 deviceExtension->DiskGeometry.SectorsPerTrack = 0x20;
2207
2208 // Calculate number of cylinders.
2209 deviceExtension->DiskGeometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1) / (32 * 64));
2210
2211 deviceExtension->DiskGeometry.MediaType = RemovableMedia;
2212
2213 return;
2214}
2215
2216
2218VOID
2219DevicePickDvdRegion(
2220 _In_ WDFDEVICE Device
2221 )
2222/*++
2223
2224Routine Description:
2225
2226 pick a default dvd region
2227
2228Arguments:
2229
2230 Device - Device Object
2231
2232Return Value:
2233
2234 none
2235
2236--*/
2237{
2239 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2240
2241 // these five pointers all point to dvdReadStructure or part of
2242 // its data, so don't deallocate them more than once!
2243 PDVD_READ_STRUCTURE dvdReadStructure;
2244 PDVD_COPY_PROTECT_KEY copyProtectKey;
2245 PDVD_COPYRIGHT_DESCRIPTOR dvdCopyRight;
2246 PDVD_RPC_KEY rpcKey;
2247 PDVD_SET_RPC_KEY dvdRpcKey;
2248
2249 size_t bytesReturned = 0;
2250 ULONG bufferLen = 0;
2251 UCHAR mediaRegion = 0;
2252 ULONG pickDvdRegion = 0;
2253 ULONG defaultDvdRegion = 0;
2254 ULONG dvdRegion = 0;
2255 WDFKEY registryKey = NULL;
2256
2258
2259 PAGED_CODE();
2260
2261 if ((pickDvdRegion = InterlockedExchange((PLONG)&deviceExtension->DeviceAdditionalData.PickDvdRegion, 0)) == 0)
2262 {
2263 // it was non-zero, so either another thread will do this, or
2264 // we no longer need to pick a region
2265 return;
2266 }
2267
2268 bufferLen = max(
2269 max(sizeof(DVD_DESCRIPTOR_HEADER) +
2271 sizeof(DVD_READ_STRUCTURE)
2272 ),
2275 )
2276 );
2277
2278 dvdReadStructure = (PDVD_READ_STRUCTURE)
2280
2281 if (dvdReadStructure == NULL)
2282 {
2283 InterlockedExchange((PLONG)&deviceExtension->DeviceAdditionalData.PickDvdRegion, pickDvdRegion);
2284 return;
2285 }
2286
2287 copyProtectKey = (PDVD_COPY_PROTECT_KEY)dvdReadStructure;
2288
2289 dvdCopyRight = (PDVD_COPYRIGHT_DESCRIPTOR)
2290 ((PDVD_DESCRIPTOR_HEADER)dvdReadStructure)->Data;
2291
2292 // get the media region
2293 RtlZeroMemory (dvdReadStructure, bufferLen);
2294 dvdReadStructure->Format = DvdCopyrightDescriptor;
2295
2296 // Build and send a request for READ_KEY
2297 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
2298 "DevicePickDvdRegion (%p): Getting Copyright Descriptor\n",
2299 Device));
2300
2301 status = ReadDvdStructure(deviceExtension,
2302 NULL,
2303 dvdReadStructure,
2304 sizeof(DVD_READ_STRUCTURE),
2305 dvdReadStructure,
2307 &bytesReturned);
2308
2309 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
2310 "DevicePickDvdRegion (%p): Got Copyright Descriptor %x\n",
2311 Device, status));
2312
2313 if ((NT_SUCCESS(status)) &&
2314 (dvdCopyRight->CopyrightProtectionType == 0x01))
2315 {
2316 // keep the media region bitmap around
2317 // a 1 means ok to play
2318 if (dvdCopyRight->RegionManagementInformation == 0xff)
2319 {
2320 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2321 "DevicePickDvdRegion (%p): RegionManagementInformation "
2322 "is set to dis-allow playback for all regions. This is "
2323 "most likely a poorly authored disc. defaulting to all "
2324 "region disc for purpose of choosing initial region\n",
2325 Device));
2326 dvdCopyRight->RegionManagementInformation = 0;
2327 }
2328
2329 mediaRegion = ~dvdCopyRight->RegionManagementInformation;
2330 }
2331 else
2332 {
2333 // can't automatically pick a default region on a drive without media, so just exit
2334 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2335 "DevicePickDvdRegion (%p): failed to auto-choose a region due to status %x getting copyright descriptor\n",
2336 Device, status));
2337 goto getout;
2338 }
2339
2340 // get the device region
2341 RtlZeroMemory (copyProtectKey, bufferLen);
2342 copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH;
2343 copyProtectKey->KeyType = DvdGetRpcKey;
2344
2345 // Build and send a request for READ_KEY for RPC key
2346 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
2347 "DevicePickDvdRegion (%p): Getting RpcKey\n",
2348 Device));
2349 status = DvdStartSessionReadKey(deviceExtension,
2351 NULL,
2352 copyProtectKey,
2354 copyProtectKey,
2356 &bytesReturned);
2357
2358 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
2359 "DevicePickDvdRegion (%p): Got RpcKey %x\n",
2360 Device, status));
2361
2362 if (!NT_SUCCESS(status))
2363 {
2364 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2365 "DevicePickDvdRegion (%p): failed to get RpcKey from "
2366 "a DVD Device\n", Device));
2367 goto getout;
2368 }
2369
2370 // so we now have what we can get for the media region and the
2371 // drive region. we will not set a region if the drive has one
2372 // set already (mask is not all 1's), nor will we set a region
2373 // if there are no more user resets available.
2374 rpcKey = (PDVD_RPC_KEY)copyProtectKey->KeyData;
2375
2376 if (rpcKey->RegionMask != 0xff)
2377 {
2378 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2379 "DevicePickDvdRegion (%p): not picking a region since "
2380 "it is already chosen\n", Device));
2381 goto getout;
2382 }
2383
2384 if (rpcKey->UserResetsAvailable <= 1)
2385 {
2386 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2387 "DevicePickDvdRegion (%p): not picking a region since "
2388 "only one change remains\n", Device));
2389 goto getout;
2390 }
2391
2392 // OOBE sets this key based upon the system locale
2393 status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(),
2394 KEY_READ,
2396 &registryKey);
2397
2398 if (NT_SUCCESS(status))
2399 {
2400 status = WdfRegistryQueryULong(registryKey,
2401 &registryValueName,
2402 &defaultDvdRegion);
2403
2404 WdfRegistryClose(registryKey);
2405 }
2406
2407 if (!NT_SUCCESS(status))
2408 {
2409 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2410 "DevicePickDvdRegion (%p): failed to read registry value due to status %x\n",
2411 Device, status));
2412
2413 // by default the default Dvd region is 0
2414 defaultDvdRegion = 0;
2416 }
2417
2418 if (defaultDvdRegion > DVD_MAX_REGION)
2419 {
2420 // the registry has a bogus default
2421 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2422 "DevicePickDvdRegion (%p): registry has a bogus default "
2423 "region value of %x\n", Device, defaultDvdRegion));
2424
2425 defaultDvdRegion = 0;
2426 }
2427
2428 // if defaultDvdRegion == 0, it means no default.
2429
2430 // we will select the initial dvd region for the user
2431
2432 if ((defaultDvdRegion != 0) &&
2433 (mediaRegion & (1 << (defaultDvdRegion - 1))))
2434 {
2435 // first choice:
2436 // the media has region that matches
2437 // the default dvd region.
2438 dvdRegion = (1 << (defaultDvdRegion - 1));
2439
2440 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2441 "DevicePickDvdRegion (%p): Choice #1: media matches "
2442 "drive's default, chose region %x\n", Device, dvdRegion));
2443 }
2444 else if (mediaRegion)
2445 {
2446 // second choice:
2447 // pick the lowest region number from the media
2448 UCHAR mask = 1;
2449 dvdRegion = 0;
2450
2451 while (mediaRegion && !dvdRegion)
2452 {
2453 // pick the lowest bit
2454 dvdRegion = mediaRegion & mask;
2455 mask <<= 1;
2456 }
2457
2458 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2459 "DevicePickDvdRegion (%p): Choice #2: choosing lowest "
2460 "media region %x\n", Device, dvdRegion));
2461 }
2462 else if (defaultDvdRegion)
2463 {
2464 // third choice:
2465 // default dvd region from the dvd class installer
2466 dvdRegion = (1 << (defaultDvdRegion - 1));
2467 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2468 "DevicePickDvdRegion (%p): Choice #3: using default "
2469 "region for this install %x\n", Device, dvdRegion));
2470 }
2471 else
2472 {
2473 // unable to pick one for the user -- this should rarely
2474 // happen, since the proppage dvd class installer sets
2475 // the key based upon the system locale
2476 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2477 "DevicePickDvdRegion (%p): Choice #4: failed to choose "
2478 "a media region\n", Device));
2479 goto getout;
2480 }
2481
2482 // now that we've chosen a region, set the region by sending the
2483 // appropriate request to the drive
2484 RtlZeroMemory (copyProtectKey, bufferLen);
2485 copyProtectKey->KeyLength = DVD_SET_RPC_KEY_LENGTH;
2486 copyProtectKey->KeyType = DvdSetRpcKey;
2487 dvdRpcKey = (PDVD_SET_RPC_KEY)copyProtectKey->KeyData;
2488 dvdRpcKey->PreferredDriveRegionCode = (UCHAR)~dvdRegion;
2489
2490 // Build and send request for SEND_KEY
2491 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
2492 "DevicePickDvdRegion (%p): Sending new Rpc Key to region %x\n",
2493 Device, dvdRegion));
2494
2495 status = DvdSendKey(deviceExtension,
2496 NULL,
2497 copyProtectKey,
2499 &bytesReturned);
2500
2501 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
2502 "DevicePickDvdRegion (%p): Sent new Rpc Key %x\n",
2503 Device, status));
2504
2505 if (!NT_SUCCESS(status))
2506 {
2507 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL, "DevicePickDvdRegion (%p): unable to set dvd initial "
2508 " region code (%x)\n", Device, status));
2509 }
2510 else
2511 {
2512 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL, "DevicePickDvdRegion (%p): Successfully set dvd "
2513 "initial region\n", Device));
2514
2515 pickDvdRegion = 0;
2516 }
2517
2518getout:
2519 if (dvdReadStructure)
2520 {
2521 FREE_POOL(dvdReadStructure);
2522 }
2523
2524 // update the new PickDvdRegion value
2525 InterlockedExchange((PLONG)&deviceExtension->DeviceAdditionalData.PickDvdRegion, pickDvdRegion);
2526
2527 return;
2528}
2529
2532DeviceRegisterInterface(
2533 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2535 )
2536/*++
2537Routine Description:
2538
2539 used to register device class interface or mount device interface
2540
2541Arguments:
2542
2543 DeviceExtension - device context
2544
2545 InterfaceType - interface type to be registered.
2546
2547Return Value:
2548
2549 NTSTATUS
2550
2551--*/
2552{
2554 WDFSTRING string = NULL;
2555 GUID* interfaceGuid = NULL;
2556 PUNICODE_STRING savingString = NULL;
2557 BOOLEAN setRestricted = FALSE;
2558 UNICODE_STRING localString;
2559
2560 PAGED_CODE();
2561
2562 //Get parameters
2563 switch(InterfaceType)
2564 {
2566 interfaceGuid = (LPGUID)&GUID_DEVINTERFACE_CDROM;
2567 setRestricted = TRUE;
2568 savingString = &localString;
2569 break;
2571 interfaceGuid = (LPGUID)&MOUNTDEV_MOUNTED_DEVICE_GUID;
2572 savingString = &(DeviceExtension->MountedDeviceInterfaceName);
2573 break;
2574 default:
2576 }
2577
2578 status = WdfDeviceCreateDeviceInterface(DeviceExtension->Device,
2579 interfaceGuid,
2580 NULL);
2581
2582 if (!NT_SUCCESS(status))
2583 {
2584 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_INIT,
2585 "DeviceRegisterInterface: Unable to register cdrom "
2586 "DCA for fdo %p type: %s [%lx]\n",
2587 DeviceExtension->Device,
2588 (InterfaceType == CdRomDeviceInterface)? "CdRom Interface" : "Mounted Device Interface",
2589 status));
2590 }
2591
2592 // Retrieve interface string
2593 if (NT_SUCCESS(status))
2594 {
2595 // The string object will be released when its parent object is released.
2596 WDF_OBJECT_ATTRIBUTES attributes;
2597
2598 WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
2599 attributes.ParentObject = DeviceExtension->Device;
2600
2601 status = WdfStringCreate(WDF_NO_OBJECT_ATTRIBUTES,
2602 NULL,
2603 &string);
2604 }
2605
2606 if (NT_SUCCESS(status))
2607 {
2608 status = WdfDeviceRetrieveDeviceInterfaceString(DeviceExtension->Device,
2609 interfaceGuid,
2610 NULL,
2611 string);
2612 }
2613
2614 if (NT_SUCCESS(status))
2615 {
2616 WdfStringGetUnicodeString(string, savingString);
2617
2618 if (setRestricted) {
2619
2620
2621 WdfObjectDelete(string);
2622 }
2623 }
2624
2625 return status;
2626} // end DeviceRegisterInterface()
2627
2628
2629VOID
2630NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2632 _In_ WDFWORKITEM WorkItem
2633 )
2634/*++
2635
2636Routine Description:
2637
2638 This workitem is called on a media change when the CDROM device
2639 speed should be restored to the default value.
2640
2641Arguments:
2642
2643 Fdo - Supplies the device object for the CDROM device.
2644 WorkItem - Supplies the pointer to the workitem.
2645
2646Return Value:
2647
2648 None
2649
2650--*/
2651{
2653 WDFDEVICE device = WdfWorkItemGetParentObject(WorkItem);
2654 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
2655 PPERFORMANCE_DESCRIPTOR perfDescriptor;
2656 ULONG transferLength = sizeof(PERFORMANCE_DESCRIPTOR);
2657 SCSI_REQUEST_BLOCK srb = {0};
2658 PCDB cdb = (PCDB)srb.Cdb;
2659
2660 PAGED_CODE();
2661
2662 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "DeviceRestoreDefaultSpeed: Restore device speed for %p\n", device));
2663
2664 perfDescriptor = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
2665 transferLength,
2667 if (perfDescriptor == NULL)
2668 {
2669 return;
2670 }
2671
2672 RtlZeroMemory(perfDescriptor, transferLength);
2673
2674 perfDescriptor->RestoreDefaults = TRUE;
2675
2676 srb.TimeOutValue = deviceExtension->TimeOutValue;
2677
2678 srb.CdbLength = 12;
2679 cdb->SET_STREAMING.OperationCode = SCSIOP_SET_STREAMING;
2680 REVERSE_BYTES_SHORT(&cdb->SET_STREAMING.ParameterListLength, &transferLength);
2681
2682 status = DeviceSendSrbSynchronously(device,
2683 &srb,
2684 perfDescriptor,
2685 transferLength,
2686 TRUE,
2687 NULL);
2688 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2689 "DeviceRestoreDefaultSpeed: Set Streaming command completed with status: 0x%X\n", status));
2690
2691 FREE_POOL(perfDescriptor);
2692 WdfObjectDelete(WorkItem);
2693
2694 return;
2695}
2696
2697// custom string match -- careful!
2699BOOLEAN
2700StringsAreMatched(
2701 _In_opt_z_ PCHAR StringToMatch,
2703 )
2704/*++
2705
2706Routine Description:
2707
2708 compares if two strings are identical
2709
2710Arguments:
2711
2712 StringToMatch - source string.
2713 TargetString - target string.
2714
2715Return Value:
2716
2717 BOOLEAN - TRUE (identical); FALSE (not match)
2718
2719--*/
2720{
2721 size_t length;
2722
2723 PAGED_CODE();
2724
2726
2727 // if no match requested, return TRUE
2728 if (StringToMatch == NULL)
2729 {
2730 return TRUE;
2731 }
2732
2733 // cache the string length for efficiency
2734 length = strlen(StringToMatch);
2735
2736 // ZERO-length strings may only match zero-length strings
2737 if (length == 0)
2738 {
2739 return (strlen(TargetString) == 0);
2740 }
2741
2742 // strncmp returns zero if the strings match
2743 return (strncmp(StringToMatch, TargetString, length) == 0);
2744}
2745
2746
2749 _In_ WDFREQUEST Request,
2751 )
2752/*++
2753
2754Routine Description:
2755
2756 set the request object context fields
2757
2758Arguments:
2759
2760 Request - request object.
2761 Handler - the function that finally handles this request.
2762
2763Return Value:
2764
2765 NTSTATUS
2766
2767--*/
2768{
2770 PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
2771 PKEVENT syncEvent = NULL;
2772
2773 syncEvent = ExAllocatePoolWithTag(NonPagedPoolNx,
2774 sizeof(KEVENT),
2776
2777 if (syncEvent == NULL)
2778 {
2779 // memory allocation failed.
2781 }
2782 else
2783 {
2784 // now, put the special synchronization information into the context
2785 requestContext->SyncRequired = TRUE;
2786 requestContext->SyncEvent = syncEvent;
2787 requestContext->SyncCallback = Handler;
2788
2790 }
2791
2792 return status;
2793}
2794
2795
2798 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2799 _In_ WDFREQUEST Request,
2801 _Out_ size_t * DataLength
2802 )
2803/*++
2804
2805Routine Description:
2806
2807
2808
2809Arguments:
2810
2811 DeviceExtension - device context
2812 Request - request object.
2813 RequestParameters - request parameter
2814 DataLength - transferred data length.
2815
2816Return Value:
2817
2818 NTSTATUS
2819
2820--*/
2821{
2823 PSTORAGE_DEVICE_ID_DESCRIPTOR deviceIdDescriptor = NULL;
2824 PSTORAGE_DESCRIPTOR_HEADER descHeader = NULL;
2826
2827 *DataLength = 0;
2828
2829 // Get the VPD page 83h data.
2830 status = DeviceRetrieveDescriptor(DeviceExtension->Device,
2831 &propertyId,
2832 (PSTORAGE_DESCRIPTOR_HEADER*)&deviceIdDescriptor);
2833
2834 if (NT_SUCCESS(status) && (deviceIdDescriptor == NULL))
2835 {
2837 }
2838
2839 if (NT_SUCCESS(status))
2840 {
2841 status = WdfRequestRetrieveOutputBuffer(Request,
2842 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
2843 &descHeader,
2844 NULL);
2845 }
2846
2847 if (NT_SUCCESS(status))
2848 {
2850 ULONG offset = descHeader->Size;
2851 PUCHAR dest = (PUCHAR)descHeader + offset;
2852 size_t outputBufferSize;
2853
2854 outputBufferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength;
2855
2856 // Adjust required size and potential destination location.
2857 status = RtlULongAdd(descHeader->Size, deviceIdDescriptor->Size, &descHeader->Size);
2858
2859 if (NT_SUCCESS(status) &&
2860 (outputBufferSize < descHeader->Size))
2861 {
2862 // Output buffer is too small. Return error and make sure
2863 // the caller gets info about required buffer size.
2864 *DataLength = descHeader->Size;
2866 }
2867
2868 if (NT_SUCCESS(status))
2869 {
2870 storageDuid = (PSTORAGE_DEVICE_UNIQUE_IDENTIFIER)descHeader;
2871 storageDuid->StorageDeviceIdOffset = offset;
2872
2874 deviceIdDescriptor,
2875 deviceIdDescriptor->Size);
2876
2877 *DataLength = storageDuid->Size;
2879 }
2880
2881 FREE_POOL(deviceIdDescriptor);
2882 }
2883
2884 return status;
2885}
2886
2889 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2890 _In_ WDFREQUEST Request,
2892 _Out_ size_t * DataLength
2893 )
2894/*++
2895
2896Routine Description:
2897
2898
2899
2900Arguments:
2901
2902 DeviceExtension - device context
2903 Request - request object.
2904 RequestParameters - request parameter
2905 DataLength - transferred data length.
2906
2907Return Value:
2908
2909 NTSTATUS
2910
2911--*/
2912{
2914 PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = DeviceExtension->DeviceDescriptor;
2915 PSTORAGE_DESCRIPTOR_HEADER descHeader = NULL;
2917 PUCHAR dest = NULL;
2918
2919 if (deviceDescriptor == NULL)
2920 {
2922 }
2923
2924 if (NT_SUCCESS(status))
2925 {
2926 status = WdfRequestRetrieveOutputBuffer(Request,
2927 RequestParameters.Parameters.DeviceIoControl.OutputBufferLength,
2928 &descHeader,
2929 NULL);
2930 }
2931
2932 if (NT_SUCCESS(status) &&
2933 (deviceDescriptor->SerialNumberOffset == 0))
2934 {
2936 }
2937
2938 // Use this info only if serial number is available.
2939 if (NT_SUCCESS(status))
2940 {
2941 ULONG offset = descHeader->Size;
2942 size_t outputBufferSize = RequestParameters.Parameters.DeviceIoControl.OutputBufferLength;
2943
2944 // Adjust required size and potential destination location.
2945 dest = (PUCHAR)descHeader + offset;
2946
2947 status = RtlULongAdd(descHeader->Size, deviceDescriptor->Size, &descHeader->Size);
2948
2949 if (NT_SUCCESS(status) &&
2950 (outputBufferSize < descHeader->Size))
2951 {
2952 // Output buffer is too small. Return error and make sure
2953 // the caller get info about required buffer size.
2954 *DataLength = descHeader->Size;
2956 }
2957
2958 if (NT_SUCCESS(status))
2959 {
2960 storageDuid = (PSTORAGE_DEVICE_UNIQUE_IDENTIFIER)descHeader;
2961 storageDuid->StorageDeviceOffset = offset;
2962
2964 deviceDescriptor,
2965 deviceDescriptor->Size);
2966
2967 *DataLength = storageDuid->Size;
2969 }
2970 }
2971
2972 return status;
2973}
2974
2976ULONG
2977DeviceRetrieveModeSenseUsingScratch(
2978 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
2979 _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
2983 )
2984/*++
2985
2986Routine Description:
2987
2988 retrieve mode sense informaiton of the device
2989
2990Arguments:
2991
2992 DeviceExtension - device context
2993 ModeSenseBuffer - buffer to savee the mode sense info.
2994 Length - buffer length
2995 PageCode - .
2996 PageControl -
2997
2998Return Value:
2999
3000 ULONG - transferred data length
3001
3002--*/
3003{
3005 ULONG transferSize = min(Length, DeviceExtension->ScratchContext.ScratchBufferSize);
3006 CDB cdb;
3007
3008 PAGED_CODE();
3009
3010 ScratchBuffer_BeginUse(DeviceExtension);
3011
3012 RtlZeroMemory(&cdb, sizeof(CDB));
3013 // Set up the CDB
3014 cdb.MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
3015 cdb.MODE_SENSE.PageCode = PageCode;
3016 cdb.MODE_SENSE.Pc = PageControl;
3017 cdb.MODE_SENSE.AllocationLength = (UCHAR)transferSize;
3018
3019 status = ScratchBuffer_ExecuteCdb(DeviceExtension, NULL, transferSize, TRUE, &cdb, 6);
3020
3021 if (NT_SUCCESS(status))
3022 {
3023 transferSize = min(Length, DeviceExtension->ScratchContext.ScratchSrb->DataTransferLength);
3024 RtlCopyMemory(ModeSenseBuffer,
3025 DeviceExtension->ScratchContext.ScratchBuffer,
3026 transferSize);
3027 }
3028
3029 ScratchBuffer_EndUse(DeviceExtension);
3030
3031 return transferSize;
3032}
3033
3035PVOID
3036ModeSenseFindSpecificPage(
3037 _In_reads_bytes_(Length) PCHAR ModeSenseBuffer,
3038 _In_ size_t Length,
3040 _In_ BOOLEAN Use6BytesCdb
3041 )
3042/*++
3043
3044Routine Description:
3045
3046 This routine scans through the mode sense data and finds the requested
3047 mode sense page code.
3048
3049Arguments:
3050 ModeSenseBuffer - Supplies a pointer to the mode sense data.
3051
3052 Length - Indicates the length of valid data.
3053
3054 PageMode - Supplies the page mode to be searched for.
3055
3056 Use6BytesCdb - Indicates whether 6 or 10 byte mode sense was used.
3057
3058Return Value:
3059
3060 A pointer to the the requested mode page. If the mode page was not found
3061 then NULL is return.
3062
3063--*/
3064{
3065 PCHAR limit;
3066 ULONG parameterHeaderLength;
3067 PVOID result = NULL;
3068
3069 PAGED_CODE();
3070
3071 limit = ModeSenseBuffer + Length;
3072 parameterHeaderLength = (Use6BytesCdb)
3073 ? sizeof(MODE_PARAMETER_HEADER)
3074 : sizeof(MODE_PARAMETER_HEADER10);
3075
3076 if (Length >= parameterHeaderLength)
3077 {
3078 PMODE_PARAMETER_HEADER10 modeParam10;
3079 ULONG blockDescriptorLength;
3080
3081 // Skip the mode select header and block descriptors.
3082 if (Use6BytesCdb)
3083 {
3084 blockDescriptorLength = ((PMODE_PARAMETER_HEADER)ModeSenseBuffer)->BlockDescriptorLength;
3085 }
3086 else
3087 {
3088 modeParam10 = (PMODE_PARAMETER_HEADER10) ModeSenseBuffer;
3089 blockDescriptorLength = modeParam10->BlockDescriptorLength[1];
3090 }
3091
3092 ModeSenseBuffer += parameterHeaderLength + blockDescriptorLength;
3093
3094 // ModeSenseBuffer now points at pages. Walk the pages looking for the
3095 // requested page until the limit is reached.
3096 while (ModeSenseBuffer +
3098 {
3099 if (((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageCode == PageMode)
3100 {
3101 // found the mode page. make sure it's safe to touch it all
3102 // before returning the pointer to caller
3103 if (ModeSenseBuffer + ((PMODE_DISCONNECT_PAGE)ModeSenseBuffer)->PageLength > limit)
3104 {
3105 // Return NULL since the page is not safe to access in full
3106 result = NULL;
3107 }
3108 else
3109 {
3110 result = ModeSenseBuffer;
3111 }
3112 break;
3113 }
3114
3115 // Advance to the next page which is 4-byte-aligned offset after this page.
3116 ModeSenseBuffer += ((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageLength +
3118 }
3119 }
3120
3121 return result;
3122} // end ModeSenseFindSpecificPage()
3123
3124
3127PerformEjectionControl(
3128 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3129 _In_ WDFREQUEST Request,
3132 )
3133/*++
3134
3135Routine Description:
3136
3137 ejection control process
3138
3139Arguments:
3140
3141 DeviceExtension - device extension
3142 Request - WDF request to be used for communication with the device
3143 LockType - the type of lock
3144 Lock - if TRUE, lock the device; if FALSE, unlock it
3145
3146Return Value:
3147
3148 NTSTATUS
3149
3150--*/
3151{
3153 PFILE_OBJECT_CONTEXT fileObjectContext = NULL;
3155 PCDB cdb = NULL;
3156
3157 LONG newLockCount = 0;
3158 LONG newProtectedLockCount = 0;
3159 LONG newInternalLockCount = 0;
3160 LONG newFileLockCount = 0;
3161 BOOLEAN countChanged = FALSE;
3162 BOOLEAN previouslyLocked = FALSE;
3163 BOOLEAN nowLocked = FALSE;
3164
3165 PAGED_CODE();
3166
3167 // Prevent race conditions while working with lock counts
3168 status = WdfWaitLockAcquire(DeviceExtension->EjectSynchronizationLock, NULL);
3169 if (!NT_SUCCESS(status))
3170 {
3172 }
3173
3174 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
3175 "PerformEjectionControl: "
3176 "Received request for %s lock type\n",
3178 ));
3179
3180
3181 // If this is a "secured" request, retrieve the file object context
3183 {
3184 WDFFILEOBJECT fileObject = NULL;
3185
3186 fileObject = WdfRequestGetFileObject(Request);
3187
3188 if (fileObject == NULL)
3189 {
3191
3192 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3193 "FileObject does not match to the one in IRP_MJ_CREATE, KMDF returns NULL\n"));
3194 goto Exit;
3195 }
3196
3197 fileObjectContext = FileObjectGetContext(fileObject);
3198 NT_ASSERT(fileObjectContext != NULL);
3199 }
3200
3201 // Lock counts should never fall below 0
3202 NT_ASSERT(DeviceExtension->LockCount >= 0);
3203 NT_ASSERT(DeviceExtension->ProtectedLockCount >= 0);
3204 NT_ASSERT(DeviceExtension->InternalLockCount >= 0);
3205
3206 // Get the current lock counts
3207 newLockCount = DeviceExtension->LockCount;
3208 newProtectedLockCount = DeviceExtension->ProtectedLockCount;
3209 newInternalLockCount = DeviceExtension->InternalLockCount;
3210 if (fileObjectContext)
3211 {
3212 // fileObjectContext->LockCount is ULONG and should always >= 0
3213 newFileLockCount = fileObjectContext->LockCount;
3214 }
3215
3216 // Determine which lock counts need to be changed and how
3217 if (Lock && LockType == SimpleMediaLock)
3218 {
3219 newLockCount++;
3220 countChanged = TRUE;
3221 }
3222 else if (Lock && LockType == SecureMediaLock)
3223 {
3224 newFileLockCount++;
3225 newProtectedLockCount++;
3226 countChanged = TRUE;
3227 }
3228 else if (Lock && LockType == InternalMediaLock)
3229 {
3230 newInternalLockCount++;
3231 countChanged = TRUE;
3232 }
3233 else if (!Lock && LockType == SimpleMediaLock)
3234 {
3235 if (newLockCount != 0)
3236 {
3237 newLockCount--;
3238 countChanged = TRUE;
3239 }
3240 }
3241 else if (!Lock && LockType == SecureMediaLock)
3242 {
3243 if ( (newFileLockCount == 0) || (newProtectedLockCount == 0) )
3244 {
3246 goto Exit;
3247 }
3248 newFileLockCount--;
3249 newProtectedLockCount--;
3250 countChanged = TRUE;
3251 }
3252 else if (!Lock && LockType == InternalMediaLock)
3253 {
3254 NT_ASSERT(newInternalLockCount != 0);
3255 newInternalLockCount--;
3256 countChanged = TRUE;
3257 }
3258
3259 if ( (DeviceExtension->LockCount != 0) ||
3260 (DeviceExtension->ProtectedLockCount != 0) ||
3261 (DeviceExtension->InternalLockCount != 0) )
3262 {
3263 previouslyLocked = TRUE;
3264 }
3265 if ( (newLockCount != 0) ||
3266 (newProtectedLockCount != 0) ||
3267 (newInternalLockCount != 0) )
3268 {
3269 nowLocked = TRUE;
3270 }
3271
3272 // Only send command down to device when necessary
3273 if (previouslyLocked != nowLocked)
3274 {
3275 // Compose and send the PREVENT ALLOW MEDIA REMOVAL command.
3276 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
3277
3278 srb.CdbLength = 6;
3279 srb.TimeOutValue = DeviceExtension->TimeOutValue;
3280
3281 cdb = (PCDB)&srb.Cdb;
3282 cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
3283 cdb->MEDIA_REMOVAL.Prevent = Lock;
3284
3285 status = DeviceSendSrbSynchronously(DeviceExtension->Device,
3286 &srb,
3287 NULL,
3288 0,
3289 FALSE,
3290 Request);
3291 }
3292
3293Exit:
3294
3295 // Store the updated lock counts on success
3296 if (countChanged && NT_SUCCESS(status))
3297 {
3298 DeviceExtension->LockCount = newLockCount;
3299 DeviceExtension->ProtectedLockCount = newProtectedLockCount;
3300 DeviceExtension->InternalLockCount = newInternalLockCount;
3301 if (fileObjectContext)
3302 {
3303 fileObjectContext->LockCount = newFileLockCount;
3304 }
3305 }
3306
3307 WdfWaitLockRelease(DeviceExtension->EjectSynchronizationLock);
3308
3309 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
3310 "PerformEjectionControl: %!STATUS!, "
3311 "Count Changed: %d, Command Sent: %d, "
3312 "Current Counts: Internal: %x Secure: %x Simple: %x\n",
3313 status,
3314 countChanged,
3315 previouslyLocked != nowLocked,
3316 DeviceExtension->InternalLockCount,
3317 DeviceExtension->ProtectedLockCount,
3318 DeviceExtension->LockCount
3319 ));
3320
3321 return status;
3322}
3323
3324
3327DeviceUnlockExclusive(
3328 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3329 _In_ WDFFILEOBJECT FileObject,
3331 )
3332/*++
3333
3334Routine Description:
3335
3336 to unlock the exclusive lock
3337
3338Arguments:
3339
3340 DeviceExtension - device context
3341 FileObject - file object that currently holds the lock
3342 IgnorePreviousMediaChanges - if TRUE, ignore previously accumulated media changes
3343
3344Return Value:
3345
3346 NTSTATUS
3347
3348--*/
3349{
3351 PCDROM_DATA cdData = &DeviceExtension->DeviceAdditionalData;
3352 PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo;
3353 BOOLEAN ANPending = 0;
3354 LONG requestInUse = 0;
3355
3356 PAGED_CODE();
3357
3358 if (!EXCLUSIVE_MODE(cdData))
3359 {
3360 // Device is not locked for exclusive access.
3361 // Can not process unlock request.
3362 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3363 "RequestHandleExclusiveAccessUnlockDevice: Device not locked for exclusive access, can't unlock device.\n"));
3365 }
3366 else if (!EXCLUSIVE_OWNER(cdData, FileObject))
3367 {
3368 // Request not from the exclusive owner, can't unlock the device.
3369 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3370 "RequestHandleExclusiveAccessUnlockDevice: Unable to unlock device, invalid file object\n"));
3371
3373 }
3374
3375 if (NT_SUCCESS(status))
3376 {
3377 // Unless we were explicitly requested not to do so, generate a media removal notification
3378 // followed by a media arrival notification similar to volume lock/unlock file system events.
3380 {
3381 MEDIA_CHANGE_DETECTION_STATE previousMediaState = MediaUnknown;
3382
3383 // Change the media state to "unavailable", which will cause a removal notification if the media
3384 // was previously present. At the same time, store the previous state in previousMediaState.
3385 DeviceSetMediaChangeStateEx(DeviceExtension, MediaUnavailable, &previousMediaState);
3386 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
3387 "DeviceUnlockExclusive: Changing the media state to MediaUnavailable\n"));
3388
3389 // Restore the previous media state, which will cause a media arrival notification if the media
3390 // was originally present.
3391 DeviceSetMediaChangeStateEx(DeviceExtension, previousMediaState, NULL);
3392 }
3393
3394 // Set DO_VERIFY_VOLUME so that the file system will remount on it.
3395 if (IsVolumeMounted(DeviceExtension->DeviceObject))
3396 {
3397 SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
3398 }
3399
3400 // Set MMC state to update required
3401 cdData->Mmc.WriteAllowed = FALSE;
3403
3404 // Send unlock notification
3405 DeviceSendNotification(DeviceExtension,
3406 &GUID_IO_CDROM_EXCLUSIVE_UNLOCK,
3407 0,
3408 NULL);
3409
3411
3412 if ((info != NULL) && (info->AsynchronousNotificationSupported != FALSE))
3413 {
3414 ANPending = info->ANSignalPendingDueToExclusiveLock;
3415 info->ANSignalPendingDueToExclusiveLock = FALSE;
3416
3417 if ((ANPending != FALSE) && (info->MediaChangeDetectionDisableCount == 0))
3418 {
3419 // if the request is not in use, mark it as such.
3420 requestInUse = InterlockedCompareExchange((PLONG)&info->MediaChangeRequestInUse, 1, 0);
3421
3422 if (requestInUse == 0)
3423 {
3424 // The last MCN finished. ok to issue the new one.
3425 RequestSetupMcnSyncIrp(DeviceExtension);
3426
3427 // The irp will go into KMDF framework and a request will be created there to represent it.
3428 IoCallDriver(DeviceExtension->DeviceObject, info->MediaChangeSyncIrp);
3429 }
3430 }
3431 }
3432 }
3433
3434 return status;
3435}
3436
3437
3438VOID
3440 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3441 _In_ WDFREQUEST Request,
3444 )
3445{
3446#ifdef DBG
3447 ULONG ioctlCode = 0;
3448 WDF_REQUEST_PARAMETERS requestParameters;
3449
3450 // Get the Request parameters
3451 WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
3452 WdfRequestGetParameters(Request, &requestParameters);
3453
3454 if (requestParameters.Type == WdfRequestTypeDeviceControl)
3455 {
3456 ioctlCode = requestParameters.Parameters.DeviceIoControl.IoControlCode;
3457
3458 if (requestParameters.Parameters.DeviceIoControl.IoControlCode != IOCTL_MCN_SYNC_FAKE_IOCTL)
3459 {
3460 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
3461 "Request complete - IOCTL - code: %X; Status: %X; Information: %X\n",
3462 ioctlCode,
3463 Status,
3464 (ULONG)Information));
3465 }
3466 else
3467 {
3468 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
3469 "Request complete - IOCTL - code: %X; Status: %X; Information: %X\n",
3470 ioctlCode,
3471 Status,
3472 (ULONG)Information));
3473 }
3474 }
3475 else if (requestParameters.Type == WdfRequestTypeRead)
3476 {
3477 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
3478 "Request complete - READ - Starting Offset: %X; Length: %X; Transferred Length: %X; Status: %X\n",
3479 (ULONG)requestParameters.Parameters.Read.DeviceOffset,
3480 (ULONG)requestParameters.Parameters.Read.Length,
3482 Status));
3483 }
3484 else if (requestParameters.Type == WdfRequestTypeWrite)
3485 {
3486 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL,
3487 "Request complete - WRITE - Starting Offset: %X; Length: %X; Transferred Length: %X; Status: %X\n",
3488 (ULONG)requestParameters.Parameters.Write.DeviceOffset,
3489 (ULONG)requestParameters.Parameters.Write.Length,
3491 Status));
3492 }
3493#endif
3494
3496 {
3497 PIRP irp = WdfRequestWdmGetIrp(Request);
3498 if (irp->Tail.Overlay.Thread)
3499 {
3500 IoSetHardErrorOrVerifyDevice(irp, DeviceExtension->DeviceObject);
3501 }
3502 }
3503
3504 if (!NT_SUCCESS(Status) && DeviceExtension->SurpriseRemoved == TRUE)
3505 {
3506 // IMAPI expects ERROR_DEV_NOT_EXISTS if recorder has been surprised removed,
3507 // or it will retry WRITE commands for up to 3 minutes
3508 // CDROM behavior should be consistent for all requests, including SCSI pass-through
3510 }
3511
3512 WdfRequestCompleteWithInformation(Request, Status, Information);
3513
3514 return;
3515}
3516
3517
3518VOID
3519NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3521 _In_ WDFREQUEST Request,
3522 _In_ WDFIOTARGET Target,
3525 )
3526/*++
3527
3528Routine Description:
3529
3530 This is a dummy competion routine that simply calls WdfRequestComplete. We have to use
3531 this dummy competion routine instead of WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET, because
3532 the latter causes the framework to not check if the I/O target is closed or not.
3533
3534Arguments:
3535
3536 Request - completed request
3537 Target - the I/O target that completed the request
3538 Params - request parameters
3539 Context - not used
3540
3541Return Value:
3542
3543 none
3544
3545--*/
3546{
3550
3551 WdfRequestCompleteWithInformation(Request,
3552 WdfRequestGetStatus(Request),
3553 WdfRequestGetInformation(Request));
3554}
3555
3556
3559DeviceSendPowerDownProcessRequest(
3560 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3563 )
3564/*++
3565
3566Routine Description:
3567
3568 This function is called during processing power down request.
3569 It is used to send either SYNC CACHE command or STOP UNIT command.
3570
3571 Caller should set proper value in deviceExtension->PowerContext.PowerChangeState.PowerDown
3572 to trigger the correct command be sent.
3573
3574Arguments:
3575
3576 DeviceExtension -
3577
3578 CompletionRoutine - Completion routine that needs to be set for the request
3579
3580 Context - Completion context associated with the completion routine
3581
3582Return Value:
3583
3584 NTSTATUS
3585
3586--*/
3587{
3589 BOOLEAN requestSent = FALSE;
3590
3591 BOOLEAN shouldRetry = TRUE;
3592 PCDB cdb = (PCDB)DeviceExtension->PowerContext.Srb.Cdb;
3593 ULONG timeoutValue = DeviceExtension->TimeOutValue;
3594 ULONG retryCount = 1;
3595
3596 // reset some fields.
3597 DeviceExtension->PowerContext.RetryIntervalIn100ns = 0;
3598 status = PowerContextReuseRequest(DeviceExtension);
3599 RequestClearSendTime(DeviceExtension->PowerContext.PowerRequest);
3600
3601 if (!NT_SUCCESS(status))
3602 {
3603 return status;
3604 }
3605
3606 // set proper timeout value and max retry count.
3607 switch(DeviceExtension->PowerContext.PowerChangeState.PowerDown)
3608 {
3612 break;
3613
3615 // Case of issuing SYNC CACHE command. Do not use power irp timeout remaining time in this case
3616 // as we want to give best try on SYNC CACHE command.
3617 retryCount = MAXIMUM_RETRIES;
3618 timeoutValue = DeviceExtension->TimeOutValue;
3619 break;
3620
3622 {
3623 // Case of issuing STOP UNIT command
3624 // As "Imme" bit is set to '1', this command should be completed in short time.
3625 // This command is at low importance, failure of this command has very small impact.
3626 ULONG secondsRemaining = 0;
3627
3628#if (WINVER >= 0x0601)
3629 // this API is introduced in Windows7
3630 PoQueryWatchdogTime(DeviceExtension->LowerPdo, &secondsRemaining);
3631#endif
3632
3633 if (secondsRemaining == 0)
3634 {
3635 // not able to retrieve remaining time from PoQueryWatchdogTime API, use default values.
3636 retryCount = MAXIMUM_RETRIES;
3637 timeoutValue = SCSI_CDROM_TIMEOUT;
3638 }
3639 else
3640 {
3641 // plan to leave about 30 seconds to lower level drivers if possible.
3642 if (secondsRemaining >= 32)
3643 {
3644 retryCount = (secondsRemaining - 30)/SCSI_CDROM_TIMEOUT + 1;
3645 timeoutValue = SCSI_CDROM_TIMEOUT;
3646
3647 if (retryCount > MAXIMUM_RETRIES)
3648 {
3649 retryCount = MAXIMUM_RETRIES;
3650 }
3651
3652 if (retryCount == 1)
3653 {
3654 timeoutValue = secondsRemaining - 30;
3655 }
3656 }
3657 else
3658 {
3659 // issue the command with minimal timeout value and do not retry on it.
3660 retryCount = 1;
3661 timeoutValue = 2;
3662 }
3663 }
3664 }
3665 break;
3666 default:
3667 NT_ASSERT( FALSE );
3669 return status;
3670 }
3671
3672 DeviceExtension->PowerContext.RetryCount = retryCount;
3673
3674 // issue command.
3675 while (shouldRetry)
3676 {
3677
3678 // set SRB fields.
3679 DeviceExtension->PowerContext.Srb.SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
3684
3685 DeviceExtension->PowerContext.Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
3686 DeviceExtension->PowerContext.Srb.TimeOutValue = timeoutValue;
3687
3688 if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceInitial)
3689 {
3690 DeviceExtension->PowerContext.Srb.Function = SRB_FUNCTION_LOCK_QUEUE;
3691 }
3692 else if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceLocked)
3693 {
3694 DeviceExtension->PowerContext.Srb.Function = SRB_FUNCTION_QUIESCE_DEVICE;
3695 }
3696 else if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceQuiesced)
3697 {
3698 // Case of issuing SYNC CACHE command.
3699 DeviceExtension->PowerContext.Srb.CdbLength = 10;
3700 cdb->SYNCHRONIZE_CACHE10.OperationCode = SCSIOP_SYNCHRONIZE_CACHE;
3701 }
3702 else if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceFlushed)
3703 {
3704 // Case of issuing STOP UNIT command.
3705 DeviceExtension->PowerContext.Srb.CdbLength = 6;
3706 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
3707 cdb->START_STOP.Start = 0;
3708 cdb->START_STOP.Immediate = 1;
3709 }
3710 else if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceStopped)
3711 {
3712 DeviceExtension->PowerContext.Srb.Function = SRB_FUNCTION_UNLOCK_QUEUE;
3713 }
3714
3715 // Set up completion routine and context if requested
3717 {
3718 WdfRequestSetCompletionRoutine(DeviceExtension->PowerContext.PowerRequest,
3720 Context);
3721 }
3722
3723 status = RequestSend(DeviceExtension,
3724 DeviceExtension->PowerContext.PowerRequest,
3725 DeviceExtension->IoTarget,
3727 &requestSent);
3728
3729 if (requestSent)
3730 {
3731 if ((CompletionRoutine == NULL) &&
3732 (SRB_STATUS(DeviceExtension->PowerContext.Srb.SrbStatus) != SRB_STATUS_SUCCESS))
3733 {
3734 TracePrint((TRACE_LEVEL_ERROR,
3735 TRACE_FLAG_POWER,
3736 "%p\tError occured when issuing %s command to device. Srb %p, Status %x\n",
3737 DeviceExtension->PowerContext.PowerRequest,
3738 (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceQuiesced) ? "SYNC CACHE" : "STOP UNIT",
3739 &DeviceExtension->PowerContext.Srb,
3740 DeviceExtension->PowerContext.Srb.SrbStatus));
3741
3742 NT_ASSERT(!(TEST_FLAG(DeviceExtension->PowerContext.Srb.SrbStatus, SRB_STATUS_QUEUE_FROZEN)));
3743
3744 shouldRetry = RequestSenseInfoInterpret(DeviceExtension,
3745 DeviceExtension->PowerContext.PowerRequest,
3746 &(DeviceExtension->PowerContext.Srb),
3747 retryCount - DeviceExtension->PowerContext.RetryCount,
3748 &status,
3749 &(DeviceExtension->PowerContext.RetryIntervalIn100ns));
3750
3751 if (shouldRetry && (DeviceExtension->PowerContext.RetryCount-- == 0))
3752 {
3753 shouldRetry = FALSE;
3754 }
3755 }
3756 else
3757 {
3758 // succeeded, do not need to retry.
3759 shouldRetry = FALSE;
3760 }
3761
3762 }
3763 else
3764 {
3765 // request failed to be sent
3766 shouldRetry = FALSE;
3767 }
3768
3769 if (shouldRetry)
3770 {
3772 t.QuadPart = -DeviceExtension->PowerContext.RetryIntervalIn100ns;
3774
3775 status = PowerContextReuseRequest(DeviceExtension);
3776 if (!NT_SUCCESS(status))
3777 {
3778 shouldRetry = FALSE;
3779 }
3780 }
3781 }
3782
3783 if (DeviceExtension->PowerContext.PowerChangeState.PowerDown == PowerDownDeviceQuiesced)
3784 {
3785 // record SYNC CACHE command completion time stamp.
3786 KeQueryTickCount(&DeviceExtension->PowerContext.Step1CompleteTime);
3787 }
3788
3789 return status;
3790}
3791
3794 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3795 _In_ WDFREQUEST Request,
3796 _In_ WDFIOTARGET IoTarget,
3798 _Out_opt_ PBOOLEAN RequestSent
3799 )
3800/*++
3801
3802Routine Description:
3803
3804 Send the request to the target, wake up the device from Zero Power state if necessary.
3805
3806Arguments:
3807
3808 DeviceExtension - device extension
3809 Request - the request to be sent
3810 IoTarget - target of the above request
3811 Flags - flags for the operation
3812 RequestSent - optional, if the request was sent
3813
3814Return Value:
3815
3816 NTSTATUS
3817
3818--*/
3819{
3821 BOOLEAN requestSent = FALSE;
3823
3824 UNREFERENCED_PARAMETER(DeviceExtension);
3825
3826 if ((DeviceExtension->ZeroPowerODDInfo != NULL) &&
3827 (DeviceExtension->ZeroPowerODDInfo->InZeroPowerState != FALSE))
3828 {
3829 }
3830
3831 // Now send down the request
3832 if (NT_SUCCESS(status))
3833 {
3835
3837
3838 // send request and check status
3839
3840 // Disable SDV warning about infinitely waiting in caller's context:
3841 // 1. Some requests (such as SCSI_PASS_THROUGH, contains buffer from user space) need to be sent down in caller’s context.
3842 // Consequently, these requests wait in caller’s context until they are allowed to be sent down.
3843 // 2. Considering the situation that during sleep, a request can be hold by storage port driver. When system resumes, any time out value (if we set using KMDF time out value) might be expires.
3844 // This will cause the waiting request being failed (behavior change). We’d rather not set time out value.
3845
3846 _Analysis_assume_(options.Timeout != 0);
3847 requestSent = WdfRequestSend(Request, IoTarget, &options);
3848 _Analysis_assume_(options.Timeout == 0);
3849
3850 // If WdfRequestSend fails, or if the WDF_REQUEST_SEND_OPTION_SYNCHRONOUS flag is set,
3851 // the driver can call WdfRequestGetStatus immediately after calling WdfRequestSend.
3852 if ((requestSent == FALSE) ||
3854 {
3855 status = WdfRequestGetStatus(Request);
3856
3857 if (requestSent == FALSE)
3858 {
3859 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL,
3860 "WdfRequestSend failed: %lx\n",
3861 status
3862 ));
3863 }
3864 }
3865 else
3866 {
3868 }
3869
3870 if (RequestSent != NULL)
3871 {
3872 *RequestSent = requestSent;
3873 }
3874 }
3875
3876 return status;
3877}
3878
#define PAGED_CODE()
unsigned char BOOLEAN
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define VOID
Definition: acefi.h:82
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER Handler
Definition: acpixf.h:672
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
LONG NTSTATUS
Definition: precomp.h:26
VOID RequestSetupMcnSyncIrp(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: autorun.c:2749
VOID DeviceSetMediaChangeStateEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
Definition: autorun.c:751
_In_ ULONG const Usable
Definition: cdrom.h:1084
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
_In_opt_ PWSTR _In_ PWSTR ParameterName
Definition: cdrom.h:961
FORCEINLINE BOOLEAN PORT_ALLOCATED_SENSE(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: cdrom.h:826
_In_ WDFFILEOBJECT _In_ BOOLEAN IgnorePreviousMediaChanges
Definition: cdrom.h:1227
#define DVD_DEFAULT_REGION
Definition: cdrom.h:760
#define IOCTL_MCN_SYNC_FAKE_IOCTL
Definition: cdrom.h:181
_In_ size_t _In_ UCHAR PageMode
Definition: cdrom.h:1326
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define START_UNIT_TIMEOUT
Definition: cdrom.h:132
FORCEINLINE VOID FREE_PORT_ALLOCATED_SENSE_BUFFER(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: cdrom.h:839
#define CdromMmcUpdateRequired
Definition: cdrom.h:242
SYNC_HANDLER * PSYNC_HANDLER
Definition: cdrom.h:628
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID BufferAddress
Definition: cdrom.h:990
_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
_In_opt_ PWSTR _In_ PWSTR _Inout_ PULONG ParameterValue
Definition: cdrom.h:963
#define MAXIMUM_RETRIES
Definition: cdrom.h:124
_In_ PSCSI_REQUEST_BLOCK _In_opt_ PVOID _In_ ULONG _In_ BOOLEAN WriteToDevice
Definition: cdrom.h:992
struct _COMPLETION_CONTEXT * PCOMPLETION_CONTEXT
#define DVD_MAX_REGION
Definition: cdrom.h:761
_In_ PREAD_CAPACITY_DATA ReadCapacityBuffer
Definition: cdrom.h:1103
#define CDROM_TAG_SYNC_EVENT
Definition: cdrom.h:732
#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 DeviceAsynchronousCompletion
Definition: cdrom.h:1045
EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestDummyCompletionRoutine
Definition: cdrom.h:1608
_In_ ULONG _In_ UCHAR PageCode
Definition: cdrom.h:1317
_In_opt_ PWSTR SubkeyName
Definition: cdrom.h:960
#define SCSI_CDROM_TIMEOUT
Definition: cdrom.h:680
BOOLEAN RequestSenseInfoInterpret(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2467
_In_ ULONG const _In_ FEATURE_NUMBER const Feature
Definition: cdrom.h:1077
EVT_WDF_REQUEST_COMPLETION_ROUTINE DeviceReleaseQueueCompletion
Definition: cdrom.h:1052
_In_z_ PCHAR TargetString
Definition: cdrom.h:954
IO_COMPLETION_ROUTINE RequestAsynchronousIrpCompletion
Definition: cdrom.h:1257
#define CDROM_READ_CAPACITY_TIMEOUT
Definition: cdrom.h:130
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
_In_ WDFREQUEST _In_ BOOLEAN RequestFormated
Definition: cdrom.h:1248
#define EXCLUSIVE_MODE(_CdData)
Definition: cdrom.h:788
_In_ WDFREQUEST _In_ MEDIA_LOCK_TYPE LockType
Definition: cdrom.h:1335
#define CDROM_TAG_NOTIFICATION
Definition: cdrom.h:739
@ PowerDownDeviceStopped
Definition: cdrom.h:412
@ PowerDownDeviceQuiesced
Definition: cdrom.h:410
@ PowerDownDeviceInitial
Definition: cdrom.h:408
@ PowerDownDeviceLocked
Definition: cdrom.h:409
@ PowerDownDeviceFlushed
Definition: cdrom.h:411
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
_In_ ULONG _In_ UCHAR _In_ UCHAR PageControl
Definition: cdrom.h:1319
#define DVD_TAG_DVD_REGION
Definition: cdrom.h:749
#define CDROM_TAG_COMPLETION_CONTEXT
Definition: cdrom.h:729
CDROM_DEVICE_INTERFACES
Definition: cdrom.h:767
@ CdRomDeviceInterface
Definition: cdrom.h:768
@ MountedDeviceInterface
Definition: cdrom.h:769
#define CDROM_TAG_SENSE_INFO
Definition: cdrom.h:735
#define CDROM_TAG_STREAM
Definition: cdrom.h:738
EVT_WDF_WORKITEM DeviceRestoreDefaultSpeed
Definition: cdrom.h:1180
#define CLASS_ERROR_LEVEL_2
Definition: cdromp.h:131
#define CLASS_ERROR_LEVEL_1
Definition: cdromp.h:130
@ MediaUnavailable
Definition: cdromp.h:84
enum _MEDIA_CHANGE_DETECTION_STATE MEDIA_CHANGE_DETECTION_STATE
MEDIA_LOCK_TYPE
Definition: cdromp.h:288
@ SimpleMediaLock
Definition: cdromp.h:289
@ InternalMediaLock
Definition: cdromp.h:291
@ SecureMediaLock
Definition: cdromp.h:290
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
struct _MODE_PARAMETER_HEADER10 MODE_PARAMETER_HEADER10
struct _MODE_PARAMETER_HEADER10 * PMODE_PARAMETER_HEADER10
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define IOCTL_SCSI_EXECUTE_OUT
Definition: cdrw_hw.h:1452
#define IOCTL_SCSI_EXECUTE_NONE
Definition: cdrw_hw.h:1453
#define SENSE_BUFFER_SIZE
Definition: cdrw_hw.h:1183
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
union _CDB * PCDB
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
struct _MODE_PARAMETER_HEADER * PMODE_PARAMETER_HEADER
#define SCSIOP_SET_STREAMING
Definition: cdrw_hw.h:963
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
#define DVD_SET_RPC_KEY_LENGTH
Definition: cdrw_usr.h:1598
#define IOCTL_DVD_READ_KEY
Definition: cdrw_usr.h:160
#define DVD_RPC_KEY_LENGTH
Definition: cdrw_usr.h:1597
Definition: bufpool.h:45
_In_ const GUID _In_ ULONG ExtraDataSize
Definition: classpnp.h:1430
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#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:33
VOID DeviceReleaseQueue(_In_ WDFDEVICE Device)
Definition: common.c:1179
NTSTATUS RequestSetContextFields(_In_ WDFREQUEST Request, _In_ PSYNC_HANDLER Handler)
Definition: common.c:2748
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
VOID RequestCompletion(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG_PTR Information)
Definition: common.c:3439
VOID DevicePerfIncrementErrorCount(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: common.c:1378
VOID RequestSetSentTime(_In_ WDFREQUEST Request)
Definition: common.c:79
NTSTATUS RequestDuidGetDeviceProperty(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: common.c:2888
VOID RequestSetReceivedTime(_In_ WDFREQUEST Request)
Definition: common.c:64
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
VOID DeviceSendIoctlAsynchronously(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT TargetDeviceObject)
Definition: common.c:1030
LPCSTR LockTypeStrings[]
Definition: common.c:58
VOID RequestClearSendTime(_In_ WDFREQUEST Request)
Definition: common.c:111
VOID DeviceSendStartUnit(_In_ WDFDEVICE Device)
Definition: common.c:877
_In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_PARAMETERS RequestParameters
Definition: ioctl.h:138
struct _DVD_RPC_KEY * PDVD_RPC_KEY
struct _DVD_COPYRIGHT_DESCRIPTOR * PDVD_COPYRIGHT_DESCRIPTOR
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:402
#define SRB_FLAGS_DISABLE_DISCONNECT
Definition: srb.h:396
#define SRB_STATUS_PENDING
Definition: srb.h:340
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:423
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_FUNCTION_LOCK_QUEUE
Definition: srb.h:332
#define SRB_FUNCTION_FLUSH_QUEUE
Definition: srb.h:329
#define SRB_FUNCTION_UNLOCK_QUEUE
Definition: srb.h:333
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:410
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#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
IN OUT PVCB IN PDEVICE_OBJECT TargetDeviceObject
Definition: fatprocs.h:1675
struct _FOUR_BYTE * PFOUR_BYTE
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
FxIrp * irp
Status
Definition: gdiplustypes.h:25
GLdouble GLdouble t
Definition: gl.h:2047
GLuint buffer
Definition: glext.h:5915
GLenum GLint GLuint mask
Definition: glext.h:6028
GLint limit
Definition: glext.h:10326
GLenum const GLfloat * params
Definition: glext.h:5645
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
if(dx< 0)
Definition: linetemp.h:194
__u16 date
Definition: mkdosfs.c:8
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
static char * dest
Definition: rtl.c:135
#define min(a, b)
Definition: monoChain.cc:55
#define KernelMode
Definition: asm.h:34
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _In_z_
Definition: no_sal2.h:164
#define _In_opt_z_
Definition: no_sal2.h:218
#define _Out_
Definition: no_sal2.h:160
#define _In_reads_opt_(s)
Definition: no_sal2.h:222
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _Analysis_assume_
Definition: no_sal2.h:388
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define KEY_WRITE
Definition: nt_native.h:1031
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:680
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
@ RemovableMedia
Definition: ntdddisk.h:382
struct _FEATURE_HEADER * PFEATURE_HEADER
enum _FEATURE_NUMBER FEATURE_NUMBER
struct _FEATURE_DATA_FIRMWARE_DATE * PFEATURE_DATA_FIRMWARE_DATE
@ FeatureRandomReadable
Definition: ntddmmc.h:80
@ FeatureDDCDRead
Definition: ntddmmc.h:100
@ FeatureHDDVDRead
Definition: ntddmmc.h:111
@ FeatureRestrictedOverwrite
Definition: ntddmmc.h:90
@ FeatureAACS
Definition: ntddmmc.h:127
@ FeatureMrw
Definition: ntddmmc.h:92
@ FeatureDDCDRWrite
Definition: ntddmmc.h:101
@ FeatureWriteOnce
Definition: ntddmmc.h:89
@ FeatureDvdPlusRW
Definition: ntddmmc.h:94
@ FeatureCore
Definition: ntddmmc.h:76
@ FeatureCdMastering
Definition: ntddmmc.h:98
@ FeatureCdRead
Definition: ntddmmc.h:82
@ FeatureMultiRead
Definition: ntddmmc.h:81
@ FeatureIncrementalStreamingWritable
Definition: ntddmmc.h:85
@ FeatureRandomWritable
Definition: ntddmmc.h:84
@ FeatureDvdCPRM
Definition: ntddmmc.h:125
@ FeatureWriteProtect
Definition: ntddmmc.h:79
@ FeatureDefectManagement
Definition: ntddmmc.h:88
@ FeatureRealTimeStreaming
Definition: ntddmmc.h:121
@ FeatureSectorErasable
Definition: ntddmmc.h:86
@ FeatureCDAudioAnalogPlay
Definition: ntddmmc.h:117
@ FeatureSMART
Definition: ntddmmc.h:115
@ FeatureRemovableMedium
Definition: ntddmmc.h:78
@ FeatureProfileList
Definition: ntddmmc.h:75
@ FeatureLogicalUnitSerialNumber
Definition: ntddmmc.h:122
@ FeatureHDDVDWrite
Definition: ntddmmc.h:112
@ FeatureEmbeddedChanger
Definition: ntddmmc.h:116
@ FeatureDiscControlBlocks
Definition: ntddmmc.h:124
@ FeatureFirmwareDate
Definition: ntddmmc.h:126
@ FeatureMorphing
Definition: ntddmmc.h:77
@ FeatureLayerJumpRecording
Definition: ntddmmc.h:103
@ FeatureMicrocodeUpgrade
Definition: ntddmmc.h:118
@ FeatureDDCDRWWrite
Definition: ntddmmc.h:102
@ FeatureFormattable
Definition: ntddmmc.h:87
@ FeatureDvdCSS
Definition: ntddmmc.h:120
@ FeatureTimeout
Definition: ntddmmc.h:119
@ FeatureRigidRestrictedOverwrite
Definition: ntddmmc.h:96
@ FeatureDvdRead
Definition: ntddmmc.h:83
@ FeatureDvdRecordableWrite
Definition: ntddmmc.h:99
@ FeatureEnhancedDefectReporting
Definition: ntddmmc.h:93
@ FeatureCdrwCAVWrite
Definition: ntddmmc.h:91
@ FeatureCdTrackAtOnce
Definition: ntddmmc.h:97
@ FeaturePowerManagement
Definition: ntddmmc.h:114
struct _FEATURE_HEADER FEATURE_HEADER
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
* PSTORAGE_DESCRIPTOR_HEADER
Definition: ntddstor.h:560
enum _STORAGE_PROPERTY_ID STORAGE_PROPERTY_ID
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:576
@ StorageDeviceIdProperty
Definition: ntddstor.h:514
* PSTORAGE_DEVICE_ID_DESCRIPTOR
Definition: ntddstor.h:742
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS NTAPI IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PVOID NotificationStructure, IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, IN PVOID Context OPTIONAL)
Definition: pnpreport.c:498
GUID * LPGUID
Definition: guiddef.h:81
@ DvdSetRpcKey
Definition: ntddcdvd.h:169
@ DvdGetRpcKey
Definition: ntddcdvd.h:170
@ DvdCopyrightDescriptor
Definition: ntddcdvd.h:110
struct DVD_READ_STRUCTURE * PDVD_READ_STRUCTURE
struct _DVD_SET_RPC_KEY * PDVD_SET_RPC_KEY
struct _DVD_COPY_PROTECT_KEY * PDVD_COPY_PROTECT_KEY
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
static calc_node_t temp
Definition: rpn_ieee.c:38
FORCEINLINE VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: scratch.h:104
#define ScratchBuffer_BeginUse(context)
Definition: scratch.h:87
struct _PERFORMANCE_DESCRIPTOR PERFORMANCE_DESCRIPTOR
struct _MODE_DISCONNECT_PAGE * PMODE_DISCONNECT_PAGE
#define REVERSE_BYTES_SHORT(Destination, Source)
Definition: scsi.h:3474
PFIXED_SENSE_DATA senseInfoBuffer
Definition: scsi.h:3710
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define SRB_FLAGS_D3_PROCESSING
Definition: srb.h:165
#define SRB_FUNCTION_QUIESCE_DEVICE
Definition: srb.h:99
#define KeQueryTickCount(CurrentCount)
Definition: ke.h:43
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
static void Exit(void)
Definition: sock.c:1330
#define WHICH_BIT(Data, Bit)
Definition: tools.h:80
struct _STORAGE_DEVICE_UNIQUE_IDENTIFIER * PSTORAGE_DEVICE_UNIQUE_IDENTIFIER
#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
DVD_STRUCTURE_FORMAT Format
Definition: ntddcdvd.h:120
CDROM_MMC_EXTENSION Mmc
Definition: cdrom.h:341
ULONG PickDvdRegion
Definition: cdrom.h:354
WDFFILEOBJECT ExclusiveOwner
Definition: cdrom.h:373
WDFIOTARGET IoTarget
Definition: cdrom.h:476
BOOLEAN ReleaseQueueInProgress
Definition: cdrom.h:581
PZERO_POWER_ODD_INFO ZeroPowerODDInfo
Definition: cdrom.h:566
WDFMEMORY ReleaseQueueInputMemory
Definition: cdrom.h:579
BOOLEAN ReleaseQueueNeeded
Definition: cdrom.h:580
PCDROM_PRIVATE_FDO_DATA PrivateFdoData
Definition: cdrom.h:605
WDFSPINLOCK ReleaseQueueSpinLock
Definition: cdrom.h:576
WDFREQUEST ReleaseQueueRequest
Definition: cdrom.h:577
LARGE_INTEGER PartitionLength
Definition: cdrom.h:530
DISK_GEOMETRY DiskGeometry
Definition: cdrom.h:524
SCSI_REQUEST_BLOCK ReleaseQueueSrb
Definition: cdrom.h:578
CDROM_DATA DeviceAdditionalData
Definition: cdrom.h:598
BOOLEAN WriteAllowed
Definition: cdrom.h:250
BOOLEAN LoggedTURFailureSinceLastIO
Definition: cdromp.h:346
struct _CDROM_PRIVATE_FDO_DATA::@1062 Perf
KSPIN_LOCK SpinLock
Definition: cdromp.h:351
WDFREQUEST OriginalRequest
Definition: cdrom.h:633
BOOLEAN SyncRequired
Definition: cdrom.h:643
LARGE_INTEGER TimeReceived
Definition: cdrom.h:635
LARGE_INTEGER TimeSentDownLasttTime
Definition: cdrom.h:637
PSYNC_HANDLER SyncCallback
Definition: cdrom.h:645
LARGE_INTEGER TimeSentDownFirstTime
Definition: cdrom.h:636
MEDIA_TYPE MediaType
Definition: ntdddisk.h:401
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:400
ULONG TracksPerCylinder
Definition: ntdddisk.h:402
ULONG SectorsPerTrack
Definition: ntdddisk.h:403
ULONG BytesPerSector
Definition: ntdddisk.h:404
DVD_KEY_TYPE KeyType
Definition: ntddcdvd.h:178
UCHAR UserResetsAvailable
Definition: scsi.h:2923
UCHAR RegionMask
Definition: scsi.h:2926
UCHAR PreferredDriveRegionCode
Definition: ntddcdvd.h:232
union _IO_STACK_LOCATION::@1581 Parameters
struct _IO_STACK_LOCATION::@3980::@4002 Scsi
struct _IO_STACK_LOCATION::@1581::@1582 DeviceIoControl
UCHAR BlockDescriptorLength[2]
Definition: cdrw_hw.h:2516
ULONG LogicalBlockAddress
Definition: cdrw_hw.h:1471
ULONG TimeOutValue
Definition: srb.h:262
PVOID OriginalRequest
Definition: srb.h:266
UCHAR SenseInfoBufferLength
Definition: srb.h:259
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
PVOID SenseInfoBuffer
Definition: srb.h:264
UCHAR Function
Definition: srb.h:250
UCHAR ScsiStatus
Definition: srb.h:252
ULONG DataTransferLength
Definition: srb.h:261
struct _SCSI_REQUEST_BLOCK * NextSrb
Definition: srb.h:265
ULONG SrbFlags
Definition: srb.h:260
USHORT Length
Definition: srb.h:249
UCHAR SrbStatus
Definition: srb.h:251
WDFOBJECT ParentObject
Definition: wdfobject.h:130
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
BOOLEAN MonitorStartStopUnit
Definition: cdromp.h:274
Definition: http.c:7252
Definition: devices.h:37
Definition: tftpd.h:86
Definition: ps.c:97
#define max(a, b)
Definition: svc.c:63
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
const char * PCSTR
Definition: typedefs.h:52
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
int32_t * PLONG
Definition: typedefs.h:58
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
@ MediaUnknown
Definition: udf_common.h:10
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
#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::_MEDIA_REMOVAL MEDIA_REMOVAL
struct _CDB::_START_STOP START_STOP
struct _CDB::_MODE_SENSE MODE_SENSE
struct _CDB::_SYNCHRONIZE_CACHE10 SYNCHRONIZE_CACHE10
struct _CDB::_SET_STREAMING SET_STREAMING
LONGLONG QuadPart
Definition: typedefs.h:114
#define PLUGPLAY_REGKEY_DRIVER
Definition: usbd.c:42
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
#define DECLARE_CONST_UNICODE_STRING(_variablename, _string)
Definition: wdfcore.h:161
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
@ WdfRequestTypeWrite
Definition: wdfdevice.h:507
@ WdfRequestTypeRead
Definition: wdfdevice.h:506
@ WdfRequestTypeDeviceControl
Definition: wdfdevice.h:517
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
FORCEINLINE WDFDRIVER WdfGetDriver(VOID)
Definition: wdfdriver.h:194
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID InterfaceType
Definition: wdffdo.h:463
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:325
_Must_inspect_result_ _In_ WDFDEVICE _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFIOTARGET * IoTarget
Definition: wdfiotarget.h:368
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
_Must_inspect_result_ FORCEINLINE BOOLEAN WdfRequestSend(_In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, _In_opt_ PWDF_REQUEST_SEND_OPTIONS Options)
Definition: wdfrequest.h:677
FORCEINLINE VOID WDF_REQUEST_SEND_OPTIONS_INIT(_Out_ PWDF_REQUEST_SEND_OPTIONS Options, _In_ ULONG Flags)
Definition: wdfrequest.h:409
@ WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE
Definition: wdfrequest.h:110
@ WDF_REQUEST_SEND_OPTION_SYNCHRONOUS
Definition: wdfrequest.h:109
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
@ WDF_REQUEST_REUSE_NO_FLAGS
Definition: wdfrequest.h:92
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
Definition: wdfrequest.h:211
EVT_WDF_REQUEST_COMPLETION_ROUTINE * PFN_WDF_REQUEST_COMPLETION_ROUTINE
Definition: wdfrequest.h:313
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:895
FORCEINLINE VOID WDF_REQUEST_REUSE_PARAMS_INIT(_Out_ PWDF_REQUEST_REUSE_PARAMS Params, _In_ ULONG Flags, _In_ NTSTATUS Status)
Definition: wdfrequest.h:364
_Must_inspect_result_ FORCEINLINE NTSTATUS WdfWaitLockAcquire(_In_ _Requires_lock_not_held_(_Curr_) WDFWAITLOCK Lock, _In_opt_ PLONGLONG Timeout)
Definition: wdfsync.h:173
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
#define WDF_NO_OBJECT_ATTRIBUTES
Definition: wdftypes.h:105
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2786
#define IRP_MJ_SCSI
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864
#define NT_ASSERT
Definition: rtlfuncs.h:3327
const char * LPCSTR
Definition: xmlstorage.h:183
unsigned char UCHAR
Definition: xmlstorage.h:181