Author: greatlrd Date: Fri Apr 14 22:23:11 2006 New Revision: 21593
URL: http://svn.reactos.ru/svn/reactos?rev=21593&view=rev Log: Bug 1391 : Commit w3seek patch for Some Ansi vs. Unicode fixes for window classes
Removed: trunk/reactos/subsystems/win32/win32k/include/ssec.h Modified: trunk/reactos/dll/win32/user32/windows/message.c trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/subsystems/win32/win32k/include/window.h trunk/reactos/subsystems/win32/win32k/ntuser/class.c trunk/reactos/subsystems/win32/win32k/ntuser/message.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c
Modified: trunk/reactos/dll/win32/user32/windows/message.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/user32/windows/mes... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/message.c (original) +++ trunk/reactos/dll/win32/user32/windows/message.c Fri Apr 14 22:23:11 2006 @@ -1014,8 +1014,9 @@ { WNDPROC_INFO wpInfo;
+ /* FIXME - can the first parameter be NULL? */ if (lpPrevWndFunc == NULL) - lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWLP_WNDPROC, FALSE); + lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWLP_WNDPROC, TRUE);
if (!NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc, &wpInfo)) @@ -1041,6 +1042,10 @@ LPARAM lParam) { WNDPROC_INFO wpInfo; + + /* FIXME - can the first parameter be NULL? */ + if (lpPrevWndFunc == NULL) + lpPrevWndFunc = (WNDPROC)NtUserGetWindowLong(hWnd, GWLP_WNDPROC, FALSE);
if (!NtUserDereferenceWndProcHandle((HANDLE)lpPrevWndFunc, &wpInfo))
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/include/reactos/win32k/ntuse... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h Fri Apr 14 22:23:11 2006 @@ -14,7 +14,7 @@ { struct _W32PROCESSINFO *pi; WNDPROC WndProc; - BOOL Unicode : 1; + UINT Unicode : 1; } CALLPROC, *PCALLPROC;
typedef struct _WINDOWCLASS @@ -46,10 +46,10 @@
ULONG_PTR ClassExtraDataOffset;
- BOOL Destroying : 1; - BOOL Unicode : 1; - BOOL System : 1; - BOOL Global : 1; + UINT Destroying : 1; + UINT Unicode : 1; + UINT System : 1; + UINT Global : 1; } WINDOWCLASS, *PWINDOWCLASS;
typedef struct _W32PROCESSINFO
Removed: trunk/reactos/subsystems/win32/win32k/include/ssec.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/incl... ============================================================================== (empty)
Modified: trunk/reactos/subsystems/win32/win32k/include/window.h URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/incl... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/window.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/window.h Fri Apr 14 22:23:11 2006 @@ -37,6 +37,9 @@ /* Extra Wnd proc (windows of system classes) */ WNDPROC WndProcExtra; }; + /* Pointer to another call procedure handle (used for returning the previous + window proc in SetWindowLongPtr) */ + PCALLPROC CallProc2; /* Indicates whether the window is derived from a system class */ BOOL IsSystem; /* Pointer to the window class. */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/class.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/class.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/class.c Fri Apr 14 22:23:11 2006 @@ -89,7 +89,7 @@ { NewCallProc->pi = pi; NewCallProc->WndProc = WndProc; - NewCallProc->Unicode = Unicode; + NewCallProc->Unicode = Unicode != FALSE; }
return NewCallProc; @@ -109,13 +109,11 @@ otCallProc); if (CallProc == NULL) { - SetLastWin32Error(ERROR_INVALID_HANDLE); return FALSE; }
if (CallProc->pi != GetW32ProcessInfo()) { - SetLastWin32Error(ERROR_ACCESS_DENIED); return FALSE; }
@@ -323,16 +321,81 @@ }
static WNDPROC +IntGetClassWndProc(IN PWINDOWCLASS Class, + IN PW32PROCESSINFO pi, + IN BOOL Ansi) +{ + /* FIXME - assert for exclusive lock! */ + + if (Class->System) + { + return (Ansi ? Class->WndProcExtra : Class->WndProc); + } + else + { + if (!Ansi == Class->Unicode) + { + return Class->WndProc; + } + else + { + if (Class->CallProc != NULL) + { + return (WNDPROC)ObmObjectToHandle(Class->CallProc); + } + else + { + PCALLPROC NewCallProc, CallProc; + + if (pi == NULL) + return NULL; + + /* NOTE: use the interlocked functions, as this operation may be done even + when only the shared lock is held! */ + NewCallProc = CreateCallProc(Class->Desktop, + Class->WndProc, + Class->Unicode, + pi); + if (NewCallProc == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + CallProc = InterlockedCompareExchangePointer(&Class->CallProc, + NewCallProc, + NULL); + if (CallProc != NULL) + { + DestroyCallProc(Class->Desktop, + NewCallProc); + } + + return (WNDPROC)ObmObjectToHandle((CallProc == NULL ? NewCallProc : CallProc)); + } + } + } +} + +static WNDPROC IntSetClassWndProc(IN OUT PWINDOWCLASS Class, IN WNDPROC WndProc, IN BOOL Ansi) { - WNDPROC Ret = Class->WndProc; + WNDPROC Ret;
if (Class->System) { DPRINT1("Attempted to change window procedure of system window class 0x%p!\n", Class->Atom); SetLastWin32Error(ERROR_ACCESS_DENIED); + return NULL; + } + + Ret = IntGetClassWndProc(Class, + GetW32ProcessInfo(), + Ansi); + if (Ret == NULL) + { return NULL; }
@@ -733,61 +796,6 @@ return Class; }
-static WNDPROC -IntGetClassWndProc(IN PWINDOWCLASS Class, - IN PW32PROCESSINFO pi, - IN BOOL Ansi) -{ - if (Class->System) - { - return (Ansi ? Class->WndProcExtra : Class->WndProc); - } - else - { - if (!Ansi == Class->Unicode) - { - return Class->WndProc; - } - else - { - if (Class->CallProc != NULL) - { - return (WNDPROC)ObmObjectToHandle(Class->CallProc); - } - else - { - PCALLPROC NewCallProc, CallProc; - - if (pi == NULL) - return NULL; - - /* NOTE: use the interlocked functions, as this operation may be done even - when only the shared lock is held! */ - NewCallProc = CreateCallProc(Class->Desktop, - Class->WndProc, - Class->Unicode, - pi); - if (NewCallProc == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return NULL; - } - - CallProc = InterlockedCompareExchangePointer(&Class->CallProc, - NewCallProc, - NULL); - if (CallProc != NULL) - { - DestroyCallProc(Class->Desktop, - NewCallProc); - } - - return (WNDPROC)ObmObjectToHandle((CallProc == NULL ? NewCallProc : CallProc)); - } - } - } -} - RTL_ATOM IntGetClassAtom(IN PUNICODE_STRING ClassName, IN HINSTANCE hInstance OPTIONAL, @@ -1760,22 +1768,9 @@ { lpwcx->style = Class->Style;
- if (Class->System) - { - lpwcx->lpfnWndProc = (!Ansi ? Class->WndProc : Class->WndProcExtra); - } - else - { - if (!Ansi == Class->Unicode) - { - lpwcx->lpfnWndProc = Class->WndProc; - } - else - { - /* FIXME - return callproc handle or function pointer? */ - lpwcx->lpfnWndProc = Class->CallProc->WndProc; - } - } + lpwcx->lpfnWndProc = IntGetClassWndProc(Class, + GetW32ProcessInfo(), + Ansi);
lpwcx->cbClsExtra = Class->ClsExtra; lpwcx->cbWndExtra = Class->WndExtra; @@ -1917,7 +1912,14 @@ PWINDOW_OBJECT Window; ULONG_PTR Ret = 0;
- UserEnterShared(); + if (Offset != GCLP_WNDPROC) + { + UserEnterShared(); + } + else + { + UserEnterExclusive(); + }
Window = UserGetWindowObject(hWnd); if (Window != NULL) @@ -2090,7 +2092,9 @@ PW32PROCESSINFO pi; BOOL Ret = FALSE;
- UserEnterShared(); + /* NOTE: need exclusive lock because getting the wndproc might require the + creation of a call procedure handle */ + UserEnterExclusive();
pi = GetW32ProcessInfo(); if (pi == NULL)
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/message.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c Fri Apr 14 22:23:11 2006 @@ -380,7 +380,10 @@ Result = 0;
MsgInfo.Ansi = !Window->Unicode; - MsgInfo.Proc = Window->WndProc; + if (Window->IsSystem) + MsgInfo.Proc = (Window->Unicode ? Window->WndProc : Window->WndProcExtra); + else + MsgInfo.Proc = Window->WndProc; } } } @@ -1563,7 +1566,10 @@ }
Info.Ansi = !Window->Unicode; - Info.Proc = Window->WndProc; + if (Window->IsSystem) + Info.Proc = (Window->Unicode ? Window->WndProc : Window->WndProcExtra); + else + Info.Proc = Window->WndProc; } else {
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntus... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c Fri Apr 14 22:23:11 2006 @@ -438,6 +438,13 @@ { DestroyCallProc(Window->ti->Desktop, Window->CallProc); + } + + if (Window->CallProc2 != NULL) + { + DbgPrint("!!!!! Destroy call proc 0x%p\n", ObmObjectToHandle(Window->CallProc2)); + DestroyCallProc(Window->ti->Desktop, + Window->CallProc2); }
/* dereference the class */ @@ -1572,17 +1579,10 @@ Window->IsSystem = Class->System; if (Class->System) { - Window->Unicode = bUnicodeWindow; - if (bUnicodeWindow) - { - Window->WndProc = Class->WndProc; - Window->WndProcExtra = Class->WndProcExtra; - } - else - { - Window->WndProc = Class->WndProcExtra; - Window->WndProcExtra = Class->WndProc; - } + /* NOTE: Always create a unicode window for system classes! */ + Window->Unicode = TRUE; + Window->WndProc = Class->WndProc; + Window->WndProcExtra = Class->WndProcExtra; } else { @@ -3422,7 +3422,93 @@ END_CLEANUP; }
- +static WNDPROC +IntSetWindowProc(PWINDOW_OBJECT Window, + WNDPROC NewWndProc, + BOOL Ansi) +{ + WNDPROC Ret; + + /* attempt to get the previous window proc */ + if (Window->IsSystem) + { + Ret = (Ansi ? Window->WndProcExtra : Window->WndProc); + } + else + { + if (!Ansi == Window->Unicode) + { + Ret = Window->WndProc; + } + else + { + /* allocate or update an existing call procedure handle to return + the old window proc */ + if (Window->CallProc2 != NULL) + { + Window->CallProc2->WndProc = Window->WndProc; + Window->CallProc2->Unicode = Window->Unicode; + } + else + { + Window->CallProc2 = CreateCallProc(Window->ti->Desktop, + Window->WndProc, + Window->Unicode, + Window->ti->kpi); + if (Window->CallProc2 == NULL) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + } + + Ret = (WNDPROC)ObmObjectToHandle(Window->CallProc2); + DbgPrint("!!!!!!!! Returning handle 0x%p\n", Ret); + } + } + + if (Window->Class->System) + { + BOOL SysWnd = Window->IsSystem; + + /* check if the new procedure matches with the one in the + window class. If so, we need to restore both procedures! */ + Window->IsSystem = (NewWndProc == Window->Class->WndProc || + NewWndProc == Window->Class->WndProcExtra); + + if (Window->IsSystem != SysWnd) + { + if (!Window->IsSystem && Window->CallProc != NULL) + { + /* destroy the callproc, we don't need it anymore */ + DestroyCallProc(Window->ti->Desktop, + Window->CallProc); + Window->CallProc = NULL; + } + } + + if (Window->IsSystem) + { + Window->WndProc = Window->Class->WndProc; + Window->WndProcExtra = Window->Class->WndProcExtra; + Window->Unicode = !Ansi; + return Ret; + } + } + + ASSERT(!Window->IsSystem); + + /* update the window procedure */ + Window->WndProc = NewWndProc; + if (Window->CallProc != NULL) + { + Window->CallProc->WndProc = NewWndProc; + Window->CallProc->Unicode = !Ansi; + } + Window->Unicode = !Ansi; + + return Ret; +}
LONG FASTCALL @@ -3490,24 +3576,9 @@ case GWL_WNDPROC: { /* FIXME: should check if window belongs to current process */ - if (Window->IsSystem) - { - /* the user changes the window procedure, the window is no longer - directly derived from the system class, because it no longer - uses independent window procedures for ansi and unicode */ - Window->IsSystem = FALSE; - Window->CallProc = NULL; - } - - /* update the window procedure */ - OldValue = (LONG)Window->WndProc; - Window->WndProc = (WNDPROC)NewValue; - if (Window->CallProc != NULL) - { - Window->CallProc->WndProc = (WNDPROC)NewValue; - Window->CallProc->Unicode = !Ansi; - } - Window->Unicode = !Ansi; + OldValue = (LONG)IntSetWindowProc(Window, + (WNDPROC)NewValue, + Ansi); break; }