Author: mjansen
Date: Sat Jul 1 20:06:30 2017
New Revision: 75258
URL:
http://svn.reactos.org/svn/reactos?rev=75258&view=rev
Log:
[APPHELP/SHIMENG] Begin implementing the core of the SHIM engine.
With this, the basics of the app compat engine are implemented and should be functional.
Currently it is disable with a policy, to be enabled soon.
CORE-13284
CORE-11300
Added:
trunk/reactos/dll/appcompat/apphelp/shimeng.h (with props)
Modified:
trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt
trunk/reactos/dll/appcompat/apphelp/apphelp.h
trunk/reactos/dll/appcompat/apphelp/shimeng.c
Modified: trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/CMak…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/CMakeLists.txt [iso-8859-1] Sat Jul 1 20:06:30
2017
@@ -2,7 +2,7 @@
include_directories(${SHIMLIB_DIR})
remove_definitions(-D_WIN32_WINNT=0x502 -DWINVER=0x502)
-add_definitions(-D_WIN32_WINNT=0x600 -DWINVER=0x600)
+add_definitions(-D_WIN32_WINNT=0x601 -DWINVER=0x601)
spec2def(apphelp.dll apphelp.spec ADD_IMPORTLIB)
Modified: trunk/reactos/dll/appcompat/apphelp/apphelp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/apph…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/apphelp.h [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/apphelp.h [iso-8859-1] Sat Jul 1 20:06:30 2017
@@ -83,7 +83,9 @@
GUID rgGuidDB[SDB_MAX_SDBS];
} SDBQUERYRESULT, *PSDBQUERYRESULT;
+#ifndef APPHELP_NOSDBPAPI
#include "sdbpapi.h"
+#endif
/* sdbapi.c */
PWSTR SdbpStrDup(LPCWSTR string);
@@ -122,7 +124,8 @@
/* hsdb.c */
BOOL WINAPI SdbGetMatchingExe(HSDB hsdb, LPCWSTR path, LPCWSTR module_name, LPCWSTR env,
DWORD flags, PSDBQUERYRESULT result);
BOOL WINAPI SdbTagIDToTagRef(HSDB hsdb, PDB pdb, TAGID tiWhich, TAGREF* ptrWhich);
-
+BOOL WINAPI SdbTagRefToTagID(HSDB hsdb, TAGREF trWhich, PDB* ppdb, TAGID* ptiWhich);
+BOOL WINAPI SdbUnpackAppCompatData(HSDB hsdb, LPCWSTR pszImageName, PVOID pData,
PSDBQUERYRESULT pQueryResult);
#define ATTRIBUTE_AVAILABLE 0x1
#define ATTRIBUTE_FAILED 0x2
Modified: trunk/reactos/dll/appcompat/apphelp/shimeng.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/shim…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/shimeng.c [iso-8859-1] (original)
+++ trunk/reactos/dll/appcompat/apphelp/shimeng.c [iso-8859-1] Sat Jul 1 20:06:30 2017
@@ -21,12 +21,69 @@
#include "ntndk.h"
#include "shimlib.h"
#include <strsafe.h>
-
-HANDLE g_pShimEngModHandle = 0;
-
-
+/* Make sure we don't include apphelp logging */
+#define APPHELP_NOSDBPAPI
+#include "apphelp.h"
+#include "shimeng.h"
+
+
+typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HINSTANCE, LPCSTR);
+
+
+FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName);
+BOOL WINAPI SE_IsShimDll(PVOID BaseAddress);
+
+
+extern HMODULE g_hInstance;
ULONG g_ShimEngDebugLevel = 0xffffffff;
-
+BOOL g_bComPlusImage = FALSE;
+BOOL g_bShimDuringInit = FALSE;
+BOOL g_bInternalHooksUsed = FALSE;
+static ARRAY g_pShimInfo; /* SHIMMODULE */
+static ARRAY g_pHookArray; /* HOOKMODULEINFO */
+
+HOOKAPIEX g_IntHookEx[] =
+{
+ {
+ "kernel32.dll", /* LibraryName */
+ "GetProcAddress", /* FunctionName */
+ StubGetProcAddress, /* ReplacementFunction*/
+ NULL, /* OriginalFunction */
+ { NULL }, /* ModuleLink */
+ { NULL } /* ApiLink */
+ },
+};
+
+
+
+
+static BOOL ARRAY_EnsureSize(PARRAY Array, DWORD ItemSize, DWORD GrowWith)
+{
+ PVOID pNewData;
+ DWORD Count;
+
+ if (Array->MaxSize > Array->Size)
+ return TRUE;
+
+ Count = Array->Size + GrowWith;
+ pNewData = SeiAlloc(Count * ItemSize);
+
+ if (!pNewData)
+ {
+ SHIMENG_FAIL("Failed to allocate %d bytes\n", Count * ItemSize);
+ return FALSE;
+ }
+ Array->MaxSize = Count;
+
+ if (Array->Data)
+ {
+ memcpy(pNewData, Array->Data, Array->Size * ItemSize);
+ SeiFree(Array->Data);
+ }
+ Array->Data = pNewData;
+
+ return TRUE;
+}
@@ -115,49 +172,782 @@
}
-
-
-
-
+PVOID SeiGetModuleFromAddress(PVOID addr)
+{
+ PVOID hModule = NULL;
+ RtlPcToFileHeader(addr, &hModule);
+ return hModule;
+}
+
+
+
+/* TODO: Guard against recursive calling / calling init multiple times! */
VOID NotifyShims(DWORD dwReason, PVOID Info)
{
- /* Enumerate all loaded shims */
-}
+ PSHIMMODULE Data;
+ DWORD n;
+
+ Data = g_pShimInfo.Data;
+ for (n = 0; n < g_pShimInfo.Size; ++n)
+ {
+ if (!Data[n].pNotifyShims)
+ continue;
+
+ Data[n].pNotifyShims(dwReason, Info);
+ }
+}
+
+
+
+VOID SeiCheckComPlusImage(PVOID BaseAddress)
+{
+ ULONG ComSectionSize;
+ g_bComPlusImage = RtlImageDirectoryEntryToData(BaseAddress, TRUE,
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &ComSectionSize) != NULL;
+
+ SHIMENG_INFO("COM+ executable %s\n", g_bComPlusImage ? "TRUE" :
"FALSE");
+}
+
+
+PSHIMMODULE SeiGetShimInfo(PVOID BaseAddress)
+{
+ PSHIMMODULE Data;
+ DWORD n;
+
+ Data = g_pShimInfo.Data;
+ for (n = 0; n < g_pShimInfo.Size; ++n)
+ {
+ if (Data[n].BaseAddress == BaseAddress)
+ return &Data[n];
+ }
+ return NULL;
+}
+
+PSHIMMODULE SeiCreateShimInfo(PCWSTR DllName, PVOID BaseAddress)
+{
+ static const ANSI_STRING GetHookAPIs = RTL_CONSTANT_STRING("GetHookAPIs");
+ static const ANSI_STRING NotifyShims = RTL_CONSTANT_STRING("NotifyShims");
+ PSHIMMODULE Data;
+ PVOID pGetHookAPIs, pNotifyShims;
+
+ if (!NT_SUCCESS(LdrGetProcedureAddress(BaseAddress, (PANSI_STRING)&GetHookAPIs,
0, &pGetHookAPIs)) ||
+ !NT_SUCCESS(LdrGetProcedureAddress(BaseAddress, (PANSI_STRING)&NotifyShims,
0, &pNotifyShims)))
+ {
+ SHIMENG_WARN("Failed to resolve entry points for %S\n", DllName);
+ return NULL;
+ }
+
+ if (!ARRAY_EnsureSize(&g_pShimInfo, sizeof(SHIMMODULE), 5))
+ return NULL;
+
+ Data = g_pShimInfo.Data;
+ Data += g_pShimInfo.Size;
+ g_pShimInfo.Size++;
+
+ RtlCreateUnicodeString(&Data->Name, DllName);
+ Data->BaseAddress = BaseAddress;
+
+ Data->pGetHookAPIs = pGetHookAPIs;
+ Data->pNotifyShims = pNotifyShims;
+
+ Data->HookApis.Data = NULL;
+ Data->HookApis.Size = 0;
+ Data->HookApis.MaxSize = 0;
+
+ return Data;
+}
+
+VOID SeiAppendHookInfo(PSHIMMODULE pShimInfo, PHOOKAPIEX pHookApi, DWORD dwHookCount)
+{
+ PHOOKAPIPOINTERS Data;
+ if (!ARRAY_EnsureSize(&pShimInfo->HookApis, sizeof(HOOKAPIPOINTERS), 5))
+ return;
+
+ Data = pShimInfo->HookApis.Data;
+ Data += pShimInfo->HookApis.Size;
+
+ Data->pHookApi = pHookApi;
+ Data->dwHookCount = dwHookCount;
+ pShimInfo->HookApis.Size++;
+}
+
+PHOOKMODULEINFO SeiFindHookModuleInfo(PUNICODE_STRING ModuleName, PVOID BaseAddress)
+{
+ DWORD n;
+ PHOOKMODULEINFO Data = g_pHookArray.Data;
+
+ for (n = 0; n < g_pHookArray.Size; ++n)
+ {
+ if (BaseAddress && BaseAddress == Data[n].BaseAddress)
+ return &Data[n];
+
+ if (!BaseAddress && RtlEqualUnicodeString(ModuleName, &Data[n].Name,
TRUE))
+ return &Data[n];
+ }
+
+ return NULL;
+}
+
+PHOOKMODULEINFO SeiFindHookModuleInfoForImportDescriptor(PBYTE DllBase,
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor)
+{
+ UNICODE_STRING DllName;
+ PVOID DllHandle;
+ NTSTATUS Success;
+
+ if (!RtlCreateUnicodeStringFromAsciiz(&DllName, (PCSZ)(DllBase +
ImportDescriptor->Name)))
+ {
+ SHIMENG_FAIL("Unable to convert dll name to unicode\n");
+ return NULL;
+ }
+
+ Success = LdrGetDllHandle(NULL, NULL, &DllName, &DllHandle);
+ RtlFreeUnicodeString(&DllName);
+
+ if (!NT_SUCCESS(Success))
+ {
+ SHIMENG_FAIL("Unable to get module handle for %wZ\n", &DllName);
+ return NULL;
+ }
+
+ return SeiFindHookModuleInfo(NULL, DllHandle);
+}
+
+static LPCWSTR SeiGetStringPtr(PDB pdb, TAGID tag, TAG type)
+{
+ TAGID tagEntry = SdbFindFirstTag(pdb, tag, type);
+ if (tagEntry == TAGID_NULL)
+ return NULL;
+
+ return SdbGetStringTagPtr(pdb, tagEntry);
+}
+
+static DWORD SeiGetDWORD(PDB pdb, TAGID tag, TAG type)
+{
+ TAGID tagEntry = SdbFindFirstTag(pdb, tag, type);
+ if (tagEntry == TAGID_NULL)
+ return 0;
+
+ return SdbReadDWORDTag(pdb, tagEntry, TAGID_NULL);
+}
+
+
+
+VOID SeiAddShim(TAGREF trShimRef, PARRAY pShimRef)
+{
+ TAGREF* Data;
+ if (!ARRAY_EnsureSize(pShimRef, sizeof(TAGREF), 10))
+ return;
+
+ Data = pShimRef->Data;
+ Data[pShimRef->Size] = trShimRef;
+ pShimRef->Size++;
+}
+
+VOID SeiBuildShimRefArray(HSDB hsdb, SDBQUERYRESULT* pQuery, PARRAY pShimRef)
+{
+ DWORD n;
+
+ for (n = 0; n < pQuery->dwExeCount; ++n)
+ {
+ PDB pdb;
+ TAGID tag;
+ if (SdbTagRefToTagID(hsdb, pQuery->atrExes[n], &pdb, &tag))
+ {
+ LPCWSTR ExeName = SeiGetStringPtr(pdb, tag, TAG_NAME);
+ TAGID ShimRef = SdbFindFirstTag(pdb, tag, TAG_SHIM_REF);
+
+ if (ExeName)
+ SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Exe(%S))\n", ExeName);
+
+ while (ShimRef != TAGID_NULL)
+ {
+ TAGREF trShimRef;
+ if (SdbTagIDToTagRef(hsdb, pdb, ShimRef, &trShimRef))
+ SeiAddShim(trShimRef, pShimRef);
+
+
+ ShimRef = SdbFindNextTag(pdb, tag, ShimRef);
+ }
+
+ /* Handle FLAG_REF */
+ }
+ }
+
+
+ for (n = 0; n < pQuery->dwLayerCount; ++n)
+ {
+ PDB pdb;
+ TAGID tag;
+ if (SdbTagRefToTagID(hsdb, pQuery->atrLayers[n], &pdb, &tag))
+ {
+ LPCWSTR LayerName = SeiGetStringPtr(pdb, tag, TAG_NAME);
+ TAGID ShimRef = SdbFindFirstTag(pdb, tag, TAG_SHIM_REF);
+ if (LayerName)
+ SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Layer(%S))\n",
LayerName);
+
+ while (ShimRef != TAGID_NULL)
+ {
+ TAGREF trShimRef;
+ if (SdbTagIDToTagRef(hsdb, pdb, ShimRef, &trShimRef))
+ SeiAddShim(trShimRef, pShimRef);
+
+ ShimRef = SdbFindNextTag(pdb, tag, ShimRef);
+ }
+
+ /* Handle FLAG_REF */
+ }
+ }
+}
+
+
+VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount)
+{
+ DWORD n;
+ UNICODE_STRING UnicodeModName;
+ WCHAR Buf[512];
+
+ RtlInitEmptyUnicodeString(&UnicodeModName, Buf, sizeof(Buf));
+
+ for (n = 0; n < dwHookCount; ++n)
+ {
+ ANSI_STRING AnsiString;
+ PVOID DllHandle;
+ PHOOKAPIEX hook = hooks + n;
+ PHOOKMODULEINFO HookModuleInfo;
+ PSINGLE_LIST_ENTRY Entry;
+
+ RtlInitAnsiString(&AnsiString, hook->LibraryName);
+ if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeModName,
&AnsiString, FALSE)))
+ {
+ SHIMENG_FAIL("Unable to convert %s to Unicode\n",
hook->LibraryName);
+ continue;
+ }
+
+ RtlInitAnsiString(&AnsiString, hook->FunctionName);
+ if (NT_SUCCESS(LdrGetDllHandle(NULL, 0, &UnicodeModName, &DllHandle)))
+ {
+ PVOID ProcAddress;
+
+
+ if (!NT_SUCCESS(LdrGetProcedureAddress(DllHandle, &AnsiString, 0,
&ProcAddress)))
+ {
+ SHIMENG_FAIL("Unable to retrieve %s!%s\n",
hook->LibraryName, hook->FunctionName);
+ continue;
+ }
+
+ HookModuleInfo = SeiFindHookModuleInfo(NULL, DllHandle);
+ hook->OriginalFunction = ProcAddress;
+ }
+ else
+ {
+ HookModuleInfo = SeiFindHookModuleInfo(&UnicodeModName, NULL);
+ DllHandle = NULL;
+ }
+
+ if (!HookModuleInfo)
+ {
+ if (!ARRAY_EnsureSize(&g_pHookArray, sizeof(HOOKMODULEINFO), 5))
+ continue;
+
+ HookModuleInfo = g_pHookArray.Data;
+ HookModuleInfo += g_pHookArray.Size;
+ g_pHookArray.Size++;
+
+ HookModuleInfo->BaseAddress = DllHandle;
+ RtlCreateUnicodeString(&HookModuleInfo->Name, UnicodeModName.Buffer);
+ }
+
+ Entry = &HookModuleInfo->ModuleLink;
+
+ while (Entry && Entry->Next)
+ {
+ PHOOKAPIEX HookApi = CONTAINING_RECORD(Entry->Next, HOOKAPIEX,
ModuleLink);
+
+ int CmpResult = strcmp(hook->FunctionName, HookApi->FunctionName);
+ if (CmpResult == 0)
+ {
+ /* Multiple hooks on one function? --> use ApiLink */
+ SHIMENG_FAIL("Multiple hooks on one API is not yet
supported!\n");
+ ASSERT(0);
+ }
+ else if (CmpResult < 0)
+ {
+ /* Break out of the loop to have the entry inserted 'in place'
*/
+ break;
+ }
+
+ Entry = Entry->Next;
+ }
+ /* If Entry is not NULL, the item is not inserted yet, so link it at the end. */
+ if (Entry)
+ {
+ hook->ModuleLink.Next = Entry->Next;
+ Entry->Next = &hook->ModuleLink;
+ }
+ }
+}
+
+
+FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName)
+{
+ char szOrdProcName[10] = "";
+ LPCSTR lpPrintName = lpProcName;
+ PVOID Addr = _ReturnAddress();
+ PHOOKMODULEINFO HookModuleInfo;
+ FARPROC proc = ((GETPROCADDRESSPROC)g_IntHookEx[0].OriginalFunction)(hModule,
lpProcName);
+
+ if (!HIWORD(lpProcName))
+ {
+ sprintf(szOrdProcName, "#%lu", (DWORD)lpProcName);
+ lpPrintName = szOrdProcName;
+ }
+
+ Addr = SeiGetModuleFromAddress(Addr);
+ if (SE_IsShimDll(Addr))
+ {
+ SHIMENG_MSG("Not touching GetProcAddress for shim dll (%p!%s)",
hModule, lpPrintName);
+ return proc;
+ }
+
+ SHIMENG_MSG("(GetProcAddress(%p!%s) => %p\n", hModule, lpProcName,
lpPrintName);
+
+ HookModuleInfo = SeiFindHookModuleInfo(NULL, hModule);
+
+ /* FIXME: Ordinal not yet supported */
+ if (HookModuleInfo && HIWORD(lpProcName))
+ {
+ PSINGLE_LIST_ENTRY Entry;
+
+ Entry = HookModuleInfo->ModuleLink.Next;
+
+ while (Entry)
+ {
+ PHOOKAPIEX HookApi = CONTAINING_RECORD(Entry, HOOKAPIEX, ModuleLink);
+
+ int CmpResult = strcmp(lpProcName, HookApi->FunctionName);
+ if (CmpResult == 0)
+ {
+ SHIMENG_MSG("Redirecting %p to %p\n", proc,
HookApi->ReplacementFunction);
+ proc = HookApi->ReplacementFunction;
+ break;
+ }
+ else if (CmpResult < 0)
+ {
+ SHIMENG_MSG("Not found %s\n", lpProcName);
+ /* We are not going to find it anymore.. */
+ break;
+ }
+
+ Entry = Entry->Next;
+ }
+ }
+
+ return proc;
+}
+
+VOID SeiResolveAPIs(VOID)
+{
+ PSHIMMODULE Data;
+ DWORD mod, n;
+
+ Data = g_pShimInfo.Data;
+
+ /* Enumerate all Shim modules */
+ for (mod = 0; mod < g_pShimInfo.Size; ++mod)
+ {
+ PHOOKAPIPOINTERS pShims = Data[mod].HookApis.Data;
+ DWORD dwShimCount = Data[mod].HookApis.Size;
+
+ /* Enumerate all Shims */
+ for (n = 0; n < dwShimCount; ++n)
+ {
+ PHOOKAPIEX hooks = pShims[n].pHookApi;
+ DWORD dwHookCount = pShims[n].dwHookCount;
+
+ SeiAddHooks(hooks, dwHookCount);
+ }
+ }
+}
+
+VOID SeiAddInternalHooks(DWORD dwNumHooks)
+{
+ if (dwNumHooks == 0)
+ {
+ g_bInternalHooksUsed = FALSE;
+ return;
+ }
+
+ SeiAddHooks(g_IntHookEx, _countof(g_IntHookEx));
+ g_bInternalHooksUsed = TRUE;
+}
+
+VOID SeiPatchNewImport(PIMAGE_THUNK_DATA FirstThunk, PHOOKAPIEX HookApi,
PLDR_DATA_TABLE_ENTRY LdrEntry)
+{
+ ULONG OldProtection = 0;
+ PVOID Ptr;
+ ULONG Size;
+ NTSTATUS Status;
+
+ SHIMENG_INFO("Hooking API \"%s!%s\" for DLL \"%wZ\"\n",
HookApi->LibraryName, HookApi->FunctionName, &LdrEntry->BaseDllName);
+
+ Ptr = &FirstThunk->u1.Function;
+ Size = sizeof(FirstThunk->u1.Function);
+ Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size,
PAGE_EXECUTE_READWRITE, &OldProtection);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SHIMENG_FAIL("Unable to unprotect 0x%p\n",
&FirstThunk->u1.Function);
+ return;
+ }
+
+ SHIMENG_INFO("changing 0x%p to 0x%p\n", FirstThunk->u1.Function,
HookApi->ReplacementFunction);
+#ifdef _WIN64
+ FirstThunk->u1.Function = (ULONGLONG)HookApi->ReplacementFunction;
+#else
+ FirstThunk->u1.Function = (DWORD)HookApi->ReplacementFunction;
+#endif
+
+ Size = sizeof(FirstThunk->u1.Function);
+ Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size,
OldProtection, &OldProtection);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SHIMENG_WARN("Unable to reprotect 0x%p\n",
&FirstThunk->u1.Function);
+ }
+}
+
+/* Level(INFO) [SeiPrintExcludeInfo] Module "kernel32.dll" excluded for shim
VistaRTMVersionLie, API "NTDLL.DLL!RtlGetVersion", because it is in
System32/WinSXS. */
+
+VOID SeiHookImports(PLDR_DATA_TABLE_ENTRY LdrEntry)
+{
+ ULONG Size;
+ PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
+ PBYTE DllBase = LdrEntry->DllBase;
+
+ if (SE_IsShimDll(DllBase) || g_hInstance == LdrEntry->DllBase)
+ {
+ SHIMENG_INFO("Skipping shim module 0x%p \"%wZ\"\n",
LdrEntry->DllBase, &LdrEntry->BaseDllName);
+ return;
+ }
+
+ ImportDescriptor = RtlImageDirectoryEntryToData(DllBase, TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT, &Size);
+ if (!ImportDescriptor)
+ {
+ SHIMENG_INFO("Skipping module 0x%p \"%wZ\" due to no iat
found\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
+ return;
+ }
+
+ SHIMENG_INFO("Hooking module 0x%p \"%wZ\"\n",
LdrEntry->DllBase, &LdrEntry->BaseDllName);
+
+ for ( ;ImportDescriptor->Name && ImportDescriptor->OriginalFirstThunk;
ImportDescriptor++)
+ {
+ PHOOKMODULEINFO HookModuleInfo;
+
+ /* Do we have hooks for this module? */
+ HookModuleInfo = SeiFindHookModuleInfoForImportDescriptor(DllBase,
ImportDescriptor);
+
+ if (HookModuleInfo)
+ {
+ PIMAGE_THUNK_DATA OriginalThunk, FirstThunk;
+ PSINGLE_LIST_ENTRY Entry;
+
+ Entry = HookModuleInfo->ModuleLink.Next;
+
+ while (Entry)
+ {
+ DWORD dwFound = 0;
+ OriginalThunk = (PIMAGE_THUNK_DATA)(DllBase +
ImportDescriptor->OriginalFirstThunk);
+ FirstThunk = (PIMAGE_THUNK_DATA)(DllBase +
ImportDescriptor->FirstThunk);
+
+ for (;OriginalThunk->u1.AddressOfData &&
FirstThunk->u1.Function && Entry; OriginalThunk++, FirstThunk++)
+ {
+ PHOOKAPIEX HookApi = CONTAINING_RECORD(Entry, HOOKAPIEX,
ModuleLink);
+
+ if (!IMAGE_SNAP_BY_ORDINAL32(OriginalThunk->u1.AddressOfData))
+ {
+ PIMAGE_IMPORT_BY_NAME ImportName;
+
+ ImportName = (PIMAGE_IMPORT_BY_NAME)(DllBase +
OriginalThunk->u1.AddressOfData);
+ if (!strcmp((PCSTR)ImportName->Name,
HookApi->FunctionName))
+ {
+ SeiPatchNewImport(FirstThunk, HookApi, LdrEntry);
+
+ /* Sadly, iat does not have to be sorted, and can even
contain duplicate entries. */
+ dwFound++;
+ }
+ }
+ else
+ {
+ SHIMENG_FAIL("Ordinals not yet supported\n");
+ ASSERT(0);
+ }
+ }
+
+ if (Entry)
+ {
+ if (dwFound != 1)
+ {
+ /* One entry not found. */
+ PHOOKAPIEX HookApi = CONTAINING_RECORD(Entry, HOOKAPIEX,
ModuleLink);
+ if (!dwFound)
+ SHIMENG_INFO("Entry \"%s!%s\" not found for
\"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName,
&LdrEntry->BaseDllName);
+ else
+ SHIMENG_INFO("Entry \"%s!%s\" found %d times
for \"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName, dwFound,
&LdrEntry->BaseDllName);
+ }
+
+ Entry = Entry->Next;
+ }
+ }
+ }
+ }
+}
+
+
+VOID PatchNewModules(PPEB Peb)
+{
+ PLIST_ENTRY ListHead, ListEntry;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+
+ ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+ ListEntry = ListHead->Flink;
+
+ while (ListHead != ListEntry)
+ {
+ LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+ SeiHookImports(LdrEntry);
+
+ ListEntry = ListEntry->Flink;
+ }
+}
+
+
+/*
+Level(INFO) Using USER apphack flags 0x2080000
+*/
+
+VOID SeiInit(PUNICODE_STRING ProcessImage, HSDB hsdb, SDBQUERYRESULT* pQuery)
+{
+ DWORD n;
+ ARRAY ShimRef;
+ TAGREF* Data;
+ DWORD dwTotalHooks = 0;
+
+ PPEB Peb = NtCurrentPeb();
+
+ ShimRef.Data = NULL;
+ ShimRef.Size = ShimRef.MaxSize = 0;
+
+ SeiCheckComPlusImage(Peb->ImageBaseAddress);
+
+ /* TODO:
+ if (pQuery->trApphelp)
+ SeiDisplayAppHelp(?pQuery->trApphelp?);
+ */
+
+ SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(ExePath(%wZ))\n", ProcessImage);
+ SeiBuildShimRefArray(hsdb, pQuery, &ShimRef);
+ SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Complete)\n");
+
+ SHIMENG_INFO("Got %d shims\n", ShimRef.Size);
+ /* TODO:
+ SeiBuildGlobalInclExclList()
+ */
+
+ Data = ShimRef.Data;
+
+ for (n = 0; n < ShimRef.Size; ++n)
+ {
+ PDB pdb;
+ TAGID ShimRef;
+ if (SdbTagRefToTagID(hsdb, Data[n], &pdb, &ShimRef))
+ {
+ LPCWSTR ShimName, DllName;
+ TAGID ShimTag;
+ WCHAR FullNameBuffer[MAX_PATH];
+ UNICODE_STRING UnicodeDllName;
+ PVOID BaseAddress;
+ PSHIMMODULE pShimInfo = NULL;
+ const char* szCommandLine = "";
+ PHOOKAPIEX pHookApi;
+ DWORD dwHookCount;
+
+ ShimName = SeiGetStringPtr(pdb, ShimRef, TAG_NAME);
+ if (!ShimName)
+ {
+ SHIMENG_FAIL("Failed to retrieve the name for 0x%x\n",
Data[n]);
+ continue;
+ }
+
+ ShimTag = SeiGetDWORD(pdb, ShimRef, TAG_SHIM_TAGID);
+ if (!ShimTag)
+ {
+ SHIMENG_FAIL("Failed to resolve %S to a shim\n", ShimName);
+ continue;
+ }
+
+ if (!SdbGetAppPatchDir(NULL, FullNameBuffer, _countof(FullNameBuffer)))
+ {
+ SHIMENG_WARN("Failed to get the AppPatch dir\n");
+ continue;
+ }
+
+ DllName = SeiGetStringPtr(pdb, ShimTag, TAG_DLLFILE);
+ if (DllName == NULL ||
+ !SUCCEEDED(StringCchCatW(FullNameBuffer, _countof(FullNameBuffer),
L"\\")) ||
+ !SUCCEEDED(StringCchCatW(FullNameBuffer, _countof(FullNameBuffer),
DllName)))
+ {
+ SHIMENG_WARN("Failed to build a full path for %S\n",
ShimName);
+ continue;
+ }
+
+ /* TODO:
+ SeiGetShimCommandLine();
+ [SeiInit] COMMAND_LINE VirtualRegistry(WINNT;VistaRTMLie) from AcLayers.DLL
+ */
+
+ RtlInitUnicodeString(&UnicodeDllName, FullNameBuffer);
+ if (NT_SUCCESS(LdrGetDllHandle(NULL, NULL, &UnicodeDllName,
&BaseAddress)))
+ {
+ pShimInfo = SeiGetShimInfo(BaseAddress);
+ }
+ else if (!NT_SUCCESS(LdrLoadDll(NULL, NULL, &UnicodeDllName,
&BaseAddress)))
+ {
+ SHIMENG_WARN("Failed to load %wZ for %S\n",
&UnicodeDllName, ShimName);
+ continue;
+ }
+ if (!pShimInfo)
+ {
+ pShimInfo = SeiCreateShimInfo(DllName, BaseAddress);
+ if (!pShimInfo)
+ {
+ SHIMENG_FAIL("Failed to allocate ShimInfo for %S\n",
DllName);
+ continue;
+ }
+ }
+
+ SHIMENG_INFO("Shim DLL 0x%p \"%wZ\" loaded\n",
BaseAddress, &UnicodeDllName);
+ SHIMENG_INFO("Using SHIM \"%S!%S\"\n", DllName,
ShimName);
+
+
+ pHookApi = pShimInfo->pGetHookAPIs(szCommandLine, ShimName,
&dwHookCount);
+ SHIMENG_INFO("GetHookAPIs returns %d hooks for DLL \"%wZ\"
SHIM \"%S\"\n", dwHookCount, &UnicodeDllName, ShimName);
+ if (dwHookCount)
+ SeiAppendHookInfo(pShimInfo, pHookApi, dwHookCount);
+
+ dwTotalHooks += dwHookCount;
+ /*SeiBuildInclExclList*/
+ }
+ }
+
+ SeiAddInternalHooks(dwTotalHooks);
+ SeiResolveAPIs();
+ PatchNewModules(Peb);
+}
+
+
+
+BOOL SeiGetShimData(PUNICODE_STRING ProcessImage, PVOID pShimData, HSDB* pHsdb,
SDBQUERYRESULT* pQuery)
+{
+ static const UNICODE_STRING ForbiddenShimmingApps[] = {
+ RTL_CONSTANT_STRING(L"ntsd.exe"),
+ RTL_CONSTANT_STRING(L"windbg.exe"),
+#if WINVER >= 0x600
+ RTL_CONSTANT_STRING(L"slsvc.exe"),
+#endif
+ };
+ static const UNICODE_STRING BackSlash = RTL_CONSTANT_STRING(L"\\");
+ static const UNICODE_STRING ForwdSlash = RTL_CONSTANT_STRING(L"/");
+ UNICODE_STRING ProcessName;
+ USHORT Back, Forward;
+ HSDB hsdb;
+ DWORD n;
+
+ if
(!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
ProcessImage, &BackSlash, &Back)))
+ Back = 0;
+
+ if
(!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
ProcessImage, &ForwdSlash, &Forward)))
+ Forward = 0;
+
+ if (Back < Forward)
+ Back = Forward;
+
+ if (Back)
+ Back += sizeof(WCHAR);
+
+ ProcessName.Buffer = ProcessImage->Buffer + Back / sizeof(WCHAR);
+ ProcessName.Length = ProcessImage->Length - Back;
+ ProcessName.MaximumLength = ProcessImage->MaximumLength - Back;
+
+ for (n = 0; n < _countof(ForbiddenShimmingApps); ++n)
+ {
+ if (RtlEqualUnicodeString(&ProcessName, ForbiddenShimmingApps + n, TRUE))
+ {
+ SHIMENG_MSG("Not shimming %wZ\n", ForbiddenShimmingApps + n);
+ return FALSE;
+ }
+ }
+
+ /* We should probably load all db's here, but since we do not support that yet...
*/
+ hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL);
+ if (hsdb)
+ {
+ if (SdbUnpackAppCompatData(hsdb, ProcessImage->Buffer, pShimData, pQuery))
+ {
+ *pHsdb = hsdb;
+ return TRUE;
+ }
+ SdbReleaseDatabase(hsdb);
+ }
+ return FALSE;
+}
+
VOID NTAPI SE_InstallBeforeInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
{
- SHIMENG_FAIL("(%wZ, %p)", ProcessImage, pShimData);
- /* Find & Load all shims.. */
+ HSDB hsdb = NULL;
+ SDBQUERYRESULT QueryResult = { { 0 } };
+ SHIMENG_MSG("(%wZ, %p)\n", ProcessImage, pShimData);
+
+ if (!SeiGetShimData(ProcessImage, pShimData, &hsdb, &QueryResult))
+ {
+ SHIMENG_FAIL("Failed to get shim data\n");
+ return;
+ }
+
+ g_bShimDuringInit = TRUE;
+ SeiInit(ProcessImage, hsdb, &QueryResult);
+ g_bShimDuringInit = FALSE;
+
+ SdbReleaseDatabase(hsdb);
}
VOID NTAPI SE_InstallAfterInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
{
- SHIMENG_FAIL("(%wZ, %p)", ProcessImage, pShimData);
NotifyShims(SHIM_NOTIFY_ATTACH, NULL);
}
VOID NTAPI SE_ProcessDying(VOID)
{
- SHIMENG_FAIL("()");
+ SHIMENG_MSG("()\n");
NotifyShims(SHIM_NOTIFY_DETACH, NULL);
}
VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
{
- SHIMENG_FAIL("(%p)", LdrEntry);
+ SHIMENG_INFO("%sINIT. loading DLL \"%wZ\"\n", g_bShimDuringInit ?
"" : "AFTER ", &LdrEntry->BaseDllName);
NotifyShims(SHIM_REASON_DLL_LOAD, LdrEntry);
}
VOID WINAPI SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
{
- SHIMENG_FAIL("(%p)", LdrEntry);
+ SHIMENG_MSG("(%p)\n", LdrEntry);
NotifyShims(SHIM_REASON_DLL_UNLOAD, LdrEntry);
}
BOOL WINAPI SE_IsShimDll(PVOID BaseAddress)
{
- SHIMENG_FAIL("(%p)", BaseAddress);
- return FALSE;
-}
-
+ SHIMENG_MSG("(%p)\n", BaseAddress);
+
+ return SeiGetShimInfo(BaseAddress) != NULL;
+}
+
Added: trunk/reactos/dll/appcompat/apphelp/shimeng.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/appcompat/apphelp/shim…
==============================================================================
--- trunk/reactos/dll/appcompat/apphelp/shimeng.h (added)
+++ trunk/reactos/dll/appcompat/apphelp/shimeng.h [iso-8859-1] Sat Jul 1 20:06:30 2017
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2017 Mark Jansen
+ *
+ * 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
+ */
+
+#ifndef SHIMENG_H
+#define SHIMENG_H
+
+/* Structure that allows dynamic growing */
+typedef struct _ARRAY
+{
+ PVOID Data;
+ DWORD Size;
+ DWORD MaxSize;
+} ARRAY, *PARRAY;
+
+
+/* Shims do not know it, but actually they use the type HOOKAPIEX.
+ We use the 'Reserved' entry for our own purposes. */
+
+typedef struct tagHOOKAPIEX
+{
+ PCSTR LibraryName;
+ PCSTR FunctionName;
+ PVOID ReplacementFunction;
+ PVOID OriginalFunction;
+ SINGLE_LIST_ENTRY ModuleLink;
+ SINGLE_LIST_ENTRY ApiLink;
+} HOOKAPIEX, *PHOOKAPIEX;
+
+C_ASSERT(sizeof(HOOKAPIEX) == sizeof(HOOKAPI));
+C_ASSERT(offsetof(HOOKAPIEX, ModuleLink) == offsetof(HOOKAPI, Reserved));
+
+
+typedef struct _HOOKAPIPOINTERS
+{
+ PHOOKAPIEX pHookApi;
+ DWORD dwHookCount;
+} HOOKAPIPOINTERS, *PHOOKAPIPOINTERS;
+
+typedef struct _SHIMMODULE
+{
+ UNICODE_STRING Name;
+ PVOID BaseAddress;
+
+ PHOOKAPIEX (WINAPI* pGetHookAPIs)(LPCSTR szCommandLine, LPCWSTR wszShimName, PDWORD
pdwHookCount);
+ BOOL (WINAPI* pNotifyShims)(DWORD fdwReason, PVOID ptr);
+
+ ARRAY HookApis; /* HOOKAPIPOINTERS */
+} SHIMMODULE, *PSHIMMODULE;
+
+typedef struct _HOOKMODULEINFO
+{
+ UNICODE_STRING Name;
+ PVOID BaseAddress;
+
+ SINGLE_LIST_ENTRY ModuleLink; /* Normal link, all entries from this module */
+ SINGLE_LIST_ENTRY ApiLink; /* Multiple hooks on one api, unsupported for now */
+} HOOKMODULEINFO, *PHOOKMODULEINFO;
+
+
+#if SDBAPI_DEBUG_ALLOC
+
+LPVOID SdbpAlloc(SIZE_T size, int line, const char* file);
+LPVOID SdbpReAlloc(LPVOID mem, SIZE_T size, SIZE_T oldSize, int line, const char* file);
+VOID SdbpFree(LPVOID mem, int line, const char* file);
+
+#define SeiAlloc(size) SdbpAlloc(size, __LINE__, __FILE__)
+#define SeiReAlloc(mem, size, oldSize) SdbpReAlloc(mem, size, oldSize, __LINE__,
__FILE__)
+#define SeiFree(mem) SdbpFree(mem, __LINE__, __FILE__)
+
+#else
+
+LPVOID SdbpAlloc(SIZE_T size);
+LPVOID SdbpReAlloc(LPVOID mem, SIZE_T size, SIZE_T oldSize);
+VOID SdbpFree(LPVOID mem);
+
+#define SeiAlloc(size) SdbpAlloc(size)
+#define SeiReAlloc(mem, size, oldSize) SdbpReAlloc(mem, size, oldSize)
+#define SeiFree(mem) SdbpFree(mem)
+
+#endif
+
+#endif // SHIMENG_H
Propchange: trunk/reactos/dll/appcompat/apphelp/shimeng.h
------------------------------------------------------------------------------
svn:eol-style = native