ReactOS  0.4.12-dev-708-g95ed44e
shimeng.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Application compatibility module
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Shim engine core
5  * COPYRIGHT: Copyright 2015-2019 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #define WIN32_NO_STATUS
9 #include "ntndk.h"
10 #define IN_APPHELP
11 #include "shimlib.h"
12 #include <strsafe.h>
13 /* Make sure we don't include apphelp logging */
14 #define APPHELP_NOSDBPAPI
15 #include "apphelp.h"
16 #include "shimeng.h"
17 
18 
19 
22 
23 
24 extern HMODULE g_hInstance;
33 static ARRAY g_pShimInfo; /* PSHIMMODULE */
34 static ARRAY g_pHookArray; /* HOOKMODULEINFO */
35 static ARRAY g_InExclude; /* INEXCLUDE */
36 
37 /* If we have setup a hook for a function, we should also redirect GetProcAddress for this function */
39 {
40  {
41  "kernel32.dll", /* LibraryName */
42  "GetProcAddress", /* FunctionName */
43  StubGetProcAddress, /* ReplacementFunction*/
44  NULL, /* OriginalFunction */
45  NULL, /* pShimInfo */
46  NULL /* Unused */
47  },
48 };
49 
50 static inline BOOL ARRAY_InitWorker(PARRAY Array, DWORD ItemSize)
51 {
52  Array->Data__ = NULL;
53  Array->Size__ = Array->MaxSize__ = 0;
54  Array->ItemSize__ = ItemSize;
55 
56  return TRUE;
57 }
58 
59 static inline BOOL ARRAY_EnsureSize(PARRAY Array, DWORD ItemSize, DWORD GrowWith)
60 {
61  PVOID pNewData;
62  DWORD Count;
63 
64  ASSERT(Array);
65  ASSERT(ItemSize == Array->ItemSize__);
66 
67  if (Array->MaxSize__ > Array->Size__)
68  return TRUE;
69 
70  Count = Array->Size__ + GrowWith;
71  pNewData = SeiAlloc(Count * ItemSize);
72 
73  if (!pNewData)
74  {
75  SHIMENG_FAIL("Failed to allocate %d bytes\n", Count * ItemSize);
76  return FALSE;
77  }
78  Array->MaxSize__ = Count;
79 
80  if (Array->Data__)
81  {
82  memcpy(pNewData, Array->Data__, Array->Size__ * ItemSize);
83  SeiFree(Array->Data__);
84  }
85  Array->Data__ = pNewData;
86 
87  return TRUE;
88 }
89 
90 static inline PVOID ARRAY_AppendWorker(PARRAY Array, DWORD ItemSize, DWORD GrowWith)
91 {
92  PBYTE pData;
93 
94  if (!ARRAY_EnsureSize(Array, ItemSize, GrowWith))
95  return NULL;
96 
97  pData = Array->Data__;
98  pData += (Array->Size__ * ItemSize);
99  Array->Size__++;
100 
101  return pData;
102 }
103 
105 {
106  PBYTE pData;
107 
108  ASSERT(Array);
109  ASSERT(ItemSize == Array->ItemSize__);
110  ASSERT(n < Array->Size__);
111 
112  pData = Array->Data__;
113  return pData + (n * ItemSize);
114 }
115 
116 
117 #define ARRAY_Init(Array, TypeOfArray) ARRAY_InitWorker((Array), sizeof(TypeOfArray))
118 #define ARRAY_Append(Array, TypeOfArray) (TypeOfArray*)ARRAY_AppendWorker((Array), sizeof(TypeOfArray), 5)
119 #define ARRAY_At(Array, TypeOfArray, at) (TypeOfArray*)ARRAY_AtWorker((Array), sizeof(TypeOfArray), at)
120 #define ARRAY_Size(Array) (Array)->Size__
121 
122 
124 {
125  static const UNICODE_STRING DebugKey = RTL_CONSTANT_STRING(L"SHIMENG_DEBUG_LEVEL");
126  UNICODE_STRING DebugValue;
128  ULONG NewLevel = SEI_MSG; /* Show some basic info in the logs, unless configured different */
129  WCHAR Buffer[40];
130 
131  RtlInitEmptyUnicodeString(&DebugValue, Buffer, sizeof(Buffer));
132 
133  Status = RtlQueryEnvironmentVariable_U(NULL, &DebugKey, &DebugValue);
134 
135  if (NT_SUCCESS(Status))
136  {
137  if (!NT_SUCCESS(RtlUnicodeStringToInteger(&DebugValue, 10, &NewLevel)))
138  NewLevel = 0;
139  }
140  g_ShimEngDebugLevel = NewLevel;
141 }
142 
143 
156 {
157  char Buffer[512];
158  char* Current = Buffer;
159  const char* LevelStr;
160  size_t Length = sizeof(Buffer);
161  va_list ArgList;
162  HRESULT hr;
163 
164  if (g_ShimEngDebugLevel == 0xffffffff)
166 
168  return FALSE;
169 
170  switch (Level)
171  {
172  case SEI_MSG:
173  LevelStr = "MSG ";
174  break;
175  case SEI_FAIL:
176  LevelStr = "FAIL";
177  break;
178  case SEI_WARN:
179  LevelStr = "WARN";
180  break;
181  case SEI_INFO:
182  LevelStr = "INFO";
183  break;
184  default:
185  LevelStr = "USER";
186  break;
187  }
188 
189  if (Function)
190  hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] [%s] ", LevelStr, Function);
191  else
192  hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] ", LevelStr);
193 
194  if (!SUCCEEDED(hr))
195  return FALSE;
196 
197  va_start(ArgList, Format);
198  hr = StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList);
199  va_end(ArgList);
200  if (!SUCCEEDED(hr))
201  return FALSE;
202 
203  DbgPrint("%s", Buffer);
204  return TRUE;
205 }
206 
207 
209 {
210  PVOID hModule = NULL;
212  return hModule;
213 }
214 
215 
216 
217 /* TODO: Guard against recursive calling / calling init multiple times! */
219 {
220  DWORD n;
221 
222  for (n = 0; n < ARRAY_Size(&g_pShimInfo); ++n)
223  {
224  PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, n);
225  if (!pShimModule->pNotifyShims)
226  continue;
227 
228  pShimModule->pNotifyShims(dwReason, Info);
229  }
230 }
231 
232 
233 
235 {
236  ULONG ComSectionSize;
238 
239  SHIMENG_INFO("COM+ executable %s\n", g_bComPlusImage ? "TRUE" : "FALSE");
240 }
241 
242 
244 {
245  DWORD n;
246 
247  for (n = 0; n < ARRAY_Size(&g_pShimInfo); ++n)
248  {
249  PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, n);
250 
251  if (pShimModule->BaseAddress == BaseAddress)
252  return pShimModule;
253  }
254  return NULL;
255 }
256 
258 {
259  static const ANSI_STRING GetHookAPIs = RTL_CONSTANT_STRING("GetHookAPIs");
260  static const ANSI_STRING NotifyShims = RTL_CONSTANT_STRING("NotifyShims");
262  PVOID pGetHookAPIs, pNotifyShims;
263 
266  {
267  SHIMENG_WARN("Failed to resolve entry points for %S\n", DllName);
268  return NULL;
269  }
270 
272  if (!pData)
273  return NULL;
274 
275  *pData = SeiAlloc(sizeof(SHIMMODULE));
276 
277  Data = *pData;
278 
279  RtlCreateUnicodeString(&Data->Name, DllName);
280  Data->BaseAddress = BaseAddress;
281 
282  Data->pGetHookAPIs = pGetHookAPIs;
283  Data->pNotifyShims = pNotifyShims;
284 
285  ARRAY_Init(&Data->EnabledShims, PSHIMINFO);
286 
287  return Data;
288 }
289 
290 PSHIMINFO SeiAppendHookInfo(PSHIMMODULE pShimModuleInfo, PHOOKAPIEX pHookApi, DWORD dwHookCount, PCWSTR ShimName)
291 {
292  PSHIMINFO* pData, Data;
293 
294  pData = ARRAY_Append(&pShimModuleInfo->EnabledShims, PSHIMINFO);
295  if (!pData)
296  return NULL;
297 
298  *pData = SeiAlloc(sizeof(SHIMINFO));
299  Data = *pData;
300 
301  if (!Data)
302  return NULL;
303 
304  Data->ShimName = SdbpStrDup(ShimName);
305  if (!Data->ShimName)
306  return NULL;
307 
308  Data->pHookApi = pHookApi;
309  Data->dwHookCount = dwHookCount;
310  Data->pShimModule = pShimModuleInfo;
311  ARRAY_Init(&Data->InExclude, INEXCLUDE);
312  return Data;
313 }
314 
316 {
317  DWORD n;
318 
319  if (ModuleName == NULL && BaseAddress == NULL)
320  {
321  BaseAddress = NtCurrentPeb()->ImageBaseAddress;
322  }
323 
324  for (n = 0; n < ARRAY_Size(&g_pHookArray); ++n)
325  {
327 
328  if (BaseAddress && BaseAddress == pModuleInfo->BaseAddress)
329  return pModuleInfo;
330 
331  if (!BaseAddress && RtlEqualUnicodeString(ModuleName, &pModuleInfo->Name, TRUE))
332  return pModuleInfo;
333  }
334 
335  return NULL;
336 }
337 
339 {
340  UNICODE_STRING DllName;
341  PVOID DllHandle;
343 
344  if (!RtlCreateUnicodeStringFromAsciiz(&DllName, (PCSZ)(DllBase + ImportDescriptor->Name)))
345  {
346  SHIMENG_FAIL("Unable to convert dll name to unicode\n");
347  return NULL;
348  }
349 
350  Success = LdrGetDllHandle(NULL, NULL, &DllName, &DllHandle);
351 
352  if (!NT_SUCCESS(Success))
353  {
354  SHIMENG_FAIL("Unable to get module handle for %wZ (%p)\n", &DllName, DllBase);
355  RtlFreeUnicodeString(&DllName);
356 
357  return NULL;
358  }
359  RtlFreeUnicodeString(&DllName);
360 
361  return SeiFindHookModuleInfo(NULL, DllHandle);
362 }
363 
365 {
366  TAGID tagEntry = SdbFindFirstTag(pdb, tag, type);
367  if (tagEntry == TAGID_NULL)
368  return NULL;
369 
370  return SdbGetStringTagPtr(pdb, tagEntry);
371 }
372 
374 {
375  TAGID tagEntry = SdbFindFirstTag(pdb, tag, type);
376  if (tagEntry == TAGID_NULL)
377  return 0;
378 
379  return SdbReadDWORDTag(pdb, tagEntry, 0);
380 }
381 
383 {
384  TAGID tagEntry = SdbFindFirstTag(pdb, tag, type);
385  if (tagEntry == TAGID_NULL)
386  return 0;
387 
388  return SdbReadQWORDTag(pdb, tagEntry, 0);
389 }
390 
391 static VOID SeiAddShim(TAGREF trShimRef, PARRAY pShimRef)
392 {
393  TAGREF* Data;
394 
395  Data = ARRAY_Append(pShimRef, TAGREF);
396  if (!Data)
397  return;
398 
399  *Data = trShimRef;
400 }
401 
402 static VOID SeiAddFlag(PDB pdb, TAGID tiFlagRef, PFLAGINFO pFlagInfo)
403 {
405 
406  /* Resolve the FLAG_REF to the real FLAG node */
407  TAGID FlagTag = SeiGetDWORD(pdb, tiFlagRef, TAG_FLAG_TAGID);
408 
409  if (FlagTag == TAGID_NULL)
410  return;
411 
414  Flag.QuadPart = SeiGetQWORD(pdb, FlagTag, TAG_FLAG_PROCESSPARAM);
415  pFlagInfo->ProcessParameters_Flags |= Flag.LowPart;
416 }
417 
418 /* Propagate layers to child processes */
420 {
422  UNICODE_STRING VarName = RTL_CONSTANT_STRING(L"__COMPAT_LAYER");
424 
426 
428  if (NT_SUCCESS(Status))
429  SHIMENG_INFO("Set env var %wZ=%wZ\n", &VarName, &Value);
430  else
431  SHIMENG_FAIL("Failed to set %wZ: 0x%x\n", &VarName, Status);
432 }
433 
434 #define MAX_LAYER_LENGTH 256
435 
436 /* Translate all Exe and Layer entries to Shims, and propagate all layers */
437 static VOID SeiBuildShimRefArray(HSDB hsdb, SDBQUERYRESULT* pQuery, PARRAY pShimRef, PFLAGINFO pFlagInfo)
438 {
439  WCHAR wszLayerEnvVar[MAX_LAYER_LENGTH] = { 0 };
440  DWORD n;
441 
442  for (n = 0; n < pQuery->dwExeCount; ++n)
443  {
444  PDB pdb;
445  TAGID tag;
446  if (SdbTagRefToTagID(hsdb, pQuery->atrExes[n], &pdb, &tag))
447  {
448  LPCWSTR ExeName = SeiGetStringPtr(pdb, tag, TAG_NAME);
451 
452  if (ExeName)
453  SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Exe(%S))\n", ExeName);
454 
455  while (ShimRef != TAGID_NULL)
456  {
457  TAGREF trShimRef;
458  if (SdbTagIDToTagRef(hsdb, pdb, ShimRef, &trShimRef))
459  SeiAddShim(trShimRef, pShimRef);
460 
462  }
463 
464  while (FlagRef != TAGID_NULL)
465  {
466  SeiAddFlag(pdb, FlagRef, pFlagInfo);
467 
469  }
470  }
471  }
472 
473 
474  for (n = 0; n < pQuery->dwLayerCount; ++n)
475  {
476  PDB pdb;
477  TAGID tag;
478  if (SdbTagRefToTagID(hsdb, pQuery->atrLayers[n], &pdb, &tag))
479  {
480  LPCWSTR LayerName = SeiGetStringPtr(pdb, tag, TAG_NAME);
483 
484  if (LayerName)
485  {
486  HRESULT hr;
487  SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Layer(%S))\n", LayerName);
488  if (wszLayerEnvVar[0])
489  StringCchCatW(wszLayerEnvVar, ARRAYSIZE(wszLayerEnvVar), L" ");
490  hr = StringCchCatW(wszLayerEnvVar, ARRAYSIZE(wszLayerEnvVar), LayerName);
491  if (!SUCCEEDED(hr))
492  {
493  SHIMENG_FAIL("Unable to append %S\n", LayerName);
494  }
495  }
496 
497  while (ShimRef != TAGID_NULL)
498  {
499  TAGREF trShimRef;
500  if (SdbTagIDToTagRef(hsdb, pdb, ShimRef, &trShimRef))
501  SeiAddShim(trShimRef, pShimRef);
502 
504  }
505 
506  while (FlagRef != TAGID_NULL)
507  {
508  SeiAddFlag(pdb, FlagRef, pFlagInfo);
509 
511  }
512  }
513  }
514  if (wszLayerEnvVar[0])
515  SeiSetLayerEnvVar(wszLayerEnvVar);
516 }
517 
518 /* Given the hooks from one shim, find the relevant modules and store the combination of module + hook */
519 VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO pShim)
520 {
521  DWORD n, j;
522  UNICODE_STRING UnicodeModName;
523  WCHAR Buf[512];
524 
525  RtlInitEmptyUnicodeString(&UnicodeModName, Buf, sizeof(Buf));
526 
527  for (n = 0; n < dwHookCount; ++n)
528  {
530  PVOID DllHandle;
531  PHOOKAPIEX hook = hooks + n;
532  PHOOKAPIEX* pHookApi;
533  PHOOKMODULEINFO HookModuleInfo;
534 
535  RtlInitAnsiString(&AnsiString, hook->LibraryName);
536  if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeModName, &AnsiString, FALSE)))
537  {
538  SHIMENG_FAIL("Unable to convert %s to Unicode\n", hook->LibraryName);
539  continue;
540  }
541 
542  RtlInitAnsiString(&AnsiString, hook->FunctionName);
543  if (NT_SUCCESS(LdrGetDllHandle(NULL, 0, &UnicodeModName, &DllHandle)))
544  {
545  PVOID ProcAddress;
546 
547 
548  if (!NT_SUCCESS(LdrGetProcedureAddress(DllHandle, &AnsiString, 0, &ProcAddress)))
549  {
550  SHIMENG_FAIL("Unable to retrieve %s!%s\n", hook->LibraryName, hook->FunctionName);
551  continue;
552  }
553 
554  HookModuleInfo = SeiFindHookModuleInfo(NULL, DllHandle);
555  hook->OriginalFunction = ProcAddress;
556  }
557  else
558  {
559  HookModuleInfo = SeiFindHookModuleInfo(&UnicodeModName, NULL);
560  DllHandle = NULL;
561  }
562 
563  if (!HookModuleInfo)
564  {
565  HookModuleInfo = ARRAY_Append(&g_pHookArray, HOOKMODULEINFO);
566  if (!HookModuleInfo)
567  continue;
568 
569  HookModuleInfo->BaseAddress = DllHandle;
570  ARRAY_Init(&HookModuleInfo->HookApis, PHOOKAPIEX);
571  RtlCreateUnicodeString(&HookModuleInfo->Name, UnicodeModName.Buffer);
572  }
573 
574  hook->pShimInfo = pShim;
575 
576  for (j = 0; j < ARRAY_Size(&HookModuleInfo->HookApis); ++j)
577  {
578  PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, j);
579  int CmpResult = strcmp(hook->FunctionName, HookApi->FunctionName);
580  if (CmpResult == 0)
581  {
582  /* Multiple hooks on one function? --> use ApiLink */
583  SHIMENG_FAIL("Multiple hooks on one API is not yet supported!\n");
584  ASSERT(0);
585  }
586  }
587  pHookApi = ARRAY_Append(&HookModuleInfo->HookApis, PHOOKAPIEX);
588  if (pHookApi)
589  *pHookApi = hook;
590  }
591 }
592 
594 
595 /* Check if we should fake the return from GetProcAddress (because we also redirected the iat for this module) */
597 {
598  char szOrdProcName[10] = "";
599  LPCSTR lpPrintName = lpProcName;
600  PVOID Addr = _ReturnAddress();
601  PHOOKMODULEINFO HookModuleInfo;
602  FARPROC proc = ((GETPROCADDRESSPROC)g_IntHookEx[0].OriginalFunction)(hModule, lpProcName);
603 
604  if ((DWORD_PTR)lpProcName <= MAXUSHORT)
605  {
606  sprintf(szOrdProcName, "#%Iu", (DWORD_PTR)lpProcName);
607  lpPrintName = szOrdProcName;
608  }
609 
610  Addr = SeiGetModuleFromAddress(Addr);
611  if (SE_IsShimDll(Addr))
612  {
613  SHIMENG_MSG("Not touching GetProcAddress for shim dll (%p!%s)", hModule, lpPrintName);
614  return proc;
615  }
616 
617  SHIMENG_INFO("(GetProcAddress(%p!%s) => %p\n", hModule, lpPrintName, proc);
618 
619  HookModuleInfo = SeiFindHookModuleInfo(NULL, hModule);
620 
621  /* FIXME: Ordinal not yet supported */
622  if (HookModuleInfo && HIWORD(lpProcName))
623  {
624  DWORD n;
625  for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n)
626  {
627  PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n);
628  int CmpResult = strcmp(lpProcName, HookApi->FunctionName);
629  if (CmpResult == 0)
630  {
631  SHIMENG_MSG("Redirecting %p to %p\n", proc, HookApi->ReplacementFunction);
632  proc = HookApi->ReplacementFunction;
633  break;
634  }
635  }
636  }
637 
638  return proc;
639 }
640 
641 /* Walk all shim modules / enabled shims, and add their hooks */
643 {
644  DWORD mod, n;
645 
646  /* Enumerate all Shim modules */
647  for (mod = 0; mod < ARRAY_Size(&g_pShimInfo); ++mod)
648  {
649  PSHIMMODULE pShimModule = *ARRAY_At(&g_pShimInfo, PSHIMMODULE, mod);
650  DWORD dwShimCount = ARRAY_Size(&pShimModule->EnabledShims);
651 
652  /* Enumerate all Shims */
653  for (n = 0; n < dwShimCount; ++n)
654  {
655  PSHIMINFO pShim = *ARRAY_At(&pShimModule->EnabledShims, PSHIMINFO, n);
656 
657  PHOOKAPIEX hooks = pShim->pHookApi;
658  DWORD dwHookCount = pShim->dwHookCount;
659 
660  SeiAddHooks(hooks, dwHookCount, pShim);
661  }
662  }
663 }
664 
665 /* If we hooked something, we should also redirect GetProcAddress */
667 {
668  if (dwNumHooks == 0)
669  {
671  return;
672  }
673 
676 }
677 
678 /* Patch one function in the iat */
680 {
681  ULONG OldProtection = 0;
682  PVOID Ptr;
683  SIZE_T Size;
685 
686  SHIMENG_INFO("Hooking API \"%s!%s\" for DLL \"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName, &LdrEntry->BaseDllName);
687 
688  Ptr = &FirstThunk->u1.Function;
689  Size = sizeof(FirstThunk->u1.Function);
691 
692  if (!NT_SUCCESS(Status))
693  {
694  SHIMENG_FAIL("Unable to unprotect 0x%p\n", &FirstThunk->u1.Function);
695  return;
696  }
697 
698  SHIMENG_INFO("changing 0x%p to 0x%p\n", FirstThunk->u1.Function, HookApi->ReplacementFunction);
699 #ifdef _WIN64
700  FirstThunk->u1.Function = (ULONGLONG)HookApi->ReplacementFunction;
701 #else
702  FirstThunk->u1.Function = (DWORD)HookApi->ReplacementFunction;
703 #endif
704 
705  Size = sizeof(FirstThunk->u1.Function);
706  Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size, OldProtection, &OldProtection);
707 
708  if (!NT_SUCCESS(Status))
709  {
710  SHIMENG_WARN("Unable to reprotect 0x%p\n", &FirstThunk->u1.Function);
711  }
712 }
713 
714 
716 {
717  DWORD n;
718 
719  for (n = 0; n < ARRAY_Size(InExclude); ++n)
720  {
722 
723  if (RtlEqualUnicodeString(&InEx->Module, DllName, TRUE))
724  return InEx;
725  }
726 
727  return NULL;
728 }
729 
731 {
732  PSHIMINFO pShimInfo = HookApi->pShimInfo;
734  BOOL IsExcluded = FALSE;
735 
736  if (!pShimInfo)
737  {
738  /* Internal hook, do not exclude it */
739  return FALSE;
740  }
741 
742  /* By default, everything from System32 or WinSxs is excluded */
745  IsExcluded = TRUE;
746 
747  InExclude = SeiFindInExclude(&pShimInfo->InExclude, &LdrEntry->BaseDllName);
748  if (InExclude)
749  {
750  /* If it is on the 'exclude' list, bail out */
751  if (!InExclude->Include)
752  {
753  SHIMENG_INFO("Module '%wZ' excluded for shim %S, API '%s!%s', because it on in the exclude list.\n",
754  &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName);
755 
756  return TRUE;
757  }
758  /* If it is on the 'include' list, override System32 / Winsxs check. */
759  if (IsExcluded)
760  {
761  SHIMENG_INFO("Module '%wZ' included for shim %S, API '%s!%s', because it is on the include list.\n",
762  &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName);
763 
764  }
765  IsExcluded = FALSE;
766  }
767 
768  if (IsExcluded)
769  {
770  SHIMENG_INFO("Module '%wZ' excluded for shim %S, API '%s!%s', because it is in System32/WinSXS.\n",
771  &LdrEntry->BaseDllName, pShimInfo->ShimName, HookApi->LibraryName, HookApi->FunctionName);
772  }
773 
774  return IsExcluded;
775 }
776 
778 {
780  UNICODE_STRING ModuleNameU;
781  RtlInitUnicodeString(&ModuleNameU, ModuleName);
782 
783  InExclude = SeiFindInExclude(dest, &ModuleNameU);
784  if (InExclude)
785  {
786  InExclude->Include = IsInclude;
787  return;
788  }
789 
791  if (InExclude)
792  {
793  PCWSTR ModuleNameCopy = SdbpStrDup(ModuleName);
794  RtlInitUnicodeString(&InExclude->Module, ModuleNameCopy);
795  InExclude->Include = IsInclude;
796  }
797 }
798 
799 /* Read the INEXCLUD tags from a given parent tag */
801 {
802  TAGID InExcludeTag;
803 
804  InExcludeTag = SdbFindFirstTag(pdb, parent, TAG_INEXCLUD);
805 
806  while (InExcludeTag != TAGID_NULL)
807  {
809  TAGID ModuleTag = SdbFindFirstTag(pdb, InExcludeTag, TAG_MODULE);
810  TAGID IncludeTag = SdbFindFirstTag(pdb, InExcludeTag, TAG_INCLUDE);
811 
812  ModuleName = SdbGetStringTagPtr(pdb, ModuleTag);
813  if (ModuleName)
814  {
815  SeiAppendInExclude(dest, ModuleName, IncludeTag != TAGID_NULL);
816  }
817  else
818  {
819  SHIMENG_WARN("INEXCLUDE without Module: 0x%x\n", InExcludeTag);
820  }
821 
822  InExcludeTag = SdbFindNextTag(pdb, parent, InExcludeTag);
823  }
824 }
825 
827 {
828  PDB pdb;
829  TAGREF tr = TAGREF_ROOT;
830  TAGID root, db, library;
831 
832  if (!SdbTagRefToTagID(hsdb, tr, &pdb, &root))
833  {
834  SHIMENG_WARN("Unable to resolve database root\n");
835  return;
836  }
838  if (db == TAGID_NULL)
839  {
840  SHIMENG_WARN("Unable to resolve database\n");
841  return;
842  }
844  if (library == TAGID_NULL)
845  {
846  SHIMENG_WARN("Unable to resolve library\n");
847  return;
848  }
849 
851 }
852 
854 {
855  DWORD n;
856 
857  /* First duplicate the global in/excludes */
858  for (n = 0; n < ARRAY_Size(&g_InExclude); ++n)
859  {
861  SeiAppendInExclude(&pShimInfo->InExclude, InEx->Module.Buffer, InEx->Include);
862  }
863 
864  /* Now read this shim's in/excludes (possibly overriding the global ones) */
865  SeiReadInExclude(pdb, ShimTag, &pShimInfo->InExclude);
866 }
867 
868 /* Given one loaded module, redirect (hook) all functions from the iat that are registered by shims */
870 {
871  ULONG Size;
872  PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
873  PBYTE DllBase = LdrEntry->DllBase;
874 
875  if (SE_IsShimDll(DllBase) || g_hInstance == LdrEntry->DllBase ||
877  {
878  SHIMENG_INFO("Skipping shim module 0x%p \"%wZ\"\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
879  return;
880  }
881 
882  if (LdrEntry->Flags & LDRP_COMPAT_DATABASE_PROCESSED)
883  {
884  SHIMENG_INFO("Skipping module 0x%p \"%wZ\" because it was already processed\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
885  return;
886  }
887 
888  ImportDescriptor = RtlImageDirectoryEntryToData(DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &Size);
889  if (!ImportDescriptor)
890  {
891  SHIMENG_INFO("Skipping module 0x%p \"%wZ\" due to no iat found\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
892  return;
893  }
894 
895  SHIMENG_INFO("Hooking module 0x%p \"%wZ\"\n", LdrEntry->DllBase, &LdrEntry->BaseDllName);
896 
897  for ( ;ImportDescriptor->Name && ImportDescriptor->OriginalFirstThunk; ImportDescriptor++)
898  {
899  PHOOKMODULEINFO HookModuleInfo;
900 
901  /* Do we have hooks for this module? */
902  HookModuleInfo = SeiFindHookModuleInfoForImportDescriptor(DllBase, ImportDescriptor);
903 
904  if (HookModuleInfo)
905  {
906  PIMAGE_THUNK_DATA OriginalThunk, FirstThunk;
907  DWORD n;
908 
909  for (n = 0; n < ARRAY_Size(&HookModuleInfo->HookApis); ++n)
910  {
911  DWORD dwFound = 0;
912  PHOOKAPIEX HookApi = *ARRAY_At(&HookModuleInfo->HookApis, PHOOKAPIEX, n);
913 
914  /* Check if this module should be excluded from being hooked (system32/winsxs, global or shim exclude) */
915  if (SeiIsExcluded(LdrEntry, HookApi))
916  {
917  continue;
918  }
919 
920  OriginalThunk = (PIMAGE_THUNK_DATA)(DllBase + ImportDescriptor->OriginalFirstThunk);
921  FirstThunk = (PIMAGE_THUNK_DATA)(DllBase + ImportDescriptor->FirstThunk);
922 
923  /* Walk all imports */
924  for (;OriginalThunk->u1.AddressOfData && FirstThunk->u1.Function; OriginalThunk++, FirstThunk++)
925  {
926  if (!IMAGE_SNAP_BY_ORDINAL32(OriginalThunk->u1.AddressOfData))
927  {
928  PIMAGE_IMPORT_BY_NAME ImportName;
929 
930  ImportName = (PIMAGE_IMPORT_BY_NAME)(DllBase + OriginalThunk->u1.AddressOfData);
931  if (!strcmp((PCSTR)ImportName->Name, HookApi->FunctionName))
932  {
933  SeiPatchNewImport(FirstThunk, HookApi, LdrEntry);
934 
935  /* Sadly, iat does not have to be sorted, and can even contain duplicate entries. */
936  dwFound++;
937  }
938  }
939  else
940  {
941  SHIMENG_FAIL("Ordinals not yet supported\n");
942  ASSERT(0);
943  }
944  }
945 
946  if (dwFound != 1)
947  {
948  /* One entry not found. */
949  if (!dwFound)
950  SHIMENG_INFO("Entry \"%s!%s\" not found for \"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName, &LdrEntry->BaseDllName);
951  else
952  SHIMENG_INFO("Entry \"%s!%s\" found %d times for \"%wZ\"\n", HookApi->LibraryName, HookApi->FunctionName, dwFound, &LdrEntry->BaseDllName);
953  }
954  }
955  }
956  }
957 
958  /* Mark this module as processed. */
960 }
961 
962 
964 {
965  PLIST_ENTRY ListHead, ListEntry;
966  PLDR_DATA_TABLE_ENTRY LdrEntry;
967 
968  ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
969  ListEntry = ListHead->Flink;
970 
971  while (ListHead != ListEntry)
972  {
973  LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
974  SeiHookImports(LdrEntry);
975 
976  ListEntry = ListEntry->Flink;
977  }
978 }
979 
980 
982 {
983 #define SYSTEM32 L"\\system32"
984 #define WINSXS L"\\winsxs"
985 
986  PWSTR WindowsDirectory = SdbpStrDup(SharedUserData->NtSystemRoot);
987  RtlInitUnicodeString(&g_WindowsDirectory, WindowsDirectory);
988 
993 
998 
999 #undef SYSTEM32
1000 #undef WINSXS
1001 }
1002 
1003 VOID SeiInit(PUNICODE_STRING ProcessImage, HSDB hsdb, SDBQUERYRESULT* pQuery)
1004 {
1005  DWORD n;
1006  ARRAY ShimRefArray;
1007  DWORD dwTotalHooks = 0;
1008  FLAGINFO ShimFlags;
1009 
1010  PPEB Peb = NtCurrentPeb();
1011 
1012  /* We should only be called once! */
1014 
1015  ARRAY_Init(&ShimRefArray, TAGREF);
1019  RtlZeroMemory(&ShimFlags, sizeof(ShimFlags));
1020 
1021  SeiInitPaths();
1022 
1024 
1025  /* TODO:
1026  if (pQuery->trApphelp)
1027  SeiDisplayAppHelp(?pQuery->trApphelp?);
1028  */
1029 
1030  SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(ExePath(%wZ))\n", ProcessImage);
1031  SeiBuildShimRefArray(hsdb, pQuery, &ShimRefArray, &ShimFlags);
1032  if (ShimFlags.AppCompatFlags.QuadPart)
1033  {
1034  SeiDbgPrint(SEI_MSG, NULL, "Using KERNEL apphack flags 0x%I64x\n", ShimFlags.AppCompatFlags.QuadPart);
1036  }
1037  if (ShimFlags.AppCompatFlagsUser.QuadPart)
1038  {
1039  SeiDbgPrint(SEI_MSG, NULL, "Using USER apphack flags 0x%I64x\n", ShimFlags.AppCompatFlagsUser.QuadPart);
1041  }
1042  if (ShimFlags.ProcessParameters_Flags)
1043  {
1044  SeiDbgPrint(SEI_MSG, NULL, "Using ProcessParameters flags 0x%x\n", ShimFlags.ProcessParameters_Flags);
1046  }
1047  SeiDbgPrint(SEI_MSG, NULL, "ShimInfo(Complete)\n");
1048 
1049  SHIMENG_INFO("Got %d shims\n", ARRAY_Size(&ShimRefArray));
1051 
1052  /* Walk all shims referenced (in layers + exes), and load their modules */
1053  for (n = 0; n < ARRAY_Size(&ShimRefArray); ++n)
1054  {
1055  PDB pdb;
1056  TAGID ShimRef;
1057 
1058  TAGREF tr = *ARRAY_At(&ShimRefArray, TAGREF, n);
1059 
1060  if (SdbTagRefToTagID(hsdb, tr, &pdb, &ShimRef))
1061  {
1062  LPCWSTR ShimName, DllName, CommandLine = NULL;
1063  TAGID ShimTag;
1064  WCHAR FullNameBuffer[MAX_PATH];
1065  UNICODE_STRING UnicodeDllName;
1067  PSHIMMODULE pShimModuleInfo = NULL;
1068  ANSI_STRING AnsiCommandLine = RTL_CONSTANT_STRING("");
1069  PSHIMINFO pShimInfo = NULL;
1070  PHOOKAPIEX pHookApi;
1071  DWORD dwHookCount;
1072 
1073  ShimName = SeiGetStringPtr(pdb, ShimRef, TAG_NAME);
1074  if (!ShimName)
1075  {
1076  SHIMENG_FAIL("Failed to retrieve the name for 0x%x\n", tr);
1077  continue;
1078  }
1079 
1080  CommandLine = SeiGetStringPtr(pdb, ShimRef, TAG_COMMAND_LINE);
1081  if (CommandLine && *CommandLine)
1082  {
1083  RtlInitUnicodeString(&UnicodeDllName, CommandLine);
1084  if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiCommandLine, &UnicodeDllName, TRUE)))
1085  {
1086  SHIMENG_INFO("COMMAND LINE %s for %S", AnsiCommandLine.Buffer, ShimName);
1087  }
1088  else
1089  {
1090  AnsiCommandLine.Buffer = "";
1091  CommandLine = NULL;
1092  }
1093  }
1094 
1095  ShimTag = SeiGetDWORD(pdb, ShimRef, TAG_SHIM_TAGID);
1096  if (!ShimTag)
1097  {
1098  SHIMENG_FAIL("Failed to resolve %S to a shim\n", ShimName);
1099  continue;
1100  }
1101 
1102  if (!SUCCEEDED(SdbGetAppPatchDir(NULL, FullNameBuffer, ARRAYSIZE(FullNameBuffer))))
1103  {
1104  SHIMENG_WARN("Failed to get the AppPatch dir\n");
1105  continue;
1106  }
1107 
1108  DllName = SeiGetStringPtr(pdb, ShimTag, TAG_DLLFILE);
1109  if (DllName == NULL ||
1110  !SUCCEEDED(StringCchCatW(FullNameBuffer, ARRAYSIZE(FullNameBuffer), L"\\")) ||
1111  !SUCCEEDED(StringCchCatW(FullNameBuffer, ARRAYSIZE(FullNameBuffer), DllName)))
1112  {
1113  SHIMENG_WARN("Failed to build a full path for %S\n", ShimName);
1114  continue;
1115  }
1116 
1118  RtlInitUnicodeString(&UnicodeDllName, FullNameBuffer);
1119  if (NT_SUCCESS(LdrGetDllHandle(NULL, NULL, &UnicodeDllName, &BaseAddress)))
1120  {
1121  /* This shim dll was already loaded, let's find it */
1122  pShimModuleInfo = SeiGetShimModuleInfo(BaseAddress);
1123  }
1124  else if (!NT_SUCCESS(LdrLoadDll(NULL, NULL, &UnicodeDllName, &BaseAddress)))
1125  {
1126  SHIMENG_WARN("Failed to load %wZ for %S\n", &UnicodeDllName, ShimName);
1127  continue;
1128  }
1130  /* No shim module found (or we just loaded it) */
1131  if (!pShimModuleInfo)
1132  {
1133  pShimModuleInfo = SeiCreateShimModuleInfo(DllName, BaseAddress);
1134  if (!pShimModuleInfo)
1135  {
1136  SHIMENG_FAIL("Failed to allocate ShimInfo for %S\n", DllName);
1137  continue;
1138  }
1139  }
1140 
1141  SHIMENG_INFO("Shim DLL 0x%p \"%wZ\" loaded\n", BaseAddress, &UnicodeDllName);
1142  SHIMENG_INFO("Using SHIM \"%S!%S\"\n", DllName, ShimName);
1143 
1144  /* Ask this shim what hooks it needs (and pass along the commandline) */
1145  pHookApi = pShimModuleInfo->pGetHookAPIs(AnsiCommandLine.Buffer, ShimName, &dwHookCount);
1146  SHIMENG_INFO("GetHookAPIs returns %d hooks for DLL \"%wZ\" SHIM \"%S\"\n", dwHookCount, &UnicodeDllName, ShimName);
1147  if (dwHookCount)
1148  pShimInfo = SeiAppendHookInfo(pShimModuleInfo, pHookApi, dwHookCount, ShimName);
1149 
1150  /* If this shim has hooks, create the include / exclude lists */
1151  if (pShimInfo)
1152  SeiBuildInclExclList(pdb, ShimTag, pShimInfo);
1153 
1154  if (CommandLine && *CommandLine)
1155  RtlFreeAnsiString(&AnsiCommandLine);
1156 
1157  dwTotalHooks += dwHookCount;
1158  }
1159  }
1160 
1161  SeiAddInternalHooks(dwTotalHooks);
1162  SeiResolveAPIs();
1164 }
1165 
1166 
1167 /* Load the database + unpack the shim data (if this process is allowed) */
1168 BOOL SeiGetShimData(PUNICODE_STRING ProcessImage, PVOID pShimData, HSDB* pHsdb, SDBQUERYRESULT* pQuery)
1169 {
1170  static const UNICODE_STRING ForbiddenShimmingApps[] = {
1171  RTL_CONSTANT_STRING(L"ntsd.exe"),
1172  RTL_CONSTANT_STRING(L"windbg.exe"),
1173 #if WINVER >= 0x600
1174  RTL_CONSTANT_STRING(L"slsvc.exe"),
1175 #endif
1176  };
1177  static const UNICODE_STRING BackSlash = RTL_CONSTANT_STRING(L"\\");
1178  static const UNICODE_STRING ForwdSlash = RTL_CONSTANT_STRING(L"/");
1179  UNICODE_STRING ProcessName;
1180  USHORT Back, Forward;
1181  HSDB hsdb;
1182  DWORD n;
1183 
1184  if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, ProcessImage, &BackSlash, &Back)))
1185  Back = 0;
1186 
1187  if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, ProcessImage, &ForwdSlash, &Forward)))
1188  Forward = 0;
1189 
1190  if (Back < Forward)
1191  Back = Forward;
1192 
1193  if (Back)
1194  Back += sizeof(WCHAR);
1195 
1196  ProcessName.Buffer = ProcessImage->Buffer + Back / sizeof(WCHAR);
1197  ProcessName.Length = ProcessImage->Length - Back;
1198  ProcessName.MaximumLength = ProcessImage->MaximumLength - Back;
1199 
1200  for (n = 0; n < ARRAYSIZE(ForbiddenShimmingApps); ++n)
1201  {
1202  if (RtlEqualUnicodeString(&ProcessName, ForbiddenShimmingApps + n, TRUE))
1203  {
1204  SHIMENG_MSG("Not shimming %wZ\n", ForbiddenShimmingApps + n);
1205  return FALSE;
1206  }
1207  }
1208 
1209  /* We should probably load all db's here, but since we do not support that yet... */
1211  if (hsdb)
1212  {
1213  if (SdbUnpackAppCompatData(hsdb, ProcessImage->Buffer, pShimData, pQuery))
1214  {
1215  *pHsdb = hsdb;
1216  return TRUE;
1217  }
1218  SdbReleaseDatabase(hsdb);
1219  }
1220  return FALSE;
1221 }
1222 
1223 
1224 
1226 {
1227  HSDB hsdb = NULL;
1228  SDBQUERYRESULT QueryResult = { { 0 } };
1229  SHIMENG_INFO("(%wZ, %p)\n", ProcessImage, pShimData);
1230 
1231  if (!SeiGetShimData(ProcessImage, pShimData, &hsdb, &QueryResult))
1232  {
1233  SHIMENG_FAIL("Failed to get shim data\n");
1234  return;
1235  }
1236 
1238  SeiInit(ProcessImage, hsdb, &QueryResult);
1240 
1241  SdbReleaseDatabase(hsdb);
1242 }
1243 
1245 {
1247 }
1248 
1250 {
1251  SHIMENG_MSG("()\n");
1253 }
1254 
1256 {
1257  SHIMENG_INFO("%sINIT. loading DLL \"%wZ\"\n", g_bShimDuringInit ? "" : "AFTER ", &LdrEntry->BaseDllName);
1258 
1259  SeiHookImports(LdrEntry);
1260 
1261  NotifyShims(SHIM_REASON_DLL_LOAD, LdrEntry);
1262 }
1263 
1265 {
1266  SHIMENG_INFO("(%p)\n", LdrEntry);
1267 
1268  /* Should we unhook here? */
1269 
1271 }
1272 
1274 {
1275  SHIMENG_INFO("(%p)\n", BaseAddress);
1276 
1278 }
1279 
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
PSHIMMODULE SeiGetShimModuleInfo(PVOID BaseAddress)
Definition: shimeng.c:243
CONST char * PCSZ
Definition: umtypes.h:125
DWORD TAGREF
#define WINSXS
const uint16_t * PCWSTR
Definition: typedefs.h:55
UNICODE_STRING Name
Definition: shimeng.h:68
VOID SeiInit(PUNICODE_STRING ProcessImage, HSDB hsdb, SDBQUERYRESULT *pQuery)
Definition: shimeng.c:1003
#define TRUE
Definition: types.h:120
static BOOL ARRAY_InitWorker(PARRAY Array, DWORD ItemSize)
Definition: shimeng.c:50
#define TAG_NAME
Definition: vfat.h:547
VOID SeiAppendInExclude(PARRAY dest, PCWSTR ModuleName, BOOL IsInclude)
Definition: shimeng.c:777
#define TAG_INCLUDE
Definition: db.cpp:54
NTSTATUS NTAPI LdrGetDllHandle(IN PWSTR DllPath OPTIONAL, IN PULONG DllCharacteristics OPTIONAL, IN PUNICODE_STRING DllName, OUT PVOID *DllHandle)
Definition: ldrapi.c:805
static ARRAY g_pShimInfo
Definition: shimeng.c:33
PPEB Peb
Definition: dllmain.c:27
static PDB pdb
Definition: db.cpp:160
static ARRAY g_InExclude
Definition: shimeng.c:35
ARRAY HookApis
Definition: shimeng.h:71
#define TAG_LIBRARY
Definition: sdbtagid.h:164
HRESULT hr
Definition: shlfolder.c:183
#define DbgPrint
Definition: loader.c:25
USHORT MaximumLength
Definition: env_spec_w32.h:370
STRSAFEAPI StringCchVPrintfExA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCSTR pszFormat, va_list argList)
Definition: strsafe.h:650
#define TAGREF_ROOT
Definition: sdbtypes.h:22
__wchar_t WCHAR
Definition: xmlstorage.h:180
uint16_t * PWSTR
Definition: typedefs.h:54
VOID PatchNewModules(PPEB Peb)
Definition: shimeng.c:963
PSHIMINFO SeiAppendHookInfo(PSHIMMODULE pShimModuleInfo, PHOOKAPIEX pHookApi, DWORD dwHookCount, PCWSTR ShimName)
Definition: shimeng.c:290
#define TAG_DATABASE
Definition: db.cpp:83
ULARGE_INTEGER AppCompatFlagsUser
Definition: winternl.h:350
BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR Function, PCSTR Format,...)
Definition: shimeng.c:155
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
Definition: ntimage.h:489
struct _root root
DWORD WINAPI SdbReadDWORDTag(PDB pdb, TAGID tagid, DWORD ret)
Definition: sdbread.c:305
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
DWORD Size__
Definition: shimeng.h:18
HSDB WINAPI SdbInitDatabase(DWORD, LPCWSTR)
Definition: hsdb.c:369
ULONG ProcessParameters_Flags
Definition: shimeng.h:79
TAGREF atrLayers[SDB_MAX_LAYERS]
Definition: apphelp.h:64
NTSTATUS NTAPI NtProtectVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UnsafeBaseAddress, IN OUT SIZE_T *UnsafeNumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG UnsafeOldAccessProtection)
Definition: virtual.c:2986
LONG NTSTATUS
Definition: precomp.h:26
bool Include
Definition: xml2sdb.h:38
VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: shimeng.c:1255
PHOOKMODULEINFO SeiFindHookModuleInfo(PUNICODE_STRING ModuleName, PVOID BaseAddress)
Definition: shimeng.c:315
HRESULT WINAPI SdbGetAppPatchDir(HSDB db, LPWSTR path, DWORD size)
Definition: hsdb.c:579
VOID NTAPI SE_InstallAfterInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
Definition: shimeng.c:1244
LPWSTR WINAPI SdbGetStringTagPtr(PDB pdb, TAGID tagid)
Definition: sdbread.c:375
GLdouble n
Definition: glext.h:7729
static VOID SeiBuildShimRefArray(HSDB hsdb, SDBQUERYRESULT *pQuery, PARRAY pShimRef, PFLAGINFO pFlagInfo)
Definition: shimeng.c:437
ULONG g_ShimEngDebugLevel
Definition: shimeng.c:29
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
ULARGE_INTEGER AppCompatFlags
Definition: shimeng.h:77
Definition: ecma_167.h:138
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define TAG_COMMAND_LINE
Definition: db.cpp:100
struct _IMAGE_IMPORT_BY_NAME * PIMAGE_IMPORT_BY_NAME
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
BOOL SeiIsExcluded(PLDR_DATA_TABLE_ENTRY LdrEntry, PHOOKAPIEX HookApi)
Definition: shimeng.c:730
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1252
static HANDLE proc()
Definition: pdb.c:32
#define TAG_FLAG_PROCESSPARAM
Definition: sdbtagid.h:124
#define ARRAY_Append(Array, TypeOfArray)
Definition: shimeng.c:118
#define SeiFree(mem)
Definition: shimeng.h:101
DWORD dwLayerCount
Definition: apphelp.h:68
PVOID NTAPI RtlPcToFileHeader(IN PVOID PcValue, PVOID *BaseOfImage)
Definition: libsupp.c:616
FT_Library library
Definition: cffdrivr.c:654
#define WCHAR
Definition: msvc.h:43
DWORD SdbpStrsize(PCWSTR string)
Definition: sdbapi.c:157
STRSAFEAPI StringCchPrintfExA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCSTR pszFormat,...)
Definition: strsafe.h:575
PVOID BaseAddress
Definition: shimeng.h:58
LPVOID SdbpAlloc(SIZE_T size)
Definition: sdbapi.c:55
DWORD dwHookCount
Definition: shimeng.h:50
struct TraceInfo Info
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
Definition: apphelp.h:27
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
PHOOKAPI WINAPI GetHookAPIs(IN LPCSTR szCommandLine, IN LPCWSTR wszShimName, OUT PDWORD pdwHookCount)
Definition: main.c:15
PVOID BaseAddress
Definition: shimeng.h:69
#define SDB_DATABASE_MAIN_SHIM
Definition: apphelp.h:24
PVOID DllBase
Definition: btrfs_drv.h:1805
PVOID ImageBaseAddress
Definition: ntddk_ex.h:249
#define sprintf(buf, format,...)
Definition: sprintf.c:55
DWORD dwReason
Definition: misc.cpp:154
#define TAG_INEXCLUD
Definition: db.cpp:84
VOID SeiHookImports(PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: shimeng.c:869
PHOOKAPIEX pHookApi
Definition: shimeng.h:49
#define TAG_DLLFILE
Definition: sdbtagid.h:137
VOID SeiInitPaths(VOID)
Definition: shimeng.c:981
static PCWSTR wszLayer
Definition: layerapi.c:35
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define TAG_MODULE
Definition: db.cpp:97
#define va_end(ap)
Definition: acmsvcex.h:90
VOID SeiBuildInclExclList(PDB pdb, TAGID ShimTag, PSHIMINFO pShimInfo)
Definition: shimeng.c:853
#define SYSTEM32
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
static LPOVERLAPPED_COMPLETION_ROUTINE Function
Definition: sync.c:684
static BOOL ARRAY_EnsureSize(PARRAY Array, DWORD ItemSize, DWORD GrowWith)
Definition: shimeng.c:59
#define IMAGE_SNAP_BY_ORDINAL32(Ordinal)
Definition: ntimage.h:524
#define LDRP_COMPAT_DATABASE_PROCESSED
Definition: ldrtypes.h:59
#define TAG_FLAG_MASK_KERNEL
Definition: sdbtagid.h:114
QWORD WINAPI SdbReadQWORDTag(PDB pdb, TAGID tagid, QWORD ret)
Definition: sdbread.c:321
VOID NTAPI SE_InstallBeforeInit(PUNICODE_STRING ProcessImage, PVOID pShimData)
Definition: shimeng.c:1225
NTSTATUS NTAPI LdrGetProcedureAddress(IN PVOID BaseAddress, IN PANSI_STRING Name, IN ULONG Ordinal, OUT PVOID *ProcedureAddress)
Definition: ldrapi.c:823
NTSYSAPI NTSTATUS NTAPI RtlQueryEnvironmentVariable_U(_In_opt_ PWSTR Environment, _In_ PCUNICODE_STRING Name, _Out_ PUNICODE_STRING Value)
smooth NULL
Definition: ftsmooth.c:416
union _IMAGE_THUNK_DATA32::@2044 u1
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
NTSYSAPI NTSTATUS NTAPI RtlSetEnvironmentVariable(_In_z_ PWSTR *Environment, _In_ PUNICODE_STRING Name, _In_ PUNICODE_STRING Value)
char * va_list
Definition: acmsvcex.h:78
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
Definition: bufpool.h:45
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
const char * LPCSTR
Definition: xmlstorage.h:183
std::string Module
Definition: xml2sdb.h:37
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define SHIM_NOTIFY_ATTACH
Definition: shimlib.h:50
static UNICODE_STRING g_SxsDirectory
Definition: shimeng.c:27
#define NtCurrentProcess()
Definition: nt_native.h:1657
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static UNICODE_STRING g_System32Directory
Definition: shimeng.c:26
TAGID WINAPI SdbFindNextTag(PDB pdb, TAGID parent, TAGID prev_child)
Definition: sdbread.c:231
VOID NTAPI SE_ProcessDying(VOID)
Definition: shimeng.c:1249
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
Definition: msg.h:42
VOID WINAPI SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: shimeng.c:1264
unsigned int BOOL
Definition: ntddk_ex.h:94
#define TAG_SHIM_TAGID
Definition: sdbtagid.h:67
VOID SeiBuildGlobalInclExclList(HSDB hsdb)
Definition: shimeng.c:826
r parent
Definition: btrfs.c:2659
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
LONG HRESULT
Definition: typedefs.h:77
uint64_t ULONGLONG
Definition: typedefs.h:65
UNICODE_STRING Module
Definition: shimeng.h:42
UINT64 QWORD
Definition: shimdbg.c:104
#define MAX_PATH
Definition: compat.h:26
Definition: xml2sdb.h:79
BOOL SeiGetShimData(PUNICODE_STRING ProcessImage, PVOID pShimData, HSDB *pHsdb, SDBQUERYRESULT *pQuery)
Definition: shimeng.c:1168
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
unsigned long DWORD
Definition: ntddk_ex.h:95
PCWSTR ShimName
Definition: shimeng.h:48
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
static tGETHOOKAPIS pGetHookAPIs
Definition: dispmode.c:26
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
BOOL Include
Definition: shimeng.h:43
#define TAG_FLAG_TAGID
Definition: sdbtagid.h:94
#define HID_DOS_PATHS
Definition: apphelp.h:19
TAGID WINAPI SdbFindFirstTag(PDB pdb, TAGID parent, TAG tag)
Definition: sdbread.c:208
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
HANDLE HINSTANCE
Definition: typedefs.h:75
static UNICODE_STRING g_WindowsDirectory
Definition: shimeng.c:25
#define SharedUserData
#define ARRAY_Size(Array)
Definition: shimeng.c:120
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
VOID SeiAddInternalHooks(DWORD dwNumHooks)
Definition: shimeng.c:666
GLenum const GLvoid * addr
Definition: glext.h:9621
static const WCHAR L[]
Definition: oid.c:1250
ULARGE_INTEGER AppCompatFlagsUser
Definition: shimeng.h:78
PCSTR LibraryName
Definition: shimeng.h:29
#define RtlImageDirectoryEntryToData
Definition: compat.h:460
PRTL_USER_PROCESS_PARAMETERS ProcessParameters
Definition: btrfs_drv.h:1838
#define TAG_SHIM_REF
Definition: db.cpp:87
void WINAPI SdbReleaseDatabase(HSDB)
Definition: hsdb.c:417
Definition: btrfs_drv.h:1801
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
NTSTATUS NTAPI DECLSPEC_HOTPATCH LdrLoadDll(IN PWSTR SearchPath OPTIONAL, IN PULONG DllCharacteristics OPTIONAL, IN PUNICODE_STRING DllName, OUT PVOID *BaseAddress)
Definition: ldrapi.c:310
DWORD dwExeCount
Definition: apphelp.h:67
PVOID Data__
Definition: shimeng.h:17
BOOL g_bComPlusImage
Definition: shimeng.c:30
Definition: typedefs.h:117
BOOL WINAPI SdbTagIDToTagRef(HSDB hsdb, PDB pdb, TAGID tiWhich, TAGREF *ptrWhich)
Definition: hsdb.c:669
#define SHIM_NOTIFY_DETACH
Definition: shimlib.h:51
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
static UCHAR ItemSize[4]
Definition: parser.c:16
PWSTR SdbpStrDup(LPCWSTR string)
Definition: sdbapi.c:162
uint32_t DWORD_PTR
Definition: typedefs.h:63
VOID SeiPatchNewImport(PIMAGE_THUNK_DATA FirstThunk, PHOOKAPIEX HookApi, PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: shimeng.c:679
static PVOID ARRAY_AtWorker(PARRAY Array, DWORD ItemSize, DWORD n)
Definition: shimeng.c:104
#define WINAPI
Definition: msvc.h:20
ARRAY EnabledShims
Definition: shimeng.h:63
static QWORD SeiGetQWORD(PDB pdb, TAGID tag, TAG type)
Definition: shimeng.c:382
std::string Name
Definition: xml2sdb.h:101
#define WINAPIV
Definition: sdbpapi.h:64
FARPROC WINAPI StubGetProcAddress(HINSTANCE hModule, LPCSTR lpProcName)
Definition: shimeng.c:596
Status
Definition: gdiplustypes.h:24
TAGREF atrExes[SDB_MAX_EXES]
Definition: apphelp.h:62
FARPROC(WINAPI * GETPROCADDRESSPROC)(HINSTANCE, LPCSTR)
Definition: shimeng.c:593
PCSTR FunctionName
Definition: shimeng.h:30
static ARRAY g_pHookArray
Definition: shimeng.c:34
#define TAGID_NULL
Definition: db.cpp:36
enum _SEI_LOG_LEVEL SEI_LOG_LEVEL
static UNICODE_STRING g_LoadingShimDll
Definition: shimeng.c:28
ULONG_PTR SIZE_T
Definition: typedefs.h:78
static LPCWSTR SeiGetStringPtr(PDB pdb, TAGID tag, TAG type)
Definition: shimeng.c:364
#define SHIM_REASON_DLL_UNLOAD
Definition: shimlib.h:48
PHOOKMODULEINFO SeiFindHookModuleInfoForImportDescriptor(PBYTE DllBase, PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor)
Definition: shimeng.c:338
#define NtCurrentPeb()
Definition: FLS.c:19
PSHIMINFO pShimInfo
Definition: shimeng.h:33
unsigned short USHORT
Definition: pedump.c:61
BOOL g_bShimDuringInit
Definition: shimeng.c:31
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define MAX_LAYER_LENGTH
Definition: shimeng.c:434
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1807
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:143
DWORD ItemSize__
Definition: shimeng.h:20
VOID SeiAddHooks(PHOOKAPIEX hooks, DWORD dwHookCount, PSHIMINFO pShim)
Definition: shimeng.c:519
#define va_start(ap, A)
Definition: acmsvcex.h:91
VOID NotifyShims(DWORD dwReason, PVOID Info)
Definition: shimeng.c:218
ARRAY InExclude
Definition: shimeng.h:52
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
Definition: fs_rec.h:142
PVOID ReplacementFunction
Definition: shimeng.h:31
#define MAXUSHORT
Definition: typedefs.h:81
ULARGE_INTEGER AppCompatFlags
Definition: winternl.h:349
#define TAG_FLAG_REF
Definition: sdbtagid.h:183
static PVOID ARRAY_AppendWorker(PARRAY Array, DWORD ItemSize, DWORD GrowWith)
Definition: shimeng.c:90
PINEXCLUDE SeiFindInExclude(PARRAY InExclude, PCUNICODE_STRING DllName)
Definition: shimeng.c:715
#define IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pedump.c:260
VOID SeiReadInExclude(PDB pdb, TAGID parent, PARRAY dest)
Definition: shimeng.c:800
VOID SeiResolveAPIs(VOID)
Definition: shimeng.c:642
void * _ReturnAddress(void)
Definition: shimeng.h:15
#define STRSAFE_NULL_ON_FAILURE
Definition: ntstrsafe.h:47
#define ARRAY_Init(Array, TypeOfArray)
Definition: shimeng.c:117
BOOL g_bInternalHooksUsed
Definition: shimeng.c:32
#define SHIM_REASON_DLL_LOAD
Definition: shimlib.h:47
ULONG Flags
Definition: ntddk_ex.h:211
NTSYSAPI NTSTATUS NTAPI RtlFindCharInUnicodeString(_In_ ULONG Flags, _In_ PCUNICODE_STRING SearchString, _In_ PCUNICODE_STRING MatchString, _Out_ PUSHORT Position)
HMODULE g_hInstance
Definition: MainWindow.cpp:18
HOOKAPIEX g_IntHookEx[]
Definition: shimeng.c:38
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
#define HIWORD(l)
Definition: typedefs.h:246
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
static VOID SeiAddFlag(PDB pdb, TAGID tiFlagRef, PFLAGINFO pFlagInfo)
Definition: shimeng.c:402
#define SeiAlloc(size)
Definition: shimeng.h:99
static char * dest
Definition: rtl.c:135
static VOID SeiAddShim(TAGREF trShimRef, PARRAY pShimRef)
Definition: shimeng.c:391
const char * PCSTR
Definition: typedefs.h:51
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1308
DWORD TAGID
#define TAG_FLAG_MASK_USER
Definition: sdbtagid.h:117
VOID SeiInitDebugSupport(VOID)
Definition: shimeng.c:123
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1827
BOOL WINAPI SdbUnpackAppCompatData(HSDB hsdb, LPCWSTR pszImageName, PVOID pData, PSDBQUERYRESULT pQueryResult)
Definition: hsdb.c:760
PVOID SeiGetModuleFromAddress(PVOID addr)
Definition: shimeng.c:208
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
static const WCHAR BackSlash[]
Definition: devclass.c:29
BOOL WINAPI SdbTagRefToTagID(HSDB hsdb, TAGREF trWhich, PDB *ppdb, TAGID *ptiWhich)
Definition: hsdb.c:638
BOOL WINAPI SE_IsShimDll(PVOID BaseAddress)
Definition: shimeng.c:1273
DWORD MaxSize__
Definition: shimeng.h:19
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
BYTE * PBYTE
Definition: pedump.c:66
static DWORD SeiGetDWORD(PDB pdb, TAGID tag, TAG type)
Definition: shimeng.c:373
#define ARRAY_At(Array, TypeOfArray, at)
Definition: shimeng.c:119
int(* FARPROC)()
Definition: compat.h:28
PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA
Definition: ntimage.h:566
static VOID SeiSetLayerEnvVar(LPCWSTR wszLayer)
Definition: shimeng.c:419
#define SUCCEEDED(hr)
Definition: intsafe.h:57
HMODULE hModule
Definition: animate.c:44
PSHIMMODULE SeiCreateShimModuleInfo(PCWSTR DllName, PVOID BaseAddress)
Definition: shimeng.c:257
static int mod
Definition: i386-dis.c:1273
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
VOID SeiCheckComPlusImage(PVOID BaseAddress)
Definition: shimeng.c:234
char * tag
Definition: main.c:59