include: Assorted spelling fixes.
[wine] / dlls / kernel32 / tests / volume.c
1 /*
2  * Unit test suite for volume functions
3  *
4  * Copyright 2006 Stefan Leichter
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "wine/test.h"
22 #include "winbase.h"
23 #include "winioctl.h"
24 #include <stdio.h>
25 #include "ddk/ntddcdvd.h"
26
27 #include <pshpack1.h>
28 struct COMPLETE_DVD_LAYER_DESCRIPTOR
29 {
30     DVD_DESCRIPTOR_HEADER Header;
31     DVD_LAYER_DESCRIPTOR Descriptor;
32     UCHAR Padding;
33 };
34 #include <poppack.h>
35 C_ASSERT(sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR) == 22);
36
37 #include <pshpack1.h>
38 struct COMPLETE_DVD_MANUFACTURER_DESCRIPTOR
39 {
40     DVD_DESCRIPTOR_HEADER Header;
41     DVD_MANUFACTURER_DESCRIPTOR Descriptor;
42     UCHAR Padding;
43 };
44 #include <poppack.h>
45 C_ASSERT(sizeof(struct COMPLETE_DVD_MANUFACTURER_DESCRIPTOR) == 2053);
46
47 static HINSTANCE hdll;
48 static BOOL (WINAPI * pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD);
49 static BOOL (WINAPI * pGetVolumeNameForVolumeMountPointW)(LPCWSTR, LPWSTR, DWORD);
50 static HANDLE (WINAPI *pFindFirstVolumeA)(LPSTR,DWORD);
51 static BOOL (WINAPI *pFindNextVolumeA)(HANDLE,LPSTR,DWORD);
52 static BOOL (WINAPI *pFindVolumeClose)(HANDLE);
53 static UINT (WINAPI *pGetLogicalDriveStringsA)(UINT,LPSTR);
54 static UINT (WINAPI *pGetLogicalDriveStringsW)(UINT,LPWSTR);
55 static BOOL (WINAPI *pGetVolumeInformationA)(LPCSTR, LPSTR, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR, DWORD);
56 static BOOL (WINAPI *pGetVolumePathNamesForVolumeNameA)(LPCSTR, LPSTR, DWORD, LPDWORD);
57 static BOOL (WINAPI *pGetVolumePathNamesForVolumeNameW)(LPCWSTR, LPWSTR, DWORD, LPDWORD);
58
59 /* ############################### */
60
61 static void test_query_dos_deviceA(void)
62 {
63     char drivestr[] = "a:";
64     char *p, *buffer, buffer2[2000];
65     DWORD ret, ret2, buflen=32768;
66     BOOL found = FALSE;
67
68     /* callers must guess the buffer size */
69     SetLastError(0xdeadbeef);
70     ret = QueryDosDeviceA( NULL, NULL, 0 );
71     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
72        "QueryDosDeviceA(no buffer): returned %u, le=%u\n", ret, GetLastError());
73
74     buffer = HeapAlloc( GetProcessHeap(), 0, buflen );
75     SetLastError(0xdeadbeef);
76     ret = QueryDosDeviceA( NULL, buffer, buflen );
77     ok((ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER),
78         "QueryDosDeviceA failed to return list, last error %u\n", GetLastError());
79
80     if (ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
81         p = buffer;
82         for (;;) {
83             if (!strlen(p)) break;
84             ret2 = QueryDosDeviceA( p, buffer2, sizeof(buffer2) );
85             ok(ret2, "QueryDosDeviceA failed to return current mapping for %s, last error %u\n", p, GetLastError());
86             p += strlen(p) + 1;
87             if (ret <= (p-buffer)) break;
88         }
89     }
90
91     for (;drivestr[0] <= 'z'; drivestr[0]++) {
92         /* Older W2K fails with ERROR_INSUFFICIENT_BUFFER when buflen is > 32767 */
93         ret = QueryDosDeviceA( drivestr, buffer, buflen - 1);
94         ok(ret || GetLastError() == ERROR_FILE_NOT_FOUND,
95             "QueryDosDeviceA failed to return current mapping for %s, last error %u\n", drivestr, GetLastError());
96         if(ret) {
97             for (p = buffer; *p; p++) *p = toupper(*p);
98             if (strstr(buffer, "HARDDISK") || strstr(buffer, "RAMDISK")) found = TRUE;
99         }
100     }
101     ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n");
102     HeapFree( GetProcessHeap(), 0, buffer );
103 }
104
105 static void test_define_dos_deviceA(void)
106 {
107     char drivestr[3];
108     char buf[MAX_PATH];
109     DWORD ret;
110
111     /* Find an unused drive letter */
112     drivestr[1] = ':';
113     drivestr[2] = 0;
114     for (drivestr[0] = 'a'; drivestr[0] <= 'z'; drivestr[0]++) {
115         ret = QueryDosDeviceA( drivestr, buf, sizeof(buf));
116         if (!ret) break;
117     }
118     if (drivestr[0] > 'z') {
119         skip("can't test creating a dos drive, none available\n");
120         return;
121     }
122
123     /* Map it to point to the current directory */
124     ret = GetCurrentDirectory(sizeof(buf), buf);
125     ok(ret, "GetCurrentDir\n");
126
127     ret = DefineDosDeviceA(0, drivestr, buf);
128     todo_wine
129     ok(ret, "Could not make drive %s point to %s!\n", drivestr, buf);
130
131     if (!ret) {
132         skip("can't test removing fake drive\n");
133     } else {
134         ret = DefineDosDeviceA(DDD_REMOVE_DEFINITION, drivestr, NULL);
135         ok(ret, "Could not remove fake drive %s!\n", drivestr);
136     }
137 }
138
139 static void test_FindFirstVolume(void)
140 {
141     char volume[51];
142     HANDLE handle;
143
144     /* not present before w2k */
145     if (!pFindFirstVolumeA) {
146         win_skip("FindFirstVolumeA not found\n");
147         return;
148     }
149
150     handle = pFindFirstVolumeA( volume, 0 );
151     ok( handle == INVALID_HANDLE_VALUE, "succeeded with short buffer\n" );
152     ok( GetLastError() == ERROR_MORE_DATA ||  /* XP */
153         GetLastError() == ERROR_FILENAME_EXCED_RANGE,  /* Vista */
154         "wrong error %u\n", GetLastError() );
155     handle = pFindFirstVolumeA( volume, 49 );
156     ok( handle == INVALID_HANDLE_VALUE, "succeeded with short buffer\n" );
157     ok( GetLastError() == ERROR_FILENAME_EXCED_RANGE, "wrong error %u\n", GetLastError() );
158     handle = pFindFirstVolumeA( volume, 51 );
159     ok( handle != INVALID_HANDLE_VALUE, "failed err %u\n", GetLastError() );
160     if (handle != INVALID_HANDLE_VALUE)
161     {
162         do
163         {
164             ok( strlen(volume) == 49, "bad volume name %s\n", volume );
165             ok( !memcmp( volume, "\\\\?\\Volume{", 11 ), "bad volume name %s\n", volume );
166             ok( !memcmp( volume + 47, "}\\", 2 ), "bad volume name %s\n", volume );
167         } while (pFindNextVolumeA( handle, volume, MAX_PATH ));
168         ok( GetLastError() == ERROR_NO_MORE_FILES, "wrong error %u\n", GetLastError() );
169         pFindVolumeClose( handle );
170     }
171 }
172
173 static void test_GetVolumeNameForVolumeMountPointA(void)
174 {
175     BOOL ret;
176     char volume[MAX_PATH], path[] = "c:\\";
177     DWORD len = sizeof(volume), reti;
178     char temp_path[MAX_PATH];
179
180     /* not present before w2k */
181     if (!pGetVolumeNameForVolumeMountPointA) {
182         win_skip("GetVolumeNameForVolumeMountPointA not found\n");
183         return;
184     }
185
186     reti = GetTempPathA(MAX_PATH, temp_path);
187     ok(reti != 0, "GetTempPathA error %d\n", GetLastError());
188     ok(reti < MAX_PATH, "temp path should fit into MAX_PATH\n");
189
190     ret = pGetVolumeNameForVolumeMountPointA(path, volume, 0);
191     ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
192     ok(GetLastError() == ERROR_FILENAME_EXCED_RANGE ||
193         GetLastError() == ERROR_INVALID_PARAMETER, /* Vista */
194         "wrong error, last=%d\n", GetLastError());
195
196     if (0) { /* these crash on XP */
197     ret = pGetVolumeNameForVolumeMountPointA(path, NULL, len);
198     ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
199
200     ret = pGetVolumeNameForVolumeMountPointA(NULL, volume, len);
201     ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
202     }
203
204     ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
205     ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
206     ok(!strncmp( volume, "\\\\?\\Volume{", 11),
207         "GetVolumeNameForVolumeMountPointA failed to return valid string <%s>\n",
208         volume);
209
210     /* test with too small buffer */
211     ret = pGetVolumeNameForVolumeMountPointA(path, volume, 10);
212     ok(ret == FALSE && GetLastError() == ERROR_FILENAME_EXCED_RANGE,
213             "GetVolumeNameForVolumeMountPointA failed, wrong error returned, was %d, should be ERROR_FILENAME_EXCED_RANGE\n",
214              GetLastError());
215
216     /* Try on a arbitrary directory */
217     /* On FAT filesystems it seems that GetLastError() is set to
218        ERROR_INVALID_FUNCTION. */
219     ret = pGetVolumeNameForVolumeMountPointA(temp_path, volume, len);
220     ok(ret == FALSE && (GetLastError() == ERROR_NOT_A_REPARSE_POINT ||
221         GetLastError() == ERROR_INVALID_FUNCTION),
222         "GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
223         temp_path, GetLastError());
224
225     /* Try on a nonexistent dos drive */
226     path[2] = 0;
227     for (;path[0] <= 'z'; path[0]++) {
228         ret = QueryDosDeviceA( path, volume, len);
229         if(!ret) break;
230     }
231     if (path[0] <= 'z')
232     {
233         path[2] = '\\';
234         ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
235         ok(ret == FALSE && GetLastError() == ERROR_FILE_NOT_FOUND,
236             "GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
237             path, GetLastError());
238
239         /* Try without trailing \ and on a nonexistent dos drive  */
240         path[2] = 0;
241         ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
242         ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
243             "GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
244             path, GetLastError());
245     }
246 }
247
248 static void test_GetVolumeNameForVolumeMountPointW(void)
249 {
250     BOOL ret;
251     WCHAR volume[MAX_PATH], path[] = {'c',':','\\',0};
252     DWORD len = sizeof(volume) / sizeof(WCHAR);
253
254     /* not present before w2k */
255     if (!pGetVolumeNameForVolumeMountPointW) {
256         win_skip("GetVolumeNameForVolumeMountPointW not found\n");
257         return;
258     }
259
260     ret = pGetVolumeNameForVolumeMountPointW(path, volume, 0);
261     ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
262     ok(GetLastError() == ERROR_FILENAME_EXCED_RANGE ||
263         GetLastError() == ERROR_INVALID_PARAMETER, /* Vista */
264         "wrong error, last=%d\n", GetLastError());
265
266     if (0) { /* these crash on XP */
267     ret = pGetVolumeNameForVolumeMountPointW(path, NULL, len);
268     ok(ret == FALSE, "GetVolumeNameForVolumeMountPointW succeeded\n");
269
270     ret = pGetVolumeNameForVolumeMountPointW(NULL, volume, len);
271     ok(ret == FALSE, "GetVolumeNameForVolumeMountPointW succeeded\n");
272     }
273
274     ret = pGetVolumeNameForVolumeMountPointW(path, volume, len);
275     ok(ret == TRUE, "GetVolumeNameForVolumeMountPointW failed\n");
276 }
277
278 static void test_GetLogicalDriveStringsA(void)
279 {
280     UINT size, size2;
281     char *buf, *ptr;
282
283     ok( pGetLogicalDriveStringsA != NULL, "GetLogicalDriveStringsA not available\n");
284     if(!pGetLogicalDriveStringsA) {
285         return;
286     }
287
288     size = pGetLogicalDriveStringsA(0, NULL);
289     ok(size%4 == 1, "size = %d\n", size);
290
291     buf = HeapAlloc(GetProcessHeap(), 0, size);
292
293     *buf = 0;
294     size2 = pGetLogicalDriveStringsA(2, buf);
295     ok(size2 == size, "size2 = %d\n", size2);
296     ok(!*buf, "buf changed\n");
297
298     size2 = pGetLogicalDriveStringsA(size, buf);
299     ok(size2 == size-1, "size2 = %d\n", size2);
300
301     for(ptr = buf; ptr < buf+size2; ptr += 4) {
302         ok(('A' <= *ptr && *ptr <= 'Z'), "device name '%c' is not uppercase\n", *ptr);
303         ok(ptr[1] == ':', "ptr[1] = %c, expected ':'\n", ptr[1]);
304         ok(ptr[2] == '\\', "ptr[2] = %c expected '\\'\n", ptr[2]);
305         ok(!ptr[3], "ptr[3] = %c expected nullbyte\n", ptr[3]);
306     }
307     ok(!*ptr, "buf[size2] is not nullbyte\n");
308
309     HeapFree(GetProcessHeap(), 0, buf);
310 }
311
312 static void test_GetLogicalDriveStringsW(void)
313 {
314     UINT size, size2;
315     WCHAR *buf, *ptr;
316
317     ok( pGetLogicalDriveStringsW != NULL, "GetLogicalDriveStringsW not available\n");
318     if(!pGetLogicalDriveStringsW) {
319         return;
320     }
321
322     SetLastError(0xdeadbeef);
323     size = pGetLogicalDriveStringsW(0, NULL);
324     if (size == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
325         win_skip("GetLogicalDriveStringsW not implemented\n");
326         return;
327     }
328     ok(size%4 == 1, "size = %d\n", size);
329
330     buf = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
331
332     *buf = 0;
333     size2 = pGetLogicalDriveStringsW(2, buf);
334     ok(size2 == size, "size2 = %d\n", size2);
335     ok(!*buf, "buf changed\n");
336
337     size2 = pGetLogicalDriveStringsW(size, buf);
338     ok(size2 == size-1, "size2 = %d\n", size2);
339
340     for(ptr = buf; ptr < buf+size2; ptr += 4) {
341         ok('A' <= *ptr && *ptr <= 'Z', "device name '%c' is not uppercase\n", *ptr);
342         ok(ptr[1] == ':', "ptr[1] = %c, expected ':'\n", ptr[1]);
343         ok(ptr[2] == '\\', "ptr[2] = %c expected '\\'\n", ptr[2]);
344         ok(!ptr[3], "ptr[3] = %c expected nullbyte\n", ptr[3]);
345     }
346     ok(!*ptr, "buf[size2] is not nullbyte\n");
347
348     HeapFree(GetProcessHeap(), 0, buf);
349 }
350
351 static void test_GetVolumeInformationA(void)
352 {
353     BOOL ret;
354     UINT result;
355     char Root_Colon[]="C:";
356     char Root_Slash[]="C:\\";
357     char Root_UNC[]="\\\\?\\C:\\";
358     char volume[MAX_PATH+1];
359     DWORD vol_name_size=MAX_PATH+1, vol_serial_num=-1, max_comp_len=0, fs_flags=0, fs_name_len=MAX_PATH+1;
360     char vol_name_buf[MAX_PATH+1], fs_name_buf[MAX_PATH+1];
361     char windowsdir[MAX_PATH+10];
362     char currentdir[MAX_PATH+1];
363
364     ok( pGetVolumeInformationA != NULL, "GetVolumeInformationA not found\n");
365     if(!pGetVolumeInformationA) {
366         return;
367     }
368
369     /* get windows drive letter and update strings for testing */
370     result = GetWindowsDirectory(windowsdir, sizeof(windowsdir));
371     ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n");
372     ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError());
373     Root_Colon[0] = windowsdir[0];
374     Root_Slash[0] = windowsdir[0];
375     Root_UNC[4] = windowsdir[0];
376
377     result = GetCurrentDirectory(MAX_PATH, currentdir);
378     ok(result, "GetCurrentDirectory: error %d\n", GetLastError());
379     /* Note that GetCurrentDir yields no trailing slash for subdirs */
380
381     /* check for NO error on no trailing \ when current dir is root dir */
382     ret = SetCurrentDirectory(Root_Slash);
383     ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
384     ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
385             NULL, NULL, fs_name_buf, fs_name_len);
386     ok(ret, "GetVolumeInformationA root failed, last error %u\n", GetLastError());
387
388     /* check for error on no trailing \ when current dir is subdir (windows) of queried drive */
389     ret = SetCurrentDirectory(windowsdir);
390     ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
391     SetLastError(0xdeadbeef);
392     ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
393             NULL, NULL, fs_name_buf, fs_name_len);
394     ok(!ret && (GetLastError() == ERROR_INVALID_NAME),
395         "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
396
397     /* reset current directory */
398     ret = SetCurrentDirectory(currentdir);
399     ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
400
401     if (toupper(currentdir[0]) == toupper(windowsdir[0])) {
402         skip("Please re-run from another device than %c:\n", windowsdir[0]);
403         /* FIXME: Use GetLogicalDrives to find another device to avoid this skip. */
404     } else {
405         char Root_Env[]="=C:"; /* where MS maintains the per volume directory */
406         Root_Env[1] = windowsdir[0];
407
408         /* C:\windows becomes the current directory on drive C: */
409         /* Note that paths to subdirs are stored without trailing slash, like what GetCurrentDir yields. */
410         ret = SetEnvironmentVariable(Root_Env, windowsdir);
411         ok(ret, "SetEnvironmentVariable %s failed\n", Root_Env);
412
413         ret = SetCurrentDirectory(windowsdir);
414         ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
415         ret = SetCurrentDirectory(currentdir);
416         ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
417
418         /* windows dir is current on the root drive, call fails */
419         SetLastError(0xdeadbeef);
420         ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
421                 NULL, NULL, fs_name_buf, fs_name_len);
422         ok(!ret && (GetLastError() == ERROR_INVALID_NAME),
423            "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
424
425         /* Try normal drive letter with trailing \ */
426         ret = pGetVolumeInformationA(Root_Slash, vol_name_buf, vol_name_size, NULL,
427                 NULL, NULL, fs_name_buf, fs_name_len);
428         ok(ret, "GetVolumeInformationA with \\ failed, last error %u\n", GetLastError());
429
430         ret = SetCurrentDirectory(Root_Slash);
431         ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
432         ret = SetCurrentDirectory(currentdir);
433         ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
434
435         /* windows dir is STILL CURRENT on root drive; the call fails as before,   */
436         /* proving that SetCurrentDir did not remember the other drive's directory */
437         SetLastError(0xdeadbeef);
438         ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
439                 NULL, NULL, fs_name_buf, fs_name_len);
440         ok(!ret && (GetLastError() == ERROR_INVALID_NAME),
441            "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
442
443         /* Now C:\ becomes the current directory on drive C: */
444         ret = SetEnvironmentVariable(Root_Env, Root_Slash); /* set =C:=C:\ */
445         ok(ret, "SetEnvironmentVariable %s failed\n", Root_Env);
446
447         /* \ is current on root drive, call succeeds */
448         ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
449                 NULL, NULL, fs_name_buf, fs_name_len);
450         ok(ret, "GetVolumeInformationA failed, last error %u\n", GetLastError());
451
452         /* again, SetCurrentDirectory on another drive does not matter */
453         ret = SetCurrentDirectory(Root_Slash);
454         ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
455         ret = SetCurrentDirectory(currentdir);
456         ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
457
458         /* \ is current on root drive, call succeeds */
459         ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
460                 NULL, NULL, fs_name_buf, fs_name_len);
461         ok(ret, "GetVolumeInformationA failed, last error %u\n", GetLastError());
462     }
463
464     /* try null root directory to return "root of the current directory"  */
465     ret = pGetVolumeInformationA(NULL, vol_name_buf, vol_name_size, NULL,
466             NULL, NULL, fs_name_buf, fs_name_len);
467     ok(ret, "GetVolumeInformationA failed on null root dir, last error %u\n", GetLastError());
468
469     /* Try normal drive letter with trailing \  */
470     ret = pGetVolumeInformationA(Root_Slash, vol_name_buf, vol_name_size,
471             &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
472     ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Slash, GetLastError());
473
474     /* try again with drive letter and the "disable parsing" prefix */
475     SetLastError(0xdeadbeef);
476     ret = pGetVolumeInformationA(Root_UNC, vol_name_buf, vol_name_size,
477             &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
478     ok(ret, "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", Root_UNC, GetLastError());
479
480     /* try again with device name space  */
481     Root_UNC[2] = '.';
482     SetLastError(0xdeadbeef);
483     ret = pGetVolumeInformationA(Root_UNC, vol_name_buf, vol_name_size,
484             &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
485     ok(ret, "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", Root_UNC, GetLastError());
486
487     /* try again with a directory off the root - should generate error  */
488     if (windowsdir[strlen(windowsdir)-1] != '\\') strcat(windowsdir, "\\");
489     SetLastError(0xdeadbeef);
490     ret = pGetVolumeInformationA(windowsdir, vol_name_buf, vol_name_size,
491             &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
492     ok(!ret && (GetLastError()==ERROR_DIR_NOT_ROOT),
493           "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", windowsdir, GetLastError());
494     /* A subdir with trailing \ yields DIR_NOT_ROOT instead of INVALID_NAME */
495     if (windowsdir[strlen(windowsdir)-1] == '\\') windowsdir[strlen(windowsdir)-1] = 0;
496     SetLastError(0xdeadbeef);
497     ret = pGetVolumeInformationA(windowsdir, vol_name_buf, vol_name_size,
498             &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
499     ok(!ret && (GetLastError()==ERROR_INVALID_NAME),
500           "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", windowsdir, GetLastError());
501
502     if (!pGetVolumeNameForVolumeMountPointA) {
503         win_skip("GetVolumeNameForVolumeMountPointA not found\n");
504         return;
505     }
506     /* get the unique volume name for the windows drive  */
507     ret = pGetVolumeNameForVolumeMountPointA(Root_Slash, volume, MAX_PATH);
508     ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
509
510     /* try again with unique volume name */
511     ret = pGetVolumeInformationA(volume, vol_name_buf, vol_name_size,
512             &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
513     ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", volume, GetLastError());
514 }
515
516 /* Test to check that unique volume name from windows dir mount point  */
517 /* matches at least one of the unique volume names returned from the   */
518 /* FindFirstVolumeA/FindNextVolumeA list.                              */
519 static void test_enum_vols(void)
520 {
521     DWORD   ret;
522     HANDLE  hFind = INVALID_HANDLE_VALUE;
523     char    Volume_1[MAX_PATH] = {0};
524     char    Volume_2[MAX_PATH] = {0};
525     char    path[] = "c:\\";
526     BOOL    found = FALSE;
527     char    windowsdir[MAX_PATH];
528
529     if (!pGetVolumeNameForVolumeMountPointA) {
530         win_skip("GetVolumeNameForVolumeMountPointA not found\n");
531         return;
532     }
533
534     /*get windows drive letter and update strings for testing  */
535     ret = GetWindowsDirectory( windowsdir, sizeof(windowsdir) );
536     ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n");
537     ok(ret != 0, "GetWindowsDirecory: error %d\n", GetLastError());
538     path[0] = windowsdir[0];
539
540     /* get the unique volume name for the windows drive  */
541     ret = pGetVolumeNameForVolumeMountPointA( path, Volume_1, MAX_PATH );
542     ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
543     ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name %s\n", Volume_1);
544
545     /* get first unique volume name of list  */
546     hFind = pFindFirstVolumeA( Volume_2, MAX_PATH );
547     ok(hFind != INVALID_HANDLE_VALUE, "FindFirstVolume failed, err=%u\n",
548                 GetLastError());
549
550     do
551     {
552         /* validate correct length of unique volume name  */
553         ok(strlen(Volume_2) == 49, "Find[First/Next]Volume returned wrong length name %s\n", Volume_1);
554         if (memcmp(Volume_1, Volume_2, 49) == 0)
555         {
556             found = TRUE;
557             break;
558         }
559     } while (pFindNextVolumeA( hFind, Volume_2, MAX_PATH ));
560     ok(found, "volume name %s not found by Find[First/Next]Volume\n", Volume_1);
561     pFindVolumeClose( hFind );
562 }
563
564 static void test_disk_extents(void)
565 {
566     BOOL ret;
567     DWORD size;
568     HANDLE handle;
569     static DWORD data[16];
570
571     handle = CreateFileA( "\\\\.\\c:", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
572     if (handle == INVALID_HANDLE_VALUE)
573     {
574         win_skip("can't open c: drive %u\n", GetLastError());
575         return;
576     }
577     size = 0;
578     ret = DeviceIoControl( handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, &data,
579                            sizeof(data), &data, sizeof(data), &size, NULL );
580     if (!ret && GetLastError() == ERROR_INVALID_FUNCTION)
581     {
582         win_skip("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS not supported\n");
583         CloseHandle( handle );
584         return;
585     }
586     ok(ret, "DeviceIoControl failed %u\n", GetLastError());
587     ok(size == 32, "expected 32, got %u\n", size);
588     CloseHandle( handle );
589 }
590
591 static void test_GetVolumePathNamesForVolumeNameA(void)
592 {
593     BOOL ret;
594     char volume[MAX_PATH], buffer[MAX_PATH];
595     DWORD len, error;
596
597     if (!pGetVolumePathNamesForVolumeNameA || !pGetVolumeNameForVolumeMountPointA)
598     {
599         win_skip("required functions not found\n");
600         return;
601     }
602
603     ret = pGetVolumeNameForVolumeMountPointA( "c:\\", volume, sizeof(volume) );
604     ok(ret, "failed to get volume name %u\n", GetLastError());
605     trace("c:\\ -> %s\n", volume);
606
607     SetLastError( 0xdeadbeef );
608     ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, 0, NULL );
609     error = GetLastError();
610     ok(!ret, "expected failure\n");
611     ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
612
613     SetLastError( 0xdeadbeef );
614     ret = pGetVolumePathNamesForVolumeNameA( "", NULL, 0, NULL );
615     error = GetLastError();
616     ok(!ret, "expected failure\n");
617     ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
618
619     SetLastError( 0xdeadbeef );
620     ret = pGetVolumePathNamesForVolumeNameA( volume, NULL, 0, NULL );
621     error = GetLastError();
622     ok(!ret, "expected failure\n");
623     ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
624
625     SetLastError( 0xdeadbeef );
626     ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, 0, NULL );
627     error = GetLastError();
628     ok(!ret, "expected failure\n");
629     ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
630
631     memset( buffer, 0xff, sizeof(buffer) );
632     ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, sizeof(buffer), NULL );
633     ok(ret, "failed to get path names %u\n", GetLastError());
634     ok(!strcmp( "C:\\", buffer ), "expected \"\\C:\" got \"%s\"\n", buffer);
635     ok(!buffer[4], "expected double null-terminated buffer\n");
636
637     len = 0;
638     SetLastError( 0xdeadbeef );
639     ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, 0, &len );
640     error = GetLastError();
641     ok(!ret, "expected failure\n");
642     ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
643
644     len = 0;
645     SetLastError( 0xdeadbeef );
646     ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, sizeof(buffer), &len );
647     error = GetLastError();
648     ok(!ret, "expected failure\n");
649     ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
650
651     len = 0;
652     SetLastError( 0xdeadbeef );
653     ret = pGetVolumePathNamesForVolumeNameA( NULL, buffer, sizeof(buffer), &len );
654     error = GetLastError();
655     ok(!ret, "expected failure\n");
656     ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
657
658     len = 0;
659     SetLastError( 0xdeadbeef );
660     ret = pGetVolumePathNamesForVolumeNameA( NULL, buffer, sizeof(buffer), &len );
661     error = GetLastError();
662     ok(!ret, "expected failure\n");
663     ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
664
665     len = 0;
666     memset( buffer, 0xff, sizeof(buffer) );
667     ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, sizeof(buffer), &len );
668     ok(ret, "failed to get path names %u\n", GetLastError());
669     ok(len == 5 || broken(len == 2), "expected 5 got %u\n", len);
670     ok(!strcmp( "C:\\", buffer ), "expected \"\\C:\" got \"%s\"\n", buffer);
671     ok(!buffer[4], "expected double null-terminated buffer\n");
672 }
673
674 static void test_GetVolumePathNamesForVolumeNameW(void)
675 {
676     static const WCHAR empty[] = {0};
677     static const WCHAR drive_c[] = {'c',':','\\',0};
678     static const WCHAR volume_null[] = {'\\','\\','?','\\','V','o','l','u','m','e',
679         '{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0','0',
680         '-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}','\\',0};
681     BOOL ret;
682     WCHAR volume[MAX_PATH], buffer[MAX_PATH];
683     DWORD len, error;
684
685     if (!pGetVolumePathNamesForVolumeNameW || !pGetVolumeNameForVolumeMountPointW)
686     {
687         win_skip("required functions not found\n");
688         return;
689     }
690
691     ret = pGetVolumeNameForVolumeMountPointW( drive_c, volume, sizeof(volume)/sizeof(volume[0]) );
692     ok(ret, "failed to get volume name %u\n", GetLastError());
693
694     SetLastError( 0xdeadbeef );
695     ret = pGetVolumePathNamesForVolumeNameW( empty, NULL, 0, NULL );
696     error = GetLastError();
697     ok(!ret, "expected failure\n");
698     ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
699
700     SetLastError( 0xdeadbeef );
701     ret = pGetVolumePathNamesForVolumeNameW( volume, NULL, 0, NULL );
702     error = GetLastError();
703     ok(!ret, "expected failure\n");
704     ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
705
706     SetLastError( 0xdeadbeef );
707     ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, 0, NULL );
708     error = GetLastError();
709     ok(!ret, "expected failure\n");
710     ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
711
712     if (0) { /* crash */
713     ret = pGetVolumePathNamesForVolumeNameW( volume, NULL, sizeof(buffer), NULL );
714     ok(ret, "failed to get path names %u\n", GetLastError());
715     }
716
717     ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), NULL );
718     ok(ret, "failed to get path names %u\n", GetLastError());
719
720     len = 0;
721     memset( buffer, 0xff, sizeof(buffer) );
722     ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
723     ok(ret, "failed to get path names %u\n", GetLastError());
724     ok(len == 5, "expected 5 got %u\n", len);
725     ok(!buffer[4], "expected double null-terminated buffer\n");
726
727     len = 0;
728     volume[1] = '?';
729     volume[lstrlenW( volume ) - 1] = 0;
730     SetLastError( 0xdeadbeef );
731     ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
732     error = GetLastError();
733     ok(!ret, "expected failure\n");
734     ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
735
736     len = 0;
737     volume[0] = '\\';
738     volume[1] = 0;
739     SetLastError( 0xdeadbeef );
740     ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
741     error = GetLastError();
742     ok(!ret, "expected failure\n");
743     todo_wine ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
744
745     len = 0;
746     lstrcpyW( volume, volume_null );
747     SetLastError( 0xdeadbeef );
748     ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
749     error = GetLastError();
750     ok(!ret, "expected failure\n");
751     ok(error == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND got %u\n", error);
752 }
753
754 static void test_dvd_read_structure(HANDLE handle)
755 {
756     int i;
757     DWORD nbBytes;
758     BOOL ret;
759     DVD_READ_STRUCTURE dvdReadStructure;
760     DVD_LAYER_DESCRIPTOR dvdLayerDescriptor;
761     struct COMPLETE_DVD_LAYER_DESCRIPTOR completeDvdLayerDescriptor;
762     DVD_COPYRIGHT_DESCRIPTOR dvdCopyrightDescriptor;
763     struct COMPLETE_DVD_MANUFACTURER_DESCRIPTOR completeDvdManufacturerDescriptor;
764
765     dvdReadStructure.BlockByteOffset.QuadPart = 0;
766     dvdReadStructure.SessionId = 0;
767     dvdReadStructure.LayerNumber = 0;
768
769
770     /* DvdPhysicalDescriptor */
771     dvdReadStructure.Format = 0;
772
773     SetLastError(0xdeadbeef);
774
775     /* Test whether this ioctl is supported */
776     ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
777         &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
778     if ((!ret && GetLastError() == ERROR_INVALID_FUNCTION)
779      || (!ret && GetLastError() == ERROR_NOT_SUPPORTED))
780     {
781         skip("IOCTL_DVD_READ_STRUCTURE not supported\n");
782         return;
783     }
784
785     ok(ret || broken(GetLastError() == ERROR_NOT_READY) || broken(GetLastError() == ERROR_INVALID_PARAMETER),
786         "IOCTL_DVD_READ_STRUCTURE (DvdPhysicalDescriptor) failed, last error = %u\n", GetLastError());
787     if(!ret)
788         return;
789
790     /* Confirm there is always a header before the actual data */
791     ok( completeDvdLayerDescriptor.Header.Length == 0x0802, "Length is 0x%04x instead of 0x0802\n", completeDvdLayerDescriptor.Header.Length);
792     ok( completeDvdLayerDescriptor.Header.Reserved[0] == 0, "Reserved[0] is %x instead of 0\n", completeDvdLayerDescriptor.Header.Reserved[0]);
793     ok( completeDvdLayerDescriptor.Header.Reserved[1] == 0, "Reserved[1] is %x instead of 0\n", completeDvdLayerDescriptor.Header.Reserved[1]);
794
795     /* TODO: Also check completeDvdLayerDescriptor.Descriptor content (via IOCTL_SCSI_PASS_THROUGH_DIRECT ?) */
796
797     /* Insufficient output buffer */
798     for(i=0; i<sizeof(DVD_DESCRIPTOR_HEADER); i++)
799     {
800         SetLastError(0xdeadbeef);
801
802         ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
803             &completeDvdLayerDescriptor, i, &nbBytes, NULL);
804         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,"IOCTL_DVD_READ_STRUCTURE should fail with small buffer\n");
805     }
806
807     SetLastError(0xdeadbeef);
808
809     /* On newer version, an output buffer of sizeof(DVD_READ_STRUCTURE) size fails.
810         I think this is to force developers to realize that there is a header before the actual content */
811     ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
812         &dvdLayerDescriptor, sizeof(DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
813     ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER) || broken(ret) /* < Win7 */,
814         "IOCTL_DVD_READ_STRUCTURE should have failed\n");
815
816     SetLastError(0xdeadbeef);
817
818     ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, NULL, sizeof(DVD_READ_STRUCTURE),
819         &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
820     ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER),
821         "IOCTL_DVD_READ_STRUCTURE should have failed\n");
822
823     /* Test wrong input parameters */
824     for(i=0; i<sizeof(DVD_READ_STRUCTURE); i++)
825     {
826         SetLastError(0xdeadbeef);
827
828         ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, i,
829         &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
830         ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER),
831             "IOCTL_DVD_READ_STRUCTURE should have failed\n");
832     }
833
834
835     /* DvdCopyrightDescriptor */
836     dvdReadStructure.Format = 1;
837
838     SetLastError(0xdeadbeef);
839
840     /* Strangely, with NULL lpOutBuffer, last error is insufficient buffer, not invalid parameter as we could expect */
841     ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
842         NULL, sizeof(DVD_COPYRIGHT_DESCRIPTOR), &nbBytes, NULL);
843     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
844
845     for(i=0; i<sizeof(DVD_COPYRIGHT_DESCRIPTOR); i++)
846     {
847         SetLastError(0xdeadbeef);
848
849         ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
850             &dvdCopyrightDescriptor, i, &nbBytes, NULL);
851         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
852     }
853
854
855     /* DvdManufacturerDescriptor */
856     dvdReadStructure.Format = 4;
857
858     SetLastError(0xdeadbeef);
859
860     ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
861         &completeDvdManufacturerDescriptor, sizeof(DVD_MANUFACTURER_DESCRIPTOR), &nbBytes, NULL);
862     ok(ret || broken(GetLastError() == ERROR_NOT_READY),
863         "IOCTL_DVD_READ_STRUCTURE (DvdManufacturerDescriptor) failed, last error = %u\n", GetLastError());
864     if(!ret)
865         return;
866
867     /* Confirm there is always a header before the actual data */
868     ok( completeDvdManufacturerDescriptor.Header.Length == 0x0802, "Length is 0x%04x instead of 0x0802\n", completeDvdManufacturerDescriptor.Header.Length);
869     ok( completeDvdManufacturerDescriptor.Header.Reserved[0] == 0, "Reserved[0] is %x instead of 0\n", completeDvdManufacturerDescriptor.Header.Reserved[0]);
870     ok( completeDvdManufacturerDescriptor.Header.Reserved[1] == 0, "Reserved[1] is %x instead of 0\n", completeDvdManufacturerDescriptor.Header.Reserved[1]);
871
872     SetLastError(0xdeadbeef);
873
874     /* Basic parameter check */
875     ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
876         NULL, sizeof(DVD_MANUFACTURER_DESCRIPTOR), &nbBytes, NULL);
877     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
878 }
879
880 static void test_cdrom_ioctl(void)
881 {
882     char drive_letter, drive_path[] = "A:\\", drive_full_path[] = "\\\\.\\A:";
883     DWORD bitmask;
884     HANDLE handle;
885
886     bitmask = GetLogicalDrives();
887     if(!bitmask)
888     {
889         trace("GetLogicalDrives failed : %u\n", GetLastError());
890         return;
891     }
892
893     for(drive_letter='A'; drive_letter<='Z'; drive_letter++)
894     {
895         if(!(bitmask & (1 << (drive_letter-'A') )))
896             continue;
897
898         drive_path[0] = drive_letter;
899         if(GetDriveTypeA(drive_path) != DRIVE_CDROM)
900         {
901             trace("Skipping %c:, not a CDROM drive.\n", drive_letter);
902             continue;
903         }
904
905         trace("Testing with %c:\n", drive_letter);
906
907         drive_full_path[4] = drive_letter;
908         handle = CreateFileA(drive_full_path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
909         if(handle == INVALID_HANDLE_VALUE)
910         {
911             trace("Failed to open the device : %u\n", GetLastError());
912             continue;
913         }
914
915         /* Add your tests here */
916         test_dvd_read_structure(handle);
917
918         CloseHandle(handle);
919     }
920
921 }
922
923 START_TEST(volume)
924 {
925     hdll = GetModuleHandleA("kernel32.dll");
926     pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hdll, "GetVolumeNameForVolumeMountPointA");
927     pGetVolumeNameForVolumeMountPointW = (void *) GetProcAddress(hdll, "GetVolumeNameForVolumeMountPointW");
928     pFindFirstVolumeA = (void *) GetProcAddress(hdll, "FindFirstVolumeA");
929     pFindNextVolumeA = (void *) GetProcAddress(hdll, "FindNextVolumeA");
930     pFindVolumeClose = (void *) GetProcAddress(hdll, "FindVolumeClose");
931     pGetLogicalDriveStringsA = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsA");
932     pGetLogicalDriveStringsW = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsW");
933     pGetVolumeInformationA = (void *) GetProcAddress(hdll, "GetVolumeInformationA");
934     pGetVolumePathNamesForVolumeNameA = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameA");
935     pGetVolumePathNamesForVolumeNameW = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameW");
936
937     test_query_dos_deviceA();
938     test_define_dos_deviceA();
939     test_FindFirstVolume();
940     test_GetVolumeNameForVolumeMountPointA();
941     test_GetVolumeNameForVolumeMountPointW();
942     test_GetLogicalDriveStringsA();
943     test_GetLogicalDriveStringsW();
944     test_GetVolumeInformationA();
945     test_enum_vols();
946     test_disk_extents();
947     test_GetVolumePathNamesForVolumeNameA();
948     test_GetVolumePathNamesForVolumeNameW();
949     test_cdrom_ioctl();
950 }