1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
/*
 * Unit test suite for virtual substituted drive functions.
 *
 * Copyright 2011 Sam Arun Raj
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "precomp.h"

#define SUBST_DRIVE_LETTER 'M'
#define SUBST_DRIVE "M:"
#define SUBST_DRIVE_NON_EXIST_DIR "M:\\deadbeef"
#define SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR "M:\\"
#define SUBST_DRIVE_SEARCH "M:\\*"
#define SUBST_DRIVE_LOWERCASE "m:"
#define SUBST_DRIVE_LOWERCASE_SEARCH "m:\\*"
#define SUBST_DRIVE2_LETTER 'N'
#define SUBST_DRIVE2 "N:"
#define SUBST_DRIVE2_WITH_TRAILING_PATH_SEPERATOR "N:\\"
#define SUBST_DRIVE2_SEARCH "N:\\*"

static void test_DefineDosDeviceA(void)
{
    CHAR Buffer[MAX_PATH], Target[MAX_PATH];
    BOOL Result;
    UINT CharCount;
    HANDLE hnd;
    WIN32_FIND_DATAA Data;
    UINT SystemDriveType, DriveType1, DriveType2;
    DWORD dwMaskPrev, dwMaskCur;
    CHAR c;

    /* Choose the symbolic link target */
    CharCount = GetSystemWindowsDirectoryA(Target, MAX_PATH);
    ok(CharCount > 0, "Failed to get windows directory\n");
    c = Target[3];
    Target[3] = '\0';
    SystemDriveType = GetDriveTypeA(Target);
    Target[3] = c;

    /* Test with a subst drive pointing to another substed drive */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE, Target);
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    Result = DefineDosDeviceA(0, SUBST_DRIVE2, SUBST_DRIVE);
    ok(Result, "Failed to subst drive\n");
    DriveType2 = GetDriveTypeA(SUBST_DRIVE2_WITH_TRAILING_PATH_SEPERATOR);
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE2_LETTER - 'A'))), "Drive bit is not set\n");
    hnd = FindFirstFileA(SUBST_DRIVE2_SEARCH, &Data);
    ok(hnd != INVALID_HANDLE_VALUE, "Failed to open subst drive\n");
    if (hnd) FindClose(hnd);
    ok(DriveType1 == DriveType2, "subst drive types don't match\n");
    ok(DriveType1 == SystemDriveType, "subst drive types don't match\n");
    ok(DriveType2 == SystemDriveType, "subst drive types don't match\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, Target);
    ok(Result, "Failed to remove subst drive using NULL Target name\n");
    hnd = FindFirstFileA(SUBST_DRIVE2_SEARCH, &Data);
    ok(hnd == INVALID_HANDLE_VALUE, "Opened subst drive when it should fail, we removed the target\n");
    if (hnd) FindClose(hnd);
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE2, SUBST_DRIVE);
    ok(Result, "Failed to remove subst drive using NULL Target name\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    Result = QueryDosDeviceA(SUBST_DRIVE2, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test using lowercase drive letter */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE_LOWERCASE, Target);
    ok(Result, "Failed to subst drive using lowercase drive letter\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 == SystemDriveType, "subst drive types don't match\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    hnd = FindFirstFileA(SUBST_DRIVE_SEARCH, &Data);
    ok(hnd != INVALID_HANDLE_VALUE, "Failed to open subst drive\n");
    if (hnd) FindClose(hnd);
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE_LOWERCASE, Target);
    ok(Result, "Failed to remove subst drive using lowercase drive letter\n");
    Result = QueryDosDeviceA(SUBST_DRIVE_LOWERCASE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test remove without using DDD_EXACT_MATCH_ON_REMOVE */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE, Target);
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 == SystemDriveType, "subst drive types don't match\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    hnd = FindFirstFileA(SUBST_DRIVE_SEARCH, &Data);
    ok(hnd != INVALID_HANDLE_VALUE, "Failed to open subst drive\n");
    if (hnd) FindClose(hnd);
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION, SUBST_DRIVE, NULL);
    ok(Result, "Failed to remove subst drive using NULL Target name\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test multiple adds and multiple removes in add order */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp1");
    ok(Result, "Failed to subst drive\n");
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp2");
    ok(Result, "Failed to subst drive\n");
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp3");
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 != SystemDriveType, "subst drive types match when it shouldn't\n");
    ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(ERROR_FILE_NOT_FOUND), GetLastError());
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp1");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "Failed to query subst drive\n");
    if (Result) ok((_stricmp(Buffer, "\\??\\C:\\temp3") == 0), "Subst drive is not pointing to correct target\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp2");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "Failed to query subst drive\n");
    if (Result) ok((_stricmp(Buffer, "\\??\\C:\\temp3") == 0), "Subst drive is not pointing to correct target\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp3");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test multiple adds and multiple removes in reverse order */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp1");
    ok(Result, "Failed to subst drive\n");
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp2");
    ok(Result, "Failed to subst drive\n");
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp3");
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 != SystemDriveType, "subst drive types match when it shouldn't\n");
    ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(ERROR_FILE_NOT_FOUND), GetLastError());
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp3");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "Failed to query subst drive\n");
    if (Result) ok((_stricmp(Buffer, "\\??\\C:\\temp2") == 0), "Subst drive is not pointing to correct target\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp2");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "Failed to query subst drive\n");
    if (Result) ok((_stricmp(Buffer, "\\??\\C:\\temp1") == 0), "Subst drive is not pointing to correct target\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp1");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test multiple adds and multiple removes out of order */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp1");
    ok(Result, "Failed to subst drive\n");
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp2");
    ok(Result, "Failed to subst drive\n");
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp3");
    ok(Result, "Failed to subst drive\n");
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp4");
    ok(Result, "Failed to subst drive\n");
    Result = DefineDosDeviceA(0, SUBST_DRIVE, "C:\\temp5");
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 != SystemDriveType, "subst drive types match when it shouldn't\n");
    ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(ERROR_FILE_NOT_FOUND), GetLastError());
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp2");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "Failed to query subst drive\n");
    if (Result) ok((_stricmp(Buffer, "\\??\\C:\\temp5") == 0), "Subst drive is not pointing to correct target\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp5");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "Failed to query subst drive\n");
    if (Result) ok((_stricmp(Buffer, "\\??\\C:\\temp4") == 0), "Subst drive is not pointing to correct target\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp1");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "Failed to query subst drive\n");
    if (Result) ok((_stricmp(Buffer, "\\??\\C:\\temp4") == 0), "Subst drive is not pointing to correct target\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp3");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "Failed to query subst drive\n");
    if (Result) ok((_stricmp(Buffer, "\\??\\C:\\temp4") == 0), "Subst drive is not pointing to correct target");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, "C:\\temp4");
    ok(Result, "Failed to remove subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test with trailing '\' appended to TargetPath */
    dwMaskPrev = GetLogicalDrives();
    snprintf(Buffer, sizeof(Buffer), "%s\\\\\\", Target);
    Result = DefineDosDeviceA(0, SUBST_DRIVE, Buffer);
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 == SystemDriveType, "subst drive types don't match\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    hnd = FindFirstFileA(SUBST_DRIVE_SEARCH, &Data);
    ok(hnd != INVALID_HANDLE_VALUE, "Failed to open subst drive\n");
    if (hnd) FindClose(hnd);
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, Buffer);
    ok(Result, "Failed to remove subst drive using NULL Target name\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test with trailing '\' appended to TargetPath and DDD_RAW_TARGET_PATH flag */
    dwMaskPrev = GetLogicalDrives();
    snprintf(Buffer, sizeof(Buffer), "\\??\\%s\\\\\\", Target);
    Result = DefineDosDeviceA(DDD_RAW_TARGET_PATH, SUBST_DRIVE, Buffer);
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 != SystemDriveType, "subst drive types match when they shouldn't\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    hnd = FindFirstFileA(SUBST_DRIVE_SEARCH, &Data);
    ok(hnd == INVALID_HANDLE_VALUE, "Opened subst drive when it should fail\n");
    ok(GetLastError() == ERROR_INVALID_NAME, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(ERROR_INVALID_NAME), GetLastError());
    if (hnd) FindClose(hnd);
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION, SUBST_DRIVE, NULL);
    ok(Result, "Failed to remove subst drive using NULL Target name\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test using trailing \ against drive letter */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR, Target);
    ok(!Result, "Subst drive using trailing path seperator, this should not happen\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 != SystemDriveType, "subst drive types match when it shouldn't\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");
    ok(!(dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is set when it shouldn't\n");
    hnd = FindFirstFileA(SUBST_DRIVE_SEARCH, &Data);
    ok(hnd == INVALID_HANDLE_VALUE, "Opened subst drive when it should fail\n");
    if (hnd) FindClose(hnd);
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR, Target);
    ok(!Result, "Removing Subst drive using trailing path seperator passed when it should fail\n");
    Result = QueryDosDeviceA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present when it should not be created in the first place\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test using arbitary string, not necessarily a DOS drive letter */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, "!QHello:", Target);
    ok(Result, "Failed to subst drive using non-DOS drive name\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, "!QHello:", Target);
    ok(Result, "Failed to subst drive using non-DOS drive name\n");
    Result = QueryDosDeviceA("!QHello:", Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test by subst a drive to itself */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE, SUBST_DRIVE);
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 != SystemDriveType, "subst drive types match when it shouldn't\n");
    ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(ERROR_FILE_NOT_FOUND), GetLastError());
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    hnd = FindFirstFileA(SUBST_DRIVE_SEARCH, &Data);
    ok(hnd == INVALID_HANDLE_VALUE, "Opened subst drive when it should fail\n");
    if (hnd) FindClose(hnd);
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, SUBST_DRIVE);
    ok(Result, "Failed to remove subst drive using lowercase drive letter\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");

    /* Test by subst a drive to an non-existent folder under itself */
    dwMaskPrev = GetLogicalDrives();
    Result = DefineDosDeviceA(0, SUBST_DRIVE, SUBST_DRIVE_NON_EXIST_DIR);
    ok(Result, "Failed to subst drive\n");
    DriveType1 = GetDriveTypeA(SUBST_DRIVE_WITH_TRAILING_PATH_SEPERATOR);
    ok(DriveType1 != SystemDriveType, "subst drive types match when it shouldn't\n");
    ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(ERROR_FILE_NOT_FOUND), GetLastError());
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur != dwMaskPrev, "Drive masks match when it shouldn't\n");
    ok((dwMaskCur & (1 << (SUBST_DRIVE_LETTER - 'A'))), "Drive bit is not set\n");
    hnd = FindFirstFileA(SUBST_DRIVE_SEARCH, &Data);
    ok(hnd == INVALID_HANDLE_VALUE, "Opened subst drive when it should fail\n");
    if (hnd) FindClose(hnd);
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, SUBST_DRIVE_NON_EXIST_DIR);
    ok(Result, "Failed to remove subst drive using lowercase drive letter\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(!Result, "Subst drive is present even after remove attempt\n");
    dwMaskCur = GetLogicalDrives();
    ok(dwMaskCur == dwMaskPrev, "Drive masks don't match\n");
}

