[CDFS] Addendum to 5429771b, 6c733856 and 3c64b4cb (r75579): When the CDFS driver...
[reactos.git] / drivers / filesystems / cdfs / volinfo.c
index 0247c45..f61c975 100644 (file)
-/*
- *  ReactOS kernel
- *  Copyright (C) 2002, 2003 ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- * COPYRIGHT:        See COPYING in the top level directory
- * PROJECT:          ReactOS kernel
- * FILE:             services/fs/vfat/volume.c
- * PURPOSE:          CDROM (ISO 9660) filesystem driver
- * PROGRAMMER:       Art Yerkes
- *                   Eric Kohl
- */
-
-/* INCLUDES *****************************************************************/
-
-#include "cdfs.h"
-
-#define NDEBUG
-#include <debug.h>
-
-/* FUNCTIONS ****************************************************************/
-
-static NTSTATUS
-CdfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
-                           PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
-                           PULONG BufferLength)
+/*++
+
+Copyright (c) 1989-2000 Microsoft Corporation
+
+Module Name:
+
+    VolInfo.c
+
+Abstract:
+
+    This module implements the volume information routines for Cdfs called by
+    the dispatch driver.
+
+
+--*/
+
+#include "cdprocs.h"
+
+//
+//  The Bug check file id for this module
+//
+
+#define BugCheckFileId                   (CDFS_BUG_CHECK_VOLINFO)
+
+//
+//  Local support routines
+//
+
+_Requires_lock_held_(_Global_critical_region_)
+NTSTATUS
+CdQueryFsVolumeInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    );
+
+NTSTATUS
+CdQueryFsSizeInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_ PFILE_FS_SIZE_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    );
+
+NTSTATUS
+CdQueryFsDeviceInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    );
+
+NTSTATUS
+CdQueryFsAttributeInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    );
+
+#ifdef __REACTOS__
+#define PFILE_FS_SECTOR_SIZE_INFORMATION PVOID
+#endif
+
+NTSTATUS
+CdQueryFsSectorSizeInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, CdCommonQueryVolInfo)
+#pragma alloc_text(PAGE, CdQueryFsAttributeInfo)
+#pragma alloc_text(PAGE, CdQueryFsDeviceInfo)
+#pragma alloc_text(PAGE, CdQueryFsSizeInfo)
+#pragma alloc_text(PAGE, CdQueryFsVolumeInfo)
+#pragma alloc_text(PAGE, CdQueryFsSectorSizeInfo)
+#endif
+
+\f
+_Requires_lock_held_(_Global_critical_region_)
+NTSTATUS
+CdCommonQueryVolInfo (
+    _Inout_ PIRP_CONTEXT IrpContext,
+    _Inout_ PIRP Irp
+    )
+
+/*++
+
+Routine Description:
+
+    This is the common routine for querying volume information called by both
+    the fsd and fsp threads.
+
+Arguments:
+
+    Irp - Supplies the Irp being processed
+
+Return Value:
+
+    NTSTATUS - The return status for the operation
+
+--*/
+
 {
-    DPRINT("CdfsGetFsVolumeInformation() called\n");
-    DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
-    DPRINT("BufferLength %lu\n", *BufferLength);
+    NTSTATUS Status = STATUS_INVALID_PARAMETER;
+    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
+
+    ULONG Length;
+
+    TYPE_OF_OPEN TypeOfOpen;
+    PFCB Fcb;
+    PCCB Ccb;
+
+    PAGED_CODE();
+
+    //
+    //  Reference our input parameters to make things easier
+    //
+
+    Length = IrpSp->Parameters.QueryVolume.Length;
+
+    //
+    //  Decode the file object and fail if this an unopened file object.
+    //
+
+    TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
+
+    if (TypeOfOpen == UnopenedFileObject) {
+
+        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    //
+    //  Acquire the Vcb for this volume.
+    //
+
+    CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE );
+
+    //
+    //  Use a try-finally to facilitate cleanup.
+    //
 
-    DPRINT("Vpb %p\n", DeviceObject->Vpb);
+    _SEH2_TRY {
 
-    DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength));
-    DPRINT("LabelLength %hu\n", DeviceObject->Vpb->VolumeLabelLength);
-    DPRINT("Label %*.S\n", DeviceObject->Vpb->VolumeLabelLength / sizeof(WCHAR), DeviceObject->Vpb->VolumeLabel);
+        //
+        //  Verify the Vcb.
+        //
 
