+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;
+ ReactOS_ShimData* pShimData = *pOldShimData;
+
+ C_ASSERT(RTL_NUMBER_OF(GuidOrder) == RTL_NUMBER_OF(GuidVersions));
+
+ if (pShimData)
+ {
+ if (pShimData->dwMagic != REACTOS_SHIMDATA_MAGIC ||
+ pShimData->dwSize != sizeof(ReactOS_ShimData))
+ {
+ DPRINT1("LdrpInitializeProcessCompat: Corrupt pShimData (0x%x, %u)\n", pShimData->dwMagic, pShimData->dwSize);
+ return;
+ }
+ if (pShimData->dwRosProcessCompatVersion)
+ {
+ DPRINT1("LdrpInitializeProcessCompat: ProcessCompatVersion already set to 0x%x\n", pShimData->dwRosProcessCompatVersion);
+ return;
+ }
+ }
+
+ 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))
+ {
+ /* 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;
+ }
+ }
+ }
+}
+
+