[KERNEL32]
[reactos.git] / reactos / dll / win32 / kernel32 / client / file / volume.c
index 3759e1e..847caf1 100644 (file)
@@ -1,12 +1,13 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
- * FILE:            lib/kernel32/file/volume.c
+ * FILE:            dll/win32/kernel32/client/file/volume.c
  * PURPOSE:         File volume functions
  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
  *                  Erik Bos, Alexandre Julliard :
  *                      GetLogicalDriveStringsA,
  *                      GetLogicalDriveStringsW, GetLogicalDrives
+ *                  Pierre Schweitzer (pierre@reactos.org)
  * UPDATE HISTORY:
  *                  Created 01/11/98
  */
 #include <debug.h>
 DEBUG_CHANNEL(kernel32file);
 
-#define MAX_DOS_DRIVES 26
-
-
-static HANDLE
-InternalOpenDirW(LPCWSTR DirName,
-                BOOLEAN Write)
+HANDLE
+WINAPI
+InternalOpenDirW(IN LPCWSTR DirName,
+                 IN BOOLEAN Write)
 {
-  UNICODE_STRING NtPathU;
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  NTSTATUS errCode;
-  IO_STATUS_BLOCK IoStatusBlock;
-  HANDLE hFile;
-
-  if (!RtlDosPathNameToNtPathName_U(DirName,
-                                   &NtPathU,
-                                   NULL,
-                                   NULL))
+    UNICODE_STRING NtPathU;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS errCode;
+    IO_STATUS_BLOCK IoStatusBlock;
+    HANDLE hFile;
+
+    if (!RtlDosPathNameToNtPathName_U(DirName, &NtPathU, NULL, NULL))
     {
-       WARN("Invalid path\n");
-       SetLastError(ERROR_BAD_PATHNAME);
-       return INVALID_HANDLE_VALUE;
+        WARN("Invalid path\n");
+        SetLastError(ERROR_BAD_PATHNAME);
+        return INVALID_HANDLE_VALUE;
     }
 
     InitializeObjectAttributes(&ObjectAttributes,
-                              &NtPathU,
-                              OBJ_CASE_INSENSITIVE,
-                              NULL,
-                              NULL);
-
-    errCode = NtCreateFile (&hFile,
-                           Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ,
-                           &ObjectAttributes,
-                           &IoStatusBlock,
-                           NULL,
-                           0,
-                           FILE_SHARE_READ|FILE_SHARE_WRITE,
-                           FILE_OPEN,
-                           0,
-                           NULL,
-                           0);
-
-    RtlFreeHeap(RtlGetProcessHeap(),
-                0,
-                NtPathU.Buffer);
+                               &NtPathU,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    errCode = NtCreateFile(&hFile,
+                           Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ,
+                           &ObjectAttributes,
+                           &IoStatusBlock,
+                           NULL,
+                           0,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE,
+                           FILE_OPEN,
+                           0,
+                           NULL,
+                           0);
+
+    RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer);
 
     if (!NT_SUCCESS(errCode))
     {
-       BaseSetLastNTError (errCode);
-       return INVALID_HANDLE_VALUE;
+        BaseSetLastNTError(errCode);
+        return INVALID_HANDLE_VALUE;
     }
+
     return hFile;
 }
 
-
 /*
  * @implemented
  */
-/* Synced to Wine-2008/12/28 */
-DWORD WINAPI
-GetLogicalDriveStringsA(DWORD nBufferLength,
-                       LPSTR lpBuffer)
-{
-   DWORD drive, count;
-   DWORD dwDriveMap;
-   LPSTR p;
-
-   dwDriveMap = GetLogicalDrives();
-
-   for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
-     {
-       if (dwDriveMap & (1<<drive))
-          count++;
-     }
-
-
-   if ((count * 4) + 1 > nBufferLength) return ((count * 4) + 1);
-
-       p = lpBuffer;
-
-       for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
-         if (dwDriveMap & (1<<drive))
-         {
-            *p++ = 'A' + (UCHAR)drive;
-            *p++ = ':';
-            *p++ = '\\';
-            *p++ = '\0';
-         }
-       *p = '\0';
+BOOL
+WINAPI
+GetVolumeInformationA(IN LPCSTR lpRootPathName,
+                      IN LPSTR lpVolumeNameBuffer,
+                      IN DWORD nVolumeNameSize,
+                      OUT LPDWORD lpVolumeSerialNumber OPTIONAL,
+                      OUT LPDWORD lpMaximumComponentLength OPTIONAL,
+                      OUT LPDWORD lpFileSystemFlags OPTIONAL,
+                      OUT LPSTR lpFileSystemNameBuffer OPTIONAL,
+                      IN DWORD nFileSystemNameSize)
+{
+    BOOL Ret;
+    NTSTATUS Status;
+    PUNICODE_STRING RootPathNameU;
+    ANSI_STRING VolumeName, FileSystemName;
+    UNICODE_STRING VolumeNameU, FileSystemNameU;
 
-    return (count * 4);
-}
+    /* If no root path provided, default to \ */
+    if (lpRootPathName == NULL)
+    {
+        lpRootPathName = "\\";
+    }
 
+    /* Convert root path to unicode */
+    RootPathNameU = Basep8BitStringToStaticUnicodeString(lpRootPathName);
+    if (RootPathNameU == NULL)
+    {
+        return FALSE;
+    }
 
-/*
- * @implemented
- */
-/* Synced to Wine-2008/12/28 */
-DWORD WINAPI
-GetLogicalDriveStringsW(DWORD nBufferLength,
-                       LPWSTR lpBuffer)
-{
-   DWORD drive, count;
-   DWORD dwDriveMap;
-   LPWSTR p;
+    /* Init all our STRINGS (U/A) */
+    VolumeNameU.Buffer = NULL;
+    VolumeNameU.MaximumLength = 0;
+    FileSystemNameU.Buffer = NULL;
+    FileSystemNameU.MaximumLength = 0;
 
-   dwDriveMap = GetLogicalDrives();
+    VolumeName.Buffer = lpVolumeNameBuffer;
+    VolumeName.MaximumLength = nVolumeNameSize + 1;
+    FileSystemName.Buffer = lpFileSystemNameBuffer;
+    FileSystemName.MaximumLength = nFileSystemNameSize + 1;
 
-   for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++)
-     {
-       if (dwDriveMap & (1<<drive))
-          count++;
-     }
+    /* Assume failure for now */
+    Ret = FALSE;
 
-    if ((count * 4) + 1 > nBufferLength) return ((count * 4) + 1);
+    /* If caller wants volume name, allocate a buffer to receive it */
+    if (lpVolumeNameBuffer != NULL)
+    {
+        VolumeNameU.MaximumLength = sizeof(WCHAR) * (nVolumeNameSize + 1);
+        VolumeNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+                                                VolumeNameU.MaximumLength);
+        if (VolumeNameU.Buffer == NULL)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto CleanAndQuit;
+        }
+    }
 