-    if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
-        return STATUS_INFO_LENGTH_MISMATCH;
+        CdVerifyVcb( IrpContext, Fcb->Vcb );
 
-    if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength))
-        return STATUS_BUFFER_OVERFLOW;
+        //
+        //  Based on the information class we'll do different actions.  Each
+        //  of the procedures that we're calling fills up the output buffer
+        //  if possible and returns true if it successfully filled the buffer
+        //  and false if it couldn't wait for any I/O to complete.
+        //
 
-    /* valid entries */
-    FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
-    FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength;
-    memcpy(FsVolumeInfo->VolumeLabel,
-        DeviceObject->Vpb->VolumeLabel,
-        DeviceObject->Vpb->VolumeLabelLength);
+        switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
 
-    /* dummy entries */
-    FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
-    FsVolumeInfo->SupportsObjects = FALSE;
+        case FileFsSizeInformation:
 
-    DPRINT("Finished FsdGetFsVolumeInformation()\n");
+            Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
+            break;
 
-    *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength);
+        case FileFsVolumeInformation:
 
-    DPRINT("BufferLength %lu\n", *BufferLength);
+            Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
+            break;
 
-    return(STATUS_SUCCESS);
+        case FileFsDeviceInformation:
+
+            Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
+            break;
+
+        case FileFsAttributeInformation:
+
+            Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
+            break;
+
+#if (NTDDI_VERSION >= NTDDI_WIN8)
+        case FileFsSectorSizeInformation:
+
+            Status = CdQueryFsSectorSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
+            break;
+#endif
+
+        /* ReactOS Change: GCC "enumeration value not handled in switch" */
+        default: break;
+        }
+
+        //
+        //  Set the information field to the number of bytes actually filled in
+        //
+
+        Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
+
+    } _SEH2_FINALLY {
+
+        //
+        //  Release the Vcb.
+        //
+
+        CdReleaseVcb( IrpContext, Fcb->Vcb );
+    } _SEH2_END;
+
+    //
+    //  Complete the request if we didn't raise.
+    //
+
+    CdCompleteRequest( IrpContext, Irp, Status );
+
+    return Status;
 }
 
+\f
+//
+//  Local support routine
+//
+
+_Requires_lock_held_(_Global_critical_region_)
+NTSTATUS
+CdQueryFsVolumeInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    )
+
+/*++
+
+Routine Description:
+
+    This routine implements the query volume info call
+
+Arguments:
+
+    Vcb - Vcb for this volume.
+
+    Buffer - Supplies a pointer to the output buffer where the information
+        is to be returned
+
+    Length - Supplies the length of the buffer in byte.  This variable
+        upon return recieves the remaining bytes free in the buffer
+
+Return Value:
+
+    NTSTATUS - Returns the status for the query
+
+--*/
 
-static NTSTATUS
-CdfsGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
-                              PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
-                              PULONG BufferLength)
 {
-    DPRINT("CdfsGetFsAttributeInformation()\n");
-    DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
-    DPRINT("BufferLength %lu\n", *BufferLength);
-    DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8));
+    ULONG BytesToCopy;
+
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    PAGED_CODE();
+
+    UNREFERENCED_PARAMETER( IrpContext );
+
+    //
+    //  Fill in the data from the Vcb.
+    //
 
-    UNREFERENCED_PARAMETER(DeviceExt);
+    Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime);
+    Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
 
