ReactOS 0.4.15-dev-7942-gd23573b
shimlib.c
Go to the documentation of this file.
1/*
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-2018 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8#define WIN32_NO_STATUS
9#include <windef.h>
10#include <winbase.h>
11#include <shimlib.h>
12#include <strsafe.h>
13#include <ndk/rtlfuncs.h>
14
15typedef struct UsedShim
16{
19#if (WINVER > _WIN32_WINNT_WS03)
20 BOOL bInitCalled;
21#endif
23
24
29
31{
33 g_ShimLib_Heap = HeapCreate(0, 0x10000, 0);
34
37}
38
40{
41 // Is this a good idea?
43}
44
46{
48}
49
51{
53}
54
56{
58}
59
60PCSTR ShimLib_StringNDuplicateA(PCSTR szString, SIZE_T stringLengthIncludingNullTerm)
61{
62 PSTR NewString = ShimLib_ShimMalloc(stringLengthIncludingNullTerm);
63 StringCchCopyA(NewString, stringLengthIncludingNullTerm, szString);
64 return NewString;
65}
66
68{
69 return ShimLib_StringNDuplicateA(szString, lstrlenA(szString) + 1);
70}
71
73{
74 while (toupper(*szString) == towupper(*wszString))
75 {
76 if (!*szString)
77 return TRUE;
78
79 szString++; wszString++;
80 }
81 return FALSE;
82}
83
84#if defined(_MSC_VER)
85
86#if defined(_M_IA64) || defined(_M_AMD64)
87#define _ATTRIBUTES read
88#else
89#define _ATTRIBUTES read
90#endif
91
92
93#pragma section(".shm",long,read)
94#pragma section(".shm$AAA",long,read)
95#pragma section(".shm$ZZZ",long,read)
96#endif
97
98#ifdef _MSC_VER
99#pragma comment(linker, "/merge:.shm=.rdata")
100#endif
101
102
103_SHMALLOC(".shm$AAA") SHIMREG _shim_start = { 0 };
104_SHMALLOC(".shm$ZZZ") SHIMREG _shim_end = { 0 };
105
106
107/* Generic GetHookAPIs function.
108 The macro's from <setup_shim.inl> and <implement_shim.inl> will register a list of all apis that should be hooked
109 for a specific shim
110 This helper function will return the correct shim, and call the init function */
111PHOOKAPI WINAPI ShimLib_GetHookAPIs(IN LPCSTR szCommandLine, IN LPCWSTR wszShimName, OUT PDWORD pdwHookCount)
112{
113 PSHIMREG ps = &_shim_start;
114 ps++;
115 for (; ps < &_shim_end; ps++)
116 {
117 if (ps->GetHookAPIs != NULL && ps->ShimName != NULL)
118 {
119 if (ShimLib_StrAEqualsWNC(ps->ShimName, wszShimName))
120 {
122 shim->pShim = ps;
123#if (WINVER > _WIN32_WINNT_WS03)
124 shim->bInitCalled = FALSE;
125#endif
127
128 return ps->GetHookAPIs(SHIM_NOTIFY_ATTACH, szCommandLine, pdwHookCount);
129 }
130 }
131 }
132 return NULL;
133}
134
135
137{
139
140 if (fdwReason < SHIM_REASON_INIT)
141 fdwReason += (SHIM_REASON_INIT - SHIM_NOTIFY_ATTACH);
142
143 while (pEntry)
144 {
146 _PVNotify Notify = pUsed->pShim->Notify;
147#if (WINVER > _WIN32_WINNT_WS03)
148 if (pUsed->bInitCalled && fdwReason == SHIM_REASON_INIT)
149 Notify = NULL;
150#endif
151 if (Notify)
152 Notify(fdwReason, ptr);
153#if (WINVER > _WIN32_WINNT_WS03)
154 if (fdwReason == SHIM_REASON_INIT)
155 pUsed->bInitCalled = TRUE;
156#endif
157
158 pEntry = pEntry->Next;
159 }
160
161 return TRUE;
162}
163
164
166{
167 static const UNICODE_STRING DebugKey = RTL_CONSTANT_STRING(L"SHIM_DEBUG_LEVEL");
168 UNICODE_STRING DebugValue;
170 ULONG NewLevel = SEI_MSG;
171 WCHAR Buffer[40];
172
173 RtlInitEmptyUnicodeString(&DebugValue, Buffer, sizeof(Buffer));
174
175 Status = RtlQueryEnvironmentVariable_U(NULL, &DebugKey, &DebugValue);
176
177 if (NT_SUCCESS(Status))
178 {
179 if (!NT_SUCCESS(RtlUnicodeStringToInteger(&DebugValue, 10, &NewLevel)))
180 NewLevel = 0;
181 }
182 g_ShimEngDebugLevel = NewLevel;
183}
184
185
198{
199 char Buffer[512];
200 char* Current = Buffer;
201 const char* LevelStr;
202 size_t Length = sizeof(Buffer);
203 va_list ArgList;
204 HRESULT hr;
205
206 if (g_ShimEngDebugLevel == 0xffffffff)
208
210 return FALSE;
211
212 switch (Level)
213 {
214 case SEI_MSG:
215 LevelStr = "MSG ";
216 break;
217 case SEI_FAIL:
218 LevelStr = "FAIL";
219 break;
220 case SEI_WARN:
221 LevelStr = "WARN";
222 break;
223 case SEI_INFO:
224 LevelStr = "INFO";
225 break;
226 default:
227 LevelStr = "USER";
228 break;
229 }
230
231 if (Function)
232 hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] [%s] ", LevelStr, Function);
233 else
234 hr = StringCchPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, "[%s] ", LevelStr);
235
236 if (!SUCCEEDED(hr))
237 return FALSE;
238
239 va_start(ArgList, Format);
240 hr = StringCchVPrintfExA(Current, Length, &Current, &Length, STRSAFE_NULL_ON_FAILURE, Format, ArgList);
241 va_end(ArgList);
242 if (!SUCCEEDED(hr))
243 return FALSE;
244
245 DbgPrint("%s", Buffer);
246 return TRUE;
247}
248
int toupper(int c)
Definition: utclib.c:881
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
LONG NTSTATUS
Definition: precomp.h:26
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
HINSTANCE hInstance
Definition: charmap.c:19
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOL WINAPI SHIM_OBJ_NAME() Notify(DWORD fdwReason, PVOID ptr)
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
Status
Definition: gdiplustypes.h:25
#define DbgPrint
Definition: hal.h:12
HANDLE WINAPI HeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize)
Definition: heapmem.c:45
BOOL WINAPI HeapDestroy(HANDLE hHeap)
Definition: heapmem.c:85
#define SUCCEEDED(hr)
Definition: intsafe.h:50
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
NTSYSAPI NTSTATUS NTAPI RtlQueryEnvironmentVariable_U(_In_opt_ PWSTR Environment, _In_ PCUNICODE_STRING Name, _Out_ PUNICODE_STRING Value)
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STRSAFE_NULL_ON_FAILURE
Definition: ntstrsafe.h:34
#define L(x)
Definition: ntvdm.h:50
DWORD * PDWORD
Definition: pedump.c:68
#define WINAPIV
Definition: sdbpapi.h:64
static PSLIST_HEADER g_UsedShims
Definition: shimlib.c:28
static HINSTANCE g_ShimLib_hInstance
Definition: shimlib.c:26
void ShimLib_Init(HINSTANCE hInstance)
Definition: shimlib.c:30
PVOID ShimLib_ShimMalloc(SIZE_T dwSize)
Definition: shimlib.c:45
struct UsedShim * pUsedShim
BOOL WINAPI ShimLib_NotifyShims(DWORD fdwReason, PVOID ptr)
Definition: shimlib.c:136
HINSTANCE ShimLib_Instance(VOID)
Definition: shimlib.c:55
BOOL WINAPIV SeiDbgPrint(SEI_LOG_LEVEL Level, PCSTR Function, PCSTR Format,...)
Definition: shimlib.c:197
void ShimLib_Deinit(VOID)
Definition: shimlib.c:39
PCSTR ShimLib_StringDuplicateA(PCSTR szString)
Definition: shimlib.c:67
BOOL ShimLib_StrAEqualsWNC(PCSTR szString, PCWSTR wszString)
Definition: shimlib.c:72
VOID SeiInitDebugSupport(VOID)
Definition: shimlib.c:165
ULONG g_ShimEngDebugLevel
Definition: shimlib.c:25
_SHMALLOC(".shm$AAA")
Definition: shimlib.c:103
PHOOKAPI WINAPI ShimLib_GetHookAPIs(IN LPCSTR szCommandLine, IN LPCWSTR wszShimName, OUT PDWORD pdwHookCount)
Definition: shimlib.c:111
void ShimLib_ShimFree(PVOID pData)
Definition: shimlib.c:50
PCSTR ShimLib_StringNDuplicateA(PCSTR szString, SIZE_T stringLengthIncludingNullTerm)
Definition: shimlib.c:60
static HANDLE g_ShimLib_Heap
Definition: shimlib.c:27
@ SEI_FAIL
Definition: shimlib.h:59
@ SEI_MSG
Definition: shimlib.h:58
@ SEI_INFO
Definition: shimlib.h:61
@ SEI_WARN
Definition: shimlib.h:60
#define SHIM_REASON_INIT
Definition: shimlib.h:45
BOOL(WINAPI * _PVNotify)(DWORD, PVOID)
Definition: shimlib.h:82
enum _SEI_LOG_LEVEL SEI_LOG_LEVEL
#define SHIM_NOTIFY_ATTACH
Definition: shimlib.h:50
HRESULT hr
Definition: shlfolder.c:183
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
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
STRSAFEAPI StringCchPrintfExA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCSTR pszFormat,...)
Definition: strsafe.h:575
base of all file and directory entries
Definition: entries.h:83
SLIST_ENTRY Entry
Definition: shimlib.c:17
PSHIMREG pShim
Definition: shimlib.c:18
PCSTR ShimName
Definition: shimlib.h:88
_PVNotify Notify
Definition: shimlib.h:87
_PVGetHookAPIs GetHookAPIs
Definition: shimlib.h:86
#define SLIST_ENTRY(type)
Definition: queue.h:102
#define towupper(c)
Definition: wctype.h:99
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
char * PSTR
Definition: typedefs.h:51
const uint16_t * PCWSTR
Definition: typedefs.h:57
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define WINAPI
Definition: msvc.h:6
NTSYSAPI PSLIST_ENTRY NTAPI RtlInterlockedPushEntrySList(_Inout_ PSLIST_HEADER ListHead, _Inout_ __drv_aliasesMem PSLIST_ENTRY ListEntry)
Definition: slist.c:226
NTSYSAPI VOID NTAPI RtlInitializeSListHead(_Out_ PSLIST_HEADER ListHead)
Definition: slist.c:25
_Must_inspect_result_ NTSYSAPI PSLIST_ENTRY NTAPI RtlFirstEntrySList(_In_ const SLIST_HEADER *ListHead)
Definition: slist.c:51
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
#define PSLIST_ENTRY
Definition: rtltypes.h:134
union _SLIST_HEADER * PSLIST_HEADER
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185