1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS user32.dll 4 * FILE: win32ss/user/user32/misc/usrapihk.c 5 * PURPOSE: User32.dll User32 Api Hook interface and support functions 6 * PROGRAMMER: 7 * 8 * 9 * 10 * Information: 11 * http://www.reactos.org/wiki/RegisterUserApiHook 12 * 13 */ 14 15 #include <user32.h> 16 17 WINE_DEFAULT_DEBUG_CHANNEL(user32); 18 19 BOOL WINAPI RealAdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD); 20 LRESULT WINAPI RealDefWindowProcA(HWND,UINT,WPARAM,LPARAM); 21 LRESULT WINAPI RealDefWindowProcW(HWND,UINT,WPARAM,LPARAM); 22 BOOL WINAPI RealDrawFrameControl(HDC,LPRECT,UINT,UINT); 23 BOOL WINAPI RealGetScrollInfo(HWND,INT,LPSCROLLINFO); 24 int WINAPI RealGetSystemMetrics(int); 25 BOOL WINAPI RealMDIRedrawFrame(HWND,DWORD); 26 INT WINAPI RealSetScrollInfo(HWND,int,LPCSCROLLINFO,BOOL); 27 BOOL WINAPI RealSystemParametersInfoA(UINT,UINT,PVOID,UINT); 28 BOOL WINAPI RealSystemParametersInfoW(UINT,UINT,PVOID,UINT); 29 DWORD WINAPI GetRealWindowOwner(HWND); 30 BOOL WINAPI RealUserDrawCaption(HWND hWnd, HDC hDC, LPCRECT lpRc, UINT uFlags); 31 32 /* GLOBALS *******************************************************************/ 33 34 DWORD gcLoadUserApiHook = 0; 35 LONG gcCallUserApiHook = 0; 36 DWORD gfUserApiHook = 0; 37 HINSTANCE ghmodUserApiHook = NULL; 38 USERAPIHOOKPROC gpfnInitUserApi; 39 RTL_CRITICAL_SECTION gcsUserApiHook; 40 // API Hooked Message group bitmaps 41 BYTE grgbDwpLiteHookMsg[128]; 42 BYTE grgbWndLiteHookMsg[128]; 43 BYTE grgbDlgLiteHookMsg[128]; 44 45 /* INTERNAL ******************************************************************/ 46 47 /* 48 Pre and Post Message handler stub. 49 */ 50 LRESULT 51 WINAPI 52 DefaultOWP(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR lResult, PDWORD pData) 53 { 54 return 0; 55 } 56 57 /* 58 Check for API Hooked Message Overrides. Using message bitmapping.. One bit 59 corresponds to one message number. 60 */ 61 BOOL 62 FASTCALL 63 IsMsgOverride( UINT Msg, PUAHOWP puaowpOverride) 64 { 65 UINT nMsg = Msg / 8; // Group Indexed, (Msg 1024) / 8 = (0 -> 127) bytes Max 66 67 if ( puaowpOverride && nMsg < puaowpOverride->Size ) 68 { 69 return (puaowpOverride->MsgBitArray[nMsg] & (1 << (Msg & WM_SETFOCUS))); 70 } 71 return FALSE; 72 } 73 74 VOID 75 FASTCALL 76 CopyMsgMask(PUAHOWP Dest, PUAHOWP Src, PVOID hkmsg, DWORD Size) 77 { 78 DWORD nSize; 79 80 if ( Src && Src->Size > 0 ) 81 { 82 Dest->MsgBitArray = hkmsg; 83 nSize = Src->Size; 84 if ( Size < nSize) nSize = Size; 85 Dest->Size = nSize; 86 RtlCopyMemory(Dest->MsgBitArray, Src->MsgBitArray, nSize); 87 return; 88 } 89 90 Dest->MsgBitArray = NULL; 91 Dest->Size = 0; 92 return; 93 } 94 95 96 BOOL 97 FASTCALL 98 IsInsideUserApiHook(VOID) 99 { 100 if ( ghmodUserApiHook && gfUserApiHook ) return TRUE; 101 return FALSE; 102 } 103 104 BOOL 105 FASTCALL 106 BeginIfHookedUserApiHook(VOID) 107 { 108 InterlockedIncrement(&gcCallUserApiHook); 109 if (IsInsideUserApiHook()) return TRUE; 110 111 InterlockedDecrement(&gcCallUserApiHook); 112 return FALSE; 113 } 114 115 BOOL 116 WINAPI 117 ForceResetUserApiHook(HINSTANCE hInstance) 118 { 119 if ( ghmodUserApiHook == hInstance && 120 RtlIsThreadWithinLoaderCallout() ) 121 { 122 ResetUserApiHook(&guah); 123 gpfnInitUserApi = NULL; 124 return TRUE; 125 } 126 return FALSE; 127 } 128 129 VOID 130 FASTCALL 131 ResetUserApiHook(PUSERAPIHOOK puah) 132 { 133 // Setup Structure..... 134 puah->size = sizeof(USERAPIHOOK); 135 puah->DefWindowProcA = RealDefWindowProcA; 136 puah->DefWindowProcW = RealDefWindowProcW; 137 puah->DefWndProcArray.MsgBitArray = NULL; 138 puah->DefWndProcArray.Size = 0; 139 puah->GetScrollInfo = RealGetScrollInfo; 140 puah->SetScrollInfo = RealSetScrollInfo; 141 puah->EnableScrollBar = NtUserEnableScrollBar; 142 puah->AdjustWindowRectEx = RealAdjustWindowRectEx; 143 puah->SetWindowRgn = NtUserSetWindowRgn; 144 puah->PreWndProc = DefaultOWP; 145 puah->PostWndProc = DefaultOWP; 146 puah->WndProcArray.MsgBitArray = NULL; 147 puah->WndProcArray.Size = 0; 148 puah->PreDefDlgProc = DefaultOWP; 149 puah->PostDefDlgProc = DefaultOWP; 150 puah->DlgProcArray.MsgBitArray = NULL; 151 puah->DlgProcArray.Size = 0; 152 puah->GetSystemMetrics = RealGetSystemMetrics; 153 puah->SystemParametersInfoA = RealSystemParametersInfoA; 154 puah->SystemParametersInfoW = RealSystemParametersInfoW; 155 puah->ForceResetUserApiHook = ForceResetUserApiHook; 156 puah->DrawFrameControl = RealDrawFrameControl; 157 puah->DrawCaption = RealUserDrawCaption; 158 puah->MDIRedrawFrame = RealMDIRedrawFrame; 159 puah->GetRealWindowOwner = GetRealWindowOwner; 160 } 161 162 BOOL 163 FASTCALL 164 EndUserApiHook(VOID) 165 { 166 HMODULE hModule; 167 USERAPIHOOKPROC pfn; 168 BOOL Ret = FALSE; 169 170 if ( !InterlockedDecrement(&gcCallUserApiHook) ) 171 { 172 if ( !gcLoadUserApiHook ) 173 { 174 RtlEnterCriticalSection(&gcsUserApiHook); 175 176 pfn = gpfnInitUserApi; 177 hModule = ghmodUserApiHook; 178 ghmodUserApiHook = NULL; 179 gpfnInitUserApi = NULL; 180 181 RtlLeaveCriticalSection(&gcsUserApiHook); 182 183 if ( pfn ) Ret = pfn(uahStop, 0); 184 185 if ( hModule ) Ret = FreeLibrary(hModule); 186 } 187 } 188 return Ret; 189 } 190 191 BOOL 192 WINAPI 193 ClearUserApiHook(HINSTANCE hInstance) 194 { 195 HMODULE hModule; 196 USERAPIHOOKPROC pfn = NULL, pfn1 = NULL; 197 198 RtlEnterCriticalSection(&gcsUserApiHook); 199 hModule = ghmodUserApiHook; 200 if ( ghmodUserApiHook == hInstance ) 201 { 202 pfn1 = gpfnInitUserApi; 203 if ( --gcLoadUserApiHook == 0 ) 204 { 205 gfUserApiHook = 0; 206 ResetUserApiHook(&guah); 207 if ( gcCallUserApiHook ) 208 { 209 hInstance = NULL; 210 pfn1 = NULL; 211 pfn = gpfnInitUserApi; 212 gcLoadUserApiHook = 1; 213 } 214 else 215 { 216 hInstance = hModule; 217 ghmodUserApiHook = NULL; 218 gpfnInitUserApi = NULL; 219 } 220 } 221 } 222 RtlLeaveCriticalSection(&gcsUserApiHook); 223 224 if ( pfn ) 225 { 226 pfn(uahShutdown, 0); // Shutdown. 227 228 RtlEnterCriticalSection(&gcsUserApiHook); 229 pfn1 = gpfnInitUserApi; 230 231 if ( --gcLoadUserApiHook == 0 ) 232 { 233 if ( gcCallUserApiHook ) 234 { 235 hInstance = NULL; 236 pfn1 = NULL; 237 } 238 else 239 { 240 hInstance = ghmodUserApiHook; 241 ghmodUserApiHook = NULL; 242 gpfnInitUserApi = NULL; 243 } 244 } 245 RtlLeaveCriticalSection(&gcsUserApiHook); 246 } 247 248 if ( pfn1 ) pfn1(uahStop, 0); 249 250 return hInstance != 0; 251 } 252 253 BOOL 254 WINAPI 255 InitUserApiHook(HINSTANCE hInstance, USERAPIHOOKPROC pfn) 256 { 257 USERAPIHOOK uah; 258 259 ResetUserApiHook(&uah); 260 261 RtlEnterCriticalSection(&gcsUserApiHook); 262 263 if (!pfn(uahLoadInit,&uah) || // Swap data, User32 to and Uxtheme from! 264 uah.ForceResetUserApiHook != ForceResetUserApiHook || 265 uah.size <= 0 ) 266 { 267 RtlLeaveCriticalSection(&gcsUserApiHook); 268 return FALSE; 269 } 270 271 if ( ghmodUserApiHook ) 272 { 273 if ( ghmodUserApiHook != hInstance ) 274 { 275 RtlLeaveCriticalSection(&gcsUserApiHook); 276 pfn(uahStop, 0); 277 return FALSE; 278 } 279 gcLoadUserApiHook++; 280 } 281 else 282 { 283 ghmodUserApiHook = hInstance; 284 // Do not over write GetRealWindowOwner. 285 RtlCopyMemory(&guah, &uah, sizeof(USERAPIHOOK) - sizeof(LONG)); 286 gpfnInitUserApi = pfn; 287 gcLoadUserApiHook = 1; 288 gfUserApiHook = 1; 289 // Copy Message Masks 290 CopyMsgMask(&guah.DefWndProcArray, 291 &uah.DefWndProcArray, 292 &grgbDwpLiteHookMsg, 293 sizeof(grgbDwpLiteHookMsg)); 294 295 CopyMsgMask(&guah.WndProcArray, 296 &uah.WndProcArray, 297 &grgbWndLiteHookMsg, 298 sizeof(grgbWndLiteHookMsg)); 299 300 CopyMsgMask(&guah.DlgProcArray, 301 &uah.DlgProcArray, 302 &grgbDlgLiteHookMsg, 303 sizeof(grgbDlgLiteHookMsg)); 304 } 305 RtlLeaveCriticalSection(&gcsUserApiHook); 306 return TRUE; 307 } 308 309 BOOL 310 WINAPI 311 RealMDIRedrawFrame(HWND hWnd, DWORD flags) 312 { 313 return NtUserxMDIRedrawFrame(hWnd); 314 } 315 316 BOOL 317 WINAPI 318 MDIRedrawFrame(HWND hWnd, DWORD flags) 319 { 320 BOOL Hook, Ret = FALSE; 321 322 LoadUserApiHook(); 323 324 Hook = BeginIfHookedUserApiHook(); 325 326 /* Bypass SEH and go direct. */ 327 if (!Hook) return RealMDIRedrawFrame(hWnd, flags); 328 329 _SEH2_TRY 330 { 331 Ret = guah.MDIRedrawFrame(hWnd, flags); 332 } 333 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 334 { 335 ERR("Got exception in hooked MDIRedrawFrame!\n"); 336 } 337 _SEH2_END; 338 339 EndUserApiHook(); 340 341 return Ret; 342 } 343 344 USERAPIHOOK guah = 345 { 346 sizeof(USERAPIHOOK), 347 RealDefWindowProcA, 348 RealDefWindowProcW, 349 {NULL, 0}, 350 RealGetScrollInfo, 351 RealSetScrollInfo, 352 NtUserEnableScrollBar, 353 RealAdjustWindowRectEx, 354 NtUserSetWindowRgn, 355 DefaultOWP, 356 DefaultOWP, 357 {NULL, 0}, 358 DefaultOWP, 359 DefaultOWP, 360 {NULL, 0}, 361 RealGetSystemMetrics, 362 RealSystemParametersInfoA, 363 RealSystemParametersInfoW, 364 ForceResetUserApiHook, 365 RealDrawFrameControl, 366 NtUserDrawCaption, 367 RealMDIRedrawFrame, 368 GetRealWindowOwner, 369 }; 370 371 /* FUNCTIONS *****************************************************************/ 372 373 /* 374 * @implemented 375 */ 376 BOOL WINAPI RegisterUserApiHook(PUSERAPIHOOKINFO puah) 377 { 378 UNICODE_STRING m_dllname1; 379 UNICODE_STRING m_funname1; 380 381 if (puah->m_size == sizeof(USERAPIHOOKINFO)) 382 { 383 WARN("RegisterUserApiHook: %S and %S",puah->m_dllname1, puah->m_funname1); 384 RtlInitUnicodeString(&m_dllname1, puah->m_dllname1); 385 RtlInitUnicodeString(&m_funname1, puah->m_funname1); 386 return NtUserRegisterUserApiHook( &m_dllname1, &m_funname1, 0, 0); 387 } 388 return FALSE; 389 } 390 391 /* 392 * @implemented 393 */ 394 BOOL WINAPI UnregisterUserApiHook(VOID) 395 { 396 return NtUserUnregisterUserApiHook(); 397 } 398