diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c index 97e3559c000..1bbdb68379d 100644 --- a/dlls/kernel32/tests/volume.c +++ b/dlls/kernel32/tests/volume.c @@ -20,6 +20,7 @@ #include "wine/test.h" #include "winbase.h" +#include static HINSTANCE hdll; static BOOL (WINAPI * pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD); @@ -29,29 +30,62 @@ static BOOL (WINAPI *pFindNextVolumeA)(HANDLE,LPSTR,DWORD); static BOOL (WINAPI *pFindVolumeClose)(HANDLE); static UINT (WINAPI *pGetLogicalDriveStringsA)(UINT,LPSTR); static UINT (WINAPI *pGetLogicalDriveStringsW)(UINT,LPWSTR); +static BOOL (WINAPI *pGetVolumeInformationA)(LPCSTR, LPSTR, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR, DWORD); /* ############################### */ static void test_query_dos_deviceA(void) { char drivestr[] = "a:"; - char *p, buffer[2000]; - DWORD ret; + char *p, *q, *buffer, buffer2[2000]; + DWORD ret, ret2, buflen=32768; BOOL found = FALSE; + buffer = HeapAlloc( GetProcessHeap(), 0, buflen ); + ret = QueryDosDeviceA( NULL, buffer, buflen ); + ok(ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER, + "QueryDosDevice buffer too small\n"); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + HeapFree( GetProcessHeap(), 0, buffer ); + return; + } + ok(ret, "QueryDosDeviceA failed to return list, last error %u\n", GetLastError()); + if (ret) { + p = buffer; + for (;;) { + if (!strlen(p)) break; + trace("device entry %s\n", p); + ret2 = QueryDosDeviceA( p, buffer2, sizeof(buffer2) ); + ok(ret2, "QueryDosDeviceA failed to return current mapping, last error %u\n", GetLastError()); + if (ret2) { + q = buffer2; + for (;;) { + if (!strlen(q)) break; + trace("for device %s, current mapping %s\n", p, q); + q += strlen(q) + 1; + if (ret2 <= (q-buffer2)) break; + } + } + p += strlen(p) + 1; + if (ret <= (p-buffer)) break; + } + } + if (!pFindFirstVolumeA) { - skip("On win9x, HARDDISK and RAMDISK not present\n"); + win_skip("On win9x, HARDDISK and RAMDISK not present\n"); + HeapFree( GetProcessHeap(), 0, buffer ); return; } for (;drivestr[0] <= 'z'; drivestr[0]++) { - ret = QueryDosDeviceA( drivestr, buffer, sizeof(buffer)); + ret = QueryDosDeviceA( drivestr, buffer, buflen); if(ret) { for (p = buffer; *p; p++) *p = toupper(*p); if (strstr(buffer, "HARDDISK") || strstr(buffer, "RAMDISK")) found = TRUE; } } ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n"); + HeapFree( GetProcessHeap(), 0, buffer ); } static void test_FindFirstVolume(void) @@ -216,6 +250,100 @@ static void test_GetLogicalDriveStringsW(void) HeapFree(GetProcessHeap(), 0, buf); } +static void test_GetVolumeInformationA(void) +{ + BOOL ret; + UINT result; + char Root_Dir0[]="C:"; + char Root_Dir1[]="C:\\"; + char Root_Dir2[]="\\\\?\\C:\\"; + char volume[MAX_PATH+1]; + DWORD vol_name_size=MAX_PATH+1, vol_serial_num=-1, max_comp_len=0, fs_flags=0, fs_name_len=MAX_PATH+1; + char vol_name_buf[MAX_PATH+1], fs_name_buf[MAX_PATH+1]; + char windowsdir[MAX_PATH+10]; + + if (!pGetVolumeInformationA) { + win_skip("GetVolumeInformationA not found\n"); + return; + } + if (!pGetVolumeNameForVolumeMountPointA) { + win_skip("GetVolumeNameForVolumeMountPointA not found\n"); + return; + } + + /* get windows drive letter and update strings for testing */ + result = GetWindowsDirectory(windowsdir, sizeof(windowsdir)); + ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n"); + ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError()); + Root_Dir0[0] = windowsdir[0]; + Root_Dir1[0] = windowsdir[0]; + Root_Dir2[4] = windowsdir[0]; + + /* get the unique volume name for the windows drive */ + ret = pGetVolumeNameForVolumeMountPointA(Root_Dir1, volume, MAX_PATH); + ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n"); + + /* **** now start the tests **** */ + /* check for error on no trailing \ */ + ret = pGetVolumeInformationA(Root_Dir0, vol_name_buf, vol_name_size, NULL, + NULL, NULL, fs_name_buf, fs_name_len); +todo_wine + ok(!ret && GetLastError() == ERROR_INVALID_NAME, + "GetVolumeInformationA w/o '\\' did not fail, last error %u\n", GetLastError()); + + /* try null root directory to return "root of the current directory" */ + ret = pGetVolumeInformationA(NULL, vol_name_buf, vol_name_size, NULL, + NULL, NULL, fs_name_buf, fs_name_len); + ok(ret, "GetVolumeInformationA failed on null root dir, last error %u\n", GetLastError()); + if (ret) { + trace("for %s, vol_serial_num=0x%08x, max_comp_len=%d, filesys flags=0x%08x, vol name=%s, filesys name=%s\n", + "", vol_serial_num, max_comp_len, fs_flags, vol_name_buf, fs_name_buf); + } + + /* Try normal drive letter with trailing \ */ + ret = pGetVolumeInformationA(Root_Dir1, vol_name_buf, vol_name_size, + &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len); + ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Dir1, GetLastError()); + if (ret) { + trace("for %s, vol_serial_num=0x%08x, max_comp_len=%d, filesys flags=0x%08x, vol name=%s, filesys name=%s\n", + Root_Dir1, vol_serial_num, max_comp_len, fs_flags, vol_name_buf, fs_name_buf); + } + + /* try again with dirve letter and the "disable parsing" prefix */ + ret = pGetVolumeInformationA(Root_Dir2, vol_name_buf, vol_name_size, + &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len); + todo_wine ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Dir2, GetLastError()); + if (ret) { + trace("for %s, vol_serial_num=0x%08x, max_comp_len=%d, filesys flags=0x%08x, vol name=%s, filesys name=%s\n", + Root_Dir2, vol_serial_num, max_comp_len, fs_flags, vol_name_buf, fs_name_buf); + } + + /* try again with unique voluem name */ + ret = pGetVolumeInformationA(volume, vol_name_buf, vol_name_size, + &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len); + todo_wine ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", volume, GetLastError()); + if (ret) { + trace("for %s, vol_serial_num=0x%08x, max_comp_len=%d, filesys flags=0x%08x, vol name=%s, filesys name=%s\n", + volume, vol_serial_num, max_comp_len, fs_flags, vol_name_buf, fs_name_buf); + } + + /* try again with device name space */ + Root_Dir2[2] = '.'; + ret = pGetVolumeInformationA(Root_Dir2, vol_name_buf, vol_name_size, + &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len); + todo_wine ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Dir2, GetLastError()); + if (ret) { + trace("for %s, vol_serial_num=0x%08x, max_comp_len=%d, filesys flags=0x%08x, vol name=%s, filesys name=%s\n", + Root_Dir2, vol_serial_num, max_comp_len, fs_flags, vol_name_buf, fs_name_buf); + } + + /* try again with a directory off the root - should generate error */ + ret = pGetVolumeInformationA(windowsdir, vol_name_buf, vol_name_size, + &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len); + todo_wine ok(!ret && GetLastError()==ERROR_DIR_NOT_ROOT, + "GetVolumeInformationA failed, root=%s, last error=%u\n", windowsdir, GetLastError()); +} + START_TEST(volume) { hdll = GetModuleHandleA("kernel32.dll"); @@ -226,6 +354,7 @@ START_TEST(volume) pFindVolumeClose = (void *) GetProcAddress(hdll, "FindVolumeClose"); pGetLogicalDriveStringsA = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsA"); pGetLogicalDriveStringsW = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsW"); + pGetVolumeInformationA = (void *) GetProcAddress(hdll, "GetVolumeInformationA"); test_query_dos_deviceA(); test_FindFirstVolume(); @@ -233,4 +362,5 @@ START_TEST(volume) test_GetVolumeNameForVolumeMountPointW(); test_GetLogicalDriveStringsA(); test_GetLogicalDriveStringsW(); + test_GetVolumeInformationA(); }