[COM_APITEST] Add a test for CLSID_ActiveDesktop
[reactos.git] / modules / rostests / apitests / kernel32 / FindActCtxSectionStringW.c
1 /*
2 * Unit test suite for virtual substituted drive functions.
3 *
4 * Copyright 2017 Giannis Adamopoulos
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 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
24
25 struct strsection_header
26 {
27 DWORD magic;
28 ULONG size;
29 DWORD unk1[3];
30 ULONG count;
31 ULONG index_offset;
32 DWORD unk2[2];
33 ULONG global_offset;
34 ULONG global_len;
35 };
36
37 struct wndclass_redirect_data
38 {
39 ULONG size;
40 DWORD res;
41 ULONG name_len;
42 ULONG name_offset; /* versioned name offset */
43 ULONG module_len;
44 ULONG module_offset; /* container name offset to the section base */
45 };
46
47 struct dllredirect_data
48 {
49 ULONG size;
50 ULONG unk;
51 DWORD res[3];
52 };
53
54 #include <pshpack1.h>
55
56 struct assemply_data
57 {
58 ULONG size;
59 DWORD ulFlags;
60 DWORD ulEncodedAssemblyIdentityLength;
61 DWORD ulEncodedAssemblyIdentityOffset; /* offset to the section base */
62 DWORD ulManifestPathType;
63 DWORD ulManifestPathLength;
64 DWORD ulManifestPathOffset; /* offset to the section base */
65 LARGE_INTEGER liManifestLastWriteTime;
66 DWORD unk3[11];
67 DWORD ulAssemblyDirectoryNameLength;
68 DWORD ulAssemblyDirectoryNameOffset; /* offset to the section base */
69 DWORD unk4[3]; /* In win10 there are two more fields */
70 };
71
72 #include <poppack.h>
73
74 HANDLE _CreateActCtxFromFile(LPCWSTR FileName, int line)
75 {
76 ACTCTXW ActCtx = {sizeof(ACTCTX)};
77 HANDLE h;
78 WCHAR buffer[MAX_PATH] , *separator;
79
80 ok (GetModuleFileNameW(NULL, buffer, MAX_PATH), "GetModuleFileName failed\n");
81 separator = wcsrchr(buffer, L'\\');
82 if (separator)
83 wcscpy(separator + 1, FileName);
84
85 ActCtx.lpSource = buffer;
86
87 SetLastError(0xdeaddead);
88 h = CreateActCtxW(&ActCtx);
89 ok_(__FILE__, line)(h != INVALID_HANDLE_VALUE, "CreateActCtx failed for %S\n", FileName);
90 // In win10 last error is unchanged and in win2k3 it is ERROR_BAD_EXE_FORMAT
91 ok_(__FILE__, line)(GetLastError() == ERROR_BAD_EXE_FORMAT || GetLastError() == 0xdeaddead, "Wrong last error %lu\n", GetLastError());
92
93 return h;
94 }
95
96 VOID _ActivateCtx(HANDLE h, ULONG_PTR *cookie, int line)
97 {
98 BOOL res;
99
100 SetLastError(0xdeaddead);
101 res = ActivateActCtx(h, cookie);
102 ok_(__FILE__, line)(res == TRUE, "ActivateActCtx failed\n");
103 ok_(__FILE__, line)(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
104 }
105
106 VOID _DeactivateCtx(ULONG_PTR cookie, int line)
107 {
108 BOOL res;
109
110 SetLastError(0xdeaddead);
111 res = DeactivateActCtx(0, cookie);
112 ok_(__FILE__, line)(res == TRUE, "DeactivateActCtx failed\n");
113 ok_(__FILE__, line)(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
114 }
115
116 void TestClassRedirection(HANDLE h, LPCWSTR ClassToTest, LPCWSTR ExpectedClassPart, LPCWSTR ExpectedModule, ULONG ExpectedClassCount)
117 {
118 ACTCTX_SECTION_KEYED_DATA KeyedData = { 0 };
119 BOOL res;
120 struct strsection_header *header;
121 struct wndclass_redirect_data *classData;
122 LPCWSTR VersionedClass, ClassLib;
123 int data_lenght;
124
125 SetLastError(0xdeaddead);
126 KeyedData.cbSize = sizeof(KeyedData);
127 res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
128 NULL,
129 ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION,
130 ClassToTest,
131 &KeyedData);
132 ok(res == TRUE, "FindActCtxSectionString failed\n");
133 ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
134
135 ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu\n", KeyedData.ulDataFormatVersion);
136 ok(KeyedData.hActCtx == h, "Wrong handle\n");
137 ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
138 ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
139 header = (struct strsection_header*)KeyedData.lpSectionBase;
140 classData = (struct wndclass_redirect_data*)KeyedData.lpData;
141
142 if(res == FALSE || KeyedData.ulDataFormatVersion != 1 || header == NULL || classData == NULL)
143 {
144 skip("Can't read data for class. Skipping\n");
145 }
146 else
147 {
148 ok(header->magic == STRSECTION_MAGIC, "%lu\n", header->magic );
149 ok(header->size == sizeof(*header), "Got %lu instead of %d\n", header->size, sizeof(*header));
150 ok(header->count == ExpectedClassCount, "Expected %lu classes, got %lu\n", ExpectedClassCount, header->count );
151
152 VersionedClass = (WCHAR*)((BYTE*)classData + classData->name_offset);
153 ClassLib = (WCHAR*)((BYTE*)header + classData->module_offset);
154 data_lenght = classData->size + classData->name_len + classData->module_len + 2*sizeof(WCHAR);
155 ok(KeyedData.ulLength == data_lenght, "Got lenght %lu instead of %d\n", KeyedData.ulLength, data_lenght);
156 ok(classData->size == sizeof(*classData), "Got %lu instead of %d\n", classData->size, sizeof(*classData));
157 ok(classData->res == 0, "Got res %lu\n", classData->res);
158 ok(classData->module_len == wcslen(ExpectedModule) * 2, "Got name len %lu, expected %d\n", classData->module_len, wcslen(ExpectedModule) *2);
159 ok(wcscmp(ClassLib, ExpectedModule) == 0, "Got %S, expected %S\n", ClassLib, ExpectedModule);
160 /* compare only if VersionedClass starts with ExpectedClassPart */
161 ok(memcmp(VersionedClass, ExpectedClassPart, sizeof(WCHAR) * wcslen(ExpectedClassPart)) == 0, "Expected %S to start with %S\n", VersionedClass, ExpectedClassPart);
162 }
163 }
164
165 VOID TestLibDependency(HANDLE h)
166 {
167 ACTCTX_SECTION_KEYED_DATA KeyedData = { 0 };
168 BOOL res;
169 struct strsection_header *SectionHeader;
170 struct dllredirect_data *redirData;
171 struct assemply_data *assemplyData;
172
173 SetLastError(0xdeaddead);
174 KeyedData.cbSize = sizeof(KeyedData);
175 res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
176 NULL,
177 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
178 L"dep1.dll",
179 &KeyedData);
180 ok(res == TRUE, "FindActCtxSectionString failed\n");
181 ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
182
183 ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu", KeyedData.ulDataFormatVersion);
184 ok(KeyedData.hActCtx == h, "Wrong handle\n");
185 ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
186 ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
187 SectionHeader = (struct strsection_header*)KeyedData.lpSectionBase;
188 redirData = (struct dllredirect_data *)KeyedData.lpData;
189
190 if(res == FALSE || KeyedData.ulDataFormatVersion != 1 || SectionHeader == NULL || redirData == NULL)
191 {
192 skip("Can't read data for dep1.dll. Skipping\n");
193 }
194 else
195 {
196 ok(SectionHeader->magic == STRSECTION_MAGIC, "%lu\n", SectionHeader->magic );
197 ok(SectionHeader->size == sizeof(*SectionHeader), "Got %lu instead of %d\n", SectionHeader->size, sizeof(*SectionHeader));
198 ok(SectionHeader->count == 2, "%lu\n", SectionHeader->count ); /* 2 dlls? */
199 ok(redirData->size == sizeof(*redirData), "Got %lu instead of %d\n", redirData->size, sizeof(*redirData));
200 }
201
202 SetLastError(0xdeaddead);
203 KeyedData.cbSize = sizeof(KeyedData);
204 res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
205 NULL,
206 ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION,
207 L"dep1",
208 &KeyedData);
209 ok(res == TRUE, "FindActCtxSectionString failed\n");
210 ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
211 ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu", KeyedData.ulDataFormatVersion);
212 ok(KeyedData.hActCtx == h, "Wrong handle\n");
213 ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
214 ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
215 SectionHeader = (struct strsection_header*)KeyedData.lpSectionBase;
216 assemplyData = (struct assemply_data*)KeyedData.lpData;;
217
218 if(res == FALSE || KeyedData.ulDataFormatVersion != 1 || SectionHeader == NULL || assemplyData == NULL)
219 {
220 skip("Can't read data for dep1. Skipping\n");
221 }
222 else
223 {
224 LPCWSTR AssemblyIdentity, ManifestPath, AssemblyDirectory;
225 int data_lenght;
226 DWORD buffer[256];
227 PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION details = (PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION)buffer;
228
229 ok(SectionHeader->magic == STRSECTION_MAGIC, "%lu\n", SectionHeader->magic );
230 ok(SectionHeader->size == sizeof(*SectionHeader), "Got %lu instead of %d\n", SectionHeader->size, sizeof(*SectionHeader));
231 ok(SectionHeader->count == 2, "%lu\n", SectionHeader->count ); /* 2 dlls? */
232
233 data_lenght = assemplyData->size +
234 assemplyData->ulEncodedAssemblyIdentityLength +
235 assemplyData->ulManifestPathLength +
236 assemplyData->ulAssemblyDirectoryNameLength + 2 * sizeof(WCHAR);
237 ok(assemplyData->size == sizeof(*assemplyData), "Got %lu instead of %d\n", assemplyData->size, sizeof(*assemplyData));
238 ok(KeyedData.ulLength == data_lenght, "Got lenght %lu instead of %d\n", KeyedData.ulLength, data_lenght);
239
240 AssemblyIdentity = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulEncodedAssemblyIdentityOffset);
241 ManifestPath = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulManifestPathOffset);
242 AssemblyDirectory = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulAssemblyDirectoryNameOffset);
243
244 /* Use AssemblyDetailedInformationInActivationContext so as to infer the contents of assemplyData */
245 res = QueryActCtxW(0, h, &KeyedData.ulAssemblyRosterIndex,
246 AssemblyDetailedInformationInActivationContext,
247 &buffer, sizeof(buffer), NULL);
248 ok(res == TRUE, "QueryActCtxW failed\n");
249 ok(assemplyData->ulFlags == details->ulFlags, "\n");
250 ok(assemplyData->ulEncodedAssemblyIdentityLength == details->ulEncodedAssemblyIdentityLength, "\n");
251 ok(assemplyData->ulManifestPathType == details->ulManifestPathType, "\n");
252 ok(assemplyData->ulManifestPathLength == details->ulManifestPathLength, "\n");
253 ok(assemplyData->ulAssemblyDirectoryNameLength == details->ulAssemblyDirectoryNameLength, "\n");
254 ok(assemplyData->liManifestLastWriteTime.QuadPart == details->liManifestLastWriteTime.QuadPart, "\n");
255
256 ok(wcscmp(ManifestPath, details->lpAssemblyManifestPath) == 0, "Expected path %S, got %S\n", details->lpAssemblyManifestPath, ManifestPath);
257 ok(wcscmp(AssemblyDirectory, details->lpAssemblyDirectoryName) == 0, "Expected path %S, got %S\n", details->lpAssemblyManifestPath, ManifestPath);
258
259 /* It looks like that AssemblyIdentity isn't null terminated */
260 ok(memcmp(AssemblyIdentity, details->lpAssemblyEncodedAssemblyIdentity, assemplyData->ulEncodedAssemblyIdentityLength) == 0, "Got wrong AssemblyIdentity\n");
261 }
262 }
263
264 START_TEST(FindActCtxSectionStringW)
265 {
266 HANDLE h, h2;
267 ULONG_PTR cookie, cookie2;
268
269 /*First run the redirection tests without using our own actctx */
270 TestClassRedirection(NULL, L"Button", L"Button", L"comctl32.dll", 27);
271 /* Something activates an activation context that mentions comctl32 but comctl32 is not loaded */
272 ok( GetModuleHandleW(L"comctl32.dll") == NULL, "Expected comctl32 not to be loaded\n");
273 ok( GetModuleHandleW(L"user32.dll") == NULL, "Expected user32 not to be loaded\n");
274
275 /* Class redirection tests */
276 h = _CreateActCtxFromFile(L"classtest.manifest", __LINE__);
277 if (h != INVALID_HANDLE_VALUE)
278 {
279 _ActivateCtx(h, &cookie, __LINE__);
280 TestClassRedirection(h, L"Button", L"2.2.2.2!Button", L"testlib.dll", 5);
281 _ActivateCtx(NULL, &cookie2, __LINE__);
282 TestClassRedirection(NULL, L"Button", L"Button", L"comctl32.dll", 27);
283 _DeactivateCtx(cookie2, __LINE__);
284 _DeactivateCtx(cookie, __LINE__);
285 }
286 else
287 {
288 skip("Failed to create context for classtest.manifest\n");
289 }
290
291 /* Class redirection tests with multiple contexts in the activation stack */
292 h2 = _CreateActCtxFromFile(L"classtest2.manifest", __LINE__);
293 if (h != INVALID_HANDLE_VALUE && h2 != INVALID_HANDLE_VALUE)
294 {
295 _ActivateCtx(h, &cookie, __LINE__);
296 _ActivateCtx(h2, &cookie2, __LINE__);
297 TestClassRedirection(NULL, L"Button", L"Button", L"comctl32.dll", 27);
298 TestClassRedirection(h2, L"MyClass", L"1.1.1.1!MyClass", L"testlib.dll", 5);
299 _DeactivateCtx(cookie2, __LINE__);
300 TestClassRedirection(h, L"Button", L"2.2.2.2!Button", L"testlib.dll", 5);
301 _DeactivateCtx(cookie, __LINE__);
302 }
303 else
304 {
305 skip("Failed to create context for classtest.manifest\n");
306 }
307
308 /* Dependency tests */
309 h = _CreateActCtxFromFile(L"deptest.manifest", __LINE__);
310 if (h != INVALID_HANDLE_VALUE)
311 {
312 _ActivateCtx(h, &cookie, __LINE__);
313 TestLibDependency(h);
314 _DeactivateCtx(cookie, __LINE__);
315 }
316 else
317 {
318 skip("Failed to create context for deptest.manifest\n");
319 }
320
321 /* Activate a context that depends on comctl32 v6 and run class tests again */
322 h = _CreateActCtxFromFile(L"comctl32dep.manifest", __LINE__);
323 if (h != INVALID_HANDLE_VALUE)
324 {
325 _ActivateCtx(h, &cookie, __LINE__);
326 TestClassRedirection(h, L"Button", L"6.0.", L"comctl32.dll", 29);
327 ok( GetModuleHandleW(L"comctl32.dll") == NULL, "Expected comctl32 not to be loaded\n");
328 ok( GetModuleHandleW(L"user32.dll") == NULL, "Expected user32 not to be loaded\n");
329 _DeactivateCtx(cookie, __LINE__);
330 }
331 else
332 {
333 skip("Failed to create context for comctl32dep.manifest\n");
334 }
335 }