[NTDLL] Check the process manifest at startup for a compatibility section.
authorMark Jansen <mark.jansen@reactos.org>
Sat, 13 Jan 2018 20:32:48 +0000 (21:32 +0100)
committerMark Jansen <mark.jansen@reactos.org>
Mon, 9 Apr 2018 17:36:09 +0000 (19:36 +0200)
dll/appcompat/apphelp/hsdb.c
dll/ntdll/ldr/ldrinit.c
sdk/include/reactos/compat_undoc.h [new file with mode: 0644]
sdk/include/reactos/compatguid_undoc.h [new file with mode: 0644]
sdk/lib/uuid/undoc.c

index 903968d..6c23ec6 100644 (file)
@@ -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",
index f62b93e..b35321e 100644 (file)
@@ -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 (file)
index 0000000..fc6a047
--- /dev/null
@@ -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 (file)
index 0000000..be4206a
--- /dev/null
@@ -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
index 5e3fab4..8768a3a 100644 (file)
@@ -5,4 +5,5 @@
 #include <guiddef.h>
 
 #include <shlguid_undoc.h>
+#include <compatguid_undoc.h>