-    p = lpBuffer;
-    for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
-        if (dwDriveMap & (1<<drive))
+    /* If caller wants file system name, allocate a buffer to receive it */
+    if (lpFileSystemNameBuffer != NULL)
+    {
+        FileSystemNameU.MaximumLength = sizeof(WCHAR) * (nVolumeNameSize + 1);
+        FileSystemNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+                                                    FileSystemNameU.MaximumLength);
+        if (FileSystemNameU.Buffer == NULL)
         {
-            *p++ = (WCHAR)('A' + drive);
-            *p++ = (WCHAR)':';
-            *p++ = (WCHAR)'\\';
-            *p++ = (WCHAR)'\0';
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto CleanAndQuit;
         }
-    *p = (WCHAR)'\0';
+    }
 
-    return (count * 4);
-}
+    /* Call W */
+    Ret = GetVolumeInformationW(RootPathNameU->Buffer,  VolumeNameU.Buffer,
+                                nVolumeNameSize, lpVolumeSerialNumber,
+                                lpMaximumComponentLength, lpFileSystemFlags,
+                                FileSystemNameU.Buffer, nFileSystemNameSize);
+    /* If it succeed, convert back to ANSI */
+    if (Ret)
+    {
+        if (lpVolumeNameBuffer != NULL)
+        {
+            RtlInitUnicodeString(&VolumeNameU, VolumeNameU.Buffer);
+            Status = RtlUnicodeStringToAnsiString(&VolumeName, &VolumeNameU, FALSE);
+            if (!NT_SUCCESS(Status))
+            {
+                BaseSetLastNTError(Status);
+                Ret = FALSE;
 
+                goto CleanAndQuit;
+            }
+        }
 
-/*
- * @implemented
- */
-/* Synced to Wine-? */
-DWORD WINAPI
-GetLogicalDrives(VOID)
-{
-       NTSTATUS Status;
-       PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo;
-
-       /* Get the Device Map for this Process */
-       Status = NtQueryInformationProcess(NtCurrentProcess(),
-                                          ProcessDeviceMap,
-                                          &ProcessDeviceMapInfo,
-                                          sizeof(ProcessDeviceMapInfo),
-                                          NULL);
-
-       /* Return the Drive Map */
-       if (!NT_SUCCESS(Status))
-       {
-               BaseSetLastNTError(Status);
-               return 0;
-       }
-
-        return ProcessDeviceMapInfo.Query.DriveMap;
-}
+        if (lpFileSystemNameBuffer != NULL)
+        {
+            RtlInitUnicodeString(&FileSystemNameU, FileSystemNameU.Buffer);
+            Status = RtlUnicodeStringToAnsiString(&FileSystemName, &FileSystemNameU, FALSE);
+            if (!NT_SUCCESS(Status))
+            {
+                BaseSetLastNTError(Status);
+                Ret = FALSE;
 
+                goto CleanAndQuit;
+            }
+        }
+    }
 
-/*
- * @implemented
- */
-BOOL WINAPI
-GetDiskFreeSpaceA (
-       LPCSTR  lpRootPathName,
-       LPDWORD lpSectorsPerCluster,
-       LPDWORD lpBytesPerSector,
-       LPDWORD lpNumberOfFreeClusters,
-       LPDWORD lpTotalNumberOfClusters
-       )
-{
-   PWCHAR RootPathNameW=NULL;
+    /* Clean and quit */
+CleanAndQuit:
+    if (VolumeNameU.Buffer != NULL)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameU.Buffer);
+    }
 
-   if (lpRootPathName)
-   {
-      if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
-         return FALSE;
-   }
+    if (FileSystemNameU.Buffer != NULL)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 0, FileSystemNameU.Buffer);
+    }
 
-       return GetDiskFreeSpaceW (RootPathNameW,
-                                   lpSectorsPerCluster,
-                                   lpBytesPerSector,
-                                   lpNumberOfFreeClusters,
-                                   lpTotalNumberOfClusters);
+    return Ret;
 }
 
-
 /*
  * @implemented
  */
-BOOL WINAPI
-GetDiskFreeSpaceW(
-    LPCWSTR lpRootPathName,
-    LPDWORD lpSectorsPerCluster,
-    LPDWORD lpBytesPerSector,
-    LPDWORD lpNumberOfFreeClusters,
-    LPDWORD lpTotalNumberOfClusters
-    )
+static BOOL
+IsThisARootDirectory(IN HANDLE VolumeHandle,
+                     IN PUNICODE_STRING NtPathName)
 {
-    FILE_FS_SIZE_INFORMATION FileFsSize;
+    NTSTATUS Status;
     IO_STATUS_BLOCK IoStatusBlock;
-    WCHAR RootPathName[MAX_PATH];
-    HANDLE hFile;
-    NTSTATUS errCode;
-
-    if (lpRootPathName)
-    {
-        wcsncpy (RootPathName, lpRootPathName, 3);
-    }
-    else
+    struct
     {
-        GetCurrentDirectoryW (MAX_PATH, RootPathName);
-    }
-    RootPathName[3] = 0;
+        FILE_NAME_INFORMATION;
+        WCHAR Buffer[MAX_PATH];
+    } FileNameInfo;
 
-  hFile = InternalOpenDirW(RootPathName, FALSE);
-  if (INVALID_HANDLE_VALUE == hFile)
+    /* If we have a handle, query the name */
+    if (VolumeHandle)
     {
-      SetLastError(ERROR_PATH_NOT_FOUND);
-      return FALSE;
+        Status = NtQueryInformationFile(VolumeHandle, &IoStatusBlock, &FileNameInfo, sizeof(FileNameInfo), FileNameInformation);
+        if (!NT_SUCCESS(Status))
+        {
+            return FALSE;
+        }
+
+        /* Check we properly end with a \ */
+        if (FileNameInfo.FileName[FileNameInfo.FileNameLength / sizeof(WCHAR) - 1] != L'\\')
+        {
+            return FALSE;
+        }
     }
 
-    errCode = NtQueryVolumeInformationFile(hFile,
-                                           &IoStatusBlock,
-                                           &FileFsSize,
-                                           sizeof(FILE_FS_SIZE_INFORMATION),
-                                           FileFsSizeInformation);
-    if (!NT_SUCCESS(errCode))
+    /* If we have a path */
+    if (NtPathName != NULL)
     {
-        CloseHandle(hFile);
-        BaseSetLastNTError (errCode);
-        return FALSE;
-    }
+        HANDLE LinkHandle;
+        WCHAR Buffer[512];
+        ULONG ReturnedLength;
+        UNICODE_STRING LinkTarget;
+        OBJECT_ATTRIBUTES ObjectAttributes;
 
