[PATCH] kernel32: Basic integration of SetVolumeMountPointA/W.

Johannes Obermayr johannesobermayr at gmx.de
Wed Nov 21 12:51:23 CST 2012


Fixes: Bug 31951 and its duplicate 31703 (crash in TomTom HOME software)

Fixes not: Bug 7711 (detecting TomTom devices)

Maybe the device detection works if wine's MountManager supports MOUNTMGR_CREATE_POINT_INPUT:
- fixme:mountmgr:mountmgr_ioctl ioctl 6dc000 not supported
- http://doxygen.reactos.org/d9/df4/drivers_2filters_2mountmgr_2device_8c_source.html#l01479
---
 dlls/kernel32/kernel32.spec |    4 +-
 dlls/kernel32/volume.c      |  161 +++++++++++++++++++++++++++++++++++++++++++
 include/winbase.h           |    2 +-
 3 Dateien geändert, 164 Zeilen hinzugefügt(+), 3 Zeilen entfernt(-)

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 0bd1adc..9b16dfe 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1179,8 +1179,8 @@
 @ stub SetVDMCurrentDirectories
 @ stdcall SetVolumeLabelA(str str)
 @ stdcall SetVolumeLabelW(wstr wstr)
-@ stub SetVolumeMountPointA
-@ stub SetVolumeMountPointW
+@ stdcall SetVolumeMountPointA(str str)
+@ stdcall SetVolumeMountPointW(wstr wstr)
 @ stdcall SetWaitableTimer(long ptr long ptr ptr long)
 @ stdcall SetupComm(long long long)
 @ stub ShowConsoleCursor
diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
index 200c293..d0fbf42 100644
--- a/dlls/kernel32/volume.c
+++ b/dlls/kernel32/volume.c
@@ -1098,6 +1098,167 @@ err_ret:
 }
 
 /***********************************************************************
+ *           SetVolumeMountPointW   (KERNEL32.@)
+ */
+BOOL WINAPI SetVolumeMountPointW(LPCWSTR path, LPCWSTR volume)
+{
+    const WCHAR prefixW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\'};
+    LPWSTR namesW = NULL;
+    UNICODE_STRING volumeU = {0};
+    DWORD buffer = MAX_PATH;
+    HANDLE mgr;
+    BOOL ret = FALSE;
+    int i;
+
+    /* This struct is a better integration of MOUNTMGR_CREATE_POINT_INPUT   */
+    /* Maybe DeviceName[14] must become adapted for mounted folders support */
+    struct
+    {
+        USHORT DeviceNameOffset;
+        USHORT DeviceNameLength;
+        USHORT VolumeNameOffset;
+        USHORT VolumeNameLength;
+        WCHAR  DeviceName[14];   /* 14 WCHARs: prefixW + 2 */
+        WCHAR  VolumeName[48];   /* without trailing '\'   */
+    } input;
+
+    TRACE("(%s, %s)\n", debugstr_w(path), debugstr_w(volume));
+
+    /* Clear input */
+    memset(&input, 0, sizeof(input));
+    /* Now prefill with always needed consts */
+    memset(&input.DeviceNameOffset, (const USHORT)((int)&input.DeviceName - (int)&input), 1);
+    memset(&input.DeviceNameLength, (const USHORT)((int)&input.VolumeName - (int)&input.DeviceName), 1);
+    memset(&input.VolumeNameOffset, (const USHORT)(input.DeviceNameOffset + input.DeviceNameLength), 1);
+    memset(&input.VolumeNameLength, (const USHORT)((strlenW(volume) - 1) * sizeof(WCHAR)), 1);
+
+    /* Begin with initial checks */
+    if (!path || !volume)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        goto free_input;
+    }
+
+    /* Abort if path has been mounted */
+    if (GetVolumeNameForVolumeMountPointW(path, namesW, MAX_PATH))
+    {
+        WARN("%s already mounts %s\n", debugstr_w(path), debugstr_w(namesW));
+        SetLastError(ERROR_DIR_NOT_EMPTY);
+        goto free_input;
+    }
+
+    /* We can use checks and error codes from GetVolumeNameForVolumeMountPointW */
+    switch (GetLastError())
+    {
+        case ERROR_INVALID_NAME:
+        case ERROR_FILENAME_EXCED_RANGE:
+            goto free_input;
+        default:
+            break;
+    }
+
+    /* Create UNICODE_STRINGs for path and volume */
+    if (RtlInitUnicodeStringEx(&volumeU, volume) != STATUS_SUCCESS)
+        goto free_input;
+
+    /* Check whether volume name is valid */
+    if (!MOUNTMGR_IS_VOLUME_NAME(&volumeU))
+    {
+        WARN("(%s, %s), invalid volume name!\n", debugstr_w(path), debugstr_w(volume));
+        SetLastError(ERROR_INVALID_NAME);
+        goto free_input;
+    }
+
+    /* Abort if volume has been mounted */
+    if (GetVolumePathNamesForVolumeNameW(volume, namesW, buffer, &buffer))
+    {
+        WARN("%s is already mounted by %s\n", debugstr_w(volume), debugstr_w(namesW));
+        SetLastError(ERROR_VOLUME_MOUNTED);
+        goto free_input;
+    }
+
+    if(strlenW(path) == 3 && path[1] == ':')
+    {
+        /* Fill input with SymlinkName */
+        memcpy(input.DeviceName, prefixW, sizeof(prefixW));
+        memset(&input.DeviceName[12], (const WCHAR)(toupper(path[0])), 1);
+        memset(&input.DeviceName[13], (const WCHAR)(':'), 1);
+
+        /* Now fill the VolumeName an make sure the 2nd WCHAR is '?' */
+        for (i = 0; i < 49; i++)
+            memset(&input.VolumeName[i], volumeU.Buffer[i], 1);
+
+        memset(&input.VolumeName[1], (const WCHAR)('?'), 1);
+
+        /* Create the handle */
+        mgr = CreateFileW(MOUNTMGR_DOS_DEVICE_NAME,
+                          GENERIC_READ | GENERIC_WRITE,
+                          FILE_SHARE_READ | FILE_SHARE_WRITE,
+                          0,
+                          OPEN_EXISTING,
+                          FILE_ATTRIBUTE_NORMAL,
+                          NULL);
+
+        if (mgr == INVALID_HANDLE_VALUE)
+        {
+            WARN("Handle could not be created\n");
+            goto free_input;
+        }
+
+        /* MountManager should now be able to create the VolumeMountPoint */
+        ret = DeviceIoControl(mgr, IOCTL_MOUNTMGR_CREATE_POINT, &input, sizeof(input), 0, 0, 0, 0);
+
+        CloseHandle(mgr);
+
+        goto free_input;
+    }
+
+    FIXME("Mounted Folders are not yet supported\n");
+
+free_input:
+    HeapFree(GetProcessHeap(), 0, &input);
+
+    return ret;
+}
+
+/************************************************************************
+ *           SetVolumeMountPointA   (KERNEL32.@)
+ */
+BOOL WINAPI SetVolumeMountPointA(LPCSTR path, LPCSTR volume)
+{
+    BOOL ret = FALSE;
+    WCHAR *pathW, *volumeW;
+
+    TRACE("(%s, %s)\n", debugstr_a(path), debugstr_a(volume));
+
+    if (!path || !volume)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (!(pathW = FILE_name_AtoW(path, TRUE)))
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
+    if (!(volumeW = FILE_name_AtoW(volume, TRUE)))
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        goto free_pathW;
+    }
+
+    ret = SetVolumeMountPointW(pathW, volumeW);
+
+    HeapFree(GetProcessHeap(), 0, volumeW);
+free_pathW:
+    HeapFree(GetProcessHeap(), 0, pathW);
+
+    return ret;
+}
+
+/***********************************************************************
  *           DefineDosDeviceW       (KERNEL32.@)
  */
 BOOL WINAPI DefineDosDeviceW( DWORD flags, LPCWSTR devname, LPCWSTR targetpath )
diff --git a/include/winbase.h b/include/winbase.h
index a9abb30..936497e 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2229,7 +2229,7 @@ WINBASEAPI BOOL        WINAPI SetVolumeLabelA(LPCSTR,LPCSTR);
 WINBASEAPI BOOL        WINAPI SetVolumeLabelW(LPCWSTR,LPCWSTR);
 #define                       SetVolumeLabel WINELIB_NAME_AW(SetVolumeLabel)
 WINBASEAPI BOOL        WINAPI SetVolumeMountPointA(LPCSTR,LPCSTR);
-WINBASEAPI BOOL        WINAPI SetVolumeMountPointW(LPCSTR,LPCSTR);
+WINBASEAPI BOOL        WINAPI SetVolumeMountPointW(LPCWSTR,LPCWSTR);
 #define                       SetVolumeMountPoint WINELIB_NAME_AW(SetVolumeMountPoint)
 WINBASEAPI BOOL        WINAPI SetWaitableTimer(HANDLE,const LARGE_INTEGER*,LONG,PTIMERAPCROUTINE,LPVOID,BOOL);
 WINBASEAPI BOOL        WINAPI SetupComm(HANDLE,DWORD,DWORD);
-- 
1.7.10.4




More information about the wine-patches mailing list