2017-05-13 18:49:27 +00:00
/*
2017-09-08 20:19:51 +00:00
* PROJECT : ReactOS Application compatibility module
2019-01-03 21:17:01 +00:00
* LICENSE : GPL - 2.0 - or - later ( https : //spdx.org/licenses/GPL-2.0-or-later)
2017-09-08 20:19:51 +00:00
* PURPOSE : Shim engine core
2019-01-03 21:17:01 +00:00
* COPYRIGHT : Copyright 2015 - 2019 Mark Jansen ( mark . jansen @ reactos . org )
2017-05-13 18:49:27 +00:00
*/
# define WIN32_NO_STATUS
# include "ntndk.h"
2017-07-16 13:50:23 +00:00
# define IN_APPHELP
2017-05-13 18:49:27 +00:00
# include "shimlib.h"
# include <strsafe.h>
2017-07-01 20:06:30 +00:00
/* Make sure we don't include apphelp logging */
# define APPHELP_NOSDBPAPI
# include "apphelp.h"
# include "shimeng.h"
2017-05-13 18:49:27 +00:00
2017-07-01 20:06:30 +00:00
FARPROC WINAPI StubGetProcAddress ( HINSTANCE hModule , LPCSTR lpProcName ) ;
BOOL WINAPI SE_IsShimDll ( PVOID BaseAddress ) ;
2019-03-11 21:51:46 +00:00
static const UNICODE_STRING Ntdll = RTL_CONSTANT_STRING ( L " ntdll.dll " ) ;
static const UNICODE_STRING Kernel32 = RTL_CONSTANT_STRING ( L " kernel32.dll " ) ;
static const UNICODE_STRING Verifier = RTL_CONSTANT_STRING ( L " verifier.dll " ) ;
2017-07-01 20:06:30 +00:00
extern HMODULE g_hInstance ;
2017-08-14 16:34:56 +00:00
static UNICODE_STRING g_WindowsDirectory ;
static UNICODE_STRING g_System32Directory ;
static UNICODE_STRING g_SxsDirectory ;
2018-11-22 23:18:17 +00:00
static UNICODE_STRING g_LoadingShimDll ;
2017-05-13 18:49:27 +00:00
ULONG g_ShimEngDebugLevel = 0xffffffff ;
2017-07-01 20:06:30 +00:00
BOOL g_bComPlusImage = FALSE ;
BOOL g_bShimDuringInit = FALSE ;
2022-10-20 17:17:33 +00:00
BOOL g_bShimEngInitialized = FALSE ;
2017-07-01 20:06:30 +00:00
BOOL g_bInternalHooksUsed = FALSE ;
2017-08-14 16:34:56 +00:00
static ARRAY g_pShimInfo ; /* PSHIMMODULE */
static ARRAY g_pHookArray ; /* HOOKMODULEINFO */
static ARRAY g_InExclude ; /* INEXCLUDE */
2017-07-01 20:06:30 +00:00
2018-02-11 21:40:51 +00:00
typedef FARPROC ( WINAPI * GETPROCADDRESSPROC ) ( HINSTANCE , LPCSTR ) ;
2017-08-14 16:34:56 +00:00
/* If we have setup a hook for a function, we should also redirect GetProcAddress for this function */
2017-07-01 20:06:30 +00:00
HOOKAPIEX g_IntHookEx [ ] =
{
{
" kernel32.dll " , /* LibraryName */
" GetProcAddress " , /* FunctionName */
StubGetProcAddress , /* ReplacementFunction*/
NULL , /* OriginalFunction */
2017-07-30 12:47:57 +00:00
NULL , /* pShimInfo */
2019-03-13 19:15:18 +00:00
NULL /* ApiLink */
2017-07-01 20:06:30 +00:00
} ,
} ;
2017-07-30 12:47:57 +00:00
static inline BOOL ARRAY_InitWorker ( PARRAY Array , DWORD ItemSize )
{
Array - > Data__ = NULL ;
Array - > Size__ = Array - > MaxSize__ = 0 ;
Array - > ItemSize__ = ItemSize ;
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
return TRUE ;
}
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
static inline BOOL ARRAY_EnsureSize ( PARRAY Array , DWORD ItemSize , DWORD GrowWith )
2017-07-01 20:06:30 +00:00
{
PVOID pNewData ;
DWORD Count ;
2017-07-30 12:47:57 +00:00
ASSERT ( Array ) ;
ASSERT ( ItemSize = = Array - > ItemSize__ ) ;
if ( Array - > MaxSize__ > Array - > Size__ )
2017-07-01 20:06:30 +00:00
return TRUE ;
2017-07-30 12:47:57 +00:00
Count = Array - > Size__ + GrowWith ;
2017-07-01 20:06:30 +00:00
pNewData = SeiAlloc ( Count * ItemSize ) ;
if ( ! pNewData )
{
SHIMENG_FAIL ( " Failed to allocate %d bytes \n " , Count * ItemSize ) ;
return FALSE ;
}
2017-07-30 12:47:57 +00:00
Array - > MaxSize__ = Count ;
2017-05-13 18:49:27 +00:00
2017-07-30 12:47:57 +00:00
if ( Array - > Data__ )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
memcpy ( pNewData , Array - > Data__ , Array - > Size__ * ItemSize ) ;
SeiFree ( Array - > Data__ ) ;
2017-07-01 20:06:30 +00:00
}
2017-07-30 12:47:57 +00:00
Array - > Data__ = pNewData ;
2017-07-01 20:06:30 +00:00
return TRUE ;
}
2017-05-13 18:49:27 +00:00
2017-07-30 12:47:57 +00:00
static inline PVOID ARRAY_AppendWorker ( PARRAY Array , DWORD ItemSize , DWORD GrowWith )
{
PBYTE pData ;
if ( ! ARRAY_EnsureSize ( Array , ItemSize , GrowWith ) )
return NULL ;
pData = Array - > Data__ ;
pData + = ( Array - > Size__ * ItemSize ) ;
Array - > Size__ + + ;
return pData ;
}
static inline PVOID ARRAY_AtWorker ( PARRAY Array , DWORD ItemSize , DWORD n )
{
PBYTE pData ;
ASSERT ( Array ) ;
ASSERT ( ItemSize = = Array - > ItemSize__ ) ;
ASSERT ( n < Array - > Size__ ) ;
pData = Array - > Data__ ;
return pData + ( n * ItemSize ) ;
}
# define ARRAY_Init(Array, TypeOfArray) ARRAY_InitWorker((Array), sizeof(TypeOfArray))
# define ARRAY_Append(Array, TypeOfArray) (TypeOfArray*)ARRAY_AppendWorker((Array), sizeof(TypeOfArray), 5)
# define ARRAY_At(Array, TypeOfArray, at) (TypeOfArray*)ARRAY_AtWorker((Array), sizeof(TypeOfArray), at)
# define ARRAY_Size(Array) (Array)->Size__
2017-05-13 18:49:27 +00:00
VOID SeiInitDebugSupport ( VOID )
{
static const UNICODE_STRING DebugKey = RTL_CONSTANT_STRING ( L " SHIMENG_DEBUG_LEVEL " ) ;
UNICODE_STRING DebugValue ;
NTSTATUS Status ;
2017-08-14 16:34:56 +00:00
ULONG NewLevel = SEI_MSG ; /* Show some basic info in the logs, unless configured different */
2017-05-13 18:49:27 +00:00
WCHAR Buffer [ 40 ] ;
RtlInitEmptyUnicodeString ( & DebugValue , Buffer , sizeof ( Buffer ) ) ;
Status = RtlQueryEnvironmentVariable_U ( NULL , & DebugKey , & DebugValue ) ;
if ( NT_SUCCESS ( Status ) )
{
if ( ! NT_SUCCESS ( RtlUnicodeStringToInteger ( & DebugValue , 10 , & NewLevel ) ) )
NewLevel = 0 ;
}
g_ShimEngDebugLevel = NewLevel ;
}
/**
* Outputs diagnostic info .
*
* @ param [ in ] Level The level to log this message with , choose any of [ SHIM_ERR ,
* SHIM_WARN , SHIM_INFO ] .
* @ param [ in ] FunctionName The function this log should be attributed to .
* @ param [ in ] Format The format string .
* @ param . . . Variable arguments providing additional information .
*
* @ return Success : TRUE Failure : FALSE .
*/
BOOL WINAPIV SeiDbgPrint ( SEI_LOG_LEVEL Level , PCSTR Function , PCSTR Format , . . . )
{
char Buffer [ 512 ] ;
char * Current = Buffer ;
const char * LevelStr ;
size_t Length = sizeof ( Buffer ) ;
va_list ArgList ;
HRESULT hr ;
if ( g_ShimEngDebugLevel = = 0xffffffff )
SeiInitDebugSupport ( ) ;
if ( Level > g_ShimEngDebugLevel )
return FALSE ;
switch ( Level )
{
case SEI_MSG :
LevelStr = " MSG " ;
break ;
case SEI_FAIL :
LevelStr = " FAIL " ;
break ;
case SEI_WARN :
LevelStr = " WARN " ;
break ;
case SEI_INFO :
LevelStr = " INFO " ;
break ;
default :
LevelStr = " USER " ;
break ;
}
if ( Function )
hr = StringCchPrintfExA ( Current , Length , & Current , & Length , STRSAFE_NULL_ON_FAILURE , " [%s] [%s] " , LevelStr , Function ) ;
else
hr = StringCchPrintfExA ( Current , Length , & Current , & Length , STRSAFE_NULL_ON_FAILURE , " [%s] " , LevelStr ) ;
if ( ! SUCCEEDED ( hr ) )
return FALSE ;
va_start ( ArgList , Format ) ;
hr = StringCchVPrintfExA ( Current , Length , & Current , & Length , STRSAFE_NULL_ON_FAILURE , Format , ArgList ) ;
va_end ( ArgList ) ;
if ( ! SUCCEEDED ( hr ) )
return FALSE ;
DbgPrint ( " %s " , Buffer ) ;
return TRUE ;
}
2018-02-11 21:40:51 +00:00
static
BOOL SeiIsOrdinalName ( LPCSTR lpProcName )
{
return ( ULONG_PTR ) lpProcName < = MAXUSHORT ;
}
LPCSTR SeiPrintFunctionName ( LPCSTR lpProcName , char szOrdProcFmt [ 10 ] )
{
if ( SeiIsOrdinalName ( lpProcName ) )
{
StringCchPrintfA ( szOrdProcFmt , 10 , " #%Iu " , ( ULONG_PTR ) lpProcName ) ;
return szOrdProcFmt ;
}
return lpProcName ;
}
int SeiCompareFunctionName ( LPCSTR lpProcName1 , LPCSTR lpProcName2 )
{
BOOL Ord1 = SeiIsOrdinalName ( lpProcName1 ) ;
BOOL Ord2 = SeiIsOrdinalName ( lpProcName2 ) ;
/* One is an ordinal, the other not */
if ( Ord1 ! = Ord2 )
return 1 ;
/* Compare ordinals */
if ( Ord1 )
return ( ULONG_PTR ) lpProcName1 ! = ( ULONG_PTR ) lpProcName2 ;
/* Compare names */
return strcmp ( lpProcName1 , lpProcName2 ) ;
}
2017-05-13 18:49:27 +00:00
2017-07-01 20:06:30 +00:00
PVOID SeiGetModuleFromAddress ( PVOID addr )
{
PVOID hModule = NULL ;
RtlPcToFileHeader ( addr , & hModule ) ;
return hModule ;
}
2017-05-13 18:49:27 +00:00
2017-07-01 20:06:30 +00:00
/* TODO: Guard against recursive calling / calling init multiple times! */
2017-05-13 18:49:27 +00:00
VOID NotifyShims ( DWORD dwReason , PVOID Info )
{
2017-07-01 20:06:30 +00:00
DWORD n ;
2017-07-30 12:47:57 +00:00
for ( n = 0 ; n < ARRAY_Size ( & g_pShimInfo ) ; + + n )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
PSHIMMODULE pShimModule = * ARRAY_At ( & g_pShimInfo , PSHIMMODULE , n ) ;
if ( ! pShimModule - > pNotifyShims )
2017-07-01 20:06:30 +00:00
continue ;
2017-07-30 12:47:57 +00:00
pShimModule - > pNotifyShims ( dwReason , Info ) ;
2017-07-01 20:06:30 +00:00
}
}
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 " ) ;
}
2017-07-30 12:47:57 +00:00
PSHIMMODULE SeiGetShimModuleInfo ( PVOID BaseAddress )
2017-07-01 20:06:30 +00:00
{
DWORD n ;
2017-07-30 12:47:57 +00:00
for ( n = 0 ; n < ARRAY_Size ( & g_pShimInfo ) ; + + n )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
PSHIMMODULE pShimModule = * ARRAY_At ( & g_pShimInfo , PSHIMMODULE , n ) ;
if ( pShimModule - > BaseAddress = = BaseAddress )
return pShimModule ;
2017-07-01 20:06:30 +00:00
}
return NULL ;
}
2017-07-30 12:47:57 +00:00
PSHIMMODULE SeiCreateShimModuleInfo ( PCWSTR DllName , PVOID BaseAddress )
2017-07-01 20:06:30 +00:00
{
static const ANSI_STRING GetHookAPIs = RTL_CONSTANT_STRING ( " GetHookAPIs " ) ;
static const ANSI_STRING NotifyShims = RTL_CONSTANT_STRING ( " NotifyShims " ) ;
2017-07-30 12:47:57 +00:00
PSHIMMODULE * pData , Data ;
2017-07-01 20:06:30 +00:00
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 ;
}
2017-07-30 12:47:57 +00:00
pData = ARRAY_Append ( & g_pShimInfo , PSHIMMODULE ) ;
if ( ! pData )
2017-07-01 20:06:30 +00:00
return NULL ;
2017-07-30 12:47:57 +00:00
* pData = SeiAlloc ( sizeof ( SHIMMODULE ) ) ;
Data = * pData ;
2017-07-01 20:06:30 +00:00
RtlCreateUnicodeString ( & Data - > Name , DllName ) ;
Data - > BaseAddress = BaseAddress ;
Data - > pGetHookAPIs = pGetHookAPIs ;
Data - > pNotifyShims = pNotifyShims ;
2017-07-30 12:47:57 +00:00
ARRAY_Init ( & Data - > EnabledShims , PSHIMINFO ) ;
2017-07-01 20:06:30 +00:00
return Data ;
}
2017-08-14 16:34:56 +00:00
PSHIMINFO SeiAppendHookInfo ( PSHIMMODULE pShimModuleInfo , PHOOKAPIEX pHookApi , DWORD dwHookCount , PCWSTR ShimName )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
PSHIMINFO * pData , Data ;
pData = ARRAY_Append ( & pShimModuleInfo - > EnabledShims , PSHIMINFO ) ;
if ( ! pData )
2017-08-14 16:34:56 +00:00
return NULL ;
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
* pData = SeiAlloc ( sizeof ( SHIMINFO ) ) ;
Data = * pData ;
2017-07-01 20:06:30 +00:00
2017-08-14 16:34:56 +00:00
if ( ! Data )
return NULL ;
Data - > ShimName = SdbpStrDup ( ShimName ) ;
if ( ! Data - > ShimName )
return NULL ;
2017-07-01 20:06:30 +00:00
Data - > pHookApi = pHookApi ;
Data - > dwHookCount = dwHookCount ;
2017-07-30 12:47:57 +00:00
Data - > pShimModule = pShimModuleInfo ;
2017-08-14 16:34:56 +00:00
ARRAY_Init ( & Data - > InExclude , INEXCLUDE ) ;
return Data ;
2017-07-01 20:06:30 +00:00
}
PHOOKMODULEINFO SeiFindHookModuleInfo ( PUNICODE_STRING ModuleName , PVOID BaseAddress )
{
DWORD n ;
2018-02-22 22:25:34 +00:00
if ( ModuleName = = NULL & & BaseAddress = = NULL )
{
BaseAddress = NtCurrentPeb ( ) - > ImageBaseAddress ;
}
2017-07-30 12:47:57 +00:00
for ( n = 0 ; n < ARRAY_Size ( & g_pHookArray ) ; + + n )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
PHOOKMODULEINFO pModuleInfo = ARRAY_At ( & g_pHookArray , HOOKMODULEINFO , n ) ;
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
if ( BaseAddress & & BaseAddress = = pModuleInfo - > BaseAddress )
return pModuleInfo ;
if ( ! BaseAddress & & RtlEqualUnicodeString ( ModuleName , & pModuleInfo - > Name , TRUE ) )
return pModuleInfo ;
2017-07-01 20:06:30 +00:00
}
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 ) ;
if ( ! NT_SUCCESS ( Success ) )
{
2018-11-22 23:18:17 +00:00
SHIMENG_FAIL ( " Unable to get module handle for %wZ (%p) \n " , & DllName , DllBase ) ;
RtlFreeUnicodeString ( & DllName ) ;
2017-07-01 20:06:30 +00:00
return NULL ;
}
2018-11-22 23:18:17 +00:00
RtlFreeUnicodeString ( & DllName ) ;
2017-07-01 20:06:30 +00:00
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 ) ;
2017-05-13 18:49:27 +00:00
}
2017-07-01 20:06:30 +00:00
static DWORD SeiGetDWORD ( PDB pdb , TAGID tag , TAG type )
{
TAGID tagEntry = SdbFindFirstTag ( pdb , tag , type ) ;
if ( tagEntry = = TAGID_NULL )
return 0 ;
2018-01-24 21:41:56 +00:00
return SdbReadDWORDTag ( pdb , tagEntry , 0 ) ;
2017-07-01 20:06:30 +00:00
}
2018-01-24 21:41:56 +00:00
static QWORD SeiGetQWORD ( PDB pdb , TAGID tag , TAG type )
{
TAGID tagEntry = SdbFindFirstTag ( pdb , tag , type ) ;
if ( tagEntry = = TAGID_NULL )
return 0 ;
return SdbReadQWORDTag ( pdb , tagEntry , 0 ) ;
}
2017-07-01 20:06:30 +00:00
2017-07-02 11:43:54 +00:00
static VOID SeiAddShim ( TAGREF trShimRef , PARRAY pShimRef )
2017-07-01 20:06:30 +00:00
{
TAGREF * Data ;
2017-07-30 12:47:57 +00:00
Data = ARRAY_Append ( pShimRef , TAGREF ) ;
if ( ! Data )
2017-07-01 20:06:30 +00:00
return ;
2017-07-30 12:47:57 +00:00
* Data = trShimRef ;
2017-07-01 20:06:30 +00:00
}
2018-01-24 21:41:56 +00:00
static VOID SeiAddFlag ( PDB pdb , TAGID tiFlagRef , PFLAGINFO pFlagInfo )
{
ULARGE_INTEGER Flag ;
/* Resolve the FLAG_REF to the real FLAG node */
TAGID FlagTag = SeiGetDWORD ( pdb , tiFlagRef , TAG_FLAG_TAGID ) ;
if ( FlagTag = = TAGID_NULL )
return ;
pFlagInfo - > AppCompatFlags . QuadPart | = SeiGetQWORD ( pdb , FlagTag , TAG_FLAG_MASK_KERNEL ) ;
pFlagInfo - > AppCompatFlagsUser . QuadPart | = SeiGetQWORD ( pdb , FlagTag , TAG_FLAG_MASK_USER ) ;
Flag . QuadPart = SeiGetQWORD ( pdb , FlagTag , TAG_FLAG_PROCESSPARAM ) ;
pFlagInfo - > ProcessParameters_Flags | = Flag . LowPart ;
}
2017-08-14 16:34:56 +00:00
/* Propagate layers to child processes */
2017-07-02 11:43:54 +00:00
static VOID SeiSetLayerEnvVar ( LPCWSTR wszLayer )
{
NTSTATUS Status ;
UNICODE_STRING VarName = RTL_CONSTANT_STRING ( L " __COMPAT_LAYER " ) ;
UNICODE_STRING Value ;
RtlInitUnicodeString ( & Value , wszLayer ) ;
Status = RtlSetEnvironmentVariable ( NULL , & VarName , & Value ) ;
if ( NT_SUCCESS ( Status ) )
2018-02-11 21:40:51 +00:00
SHIMENG_INFO ( " %wZ=%wZ \n " , & VarName , & Value ) ;
2017-07-02 11:43:54 +00:00
else
SHIMENG_FAIL ( " Failed to set %wZ: 0x%x \n " , & VarName , Status ) ;
}
# define MAX_LAYER_LENGTH 256
2017-08-14 16:34:56 +00:00
/* Translate all Exe and Layer entries to Shims, and propagate all layers */
2018-01-24 21:41:56 +00:00
static VOID SeiBuildShimRefArray ( HSDB hsdb , SDBQUERYRESULT * pQuery , PARRAY pShimRef , PFLAGINFO pFlagInfo )
2017-07-01 20:06:30 +00:00
{
2017-07-02 11:43:54 +00:00
WCHAR wszLayerEnvVar [ MAX_LAYER_LENGTH ] = { 0 } ;
2017-07-01 20:06:30 +00:00
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 ) ;
2018-01-24 21:41:56 +00:00
TAGID FlagRef = SdbFindFirstTag ( pdb , tag , TAG_FLAG_REF ) ;
2017-07-01 20:06:30 +00:00
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 ) ;
}
2018-01-24 21:41:56 +00:00
while ( FlagRef ! = TAGID_NULL )
{
SeiAddFlag ( pdb , FlagRef , pFlagInfo ) ;
FlagRef = SdbFindNextTag ( pdb , tag , FlagRef ) ;
}
2017-07-01 20:06:30 +00:00
}
}
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 ) ;
2018-01-24 21:41:56 +00:00
TAGID FlagRef = SdbFindFirstTag ( pdb , tag , TAG_FLAG_REF ) ;
2017-07-01 20:06:30 +00:00
if ( LayerName )
2017-07-02 11:43:54 +00:00
{
HRESULT hr ;
2017-07-01 20:06:30 +00:00
SeiDbgPrint ( SEI_MSG , NULL , " ShimInfo(Layer(%S)) \n " , LayerName ) ;
2017-07-02 11:43:54 +00:00
if ( wszLayerEnvVar [ 0 ] )
2017-07-30 12:47:57 +00:00
StringCchCatW ( wszLayerEnvVar , ARRAYSIZE ( wszLayerEnvVar ) , L " " ) ;
hr = StringCchCatW ( wszLayerEnvVar , ARRAYSIZE ( wszLayerEnvVar ) , LayerName ) ;
2017-07-02 11:43:54 +00:00
if ( ! SUCCEEDED ( hr ) )
{
SHIMENG_FAIL ( " Unable to append %S \n " , LayerName ) ;
}
}
2017-07-01 20:06:30 +00:00
while ( ShimRef ! = TAGID_NULL )
{
TAGREF trShimRef ;
if ( SdbTagIDToTagRef ( hsdb , pdb , ShimRef , & trShimRef ) )
SeiAddShim ( trShimRef , pShimRef ) ;
ShimRef = SdbFindNextTag ( pdb , tag , ShimRef ) ;
}
2018-01-24 21:41:56 +00:00
while ( FlagRef ! = TAGID_NULL )
{
SeiAddFlag ( pdb , FlagRef , pFlagInfo ) ;
FlagRef = SdbFindNextTag ( pdb , tag , FlagRef ) ;
}
2017-07-01 20:06:30 +00:00
}
}
2017-07-02 11:43:54 +00:00
if ( wszLayerEnvVar [ 0 ] )
SeiSetLayerEnvVar ( wszLayerEnvVar ) ;
2017-07-01 20:06:30 +00:00
}
2017-08-14 16:34:56 +00:00
/* Given the hooks from one shim, find the relevant modules and store the combination of module + hook */
2017-07-30 12:47:57 +00:00
VOID SeiAddHooks ( PHOOKAPIEX hooks , DWORD dwHookCount , PSHIMINFO pShim )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
DWORD n , j ;
2017-07-01 20:06:30 +00:00
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 ;
2017-07-30 12:47:57 +00:00
PHOOKAPIEX * pHookApi ;
2017-07-01 20:06:30 +00:00
PHOOKMODULEINFO HookModuleInfo ;
RtlInitAnsiString ( & AnsiString , hook - > LibraryName ) ;
if ( ! NT_SUCCESS ( RtlAnsiStringToUnicodeString ( & UnicodeModName , & AnsiString , FALSE ) ) )
{
SHIMENG_FAIL ( " Unable to convert %s to Unicode \n " , hook - > LibraryName ) ;
continue ;
}
if ( NT_SUCCESS ( LdrGetDllHandle ( NULL , 0 , & UnicodeModName , & DllHandle ) ) )
{
HookModuleInfo = SeiFindHookModuleInfo ( NULL , DllHandle ) ;
}
else
{
HookModuleInfo = SeiFindHookModuleInfo ( & UnicodeModName , NULL ) ;
DllHandle = NULL ;
}
if ( ! HookModuleInfo )
{
2017-07-30 12:47:57 +00:00
HookModuleInfo = ARRAY_Append ( & g_pHookArray , HOOKMODULEINFO ) ;
if ( ! HookModuleInfo )
2017-07-01 20:06:30 +00:00
continue ;
HookModuleInfo - > BaseAddress = DllHandle ;
2017-07-30 12:47:57 +00:00
ARRAY_Init ( & HookModuleInfo - > HookApis , PHOOKAPIEX ) ;
2017-07-01 20:06:30 +00:00
RtlCreateUnicodeString ( & HookModuleInfo - > Name , UnicodeModName . Buffer ) ;
}
2017-07-30 12:47:57 +00:00
hook - > pShimInfo = pShim ;
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
for ( j = 0 ; j < ARRAY_Size ( & HookModuleInfo - > HookApis ) ; + + j )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
PHOOKAPIEX HookApi = * ARRAY_At ( & HookModuleInfo - > HookApis , PHOOKAPIEX , j ) ;
2018-02-11 21:40:51 +00:00
int CmpResult = SeiCompareFunctionName ( hook - > FunctionName , HookApi - > FunctionName ) ;
2017-07-01 20:06:30 +00:00
if ( CmpResult = = 0 )
{
2019-03-13 19:15:18 +00:00
while ( HookApi - > ApiLink )
{
HookApi = HookApi - > ApiLink ;
}
HookApi - > ApiLink = hook ;
hook = NULL ;
break ;
2017-07-01 20:06:30 +00:00
}
}
2019-03-13 19:15:18 +00:00
/* No place found yet, append it */
if ( hook )
{
pHookApi = ARRAY_Append ( & HookModuleInfo - > HookApis , PHOOKAPIEX ) ;
if ( pHookApi )
* pHookApi = hook ;
}
2017-07-01 20:06:30 +00:00
}
}
2017-08-14 16:34:56 +00:00
/* Check if we should fake the return from GetProcAddress (because we also redirected the iat for this module) */
2017-07-01 20:06:30 +00:00
FARPROC WINAPI StubGetProcAddress ( HINSTANCE hModule , LPCSTR lpProcName )
{
PVOID Addr = _ReturnAddress ( ) ;
PHOOKMODULEINFO HookModuleInfo ;
FARPROC proc = ( ( GETPROCADDRESSPROC ) g_IntHookEx [ 0 ] . OriginalFunction ) ( hModule , lpProcName ) ;
2018-02-11 21:40:51 +00:00
char szOrdProcFmt [ 10 ] ;
2017-07-01 20:06:30 +00:00
Addr = SeiGetModuleFromAddress ( Addr ) ;
if ( SE_IsShimDll ( Addr ) )
{
2018-02-11 21:40:51 +00:00
SHIMENG_MSG ( " Not touching GetProcAddress for shim dll (%p!%s) " , hModule , SeiPrintFunctionName ( lpProcName , szOrdProcFmt ) ) ;
2017-07-01 20:06:30 +00:00
return proc ;
}
2018-02-11 21:40:51 +00:00
SHIMENG_INFO ( " (GetProcAddress(%p!%s) => %p \n " , hModule , SeiPrintFunctionName ( lpProcName , szOrdProcFmt ) , proc ) ;
2017-07-01 20:06:30 +00:00
HookModuleInfo = SeiFindHookModuleInfo ( NULL , hModule ) ;
2018-02-11 21:40:51 +00:00
if ( HookModuleInfo )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
DWORD n ;
for ( n = 0 ; n < ARRAY_Size ( & HookModuleInfo - > HookApis ) ; + + n )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
PHOOKAPIEX HookApi = * ARRAY_At ( & HookModuleInfo - > HookApis , PHOOKAPIEX , n ) ;
2018-02-11 21:40:51 +00:00
int CmpResult = SeiCompareFunctionName ( lpProcName , HookApi - > FunctionName ) ;
2017-07-01 20:06:30 +00:00
if ( CmpResult = = 0 )
{
SHIMENG_MSG ( " Redirecting %p to %p \n " , proc , HookApi - > ReplacementFunction ) ;
proc = HookApi - > ReplacementFunction ;
break ;
}
}
}
return proc ;
}
2019-03-13 19:15:18 +00:00
VOID SeiResolveAPI ( PHOOKMODULEINFO HookModuleInfo )
{
DWORD n ;
ANSI_STRING AnsiString ;
ASSERT ( HookModuleInfo - > BaseAddress ! = NULL ) ;
for ( n = 0 ; n < ARRAY_Size ( & HookModuleInfo - > HookApis ) ; + + n )
{
2018-02-11 21:40:51 +00:00
NTSTATUS Status ;
2019-03-13 19:15:18 +00:00
PVOID ProcAddress ;
PHOOKAPIEX HookApi = * ARRAY_At ( & HookModuleInfo - > HookApis , PHOOKAPIEX , n ) ;
2018-02-11 21:40:51 +00:00
if ( ! SeiIsOrdinalName ( HookApi - > FunctionName ) )
{
RtlInitAnsiString ( & AnsiString , HookApi - > FunctionName ) ;
Status = LdrGetProcedureAddress ( HookModuleInfo - > BaseAddress , & AnsiString , 0 , & ProcAddress ) ;
}
else
{
Status = LdrGetProcedureAddress ( HookModuleInfo - > BaseAddress , NULL , ( ULONG_PTR ) HookApi - > FunctionName , & ProcAddress ) ;
}
if ( ! NT_SUCCESS ( Status ) )
2019-03-13 19:15:18 +00:00
{
2018-02-11 21:40:51 +00:00
char szOrdProcFmt [ 10 ] ;
LPCSTR lpFunctionName = SeiPrintFunctionName ( HookApi - > FunctionName , szOrdProcFmt ) ;
SHIMENG_FAIL ( " Unable to retrieve %s!%s \n " , HookApi - > LibraryName , lpFunctionName ) ;
2019-03-13 19:15:18 +00:00
continue ;
}
HookApi - > OriginalFunction = ProcAddress ;
if ( HookApi - > ApiLink )
{
SHIMENG_MSG ( " TODO: Figure out how to handle conflicting In/Exports with ApiLink! \n " ) ;
}
while ( HookApi - > ApiLink )
{
HookApi - > ApiLink - > OriginalFunction = HookApi - > OriginalFunction ;
HookApi - > OriginalFunction = HookApi - > ApiLink - > ReplacementFunction ;
HookApi = HookApi - > ApiLink ;
}
}
}
2017-08-14 16:34:56 +00:00
/* Walk all shim modules / enabled shims, and add their hooks */
2017-07-01 20:06:30 +00:00
VOID SeiResolveAPIs ( VOID )
2019-03-13 19:15:18 +00:00
{
DWORD n ;
for ( n = 0 ; n < ARRAY_Size ( & g_pHookArray ) ; + + n )
{
PHOOKMODULEINFO pModuleInfo = ARRAY_At ( & g_pHookArray , HOOKMODULEINFO , n ) ;
/* Is this module loaded? */
if ( pModuleInfo - > BaseAddress )
{
SeiResolveAPI ( pModuleInfo ) ;
}
}
}
VOID SeiCombineHookInfo ( VOID )
2017-07-01 20:06:30 +00:00
{
DWORD mod , n ;
/* Enumerate all Shim modules */
2017-07-30 12:47:57 +00:00
for ( mod = 0 ; mod < ARRAY_Size ( & g_pShimInfo ) ; + + mod )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
PSHIMMODULE pShimModule = * ARRAY_At ( & g_pShimInfo , PSHIMMODULE , mod ) ;
DWORD dwShimCount = ARRAY_Size ( & pShimModule - > EnabledShims ) ;
2017-07-01 20:06:30 +00:00
/* Enumerate all Shims */
for ( n = 0 ; n < dwShimCount ; + + n )
{
2017-07-30 12:47:57 +00:00
PSHIMINFO pShim = * ARRAY_At ( & pShimModule - > EnabledShims , PSHIMINFO , n ) ;
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
PHOOKAPIEX hooks = pShim - > pHookApi ;
DWORD dwHookCount = pShim - > dwHookCount ;
SeiAddHooks ( hooks , dwHookCount , pShim ) ;
2017-07-01 20:06:30 +00:00
}
}
}
2017-08-14 16:34:56 +00:00
/* If we hooked something, we should also redirect GetProcAddress */
2017-07-01 20:06:30 +00:00
VOID SeiAddInternalHooks ( DWORD dwNumHooks )
{
if ( dwNumHooks = = 0 )
{
g_bInternalHooksUsed = FALSE ;
return ;
}
2017-07-30 12:47:57 +00:00
SeiAddHooks ( g_IntHookEx , ARRAYSIZE ( g_IntHookEx ) , NULL ) ;
2017-07-01 20:06:30 +00:00
g_bInternalHooksUsed = TRUE ;
}
2017-08-14 16:34:56 +00:00
/* Patch one function in the iat */
2017-07-01 20:06:30 +00:00
VOID SeiPatchNewImport ( PIMAGE_THUNK_DATA FirstThunk , PHOOKAPIEX HookApi , PLDR_DATA_TABLE_ENTRY LdrEntry )
{
ULONG OldProtection = 0 ;
PVOID Ptr ;
2018-03-04 15:04:17 +00:00
SIZE_T Size ;
2017-07-01 20:06:30 +00:00
NTSTATUS Status ;
2018-02-11 21:40:51 +00:00
char szOrdProcFmt [ 10 ] ;
2017-07-01 20:06:30 +00:00
2018-02-11 21:40:51 +00:00
SHIMENG_INFO ( " Hooking API \" %s!%s \" for DLL \" %wZ \" \n " , HookApi - > LibraryName , SeiPrintFunctionName ( HookApi - > FunctionName , szOrdProcFmt ) , & LdrEntry - > BaseDllName ) ;
2017-07-01 20:06:30 +00:00
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 ) ;
2018-02-11 21:40:51 +00:00
FirstThunk - > u1 . Function = ( ULONG_PTR ) HookApi - > ReplacementFunction ;
2017-07-01 20:06:30 +00:00
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 ) ;
}
}
2017-08-14 16:34:56 +00:00
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 ;
2018-02-11 21:40:51 +00:00
char szOrdProcFmt [ 10 ] ;
2017-08-14 16:34:56 +00:00
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 " ,
2018-02-11 21:40:51 +00:00
& LdrEntry - > BaseDllName , pShimInfo - > ShimName , HookApi - > LibraryName , SeiPrintFunctionName ( HookApi - > FunctionName , szOrdProcFmt ) ) ;
2017-08-14 16:34:56 +00:00
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 " ,
2018-02-11 21:40:51 +00:00
& LdrEntry - > BaseDllName , pShimInfo - > ShimName , HookApi - > LibraryName , SeiPrintFunctionName ( HookApi - > FunctionName , szOrdProcFmt ) ) ;
2017-08-14 16:34:56 +00:00
}
IsExcluded = FALSE ;
}
if ( IsExcluded )
{
SHIMENG_INFO ( " Module '%wZ' excluded for shim %S, API '%s!%s', because it is in System32/WinSXS. \n " ,
2018-02-11 21:40:51 +00:00
& LdrEntry - > BaseDllName , pShimInfo - > ShimName , HookApi - > LibraryName , SeiPrintFunctionName ( HookApi - > FunctionName , szOrdProcFmt ) ) ;
2017-08-14 16:34:56 +00:00
}
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 ;
}
}
2018-11-18 22:18:13 +00:00
/* Read the INEXCLUD tags from a given parent tag
FIXME :
Some observed tags :
' * ' with include
' $ ' with include , followed by ' * ' without include
Include list logging , referring to : ( MODE : EA )
*/
2017-08-14 16:34:56 +00:00
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 */
2017-07-01 20:06:30 +00:00
VOID SeiHookImports ( PLDR_DATA_TABLE_ENTRY LdrEntry )
{
ULONG Size ;
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor ;
PBYTE DllBase = LdrEntry - > DllBase ;
2019-03-11 21:51:46 +00:00
if ( SE_IsShimDll ( DllBase ) | |
g_hInstance = = LdrEntry - > DllBase | |
RtlEqualUnicodeString ( & g_LoadingShimDll , & LdrEntry - > BaseDllName , TRUE ) )
2017-07-01 20:06:30 +00:00
{
SHIMENG_INFO ( " Skipping shim module 0x%p \" %wZ \" \n " , LdrEntry - > DllBase , & LdrEntry - > BaseDllName ) ;
return ;
}
2017-08-29 20:21:58 +00:00
if ( LdrEntry - > Flags & LDRP_COMPAT_DATABASE_PROCESSED )
{
SHIMENG_INFO ( " Skipping module 0x%p \" %wZ \" because it was already processed \n " , LdrEntry - > DllBase , & LdrEntry - > BaseDllName ) ;
return ;
}
2017-07-01 20:06:30 +00:00
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 ;
2017-07-30 12:47:57 +00:00
DWORD n ;
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
for ( n = 0 ; n < ARRAY_Size ( & HookModuleInfo - > HookApis ) ; + + n )
2017-07-01 20:06:30 +00:00
{
DWORD dwFound = 0 ;
2017-07-30 12:47:57 +00:00
PHOOKAPIEX HookApi = * ARRAY_At ( & HookModuleInfo - > HookApis , PHOOKAPIEX , n ) ;
2017-08-14 16:34:56 +00:00
/* Check if this module should be excluded from being hooked (system32/winsxs, global or shim exclude) */
if ( SeiIsExcluded ( LdrEntry , HookApi ) )
{
continue ;
}
2017-07-01 20:06:30 +00:00
OriginalThunk = ( PIMAGE_THUNK_DATA ) ( DllBase + ImportDescriptor - > OriginalFirstThunk ) ;
FirstThunk = ( PIMAGE_THUNK_DATA ) ( DllBase + ImportDescriptor - > FirstThunk ) ;
2017-08-14 16:34:56 +00:00
/* Walk all imports */
2017-07-30 12:47:57 +00:00
for ( ; OriginalThunk - > u1 . AddressOfData & & FirstThunk - > u1 . Function ; OriginalThunk + + , FirstThunk + + )
2017-07-01 20:06:30 +00:00
{
2018-02-11 21:40:51 +00:00
if ( ! IMAGE_SNAP_BY_ORDINAL ( OriginalThunk - > u1 . Function ) )
2017-07-01 20:06:30 +00:00
{
2018-02-11 21:40:51 +00:00
if ( ! SeiIsOrdinalName ( HookApi - > FunctionName ) )
2017-07-01 20:06:30 +00:00
{
2018-02-11 21:40:51 +00:00
PIMAGE_IMPORT_BY_NAME ImportName ;
2017-07-01 20:06:30 +00:00
2018-02-11 21:40:51 +00:00
ImportName = ( PIMAGE_IMPORT_BY_NAME ) ( DllBase + OriginalThunk - > u1 . Function ) ;
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 + + ;
}
2017-07-01 20:06:30 +00:00
}
}
else
{
2018-02-11 21:40:51 +00:00
if ( SeiIsOrdinalName ( HookApi - > FunctionName ) )
{
if ( ( PCSTR ) IMAGE_ORDINAL ( OriginalThunk - > u1 . Function ) = = HookApi - > FunctionName )
{
SeiPatchNewImport ( FirstThunk , HookApi , LdrEntry ) ;
dwFound + + ;
}
}
2017-07-01 20:06:30 +00:00
}
}
2017-07-30 12:47:57 +00:00
if ( dwFound ! = 1 )
2017-07-01 20:06:30 +00:00
{
2018-02-11 21:40:51 +00:00
char szOrdProcFmt [ 10 ] ;
LPCSTR FuncName = SeiPrintFunctionName ( HookApi - > FunctionName , szOrdProcFmt ) ;
2017-07-30 12:47:57 +00:00
/* One entry not found. */
if ( ! dwFound )
2018-02-11 21:40:51 +00:00
SHIMENG_INFO ( " Entry \" %s!%s \" not found for \" %wZ \" \n " , HookApi - > LibraryName , FuncName , & LdrEntry - > BaseDllName ) ;
2017-07-30 12:47:57 +00:00
else
2018-02-11 21:40:51 +00:00
SHIMENG_INFO ( " Entry \" %s!%s \" found %d times for \" %wZ \" \n " , HookApi - > LibraryName , FuncName , dwFound , & LdrEntry - > BaseDllName ) ;
2017-07-01 20:06:30 +00:00
}
}
}
}
2017-08-29 20:21:58 +00:00
/* Mark this module as processed. */
LdrEntry - > Flags | = LDRP_COMPAT_DATABASE_PROCESSED ;
2017-07-01 20:06:30 +00:00
}
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 ;
}
}
2017-08-14 16:34:56 +00:00
VOID SeiInitPaths ( VOID )
{
# define SYSTEM32 L"\\system32"
# define WINSXS L"\\winsxs"
PWSTR WindowsDirectory = SdbpStrDup ( SharedUserData - > NtSystemRoot ) ;
RtlInitUnicodeString ( & g_WindowsDirectory , WindowsDirectory ) ;
g_System32Directory . MaximumLength = g_WindowsDirectory . Length + SdbpStrsize ( SYSTEM32 ) ;
g_System32Directory . Buffer = SdbpAlloc ( g_System32Directory . MaximumLength ) ;
RtlCopyUnicodeString ( & g_System32Directory , & g_WindowsDirectory ) ;
RtlAppendUnicodeToString ( & g_System32Directory , SYSTEM32 ) ;
g_SxsDirectory . MaximumLength = g_WindowsDirectory . Length + SdbpStrsize ( WINSXS ) ;
g_SxsDirectory . Buffer = SdbpAlloc ( g_SxsDirectory . MaximumLength ) ;
RtlCopyUnicodeString ( & g_SxsDirectory , & g_WindowsDirectory ) ;
RtlAppendUnicodeToString ( & g_SxsDirectory , WINSXS ) ;
# undef SYSTEM32
# undef WINSXS
}
2019-03-11 21:51:46 +00:00
VOID SeiSetEntryProcessed ( PPEB Peb )
{
PLIST_ENTRY ListHead , Entry ;
PLDR_DATA_TABLE_ENTRY LdrEntry ;
ListHead = & NtCurrentPeb ( ) - > Ldr - > InInitializationOrderModuleList ;
Entry = ListHead - > Flink ;
while ( Entry ! = ListHead )
{
LdrEntry = CONTAINING_RECORD ( Entry , LDR_DATA_TABLE_ENTRY , InInitializationOrderLinks ) ;
Entry = Entry - > Flink ;
if ( RtlEqualUnicodeString ( & LdrEntry - > BaseDllName , & Ntdll , TRUE ) | |
RtlEqualUnicodeString ( & LdrEntry - > BaseDllName , & Kernel32 , TRUE ) | |
RtlEqualUnicodeString ( & LdrEntry - > BaseDllName , & Verifier , TRUE ) | |
RtlEqualUnicodeString ( & LdrEntry - > BaseDllName , & g_LoadingShimDll , TRUE ) | |
SE_IsShimDll ( LdrEntry - > DllBase ) | |
( LdrEntry - > Flags & LDRP_ENTRY_PROCESSED ) )
{
SHIMENG_WARN ( " Don't mess with 0x%p '%wZ' \n " , LdrEntry - > DllBase , & LdrEntry - > BaseDllName ) ;
}
else
{
SHIMENG_WARN ( " Touching 0x%p '%wZ' \n " , LdrEntry - > DllBase , & LdrEntry - > BaseDllName ) ;
LdrEntry - > Flags | = ( LDRP_ENTRY_PROCESSED | LDRP_SHIMENG_SUPPRESSED_ENTRY ) ;
}
}
ListHead = & NtCurrentPeb ( ) - > Ldr - > InMemoryOrderModuleList ;
Entry = ListHead - > Flink ;
SHIMENG_INFO ( " In memory: \n " ) ;
while ( Entry ! = ListHead )
{
LdrEntry = CONTAINING_RECORD ( Entry , LDR_DATA_TABLE_ENTRY , InMemoryOrderLinks ) ;
Entry = Entry - > Flink ;
SHIMENG_INFO ( " 0x%p '%wZ' \n " , LdrEntry - > DllBase , & LdrEntry - > BaseDllName ) ;
}
ListHead = & NtCurrentPeb ( ) - > Ldr - > InLoadOrderModuleList ;
Entry = ListHead - > Flink ;
SHIMENG_INFO ( " In load: \n " ) ;
while ( Entry ! = ListHead )
{
LdrEntry = CONTAINING_RECORD ( Entry , LDR_DATA_TABLE_ENTRY , InLoadOrderLinks ) ;
Entry = Entry - > Flink ;
SHIMENG_INFO ( " 0x%p '%wZ' \n " , LdrEntry - > DllBase , & LdrEntry - > BaseDllName ) ;
}
}
VOID SeiResetEntryProcessed ( PPEB Peb )
{
PLIST_ENTRY ListHead , Entry ;
PLDR_DATA_TABLE_ENTRY LdrEntry ;
ListHead = & NtCurrentPeb ( ) - > Ldr - > InInitializationOrderModuleList ;
Entry = ListHead - > Flink ;
while ( Entry ! = ListHead )
{
LdrEntry = CONTAINING_RECORD ( Entry , LDR_DATA_TABLE_ENTRY , InInitializationOrderLinks ) ;
Entry = Entry - > Flink ;
if ( SE_IsShimDll ( LdrEntry - > DllBase ) | |
g_hInstance = = LdrEntry - > DllBase | |
RtlEqualUnicodeString ( & LdrEntry - > BaseDllName , & Ntdll , TRUE ) | |
RtlEqualUnicodeString ( & LdrEntry - > BaseDllName , & Kernel32 , TRUE ) | |
RtlEqualUnicodeString ( & LdrEntry - > BaseDllName , & Verifier , TRUE ) | |
! ( LdrEntry - > Flags & LDRP_SHIMENG_SUPPRESSED_ENTRY ) )
{
SHIMENG_WARN ( " Don't mess with 0x%p '%wZ' \n " , LdrEntry - > DllBase , & LdrEntry - > BaseDllName ) ;
}
else
{
SHIMENG_WARN ( " Resetting 0x%p '%wZ' \n " , LdrEntry - > DllBase , & LdrEntry - > BaseDllName ) ;
LdrEntry - > Flags & = ~ ( LDRP_ENTRY_PROCESSED | LDRP_SHIMENG_SUPPRESSED_ENTRY ) ;
}
}
}
2018-11-18 22:18:13 +00:00
VOID SeiInit ( LPCWSTR ProcessImage , HSDB hsdb , SDBQUERYRESULT * pQuery , BOOLEAN ProcessInit )
2017-07-01 20:06:30 +00:00
{
DWORD n ;
2017-07-30 12:47:57 +00:00
ARRAY ShimRefArray ;
2017-07-01 20:06:30 +00:00
DWORD dwTotalHooks = 0 ;
2018-01-24 21:41:56 +00:00
FLAGINFO ShimFlags ;
2017-07-01 20:06:30 +00:00
PPEB Peb = NtCurrentPeb ( ) ;
2017-07-30 12:47:57 +00:00
/* We should only be called once! */
ASSERT ( g_pShimInfo . ItemSize__ = = 0 ) ;
ARRAY_Init ( & ShimRefArray , TAGREF ) ;
ARRAY_Init ( & g_pShimInfo , PSHIMMODULE ) ;
ARRAY_Init ( & g_pHookArray , HOOKMODULEINFO ) ;
2017-08-14 16:34:56 +00:00
ARRAY_Init ( & g_InExclude , INEXCLUDE ) ;
2018-01-24 21:41:56 +00:00
RtlZeroMemory ( & ShimFlags , sizeof ( ShimFlags ) ) ;
2017-08-14 16:34:56 +00:00
SeiInitPaths ( ) ;
2017-07-01 20:06:30 +00:00
SeiCheckComPlusImage ( Peb - > ImageBaseAddress ) ;
2018-11-18 22:18:13 +00:00
if ( ProcessInit )
{
/* Mark all modules loaded until now as 'LDRP_ENTRY_PROCESSED' so that their entrypoint is not called while we are loading shims */
SeiSetEntryProcessed ( Peb ) ;
}
2019-03-11 21:51:46 +00:00
2017-07-01 20:06:30 +00:00
/* TODO:
if ( pQuery - > trApphelp )
SeiDisplayAppHelp ( ? pQuery - > trApphelp ? ) ;
*/
2018-11-18 22:18:13 +00:00
SeiDbgPrint ( SEI_MSG , NULL , " ShimInfo(ExePath(%S)) \n " , ProcessImage ) ;
2018-01-24 21:41:56 +00:00
SeiBuildShimRefArray ( hsdb , pQuery , & ShimRefArray , & ShimFlags ) ;
if ( ShimFlags . AppCompatFlags . QuadPart )
{
SeiDbgPrint ( SEI_MSG , NULL , " Using KERNEL apphack flags 0x%I64x \n " , ShimFlags . AppCompatFlags . QuadPart ) ;
Peb - > AppCompatFlags . QuadPart | = ShimFlags . AppCompatFlags . QuadPart ;
}
if ( ShimFlags . AppCompatFlagsUser . QuadPart )
{
SeiDbgPrint ( SEI_MSG , NULL , " Using USER apphack flags 0x%I64x \n " , ShimFlags . AppCompatFlagsUser . QuadPart ) ;
Peb - > AppCompatFlagsUser . QuadPart | = ShimFlags . AppCompatFlagsUser . QuadPart ;
}
if ( ShimFlags . ProcessParameters_Flags )
{
SeiDbgPrint ( SEI_MSG , NULL , " Using ProcessParameters flags 0x%x \n " , ShimFlags . ProcessParameters_Flags ) ;
Peb - > ProcessParameters - > Flags | = ShimFlags . ProcessParameters_Flags ;
}
2017-07-01 20:06:30 +00:00
SeiDbgPrint ( SEI_MSG , NULL , " ShimInfo(Complete) \n " ) ;
2017-07-30 12:47:57 +00:00
SHIMENG_INFO ( " Got %d shims \n " , ARRAY_Size ( & ShimRefArray ) ) ;
2017-08-14 16:34:56 +00:00
SeiBuildGlobalInclExclList ( hsdb ) ;
2017-07-01 20:06:30 +00:00
2017-08-14 16:34:56 +00:00
/* Walk all shims referenced (in layers + exes), and load their modules */
2017-07-30 12:47:57 +00:00
for ( n = 0 ; n < ARRAY_Size ( & ShimRefArray ) ; + + n )
2017-07-01 20:06:30 +00:00
{
PDB pdb ;
TAGID ShimRef ;
2017-07-30 12:47:57 +00:00
TAGREF tr = * ARRAY_At ( & ShimRefArray , TAGREF , n ) ;
if ( SdbTagRefToTagID ( hsdb , tr , & pdb , & ShimRef ) )
2017-07-01 20:06:30 +00:00
{
2017-07-16 13:56:08 +00:00
LPCWSTR ShimName , DllName , CommandLine = NULL ;
2017-07-01 20:06:30 +00:00
TAGID ShimTag ;
WCHAR FullNameBuffer [ MAX_PATH ] ;
UNICODE_STRING UnicodeDllName ;
PVOID BaseAddress ;
2017-07-30 12:47:57 +00:00
PSHIMMODULE pShimModuleInfo = NULL ;
2017-07-16 13:56:08 +00:00
ANSI_STRING AnsiCommandLine = RTL_CONSTANT_STRING ( " " ) ;
2017-08-14 16:34:56 +00:00
PSHIMINFO pShimInfo = NULL ;
2017-07-01 20:06:30 +00:00
PHOOKAPIEX pHookApi ;
DWORD dwHookCount ;
ShimName = SeiGetStringPtr ( pdb , ShimRef , TAG_NAME ) ;
if ( ! ShimName )
{
2017-07-30 12:47:57 +00:00
SHIMENG_FAIL ( " Failed to retrieve the name for 0x%x \n " , tr ) ;
2017-07-01 20:06:30 +00:00
continue ;
}
2017-07-16 13:56:08 +00:00
CommandLine = SeiGetStringPtr ( pdb , ShimRef , TAG_COMMAND_LINE ) ;
if ( CommandLine & & * CommandLine )
{
RtlInitUnicodeString ( & UnicodeDllName , CommandLine ) ;
if ( NT_SUCCESS ( RtlUnicodeStringToAnsiString ( & AnsiCommandLine , & UnicodeDllName , TRUE ) ) )
{
SHIMENG_INFO ( " COMMAND LINE %s for %S " , AnsiCommandLine . Buffer , ShimName ) ;
}
else
{
AnsiCommandLine . Buffer = " " ;
CommandLine = NULL ;
}
}
2017-07-01 20:06:30 +00:00
ShimTag = SeiGetDWORD ( pdb , ShimRef , TAG_SHIM_TAGID ) ;
if ( ! ShimTag )
{
SHIMENG_FAIL ( " Failed to resolve %S to a shim \n " , ShimName ) ;
continue ;
}
2018-01-21 10:18:59 +00:00
if ( ! SUCCEEDED ( SdbGetAppPatchDir ( NULL , FullNameBuffer , ARRAYSIZE ( FullNameBuffer ) ) ) )
2017-07-01 20:06:30 +00:00
{
SHIMENG_WARN ( " Failed to get the AppPatch dir \n " ) ;
continue ;
}
DllName = SeiGetStringPtr ( pdb , ShimTag , TAG_DLLFILE ) ;
if ( DllName = = NULL | |
2017-07-30 12:47:57 +00:00
! SUCCEEDED ( StringCchCatW ( FullNameBuffer , ARRAYSIZE ( FullNameBuffer ) , L " \\ " ) ) | |
! SUCCEEDED ( StringCchCatW ( FullNameBuffer , ARRAYSIZE ( FullNameBuffer ) , DllName ) ) )
2017-07-01 20:06:30 +00:00
{
SHIMENG_WARN ( " Failed to build a full path for %S \n " , ShimName ) ;
continue ;
}
2018-11-22 23:18:17 +00:00
RtlInitUnicodeString ( & g_LoadingShimDll , DllName ) ;
2017-07-01 20:06:30 +00:00
RtlInitUnicodeString ( & UnicodeDllName , FullNameBuffer ) ;
if ( NT_SUCCESS ( LdrGetDllHandle ( NULL , NULL , & UnicodeDllName , & BaseAddress ) ) )
{
2017-08-14 16:34:56 +00:00
/* This shim dll was already loaded, let's find it */
2017-07-30 12:47:57 +00:00
pShimModuleInfo = SeiGetShimModuleInfo ( BaseAddress ) ;
2017-07-01 20:06:30 +00:00
}
else if ( ! NT_SUCCESS ( LdrLoadDll ( NULL , NULL , & UnicodeDllName , & BaseAddress ) ) )
{
SHIMENG_WARN ( " Failed to load %wZ for %S \n " , & UnicodeDllName , ShimName ) ;
continue ;
}
2018-11-22 23:18:17 +00:00
RtlInitUnicodeString ( & g_LoadingShimDll , NULL ) ;
2017-08-14 16:34:56 +00:00
/* No shim module found (or we just loaded it) */
2017-07-30 12:47:57 +00:00
if ( ! pShimModuleInfo )
2017-07-01 20:06:30 +00:00
{
2017-07-30 12:47:57 +00:00
pShimModuleInfo = SeiCreateShimModuleInfo ( DllName , BaseAddress ) ;
if ( ! pShimModuleInfo )
2017-07-01 20:06:30 +00:00
{
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 ) ;
2017-08-14 16:34:56 +00:00
/* Ask this shim what hooks it needs (and pass along the commandline) */
2019-03-11 21:47:22 +00:00
dwHookCount = 0 ;
2017-07-30 12:47:57 +00:00
pHookApi = pShimModuleInfo - > pGetHookAPIs ( AnsiCommandLine . Buffer , ShimName , & dwHookCount ) ;
2017-07-01 20:06:30 +00:00
SHIMENG_INFO ( " GetHookAPIs returns %d hooks for DLL \" %wZ \" SHIM \" %S \" \n " , dwHookCount , & UnicodeDllName , ShimName ) ;
2019-03-11 21:47:22 +00:00
if ( dwHookCount & & pHookApi )
2017-08-14 16:34:56 +00:00
pShimInfo = SeiAppendHookInfo ( pShimModuleInfo , pHookApi , dwHookCount , ShimName ) ;
2019-03-11 21:47:22 +00:00
else
dwHookCount = 0 ;
2017-08-14 16:34:56 +00:00
/* If this shim has hooks, create the include / exclude lists */
if ( pShimInfo )
SeiBuildInclExclList ( pdb , ShimTag , pShimInfo ) ;
2017-07-01 20:06:30 +00:00
2017-07-16 13:56:08 +00:00
if ( CommandLine & & * CommandLine )
RtlFreeAnsiString ( & AnsiCommandLine ) ;
2017-07-01 20:06:30 +00:00
dwTotalHooks + = dwHookCount ;
}
}
SeiAddInternalHooks ( dwTotalHooks ) ;
2019-03-13 19:15:18 +00:00
SeiCombineHookInfo ( ) ;
2017-07-01 20:06:30 +00:00
SeiResolveAPIs ( ) ;
PatchNewModules ( Peb ) ;
2019-03-11 21:51:46 +00:00
2018-11-18 22:18:13 +00:00
if ( ProcessInit )
{
/* Remove the 'LDRP_ENTRY_PROCESSED' flag from entries we modified, so that the loader can continue to process them */
SeiResetEntryProcessed ( Peb ) ;
}
2022-10-20 17:17:33 +00:00
g_bShimEngInitialized = TRUE ;
2017-07-01 20:06:30 +00:00
}
2017-08-14 16:34:56 +00:00
/* Load the database + unpack the shim data (if this process is allowed) */
2017-07-01 20:06:30 +00:00
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
} ;
2018-02-11 21:40:51 +00:00
static const UNICODE_STRING PathDividerFind = RTL_CONSTANT_STRING ( L " \\ / " ) ;
2017-07-01 20:06:30 +00:00
UNICODE_STRING ProcessName ;
2018-02-11 21:40:51 +00:00
USHORT PathDivider ;
2017-07-01 20:06:30 +00:00
HSDB hsdb ;
DWORD n ;
2018-02-11 21:40:51 +00:00
if ( ! NT_SUCCESS ( RtlFindCharInUnicodeString ( RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END , ProcessImage , & PathDividerFind , & PathDivider ) ) )
PathDivider = 0 ;
2017-07-01 20:06:30 +00:00
2018-02-11 21:40:51 +00:00
if ( PathDivider )
PathDivider + = sizeof ( WCHAR ) ;
2017-07-01 20:06:30 +00:00
2018-02-11 21:40:51 +00:00
ProcessName . Buffer = ProcessImage - > Buffer + PathDivider / sizeof ( WCHAR ) ;
ProcessName . Length = ProcessImage - > Length - PathDivider ;
ProcessName . MaximumLength = ProcessImage - > MaximumLength - PathDivider ;
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
for ( n = 0 ; n < ARRAYSIZE ( ForbiddenShimmingApps ) ; + + n )
2017-07-01 20:06:30 +00:00
{
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 ;
}
2017-05-13 18:49:27 +00:00
VOID NTAPI SE_InstallBeforeInit ( PUNICODE_STRING ProcessImage , PVOID pShimData )
{
2017-07-01 20:06:30 +00:00
HSDB hsdb = NULL ;
SDBQUERYRESULT QueryResult = { { 0 } } ;
2018-01-25 20:39:01 +00:00
SHIMENG_INFO ( " (%wZ, %p) \n " , ProcessImage , pShimData ) ;
2017-07-01 20:06:30 +00:00
if ( ! SeiGetShimData ( ProcessImage , pShimData , & hsdb , & QueryResult ) )
{
SHIMENG_FAIL ( " Failed to get shim data \n " ) ;
return ;
}
g_bShimDuringInit = TRUE ;
2018-11-18 22:18:13 +00:00
SeiInit ( ProcessImage - > Buffer , hsdb , & QueryResult , TRUE ) ;
2017-07-01 20:06:30 +00:00
g_bShimDuringInit = FALSE ;
SdbReleaseDatabase ( hsdb ) ;
2017-05-13 18:49:27 +00:00
}
VOID NTAPI SE_InstallAfterInit ( PUNICODE_STRING ProcessImage , PVOID pShimData )
{
NotifyShims ( SHIM_NOTIFY_ATTACH , NULL ) ;
}
VOID NTAPI SE_ProcessDying ( VOID )
{
2017-07-01 20:06:30 +00:00
SHIMENG_MSG ( " () \n " ) ;
2017-05-13 18:49:27 +00:00
NotifyShims ( SHIM_NOTIFY_DETACH , NULL ) ;
}
VOID WINAPI SE_DllLoaded ( PLDR_DATA_TABLE_ENTRY LdrEntry )
{
2019-03-13 19:15:18 +00:00
PHOOKMODULEINFO HookModuleInfo ;
2017-07-01 20:06:30 +00:00
SHIMENG_INFO ( " %sINIT. loading DLL \" %wZ \" \n " , g_bShimDuringInit ? " " : " AFTER " , & LdrEntry - > BaseDllName ) ;
2017-08-29 20:21:58 +00:00
2019-03-13 19:15:18 +00:00
HookModuleInfo = SeiFindHookModuleInfo ( & LdrEntry - > BaseDllName , NULL ) ;
if ( HookModuleInfo )
{
ASSERT ( HookModuleInfo - > BaseAddress = = NULL ) ;
HookModuleInfo - > BaseAddress = LdrEntry - > DllBase ;
SeiResolveAPI ( HookModuleInfo ) ;
}
2017-08-29 20:21:58 +00:00
SeiHookImports ( LdrEntry ) ;
2017-05-13 18:49:27 +00:00
NotifyShims ( SHIM_REASON_DLL_LOAD , LdrEntry ) ;
}
VOID WINAPI SE_DllUnloaded ( PLDR_DATA_TABLE_ENTRY LdrEntry )
{
2017-08-17 16:42:29 +00:00
SHIMENG_INFO ( " (%p) \n " , LdrEntry ) ;
2017-08-29 20:21:58 +00:00
/* Should we unhook here? */
2017-05-13 18:49:27 +00:00
NotifyShims ( SHIM_REASON_DLL_UNLOAD , LdrEntry ) ;
}
BOOL WINAPI SE_IsShimDll ( PVOID BaseAddress )
{
2017-08-17 16:42:29 +00:00
SHIMENG_INFO ( " (%p) \n " , BaseAddress ) ;
2017-07-01 20:06:30 +00:00
2017-07-30 12:47:57 +00:00
return SeiGetShimModuleInfo ( BaseAddress ) ! = NULL ;
2017-05-13 18:49:27 +00:00
}
2018-11-18 22:18:13 +00:00
/* 'Private' ntdll function */
BOOLEAN
NTAPI
LdrInitShimEngineDynamic ( IN PVOID BaseAddress ) ;
BOOL WINAPI SE_DynamicShim ( LPCWSTR ProcessImage , HSDB hsdb , PVOID pQueryResult , LPCSTR Module , LPDWORD lpdwDynamicToken )
{
2022-10-20 17:17:33 +00:00
if ( g_bShimEngInitialized )
{
SHIMENG_MSG ( " ReactOS HACK(CORE-13283): ShimEng already initialized! \n " ) ;
return TRUE ;
}
2018-11-18 22:18:13 +00:00
g_bShimDuringInit = TRUE ;
SeiInit ( ProcessImage , hsdb , pQueryResult , FALSE ) ;
g_bShimDuringInit = FALSE ;
LdrInitShimEngineDynamic ( g_hInstance ) ;
return TRUE ;
}