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");
|
||||
|
||||
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 );
|
||||
}
|
||||
|
|
|
@ -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 || !path[0]) return FALSE;
|
||||
|
||||
if (size >= sizeof(fmt) / sizeof(WCHAR))
|
||||
if (path[lstrlenW(path)-1] != '\\')
|
||||
{
|
||||
/* FIXME: will break when we support volume mounts */
|
||||
sprintfW( volume, fmt, tolowerW( path[0] ) - 'a' );
|
||||
ret = TRUE;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue