+PINEXCLUDE SeiFindInExclude(PARRAY InExclude, PCUNICODE_STRING DllName)
+{
+ DWORD n;
+
+ for (n = 0; n < ARRAY_Size(InExclude); ++n)
+ {
+ PINEXCLUDE InEx = ARRAY_At(InExclude, INEXCLUDE, n);
+
+ if (RtlEqualUnicodeString(&InEx->Module, DllName, TRUE))
+ return InEx;
+ }
+
+ return NULL;
+}
+
+BOOL SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry, PHOOKAPIEX HookApi)
+{
+ PSHIMINFO pShimInfo = HookApi->pShimInfo;
+ PINEXCLUDE InExclude;
+ BOOL IsExcluded = FALSE;
+
+ if (!pShimInfo)
+ {
+ /* Internal hook, do not exclude it */
+ return FALSE;
+ }
+
+ /* By default, everything from System32 or WinSxs is excluded */
+ if (RtlPrefixUnicodeString(&g_System32Directory, &LdrEntry->FullDllName, TRUE) ||
+ RtlPrefixUnicodeString(&g_SxsDirectory, &LdrEntry->FullDllName, TRUE))
+ IsExcluded = TRUE;
+
+ InExclude = SeiFindInExclude(&pShimInfo->InExclude, &LdrEntry->BaseDllName);
+ if (InExclude)
+ {
+ /* If it is on the 'exclude' list, bail out */
+ if (!InExclude->Include)
+ {
+ SHIMENG_INFO("Module '%wZ' excluded for shim %S, API '%s!%s', because it on in the exclude list.\n",
+ &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName);
+
+ return TRUE;
+ }
+ /* If it is on the 'include' list, override System32 / Winsxs check. */
+ if (IsExcluded)
+ {
+ SHIMENG_INFO("Module '%wZ' included for shim %S, API '%s!%s', because it is on the include list.\n",
+ &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName);
+
+ }
+ IsExcluded = FALSE;
+ }
+
+ if (IsExcluded)
+ {
+ SHIMENG_INFO("Module '%wZ' excluded for shim %S, API '%s!%s', because it is in System32/WinSXS.\n",
+ &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName);
+ }
+
+ return IsExcluded;
+}
+
+VOID SeiAppendInExclude(PARRAY dest, PCWSTR ModuleName, BOOL IsInclude)
+{
+ PINEXCLUDE InExclude;
+ UNICODE_STRING ModuleNameU;
+ RtlInitUnicodeString(&ModuleNameU, ModuleName);
+
+ InExclude = SeiFindInExclude(dest, &ModuleNameU);
+ if (InExclude)
+ {
+ InExclude->Include = IsInclude;
+ return;
+ }
+
+ InExclude = ARRAY_Append(dest, INEXCLUDE);
+ if (InExclude)
+ {
+ PCWSTR ModuleNameCopy = SdbpStrDup(ModuleName);
+ RtlInitUnicodeString(&InExclude->Module, ModuleNameCopy);
+ InExclude->Include = IsInclude;
+ }
+}
+
+/* Read the INEXCLUD tags from a given parent tag */
+VOID SeiReadInExclude(PDB pdb, TAGID parent, PARRAY dest)
+{
+ TAGID InExcludeTag;
+
+ InExcludeTag = SdbFindFirstTag(pdb, parent, TAG_INEXCLUD);
+
+ while (InExcludeTag != TAGID_NULL)
+ {
+ PCWSTR ModuleName;
+ TAGID ModuleTag = SdbFindFirstTag(pdb, InExcludeTag, TAG_MODULE);
+ TAGID IncludeTag = SdbFindFirstTag(pdb, InExcludeTag, TAG_INCLUDE);
+
+ ModuleName = SdbGetStringTagPtr(pdb, ModuleTag);
+ if (ModuleName)
+ {
+ SeiAppendInExclude(dest, ModuleName, IncludeTag != TAGID_NULL);
+ }
+ else
+ {
+ SHIMENG_WARN("INEXCLUDE without Module: 0x%x\n", InExcludeTag);
+ }
+
+ InExcludeTag = SdbFindNextTag(pdb, parent, InExcludeTag);
+ }
+}
+
+VOID SeiBuildGlobalInclExclList(HSDB hsdb)
+{
+ PDB pdb;
+ TAGREF tr = TAGREF_ROOT;
+ TAGID root, db, library;
+
+ if (!SdbTagRefToTagID(hsdb, tr, &pdb, &root))
+ {
+ SHIMENG_WARN("Unable to resolve database root\n");
+ return;
+ }
+ db = SdbFindFirstTag(pdb, root, TAG_DATABASE);
+ if (db == TAGID_NULL)
+ {
+ SHIMENG_WARN("Unable to resolve database\n");
+ return;
+ }
+ library = SdbFindFirstTag(pdb, db, TAG_LIBRARY);
+ if (library == TAGID_NULL)
+ {
+ SHIMENG_WARN("Unable to resolve library\n");
+ return;
+ }
+
+ SeiReadInExclude(pdb, library, &g_InExclude);
+}
+
+VOID SeiBuildInclExclList(PDB pdb, TAGID ShimTag, PSHIMINFO pShimInfo)
+{
+ DWORD n;
+
+ /* First duplicate the global in/excludes */
+ for (n = 0; n < ARRAY_Size(&g_InExclude); ++n)
+ {
+ PINEXCLUDE InEx = ARRAY_At(&g_InExclude, INEXCLUDE, n);
+ SeiAppendInExclude(&pShimInfo->InExclude, InEx->Module.Buffer, InEx->Include);
+ }
+
+ /* Now read this shim's in/excludes (possibly overriding the global ones) */
+ SeiReadInExclude(pdb, ShimTag, &pShimInfo->InExclude);
+}
+
+/* Given one loaded module, redirect (hook) all functions from the iat that are registered by shims */