1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test for RtlDosApplyFileIsolationRedirection_Ustr
5  * PROGRAMMER:      Giannis Adamopoulos
6  */
7 
8 #include "precomp.h"
9 
10 #define EXPECT_IN_SAME_DIR (WCHAR*)0xdead
11 
12 UNICODE_STRING DotDll = RTL_CONSTANT_STRING(L".DLL");
13 
14 struct test_data
15 {
16     int testline;
17     NTSTATUS ExpectedStatus;
18     WCHAR* Param;
19     WCHAR* ExpectedSubString;
20 };
21 
22 struct test_data Tests[] =
23 {
24     /* Not redirected file */
25     {__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"somefilesomefile", NULL},
26     {__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"ntdll.dll", NULL},
27     /* Files redirected with sxs */
28     {__LINE__, STATUS_SUCCESS, L"GDIPLUS", L"\\winsxs\\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1."},
29     {__LINE__, STATUS_SUCCESS, L"GDIPLUS.DLL", L"\\winsxs\\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1."},
30     {__LINE__, STATUS_SUCCESS, L"COMCTL32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"},
31     {__LINE__, STATUS_SUCCESS, L"comctl32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"},
32     {__LINE__, STATUS_SUCCESS, L"c:\\windows\\system32\\comctl32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"},
33     /* Files not redirected with sxs */
34     {__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"MSVCR90.DLL", NULL},
35     {__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"c:\\windows\\system32\\MSVCR90.DLL", NULL},
36     /* Files defined in the manifest, one exists, one doesn't */
37     {__LINE__, STATUS_SUCCESS, L"deptest.dll", EXPECT_IN_SAME_DIR},
38     {__LINE__, STATUS_SUCCESS, L"adllfile.dll", EXPECT_IN_SAME_DIR},
39     /* A file that exists in the same dir but isn't mentioned in the manifest */
40     {__LINE__, STATUS_SUCCESS, L"fil1.txt", EXPECT_IN_SAME_DIR},
41     /* This is a weird case; the source doesn't exist but does get redirected */
42     {__LINE__, STATUS_SUCCESS, L"c:\\windows\\system32\\gdiplus.DLL", L"\\winsxs\\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1."},
43     /* But redirecting gdiplus from a different directory doesn't work */
44     {__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"c:\\GDIPLUS.DLL", NULL},
45     {__LINE__, STATUS_SXS_KEY_NOT_FOUND, L"c:\\comctl32.DLL", NULL},
46     /* Redirection based on .local */
47     {__LINE__, STATUS_SUCCESS, L"test", EXPECT_IN_SAME_DIR},
48     {__LINE__, STATUS_SUCCESS, L"test.dll", EXPECT_IN_SAME_DIR},
49     {__LINE__, STATUS_SUCCESS, L"c:\\test.dll", EXPECT_IN_SAME_DIR},
50     /* known dlls are also covered */
51     {__LINE__, STATUS_SUCCESS, L"shell32", EXPECT_IN_SAME_DIR},
52     {__LINE__, STATUS_SUCCESS, L"shell32.dll", EXPECT_IN_SAME_DIR},
53     {__LINE__, STATUS_SUCCESS, L"c:\\shell32.dll", EXPECT_IN_SAME_DIR}
54 };
55 
_CreateActCtxFromFile(LPCWSTR FileName,int line)56 HANDLE _CreateActCtxFromFile(LPCWSTR FileName, int line)
57 {
58     ACTCTXW ActCtx = {sizeof(ACTCTX)};
59     HANDLE h;
60     WCHAR buffer[MAX_PATH] , *separator;
61 
62     ok (GetModuleFileNameW(NULL, buffer, MAX_PATH), "GetModuleFileName failed\n");
63     separator = wcsrchr(buffer, L'\\');
64     if (separator)
65         wcscpy(separator + 1, FileName);
66 
67     ActCtx.lpSource = buffer;
68 
69     SetLastError(0xdeaddead);
70     h = CreateActCtxW(&ActCtx);
71     ok_(__FILE__, line)(h != INVALID_HANDLE_VALUE, "CreateActCtx failed for %S\n", FileName);
72     // In win10 last error is unchanged and in win2k3 it is ERROR_BAD_EXE_FORMAT
73     ok_(__FILE__, line)(GetLastError() == ERROR_BAD_EXE_FORMAT || GetLastError() == 0xdeaddead, "Wrong last error %lu\n", GetLastError());
74 
75     return h;
76 }
77 
TestRedirection(void)78 void TestRedirection(void)
79 {
80     WCHAR SystemDir[MAX_PATH];
81     WCHAR TestPath[MAX_PATH];
82     WCHAR ParameterBuffer[MAX_PATH];
83     WCHAR* separator;
84     NTSTATUS Status;
85     int i;
86 
87     GetSystemDirectoryW(SystemDir, MAX_PATH);
88     GetModuleFileNameW(NULL, TestPath, MAX_PATH);
89     separator = wcsrchr(TestPath, L'\\');
90     separator++;
91     *separator = 0;
92 
93     for (i = 0; i < _countof(Tests); i ++)
94     {
95         UNICODE_STRING OriginalName, DynamicString;
96         PUNICODE_STRING StringUsed = NULL;
97 
98         if (memcmp(Tests[i].Param, L"c:\\windows\\system32", 38) == 0)
99         {
100             wcscpy(ParameterBuffer, SystemDir);
101             wcscat(ParameterBuffer, &Tests[i].Param[19]);
102         }
103         else
104         {
105             wcscpy(ParameterBuffer, Tests[i].Param);
106         }
107 
108         RtlInitUnicodeString(&OriginalName, ParameterBuffer);
109         RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
110 
111         Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
112                                                           &OriginalName,
113                                                           &DotDll,
114                                                           NULL,
115                                                           &DynamicString,
116                                                           &StringUsed,
117                                                           NULL,
118                                                           NULL,
119                                                           NULL);
120         ok(Status == Tests[i].ExpectedStatus, "%d: Status 0x%lx, expected 0x%lx\n", Tests[i].testline, Status, Tests[i].ExpectedStatus);
121 
122         if(Tests[i].ExpectedSubString && DynamicString.Buffer == NULL)
123         {
124             ok(0, "%d: Expected a returned string\n", Tests[i].testline);
125         }
126 
127         if (Tests[i].ExpectedSubString  && DynamicString.Buffer != NULL)
128         {
129             if (Tests[i].ExpectedSubString == EXPECT_IN_SAME_DIR)
130             {
131                 ok(wcsstr(DynamicString.Buffer, TestPath) != 0, "%d: Expected string %S in %S\n", Tests[i].testline, TestPath, DynamicString.Buffer);
132             }
133             else
134             {
135                 RtlDowncaseUnicodeString(&DynamicString, &DynamicString, FALSE);
136                 ok(wcsstr(DynamicString.Buffer, Tests[i].ExpectedSubString) != 0, "%d: Expected string %S in %S\n", Tests[i].testline, Tests[i].ExpectedSubString, DynamicString.Buffer);
137             }
138         }
139     }
140 }
141 
TestBuffers()142 void TestBuffers()
143 {
144     UNICODE_STRING Param, DynamicString, StaticString;
145     PUNICODE_STRING StringUsed = NULL;
146     NTSTATUS Status;
147     WCHAR buffer[MAX_PATH];
148 
149     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
150     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
151                                                       NULL,
152                                                       NULL,
153                                                       NULL,
154                                                       &DynamicString,
155                                                       &StringUsed,
156                                                       NULL,
157                                                       NULL,
158                                                       NULL);
159     ok(Status ==STATUS_INVALID_PARAMETER, "0x%lx\n", Status);
160 
161     RtlInitEmptyUnicodeString(&Param, NULL, 0);
162     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
163     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
164                                                       &Param,
165                                                       NULL,
166                                                       NULL,
167                                                       &DynamicString,
168                                                       &StringUsed,
169                                                       NULL,
170                                                       NULL,
171                                                       NULL);
172     ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%lx\n", Status);
173 
174     /* Tests for NULL termination of OriginalName */
175     Param.MaximumLength = Param.Length = 12 * sizeof(WCHAR);
176     Param.Buffer = L"comctl32.dllcrapcrap";
177     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
178     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
179                                                       &Param,
180                                                       NULL,
181                                                       NULL,
182                                                       &DynamicString,
183                                                       &StringUsed,
184                                                       NULL,
185                                                       NULL,
186                                                       NULL);
187     ok(Status ==STATUS_SUCCESS, "\n");
188 
189     /* Tests for the Extension parameter */
190     RtlInitUnicodeString(&Param, L"comctl32.dll");
191     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
192     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
193                                                       &Param,
194                                                       NULL,
195                                                       NULL,
196                                                       &DynamicString,
197                                                       &StringUsed,
198                                                       NULL,
199                                                       NULL,
200                                                       NULL);
201     ok(Status ==STATUS_SUCCESS, "\n");
202 
203     RtlInitUnicodeString(&Param, L"comctl32");
204     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
205     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
206                                                       &Param,
207                                                       NULL,
208                                                       NULL,
209                                                       &DynamicString,
210                                                       &StringUsed,
211                                                       NULL,
212                                                       NULL,
213                                                       NULL);
214     ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%lx\n", Status);
215 
216     RtlInitUnicodeString(&Param, L"comctl32");
217     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
218     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
219                                                       &Param,
220                                                       &DotDll,
221                                                       NULL,
222                                                       &DynamicString,
223                                                       &StringUsed,
224                                                       NULL,
225                                                       NULL,
226                                                       NULL);
227     ok(Status ==STATUS_SUCCESS, "\n");
228 
229     /* Tests for the DynamicString parameter */
230     RtlInitUnicodeString(&Param, L"comctl32.dll");
231     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
232     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
233                                                       &Param,
234                                                       NULL,
235                                                       NULL,
236                                                       &DynamicString,
237                                                       &StringUsed,
238                                                       NULL,
239                                                       NULL,
240                                                       NULL);
241     ok(Status ==STATUS_SUCCESS, "\n");
242     ok(DynamicString.Length >0 , "\n");
243     ok(DynamicString.MaximumLength == DynamicString.Length + sizeof(WCHAR) , "\n");
244     if (DynamicString.Buffer && DynamicString.Length)
245         ok(wcslen(DynamicString.Buffer) * sizeof(WCHAR) == DynamicString.Length, "got %d and %d\n", wcslen(DynamicString.Buffer)  * sizeof(WCHAR) , DynamicString.Length);
246     else
247         ok(DynamicString.Buffer != NULL, "Expected non NULL buffer\n");
248     ok(StringUsed == &DynamicString, "\n");
249 
250     /* Tests for the StaticString parameter */
251     wcscpy(buffer, L"comctl32.dll");
252     StaticString.Buffer = buffer;
253     StaticString.Length = sizeof(L"comctl32.dll");
254     StaticString.MaximumLength = sizeof(buffer);
255     Param = StaticString;
256     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
257                                                       &Param,
258                                                       NULL,
259                                                       &StaticString,
260                                                       NULL,
261                                                       &StringUsed,
262                                                       NULL,
263                                                       NULL,
264                                                       NULL);
265     ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%lx\n", Status);
266 
267     wcscpy(buffer, L"comctl32.dll");
268     StaticString.Buffer = buffer;
269     StaticString.Length = sizeof(L"comctl32.dll");
270     StaticString.MaximumLength = sizeof(buffer);
271     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
272                                                       &StaticString,
273                                                       NULL,
274                                                       &StaticString,
275                                                       NULL,
276                                                       &StringUsed,
277                                                       NULL,
278                                                       NULL,
279                                                       NULL);
280     ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%lx\n", Status);
281 
282     RtlInitUnicodeString(&Param, L"comctl32.dll");
283     RtlInitEmptyUnicodeString(&StaticString, buffer, sizeof(buffer));
284     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
285                                                       &Param,
286                                                       NULL,
287                                                       &StaticString,
288                                                       NULL,
289                                                       &StringUsed,
290                                                       NULL,
291                                                       NULL,
292                                                       NULL);
293     ok(Status ==STATUS_SUCCESS, "\n");
294     ok(StaticString.Length >0 , "\n");
295     ok(StaticString.MaximumLength == sizeof(buffer) , "\n");
296     if (StaticString.Buffer && StaticString.Length)
297         ok(wcslen(StaticString.Buffer) * sizeof(WCHAR) == StaticString.Length, "got %d and %d\n", wcslen(StaticString.Buffer)  * sizeof(WCHAR) , StaticString.Length);
298     else
299         ok(StaticString.Length != 0, "Expected non 0 lenght\n");
300     ok(StringUsed == &StaticString, "\n");
301 
302     RtlInitEmptyUnicodeString(&StaticString, buffer, 5 * sizeof(WCHAR));
303     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
304                                                       &Param,
305                                                       NULL,
306                                                       &StaticString,
307                                                       NULL,
308                                                       &StringUsed,
309                                                       NULL,
310                                                       NULL,
311                                                       NULL);
312     ok(Status == STATUS_BUFFER_TOO_SMALL, "0x%lx\n", Status);
313 
314     RtlInitUnicodeString(&Param, L"comctl32.dll");
315     RtlInitEmptyUnicodeString(&StaticString, buffer, sizeof(buffer));
316     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
317     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
318                                                       &Param,
319                                                       NULL,
320                                                       &StaticString,
321                                                       &DynamicString,
322                                                       &StringUsed,
323                                                       NULL,
324                                                       NULL,
325                                                       NULL);
326     ok(Status ==STATUS_SUCCESS, "\n");
327     ok(StaticString.Length >0 , "\n");
328     ok(StaticString.MaximumLength == sizeof(buffer) , "\n");
329     if (StaticString.Buffer && StaticString.Length)
330         ok(wcslen(StaticString.Buffer) * sizeof(WCHAR) == StaticString.Length, "got %d and %d\n", wcslen(StaticString.Buffer)  * sizeof(WCHAR) , StaticString.Length);
331     else
332         ok(StaticString.Length != 0, "Expected non 0 lenght\n");
333     ok(DynamicString.Buffer == NULL, "\n");
334     ok(DynamicString.Length == 0, "\n");
335     ok(DynamicString.MaximumLength == 0, "\n");
336     ok(StringUsed == &StaticString, "\n");
337 
338     /* Test a small buffer and a dynamic buffer */
339     RtlInitUnicodeString(&Param, L"comctl32.dll");
340     RtlInitEmptyUnicodeString(&StaticString, buffer, 5 * sizeof(WCHAR));
341     RtlInitEmptyUnicodeString(&DynamicString, NULL, 0);
342     StaticString.Buffer[0] = 1;
343     Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
344                                                       &Param,
345                                                       NULL,
346                                                       &StaticString,
347                                                       &DynamicString,
348                                                       &StringUsed,
349                                                       NULL,
350                                                       NULL,
351                                                       NULL);
352     ok(Status ==STATUS_SUCCESS, "\n");
353     ok(StaticString.Buffer == buffer, "\n");
354     ok(StaticString.Length == 0 , "%d\n", StaticString.Length);
355     ok(StaticString.Buffer[0] == 0, "\n");
356     ok(StaticString.MaximumLength == 5 * sizeof(WCHAR) , "%d\n", StaticString.MaximumLength);
357     ok(DynamicString.Length >0 , "\n");
358     ok(DynamicString.MaximumLength == DynamicString.Length + sizeof(WCHAR) , "\n");
359     if (DynamicString.Buffer && DynamicString.Length)
360         ok(wcslen(DynamicString.Buffer) * sizeof(WCHAR) == DynamicString.Length, "got %d and %d\n", wcslen(DynamicString.Buffer)  * sizeof(WCHAR) , DynamicString.Length);
361     else
362         ok(DynamicString.Length != 0, "Expected non 0 lenght\n");
363 
364     ok(StringUsed == &DynamicString, "\n");
365 }
366 
START_TEST(RtlDosApplyFileIsolationRedirection_Ustr)367 START_TEST(RtlDosApplyFileIsolationRedirection_Ustr)
368 {
369     int argc;
370     char **test_argv;
371     argc = winetest_get_mainargs( &test_argv );
372     if (argc >= 3)
373     {
374         HANDLE h = _CreateActCtxFromFile(L"ntdlltest.manifest", __LINE__);
375         BOOL bactivated = FALSE;
376         ULONG_PTR cookie;
377 
378         if (h != INVALID_HANDLE_VALUE)
379             bactivated = ActivateActCtx(h, &cookie);
380 
381         TestRedirection();
382         TestBuffers();
383 
384         if (bactivated)
385             DeactivateActCtx(0, cookie);
386     }
387     else
388     {
389         WCHAR TestPath[MAX_PATH];
390         WCHAR* separator;
391         STARTUPINFOW si = { sizeof(si) };
392         PROCESS_INFORMATION pi;
393         BOOL created;
394 
395         GetModuleFileNameW(NULL, TestPath, MAX_PATH);
396         separator = wcsrchr(TestPath, L'\\');
397         separator++;
398         wcscpy(separator, L"testdata\\ntdll_apitest.exe RtlDosApplyFileIsolationRedirection_Ustr DoTest");
399 
400         created = CreateProcessW(NULL, TestPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
401         ok(created, "Expected CreateProcess to succeed\n");
402         if (created)
403         {
404             winetest_wait_child_process(pi.hProcess);
405             CloseHandle(pi.hThread);
406             CloseHandle(pi.hProcess);
407         }
408     }
409 }
410