-    if (lpSectorsPerCluster)
-        *lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit;
-    if (lpBytesPerSector)
-        *lpBytesPerSector = FileFsSize.BytesPerSector;
-    if (lpNumberOfFreeClusters)
-        *lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart;
-    if (lpTotalNumberOfClusters)
-        *lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart;
-    CloseHandle(hFile);
+        NtPathName->Length -= sizeof(WCHAR);
 
-    return TRUE;
-}
+        InitializeObjectAttributes(&ObjectAttributes, NtPathName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL, NULL);
 
+        /* Try to see whether that's a symbolic name */
+        Status = NtOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes);
+        NtPathName->Length += sizeof(WCHAR);
+        if (!NT_SUCCESS(Status))
+        {
+            return FALSE;
+        }
 
-/*
- * @implemented
- */
-BOOL WINAPI
-GetDiskFreeSpaceExA (
-       LPCSTR lpDirectoryName   OPTIONAL,
-       PULARGE_INTEGER lpFreeBytesAvailableToCaller,
-       PULARGE_INTEGER lpTotalNumberOfBytes,
-       PULARGE_INTEGER lpTotalNumberOfFreeBytes
-       )
-{
-   PWCHAR DirectoryNameW=NULL;
+        /* If so, query the target */
+        LinkTarget.Buffer = Buffer;
+        LinkTarget.Length = 0;
+        LinkTarget.MaximumLength = sizeof(Buffer);
 
-       if (lpDirectoryName)
-       {
-      if (!(DirectoryNameW = FilenameA2W(lpDirectoryName, FALSE)))
-         return FALSE;
-       }
+        Status = NtQuerySymbolicLinkObject(LinkHandle, &LinkTarget, &ReturnedLength);
+        NtClose(LinkHandle);
+        /* A root directory (NtName) is a symbolic link */
+        if (!NT_SUCCESS(Status))
+        {
+            return FALSE;
+        }
+    }
 
-   return GetDiskFreeSpaceExW (DirectoryNameW ,
-                                     lpFreeBytesAvailableToCaller,
-                                     lpTotalNumberOfBytes,
-                                     lpTotalNumberOfFreeBytes);
+    return TRUE;
 }
 
-
 /*
  * @implemented
  */
-BOOL WINAPI
-GetDiskFreeSpaceExW(
-    LPCWSTR lpDirectoryName OPTIONAL,
-    PULARGE_INTEGER lpFreeBytesAvailableToCaller,
-    PULARGE_INTEGER lpTotalNumberOfBytes,
-    PULARGE_INTEGER lpTotalNumberOfFreeBytes
-    )
-{
-    union
-    {
-        FILE_FS_SIZE_INFORMATION FsSize;
-        FILE_FS_FULL_SIZE_INFORMATION FsFullSize;
-    } FsInfo;
-    IO_STATUS_BLOCK IoStatusBlock;
-    ULARGE_INTEGER BytesPerCluster;
-    HANDLE hFile;
+BOOL
+WINAPI
+GetVolumeInformationW(IN LPCWSTR lpRootPathName,
+                      IN LPWSTR lpVolumeNameBuffer,
+                      IN DWORD nVolumeNameSize,
+                      OUT LPDWORD lpVolumeSerialNumber OPTIONAL,
+                      OUT LPDWORD lpMaximumComponentLength OPTIONAL,
+                      OUT LPDWORD lpFileSystemFlags OPTIONAL,
+                      OUT LPWSTR lpFileSystemNameBuffer OPTIONAL,
+                      IN DWORD nFileSystemNameSize)
+{
+    BOOL Ret;
     NTSTATUS Status;
+    HANDLE VolumeHandle;
+    LPCWSTR RootPathName;
+    UNICODE_STRING NtPathName;
+    IO_STATUS_BLOCK IoStatusBlock;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    PFILE_FS_VOLUME_INFORMATION VolumeInfo;
+    PFILE_FS_ATTRIBUTE_INFORMATION VolumeAttr;
+    ULONG OldMode, VolumeInfoSize, VolumeAttrSize;
 
-    if (lpDirectoryName == NULL)
-        lpDirectoryName = L"\\";
+    /* If no root path provided, default to \ */
+    if (lpRootPathName == NULL)
+    {
+        RootPathName = L"\\";
+    }
+    else
+    {
+        RootPathName = lpRootPathName;
+    }
 
-    hFile = InternalOpenDirW(lpDirectoryName, FALSE);
-    if (INVALID_HANDLE_VALUE == hFile)
+    /* Convert to NT name */
+    if (!RtlDosPathNameToNtPathName_U(RootPathName, &NtPathName, NULL, NULL))
     {
+        SetLastError(ERROR_PATH_NOT_FOUND);
         return FALSE;
     }
 
-    if (lpFreeBytesAvailableToCaller != NULL || lpTotalNumberOfBytes != NULL)
+    /* Check we really end with a backslash */
+    if (NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 1] != L'\\')
     {
-        /* To get the free space available to the user associated with the
-           current thread, try FileFsFullSizeInformation. If this is not
-           supported by the file system, fall back to FileFsSize */
-
-        Status = NtQueryVolumeInformationFile(hFile,
-                                              &IoStatusBlock,
-                                              &FsInfo.FsFullSize,
-                                              sizeof(FsInfo.FsFullSize),
-                                              FileFsFullSizeInformation);
-
-        if (NT_SUCCESS(Status))
-        {
-            /* Close the handle before returning data
-               to avoid a handle leak in case of a fault! */
-            CloseHandle(hFile);
-
-            BytesPerCluster.QuadPart =
-                FsInfo.FsFullSize.BytesPerSector * FsInfo.FsFullSize.SectorsPerAllocationUnit;
-
-            if (lpFreeBytesAvailableToCaller != NULL)
-            {
-                lpFreeBytesAvailableToCaller->QuadPart =
-                    BytesPerCluster.QuadPart * FsInfo.FsFullSize.CallerAvailableAllocationUnits.QuadPart;
-            }
-
-            if (lpTotalNumberOfBytes != NULL)
-            {
-                lpTotalNumberOfBytes->QuadPart =
-                    BytesPerCluster.QuadPart * FsInfo.FsFullSize.TotalAllocationUnits.QuadPart;
-            }
-
-            if (lpTotalNumberOfFreeBytes != NULL)
-            {
-                lpTotalNumberOfFreeBytes->QuadPart =
-                    BytesPerCluster.QuadPart * FsInfo.FsFullSize.ActualAvailableAllocationUnits.QuadPart;
-            }
-
-            return TRUE;
-        }
+        RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+        BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);
+        return FALSE;
     }
 
-    Status = NtQueryVolumeInformationFile(hFile,
-                                          &IoStatusBlock,
-                                          &FsInfo.FsSize,
-                                          sizeof(FsInfo.FsSize),
-                                          FileFsSizeInformation);
-
-    /* Close the handle before returning data
-       to avoid a handle leak in case of a fault! */
-    CloseHandle(hFile);
+    /* Try to open the received path */
+    InitializeObjectAttributes(&ObjectAttributes, &NtPathName,
+                                OBJ_CASE_INSENSITIVE,
+                                NULL, NULL);
 
+    /* No errors to the user */
+    RtlSetThreadErrorMode(RTL_SEM_FAILCRITICALERRORS, &OldMode);
+    Status = NtOpenFile(&VolumeHandle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, 0, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT);
+    RtlSetThreadErrorMode(OldMode, NULL);
     if (!NT_SUCCESS(Status))
     {
-        BaseSetLastNTError (Status);
+        RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+        BaseSetLastNTError(Status);
         return FALSE;
     }
 
-    BytesPerCluster.QuadPart =
-        FsInfo.FsSize.BytesPerSector * FsInfo.FsSize.SectorsPerAllocationUnit;
-
-    if (lpFreeBytesAvailableToCaller)
+    /* Check whether that's a root directory */
+    if (!IsThisARootDirectory(VolumeHandle, &NtPathName))
     {
-        lpFreeBytesAvailableToCaller->QuadPart =
-            BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart;
+        RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+        NtClose(VolumeHandle);
+        SetLastError(ERROR_DIR_NOT_ROOT);
+        return FALSE;
     }
 
-    if (lpTotalNumberOfBytes)
+    RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
+
+    /* Assume we don't need to query FileFsVolumeInformation */
+    VolumeInfo = NULL;
+    /* If user wants volume name, allocate a buffer to query it */
+    if (lpVolumeNameBuffer != NULL)
     {
-        lpTotalNumberOfBytes->QuadPart =
-            BytesPerCluster.QuadPart * FsInfo.FsSize.TotalAllocationUnits.QuadPart;
+        VolumeInfoSize = nVolumeNameSize + sizeof(FILE_FS_VOLUME_INFORMATION);
     }
-
-    if (lpTotalNumberOfFreeBytes)
+    /* If user just wants the serial number, allocate a dummy buffer */
+    else if (lpVolumeSerialNumber != NULL)
     {
-        lpTotalNumberOfFreeBytes->QuadPart =
-            BytesPerCluster.QuadPart * FsInfo.FsSize.AvailableAllocationUnits.QuadPart;
+        VolumeInfoSize = MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION);
+    }
+    /* Otherwise, nothing to query */
+    else
+    {
+        VolumeInfoSize = 0;
     }
 
-    return TRUE;
-}
-
-
-/*
- * @implemented
- */
-UINT WINAPI
-GetDriveTypeA(LPCSTR lpRootPathName)
-{
-   PWCHAR RootPathNameW;
-
-   if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
-      return DRIVE_UNKNOWN;
-
-   return GetDriveTypeW(RootPathNameW);
-}
-
-
-/*
- * @implemented
- */
-UINT WINAPI
-GetDriveTypeW(LPCWSTR lpRootPathName)
-{
-       FILE_FS_DEVICE_INFORMATION FileFsDevice;
-       IO_STATUS_BLOCK IoStatusBlock;
-
-       HANDLE hFile;
-       NTSTATUS errCode;
-
-       hFile = InternalOpenDirW(lpRootPathName, FALSE);
-       if (hFile == INVALID_HANDLE_VALUE)
-       {
-           return DRIVE_NO_ROOT_DIR;   /* According to WINE regression tests */
-       }
-
-       errCode = NtQueryVolumeInformationFile (hFile,
-                                               &IoStatusBlock,
-                                               &FileFsDevice,
-                                               sizeof(FILE_FS_DEVICE_INFORMATION),
-                                               FileFsDeviceInformation);
-       if (!NT_SUCCESS(errCode))
-       {
-               CloseHandle(hFile);
-               BaseSetLastNTError (errCode);
-               return 0;
-       }
-       CloseHandle(hFile);
-
-        switch (FileFsDevice.DeviceType)
+    /* If we're to query, allocate a big enough buffer */
+    if (VolumeInfoSize != 0)
+    {
+        VolumeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeInfoSize);
+        if (VolumeInfo == NULL)
         {
-               case FILE_DEVICE_CD_ROM:
-               case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
-                       return DRIVE_CDROM;
-               case FILE_DEVICE_VIRTUAL_DISK:
-                       return DRIVE_RAMDISK;
-               case FILE_DEVICE_NETWORK_FILE_SYSTEM:
-                       return DRIVE_REMOTE;
-               case FILE_DEVICE_DISK:
-               case FILE_DEVICE_DISK_FILE_SYSTEM:
-                       if (FileFsDevice.Characteristics & FILE_REMOTE_DEVICE)
-                               return DRIVE_REMOTE;
-                       if (FileFsDevice.Characteristics & FILE_REMOVABLE_MEDIA)
-                               return DRIVE_REMOVABLE;
-                       return DRIVE_FIXED;
+            NtClose(VolumeHandle);
+            BaseSetLastNTError(STATUS_NO_MEMORY);
+            return FALSE;
         }
+    }
 
-        ERR("Returning DRIVE_UNKNOWN for device type %d\n", FileFsDevice.DeviceType);
-
-       return DRIVE_UNKNOWN;
-}
-
-
-/*
- * @implemented
- */
-BOOL WINAPI
-GetVolumeInformationA(
-       LPCSTR  lpRootPathName,
-       LPSTR   lpVolumeNameBuffer,
-       DWORD   nVolumeNameSize,
-       LPDWORD lpVolumeSerialNumber,
-       LPDWORD lpMaximumComponentLength,
-       LPDWORD lpFileSystemFlags,
-       LPSTR   lpFileSystemNameBuffer,
-       DWORD   nFileSystemNameSize
-       )
-{
-  UNICODE_STRING FileSystemNameU;
-  UNICODE_STRING VolumeNameU = { 0, 0, NULL };
-  ANSI_STRING VolumeName;
-  ANSI_STRING FileSystemName;
-  PWCHAR RootPathNameW;
-  BOOL Result;
-
-  if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE)))
-     return FALSE;
-
-  if (lpVolumeNameBuffer)
+    /* Assume we don't need to query FileFsAttributeInformation */
+    VolumeAttr = NULL;
+    /* If user wants filesystem name, allocate a buffer to query it */
+    if (lpFileSystemNameBuffer != NULL)
+    {
+        VolumeAttrSize = nFileSystemNameSize + sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
+    }
+    /* If user just wants max compo len or flags, allocate a dummy buffer */
+    else if (lpMaximumComponentLength != NULL || lpFileSystemFlags != NULL)
+    {
+        VolumeAttrSize = MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
+    }
+    else
     {
-      VolumeNameU.MaximumLength = (USHORT)nVolumeNameSize * sizeof(WCHAR);
-      VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
-                                           0,
-                                           VolumeNameU.MaximumLength);
-      if (VolumeNameU.Buffer == NULL)
-      {
-          goto FailNoMem;
-      }
+        VolumeAttrSize = 0;
     }
 