static void test_QueryDosDeviceA(void)
{
    CHAR Buffer[MAX_PATH], Target[MAX_PATH];
    BOOL Result;
    UINT CharCount;

    /* Choose the symbolic link target */
    CharCount = GetSystemWindowsDirectoryA(Target, MAX_PATH);
    ok(CharCount > 0, "Failed to get windows directory\n");

    Result = DefineDosDeviceA(0, SUBST_DRIVE, Target);
    ok(Result, "Failed to subst drive\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, 0);
    ok(!Result, "Should fail as the buffer passed is supposed to be small\n");
    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(ERROR_INSUFFICIENT_BUFFER), GetLastError());
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);
    ok(Result, "failed to get target path\n");
    ok(_strnicmp(Buffer, "\\??\\", 4) == 0, "The target returned does have correct prefix set\n");
    ok(stricmp(&Buffer[4], Target) == 0, "The target returned does not match the one set\n");
    Result = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, SUBST_DRIVE, Target);
    ok(Result, "Failed to remove subst drive using lowercase drive letter\n");
    Result = QueryDosDeviceA(SUBST_DRIVE, Buffer, MAX_PATH);<--- Result is assigned

    /* This will try to retrieve all existing MS-DOS device names */
    Result = QueryDosDeviceA(NULL, Buffer, 0);<--- Result is overwritten
    ok(!Result, "Should fail as the buffer passed is supposed to be small\n");
    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(ERROR_INSUFFICIENT_BUFFER), GetLastError());
}

START_TEST(dosdev)
{
    test_DefineDosDeviceA();
    test_QueryDosDeviceA();
}