kernel32: Fix GetVolumeNameForVolumeMountPointW to match Mountmgr.
This commit is contained in:
parent
e7ebbbe62e
commit
c1f161a678
@ -129,7 +129,9 @@ static void test_GetVolumeNameForVolumeMountPointA(void)
|
|||||||
ok(reti < MAX_PATH, "temp path should fit into MAX_PATH\n");
|
ok(reti < MAX_PATH, "temp path should fit into MAX_PATH\n");
|
||||||
|
|
||||||
ret = pGetVolumeNameForVolumeMountPointA(path, volume, 0);
|
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 */
|
if (0) { /* these crash on XP */
|
||||||
ret = pGetVolumeNameForVolumeMountPointA(path, NULL, len);
|
ret = pGetVolumeNameForVolumeMountPointA(path, NULL, len);
|
||||||
@ -147,14 +149,12 @@ static void test_GetVolumeNameForVolumeMountPointA(void)
|
|||||||
|
|
||||||
/* test with too small buffer */
|
/* test with too small buffer */
|
||||||
ret = pGetVolumeNameForVolumeMountPointA(path, volume, 10);
|
ret = pGetVolumeNameForVolumeMountPointA(path, volume, 10);
|
||||||
todo_wine
|
|
||||||
ok(ret == FALSE && GetLastError() == ERROR_FILENAME_EXCED_RANGE,
|
ok(ret == FALSE && GetLastError() == ERROR_FILENAME_EXCED_RANGE,
|
||||||
"GetVolumeNameForVolumeMountPointA failed, wrong error returned, was %d, should be ERROR_FILENAME_EXCED_RANGE\n",
|
"GetVolumeNameForVolumeMountPointA failed, wrong error returned, was %d, should be ERROR_FILENAME_EXCED_RANGE\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
|
|
||||||
/* Try on a arbitrary directory */
|
/* Try on a arbitrary directory */
|
||||||
ret = pGetVolumeNameForVolumeMountPointA(temp_path, volume, len);
|
ret = pGetVolumeNameForVolumeMountPointA(temp_path, volume, len);
|
||||||
todo_wine
|
|
||||||
ok(ret == FALSE && GetLastError() == ERROR_NOT_A_REPARSE_POINT,
|
ok(ret == FALSE && GetLastError() == ERROR_NOT_A_REPARSE_POINT,
|
||||||
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
|
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
|
||||||
temp_path, GetLastError());
|
temp_path, GetLastError());
|
||||||
@ -169,7 +169,6 @@ todo_wine
|
|||||||
{
|
{
|
||||||
path[2] = '\\';
|
path[2] = '\\';
|
||||||
ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
|
ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
|
||||||
todo_wine
|
|
||||||
ok(ret == FALSE && GetLastError() == ERROR_FILE_NOT_FOUND,
|
ok(ret == FALSE && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||||
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
|
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
|
||||||
path, GetLastError());
|
path, GetLastError());
|
||||||
@ -177,7 +176,6 @@ todo_wine
|
|||||||
/* Try without trailing \ and on a non-existent dos drive */
|
/* Try without trailing \ and on a non-existent dos drive */
|
||||||
path[2] = 0;
|
path[2] = 0;
|
||||||
ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
|
ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
|
||||||
todo_wine
|
|
||||||
ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
|
ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
|
||||||
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
|
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
|
||||||
path, GetLastError());
|
path, GetLastError());
|
||||||
@ -197,7 +195,9 @@ static void test_GetVolumeNameForVolumeMountPointW(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = pGetVolumeNameForVolumeMountPointW(path, volume, 0);
|
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 */
|
if (0) { /* these crash on XP */
|
||||||
ret = pGetVolumeNameForVolumeMountPointW(path, NULL, len);
|
ret = pGetVolumeNameForVolumeMountPointW(path, NULL, len);
|
||||||
@ -387,7 +387,6 @@ static void test_enum_vols(void)
|
|||||||
/* get the unique volume name for the windows drive */
|
/* get the unique volume name for the windows drive */
|
||||||
ret = pGetVolumeNameForVolumeMountPointA( path, Volume_1, MAX_PATH );
|
ret = pGetVolumeNameForVolumeMountPointA( path, Volume_1, MAX_PATH );
|
||||||
ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
|
ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
|
||||||
todo_wine
|
|
||||||
ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name %s\n", Volume_1);
|
ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name %s\n", Volume_1);
|
||||||
|
|
||||||
/* get first unique volume name of list */
|
/* get first unique volume name of list */
|
||||||
@ -405,7 +404,6 @@ todo_wine
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (pFindNextVolumeA( hFind, Volume_2, MAX_PATH ));
|
} while (pFindNextVolumeA( hFind, Volume_2, MAX_PATH ));
|
||||||
todo_wine
|
|
||||||
ok(found, "volume name %s not found by Find[First/Next]Volume\n", Volume_1);
|
ok(found, "volume name %s not found by Find[First/Next]Volume\n", Volume_1);
|
||||||
pFindVolumeClose( hFind );
|
pFindVolumeClose( hFind );
|
||||||
}
|
}
|
||||||
|
@ -788,20 +788,132 @@ BOOL WINAPI GetVolumeNameForVolumeMountPointA( LPCSTR path, LPSTR volume, DWORD
|
|||||||
*/
|
*/
|
||||||
BOOL WINAPI GetVolumeNameForVolumeMountPointW( LPCWSTR path, LPWSTR volume, DWORD size )
|
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;
|
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);
|
TRACE("(%s, %p, %x)\n", debugstr_w(path), volume, size);
|
||||||
|
if (path[lstrlenW(path)-1] != '\\')
|
||||||
if (!path || !path[0]) return FALSE;
|
|
||||||
|
|
||||||
if (size >= sizeof(fmt) / sizeof(WCHAR))
|
|
||||||
{
|
{
|
||||||
/* FIXME: will break when we support volume mounts */
|
SetLastError( ERROR_INVALID_NAME );
|
||||||
sprintfW( volume, fmt, tolowerW( path[0] ) - 'a' );
|
return FALSE;
|
||||||
ret = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
|
||||||
|
/* look for the volume name in returned values */
|
||||||
|
for(i=0;i<output->NumberOfMountPoints;i++)
|
||||||
|
{
|
||||||
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user