NTSTATUS CdCommonDevControl ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: Arguments: Return Value: --*/ { NTSTATUS Status; TYPE_OF_OPEN TypeOfOpen; PFCB Fcb; PCCB Ccb; PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION NextIrpSp; PVOID TargetBuffer; PAGED_CODE(); // // Extract and decode the file object. // IrpSp = IoGetCurrentIrpStackLocation( Irp ); TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ); // // The only type of opens we accept are user volume opens. // if (TypeOfOpen != UserVolumeOpen) { CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); return STATUS_INVALID_PARAMETER; } // // If we have the TOC in the Vcb then copy it directly to the user's buffer. // if ((IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) && (Fcb->Vcb->CdromToc != NULL)) { // // Verify the Vcb in this case to detect if the volume has changed. // CdVerifyVcb( IrpContext, Fcb->Vcb ); if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < Fcb->Vcb->TocLength) { CdCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL ); return STATUS_BUFFER_TOO_SMALL; } // // Find the buffer for this request. // if (!FlagOn( Irp->Flags, IRP_ASSOCIATED_IRP ) && (Irp->AssociatedIrp.SystemBuffer != NULL)) { TargetBuffer = Irp->AssociatedIrp.SystemBuffer; } else if (Irp->MdlAddress != NULL) { TargetBuffer = MmGetSystemAddressForMdl( Irp->MdlAddress ); } // // If we have a buffer then perform the copy and return. // if (TargetBuffer) { RtlCopyMemory( TargetBuffer, Fcb->Vcb->CdromToc, Fcb->Vcb->TocLength ); Irp->IoStatus.Information = Fcb->Vcb->TocLength; CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); return STATUS_SUCCESS; } // // Handle the case of the disk type ourselves. // } else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) { // // Verify the Vcb in this case to detect if the volume has changed. // CdVerifyVcb( IrpContext, Fcb->Vcb ); // // Check the size of the output buffer. // if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) { CdCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL ); return STATUS_BUFFER_TOO_SMALL; } // // Copy the data from the Vcb. // ((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = Fcb->Vcb->DiskFlags; Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA ); CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS ); return STATUS_SUCCESS; } // // Get the next stack location, and copy over the stack parameter // information. // NextIrpSp = IoGetNextIrpStackLocation( Irp ); *NextIrpSp = *IrpSp; // // Set up the completion routine // IoSetCompletionRoutine( Irp, CdDevCtrlCompletionRoutine, NULL, TRUE, TRUE, TRUE ); // // Send the request. // Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp ); // // Cleanup our Irp Context. The driver has completed the Irp. // CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); return Status; }
__drv_mustHoldCriticalRegion NTSTATUS CdNotifyChangeDirectory ( __inout PIRP_CONTEXT IrpContext, __inout PIRP Irp, __in PIO_STACK_LOCATION IrpSp, __in PCCB Ccb ) /*++ Routine Description: This routine performs the notify change directory operation. It is responsible for either completing of enqueuing the input Irp. Although there will never be a notify signalled on a CDROM disk we still support this call. We have already checked that this is not an OpenById handle. Arguments: Irp - Supplies the Irp to process IrpSp - Io stack location for this request. Ccb - Handle to the directory being watched. Return Value: NTSTATUS - STATUS_PENDING, any other error will raise. --*/ { PAGED_CODE(); // // Always set the wait bit in the IrpContext so the initial wait can't fail. // SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ); // // Acquire the Vcb shared. // CdAcquireVcbShared( IrpContext, IrpContext->Vcb, FALSE ); // // Use a try-finally to facilitate cleanup. // try { // // Verify the Vcb. // CdVerifyVcb( IrpContext, IrpContext->Vcb ); // // Call the Fsrtl package to process the request. We cast the // unicode strings to ansi strings as the dir notify package // only deals with memory matching. // FsRtlNotifyFullChangeDirectory( IrpContext->Vcb->NotifySync, &IrpContext->Vcb->DirNotifyList, Ccb, (PSTRING) &IrpSp->FileObject->FileName, BooleanFlagOn( IrpSp->Flags, SL_WATCH_TREE ), FALSE, IrpSp->Parameters.NotifyDirectory.CompletionFilter, Irp, NULL, NULL ); } finally { // // Release the Vcb. // CdReleaseVcb( IrpContext, IrpContext->Vcb ); } // // Cleanup the IrpContext. // CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS ); return STATUS_PENDING; }
NTSTATUS CdCommonQueryVolInfo ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for querying volume information called by both the fsd and fsp threads. Arguments: Irp - Supplies the Irp being processed Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_INVALID_PARAMETER; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); ULONG Length; TYPE_OF_OPEN TypeOfOpen; PFCB Fcb; PCCB Ccb; PAGED_CODE(); // // Reference our input parameters to make things easier // Length = IrpSp->Parameters.QueryVolume.Length; // // Decode the file object and fail if this an unopened file object. // TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ); if (TypeOfOpen == UnopenedFileObject) { CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); return STATUS_INVALID_PARAMETER; } // // Acquire the Vcb for this volume. // CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE ); // // Use a try-finally to facilitate cleanup. // try { // // Verify the Vcb. // CdVerifyVcb( IrpContext, Fcb->Vcb ); // // Based on the information class we'll do different actions. Each // of the procedures that we're calling fills up the output buffer // if possible and returns true if it successfully filled the buffer // and false if it couldn't wait for any I/O to complete. // switch (IrpSp->Parameters.QueryVolume.FsInformationClass) { case FileFsSizeInformation: Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); break; case FileFsVolumeInformation: Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); break; case FileFsDeviceInformation: Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); break; case FileFsAttributeInformation: Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length ); break; } // // Set the information field to the number of bytes actually filled in // Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length; } finally { // // Release the Vcb. // CdReleaseVcb( IrpContext, Fcb->Vcb ); } // // Complete the request if we didn't raise. // CdCompleteRequest( IrpContext, Irp, Status ); return Status; }