-  if (lpFileSystemNameBuffer)
+    /* If we're to query, allocate a big enough buffer */
+    if (VolumeAttrSize != 0)
     {
-      FileSystemNameU.Length = 0;
-      FileSystemNameU.MaximumLength = (USHORT)nFileSystemNameSize * sizeof(WCHAR);
-      FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
-                                               0,
-                                               FileSystemNameU.MaximumLength);
-      if (FileSystemNameU.Buffer == NULL)
-      {
-          if (VolumeNameU.Buffer != NULL)
-          {
-              RtlFreeHeap(RtlGetProcessHeap(),
-                          0,
-                          VolumeNameU.Buffer);
-          }
-
-FailNoMem:
-          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-          return FALSE;
-      }
+        VolumeAttr = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeAttrSize);
+        if (VolumeAttr == NULL)
+        {
+            if (VolumeInfo != NULL)
+            {
+                RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
+            }
+
+            NtClose(VolumeHandle);
+            BaseSetLastNTError(STATUS_NO_MEMORY);
+            return FALSE;
+        }
     }
 
-  Result = GetVolumeInformationW (RootPathNameW,
-                                 lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL,
-                                 nVolumeNameSize,
-                                 lpVolumeSerialNumber,
-                                 lpMaximumComponentLength,
-                                 lpFileSystemFlags,
-                                 lpFileSystemNameBuffer ? FileSystemNameU.Buffer : NULL,
-                                 nFileSystemNameSize);
+    /* Assume we'll fail */
+    Ret = FALSE;
 
-  if (Result)
+    /* If we're to query FileFsVolumeInformation, do it now! */
+    if (VolumeInfo != NULL)
     {
-      if (lpVolumeNameBuffer)
+        Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, VolumeInfo, VolumeInfoSize, FileFsVolumeInformation);
+        if (!NT_SUCCESS(Status))
         {
-          VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR);
-         VolumeName.Length = 0;
-         VolumeName.MaximumLength = (USHORT)nVolumeNameSize;
-         VolumeName.Buffer = lpVolumeNameBuffer;
-       }
-
-      if (lpFileSystemNameBuffer)
-       {
-         FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR);
-         FileSystemName.Length = 0;
-         FileSystemName.MaximumLength = (USHORT)nFileSystemNameSize;
-         FileSystemName.Buffer = lpFileSystemNameBuffer;
-       }
-
-      /* convert unicode strings to ansi (or oem) */
-      if (bIsFileApiAnsi)
-        {
-         if (lpVolumeNameBuffer)
-           {
-             RtlUnicodeStringToAnsiString (&VolumeName,
-                                           &VolumeNameU,
-                                           FALSE);
-           }
-         if (lpFileSystemNameBuffer)
-           {
-             RtlUnicodeStringToAnsiString (&FileSystemName,
-                                           &FileSystemNameU,
-                                           FALSE);
-           }
-       }
-      else
-        {
-         if (lpVolumeNameBuffer)
-           {
-             RtlUnicodeStringToOemString (&VolumeName,
-                                          &VolumeNameU,
-                                          FALSE);
-           }
-          if (lpFileSystemNameBuffer)
-           {
-             RtlUnicodeStringToOemString (&FileSystemName,
-                                          &FileSystemNameU,
-                                          FALSE);
-           }
-       }
+            BaseSetLastNTError(Status);
+            goto CleanAndQuit;
+        }
     }
 
-  if (lpVolumeNameBuffer)
+    /* If we're to query FileFsAttributeInformation, do it now! */
+    if (VolumeAttr != NULL)
     {
-      RtlFreeHeap (RtlGetProcessHeap (),
-                  0,
-                  VolumeNameU.Buffer);
+        Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, VolumeAttr, VolumeAttrSize, FileFsAttributeInformation);
+        if (!NT_SUCCESS(Status))
+        {
+            BaseSetLastNTError(Status);
+            goto CleanAndQuit;
+        }
     }
-  if (lpFileSystemNameBuffer)
+
+    /* If user wants volume name */
+    if (lpVolumeNameBuffer != NULL)
     {
-      RtlFreeHeap (RtlGetProcessHeap (),
-                  0,
-                  FileSystemNameU.Buffer);
+        /* Check its buffer can hold it (+ 0) */
+        if (VolumeInfo->VolumeLabelLength >= nVolumeNameSize)
+        {
+            SetLastError(ERROR_BAD_LENGTH);
+            goto CleanAndQuit;
+        }
+
+        /* Copy and zero */
+        RtlCopyMemory(lpVolumeNameBuffer, VolumeInfo->VolumeLabel, VolumeInfo->VolumeLabelLength);
+        lpVolumeNameBuffer[VolumeInfo->VolumeLabelLength / sizeof(WCHAR)] = UNICODE_NULL;
     }
 
-  return Result;
-}
+    /* If user wants wants serial number, return it */
+    if (lpVolumeSerialNumber != NULL)
+    {
+        *lpVolumeSerialNumber = VolumeInfo->VolumeSerialNumber;
+    }
 
-#define FS_VOLUME_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION))
+    /* If user wants filesystem name */
+    if (lpFileSystemNameBuffer != NULL)
+    {
+        /* Check its buffer can hold it (+ 0) */
+        if (VolumeAttr->FileSystemNameLength >= nFileSystemNameSize)
+        {
+            SetLastError(ERROR_BAD_LENGTH);
+            goto CleanAndQuit;
+        }
 
-#define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
+        /* Copy and zero */
+        RtlCopyMemory(lpFileSystemNameBuffer, VolumeAttr->FileSystemName, VolumeAttr->FileSystemNameLength);
+        lpFileSystemNameBuffer[VolumeAttr->FileSystemNameLength / sizeof(WCHAR)] = UNICODE_NULL;
+    }
 
