+++ /dev/null
-////////////////////////////////////////////////////////////////////
-// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
-// All rights reserved
-// This file was released under the GPLv2 on June 2015.
-////////////////////////////////////////////////////////////////////
-/*++
-
-Module Name:
-
- VolInfo.cpp
-
-Abstract:
-
- This module implements the volume information routines for UDF called by
- the dispatch driver.
-
---*/
-
-#include "udffs.h"
-
-// define the file specific bug-check id
-#define UDF_BUG_CHECK_ID UDF_FILE_VOL_INFORMATION
-
-// Local support routines
-NTSTATUS
-UDFQueryFsVolumeInfo (
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_VOLUME_INFORMATION Buffer,
- IN OUT PULONG Length
- );
-
-NTSTATUS
-UDFQueryFsSizeInfo (
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_SIZE_INFORMATION Buffer,
- IN OUT PULONG Length
- );
-
-NTSTATUS
-UDFQueryFsFullSizeInfo (
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_FULL_SIZE_INFORMATION Buffer,
- IN OUT PULONG Length
- );
-
-NTSTATUS
-UDFQueryFsDeviceInfo (
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_DEVICE_INFORMATION Buffer,
- IN OUT PULONG Length
- );
-
-NTSTATUS
-UDFQueryFsAttributeInfo (
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
- IN OUT PULONG Length
- );
-
-NTSTATUS
-UDFSetLabelInfo (
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_LABEL_INFORMATION Buffer,
- IN OUT PULONG Length);
-
-/*
- This is the routine for querying volume information
-
-Arguments:
-
- Irp - Supplies the Irp being processed
-
-Return Value:
-
- NTSTATUS - The return status for the operation
-
- */
-NTSTATUS
-NTAPI
-UDFQueryVolInfo(
- PDEVICE_OBJECT DeviceObject, // the logical volume device object
- PIRP Irp // I/O Request Packet
- )
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrUDFIrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
-
- UDFPrint(("UDFQueryVolInfo: \n"));
-
- FsRtlEnterFileSystem();
- ASSERT(DeviceObject);
- ASSERT(Irp);
-
- // set the top level context
- AreWeTopLevel = UDFIsIrpTopLevel(Irp);
- ASSERT(!UDFIsFSDevObj(DeviceObject));
-
- _SEH2_TRY {
-
- // get an IRP context structure and issue the request
- PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
- if(PtrIrpContext) {
- RC = UDFCommonQueryVolInfo(PtrIrpContext, Irp);
- } else {
- RC = STATUS_INSUFFICIENT_RESOURCES;
- Irp->IoStatus.Status = RC;
- Irp->IoStatus.Information = 0;
- // complete the IRP
- IoCompleteRequest(Irp, IO_DISK_INCREMENT);
- }
-
- } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
-
- RC = UDFExceptionHandler(PtrIrpContext, Irp);
-
- UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
- } _SEH2_END;
-
- if (AreWeTopLevel) {
- IoSetTopLevelIrp(NULL);
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
-} // end UDFQueryVolInfo()
-
-/*
- 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
-UDFCommonQueryVolInfo(
- PtrUDFIrpContext PtrIrpContext,
- PIRP Irp
- )
-{
- NTSTATUS RC = STATUS_INVALID_PARAMETER;
- PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
- ULONG Length;
- BOOLEAN CanWait = FALSE;
- PVCB Vcb;
- BOOLEAN PostRequest = FALSE;
- BOOLEAN AcquiredVCB = FALSE;
- PFILE_OBJECT FileObject = NULL;
-// PtrUDFFCB Fcb = NULL;
- PtrUDFCCB Ccb = NULL;
-
- _SEH2_TRY {
-
- UDFPrint(("UDFCommonQueryVolInfo: \n"));
-
- ASSERT(PtrIrpContext);
- ASSERT(Irp);
-
- PAGED_CODE();
-
- FileObject = IrpSp->FileObject;
- ASSERT(FileObject);
-
- // Get the FCB and CCB pointers.
- Ccb = (PtrUDFCCB)(FileObject->FsContext2);
- ASSERT(Ccb);
-
- Vcb = (PVCB)(IrpSp->DeviceObject->DeviceExtension);
- ASSERT(Vcb);
- //Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
- // Reference our input parameters to make things easier
- Length = IrpSp->Parameters.QueryVolume.Length;
- // Acquire the Vcb for this volume.
- CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
-#ifdef UDF_ENABLE_SECURITY
- RC = IoCheckFunctionAccess(
- Ccb->PreviouslyGrantedAccess,
- PtrIrpContext->MajorFunction,
- PtrIrpContext->MinorFunction,
- 0,
- NULL,
- &(IrpSp->Parameters.QueryVolume.FsInformationClass));
- if(!NT_SUCCESS(RC)) {
- try_return(RC);
- }
-#endif //UDF_ENABLE_SECURITY
- switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
-
- case FileFsVolumeInformation:
-
- // This is the only routine we need the Vcb shared because of
- // copying the volume label. All other routines copy fields that
- // cannot change or are just manifest constants.
- UDFFlushTryBreak(Vcb);
- if (!UDFAcquireResourceShared(&(Vcb->VCBResource), CanWait)) {
- PostRequest = TRUE;
- try_return (RC = STATUS_PENDING);
- }
- AcquiredVCB = TRUE;
-
- RC = UDFQueryFsVolumeInfo( PtrIrpContext, Vcb, (PFILE_FS_VOLUME_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
- break;
-
- case FileFsSizeInformation:
-
- RC = UDFQueryFsSizeInfo( PtrIrpContext, Vcb, (PFILE_FS_SIZE_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
- break;
-
- case FileFsDeviceInformation:
-
- RC = UDFQueryFsDeviceInfo( PtrIrpContext, Vcb, (PFILE_FS_DEVICE_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
- break;
-
- case FileFsAttributeInformation:
-
- RC = UDFQueryFsAttributeInfo( PtrIrpContext, Vcb, (PFILE_FS_ATTRIBUTE_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
- break;
-
- case FileFsFullSizeInformation:
-
- RC = UDFQueryFsFullSizeInfo( PtrIrpContext, Vcb, (PFILE_FS_FULL_SIZE_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
- break;
-
- default:
-
- RC = STATUS_INVALID_DEVICE_REQUEST;
- Irp->IoStatus.Information = 0;
- break;
-
- }
-
- // Set the information field to the number of bytes actually filled in
- Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
-
-try_exit: NOTHING;
-
- } _SEH2_FINALLY {
-
- if (AcquiredVCB) {
- UDFReleaseResource(&(Vcb->VCBResource));
- AcquiredVCB = FALSE;
- }
-
- // Post IRP if required
- if (PostRequest) {
-
- // Since, the I/O Manager gave us a system buffer, we do not
- // need to "lock" anything.
-
- // Perform the post operation which will mark the IRP pending
- // and will return STATUS_PENDING back to us
- RC = UDFPostRequest(PtrIrpContext, Irp);
-
- } else
- if(!_SEH2_AbnormalTermination()) {
-
- Irp->IoStatus.Status = RC;
- // Free up the Irp Context
- UDFReleaseIrpContext(PtrIrpContext);
- // complete the IRP
- IoCompleteRequest(Irp, IO_DISK_INCREMENT);
- } // can we complete the IRP ?
-
- } _SEH2_END;
-
- return RC;
-} // end UDFCommonQueryVolInfo()
-
-
-// Local support routine
-
-/*
- This routine implements the query volume info call
-
-Arguments:
-
- Vcb - Vcb for this volume.
- Buffer - Supplies a pointer to the output buffer where the information
- is to be returned
- Length - Supplies the length of the buffer in byte. This variable
- upon return recieves the remaining bytes free in the buffer
- */
-NTSTATUS
-UDFQueryFsVolumeInfo(
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_VOLUME_INFORMATION Buffer,
- IN OUT PULONG Length
- )
-{
- ULONG BytesToCopy;
- NTSTATUS Status;
-
- PAGED_CODE();
-
- UDFPrint((" UDFQueryFsVolumeInfo: \n"));
- // Fill in the data from the Vcb.
- Buffer->VolumeCreationTime.QuadPart = Vcb->VolCreationTime;
- Buffer->VolumeSerialNumber = Vcb->PhSerialNumber;
- UDFPrint((" SN %x\n", Vcb->PhSerialNumber));
-
- Buffer->SupportsObjects = FALSE;
-
- *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );
-
- // Check if the buffer we're given is long enough
- if (*Length >= (ULONG) Vcb->VolIdent.Length) {
- BytesToCopy = Vcb->VolIdent.Length;
- Status = STATUS_SUCCESS;
- } else {
- BytesToCopy = *Length;
- Status = STATUS_BUFFER_OVERFLOW;
- }
- // Copy over what we can of the volume label, and adjust *Length
- Buffer->VolumeLabelLength = BytesToCopy;
-
- if (BytesToCopy)
- RtlCopyMemory( &(Buffer->VolumeLabel[0]), Vcb->VolIdent.Buffer, BytesToCopy );
- *Length -= BytesToCopy;
-
- return Status;
-} // end UDFQueryFsVolumeInfo()
-
-/*
- This routine implements the query volume size call.
-
-Arguments:
-
- Vcb - Vcb for this volume.
- Buffer - Supplies a pointer to the output buffer where the information
- is to be returned
- Length - Supplies the length of the buffer in byte. This variable
- upon return recieves the remaining bytes free in the buffer
- */
-NTSTATUS
-UDFQueryFsSizeInfo(
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_SIZE_INFORMATION Buffer,
- IN OUT PULONG Length
- )
-{
- PAGED_CODE();
-
- UDFPrint((" UDFQueryFsSizeInfo: \n"));
- // Fill in the output buffer.
- if(Vcb->BitmapModified) {
- Vcb->TotalAllocUnits =
- Buffer->TotalAllocationUnits.QuadPart = UDFGetTotalSpace(Vcb);
- Vcb->FreeAllocUnits =
- Buffer->AvailableAllocationUnits.QuadPart = UDFGetFreeSpace(Vcb);
- Vcb->BitmapModified = FALSE;
- } else {
- Buffer->TotalAllocationUnits.QuadPart = Vcb->TotalAllocUnits;
- Buffer->AvailableAllocationUnits.QuadPart = Vcb->FreeAllocUnits;
- }
- Vcb->LowFreeSpace = (Vcb->FreeAllocUnits < max(Vcb->FECharge,UDF_DEFAULT_FE_CHARGE)*128);
- if(!Buffer->TotalAllocationUnits.QuadPart)
- Buffer->TotalAllocationUnits.QuadPart = max(1, Vcb->LastPossibleLBA);
- Buffer->SectorsPerAllocationUnit = Vcb->LBlockSize / Vcb->BlockSize;
- if(!Buffer->SectorsPerAllocationUnit)
- Buffer->SectorsPerAllocationUnit = 1;
- Buffer->BytesPerSector = Vcb->BlockSize;
- if(!Buffer->BytesPerSector)
- Buffer->BytesPerSector = 2048;
-
- UDFPrint((" Space: Total %I64x, Free %I64x\n",
- Buffer->TotalAllocationUnits.QuadPart,
- Buffer->AvailableAllocationUnits.QuadPart));
-
- // Adjust the length variable
- *Length -= sizeof( FILE_FS_SIZE_INFORMATION );
- return STATUS_SUCCESS;
-} // UDFQueryFsSizeInfo()
-
-/*
- This routine implements the query volume full size call.
-
-Arguments:
-
- Vcb - Vcb for this volume.
- Buffer - Supplies a pointer to the output buffer where the information
- is to be returned
- Length - Supplies the length of the buffer in byte. This variable
- upon return recieves the remaining bytes free in the buffer
- */
-NTSTATUS
-UDFQueryFsFullSizeInfo(
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_FULL_SIZE_INFORMATION Buffer,
- IN OUT PULONG Length
- )
-{
- PAGED_CODE();
-
- UDFPrint((" UDFQueryFsFullSizeInfo: \n"));
- // Fill in the output buffer.
- if(Vcb->BitmapModified) {
- Vcb->TotalAllocUnits =
- Buffer->TotalAllocationUnits.QuadPart = UDFGetTotalSpace(Vcb);
- Vcb->FreeAllocUnits =
- Buffer->CallerAvailableAllocationUnits.QuadPart =
- Buffer->ActualAvailableAllocationUnits.QuadPart = UDFGetFreeSpace(Vcb);
- Vcb->BitmapModified = FALSE;
- } else {
- Buffer->TotalAllocationUnits.QuadPart = Vcb->TotalAllocUnits;
- Buffer->CallerAvailableAllocationUnits.QuadPart =
- Buffer->ActualAvailableAllocationUnits.QuadPart = Vcb->FreeAllocUnits;
- }
- if(!Buffer->TotalAllocationUnits.QuadPart)
- Buffer->TotalAllocationUnits.QuadPart = max(1, Vcb->LastPossibleLBA);
- Buffer->SectorsPerAllocationUnit = Vcb->LBlockSize / Vcb->BlockSize;
- if(!Buffer->SectorsPerAllocationUnit)
- Buffer->SectorsPerAllocationUnit = 1;
- Buffer->BytesPerSector = Vcb->BlockSize;
- if(!Buffer->BytesPerSector)
- Buffer->BytesPerSector = 2048;
-
- UDFPrint((" Space: Total %I64x, Free %I64x\n",
- Buffer->TotalAllocationUnits.QuadPart,
- Buffer->ActualAvailableAllocationUnits.QuadPart));
-
- // Adjust the length variable
- *Length -= sizeof( FILE_FS_FULL_SIZE_INFORMATION );
- return STATUS_SUCCESS;
-} // UDFQueryFsSizeInfo()
-
-/*
- This routine implements the query volume device call.
-
-Arguments:
-
- Vcb - Vcb for this volume.
- Buffer - Supplies a pointer to the output buffer where the information
- is to be returned
- Length - Supplies the length of the buffer in byte. This variable
- upon return recieves the remaining bytes free in the buffer
- */
-NTSTATUS
-UDFQueryFsDeviceInfo(
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_DEVICE_INFORMATION Buffer,
- IN OUT PULONG Length
- )
-{
- PAGED_CODE();
-
- UDFPrint((" UDFQueryFsDeviceInfo: \n"));
- // Update the output buffer.
- if (Vcb->TargetDeviceObject->DeviceType != FILE_DEVICE_CD_ROM && Vcb->TargetDeviceObject->DeviceType != FILE_DEVICE_DVD)
- {
- ASSERT(! (Vcb->TargetDeviceObject->Characteristics & (FILE_READ_ONLY_DEVICE | FILE_WRITE_ONCE_MEDIA)));
- Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics & ~(FILE_READ_ONLY_DEVICE | FILE_WRITE_ONCE_MEDIA);
- }
- else
- {
- Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
- }
- Buffer->DeviceType = Vcb->TargetDeviceObject->DeviceType;
- UDFPrint((" Characteristics %x, DeviceType %x\n", Buffer->Characteristics, Buffer->DeviceType));
- // Adjust the length variable
- *Length -= sizeof( FILE_FS_DEVICE_INFORMATION );
- return STATUS_SUCCESS;
-} // end UDFQueryFsDeviceInfo()
-
-/*
- This routine implements the query volume attribute call.
-
-Arguments:
-
- Vcb - Vcb for this volume.
- Buffer - Supplies a pointer to the output buffer where the information
- is to be returned
- Length - Supplies the length of the buffer in byte. This variable
- upon return recieves the remaining bytes free in the buffer
- */
-NTSTATUS
-UDFQueryFsAttributeInfo(
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
- IN OUT PULONG Length
- )
-{
- ULONG BytesToCopy;
-
- NTSTATUS Status = STATUS_SUCCESS;
- PCWSTR FsTypeTitle;
- ULONG FsTypeTitleLen;
-
- PAGED_CODE();
- UDFPrint((" UDFQueryFsAttributeInfo: \n"));
- // Fill out the fixed portion of the buffer.
- Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH |
- FILE_CASE_PRESERVED_NAMES |
- (UDFStreamsSupported(Vcb) ? FILE_NAMED_STREAMS : 0) |
-#ifdef ALLOW_SPARSE
- FILE_SUPPORTS_SPARSE_FILES |
-#endif //ALLOW_SPARSE
-#ifdef UDF_ENABLE_SECURITY
- (UDFNtAclSupported(Vcb) ? FILE_PERSISTENT_ACLS : 0) |
-#endif //UDF_ENABLE_SECURITY
- ((Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) ? FILE_READ_ONLY_VOLUME : 0) |
-
- FILE_UNICODE_ON_DISK;
-
- Buffer->MaximumComponentNameLength = UDF_X_NAME_LEN-1;
-
- *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
- // Make sure we can copy full unicode characters.
- *Length &= ~1;
- // Determine how much of the file system name will fit.
-
-#define UDFSetFsTitle(tit) \
- FsTypeTitle = UDF_FS_TITLE_##tit; \
- FsTypeTitleLen = sizeof(UDF_FS_TITLE_##tit) - sizeof(WCHAR);
-
- switch(Vcb->TargetDeviceObject->DeviceType) {
- case FILE_DEVICE_CD_ROM: {
- if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
- if(!Vcb->LastLBA) {
- UDFSetFsTitle(BLANK);
- } else {
- UDFSetFsTitle(UNKNOWN);
- }
- } else
- if(Vcb->CDR_Mode) {
- if(Vcb->MediaClassEx == CdMediaClass_DVDR ||
- Vcb->MediaClassEx == CdMediaClass_DVDRW ||
- Vcb->MediaClassEx == CdMediaClass_DVDRAM) {
- UDFSetFsTitle(DVDR);
- } else
- if(Vcb->MediaClassEx == CdMediaClass_DVDpR ||
- Vcb->MediaClassEx == CdMediaClass_DVDpRW) {
- UDFSetFsTitle(DVDpR);
- } else
- if(Vcb->MediaClassEx == CdMediaClass_DVDROM) {
- UDFSetFsTitle(DVDROM);
- } else
- if(Vcb->MediaClassEx == CdMediaClass_CDROM) {
- UDFSetFsTitle(CDROM);
- } else {
- UDFSetFsTitle(CDR);
- }
- } else {
- if(Vcb->MediaClassEx == CdMediaClass_DVDROM ||
- Vcb->MediaClassEx == CdMediaClass_DVDR ||
- Vcb->MediaClassEx == CdMediaClass_DVDpR) {
- UDFSetFsTitle(DVDROM);
- } else
- if(Vcb->MediaClassEx == CdMediaClass_DVDR) {
- UDFSetFsTitle(DVDR);
- } else
- if(Vcb->MediaClassEx == CdMediaClass_DVDRW) {
- UDFSetFsTitle(DVDRW);
- } else
- if(Vcb->MediaClassEx == CdMediaClass_DVDpRW) {
- UDFSetFsTitle(DVDpRW);
- } else
- if(Vcb->MediaClassEx == CdMediaClass_DVDRAM) {
- UDFSetFsTitle(DVDRAM);
- } else
- if(Vcb->MediaClassEx == CdMediaClass_CDROM) {
- UDFSetFsTitle(CDROM);
- } else {
- UDFSetFsTitle(CDRW);
- }
- }
- break;
- }
- default: {
- UDFSetFsTitle(HDD);
- break;
- }
- }
-
-#undef UDFSetFsTitle
-
- if (*Length >= FsTypeTitleLen) {
- BytesToCopy = FsTypeTitleLen;
- } else {
- BytesToCopy = *Length;
- Status = STATUS_BUFFER_OVERFLOW;
- }
-
- *Length -= BytesToCopy;
- // Do the file system name.
- Buffer->FileSystemNameLength = BytesToCopy;
- RtlCopyMemory( &Buffer->FileSystemName[0], FsTypeTitle, BytesToCopy );
- // And return to our caller
- return Status;
-} // end UDFQueryFsAttributeInfo()
-
-
-#ifndef UDF_READ_ONLY_BUILD
-
-NTSTATUS
-NTAPI
-UDFSetVolInfo(
- PDEVICE_OBJECT DeviceObject, // the logical volume device object
- PIRP Irp // I/O Request Packet
- )
-{
- NTSTATUS RC = STATUS_SUCCESS;
- PtrUDFIrpContext PtrIrpContext = NULL;
- BOOLEAN AreWeTopLevel = FALSE;
-
- UDFPrint(("UDFSetVolInfo: \n"));
-
- FsRtlEnterFileSystem();
- ASSERT(DeviceObject);
- ASSERT(Irp);
-
- // set the top level context
- AreWeTopLevel = UDFIsIrpTopLevel(Irp);
- ASSERT(!UDFIsFSDevObj(DeviceObject));
-
- _SEH2_TRY {
-
- // get an IRP context structure and issue the request
- PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
- ASSERT(PtrIrpContext);
-
- RC = UDFCommonSetVolInfo(PtrIrpContext, Irp);
-
- } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
-
- RC = UDFExceptionHandler(PtrIrpContext, Irp);
-
- UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
- } _SEH2_END;
-
- if (AreWeTopLevel) {
- IoSetTopLevelIrp(NULL);
- }
-
- FsRtlExitFileSystem();
-
- return(RC);
-} // end UDFSetVolInfo()
-
-
-/*
- This is the common routine for setting volume information called by both
- the fsd and fsp threads.
- */
-NTSTATUS
-UDFCommonSetVolInfo(
- PtrUDFIrpContext PtrIrpContext,
- PIRP Irp
- )
-{
- NTSTATUS RC = STATUS_INVALID_PARAMETER;
- PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
- ULONG Length;
- BOOLEAN CanWait = FALSE;
- PVCB Vcb;
- BOOLEAN PostRequest = FALSE;
- BOOLEAN AcquiredVCB = FALSE;
- PFILE_OBJECT FileObject = NULL;
-// PtrUDFFCB Fcb = NULL;
- PtrUDFCCB Ccb = NULL;
-
- _SEH2_TRY {
-
- UDFPrint(("UDFCommonSetVolInfo: \n"));
- ASSERT(PtrIrpContext);
- ASSERT(Irp);
-
- PAGED_CODE();
-
- FileObject = IrpSp->FileObject;
- ASSERT(FileObject);
-
- // Get the FCB and CCB pointers.
- Ccb = (PtrUDFCCB)(FileObject->FsContext2);
- ASSERT(Ccb);
-
- if(Ccb && Ccb->Fcb && (Ccb->Fcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB)) {
- UDFPrint((" Can't change Label on Non-volume object\n"));
- try_return(RC = STATUS_ACCESS_DENIED);
- }
-
- Vcb = (PVCB)(IrpSp->DeviceObject->DeviceExtension);
- ASSERT(Vcb);
- Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
- // Reference our input parameters to make things easier
-
- if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
- UDFPrint((" Can't change Label on blank volume ;)\n"));
- try_return(RC = STATUS_ACCESS_DENIED);
- }
-
- Length = IrpSp->Parameters.SetVolume.Length;
- // Acquire the Vcb for this volume.
- CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
- if (!UDFAcquireResourceShared(&(Vcb->VCBResource), CanWait)) {
- PostRequest = TRUE;
- try_return (RC = STATUS_PENDING);
- }
- AcquiredVCB = TRUE;
-#ifdef UDF_ENABLE_SECURITY
- RC = IoCheckFunctionAccess(
- Ccb->PreviouslyGrantedAccess,
- PtrIrpContext->MajorFunction,
- PtrIrpContext->MinorFunction,
- 0,
- NULL,
- &(IrpSp->Parameters.SetVolume.FsInformationClass));
- if(!NT_SUCCESS(RC)) {
- try_return(RC);
- }
-#endif //UDF_ENABLE_SECURITY
- switch (IrpSp->Parameters.SetVolume.FsInformationClass) {
-
- case FileFsLabelInformation:
-
- RC = UDFSetLabelInfo( PtrIrpContext, Vcb, (PFILE_FS_LABEL_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
- Irp->IoStatus.Information = 0;
- break;
-
- default:
-
- RC = STATUS_INVALID_DEVICE_REQUEST;
- Irp->IoStatus.Information = 0;
- break;
-
- }
-
- // Set the information field to the number of bytes actually filled in
- Irp->IoStatus.Information = IrpSp->Parameters.SetVolume.Length - Length;
-
-try_exit: NOTHING;
-
- } _SEH2_FINALLY {
-
- if (AcquiredVCB) {
- UDFReleaseResource(&(Vcb->VCBResource));
- AcquiredVCB = FALSE;
- }
-
- // Post IRP if required
- if (PostRequest) {
-
- // Since, the I/O Manager gave us a system buffer, we do not
- // need to "lock" anything.
-
- // Perform the post operation which will mark the IRP pending
- // and will return STATUS_PENDING back to us
- RC = UDFPostRequest(PtrIrpContext, Irp);
-
- } else {
-
- // Can complete the IRP here if no exception was encountered
- if (!_SEH2_AbnormalTermination()) {
- Irp->IoStatus.Status = RC;
-
- // Free up the Irp Context
- UDFReleaseIrpContext(PtrIrpContext);
- // complete the IRP
- IoCompleteRequest(Irp, IO_DISK_INCREMENT);
- }
- } // can we complete the IRP ?
-
- } _SEH2_END;
-
- return RC;
-} // end UDFCommonSetVolInfo()
-
-/*
- This sets Volume Label
- */
-NTSTATUS
-UDFSetLabelInfo (
- IN PtrUDFIrpContext PtrIrpContext,
- IN PVCB Vcb,
- IN PFILE_FS_LABEL_INFORMATION Buffer,
- IN OUT PULONG Length
- )
-{
- PAGED_CODE();
-
- UDFPrint((" UDFSetLabelInfo: \n"));
- if(Buffer->VolumeLabelLength > UDF_VOL_LABEL_LEN*sizeof(WCHAR)) {
- // Too long Volume Label... NT doesn't like it
- UDFPrint((" UDFSetLabelInfo: STATUS_INVALID_VOLUME_LABEL\n"));
- return STATUS_INVALID_VOLUME_LABEL;
- }
-
- if(Vcb->VolIdent.Buffer) MyFreePool__(Vcb->VolIdent.Buffer);
- Vcb->VolIdent.Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool, Buffer->VolumeLabelLength+sizeof(WCHAR));
- if(!Vcb->VolIdent.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
-
- Vcb->VolIdent.Length = (USHORT)Buffer->VolumeLabelLength;
- Vcb->VolIdent.MaximumLength = (USHORT)Buffer->VolumeLabelLength+sizeof(WCHAR);
- RtlCopyMemory(Vcb->VolIdent.Buffer, &(Buffer->VolumeLabel), Buffer->VolumeLabelLength);
- Vcb->VolIdent.Buffer[Buffer->VolumeLabelLength/sizeof(WCHAR)] = 0;
- UDFSetModified(Vcb);
-
- UDFPrint((" UDFSetLabelInfo: OK\n"));
- return STATUS_SUCCESS;
-} // end UDFSetLabelInfo ()
-
-#endif //UDF_READ_ONLY_BUILD