ReactOS 0.4.16-dev-927-g467dec4
DllLoadNotification.c File Reference
#include "precomp.h"
#include <winuser.h>
Include dependency graph for DllLoadNotification.c:

Go to the source code of this file.

Macros

#define UNICODE
 

Typedefs

typedef NTSTATUS NTAPI FN_LdrRegisterDllNotification(_In_ ULONG Flags, _In_ PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, _In_opt_ PVOID Context, _Out_ PVOID *Cookie)
 
typedef NTSTATUS NTAPI FN_LdrUnregisterDllNotification(_In_ PVOID Cookie)
 

Functions

static BOOL ExtractResource (_In_z_ PCWSTR SavePath, _In_ PCWSTR ResourceType, _In_ PCWSTR ResourceName)
 
static VOID NTAPI DllLoadCallback (_In_ ULONG NotificationReason, _In_ PCLDR_DLL_NOTIFICATION_DATA NotificationData, _In_opt_ PVOID Context)
 
 START_TEST (DllLoadNotification)
 

Variables

static WCHAR g_szDllPath [MAX_PATH]
 
static UNICODE_STRING g_usDllPath
 
static UNICODE_STRING g_usDllName
 
static volatile LONG g_lDllLoadCount = 0
 

Macro Definition Documentation

◆ UNICODE

Definition at line 8 of file DllLoadNotification.c.

Typedef Documentation

◆ FN_LdrRegisterDllNotification

typedef NTSTATUS NTAPI FN_LdrRegisterDllNotification(_In_ ULONG Flags, _In_ PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, _In_opt_ PVOID Context, _Out_ PVOID *Cookie)

Definition at line 22 of file DllLoadNotification.c.

◆ FN_LdrUnregisterDllNotification

typedef NTSTATUS NTAPI FN_LdrUnregisterDllNotification(_In_ PVOID Cookie)

Definition at line 31 of file DllLoadNotification.c.

Function Documentation

◆ DllLoadCallback()

static VOID NTAPI DllLoadCallback ( _In_ ULONG  NotificationReason,
_In_ PCLDR_DLL_NOTIFICATION_DATA  NotificationData,
_In_opt_ PVOID  Context 
)
static

Definition at line 83 of file DllLoadNotification.c.

87{
88 LONG lRet;
89 HMODULE* phNotifiedDllBase = Context;
90
91 /*
92 * Verify the data,
93 * NotificationData->Loaded and NotificationData->Unloaded currently are the same.
94 */
95
96 /* Verify the FullDllName and BaseDllName */
97 ok_eq_ulong(NotificationData->Loaded.Flags, 0UL);
98 lRet = RtlCompareUnicodeString(NotificationData->Loaded.FullDllName,
100 TRUE);
101 ok_eq_long(lRet, 0L);
102 lRet = RtlCompareUnicodeString(NotificationData->Loaded.BaseDllName,
104 TRUE);
105 ok_eq_long(lRet, 0L);
106
107 /*
108 * Verify SizeOfImage and read SizeOfImage from PE header,
109 * make sure the DLL is not unmapped, the memory is still accessible.
110 */
111 ok_eq_ulong(NotificationData->Loaded.SizeOfImage,
112 RtlImageNtHeader(NotificationData->Loaded.DllBase)->OptionalHeader.SizeOfImage);
113
114 /* Reason can be load or unload */
115 ok(NotificationReason == LDR_DLL_NOTIFICATION_REASON_LOADED ||
116 NotificationReason == LDR_DLL_NOTIFICATION_REASON_UNLOADED, "Incorrect NotificationReason\n");
117 if (NotificationReason == LDR_DLL_NOTIFICATION_REASON_LOADED)
118 {
119 *phNotifiedDllBase = NotificationData->Loaded.DllBase;
121 }
122 else if (NotificationReason == LDR_DLL_NOTIFICATION_REASON_UNLOADED)
123 {
125 }
126}
static volatile LONG g_lDllLoadCount
static UNICODE_STRING g_usDllPath
static UNICODE_STRING g_usDllName
#define ok_eq_ulong(value, expected)
Definition: apitest.h:44
#define ok_eq_long(value, expected)
Definition: apitest.h:43
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define ok(value,...)
Definition: atltest.h:57
#define TRUE
Definition: types.h:120
#define RtlImageNtHeader
Definition: compat.h:806
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED
Definition: ldrtypes.h:204
#define LDR_DLL_NOTIFICATION_REASON_LOADED
Definition: ldrtypes.h:203
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
#define UL
Definition: tui.h:164
_In_ PCWDF_DEVICE_PNP_NOTIFICATION_DATA NotificationData
Definition: wdfdevice.h:782

