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