Windows: DOS Device VolumeInfo max name length
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSVolumeInfo.cpp
index 72c1e4c..4087465 100644 (file)
@@ -43,37 +43,66 @@ AFSQueryVolumeInfo( IN PDEVICE_OBJECT LibDeviceObject,
                     IN PIRP Irp)
 {
 
+    UNREFERENCED_PARAMETER(LibDeviceObject);
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     IO_STACK_LOCATION *pIrpSp;
-    FS_INFORMATION_CLASS FsInformationClass;
+    FS_INFORMATION_CLASS FsInformationClass = FileFsMaximumInformation;
     void *pBuffer = NULL;
     ULONG ulLength = 0;
     BOOLEAN bReleaseResource = FALSE;
+    PFILE_OBJECT pFileObject = NULL;
     AFSFcb *pFcb = NULL;
+    AFSObjectInfoCB *pObjectInfo = NULL;
     AFSVolumeCB *pVolumeCB = NULL;
+    BOOLEAN bDosDevice = FALSE;
 
     pIrpSp = IoGetCurrentIrpStackLocation( Irp);
 
     __try
     {
 
-        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
+        pFileObject = pIrpSp->FileObject;
+
+        if( pFileObject == NULL)
+        {
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSQueryVolumeInfo Failing request with NULL FileObject\n"));
+
+            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
+        }
+
+        pFcb = (AFSFcb *)pFileObject->FsContext;
 
         if( pFcb == NULL)
         {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSQueryVolumeInfo Failing request with NULL Fcb\n"));
+
+            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
+        }
+
+        pObjectInfo = pFcb->ObjectInformation;
+
+        if( pObjectInfo == NULL)
+        {
+
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueryVolumeInfo Failing request with NULL Fcb\n");
+                          "AFSQueryVolumeInfo Failing request with NULL ObjectInformation\n"));
 
             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
         }
 
-        pVolumeCB = pFcb->ObjectInformation->VolumeCB;
+        bDosDevice = pFileObject->FileName.Length > 4 * sizeof( WCHAR) &&
+            pFileObject->FileName.Buffer[0] == L'\\' &&
+            pFileObject->FileName.Buffer[1] == L';' &&
+            pFileObject->FileName.Buffer[3] == L':';
 
-        ASSERT( pVolumeCB->ObjectInformation.FileType == AFS_FILE_TYPE_DIRECTORY &&
-                pVolumeCB->ObjectInformation.FileId.Vnode == 1);
+        pVolumeCB = pObjectInfo->VolumeCB;
 
         ulLength = pIrpSp->Parameters.QueryVolume.Length;
         FsInformationClass = pIrpSp->Parameters.QueryVolume.FsInformationClass;
@@ -91,27 +120,27 @@ AFSQueryVolumeInfo( IN PDEVICE_OBJECT LibDeviceObject,
         if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
         {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueryVolumeInfo Failing request against PIOCtl Fcb\n");
+                          "AFSQueryVolumeInfo Failing request against PIOCtl Fcb\n"));
 
             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
         }
         else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
         {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n");
+                          "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n"));
 
             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
         }
         else if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
         {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n");
+                          "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n"));
 
             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
         }
@@ -128,6 +157,7 @@ AFSQueryVolumeInfo( IN PDEVICE_OBJECT LibDeviceObject,
 
                 ntStatus = AFSQueryFsVolumeInfo( &pVolumeCB->VolumeInformation,
                                                  (PFILE_FS_VOLUME_INFORMATION)pBuffer,
+                                                 bDosDevice,
                                                  &ulLength);
 
                 break;
@@ -175,10 +205,10 @@ AFSQueryVolumeInfo( IN PDEVICE_OBJECT LibDeviceObject,
 
             default:
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_WARNING,
                               "AFSQueryVolumeInfo Invalid class %d\n",
-                              FsInformationClass);
+                              FsInformationClass));
 
                 ntStatus = STATUS_INVALID_PARAMETER;
 
@@ -203,12 +233,19 @@ try_exit:
                             ntStatus);
 
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
-        AFSDbgLogMsg( 0,
+        AFSDbgTrace(( 0,
                       0,
-                      "EXCEPTION - AFSQueryVolumeInfo\n");
+                      "EXCEPTION - AFSQueryVolumeInfo FO %p InfoClass %d FCB %p ObjectInfo %p VolCB %p\n",
+                      pFileObject,
+                      FsInformationClass,
+                      pFcb,
+                      pObjectInfo,
+                      pVolumeCB));
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
@@ -219,6 +256,7 @@ AFSSetVolumeInfo( IN PDEVICE_OBJECT DeviceObject,
                   IN PIRP Irp)
 {
 
+    UNREFERENCED_PARAMETER(DeviceObject);
     NTSTATUS ntStatus = STATUS_SUCCESS;
     IO_STACK_LOCATION *pIrpSp;
 
@@ -227,20 +265,23 @@ AFSSetVolumeInfo( IN PDEVICE_OBJECT DeviceObject,
     __try
     {
 
-        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                       AFS_TRACE_LEVEL_WARNING,
-                      "AFSSetVolumeInfo Entry for FO %08lX\n", pIrpSp->FileObject);
+                      "AFSSetVolumeInfo Entry for FO %p\n",
+                      pIrpSp->FileObject));
 
         AFSCompleteRequest( Irp,
                             ntStatus);
 
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
-        AFSDbgLogMsg( 0,
+        AFSDbgTrace(( 0,
                       0,
-                      "EXCEPTION - AFSSetVolumeInfo\n");
+                      "EXCEPTION - AFSSetVolumeInfo\n"));
+
+        AFSDumpTraceFilesFnc();
     }
 
     return ntStatus;
