1 /*
2  * Unit test suite for drive functions.
3  *
4  * Copyright 2002 Dmitry Timoshkov
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 "precomp.h"
22 
23 static DWORD (WINAPI *pGetDiskFreeSpaceExA)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
24 
25 static void test_GetDriveTypeA(void)
26 {
27     char drive[] = "?:\\";
28     char existing_drive_letter = 0;
29     DWORD logical_drives;
30     UINT type;
31 
32     logical_drives = GetLogicalDrives();
33     ok(logical_drives != 0, "GetLogicalDrives error %d\n", GetLastError());
34 
35     for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
36     {
37         type = GetDriveTypeA(drive);
38         ok(type > DRIVE_UNKNOWN && type <= DRIVE_RAMDISK,
39            "not a valid drive %c: type %u\n", drive[0], type);
40 
41         if (!(logical_drives & 1))
42             ok(type == DRIVE_NO_ROOT_DIR,
43                "GetDriveTypeA should return DRIVE_NO_ROOT_DIR for inexistent drive %c: but not %u\n",
44                drive[0], type);
45         else if (type != DRIVE_NO_ROOT_DIR)
46             existing_drive_letter = drive[0];
47 
48         logical_drives >>= 1;
49     }
50 
51     if (!existing_drive_letter) {
52         skip("No drives found, skipping drive spec format tests.\n");
53         return;
54     }
55 
56     drive[0] = existing_drive_letter;
57     drive[2] = 0; /* C: */
58     type = GetDriveTypeA(drive);
59     ok(type > DRIVE_NO_ROOT_DIR && type <= DRIVE_RAMDISK, "got %u for drive spec '%s'\n", type, drive);
60 
61     drive[1] = '?'; /* C? */
62     type = GetDriveTypeA(drive);
63     ok(type == DRIVE_NO_ROOT_DIR, "got %u for drive spec '%s'\n", type, drive);
64 
65     drive[1] = 0; /* C */
66     type = GetDriveTypeA(drive);
67     ok(type == DRIVE_NO_ROOT_DIR, "got %u for drive spec '%s'\n", type, drive);
68 
69     drive[0] = '?'; /* the string "?" */
70     type = GetDriveTypeA(drive);
71     ok(type == DRIVE_NO_ROOT_DIR, "got %u for drive spec '%s'\n", type, drive);
72 
73     drive[0] = 0; /* the empty string */
74     type = GetDriveTypeA(drive);
75     ok(type == DRIVE_NO_ROOT_DIR, "got %u for drive spec '%s'\n", type, drive);
76 }
77 
78 static void test_GetDriveTypeW(void)
79 {
80     WCHAR drive[] = {'?',':','\\',0};
81     WCHAR existing_drive_letter = 0;
82     DWORD logical_drives;
83     UINT type;
84 
85     logical_drives = GetLogicalDrives();
86     ok(logical_drives != 0, "GetLogicalDrives error %d\n", GetLastError());
87 
88     for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
89     {
90         type = GetDriveTypeW(drive);
91         ok(type > DRIVE_UNKNOWN && type <= DRIVE_RAMDISK,
92            "not a valid drive %c: type %u\n", drive[0], type);
93 
94         if (!(logical_drives & 1))
95             ok(type == DRIVE_NO_ROOT_DIR,
96                "GetDriveTypeW should return DRIVE_NO_ROOT_DIR for inexistent drive %c: but not %u\n",
97                drive[0], type);
98         else if (type != DRIVE_NO_ROOT_DIR)
99             existing_drive_letter = drive[0];
100 
101         logical_drives >>= 1;
102     }
103 
104     if (!existing_drive_letter) {
105         skip("No drives found, skipping drive spec format tests.\n");
106         return;
107     }
108 
109     drive[0] = existing_drive_letter;
110     drive[2] = 0; /* C: */
111     type = GetDriveTypeW(drive);
112     ok(type > DRIVE_NO_ROOT_DIR && type <= DRIVE_RAMDISK, "got %u for drive spec '%s'\n",
113        type, wine_dbgstr_w(drive));
114 
115     drive[1] = '?'; /* C? */
116     type = GetDriveTypeW(drive);
117     ok(type == DRIVE_NO_ROOT_DIR, "got %u for drive spec '%s'\n", type, wine_dbgstr_w(drive));
118 
119     drive[1] = 0; /* C */
120     type = GetDriveTypeW(drive);
121     ok(type == DRIVE_NO_ROOT_DIR, "got %u for drive spec '%s'\n", type, wine_dbgstr_w(drive));
122 
123     drive[0] = '?'; /* the string "?" */
124     type = GetDriveTypeW(drive);
125     ok(type == DRIVE_NO_ROOT_DIR, "got %u for drive spec '%s'\n", type, wine_dbgstr_w(drive));
126 
127     drive[0] = 0; /* the empty string */
128     type = GetDriveTypeW(drive);
129     ok(type == DRIVE_NO_ROOT_DIR, "got %u for drive spec '%s'\n", type, wine_dbgstr_w(drive));
130 }
131 
132 static void test_GetDiskFreeSpaceA(void)
133 {
134     BOOL ret;
135     DWORD sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters;
136     char drive[] = "?:\\";
137     DWORD logical_drives;
138 
139     ret = GetDiskFreeSpaceA(NULL, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
140     ok(ret, "GetDiskFreeSpaceA error %d\n", GetLastError());
141 
142     ret = GetDiskFreeSpaceA("", &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
143     ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME),
144        "GetDiskFreeSpaceA(\"\"): ret=%d GetLastError=%d\n",
145        ret, GetLastError());
146 
147     ret = GetDiskFreeSpaceA("\\", &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
148     ok(ret, "GetDiskFreeSpaceA error %d\n", GetLastError());
149 
150     ret = GetDiskFreeSpaceA("/", &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
151     ok(ret, "GetDiskFreeSpaceA error %d\n", GetLastError());
152 
153     logical_drives = GetLogicalDrives();
154     ok(logical_drives != 0, "GetLogicalDrives error %d\n", GetLastError());
155 
156     for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
157     {
158         UINT drivetype = GetDriveTypeA(drive);
159         /* Skip floppy drives because NT pops up a MessageBox if no
160          * floppy is present
161          */
162         if (drivetype != DRIVE_REMOVABLE && drivetype != DRIVE_NO_ROOT_DIR)
163         {
164             ret = GetDiskFreeSpaceA(drive, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
165             if (!(logical_drives & 1))
166                 ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND || GetLastError() == ERROR_INVALID_DRIVE),
167                    "GetDiskFreeSpaceA(%s): ret=%d GetLastError=%d\n",
168                    drive, ret, GetLastError());
169             else
170             {
171 
172                 if (!ret)
173                     /* GetDiskFreeSpaceA() should succeed, but it can fail with too many
174                        different GetLastError() results to be usable for an ok() */
175                     trace("GetDiskFreeSpaceA(%s) failed with %d\n", drive, GetLastError());
176 
177                 if( GetVersion() & 0x80000000)
178                     /* win3.0 through winME */
179                     ok( total_clusters <= 65535,
180                             "total clusters is %d > 65535\n", total_clusters);
181                 else if (pGetDiskFreeSpaceExA) {
182                     /* NT, 2k, XP : GetDiskFreeSpace should be accurate */
183                     ULARGE_INTEGER totEx, tot, d;
184 
185                     tot.QuadPart = sectors_per_cluster;
186                     tot.QuadPart = (tot.QuadPart * bytes_per_sector) * total_clusters;
187                     ret = pGetDiskFreeSpaceExA( drive, &d, &totEx, NULL);
188 
189                     if (!ret)
190                         /* GetDiskFreeSpaceExA() should succeed, but it can fail with too many
191                            different GetLastError() results to be usable for an ok() */
192                         trace("GetDiskFreeSpaceExA(%s) failed with %d\n", drive, GetLastError());
193 
194                     ok( bytes_per_sector == 0 || /* empty cd rom drive */
195                         totEx.QuadPart <= tot.QuadPart,
196                         "GetDiskFreeSpaceA should report at least as much bytes on disk %s as GetDiskFreeSpaceExA\n", drive);
197                 }
198             }
199         }
200         logical_drives >>= 1;
201     }
202 }
203 
204 static void test_GetDiskFreeSpaceW(void)
205 {
206     BOOL ret;
207     DWORD sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters;
208     WCHAR drive[] = {'?',':','\\',0};
209     DWORD logical_drives;
210     static const WCHAR empty_pathW[] = { 0 };
211     static const WCHAR root_pathW[] = { '\\', 0 };
212     static const WCHAR unix_style_root_pathW[] = { '/', 0 };
213 
214     ret = GetDiskFreeSpaceW(NULL, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
215     if (ret == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
216     {
217         win_skip("GetDiskFreeSpaceW is not available\n");
218         return;
219     }
220     ok(ret, "GetDiskFreeSpaceW error %d\n", GetLastError());
221 
222     ret = GetDiskFreeSpaceW(empty_pathW, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
223     ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
224        "GetDiskFreeSpaceW(\"\"): ret=%d GetLastError=%d\n",
225        ret, GetLastError());
226 
227     ret = GetDiskFreeSpaceW(root_pathW, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
228     ok(ret, "GetDiskFreeSpaceW(\"\") error %d\n", GetLastError());
229 
230     ret = GetDiskFreeSpaceW(unix_style_root_pathW, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
231     ok(ret, "GetDiskFreeSpaceW error %d\n", GetLastError());
232 
233     logical_drives = GetLogicalDrives();
234     ok(logical_drives != 0, "GetLogicalDrives error %d\n", GetLastError());
235 
236     for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
237     {
238 	UINT drivetype = GetDriveTypeW(drive);
239         /* Skip floppy drives because NT4 pops up a MessageBox if no floppy is present */
240         if (drivetype != DRIVE_REMOVABLE && drivetype != DRIVE_NO_ROOT_DIR)
241         {
242             ret = GetDiskFreeSpaceW(drive, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
243             if (!(logical_drives & 1))
244                 ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
245                    "GetDiskFreeSpaceW(%c): ret=%d GetLastError=%d\n",
246                    drive[0], ret, GetLastError());
247             else if (!ret)
248                 /* GetDiskFreeSpaceW() should succeed, but it can fail with too many
249                    different GetLastError() results to be usable for an ok() */
250                 trace("GetDiskFreeSpaceW(%c) failed with %d\n", drive[0], GetLastError());
251         }
252         logical_drives >>= 1;
253     }
254 }
255 
256 START_TEST(drive)
257 {
258     HANDLE hkernel32 = GetModuleHandleA("kernel32");
259     pGetDiskFreeSpaceExA = (void *) GetProcAddress(hkernel32, "GetDiskFreeSpaceExA");
260 
261     test_GetDriveTypeA();
262     test_GetDriveTypeW();
263 
264     test_GetDiskFreeSpaceA();
265     test_GetDiskFreeSpaceW();
266 }
267