-/*
- * @implemented
- */
-BOOL WINAPI
-GetVolumeInformationW(
-    LPCWSTR lpRootPathName,
-    LPWSTR lpVolumeNameBuffer,
-    DWORD nVolumeNameSize,
-    LPDWORD lpVolumeSerialNumber,
-    LPDWORD lpMaximumComponentLength,
-    LPDWORD lpFileSystemFlags,
-    LPWSTR lpFileSystemNameBuffer,
-    DWORD nFileSystemNameSize
-    )
-{
-  PFILE_FS_VOLUME_INFORMATION FileFsVolume;
-  PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
-  IO_STATUS_BLOCK IoStatusBlock;
-  WCHAR RootPathName[MAX_PATH];
-  UCHAR Buffer[max(FS_VOLUME_BUFFER_SIZE, FS_ATTRIBUTE_BUFFER_SIZE)];
-
-  HANDLE hFile;
-  NTSTATUS errCode;
-
-  FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer;
-  FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
-
-  TRACE("FileFsVolume %p\n", FileFsVolume);
-  TRACE("FileFsAttribute %p\n", FileFsAttribute);
-
-  if (!lpRootPathName || !wcscmp(lpRootPathName, L""))
-  {
-      GetCurrentDirectoryW (MAX_PATH, RootPathName);
-  }
-  else
-  {
-      wcsncpy (RootPathName, lpRootPathName, 3);
-  }
-  RootPathName[3] = 0;
-
-  hFile = InternalOpenDirW(RootPathName, FALSE);
-  if (hFile == INVALID_HANDLE_VALUE)
+    /* If user wants wants max compo len, return it */
+    if (lpMaximumComponentLength != NULL)
     {
-      return FALSE;
+        *lpMaximumComponentLength = VolumeAttr->MaximumComponentNameLength;
     }
 
-  TRACE("hFile: %x\n", hFile);
-  errCode = NtQueryVolumeInformationFile(hFile,
-                                         &IoStatusBlock,
-                                         FileFsVolume,
-                                         FS_VOLUME_BUFFER_SIZE,
-                                         FileFsVolumeInformation);
-  if ( !NT_SUCCESS(errCode) )
+    /* If user wants wants FS flags, return them */
+    if (lpFileSystemFlags != NULL)
     {
-      WARN("Status: %x\n", errCode);
-      CloseHandle(hFile);
-      BaseSetLastNTError (errCode);
-      return FALSE;
+        *lpFileSystemFlags = VolumeAttr->FileSystemAttributes;
     }
 
-  if (lpVolumeSerialNumber)
-    *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber;
+    /* We did it! */
+    Ret = TRUE;
 
-  if (lpVolumeNameBuffer)
-    {
-      if (nVolumeNameSize * sizeof(WCHAR) >= FileFsVolume->VolumeLabelLength + sizeof(WCHAR))
-        {
-         memcpy(lpVolumeNameBuffer,
-                FileFsVolume->VolumeLabel,
-                FileFsVolume->VolumeLabelLength);
-         lpVolumeNameBuffer[FileFsVolume->VolumeLabelLength / sizeof(WCHAR)] = 0;
-       }
-      else
-        {
-         CloseHandle(hFile);
-         SetLastError(ERROR_MORE_DATA);
-         return FALSE;
-       }
-    }
+CleanAndQuit:
+    NtClose(VolumeHandle);
 
-  errCode = NtQueryVolumeInformationFile (hFile,
-                                         &IoStatusBlock,
-                                         FileFsAttribute,
-                                         FS_ATTRIBUTE_BUFFER_SIZE,
-                                         FileFsAttributeInformation);
-  CloseHandle(hFile);
-  if (!NT_SUCCESS(errCode))
+    if (VolumeInfo != NULL)
     {
-      WARN("Status: %x\n", errCode);
-      BaseSetLastNTError (errCode);
-      return FALSE;
+        RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
     }
 
-  if (lpFileSystemFlags)
-    *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes;
-  if (lpMaximumComponentLength)
-    *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength;
-  if (lpFileSystemNameBuffer)
+    if (VolumeAttr != NULL)
     {
-      if (nFileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
-        {
-         memcpy(lpFileSystemNameBuffer,
-                FileFsAttribute->FileSystemName,
-                FileFsAttribute->FileSystemNameLength);
-         lpFileSystemNameBuffer[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0;
-       }
-      else
-        {
-         SetLastError(ERROR_MORE_DATA);
-         return FALSE;
-       }
+        RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeAttr);
     }
-  return TRUE;
-}
 
+    return Ret;
+}
 
 /*
  * @implemented
  */
 BOOL
 WINAPI
