Alexandre Julliard : kernel32: Implemented FindFirstVolume/ FindNextVolume using the mount point manager.

Alexandre Julliard julliard at winehq.org
Mon Jan 7 08:38:57 CST 2008


Module: wine
Branch: master
Commit: 7f508df25b1e068f58e8299dd113f51b014c721e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7f508df25b1e068f58e8299dd113f51b014c721e

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Jan  4 14:31:40 2008 +0100

kernel32: Implemented FindFirstVolume/FindNextVolume using the mount point manager.

---

 dlls/kernel32/kernel32.spec |    4 +-
 dlls/kernel32/volume.c      |  121 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 107 insertions(+), 18 deletions(-)

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 7bc5db3..51eec84 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -378,10 +378,10 @@
 @ stdcall FindNextChangeNotification(long)
 @ stdcall FindNextFileA(long ptr)
 @ stdcall FindNextFileW(long ptr)
-@ stub FindNextVolumeA
+@ stdcall FindNextVolumeA(long ptr long)
 @ stub FindNextVolumeMountPointA
 @ stub FindNextVolumeMountPointW
-@ stub FindNextVolumeW
+@ stdcall FindNextVolumeW(long ptr long)
 @ stdcall FindResourceA(long str str)
 @ stdcall FindResourceExA(long str str long)
 @ stdcall FindResourceExW(long wstr wstr long)
diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
index 1869d0d..9edcf64 100644
--- a/dlls/kernel32/volume.c
+++ b/dlls/kernel32/volume.c
@@ -37,6 +37,7 @@
 #include "winternl.h"
 #include "winioctl.h"
 #include "ntddcdrm.h"
+#include "ddk/mountmgr.h"
 #include "kernel_private.h"
 #include "wine/library.h"
 #include "wine/unicode.h"
@@ -1403,22 +1404,120 @@ BOOL WINAPI GetVolumePathNameW(LPCWSTR filename, LPWSTR volumepathname, DWORD bu
  */
 HANDLE WINAPI FindFirstVolumeA(LPSTR volume, DWORD len)
 {
-    FIXME("(%p, %d), stub!\n", volume, len);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return INVALID_HANDLE_VALUE;
+    WCHAR *buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+    HANDLE handle = FindFirstVolumeW( buffer, len );
+
+    if (handle != INVALID_HANDLE_VALUE)
+    {
+        if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL ))
+        {
+            FindVolumeClose( handle );
+            handle = INVALID_HANDLE_VALUE;
+        }
+    }
+    HeapFree( GetProcessHeap(), 0, buffer );
+    return handle;
 }
 
 /***********************************************************************
  *           FindFirstVolumeW   (KERNEL32.@)
  */
-HANDLE WINAPI FindFirstVolumeW(LPWSTR volume, DWORD len)
+HANDLE WINAPI FindFirstVolumeW( LPWSTR volume, DWORD len )
 {
-    FIXME("(%p, %d), stub!\n", volume, len);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    DWORD size = 1024;
+    HANDLE mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
+                              NULL, OPEN_EXISTING, 0, 0 );
+    if (mgr == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
+
+    for (;;)
+    {
+        MOUNTMGR_MOUNT_POINT input;
+        MOUNTMGR_MOUNT_POINTS *output;
+
+        if (!(output = HeapAlloc( GetProcessHeap(), 0, size )))
+        {
+            SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+            break;
+        }
+        memset( &input, 0, sizeof(input) );
+
+        if (!DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_POINTS, &input, sizeof(input),
+                              output, size, NULL, NULL ))
+        {
+            if (GetLastError() != ERROR_MORE_DATA) break;
+            size = output->Size;
+            HeapFree( GetProcessHeap(), 0, output );
+            continue;
+        }
+        CloseHandle( mgr );
+        /* abuse the Size field to store the current index */
+        output->Size = 0;
+        if (!FindNextVolumeW( output, volume, len ))
+        {
+            HeapFree( GetProcessHeap(), 0, output );
+            return INVALID_HANDLE_VALUE;
+        }
+        return (HANDLE)output;
+    }
+    CloseHandle( mgr );
     return INVALID_HANDLE_VALUE;
 }
 
 /***********************************************************************
+ *           FindNextVolumeA   (KERNEL32.@)
+ */
+BOOL WINAPI FindNextVolumeA( HANDLE handle, LPSTR volume, DWORD len )
+{
+    WCHAR *buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+    BOOL ret;
+
+    if ((ret = FindNextVolumeW( handle, buffer, len )))
+    {
+        if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) ret = FALSE;
+    }
+    return ret;
+}
+
+/***********************************************************************
+ *           FindNextVolumeW   (KERNEL32.@)
+ */
+BOOL WINAPI FindNextVolumeW( HANDLE handle, LPWSTR volume, DWORD len )
+{
+    MOUNTMGR_MOUNT_POINTS *data = handle;
+
+    while (data->Size < data->NumberOfMountPoints)
+    {
+        static const WCHAR volumeW[] = {'\\','?','?','\\','V','o','l','u','m','e','{',};
+        WCHAR *link = (WCHAR *)((char *)data + data->MountPoints[data->Size].SymbolicLinkNameOffset);
+        DWORD size = data->MountPoints[data->Size].SymbolicLinkNameLength;
+        data->Size++;
+        /* skip non-volumes */
+        if (size < sizeof(volumeW) || memcmp( link, volumeW, sizeof(volumeW) )) continue;
+        if (size + sizeof(WCHAR) >= len * sizeof(WCHAR))
+        {
+            SetLastError( ERROR_FILENAME_EXCED_RANGE );
+            return FALSE;
+        }
+        memcpy( volume, link, size );
+        volume[1] = '\\';  /* map \??\ to \\?\ */
+        volume[size / sizeof(WCHAR)] = '\\';  /* Windows appends a backslash */
+        volume[size / sizeof(WCHAR) + 1] = 0;
+        TRACE( "returning entry %u %s\n", data->Size - 1, debugstr_w(volume) );
+        return TRUE;
+    }
+    SetLastError( ERROR_NO_MORE_FILES );
+    return FALSE;
+}
+
+/***********************************************************************
+ *           FindVolumeClose   (KERNEL32.@)
+ */
+BOOL WINAPI FindVolumeClose(HANDLE handle)
+{
+    return HeapFree( GetProcessHeap(), 0, handle );
+}
+
+/***********************************************************************
  *           FindFirstVolumeMountPointA   (KERNEL32.@)
  */
 HANDLE WINAPI FindFirstVolumeMountPointA(LPCSTR root, LPSTR mount_point, DWORD len)
@@ -1439,16 +1538,6 @@ HANDLE WINAPI FindFirstVolumeMountPointW(LPCWSTR root, LPWSTR mount_point, DWORD
 }
 
 /***********************************************************************
- *           FindVolumeClose   (KERNEL32.@)
- */
-BOOL WINAPI FindVolumeClose(HANDLE handle)
-{
-    FIXME("(%p), stub!\n", handle);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-/***********************************************************************
  *           FindVolumeMountPointClose   (KERNEL32.@)
  */
 BOOL WINAPI FindVolumeMountPointClose(HANDLE h)




More information about the wine-cvs mailing list