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
25 PWCHAR DemoVolIdent
= UDF_DEMO_VOLUME_LABEL
;
28 // Local support routines
30 UDFQueryFsVolumeInfo (
31 IN PtrUDFIrpContext PtrIrpContext
,
33 IN PFILE_FS_VOLUME_INFORMATION Buffer
,
39 IN PtrUDFIrpContext PtrIrpContext
,
41 IN PFILE_FS_SIZE_INFORMATION Buffer
,
46 UDFQueryFsFullSizeInfo (
47 IN PtrUDFIrpContext PtrIrpContext
,
49 IN PFILE_FS_FULL_SIZE_INFORMATION Buffer
,
54 UDFQueryFsDeviceInfo (
55 IN PtrUDFIrpContext PtrIrpContext
,
57 IN PFILE_FS_DEVICE_INFORMATION Buffer
,
62 UDFQueryFsAttributeInfo (
63 IN PtrUDFIrpContext PtrIrpContext
,
65 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer
,
71 IN PtrUDFIrpContext PtrIrpContext
,
73 IN PFILE_FS_LABEL_INFORMATION Buffer
,
74 IN OUT PULONG Length
);
77 This is the routine for querying volume information
81 Irp - Supplies the Irp being processed
85 NTSTATUS - The return status for the operation
91 PDEVICE_OBJECT DeviceObject
, // the logical volume device object
92 PIRP Irp
// I/O Request Packet
95 NTSTATUS RC
= STATUS_SUCCESS
;
96 PtrUDFIrpContext PtrIrpContext
= NULL
;
97 BOOLEAN AreWeTopLevel
= FALSE
;
99 KdPrint(("UDFQueryVolInfo: \n"));
101 FsRtlEnterFileSystem();
102 ASSERT(DeviceObject
);
105 // set the top level context
106 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
107 ASSERT(!UDFIsFSDevObj(DeviceObject
));
111 // get an IRP context structure and issue the request
112 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
114 RC
= UDFCommonQueryVolInfo(PtrIrpContext
, Irp
);
116 RC
= STATUS_INSUFFICIENT_RESOURCES
;
117 Irp
->IoStatus
.Status
= RC
;
118 Irp
->IoStatus
.Information
= 0;
120 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
123 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
125 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
127 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
131 IoSetTopLevelIrp(NULL
);
134 FsRtlExitFileSystem();
137 } // end UDFQueryVolInfo()
140 This is the common routine for querying volume information called by both
141 the fsd and fsp threads.
145 Irp - Supplies the Irp being processed
149 NTSTATUS - The return status for the operation
153 UDFCommonQueryVolInfo(
154 PtrUDFIrpContext PtrIrpContext
,
158 NTSTATUS RC
= STATUS_INVALID_PARAMETER
;
159 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
161 BOOLEAN CanWait
= FALSE
;
163 BOOLEAN PostRequest
= FALSE
;
164 BOOLEAN AcquiredVCB
= FALSE
;
165 PFILE_OBJECT FileObject
= NULL
;
166 // PtrUDFFCB Fcb = NULL;
167 PtrUDFCCB Ccb
= NULL
;
171 KdPrint(("UDFCommonQueryVolInfo: \n"));
173 ASSERT(PtrIrpContext
);
178 FileObject
= IrpSp
->FileObject
;
181 // Get the FCB and CCB pointers.
182 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
185 Vcb
= (PVCB
)(IrpSp
->DeviceObject
->DeviceExtension
);
187 //Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
188 // Reference our input parameters to make things easier
189 Length
= IrpSp
->Parameters
.QueryVolume
.Length
;
190 // Acquire the Vcb for this volume.
191 CanWait
= ((PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_CAN_BLOCK
) ? TRUE
: FALSE
);
192 #ifdef UDF_ENABLE_SECURITY
193 RC
= IoCheckFunctionAccess(
194 Ccb
->PreviouslyGrantedAccess
,
195 PtrIrpContext
->MajorFunction
,
196 PtrIrpContext
->MinorFunction
,
199 &(IrpSp
->Parameters
.QueryVolume
.FsInformationClass
));
200 if(!NT_SUCCESS(RC
)) {
203 #endif //UDF_ENABLE_SECURITY
204 switch (IrpSp
->Parameters
.QueryVolume
.FsInformationClass
) {
206 case FileFsVolumeInformation
:
208 // This is the only routine we need the Vcb shared because of
209 // copying the volume label. All other routines copy fields that
210 // cannot change or are just manifest constants.
211 UDFFlushTryBreak(Vcb
);
212 if (!UDFAcquireResourceShared(&(Vcb
->VCBResource
), CanWait
)) {
214 try_return (RC
= STATUS_PENDING
);
218 RC
= UDFQueryFsVolumeInfo( PtrIrpContext
, Vcb
, (PFILE_FS_VOLUME_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
221 case FileFsSizeInformation
:
223 RC
= UDFQueryFsSizeInfo( PtrIrpContext
, Vcb
, (PFILE_FS_SIZE_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
226 case FileFsDeviceInformation
:
228 RC
= UDFQueryFsDeviceInfo( PtrIrpContext
, Vcb
, (PFILE_FS_DEVICE_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
231 case FileFsAttributeInformation
:
233 RC
= UDFQueryFsAttributeInfo( PtrIrpContext
, Vcb
, (PFILE_FS_ATTRIBUTE_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
236 case FileFsFullSizeInformation
:
238 RC
= UDFQueryFsFullSizeInfo( PtrIrpContext
, Vcb
, (PFILE_FS_FULL_SIZE_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
243 RC
= STATUS_INVALID_DEVICE_REQUEST
;
244 Irp
->IoStatus
.Information
= 0;
249 // Set the information field to the number of bytes actually filled in
250 Irp
->IoStatus
.Information
= IrpSp
->Parameters
.QueryVolume
.Length
- Length
;
257 UDFReleaseResource(&(Vcb
->VCBResource
));
261 // Post IRP if required
264 // Since, the I/O Manager gave us a system buffer, we do not
265 // need to "lock" anything.
267 // Perform the post operation which will mark the IRP pending
268 // and will return STATUS_PENDING back to us
269 RC
= UDFPostRequest(PtrIrpContext
, Irp
);
272 if(!_SEH2_AbnormalTermination()) {
274 Irp
->IoStatus
.Status
= RC
;
275 // Free up the Irp Context
276 UDFReleaseIrpContext(PtrIrpContext
);
278 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
279 } // can we complete the IRP ?
284 } // end UDFCommonQueryVolInfo()
287 // Local support routine
290 This routine implements the query volume info call
294 Vcb - Vcb for this volume.
295 Buffer - Supplies a pointer to the output buffer where the information
297 Length - Supplies the length of the buffer in byte. This variable
298 upon return recieves the remaining bytes free in the buffer
301 UDFQueryFsVolumeInfo(
302 IN PtrUDFIrpContext PtrIrpContext
,
304 IN PFILE_FS_VOLUME_INFORMATION Buffer
,
313 KdPrint((" UDFQueryFsVolumeInfo: \n"));
314 // Fill in the data from the Vcb.
315 Buffer
->VolumeCreationTime
.QuadPart
= Vcb
->VolCreationTime
;
316 #ifndef DEMO // release
317 Buffer
->VolumeSerialNumber
= Vcb
->PhSerialNumber
;
319 Buffer
->VolumeSerialNumber
= 0xDE1770;
321 KdPrint((" SN %x\n", Vcb
->PhSerialNumber
));
323 Buffer
->SupportsObjects
= FALSE
;
325 *Length
-= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION
, VolumeLabel
[0] );
327 // Check if the buffer we're given is long enough
328 if (*Length
>= (ULONG
) Vcb
->VolIdent
.Length
) {
329 #ifndef DEMO // release
330 BytesToCopy
= Vcb
->VolIdent
.Length
;
332 BytesToCopy
= sizeof(UDF_DEMO_VOLUME_LABEL
) - sizeof(WCHAR
);
334 Status
= STATUS_SUCCESS
;
336 BytesToCopy
= *Length
;
337 Status
= STATUS_BUFFER_OVERFLOW
;
339 // Copy over what we can of the volume label, and adjust *Length
340 Buffer
->VolumeLabelLength
= BytesToCopy
;
343 #ifndef DEMO // release
344 RtlCopyMemory( &(Buffer
->VolumeLabel
[0]), Vcb
->VolIdent
.Buffer
, BytesToCopy
);
346 RtlCopyMemory( &(Buffer
->VolumeLabel
[0]), DemoVolIdent
, BytesToCopy
);
348 *Length
-= BytesToCopy
;
351 } // end UDFQueryFsVolumeInfo()
354 This routine implements the query volume size call.
358 Vcb - Vcb for this volume.
359 Buffer - Supplies a pointer to the output buffer where the information
361 Length - Supplies the length of the buffer in byte. This variable
362 upon return recieves the remaining bytes free in the buffer
366 IN PtrUDFIrpContext PtrIrpContext
,
368 IN PFILE_FS_SIZE_INFORMATION Buffer
,
374 KdPrint((" UDFQueryFsSizeInfo: \n"));
375 // Fill in the output buffer.
376 if(Vcb
->BitmapModified
) {
377 Vcb
->TotalAllocUnits
=
378 Buffer
->TotalAllocationUnits
.QuadPart
= UDFGetTotalSpace(Vcb
);
379 Vcb
->FreeAllocUnits
=
380 Buffer
->AvailableAllocationUnits
.QuadPart
= UDFGetFreeSpace(Vcb
);
381 Vcb
->BitmapModified
= FALSE
;
383 Buffer
->TotalAllocationUnits
.QuadPart
= Vcb
->TotalAllocUnits
;
384 Buffer
->AvailableAllocationUnits
.QuadPart
= Vcb
->FreeAllocUnits
;
386 Vcb
->LowFreeSpace
= (Vcb
->FreeAllocUnits
< max(Vcb
->FECharge
,UDF_DEFAULT_FE_CHARGE
)*128);
387 if(!Buffer
->TotalAllocationUnits
.QuadPart
)
388 Buffer
->TotalAllocationUnits
.QuadPart
= max(1, Vcb
->LastPossibleLBA
);
389 Buffer
->SectorsPerAllocationUnit
= Vcb
->LBlockSize
/ Vcb
->BlockSize
;
390 if(!Buffer
->SectorsPerAllocationUnit
)
391 Buffer
->SectorsPerAllocationUnit
= 1;
392 Buffer
->BytesPerSector
= Vcb
->BlockSize
;
393 if(!Buffer
->BytesPerSector
)
394 Buffer
->BytesPerSector
= 2048;
396 KdPrint((" Space: Total %I64x, Free %I64x\n",
397 Buffer
->TotalAllocationUnits
.QuadPart
,
398 Buffer
->AvailableAllocationUnits
.QuadPart
));
400 // Adjust the length variable
401 *Length
-= sizeof( FILE_FS_SIZE_INFORMATION
);
402 return STATUS_SUCCESS
;
403 } // UDFQueryFsSizeInfo()
406 This routine implements the query volume full size call.
410 Vcb - Vcb for this volume.
411 Buffer - Supplies a pointer to the output buffer where the information
413 Length - Supplies the length of the buffer in byte. This variable
414 upon return recieves the remaining bytes free in the buffer
417 UDFQueryFsFullSizeInfo(
418 IN PtrUDFIrpContext PtrIrpContext
,
420 IN PFILE_FS_FULL_SIZE_INFORMATION Buffer
,
426 KdPrint((" UDFQueryFsFullSizeInfo: \n"));
427 // Fill in the output buffer.
428 if(Vcb
->BitmapModified
) {
429 Vcb
->TotalAllocUnits
=
430 Buffer
->TotalAllocationUnits
.QuadPart
= UDFGetTotalSpace(Vcb
);
431 Vcb
->FreeAllocUnits
=
432 Buffer
->CallerAvailableAllocationUnits
.QuadPart
=
433 Buffer
->ActualAvailableAllocationUnits
.QuadPart
= UDFGetFreeSpace(Vcb
);
434 Vcb
->BitmapModified
= FALSE
;
436 Buffer
->TotalAllocationUnits
.QuadPart
= Vcb
->TotalAllocUnits
;
437 Buffer
->CallerAvailableAllocationUnits
.QuadPart
=
438 Buffer
->ActualAvailableAllocationUnits
.QuadPart
= Vcb
->FreeAllocUnits
;
440 if(!Buffer
->TotalAllocationUnits
.QuadPart
)
441 Buffer
->TotalAllocationUnits
.QuadPart
= max(1, Vcb
->LastPossibleLBA
);
442 Buffer
->SectorsPerAllocationUnit
= Vcb
->LBlockSize
/ Vcb
->BlockSize
;
443 if(!Buffer
->SectorsPerAllocationUnit
)
444 Buffer
->SectorsPerAllocationUnit
= 1;
445 Buffer
->BytesPerSector
= Vcb
->BlockSize
;
446 if(!Buffer
->BytesPerSector
)
447 Buffer
->BytesPerSector
= 2048;
449 KdPrint((" Space: Total %I64x, Free %I64x\n",
450 Buffer
->TotalAllocationUnits
.QuadPart
,
451 Buffer
->ActualAvailableAllocationUnits
.QuadPart
));
453 // Adjust the length variable
454 *Length
-= sizeof( FILE_FS_FULL_SIZE_INFORMATION
);
455 return STATUS_SUCCESS
;
456 } // UDFQueryFsSizeInfo()
459 This routine implements the query volume device call.
463 Vcb - Vcb for this volume.
464 Buffer - Supplies a pointer to the output buffer where the information
466 Length - Supplies the length of the buffer in byte. This variable
467 upon return recieves the remaining bytes free in the buffer
470 UDFQueryFsDeviceInfo(
471 IN PtrUDFIrpContext PtrIrpContext
,
473 IN PFILE_FS_DEVICE_INFORMATION Buffer
,
479 KdPrint((" UDFQueryFsDeviceInfo: \n"));
480 // Update the output buffer.
481 ASSERT(! (Vcb
->TargetDeviceObject
->Characteristics
& (FILE_READ_ONLY_DEVICE
| FILE_WRITE_ONCE_MEDIA
)));
482 Buffer
->Characteristics
= Vcb
->TargetDeviceObject
->Characteristics
& ~(FILE_READ_ONLY_DEVICE
| FILE_WRITE_ONCE_MEDIA
);
483 Buffer
->DeviceType
= Vcb
->TargetDeviceObject
->DeviceType
;
484 KdPrint((" Characteristics %x, DeviceType %x\n", Buffer
->Characteristics
, Buffer
->DeviceType
));
485 // Adjust the length variable
486 *Length
-= sizeof( FILE_FS_DEVICE_INFORMATION
);
487 return STATUS_SUCCESS
;
488 } // end UDFQueryFsDeviceInfo()
491 This routine implements the query volume attribute call.
495 Vcb - Vcb for this volume.
496 Buffer - Supplies a pointer to the output buffer where the information
498 Length - Supplies the length of the buffer in byte. This variable
499 upon return recieves the remaining bytes free in the buffer
502 UDFQueryFsAttributeInfo(
503 IN PtrUDFIrpContext PtrIrpContext
,
505 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer
,
511 NTSTATUS Status
= STATUS_SUCCESS
;
513 ULONG FsTypeTitleLen
;
517 KdPrint((" UDFQueryFsAttributeInfo: \n"));
518 // Fill out the fixed portion of the buffer.
519 Buffer
->FileSystemAttributes
= FILE_CASE_SENSITIVE_SEARCH
|
520 FILE_CASE_PRESERVED_NAMES
|
521 (UDFStreamsSupported(Vcb
) ? FILE_NAMED_STREAMS
: 0) |
523 FILE_SUPPORTS_SPARSE_FILES
|
524 #endif //ALLOW_SPARSE
525 #ifdef UDF_ENABLE_SECURITY
526 (UDFNtAclSupported(Vcb
) ? FILE_PERSISTENT_ACLS
: 0) |
527 #endif //UDF_ENABLE_SECURITY
528 ((Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
) ? FILE_READ_ONLY_VOLUME
: 0) |
530 FILE_UNICODE_ON_DISK
;
532 Buffer
->MaximumComponentNameLength
= UDF_X_NAME_LEN
-1;
534 *Length
-= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION
, FileSystemName
);
535 // Make sure we can copy full unicode characters.
537 // Determine how much of the file system name will fit.
539 #define UDFSetFsTitle(tit) \
540 FsTypeTitle = UDF_FS_TITLE_##tit; \
541 FsTypeTitleLen = sizeof(UDF_FS_TITLE_##tit) - sizeof(WCHAR);
543 switch(Vcb
->TargetDeviceObject
->DeviceType
) {
544 case FILE_DEVICE_CD_ROM
: {
545 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
547 UDFSetFsTitle(BLANK
);
549 UDFSetFsTitle(UNKNOWN
);
553 if(Vcb
->MediaClassEx
== CdMediaClass_DVDR
||
554 Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
555 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
) {
558 if(Vcb
->MediaClassEx
== CdMediaClass_DVDpR
||
559 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
) {
560 UDFSetFsTitle(DVDpR
);
562 if(Vcb
->MediaClassEx
== CdMediaClass_DVDROM
) {
563 UDFSetFsTitle(DVDROM
);
565 if(Vcb
->MediaClassEx
== CdMediaClass_CDROM
) {
566 UDFSetFsTitle(CDROM
);
571 if(Vcb
->MediaClassEx
== CdMediaClass_DVDROM
||
572 Vcb
->MediaClassEx
== CdMediaClass_DVDR
||
573 Vcb
->MediaClassEx
== CdMediaClass_DVDpR
) {
574 UDFSetFsTitle(DVDROM
);
576 if(Vcb
->MediaClassEx
== CdMediaClass_DVDR
) {
579 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
) {
580 UDFSetFsTitle(DVDRW
);
582 if(Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
) {
583 UDFSetFsTitle(DVDpRW
);
585 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
) {
586 UDFSetFsTitle(DVDRAM
);
588 if(Vcb
->MediaClassEx
== CdMediaClass_CDROM
) {
589 UDFSetFsTitle(CDROM
);
604 if (*Length
>= FsTypeTitleLen
) {
605 BytesToCopy
= FsTypeTitleLen
;
607 BytesToCopy
= *Length
;
608 Status
= STATUS_BUFFER_OVERFLOW
;
611 *Length
-= BytesToCopy
;
612 // Do the file system name.
613 Buffer
->FileSystemNameLength
= BytesToCopy
;
614 RtlCopyMemory( &Buffer
->FileSystemName
[0], FsTypeTitle
, BytesToCopy
);
615 // And return to our caller
617 } // end UDFQueryFsAttributeInfo()
620 #ifndef UDF_READ_ONLY_BUILD
621 #ifndef DEMO // release
626 PDEVICE_OBJECT DeviceObject
, // the logical volume device object
627 PIRP Irp
// I/O Request Packet
630 NTSTATUS RC
= STATUS_SUCCESS
;
631 PtrUDFIrpContext PtrIrpContext
= NULL
;
632 BOOLEAN AreWeTopLevel
= FALSE
;
634 KdPrint(("UDFSetVolInfo: \n"));
636 FsRtlEnterFileSystem();
637 ASSERT(DeviceObject
);
640 // set the top level context
641 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
642 ASSERT(!UDFIsFSDevObj(DeviceObject
));
646 // get an IRP context structure and issue the request
647 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
648 ASSERT(PtrIrpContext
);
650 RC
= UDFCommonSetVolInfo(PtrIrpContext
, Irp
);
652 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
654 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
656 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
660 IoSetTopLevelIrp(NULL
);
663 FsRtlExitFileSystem();
666 } // end UDFSetVolInfo()
670 This is the common routine for setting volume information called by both
671 the fsd and fsp threads.
675 PtrUDFIrpContext PtrIrpContext
,
679 NTSTATUS RC
= STATUS_INVALID_PARAMETER
;
680 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
682 BOOLEAN CanWait
= FALSE
;
684 BOOLEAN PostRequest
= FALSE
;
685 BOOLEAN AcquiredVCB
= FALSE
;
686 PFILE_OBJECT FileObject
= NULL
;
687 // PtrUDFFCB Fcb = NULL;
688 PtrUDFCCB Ccb
= NULL
;
692 KdPrint(("UDFCommonSetVolInfo: \n"));
693 ASSERT(PtrIrpContext
);
698 FileObject
= IrpSp
->FileObject
;
701 // Get the FCB and CCB pointers.
702 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
705 if(Ccb
&& Ccb
->Fcb
&& (Ccb
->Fcb
->NodeIdentifier
.NodeType
!= UDF_NODE_TYPE_VCB
)) {
706 KdPrint((" Can't change Label on Non-volume object\n"));
707 try_return(RC
= STATUS_ACCESS_DENIED
);
710 Vcb
= (PVCB
)(IrpSp
->DeviceObject
->DeviceExtension
);
712 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
713 // Reference our input parameters to make things easier
715 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
716 KdPrint((" Can't change Label on blank volume ;)\n"));
717 try_return(RC
= STATUS_ACCESS_DENIED
);
720 Length
= IrpSp
->Parameters
.SetVolume
.Length
;
721 // Acquire the Vcb for this volume.
722 CanWait
= ((PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_CAN_BLOCK
) ? TRUE
: FALSE
);
723 if (!UDFAcquireResourceShared(&(Vcb
->VCBResource
), CanWait
)) {
725 try_return (RC
= STATUS_PENDING
);
728 #ifdef UDF_ENABLE_SECURITY
729 RC
= IoCheckFunctionAccess(
730 Ccb
->PreviouslyGrantedAccess
,
731 PtrIrpContext
->MajorFunction
,
732 PtrIrpContext
->MinorFunction
,
735 &(IrpSp
->Parameters
.SetVolume
.FsInformationClass
));
736 if(!NT_SUCCESS(RC
)) {
739 #endif //UDF_ENABLE_SECURITY
740 switch (IrpSp
->Parameters
.SetVolume
.FsInformationClass
) {
742 case FileFsLabelInformation
:
744 RC
= UDFSetLabelInfo( PtrIrpContext
, Vcb
, (PFILE_FS_LABEL_INFORMATION
)(Irp
->AssociatedIrp
.SystemBuffer
), &Length
);
745 Irp
->IoStatus
.Information
= 0;
750 RC
= STATUS_INVALID_DEVICE_REQUEST
;
751 Irp
->IoStatus
.Information
= 0;
756 // Set the information field to the number of bytes actually filled in
757 Irp
->IoStatus
.Information
= IrpSp
->Parameters
.SetVolume
.Length
- Length
;
764 UDFReleaseResource(&(Vcb
->VCBResource
));
768 // Post IRP if required
771 // Since, the I/O Manager gave us a system buffer, we do not
772 // need to "lock" anything.
774 // Perform the post operation which will mark the IRP pending
775 // and will return STATUS_PENDING back to us
776 RC
= UDFPostRequest(PtrIrpContext
, Irp
);
780 // Can complete the IRP here if no exception was encountered
781 if (!_SEH2_AbnormalTermination()) {
782 Irp
->IoStatus
.Status
= RC
;
784 // Free up the Irp Context
785 UDFReleaseIrpContext(PtrIrpContext
);
787 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
789 } // can we complete the IRP ?
794 } // end UDFCommonSetVolInfo()
797 This sets Volume Label
801 IN PtrUDFIrpContext PtrIrpContext
,
803 IN PFILE_FS_LABEL_INFORMATION Buffer
,
809 KdPrint((" UDFSetLabelInfo: \n"));
810 if(Buffer
->VolumeLabelLength
> UDF_VOL_LABEL_LEN
*sizeof(WCHAR
)) {
811 // Too long Volume Label... NT doesn't like it
812 KdPrint((" UDFSetLabelInfo: STATUS_INVALID_VOLUME_LABEL\n"));
813 return STATUS_INVALID_VOLUME_LABEL
;
816 if(Vcb
->VolIdent
.Buffer
) MyFreePool__(Vcb
->VolIdent
.Buffer
);
817 Vcb
->VolIdent
.Buffer
= (PWCHAR
)MyAllocatePool__(NonPagedPool
, Buffer
->VolumeLabelLength
+sizeof(WCHAR
));
818 if(!Vcb
->VolIdent
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
820 Vcb
->VolIdent
.Length
= (USHORT
)Buffer
->VolumeLabelLength
;
821 Vcb
->VolIdent
.MaximumLength
= (USHORT
)Buffer
->VolumeLabelLength
+sizeof(WCHAR
);
822 RtlCopyMemory(Vcb
->VolIdent
.Buffer
, &(Buffer
->VolumeLabel
), Buffer
->VolumeLabelLength
);
823 Vcb
->VolIdent
.Buffer
[Buffer
->VolumeLabelLength
/sizeof(WCHAR
)] = 0;
826 KdPrint((" UDFSetLabelInfo: OK\n"));
827 return STATUS_SUCCESS
;
828 } // end UDFSetLabelInfo ()
831 #endif //UDF_READ_ONLY_BUILD