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