-SetVolumeLabelA (
-       LPCSTR  lpRootPathName,
-       LPCSTR  lpVolumeName /* NULL if deleting label */
-       )
+SetVolumeLabelA(IN LPCSTR lpRootPathName,
+                IN LPCSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
 {
        PWCHAR RootPathNameW;
    PWCHAR VolumeNameW = NULL;
@@ -771,15 +532,13 @@ SetVolumeLabelA (
        return Result;
 }
 
-
 /*
  * @implemented
  */
-BOOL WINAPI
-SetVolumeLabelW(
-   LPCWSTR lpRootPathName,
-   LPCWSTR lpVolumeName /* NULL if deleting label */
-   )
+BOOL
+WINAPI
+SetVolumeLabelW(IN LPCWSTR lpRootPathName,
+                IN LPCWSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
 {
    PFILE_FS_LABEL_INFORMATION LabelInfo;
    IO_STATUS_BLOCK IoStatusBlock;
@@ -834,278 +593,16 @@ SetVolumeLabelW(
    return TRUE;
 }
 
-/**
- * @name GetVolumeNameForVolumeMountPointW
- *
- * Return an unique volume name for a drive root or mount point.
- *
- * @param VolumeMountPoint
- *        Pointer to string that contains either root drive name or
- *        mount point name.
- * @param VolumeName
- *        Pointer to buffer that is filled with resulting unique
- *        volume name on success.
- * @param VolumeNameLength
- *        Size of VolumeName buffer in TCHARs.
- *
- * @return
- *     TRUE when the function succeeds and the VolumeName buffer is filled,
- *     FALSE otherwise.
- */
-
-BOOL WINAPI
-GetVolumeNameForVolumeMountPointW(
-   IN LPCWSTR VolumeMountPoint,
-   OUT LPWSTR VolumeName,
-   IN DWORD VolumeNameLength)
-{
-   UNICODE_STRING NtFileName;
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   HANDLE FileHandle;
-   IO_STATUS_BLOCK Iosb;
-   ULONG BufferLength;
-   PMOUNTDEV_NAME MountDevName;
-   PMOUNTMGR_MOUNT_POINT MountPoint;
-   ULONG MountPointSize;
-   PMOUNTMGR_MOUNT_POINTS MountPoints;
-   ULONG Index;
-   PUCHAR SymbolicLinkName;
-   BOOL Result;
-   NTSTATUS Status;
-
-   if (!VolumeMountPoint || !VolumeMountPoint[0])
-   {
-       SetLastError(ERROR_PATH_NOT_FOUND);
-       return FALSE;
-   }
-
-   /*
-    * First step is to convert the passed volume mount point name to
-    * an NT acceptable name.
-    */
-
-   if (!RtlDosPathNameToNtPathName_U(VolumeMountPoint, &NtFileName, NULL, NULL))
-   {
-      SetLastError(ERROR_PATH_NOT_FOUND);
-      return FALSE;
-   }
-
-   if (NtFileName.Length > sizeof(WCHAR) &&
-       NtFileName.Buffer[(NtFileName.Length / sizeof(WCHAR)) - 1] == '\\')
-   {
-      NtFileName.Length -= sizeof(WCHAR);
-   }
-
-   /*
-    * Query mount point device name which we will later use for determining
-    * the volume name.
-    */
-
-   InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL);
-   Status = NtOpenFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE,
-                       &ObjectAttributes, &Iosb,
-                       FILE_SHARE_READ | FILE_SHARE_WRITE,
-                       FILE_SYNCHRONOUS_IO_NONALERT);
-   RtlFreeUnicodeString(&NtFileName);
-   if (!NT_SUCCESS(Status))
-   {
-      BaseSetLastNTError(Status);
-      return FALSE;
-   }
-
-   BufferLength = sizeof(MOUNTDEV_NAME) + 50 * sizeof(WCHAR);
-   do
-   {
-      MountDevName = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
-      if (MountDevName == NULL)
-      {
-         NtClose(FileHandle);
-         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-         return FALSE;
-      }
-
-      Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb,
-                                     IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
-                                     NULL, 0, MountDevName, BufferLength);
-      if (!NT_SUCCESS(Status))
-      {
-         RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
-         if (Status == STATUS_BUFFER_OVERFLOW)
-         {
-            BufferLength = sizeof(MOUNTDEV_NAME) + MountDevName->NameLength;
-            continue;
-         }
-         else
-         {
-            NtClose(FileHandle);
-            BaseSetLastNTError(Status);
-            return FALSE;
-         }
-      }
-   }
-   while (!NT_SUCCESS(Status));
-
-   NtClose(FileHandle);
-
-   /*
-    * Get the mount point information from mount manager.
-    */
-
-   MountPointSize = MountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT);
-   MountPoint = RtlAllocateHeap(GetProcessHeap(), 0, MountPointSize);
-   if (MountPoint == NULL)
-   {
-      RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
-      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-      return FALSE;
-   }
-   RtlZeroMemory(MountPoint, sizeof(MOUNTMGR_MOUNT_POINT));
-   MountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
-   MountPoint->DeviceNameLength = MountDevName->NameLength;
-   RtlCopyMemory(MountPoint + 1, MountDevName->Name, MountDevName->NameLength);
-   RtlFreeHeap(RtlGetProcessHeap(), 0, MountDevName);
-
-   RtlInitUnicodeString(&NtFileName, L"\\??\\MountPointManager");
-   InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL);
-   Status = NtOpenFile(&FileHandle, FILE_GENERIC_READ | SYNCHRONIZE, &ObjectAttributes,
-                       &Iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
-                       FILE_SYNCHRONOUS_IO_NONALERT);
-   if (!NT_SUCCESS(Status))
-   {
-      BaseSetLastNTError(Status);
-      RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
-      return FALSE;
-   }
-
-   BufferLength = sizeof(MOUNTMGR_MOUNT_POINTS);
-   do
-   {
-      MountPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
-      if (MountPoints == NULL)
-      {
-         RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
-         NtClose(FileHandle);
-         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-         return FALSE;
-      }
-
-      Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb,
-                                     IOCTL_MOUNTMGR_QUERY_POINTS,
-                                     MountPoint, MountPointSize,
-                                     MountPoints, BufferLength);
-      if (!NT_SUCCESS(Status))
-      {
-         if (Status == STATUS_BUFFER_OVERFLOW)
-         {
-            BufferLength = MountPoints->Size;
-            RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
-            continue;
-         }
-         else if (!NT_SUCCESS(Status))
-         {
-            RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
-            NtClose(FileHandle);
-            BaseSetLastNTError(Status);
-            return FALSE;
-         }
-      }
-   }
-   while (!NT_SUCCESS(Status));
-
-   RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
-   NtClose(FileHandle);
-
-   /*
-    * Now we've gathered info about all mount points mapped to our device, so
-    * select the correct one and copy it into the output buffer.
-    */
-
-   for (Index = 0; Index < MountPoints->NumberOfMountPoints; Index++)
-   {
-      MountPoint = MountPoints->MountPoints + Index;
-      SymbolicLinkName = (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset;
-
-      /*
-       * Check for "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\"
-       * (with the last slash being optional) style symbolic links.
-       */
-
-      if (MountPoint->SymbolicLinkNameLength == 48 * sizeof(WCHAR) ||
-          (MountPoint->SymbolicLinkNameLength == 49 * sizeof(WCHAR) &&
-           SymbolicLinkName[48] == L'\\'))
-      {
-         if (RtlCompareMemory(SymbolicLinkName, L"\\??\\Volume{",
-                              11 * sizeof(WCHAR)) == 11 * sizeof(WCHAR) &&
-             SymbolicLinkName[19] == L'-' && SymbolicLinkName[24] == L'-' &&
-             SymbolicLinkName[29] == L'-' && SymbolicLinkName[34] == L'-' &&
-             SymbolicLinkName[47] == L'}')
-         {
-            if (VolumeNameLength >= MountPoint->SymbolicLinkNameLength / sizeof(WCHAR))
-            {
-               RtlCopyMemory(VolumeName,
-                             (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset,
-                             MountPoint->SymbolicLinkNameLength);
-               VolumeName[1] = L'\\';
-               Result = TRUE;
-            }
-            else
-            {
-               SetLastError(ERROR_FILENAME_EXCED_RANGE);
-               Result = FALSE;
-            }
-
-            RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
-
-            return Result;
-         }
-      }
-   }
-
-   RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
-   SetLastError(ERROR_INVALID_PARAMETER);
-
-   return FALSE;
-}
-
-/*
- * @implemented (Wine 13 sep 2008)
- */
-BOOL
-WINAPI
-GetVolumeNameForVolumeMountPointA(
-    LPCSTR lpszVolumeMountPoint,
-    LPSTR lpszVolumeName,
-    DWORD cchBufferLength
-    )
-{
-    BOOL ret;
-    WCHAR volumeW[50], *pathW = NULL;
-    DWORD len = min( sizeof(volumeW) / sizeof(WCHAR), cchBufferLength );
-
-    TRACE("(%s, %p, %x)\n", debugstr_a(lpszVolumeMountPoint), lpszVolumeName, cchBufferLength);
-
-    if (!lpszVolumeMountPoint || !(pathW = FilenameA2W( lpszVolumeMountPoint, TRUE )))
-        return FALSE;
-
-    if ((ret = GetVolumeNameForVolumeMountPointW( pathW, volumeW, len )))
-        FilenameW2A_N( lpszVolumeName, len, volumeW, -1 );
-
-    RtlFreeHeap( RtlGetProcessHeap(), 0, pathW );
-    return ret;
-}
-
 /*
  * @implemented (Wine 13 sep 2008)
  */
 HANDLE
 WINAPI
-FindFirstVolumeW(
-       LPWSTR volume,
-       DWORD len
-    )
+FindFirstVolumeW(IN LPWSTR volume,
+                 IN DWORD len)
 {
     DWORD size = 1024;
+    DWORD br;
     HANDLE mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
                               NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE );
     if (mgr == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
@@ -1123,7 +620,7 @@ FindFirstVolumeW(
         memset( &input, 0, sizeof(input) );
 
         if (!DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_POINTS, &input, sizeof(input),
-                              output, size, NULL, NULL ))
+                              output, size, &br, NULL ))
         {
             if (GetLastError() != ERROR_MORE_DATA) break;
             size = output->Size;
@@ -1149,10 +646,8 @@ FindFirstVolumeW(
  */
 HANDLE
 WINAPI
-FindFirstVolumeA(
-       LPSTR volume,
-       DWORD len
-    )
+FindFirstVolumeA(IN LPSTR volume,
+                 IN DWORD len)
 {
     WCHAR *buffer = NULL;
     HANDLE handle;
@@ -1184,9 +679,7 @@ FindFirstVolumeA(
  */
 BOOL
 WINAPI
-FindVolumeClose(
-    HANDLE hFindVolume
-    )
+FindVolumeClose(IN HANDLE hFindVolume)
 {
     return RtlFreeHeap(RtlGetProcessHeap(), 0, hFindVolume);
 }
@@ -1196,9 +689,9 @@ FindVolumeClose(
  */
 BOOL
 WINAPI
-GetVolumePathNameA(LPCSTR lpszFileName,
-                   LPSTR lpszVolumePathName,
-                   DWORD cchBufferLength)
+GetVolumePathNameA(IN LPCSTR lpszFileName,
+                   IN LPSTR lpszVolumePathName,
+                   IN DWORD cchBufferLength)
 {
     PWCHAR FileNameW = NULL;
     WCHAR VolumePathName[MAX_PATH];
@@ -1223,9 +716,9 @@ GetVolumePathNameA(LPCSTR lpszFileName,
  */
 BOOL
 WINAPI
-GetVolumePathNameW(LPCWSTR lpszFileName,
-                   LPWSTR lpszVolumePathName,
-                   DWORD cchBufferLength)
+GetVolumePathNameW(IN LPCWSTR lpszFileName,
+                   IN LPWSTR lpszVolumePathName,
+                   IN DWORD cchBufferLength)
 {
     DWORD PathLength;
     UNICODE_STRING UnicodeFilePath;
@@ -1236,6 +729,12 @@ GetVolumePathNameW(LPCWSTR lpszFileName,
     DWORD ErrorCode;
     BOOL Result = FALSE;
 
+    if (!lpszFileName || !lpszVolumePathName || !cchBufferLength)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    
     if (!(PathLength = GetFullPathNameW(lpszFileName, 0, NULL, NULL)))
     {
         return Result;
@@ -1329,57 +828,14 @@ Cleanup2:
     return Result;
 }
 
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-SetVolumeMountPointW(
-    LPCWSTR lpszVolumeMountPoint,
-    LPCWSTR lpszVolumeName
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-DeleteVolumeMountPointA(
-    LPCSTR lpszVolumeMountPoint
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-HANDLE
-WINAPI
-FindFirstVolumeMountPointA(
-    LPCSTR lpszRootPathName,
-    LPSTR lpszVolumeMountPoint,
-    DWORD cchBufferLength
-    )
-{
-    STUB;
-    return 0;
-}
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-FindNextVolumeA(HANDLE handle,
-                LPSTR volume,
-                DWORD len)
+FindNextVolumeA(IN HANDLE handle,
+                IN LPSTR volume,
+                IN DWORD len)
 {
     WCHAR *buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, len * sizeof(WCHAR));
     BOOL ret;
@@ -1395,106 +851,18 @@ FindNextVolumeA(HANDLE handle,
         if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) ret = FALSE;
     }
 
-    HeapFree( GetProcessHeap(), 0, buffer );
+    RtlFreeHeap(RtlGetProcessHeap(), 0, buffer);
     return ret;
 }
 
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-FindNextVolumeMountPointA(
-    HANDLE hFindVolumeMountPoint,
-    LPSTR lpszVolumeMountPoint,
-    DWORD cchBufferLength
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-GetVolumePathNamesForVolumeNameA(
-    LPCSTR lpszVolumeName,
-    LPSTR lpszVolumePathNames,
-    DWORD cchBufferLength,
-    PDWORD lpcchReturnLength
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-SetVolumeMountPointA(
-    LPCSTR lpszVolumeMountPoint,
-    LPCSTR lpszVolumeName
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-FindVolumeMountPointClose(
-    HANDLE hFindVolumeMountPoint
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-DeleteVolumeMountPointW(
-    LPCWSTR lpszVolumeMountPoint
-    )
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-HANDLE
-WINAPI
-FindFirstVolumeMountPointW(
-    LPCWSTR lpszRootPathName,
-    LPWSTR lpszVolumeMountPoint,
-    DWORD cchBufferLength
-    )
-{
-    STUB;
-    return 0;
-}
-
 /*
  * @implemented
  */
 BOOL
 WINAPI
-FindNextVolumeW(
-       HANDLE handle,
-       LPWSTR volume,
-       DWORD len
-    )
+FindNextVolumeW(IN HANDLE handle,
+                IN LPWSTR volume,
+                IN DWORD len)
 {
     MOUNTMGR_MOUNT_POINTS *data = handle;
 
@@ -1527,31 +895,28 @@ FindNextVolumeW(
  */
 BOOL
 WINAPI
-FindNextVolumeMountPointW(
-    HANDLE hFindVolumeMountPoint,
-    LPWSTR lpszVolumeMountPoint,
-    DWORD cchBufferLength
-    )
+GetVolumePathNamesForVolumeNameA(IN LPCSTR lpszVolumeName,
+                                 IN LPSTR lpszVolumePathNames,
+                                 IN DWORD cchBufferLength,
+                                 OUT PDWORD lpcchReturnLength)
 {
     STUB;
     return 0;
 }
 
+
 /*
  * @unimplemented
  */
 BOOL
 WINAPI
-GetVolumePathNamesForVolumeNameW(
-    LPCWSTR lpszVolumeName,
-    LPWSTR lpszVolumePathNames,
-    DWORD cchBufferLength,
-    PDWORD lpcchReturnLength
-    )
+GetVolumePathNamesForVolumeNameW(IN LPCWSTR lpszVolumeName,
+                                 IN LPWSTR lpszVolumePathNames,
+                                 IN DWORD cchBufferLength,
+                                 OUT PDWORD lpcchReturnLength)
 {
     STUB;
     return 0;
 }
 
-
 /* EOF */