dbe8ec115d6990669b9cc64b4df09526c569e4ce
[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), 0, FileName};
83 HANDLE h;
84
85 SetLastError(0xdeaddead);
86 h = CreateActCtxW(&ActCtx);
87 ok_(__FILE__, line)(h != INVALID_HANDLE_VALUE, "CreateActCtx failed\n");
88 // In win10 last error is unchanged and in win2k3 it is ERROR_BAD_EXE_FORMAT
89 ok_(__FILE__, line)(GetLastError() == ERROR_BAD_EXE_FORMAT, "Wrong last error. Expected %d, got %lu\n", ERROR_BAD_EXE_FORMAT, GetLastError());
90
91 return h;
92 }
93
94 VOID _ActivateCtx(HANDLE h, ULONG_PTR *cookie, int line)
95 {
96 BOOL res;
97
98 SetLastError(0xdeaddead);
99 res = ActivateActCtx(h, cookie);
100 ok_(__FILE__, line)(res == TRUE, "ActivateActCtx failed\n");
101 ok_(__FILE__, line)(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
102 }
103
104 VOID _DeactivateCtx(ULONG_PTR cookie, int line)
105 {
106 BOOL res;
107
108 SetLastError(0xdeaddead);
109 res = DeactivateActCtx(0, cookie);
110 ok_(__FILE__, line)(res == TRUE, "DeactivateActCtx failed\n");
111 ok_(__FILE__, line)(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
112 }
113
114 void TestClassRedirection(HANDLE h, LPCWSTR ClassToTest, LPCWSTR ExpectedClassName, LPCWSTR ExpectedModule, ULONG ExpectedClassCount)
115 {
116 ACTCTX_SECTION_KEYED_DATA KeyedData = { 0 };
117 BOOL res;
118 struct strsection_header *header;
119 struct wndclass_redirect_data *classData;
120 LPCWSTR VersionedClass, ClassLib;
121 int data_lenght;
122
123 SetLastError(0xdeaddead);
124 KeyedData.cbSize = sizeof(KeyedData);
125 res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
126 NULL,
127 ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION,
128 ClassToTest,
129 &KeyedData);
130 ok(res == TRUE, "FindActCtxSectionString failed\n");
131 ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
132
133 ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu", KeyedData.ulDataFormatVersion);
134 ok(KeyedData.hActCtx == h, "Wrong handle\n");
135 ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
136 ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
137 header = (struct strsection_header*)KeyedData.lpSectionBase;
138 classData = (struct wndclass_redirect_data*)KeyedData.lpData;
139
140 ok(header->magic == STRSECTION_MAGIC, "%lu\n", header->magic );
141 ok(header->size == sizeof(*header), "Got %lu instead of %d\n", header->size, sizeof(*header));
142 ok(header->count == ExpectedClassCount, "Expected %lu classes, got %lu\n", ExpectedClassCount, header->count );
143
144 VersionedClass = (WCHAR*)((BYTE*)classData + classData->name_offset);
145 ClassLib = (WCHAR*)((BYTE*)header + classData->module_offset);
146 data_lenght = classData->size + classData->name_len + classData->module_len + 2*sizeof(WCHAR);
147 ok(KeyedData.ulLength == data_lenght, "Got lenght %lu instead of %d\n", KeyedData.ulLength, data_lenght);
148 ok(classData->size == sizeof(*classData), "Got %lu instead of %d\n", classData->size, sizeof(*classData));
149 ok(classData->res == 0, "Got res %lu\n", classData->res);
150 ok(classData->name_len == wcslen(ExpectedClassName) * 2, "Got name len %lu, expected %d\n", classData->name_len, wcslen(ExpectedClassName) *2);
151 ok(classData->module_len == wcslen(ExpectedModule) * 2, "Got name len %lu, expected %d\n", classData->module_len, wcslen(ExpectedModule) *2);
152 ok(wcscmp(VersionedClass, ExpectedClassName) == 0, "Got %S, expected %S\n", VersionedClass, ExpectedClassName);
153 ok(wcscmp(ClassLib, ExpectedModule) == 0, "Got %S, expected %S\n", ClassLib, ExpectedModule);
154 }
155
156 VOID TestLibDependency(HANDLE h)
157 {
158 ACTCTX_SECTION_KEYED_DATA KeyedData = { 0 };
159 BOOL res;
160 struct strsection_header *SectionHeader;
161 struct dllredirect_data *redirData;
162 struct assemply_data *assemplyData;
163
164 SetLastError(0xdeaddead);
165 KeyedData.cbSize = sizeof(KeyedData);
166 res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
167 NULL,
168 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
169 L"dep1.dll",
170 &KeyedData);
171 ok(res == TRUE, "FindActCtxSectionString failed\n");
172 ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
173
174 ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu", KeyedData.ulDataFormatVersion);
175 ok(KeyedData.hActCtx == h, "Wrong handle\n");
176 ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
177 ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
178 SectionHeader = (struct strsection_header*)KeyedData.lpSectionBase;
179 redirData = (struct dllredirect_data *)KeyedData.lpData;
180
181 if(res == FALSE || KeyedData.ulDataFormatVersion != 1)
182 {
183 skip("Can't read data for dep1.dll. Skipping\n");
184 }
185 else
186 {
187 ok(SectionHeader->magic == STRSECTION_MAGIC, "%lu\n", SectionHeader->magic );
188 ok(SectionHeader->size == sizeof(*SectionHeader), "Got %lu instead of %d\n", SectionHeader->size, sizeof(*SectionHeader));
189 ok(SectionHeader->count == 2, "%lu\n", SectionHeader->count ); /* 2 dlls? */
190 ok(redirData->size == sizeof(*redirData), "Got %lu instead of %d\n", redirData->size, sizeof(*redirData));
191 }
192
193 SetLastError(0xdeaddead);
194 KeyedData.cbSize = sizeof(KeyedData);
195 res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
196 NULL,
197 ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION,
198 L"dep1",
199 &KeyedData);
200 ok(res == TRUE, "FindActCtxSectionString failed\n");
201 ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
202 ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu", KeyedData.ulDataFormatVersion);
203 ok(KeyedData.hActCtx == h, "Wrong handle\n");
204 ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
205 ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
206 SectionHeader = (struct strsection_header*)KeyedData.lpSectionBase;
207 assemplyData = (struct assemply_data*)KeyedData.lpData;;
208
209 if(res == FALSE || KeyedData.ulDataFormatVersion != 1)
210 {
211 skip("Can't read data for dep1. Skipping\n");
212 }
213 else
214 {
215 LPCWSTR AssemblyIdentity, ManifestPath, AssemblyDirectory;
216 int data_lenght;
217 DWORD buffer[256];
218 PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION details = (PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION)buffer;
219
220 ok(SectionHeader->magic == STRSECTION_MAGIC, "%lu\n", SectionHeader->magic );
221 ok(SectionHeader->size == sizeof(*SectionHeader), "Got %lu instead of %d\n", SectionHeader->size, sizeof(*SectionHeader));
222 ok(SectionHeader->count == 2, "%lu\n", SectionHeader->count ); /* 2 dlls? */
223
224 data_lenght = assemplyData->size +
225 assemplyData->ulEncodedAssemblyIdentityLength +
226 assemplyData->ulManifestPathLength +
227 assemplyData->ulAssemblyDirectoryNameLength + 2 * sizeof(WCHAR);
228 ok(assemplyData->size == sizeof(*assemplyData), "Got %lu instead of %d\n", assemplyData->size, sizeof(*assemplyData));
229 ok(KeyedData.ulLength == data_lenght, "Got lenght %lu instead of %d\n", KeyedData.ulLength, data_lenght);
230
231 AssemblyIdentity = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulEncodedAssemblyIdentityOffset);
232 ManifestPath = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulManifestPathOffset);
233 AssemblyDirectory = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulAssemblyDirectoryNameOffset);
234
235 /* Use AssemblyDetailedInformationInActivationContext so as to infer the contents of assemplyData */
236 res = QueryActCtxW(0, h, &KeyedData.ulAssemblyRosterIndex,
237 AssemblyDetailedInformationInActivationContext,
238 &buffer, sizeof(buffer), NULL);
239 ok(res == TRUE, "QueryActCtxW failed\n");
240 ok(assemplyData->ulFlags == details->ulFlags, "\n");
241 ok(assemplyData->ulEncodedAssemblyIdentityLength == details->ulEncodedAssemblyIdentityLength, "\n");
242 ok(assemplyData->ulManifestPathType == details->ulManifestPathType, "\n");
243 ok(assemplyData->ulManifestPathLength == details->ulManifestPathLength, "\n");
244 ok(assemplyData->ulAssemblyDirectoryNameLength == details->ulAssemblyDirectoryNameLength, "\n");
245 ok(assemplyData->liManifestLastWriteTime.QuadPart == details->liManifestLastWriteTime.QuadPart, "\n");
246
247 ok(wcscmp(ManifestPath, details->lpAssemblyManifestPath) == 0, "Expected path %S, got %S\n", details->lpAssemblyManifestPath, ManifestPath);
248 ok(wcscmp(AssemblyDirectory, details->lpAssemblyDirectoryName) == 0, "Expected path %S, got %S\n", details->lpAssemblyManifestPath, ManifestPath);
249
250 /* It looks like that AssemblyIdentity isn't null terminated */
251 ok(memcmp(AssemblyIdentity, details->lpAssemblyEncodedAssemblyIdentity, assemplyData->ulEncodedAssemblyIdentityLength) == 0, "Got wrong AssemblyIdentity\n");
252 }
253 }
254
255 START_TEST(FindActCtxSectionStringW)
256 {
257 HANDLE h;
258 ULONG_PTR cookie;
259
260 /*First run the redirection tests without using our own actctx */
261 TestClassRedirection(NULL, L"Button", L"Button", L"comctl32.dll", 27);
262 /* Something activates an activation context that mentions comctl32 but comctl32 is not loaded */
263 ok( GetModuleHandleW(L"comctl32.dll") == NULL, "Expected comctl32 not to be loaded\n");
264 ok( GetModuleHandleW(L"user32.dll") == NULL, "Expected user32 not to be loaded\n");
265
266 /* Class redirection tests */
267 h = _CreateActCtxFromFile(L"classtest.manifest", __LINE__);
268 _ActivateCtx(h, &cookie, __LINE__);
269 TestClassRedirection(h, L"Button", L"2.2.2.2!Button", L"testlib.dll", 5);
270 _DeactivateCtx(cookie, __LINE__);
271
272 /* Dependency tests */
273 h = _CreateActCtxFromFile(L"deptest.manifest", __LINE__);
274 _ActivateCtx(h, &cookie, __LINE__);
275 TestLibDependency(h);
276 _DeactivateCtx(cookie, __LINE__);
277
278 /* Activate a context that depends on comctl32 v6 and run class tests again */
279 h = _CreateActCtxFromFile(L"comctl32dep.manifest", __LINE__);
280 _ActivateCtx(h, &cookie, __LINE__);
281 TestClassRedirection(h, L"Button", L"6.0.3790.1830!Button", L"comctl32.dll", 29);
282 ok( GetModuleHandleW(L"comctl32.dll") == NULL, "Expected comctl32 not to be loaded\n");
283 ok( GetModuleHandleW(L"user32.dll") == NULL, "Expected user32 not to be loaded\n");
284 _DeactivateCtx(cookie, __LINE__);
285
286 }