https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d49004352fd3927e94db440ea0a61185f45eab4e
commit d49004352fd3927e94db440ea0a61185f45eab4e Author: Mark Jansen <mark.jan...@reactos.org> AuthorDate: Sat Jan 13 21:32:48 2018 +0100 Commit: Mark Jansen <mark.jan...@reactos.org> CommitDate: Mon Apr 9 19:36:09 2018 +0200 [NTDLL] Check the process manifest at startup for a compatibility section. --- dll/appcompat/apphelp/hsdb.c | 12 +++-- dll/ntdll/ldr/ldrinit.c | 86 +++++++++++++++++++++++++++++++++- sdk/include/reactos/compat_undoc.h | 43 +++++++++++++++++ sdk/include/reactos/compatguid_undoc.h | 12 +++++ sdk/lib/uuid/undoc.c | 1 + 5 files changed, 149 insertions(+), 5 deletions(-) diff --git a/dll/appcompat/apphelp/hsdb.c b/dll/appcompat/apphelp/hsdb.c index 903968d0d6..6c23ec6fa3 100644 --- a/dll/appcompat/apphelp/hsdb.c +++ b/dll/appcompat/apphelp/hsdb.c @@ -12,7 +12,7 @@ #include "ntndk.h" #include "strsafe.h" #include "apphelp.h" - +#include "compat_undoc.h" #define MAX_LAYER_LENGTH 256 #define GPLK_USER 1 @@ -25,12 +25,18 @@ typedef struct _ShimData DWORD dwMagic; SDBQUERYRESULT Query; WCHAR szLayer[MAX_LAYER_LENGTH]; - DWORD unknown; // 0x14c + DWORD dwRosProcessCompatVersion; // ReactOS specific } ShimData; #define SHIMDATA_MAGIC 0xAC0DEDAB +C_ASSERT(SHIMDATA_MAGIC == REACTOS_SHIMDATA_MAGIC); +C_ASSERT(sizeof(ShimData) == sizeof(ReactOS_ShimData)); +C_ASSERT(offsetof(ShimData, dwMagic) == offsetof(ReactOS_ShimData, dwMagic)); +C_ASSERT(offsetof(ShimData, dwRosProcessCompatVersion) == offsetof(ReactOS_ShimData, dwRosProcessCompatVersion)); + + static BOOL WINAPI SdbpFileExists(LPCWSTR path) { DWORD attr = GetFileAttributesW(path); @@ -706,7 +712,7 @@ BOOL WINAPI SdbPackAppCompatData(HSDB hsdb, PSDBQUERYRESULT pQueryResult, PVOID* pData->dwSize = sizeof(*pData); pData->dwMagic = SHIMDATA_MAGIC; pData->Query = *pQueryResult; - pData->unknown = 0; + pData->dwRosProcessCompatVersion = 0; pData->szLayer[0] = UNICODE_NULL; /* TODO */ SHIM_INFO("\ndwFlags 0x%x\ndwMagic 0x%x\ntrExe 0x%x\ntrLayer 0x%x\n", diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c index f62b93ef65..b35321e8c6 100644 --- a/dll/ntdll/ldr/ldrinit.c +++ b/dll/ntdll/ldr/ldrinit.c @@ -10,6 +10,8 @@ /* INCLUDES *****************************************************************/ #include <ntdll.h> +#include <compat_undoc.h> +#include <compatguid_undoc.h> #define NDEBUG #include <debug.h> @@ -1455,6 +1457,83 @@ LdrpValidateImageForMp(IN PLDR_DATA_TABLE_ENTRY LdrDataTableEntry) UNIMPLEMENTED; } +VOID +NTAPI +LdrpInitializeProcessCompat(PVOID* pOldShimData) +{ + static const GUID* GuidOrder[] = { &COMPAT_GUID_WIN10, &COMPAT_GUID_WIN81, &COMPAT_GUID_WIN8, + &COMPAT_GUID_WIN7, &COMPAT_GUID_VISTA }; + static const DWORD GuidVersions[] = { WINVER_WIN10, WINVER_WIN81, WINVER_WIN8, WINVER_WIN7, WINVER_VISTA }; + + ULONG Buffer[(sizeof(COMPATIBILITY_CONTEXT_ELEMENT) * 10 + sizeof(ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION)) / sizeof(ULONG)]; + ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION* ContextCompatInfo; + SIZE_T SizeRequired; + NTSTATUS Status; + DWORD n, cur; + + C_ASSERT(RTL_NUMBER_OF(GuidOrder) == RTL_NUMBER_OF(GuidVersions)); + + SizeRequired = sizeof(Buffer); + Status = RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF, + NULL, + NULL, + CompatibilityInformationInActivationContext, + Buffer, + sizeof(Buffer), + &SizeRequired); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("LdrpInitializeProcessCompat: Unable to query process actctx with status %x\n", Status); + return; + } + + ContextCompatInfo = (ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*)Buffer; + /* No Compatibility elements present, bail out */ + if (ContextCompatInfo->ElementCount == 0) + return; + + /* Search for known GUID's, starting from newest to oldest. */ + for (cur = 0; cur < RTL_NUMBER_OF(GuidOrder); ++cur) + { + for (n = 0; n < ContextCompatInfo->ElementCount; ++n) + { + if (ContextCompatInfo->Elements[n].Type == ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS && + RtlCompareMemory(&ContextCompatInfo->Elements[n].Id, GuidOrder[cur], sizeof(GUID)) == sizeof(GUID)) + { + ReactOS_ShimData* pShimData = *pOldShimData; + + /* If this process did not need shim data before, allocate and store it */ + if (pShimData == NULL) + { + PPEB Peb = NtCurrentPeb(); + + ASSERT(Peb->pShimData == NULL); + pShimData = RtlAllocateHeap(Peb->ProcessHeap, HEAP_ZERO_MEMORY, sizeof(*pShimData)); + + if (!pShimData) + { + DPRINT1("LdrpInitializeProcessCompat: Unable to allocated %u bytes\n", sizeof(*pShimData)); + return; + } + + pShimData->dwSize = sizeof(*pShimData); + pShimData->dwMagic = REACTOS_SHIMDATA_MAGIC; + + Peb->pShimData = pShimData; + *pOldShimData = pShimData; + } + + /* Store the highest found version, and bail out. */ + pShimData->dwRosProcessCompatVersion = GuidVersions[cur]; + DPRINT1("LdrpInitializeProcessCompat: Found guid for winver 0x%x\n", GuidVersions[cur]); + return; + } + } + } +} + + NTSTATUS NTAPI LdrpInitializeProcess(IN PCONTEXT Context, @@ -1542,8 +1621,8 @@ LdrpInitializeProcess(IN PCONTEXT Context, /* Save the old Shim Data */ OldShimData = Peb->pShimData; - /* Clear it */ - Peb->pShimData = NULL; + /* ReactOS specific: do not clear it. (Windows starts doing the same in later versions) */ + //Peb->pShimData = NULL; /* Save the number of processors and CS Timeout */ LdrpNumberOfProcessors = Peb->NumberOfProcessors; @@ -1934,6 +2013,9 @@ LdrpInitializeProcess(IN PCONTEXT Context, /* Initialize Wine's active context implementation for the current process */ actctx_init(); + /* ReactOS specific */ + LdrpInitializeProcessCompat(&OldShimData); + /* Set the current directory */ Status = RtlSetCurrentDirectory_U(&CurrentDirectory); if (!NT_SUCCESS(Status)) diff --git a/sdk/include/reactos/compat_undoc.h b/sdk/include/reactos/compat_undoc.h new file mode 100644 index 0000000000..fc6a04794d --- /dev/null +++ b/sdk/include/reactos/compat_undoc.h @@ -0,0 +1,43 @@ +#ifndef COMPAT_UNDOC_H +#define COMPAT_UNDOC_H + + +typedef struct _ReactOS_ShimData +{ + DWORD dwReserved1[130]; + DWORD dwSize; + DWORD dwMagic; + DWORD dwReserved2[242]; + DWORD dwRosProcessCompatVersion; +} ReactOS_ShimData; + + +#define REACTOS_SHIMDATA_MAGIC 0xAC0DEDAB + +#ifndef WINVER_VISTA +#define WINVER_VISTA 0x0600 +#define WINVER_WIN7 0x0601 +#define WINVER_WIN8 0x0602 +#define WINVER_WIN81 0x0603 +#define WINVER_WIN10 0x0a00 +#endif + +static +inline +DWORD RosGetProcessCompatVersion(VOID) +{ + static DWORD g_CompatVersion = 0xffffffff; + if (g_CompatVersion == 0xffffffff) + { + ReactOS_ShimData* pShimData = (ReactOS_ShimData*)NtCurrentPeb()->pShimData; + if (pShimData && pShimData->dwMagic == REACTOS_SHIMDATA_MAGIC && + pShimData->dwSize == sizeof(ReactOS_ShimData)) + { + g_CompatVersion = pShimData->dwRosProcessCompatVersion; + } + } + return g_CompatVersion != 0xffffffff ? g_CompatVersion : 0; +} + + +#endif // COMPAT_UNDOC_H diff --git a/sdk/include/reactos/compatguid_undoc.h b/sdk/include/reactos/compatguid_undoc.h new file mode 100644 index 0000000000..be4206aa94 --- /dev/null +++ b/sdk/include/reactos/compatguid_undoc.h @@ -0,0 +1,12 @@ +#ifndef COMPATGUID_UNDOC_H +#define COMPATGUID_UNDOC_H + + +DEFINE_GUID(COMPAT_GUID_VISTA, 0xe2011457, 0x1546, 0x43c5, 0xa5, 0xfe, 0x00, 0x8d, 0xee, 0xe3, 0xd3, 0xf0); +DEFINE_GUID(COMPAT_GUID_WIN7, 0x35138b9a, 0x5d96, 0x4fbd, 0x8e, 0x2d, 0xa2, 0x44, 0x02, 0x25, 0xf9, 0x3a); +DEFINE_GUID(COMPAT_GUID_WIN8, 0x4a2f28e3, 0x53b9, 0x4441, 0xba, 0x9c, 0xd6, 0x9d, 0x4a, 0x4a, 0x6e, 0x38); +DEFINE_GUID(COMPAT_GUID_WIN81, 0x1f676c76, 0x80e1, 0x4239, 0x95, 0xbb, 0x83, 0xd0, 0xf6, 0xd0, 0xda, 0x78); +DEFINE_GUID(COMPAT_GUID_WIN10, 0x8e0f7a12, 0xbfb3, 0x4fe8, 0xb9, 0xa5, 0x48, 0xfd, 0x50, 0xa1, 0x5a, 0x9a); + + +#endif // COMPATGUID_UNDOC_H diff --git a/sdk/lib/uuid/undoc.c b/sdk/lib/uuid/undoc.c index 5e3fab4653..8768a3a2ff 100644 --- a/sdk/lib/uuid/undoc.c +++ b/sdk/lib/uuid/undoc.c @@ -5,4 +5,5 @@ #include <guiddef.h> #include <shlguid_undoc.h> +#include <compatguid_undoc.h>