@@ -249,12 +290,13 @@ AFSSetVolumeInfo( IN PDEVICE_OBJECT DeviceObject,
 NTSTATUS
 AFSQueryFsVolumeInfo( IN AFSVolumeInfoCB *VolumeInfo,
                       IN PFILE_FS_VOLUME_INFORMATION Buffer,
+                      IN BOOLEAN bDosDevice,
                       IN OUT PULONG Length)
 
 {
 
     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
-    ULONG ulCopyLength;
+    ULONG ulLabelLength;
 
     RtlZeroMemory( Buffer,
                    *Length);
@@ -262,18 +304,26 @@ AFSQueryFsVolumeInfo( IN AFSVolumeInfoCB *VolumeInfo,
     if( *Length >= (ULONG)sizeof( FILE_FS_VOLUME_INFORMATION))
     {
 
-        if( *Length >= (ULONG)(FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel) + (LONG)VolumeInfo->VolumeLabelLength))
+        if ( bDosDevice)
+        {
+
+            ulLabelLength = VolumeInfo->VolumeLabelLength;
+        }
+        else
         {
 
-            ulCopyLength = (LONG)VolumeInfo->VolumeLabelLength;
+            ulLabelLength = VolumeInfo->VolumeLabelLength +
+                VolumeInfo->CellLength + sizeof( WCHAR);
+        }
+
+        if( *Length >= (ULONG)(FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel) + ulLabelLength))
+        {
 
             ntStatus = STATUS_SUCCESS;
         }
         else
         {
 
-            ulCopyLength = *Length - FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel);
-
             ntStatus = STATUS_BUFFER_OVERFLOW;
         }
 
@@ -281,20 +331,50 @@ AFSQueryFsVolumeInfo( IN AFSVolumeInfoCB *VolumeInfo,
 
         Buffer->VolumeSerialNumber = VolumeInfo->VolumeID;
 
-        Buffer->VolumeLabelLength = VolumeInfo->VolumeLabelLength;
+        Buffer->VolumeLabelLength = ulLabelLength;
 
         Buffer->SupportsObjects = FALSE;
 
         *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel);
 
-        if( ulCopyLength > 0)
+        if( *Length > 0)
         {
 
-            RtlCopyMemory( Buffer->VolumeLabel,
-                           VolumeInfo->VolumeLabel,
-                           ulCopyLength);
+            if ( bDosDevice)
+            {
+
+                RtlCopyMemory( Buffer->VolumeLabel,
+                               VolumeInfo->VolumeLabel,
+                               min( *Length, VolumeInfo->VolumeLabelLength));
 
-            *Length -= ulCopyLength;
+                *Length -= min( *Length, VolumeInfo->VolumeLabelLength);
+            }
+            else
+            {
+
+                RtlCopyMemory( Buffer->VolumeLabel,
+                               VolumeInfo->Cell,
+                               min( *Length, VolumeInfo->CellLength));
+
+                *Length -= min( *Length, VolumeInfo->CellLength);
+
+                if ( *Length >= sizeof( WCHAR))
+                {
+
+                    Buffer->VolumeLabel[ VolumeInfo->CellLength / sizeof( WCHAR)] = L'#';
+
+                    *Length -= sizeof( WCHAR);
+
+                    if ( *Length > 0) {
+
+                        RtlCopyMemory( &Buffer->VolumeLabel[ (VolumeInfo->CellLength + sizeof( WCHAR)) / sizeof( WCHAR)],
+                                       VolumeInfo->VolumeLabel,
+                                       min( *Length, VolumeInfo->VolumeLabelLength));
+
+                        *Length -= min( *Length, VolumeInfo->VolumeLabelLength);
+                    }
+                }
+            }
         }
     }
 