Referenced by START_TEST().

◆ ExtractResource()

static BOOL ExtractResource ( _In_z_ PCWSTR  SavePath,
_In_ PCWSTR  ResourceType,
_In_ PCWSTR  ResourceName 
)
static

Definition at line 34 of file DllLoadNotification.c.

38{
39 BOOL bSuccess;
40 DWORD dwWritten, dwSize;
41 HGLOBAL hGlobal;
44 HRSRC hRsrc;
45
46 /* Load resource */
47 if ((hRsrc = FindResourceW(NULL, ResourceName, ResourceType)) == NULL ||
48 (dwSize = SizeofResource(NULL, hRsrc)) == 0 ||
49 (hGlobal = LoadResource(NULL, hRsrc)) == NULL ||
50 (pData = LockResource(hGlobal)) == NULL)
51 {
52 return FALSE;
53 }
54
55 /* Save to file */
56 hFile = CreateFileW(SavePath,
59 NULL,
62 NULL);
64 {
65 return FALSE;
66 }
67 bSuccess = WriteFile(hFile, pData, dwSize, &dwWritten, NULL);
69 if (!bSuccess)
70 {
71 return FALSE;
72 }
73 else if (dwWritten != dwSize)
74 {
75 trace("Extract resource failed, written size (%lu) is not actual size (%lu)\n", dwWritten, dwSize);
76 DeleteFileW(SavePath);
78 return FALSE;
79 }
80 return TRUE;
81}
#define trace
Definition: atltest.h:70
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
Definition: res.c:176
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define CREATE_ALWAYS
Definition: disk.h:72
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
_In_ HANDLE hFile
Definition: mswsock.h:90
#define GENERIC_WRITE
Definition: nt_native.h:90
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
#define ERROR_INCORRECT_SIZE
Definition: winerror.h:943

Referenced by START_TEST().

◆ START_TEST()

START_TEST ( DllLoadNotification  )

Definition at line 128 of file DllLoadNotification.c.

