Dereference callproc handles without a system call

svn path=/trunk/; revision=30455
This commit is contained in:
Thomas Bluemel 2007-11-15 05:42:44 +00:00
parent 1392564c0d
commit bbf86d9a89
7 changed files with 133 additions and 60 deletions

View file

@ -45,8 +45,9 @@ LONG STDCALL GdiGetCharDimensions(HDC, LPTEXTMETRICW, LONG *);
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 @@ SharedPtrToUser(PVOID Ptr)
return (PVOID)((ULONG_PTR)Ptr - g_pi->UserHeapDelta);
}
static PVOID __inline
static __inline PVOID
DesktopPtrToUser(PVOID Ptr)
{
PW32THREADINFO ti = GetW32ThreadInfo();
@ -65,3 +66,13 @@ DesktopPtrToUser(PVOID Ptr)
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);

View file

@ -200,7 +200,12 @@ extern int SPY_Init(void);
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 @@ typedef struct _USER_HANDLE_TABLE
} 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);

View file

@ -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 @@ Init(VOID)
(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();

View file

@ -314,23 +314,23 @@ PUSER_HANDLE_ENTRY
FASTCALL
GetUser32Handle(HANDLE handle)
{
PUSER_HANDLE_TABLE ht = gHandleTable;
USHORT generation;
INT Index;
USHORT generation;
TRACE("Main Handle Table %x\n", ht);
Index = (((UINT)handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
INT Index = (((UINT)handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
if (Index < 0 || Index >= gHandleTable->nb_handles)
return NULL;
if (Index < 0 || Index >= ht->nb_handles) return NULL;
if (!gHandleEntries[Index].type || !gHandleEntries[Index].ptr)
return NULL;
if (!ht->handles[Index].type) return NULL;
generation = (UINT)handle >> 16;
generation = (UINT)handle >> 16;
if (generation == gHandleEntries[Index].generation || !generation || generation == 0xffff)
return &gHandleEntries[Index];
if (generation == ht->handles[Index].generation || !generation || generation == 0xffff)
return &ht->handles[Index];
return NULL;
return NULL;
}
/*
@ -345,8 +345,8 @@ static const BOOL g_ObjectHeapTypeShared[VALIDATE_TYPE_MONITOR + 1] =
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 @@ FASTCALL
ValidateHandle(HANDLE handle, UINT uType)
{
PVOID ret;
PUSER_HANDLE_ENTRY pEntry;
PW32CLIENTINFO ClientInfo = GetWin32ClientInfo();
ASSERT(uType <= VALIDATE_TYPE_MONITOR);
@ -372,13 +373,13 @@ ValidateHandle(HANDLE handle, UINT uType)
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!
@ -407,8 +408,6 @@ ValidateHandle(HANDLE handle, UINT uType)
return NULL;
}
if (!(NtUserValidateHandleSecure(handle, FALSE))) return NULL;
if (g_ObjectHeapTypeShared[uType])
ret = SharedPtrToUser(pEntry->ptr);
else
@ -427,3 +426,17 @@ ValidateHandle(HANDLE handle, UINT uType)
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;
}

View file

@ -1233,27 +1233,29 @@ CallWindowProcA(WNDPROC lpPrevWndFunc,
WPARAM wParam,
LPARAM lParam)
{
WNDPROC_INFO wpInfo;
PCALLPROC CallProc;
if (lpPrevWndFunc == NULL)
if (lpPrevWndFunc == NULL)
{
WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
return 0;
WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
return 0;
}
if (!IsCallProcHandle(lpPrevWndFunc))
return IntCallWindowProcA(TRUE, lpPrevWndFunc, hWnd, Msg, wParam, lParam);
else
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;
}
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 @@ CallWindowProcW(WNDPROC lpPrevWndFunc,
WPARAM wParam,
LPARAM lParam)
{
WNDPROC_INFO wpInfo;
PCALLPROC CallProc;
/* FIXME - can the first parameter be NULL? */
if (lpPrevWndFunc == NULL)
/* FIXME - can the first parameter be NULL? */
if (lpPrevWndFunc == NULL)
{
WARN("CallWindowProcA: lpPrevWndFunc == NULL!\n");
return 0;
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;
}
}
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;
}
}
}

View file

@ -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;

View file

@ -108,7 +108,7 @@ __inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY
ret = entry->ptr;
entry->ptr = ht->freelist;
entry->type = 0;
entry->pti = 0;
entry->pi = NULL;
ht->freelist = entry;
usedHandles--;
@ -116,6 +116,37 @@ __inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY
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 */
HANDLE UserAllocHandle(PUSER_HANDLE_TABLE ht, PVOID object, USER_OBJECT_TYPE type )
{
@ -124,8 +155,7 @@ HANDLE UserAllocHandle(PUSER_HANDLE_TABLE ht, PVOID object, USER_OBJECT_TYPE typ
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 );