Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenioctl.c
Go to the documentation of this file.
00001 /*-- 00002 00003 Copyright (C) Microsoft Corporation, 1999 - 1999 00004 00005 Module Name: 00006 00007 ioctl.c 00008 00009 Abstract: 00010 00011 The CDROM class driver tranlates IRPs to SRBs with embedded CDBs 00012 and sends them to its devices through the port driver. 00013 00014 Environment: 00015 00016 kernel mode only 00017 00018 Notes: 00019 00020 SCSI Tape, CDRom and Disk class drivers share common routines 00021 that can be found in the CLASS directory (..\ntos\dd\class). 00022 00023 Revision History: 00024 00025 --*/ 00026 00027 #include "stddef.h" 00028 #include "string.h" 00029 00030 #include "ntddk.h" 00031 00032 #include "ntddcdvd.h" 00033 #include "classpnp.h" 00034 00035 #include "initguid.h" 00036 #include "ntddstor.h" 00037 #include "cdrom.h" 00038 00039 00040 #if DBG 00041 PUCHAR READ_DVD_STRUCTURE_FORMAT_STRINGS[DvdMaxDescriptor+1] = { 00042 "Physical", 00043 "Copyright", 00044 "DiskKey", 00045 "BCA", 00046 "Manufacturer", 00047 "Unknown" 00048 }; 00049 #endif // DBG 00050 00051 #define DEFAULT_CDROM_SECTORS_PER_TRACK 32 00052 #define DEFAULT_TRACKS_PER_CYLINDER 64 00053 00054 00055 00056 NTSTATUS 00057 CdRomDeviceControlDispatch( 00058 IN PDEVICE_OBJECT DeviceObject, 00059 IN PIRP Irp 00060 ) 00061 /*++ 00062 00063 Routine Description: 00064 00065 This is the NT device control handler for CDROMs. 00066 00067 Arguments: 00068 00069 DeviceObject - for this CDROM 00070 00071 Irp - IO Request packet 00072 00073 Return Value: 00074 00075 NTSTATUS 00076 00077 --*/ 00078 { 00079 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; 00080 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; 00081 00082 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 00083 PIO_STACK_LOCATION nextStack; 00084 PCDROM_DATA cdData = (PCDROM_DATA)(commonExtension->DriverData); 00085 00086 BOOLEAN use6Byte = TEST_FLAG(cdData->XAFlags, XA_USE_6_BYTE); 00087 SCSI_REQUEST_BLOCK srb; 00088 PCDB cdb = (PCDB)srb.Cdb; 00089 PVOID outputBuffer; 00090 ULONG bytesTransferred = 0; 00091 NTSTATUS status; 00092 NTSTATUS status2; 00093 KIRQL irql; 00094 00095 ULONG ioctlCode; 00096 ULONG baseCode; 00097 ULONG functionCode; 00098 00099 RetryControl: 00100 00101 // 00102 // Zero the SRB on stack. 00103 // 00104 00105 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); 00106 00107 Irp->IoStatus.Information = 0; 00108 00109 // 00110 // if this is a class driver ioctl then we need to change the base code 00111 // to IOCTL_CDROM_BASE so that the switch statement can handle it. 00112 // 00113 // WARNING - currently the scsi class ioctl function codes are between 00114 // 0x200 & 0x300. this routine depends on that fact 00115 // 00116 00117 ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; 00118 baseCode = ioctlCode >> 16; 00119 functionCode = (ioctlCode & (~0xffffc003)) >> 2; 00120 00121 TraceLog((CdromDebugTrace, 00122 "CdRomDeviceControl: Ioctl Code = %lx, Base Code = %lx," 00123 " Function Code = %lx\n", 00124 ioctlCode, 00125 baseCode, 00126 functionCode 00127 )); 00128 00129 if((functionCode >= 0x200) && (functionCode <= 0x300)) { 00130 00131 ioctlCode = (ioctlCode & 0x0000ffff) | CTL_CODE(IOCTL_CDROM_BASE, 0, 0, 0); 00132 00133 TraceLog((CdromDebugTrace, 00134 "CdRomDeviceControl: Class Code - new ioctl code is %lx\n", 00135 ioctlCode)); 00136 00137 irpStack->Parameters.DeviceIoControl.IoControlCode = ioctlCode; 00138 00139 } 00140 00141 switch (ioctlCode) { 00142 00143 case IOCTL_STORAGE_GET_MEDIA_TYPES_EX: { 00144 00145 PGET_MEDIA_TYPES mediaTypes = Irp->AssociatedIrp.SystemBuffer; 00146 PDEVICE_MEDIA_INFO mediaInfo = &mediaTypes->MediaInfo[0]; 00147 ULONG sizeNeeded; 00148 00149 sizeNeeded = sizeof(GET_MEDIA_TYPES); 00150 00151 // 00152 // IsMmc is static... 00153 // 00154 00155 if (cdData->Mmc.IsMmc) { 00156 sizeNeeded += sizeof(DEVICE_MEDIA_INFO) * 1; // return two media types 00157 } 00158 00159 // 00160 // Ensure that buffer is large enough. 00161 // 00162 00163 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00164 sizeNeeded) { 00165 00166 // 00167 // Buffer too small. 00168 // 00169 00170 Irp->IoStatus.Information = sizeNeeded; 00171 status = STATUS_BUFFER_TOO_SMALL; 00172 break; 00173 } 00174 00175 RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, sizeNeeded); 00176 00177 // 00178 // ISSUE-2000/5/11-henrygab - need to update GET_MEDIA_TYPES_EX 00179 // 00180 00181 mediaTypes->DeviceType = CdRomGetDeviceType(DeviceObject); 00182 00183 mediaTypes->MediaInfoCount = 1; 00184 mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = CD_ROM; 00185 mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1; 00186 mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_READ_ONLY; 00187 mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = fdoExtension->DiskGeometry.Cylinders.QuadPart; 00188 mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = fdoExtension->DiskGeometry.TracksPerCylinder; 00189 mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = fdoExtension->DiskGeometry.SectorsPerTrack; 00190 mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = fdoExtension->DiskGeometry.BytesPerSector; 00191 00192 if (cdData->Mmc.IsMmc) { 00193 00194 // 00195 // also report a removable disk 00196 // 00197 mediaTypes->MediaInfoCount += 1; 00198 00199 mediaInfo++; 00200 mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = RemovableMedia; 00201 mediaInfo->DeviceSpecific.RemovableDiskInfo.NumberMediaSides = 1; 00202 mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = MEDIA_READ_WRITE; 00203 mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = fdoExtension->DiskGeometry.Cylinders.QuadPart; 00204 mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = fdoExtension->DiskGeometry.TracksPerCylinder; 00205 mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = fdoExtension->DiskGeometry.SectorsPerTrack; 00206 mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = fdoExtension->DiskGeometry.BytesPerSector; 00207 mediaInfo--; 00208 00209 } 00210 00211 // 00212 // Status will either be success, if media is present, or no media. 00213 // It would be optimal to base from density code and medium type, but not all devices 00214 // have values for these fields. 00215 // 00216 00217 // 00218 // Send a TUR to determine if media is present. 00219 // 00220 00221 srb.CdbLength = 6; 00222 cdb = (PCDB)srb.Cdb; 00223 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; 00224 00225 // 00226 // Set timeout value. 00227 // 00228 00229 srb.TimeOutValue = fdoExtension->TimeOutValue; 00230 00231 status = ClassSendSrbSynchronous(DeviceObject, 00232 &srb, 00233 NULL, 00234 0, 00235 FALSE); 00236 00237 00238 TraceLog((CdromDebugWarning, 00239 "CdRomDeviceControl: GET_MEDIA_TYPES status of TUR - %lx\n", 00240 status)); 00241 00242 if (NT_SUCCESS(status)) { 00243 00244 // 00245 // set the disk's media as current if we can write to it. 00246 // 00247 00248 if (cdData->Mmc.IsMmc && cdData->Mmc.WriteAllowed) { 00249 00250 mediaInfo++; 00251 SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, 00252 MEDIA_CURRENTLY_MOUNTED); 00253 mediaInfo--; 00254 00255 00256 } else { 00257 00258 SET_FLAG(mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics, 00259 MEDIA_CURRENTLY_MOUNTED); 00260 00261 } 00262 00263 } 00264 00265 Irp->IoStatus.Information = sizeNeeded; 00266 status = STATUS_SUCCESS; 00267 break; 00268 } 00269 00270 00271 case IOCTL_CDROM_RAW_READ: { 00272 00273 LARGE_INTEGER startingOffset; 00274 ULONGLONG transferBytes; 00275 ULONGLONG endOffset; 00276 ULONGLONG mdlBytes; 00277 ULONG startingSector; 00278 PRAW_READ_INFO rawReadInfo = (PRAW_READ_INFO)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; 00279 00280 // 00281 // Ensure that XA reads are supported. 00282 // 00283 00284 if (TEST_FLAG(cdData->XAFlags, XA_NOT_SUPPORTED)) { 00285 TraceLog((CdromDebugWarning, 00286 "CdRomDeviceControl: XA Reads not supported. Flags (%x)\n", 00287 cdData->XAFlags)); 00288 status = STATUS_INVALID_DEVICE_REQUEST; 00289 break; 00290 } 00291 00292 // 00293 // Check that ending sector is on disc and buffers are there and of 00294 // correct size. 00295 // 00296 00297 if (rawReadInfo == NULL) { 00298 00299 // 00300 // Called from user space. Save the userbuffer in the 00301 // Type3InputBuffer so we can reduce the number of code paths. 00302 // 00303 00304 irpStack->Parameters.DeviceIoControl.Type3InputBuffer = 00305 Irp->AssociatedIrp.SystemBuffer; 00306 00307 // 00308 // Called from user space. Validate the buffers. 00309 // 00310 00311 rawReadInfo = (PRAW_READ_INFO)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; 00312 00313 if (rawReadInfo == NULL) { 00314 00315 TraceLog((CdromDebugWarning, 00316 "CdRomDeviceControl: Invalid I/O parameters for " 00317 "XA Read (No extent info\n")); 00318 status = STATUS_INVALID_PARAMETER; 00319 break; 00320 00321 } 00322 00323 if (irpStack->Parameters.DeviceIoControl.InputBufferLength != 00324 sizeof(RAW_READ_INFO)) { 00325 00326 TraceLog((CdromDebugWarning, 00327 "CdRomDeviceControl: Invalid I/O parameters for " 00328 "XA Read (Invalid info buffer\n")); 00329 status = STATUS_INVALID_PARAMETER; 00330 break; 00331 00332 } 00333 } 00334 00335 // 00336 // if they don't request any data, just fail the request 00337 // 00338 00339 if (rawReadInfo->SectorCount == 0) { 00340 00341 status = STATUS_INVALID_PARAMETER; 00342 break; 00343 00344 } 00345 00346 startingOffset.QuadPart = rawReadInfo->DiskOffset.QuadPart; 00347 startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> 00348 fdoExtension->SectorShift); 00349 transferBytes = (ULONGLONG)rawReadInfo->SectorCount * RAW_SECTOR_SIZE; 00350 00351 endOffset = (ULONGLONG)rawReadInfo->SectorCount * COOKED_SECTOR_SIZE; 00352 endOffset += startingOffset.QuadPart; 00353 00354 // 00355 // check for overflows.... 00356 // 00357 00358 if (transferBytes < (ULONGLONG)(rawReadInfo->SectorCount)) { 00359 TraceLog((CdromDebugWarning, 00360 "CdRomDeviceControl: Invalid I/O parameters for XA " 00361 "Read (TransferBytes Overflow)\n")); 00362 status = STATUS_INVALID_PARAMETER; 00363 break; 00364 } 00365 if (endOffset < (ULONGLONG)startingOffset.QuadPart) { 00366 TraceLog((CdromDebugWarning, 00367 "CdRomDeviceControl: Invalid I/O parameters for XA " 00368 "Read (EndingOffset Overflow)\n")); 00369 status = STATUS_INVALID_PARAMETER; 00370 break; 00371 } 00372 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00373 transferBytes) { 00374 TraceLog((CdromDebugWarning, 00375 "CdRomDeviceControl: Invalid I/O parameters for XA " 00376 "Read (Bad buffer size)\n")); 00377 status = STATUS_INVALID_PARAMETER; 00378 break; 00379 } 00380 if (endOffset > (ULONGLONG)commonExtension->PartitionLength.QuadPart) { 00381 TraceLog((CdromDebugWarning, 00382 "CdRomDeviceControl: Invalid I/O parameters for XA " 00383 "Read (Request Out of Bounds)\n")); 00384 status = STATUS_INVALID_PARAMETER; 00385 break; 00386 } 00387 00388 // 00389 // cannot validate the MdlAddress, since it is not included in any 00390 // other location per the DDK and file system calls. 00391 // 00392 00393 // 00394 // validate the mdl describes at least the number of bytes 00395 // requested from us. 00396 // 00397 00398 mdlBytes = (ULONGLONG)MmGetMdlByteCount(Irp->MdlAddress); 00399 if (mdlBytes < transferBytes) { 00400 TraceLog((CdromDebugWarning, 00401 "CdRomDeviceControl: Invalid MDL %s, Irp %p\n", 00402 "size (5)", Irp)); 00403 status = STATUS_INVALID_PARAMETER; 00404 break; 00405 } 00406 00407 // 00408 // HACKHACK - REF #0001 00409 // The retry count will be in this irp's IRP_MN function, 00410 // as the new irp was freed, and we therefore cannot use 00411 // this irp's next stack location for this function. 00412 // This may be a good location to store this info for 00413 // when we remove RAW_READ (mode switching), as we will 00414 // no longer have the nextIrpStackLocation to play with 00415 // when that occurs 00416 // 00417 // once XA_READ is removed, then this hack can also be 00418 // removed. 00419 // 00420 irpStack->MinorFunction = MAXIMUM_RETRIES; // HACKHACK - REF #0001 00421 00422 IoMarkIrpPending(Irp); 00423 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00424 00425 return STATUS_PENDING; 00426 } 00427 00428 case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: 00429 case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: { 00430 TraceLog((CdromDebugTrace, 00431 "CdRomDeviceControl: Get drive geometryEx\n")); 00432 if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00433 FIELD_OFFSET(DISK_GEOMETRY_EX, Data)) { 00434 status = STATUS_BUFFER_TOO_SMALL; 00435 Irp->IoStatus.Information = FIELD_OFFSET(DISK_GEOMETRY_EX, Data); 00436 break; 00437 } 00438 IoMarkIrpPending(Irp); 00439 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00440 return STATUS_PENDING; 00441 } 00442 00443 case IOCTL_DISK_GET_DRIVE_GEOMETRY: 00444 case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { 00445 00446 TraceLog((CdromDebugTrace, 00447 "CdRomDeviceControl: Get drive geometry\n")); 00448 00449 if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00450 sizeof( DISK_GEOMETRY ) ) { 00451 00452 status = STATUS_BUFFER_TOO_SMALL; 00453 Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); 00454 break; 00455 } 00456 00457 IoMarkIrpPending(Irp); 00458 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00459 00460 return STATUS_PENDING; 00461 } 00462 00463 case IOCTL_CDROM_READ_TOC_EX: { 00464 00465 PCDROM_READ_TOC_EX inputBuffer; 00466 00467 if (CdRomIsPlayActive(DeviceObject)) { 00468 status = STATUS_DEVICE_BUSY; 00469 break; 00470 } 00471 00472 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 00473 sizeof(CDROM_READ_TOC_EX)) { 00474 status = STATUS_INFO_LENGTH_MISMATCH; 00475 break; 00476 } 00477 00478 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00479 MINIMUM_CDROM_READ_TOC_EX_SIZE) { 00480 status = STATUS_BUFFER_TOO_SMALL; 00481 Irp->IoStatus.Information = MINIMUM_CDROM_READ_TOC_EX_SIZE; 00482 break; 00483 } 00484 00485 if (irpStack->Parameters.Read.Length > ((USHORT)-1)) { 00486 status = STATUS_INVALID_PARAMETER; 00487 break; 00488 } 00489 00490 inputBuffer = Irp->AssociatedIrp.SystemBuffer; 00491 00492 if ((inputBuffer->Reserved1 != 0) || 00493 (inputBuffer->Reserved2 != 0) || 00494 (inputBuffer->Reserved3 != 0)) { 00495 status = STATUS_INVALID_PARAMETER; 00496 break; 00497 } 00498 00499 // 00500 // NOTE: when adding new formats, ensure that first two bytes 00501 // specify the amount of additional data available. 00502 // 00503 00504 if ((inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_TOC ) || 00505 (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_FULL_TOC) || 00506 (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_CDTEXT )) { 00507 00508 // SessionTrack field is used 00509 00510 } else 00511 if ((inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_SESSION) || 00512 (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_PMA) || 00513 (inputBuffer->Format == CDROM_READ_TOC_EX_FORMAT_ATIP)) { 00514 00515 // SessionTrack field is reserved 00516 00517 if (inputBuffer->SessionTrack != 0) { 00518 status = STATUS_INVALID_PARAMETER; 00519 break; 00520 } 00521 00522 } else { 00523 status = STATUS_INVALID_PARAMETER; 00524 break; 00525 } 00526 00527 IoMarkIrpPending(Irp); 00528 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00529 return STATUS_PENDING; 00530 } 00531 00532 case IOCTL_CDROM_GET_LAST_SESSION: { 00533 00534 // 00535 // If the cd is playing music then reject this request. 00536 // 00537 00538 if (CdRomIsPlayActive(DeviceObject)) { 00539 status = STATUS_DEVICE_BUSY; 00540 break; 00541 } 00542 00543 // 00544 // Make sure the caller is requesting enough data to make this worth 00545 // our while. 00546 // 00547 00548 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00549 sizeof(CDROM_TOC_SESSION_DATA)) { 00550 00551 // 00552 // they didn't request the entire TOC -- use _EX version 00553 // for partial transfers and such. 00554 // 00555 00556 status = STATUS_BUFFER_TOO_SMALL; 00557 Irp->IoStatus.Information = sizeof(CDROM_TOC_SESSION_DATA); 00558 break; 00559 } 00560 00561 IoMarkIrpPending(Irp); 00562 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00563 00564 return STATUS_PENDING; 00565 } 00566 00567 case IOCTL_CDROM_READ_TOC: { 00568 00569 // 00570 // If the cd is playing music then reject this request. 00571 // 00572 00573 if (CdRomIsPlayActive(DeviceObject)) { 00574 status = STATUS_DEVICE_BUSY; 00575 break; 00576 } 00577 00578 // 00579 // Make sure the caller is requesting enough data to make this worth 00580 // our while. 00581 // 00582 00583 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00584 sizeof(CDROM_TOC)) { 00585 00586 // 00587 // they didn't request the entire TOC -- use _EX version 00588 // for partial transfers and such. 00589 // 00590 00591 status = STATUS_BUFFER_TOO_SMALL; 00592 Irp->IoStatus.Information = sizeof(CDROM_TOC); 00593 break; 00594 } 00595 00596 IoMarkIrpPending(Irp); 00597 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00598 00599 return STATUS_PENDING; 00600 } 00601 00602 case IOCTL_CDROM_PLAY_AUDIO_MSF: { 00603 00604 // 00605 // Play Audio MSF 00606 // 00607 00608 TraceLog((CdromDebugTrace, 00609 "CdRomDeviceControl: Play audio MSF\n")); 00610 00611 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 00612 sizeof(CDROM_PLAY_AUDIO_MSF)) { 00613 00614 // 00615 // Indicate unsuccessful status. 00616 // 00617 00618 status = STATUS_INFO_LENGTH_MISMATCH; 00619 break; 00620 } 00621 00622 IoMarkIrpPending(Irp); 00623 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00624 00625 return STATUS_PENDING; 00626 } 00627 00628 case IOCTL_CDROM_SEEK_AUDIO_MSF: { 00629 00630 00631 // 00632 // Seek Audio MSF 00633 // 00634 00635 TraceLog((CdromDebugTrace, 00636 "CdRomDeviceControl: Seek audio MSF\n")); 00637 00638 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 00639 sizeof(CDROM_SEEK_AUDIO_MSF)) { 00640 00641 // 00642 // Indicate unsuccessful status. 00643 // 00644 00645 status = STATUS_INFO_LENGTH_MISMATCH; 00646 break; 00647 } 00648 00649 IoMarkIrpPending(Irp); 00650 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00651 return STATUS_PENDING; 00652 00653 } 00654 00655 case IOCTL_CDROM_PAUSE_AUDIO: { 00656 00657 // 00658 // Pause audio 00659 // 00660 00661 TraceLog((CdromDebugTrace, 00662 "CdRomDeviceControl: Pause audio\n")); 00663 00664 IoMarkIrpPending(Irp); 00665 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00666 00667 return STATUS_PENDING; 00668 00669 break; 00670 } 00671 00672 case IOCTL_CDROM_RESUME_AUDIO: { 00673 00674 // 00675 // Resume audio 00676 // 00677 00678 TraceLog((CdromDebugTrace, 00679 "CdRomDeviceControl: Resume audio\n")); 00680 00681 IoMarkIrpPending(Irp); 00682 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00683 00684 return STATUS_PENDING; 00685 } 00686 00687 case IOCTL_CDROM_READ_Q_CHANNEL: { 00688 00689 PCDROM_SUB_Q_DATA_FORMAT inputBuffer = 00690 Irp->AssociatedIrp.SystemBuffer; 00691 00692 if(irpStack->Parameters.DeviceIoControl.InputBufferLength < 00693 sizeof(CDROM_SUB_Q_DATA_FORMAT)) { 00694 00695 status = STATUS_INFO_LENGTH_MISMATCH; 00696 break; 00697 } 00698 00699 // 00700 // check for all valid types of request 00701 // 00702 00703 if (inputBuffer->Format != IOCTL_CDROM_CURRENT_POSITION && 00704 inputBuffer->Format != IOCTL_CDROM_MEDIA_CATALOG && 00705 inputBuffer->Format != IOCTL_CDROM_TRACK_ISRC ) { 00706 status = STATUS_INVALID_PARAMETER; 00707 Irp->IoStatus.Information = 0; 00708 break; 00709 } 00710 00711 IoMarkIrpPending(Irp); 00712 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00713 00714 return STATUS_PENDING; 00715 } 00716 00717 case IOCTL_CDROM_GET_CONTROL: { 00718 00719 TraceLog((CdromDebugTrace, 00720 "CdRomDeviceControl: Get audio control\n")); 00721 00722 // 00723 // Verify user buffer is large enough for the data. 00724 // 00725 00726 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00727 sizeof(CDROM_AUDIO_CONTROL)) { 00728 00729 // 00730 // Indicate unsuccessful status and no data transferred. 00731 // 00732 00733 status = STATUS_BUFFER_TOO_SMALL; 00734 Irp->IoStatus.Information = sizeof(CDROM_AUDIO_CONTROL); 00735 break; 00736 00737 } 00738 00739 IoMarkIrpPending(Irp); 00740 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00741 00742 return STATUS_PENDING; 00743 } 00744 00745 case IOCTL_CDROM_GET_VOLUME: { 00746 00747 TraceLog((CdromDebugTrace, 00748 "CdRomDeviceControl: Get volume control\n")); 00749 00750 // 00751 // Verify user buffer is large enough for data. 00752 // 00753 00754 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00755 sizeof(VOLUME_CONTROL)) { 00756 00757 // 00758 // Indicate unsuccessful status and no data transferred. 00759 // 00760 00761 status = STATUS_BUFFER_TOO_SMALL; 00762 Irp->IoStatus.Information = sizeof(VOLUME_CONTROL); 00763 break; 00764 00765 } 00766 00767 IoMarkIrpPending(Irp); 00768 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00769 00770 return STATUS_PENDING; 00771 } 00772 00773 case IOCTL_CDROM_SET_VOLUME: { 00774 00775 TraceLog((CdromDebugTrace, 00776 "CdRomDeviceControl: Set volume control\n")); 00777 00778 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 00779 sizeof(VOLUME_CONTROL)) { 00780 00781 // 00782 // Indicate unsuccessful status. 00783 // 00784 00785 status = STATUS_INFO_LENGTH_MISMATCH; 00786 break; 00787 00788 } 00789 00790 IoMarkIrpPending(Irp); 00791 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00792 00793 return STATUS_PENDING; 00794 } 00795 00796 case IOCTL_CDROM_STOP_AUDIO: { 00797 00798 // 00799 // Stop play. 00800 // 00801 00802 TraceLog((CdromDebugTrace, 00803 "CdRomDeviceControl: Stop audio\n")); 00804 00805 IoMarkIrpPending(Irp); 00806 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00807 00808 return STATUS_PENDING; 00809 } 00810 00811 case IOCTL_STORAGE_CHECK_VERIFY: 00812 case IOCTL_DISK_CHECK_VERIFY: 00813 case IOCTL_CDROM_CHECK_VERIFY: { 00814 00815 TraceLog((CdromDebugTrace, 00816 "CdRomDeviceControl: [%p] Check Verify\n", Irp)); 00817 00818 if((irpStack->Parameters.DeviceIoControl.OutputBufferLength) && 00819 (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))) { 00820 00821 TraceLog((CdromDebugWarning, 00822 "CdRomDeviceControl: Check Verify: media count " 00823 "buffer too small\n")); 00824 00825 status = STATUS_BUFFER_TOO_SMALL; 00826 Irp->IoStatus.Information = sizeof(ULONG); 00827 break; 00828 } 00829 00830 IoMarkIrpPending(Irp); 00831 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00832 00833 return STATUS_PENDING; 00834 } 00835 00836 case IOCTL_DVD_READ_STRUCTURE: { 00837 00838 TraceLog((CdromDebugTrace, 00839 "DvdDeviceControl: [%p] IOCTL_DVD_READ_STRUCTURE\n", Irp)); 00840 00841 if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) { 00842 TraceLog((CdromDebugWarning, 00843 "DvdDeviceControl: License Failure\n")); 00844 status = STATUS_COPY_PROTECTION_FAILURE; 00845 break; 00846 } 00847 00848 if (cdData->DvdRpc0Device && cdData->Rpc0RetryRegistryCallback) { 00849 // 00850 // if currently in-progress, this will just return. 00851 // prevents looping by doing that interlockedExchange() 00852 // 00853 TraceLog((CdromDebugWarning, 00854 "DvdDeviceControl: PickRegion() from " 00855 "READ_STRUCTURE\n")); 00856 CdRomPickDvdRegion(DeviceObject); 00857 } 00858 00859 00860 if(irpStack->Parameters.DeviceIoControl.InputBufferLength < 00861 sizeof(DVD_READ_STRUCTURE)) { 00862 00863 TraceLog((CdromDebugWarning, 00864 "DvdDeviceControl - READ_STRUCTURE: input buffer " 00865 "length too small (was %d should be %d)\n", 00866 irpStack->Parameters.DeviceIoControl.InputBufferLength, 00867 sizeof(DVD_READ_STRUCTURE))); 00868 status = STATUS_INVALID_PARAMETER; 00869 break; 00870 } 00871 00872 if(irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00873 sizeof(READ_DVD_STRUCTURES_HEADER)) { 00874 00875 TraceLog((CdromDebugWarning, 00876 "DvdDeviceControl - READ_STRUCTURE: output buffer " 00877 "cannot hold header information\n")); 00878 status = STATUS_BUFFER_TOO_SMALL; 00879 Irp->IoStatus.Information = sizeof(READ_DVD_STRUCTURES_HEADER); 00880 break; 00881 } 00882 00883 if(irpStack->Parameters.DeviceIoControl.OutputBufferLength > 00884 MAXUSHORT) { 00885 00886 // 00887 // key length must fit in two bytes 00888 // 00889 TraceLog((CdromDebugWarning, 00890 "DvdDeviceControl - READ_STRUCTURE: output buffer " 00891 "too large\n")); 00892 status = STATUS_INVALID_PARAMETER; 00893 break; 00894 } 00895 00896 IoMarkIrpPending(Irp); 00897 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00898 00899 return STATUS_PENDING; 00900 } 00901 00902 case IOCTL_DVD_START_SESSION: { 00903 00904 TraceLog((CdromDebugTrace, 00905 "DvdDeviceControl: [%p] IOCTL_DVD_START_SESSION\n", Irp)); 00906 00907 if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) { 00908 TraceLog((CdromDebugWarning, 00909 "DvdDeviceControl: License Failure\n")); 00910 status = STATUS_COPY_PROTECTION_FAILURE; 00911 break; 00912 } 00913 00914 if(irpStack->Parameters.DeviceIoControl.OutputBufferLength < 00915 sizeof(DVD_SESSION_ID)) { 00916 00917 TraceLog((CdromDebugWarning, 00918 "DvdDeviceControl: DVD_START_SESSION - output " 00919 "buffer too small\n")); 00920 status = STATUS_BUFFER_TOO_SMALL; 00921 Irp->IoStatus.Information = sizeof(DVD_SESSION_ID); 00922 break; 00923 } 00924 00925 IoMarkIrpPending(Irp); 00926 IoStartPacket(DeviceObject, Irp, NULL, NULL); 00927 00928 return STATUS_PENDING; 00929 } 00930 00931 case IOCTL_DVD_SEND_KEY: 00932 case IOCTL_DVD_SEND_KEY2: { 00933 00934 PDVD_COPY_PROTECT_KEY key = Irp->AssociatedIrp.SystemBuffer; 00935 ULONG keyLength; 00936 00937 TraceLog((CdromDebugTrace, 00938 "DvdDeviceControl: [%p] IOCTL_DVD_SEND_KEY\n", Irp)); 00939 00940 if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) { 00941 TraceLog((CdromDebugWarning, 00942 "DvdDeviceControl: License Failure\n")); 00943 status = STATUS_COPY_PROTECTION_FAILURE; 00944 break; 00945 } 00946 00947 if((irpStack->Parameters.DeviceIoControl.InputBufferLength < 00948 sizeof(DVD_COPY_PROTECT_KEY)) || 00949 (irpStack->Parameters.DeviceIoControl.InputBufferLength != 00950 key->KeyLength)) { 00951 00952 // 00953 // Key is too small to have a header or the key length doesn't 00954 // match the input buffer length. Key must be invalid 00955 // 00956 00957 TraceLog((CdromDebugWarning, 00958 "DvdDeviceControl: [%p] IOCTL_DVD_SEND_KEY - " 00959 "key is too small or does not match KeyLength\n", 00960 Irp)); 00961 status = STATUS_INVALID_PARAMETER; 00962 break; 00963 } 00964 00965 // 00966 // allow only certain key type (non-destructive) to go through 00967 // IOCTL_DVD_SEND_KEY (which only requires READ access to the device 00968 // 00969 if (ioctlCode == IOCTL_DVD_SEND_KEY) { 00970 00971 if ((key->KeyType != DvdChallengeKey) && 00972 (key->KeyType != DvdBusKey2) && 00973 (key->KeyType != DvdInvalidateAGID)) { 00974 00975 status = STATUS_INVALID_PARAMETER; 00976 break; 00977 } 00978 } 00979 00980 if (cdData->DvdRpc0Device) { 00981 00982 if (key->KeyType == DvdSetRpcKey) { 00983 00984 PDVD_SET_RPC_KEY rpcKey = (PDVD_SET_RPC_KEY) key->KeyData; 00985 00986 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 00987 DVD_SET_RPC_KEY_LENGTH) { 00988 00989 status = STATUS_INVALID_PARAMETER; 00990 break; 00991 } 00992 00993 // 00994 // we have a request to set region code 00995 // on a RPC0 device which doesn't support 00996 // region coding. 00997 // 00998 // we have to fake it. 00999 // 01000 01001 KeWaitForMutexObject( 01002 &cdData->Rpc0RegionMutex, 01003 UserRequest, 01004 KernelMode, 01005 FALSE, 01006 NULL 01007 ); 01008 01009 if (cdData->DvdRpc0Device && cdData->Rpc0RetryRegistryCallback) { 01010 // 01011 // if currently in-progress, this will just return. 01012 // prevents looping by doing that interlockedExchange() 01013 // 01014 TraceLog((CdromDebugWarning, 01015 "DvdDeviceControl: PickRegion() from " 01016 "SEND_KEY\n")); 01017 CdRomPickDvdRegion(DeviceObject); 01018 } 01019 01020 if (cdData->Rpc0SystemRegion == rpcKey->PreferredDriveRegionCode) { 01021 01022 // 01023 // nothing to change 01024 // 01025 TraceLog((CdromDebugWarning, 01026 "DvdDeviceControl (%p) => not changing " 01027 "regions -- requesting current region\n", 01028 DeviceObject)); 01029 status = STATUS_SUCCESS; 01030 01031 } else if (cdData->Rpc0SystemRegionResetCount == 0) { 01032 01033 // 01034 // not allowed to change it again 01035 // 01036 01037 TraceLog((CdromDebugWarning, 01038 "DvdDeviceControl (%p) => no more region " 01039 "changes are allowed for this device\n", 01040 DeviceObject)); 01041 status = STATUS_CSS_RESETS_EXHAUSTED; 01042 01043 } else { 01044 01045 ULONG i; 01046 UCHAR mask; 01047 ULONG bufferLen; 01048 PDVD_READ_STRUCTURE dvdReadStructure; 01049 PDVD_COPYRIGHT_DESCRIPTOR dvdCopyRight; 01050 IO_STATUS_BLOCK ioStatus; 01051 UCHAR mediaRegionData; 01052 01053 mask = ~rpcKey->PreferredDriveRegionCode; 01054 01055 if (CountOfSetBitsUChar(mask) != 1) { 01056 01057 status = STATUS_INVALID_DEVICE_REQUEST; 01058 break; 01059 } 01060 01061 // 01062 // this test will always be TRUE except during initial 01063 // automatic selection of the first region. 01064 // 01065 01066 if (cdData->Rpc0SystemRegion != 0xff) { 01067 01068 // 01069 // make sure we have a media in the drive with the same 01070 // region code if the drive is already has a region set 01071 // 01072 01073 TraceLog((CdromDebugTrace, 01074 "DvdDeviceControl (%p) => Checking " 01075 "media region\n", 01076 DeviceObject)); 01077 01078 bufferLen = max(sizeof(DVD_DESCRIPTOR_HEADER) + 01079 sizeof(DVD_COPYRIGHT_DESCRIPTOR), 01080 sizeof(DVD_READ_STRUCTURE) 01081 ); 01082 01083 dvdReadStructure = (PDVD_READ_STRUCTURE) 01084 ExAllocatePoolWithTag(PagedPool, 01085 bufferLen, 01086 DVD_TAG_RPC2_CHECK); 01087 01088 if (dvdReadStructure == NULL) { 01089 status = STATUS_INSUFFICIENT_RESOURCES; 01090 KeReleaseMutex(&cdData->Rpc0RegionMutex,FALSE); 01091 break; 01092 } 01093 01094 dvdCopyRight = (PDVD_COPYRIGHT_DESCRIPTOR) 01095 ((PDVD_DESCRIPTOR_HEADER) dvdReadStructure)->Data; 01096 01097 // 01098 // check to see if we have a DVD device 01099 // 01100 01101 RtlZeroMemory (dvdReadStructure, bufferLen); 01102 dvdReadStructure->Format = DvdCopyrightDescriptor; 01103 01104 // 01105 // Build a request for READ_KEY 01106 // 01107 ClassSendDeviceIoControlSynchronous( 01108 IOCTL_DVD_READ_STRUCTURE, 01109 DeviceObject, 01110 dvdReadStructure, 01111 sizeof(DVD_READ_STRUCTURE), 01112 sizeof(DVD_DESCRIPTOR_HEADER) + 01113 sizeof(DVD_COPYRIGHT_DESCRIPTOR), 01114 FALSE, 01115 &ioStatus); 01116 01117 // 01118 // this is just to prevent bugs from creeping in 01119 // if status is not set later in development 01120 // 01121 01122 status = ioStatus.Status; 01123 01124 // 01125 // handle errors 01126 // 01127 01128 if (!NT_SUCCESS(status)) { 01129 KeReleaseMutex(&cdData->Rpc0RegionMutex,FALSE); 01130 ExFreePool(dvdReadStructure); 01131 status = STATUS_INVALID_DEVICE_REQUEST; 01132 break; 01133 } 01134 01135 // 01136 // save the mediaRegionData before freeing the 01137 // allocated memory 01138 // 01139 01140 mediaRegionData = 01141 dvdCopyRight->RegionManagementInformation; 01142 ExFreePool(dvdReadStructure); 01143 01144 TraceLog((CdromDebugWarning, 01145 "DvdDeviceControl (%p) => new mask is %x" 01146 " MediaRegionData is %x\n", DeviceObject, 01147 rpcKey->PreferredDriveRegionCode, 01148 mediaRegionData)); 01149 01150 // 01151 // the media region must match the requested region 01152 // for RPC0 drives for initial region selection 01153 // 01154 01155 if (((UCHAR)~(mediaRegionData | rpcKey->PreferredDriveRegionCode)) == 0) { 01156 KeReleaseMutex(&cdData->Rpc0RegionMutex,FALSE); 01157 status = STATUS_CSS_REGION_MISMATCH; 01158 break; 01159 } 01160 01161 } 01162 01163 // 01164 // now try to set the region 01165 // 01166 01167 TraceLog((CdromDebugTrace, 01168 "DvdDeviceControl (%p) => Soft-Setting " 01169 "region of RPC1 device to %x\n", 01170 DeviceObject, 01171 rpcKey->PreferredDriveRegionCode 01172 )); 01173 01174 status = CdRomSetRpc0Settings(DeviceObject, 01175 rpcKey->PreferredDriveRegionCode); 01176 01177 if (!NT_SUCCESS(status)) { 01178 TraceLog((CdromDebugWarning, 01179 "DvdDeviceControl (%p) => Could not " 01180 "set region code (%x)\n", 01181 DeviceObject, status 01182 )); 01183 } else { 01184 01185 TraceLog((CdromDebugTrace, 01186 "DvdDeviceControl (%p) => New region set " 01187 " for RPC1 drive\n", DeviceObject)); 01188 01189 // 01190 // if it worked, our extension is already updated. 01191 // release the mutex 01192 // 01193 01194 DebugPrint ((4, "DvdDeviceControl (%p) => DVD current " 01195 "region bitmap 0x%x\n", DeviceObject, 01196 cdData->Rpc0SystemRegion)); 01197 DebugPrint ((4, "DvdDeviceControl (%p) => DVD region " 01198 " reset Count 0x%x\n", DeviceObject, 01199 cdData->Rpc0SystemRegionResetCount)); 01200 } 01201 01202 } 01203 01204 KeReleaseMutex(&cdData->Rpc0RegionMutex,FALSE); 01205 break; 01206 } // end of key->KeyType == DvdSetRpcKey 01207 } // end of Rpc0Device hacks 01208 01209 IoMarkIrpPending(Irp); 01210 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01211 return STATUS_PENDING; 01212 break; 01213 } 01214 01215 case IOCTL_DVD_READ_KEY: { 01216 01217 PDVD_COPY_PROTECT_KEY keyParameters = Irp->AssociatedIrp.SystemBuffer; 01218 ULONG keyLength; 01219 01220 TraceLog((CdromDebugTrace, 01221 "DvdDeviceControl: [%p] IOCTL_DVD_READ_KEY\n", Irp)); 01222 01223 if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) { 01224 TraceLog((CdromDebugWarning, 01225 "DvdDeviceControl: License Failure\n")); 01226 status = STATUS_COPY_PROTECTION_FAILURE; 01227 break; 01228 } 01229 01230 if (cdData->DvdRpc0Device && cdData->Rpc0RetryRegistryCallback) { 01231 TraceLog((CdromDebugWarning, 01232 "DvdDeviceControl: PickRegion() from READ_KEY\n")); 01233 CdRomPickDvdRegion(DeviceObject); 01234 } 01235 01236 01237 if(irpStack->Parameters.DeviceIoControl.InputBufferLength < 01238 sizeof(DVD_COPY_PROTECT_KEY)) { 01239 01240 TraceLog((CdromDebugWarning, 01241 "DvdDeviceControl: EstablishDriveKey - challenge " 01242 "key buffer too small\n")); 01243 01244 status = STATUS_INVALID_PARAMETER; 01245 break; 01246 01247 } 01248 01249 01250 switch(keyParameters->KeyType) { 01251 01252 case DvdChallengeKey: 01253 keyLength = DVD_CHALLENGE_KEY_LENGTH; 01254 break; 01255 01256 case DvdBusKey1: 01257 case DvdBusKey2: 01258 01259 keyLength = DVD_BUS_KEY_LENGTH; 01260 break; 01261 01262 case DvdTitleKey: 01263 keyLength = DVD_TITLE_KEY_LENGTH; 01264 break; 01265 01266 case DvdAsf: 01267 keyLength = DVD_ASF_LENGTH; 01268 break; 01269 01270 case DvdDiskKey: 01271 keyLength = DVD_DISK_KEY_LENGTH; 01272 break; 01273 01274 case DvdGetRpcKey: 01275 keyLength = DVD_RPC_KEY_LENGTH; 01276 break; 01277 01278 default: 01279 keyLength = sizeof(DVD_COPY_PROTECT_KEY); 01280 break; 01281 } 01282 01283 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 01284 keyLength) { 01285 01286 TraceLog((CdromDebugWarning, 01287 "DvdDeviceControl: EstablishDriveKey - output " 01288 "buffer too small\n")); 01289 status = STATUS_BUFFER_TOO_SMALL; 01290 Irp->IoStatus.Information = keyLength; 01291 break; 01292 } 01293 01294 if (keyParameters->KeyType == DvdGetRpcKey) { 01295 01296 CdRomPickDvdRegion(DeviceObject); 01297 } 01298 01299 if ((keyParameters->KeyType == DvdGetRpcKey) && 01300 (cdData->DvdRpc0Device)) { 01301 01302 PDVD_RPC_KEY rpcKey; 01303 rpcKey = (PDVD_RPC_KEY)keyParameters->KeyData; 01304 RtlZeroMemory (rpcKey, sizeof (*rpcKey)); 01305 01306 KeWaitForMutexObject( 01307 &cdData->Rpc0RegionMutex, 01308 UserRequest, 01309 KernelMode, 01310 FALSE, 01311 NULL 01312 ); 01313 01314 // 01315 // make up the data 01316 // 01317 rpcKey->UserResetsAvailable = cdData->Rpc0SystemRegionResetCount; 01318 rpcKey->ManufacturerResetsAvailable = 0; 01319 if (cdData->Rpc0SystemRegion == 0xff) { 01320 rpcKey->TypeCode = 0; 01321 } else { 01322 rpcKey->TypeCode = 1; 01323 } 01324 rpcKey->RegionMask = (UCHAR) cdData->Rpc0SystemRegion; 01325 rpcKey->RpcScheme = 1; 01326 01327 KeReleaseMutex( 01328 &cdData->Rpc0RegionMutex, 01329 FALSE 01330 ); 01331 01332 Irp->IoStatus.Information = DVD_RPC_KEY_LENGTH; 01333 status = STATUS_SUCCESS; 01334 break; 01335 01336 } else if (keyParameters->KeyType == DvdDiskKey) { 01337 01338 PDVD_COPY_PROTECT_KEY keyHeader; 01339 PDVD_READ_STRUCTURE readStructureRequest; 01340 01341 // 01342 // Special case - build a request to get the dvd structure 01343 // so we can get the disk key. 01344 // 01345 01346 // 01347 // save the key header so we can restore the interesting 01348 // parts later 01349 // 01350 01351 keyHeader = ExAllocatePoolWithTag(NonPagedPool, 01352 sizeof(DVD_COPY_PROTECT_KEY), 01353 DVD_TAG_READ_KEY); 01354 01355 if(keyHeader == NULL) { 01356 01357 // 01358 // Can't save the context so return an error 01359 // 01360 01361 TraceLog((CdromDebugWarning, 01362 "DvdDeviceControl - READ_KEY: unable to " 01363 "allocate context\n")); 01364 status = STATUS_INSUFFICIENT_RESOURCES; 01365 break; 01366 } 01367 01368 RtlCopyMemory(keyHeader, 01369 Irp->AssociatedIrp.SystemBuffer, 01370 sizeof(DVD_COPY_PROTECT_KEY)); 01371 01372 IoCopyCurrentIrpStackLocationToNext(Irp); 01373 01374 nextStack = IoGetNextIrpStackLocation(Irp); 01375 01376 nextStack->Parameters.DeviceIoControl.IoControlCode = 01377 IOCTL_DVD_READ_STRUCTURE; 01378 01379 readStructureRequest = Irp->AssociatedIrp.SystemBuffer; 01380 readStructureRequest->Format = DvdDiskKeyDescriptor; 01381 readStructureRequest->BlockByteOffset.QuadPart = 0; 01382 readStructureRequest->LayerNumber = 0; 01383 readStructureRequest->SessionId = keyHeader->SessionId; 01384 01385 nextStack->Parameters.DeviceIoControl.InputBufferLength = 01386 sizeof(DVD_READ_STRUCTURE); 01387 01388 nextStack->Parameters.DeviceIoControl.OutputBufferLength = 01389 sizeof(READ_DVD_STRUCTURES_HEADER) + sizeof(DVD_DISK_KEY_DESCRIPTOR); 01390 01391 IoSetCompletionRoutine(Irp, 01392 CdRomDvdReadDiskKeyCompletion, 01393 (PVOID) keyHeader, 01394 TRUE, 01395 TRUE, 01396 TRUE); 01397 01398 { 01399 UCHAR uniqueAddress; 01400 ClassAcquireRemoveLock(DeviceObject, (PIRP)&uniqueAddress); 01401 ClassReleaseRemoveLock(DeviceObject, Irp); 01402 01403 IoMarkIrpPending(Irp); 01404 IoCallDriver(commonExtension->DeviceObject, Irp); 01405 status = STATUS_PENDING; 01406 01407 ClassReleaseRemoveLock(DeviceObject, (PIRP)&uniqueAddress); 01408 } 01409 01410 return STATUS_PENDING; 01411 01412 } else { 01413 01414 IoMarkIrpPending(Irp); 01415 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01416 01417 } 01418 return STATUS_PENDING; 01419 } 01420 01421 case IOCTL_DVD_END_SESSION: { 01422 01423 PDVD_SESSION_ID sessionId = Irp->AssociatedIrp.SystemBuffer; 01424 01425 TraceLog((CdromDebugTrace, 01426 "DvdDeviceControl: [%p] END_SESSION\n", Irp)); 01427 01428 if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) { 01429 TraceLog((CdromDebugWarning, 01430 "DvdDeviceControl: License Failure\n")); 01431 status = STATUS_COPY_PROTECTION_FAILURE; 01432 break; 01433 } 01434 01435 if(irpStack->Parameters.DeviceIoControl.InputBufferLength < 01436 sizeof(DVD_SESSION_ID)) { 01437 01438 TraceLog((CdromDebugWarning, 01439 "DvdDeviceControl: EndSession - input buffer too " 01440 "small\n")); 01441 status = STATUS_INVALID_PARAMETER; 01442 break; 01443 } 01444 01445 IoMarkIrpPending(Irp); 01446 01447 if(*sessionId == DVD_END_ALL_SESSIONS) { 01448 01449 status = CdRomDvdEndAllSessionsCompletion(DeviceObject, Irp, NULL); 01450 01451 if(status == STATUS_SUCCESS) { 01452 01453 // 01454 // Just complete the request - it was never issued to the 01455 // lower device 01456 // 01457 01458 break; 01459 01460 } else { 01461 01462 return STATUS_PENDING; 01463 01464 } 01465 } 01466 01467 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01468 01469 return STATUS_PENDING; 01470 } 01471 01472 case IOCTL_DVD_GET_REGION: { 01473 01474 PDVD_COPY_PROTECT_KEY copyProtectKey; 01475 ULONG keyLength; 01476 IO_STATUS_BLOCK ioStatus; 01477 PDVD_DESCRIPTOR_HEADER dvdHeader; 01478 PDVD_COPYRIGHT_DESCRIPTOR copyRightDescriptor; 01479 PDVD_REGION dvdRegion; 01480 PDVD_READ_STRUCTURE readStructure; 01481 PDVD_RPC_KEY rpcKey; 01482 01483 TraceLog((CdromDebugTrace, 01484 "DvdDeviceControl: [%p] IOCTL_DVD_GET_REGION\n", Irp)); 01485 01486 if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) { 01487 TraceLog((CdromDebugWarning, 01488 "DvdDeviceControl: License Failure\n")); 01489 status = STATUS_COPY_PROTECTION_FAILURE; 01490 break; 01491 } 01492 01493 if(irpStack->Parameters.DeviceIoControl.OutputBufferLength < 01494 sizeof(DVD_REGION)) { 01495 01496 TraceLog((CdromDebugWarning, 01497 "DvdDeviceControl: output buffer DVD_REGION too small\n")); 01498 status = STATUS_INVALID_PARAMETER; 01499 break; 01500 } 01501 01502 // 01503 // figure out how much data buffer we need 01504 // 01505 01506 keyLength = max(sizeof(DVD_DESCRIPTOR_HEADER) + 01507 sizeof(DVD_COPYRIGHT_DESCRIPTOR), 01508 sizeof(DVD_READ_STRUCTURE) 01509 ); 01510 keyLength = max(keyLength, 01511 DVD_RPC_KEY_LENGTH 01512 ); 01513 01514 // 01515 // round the size to nearest ULONGLONG -- why? 01516 // 01517 01518 keyLength += sizeof(ULONGLONG) - (keyLength & (sizeof(ULONGLONG) - 1)); 01519 01520 readStructure = ExAllocatePoolWithTag(NonPagedPool, 01521 keyLength, 01522 DVD_TAG_READ_KEY); 01523 if (readStructure == NULL) { 01524 status = STATUS_INSUFFICIENT_RESOURCES; 01525 break; 01526 } 01527 01528 RtlZeroMemory (readStructure, keyLength); 01529 readStructure->Format = DvdCopyrightDescriptor; 01530 01531 // 01532 // Build a request for READ_STRUCTURE 01533 // 01534 01535 ClassSendDeviceIoControlSynchronous( 01536 IOCTL_DVD_READ_STRUCTURE, 01537 DeviceObject, 01538 readStructure, 01539 keyLength, 01540 sizeof(DVD_DESCRIPTOR_HEADER) + 01541 sizeof(DVD_COPYRIGHT_DESCRIPTOR), 01542 FALSE, 01543 &ioStatus); 01544 01545 status = ioStatus.Status; 01546 01547 if (!NT_SUCCESS(status)) { 01548 TraceLog((CdromDebugWarning, 01549 "CdRomDvdGetRegion => read structure failed %x\n", 01550 status)); 01551 ExFreePool(readStructure); 01552 break; 01553 } 01554 01555 // 01556 // we got the copyright descriptor, so now get the region if possible 01557 // 01558 01559 dvdHeader = (PDVD_DESCRIPTOR_HEADER) readStructure; 01560 copyRightDescriptor = (PDVD_COPYRIGHT_DESCRIPTOR) dvdHeader->Data; 01561 01562 // 01563 // the original irp's systembuffer has a copy of the info that 01564 // should be passed down in the request 01565 // 01566 01567 dvdRegion = Irp->AssociatedIrp.SystemBuffer; 01568 01569 dvdRegion->CopySystem = copyRightDescriptor->CopyrightProtectionType; 01570 dvdRegion->RegionData = copyRightDescriptor->RegionManagementInformation; 01571 01572 // 01573 // now reuse the buffer to request the copy protection info 01574 // 01575 01576 copyProtectKey = (PDVD_COPY_PROTECT_KEY) readStructure; 01577 RtlZeroMemory (copyProtectKey, DVD_RPC_KEY_LENGTH); 01578 copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH; 01579 copyProtectKey->KeyType = DvdGetRpcKey; 01580 01581 // 01582 // send a request for READ_KEY 01583 // 01584 01585 ClassSendDeviceIoControlSynchronous( 01586 IOCTL_DVD_READ_KEY, 01587 DeviceObject, 01588 copyProtectKey, 01589 DVD_RPC_KEY_LENGTH, 01590 DVD_RPC_KEY_LENGTH, 01591 FALSE, 01592 &ioStatus); 01593 status = ioStatus.Status; 01594 01595 if (!NT_SUCCESS(status)) { 01596 TraceLog((CdromDebugWarning, 01597 "CdRomDvdGetRegion => read key failed %x\n", 01598 status)); 01599 ExFreePool(readStructure); 01600 break; 01601 } 01602 01603 // 01604 // the request succeeded. if a supported scheme is returned, 01605 // then return the information to the caller 01606 // 01607 01608 rpcKey = (PDVD_RPC_KEY) copyProtectKey->KeyData; 01609 01610 if (rpcKey->RpcScheme == 1) { 01611 01612 if (rpcKey->TypeCode) { 01613 01614 dvdRegion->SystemRegion = ~rpcKey->RegionMask; 01615 dvdRegion->ResetCount = rpcKey->UserResetsAvailable; 01616 01617 } else { 01618 01619 // 01620 // the drive has not been set for any region 01621 // 01622 01623 dvdRegion->SystemRegion = 0; 01624 dvdRegion->ResetCount = rpcKey->UserResetsAvailable; 01625 } 01626 Irp->IoStatus.Information = sizeof(DVD_REGION); 01627 01628 } else { 01629 01630 TraceLog((CdromDebugWarning, 01631 "CdRomDvdGetRegion => rpcKey->RpcScheme != 1\n")); 01632 status = STATUS_INVALID_DEVICE_REQUEST; 01633 } 01634 01635 ExFreePool(readStructure); 01636 break; 01637 } 01638 01639 01640 case IOCTL_STORAGE_SET_READ_AHEAD: { 01641 01642 if(irpStack->Parameters.DeviceIoControl.InputBufferLength < 01643 sizeof(STORAGE_SET_READ_AHEAD)) { 01644 01645 TraceLog((CdromDebugWarning, 01646 "DvdDeviceControl: SetReadAhead buffer too small\n")); 01647 status = STATUS_INVALID_PARAMETER; 01648 break; 01649 } 01650 01651 IoMarkIrpPending(Irp); 01652 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01653 01654 return STATUS_PENDING; 01655 } 01656 01657 case IOCTL_DISK_IS_WRITABLE: { 01658 01659 IoMarkIrpPending(Irp); 01660 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01661 01662 return STATUS_PENDING; 01663 01664 } 01665 01666 case IOCTL_DISK_GET_DRIVE_LAYOUT: { 01667 01668 ULONG size; 01669 01670 // 01671 // we always fake zero or one partitions, and one partition 01672 // structure is included in DRIVE_LAYOUT_INFORMATION 01673 // 01674 01675 size = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]); 01676 01677 01678 TraceLog((CdromDebugTrace, 01679 "CdRomDeviceControl: Get drive layout\n")); 01680 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < size) { 01681 status = STATUS_BUFFER_TOO_SMALL; 01682 Irp->IoStatus.Information = size; 01683 break; 01684 } 01685 01686 IoMarkIrpPending(Irp); 01687 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01688 return STATUS_PENDING; 01689 01690 01691 } 01692 case IOCTL_DISK_GET_DRIVE_LAYOUT_EX: { 01693 01694 ULONG size; 01695 01696 // 01697 // we always fake zero or one partitions, and one partition 01698 // structure is included in DRIVE_LAYOUT_INFORMATION_EX 01699 // 01700 01701 size = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]); 01702 01703 TraceLog((CdromDebugTrace, 01704 "CdRomDeviceControl: Get drive layout ex\n")); 01705 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < size) { 01706 status = STATUS_BUFFER_TOO_SMALL; 01707 Irp->IoStatus.Information = size; 01708 break; 01709 } 01710 01711 IoMarkIrpPending(Irp); 01712 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01713 return STATUS_PENDING; 01714 01715 } 01716 01717 01718 case IOCTL_DISK_GET_PARTITION_INFO: { 01719 01720 // 01721 // Check that the buffer is large enough. 01722 // 01723 01724 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 01725 sizeof(PARTITION_INFORMATION)) { 01726 01727 status = STATUS_BUFFER_TOO_SMALL; 01728 Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION); 01729 break; 01730 } 01731 01732 IoMarkIrpPending(Irp); 01733 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01734 return STATUS_PENDING; 01735 01736 } 01737 case IOCTL_DISK_GET_PARTITION_INFO_EX: { 01738 01739 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 01740 sizeof(PARTITION_INFORMATION_EX)) { 01741 01742 status = STATUS_BUFFER_TOO_SMALL; 01743 Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX); 01744 break; 01745 } 01746 01747 IoMarkIrpPending(Irp); 01748 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01749 return STATUS_PENDING; 01750 } 01751 01752 case IOCTL_DISK_VERIFY: { 01753 01754 TraceLog((CdromDebugTrace, 01755 "IOCTL_DISK_VERIFY to device %p through irp %p\n", 01756 DeviceObject, Irp)); 01757 01758 // 01759 // Validate buffer length. 01760 // 01761 01762 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < 01763 sizeof(VERIFY_INFORMATION)) { 01764 01765 status = STATUS_INFO_LENGTH_MISMATCH; 01766 break; 01767 } 01768 IoMarkIrpPending(Irp); 01769 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01770 return STATUS_PENDING; 01771 } 01772 01773 case IOCTL_DISK_GET_LENGTH_INFO: { 01774 01775 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 01776 sizeof(GET_LENGTH_INFORMATION)) { 01777 status = STATUS_BUFFER_TOO_SMALL; 01778 Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); 01779 break; 01780 } 01781 IoMarkIrpPending(Irp); 01782 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01783 return STATUS_PENDING; 01784 } 01785 01786 case IOCTL_CDROM_GET_CONFIGURATION: { 01787 01788 PGET_CONFIGURATION_IOCTL_INPUT inputBuffer; 01789 01790 TraceLog((CdromDebugTrace, 01791 "IOCTL_CDROM_GET_CONFIGURATION to via irp %p\n", Irp)); 01792 01793 // 01794 // Validate buffer length. 01795 // 01796 01797 if (irpStack->Parameters.DeviceIoControl.InputBufferLength != 01798 sizeof(GET_CONFIGURATION_IOCTL_INPUT)) { 01799 status = STATUS_INFO_LENGTH_MISMATCH; 01800 break; 01801 } 01802 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < 01803 sizeof(GET_CONFIGURATION_HEADER)) { 01804 status = STATUS_BUFFER_TOO_SMALL; 01805 Irp->IoStatus.Information = sizeof(GET_CONFIGURATION_HEADER); 01806 break; 01807 } 01808 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength > 0xffff) { 01809 // output buffer is too large 01810 status = STATUS_INVALID_BUFFER_SIZE; 01811 break; 01812 } 01813 01814 // 01815 // also verify the arguments are reasonable. 01816 // 01817 01818 inputBuffer = Irp->AssociatedIrp.SystemBuffer; 01819 if (inputBuffer->Feature > 0xffff) { 01820 status = STATUS_INVALID_PARAMETER; 01821 break; 01822 } 01823 if ((inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) && 01824 (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT) && 01825 (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL)) { 01826 status = STATUS_INVALID_PARAMETER; 01827 break; 01828 } 01829 if (inputBuffer->Reserved[0] || inputBuffer->Reserved[1]) { 01830 status = STATUS_INVALID_PARAMETER; 01831 break; 01832 } 01833 01834 IoMarkIrpPending(Irp); 01835 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01836 return STATUS_PENDING; 01837 01838 } 01839 01840 default: { 01841 01842 BOOLEAN synchronize = (KeGetCurrentIrql() == PASSIVE_LEVEL); 01843 PKEVENT deviceControlEvent; 01844 01845 // 01846 // If the ioctl has come in at passive level then we will synchronize 01847 // with our start-io routine when sending the ioctl. If the ioctl 01848 // has come in at a higher interrupt level and it was not handled 01849 // above then it's unlikely to be a request for the class DLL - however 01850 // we'll still use it's common code to forward the request through. 01851 // 01852 01853 if (synchronize) { 01854 01855 deviceControlEvent = ExAllocatePoolWithTag(NonPagedPool, 01856 sizeof(KEVENT), 01857 CDROM_TAG_DC_EVENT); 01858 01859 if (deviceControlEvent == NULL) { 01860 01861 // 01862 // must complete this irp unsuccessful here 01863 // 01864 status = STATUS_INSUFFICIENT_RESOURCES; 01865 break; 01866 01867 } else { 01868 01869 PIO_STACK_LOCATION currentStack; 01870 01871 KeInitializeEvent(deviceControlEvent, NotificationEvent, FALSE); 01872 01873 currentStack = IoGetCurrentIrpStackLocation(Irp); 01874 nextStack = IoGetNextIrpStackLocation(Irp); 01875 01876 // 01877 // Copy the stack down a notch 01878 // 01879 01880 IoCopyCurrentIrpStackLocationToNext(Irp); 01881 01882 IoSetCompletionRoutine( 01883 Irp, 01884 CdRomClassIoctlCompletion, 01885 deviceControlEvent, 01886 TRUE, 01887 TRUE, 01888 TRUE 01889 ); 01890 01891 IoSetNextIrpStackLocation(Irp); 01892 01893 Irp->IoStatus.Status = STATUS_SUCCESS; 01894 Irp->IoStatus.Information = 0; 01895 01896 // 01897 // Override volume verifies on this stack location so that we 01898 // will be forced through the synchronization. Once this 01899 // location goes away we get the old value back 01900 // 01901 01902 SET_FLAG(nextStack->Flags, SL_OVERRIDE_VERIFY_VOLUME); 01903 01904 IoStartPacket(DeviceObject, Irp, NULL, NULL); 01905 01906 // 01907 // Wait for CdRomClassIoctlCompletion to set the event. This 01908 // ensures serialization remains intact for these unhandled device 01909 // controls. 01910 // 01911 01912 KeWaitForSingleObject( 01913 deviceControlEvent, 01914 Executive, 01915 KernelMode, 01916 FALSE, 01917 NULL); 01918 01919 ExFreePool(deviceControlEvent); 01920 01921 TraceLog((CdromDebugTrace, 01922 "CdRomDeviceControl: irp %p synchronized\n", Irp)); 01923 01924 status = Irp->IoStatus.Status; 01925 } 01926 01927 } else { 01928 status = STATUS_SUCCESS; 01929 } 01930 01931 // 01932 // If an error occured then propagate that back up - we are no longer 01933 // guaranteed synchronization and the upper layers will have to 01934 // retry. 01935 // 01936 // If no error occured, call down to the class driver directly 01937 // then start up the next request. 01938 // 01939 01940 if (NT_SUCCESS(status)) { 01941 01942 UCHAR uniqueAddress; 01943 01944 // 01945 // The class device control routine will release the remove 01946 // lock for this Irp. We need to make sure we have one 01947 // available so that it's safe to call IoStartNextPacket 01948 // 01949 01950 if(synchronize) { 01951 01952 ClassAcquireRemoveLock(DeviceObject, (PIRP)&uniqueAddress); 01953 01954 } 01955 01956 status = ClassDeviceControl(DeviceObject, Irp); 01957 01958 if(synchronize) { 01959 KeRaiseIrql(DISPATCH_LEVEL, &irql); 01960 IoStartNextPacket(DeviceObject, FALSE); 01961 KeLowerIrql(irql); 01962 ClassReleaseRemoveLock(DeviceObject, (PIRP)&uniqueAddress); 01963 } 01964 return status; 01965 01966 } 01967 01968 // 01969 // an error occurred (either STATUS_INSUFFICIENT_RESOURCES from 01970 // attempting to synchronize or StartIo() error'd this one 01971 // out), so we need to finish the irp, which is 01972 // done at the end of this routine. 01973 // 01974 break; 01975 01976 } // end default case 01977 01978 } // end switch() 01979 01980 if (status == STATUS_VERIFY_REQUIRED) { 01981 01982 // 01983 // If the status is verified required and this request 01984 // should bypass verify required then retry the request. 01985 // 01986 01987 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) { 01988 01989 status = STATUS_IO_DEVICE_ERROR; 01990 goto RetryControl; 01991 01992 } 01993 } 01994 01995 if (IoIsErrorUserInduced(status)) { 01996 01997 if (Irp->Tail.Overlay.Thread) { 01998 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); 01999 } 02000 02001 } 02002 02003 // 02004 // Update IRP with completion status. 02005 // 02006 02007 Irp->IoStatus.Status = status; 02008 02009 // 02010 // Complete the request. 02011 // 02012 02013 ClassReleaseRemoveLock(DeviceObject, Irp); 02014 ClassCompleteRequest(DeviceObject, Irp, IO_DISK_INCREMENT); 02015 TraceLog((CdromDebugTrace, 02016 "CdRomDeviceControl: Status is %lx\n", status)); 02017 return status; 02018 02019 } // end CdRomDeviceControl() 02020 02021 02022 NTSTATUS 02023 CdRomClassIoctlCompletion( 02024 IN PDEVICE_OBJECT DeviceObject, 02025 IN PIRP Irp, 02026 IN PVOID Context 02027 ) 02028 /*++ 02029 02030 Routine Description: 02031 02032 This routine signals the event used by CdRomDeviceControl to synchronize 02033 class driver (and lower level driver) ioctls with cdrom's startio routine. 02034 The irp completion is short-circuited so that CdRomDeviceControlDispatch 02035 can reissue it once it wakes up. 02036 02037 Arguments: 02038 02039 DeviceObject - the device object 02040 Irp - the request we are synchronizing 02041 Context - a PKEVENT that we need to signal 02042 02043 Return Value: 02044 02045 NTSTATUS 02046 02047 --*/ 02048 { 02049 PKEVENT syncEvent = (PKEVENT) Context; 02050 02051 TraceLog((CdromDebugTrace, 02052 "CdRomClassIoctlCompletion: setting event for irp %p\n", Irp)); 02053 02054 // 02055 // We released the lock when we completed this request. Reacquire it. 02056 // 02057 02058 ClassAcquireRemoveLock(DeviceObject, Irp); 02059 02060 KeSetEvent(syncEvent, IO_DISK_INCREMENT, FALSE); 02061 02062 return STATUS_MORE_PROCESSING_REQUIRED; 02063 } 02064 02065 02066 NTSTATUS 02067 CdRomDeviceControlCompletion( 02068 IN PDEVICE_OBJECT DeviceObject, 02069 IN PIRP Irp, 02070 IN PVOID Context 02071 ) 02072 { 02073 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; 02074 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; 02075 02076 PCDROM_DATA cdData = (PCDROM_DATA)(commonExtension->DriverData); 02077 BOOLEAN use6Byte = TEST_FLAG(cdData->XAFlags, XA_USE_6_BYTE); 02078 02079 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 02080 PIO_STACK_LOCATION realIrpStack; 02081 PIO_STACK_LOCATION realIrpNextStack; 02082 02083 PSCSI_REQUEST_BLOCK srb = Context; 02084 02085 PIRP realIrp = NULL; 02086 02087 NTSTATUS status; 02088 BOOLEAN retry; 02089 ULONG retryCount; 02090 02091 // 02092 // Extract the 'real' irp from the irpstack. 02093 // 02094 02095 realIrp = (PIRP) irpStack->Parameters.Others.Argument2; 02096 realIrpStack = IoGetCurrentIrpStackLocation(realIrp); 02097 realIrpNextStack = IoGetNextIrpStackLocation(realIrp); 02098 02099 // 02100 // check that we've really got the correct irp 02101 // 02102 02103 ASSERT(realIrpNextStack->Parameters.Others.Argument3 == Irp); 02104 02105 // 02106 // Check SRB status for success of completing request. 02107 // 02108 02109 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 02110 02111 ULONG retryInterval; 02112 02113 TraceLog((CdromDebugTrace, 02114 "CdRomDeviceControlCompletion: Irp %p, Srb %p Real Irp %p Status %lx\n", 02115 Irp, 02116 srb, 02117 realIrp, 02118 srb->SrbStatus)); 02119 02120 // 02121 // Release the queue if it is frozen. 02122 // 02123 02124 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 02125 TraceLog((CdromDebugTrace, 02126 "CdRomDeviceControlCompletion: Releasing Queue\n")); 02127 ClassReleaseQueue(DeviceObject); 02128 } 02129 02130 02131 retry = ClassInterpretSenseInfo(DeviceObject, 02132 srb, 02133 irpStack->MajorFunction, 02134 irpStack->Parameters.DeviceIoControl.IoControlCode, 02135 MAXIMUM_RETRIES - ((ULONG)(ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1), 02136 &status, 02137 &retryInterval); 02138 02139 TraceLog((CdromDebugTrace, 02140 "CdRomDeviceControlCompletion: IRP will %sbe retried\n", 02141 (retry ? "" : "not "))); 02142 02143 // 02144 // Some of the Device Controls need special cases on non-Success status's. 02145 // 02146 02147 if (realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) { 02148 if ((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_LAST_SESSION) || 02149 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) || 02150 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC_EX) || 02151 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_CONTROL) || 02152 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_VOLUME)) { 02153 02154 if (status == STATUS_DATA_OVERRUN) { 02155 status = STATUS_SUCCESS; 02156 retry = FALSE; 02157 } 02158 } 02159 02160 if (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_Q_CHANNEL) { 02161 PLAY_ACTIVE(fdoExtension) = FALSE; 02162 } 02163 } 02164 02165 // 02166 // If the status is verified required and the this request 02167 // should bypass verify required then retry the request. 02168 // 02169 02170 if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 02171 status == STATUS_VERIFY_REQUIRED) { 02172 02173 // note: status gets overwritten here 02174 status = STATUS_IO_DEVICE_ERROR; 02175 retry = TRUE; 02176 02177 if (((realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) || 02178 (realIrpStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) 02179 ) && 02180 ((realIrpStack->Parameters.DeviceIoControl.IoControlCode == 02181 IOCTL_CDROM_CHECK_VERIFY) || 02182 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == 02183 IOCTL_STORAGE_CHECK_VERIFY) || 02184 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == 02185 IOCTL_STORAGE_CHECK_VERIFY2) || 02186 (realIrpStack->Parameters.DeviceIoControl.IoControlCode == 02187 IOCTL_DISK_CHECK_VERIFY) 02188 ) 02189 ) { 02190 02191 // 02192 // Update the geometry information, as the media could have 02193 // changed. The completion routine for this will complete 02194 // the real irp and start the next packet. 02195 // 02196 02197 if (srb) { 02198 if (srb->SenseInfoBuffer) { 02199 ExFreePool(srb->SenseInfoBuffer); 02200 } 02201 if (srb->DataBuffer) { 02202 ExFreePool(srb->DataBuffer); 02203 } 02204 ExFreePool(srb); 02205 srb = NULL; 02206 } 02207 02208 if (Irp->MdlAddress) { 02209 IoFreeMdl(Irp->MdlAddress); 02210 Irp->MdlAddress = NULL; 02211 } 02212 02213 IoFreeIrp(Irp); 02214 Irp = NULL; 02215 02216 status = CdRomUpdateCapacity(fdoExtension, realIrp, NULL); 02217 TraceLog((CdromDebugTrace, 02218 "CdRomDeviceControlCompletion: [%p] " 02219 "CdRomUpdateCapacity completed with status %lx\n", 02220 realIrp, status)); 02221 02222 // 02223 // needed to update the capacity. 02224 // the irp's already handed off to CdRomUpdateCapacity(). 02225 // we've already free'd the current irp. 02226 // nothing left to do in this code path. 02227 // 02228 02229 return STATUS_MORE_PROCESSING_REQUIRED; 02230 02231 } // end of ioctls to update capacity 02232 02233 } 02234 02235 // 02236 // get current retry count 02237 // 02238 retryCount = PtrToUlong(realIrpNextStack->Parameters.Others.Argument1); 02239 02240 if (retry && retryCount) { 02241 02242 // 02243 // update retry count 02244 // 02245 realIrpNextStack->Parameters.Others.Argument1 = UlongToPtr(retryCount-1); 02246 02247 if (((ULONG)(ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) { 02248 02249 // 02250 // Retry request. 02251 // 02252 02253 TraceLog((CdromDebugWarning, 02254 "Retry request %p - Calling StartIo\n", Irp)); 02255 02256 02257 ExFreePool(srb->SenseInfoBuffer); 02258 if (srb->DataBuffer) { 02259 ExFreePool(srb->DataBuffer); 02260 } 02261 ExFreePool(srb); 02262 if (Irp->MdlAddress) { 02263 IoFreeMdl(Irp->MdlAddress); 02264 } 02265 02266 realIrpNextStack->Parameters.Others.Argument3 = (PVOID)-1; 02267 IoFreeIrp(Irp); 02268 02269 CdRomRetryRequest(fdoExtension, realIrp, retryInterval, FALSE); 02270 return STATUS_MORE_PROCESSING_REQUIRED; 02271 } 02272 02273 // 02274 // Exhausted retries. Fall through and complete the request with 02275 // the appropriate status. 02276 // 02277 02278 } 02279 } else { 02280 02281 // 02282 // Set status for successful request. 02283 // 02284 02285 status = STATUS_SUCCESS; 02286 02287 } 02288 02289 02290 if (NT_SUCCESS(status)) { 02291 02292 BOOLEAN b = FALSE; 02293 02294 02295 switch (realIrpStack->Parameters.DeviceIoControl.IoControlCode) { 02296 02297 case IOCTL_CDROM_GET_CONFIGURATION: { 02298 RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, 02299 srb->DataBuffer, 02300 srb->DataTransferLength); 02301 realIrp->IoStatus.Information = srb->DataTransferLength; 02302 break; 02303 } 02304 02305 case IOCTL_DISK_GET_LENGTH_INFO: { 02306 02307 PGET_LENGTH_INFORMATION lengthInfo; 02308 02309 CdRomInterpretReadCapacity(DeviceObject, 02310 (PREAD_CAPACITY_DATA)srb->DataBuffer); 02311 02312 lengthInfo = (PGET_LENGTH_INFORMATION)realIrp->AssociatedIrp.SystemBuffer; 02313 lengthInfo->Length = commonExtension->PartitionLength; 02314 realIrp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); 02315 status = STATUS_SUCCESS; 02316 break; 02317 } 02318 02319 case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: 02320 case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: { 02321 02322 PDISK_GEOMETRY_EX geometryEx; 02323 02324 CdRomInterpretReadCapacity(DeviceObject, 02325 (PREAD_CAPACITY_DATA)srb->DataBuffer); 02326 02327 geometryEx = (PDISK_GEOMETRY_EX)(realIrp->AssociatedIrp.SystemBuffer); 02328 geometryEx->DiskSize = commonExtension->PartitionLength; 02329 geometryEx->Geometry = fdoExtension->DiskGeometry; 02330 realIrp->IoStatus.Information = 02331 FIELD_OFFSET(DISK_GEOMETRY_EX, Data); 02332 break; 02333 } 02334 02335 case IOCTL_DISK_GET_DRIVE_GEOMETRY: 02336 case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { 02337 02338 PDISK_GEOMETRY geometry; 02339 02340 CdRomInterpretReadCapacity(DeviceObject, 02341 (PREAD_CAPACITY_DATA)srb->DataBuffer); 02342 02343 geometry = (PDISK_GEOMETRY)(realIrp->AssociatedIrp.SystemBuffer); 02344 *geometry = fdoExtension->DiskGeometry; 02345 realIrp->IoStatus.Information = sizeof(DISK_GEOMETRY); 02346 break; 02347 } 02348 02349 case IOCTL_DISK_VERIFY: { 02350 // 02351 // nothing to do but return the status... 02352 // 02353 break; 02354 } 02355 02356 case IOCTL_DISK_CHECK_VERIFY: 02357 case IOCTL_STORAGE_CHECK_VERIFY: 02358 case IOCTL_CDROM_CHECK_VERIFY: { 02359 02360 if((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY) && 02361 (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength)) { 02362 02363 *((PULONG)realIrp->AssociatedIrp.SystemBuffer) = 02364 commonExtension->PartitionZeroExtension->MediaChangeCount; 02365 02366 realIrp->IoStatus.Information = sizeof(ULONG); 02367 } else { 02368 realIrp->IoStatus.Information = 0; 02369 } 02370 02371 TraceLog((CdromDebugTrace, 02372 "CdRomDeviceControlCompletion: [%p] completing " 02373 "CHECK_VERIFY buddy irp %p\n", realIrp, Irp)); 02374 break; 02375 } 02376 02377 case IOCTL_CDROM_READ_TOC_EX: { 02378 02379 if (srb->DataTransferLength < MINIMUM_CDROM_READ_TOC_EX_SIZE) { 02380 status = STATUS_INVALID_DEVICE_REQUEST; 02381 break; 02382 } 02383 02384 // 02385 // Copy the returned info into the user buffer. 02386 // 02387 02388 RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, 02389 srb->DataBuffer, 02390 srb->DataTransferLength); 02391 02392 // 02393 // update information field. 02394 // 02395 02396 realIrp->IoStatus.Information = srb->DataTransferLength; 02397 break; 02398 } 02399 02400 02401 case IOCTL_CDROM_GET_LAST_SESSION: 02402 case IOCTL_CDROM_READ_TOC: { 02403 02404 // 02405 // Copy the returned info into the user buffer. 02406 // 02407 02408 RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, 02409 srb->DataBuffer, 02410 srb->DataTransferLength); 02411 02412 // 02413 // update information field. 02414 // 02415 02416 realIrp->IoStatus.Information = srb->DataTransferLength; 02417 break; 02418 } 02419 02420 case IOCTL_DVD_READ_STRUCTURE: { 02421 02422 DVD_STRUCTURE_FORMAT format = ((PDVD_READ_STRUCTURE) realIrp->AssociatedIrp.SystemBuffer)->Format; 02423 02424 PDVD_DESCRIPTOR_HEADER header = realIrp->AssociatedIrp.SystemBuffer; 02425 02426 FOUR_BYTE fourByte; 02427 PTWO_BYTE twoByte; 02428 UCHAR tmp; 02429 02430 TraceLog((CdromDebugTrace, 02431 "DvdDeviceControlCompletion - IOCTL_DVD_READ_STRUCTURE: completing irp %p (buddy %p)\n", 02432 Irp, 02433 realIrp)); 02434 02435 TraceLog((CdromDebugTrace, 02436 "DvdDCCompletion - READ_STRUCTURE: descriptor format of %d\n", format)); 02437 02438 RtlMoveMemory(header, 02439 srb->DataBuffer, 02440 srb->DataTransferLength); 02441 02442 // 02443 // Cook the data. There are a number of fields that really 02444 // should be byte-swapped for the caller. 02445 // 02446 02447 TraceLog((CdromDebugInfo, 02448 "DvdDCCompletion - READ_STRUCTURE:\n" 02449 "\tHeader at %p\n" 02450 "\tDvdDCCompletion - READ_STRUCTURE: data at %p\n" 02451 "\tDataBuffer was at %p\n" 02452 "\tDataTransferLength was %lx\n", 02453 header, 02454 header->Data, 02455 srb->DataBuffer, 02456 srb->DataTransferLength)); 02457 02458 // 02459 // First the fields in the header 02460 // 02461 02462 TraceLog((CdromDebugInfo, "READ_STRUCTURE: header->Length %lx -> ", 02463 header->Length)); 02464 REVERSE_SHORT(&header->Length); 02465 TraceLog((CdromDebugInfo, "%lx\n", header->Length)); 02466 02467 // 02468 // Now the fields in the descriptor 02469 // 02470 02471 if(format == DvdPhysicalDescriptor) { 02472 02473 PDVD_LAYER_DESCRIPTOR layer = (PDVD_LAYER_DESCRIPTOR) &(header->Data[0]); 02474 02475 TraceLog((CdromDebugInfo, "READ_STRUCTURE: StartingDataSector %lx -> ", 02476 layer->StartingDataSector)); 02477 REVERSE_LONG(&(layer->StartingDataSector)); 02478 TraceLog((CdromDebugInfo, "%lx\n", layer->StartingDataSector)); 02479 02480 TraceLog((CdromDebugInfo, "READ_STRUCTURE: EndDataSector %lx -> ", 02481 layer->EndDataSector)); 02482 REVERSE_LONG(&(layer->EndDataSector)); 02483 TraceLog((CdromDebugInfo, "%lx\n", layer->EndDataSector)); 02484 02485 TraceLog((CdromDebugInfo, "READ_STRUCTURE: EndLayerZeroSector %lx -> ", 02486 layer->EndLayerZeroSector)); 02487 REVERSE_LONG(&(layer->EndLayerZeroSector)); 02488 TraceLog((CdromDebugInfo, "%lx\n", layer->EndLayerZeroSector)); 02489 } 02490 02491 TraceLog((CdromDebugTrace, "Status is %lx\n", Irp->IoStatus.Status)); 02492 TraceLog((CdromDebugTrace, "DvdDeviceControlCompletion - " 02493 "IOCTL_DVD_READ_STRUCTURE: data transfer length of %d\n", 02494 srb->DataTransferLength)); 02495 02496 realIrp->IoStatus.Information = srb->DataTransferLength; 02497 break; 02498 } 02499 02500 case IOCTL_DVD_READ_KEY: { 02501 02502 PDVD_COPY_PROTECT_KEY copyProtectKey = realIrp->AssociatedIrp.SystemBuffer; 02503 02504 PCDVD_KEY_HEADER keyHeader = srb->DataBuffer; 02505 ULONG dataLength; 02506 02507 ULONG transferLength = 02508 srb->DataTransferLength - 02509 FIELD_OFFSET(CDVD_KEY_HEADER, Data); 02510 02511 // 02512 // Adjust the data length to ignore the two reserved bytes in the 02513 // header. 02514 // 02515 02516 dataLength = (keyHeader->DataLength[0] << 8) + 02517 keyHeader->DataLength[1]; 02518 dataLength -= 2; 02519 02520 // 02521 // take the minimum of the transferred length and the 02522 // length as specified in the header. 02523 // 02524 02525 if(dataLength < transferLength) { 02526 transferLength = dataLength; 02527 } 02528 02529 TraceLog((CdromDebugTrace, 02530 "DvdDeviceControlCompletion: [%p] - READ_KEY with " 02531 "transfer length of (%d or %d) bytes\n", 02532 Irp, 02533 dataLength, 02534 srb->DataTransferLength - 2)); 02535 02536 // 02537 // Copy the key data into the return buffer 02538 // 02539 if(copyProtectKey->KeyType == DvdTitleKey) { 02540 02541 RtlMoveMemory(copyProtectKey->KeyData, 02542 keyHeader->Data + 1, 02543 transferLength - 1); 02544 copyProtectKey->KeyData[transferLength - 1] = 0; 02545 02546 // 02547 // If this is a title key then we need to copy the CGMS flags 02548 // as well. 02549 // 02550 copyProtectKey->KeyFlags = *(keyHeader->Data); 02551 02552 } else { 02553 02554 RtlMoveMemory(copyProtectKey->KeyData, 02555 keyHeader->Data, 02556 transferLength); 02557 } 02558 02559 copyProtectKey->KeyLength = sizeof(DVD_COPY_PROTECT_KEY); 02560 copyProtectKey->KeyLength += transferLength; 02561 02562 realIrp->IoStatus.Information = copyProtectKey->KeyLength; 02563 break; 02564 } 02565 02566 case IOCTL_DVD_START_SESSION: { 02567 02568 PDVD_SESSION_ID sessionId = realIrp->AssociatedIrp.SystemBuffer; 02569 02570 PCDVD_KEY_HEADER keyHeader = srb->DataBuffer; 02571 PCDVD_REPORT_AGID_DATA keyData = (PCDVD_REPORT_AGID_DATA) keyHeader->Data; 02572 02573 *sessionId = keyData->AGID; 02574 02575 realIrp->IoStatus.Information = sizeof(DVD_SESSION_ID); 02576 02577 break; 02578 } 02579 02580 case IOCTL_DVD_END_SESSION: 02581 case IOCTL_DVD_SEND_KEY: 02582 case IOCTL_DVD_SEND_KEY2: 02583 02584 // 02585 // nothing to return 02586 // 02587 realIrp->IoStatus.Information = 0; 02588 break; 02589 02590 case IOCTL_CDROM_PLAY_AUDIO_MSF: 02591 02592 PLAY_ACTIVE(fdoExtension) = TRUE; 02593 02594 break; 02595 02596 case IOCTL_CDROM_READ_Q_CHANNEL: { 02597 02598 PSUB_Q_CHANNEL_DATA userChannelData = realIrp->AssociatedIrp.SystemBuffer; 02599 PCDROM_SUB_Q_DATA_FORMAT inputBuffer = realIrp->AssociatedIrp.SystemBuffer; 02600 PSUB_Q_CHANNEL_DATA subQPtr = srb->DataBuffer; 02601 02602 #if DBG 02603 switch( inputBuffer->Format ) { 02604 02605 case IOCTL_CDROM_CURRENT_POSITION: 02606 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->CurrentPosition.Header.AudioStatus )); 02607 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: ADR = 0x%x\n", subQPtr->CurrentPosition.ADR )); 02608 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Control = 0x%x\n", subQPtr->CurrentPosition.Control )); 02609 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Track = %u\n", subQPtr->CurrentPosition.TrackNumber )); 02610 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Index = %u\n", subQPtr->CurrentPosition.IndexNumber )); 02611 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Absolute Address = %x\n", *((PULONG)subQPtr->CurrentPosition.AbsoluteAddress) )); 02612 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Relative Address = %x\n", *((PULONG)subQPtr->CurrentPosition.TrackRelativeAddress) )); 02613 break; 02614 02615 case IOCTL_CDROM_MEDIA_CATALOG: 02616 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->MediaCatalog.Header.AudioStatus )); 02617 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Mcval is %u\n", subQPtr->MediaCatalog.Mcval )); 02618 break; 02619 02620 case IOCTL_CDROM_TRACK_ISRC: 02621 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->TrackIsrc.Header.AudioStatus )); 02622 TraceLog((CdromDebugTrace,"CdRomDeviceControlCompletion: Tcval is %u\n", subQPtr->TrackIsrc.Tcval )); 02623 break; 02624 02625 } 02626 #endif 02627 02628 // 02629 // Update the play active status. 02630 // 02631 02632 if (subQPtr->CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) { 02633 02634 PLAY_ACTIVE(fdoExtension) = TRUE; 02635 02636 } else { 02637 02638 PLAY_ACTIVE(fdoExtension) = FALSE; 02639 02640 } 02641 02642 // 02643 // Check if output buffer is large enough to contain 02644 // the data. 02645 // 02646 02647 if (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength < 02648 srb->DataTransferLength) { 02649 02650 srb->DataTransferLength = 02651 realIrpStack->Parameters.DeviceIoControl.OutputBufferLength; 02652 } 02653 02654 // 02655 // Copy our buffer into users. 02656 // 02657 02658 RtlMoveMemory(userChannelData, 02659 subQPtr, 02660 srb->DataTransferLength); 02661 02662 realIrp->IoStatus.Information = srb->DataTransferLength; 02663 break; 02664 } 02665 02666 case IOCTL_CDROM_PAUSE_AUDIO: 02667 02668 PLAY_ACTIVE(fdoExtension) = FALSE; 02669 realIrp->IoStatus.Information = 0; 02670 break; 02671 02672 case IOCTL_CDROM_RESUME_AUDIO: 02673 02674 realIrp->IoStatus.Information = 0; 02675 break; 02676 02677 case IOCTL_CDROM_SEEK_AUDIO_MSF: 02678 02679 realIrp->IoStatus.Information = 0; 02680 break; 02681 02682 case IOCTL_CDROM_STOP_AUDIO: 02683 02684 PLAY_ACTIVE(fdoExtension) = FALSE; 02685 realIrp->IoStatus.Information = 0; 02686 break; 02687 02688 case IOCTL_CDROM_GET_CONTROL: { 02689 02690 PCDROM_AUDIO_CONTROL audioControl = srb->DataBuffer; 02691 PAUDIO_OUTPUT audioOutput; 02692 ULONG bytesTransferred; 02693 02694 audioOutput = ClassFindModePage((PCHAR)audioControl, 02695 srb->DataTransferLength, 02696 CDROM_AUDIO_CONTROL_PAGE, 02697 use6Byte); 02698 // 02699 // Verify the page is as big as expected. 02700 // 02701 02702 bytesTransferred = (ULONG)((PCHAR) audioOutput - (PCHAR) audioControl) + 02703 sizeof(AUDIO_OUTPUT); 02704 02705 if (audioOutput != NULL && 02706 srb->DataTransferLength >= bytesTransferred) { 02707 02708 audioControl->LbaFormat = audioOutput->LbaFormat; 02709 02710 audioControl->LogicalBlocksPerSecond = 02711 (audioOutput->LogicalBlocksPerSecond[0] << (UCHAR)8) | 02712 audioOutput->LogicalBlocksPerSecond[1]; 02713 02714 realIrp->IoStatus.Information = sizeof(CDROM_AUDIO_CONTROL); 02715 02716 } else { 02717 realIrp->IoStatus.Information = 0; 02718 status = STATUS_INVALID_DEVICE_REQUEST; 02719 } 02720 break; 02721 } 02722 02723 case IOCTL_CDROM_GET_VOLUME: { 02724 02725 PAUDIO_OUTPUT audioOutput; 02726 PVOLUME_CONTROL volumeControl = srb->DataBuffer; 02727 ULONG i; 02728 ULONG bytesTransferred; 02729 02730 audioOutput = ClassFindModePage((PCHAR)volumeControl, 02731 srb->DataTransferLength, 02732 CDROM_AUDIO_CONTROL_PAGE, 02733 use6Byte); 02734 02735 // 02736 // Verify the page is as big as expected. 02737 // 02738 02739 bytesTransferred = (ULONG)((PCHAR) audioOutput - (PCHAR) volumeControl) + 02740 sizeof(AUDIO_OUTPUT); 02741 02742 if (audioOutput != NULL && 02743 srb->DataTransferLength >= bytesTransferred) { 02744 02745 for (i=0; i<4; i++) { 02746 volumeControl->PortVolume[i] = 02747 audioOutput->PortOutput[i].Volume; 02748 } 02749 02750 // 02751 // Set bytes transferred in IRP. 02752 // 02753 02754 realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL); 02755 02756 } else { 02757 realIrp->IoStatus.Information = 0; 02758 status = STATUS_INVALID_DEVICE_REQUEST; 02759 } 02760 02761 break; 02762 } 02763 02764 case IOCTL_CDROM_SET_VOLUME: 02765 02766 realIrp->IoStatus.Information = 0; 02767 break; 02768 02769 default: 02770 02771 ASSERT(FALSE); 02772 realIrp->IoStatus.Information = 0; 02773 status = STATUS_INVALID_DEVICE_REQUEST; 02774 02775 } // end switch() 02776 } 02777 02778 // 02779 // Deallocate srb and sense buffer. 02780 // 02781 02782 if (srb) { 02783 if (srb->DataBuffer) { 02784 ExFreePool(srb->DataBuffer); 02785 } 02786 if (srb->SenseInfoBuffer) { 02787 ExFreePool(srb->SenseInfoBuffer); 02788 } 02789 ExFreePool(srb); 02790 } 02791 02792 if (realIrp->PendingReturned) { 02793 IoMarkIrpPending(realIrp); 02794 } 02795 02796 if (Irp->MdlAddress) { 02797 IoFreeMdl(Irp->MdlAddress); 02798 } 02799 02800 IoFreeIrp(Irp); 02801 02802 // 02803 // Set status in completing IRP. 02804 // 02805 02806 realIrp->IoStatus.Status = status; 02807 02808 // 02809 // Set the hard error if necessary. 02810 // 02811 02812 if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { 02813 02814 // 02815 // Store DeviceObject for filesystem, and clear 02816 // in IoStatus.Information field. 02817 // 02818 02819 TraceLog((CdromDebugWarning, 02820 "CdRomDeviceCompletion - Setting Hard Error on realIrp %p\n", 02821 realIrp)); 02822 if (realIrp->Tail.Overlay.Thread) { 02823 IoSetHardErrorOrVerifyDevice(realIrp, DeviceObject); 02824 } 02825 02826 realIrp->IoStatus.Information = 0; 02827 } 02828 02829 // 02830 // note: must complete the realIrp, as the completed irp (above) 02831 // was self-allocated. 02832 // 02833 02834 CdRomCompleteIrpAndStartNextPacketSafely(DeviceObject, realIrp); 02835 return STATUS_MORE_PROCESSING_REQUIRED; 02836 } 02837 02838 02839 NTSTATUS 02840 CdRomSetVolumeIntermediateCompletion( 02841 IN PDEVICE_OBJECT DeviceObject, 02842 IN PIRP Irp, 02843 IN PVOID Context 02844 ) 02845 { 02846 PFUNCTIONAL_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 02847 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; 02848 02849 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 02850 PCDROM_DATA cdData = (PCDROM_DATA)(commonExtension->DriverData); 02851 BOOLEAN use6Byte = TEST_FLAG(cdData->XAFlags, XA_USE_6_BYTE); 02852 PIO_STACK_LOCATION realIrpStack; 02853 PIO_STACK_LOCATION realIrpNextStack; 02854 PSCSI_REQUEST_BLOCK srb = Context; 02855 PIRP realIrp = NULL; 02856 NTSTATUS status; 02857 BOOLEAN retry; 02858 ULONG retryCount; 02859 02860 // 02861 // Extract the 'real' irp from the irpstack. 02862 // 02863 02864 realIrp = (PIRP) irpStack->Parameters.Others.Argument2; 02865 realIrpStack = IoGetCurrentIrpStackLocation(realIrp); 02866 realIrpNextStack = IoGetNextIrpStackLocation(realIrp); 02867 02868 // 02869 // Check SRB status for success of completing request. 02870 // 02871 02872 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 02873 02874 ULONG retryInterval; 02875 02876 TraceLog((CdromDebugTrace, 02877 "CdRomSetVolumeIntermediateCompletion: Irp %p, Srb %p, Real Irp %p\n", 02878 Irp, 02879 srb, 02880 realIrp)); 02881 02882 // 02883 // Release the queue if it is frozen. 02884 // 02885 02886 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 02887 ClassReleaseQueue(DeviceObject); 02888 } 02889 02890 02891 retry = ClassInterpretSenseInfo(DeviceObject, 02892 srb, 02893 irpStack->MajorFunction, 02894 irpStack->Parameters.DeviceIoControl.IoControlCode, 02895 MAXIMUM_RETRIES - ((ULONG)(ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1), 02896 &status, 02897 &retryInterval); 02898 02899 if (status == STATUS_DATA_OVERRUN) { 02900 status = STATUS_SUCCESS; 02901 retry = FALSE; 02902 } 02903 02904 // 02905 // If the status is verified required and the this request 02906 // should bypass verify required then retry the request. 02907 // 02908 02909 if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 02910 status == STATUS_VERIFY_REQUIRED) { 02911 02912 status = STATUS_IO_DEVICE_ERROR; 02913 retry = TRUE; 02914 } 02915 02916 // 02917 // get current retry count 02918 // 02919 retryCount = PtrToUlong(realIrpNextStack->Parameters.Others.Argument1); 02920 02921 if (retry && retryCount) { 02922 02923 // 02924 // update retry count 02925 // 02926 realIrpNextStack->Parameters.Others.Argument1 = UlongToPtr(retryCount-1); 02927 02928 02929 if (((ULONG)(ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) { 02930 02931 // 02932 // Retry request. 02933 // 02934 02935 TraceLog((CdromDebugWarning, 02936 "Retry request %p - Calling StartIo\n", Irp)); 02937 02938 02939 ExFreePool(srb->SenseInfoBuffer); 02940 ExFreePool(srb->DataBuffer); 02941 ExFreePool(srb); 02942 if (Irp->MdlAddress) { 02943 IoFreeMdl(Irp->MdlAddress); 02944 } 02945 02946 IoFreeIrp(Irp); 02947 02948 CdRomRetryRequest(deviceExtension, 02949 realIrp, 02950 retryInterval, 02951 FALSE); 02952 02953 return STATUS_MORE_PROCESSING_REQUIRED; 02954 02955 } 02956 02957 // 02958 // Exhausted retries. Fall through and complete the request with the appropriate status. 02959 // 02960 02961 } 02962 } else { 02963 02964 // 02965 // Set status for successful request. 02966 // 02967 02968 status = STATUS_SUCCESS; 02969 02970 } 02971 02972 if (NT_SUCCESS(status)) { 02973 02974 PAUDIO_OUTPUT audioInput = NULL; 02975 PAUDIO_OUTPUT audioOutput; 02976 PVOLUME_CONTROL volumeControl = realIrp->AssociatedIrp.SystemBuffer; 02977 ULONG i,bytesTransferred,headerLength; 02978 PVOID dataBuffer; 02979 PCDB cdb; 02980 02981 audioInput = ClassFindModePage((PCHAR)srb->DataBuffer, 02982 srb->DataTransferLength, 02983 CDROM_AUDIO_CONTROL_PAGE, 02984 use6Byte); 02985 02986 // 02987 // Check to make sure the mode sense data is valid before we go on 02988 // 02989 02990 if(audioInput == NULL) { 02991 02992 TraceLog((CdromDebugWarning, 02993 "Mode Sense Page %d not found\n", 02994 CDROM_AUDIO_CONTROL_PAGE)); 02995 02996 realIrp->IoStatus.Information = 0; 02997 realIrp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 02998 goto SafeExit; 02999 } 03000 03001 if (use6Byte) { 03002 headerLength = sizeof(MODE_PARAMETER_HEADER); 03003 } else { 03004 headerLength = sizeof(MODE_PARAMETER_HEADER10); 03005 } 03006 03007 bytesTransferred = sizeof(AUDIO_OUTPUT) + headerLength; 03008 03009 // 03010 // Allocate a new buffer for the mode select. 03011 // 03012 03013 dataBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 03014 bytesTransferred, 03015 CDROM_TAG_VOLUME_INT); 03016 03017 if (!dataBuffer) { 03018 realIrp->IoStatus.Information = 0; 03019 realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 03020 goto SafeExit; 03021 } 03022 03023 RtlZeroMemory(dataBuffer, bytesTransferred); 03024 03025 // 03026 // Rebuild the data buffer to include the user requested values. 03027 // 03028 03029 audioOutput = (PAUDIO_OUTPUT) ((PCHAR) dataBuffer + headerLength); 03030 03031 for (i=0; i<4; i++) { 03032 audioOutput->PortOutput[i].Volume = 03033 volumeControl->PortVolume[i]; 03034 audioOutput->PortOutput[i].ChannelSelection = 03035 audioInput->PortOutput[i].ChannelSelection; 03036 } 03037 03038 audioOutput->CodePage = CDROM_AUDIO_CONTROL_PAGE; 03039 audioOutput->ParameterLength = sizeof(AUDIO_OUTPUT) - 2; 03040 audioOutput->Immediate = MODE_SELECT_IMMEDIATE; 03041 03042 // 03043 // Free the old data buffer, mdl. 03044 // 03045 03046 IoFreeMdl(Irp->MdlAddress); 03047 Irp->MdlAddress = NULL; 03048 ExFreePool(srb->DataBuffer); 03049 03050 // 03051 // set the data buffer to new allocation, so it can be 03052 // freed in the exit path 03053 // 03054 03055 srb->DataBuffer = dataBuffer; 03056 03057 // 03058 // rebuild the srb. 03059 // 03060 03061 cdb = (PCDB)srb->Cdb; 03062 RtlZeroMemory(cdb, CDB12GENERIC_LENGTH); 03063 03064 srb->SrbStatus = srb->ScsiStatus = 0; 03065 srb->SrbFlags = deviceExtension->SrbFlags; 03066 SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); 03067 SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_OUT); 03068 srb->DataTransferLength = bytesTransferred; 03069 03070 if (use6Byte) { 03071 03072 cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; 03073 cdb->MODE_SELECT.ParameterListLength = (UCHAR) bytesTransferred; 03074 cdb->MODE_SELECT.PFBit = 1; 03075 srb->CdbLength = 6; 03076 } else { 03077 03078 cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10; 03079 cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR) (bytesTransferred >> 8); 03080 cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR) (bytesTransferred & 0xFF); 03081 cdb->MODE_SELECT10.PFBit = 1; 03082 srb->CdbLength = 10; 03083 } 03084 03085 // 03086 // Prepare the MDL 03087 // 03088 03089 Irp->MdlAddress = IoAllocateMdl(dataBuffer, 03090 bytesTransferred, 03091 FALSE, 03092 FALSE, 03093 (PIRP) NULL); 03094 03095 if (!Irp->MdlAddress) { 03096 realIrp->IoStatus.Information = 0; 03097 realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 03098 goto SafeExit; 03099 } 03100 03101 MmBuildMdlForNonPagedPool(Irp->MdlAddress); 03102 03103 irpStack = IoGetNextIrpStackLocation(Irp); 03104 irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 03105 irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; 03106 irpStack->Parameters.Scsi.Srb = srb; 03107 03108 // 03109 // reset the irp completion. 03110 // 03111 03112 IoSetCompletionRoutine(Irp, 03113 CdRomDeviceControlCompletion, 03114 srb, 03115 TRUE, 03116 TRUE, 03117 TRUE); 03118 // 03119 // Call the port driver. 03120 // 03121 03122 IoCallDriver(commonExtension->LowerDeviceObject, Irp); 03123 03124 return STATUS_MORE_PROCESSING_REQUIRED; 03125 } 03126 03127 SafeExit: 03128 03129 // 03130 // Deallocate srb and sense buffer. 03131 // 03132 03133 if (srb) { 03134 if (srb->DataBuffer) { 03135 ExFreePool(srb->DataBuffer); 03136 } 03137 if (srb->SenseInfoBuffer) { 03138 ExFreePool(srb->SenseInfoBuffer); 03139 } 03140 ExFreePool(srb); 03141 } 03142 03143 if (Irp->PendingReturned) { 03144 IoMarkIrpPending(Irp); 03145 } 03146 03147 if (realIrp->PendingReturned) { 03148 IoMarkIrpPending(realIrp); 03149 } 03150 03151 if (Irp->MdlAddress) { 03152 IoFreeMdl(Irp->MdlAddress); 03153 } 03154 03155 IoFreeIrp(Irp); 03156 03157 // 03158 // Set status in completing IRP. 03159 // 03160 03161 realIrp->IoStatus.Status = status; 03162 03163 // 03164 // Set the hard error if necessary. 03165 // 03166 03167 if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { 03168 03169 // 03170 // Store DeviceObject for filesystem, and clear 03171 // in IoStatus.Information field. 03172 // 03173 03174 if (realIrp->Tail.Overlay.Thread) { 03175 IoSetHardErrorOrVerifyDevice(realIrp, DeviceObject); 03176 } 03177 realIrp->IoStatus.Information = 0; 03178 } 03179 03180 CdRomCompleteIrpAndStartNextPacketSafely(DeviceObject, realIrp); 03181 return STATUS_MORE_PROCESSING_REQUIRED; 03182 } 03183 03184 NTSTATUS 03185 CdRomDvdEndAllSessionsCompletion( 03186 IN PDEVICE_OBJECT DeviceObject, 03187 IN PIRP Irp, 03188 IN PVOID Context 03189 ) 03190 03191 /*++ 03192 03193 Routine Description: 03194 03195 This routine will setup the next stack location to issue an end session 03196 to the device. It will increment the session id in the system buffer 03197 and issue an END_SESSION for that AGID if the AGID is valid. 03198 03199 When the new AGID is > 3 this routine will complete the request. 03200 03201 Arguments: 03202 03203 DeviceObject - the device object for this drive 03204 03205 Irp - the request 03206 03207 Context - done 03208 03209 Return Value: 03210 03211 STATUS_MORE_PROCESSING_REQUIRED if there is another AGID to clear 03212 status otherwise. 03213 03214 --*/ 03215 03216 { 03217 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension; 03218 03219 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); 03220 03221 PDVD_SESSION_ID sessionId = Irp->AssociatedIrp.SystemBuffer; 03222 03223 NTSTATUS status; 03224 03225 if(++(*sessionId) > MAX_COPY_PROTECT_AGID) { 03226 03227 // 03228 // We're done here - just return success and let the io system 03229 // continue to complete it. 03230 // 03231 03232 return STATUS_SUCCESS; 03233 03234 } 03235 03236 IoCopyCurrentIrpStackLocationToNext(Irp); 03237 03238 IoSetCompletionRoutine(Irp, 03239 CdRomDvdEndAllSessionsCompletion, 03240 NULL, 03241 TRUE, 03242 FALSE, 03243 FALSE); 03244 03245 IoMarkIrpPending(Irp); 03246 03247 IoCallDriver(fdoExtension->CommonExtension.DeviceObject, Irp); 03248 03249 // 03250 // At this point we have to assume the irp may have already been 03251 // completed. Ignore the returned status and return. 03252 // 03253 03254 return STATUS_MORE_PROCESSING_REQUIRED; 03255 } 03256 03257 NTSTATUS 03258 CdRomDvdReadDiskKeyCompletion( 03259 IN PDEVICE_OBJECT DeviceObject, 03260 IN PIRP Irp, 03261 IN PVOID Context 03262 ) 03263 03264 /*++ 03265 03266 Routine Description: 03267 03268 This routine handles the completion of a request to obtain the disk 03269 key from the dvd media. It will transform the raw 2K of key data into 03270 a DVD_COPY_PROTECT_KEY structure and copy back the saved key parameters 03271 from the context pointer before returning. 03272 03273 Arguments: 03274 03275 DeviceObject - 03276 03277 Irp - 03278 03279 Context - a DVD_COPY_PROTECT_KEY pointer which contains the key 03280 parameters handed down by the caller. 03281 03282 Return Value: 03283 03284 STATUS_SUCCESS; 03285 03286 --*/ 03287 03288 { 03289 PDVD_COPY_PROTECT_KEY savedKey = Context; 03290 03291 PREAD_DVD_STRUCTURES_HEADER rawKey = Irp->AssociatedIrp.SystemBuffer; 03292 PDVD_COPY_PROTECT_KEY outputKey = Irp->AssociatedIrp.SystemBuffer; 03293 03294 if (NT_SUCCESS(Irp->IoStatus.Status)) { 03295 03296 // 03297 // Shift the data down to its new position. 03298 // 03299 03300 RtlMoveMemory(outputKey->KeyData, 03301 rawKey->Data, 03302 sizeof(DVD_DISK_KEY_DESCRIPTOR)); 03303 03304 RtlCopyMemory(outputKey, 03305 savedKey, 03306 sizeof(DVD_COPY_PROTECT_KEY)); 03307 03308 outputKey->KeyLength = DVD_DISK_KEY_LENGTH; 03309 03310 Irp->IoStatus.Information = DVD_DISK_KEY_LENGTH; 03311 03312 } else { 03313 03314 TraceLog((CdromDebugWarning, 03315 "DiskKey Failed with status %x, %p (%x) bytes\n", 03316 Irp->IoStatus.Status, 03317 (PVOID)Irp->IoStatus.Information, 03318 ((rawKey->Length[0] << 16) | rawKey->Length[1]) 03319 )); 03320 03321 } 03322 03323 // 03324 // release the context block 03325 // 03326 03327 ExFreePool(Context); 03328 03329 return STATUS_SUCCESS; 03330 } 03331 03332 NTSTATUS 03333 CdRomXACompletion( 03334 IN PDEVICE_OBJECT DeviceObject, 03335 IN PIRP Irp, 03336 IN PVOID Context 03337 ) 03338 03339 /*++ 03340 03341 Routine Description: 03342 03343 This routine executes when the port driver has completed a request. 03344 It looks at the SRB status in the completing SRB and if not success 03345 it checks for valid request sense buffer information. If valid, the 03346 info is used to update status with more precise message of type of 03347 error. This routine deallocates the SRB. 03348 03349 Arguments: 03350 03351 DeviceObject - Supplies the device object which represents the logical 03352 unit. 03353 03354 Irp - Supplies the Irp which has completed. 03355 03356 Context - Supplies a pointer to the SRB. 03357 03358 Return Value: 03359 03360 NT status 03361 03362 --*/ 03363 03364 { 03365 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); 03366 PSCSI_REQUEST_BLOCK srb = Context; 03367 PFUNCTIONAL_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 03368 NTSTATUS status; 03369 BOOLEAN retry; 03370 03371 // 03372 // Check SRB status for success of completing request. 03373 // 03374 03375 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { 03376 03377 ULONG retryInterval; 03378 03379 TraceLog((CdromDebugTrace, "CdromXAComplete: IRP %p SRB %p Status %x\n", 03380 Irp, srb, srb->SrbStatus)); 03381 03382 // 03383 // Release the queue if it is frozen. 03384 // 03385 03386 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { 03387 ClassReleaseQueue(DeviceObject); 03388 } 03389 03390 retry = ClassInterpretSenseInfo( 03391 DeviceObject, 03392 srb, 03393 irpStack->MajorFunction, 03394 irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, 03395 MAXIMUM_RETRIES - irpStack->MinorFunction, // HACKHACK - REF #0001 03396 &status, 03397 &retryInterval); 03398 03399 // 03400 // If the status is verified required and the this request 03401 // should bypass verify required then retry the request. 03402 // 03403 03404 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && 03405 status == STATUS_VERIFY_REQUIRED) { 03406 03407 status = STATUS_IO_DEVICE_ERROR; 03408 retry = TRUE; 03409 } 03410 03411 if (retry) { 03412 03413 if (irpStack->MinorFunction != 0) { // HACKHACK - REF #0001 03414 03415 irpStack->MinorFunction--; // HACKHACK - REF #0001 03416 03417 // 03418 // Retry request. 03419 // 03420 03421 TraceLog((CdromDebugWarning, 03422 "CdRomXACompletion: Retry request %p (%x) - " 03423 "Calling StartIo\n", Irp, irpStack->MinorFunction)); 03424 03425 03426 ExFreePool(srb->SenseInfoBuffer); 03427 ExFreePool(srb); 03428 03429 // 03430 // Call StartIo directly since IoStartNextPacket hasn't been called, 03431 // the serialisation is still intact. 03432 // 03433 03434 CdRomRetryRequest(deviceExtension, 03435 Irp, 03436 retryInterval, 03437 FALSE); 03438 03439 return STATUS_MORE_PROCESSING_REQUIRED; 03440 03441 } 03442 03443 // 03444 // Exhausted retries, fall through and complete the request 03445 // with the appropriate status 03446 // 03447 03448 TraceLog((CdromDebugWarning, 03449 "CdRomXACompletion: Retries exhausted for irp %p\n", 03450 Irp)); 03451 03452 } 03453 03454 } else { 03455 03456 // 03457 // Set status for successful request. 03458 // 03459 03460 status = STATUS_SUCCESS; 03461 03462 } // end if (SRB_STATUS(srb->SrbStatus) ... 03463 03464 // 03465 // Return SRB to nonpaged pool. 03466 // 03467 03468 ExFreePool(srb->SenseInfoBuffer); 03469 ExFreePool(srb); 03470 03471 // 03472 // Set status in completing IRP. 03473 // 03474 03475 Irp->IoStatus.Status = status; 03476 03477 // 03478 // Set the hard error if necessary. 03479 // 03480 03481 if (!NT_SUCCESS(status) && 03482 IoIsErrorUserInduced(status) && 03483 Irp->Tail.Overlay.Thread != NULL ) { 03484 03485 // 03486 // Store DeviceObject for filesystem, and clear 03487 // in IoStatus.Information field. 03488 // 03489 03490 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); 03491 Irp->IoStatus.Information = 0; 03492 } 03493 03494 // 03495 // If pending has be returned for this irp then mark the current stack as 03496 // pending. 03497 // 03498 03499 if (Irp->PendingReturned) { 03500 IoMarkIrpPending(Irp); 03501 } 03502 03503 { 03504 KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); 03505 IoStartNextPacket(DeviceObject, FALSE); 03506 KeLowerIrql(oldIrql); 03507 } 03508 ClassReleaseRemoveLock(DeviceObject, Irp); 03509 03510 return status; 03511 } 03512 03513 03514 VOID 03515 CdRomDeviceControlDvdReadStructure( 03516 IN PDEVICE_OBJECT Fdo, 03517 IN PIRP OriginalIrp, 03518 IN PIRP NewIrp, 03519 IN PSCSI_REQUEST_BLOCK Srb 03520 ) 03521 { 03522 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(OriginalIrp); 03523 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 03524 PCDB cdb = (PCDB)Srb->Cdb; 03525 PVOID dataBuffer; 03526 03527 PDVD_READ_STRUCTURE request; 03528 USHORT dataLength; 03529 ULONG blockNumber; 03530 PFOUR_BYTE fourByte; 03531 03532 dataLength = 03533 (USHORT)currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength; 03534 03535 request = OriginalIrp->AssociatedIrp.SystemBuffer; 03536 blockNumber = 03537 (ULONG)(request->BlockByteOffset.QuadPart >> fdoExtension->SectorShift); 03538 fourByte = (PFOUR_BYTE) &blockNumber; 03539 03540 Srb->CdbLength = 12; 03541 Srb->TimeOutValue = fdoExtension->TimeOutValue; 03542 Srb->SrbFlags = fdoExtension->SrbFlags; 03543 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN); 03544 03545 cdb->READ_DVD_STRUCTURE.OperationCode = SCSIOP_READ_DVD_STRUCTURE; 03546 cdb->READ_DVD_STRUCTURE.RMDBlockNumber[0] = fourByte->Byte3; 03547 cdb->READ_DVD_STRUCTURE.RMDBlockNumber[1] = fourByte->Byte2; 03548 cdb->READ_DVD_STRUCTURE.RMDBlockNumber[2] = fourByte->Byte1; 03549 cdb->READ_DVD_STRUCTURE.RMDBlockNumber[3] = fourByte->Byte0; 03550 cdb->READ_DVD_STRUCTURE.LayerNumber = request->LayerNumber; 03551 cdb->READ_DVD_STRUCTURE.Format = (UCHAR)request->Format; 03552 03553 #if DBG 03554 { 03555 if ((UCHAR)request->Format > DvdMaxDescriptor) { 03556 TraceLog((CdromDebugWarning, 03557 "READ_DVD_STRUCTURE format %x = %s (%x bytes)\n", 03558 (UCHAR)request->Format, 03559 READ_DVD_STRUCTURE_FORMAT_STRINGS[DvdMaxDescriptor], 03560 dataLength 03561 )); 03562 } else { 03563 TraceLog((CdromDebugWarning, 03564 "READ_DVD_STRUCTURE format %x = %s (%x bytes)\n", 03565 (UCHAR)request->Format, 03566 READ_DVD_STRUCTURE_FORMAT_STRINGS[(UCHAR)request->Format], 03567 dataLength 03568 )); 03569 } 03570 } 03571 #endif // DBG 03572 03573 if (request->Format == DvdDiskKeyDescriptor) { 03574 03575 cdb->READ_DVD_STRUCTURE.AGID = (UCHAR) request->SessionId; 03576 03577 } 03578 03579 cdb->READ_DVD_STRUCTURE.AllocationLength[0] = (UCHAR)(dataLength >> 8); 03580 cdb->READ_DVD_STRUCTURE.AllocationLength[1] = (UCHAR)(dataLength & 0xff); 03581 Srb->DataTransferLength = dataLength; 03582 03583 03584 03585 dataBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 03586 dataLength, 03587 DVD_TAG_READ_STRUCTURE); 03588 03589 if (!dataBuffer) { 03590 ExFreePool(Srb->SenseInfoBuffer); 03591 ExFreePool(Srb); 03592 IoFreeIrp(NewIrp); 03593 OriginalIrp->IoStatus.Information = 0; 03594 OriginalIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 03595 03596 BAIL_OUT(OriginalIrp); 03597 CdRomCompleteIrpAndStartNextPacketSafely(Fdo, OriginalIrp); 03598 return; 03599 } 03600 RtlZeroMemory(dataBuffer, dataLength); 03601 03602 NewIrp->MdlAddress = IoAllocateMdl(dataBuffer, 03603 currentIrpStack->Parameters.Read.Length, 03604 FALSE, 03605 FALSE, 03606 (PIRP) NULL); 03607 03608 if (NewIrp->MdlAddress == NULL) { 03609 ExFreePool(dataBuffer); 03610 ExFreePool(Srb->SenseInfoBuffer); 03611 ExFreePool(Srb); 03612 IoFreeIrp(NewIrp); 03613 OriginalIrp->IoStatus.Information = 0; 03614 OriginalIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 03615 03616 BAIL_OUT(OriginalIrp); 03617 CdRomCompleteIrpAndStartNextPacketSafely(Fdo, OriginalIrp); 03618 return; 03619 } 03620 03621 // 03622 // Prepare the MDL 03623 // 03624 03625 MmBuildMdlForNonPagedPool(NewIrp->MdlAddress); 03626 03627 Srb->DataBuffer = dataBuffer; 03628 03629 IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, NewIrp); 03630 03631 return; 03632 } 03633 03634 03635 VOID 03636 CdRomDeviceControlDvdEndSession( 03637 IN PDEVICE_OBJECT Fdo, 03638 IN PIRP OriginalIrp, 03639 IN PIRP NewIrp, 03640 IN PSCSI_REQUEST_BLOCK Srb 03641 ) 03642 { 03643 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(OriginalIrp); 03644 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 03645 PCDB cdb = (PCDB)Srb->Cdb; 03646 03647 PDVD_SESSION_ID sessionId = OriginalIrp->AssociatedIrp.SystemBuffer; 03648 03649 Srb->CdbLength = 12; 03650 Srb->TimeOutValue = fdoExtension->TimeOutValue; 03651 Srb->SrbFlags = fdoExtension->SrbFlags; 03652 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_NO_DATA_TRANSFER); 03653 03654 cdb->SEND_KEY.OperationCode = SCSIOP_SEND_KEY; 03655 cdb->SEND_KEY.AGID = (UCHAR) (*sessionId); 03656 cdb->SEND_KEY.KeyFormat = DVD_INVALIDATE_AGID; 03657 03658 IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, NewIrp); 03659 return; 03660 03661 } 03662 03663 03664 VOID 03665 CdRomDeviceControlDvdStartSessionReadKey( 03666 IN PDEVICE_OBJECT Fdo, 03667 IN PIRP OriginalIrp, 03668 IN PIRP NewIrp, 03669 IN PSCSI_REQUEST_BLOCK Srb 03670 ) 03671 { 03672 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(OriginalIrp); 03673 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 03674 PCDB cdb = (PCDB)Srb->Cdb; 03675 NTSTATUS status; 03676 03677 PDVD_COPY_PROTECT_KEY keyParameters; 03678 PCDVD_KEY_HEADER keyBuffer = NULL; 03679 03680 ULONG keyLength; 03681 03682 ULONG allocationLength; 03683 PFOUR_BYTE fourByte; 03684 03685 // 03686 // Both of these use REPORT_KEY commands. 03687 // Determine the size of the input buffer 03688 // 03689 03690 if(currentIrpStack->Parameters.DeviceIoControl.IoControlCode == 03691 IOCTL_DVD_READ_KEY) { 03692 03693 keyParameters = OriginalIrp->AssociatedIrp.SystemBuffer; 03694 03695 keyLength = sizeof(CDVD_KEY_HEADER) + 03696 (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength - 03697 sizeof(DVD_COPY_PROTECT_KEY)); 03698 } else { 03699 03700 keyParameters = NULL; 03701 keyLength = sizeof(CDVD_KEY_HEADER) + 03702 sizeof(CDVD_REPORT_AGID_DATA); 03703 } 03704 03705 TRY { 03706 03707 keyBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 03708 keyLength, 03709 DVD_TAG_READ_KEY); 03710 03711 if(keyBuffer == NULL) { 03712 03713 TraceLog((CdromDebugWarning, 03714 "IOCTL_DVD_READ_KEY - couldn't allocate " 03715 "%d byte buffer for key\n", 03716 keyLength)); 03717 status = STATUS_INSUFFICIENT_RESOURCES; 03718 LEAVE; 03719 } 03720 03721 03722 NewIrp->MdlAddress = IoAllocateMdl(keyBuffer, 03723 keyLength, 03724 FALSE, 03725 FALSE, 03726 (PIRP) NULL); 03727 03728 if(NewIrp->MdlAddress == NULL) { 03729 03730 TraceLog((CdromDebugWarning, 03731 "IOCTL_DVD_READ_KEY - couldn't create mdl\n")); 03732 status = STATUS_INSUFFICIENT_RESOURCES; 03733 LEAVE; 03734 } 03735 03736 MmBuildMdlForNonPagedPool(NewIrp->MdlAddress); 03737 03738 Srb->DataBuffer = keyBuffer; 03739 Srb->CdbLength = 12; 03740 03741 cdb->REPORT_KEY.OperationCode = SCSIOP_REPORT_KEY; 03742 03743 allocationLength = keyLength; 03744 fourByte = (PFOUR_BYTE) &allocationLength; 03745 cdb->REPORT_KEY.AllocationLength[0] = fourByte->Byte1; 03746 cdb->REPORT_KEY.AllocationLength[1] = fourByte->Byte0; 03747 03748 Srb->DataTransferLength = keyLength; 03749 03750 // 03751 // set the specific parameters.... 03752 // 03753 03754 if(currentIrpStack->Parameters.DeviceIoControl.IoControlCode == 03755 IOCTL_DVD_READ_KEY) { 03756 03757 if(keyParameters->KeyType == DvdTitleKey) { 03758 03759 ULONG logicalBlockAddress; 03760 03761 logicalBlockAddress = (ULONG) 03762 (keyParameters->Parameters.TitleOffset.QuadPart >> 03763 fdoExtension->SectorShift); 03764 03765 fourByte = (PFOUR_BYTE) &(logicalBlockAddress); 03766 03767 cdb->REPORT_KEY.LogicalBlockAddress[0] = fourByte->Byte3; 03768 cdb->REPORT_KEY.LogicalBlockAddress[1] = fourByte->Byte2; 03769 cdb->REPORT_KEY.LogicalBlockAddress[2] = fourByte->Byte1; 03770 cdb->REPORT_KEY.LogicalBlockAddress[3] = fourByte->Byte0; 03771 } 03772 03773 cdb->REPORT_KEY.KeyFormat = (UCHAR)keyParameters->KeyType; 03774 cdb->REPORT_KEY.AGID = (UCHAR) keyParameters->SessionId; 03775 TraceLog((CdromDebugWarning, 03776 "CdRomDvdReadKey => sending irp %p for irp %p (%s)\n", 03777 NewIrp, OriginalIrp, "READ_KEY")); 03778 03779 } else { 03780 03781 cdb->REPORT_KEY.KeyFormat = DVD_REPORT_AGID; 03782 cdb->REPORT_KEY.AGID = 0; 03783 TraceLog((CdromDebugWarning, 03784 "CdRomDvdReadKey => sending irp %p for irp %p (%s)\n", 03785 NewIrp, OriginalIrp, "START_SESSION")); 03786 } 03787 03788 Srb->TimeOutValue = fdoExtension->TimeOutValue; 03789 Srb->SrbFlags = fdoExtension->SrbFlags; 03790 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN); 03791 03792 IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, NewIrp); 03793 03794 status = STATUS_SUCCESS; 03795 03796 } FINALLY { 03797 03798 if (!NT_SUCCESS(status)) { 03799 03800 // 03801 // An error occured during setup - free resources and 03802 // complete this request. 03803 // 03804 if (NewIrp->MdlAddress != NULL) { 03805 IoFreeMdl(NewIrp->MdlAddress); 03806 } 03807 03808 if (keyBuffer != NULL) { 03809 ExFreePool(keyBuffer); 03810 } 03811 ExFreePool(Srb->SenseInfoBuffer); 03812 ExFreePool(Srb); 03813 IoFreeIrp(NewIrp); 03814 03815 OriginalIrp->IoStatus.Information = 0; 03816 OriginalIrp->IoStatus.Status = status; 03817 03818 BAIL_OUT(OriginalIrp); 03819 CdRomCompleteIrpAndStartNextPacketSafely(Fdo, OriginalIrp); 03820 03821 } // end !NT_SUCCESS 03822 } 03823 return; 03824 } 03825 03826 03827 VOID 03828 CdRomDeviceControlDvdSendKey( 03829 IN PDEVICE_OBJECT Fdo, 03830 IN PIRP OriginalIrp, 03831 IN PIRP NewIrp, 03832 IN PSCSI_REQUEST_BLOCK Srb 03833 ) 03834 { 03835 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(OriginalIrp); 03836 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 03837 PCDB cdb = (PCDB)Srb->Cdb; 03838 03839 PDVD_COPY_PROTECT_KEY key; 03840 PCDVD_KEY_HEADER keyBuffer = NULL; 03841 03842 NTSTATUS status; 03843 ULONG keyLength; 03844 PFOUR_BYTE fourByte; 03845 03846 key = OriginalIrp->AssociatedIrp.SystemBuffer; 03847 keyLength = (key->KeyLength - sizeof(DVD_COPY_PROTECT_KEY)) + 03848 sizeof(CDVD_KEY_HEADER); 03849 03850 TRY { 03851 03852 keyBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, 03853 keyLength, 03854 DVD_TAG_SEND_KEY); 03855 03856 if(keyBuffer == NULL) { 03857 03858 TraceLog((CdromDebugWarning, 03859 "IOCTL_DVD_SEND_KEY - couldn't allocate " 03860 "%d byte buffer for key\n", 03861 keyLength)); 03862 status = STATUS_INSUFFICIENT_RESOURCES; 03863 LEAVE; 03864 } 03865 03866 RtlZeroMemory(keyBuffer, keyLength); 03867 03868 // 03869 // keylength is decremented here by two because the 03870 // datalength does not include the header, which is two 03871 // bytes. keylength is immediately incremented later 03872 // by the same amount. 03873 // 03874 03875 keyLength -= 2; 03876 fourByte = (PFOUR_BYTE) &keyLength; 03877 keyBuffer->DataLength[0] = fourByte->Byte1; 03878 keyBuffer->DataLength[1] = fourByte->Byte0; 03879 keyLength += 2; 03880 03881 // 03882 // copy the user's buffer to our own allocated buffer 03883 // 03884 03885 RtlMoveMemory(keyBuffer->Data, 03886 key->KeyData, 03887 key->KeyLength - sizeof(DVD_COPY_PROTECT_KEY)); 03888 03889 03890 NewIrp->MdlAddress = IoAllocateMdl(keyBuffer, 03891 keyLength, 03892 FALSE, 03893 FALSE, 03894 (PIRP) NULL); 03895 03896 if(NewIrp->MdlAddress == NULL) { 03897 TraceLog((CdromDebugWarning, 03898 "IOCTL_DVD_SEND_KEY - couldn't create mdl\n")); 03899 status = STATUS_INSUFFICIENT_RESOURCES; 03900 LEAVE; 03901 } 03902 03903 03904 MmBuildMdlForNonPagedPool(NewIrp->MdlAddress); 03905 03906 Srb->CdbLength = 12; 03907 Srb->DataBuffer = keyBuffer; 03908 Srb->DataTransferLength = keyLength; 03909 03910 Srb->TimeOutValue = fdoExtension->TimeOutValue; 03911 Srb->SrbFlags = fdoExtension->SrbFlags; 03912 SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_OUT); 03913 03914 cdb->REPORT_KEY.OperationCode = SCSIOP_SEND_KEY; 03915 03916 fourByte = (PFOUR_BYTE) &keyLength; 03917 03918 cdb->SEND_KEY.ParameterListLength[0] = fourByte->Byte1; 03919 cdb->SEND_KEY.ParameterListLength[1] = fourByte->Byte0; 03920 cdb->SEND_KEY.KeyFormat = (UCHAR)key->KeyType; 03921 cdb->SEND_KEY.AGID = (UCHAR) key->SessionId; 03922 03923 if (key->KeyType == DvdSetRpcKey) { 03924 TraceLog((CdromDebugWarning, 03925 "IOCTL_DVD_SEND_KEY - Setting RPC2 drive region\n")); 03926 } else { 03927 TraceLog((CdromDebugWarning, 03928 "IOCTL_DVD_SEND_KEY - key type %x\n", key->KeyType)); 03929 } 03930 03931 IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, NewIrp); 03932 03933 status = STATUS_SUCCESS; 03934 03935 } FINALLY { 03936 03937 if (!NT_SUCCESS(status)) { 03938 03939 // 03940 // An error occured during setup - free resources and 03941 // complete this request. 03942 // 03943 03944 if (NewIrp->MdlAddress != NULL) { 03945 IoFreeMdl(NewIrp->MdlAddress); 03946 } 03947 03948 if (keyBuffer != NULL) { 03949 ExFreePool(keyBuffer); 03950 } 03951 03952 ExFreePool(Srb->SenseInfoBuffer); 03953 ExFreePool(Srb); 03954 IoFreeIrp(NewIrp); 03955 03956 OriginalIrp->IoStatus.Information = 0; 03957 OriginalIrp->IoStatus.Status = status; 03958 03959 BAIL_OUT(OriginalIrp); 03960 CdRomCompleteIrpAndStartNextPacketSafely(Fdo, OriginalIrp); 03961 03962 } 03963 } 03964 03965 return; 03966 } 03967 03968 03969 VOID 03970 CdRomInterpretReadCapacity( 03971 IN PDEVICE_OBJECT Fdo, 03972 IN PREAD_CAPACITY_DATA ReadCapacityBuffer 03973 ) 03974 { 03975 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; 03976 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; 03977 ULONG lastSector; 03978 ULONG bps; 03979 ULONG lastBit; 03980 ULONG tmp; 03981 03982 ASSERT(ReadCapacityBuffer); 03983 ASSERT(commonExtension->IsFdo); 03984 03985 TraceLog((CdromDebugError, 03986 "CdRomInterpretReadCapacity: Entering\n")); 03987 03988 // 03989 // Swizzle bytes from Read Capacity and translate into 03990 // the necessary geometry information in the device extension. 03991 // 03992 03993 tmp = ReadCapacityBuffer->BytesPerBlock; 03994 ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; 03995 ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; 03996 ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; 03997 ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; 03998 03999 // 04000 // Insure that bps is a power of 2. 04001 // This corrects a problem with the HP 4020i CDR where it 04002 // returns an incorrect number for bytes per sector. 04003 // 04004 04005 if (!bps) { 04006 bps = 2048; 04007 } else { 04008 lastBit = (ULONG) -1; 04009 while (bps) { 04010 lastBit++; 04011 bps = bps >> 1; 04012 } 04013 bps = 1 << lastBit; 04014 } 04015 04016 fdoExtension->DiskGeometry.BytesPerSector = bps; 04017 04018 TraceLog((CdromDebugTrace, "CdRomInterpretReadCapacity: Calculated bps %#x\n", 04019 fdoExtension->DiskGeometry.BytesPerSector)); 04020 04021 // 04022 // Copy last sector in reverse byte order. 04023 // 04024 04025 tmp = ReadCapacityBuffer->LogicalBlockAddress; 04026 ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; 04027 ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; 04028 ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; 04029 ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; 04030 04031 // 04032 // Calculate sector to byte shift. 04033 // 04034 04035 WHICH_BIT(bps, fdoExtension->SectorShift); 04036 04037 TraceLog((CdromDebugTrace,"CdRomInterpretReadCapacity: Sector size is %d\n", 04038 fdoExtension->DiskGeometry.BytesPerSector)); 04039 04040 TraceLog((CdromDebugTrace,"CdRomInterpretReadCapacity: Number of Sectors is %d\n", 04041 lastSector + 1)); 04042 04043 // 04044 // Calculate media capacity in bytes. 04045 // 04046 04047 commonExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); 04048 04049 // 04050 // we've defaulted to 32/64 forever. don't want to change this now... 04051 // 04052 04053 fdoExtension->DiskGeometry.TracksPerCylinder = 0x40; 04054 fdoExtension->DiskGeometry.SectorsPerTrack = 0x20; 04055 04056 // 04057 // Calculate number of cylinders. 04058 // 04059 04060 fdoExtension->DiskGeometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1) / (32 * 64)); 04061 04062 commonExtension->PartitionLength.QuadPart = 04063 (commonExtension->PartitionLength.QuadPart << fdoExtension->SectorShift); 04064 04065 04066 ASSERT(TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)); 04067 04068 // 04069 // This device supports removable media. 04070 // 04071 04072 fdoExtension->DiskGeometry.MediaType = RemovableMedia; 04073 04074 return; 04075 } 04076 04077 Generated on Sun May 27 2012 04:27:10 for ReactOS by
1.7.6.1
|