129{
132 HMODULE hNtDll, hTestDll, hNotifiedDllBase;
133 FN_LdrRegisterDllNotification* pfnLdrRegisterDllNotification;
134 FN_LdrUnregisterDllNotification* pfnLdrUnregisterDllNotification;
136 PVOID Cookie1, Cookie2;
137
138 /* Load functions */
139 hNtDll = GetModuleHandleW(L"ntdll.dll");
140 if (hNtDll == NULL)
141 {
142 skip("GetModuleHandleW for ntdll failed with 0x%08lX\n", GetLastError());
143 return;
144 }
145 pfnLdrRegisterDllNotification = (FN_LdrRegisterDllNotification*)GetProcAddress(hNtDll, "LdrRegisterDllNotification");
146 pfnLdrUnregisterDllNotification = (FN_LdrUnregisterDllNotification*)GetProcAddress(hNtDll, "LdrUnregisterDllNotification");
147 if (!pfnLdrRegisterDllNotification || !pfnLdrUnregisterDllNotification)
148 {
149 skip("ntdll.dll!Ldr[Un]RegisterDllNotification not found\n");
150 return;
151 }
152
153 /* Extract DLL to temp directory */
155 {
156 skip("GetTempPathW failed with 0x%08lX\n", GetLastError());
157 return;
158 }
159 if (GetTempFileNameW(szTempPath, L"DLN", 0, g_szDllPath) == 0)
160 {
161 skip("GetTempFileNameW failed with 0x%08lX\n", GetLastError());
162 return;
163 }
165 pszDllName = wcsrchr(g_szDllPath, L'\\') + 1;
166 if (pszDllName == NULL)
167 {
168 skip("Find file name of %ls failed\n", g_szDllPath);
169 return;
170 }
173 {
174 skip("ExtractResource failed with 0x%08lX\n", GetLastError());
175 return;
176 }
177
178 /* Register DLL load notification callback */
179 hNotifiedDllBase = NULL;
180 Cookie1 = NULL;
181 Cookie2 = NULL;
182 Status = pfnLdrRegisterDllNotification(0, DllLoadCallback, &hNotifiedDllBase, &Cookie1);
184 ok(Cookie1 != NULL, "Cookie1 is NULL\n");
185
186 /* Register the callback again is valid */
187 Status = pfnLdrRegisterDllNotification(0, DllLoadCallback, &hNotifiedDllBase, &Cookie2);
189 ok(Cookie2 != NULL, "Cookie2 is NULL\n");
190
191 /* Load the test DLL */
192 hTestDll = LoadLibraryW(g_szDllPath);
193 if (!hTestDll)
194 {
195 skip("LoadLibraryW failed with 0x%08lX\n", GetLastError());
196 goto _exit;
197 }
198
199 /* Verify the Dll base received in callback and returned via context */
200 ok_eq_pointer(hNotifiedDllBase, hTestDll);
201
202 /* The count should be 2 because the callback was registered twice */
204
205 /*
206 * Callback will not be triggered because following
207 * load and unload actions change the DLL reference count only
208 */
211 FreeLibrary(hTestDll);
213
214 /* Unregister the callback once */
215 Status = pfnLdrUnregisterDllNotification(Cookie1);
217
218 /* Unload the test DLL */
219 if (FreeLibrary(hTestDll))
220 {
221 /* The count will decrease 1 because the last callback still there */
223 }
224 else
225 {
226 skip("FreeLibrary failed with 0x%08lX\n", GetLastError());
227 }
228
229 /* Unregister the last callback */
230 Status = pfnLdrUnregisterDllNotification(Cookie2);
232
233_exit:
235}
static WCHAR g_szDllPath[MAX_PATH]
static BOOL ExtractResource(_In_z_ PCWSTR SavePath, _In_ PCWSTR ResourceType, _In_ PCWSTR ResourceName)
NTSTATUS NTAPI FN_LdrUnregisterDllNotification(_In_ PVOID Cookie)
static VOID NTAPI DllLoadCallback(_In_ ULONG NotificationReason, _In_ PCLDR_DLL_NOTIFICATION_DATA NotificationData, _In_opt_ PVOID Context)
NTSTATUS NTAPI FN_LdrRegisterDllNotification(_In_ ULONG Flags, _In_ PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, _In_opt_ PVOID Context, _Out_ PVOID *Cookie)
void _exit(int exitcode)
Definition: _exit.c:25
#define ok_eq_pointer(value, expected)
Definition: apitest.h:40
#define ok_eq_bool(value, expected)
Definition: apitest.h:61
#define skip(...)
Definition: atltest.h:64
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define wcsrchr
Definition: compat.h:16
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
#define MAX_PATH
Definition: compat.h:34
#define LoadLibraryW(x)
Definition: compat.h:747
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2080
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
Status
Definition: gdiplustypes.h:25
static char szTempPath[MAX_PATH]
Definition: data.c:16
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RT_RCDATA
Definition: pedump.c:372
char * pszDllName
Definition: spec2def.c:74
const uint16_t * PCWSTR
Definition: typedefs.h:57
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
__wchar_t WCHAR
Definition: xmlstorage.h:180

Variable Documentation

◆ g_lDllLoadCount

volatile LONG g_lDllLoadCount = 0
static

Definition at line 17 of file DllLoadNotification.c.

Referenced by DllLoadCallback(), and START_TEST().

◆ g_szDllPath

WCHAR g_szDllPath[MAX_PATH]
static

Definition at line 14 of file DllLoadNotification.c.

Referenced by START_TEST().

◆ g_usDllName

UNICODE_STRING g_usDllName
static

Definition at line 16 of file DllLoadNotification.c.

Referenced by DllLoadCallback(), and START_TEST().

◆ g_usDllPath

UNICODE_STRING g_usDllPath
static

Definition at line 15 of file DllLoadNotification.c.

Referenced by DllLoadCallback(), and START_TEST().