-    if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
-        return STATUS_INFO_LENGTH_MISMATCH;
+    Buffer->SupportsObjects = FALSE;
 
-    if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8))
-        return STATUS_BUFFER_OVERFLOW;
+    *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );
 
-    FsAttributeInfo->FileSystemAttributes =
-        FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
-    FsAttributeInfo->MaximumComponentNameLength = 255;
-    FsAttributeInfo->FileSystemNameLength = 8;
+    //
+    //  Check if the buffer we're given is long enough
+    //
 
-    memcpy(FsAttributeInfo->FileSystemName, L"CDFS", 8);
+    if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) {
+
+        BytesToCopy = Vcb->Vpb->VolumeLabelLength;
+
+    } else {
+
+        BytesToCopy = *Length;
+
+        Status = STATUS_BUFFER_OVERFLOW;
+    }
+
+    //
+    //  Copy over what we can of the volume label, and adjust *Length
+    //
+
+    Buffer->VolumeLabelLength = BytesToCopy;
+
+    if (BytesToCopy) {
+
+        RtlCopyMemory( &Buffer->VolumeLabel[0],
+                       &Vcb->Vpb->VolumeLabel[0],
+                       BytesToCopy );
+    }
 
-    DPRINT("Finished FsdGetFsAttributeInformation()\n");
+    *Length -= BytesToCopy;
 
-    *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8);
-    DPRINT("BufferLength %lu\n", *BufferLength);
+    //
+    //  Set our status and return to our caller
+    //
 
-    return(STATUS_SUCCESS);
+    return Status;
 }
 
+\f
+//
+//  Local support routine
+//
+
+NTSTATUS
+CdQueryFsSizeInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_ PFILE_FS_SIZE_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    )
+
+/*++
+
+Routine Description:
+
+    This routine implements the query volume size call.
+
+Arguments:
+
+    Vcb - Vcb for this volume.
+
+    Buffer - Supplies a pointer to the output buffer where the information
+        is to be returned
+
+    Length - Supplies the length of the buffer in byte.  This variable
+        upon return recieves the remaining bytes free in the buffer
+
+Return Value:
+
+    NTSTATUS - Returns the status for the query
+
+--*/
 
-static NTSTATUS
-CdfsGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
-                         PFILE_FS_SIZE_INFORMATION FsSizeInfo,
-                         PULONG BufferLength)
 {
-    PDEVICE_EXTENSION DeviceExt;
-    NTSTATUS Status = STATUS_SUCCESS;
+    PAGED_CODE();
+
+    UNREFERENCED_PARAMETER( IrpContext );
 
-    DPRINT("CdfsGetFsSizeInformation()\n");
-    DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
+    //
+    //  Fill in the output buffer.
+    //
 
-    if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION))
-        return(STATUS_BUFFER_OVERFLOW);
+    Buffer->TotalAllocationUnits.QuadPart = LlSectorsFromBytes( Vcb->VolumeDasdFcb->AllocationSize.QuadPart );
 
-    DeviceExt = DeviceObject->DeviceExtension;
+    Buffer->AvailableAllocationUnits.QuadPart = 0;
+    Buffer->SectorsPerAllocationUnit = 1;
+    Buffer->BytesPerSector = SECTOR_SIZE;
 
-    FsSizeInfo->AvailableAllocationUnits.QuadPart = 0;
-    FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize;
-    FsSizeInfo->SectorsPerAllocationUnit = 1;
-    FsSizeInfo->BytesPerSector = BLOCKSIZE;
+    //
+    //  Adjust the length variable
+    //
 
-    DPRINT("Finished FsdGetFsSizeInformation()\n");
-    if (NT_SUCCESS(Status))
-        *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
+    *Length -= sizeof( FILE_FS_SIZE_INFORMATION );
 
-    return(Status);
+    //
+    //  And return success to our caller
+    //
+
+    return STATUS_SUCCESS;
 }
 
