1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
14 This module implements the volume information routines for UDF called by
21 // define the file specific bug-check id
22 #define UDF_BUG_CHECK_ID UDF_FILE_VOL_INFORMATION
24 // Local support routines
26 UDFQueryFsVolumeInfo (
27 IN PtrUDFIrpContext PtrIrpContext
,
29 IN PFILE_FS_VOLUME_INFORMATION Buffer
,
35 IN PtrUDFIrpContext PtrIrpContext
,
37 IN PFILE_FS_SIZE_INFORMATION Buffer
,
42 UDFQueryFsFullSizeInfo (
43 IN PtrUDFIrpContext PtrIrpContext
,
45 IN PFILE_FS_FULL_SIZE_INFORMATION Buffer
,
50 UDFQueryFsDeviceInfo (
51 IN PtrUDFIrpContext PtrIrpContext
,
53 IN PFILE_FS_DEVICE_INFORMATION Buffer
,
58 UDFQueryFsAttributeInfo (
59 IN PtrUDFIrpContext PtrIrpContext
,
61 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer
,
67 IN PtrUDFIrpContext PtrIrpContext
,
69 IN PFILE_FS_LABEL_INFORMATION Buffer
,
70 IN OUT PULONG Length
);
73 This is the routine for querying volume information
77 Irp - Supplies the Irp being processed
81 NTSTATUS - The return status for the operation
87 PDEVICE_OBJECT DeviceObject
, // the logical volume device object
88 PIRP Irp
// I/O Request Packet
91 NTSTATUS RC
= STATUS_SUCCESS
;
92 PtrUDFIrpContext PtrIrpContext
= NULL
;
93 BOOLEAN AreWeTopLevel
= FALSE
;
95 UDFPrint(("UDFQueryVolInfo: \n"));
97 FsRtlEnterFileSystem();
101 // set the top level context
102 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
103 ASSERT(!UDFIsFSDevObj(DeviceObject
));
107 // get an IRP context structure and issue the request
108 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
110 RC
= UDFCommonQueryVolInfo(PtrIrpContext
, Irp
);
112 RC
= STATUS_INSUFFICIENT_RESOURCES
;
113 Irp
->IoStatus
.Status
= RC
;
114 Irp
->IoStatus
.Information
= 0;
116 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
119 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
121 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
123 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
127 IoSetTopLevelIrp(NULL
);
130 FsRtlExitFileSystem();
133 } // end UDFQueryVolInfo()
136 This is the common routine for querying volume information called by both
137 the fsd and fsp threads.
141 Irp - Supplies the Irp being processed
145 NTSTATUS - The return status for the operation
149 UDFCommonQueryVolInfo(
150 PtrUDFIrpContext PtrIrpContext
,
154 NTSTATUS RC
= STATUS_INVALID_PARAMETER
;
155 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
157 BOOLEAN CanWait
= FALSE
;
159 BOOLEAN PostRequest
= FALSE
;
160 BOOLEAN AcquiredVCB
= FALSE
;
161 PFILE_OBJECT FileObject
= NULL
;
162 // PtrUDFFCB Fcb = NULL;
163 PtrUDFCCB Ccb
= NULL
;
167 UDFPrint(("UDFCommonQueryVolInfo: \n"));
169 ASSERT(PtrIrpContext
);
174 FileObject
= IrpSp
->FileObject
;
177 // Get the FCB and CCB pointers.
178 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
181 Vcb
= (PVCB
)(IrpSp
->DeviceObject
->DeviceExtension
);
183 //Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
184 // Reference our input parameters to make things easier
185 Length
= IrpSp
->Parameters
.QueryVolume
.Length
;
186 // Acquire the Vcb for this volume.
187 CanWait
= ((PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_CAN_BLOCK
) ? TRUE
: FALSE
);
188 #ifdef UDF_ENABLE_SECURITY
189 RC
= IoCheckFunctionAccess(
190 Ccb
->PreviouslyGrantedAccess
,
191 PtrIrpContext
->MajorFunction
,
192 PtrIrpContext
->MinorFunction
,
195 &(IrpSp
->Parameters
.QueryVolume
.FsInformationClass
));
196 if(!NT_SUCCESS(RC
)) {
199 #endif //UDF_ENABLE_SECURITY
200 switch (IrpSp
->Parameters
.QueryVolume
.FsInformationClass
) {
202 case FileFsVolumeInformation
:
204 // This is the only routine we need the Vcb shared because of
205 // copying the volume label. All other routines copy fields that
206 // cannot change or are just manifest constants.
207 UDFFlushTryBreak(Vcb
);
208 if (!UDFAcquireResourceShared(&(Vcb
->VCBResource
), CanWait
)) {
210 try_return (RC
= STATUS_PENDING
);
214 RC
= UDFQueryFsVolumeInfo( PtrIrpContext
, Vcb
, (PFILE_FS_VOLUME_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
217 case FileFsSizeInformation
:
219 RC
= UDFQueryFsSizeInfo( PtrIrpContext
, Vcb
, (PFILE_FS_SIZE_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
222 case FileFsDeviceInformation
:
224 RC
= UDFQueryFsDeviceInfo( PtrIrpContext
, Vcb
, (PFILE_FS_DEVICE_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
227 case FileFsAttributeInformation
:
229 RC
= UDFQueryFsAttributeInfo( PtrIrpContext
, Vcb
, (PFILE_FS_ATTRIBUTE_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
232 case FileFsFullSizeInformation
:
234 RC
= UDFQueryFsFullSizeInfo( PtrIrpContext
, Vcb
, (PFILE_FS_FULL_SIZE_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
239 RC
= STATUS_INVALID_DEVICE_REQUEST
;
240 Irp
->IoStatus
.Information
= 0;
245 // Set the information field to the number of bytes actually filled in
246 Irp
->IoStatus
.Information
= IrpSp
->Parameters
.QueryVolume
.Length
- Length
;
253 UDFReleaseResource(&(Vcb
->VCBResource
));
257 // Post IRP if required
260 // Since, the I/O Manager gave us a system buffer, we do not
261 // need to "lock" anything.
263 // Perform the post operation which will mark the IRP pending
264 // and will return STATUS_PENDING back to us
265 RC
= UDFPostRequest(PtrIrpContext
, Irp
);
268 if(!_SEH2_AbnormalTermination()) {
270 Irp
->IoStatus
.Status
= RC
;
271 // Free up the Irp Context
272 UDFReleaseIrpContext(PtrIrpContext
);
274 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
275 } // can we complete the IRP ?
280 } // end UDFCommonQueryVolInfo()
283 // Local support routine
286 This routine implements the query volume info call
290 Vcb - Vcb for this volume.
291 Buffer - Supplies a pointer to the output buffer where the information
293 Length - Supplies the length of the buffer in byte. This variable
294 upon return recieves the remaining bytes free in the buffer
297 UDFQueryFsVolumeInfo(
298 IN PtrUDFIrpContext PtrIrpContext
,
300 IN PFILE_FS_VOLUME_INFORMATION Buffer
,
309 UDFPrint((" UDFQueryFsVolumeInfo: \n"));
310 // Fill in the data from the Vcb.
311 Buffer
->VolumeCreationTime
.QuadPart
= Vcb
->VolCreationTime
;
312 Buffer
->VolumeSerialNumber
= Vcb
->PhSerialNumber
;
313 UDFPrint((" SN %x\n", Vcb
->PhSerialNumber
));
315 Buffer
->SupportsObjects
= FALSE
;
317 *Length
-= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION
, VolumeLabel
[0] );
319 // Check if the buffer we're given is long enough
320 if (*Length
>= (ULONG
) Vcb
->VolIdent
.Length
) {
321 BytesToCopy
= Vcb
->VolIdent
.Length
;
322 Status
= STATUS_SUCCESS
;
324 BytesToCopy
= *Length
;
325 Status
= STATUS_BUFFER_OVERFLOW
;
327 // Copy over what we can of the volume label, and adjust *Length
328 Buffer
->VolumeLabelLength
= BytesToCopy
;
331 RtlCopyMemory( &(Buffer
->VolumeLabel
[0]), Vcb
->VolIdent
.Buffer
, BytesToCopy
);
332 *Length
-= BytesToCopy
;
335 } // end UDFQueryFsVolumeInfo()
338 This routine implements the query volume size call.
342 Vcb - Vcb for this volume.
343 Buffer - Supplies a pointer to the output buffer where the information
345 Length - Supplies the length of the buffer in byte. This variable
346 upon return recieves the remaining bytes free in the buffer
350 IN PtrUDFIrpContext PtrIrpContext
,
352 IN PFILE_FS_SIZE_INFORMATION Buffer
,
358 UDFPrint((" UDFQueryFsSizeInfo: \n"));
359 // Fill in the output buffer.
360 if(Vcb
->BitmapModified
) {
361 Vcb
->TotalAllocUnits
=
362 Buffer
->TotalAllocationUnits
.QuadPart
= UDFGetTotalSpace(Vcb
);
363 Vcb
->FreeAllocUnits
=
364 Buffer
->AvailableAllocationUnits
.QuadPart
= UDFGetFreeSpace(Vcb
);
365 Vcb
->BitmapModified
= FALSE
;
367 Buffer
->TotalAllocationUnits
.QuadPart
= Vcb
->TotalAllocUnits
;
368 Buffer
->AvailableAllocationUnits
.QuadPart
= Vcb
->FreeAllocUnits
;
370 Vcb
->LowFreeSpace
= (Vcb
->FreeAllocUnits
< max(Vcb
->FECharge
,UDF_DEFAULT_FE_CHARGE
)*128);
371 if(!Buffer
->TotalAllocationUnits
.QuadPart
)
372 Buffer
->TotalAllocationUnits
.QuadPart
= max(1, Vcb
->LastPossibleLBA
);
373 Buffer
->SectorsPerAllocationUnit
= Vcb
->LBlockSize
/ Vcb
->BlockSize
;
374 if(!Buffer
->SectorsPerAllocationUnit
)
375 Buffer
->SectorsPerAllocationUnit
= 1;
376 Buffer
->BytesPerSector
= Vcb
->BlockSize
;
377 if(!Buffer
->BytesPerSector
)
378 Buffer
->BytesPerSector
= 2048;
380 UDFPrint((" Space: Total %I64x, Free %I64x\n",
381 Buffer
->TotalAllocationUnits
.QuadPart
,
382 Buffer
->AvailableAllocationUnits
.QuadPart
));
384 // Adjust the length variable
385 *Length
-= sizeof( FILE_FS_SIZE_INFORMATION
);
386 return STATUS_SUCCESS
;
387 } // UDFQueryFsSizeInfo()
390 This routine implements the query volume full size call.
394 Vcb - Vcb for this volume.
395 Buffer - Supplies a pointer to the output buffer where the information
397 Length - Supplies the length of the buffer in byte. This variable
398 upon return recieves the remaining bytes free in the buffer
401 UDFQueryFsFullSizeInfo(
402 IN PtrUDFIrpContext PtrIrpContext
,
404 IN PFILE_FS_FULL_SIZE_INFORMATION Buffer
,
410 UDFPrint((" UDFQueryFsFullSizeInfo: \n"));
411 // Fill in the output buffer.
412 if(Vcb
->BitmapModified
) {
413 Vcb
->TotalAllocUnits
=
414 Buffer
->TotalAllocationUnits
.QuadPart
= UDFGetTotalSpace(Vcb
);
415 Vcb
->FreeAllocUnits
=
416 Buffer
->CallerAvailableAllocationUnits
.QuadPart
=
417 Buffer
->ActualAvailableAllocationUnits
.QuadPart
= UDFGetFreeSpace(Vcb
);
418 Vcb
->BitmapModified
= FALSE
;
420 Buffer
->TotalAllocationUnits
.QuadPart
= Vcb
->TotalAllocUnits
;
421 Buffer
->CallerAvailableAllocationUnits
.QuadPart
=
422 Buffer
->ActualAvailableAllocationUnits
.QuadPart
= Vcb
->FreeAllocUnits
;
424 if(!Buffer
->TotalAllocationUnits
.QuadPart
)
425 Buffer
->TotalAllocationUnits
.QuadPart
= max(1, Vcb
->LastPossibleLBA
);
426 Buffer
->SectorsPerAllocationUnit
= Vcb
->LBlockSize
/ Vcb
->BlockSize
;
427 if(!Buffer
->SectorsPerAllocationUnit
)
428 Buffer
->SectorsPerAllocationUnit
= 1;
429 Buffer
->BytesPerSector
= Vcb
->BlockSize
;
430 if(!Buffer
->BytesPerSector
)
431 Buffer
->BytesPerSector
= 2048;
433 UDFPrint((" Space: Total %I64x, Free %I64x\n",
434 Buffer
->TotalAllocationUnits
.QuadPart
,
435 Buffer
->ActualAvailableAllocationUnits
.QuadPart
));
437 // Adjust the length variable
438 *Length
-= sizeof( FILE_FS_FULL_SIZE_INFORMATION
);
439 return STATUS_SUCCESS
;
440 } // UDFQueryFsSizeInfo()
443 This routine implements the query volume device call.
447 Vcb - Vcb for this volume.
448 Buffer - Supplies a pointer to the output buffer where the information
450 Length - Supplies the length of the buffer in byte. This variable
451 upon return recieves the remaining bytes free in the buffer
454 UDFQueryFsDeviceInfo(
455 IN PtrUDFIrpContext PtrIrpContext
,
457 IN PFILE_FS_DEVICE_INFORMATION Buffer
,
463 UDFPrint((" UDFQueryFsDeviceInfo: \n"));
464 // Update the output buffer.
465 if (Vcb
->TargetDeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
&& Vcb
->TargetDeviceObject
->DeviceType
!= FILE_DEVICE_DVD
)
467 ASSERT(! (Vcb
->TargetDeviceObject
->Characteristics
& (FILE_READ_ONLY_DEVICE
| FILE_WRITE_ONCE_MEDIA
)));
468 Buffer
->Characteristics
= Vcb
->TargetDeviceObject
->Characteristics
& ~(FILE_READ_ONLY_DEVICE
| FILE_WRITE_ONCE_MEDIA
);
472 Buffer
->Characteristics
= Vcb
->TargetDeviceObject
->Characteristics
;
474 Buffer
->DeviceType
= Vcb
->TargetDeviceObject
->DeviceType
;
475 UDFPrint((" Characteristics %x, DeviceType %x\n", Buffer
->Characteristics
, Buffer
->DeviceType
));
476 // Adjust the length variable
477 *Length
-= sizeof( FILE_FS_DEVICE_INFORMATION
);
478 return STATUS_SUCCESS
;
479 } // end UDFQueryFsDeviceInfo()
482 This routine implements the query volume attribute call.
486 Vcb - Vcb for this volume.
487 Buffer - Supplies a pointer to the output buffer where the information
489 Length - Supplies the length of the buffer in byte. This variable
490 upon return recieves the remaining bytes free in the buffer
493 UDFQueryFsAttributeInfo(
494 IN PtrUDFIrpContext PtrIrpContext
,
496 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer
,
502 NTSTATUS Status
= STATUS_SUCCESS
;
504 ULONG FsTypeTitleLen
;
507 UDFPrint((" UDFQueryFsAttributeInfo: \n"));
508 // Fill out the fixed portion of the buffer.
509 Buffer
->FileSystemAttributes
= FILE_CASE_SENSITIVE_SEARCH
|
510 FILE_CASE_PRESERVED_NAMES
|
511 (UDFStreamsSupported(Vcb
) ? FILE_NAMED_STREAMS
: 0) |
513 FILE_SUPPORTS_SPARSE_FILES
|
514 #endif //ALLOW_SPARSE
515 #ifdef UDF_ENABLE_SECURITY
516 (UDFNtAclSupported(Vcb
) ? FILE_PERSISTENT_ACLS
: 0) |
517 #endif //UDF_ENABLE_SECURITY
518 ((Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
) ? FILE_READ_ONLY_VOLUME
: 0) |
520 FILE_UNICODE_ON_DISK
;
522 Buffer
->MaximumComponentNameLength
= UDF_X_NAME_LEN
-1;
524 *Length
-= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION
, FileSystemName
);
525 // Make sure we can copy full unicode characters.
527 // Determine how much of the file system name will fit.
529 #define UDFSetFsTitle(tit) \
530 FsTypeTitle = UDF_FS_TITLE_##tit; \
531 FsTypeTitleLen = sizeof(UDF_FS_TITLE_##tit) - sizeof(WCHAR);
533 switch(Vcb
->TargetDeviceObject
->DeviceType
) {
534 case FILE_DEVICE_CD_ROM
: {
535 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
537 UDFSetFsTitle(BLANK
);
539 UDFSetFsTitle(UNKNOWN
);
543 if(Vcb
->MediaClassEx
== CdMediaClass_DVDR
||
544 Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
545 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
) {
548 if(Vcb
->MediaClassEx
== CdMediaClass_DVDpR
||
549 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
) {
550 UDFSetFsTitle(DVDpR
);
552 if(Vcb
->MediaClassEx
== CdMediaClass_DVDROM
) {
553 UDFSetFsTitle(DVDROM
);
555 if(Vcb
->MediaClassEx
== CdMediaClass_CDROM
) {
556 UDFSetFsTitle(CDROM
);
561 if(Vcb
->MediaClassEx
== CdMediaClass_DVDROM
||
562 Vcb
->MediaClassEx
== CdMediaClass_DVDR
||
563 Vcb
->MediaClassEx
== CdMediaClass_DVDpR
) {
564 UDFSetFsTitle(DVDROM
);
566 if(Vcb
->MediaClassEx
== CdMediaClass_DVDR
) {
569 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
) {
570 UDFSetFsTitle(DVDRW
);
572 if(Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
) {
573 UDFSetFsTitle(DVDpRW
);
575 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
) {
576 UDFSetFsTitle(DVDRAM
);
578 if(Vcb
->MediaClassEx
== CdMediaClass_CDROM
) {
579 UDFSetFsTitle(CDROM
);
594 if (*Length
>= FsTypeTitleLen
) {
595 BytesToCopy
= FsTypeTitleLen
;
597 BytesToCopy
= *Length
;
598 Status
= STATUS_BUFFER_OVERFLOW
;
601 *Length
-= BytesToCopy
;
602 // Do the file system name.
603 Buffer
->FileSystemNameLength
= BytesToCopy
;
604 RtlCopyMemory( &Buffer
->FileSystemName
[0], FsTypeTitle
, BytesToCopy
);
605 // And return to our caller
607 } // end UDFQueryFsAttributeInfo()
610 #ifndef UDF_READ_ONLY_BUILD
615 PDEVICE_OBJECT DeviceObject
, // the logical volume device object
616 PIRP Irp
// I/O Request Packet
619 NTSTATUS RC
= STATUS_SUCCESS
;
620 PtrUDFIrpContext PtrIrpContext
= NULL
;
621 BOOLEAN AreWeTopLevel
= FALSE
;
623 UDFPrint(("UDFSetVolInfo: \n"));
625 FsRtlEnterFileSystem();
626 ASSERT(DeviceObject
);
629 // set the top level context
630 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
631 ASSERT(!UDFIsFSDevObj(DeviceObject
));
635 // get an IRP context structure and issue the request
636 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
637 ASSERT(PtrIrpContext
);
639 RC
= UDFCommonSetVolInfo(PtrIrpContext
, Irp
);
641 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
643 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
645 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
649 IoSetTopLevelIrp(NULL
);
652 FsRtlExitFileSystem();
655 } // end UDFSetVolInfo()
659 This is the common routine for setting volume information called by both
660 the fsd and fsp threads.
664 PtrUDFIrpContext PtrIrpContext
,
668 NTSTATUS RC
= STATUS_INVALID_PARAMETER
;
669 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
671 BOOLEAN CanWait
= FALSE
;
673 BOOLEAN PostRequest
= FALSE
;
674 BOOLEAN AcquiredVCB
= FALSE
;
675 PFILE_OBJECT FileObject
= NULL
;
676 // PtrUDFFCB Fcb = NULL;
677 PtrUDFCCB Ccb
= NULL
;
681 UDFPrint(("UDFCommonSetVolInfo: \n"));
682 ASSERT(PtrIrpContext
);
687 FileObject
= IrpSp
->FileObject
;
690 // Get the FCB and CCB pointers.
691 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
694 if(Ccb
&& Ccb
->Fcb
&& (Ccb
->Fcb
->NodeIdentifier
.NodeType
!= UDF_NODE_TYPE_VCB
)) {
695 UDFPrint((" Can't change Label on Non-volume object\n"));
696 try_return(RC
= STATUS_ACCESS_DENIED
);
699 Vcb
= (PVCB
)(IrpSp
->DeviceObject
->DeviceExtension
);
701 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
702 // Reference our input parameters to make things easier
704 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
705 UDFPrint((" Can't change Label on blank volume ;)\n"));
706 try_return(RC
= STATUS_ACCESS_DENIED
);
709 Length
= IrpSp
->Parameters
.SetVolume
.Length
;
710 // Acquire the Vcb for this volume.
711 CanWait
= ((PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_CAN_BLOCK
) ? TRUE
: FALSE
);
712 if (!UDFAcquireResourceShared(&(Vcb
->VCBResource
), CanWait
)) {
714 try_return (RC
= STATUS_PENDING
);
717 #ifdef UDF_ENABLE_SECURITY
718 RC
= IoCheckFunctionAccess(
719 Ccb
->PreviouslyGrantedAccess
,
720 PtrIrpContext
->MajorFunction
,
721 PtrIrpContext
->MinorFunction
,
724 &(IrpSp
->Parameters
.SetVolume
.FsInformationClass
));
725 if(!NT_SUCCESS(RC
)) {
728 #endif //UDF_ENABLE_SECURITY
729 switch (IrpSp
->Parameters
.SetVolume
.FsInformationClass
) {
731 case FileFsLabelInformation
:
733 RC
= UDFSetLabelInfo( PtrIrpContext
, Vcb
, (PFILE_FS_LABEL_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
734 Irp
->IoStatus
.Information
= 0;
739 RC
= STATUS_INVALID_DEVICE_REQUEST
;
740 Irp
->IoStatus
.Information
= 0;
745 // Set the information field to the number of bytes actually filled in
746 Irp
->IoStatus
.Information
= IrpSp
->Parameters
.SetVolume
.Length
- Length
;
753 UDFReleaseResource(&(Vcb
->VCBResource
));
757 // Post IRP if required
760 // Since, the I/O Manager gave us a system buffer, we do not
761 // need to "lock" anything.
763 // Perform the post operation which will mark the IRP pending
764 // and will return STATUS_PENDING back to us
765 RC
= UDFPostRequest(PtrIrpContext
, Irp
);
769 // Can complete the IRP here if no exception was encountered
770 if (!_SEH2_AbnormalTermination()) {
771 Irp
->IoStatus
.Status
= RC
;
773 // Free up the Irp Context
774 UDFReleaseIrpContext(PtrIrpContext
);
776 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
778 } // can we complete the IRP ?
783 } // end UDFCommonSetVolInfo()
786 This sets Volume Label
790 IN PtrUDFIrpContext PtrIrpContext
,
792 IN PFILE_FS_LABEL_INFORMATION Buffer
,
798 UDFPrint((" UDFSetLabelInfo: \n"));
799 if(Buffer
->VolumeLabelLength
> UDF_VOL_LABEL_LEN
*sizeof(WCHAR
)) {
800 // Too long Volume Label... NT doesn't like it
801 UDFPrint((" UDFSetLabelInfo: STATUS_INVALID_VOLUME_LABEL\n"));
802 return STATUS_INVALID_VOLUME_LABEL
;
805 if(Vcb
->VolIdent
.Buffer
) MyFreePool__(Vcb
->VolIdent
.Buffer
);
806 Vcb
->VolIdent
.Buffer
= (PWCHAR
)MyAllocatePool__(NonPagedPool
, Buffer
->VolumeLabelLength
+sizeof(WCHAR
));
807 if(!Vcb
->VolIdent
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
809 Vcb
->VolIdent
.Length
= (USHORT
)Buffer
->VolumeLabelLength
;
810 Vcb
->VolIdent
.MaximumLength
= (USHORT
)Buffer
->VolumeLabelLength
+sizeof(WCHAR
);
811 RtlCopyMemory(Vcb
->VolIdent
.Buffer
, &(Buffer
->VolumeLabel
), Buffer
->VolumeLabelLength
);
812 Vcb
->VolIdent
.Buffer
[Buffer
->VolumeLabelLength
/sizeof(WCHAR
)] = 0;
815 UDFPrint((" UDFSetLabelInfo: OK\n"));
816 return STATUS_SUCCESS
;
817 } // end UDFSetLabelInfo ()
819 #endif //UDF_READ_ONLY_BUILD