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