2e7b45e04c89ab62294276f6be632d66c76603c2
[reactos.git] / reactos / drivers / filesystems / udfs / volinfo.cpp
1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*++
7
8 Module Name:
9
10 VolInfo.cpp
11
12 Abstract:
13
14 This module implements the volume information routines for UDF called by
15 the dispatch driver.
16
17 --*/
18
19 #include "udffs.h"
20
21 // define the file specific bug-check id
22 #define UDF_BUG_CHECK_ID UDF_FILE_VOL_INFORMATION
23
24 #ifdef DEMO
25 PWCHAR DemoVolIdent = UDF_DEMO_VOLUME_LABEL;
26 #endif // DEMO
27
28 // Local support routines
29 NTSTATUS
30 UDFQueryFsVolumeInfo (
31 IN PtrUDFIrpContext PtrIrpContext,
32 IN PVCB Vcb,
33 IN PFILE_FS_VOLUME_INFORMATION Buffer,
34 IN OUT PULONG Length
35 );
36
37 NTSTATUS
38 UDFQueryFsSizeInfo (
39 IN PtrUDFIrpContext PtrIrpContext,
40 IN PVCB Vcb,
41 IN PFILE_FS_SIZE_INFORMATION Buffer,
42 IN OUT PULONG Length
43 );
44
45 NTSTATUS
46 UDFQueryFsFullSizeInfo (
47 IN PtrUDFIrpContext PtrIrpContext,
48 IN PVCB Vcb,
49 IN PFILE_FS_FULL_SIZE_INFORMATION Buffer,
50 IN OUT PULONG Length
51 );
52
53 NTSTATUS
54 UDFQueryFsDeviceInfo (
55 IN PtrUDFIrpContext PtrIrpContext,
56 IN PVCB Vcb,
57 IN PFILE_FS_DEVICE_INFORMATION Buffer,
58 IN OUT PULONG Length
59 );
60
61 NTSTATUS
62 UDFQueryFsAttributeInfo (
63 IN PtrUDFIrpContext PtrIrpContext,
64 IN PVCB Vcb,
65 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
66 IN OUT PULONG Length
67 );
68
69 NTSTATUS
70 UDFSetLabelInfo (
71 IN PtrUDFIrpContext PtrIrpContext,
72 IN PVCB Vcb,
73 IN PFILE_FS_LABEL_INFORMATION Buffer,
74 IN OUT PULONG Length);
75
76 /*
77 This is the routine for querying volume information
78
79 Arguments:
80
81 Irp - Supplies the Irp being processed
82
83 Return Value:
84
85 NTSTATUS - The return status for the operation
86
87 */
88 NTSTATUS
89 NTAPI
90 UDFQueryVolInfo(
91 PDEVICE_OBJECT DeviceObject, // the logical volume device object
92 PIRP Irp // I/O Request Packet
93 )
94 {
95 NTSTATUS RC = STATUS_SUCCESS;
96 PtrUDFIrpContext PtrIrpContext = NULL;
97 BOOLEAN AreWeTopLevel = FALSE;
98
99 KdPrint(("UDFQueryVolInfo: \n"));
100
101 FsRtlEnterFileSystem();
102 ASSERT(DeviceObject);
103 ASSERT(Irp);
104
105 // set the top level context
106 AreWeTopLevel = UDFIsIrpTopLevel(Irp);
107 ASSERT(!UDFIsFSDevObj(DeviceObject));
108
109 _SEH2_TRY {
110
111 // get an IRP context structure and issue the request
112 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
113 if(PtrIrpContext) {
114 RC = UDFCommonQueryVolInfo(PtrIrpContext, Irp);
115 } else {
116 RC = STATUS_INSUFFICIENT_RESOURCES;
117 Irp->IoStatus.Status = RC;
118 Irp->IoStatus.Information = 0;
119 // complete the IRP
120 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
121 }
122
123 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
124
125 RC = UDFExceptionHandler(PtrIrpContext, Irp);
126
127 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
128 } _SEH2_END;
129
130 if (AreWeTopLevel) {
131 IoSetTopLevelIrp(NULL);
132 }
133
134 FsRtlExitFileSystem();
135
136 return(RC);
137 } // end UDFQueryVolInfo()
138
139 /*
140 This is the common routine for querying volume information called by both
141 the fsd and fsp threads.
142
143 Arguments:
144
145 Irp - Supplies the Irp being processed
146
147 Return Value:
148
149 NTSTATUS - The return status for the operation
150
151 */
152 NTSTATUS
153 UDFCommonQueryVolInfo(
154 PtrUDFIrpContext PtrIrpContext,
155 PIRP Irp
156 )
157 {
158 NTSTATUS RC = STATUS_INVALID_PARAMETER;
159 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
160 ULONG Length;
161 BOOLEAN CanWait = FALSE;
162 PVCB Vcb;
163 BOOLEAN PostRequest = FALSE;
164 BOOLEAN AcquiredVCB = FALSE;
165 PFILE_OBJECT FileObject = NULL;
166 // PtrUDFFCB Fcb = NULL;
167 PtrUDFCCB Ccb = NULL;
168
169 _SEH2_TRY {
170
171 KdPrint(("UDFCommonQueryVolInfo: \n"));
172
173 ASSERT(PtrIrpContext);
174 ASSERT(Irp);
175
176 PAGED_CODE();
177
178 FileObject = IrpSp->FileObject;
179 ASSERT(FileObject);
180
181 // Get the FCB and CCB pointers.
182 Ccb = (PtrUDFCCB)(FileObject->FsContext2);
183 ASSERT(Ccb);
184
185 Vcb = (PVCB)(IrpSp->DeviceObject->DeviceExtension);
186 ASSERT(Vcb);
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,
197 0,
198 NULL,
199 &(IrpSp->Parameters.QueryVolume.FsInformationClass));
200 if(!NT_SUCCESS(RC)) {
201 try_return(RC);
202 }
203 #endif //UDF_ENABLE_SECURITY
204 switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
205
206 case FileFsVolumeInformation:
207
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)) {
213 PostRequest = TRUE;
214 try_return (RC = STATUS_PENDING);
215 }
216 AcquiredVCB = TRUE;
217
218 RC = UDFQueryFsVolumeInfo( PtrIrpContext, Vcb, (PFILE_FS_VOLUME_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
219 break;
220
221 case FileFsSizeInformation:
222
223 RC = UDFQueryFsSizeInfo( PtrIrpContext, Vcb, (PFILE_FS_SIZE_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
224 break;
225
226 case FileFsDeviceInformation:
227
228 RC = UDFQueryFsDeviceInfo( PtrIrpContext, Vcb, (PFILE_FS_DEVICE_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
229 break;
230
231 case FileFsAttributeInformation:
232
233 RC = UDFQueryFsAttributeInfo( PtrIrpContext, Vcb, (PFILE_FS_ATTRIBUTE_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
234 break;
235
236 case FileFsFullSizeInformation:
237
238 RC = UDFQueryFsFullSizeInfo( PtrIrpContext, Vcb, (PFILE_FS_FULL_SIZE_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
239 break;
240
241 default:
242
243 RC = STATUS_INVALID_DEVICE_REQUEST;
244 Irp->IoStatus.Information = 0;
245 break;
246
247 }
248
249 // Set the information field to the number of bytes actually filled in
250 Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
251
252 try_exit: NOTHING;
253
254 } _SEH2_FINALLY {
255
256 if (AcquiredVCB) {
257 UDFReleaseResource(&(Vcb->VCBResource));
258 AcquiredVCB = FALSE;
259 }
260
261 // Post IRP if required
262 if (PostRequest) {
263
264 // Since, the I/O Manager gave us a system buffer, we do not
265 // need to "lock" anything.
266
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);
270
271 } else
272 if(!_SEH2_AbnormalTermination()) {
273
274 Irp->IoStatus.Status = RC;
275 // Free up the Irp Context
276 UDFReleaseIrpContext(PtrIrpContext);
277 // complete the IRP
278 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
279 } // can we complete the IRP ?
280
281 } _SEH2_END;
282
283 return RC;
284 } // end UDFCommonQueryVolInfo()
285
286
287 // Local support routine
288
289 /*
290 This routine implements the query volume info call
291
292 Arguments:
293
294 Vcb - Vcb for this volume.
295 Buffer - Supplies a pointer to the output buffer where the information
296 is to be returned
297 Length - Supplies the length of the buffer in byte. This variable
298 upon return recieves the remaining bytes free in the buffer
299 */
300 NTSTATUS
301 UDFQueryFsVolumeInfo(
302 IN PtrUDFIrpContext PtrIrpContext,
303 IN PVCB Vcb,
304 IN PFILE_FS_VOLUME_INFORMATION Buffer,
305 IN OUT PULONG Length
306 )
307 {
308 ULONG BytesToCopy;
309 NTSTATUS Status;
310
311 PAGED_CODE();
312
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;
318 #else // DEMO
319 Buffer->VolumeSerialNumber = 0xDE1770;
320 #endif // DEMO
321 KdPrint((" SN %x\n", Vcb->PhSerialNumber));
322
323 Buffer->SupportsObjects = FALSE;
324
325 *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );
326
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;
331 #else // DEMO
332 BytesToCopy = sizeof(UDF_DEMO_VOLUME_LABEL) - sizeof(WCHAR);
333 #endif // DEMO
334 Status = STATUS_SUCCESS;
335 } else {
336 BytesToCopy = *Length;
337 Status = STATUS_BUFFER_OVERFLOW;
338 }
339 // Copy over what we can of the volume label, and adjust *Length
340 Buffer->VolumeLabelLength = BytesToCopy;
341
342 if (BytesToCopy)
343 #ifndef DEMO // release
344 RtlCopyMemory( &(Buffer->VolumeLabel[0]), Vcb->VolIdent.Buffer, BytesToCopy );
345 #else // DEMO
346 RtlCopyMemory( &(Buffer->VolumeLabel[0]), DemoVolIdent, BytesToCopy );
347 #endif // DEMO
348 *Length -= BytesToCopy;
349
350 return Status;
351 } // end UDFQueryFsVolumeInfo()
352
353 /*
354 This routine implements the query volume size call.
355
356 Arguments:
357
358 Vcb - Vcb for this volume.
359 Buffer - Supplies a pointer to the output buffer where the information
360 is to be returned
361 Length - Supplies the length of the buffer in byte. This variable
362 upon return recieves the remaining bytes free in the buffer
363 */
364 NTSTATUS
365 UDFQueryFsSizeInfo(
366 IN PtrUDFIrpContext PtrIrpContext,
367 IN PVCB Vcb,
368 IN PFILE_FS_SIZE_INFORMATION Buffer,
369 IN OUT PULONG Length
370 )
371 {
372 PAGED_CODE();
373
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;
382 } else {
383 Buffer->TotalAllocationUnits.QuadPart = Vcb->TotalAllocUnits;
384 Buffer->AvailableAllocationUnits.QuadPart = Vcb->FreeAllocUnits;
385 }
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;
395
396 KdPrint((" Space: Total %I64x, Free %I64x\n",
397 Buffer->TotalAllocationUnits.QuadPart,
398 Buffer->AvailableAllocationUnits.QuadPart));
399
400 // Adjust the length variable
401 *Length -= sizeof( FILE_FS_SIZE_INFORMATION );
402 return STATUS_SUCCESS;
403 } // UDFQueryFsSizeInfo()
404
405 /*
406 This routine implements the query volume full size call.
407
408 Arguments:
409
410 Vcb - Vcb for this volume.
411 Buffer - Supplies a pointer to the output buffer where the information
412 is to be returned
413 Length - Supplies the length of the buffer in byte. This variable
414 upon return recieves the remaining bytes free in the buffer
415 */
416 NTSTATUS
417 UDFQueryFsFullSizeInfo(
418 IN PtrUDFIrpContext PtrIrpContext,
419 IN PVCB Vcb,
420 IN PFILE_FS_FULL_SIZE_INFORMATION Buffer,
421 IN OUT PULONG Length
422 )
423 {
424 PAGED_CODE();
425
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;
435 } else {
436 Buffer->TotalAllocationUnits.QuadPart = Vcb->TotalAllocUnits;
437 Buffer->CallerAvailableAllocationUnits.QuadPart =
438 Buffer->ActualAvailableAllocationUnits.QuadPart = Vcb->FreeAllocUnits;
439 }
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;
448
449 KdPrint((" Space: Total %I64x, Free %I64x\n",
450 Buffer->TotalAllocationUnits.QuadPart,
451 Buffer->ActualAvailableAllocationUnits.QuadPart));
452
453 // Adjust the length variable
454 *Length -= sizeof( FILE_FS_FULL_SIZE_INFORMATION );
455 return STATUS_SUCCESS;
456 } // UDFQueryFsSizeInfo()
457
458 /*
459 This routine implements the query volume device call.
460
461 Arguments:
462
463 Vcb - Vcb for this volume.
464 Buffer - Supplies a pointer to the output buffer where the information
465 is to be returned
466 Length - Supplies the length of the buffer in byte. This variable
467 upon return recieves the remaining bytes free in the buffer
468 */
469 NTSTATUS
470 UDFQueryFsDeviceInfo(
471 IN PtrUDFIrpContext PtrIrpContext,
472 IN PVCB Vcb,
473 IN PFILE_FS_DEVICE_INFORMATION Buffer,
474 IN OUT PULONG Length
475 )
476 {
477 PAGED_CODE();
478
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()
489
490 /*
491 This routine implements the query volume attribute call.
492
493 Arguments:
494
495 Vcb - Vcb for this volume.
496 Buffer - Supplies a pointer to the output buffer where the information
497 is to be returned
498 Length - Supplies the length of the buffer in byte. This variable
499 upon return recieves the remaining bytes free in the buffer
500 */
501 NTSTATUS
502 UDFQueryFsAttributeInfo(
503 IN PtrUDFIrpContext PtrIrpContext,
504 IN PVCB Vcb,
505 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
506 IN OUT PULONG Length
507 )
508 {
509 ULONG BytesToCopy;
510
511 NTSTATUS Status = STATUS_SUCCESS;
512 PWCHAR FsTypeTitle;
513 ULONG FsTypeTitleLen;
514
515 PAGED_CODE();
516
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) |
522 #ifdef ALLOW_SPARSE
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) |
529
530 FILE_UNICODE_ON_DISK;
531
532 Buffer->MaximumComponentNameLength = UDF_X_NAME_LEN-1;
533
534 *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
535 // Make sure we can copy full unicode characters.
536 *Length &= ~1;
537 // Determine how much of the file system name will fit.
538
539 #define UDFSetFsTitle(tit) \
540 FsTypeTitle = UDF_FS_TITLE_##tit; \
541 FsTypeTitleLen = sizeof(UDF_FS_TITLE_##tit) - sizeof(WCHAR);
542
543 switch(Vcb->TargetDeviceObject->DeviceType) {
544 case FILE_DEVICE_CD_ROM: {
545 if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
546 if(!Vcb->LastLBA) {
547 UDFSetFsTitle(BLANK);
548 } else {
549 UDFSetFsTitle(UNKNOWN);
550 }
551 } else
552 if(Vcb->CDR_Mode) {
553 if(Vcb->MediaClassEx == CdMediaClass_DVDR ||
554 Vcb->MediaClassEx == CdMediaClass_DVDRW ||
555 Vcb->MediaClassEx == CdMediaClass_DVDRAM) {
556 UDFSetFsTitle(DVDR);
557 } else
558 if(Vcb->MediaClassEx == CdMediaClass_DVDpR ||
559 Vcb->MediaClassEx == CdMediaClass_DVDpRW) {
560 UDFSetFsTitle(DVDpR);
561 } else
562 if(Vcb->MediaClassEx == CdMediaClass_DVDROM) {
563 UDFSetFsTitle(DVDROM);
564 } else
565 if(Vcb->MediaClassEx == CdMediaClass_CDROM) {
566 UDFSetFsTitle(CDROM);
567 } else {
568 UDFSetFsTitle(CDR);
569 }
570 } else {
571 if(Vcb->MediaClassEx == CdMediaClass_DVDROM ||
572 Vcb->MediaClassEx == CdMediaClass_DVDR ||
573 Vcb->MediaClassEx == CdMediaClass_DVDpR) {
574 UDFSetFsTitle(DVDROM);
575 } else
576 if(Vcb->MediaClassEx == CdMediaClass_DVDR) {
577 UDFSetFsTitle(DVDR);
578 } else
579 if(Vcb->MediaClassEx == CdMediaClass_DVDRW) {
580 UDFSetFsTitle(DVDRW);
581 } else
582 if(Vcb->MediaClassEx == CdMediaClass_DVDpRW) {
583 UDFSetFsTitle(DVDpRW);
584 } else
585 if(Vcb->MediaClassEx == CdMediaClass_DVDRAM) {
586 UDFSetFsTitle(DVDRAM);
587 } else
588 if(Vcb->MediaClassEx == CdMediaClass_CDROM) {
589 UDFSetFsTitle(CDROM);
590 } else {
591 UDFSetFsTitle(CDRW);
592 }
593 }
594 break;
595 }
596 default: {
597 UDFSetFsTitle(HDD);
598 break;
599 }
600 }
601
602 #undef UDFSetFsTitle
603
604 if (*Length >= FsTypeTitleLen) {
605 BytesToCopy = FsTypeTitleLen;
606 } else {
607 BytesToCopy = *Length;
608 Status = STATUS_BUFFER_OVERFLOW;
609 }
610
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
616 return Status;
617 } // end UDFQueryFsAttributeInfo()
618
619
620 #ifndef UDF_READ_ONLY_BUILD
621 #ifndef DEMO // release
622
623 NTSTATUS
624 NTAPI
625 UDFSetVolInfo(
626 PDEVICE_OBJECT DeviceObject, // the logical volume device object
627 PIRP Irp // I/O Request Packet
628 )
629 {
630 NTSTATUS RC = STATUS_SUCCESS;
631 PtrUDFIrpContext PtrIrpContext = NULL;
632 BOOLEAN AreWeTopLevel = FALSE;
633
634 KdPrint(("UDFSetVolInfo: \n"));
635
636 FsRtlEnterFileSystem();
637 ASSERT(DeviceObject);
638 ASSERT(Irp);
639
640 // set the top level context
641 AreWeTopLevel = UDFIsIrpTopLevel(Irp);
642 ASSERT(!UDFIsFSDevObj(DeviceObject));
643
644 _SEH2_TRY {
645
646 // get an IRP context structure and issue the request
647 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
648 ASSERT(PtrIrpContext);
649
650 RC = UDFCommonSetVolInfo(PtrIrpContext, Irp);
651
652 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
653
654 RC = UDFExceptionHandler(PtrIrpContext, Irp);
655
656 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
657 } _SEH2_END;
658
659 if (AreWeTopLevel) {
660 IoSetTopLevelIrp(NULL);
661 }
662
663 FsRtlExitFileSystem();
664
665 return(RC);
666 } // end UDFSetVolInfo()
667
668
669 /*
670 This is the common routine for setting volume information called by both
671 the fsd and fsp threads.
672 */
673 NTSTATUS
674 UDFCommonSetVolInfo(
675 PtrUDFIrpContext PtrIrpContext,
676 PIRP Irp
677 )
678 {
679 NTSTATUS RC = STATUS_INVALID_PARAMETER;
680 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
681 ULONG Length;
682 BOOLEAN CanWait = FALSE;
683 PVCB Vcb;
684 BOOLEAN PostRequest = FALSE;
685 BOOLEAN AcquiredVCB = FALSE;
686 PFILE_OBJECT FileObject = NULL;
687 // PtrUDFFCB Fcb = NULL;
688 PtrUDFCCB Ccb = NULL;
689
690 _SEH2_TRY {
691
692 KdPrint(("UDFCommonSetVolInfo: \n"));
693 ASSERT(PtrIrpContext);
694 ASSERT(Irp);
695
696 PAGED_CODE();
697
698 FileObject = IrpSp->FileObject;
699 ASSERT(FileObject);
700
701 // Get the FCB and CCB pointers.
702 Ccb = (PtrUDFCCB)(FileObject->FsContext2);
703 ASSERT(Ccb);
704
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);
708 }
709
710 Vcb = (PVCB)(IrpSp->DeviceObject->DeviceExtension);
711 ASSERT(Vcb);
712 Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
713 // Reference our input parameters to make things easier
714
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);
718 }
719
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)) {
724 PostRequest = TRUE;
725 try_return (RC = STATUS_PENDING);
726 }
727 AcquiredVCB = TRUE;
728 #ifdef UDF_ENABLE_SECURITY
729 RC = IoCheckFunctionAccess(
730 Ccb->PreviouslyGrantedAccess,
731 PtrIrpContext->MajorFunction,
732 PtrIrpContext->MinorFunction,
733 0,
734 NULL,
735 &(IrpSp->Parameters.SetVolume.FsInformationClass));
736 if(!NT_SUCCESS(RC)) {
737 try_return(RC);
738 }
739 #endif //UDF_ENABLE_SECURITY
740 switch (IrpSp->Parameters.SetVolume.FsInformationClass) {
741
742 case FileFsLabelInformation:
743
744 RC = UDFSetLabelInfo( PtrIrpContext, Vcb, (PFILE_FS_LABEL_INFORMATION)(Irp->AssociatedIrp.SystemBuffer), &Length );
745 Irp->IoStatus.Information = 0;
746 break;
747
748 default:
749
750 RC = STATUS_INVALID_DEVICE_REQUEST;
751 Irp->IoStatus.Information = 0;
752 break;
753
754 }
755
756 // Set the information field to the number of bytes actually filled in
757 Irp->IoStatus.Information = IrpSp->Parameters.SetVolume.Length - Length;
758
759 try_exit: NOTHING;
760
761 } _SEH2_FINALLY {
762
763 if (AcquiredVCB) {
764 UDFReleaseResource(&(Vcb->VCBResource));
765 AcquiredVCB = FALSE;
766 }
767
768 // Post IRP if required
769 if (PostRequest) {
770
771 // Since, the I/O Manager gave us a system buffer, we do not
772 // need to "lock" anything.
773
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);
777
778 } else {
779
780 // Can complete the IRP here if no exception was encountered
781 if (!_SEH2_AbnormalTermination()) {
782 Irp->IoStatus.Status = RC;
783
784 // Free up the Irp Context
785 UDFReleaseIrpContext(PtrIrpContext);
786 // complete the IRP
787 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
788 }
789 } // can we complete the IRP ?
790
791 } _SEH2_END;
792
793 return RC;
794 } // end UDFCommonSetVolInfo()
795
796 /*
797 This sets Volume Label
798 */
799 NTSTATUS
800 UDFSetLabelInfo (
801 IN PtrUDFIrpContext PtrIrpContext,
802 IN PVCB Vcb,
803 IN PFILE_FS_LABEL_INFORMATION Buffer,
804 IN OUT PULONG Length
805 )
806 {
807 PAGED_CODE();
808
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;
814 }
815
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;
819
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;
824 UDFSetModified(Vcb);
825
826 KdPrint((" UDFSetLabelInfo: OK\n"));
827 return STATUS_SUCCESS;
828 } // end UDFSetLabelInfo ()
829
830 #endif // DEMO
831 #endif //UDF_READ_ONLY_BUILD