+\f
+//
+//  Local support routine
+//
+
+NTSTATUS
+CdQueryFsDeviceInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    )
+
+/*++
+
+Routine Description:
+
+    This routine implements the query volume device call.
+
+Arguments:
+
+    Vcb - Vcb for this volume.
+
+    Buffer - Supplies a pointer to the output buffer where the information
+        is to be returned
+
+    Length - Supplies the length of the buffer in byte.  This variable
+        upon return recieves the remaining bytes free in the buffer
+
+Return Value:
+
+    NTSTATUS - Returns the status for the query
+
+--*/
 
-static NTSTATUS
-CdfsGetFsDeviceInformation
-(
-    PDEVICE_OBJECT DeviceObject,
-    PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
-    PULONG BufferLength
-)
 {
-    DPRINT("CdfsGetFsDeviceInformation()\n");
-    DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
-    DPRINT("BufferLength %lu\n", *BufferLength);
-    DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
+    PAGED_CODE();
 
-    if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
-        return(STATUS_BUFFER_OVERFLOW);
+    UNREFERENCED_PARAMETER( IrpContext );
 
-    FsDeviceInfo->DeviceType = FILE_DEVICE_CD_ROM;
-    FsDeviceInfo->Characteristics = DeviceObject->Characteristics;
+    //
+    //  Update the output buffer.
+    //
 
-    DPRINT("FsdGetFsDeviceInformation() finished.\n");
+    Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
+#ifndef __REACTOS__
+    Buffer->DeviceType = FILE_DEVICE_CD_ROM;
+#else
+    Buffer->DeviceType = Vcb->TargetDeviceObject->DeviceType;
+#endif
 
-    *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
-    DPRINT("BufferLength %lu\n", *BufferLength);
+    //
+    //  Adjust the length variable
+    //
 
-    return(STATUS_SUCCESS);
+    *Length -= sizeof( FILE_FS_DEVICE_INFORMATION );
+
+    //
+    //  And return success to our caller
+    //
+
+    return STATUS_SUCCESS;
 }
 
+\f
+//
+//  Local support routine
+//
+
+NTSTATUS
+CdQueryFsAttributeInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    )
+
+/*++
+
+Routine Description:
+
+    This routine implements the query volume attribute call.
+
+Arguments:
+
+    Vcb - Vcb for this volume.
+
+    Buffer - Supplies a pointer to the output buffer where the information
+        is to be returned
+
+    Length - Supplies the length of the buffer in byte.  This variable
+        upon return recieves the remaining bytes free in the buffer
+
+Return Value:
+
+    NTSTATUS - Returns the status for the query
+
+--*/
 
