2 * Unit test suite for virtual substituted drive functions.
4 * Copyright 2017 Giannis Adamopoulos
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.
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.
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
24 #include "wine/test.h"
29 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
31 struct strsection_header
43 struct wndclass_redirect_data
48 ULONG name_offset
; /* versioned name offset */
50 ULONG module_offset
; /* container name offset to the section base */
53 struct dllredirect_data
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
;
73 DWORD ulAssemblyDirectoryNameLength
;
74 DWORD ulAssemblyDirectoryNameOffset
; /* offset to the section base */
75 DWORD unk4
[3]; /* In win10 there are two more fields */
80 HANDLE
_CreateActCtxFromFile(LPCWSTR FileName
, int line
)
82 ACTCTXW ActCtx
= {sizeof(ACTCTX
)};
84 WCHAR buffer
[MAX_PATH
] , *separator
;
86 ok (GetModuleFileNameW(NULL
, buffer
, MAX_PATH
), "GetModuleFileName failed\n");
87 separator
= wcsrchr(buffer
, L
'\\');
89 wcscpy(separator
+ 1, FileName
);
91 ActCtx
.lpSource
= buffer
;
93 SetLastError(0xdeaddead);
94 h
= CreateActCtxW(&ActCtx
);
95 ok_(__FILE__
, line
)(h
!= INVALID_HANDLE_VALUE
, "CreateActCtx failed\n");
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
, "Wrong last error. Expected %d, got %lu\n", ERROR_BAD_EXE_FORMAT
, GetLastError());
102 VOID
_ActivateCtx(HANDLE h
, ULONG_PTR
*cookie
, int line
)
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());
112 VOID
_DeactivateCtx(ULONG_PTR cookie
, int line
)
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());
122 void TestClassRedirection(HANDLE h
, LPCWSTR ClassToTest
, LPCWSTR ExpectedClassName
, LPCWSTR ExpectedModule
, ULONG ExpectedClassCount
)
124 ACTCTX_SECTION_KEYED_DATA KeyedData
= { 0 };
126 struct strsection_header
*header
;
127 struct wndclass_redirect_data
*classData
;
128 LPCWSTR VersionedClass
, ClassLib
;
131 SetLastError(0xdeaddead);
132 KeyedData
.cbSize
= sizeof(KeyedData
);
133 res
= FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
,
135 ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
,
138 ok(res
== TRUE
, "FindActCtxSectionString failed\n");
139 ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD
)(0xdeaddead), GetLastError());
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
;
148 if(res
== FALSE
|| KeyedData
.ulDataFormatVersion
!= 1 || header
== NULL
|| classData
== NULL
)
150 skip("Can't read data for class. Skipping\n");
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
);
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
->name_len
== wcslen(ExpectedClassName
) * 2, "Got name len %lu, expected %d\n", classData
->name_len
, wcslen(ExpectedClassName
) *2);
165 ok(classData
->module_len
== wcslen(ExpectedModule
) * 2, "Got name len %lu, expected %d\n", classData
->module_len
, wcslen(ExpectedModule
) *2);
166 ok(wcscmp(VersionedClass
, ExpectedClassName
) == 0, "Got %S, expected %S\n", VersionedClass
, ExpectedClassName
);
167 ok(wcscmp(ClassLib
, ExpectedModule
) == 0, "Got %S, expected %S\n", ClassLib
, ExpectedModule
);
171 VOID
TestLibDependency(HANDLE h
)
173 ACTCTX_SECTION_KEYED_DATA KeyedData
= { 0 };
175 struct strsection_header
*SectionHeader
;
176 struct dllredirect_data
*redirData
;
177 struct assemply_data
*assemplyData
;
179 SetLastError(0xdeaddead);
180 KeyedData
.cbSize
= sizeof(KeyedData
);
181 res
= FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
,
183 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
,
186 ok(res
== TRUE
, "FindActCtxSectionString failed\n");
187 ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD
)(0xdeaddead), GetLastError());
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
;
196 if(res
== FALSE
|| KeyedData
.ulDataFormatVersion
!= 1 || SectionHeader
== NULL
|| redirData
== NULL
)
198 skip("Can't read data for dep1.dll. Skipping\n");
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
));
208 SetLastError(0xdeaddead);
209 KeyedData
.cbSize
= sizeof(KeyedData
);
210 res
= FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
,
212 ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION
,
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
;;
224 if(res
== FALSE
|| KeyedData
.ulDataFormatVersion
!= 1 || SectionHeader
== NULL
|| assemplyData
== NULL
)
226 skip("Can't read data for dep1. Skipping\n");
230 LPCWSTR AssemblyIdentity
, ManifestPath
, AssemblyDirectory
;
233 PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION details
= (PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
)buffer
;
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? */
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
);
246 AssemblyIdentity
= (WCHAR
*)((BYTE
*)SectionHeader
+ assemplyData
->ulEncodedAssemblyIdentityOffset
);
247 ManifestPath
= (WCHAR
*)((BYTE
*)SectionHeader
+ assemplyData
->ulManifestPathOffset
);
248 AssemblyDirectory
= (WCHAR
*)((BYTE
*)SectionHeader
+ assemplyData
->ulAssemblyDirectoryNameOffset
);
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");
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
);
265 /* It looks like that AssemblyIdentity isn't null terminated */
266 ok(memcmp(AssemblyIdentity
, details
->lpAssemblyEncodedAssemblyIdentity
, assemplyData
->ulEncodedAssemblyIdentityLength
) == 0, "Got wrong AssemblyIdentity\n");
270 START_TEST(FindActCtxSectionStringW
)
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");
281 /* Class redirection tests */
282 h
= _CreateActCtxFromFile(L
"classtest.manifest", __LINE__
);
283 if (h
!= INVALID_HANDLE_VALUE
)
285 _ActivateCtx(h
, &cookie
, __LINE__
);
286 TestClassRedirection(h
, L
"Button", L
"2.2.2.2!Button", L
"testlib.dll", 5);
287 _DeactivateCtx(cookie
, __LINE__
);
291 skip("Failed to create context for classtest.manifest\n");
294 /* Dependency tests */
295 h
= _CreateActCtxFromFile(L
"deptest.manifest", __LINE__
);
296 if (h
!= INVALID_HANDLE_VALUE
)
298 _ActivateCtx(h
, &cookie
, __LINE__
);
299 TestLibDependency(h
);
300 _DeactivateCtx(cookie
, __LINE__
);
304 skip("Failed to create context for deptest.manifest\n");
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
)
311 _ActivateCtx(h
, &cookie
, __LINE__
);
312 TestClassRedirection(h
, L
"Button", L
"6.0.3790.1830!Button", 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__
);
319 skip("Failed to create context for comctl32dep.manifest\n");