- Merge from trunk up to r45543
[reactos.git] / dll / win32 / kernel32 / file / volume.c
index fa8f311..ee74d9f 100644 (file)
@@ -81,13 +81,14 @@ InternalOpenDirW(LPCWSTR DirName,
 /*
  * @implemented
  */
-/* Synced to Wine-? */
-DWORD STDCALL
+/* Synced to Wine-2008/12/28 */
+DWORD WINAPI
 GetLogicalDriveStringsA(DWORD nBufferLength,
                        LPSTR lpBuffer)
 {
    DWORD drive, count;
    DWORD dwDriveMap;
+   LPSTR p;
 
    dwDriveMap = GetLogicalDrives();
 
@@ -98,9 +99,9 @@ GetLogicalDriveStringsA(DWORD nBufferLength,
      }
 
 
-   if (count * 4 <= nBufferLength)
-     {
-       LPSTR p = lpBuffer;
+   if ((count * 4) + 1 > nBufferLength) return ((count * 4) + 1);
+
+       p = lpBuffer;
 
        for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
          if (dwDriveMap & (1<<drive))
@@ -111,7 +112,7 @@ GetLogicalDriveStringsA(DWORD nBufferLength,
             *p++ = '\0';
          }
        *p = '\0';
-     }
+
     return (count * 4);
 }
 
@@ -119,13 +120,14 @@ GetLogicalDriveStringsA(DWORD nBufferLength,
 /*
  * @implemented
  */
-/* Synced to Wine-? */
-DWORD STDCALL
+/* Synced to Wine-2008/12/28 */
+DWORD WINAPI
 GetLogicalDriveStringsW(DWORD nBufferLength,
                        LPWSTR lpBuffer)
 {
    DWORD drive, count;
    DWORD dwDriveMap;
+   LPWSTR p;
 
    dwDriveMap = GetLogicalDrives();
 
@@ -135,19 +137,19 @@ GetLogicalDriveStringsW(DWORD nBufferLength,
           count++;
      }
 
-    if (count * 4 <=  nBufferLength)
-    {
-        LPWSTR p = lpBuffer;
-        for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
-            if (dwDriveMap & (1<<drive))
-            {
-                *p++ = (WCHAR)('A' + drive);
-                *p++ = (WCHAR)':';
-                *p++ = (WCHAR)'\\';
-                *p++ = (WCHAR)'\0';
-            }
-        *p = (WCHAR)'\0';
-    }
+    if ((count * 4) + 1 > nBufferLength) return ((count * 4) + 1);
+
+    p = lpBuffer;
+    for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
+        if (dwDriveMap & (1<<drive))
+        {
+            *p++ = (WCHAR)('A' + drive);
+            *p++ = (WCHAR)':';
+            *p++ = (WCHAR)'\\';
+            *p++ = (WCHAR)'\0';
+        }
+    *p = (WCHAR)'\0';
+
     return (count * 4);
 }
 
@@ -156,7 +158,7 @@ GetLogicalDriveStringsW(DWORD nBufferLength,
  * @implemented
  */
 /* Synced to Wine-? */
-DWORD STDCALL
+DWORD WINAPI
 GetLogicalDrives(VOID)
 {
        NTSTATUS Status;
@@ -183,7 +185,7 @@ GetLogicalDrives(VOID)
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetDiskFreeSpaceA (
        LPCSTR  lpRootPathName,
        LPDWORD lpSectorsPerCluster,
@@ -211,7 +213,7 @@ GetDiskFreeSpaceA (
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetDiskFreeSpaceW(
     LPCWSTR lpRootPathName,
     LPDWORD lpSectorsPerCluster,
@@ -272,7 +274,7 @@ GetDiskFreeSpaceW(
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetDiskFreeSpaceExA (
        LPCSTR lpDirectoryName   OPTIONAL,
        PULARGE_INTEGER lpFreeBytesAvailableToCaller,
@@ -298,7 +300,7 @@ GetDiskFreeSpaceExA (
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetDiskFreeSpaceExW(
     LPCWSTR lpDirectoryName OPTIONAL,
     PULARGE_INTEGER lpFreeBytesAvailableToCaller,
@@ -412,7 +414,7 @@ GetDiskFreeSpaceExW(
 /*
  * @implemented
  */
-UINT STDCALL
+UINT WINAPI
 GetDriveTypeA(LPCSTR lpRootPathName)
 {
    PWCHAR RootPathNameW;
@@ -427,7 +429,7 @@ GetDriveTypeA(LPCSTR lpRootPathName)
 /*
  * @implemented
  */
-UINT STDCALL
+UINT WINAPI
 GetDriveTypeW(LPCWSTR lpRootPathName)
 {
        FILE_FS_DEVICE_INFORMATION FileFsDevice;
@@ -482,7 +484,7 @@ GetDriveTypeW(LPCWSTR lpRootPathName)
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetVolumeInformationA(
        LPCSTR  lpRootPathName,
        LPSTR   lpVolumeNameBuffer,
@@ -495,7 +497,7 @@ GetVolumeInformationA(
        )
 {
   UNICODE_STRING FileSystemNameU;
-  UNICODE_STRING VolumeNameU = {0};
+  UNICODE_STRING VolumeNameU = { 0, 0, NULL };
   ANSI_STRING VolumeName;
   ANSI_STRING FileSystemName;
   PWCHAR RootPathNameW;
@@ -621,7 +623,7 @@ FailNoMem:
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 GetVolumeInformationW(
     LPCWSTR lpRootPathName,
     LPWSTR lpVolumeNameBuffer,
@@ -738,7 +740,7 @@ GetVolumeInformationW(
  * @implemented
  */
 BOOL
-STDCALL
+WINAPI
 SetVolumeLabelA (
        LPCSTR  lpRootPathName,
        LPCSTR  lpVolumeName /* NULL if deleting label */
@@ -774,7 +776,7 @@ SetVolumeLabelA (
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 SetVolumeLabelW(
    LPCWSTR lpRootPathName,
    LPCWSTR lpVolumeName /* NULL if deleting label */
@@ -872,6 +874,12 @@ GetVolumeNameForVolumeMountPointW(
    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.
@@ -909,7 +917,7 @@ GetVolumeNameForVolumeMountPointW(
    BufferLength = sizeof(MOUNTDEV_NAME) + 50 * sizeof(WCHAR);
    do
    {
-      MountDevName = RtlAllocateHeap(GetProcessHeap(), 0, BufferLength);
+      MountDevName = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
       if (MountDevName == NULL)
       {
          NtClose(FileHandle);
@@ -928,7 +936,7 @@ GetVolumeNameForVolumeMountPointW(
             BufferLength = sizeof(MOUNTDEV_NAME) + MountDevName->NameLength;
             continue;
          }
-         else 
+         else
          {
             NtClose(FileHandle);
             SetLastErrorByStatus(Status);
@@ -956,27 +964,27 @@ GetVolumeNameForVolumeMountPointW(
    MountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
    MountPoint->DeviceNameLength = MountDevName->NameLength;
    RtlCopyMemory(MountPoint + 1, MountDevName->Name, MountDevName->NameLength);
-   RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
+   RtlFreeHeap(RtlGetProcessHeap(), 0, MountDevName);
 
    RtlInitUnicodeString(&NtFileName, L"\\??\\MountPointManager");
    InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL);
-   Status = NtOpenFile(&FileHandle, FILE_GENERIC_READ, &ObjectAttributes,
+   Status = NtOpenFile(&FileHandle, FILE_GENERIC_READ | SYNCHRONIZE, &ObjectAttributes,
                        &Iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
                        FILE_SYNCHRONOUS_IO_NONALERT);
    if (!NT_SUCCESS(Status))
    {
       SetLastErrorByStatus(Status);
-      RtlFreeHeap(GetProcessHeap(), 0, MountPoint);
+      RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
       return FALSE;
    }
 
    BufferLength = sizeof(MOUNTMGR_MOUNT_POINTS);
    do
    {
-      MountPoints = RtlAllocateHeap(GetProcessHeap(), 0, BufferLength);
+      MountPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
       if (MountPoints == NULL)
       {
-         RtlFreeHeap(GetProcessHeap(), 0, MountPoint);
+         RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
          NtClose(FileHandle);
          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
          return FALSE;
@@ -988,15 +996,16 @@ GetVolumeNameForVolumeMountPointW(
                                      MountPoints, BufferLength);
       if (!NT_SUCCESS(Status))
       {
-         RtlFreeHeap(GetProcessHeap(), 0, MountPoints);
          if (Status == STATUS_BUFFER_OVERFLOW)
          {
             BufferLength = MountPoints->Size;
+            RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
             continue;
          }
          else if (!NT_SUCCESS(Status))
          {
-            RtlFreeHeap(GetProcessHeap(), 0, MountPoint);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
             NtClose(FileHandle);
             SetLastErrorByStatus(Status);
             return FALSE;
@@ -1005,7 +1014,7 @@ GetVolumeNameForVolumeMountPointW(
    }
    while (!NT_SUCCESS(Status));
 
-   RtlFreeHeap(GetProcessHeap(), 0, MountPoint);
+   RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
    NtClose(FileHandle);
 
    /*
@@ -1017,7 +1026,7 @@ GetVolumeNameForVolumeMountPointW(
    {
       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.
@@ -1047,14 +1056,14 @@ GetVolumeNameForVolumeMountPointW(
                Result = FALSE;
             }
 
-            RtlFreeHeap(GetProcessHeap(), 0, MountPoints);
+            RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
 
             return Result;
          }
       }
    }
 
-   RtlFreeHeap(GetProcessHeap(), 0, MountPoints);
+   RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
    SetLastError(ERROR_INVALID_PARAMETER);
 
    return FALSE;
@@ -1064,7 +1073,7 @@ GetVolumeNameForVolumeMountPointW(
  * @implemented (Wine 13 sep 2008)
  */
 BOOL
-STDCALL
+WINAPI
 GetVolumeNameForVolumeMountPointA(
     LPCSTR lpszVolumeMountPoint,
     LPSTR lpszVolumeName,
@@ -1083,7 +1092,7 @@ GetVolumeNameForVolumeMountPointA(
     if ((ret = GetVolumeNameForVolumeMountPointW( pathW, volumeW, len )))
         FilenameW2A_N( lpszVolumeName, len, volumeW, -1 );
 
-    RtlFreeHeap( GetProcessHeap(), 0, pathW );
+    RtlFreeHeap( RtlGetProcessHeap(), 0, pathW );
     return ret;
 }
 
@@ -1091,7 +1100,7 @@ GetVolumeNameForVolumeMountPointA(
  * @implemented (Wine 13 sep 2008)
  */
 HANDLE
-STDCALL
+WINAPI
 FindFirstVolumeW(
        LPWSTR volume,
        DWORD len
@@ -1099,7 +1108,7 @@ FindFirstVolumeW(
 {
     DWORD size = 1024;
     HANDLE mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
-                              NULL, OPEN_EXISTING, 0, 0 );
+                              NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE );
     if (mgr == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
 
     for (;;)
@@ -1107,7 +1116,7 @@ FindFirstVolumeW(
         MOUNTMGR_MOUNT_POINT input;
         MOUNTMGR_MOUNT_POINTS *output;
 
-        if (!(output = RtlAllocateHeap( GetProcessHeap(), 0, size )))
+        if (!(output = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
         {
             SetLastError( ERROR_NOT_ENOUGH_MEMORY );
             break;
@@ -1119,7 +1128,7 @@ FindFirstVolumeW(
         {
             if (GetLastError() != ERROR_MORE_DATA) break;
             size = output->Size;
-            RtlFreeHeap( GetProcessHeap(), 0, output );
+            RtlFreeHeap( RtlGetProcessHeap(), 0, output );
             continue;
         }
         CloseHandle( mgr );
@@ -1127,7 +1136,7 @@ FindFirstVolumeW(
         output->Size = 0;
         if (!FindNextVolumeW( output, volume, len ))
         {
-            RtlFreeHeap( GetProcessHeap(), 0, output );
+            RtlFreeHeap( RtlGetProcessHeap(), 0, output );
             return INVALID_HANDLE_VALUE;
         }
         return (HANDLE)output;
@@ -1140,14 +1149,24 @@ FindFirstVolumeW(
  * @implemented (Wine 13 sep 2008)
  */
 HANDLE
-STDCALL
+WINAPI
 FindFirstVolumeA(
        LPSTR volume,
        DWORD len
     )
 {
-    WCHAR *buffer = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-    HANDLE handle = FindFirstVolumeW( buffer, len );
+    WCHAR *buffer = NULL;
+    HANDLE handle;
+
+    buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, len * sizeof(WCHAR) );
+
+    if (!buffer)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return INVALID_HANDLE_VALUE;
+    }
+
+    handle = FindFirstVolumeW( buffer, len );
 
     if (handle != INVALID_HANDLE_VALUE)
     {
@@ -1157,7 +1176,7 @@ FindFirstVolumeA(
             handle = INVALID_HANDLE_VALUE;
         }
     }
-    RtlFreeHeap( GetProcessHeap(), 0, buffer );
+    RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
     return handle;
 }
 
@@ -1165,12 +1184,150 @@ FindFirstVolumeA(
  * @implemented (Wine 13 sep 2008)
  */
 BOOL
-STDCALL
+WINAPI
 FindVolumeClose(
     HANDLE hFindVolume
     )
 {
-    return RtlFreeHeap(GetProcessHeap(), 0, hFindVolume);
+    return RtlFreeHeap(RtlGetProcessHeap(), 0, hFindVolume);
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetVolumePathNameA(LPCSTR lpszFileName,
+                   LPSTR lpszVolumePathName,
+                   DWORD cchBufferLength)
+{
+    PWCHAR FileNameW = NULL;
+    WCHAR VolumePathName[MAX_PATH];
+    BOOL Result;
+
+    if (lpszFileName)
+    {
+        if (!(FileNameW = FilenameA2W(lpszFileName, FALSE)))
+            return FALSE;
+    }
+
+    Result = GetVolumePathNameW(FileNameW, VolumePathName, cchBufferLength);
+
+    if (Result)
+        FilenameW2A_N(lpszVolumePathName, MAX_PATH, VolumePathName, -1);
+
+    return Result;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetVolumePathNameW(LPCWSTR lpszFileName,
+                   LPWSTR lpszVolumePathName,
+                   DWORD cchBufferLength)
+{
+    DWORD PathLength;
+    UNICODE_STRING UnicodeFilePath;
+    LPWSTR FilePart;
+    PWSTR FullFilePath, FilePathName;
+    ULONG PathSize;
+    WCHAR VolumeName[MAX_PATH];
+    DWORD ErrorCode;
+    BOOL Result = FALSE;
+
+    if (!(PathLength = GetFullPathNameW(lpszFileName, 0, NULL, NULL)))
+    {
+        return Result;
+    }
+    else
+    {
+        PathLength = PathLength + 10;
+        PathSize = PathLength * sizeof(WCHAR);
+
+        if (!(FullFilePath = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathSize)))
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return Result;
+        }
+
+        if (!GetFullPathNameW(lpszFileName, PathLength, FullFilePath, &FilePart))
+        {
+            RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath);
+            return Result;
+        }
+
+        RtlInitUnicodeString(&UnicodeFilePath, FullFilePath);
+
+        if (UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] != '\\')
+        {
+            UnicodeFilePath.Length += sizeof(WCHAR);
+            UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] = '\\';
+            UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0';
+        }
+
+        if (!(FilePathName = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathSize)))
+        {
+            RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath);
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return Result;
+        }
+
+        while (!GetVolumeNameForVolumeMountPointW(UnicodeFilePath.Buffer,
+                                                  VolumeName,
+                                                  MAX_PATH))
+        {
+            if (((UnicodeFilePath.Length == 4) && (UnicodeFilePath.Buffer[0] == '\\') &&
+                (UnicodeFilePath.Buffer[1] == '\\')) || ((UnicodeFilePath.Length == 6) &&
+                (UnicodeFilePath.Buffer[1] == ':')))
+            {
+                break;
+            }
+
+            UnicodeFilePath.Length -= sizeof(WCHAR);
+            UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0';
+
+            memcpy(FilePathName, UnicodeFilePath.Buffer, UnicodeFilePath.Length);
+            FilePathName[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0';
+
+            if (!GetFullPathNameW(FilePathName, PathLength, FullFilePath, &FilePart))
+            {
+                goto Cleanup2;
+            }
+
+            if (!FilePart)
+            {
+                RtlInitUnicodeString(&UnicodeFilePath, FullFilePath);
+                UnicodeFilePath.Length += sizeof(WCHAR);
+                UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR) - 1] = '\\';
+                UnicodeFilePath.Buffer[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0';
+                break;
+            }
+
+            FilePart[0] = '\0';
+            RtlInitUnicodeString(&UnicodeFilePath, FullFilePath);
+        }
+    }
+
+    if (UnicodeFilePath.Length > (cchBufferLength * sizeof(WCHAR)) - sizeof(WCHAR))
+    {
+        ErrorCode = ERROR_FILENAME_EXCED_RANGE;
+        goto Cleanup1;
+    }
+
+    memcpy(lpszVolumePathName, UnicodeFilePath.Buffer, UnicodeFilePath.Length);
+    lpszVolumePathName[UnicodeFilePath.Length / sizeof(WCHAR)] = '\0';
+
+    Result = TRUE;
+    goto Cleanup2;
+
+Cleanup1:
+    SetLastError(ErrorCode);
+Cleanup2:
+    RtlFreeHeap(RtlGetProcessHeap(), 0, FullFilePath);
+    RtlFreeHeap(RtlGetProcessHeap(), 0, FilePathName);
+    return Result;
 }
 
 /* EOF */