win32k: minor window class fixes

- minor callproc handling bug
- correctly updating the menu name pointers when moving classes to the shared
heap
Patch by w3seek.

svn path=/trunk/; revision=21867
This commit is contained in:
Andrew Munger 2006-05-09 20:21:52 +00:00
parent 45cc9049ea
commit 4a37f88e19
3 changed files with 43 additions and 215 deletions

View file

@ -4,6 +4,13 @@
#define IS_ATOM(x) \
(((ULONG_PTR)(x) > 0x0) && ((ULONG_PTR)(x) < 0x10000))
static BOOL __inline
IsCallProcHandle(IN WNDPROC lpWndProc)
{
/* FIXME - check for 64 bit architectures... */
return ((ULONG_PTR)lpWndProc & 0xFFFF0000) == 0xFFFF0000;
}
WNDPROC
GetCallProcHandle(IN PCALLPROC CallProc);

View file

@ -55,11 +55,6 @@ IntDestroyClass(IN OUT PWINDOWCLASS Class)
ASSERT(Class->Windows == 0);
ASSERT(Class->Clone == NULL);
if (Class->Desktop != NULL)
{
ASSERT(Class->Clone == NULL);
}
if (Class->Base == Class)
{
/* destruct resources shared with clones */
@ -316,6 +311,19 @@ IntSetClassWndProc(IN OUT PWINDOWCLASS Class,
/* update the base class first */
Class = Class->Base;
/* resolve any callproc handle if possible */
if (IsCallProcHandle(WndProc))
{
WNDPROC_INFO wpInfo;
if (UserGetCallProcInfo((HANDLE)WndProc,
&wpInfo))
{
WndProc = wpInfo.WindowProc;
/* FIXME - what if wpInfo.IsUnicode doesn't match Ansi? */
}
}
Ret = IntGetClassWndProc(Class,
GetW32ProcessInfo(),
Ansi,
@ -649,6 +657,15 @@ IntMoveClassToSharedHeap(IN OUT PWINDOWCLASS Class,
NewClass->Desktop = NULL;
NewClass->Base = NewClass;
if (Class->MenuName == (PWSTR)(Class + 1))
{
ULONG_PTR AnsiDelta = (ULONG_PTR)Class->AnsiMenuName - (ULONG_PTR)Class->MenuName;
/* fixup the self-relative MenuName pointers */
NewClass->MenuName = (PWSTR)(NewClass + 1);
NewClass->AnsiMenuName = (PSTR)((ULONG_PTR)NewClass->MenuName + AnsiDelta);
}
if (!NewClass->System && NewClass->CallProc != NULL &&
!NewClass->GlobalCallProc)
{
@ -1088,206 +1105,6 @@ FoundClass:
return Atom;
}
static PWINDOWCLASS
IntClassResizeInternal(IN OUT PWINDOWCLASS Class,
IN INT ClsExtraNew,
IN PWINDOWCLASS *PrevLink)
{
PWINDOWCLASS NewClass;
SIZE_T NewSize;
/* NOTE: Do *not* access Class->Base here, it may be invalid at this point! */
/* temporarily unlink the class, as resizing it may change it's location */
(void)InterlockedExchangePointer(PrevLink,
Class->Next);
NewSize = (SIZE_T)ClsExtraNew + Class->ClassExtraDataOffset;
if (Class->Desktop != NULL)
{
NewClass = DesktopHeapReAlloc(Class->Desktop,
Class,
NewSize);
}
else
{
NewClass = UserHeapReAlloc(Class,
NewSize);
}
if (NewClass == NULL)
{
/* link in the class again */
(void)InterlockedExchangePointer(PrevLink,
Class);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
if (Class != NewClass)
{
/* adjust the menu name pointers, if neccessary */
if (NewClass->MenuName != NULL && !IS_INTRESOURCE(NewClass->MenuName) &&
NewClass->MenuName == (PWSTR)(NewClass + 1))
{
ULONG_PTR PtrDelta = (ULONG_PTR)NewClass - (ULONG_PTR)Class;
NewClass->MenuName = (PWSTR)((ULONG_PTR)NewClass->MenuName + PtrDelta);
NewClass->AnsiMenuName = (PSTR)((ULONG_PTR)NewClass->MenuName + PtrDelta);
}
Class = NewClass;
}
if (Class->ClsExtra < ClsExtraNew)
{
/* zero the memory allocated */
RtlZeroMemory((PVOID)((ULONG_PTR)Class + Class->ClassExtraDataOffset + Class->ClsExtra),
ClsExtraNew - Class->ClsExtra);
}
/* link in the class again */
(void)InterlockedExchangePointer(PrevLink,
Class);
return Class;
}
static BOOL
IntClassResize(IN OUT PWINDOWCLASS Class,
IN PW32PROCESSINFO pi,
IN INT ClsExtraNew)
{
PWINDOWCLASS *Link, NewClass, Clone, FailedResize = NULL;
BOOL FailOnResize;
if (pi == NULL)
return FALSE;
/* first modify the base class, then the clones */
Class = Class->Base;
if (ClsExtraNew < 0 ||
(ULONG_PTR)ClsExtraNew + Class->ClassExtraDataOffset < Class->ClassExtraDataOffset)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (Class->System)
Link = &pi->SystemClassList;
else if (Class->Global)
Link = &pi->GlobalClassList;
else
Link = &pi->LocalClassList;
FailOnResize = Class->ClsExtra < ClsExtraNew;
/* resize the base class */
NewClass = IntClassResizeInternal(Class,
ClsExtraNew,
Link);
if (NewClass == NULL)
{
if (FailOnResize)
{
DPRINT1("Failed to resize the base class\n");
return FALSE;
}
}
else
Class = NewClass;
/* resize the clones */
Link = &Class->Clone;
Clone = Class->Clone;
while (Clone != NULL)
{
NewClass = IntClassResizeInternal(Clone,
ClsExtraNew,
Link);
if (NewClass == NULL)
{
if (FailOnResize)
{
/* roll back all changes */
FailedResize = Clone;
break;
}
}
else
Clone = NewClass;
/* save the pointer to the base class in case it changed */
Clone->Base = Class;
Link = &Clone->Next;
Clone = Clone->Next;
}
if (FailedResize != NULL)
{
/* failed to resize one clone, roll back the changes to all
other clones and to the base class */
DPRINT1("Failed to resize the cloned class 0x%p\n", FailedResize);
if (Class->System)
Link = &pi->SystemClassList;
else if (Class->Global)
Link = &pi->GlobalClassList;
else
Link = &pi->LocalClassList;
/* roll back the changes made to the base class */
NewClass = IntClassResizeInternal(Class,
Class->ClsExtra,
Link);
if (NewClass != NULL)
Class = NewClass;
/* roll back all changes made to the class clones */
Link = &Class->Clone;
Clone = Class->Clone;
while (Clone != FailedResize)
{
ASSERT(Clone != NULL);
NewClass = IntClassResizeInternal(Clone,
Class->ClsExtra,
Link);
if (NewClass != NULL)
Clone = NewClass;
/* save the pointer to the base class in case it changed */
Clone->Base = Class;
Link = &Clone->Next;
Clone = Clone->Next;
}
return FALSE;
}
else
{
/* all classes were successfully resized,
save the new extra data size */
Class->ClsExtra = ClsExtraNew;
Clone = Class->Clone;
while (Clone != NULL)
{
Clone->ClsExtra = ClsExtraNew;
ASSERT(Clone->Base == Class);
Clone = Clone->Next;
}
return TRUE;
}
}
RTL_ATOM
UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
IN PUNICODE_STRING ClassName,
@ -1807,16 +1624,7 @@ UserSetClassLongPtr(IN PWINDOWCLASS Class,
break;
case GCL_CBCLSEXTRA:
Ret = (ULONG_PTR)Class->ClsExtra;
if (Class->ClsExtra != (INT)NewLong)
{
if (!IntClassResize(Class,
GetW32ProcessInfo(),
(INT)NewLong))
{
Ret = 0;
}
}
SetLastWin32Error(ERROR_INVALID_PARAMETER);
break;
case GCLP_HBRBACKGROUND:

View file

@ -3431,6 +3431,19 @@ IntSetWindowProc(PWINDOW_OBJECT Window,
{
WNDPROC Ret;
/* resolve any callproc handle if possible */
if (IsCallProcHandle(NewWndProc))
{
WNDPROC_INFO wpInfo;
if (UserGetCallProcInfo((HANDLE)NewWndProc,
&wpInfo))
{
NewWndProc = wpInfo.WindowProc;
/* FIXME - what if wpInfo.IsUnicode doesn't match Ansi? */
}
}
/* attempt to get the previous window proc */
if (Window->IsSystem)
{