2 * PROJECT: ReactOS Shim helper library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Shim helper functions
5 * COPYRIGHT: Copyright 2016,2017 Mark Jansen (mark.jansen@reactos.org)
8 #define WIN32_NO_STATUS
13 #include <ndk/rtlfuncs.h>
15 typedef struct UsedShim
19 #if (WINVER > _WIN32_WINNT_WS03)
22 } UsedShim
, *pUsedShim
;
25 ULONG g_ShimEngDebugLevel
= 0xffffffff;
26 static HANDLE g_ShimLib_Heap
;
27 static PSLIST_HEADER g_UsedShims
;
29 void ShimLib_Init(HINSTANCE hInstance
)
31 g_ShimLib_Heap
= HeapCreate(0, 0x10000, 0);
33 g_UsedShims
= (PSLIST_HEADER
)ShimLib_ShimMalloc(sizeof(SLIST_HEADER
));
34 RtlInitializeSListHead(g_UsedShims
);
39 // Is this a good idea?
40 HeapDestroy(g_ShimLib_Heap
);
43 PVOID
ShimLib_ShimMalloc(SIZE_T dwSize
)
45 return HeapAlloc(g_ShimLib_Heap
, 0, dwSize
);
48 void ShimLib_ShimFree(PVOID pData
)
50 HeapFree(g_ShimLib_Heap
, 0, pData
);
53 PCSTR
ShimLib_StringDuplicateA(PCSTR szString
)
55 SIZE_T Length
= lstrlenA(szString
);
56 PSTR NewString
= ShimLib_ShimMalloc(Length
+1);
57 return lstrcpyA(NewString
, szString
);
60 BOOL
ShimLib_StrAEqualsW(PCSTR szString
, PCWSTR wszString
)
62 while (*szString
== *wszString
)
67 szString
++; wszString
++;
74 #if defined(_M_IA64) || defined(_M_AMD64)
75 #define _ATTRIBUTES read
77 #define _ATTRIBUTES read
81 #pragma section(".shm",long,read)
82 #pragma section(".shm$AAA",long,read)
83 #pragma section(".shm$ZZZ",long,read)
87 #pragma comment(linker, "/merge:.shm=.rdata")
91 _SHMALLOC(".shm") SHIMREG _shim_start
= { 0 };
92 _SHMALLOC(".shm$ZZZ") SHIMREG _shim_end
= { 0 };
95 /* Generic GetHookAPIs function.
96 The macro's from <setup_shim.inl> and <implement_shim.inl> will register a list of all apis that should be hooked
98 This helper function will return the correct shim, and call the init function */
99 PHOOKAPI WINAPI
ShimLib_GetHookAPIs(IN LPCSTR szCommandLine
, IN LPCWSTR wszShimName
, OUT PDWORD pdwHookCount
)
101 PSHIMREG ps
= &_shim_start
;
103 for (; ps
!= &_shim_end
; ps
++)
105 if (ps
->GetHookAPIs
!= NULL
&& ps
->ShimName
!= NULL
)
107 if (ShimLib_StrAEqualsW(ps
->ShimName
, wszShimName
))
109 pUsedShim shim
= (pUsedShim
)ShimLib_ShimMalloc(sizeof(UsedShim
));
111 #if (WINVER > _WIN32_WINNT_WS03)
112 shim
->bInitCalled
= FALSE
;
114 RtlInterlockedPushEntrySList(g_UsedShims
, &(shim
->Entry
));
116 return ps
->GetHookAPIs(SHIM_NOTIFY_ATTACH
, szCommandLine
, pdwHookCount
);
124 BOOL WINAPI
ShimLib_NotifyShims(DWORD fdwReason
, PVOID ptr
)
126 PSLIST_ENTRY pEntry
= RtlFirstEntrySList(g_UsedShims
);
128 if (fdwReason
< SHIM_REASON_INIT
)
129 fdwReason
+= (SHIM_REASON_INIT
- SHIM_NOTIFY_ATTACH
);
133 pUsedShim pUsed
= CONTAINING_RECORD(pEntry
, UsedShim
, Entry
);
134 _PVNotify Notify
= pUsed
->pShim
->Notify
;
135 #if (WINVER > _WIN32_WINNT_WS03)
136 if (pUsed
->bInitCalled
&& fdwReason
== SHIM_REASON_INIT
)
140 Notify(fdwReason
, ptr
);
141 #if (WINVER > _WIN32_WINNT_WS03)
142 if (fdwReason
== SHIM_REASON_INIT
)
143 pUsed
->bInitCalled
= TRUE
;
146 pEntry
= pEntry
->Next
;
153 VOID
SeiInitDebugSupport(VOID
)
155 static const UNICODE_STRING DebugKey
= RTL_CONSTANT_STRING(L
"SHIM_DEBUG_LEVEL");
156 UNICODE_STRING DebugValue
;
161 RtlInitEmptyUnicodeString(&DebugValue
, Buffer
, sizeof(Buffer
));
163 Status
= RtlQueryEnvironmentVariable_U(NULL
, &DebugKey
, &DebugValue
);
165 if (NT_SUCCESS(Status
))
167 if (!NT_SUCCESS(RtlUnicodeStringToInteger(&DebugValue
, 10, &NewLevel
)))
170 g_ShimEngDebugLevel
= NewLevel
;
175 * Outputs diagnostic info.
177 * @param [in] Level The level to log this message with, choose any of [SHIM_ERR,
178 * SHIM_WARN, SHIM_INFO].
179 * @param [in] FunctionName The function this log should be attributed to.
180 * @param [in] Format The format string.
181 * @param ... Variable arguments providing additional information.
183 * @return Success: TRUE Failure: FALSE.
185 BOOL WINAPIV
SeiDbgPrint(SEI_LOG_LEVEL Level
, PCSTR Function
, PCSTR Format
, ...)
188 char* Current
= Buffer
;
189 const char* LevelStr
;
190 size_t Length
= sizeof(Buffer
);
194 if (g_ShimEngDebugLevel
== 0xffffffff)
195 SeiInitDebugSupport();
197 if (Level
> g_ShimEngDebugLevel
)
220 hr
= StringCchPrintfExA(Current
, Length
, &Current
, &Length
, STRSAFE_NULL_ON_FAILURE
, "[%s] [%s] ", LevelStr
, Function
);
222 hr
= StringCchPrintfExA(Current
, Length
, &Current
, &Length
, STRSAFE_NULL_ON_FAILURE
, "[%s] ", LevelStr
);
227 va_start(ArgList
, Format
);
228 hr
= StringCchVPrintfExA(Current
, Length
, &Current
, &Length
, STRSAFE_NULL_ON_FAILURE
, Format
, ArgList
);
233 DbgPrint("%s", Buffer
);