mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 04:13:34 +00:00
Bug 1391 : Commit w3seek patch for Some Ansi vs. Unicode fixes for window classes
svn path=/trunk/; revision=21593
This commit is contained in:
@@ -1014,8 +1014,9 @@ CallWindowProcA(WNDPROC lpPrevWndFunc,
|
||||
{
|
||||
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))
|
||||
@@ -1042,6 +1043,10 @@ CallWindowProcW(WNDPROC lpPrevWndFunc,
|
||||
{
|
||||
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))
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ typedef struct _CALLPROC
|
||||
{
|
||||
struct _W32PROCESSINFO *pi;
|
||||
WNDPROC WndProc;
|
||||
BOOL Unicode : 1;
|
||||
UINT Unicode : 1;
|
||||
} CALLPROC, *PCALLPROC;
|
||||
|
||||
typedef struct _WINDOWCLASS
|
||||
@@ -46,10 +46,10 @@ typedef struct _WINDOWCLASS
|
||||
|
||||
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
|
||||
|
||||
@@ -37,6 +37,9 @@ typedef struct _WINDOW_OBJECT
|
||||
/* 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. */
|
||||
|
||||
@@ -89,7 +89,7 @@ CreateCallProc(IN PDESKTOP Desktop,
|
||||
{
|
||||
NewCallProc->pi = pi;
|
||||
NewCallProc->WndProc = WndProc;
|
||||
NewCallProc->Unicode = Unicode;
|
||||
NewCallProc->Unicode = Unicode != FALSE;
|
||||
}
|
||||
|
||||
return NewCallProc;
|
||||
@@ -109,13 +109,11 @@ UserGetCallProcInfo(IN HANDLE hCallProc,
|
||||
otCallProc);
|
||||
if (CallProc == NULL)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (CallProc->pi != GetW32ProcessInfo())
|
||||
{
|
||||
SetLastWin32Error(ERROR_ACCESS_DENIED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -322,12 +320,69 @@ IntSetClassAtom(IN OUT PWINDOWCLASS Class,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -336,6 +391,14 @@ IntSetClassWndProc(IN OUT PWINDOWCLASS Class,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Ret = IntGetClassWndProc(Class,
|
||||
GetW32ProcessInfo(),
|
||||
Ansi);
|
||||
if (Ret == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* update the base class first */
|
||||
Class = Class->Base;
|
||||
|
||||
@@ -733,61 +796,6 @@ IntFindClass(IN RTL_ATOM Atom,
|
||||
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 @@ UserGetClassInfo(IN PWINDOWCLASS Class,
|
||||
{
|
||||
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 @@ NtUserGetClassLong(IN HWND hWnd,
|
||||
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 @@ NtUserGetClassInfo(
|
||||
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)
|
||||
|
||||
@@ -380,7 +380,10 @@ NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo)
|
||||
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 @@ co_IntDoSendMessage(HWND hWnd,
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
@@ -440,6 +440,13 @@ static LRESULT co_UserFreeWindow(PWINDOW_OBJECT Window,
|
||||
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 */
|
||||
IntDereferenceClass(Window->Class,
|
||||
Window->ti->Desktop,
|
||||
@@ -1572,17 +1579,10 @@ co_IntCreateWindowEx(DWORD dwExStyle,
|
||||
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 @@ CLEANUP:
|
||||
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 @@ co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user