ReactOS  0.4.13-dev-257-gfabbd7c
volume.c
Go to the documentation of this file.
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 "wine/ddk/ntddcdvd.h"
26 
27 #include <pshpack1.h>
29 {
33 };
34 #include <poppack.h>
35 C_ASSERT(sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR) == 22);
36 
37 #include <pshpack1.h>
39 {
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 *pGetVolumePathNameA)(LPCSTR, LPSTR, DWORD);
57 static BOOL (WINAPI *pGetVolumePathNameW)(LPWSTR, LPWSTR, DWORD);
58 static BOOL (WINAPI *pGetVolumePathNamesForVolumeNameA)(LPCSTR, LPSTR, DWORD, LPDWORD);
59 static BOOL (WINAPI *pGetVolumePathNamesForVolumeNameW)(LPCWSTR, LPWSTR, DWORD, LPDWORD);
60 
61 /* ############################### */
62 
63 static void test_query_dos_deviceA(void)
64 {
65  char drivestr[] = "a:";
66  char *p, *buffer, buffer2[2000];
67  DWORD ret, ret2, buflen=32768;
68  BOOL found = FALSE;
69 
70  /* callers must guess the buffer size */
71  SetLastError(0xdeadbeef);
72  ret = QueryDosDeviceA( NULL, NULL, 0 );
74  "QueryDosDeviceA(no buffer): returned %u, le=%u\n", ret, GetLastError());
75 
76  buffer = HeapAlloc( GetProcessHeap(), 0, buflen );
77  SetLastError(0xdeadbeef);
78  ret = QueryDosDeviceA( NULL, buffer, buflen );
80  "QueryDosDeviceA failed to return list, last error %u\n", GetLastError());
81 
83  p = buffer;
84  for (;;) {
85  if (!strlen(p)) break;
86  ret2 = QueryDosDeviceA( p, buffer2, sizeof(buffer2) );
87  ok(ret2, "QueryDosDeviceA failed to return current mapping for %s, last error %u\n", p, GetLastError());
88  p += strlen(p) + 1;
89  if (ret <= (p-buffer)) break;
90  }
91  }
92 
93  for (;drivestr[0] <= 'z'; drivestr[0]++) {
94  /* Older W2K fails with ERROR_INSUFFICIENT_BUFFER when buflen is > 32767 */
95  ret = QueryDosDeviceA( drivestr, buffer, buflen - 1);
97  "QueryDosDeviceA failed to return current mapping for %s, last error %u\n", drivestr, GetLastError());
98  if(ret) {
99  for (p = buffer; *p; p++) *p = toupper(*p);
100  if (strstr(buffer, "HARDDISK") || strstr(buffer, "RAMDISK")) found = TRUE;
101  }
102  }
103  ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n");
104  HeapFree( GetProcessHeap(), 0, buffer );
105 }
106 
107 static void test_define_dos_deviceA(void)
108 {
109  char drivestr[3];
110  char buf[MAX_PATH];
111  DWORD ret;
112 
113  /* Find an unused drive letter */
114  drivestr[1] = ':';
115  drivestr[2] = 0;
116  for (drivestr[0] = 'a'; drivestr[0] <= 'z'; drivestr[0]++) {
117  ret = QueryDosDeviceA( drivestr, buf, sizeof(buf));
118  if (!ret) break;
119  }
120  if (drivestr[0] > 'z') {
121  skip("can't test creating a dos drive, none available\n");
122  return;
123  }
124 
125  /* Map it to point to the current directory */
126  ret = GetCurrentDirectoryA(sizeof(buf), buf);
127  ok(ret, "GetCurrentDir\n");
128 
129  ret = DefineDosDeviceA(0, drivestr, buf);
130  todo_wine
131  ok(ret, "Could not make drive %s point to %s!\n", drivestr, buf);
132 
133  if (!ret) {
134  skip("can't test removing fake drive\n");
135  } else {
137  ok(ret, "Could not remove fake drive %s!\n", drivestr);
138  }
139 }
140 
141 static void test_FindFirstVolume(void)
142 {
143  char volume[51];
144  HANDLE handle;
145 
146  /* not present before w2k */
147  if (!pFindFirstVolumeA) {
148  win_skip("FindFirstVolumeA not found\n");
149  return;
150  }
151 
152  handle = pFindFirstVolumeA( volume, 0 );
153  ok( handle == INVALID_HANDLE_VALUE, "succeeded with short buffer\n" );
154  ok( GetLastError() == ERROR_MORE_DATA || /* XP */
155  GetLastError() == ERROR_FILENAME_EXCED_RANGE, /* Vista */
156  "wrong error %u\n", GetLastError() );
157  handle = pFindFirstVolumeA( volume, 49 );
158  ok( handle == INVALID_HANDLE_VALUE, "succeeded with short buffer\n" );
159  ok( GetLastError() == ERROR_FILENAME_EXCED_RANGE, "wrong error %u\n", GetLastError() );
160  handle = pFindFirstVolumeA( volume, 51 );
161  ok( handle != INVALID_HANDLE_VALUE, "failed err %u\n", GetLastError() );
163  {
164  do
165  {
166  ok( strlen(volume) == 49, "bad volume name %s\n", volume );
167  ok( !memcmp( volume, "\\\\?\\Volume{", 11 ), "bad volume name %s\n", volume );
168  ok( !memcmp( volume + 47, "}\\", 2 ), "bad volume name %s\n", volume );
169  } while (pFindNextVolumeA( handle, volume, MAX_PATH ));
170  ok( GetLastError() == ERROR_NO_MORE_FILES, "wrong error %u\n", GetLastError() );
171  pFindVolumeClose( handle );
172  }
173 }
174 
176 {
177  BOOL ret;
178  char volume[MAX_PATH], path[] = "c:\\";
179  DWORD len = sizeof(volume), reti;
180  char temp_path[MAX_PATH];
181 
182  /* not present before w2k */
183  if (!pGetVolumeNameForVolumeMountPointA) {
184  win_skip("GetVolumeNameForVolumeMountPointA not found\n");
185  return;
186  }
187 
189  ok(reti != 0, "GetTempPathA error %d\n", GetLastError());
190  ok(reti < MAX_PATH, "temp path should fit into MAX_PATH\n");
191 
192  ret = pGetVolumeNameForVolumeMountPointA(path, volume, 0);
193  ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
195  GetLastError() == ERROR_INVALID_PARAMETER, /* Vista */
196  "wrong error, last=%d\n", GetLastError());
197 
198  if (0) { /* these crash on XP */
199  ret = pGetVolumeNameForVolumeMountPointA(path, NULL, len);
200  ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
201 
202  ret = pGetVolumeNameForVolumeMountPointA(NULL, volume, len);
203  ok(ret == FALSE, "GetVolumeNameForVolumeMountPointA succeeded\n");
204  }
205 
206  ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
207  ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
208  ok(!strncmp( volume, "\\\\?\\Volume{", 11),
209  "GetVolumeNameForVolumeMountPointA failed to return valid string <%s>\n",
210  volume);
211 
212  /* test with too small buffer */
213  ret = pGetVolumeNameForVolumeMountPointA(path, volume, 10);
215  "GetVolumeNameForVolumeMountPointA failed, wrong error returned, was %d, should be ERROR_FILENAME_EXCED_RANGE\n",
216  GetLastError());
217 
218  /* Try on an arbitrary directory */
219  /* On FAT filesystems it seems that GetLastError() is set to
220  ERROR_INVALID_FUNCTION. */
221  ret = pGetVolumeNameForVolumeMountPointA(temp_path, volume, len);
224  "GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
226 
227  /* Try on a nonexistent dos drive */
228  path[2] = 0;
229  for (;path[0] <= 'z'; path[0]++) {
231  if(!ret) break;
232  }
233  if (path[0] <= 'z')
234  {
235  path[2] = '\\';
236  ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
238  "GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
239  path, GetLastError());
240 
241  /* Try without trailing \ and on a nonexistent dos drive */
242  path[2] = 0;
243  ret = pGetVolumeNameForVolumeMountPointA(path, volume, len);
245  "GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
246  path, GetLastError());
247  }
248 }
249 
251 {
252  BOOL ret;
253  WCHAR volume[MAX_PATH], path[] = {'c',':','\\',0};
254  DWORD len = sizeof(volume) / sizeof(WCHAR);
255 
256  /* not present before w2k */
257  if (!pGetVolumeNameForVolumeMountPointW) {
258  win_skip("GetVolumeNameForVolumeMountPointW not found\n");
259  return;
260  }
261 
262  ret = pGetVolumeNameForVolumeMountPointW(path, volume, 0);
263  ok(ret == FALSE, "GetVolumeNameForVolumeMountPointW succeeded\n");
265  GetLastError() == ERROR_INVALID_PARAMETER, /* Vista */
266  "wrong error, last=%d\n", GetLastError());
267 
268  if (0) { /* these crash on XP */
269  ret = pGetVolumeNameForVolumeMountPointW(path, NULL, len);
270  ok(ret == FALSE, "GetVolumeNameForVolumeMountPointW succeeded\n");
271 
272  ret = pGetVolumeNameForVolumeMountPointW(NULL, volume, len);
273  ok(ret == FALSE, "GetVolumeNameForVolumeMountPointW succeeded\n");
274  }
275 
276  ret = pGetVolumeNameForVolumeMountPointW(path, volume, len);
277  ok(ret == TRUE, "GetVolumeNameForVolumeMountPointW failed\n");
278 }
279 
281 {
282  UINT size, size2;
283  char *buf, *ptr;
284 
285  ok( pGetLogicalDriveStringsA != NULL, "GetLogicalDriveStringsA not available\n");
286  if(!pGetLogicalDriveStringsA) {
287  return;
288  }
289 
290  size = pGetLogicalDriveStringsA(0, NULL);
291  ok(size%4 == 1, "size = %d\n", size);
292 
293  buf = HeapAlloc(GetProcessHeap(), 0, size);
294 
295  *buf = 0;
296  size2 = pGetLogicalDriveStringsA(2, buf);
297  ok(size2 == size, "size2 = %d\n", size2);
298  ok(!*buf, "buf changed\n");
299 
300  size2 = pGetLogicalDriveStringsA(size, buf);
301  ok(size2 == size-1, "size2 = %d\n", size2);
302 
303  for(ptr = buf; ptr < buf+size2; ptr += 4) {
304  ok(('A' <= *ptr && *ptr <= 'Z'), "device name '%c' is not uppercase\n", *ptr);
305  ok(ptr[1] == ':', "ptr[1] = %c, expected ':'\n", ptr[1]);
306  ok(ptr[2] == '\\', "ptr[2] = %c expected '\\'\n", ptr[2]);
307  ok(!ptr[3], "ptr[3] = %c expected nullbyte\n", ptr[3]);
308  }
309  ok(!*ptr, "buf[size2] is not nullbyte\n");
310 
311  HeapFree(GetProcessHeap(), 0, buf);
312 }
313 
315 {
316  UINT size, size2;
317  WCHAR *buf, *ptr;
318 
319  ok( pGetLogicalDriveStringsW != NULL, "GetLogicalDriveStringsW not available\n");
320  if(!pGetLogicalDriveStringsW) {
321  return;
322  }
323 
324  SetLastError(0xdeadbeef);
325  size = pGetLogicalDriveStringsW(0, NULL);
326  if (size == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
327  win_skip("GetLogicalDriveStringsW not implemented\n");
328  return;
329  }
330  ok(size%4 == 1, "size = %d\n", size);
331 
332  buf = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
333 
334  *buf = 0;
335  size2 = pGetLogicalDriveStringsW(2, buf);
336  ok(size2 == size, "size2 = %d\n", size2);
337  ok(!*buf, "buf changed\n");
338 
339  size2 = pGetLogicalDriveStringsW(size, buf);
340  ok(size2 == size-1, "size2 = %d\n", size2);
341 
342  for(ptr = buf; ptr < buf+size2; ptr += 4) {
343  ok('A' <= *ptr && *ptr <= 'Z', "device name '%c' is not uppercase\n", *ptr);
344  ok(ptr[1] == ':', "ptr[1] = %c, expected ':'\n", ptr[1]);
345  ok(ptr[2] == '\\', "ptr[2] = %c expected '\\'\n", ptr[2]);
346  ok(!ptr[3], "ptr[3] = %c expected nullbyte\n", ptr[3]);
347  }
348  ok(!*ptr, "buf[size2] is not nullbyte\n");
349 
350  HeapFree(GetProcessHeap(), 0, buf);
351 }
352 
353 static void test_GetVolumeInformationA(void)
354 {
355  BOOL ret;
356  UINT result;
357  char Root_Colon[]="C:";
358  char Root_Slash[]="C:\\";
359  char Root_UNC[]="\\\\?\\C:\\";
360  char volume[MAX_PATH+1];
361  DWORD vol_name_size=MAX_PATH+1, vol_serial_num=-1, max_comp_len=0, fs_flags=0, fs_name_len=MAX_PATH+1;
362  char vol_name_buf[MAX_PATH+1], fs_name_buf[MAX_PATH+1];
363  char windowsdir[MAX_PATH+10];
364  char currentdir[MAX_PATH+1];
365 
366  ok( pGetVolumeInformationA != NULL, "GetVolumeInformationA not found\n");
367  if(!pGetVolumeInformationA) {
368  return;
369  }
370 
371  /* get windows drive letter and update strings for testing */
372  result = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
373  ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n");
374  ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError());
375  Root_Colon[0] = windowsdir[0];
376  Root_Slash[0] = windowsdir[0];
377  Root_UNC[4] = windowsdir[0];
378 
379  result = GetCurrentDirectoryA(MAX_PATH, currentdir);
380  ok(result, "GetCurrentDirectory: error %d\n", GetLastError());
381  /* Note that GetCurrentDir yields no trailing slash for subdirs */
382 
383  /* check for NO error on no trailing \ when current dir is root dir */
384  ret = SetCurrentDirectoryA(Root_Slash);
385  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
386  ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
387  NULL, NULL, fs_name_buf, fs_name_len);
388  ok(ret, "GetVolumeInformationA root failed, last error %u\n", GetLastError());
389 
390  /* check for error on no trailing \ when current dir is subdir (windows) of queried drive */
391  ret = SetCurrentDirectoryA(windowsdir);
392  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
393  SetLastError(0xdeadbeef);
394  ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
395  NULL, NULL, fs_name_buf, fs_name_len);
397  "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
398 
399  /* reset current directory */
400  ret = SetCurrentDirectoryA(currentdir);
401  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
402 
403  if (toupper(currentdir[0]) == toupper(windowsdir[0])) {
404  skip("Please re-run from another device than %c:\n", windowsdir[0]);
405  /* FIXME: Use GetLogicalDrives to find another device to avoid this skip. */
406  } else {
407  char Root_Env[]="=C:"; /* where MS maintains the per volume directory */
408  Root_Env[1] = windowsdir[0];
409 
410  /* C:\windows becomes the current directory on drive C: */
411  /* Note that paths to subdirs are stored without trailing slash, like what GetCurrentDir yields. */
412  ret = SetEnvironmentVariableA(Root_Env, windowsdir);
413  ok(ret, "SetEnvironmentVariable %s failed\n", Root_Env);
414 
415  ret = SetCurrentDirectoryA(windowsdir);
416  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
417  ret = SetCurrentDirectoryA(currentdir);
418  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
419 
420  /* windows dir is current on the root drive, call fails */
421  SetLastError(0xdeadbeef);
422  ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
423  NULL, NULL, fs_name_buf, fs_name_len);
425  "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
426 
427  /* Try normal drive letter with trailing \ */
428  ret = pGetVolumeInformationA(Root_Slash, vol_name_buf, vol_name_size, NULL,
429  NULL, NULL, fs_name_buf, fs_name_len);
430  ok(ret, "GetVolumeInformationA with \\ failed, last error %u\n", GetLastError());
431 
432  ret = SetCurrentDirectoryA(Root_Slash);
433  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
434  ret = SetCurrentDirectoryA(currentdir);
435  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
436 
437  /* windows dir is STILL CURRENT on root drive; the call fails as before, */
438  /* proving that SetCurrentDir did not remember the other drive's directory */
439  SetLastError(0xdeadbeef);
440  ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
441  NULL, NULL, fs_name_buf, fs_name_len);
443  "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
444 
445  /* Now C:\ becomes the current directory on drive C: */
446  ret = SetEnvironmentVariableA(Root_Env, Root_Slash); /* set =C:=C:\ */
447  ok(ret, "SetEnvironmentVariable %s failed\n", Root_Env);
448 
449  /* \ is current on root drive, call succeeds */
450  ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
451  NULL, NULL, fs_name_buf, fs_name_len);
452  ok(ret, "GetVolumeInformationA failed, last error %u\n", GetLastError());
453 
454  /* again, SetCurrentDirectory on another drive does not matter */
455  ret = SetCurrentDirectoryA(Root_Slash);
456  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
457  ret = SetCurrentDirectoryA(currentdir);
458  ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
459 
460  /* \ is current on root drive, call succeeds */
461  ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
462  NULL, NULL, fs_name_buf, fs_name_len);
463  ok(ret, "GetVolumeInformationA failed, last error %u\n", GetLastError());
464  }
465 
466  /* try null root directory to return "root of the current directory" */
467  ret = pGetVolumeInformationA(NULL, vol_name_buf, vol_name_size, NULL,
468  NULL, NULL, fs_name_buf, fs_name_len);
469  ok(ret, "GetVolumeInformationA failed on null root dir, last error %u\n", GetLastError());
470 
471  /* Try normal drive letter with trailing \ */
472  ret = pGetVolumeInformationA(Root_Slash, vol_name_buf, vol_name_size,
473  &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
474  ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Slash, GetLastError());
475 
476  /* try again with drive letter and the "disable parsing" prefix */
477  SetLastError(0xdeadbeef);
478  ret = pGetVolumeInformationA(Root_UNC, vol_name_buf, vol_name_size,
479  &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
480  ok(ret, "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", Root_UNC, GetLastError());
481 
482  /* try again with device name space */
483  Root_UNC[2] = '.';
484  SetLastError(0xdeadbeef);
485  ret = pGetVolumeInformationA(Root_UNC, vol_name_buf, vol_name_size,
486  &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
487  ok(ret, "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", Root_UNC, GetLastError());
488 
489  /* try again with a directory off the root - should generate error */
490  if (windowsdir[strlen(windowsdir)-1] != '\\') strcat(windowsdir, "\\");
491  SetLastError(0xdeadbeef);
492  ret = pGetVolumeInformationA(windowsdir, vol_name_buf, vol_name_size,
493  &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
495  "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", windowsdir, GetLastError());
496  /* A subdir with trailing \ yields DIR_NOT_ROOT instead of INVALID_NAME */
497  if (windowsdir[strlen(windowsdir)-1] == '\\') windowsdir[strlen(windowsdir)-1] = 0;
498  SetLastError(0xdeadbeef);
499  ret = pGetVolumeInformationA(windowsdir, vol_name_buf, vol_name_size,
500  &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
502  "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", windowsdir, GetLastError());
503 
504  if (!pGetVolumeNameForVolumeMountPointA) {
505  win_skip("GetVolumeNameForVolumeMountPointA not found\n");
506  return;
507  }
508  /* get the unique volume name for the windows drive */
509  ret = pGetVolumeNameForVolumeMountPointA(Root_Slash, volume, MAX_PATH);
510  ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
511 
512  /* try again with unique volume name */
513  ret = pGetVolumeInformationA(volume, vol_name_buf, vol_name_size,
514  &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
515  ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", volume, GetLastError());
516 }
517 
518 /* Test to check that unique volume name from windows dir mount point */
519 /* matches at least one of the unique volume names returned from the */
520 /* FindFirstVolumeA/FindNextVolumeA list. */
521 static void test_enum_vols(void)
522 {
523  DWORD ret;
525  char Volume_1[MAX_PATH] = {0};
526  char Volume_2[MAX_PATH] = {0};
527  char path[] = "c:\\";
528  BOOL found = FALSE;
529  char windowsdir[MAX_PATH];
530 
531  if (!pGetVolumeNameForVolumeMountPointA) {
532  win_skip("GetVolumeNameForVolumeMountPointA not found\n");
533  return;
534  }
535 
536  /*get windows drive letter and update strings for testing */
537  ret = GetWindowsDirectoryA( windowsdir, sizeof(windowsdir) );
538  ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n");
539  ok(ret != 0, "GetWindowsDirectory: error %d\n", GetLastError());
540  path[0] = windowsdir[0];
541 
542  /* get the unique volume name for the windows drive */
543  ret = pGetVolumeNameForVolumeMountPointA( path, Volume_1, MAX_PATH );
544  ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
545  ok(strlen(Volume_1) == 49, "GetVolumeNameForVolumeMountPointA returned wrong length name %s\n", Volume_1);
546 
547  /* get first unique volume name of list */
548  hFind = pFindFirstVolumeA( Volume_2, MAX_PATH );
549  ok(hFind != INVALID_HANDLE_VALUE, "FindFirstVolume failed, err=%u\n",
550  GetLastError());
551  /* ReactOS */
552  if (hFind != INVALID_HANDLE_VALUE) {
553  do
554  {
555  /* validate correct length of unique volume name */
556  ok(strlen(Volume_2) == 49, "Find[First/Next]Volume returned wrong length name %s\n", Volume_1);
557  if (memcmp(Volume_1, Volume_2, 49) == 0)
558  {
559  found = TRUE;
560  break;
561  }
562  } while (pFindNextVolumeA( hFind, Volume_2, MAX_PATH ));
563  ok(found, "volume name %s not found by Find[First/Next]Volume\n", Volume_1);
564  pFindVolumeClose( hFind );
565  }
566 }
567 
568 static void test_disk_extents(void)
569 {
570  BOOL ret;
571  DWORD size;
572  HANDLE handle;
573  static DWORD data[16];
574 
577  {
578  win_skip("can't open c: drive %u\n", GetLastError());
579  return;
580  }
581  size = 0;
583  sizeof(data), &data, sizeof(data), &size, NULL );
585  {
586  win_skip("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS not supported\n");
587  CloseHandle( handle );
588  return;
589  }
590  ok(ret, "DeviceIoControl failed %u\n", GetLastError());
591  ok(size == 32, "expected 32, got %u\n", size);
592  CloseHandle( handle );
593 }
594 
595 static void test_GetVolumePathNameA(void)
596 {
597  char volume_path[MAX_PATH], cwd[MAX_PATH];
598  struct {
599  const char *file_name;
600  const char *path_name;
601  DWORD path_len;
602  DWORD error;
603  DWORD broken_error;
604  } test_paths[] = {
605  { /* test 0: NULL parameters, 0 output length */
606  NULL, NULL, 0,
607  ERROR_INVALID_PARAMETER, 0xdeadbeef /* winxp */
608  },
609  { /* test 1: empty input, NULL output, 0 output length */
610  "", NULL, 0,
611  ERROR_INVALID_PARAMETER, 0xdeadbeef /* winxp */
612  },
613  { /* test 2: valid input, NULL output, 0 output length */
614  "C:\\", NULL, 0,
616  },
617  { /* test 3: valid input, valid output, 0 output length */
618  "C:\\", "C:\\", 0,
620  },
621  { /* test 4: valid input, valid output, 1 output length */
622  "C:\\", "C:\\", 1,
624  },
625  { /* test 5: valid input, valid output, valid output length */
626  "C:\\", "C:\\", sizeof(volume_path),
628  },
629  { /* test 6: lowercase input, uppercase output, valid output length */
630  "c:\\", "C:\\", sizeof(volume_path),
632  },
633  { /* test 7: poor quality input, valid output, valid output length */
634  "C::", "C:\\", sizeof(volume_path),
636  },
637  { /* test 8: really bogus input, valid output, 1 output length */
638  "\\\\$$$", "C:\\", 1,
640  },
641  { /* test 9: a reasonable DOS path that is guaranteed to exist */
642  "C:\\windows\\system32", "C:\\", sizeof(volume_path),
644  },
645  { /* test 10: a reasonable DOS path that shouldn't exist */
646  "C:\\windows\\system32\\AnInvalidFolder", "C:\\", sizeof(volume_path),
648  },
649  { /* test 11: a reasonable NT-converted DOS path that shouldn't exist */
650  "\\\\?\\C:\\AnInvalidFolder", "\\\\?\\C:\\", sizeof(volume_path),
652  },
653  { /* test 12: an unreasonable NT-converted DOS path */
654  "\\\\?\\InvalidDrive:\\AnInvalidFolder", "\\\\?\\InvalidDrive:\\" /* win2k, winxp */,
655  sizeof(volume_path),
657  },
658  { /* test 13: an unreasonable NT volume path */
659  "\\\\?\\Volume{00000000-00-0000-0000-000000000000}\\AnInvalidFolder",
660  "\\\\?\\Volume{00000000-00-0000-0000-000000000000}\\" /* win2k, winxp */,
661  sizeof(volume_path),
663  },
664  { /* test 14: an unreasonable NT-ish path */
665  "\\\\ReallyBogus\\InvalidDrive:\\AnInvalidFolder",
666  "\\\\ReallyBogus\\InvalidDrive:\\" /* win2k, winxp */, sizeof(volume_path),
668  },
669  { /* test 15: poor quality input, valid output, valid (but short) output length */
670  "C::", "C:\\", 4,
672  },
673  { /* test 16: unused drive letter */
674  "M::", "C:\\", 4,
676  },
677  { /* test 17: an unreasonable DOS path */
678  "InvalidDrive:\\AnInvalidFolder", "%CurrentDrive%\\", sizeof(volume_path),
680  },
681  { /* test 18: a reasonable device path */
682  "\\??\\CdRom0", "%CurrentDrive%\\", sizeof(volume_path),
684  },
685  { /* test 19: an unreasonable device path */
686  "\\??\\ReallyBogus", "%CurrentDrive%\\", sizeof(volume_path),
688  },
689  { /* test 20 */
690  "C:", "C:", 2,
692  },
693  { /* test 21 */
694  "C:", "C:", 3,
696  },
697  { /* test 22 */
698  "C:\\", "C:", 2,
700  },
701  { /* test 23 */
702  "C:\\", "C:", 3,
704  },
705  { /* test 24 */
706  "C::", "C:", 2,
708  },
709  { /* test 25 */
710  "C::", "C:", 3,
712  },
713  { /* test 26 */
714  "C::", "C:\\", 4,
716  },
717  { /* test 27 */
718  "C:\\windows\\system32\\AnInvalidFolder", "C:", 3,
720  },
721  { /* test 28 */
722  "\\\\?\\C:\\AnInvalidFolder", "\\\\?\\C:", 3,
724  },
725  { /* test 29 */
726  "\\\\?\\C:\\AnInvalidFolder", "\\\\?\\C:", 6,
728  },
729  { /* test 30 */
730  "\\\\?\\C:\\AnInvalidFolder", "\\\\?\\C:", 7,
732  },
733  { /* test 31 */
734  "\\\\?\\c:\\AnInvalidFolder", "\\\\?\\c:", 7,
736  },
737  { /* test 32 */
738  "C:/", "C:\\", 4,
740  },
741  { /* test 33 */
742  "M:/", "", 4,
744  },
745  { /* test 34 */
746  "C:ABC:DEF:\\AnInvalidFolder", "C:\\", 4,
748  },
749  { /* test 35 */
750  "?:ABC:DEF:\\AnInvalidFolder", "?:\\" /* win2k, winxp */, sizeof(volume_path),
752  },
753  { /* test 36 */
754  "relative/path", "%CurrentDrive%\\", sizeof(volume_path),
756  },
757  { /* test 37 */
758  "/unix-style/absolute/path", "%CurrentDrive%\\", sizeof(volume_path),
760  },
761  { /* test 38 */
762  "\\??\\C:\\NonExistent", "%CurrentDrive%\\", sizeof(volume_path),
764  },
765  { /* test 39 */
766  "\\??\\M:\\NonExistent", "%CurrentDrive%\\", sizeof(volume_path),
768  },
769  { /* test 40 */
770  "somefile:def", "%CurrentDrive%\\", sizeof(volume_path),
772  },
773  { /* test 41 */
774  "s:omefile", "S:\\" /* win2k, winxp */, sizeof(volume_path),
776  },
777  };
778  BOOL ret, success;
779  DWORD error;
780  UINT i;
781 
782  /* GetVolumePathNameA is not present before w2k */
783  if (!pGetVolumePathNameA)
784  {
785  win_skip("required functions not found\n");
786  return;
787  }
788 
789  /* Obtain the drive of the working directory */
790  ret = GetCurrentDirectoryA( sizeof(cwd), cwd );
791  ok( ret, "Failed to obtain the current working directory.\n" );
792  cwd[2] = 0;
793  ret = SetEnvironmentVariableA( "CurrentDrive", cwd );
794  ok( ret, "Failed to set an environment variable for the current working drive.\n" );
795 
796  for (i=0; i<sizeof(test_paths)/sizeof(test_paths[0]); i++)
797  {
798  BOOL broken_ret = test_paths[i].broken_error == NO_ERROR;
799  char *output = (test_paths[i].path_name != NULL ? volume_path : NULL);
800  BOOL expected_ret = test_paths[i].error == NO_ERROR;
801 
802  volume_path[0] = 0;
803  if (test_paths[i].path_len < sizeof(volume_path))
804  volume_path[ test_paths[i].path_len ] = 0x11;
805 
806  SetLastError( 0xdeadbeef );
807  ret = pGetVolumePathNameA( test_paths[i].file_name, output, test_paths[i].path_len );
808  error = GetLastError();
809  ok(ret == expected_ret || broken(ret == broken_ret),
810  "GetVolumePathName test %d %s unexpectedly.\n",
811  i, test_paths[i].error == NO_ERROR ? "failed" : "succeeded");
812 
813  if (ret)
814  {
815  char path_name[MAX_PATH];
816 
818  /* If we succeeded then make sure the path is correct */
819  success = (strcmp( volume_path, path_name ) == 0)
820  || broken(strcasecmp( volume_path, path_name ) == 0) /* XP */;
821  ok(success, "GetVolumePathName test %d unexpectedly returned path %s (expected %s).\n",
822  i, volume_path, path_name);
823  }
824  else
825  {
826  /* On success Windows always returns ERROR_MORE_DATA, so only worry about failure */
827  success = (error == test_paths[i].error || broken(error == test_paths[i].broken_error));
828  ok(success, "GetVolumePathName test %d unexpectedly returned error 0x%x (expected 0x%x).\n",
829  i, error, test_paths[i].error);
830  }
831 
832  if (test_paths[i].path_len < sizeof(volume_path))
833  ok(volume_path[ test_paths[i].path_len ] == 0x11,
834  "GetVolumePathName test %d corrupted byte after end of buffer.\n", i);
835  }
836 }
837 
838 static void test_GetVolumePathNameW(void)
839 {
840  static WCHAR drive_c1[] = {'C',':',0};
841  static WCHAR drive_c2[] = {'C',':','\\',0};
842  WCHAR volume_path[MAX_PATH];
843  BOOL ret;
844 
845  if (!pGetVolumePathNameW)
846  {
847  win_skip("required functions not found\n");
848  return;
849  }
850 
851  volume_path[0] = 0;
852  volume_path[1] = 0x11;
853  ret = pGetVolumePathNameW( drive_c1, volume_path, 1 );
854  ok(!ret, "GetVolumePathNameW test succeeded unexpectedly.\n");
855  ok(GetLastError() == ERROR_FILENAME_EXCED_RANGE, "GetVolumePathNameW unexpectedly returned error 0x%x (expected 0x%x).\n",
857  ok(volume_path[1] == 0x11, "GetVolumePathW corrupted byte after end of buffer.\n");
858 
859  volume_path[0] = 0;
860  volume_path[2] = 0x11;
861  ret = pGetVolumePathNameW( drive_c1, volume_path, 2 );
862  ok(!ret, "GetVolumePathNameW test succeeded unexpectedly.\n");
863  ok(GetLastError() == ERROR_FILENAME_EXCED_RANGE, "GetVolumePathNameW unexpectedly returned error 0x%x (expected 0x%x).\n",
865  ok(volume_path[2] == 0x11, "GetVolumePathW corrupted byte after end of buffer.\n");
866 
867  volume_path[0] = 0;
868  volume_path[3] = 0x11;
869  ret = pGetVolumePathNameW( drive_c1, volume_path, 3 );
870  ok(ret || broken(!ret) /* win2k */, "GetVolumePathNameW test failed unexpectedly.\n");
871  ok(memcmp(volume_path, drive_c1, sizeof(drive_c1)) == 0
872  || broken(volume_path[0] == 0) /* win2k */,
873  "GetVolumePathNameW unexpectedly returned wrong path.\n");
874  ok(volume_path[3] == 0x11, "GetVolumePathW corrupted byte after end of buffer.\n");
875 
876  volume_path[0] = 0;
877  volume_path[4] = 0x11;
878  ret = pGetVolumePathNameW( drive_c1, volume_path, 4 );
879  ok(ret, "GetVolumePathNameW test failed unexpectedly.\n");
880  ok(memcmp(volume_path, drive_c2, sizeof(drive_c2)) == 0, "GetVolumePathNameW unexpectedly returned wrong path.\n");
881  ok(volume_path[4] == 0x11, "GetVolumePathW corrupted byte after end of buffer.\n");
882 }
883 
885 {
886  BOOL ret;
887  char volume[MAX_PATH], buffer[MAX_PATH];
888  DWORD len, error;
889 
890  if (!pGetVolumePathNamesForVolumeNameA || !pGetVolumeNameForVolumeMountPointA)
891  {
892  win_skip("required functions not found\n");
893  return;
894  }
895 
896  ret = pGetVolumeNameForVolumeMountPointA( "c:\\", volume, sizeof(volume) );
897  ok(ret, "failed to get volume name %u\n", GetLastError());
898  trace("c:\\ -> %s\n", volume);
899 
900  SetLastError( 0xdeadbeef );
901  ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, 0, NULL );
902  error = GetLastError();
903  ok(!ret, "expected failure\n");
904  ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
905 
906  SetLastError( 0xdeadbeef );
907  ret = pGetVolumePathNamesForVolumeNameA( "", NULL, 0, NULL );
908  error = GetLastError();
909  ok(!ret, "expected failure\n");
910  ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
911 
912  SetLastError( 0xdeadbeef );
913  ret = pGetVolumePathNamesForVolumeNameA( volume, NULL, 0, NULL );
914  error = GetLastError();
915  ok(!ret, "expected failure\n");
916  ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
917 
918  SetLastError( 0xdeadbeef );
919  ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, 0, NULL );
920  error = GetLastError();
921  ok(!ret, "expected failure\n");
922  ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
923 
924  memset( buffer, 0xff, sizeof(buffer) );
925  ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, sizeof(buffer), NULL );
926  ok(ret, "failed to get path names %u\n", GetLastError());
927  ok(!strcmp( "C:\\", buffer ), "expected \"\\C:\" got \"%s\"\n", buffer);
928  ok(!buffer[4], "expected double null-terminated buffer\n");
929 
930  len = 0;
931  SetLastError( 0xdeadbeef );
932  ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, 0, &len );
933  error = GetLastError();
934  ok(!ret, "expected failure\n");
935  ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
936 
937  len = 0;
938  SetLastError( 0xdeadbeef );
939  ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, sizeof(buffer), &len );
940  error = GetLastError();
941  ok(!ret, "expected failure\n");
942  ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
943 
944  len = 0;
945  SetLastError( 0xdeadbeef );
946  ret = pGetVolumePathNamesForVolumeNameA( NULL, buffer, sizeof(buffer), &len );
947  error = GetLastError();
948  ok(!ret, "expected failure\n");
949  ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
950 
951  len = 0;
952  SetLastError( 0xdeadbeef );
953  ret = pGetVolumePathNamesForVolumeNameA( NULL, buffer, sizeof(buffer), &len );
954  error = GetLastError();
955  ok(!ret, "expected failure\n");
956  ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
957 
958  len = 0;
959  memset( buffer, 0xff, sizeof(buffer) );
960  ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, sizeof(buffer), &len );
961  ok(ret, "failed to get path names %u\n", GetLastError());
962  ok(len == 5 || broken(len == 2), "expected 5 got %u\n", len);
963  ok(!strcmp( "C:\\", buffer ), "expected \"\\C:\" got \"%s\"\n", buffer);
964  ok(!buffer[4], "expected double null-terminated buffer\n");
965 }
966 
968 {
969  static const WCHAR empty[] = {0};
970  static const WCHAR drive_c[] = {'c',':','\\',0};
971  static const WCHAR volume_null[] = {'\\','\\','?','\\','V','o','l','u','m','e',
972  '{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0','0',
973  '-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}','\\',0};
974  BOOL ret;
976  DWORD len, error;
977 
978 #ifdef __REACTOS__
979  /* due to failing all calls to GetVolumeNameForVolumeMountPointW, this
980  * buffer never gets initialized and could cause a buffer overflow later */
981  volume[0] = '$';
982  volume[1] = 0;
983 #endif /* __REACTOS__ */
984 
985  if (!pGetVolumePathNamesForVolumeNameW || !pGetVolumeNameForVolumeMountPointW)
986  {
987  win_skip("required functions not found\n");
988  return;
989  }
990 
991  ret = pGetVolumeNameForVolumeMountPointW( drive_c, volume, sizeof(volume)/sizeof(volume[0]) );
992  ok(ret, "failed to get volume name %u\n", GetLastError());
993 
994  SetLastError( 0xdeadbeef );
995  ret = pGetVolumePathNamesForVolumeNameW( empty, NULL, 0, NULL );
996  error = GetLastError();
997  ok(!ret, "expected failure\n");
998  ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
999 
1000  SetLastError( 0xdeadbeef );
1001  ret = pGetVolumePathNamesForVolumeNameW( volume, NULL, 0, NULL );
1002  error = GetLastError();
1003  ok(!ret, "expected failure\n");
1004  ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
1005 
1006  SetLastError( 0xdeadbeef );
1007  ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, 0, NULL );
1008  error = GetLastError();
1009  ok(!ret, "expected failure\n");
1010  ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
1011 
1012  if (0) { /* crash */
1013  ret = pGetVolumePathNamesForVolumeNameW( volume, NULL, sizeof(buffer), NULL );
1014  ok(ret, "failed to get path names %u\n", GetLastError());
1015  }
1016 
1017  ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), NULL );
1018  ok(ret, "failed to get path names %u\n", GetLastError());
1019 
1020  len = 0;
1021  memset( buffer, 0xff, sizeof(buffer) );
1022  ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
1023  ok(ret, "failed to get path names %u\n", GetLastError());
1024  ok(len == 5, "expected 5 got %u\n", len);
1025  ok(!buffer[4], "expected double null-terminated buffer\n");
1026 
1027  len = 0;
1028  volume[1] = '?';
1029  volume[lstrlenW( volume ) - 1] = 0;
1030  SetLastError( 0xdeadbeef );
1031  ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
1032  error = GetLastError();
1033  ok(!ret, "expected failure\n");
1034  ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
1035 
1036  len = 0;
1037  volume[0] = '\\';
1038  volume[1] = 0;
1039  SetLastError( 0xdeadbeef );
1040  ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
1041  error = GetLastError();
1042  ok(!ret, "expected failure\n");
1043  todo_wine ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
1044 
1045  len = 0;
1046  lstrcpyW( volume, volume_null );
1047  SetLastError( 0xdeadbeef );
1048  ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
1049  error = GetLastError();
1050  ok(!ret, "expected failure\n");
1051  ok(error == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND got %u\n", error);
1052 }
1053 
1055 {
1056  int i;
1057  DWORD nbBytes;
1058  BOOL ret;
1059  DVD_READ_STRUCTURE dvdReadStructure;
1060  DVD_LAYER_DESCRIPTOR dvdLayerDescriptor;
1061  struct COMPLETE_DVD_LAYER_DESCRIPTOR completeDvdLayerDescriptor;
1062  DVD_COPYRIGHT_DESCRIPTOR dvdCopyrightDescriptor;
1063  struct COMPLETE_DVD_MANUFACTURER_DESCRIPTOR completeDvdManufacturerDescriptor;
1064 
1065  dvdReadStructure.BlockByteOffset.QuadPart = 0;
1066  dvdReadStructure.SessionId = 0;
1067  dvdReadStructure.LayerNumber = 0;
1068 
1069 
1070  /* DvdPhysicalDescriptor */
1071  dvdReadStructure.Format = 0;
1072 
1073  SetLastError(0xdeadbeef);
1074 
1075  /* Test whether this ioctl is supported */
1076  ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
1077  &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
1078 
1079  if(!ret)
1080  {
1081  skip("IOCTL_DVD_READ_STRUCTURE not supported: %u\n", GetLastError());
1082  return;
1083  }
1084 
1085  /* Confirm there is always a header before the actual data */
1086  ok( completeDvdLayerDescriptor.Header.Length == 0x0802, "Length is 0x%04x instead of 0x0802\n", completeDvdLayerDescriptor.Header.Length);
1087  ok( completeDvdLayerDescriptor.Header.Reserved[0] == 0, "Reserved[0] is %x instead of 0\n", completeDvdLayerDescriptor.Header.Reserved[0]);
1088  ok( completeDvdLayerDescriptor.Header.Reserved[1] == 0, "Reserved[1] is %x instead of 0\n", completeDvdLayerDescriptor.Header.Reserved[1]);
1089 
1090  /* TODO: Also check completeDvdLayerDescriptor.Descriptor content (via IOCTL_SCSI_PASS_THROUGH_DIRECT ?) */
1091 
1092  /* Insufficient output buffer */
1093  for(i=0; i<sizeof(DVD_DESCRIPTOR_HEADER); i++)
1094  {
1095  SetLastError(0xdeadbeef);
1096 
1097  ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
1098  &completeDvdLayerDescriptor, i, &nbBytes, NULL);
1099  ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,"IOCTL_DVD_READ_STRUCTURE should fail with small buffer\n");
1100  }
1101 
1102  SetLastError(0xdeadbeef);
1103 
1104  /* On newer version, an output buffer of sizeof(DVD_READ_STRUCTURE) size fails.
1105  I think this is to force developers to realize that there is a header before the actual content */
1106  ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
1107  &dvdLayerDescriptor, sizeof(DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
1108  ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER) || broken(ret) /* < Win7 */,
1109  "IOCTL_DVD_READ_STRUCTURE should have failed\n");
1110 
1111  SetLastError(0xdeadbeef);
1112 
1114  &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
1116  "IOCTL_DVD_READ_STRUCTURE should have failed\n");
1117 
1118  /* Test wrong input parameters */
1119  for(i=0; i<sizeof(DVD_READ_STRUCTURE); i++)
1120  {
1121  SetLastError(0xdeadbeef);
1122 
1123  ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, i,
1124  &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
1126  "IOCTL_DVD_READ_STRUCTURE should have failed\n");
1127  }
1128 
1129 
1130  /* DvdCopyrightDescriptor */
1131  dvdReadStructure.Format = 1;
1132 
1133  SetLastError(0xdeadbeef);
1134 
1135  /* Strangely, with NULL lpOutBuffer, last error is insufficient buffer, not invalid parameter as we could expect */
1136  ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
1137  NULL, sizeof(DVD_COPYRIGHT_DESCRIPTOR), &nbBytes, NULL);
1138  ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
1139 
1140  for(i=0; i<sizeof(DVD_COPYRIGHT_DESCRIPTOR); i++)
1141  {
1142  SetLastError(0xdeadbeef);
1143 
1144  ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
1145  &dvdCopyrightDescriptor, i, &nbBytes, NULL);
1146  ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
1147  }
1148 
1149 
1150  /* DvdManufacturerDescriptor */
1151  dvdReadStructure.Format = 4;
1152 
1153  SetLastError(0xdeadbeef);
1154 
1155  ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
1156  &completeDvdManufacturerDescriptor, sizeof(DVD_MANUFACTURER_DESCRIPTOR), &nbBytes, NULL);
1158  "IOCTL_DVD_READ_STRUCTURE (DvdManufacturerDescriptor) failed, last error = %u\n", GetLastError());
1159  if(!ret)
1160  return;
1161 
1162  /* Confirm there is always a header before the actual data */
1163  ok( completeDvdManufacturerDescriptor.Header.Length == 0x0802, "Length is 0x%04x instead of 0x0802\n", completeDvdManufacturerDescriptor.Header.Length);
1164  ok( completeDvdManufacturerDescriptor.Header.Reserved[0] == 0, "Reserved[0] is %x instead of 0\n", completeDvdManufacturerDescriptor.Header.Reserved[0]);
1165  ok( completeDvdManufacturerDescriptor.Header.Reserved[1] == 0, "Reserved[1] is %x instead of 0\n", completeDvdManufacturerDescriptor.Header.Reserved[1]);
1166 
1167  SetLastError(0xdeadbeef);
1168 
1169  /* Basic parameter check */
1170  ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
1171  NULL, sizeof(DVD_MANUFACTURER_DESCRIPTOR), &nbBytes, NULL);
1172  ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
1173 }
1174 
1175 static void test_cdrom_ioctl(void)
1176 {
1177  char drive_letter, drive_path[] = "A:\\", drive_full_path[] = "\\\\.\\A:";
1178  DWORD bitmask;
1179  HANDLE handle;
1180 
1181  bitmask = GetLogicalDrives();
1182  if(!bitmask)
1183  {
1184  trace("GetLogicalDrives failed : %u\n", GetLastError());
1185  return;
1186  }
1187 
1188  for(drive_letter='A'; drive_letter<='Z'; drive_letter++)
1189  {
1190  if(!(bitmask & (1 << (drive_letter-'A') )))
1191  continue;
1192 
1193  drive_path[0] = drive_letter;
1194  if(GetDriveTypeA(drive_path) != DRIVE_CDROM)
1195  {
1196  trace("Skipping %c:, not a CDROM drive.\n", drive_letter);
1197  continue;
1198  }
1199 
1200  trace("Testing with %c:\n", drive_letter);
1201 
1202  drive_full_path[4] = drive_letter;
1205  {
1206  trace("Failed to open the device : %u\n", GetLastError());
1207  continue;
1208  }
1209 
1210  /* Add your tests here */
1212 
1214  }
1215 
1216 }
1217 
1219 {
1220  hdll = GetModuleHandleA("kernel32.dll");
1221  pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hdll, "GetVolumeNameForVolumeMountPointA");
1222  pGetVolumeNameForVolumeMountPointW = (void *) GetProcAddress(hdll, "GetVolumeNameForVolumeMountPointW");
1223  pFindFirstVolumeA = (void *) GetProcAddress(hdll, "FindFirstVolumeA");
1224  pFindNextVolumeA = (void *) GetProcAddress(hdll, "FindNextVolumeA");
1225  pFindVolumeClose = (void *) GetProcAddress(hdll, "FindVolumeClose");
1226  pGetLogicalDriveStringsA = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsA");
1227  pGetLogicalDriveStringsW = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsW");
1228  pGetVolumeInformationA = (void *) GetProcAddress(hdll, "GetVolumeInformationA");
1229  pGetVolumePathNameA = (void *) GetProcAddress(hdll, "GetVolumePathNameA");
1230  pGetVolumePathNameW = (void *) GetProcAddress(hdll, "GetVolumePathNameW");
1231  pGetVolumePathNamesForVolumeNameA = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameA");
1232  pGetVolumePathNamesForVolumeNameW = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameW");
1233 
1244  test_enum_vols();
1248  test_cdrom_ioctl();
1249 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define trace(...)
Definition: kmt_test.h:217
#define ERROR_NOT_A_REPARSE_POINT
Definition: winerror.h:1288
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
#define CloseHandle
Definition: compat.h:398
UINT WINAPI GetDriveTypeA(IN LPCSTR lpRootPathName)
Definition: disk.c:468
static HINSTANCE hdll
Definition: volume.c:47
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define error(str)
Definition: mkdosfs.c:1605
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define strcasecmp
Definition: fake.h:9
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static LPDWORD
Definition: volume.c:55
#define DDD_REMOVE_DEFINITION
Definition: winbase.h:505
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
static const WCHAR empty[]
Definition: main.c:49
static void test_FindFirstVolume(void)
Definition: volume.c:141
LARGE_INTEGER BlockByteOffset
Definition: ntddcdvd.h:80
static void test_GetVolumePathNamesForVolumeNameW(void)
Definition: volume.c:967
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
GLuint buffer
Definition: glext.h:5915
DVD_SESSION_ID SessionId
Definition: ntddcdvd.h:82
C_ASSERT(sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR)==22)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
START_TEST(volume)
Definition: volume.c:1218
static void test_query_dos_deviceA(void)
Definition: volume.c:63
#define NO_ERROR
Definition: dderror.h:5
#define lstrlenW
Definition: compat.h:407
struct _DVD_DESCRIPTOR_HEADER DVD_DESCRIPTOR_HEADER
#define FILE_SHARE_READ
Definition: compat.h:125
UCHAR Reserved[2]
Definition: scsi.h:2839
static void test_GetLogicalDriveStringsW(void)
Definition: volume.c:314
static LPSTR
Definition: volume.c:48
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int BOOL
Definition: ntddk_ex.h:94
static DWORD
Definition: volume.c:48
static void test_GetVolumeNameForVolumeMountPointW(void)
Definition: volume.c:250
static PVOID ptr
Definition: dispmode.c:27
#define ok(value,...)
static void test_GetVolumeInformationA(void)
Definition: volume.c:353
static void test_enum_vols(void)
Definition: volume.c:521
smooth NULL
Definition: ftsmooth.c:416
#define ERROR_NOT_READY
Definition: winerror.h:124
#define ERROR_DIR_NOT_ROOT
Definition: winerror.h:216
DWORD WINAPI ExpandEnvironmentStringsA(IN LPCSTR lpSrc, IN LPSTR lpDst, IN DWORD nSize)
Definition: environ.c:399
const char * LPCSTR
Definition: xmlstorage.h:183
DVD_DESCRIPTOR_HEADER Header
Definition: volume.c:40
static LPWSTR
Definition: volume.c:49
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define ERROR_NO_MORE_FILES
Definition: winerror.h:121
#define OPEN_EXISTING
Definition: compat.h:426
int toupper(int c)
Definition: utclib.c:881
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
__wchar_t WCHAR
Definition: xmlstorage.h:180
static char * path_name(DOS_FILE *file)
Definition: check.c:208
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA(IN LPCSTR lpName, IN LPCSTR lpValue)
Definition: environ.c:218
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:8
DWORD WINAPI QueryDosDeviceA(LPCSTR lpDeviceName, LPSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:422
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
unsigned long DWORD
Definition: ntddk_ex.h:95
#define success(from, fromstr, to, tostr)
#define SetLastError(x)
Definition: compat.h:409
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static HANDLE(WINAPI *pFindFirstVolumeA)(LPSTR
unsigned char UCHAR
Definition: xmlstorage.h:181
int ret
static void test_GetVolumeNameForVolumeMountPointA(void)
Definition: volume.c:175
#define todo_wine
Definition: test.h:154
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2205
struct DVD_READ_STRUCTURE DVD_READ_STRUCTURE
GLenum GLsizei len
Definition: glext.h:6722
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:819
#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
Definition: ntddvol.h:41
#define GENERIC_READ
Definition: compat.h:124
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define broken(x)
Definition: _sntprintf.h:21
DWORD WINAPI GetLogicalDrives(VOID)
Definition: disk.c:110
DVD_LAYER_DESCRIPTOR Descriptor
Definition: volume.c:31
BOOL WINAPI DefineDosDeviceA(DWORD dwFlags, LPCSTR lpDeviceName, LPCSTR lpTargetPath)
Definition: dosdev.c:162
static DWORD path_len
Definition: batch.c:31
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define lstrcpyW
Definition: compat.h:406
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2053
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2145
static UINT(WINAPI *pGetLogicalDriveStringsA)(UINT
Definition: services.c:325
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2336
#define DRIVE_CDROM
Definition: winbase.h:251
DVD_MANUFACTURER_DESCRIPTOR Descriptor
Definition: volume.c:41
unsigned int UINT
Definition: ndis.h:50
static void test_dvd_read_structure(HANDLE handle)
Definition: volume.c:1054
static void test_disk_extents(void)
Definition: volume.c:568
static LPCWSTR file_name
Definition: protocol.c:146
#define skip(...)
static void test_GetVolumePathNameW(void)
Definition: volume.c:838
DVD_STRUCTURE_FORMAT Format
Definition: ntddcdvd.h:81
struct _DVD_COPYRIGHT_DESCRIPTOR DVD_COPYRIGHT_DESCRIPTOR
static void test_define_dos_deviceA(void)
Definition: volume.c:107
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:92
#define ERROR_INVALID_NAME
Definition: compat.h:93
#define GetProcAddress(x, y)
Definition: compat.h:410
static void test_cdrom_ioctl(void)
Definition: volume.c:1175
static void test_GetVolumePathNamesForVolumeNameA(void)
Definition: volume.c:884
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:399
static BOOL(WINAPI *pGetVolumeNameForVolumeMountPointA)(LPCSTR
GLfloat GLfloat p
Definition: glext.h:8902
DVD_DESCRIPTOR_HEADER Header
Definition: volume.c:30
static void test_GetVolumePathNameA(void)
Definition: volume.c:595
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
#define win_skip
Definition: test.h:141
#define HeapFree(x, y, z)
Definition: compat.h:394
LONGLONG QuadPart
Definition: typedefs.h:112
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
char temp_path[MAX_PATH]
Definition: mspatcha.c:123
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
static void test_GetLogicalDriveStringsA(void)
Definition: volume.c:280
#define IOCTL_DVD_READ_STRUCTURE
Definition: cdrw_usr.h:157