From 7f508df25b1e068f58e8299dd113f51b014c721e Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 4 Jan 2008 14:31:40 +0100 Subject: [PATCH] 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 7bc5db34fdb..51eec84ef2a 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 1869d0d072a..9edcf64c2b5 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,21 +1404,119 @@ 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.@) */ @@ -1438,16 +1537,6 @@ HANDLE WINAPI FindFirstVolumeMountPointW(LPCWSTR root, LPWSTR mount_point, DWORD return INVALID_HANDLE_VALUE; } -/*********************************************************************** - * FindVolumeClose (KERNEL32.@) - */ -BOOL WINAPI FindVolumeClose(HANDLE handle) -{ - FIXME("(%p), stub!\n", handle); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - /*********************************************************************** * FindVolumeMountPointClose (KERNEL32.@) */