Guy Albertelli : kernel32: Fix GetVolumeNameForVolumeMountPointW to match Mountmgr.
Alexandre Julliard
julliard at winehq.org
Tue May 26 09:24:57 CDT 2009
Module: wine
Branch: master
Commit: c1f161a678e75f12b9378df9fba7a951c39cf242
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c1f161a678e75f12b9378df9fba7a951c39cf242
Author: Guy Albertelli <galberte at neo.rr.com>
Date: Sat May 23 23:45:07 2009 -0400
kernel32: Fix GetVolumeNameForVolumeMountPointW to match Mountmgr.
---
dlls/kernel32/tests/volume.c | 14 ++---
dlls/kernel32/volume.c | 126 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 125 insertions(+), 15 deletions(-)
diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c
index e447e0f..dab59bc 100644
--- a/dlls/kernel32/tests/volume.c
+++ b/dlls/kernel32/tests/volume.c
@@ -129,7 +129,9 @@ static void test_GetVolumeNameForVolumeMountPointA(void)
ok(reti < MAX_PATH, "temp path should fit into MAX_PATH\n");
ret = pGetVolumeNameForVolumeMountPointA(path, volume, 0);
- ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
+ ok(ret == FALSE && GetLastError() == ERROR_FILENAME_EXCED_RANGE,
+ "GetVolumeNameForVolumeMountPointA succeeded or wrong error, last=%d\n",
+ GetLastError());
if (0) { /* these crash on XP */
ret = pGetVolumeNameForVolumeMountPointA(path, NULL, len);
@@ -147,14 +149,12 @@ static void test_GetVolumeNameForVolumeMountPointA(void)
/* test with too small buffer */
ret = pGetVolumeNameForVolumeMountPointA(path, volume, 10);
-todo_wine
ok(ret == FALSE && GetLastError() == ERROR_FILENAME_EXCED_RANGE,
"GetVolumeNameForVolumeMountPointA failed, wrong error returned, was %d, should be ERROR_FILENAME_EXCED_RANGE\n",
GetLastError());
/* Try on a arbitrary directory */
ret = pGetVolumeNameForVolumeMountPointA(temp_path, volume, len);
-todo_wine
ok(ret == FALSE && GetLastError() == ERROR_NOT_A_REPARSE_POINT,
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
temp_path, GetLastError());
@@ -169,7 +169,6 @@ todo_wine
{
path[2] = '\\';
ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
-todo_wine
ok(ret == FALSE && GetLastError() == ERROR_FILE_NOT_FOUND,
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
path, GetLastError());
@@ -177,7 +176,6 @@ todo_wine
/* Try without trailing \ and on a non-existent dos drive */
path[2] = 0;
ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
-todo_wine
ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
path, GetLastError());
@@ -197,7 +195,9 @@ static void test_GetVolumeNameForVolumeMountPointW(void)
}
ret = pGetVolumeNameForVolumeMountPointW(path, volume, 0);
- ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
+ ok(ret == FALSE && GetLastError() == ERROR_FILENAME_EXCED_RANGE,
+ "GetVolumeNameForVolumeMountPointA succeeded or wrong error, last=%d\n",
+ GetLastError());
if (0) { /* these crash on XP */
ret = pGetVolumeNameForVolumeMountPointW(path, NULL, len);
@@ -387,7 +387,6 @@ static void test_enum_vols(void)
/* get the unique volume name for the windows drive */
ret = pGetVolumeNameForVolumeMountPointA( path, Volume_1, MAX_PATH );
ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
-todo_wine
ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name %s\n", Volume_1);
/* get first unique volume name of list */
@@ -405,7 +404,6 @@ todo_wine
break;
}
} while (pFindNextVolumeA( hFind, Volume_2, MAX_PATH ));
-todo_wine
ok(found, "volume name %s not found by Find[First/Next]Volume\n", Volume_1);
pFindVolumeClose( hFind );
}
diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
index 1b44ace..0f4161c 100644
--- a/dlls/kernel32/volume.c
+++ b/dlls/kernel32/volume.c
@@ -788,20 +788,132 @@ BOOL WINAPI GetVolumeNameForVolumeMountPointA( LPCSTR path, LPSTR volume, DWORD
*/
BOOL WINAPI GetVolumeNameForVolumeMountPointW( LPCWSTR path, LPWSTR volume, DWORD size )
{
+ static const WCHAR prefixW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
+ static const WCHAR volumeW[] = {'\\','?','?','\\','V','o','l','u','m','e','{',0};
+ static const WCHAR trailingW[] = {'\\',0};
+
+ MOUNTMGR_MOUNT_POINT *input = NULL, *o1;
+ MOUNTMGR_MOUNT_POINTS *output = NULL;
+ WCHAR *p;
+ char *r;
+ DWORD i, i_size = 1024, o_size = 1024;
+ WCHAR nonpersist_name[200];
+ WCHAR symlink_name[MAX_PATH];
+ NTSTATUS status;
+ HANDLE mgr = INVALID_HANDLE_VALUE;
BOOL ret = FALSE;
- static const WCHAR fmt[] =
- { '\\','\\','?','\\','V','o','l','u','m','e','{','%','0','2','x','}','\\',0 };
TRACE("(%s, %p, %x)\n", debugstr_w(path), volume, size);
+ if (path[lstrlenW(path)-1] != '\\')
+ {
+ SetLastError( ERROR_INVALID_NAME );
+ return FALSE;
+ }
+
+ if (size < 50)
+ {
+ SetLastError( ERROR_FILENAME_EXCED_RANGE );
+ return FALSE;
+ }
+ /* if length of input is > 3 then it must be a mounted folder */
+ if (lstrlenW(path) > 3)
+ {
+ FIXME("Mounted Folders are not yet supported\n");
+ SetLastError( ERROR_NOT_A_REPARSE_POINT );
+ return FALSE;
+ }
+
+ mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, 0 );
+ if (mgr == INVALID_HANDLE_VALUE) return FALSE;
+
+ if (!(input = HeapAlloc( GetProcessHeap(), 0, i_size )))
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ goto err_ret;
+ }
+
+ if (!(output = HeapAlloc( GetProcessHeap(), 0, o_size )))
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ goto err_ret;
+ }
+
+ /* construct the symlink name as "\DosDevices\C:" */
+ lstrcpyW( symlink_name, prefixW );
+ lstrcatW( symlink_name, path );
+ symlink_name[lstrlenW(symlink_name)-1] = 0;
+
+ /* Take the mount point and get the "nonpersistent name" */
+ /* We will then take that and get the volume name */
+ status = read_nt_symlink( symlink_name, nonpersist_name,
+ sizeof(nonpersist_name)/sizeof(WCHAR) );
+ TRACE("read_nt_symlink got stat=%x, for %s, got <%s>\n", status,
+ debugstr_w(symlink_name), debugstr_w(nonpersist_name));
+ if (status != STATUS_SUCCESS)
+ {
+ SetLastError( ERROR_FILE_NOT_FOUND );
+ goto err_ret;
+ }
+
+ /* Now take the "nonpersistent name" and ask the mountmgr */
+ /* to give us all the mount points. One of them will be */
+ /* the volume name (format of \??\Volume{). */
+ memset( input, 0, sizeof(*input) ); /* clear all input parameters */
+ input->DeviceNameOffset = sizeof(*input);
+ input->DeviceNameLength = lstrlenW( nonpersist_name) * sizeof(WCHAR);
+ memcpy( input + 1, nonpersist_name, input->DeviceNameLength );
+
+ output->Size = o_size;
+
+ /* now get the true volume name from the mountmgr */
+ if (!DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_POINTS, input, i_size,
+ output, o_size, NULL, NULL ))
+ goto err_ret;
- if (!path || !path[0]) return FALSE;
+ /* Verify and return the data, note string is not null terminated */
+ TRACE("found %d matching mount points\n", output->NumberOfMountPoints);
+ if (output->NumberOfMountPoints < 1)
+ {
+ SetLastError( ERROR_NO_VOLUME_ID );
+ goto err_ret;
+ }
+ o1 = &output->MountPoints[0];
- if (size >= sizeof(fmt) / sizeof(WCHAR))
+ /* look for the volume name in returned values */
+ for(i=0;i<output->NumberOfMountPoints;i++)
{
- /* FIXME: will break when we support volume mounts */
- sprintfW( volume, fmt, tolowerW( path[0] ) - 'a' );
- ret = TRUE;
+ p = (WCHAR*)((char *)output + o1->SymbolicLinkNameOffset);
+ r = (char *)output + o1->UniqueIdOffset;
+ TRACE("found symlink=%s, unique=%s, devname=%s\n",
+ debugstr_wn(p, o1->SymbolicLinkNameLength/sizeof(WCHAR)),
+ debugstr_an(r, o1->UniqueIdLength),
+ debugstr_wn((WCHAR*)((char *)output + o1->DeviceNameOffset),
+ o1->DeviceNameLength/sizeof(WCHAR)));
+
+ if (!strncmpW( p, volumeW, (sizeof(volumeW)-1)/sizeof(WCHAR) ))
+ {
+ /* is there space in the return variable ?? */
+ if ((o1->SymbolicLinkNameLength/sizeof(WCHAR))+2 > size)
+ {
+ SetLastError( ERROR_FILENAME_EXCED_RANGE );
+ goto err_ret;
+ }
+ memcpy( volume, p, o1->SymbolicLinkNameLength );
+ volume[o1->SymbolicLinkNameLength / sizeof(WCHAR)] = 0;
+ lstrcatW( volume, trailingW );
+ /* change second char from '?' to '\' */
+ volume[1] = '\\';
+ ret = TRUE;
+ break;
+ }
+ o1++;
}
+
+err_ret:
+ HeapFree( GetProcessHeap(), 0, input );
+ HeapFree( GetProcessHeap(), 0, output );
+ CloseHandle( mgr );
return ret;
}
More information about the wine-cvs
mailing list