windows: AFSQueryVolumeInfo exception info
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSVolumeInfo.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSVolumeInfo.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 NTSTATUS
42 AFSQueryVolumeInfo( IN PDEVICE_OBJECT LibDeviceObject,
43                     IN PIRP Irp)
44 {
45
46     NTSTATUS ntStatus = STATUS_SUCCESS;
47     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
48     IO_STACK_LOCATION *pIrpSp;
49     FS_INFORMATION_CLASS FsInformationClass;
50     void *pBuffer = NULL;
51     ULONG ulLength = 0;
52     BOOLEAN bReleaseResource = FALSE;
53     PFILE_OBJECT pFileObject = NULL;
54     AFSFcb *pFcb = NULL;
55     AFSObjectInfoCB *pObjectInfo = NULL;
56     AFSVolumeCB *pVolumeCB = NULL;
57
58     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
59
60     __try
61     {
62
63         pFileObject = pIrpSp->FileObject;
64
65         if( pFileObject == NULL)
66         {
67
68             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
69                           AFS_TRACE_LEVEL_ERROR,
70                           "AFSQueryVolumeInfo Failing request with NULL FileObject\n");
71
72             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
73         }
74
75         pFcb = (AFSFcb *)pFileObject->FsContext;
76
77         if( pFcb == NULL)
78         {
79
80             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
81                           AFS_TRACE_LEVEL_ERROR,
82                           "AFSQueryVolumeInfo Failing request with NULL Fcb\n");
83
84             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
85         }
86
87         pObjectInfo = pFcb->ObjectInformation;
88
89         if( pObjectInfo == NULL)
90         {
91
92             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
93                           AFS_TRACE_LEVEL_ERROR,
94                           "AFSQueryVolumeInfo Failing request with NULL ObjectInformation\n");
95
96             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
97         }
98
99         pVolumeCB = pObjectInfo->VolumeCB;
100
101         ASSERT( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY &&
102                 pObjectInfo->FileId.Vnode == 1);
103
104         ulLength = pIrpSp->Parameters.QueryVolume.Length;
105         FsInformationClass = pIrpSp->Parameters.QueryVolume.FsInformationClass;
106         pBuffer = Irp->AssociatedIrp.SystemBuffer;
107
108         AFSAcquireShared( pVolumeCB->VolumeLock,
109                           TRUE);
110
111         bReleaseResource = TRUE;
112
113         //
114         // Don't allow requests against IOCtl nodes
115         //
116
117         if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
118         {
119
120             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
121                           AFS_TRACE_LEVEL_ERROR,
122                           "AFSQueryVolumeInfo Failing request against PIOCtl Fcb\n");
123
124             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
125         }
126         else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
127         {
128
129             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
130                           AFS_TRACE_LEVEL_ERROR,
131                           "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n");
132
133             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
134         }
135         else if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
136         {
137
138             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
139                           AFS_TRACE_LEVEL_ERROR,
140                           "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n");
141
142             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
143         }
144
145         //
146         // Process the request
147         //
148
149         switch( FsInformationClass)
150         {
151
152             case FileFsVolumeInformation:
153             {
154
155                 ntStatus = AFSQueryFsVolumeInfo( &pVolumeCB->VolumeInformation,
156                                                  (PFILE_FS_VOLUME_INFORMATION)pBuffer,
157                                                  &ulLength);
158
159                 break;
160             }
161
162             case FileFsSizeInformation:
163             {
164
165                 ntStatus = AFSQueryFsSizeInfo( &pVolumeCB->VolumeInformation,
166                                                (PFILE_FS_SIZE_INFORMATION)pBuffer,
167                                                &ulLength);
168
169                 break;
170             }
171
172             case FileFsDeviceInformation:
173             {
174
175                 ntStatus = AFSQueryFsDeviceInfo( &pVolumeCB->VolumeInformation,
176                                                  (PFILE_FS_DEVICE_INFORMATION)pBuffer,
177                                                  &ulLength);
178
179                 break;
180             }
181
182             case FileFsAttributeInformation:
183             {
184
185                 ntStatus = AFSQueryFsAttributeInfo( &pVolumeCB->VolumeInformation,
186                                                     (PFILE_FS_ATTRIBUTE_INFORMATION)pBuffer,
187                                                     &ulLength);
188
189                 break;
190             }
191
192             case FileFsFullSizeInformation:
193             {
194
195                 ntStatus = AFSQueryFsFullSizeInfo( &pVolumeCB->VolumeInformation,
196                                                    (PFILE_FS_FULL_SIZE_INFORMATION)pBuffer,
197                                                    &ulLength);
198
199                 break;
200             }
201
202             default:
203
204                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
205                               AFS_TRACE_LEVEL_WARNING,
206                               "AFSQueryVolumeInfo Invalid class %d\n",
207                               FsInformationClass);
208
209                 ntStatus = STATUS_INVALID_PARAMETER;
210
211                 break;
212         }
213
214 try_exit:
215
216         //
217         // Setup the Irp's information field to what we actually copied in.
218         //
219
220         Irp->IoStatus.Information = pIrpSp->Parameters.QueryVolume.Length - ulLength;
221
222         if( bReleaseResource)
223         {
224
225             AFSReleaseResource( pVolumeCB->VolumeLock);
226         }
227
228         AFSCompleteRequest( Irp,
229                             ntStatus);
230
231     }
232     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
233     {
234
235         AFSDbgLogMsg( 0,
236                       0,
237                       "EXCEPTION - AFSQueryVolumeInfo FO %08lX InfoClass %d FCB %08lX ObjectInfo %08lX VolCB %08lX\n",
238                       pFileObject,
239                       FsInformationClass,
240                       pFcb,
241                       pObjectInfo,
242                       pVolumeCB);
243
244         AFSDumpTraceFilesFnc();
245     }
246
247     return ntStatus;
248 }
249
250 NTSTATUS
251 AFSSetVolumeInfo( IN PDEVICE_OBJECT DeviceObject,
252                   IN PIRP Irp)
253 {
254
255     NTSTATUS ntStatus = STATUS_SUCCESS;
256     IO_STACK_LOCATION *pIrpSp;
257
258     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
259
260     __try
261     {
262
263         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
264                       AFS_TRACE_LEVEL_WARNING,
265                       "AFSSetVolumeInfo Entry for FO %08lX\n", pIrpSp->FileObject);
266
267         AFSCompleteRequest( Irp,
268                             ntStatus);
269
270     }
271     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
272     {
273
274         AFSDbgLogMsg( 0,
275                       0,
276                       "EXCEPTION - AFSSetVolumeInfo\n");
277
278         AFSDumpTraceFilesFnc();
279     }
280
281     return ntStatus;
282 }
283
284 NTSTATUS
285 AFSQueryFsVolumeInfo( IN AFSVolumeInfoCB *VolumeInfo,
286                       IN PFILE_FS_VOLUME_INFORMATION Buffer,
287                       IN OUT PULONG Length)
288
289 {
290
291     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
292     ULONG ulCopyLength;
293
294     RtlZeroMemory( Buffer,
295                    *Length);
296
297     if( *Length >= (ULONG)sizeof( FILE_FS_VOLUME_INFORMATION))
298     {
299
300         if( *Length >= (ULONG)(FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel) + (LONG)VolumeInfo->VolumeLabelLength))
301         {
302
303             ulCopyLength = (LONG)VolumeInfo->VolumeLabelLength;
304
305             ntStatus = STATUS_SUCCESS;
306         }
307         else
308         {
309
310             ulCopyLength = *Length - FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel);
311
312             ntStatus = STATUS_BUFFER_OVERFLOW;
313         }
314
315         Buffer->VolumeCreationTime.QuadPart = VolumeInfo->VolumeCreationTime.QuadPart;
316
317         Buffer->VolumeSerialNumber = VolumeInfo->VolumeID;
318
319         Buffer->VolumeLabelLength = VolumeInfo->VolumeLabelLength;
320
321         Buffer->SupportsObjects = FALSE;
322
323         *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel);
324
325         if( ulCopyLength > 0)
326         {
327
328             RtlCopyMemory( Buffer->VolumeLabel,
329                            VolumeInfo->VolumeLabel,
330                            ulCopyLength);
331
332             *Length -= ulCopyLength;
333         }
334     }
335
336     return ntStatus;
337 }
338
339 NTSTATUS
340 AFSQueryFsSizeInfo( IN AFSVolumeInfoCB *VolumeInfo,
341                     IN PFILE_FS_SIZE_INFORMATION Buffer,
342                     IN OUT PULONG Length)
343 {
344
345     NTSTATUS ntStatus = STATUS_SUCCESS;
346     AFSFileID FileID;
347     AFSVolumeSizeInfoCB VolumeSizeInfo;
348
349     RtlZeroMemory( Buffer,
350                    *Length);
351
352     if( *Length >= sizeof( FILE_FS_SIZE_INFORMATION))
353     {
354
355         RtlZeroMemory( &FileID,
356                        sizeof(AFSFileID));
357
358         FileID.Cell = VolumeInfo->CellID;
359
360         FileID.Volume = VolumeInfo->VolumeID;
361
362         ntStatus = AFSRetrieveVolumeSizeInformation( NULL,
363                                                      &FileID,
364                                                      &VolumeSizeInfo);
365
366         if ( NT_SUCCESS( ntStatus))
367         {
368
369             Buffer->TotalAllocationUnits.QuadPart = VolumeSizeInfo.TotalAllocationUnits.QuadPart;
370
371             Buffer->AvailableAllocationUnits.QuadPart = VolumeSizeInfo.AvailableAllocationUnits.QuadPart;
372
373             Buffer->SectorsPerAllocationUnit = VolumeSizeInfo.SectorsPerAllocationUnit;
374
375             Buffer->BytesPerSector = VolumeSizeInfo.BytesPerSector;
376
377             *Length -= sizeof( FILE_FS_SIZE_INFORMATION);
378         }
379     }
380     else
381     {
382
383         ntStatus = STATUS_BUFFER_TOO_SMALL;
384     }
385
386     return ntStatus;
387 }
388
389 NTSTATUS
390 AFSQueryFsDeviceInfo( IN AFSVolumeInfoCB *VolumeInfo,
391                       IN PFILE_FS_DEVICE_INFORMATION Buffer,
392                       IN OUT PULONG Length)
393 {
394     NTSTATUS ntStatus = STATUS_SUCCESS;
395
396     RtlZeroMemory( Buffer,
397                    *Length);
398
399     if( *Length >= (LONG)sizeof( FILE_FS_DEVICE_INFORMATION))
400     {
401
402         Buffer->DeviceType = FILE_DEVICE_DISK;
403
404         Buffer->Characteristics = VolumeInfo->Characteristics;
405
406         *Length -= sizeof( FILE_FS_DEVICE_INFORMATION);
407     }
408     else
409     {
410
411         ntStatus = STATUS_BUFFER_TOO_SMALL;
412     }
413
414     return ntStatus;
415 }
416
417 NTSTATUS
418 AFSQueryFsAttributeInfo( IN AFSVolumeInfoCB *VolumeInfo,
419                          IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
420                          IN OUT PULONG Length)
421 {
422     NTSTATUS ntStatus = STATUS_SUCCESS;
423
424     RtlZeroMemory( Buffer,
425                    *Length);
426
427     if( *Length >= (LONG)(sizeof( FILE_FS_ATTRIBUTE_INFORMATION)))
428     {
429
430         Buffer->FileSystemAttributes = (FILE_CASE_PRESERVED_NAMES |
431                                         FILE_UNICODE_ON_DISK |
432                                         FILE_SUPPORTS_REPARSE_POINTS);
433
434         Buffer->MaximumComponentNameLength = 255;
435
436         Buffer->FileSystemNameLength = 18;
437
438         *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName);
439
440         if( *Length >= 18)
441         {
442
443             RtlCopyMemory( Buffer->FileSystemName,
444                            L"AFSRDRFsd",
445                            18);
446
447             *Length -= 18;
448         }
449         else
450         {
451
452             ntStatus = STATUS_BUFFER_OVERFLOW;
453         }
454     }
455     else
456     {
457
458         ntStatus = STATUS_BUFFER_TOO_SMALL;
459     }
460
461     return ntStatus;
462 }
463
464 NTSTATUS
465 AFSQueryFsFullSizeInfo( IN AFSVolumeInfoCB *VolumeInfo,
466                         IN PFILE_FS_FULL_SIZE_INFORMATION Buffer,
467                         IN OUT PULONG Length)
468 {
469
470     NTSTATUS ntStatus = STATUS_SUCCESS;
471     AFSFileID FileID;
472     AFSVolumeSizeInfoCB VolumeSizeInfo;
473
474     RtlZeroMemory( Buffer,
475                    *Length);
476
477     if( *Length >= sizeof( FILE_FS_FULL_SIZE_INFORMATION))
478     {
479
480         RtlZeroMemory( &FileID,
481                        sizeof(AFSFileID));
482
483         FileID.Cell = VolumeInfo->CellID;
484
485         FileID.Volume = VolumeInfo->VolumeID;
486
487         ntStatus = AFSRetrieveVolumeSizeInformation( NULL,
488                                                      &FileID,
489                                                      &VolumeSizeInfo);
490
491         if ( NT_SUCCESS( ntStatus))
492         {
493
494             Buffer->TotalAllocationUnits.QuadPart = VolumeSizeInfo.TotalAllocationUnits.QuadPart;
495
496             Buffer->CallerAvailableAllocationUnits.QuadPart = VolumeSizeInfo.AvailableAllocationUnits.QuadPart;
497
498             Buffer->ActualAvailableAllocationUnits.QuadPart = VolumeSizeInfo.AvailableAllocationUnits.QuadPart;
499
500             Buffer->SectorsPerAllocationUnit = VolumeSizeInfo.SectorsPerAllocationUnit;
501
502             Buffer->BytesPerSector = VolumeSizeInfo.BytesPerSector;
503
504             *Length -= sizeof( FILE_FS_FULL_SIZE_INFORMATION);
505         }
506     }
507     else
508     {
509
510         ntStatus = STATUS_BUFFER_TOO_SMALL;
511     }
512
513     return ntStatus;
514 }