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 }