kernel32.dll: implementation of GetVolumePathNamesForVolumeNameA/W (try 2)

Tuomo Mattila tuomom at ee.oulu.fi
Tue Jul 20 21:22:51 CDT 2010


---
 dlls/kernel32/kernel32.spec |    2 +-
 dlls/kernel32/volume.c      |   97 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 95 insertions(+), 4 deletions(-)

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index e7ae774..02a7553 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -672,7 +672,7 @@
 @ stdcall GetVolumeNameForVolumeMountPointW(wstr ptr long)
 @ stdcall GetVolumePathNameA(str ptr long)
 @ stdcall GetVolumePathNameW(wstr ptr long)
-# @ stub GetVolumePathNamesForVolumeNameA
+@ stdcall GetVolumePathNamesForVolumeNameA(str ptr long ptr)
 @ stdcall GetVolumePathNamesForVolumeNameW(wstr ptr long ptr)
 @ stdcall GetWindowsDirectoryA(ptr long)
 @ stdcall GetWindowsDirectoryW(ptr long)
diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
index 7596864..c6a9561 100644
--- a/dlls/kernel32/volume.c
+++ b/dlls/kernel32/volume.c
@@ -1566,13 +1566,104 @@ BOOL WINAPI GetVolumePathNameW(LPCWSTR filename, LPWSTR volumepathname, DWORD bu
 }
 
 /***********************************************************************
+ *           GetVolumePathNamesForVolumeNameA   (KERNEL32.@)
+ */
+BOOL WINAPI GetVolumePathNamesForVolumeNameA(LPCSTR volumename, LPSTR volumepathname, DWORD buflen, PDWORD returnlen)
+{
+
+    BOOL ret = FALSE;
+    WCHAR* volumenameW = NULL;
+    LPWSTR volumepathnameW = NULL;
+
+
+    /* FIXME: The winxp version of this function raises an exception (access violation) if called with a NULL volumename or volumepathname argument. Alternatively, we might want to set an error code and return a failure */
+/*
+    if (volumename == NULL || volumepathname == NULL)
+    {
+        return FALSE;
+    }
+*/
+
+    volumepathnameW = HeapAlloc(GetProcessHeap(), 0, buflen*sizeof(WCHAR));
+    if (volumepathnameW == NULL) return FALSE;
+
+    if ((volumenameW = FILE_name_AtoW(volumename, TRUE)) == 0) return FALSE;
+    
+    ret = GetVolumePathNamesForVolumeNameW(volumenameW, volumepathnameW, buflen, returnlen);
+    if (buflen > 0)
+        FILE_name_WtoA(volumepathnameW, buflen, volumepathname, buflen);
+    
+    HeapFree(GetProcessHeap(), 0, volumepathnameW);
+    HeapFree(GetProcessHeap(), 0, volumenameW);
+
+    return ret;
+}
+
+/***********************************************************************
  *           GetVolumePathNamesForVolumeNameW   (KERNEL32.@)
  */
 BOOL WINAPI GetVolumePathNamesForVolumeNameW(LPCWSTR volumename, LPWSTR volumepathname, DWORD buflen, PDWORD returnlen)
 {
-    FIXME("(%s, %p, %d, %p), stub!\n", debugstr_w(volumename), volumepathname, buflen, returnlen);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+
+    DWORD available_drives = GetLogicalDrives();
+    WCHAR letter;
+    DWORD count = 0;
+    WCHAR volumename2string[50];
+    LPWSTR volumename2 = volumename2string;
+    WCHAR pstr[4] = {'A', ':', '\\', 0};
+    LPCWSTR pathstring = pstr;
+    int pstr_counter = 0;
+    WCHAR volname_prefix[11] = {'\\', '\\', '?', '\\', 'V', 'o', 'l', 'u', 'm', 'e', '{'};
+
+
+    /* FIXME: The winxp version of this function raises an exception (access violation) if called with a NULL volumename or volumepathname argument. Alternatively, we might want to set an error code and return a failure */
+/*
+    if (volumename == NULL || volumepathname == NULL)
+    {
+        return FALSE;
+    }
+*/
+
+    if (strncmpW(volumename, volname_prefix, 11) != 0 || volumename[19] != '-' || volumename[24] != '-' || volumename[29] != '-' || volumename[34] != '-' || volumename[47] != '}')
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (volumename[48] != '\\' || volumename[49] != 0)
+    {
+        SetLastError(ERROR_INVALID_NAME);
+        return FALSE;
+    }
+    /* FIXME: combination of the above may set other error codes */
+
+
+    for (letter='A'; letter<='Z'; letter++)
+    {
+        memset(volumename2string, 0, sizeof(volumename2string));
+        if (available_drives & (1<<(letter-'A')))
+        {
+            pstr[0] = letter;
+            if( (GetVolumeNameForVolumeMountPointW(pathstring, volumename2, 50)) && (!strncmpW(volumename, volumename2, 50))) 
+                for (pstr_counter=0; pstr_counter<4 && count<buflen; pstr_counter++, count++)
+                    volumepathname[count] = pstr[pstr_counter];
+                    /* if the buffer length is insufficient, write as much of the strings as possible, overwriting trailing nulls */
+        }
+    }
+    if (count == 0)
+    {
+        SetLastError(ERROR_FILE_NOT_FOUND);
+        return FALSE;
+    }
+    count += ((4-pstr_counter) +1); /* the buffer should have space for an additional trailing null as well as the rest of the string if it was truncated*/
+    if (returnlen)
+        *returnlen = count;
+
+    SetLastError(ERROR_MORE_DATA); /* set even on success */
+    if (count > buflen)
+        return FALSE;
+    else volumepathname[count-1] = 0;
+
+    return TRUE;
 }
 
 /***********************************************************************
-- 
1.7.1




More information about the wine-patches mailing list