Author: weiden Date: Thu Nov 15 08:42:44 2007 New Revision: 30455
URL: http://svn.reactos.org/svn/reactos?rev=30455&view=rev Log: Dereference callproc handles without a system call
Modified: trunk/reactos/dll/win32/user32/include/user32.h trunk/reactos/dll/win32/user32/include/user32p.h trunk/reactos/dll/win32/user32/misc/dllmain.c trunk/reactos/dll/win32/user32/misc/misc.c trunk/reactos/dll/win32/user32/windows/message.c trunk/reactos/subsystems/win32/win32k/include/object.h trunk/reactos/subsystems/win32/win32k/ntuser/object.c
Modified: trunk/reactos/dll/win32/user32/include/user32.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/include/us... ============================================================================== --- trunk/reactos/dll/win32/user32/include/user32.h (original) +++ trunk/reactos/dll/win32/user32/include/user32.h Thu Nov 15 08:42:44 2007 @@ -45,8 +45,9 @@ BOOL FASTCALL IsMetaFile(HDC);
extern PW32PROCESSINFO g_pi; +extern PW32PROCESSINFO g_kpi;
-static PVOID __inline +static __inline PVOID SharedPtrToUser(PVOID Ptr) { ASSERT(Ptr != NULL); @@ -55,7 +56,7 @@ return (PVOID)((ULONG_PTR)Ptr - g_pi->UserHeapDelta); }
-static PVOID __inline +static __inline PVOID DesktopPtrToUser(PVOID Ptr) { PW32THREADINFO ti = GetW32ThreadInfo(); @@ -65,3 +66,13 @@ return (PVOID)((ULONG_PTR)Ptr - ti->DesktopHeapDelta); }
+static __inline PVOID +SharedPtrToKernel(PVOID Ptr) +{ + ASSERT(Ptr != NULL); + ASSERT(g_pi != NULL); + ASSERT(g_pi->UserHeapDelta != 0); + return (PVOID)((ULONG_PTR)Ptr + g_pi->UserHeapDelta); +} + +PCALLPROC FASTCALL ValidateCallProc(HANDLE hCallProc);
Modified: trunk/reactos/dll/win32/user32/include/user32p.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/include/us... ============================================================================== --- trunk/reactos/dll/win32/user32/include/user32p.h (original) +++ trunk/reactos/dll/win32/user32/include/user32p.h Thu Nov 15 08:42:44 2007 @@ -200,7 +200,12 @@ typedef struct _USER_HANDLE_ENTRY { void *ptr; /* pointer to object */ - PW32THREADINFO pti; // pointer to Win32ThreadInfo + union + { + PVOID pi; + PW32THREADINFO pti; // pointer to Win32ThreadInfo + PW32PROCESSINFO ppi; // pointer to W32ProcessInfo + }; unsigned short type; /* object type (0 if free) */ unsigned short generation; /* generation counter */ } USER_HANDLE_ENTRY, * PUSER_HANDLE_ENTRY; @@ -214,6 +219,7 @@ } USER_HANDLE_TABLE, * PUSER_HANDLE_TABLE;
extern PUSER_HANDLE_TABLE gHandleTable; +extern PUSER_HANDLE_ENTRY gHandleEntries;
PUSER_HANDLE_ENTRY FASTCALL GetUser32Handle(HANDLE); PVOID FASTCALL ValidateHandle(HANDLE, UINT);
Modified: trunk/reactos/dll/win32/user32/misc/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/misc/dllma... ============================================================================== --- trunk/reactos/dll/win32/user32/misc/dllmain.c (original) +++ trunk/reactos/dll/win32/user32/misc/dllmain.c Thu Nov 15 08:42:44 2007 @@ -5,7 +5,9 @@ static ULONG User32TlsIndex; HINSTANCE User32Instance; PUSER_HANDLE_TABLE gHandleTable = NULL; -PW32PROCESSINFO g_pi = NULL; +PUSER_HANDLE_ENTRY gHandleEntries = NULL; +PW32PROCESSINFO g_pi = NULL; /* User Mode Pointer */ +PW32PROCESSINFO g_kpi = NULL; /* Kernel Mode Pointer */
PW32PROCESSINFO GetW32ProcessInfo(VOID); @@ -56,7 +58,9 @@ (PVOID)User32CallHookProcFromKernel;
g_pi = GetW32ProcessInfo(); + g_kpi = SharedPtrToKernel(g_pi); gHandleTable = SharedPtrToUser(g_pi->UserHandleTable); + gHandleEntries = SharedPtrToUser(gHandleTable->handles);
/* Allocate an index for user32 thread local data. */ User32TlsIndex = TlsAlloc();
Modified: trunk/reactos/dll/win32/user32/misc/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/misc/misc.... ============================================================================== --- trunk/reactos/dll/win32/user32/misc/misc.c (original) +++ trunk/reactos/dll/win32/user32/misc/misc.c Thu Nov 15 08:42:44 2007 @@ -314,23 +314,23 @@ FASTCALL GetUser32Handle(HANDLE handle) { - PUSER_HANDLE_TABLE ht = gHandleTable; - USHORT generation; - - TRACE("Main Handle Table %x\n", ht); - - INT Index = (((UINT)handle & 0xffff) - FIRST_USER_HANDLE) >> 1; - - if (Index < 0 || Index >= ht->nb_handles) return NULL; - - if (!ht->handles[Index].type) return NULL; - - generation = (UINT)handle >> 16; - - if (generation == ht->handles[Index].generation || !generation || generation == 0xffff) - return &ht->handles[Index]; - - return NULL; + INT Index; + USHORT generation; + + Index = (((UINT)handle & 0xffff) - FIRST_USER_HANDLE) >> 1; + + if (Index < 0 || Index >= gHandleTable->nb_handles) + return NULL; + + if (!gHandleEntries[Index].type || !gHandleEntries[Index].ptr) + return NULL; + + generation = (UINT)handle >> 16; + + if (generation == gHandleEntries[Index].generation || !generation || generation == 0xffff) + return &gHandleEntries[Index]; + + return NULL; }
/* @@ -345,8 +345,8 @@ TRUE, /* VALIDATE_TYPE_MWPOS */ TRUE, /* VALIDATE_TYPE_HOOK */ FALSE, /* (not used) */ - FALSE, /* VALIDATE_TYPE_CALLPROC */ - FALSE, /* VALIDATE_TYPE_ACCEL */ + TRUE, /* VALIDATE_TYPE_CALLPROC */ + TRUE, /* VALIDATE_TYPE_ACCEL */ FALSE, /* (not used) */ FALSE, /* (not used) */ FALSE, /* (not used) */ @@ -361,6 +361,7 @@ ValidateHandle(HANDLE handle, UINT uType) { PVOID ret; + PUSER_HANDLE_ENTRY pEntry; PW32CLIENTINFO ClientInfo = GetWin32ClientInfo();
ASSERT(uType <= VALIDATE_TYPE_MONITOR); @@ -372,13 +373,13 @@ if (handle == ClientInfo->hWND) return ClientInfo->pvWND; }
- PUSER_HANDLE_ENTRY pEntry = GetUser32Handle(handle); + pEntry = GetUser32Handle(handle);
if (pEntry && uType == 0) uType = pEntry->type;
// Must have an entry and must be the same type! - if ( (!pEntry) || (pEntry->type != uType) ) + if ( (!pEntry) || (pEntry->type != uType) || !pEntry->ptr ) { switch ( uType ) { // Test (with wine too) confirms these results! @@ -406,8 +407,6 @@ } return NULL; } - - if (!(NtUserValidateHandleSecure(handle, FALSE))) return NULL;
if (g_ObjectHeapTypeShared[uType]) ret = SharedPtrToUser(pEntry->ptr); @@ -427,3 +426,17 @@
return ret; } + +// +// Validate callproc handle and return the pointer to the object. +// +PCALLPROC +FASTCALL +ValidateCallProc(HANDLE hCallProc) +{ + PCALLPROC CallProc = ValidateHandle(hCallProc, VALIDATE_TYPE_CALLPROC); + if (CallProc != NULL && CallProc->pi == g_kpi) + return CallProc; + + return NULL; +}
Modified: trunk/reactos/dll/win32/user32/windows/message.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/me... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/message.c (original) +++ trunk/reactos/dll/win32/user32/windows/message.c Thu Nov 15 08:42:44 2007 @@ -1233,27 +1233,29 @@ WPARAM wParam, LPARAM lParam) { - WNDPROC_INFO wpInfo; - - if (lpPrevWndFunc == NULL) - { - WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n"); - return 0; - } - - if (!IsCallProcHandle(lpPrevWndFunc)) - return IntCallWindowProcA(TRUE, lpPrevWndFunc, hWnd, Msg, wParam, lParam); - else - { - if (NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc, - &wpInfo)) - return IntCallWindowProcA(!wpInfo.IsUnicode, wpInfo.WindowProc, - hWnd, Msg, wParam, lParam); - else - { - WARN("CallWindowProcA: can not dereference WndProcHandle\n"); - return 0; - } + PCALLPROC CallProc; + + if (lpPrevWndFunc == NULL) + { + WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n"); + return 0; + } + + if (!IsCallProcHandle(lpPrevWndFunc)) + return IntCallWindowProcA(TRUE, lpPrevWndFunc, hWnd, Msg, wParam, lParam); + else + { + CallProc = ValidateCallProc((HANDLE)lpPrevWndFunc); + if (CallProc != NULL) + { + return IntCallWindowProcA(!CallProc->Unicode, CallProc->WndProc, + hWnd, Msg, wParam, lParam); + } + else + { + WARN("CallWindowProcA: can not dereference WndProcHandle\n"); + return 0; + } } }
@@ -1268,29 +1270,31 @@ WPARAM wParam, LPARAM lParam) { - WNDPROC_INFO wpInfo; - - /* FIXME - can the first parameter be NULL? */ - if (lpPrevWndFunc == NULL) - { - WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n"); - return 0; - } - - if (!IsCallProcHandle(lpPrevWndFunc)) - return IntCallWindowProcW(FALSE, lpPrevWndFunc, hWnd, Msg, wParam, lParam); - else - { - if (NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc, - &wpInfo)) - return IntCallWindowProcW(!wpInfo.IsUnicode, wpInfo.WindowProc, - hWnd, Msg, wParam, lParam); - else - { - WARN("CallWindowProcW: can not dereference WndProcHandle\n"); - return 0; - } - } + PCALLPROC CallProc; + + /* FIXME - can the first parameter be NULL? */ + if (lpPrevWndFunc == NULL) + { + WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n"); + return 0; + } + + if (!IsCallProcHandle(lpPrevWndFunc)) + return IntCallWindowProcW(FALSE, lpPrevWndFunc, hWnd, Msg, wParam, lParam); + else + { + CallProc = ValidateCallProc((HANDLE)lpPrevWndFunc); + if (CallProc != NULL) + { + return IntCallWindowProcW(!CallProc->Unicode, CallProc->WndProc, + hWnd, Msg, wParam, lParam); + } + else + { + WARN("CallWindowProcW: can not dereference WndProcHandle\n"); + return 0; + } + } }
Modified: trunk/reactos/subsystems/win32/win32k/include/object.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/object.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/object.h Thu Nov 15 08:42:44 2007 @@ -20,7 +20,12 @@ typedef struct _USER_HANDLE_ENTRY { void *ptr; /* pointer to object */ - PW32THREADINFO pti; // pointer to Win32ThreadInfo + union + { + PVOID pi; + PW32THREADINFO pti; // pointer to Win32ThreadInfo + PW32PROCESSINFO ppi; // pointer to W32ProcessInfo + }; unsigned short type; /* object type (0 if free) */ unsigned short generation; /* generation counter */ } USER_HANDLE_ENTRY, * PUSER_HANDLE_ENTRY;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/object.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/object.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/object.c Thu Nov 15 08:42:44 2007 @@ -108,12 +108,43 @@ ret = entry->ptr; entry->ptr = ht->freelist; entry->type = 0; - entry->pti = 0; + entry->pi = NULL; ht->freelist = entry;
usedHandles--;
return ret; +} + +static __inline PVOID +UserHandleOwnerByType(USER_OBJECT_TYPE type) +{ + PVOID pi; + + switch (type) + { + case otWindow: + pi = GetW32ThreadInfo(); + break; + + case otMenu: + case otCursorIcon: + case otHook: + case otCallProc: + case otAccel: + pi = GetW32ProcessInfo(); + break; + + case otMonitor: + pi = NULL; /* System */ + break; + + default: + pi = NULL; + break; + } + + return pi; }
/* allocate a user handle for a given object */ @@ -124,8 +155,7 @@ return 0; entry->ptr = object; entry->type = type; - entry->pti = GetW32ThreadInfo(); - if (entry->pti->pi->UserHandleTable == NULL) GetW32ProcessInfo(); + entry->pi = UserHandleOwnerByType(type); if (++entry->generation >= 0xffff) entry->generation = 1; return entry_to_handle(ht, entry );