Something went wrong. Try again.
Reactos
Something went wrong. Try again.
25 kB · 822 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823////////////////////////////////////////////////////////////////////// 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 routinesNTSTATUSUDFQueryFsVolumeInfo ( IN PtrUDFIrpContext PtrIrpContext, IN PVCB Vcb, IN PFILE_FS_VOLUME_INFORMATION Buffer, IN OUT PULONG Length );
NTSTATUSUDFQueryFsSizeInfo ( IN PtrUDFIrpContext PtrIrpContext, IN PVCB Vcb, IN PFILE_FS_SIZE_INFORMATION Buffer, IN OUT PULONG Length );
NTSTATUSUDFQueryFsFullSizeInfo ( IN PtrUDFIrpContext PtrIrpContext, IN PVCB Vcb, IN PFILE_FS_FULL_SIZE_INFORMATION Buffer, IN OUT PULONG Length );
NTSTATUSUDFQueryFsDeviceInfo ( IN PtrUDFIrpContext PtrIrpContext, IN PVCB Vcb, IN PFILE_FS_DEVICE_INFORMATION Buffer, IN OUT PULONG Length );
NTSTATUSUDFQueryFsAttributeInfo ( IN PtrUDFIrpContext PtrIrpContext, IN PVCB Vcb, IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer, IN OUT PULONG Length );
NTSTATUSUDFSetLabelInfo ( 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
*/NTSTATUSNTAPIUDFQueryVolInfo( 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
*/NTSTATUSUDFCommonQueryVolInfo( 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
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, Length);
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 */NTSTATUSUDFQueryFsVolumeInfo( 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 */NTSTATUSUDFQueryFsSizeInfo( 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 */NTSTATUSUDFQueryFsFullSizeInfo( 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 */NTSTATUSUDFQueryFsDeviceInfo( 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 */NTSTATUSUDFQueryFsAttributeInfo( 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
NTSTATUSNTAPIUDFSetVolInfo( 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. */NTSTATUSUDFCommonSetVolInfo( 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 */NTSTATUSUDFSetLabelInfo ( 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