mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 14:18:41 +00:00
335 lines
15 KiB
C
335 lines
15 KiB
C
/*
|
|
* Unit test suite for virtual substituted drive functions.
|
|
*
|
|
* Copyright 2017 Giannis Adamopoulos
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define STRSECTION_MAGIC 0x64487353 /* dHsS */
|
|
|
|
struct strsection_header
|
|
{
|
|
DWORD magic;
|
|
ULONG size;
|
|
DWORD unk1[3];
|
|
ULONG count;
|
|
ULONG index_offset;
|
|
DWORD unk2[2];
|
|
ULONG global_offset;
|
|
ULONG global_len;
|
|
};
|
|
|
|
struct wndclass_redirect_data
|
|
{
|
|
ULONG size;
|
|
DWORD res;
|
|
ULONG name_len;
|
|
ULONG name_offset; /* versioned name offset */
|
|
ULONG module_len;
|
|
ULONG module_offset; /* container name offset to the section base */
|
|
};
|
|
|
|
struct dllredirect_data
|
|
{
|
|
ULONG size;
|
|
ULONG unk;
|
|
DWORD res[3];
|
|
};
|
|
|
|
#include <pshpack1.h>
|
|
|
|
struct assemply_data
|
|
{
|
|
ULONG size;
|
|
DWORD ulFlags;
|
|
DWORD ulEncodedAssemblyIdentityLength;
|
|
DWORD ulEncodedAssemblyIdentityOffset; /* offset to the section base */
|
|
DWORD ulManifestPathType;
|
|
DWORD ulManifestPathLength;
|
|
DWORD ulManifestPathOffset; /* offset to the section base */
|
|
LARGE_INTEGER liManifestLastWriteTime;
|
|
DWORD unk3[11];
|
|
DWORD ulAssemblyDirectoryNameLength;
|
|
DWORD ulAssemblyDirectoryNameOffset; /* offset to the section base */
|
|
DWORD unk4[3]; /* In win10 there are two more fields */
|
|
};
|
|
|
|
#include <poppack.h>
|
|
|
|
HANDLE _CreateActCtxFromFile(LPCWSTR FileName, int line)
|
|
{
|
|
ACTCTXW ActCtx = {sizeof(ACTCTX)};
|
|
HANDLE h;
|
|
WCHAR buffer[MAX_PATH] , *separator;
|
|
|
|
ok (GetModuleFileNameW(NULL, buffer, MAX_PATH), "GetModuleFileName failed\n");
|
|
separator = wcsrchr(buffer, L'\\');
|
|
if (separator)
|
|
wcscpy(separator + 1, FileName);
|
|
|
|
ActCtx.lpSource = buffer;
|
|
|
|
SetLastError(0xdeaddead);
|
|
h = CreateActCtxW(&ActCtx);
|
|
ok_(__FILE__, line)(h != INVALID_HANDLE_VALUE, "CreateActCtx failed for %S\n", FileName);
|
|
// In win10 last error is unchanged and in win2k3 it is ERROR_BAD_EXE_FORMAT
|
|
ok_(__FILE__, line)(GetLastError() == ERROR_BAD_EXE_FORMAT || GetLastError() == 0xdeaddead, "Wrong last error %lu\n", GetLastError());
|
|
|
|
return h;
|
|
}
|
|
|
|
VOID _ActivateCtx(HANDLE h, ULONG_PTR *cookie, int line)
|
|
{
|
|
BOOL res;
|
|
|
|
SetLastError(0xdeaddead);
|
|
res = ActivateActCtx(h, cookie);
|
|
ok_(__FILE__, line)(res == TRUE, "ActivateActCtx failed\n");
|
|
ok_(__FILE__, line)(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
|
|
}
|
|
|
|
VOID _DeactivateCtx(ULONG_PTR cookie, int line)
|
|
{
|
|
BOOL res;
|
|
|
|
SetLastError(0xdeaddead);
|
|
res = DeactivateActCtx(0, cookie);
|
|
ok_(__FILE__, line)(res == TRUE, "DeactivateActCtx failed\n");
|
|
ok_(__FILE__, line)(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
|
|
}
|
|
|
|
void TestClassRedirection(HANDLE h, LPCWSTR ClassToTest, LPCWSTR ExpectedClassPart, LPCWSTR ExpectedModule, ULONG ExpectedClassCount)
|
|
{
|
|
ACTCTX_SECTION_KEYED_DATA KeyedData = { 0 };
|
|
BOOL res;
|
|
struct strsection_header *header;
|
|
struct wndclass_redirect_data *classData;
|
|
LPCWSTR VersionedClass, ClassLib;
|
|
int data_lenght;
|
|
|
|
SetLastError(0xdeaddead);
|
|
KeyedData.cbSize = sizeof(KeyedData);
|
|
res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
|
|
NULL,
|
|
ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION,
|
|
ClassToTest,
|
|
&KeyedData);
|
|
ok(res == TRUE, "FindActCtxSectionString failed\n");
|
|
ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
|
|
|
|
ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu\n", KeyedData.ulDataFormatVersion);
|
|
ok(KeyedData.hActCtx == h, "Wrong handle\n");
|
|
ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
|
|
ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
|
|
header = (struct strsection_header*)KeyedData.lpSectionBase;
|
|
classData = (struct wndclass_redirect_data*)KeyedData.lpData;
|
|
|
|
if(res == FALSE || KeyedData.ulDataFormatVersion != 1 || header == NULL || classData == NULL)
|
|
{
|
|
skip("Can't read data for class. Skipping\n");
|
|
}
|
|
else
|
|
{
|
|
ok(header->magic == STRSECTION_MAGIC, "%lu\n", header->magic );
|
|
ok(header->size == sizeof(*header), "Got %lu instead of %d\n", header->size, sizeof(*header));
|
|
ok(header->count == ExpectedClassCount, "Expected %lu classes, got %lu\n", ExpectedClassCount, header->count );
|
|
|
|
VersionedClass = (WCHAR*)((BYTE*)classData + classData->name_offset);
|
|
ClassLib = (WCHAR*)((BYTE*)header + classData->module_offset);
|
|
data_lenght = classData->size + classData->name_len + classData->module_len + 2*sizeof(WCHAR);
|
|
ok(KeyedData.ulLength == data_lenght, "Got lenght %lu instead of %d\n", KeyedData.ulLength, data_lenght);
|
|
ok(classData->size == sizeof(*classData), "Got %lu instead of %d\n", classData->size, sizeof(*classData));
|
|
ok(classData->res == 0, "Got res %lu\n", classData->res);
|
|
ok(classData->module_len == wcslen(ExpectedModule) * 2, "Got name len %lu, expected %d\n", classData->module_len, wcslen(ExpectedModule) *2);
|
|
ok(wcscmp(ClassLib, ExpectedModule) == 0, "Got %S, expected %S\n", ClassLib, ExpectedModule);
|
|
/* compare only if VersionedClass starts with ExpectedClassPart */
|
|
ok(memcmp(VersionedClass, ExpectedClassPart, sizeof(WCHAR) * wcslen(ExpectedClassPart)) == 0, "Expected %S to start with %S\n", VersionedClass, ExpectedClassPart);
|
|
}
|
|
}
|
|
|
|
VOID TestLibDependency(HANDLE h)
|
|
{
|
|
ACTCTX_SECTION_KEYED_DATA KeyedData = { 0 };
|
|
BOOL res;
|
|
struct strsection_header *SectionHeader;
|
|
struct dllredirect_data *redirData;
|
|
struct assemply_data *assemplyData;
|
|
|
|
SetLastError(0xdeaddead);
|
|
KeyedData.cbSize = sizeof(KeyedData);
|
|
res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
|
|
NULL,
|
|
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
|
|
L"dep1.dll",
|
|
&KeyedData);
|
|
ok(res == TRUE, "FindActCtxSectionString failed\n");
|
|
ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
|
|
|
|
ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu", KeyedData.ulDataFormatVersion);
|
|
ok(KeyedData.hActCtx == h, "Wrong handle\n");
|
|
ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
|
|
ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
|
|
SectionHeader = (struct strsection_header*)KeyedData.lpSectionBase;
|
|
redirData = (struct dllredirect_data *)KeyedData.lpData;
|
|
|
|
if(res == FALSE || KeyedData.ulDataFormatVersion != 1 || SectionHeader == NULL || redirData == NULL)
|
|
{
|
|
skip("Can't read data for dep1.dll. Skipping\n");
|
|
}
|
|
else
|
|
{
|
|
ok(SectionHeader->magic == STRSECTION_MAGIC, "%lu\n", SectionHeader->magic );
|
|
ok(SectionHeader->size == sizeof(*SectionHeader), "Got %lu instead of %d\n", SectionHeader->size, sizeof(*SectionHeader));
|
|
ok(SectionHeader->count == 2, "%lu\n", SectionHeader->count ); /* 2 dlls? */
|
|
ok(redirData->size == sizeof(*redirData), "Got %lu instead of %d\n", redirData->size, sizeof(*redirData));
|
|
}
|
|
|
|
SetLastError(0xdeaddead);
|
|
KeyedData.cbSize = sizeof(KeyedData);
|
|
res = FindActCtxSectionStringW(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,
|
|
NULL,
|
|
ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION,
|
|
L"dep1",
|
|
&KeyedData);
|
|
ok(res == TRUE, "FindActCtxSectionString failed\n");
|
|
ok(GetLastError() == 0xdeaddead, "Wrong last error. Expected %lu, got %lu\n", (DWORD)(0xdeaddead), GetLastError());
|
|
ok(KeyedData.ulDataFormatVersion == 1, "Wrong format version: %lu", KeyedData.ulDataFormatVersion);
|
|
ok(KeyedData.hActCtx == h, "Wrong handle\n");
|
|
ok(KeyedData.lpSectionBase != NULL, "Expected non null lpSectionBase\n");
|
|
ok(KeyedData.lpData != NULL, "Expected non null lpData\n");
|
|
SectionHeader = (struct strsection_header*)KeyedData.lpSectionBase;
|
|
assemplyData = (struct assemply_data*)KeyedData.lpData;;
|
|
|
|
if(res == FALSE || KeyedData.ulDataFormatVersion != 1 || SectionHeader == NULL || assemplyData == NULL)
|
|
{
|
|
skip("Can't read data for dep1. Skipping\n");
|
|
}
|
|
else
|
|
{
|
|
LPCWSTR AssemblyIdentity, ManifestPath, AssemblyDirectory;
|
|
int data_lenght;
|
|
DWORD buffer[256];
|
|
PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION details = (PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION)buffer;
|
|
|
|
ok(SectionHeader->magic == STRSECTION_MAGIC, "%lu\n", SectionHeader->magic );
|
|
ok(SectionHeader->size == sizeof(*SectionHeader), "Got %lu instead of %d\n", SectionHeader->size, sizeof(*SectionHeader));
|
|
ok(SectionHeader->count == 2, "%lu\n", SectionHeader->count ); /* 2 dlls? */
|
|
|
|
data_lenght = assemplyData->size +
|
|
assemplyData->ulEncodedAssemblyIdentityLength +
|
|
assemplyData->ulManifestPathLength +
|
|
assemplyData->ulAssemblyDirectoryNameLength + 2 * sizeof(WCHAR);
|
|
ok(assemplyData->size == sizeof(*assemplyData), "Got %lu instead of %d\n", assemplyData->size, sizeof(*assemplyData));
|
|
ok(KeyedData.ulLength == data_lenght, "Got lenght %lu instead of %d\n", KeyedData.ulLength, data_lenght);
|
|
|
|
AssemblyIdentity = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulEncodedAssemblyIdentityOffset);
|
|
ManifestPath = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulManifestPathOffset);
|
|
AssemblyDirectory = (WCHAR*)((BYTE*)SectionHeader + assemplyData->ulAssemblyDirectoryNameOffset);
|
|
|
|
/* Use AssemblyDetailedInformationInActivationContext so as to infer the contents of assemplyData */
|
|
res = QueryActCtxW(0, h, &KeyedData.ulAssemblyRosterIndex,
|
|
AssemblyDetailedInformationInActivationContext,
|
|
&buffer, sizeof(buffer), NULL);
|
|
ok(res == TRUE, "QueryActCtxW failed\n");
|
|
ok(assemplyData->ulFlags == details->ulFlags, "\n");
|
|
ok(assemplyData->ulEncodedAssemblyIdentityLength == details->ulEncodedAssemblyIdentityLength, "\n");
|
|
ok(assemplyData->ulManifestPathType == details->ulManifestPathType, "\n");
|
|
ok(assemplyData->ulManifestPathLength == details->ulManifestPathLength, "\n");
|
|
ok(assemplyData->ulAssemblyDirectoryNameLength == details->ulAssemblyDirectoryNameLength, "\n");
|
|
ok(assemplyData->liManifestLastWriteTime.QuadPart == details->liManifestLastWriteTime.QuadPart, "\n");
|
|
|
|
ok(wcscmp(ManifestPath, details->lpAssemblyManifestPath) == 0, "Expected path %S, got %S\n", details->lpAssemblyManifestPath, ManifestPath);
|
|
ok(wcscmp(AssemblyDirectory, details->lpAssemblyDirectoryName) == 0, "Expected path %S, got %S\n", details->lpAssemblyManifestPath, ManifestPath);
|
|
|
|
/* It looks like that AssemblyIdentity isn't null terminated */
|
|
ok(memcmp(AssemblyIdentity, details->lpAssemblyEncodedAssemblyIdentity, assemplyData->ulEncodedAssemblyIdentityLength) == 0, "Got wrong AssemblyIdentity\n");
|
|
}
|
|
}
|
|
|
|
START_TEST(FindActCtxSectionStringW)
|
|
{
|
|
HANDLE h, h2;
|
|
ULONG_PTR cookie, cookie2;
|
|
|
|
/*First run the redirection tests without using our own actctx */
|
|
TestClassRedirection(NULL, L"Button", L"Button", L"comctl32.dll", 27);
|
|
/* Something activates an activation context that mentions comctl32 but comctl32 is not loaded */
|
|
ok( GetModuleHandleW(L"comctl32.dll") == NULL, "Expected comctl32 not to be loaded\n");
|
|
ok( GetModuleHandleW(L"user32.dll") == NULL, "Expected user32 not to be loaded\n");
|
|
|
|
/* Class redirection tests */
|
|
h = _CreateActCtxFromFile(L"classtest.manifest", __LINE__);
|
|
if (h != INVALID_HANDLE_VALUE)
|
|
{
|
|
_ActivateCtx(h, &cookie, __LINE__);
|
|
TestClassRedirection(h, L"Button", L"2.2.2.2!Button", L"testlib.dll", 5);
|
|
_ActivateCtx(NULL, &cookie2, __LINE__);
|
|
TestClassRedirection(NULL, L"Button", L"Button", L"comctl32.dll", 27);
|
|
_DeactivateCtx(cookie2, __LINE__);
|
|
_DeactivateCtx(cookie, __LINE__);
|
|
}
|
|
else
|
|
{
|
|
skip("Failed to create context for classtest.manifest\n");
|
|
}
|
|
|
|
/* Class redirection tests with multiple contexts in the activation stack */
|
|
h2 = _CreateActCtxFromFile(L"classtest2.manifest", __LINE__);
|
|
if (h != INVALID_HANDLE_VALUE && h2 != INVALID_HANDLE_VALUE)
|
|
{
|
|
_ActivateCtx(h, &cookie, __LINE__);
|
|
_ActivateCtx(h2, &cookie2, __LINE__);
|
|
TestClassRedirection(NULL, L"Button", L"Button", L"comctl32.dll", 27);
|
|
TestClassRedirection(h2, L"MyClass", L"1.1.1.1!MyClass", L"testlib.dll", 5);
|
|
_DeactivateCtx(cookie2, __LINE__);
|
|
TestClassRedirection(h, L"Button", L"2.2.2.2!Button", L"testlib.dll", 5);
|
|
_DeactivateCtx(cookie, __LINE__);
|
|
}
|
|
else
|
|
{
|
|
skip("Failed to create context for classtest.manifest\n");
|
|
}
|
|
|
|
/* Dependency tests */
|
|
h = _CreateActCtxFromFile(L"deptest.manifest", __LINE__);
|
|
if (h != INVALID_HANDLE_VALUE)
|
|
{
|
|
_ActivateCtx(h, &cookie, __LINE__);
|
|
TestLibDependency(h);
|
|
_DeactivateCtx(cookie, __LINE__);
|
|
}
|
|
else
|
|
{
|
|
skip("Failed to create context for deptest.manifest\n");
|
|
}
|
|
|
|
/* Activate a context that depends on comctl32 v6 and run class tests again */
|
|
h = _CreateActCtxFromFile(L"comctl32dep.manifest", __LINE__);
|
|
if (h != INVALID_HANDLE_VALUE)
|
|
{
|
|
_ActivateCtx(h, &cookie, __LINE__);
|
|
TestClassRedirection(h, L"Button", L"6.0.", L"comctl32.dll", 29);
|
|
ok( GetModuleHandleW(L"comctl32.dll") == NULL, "Expected comctl32 not to be loaded\n");
|
|
ok( GetModuleHandleW(L"user32.dll") == NULL, "Expected user32 not to be loaded\n");
|
|
_DeactivateCtx(cookie, __LINE__);
|
|
}
|
|
else
|
|
{
|
|
skip("Failed to create context for comctl32dep.manifest\n");
|
|
}
|
|
} |