-NTSTATUS NTAPI
-CdfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject,
-                           PIRP Irp)
 {
-    FS_INFORMATION_CLASS FsInformationClass;
-    PIO_STACK_LOCATION Stack;
+    ULONG BytesToCopy;
+
     NTSTATUS Status = STATUS_SUCCESS;
-    PVOID SystemBuffer;
-    ULONG BufferLength;
-
-    DPRINT("CdfsQueryVolumeInformation() called\n");
-
-    Stack = IoGetCurrentIrpStackLocation(Irp);
-    FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
-    BufferLength = Stack->Parameters.QueryVolume.Length;
-    SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
-
-    DPRINT("FsInformationClass %d\n", FsInformationClass);
-    DPRINT("SystemBuffer %p\n", SystemBuffer);
-
-    switch (FsInformationClass)
-    {
-    case FileFsVolumeInformation:
-        Status = CdfsGetFsVolumeInformation(DeviceObject,
-            SystemBuffer,
-            &BufferLength);
-        break;
-
-    case FileFsAttributeInformation:
-        Status = CdfsGetFsAttributeInformation(DeviceObject->DeviceExtension,
-            SystemBuffer,
-            &BufferLength);
-        break;
-
-    case FileFsSizeInformation:
-        Status = CdfsGetFsSizeInformation(DeviceObject,
-            SystemBuffer,
-            &BufferLength);
-        break;
-
-    case FileFsDeviceInformation:
-        Status = CdfsGetFsDeviceInformation(DeviceObject,
-            SystemBuffer,
-            &BufferLength);
-        break;
-
-    default:
-        Status = STATUS_NOT_SUPPORTED;
+
+    PAGED_CODE();
+
+    UNREFERENCED_PARAMETER( Vcb );
+
+    //
+    //  Fill out the fixed portion of the buffer.
+    //
+
+    Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH |
+                                   FILE_READ_ONLY_VOLUME |
+                                   FILE_SUPPORTS_OPEN_BY_FILE_ID;
+
+    if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
+
+        SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK );
+
+        Buffer->MaximumComponentNameLength = 110;
+
+    } else {
+
+        Buffer->MaximumComponentNameLength = 221;
+    }
+
+    *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
+
+    //
+    //  Make sure we can copy full unicode characters.
+    //
+
+    ClearFlag( *Length, 1 );
+
+    //
+    //  Determine how much of the file system name will fit.
+    //
+
+    if (*Length >= 8) {
+
+        BytesToCopy = 8;
+
+    } else {
+
+        BytesToCopy = *Length;
+        Status = STATUS_BUFFER_OVERFLOW;
     }
 
-    Irp->IoStatus.Status = Status;
-    if (NT_SUCCESS(Status))
-        Irp->IoStatus.Information =
-        Stack->Parameters.QueryVolume.Length - BufferLength;
-    else
-        Irp->IoStatus.Information = 0;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    *Length -= BytesToCopy;
+
+    //
+    //  Do the file system name.
+    //
+
+    Buffer->FileSystemNameLength = BytesToCopy;
+
+    RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy );
 
-    return(Status);
+    //
+    //  And return to our caller
+    //
+
+    return Status;
 }
 
+#if (NTDDI_VERSION >= NTDDI_WIN8)
+
+NTSTATUS
+CdQueryFsSectorSizeInfo (
+    _In_ PIRP_CONTEXT IrpContext,
+    _In_ PVCB Vcb,
+    _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
+    _Inout_ PULONG Length
+    )
+
+/*++
+
+Routine Description:
+
+    This routine implements the query sector size information call
+    This operation will work on any handle and requires no privilege.
+
+Arguments:
+
+    Vcb - Supplies the Vcb being queried
+
+    Buffer - Supplies a pointer to the output buffer where the information
+        is to be returned
+
+    Length - Supplies the length of the buffer in byte.  This variable
+        upon return receives the remaining bytes free in the buffer
+
+Return Value:
+
+    NTSTATUS - Returns the status for the query
+
+--*/
 
-NTSTATUS NTAPI
-CdfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject,
-                         PIRP Irp)
 {
-    DPRINT("CdfsSetVolumeInformation() called\n");
+    NTSTATUS Status;
+
+    PAGED_CODE();
+    UNREFERENCED_PARAMETER( IrpContext );
+
+    //
+    //  Sufficient buffer size is guaranteed by the I/O manager or the
+    //  originating kernel mode driver.
+    //
+
+    ASSERT( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
+    _Analysis_assume_( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
 
-    UNREFERENCED_PARAMETER(DeviceObject);
+    //
+    //  Retrieve the sector size information
+    //
 
-    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-    Irp->IoStatus.Information = 0;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    Status = FsRtlGetSectorSizeInformation( Vcb->Vpb->RealDevice,
+                                            Buffer );
 
-    return(STATUS_NOT_SUPPORTED);
+    //
+    //  Adjust the length variable
+    //
+
+    if (NT_SUCCESS( Status )) {
+
+        *Length -= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION );
+    }
+
+    return Status;
 }
 
-/* EOF */
+#endif
+