@@ -308,6 +388,8 @@ AFSQueryFsSizeInfo( IN AFSVolumeInfoCB *VolumeInfo,
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSFileID FileID;
+    AFSVolumeSizeInfoCB VolumeSizeInfo;
 
     RtlZeroMemory( Buffer,
                    *Length);
@@ -315,15 +397,30 @@ AFSQueryFsSizeInfo( IN AFSVolumeInfoCB *VolumeInfo,
     if( *Length >= sizeof( FILE_FS_SIZE_INFORMATION))
     {
 
-        Buffer->TotalAllocationUnits.QuadPart = VolumeInfo->TotalAllocationUnits.QuadPart;
+        RtlZeroMemory( &FileID,
+                       sizeof(AFSFileID));
+
+        FileID.Cell = VolumeInfo->CellID;
 
-        Buffer->AvailableAllocationUnits.QuadPart = VolumeInfo->AvailableAllocationUnits.QuadPart;
+        FileID.Volume = VolumeInfo->VolumeID;
+
+        ntStatus = AFSRetrieveVolumeSizeInformation( NULL,
+                                                     &FileID,
+                                                     &VolumeSizeInfo);
+
+        if ( NT_SUCCESS( ntStatus))
+        {
 
-        Buffer->SectorsPerAllocationUnit = VolumeInfo->SectorsPerAllocationUnit;
+            Buffer->TotalAllocationUnits.QuadPart = VolumeSizeInfo.TotalAllocationUnits.QuadPart;
 
-        Buffer->BytesPerSector = VolumeInfo->BytesPerSector;
+            Buffer->AvailableAllocationUnits.QuadPart = VolumeSizeInfo.AvailableAllocationUnits.QuadPart;
 
-        *Length -= sizeof( FILE_FS_SIZE_INFORMATION);
+            Buffer->SectorsPerAllocationUnit = VolumeSizeInfo.SectorsPerAllocationUnit;
+
+            Buffer->BytesPerSector = VolumeSizeInfo.BytesPerSector;
+
+            *Length -= sizeof( FILE_FS_SIZE_INFORMATION);
+        }
     }
     else
     {
@@ -347,6 +444,14 @@ AFSQueryFsDeviceInfo( IN AFSVolumeInfoCB *VolumeInfo,
     if( *Length >= (LONG)sizeof( FILE_FS_DEVICE_INFORMATION))
     {
 
+        //
+        // This value is used to determine the return type of
+        // Win32 GetFileType().  Returning FILE_DEVICE_NETWORK_FILE_SYSTEM
+        // results in GetFileType returning FILE_TYPE_UNKNOWN which breaks
+        // msys-based applications.  They treat all files as character
+        // special devices instead of files.
+        //
+
         Buffer->DeviceType = FILE_DEVICE_DISK;
 
         Buffer->Characteristics = VolumeInfo->Characteristics;
@@ -375,9 +480,7 @@ AFSQueryFsAttributeInfo( IN AFSVolumeInfoCB *VolumeInfo,
     if( *Length >= (LONG)(sizeof( FILE_FS_ATTRIBUTE_INFORMATION)))
     {
 
-        Buffer->FileSystemAttributes = (FILE_CASE_PRESERVED_NAMES |
-                                        FILE_UNICODE_ON_DISK |
-                                        FILE_SUPPORTS_REPARSE_POINTS);
+        Buffer->FileSystemAttributes = VolumeInfo->FileSystemAttributes;
 
         Buffer->MaximumComponentNameLength = 255;
 
@@ -416,6 +519,8 @@ AFSQueryFsFullSizeInfo( IN AFSVolumeInfoCB *VolumeInfo,
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
+    AFSFileID FileID;
+    AFSVolumeSizeInfoCB VolumeSizeInfo;
 
     RtlZeroMemory( Buffer,
                    *Length);
@@ -423,17 +528,32 @@ AFSQueryFsFullSizeInfo( IN AFSVolumeInfoCB *VolumeInfo,
     if( *Length >= sizeof( FILE_FS_FULL_SIZE_INFORMATION))
     {
 
-        Buffer->TotalAllocationUnits.QuadPart = VolumeInfo->TotalAllocationUnits.QuadPart;
+        RtlZeroMemory( &FileID,
+                       sizeof(AFSFileID));
 
-        Buffer->CallerAvailableAllocationUnits.QuadPart = VolumeInfo->AvailableAllocationUnits.QuadPart;
+        FileID.Cell = VolumeInfo->CellID;
 
-        Buffer->ActualAvailableAllocationUnits.QuadPart = VolumeInfo->AvailableAllocationUnits.QuadPart;
+        FileID.Volume = VolumeInfo->VolumeID;
 
-        Buffer->SectorsPerAllocationUnit = VolumeInfo->SectorsPerAllocationUnit;
+        ntStatus = AFSRetrieveVolumeSizeInformation( NULL,
+                                                     &FileID,
+                                                     &VolumeSizeInfo);
 
-        Buffer->BytesPerSector = VolumeInfo->BytesPerSector;
+        if ( NT_SUCCESS( ntStatus))
+        {
 
-        *Length -= sizeof( FILE_FS_FULL_SIZE_INFORMATION);
+            Buffer->TotalAllocationUnits.QuadPart = VolumeSizeInfo.TotalAllocationUnits.QuadPart;
+
+            Buffer->CallerAvailableAllocationUnits.QuadPart = VolumeSizeInfo.AvailableAllocationUnits.QuadPart;
+
+            Buffer->ActualAvailableAllocationUnits.QuadPart = VolumeSizeInfo.AvailableAllocationUnits.QuadPart;
+
+            Buffer->SectorsPerAllocationUnit = VolumeSizeInfo.SectorsPerAllocationUnit;
+
+            Buffer->BytesPerSector = VolumeSizeInfo.BytesPerSector;
+
+            *Length -= sizeof( FILE_FS_FULL_SIZE_INFORMATION);
+        }
     }
     else
     {