-/*
- * ReactOS W32 Subsystem
- * Copyright (C) 1998 - 2006 ReactOS Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window classes
- * FILE: subsys/win32k/ntuser/class.c
+ * FILE: subsystems/win32/win32k/ntuser/class.c
* PROGRAMER: Thomas Weidenmueller <w3seek@reactos.com>
* REVISION HISTORY:
* 06-06-2001 CSH Created
#define WARN DPRINT1
#define ERR DPRINT1
+REGISTER_SYSCLASS DefaultServerClasses[] =
+{
+/* { ((PWSTR)((ULONG_PTR)(WORD)(0x8001))),
+ CS_GLOBALCLASS|CS_DBLCLKS,
+ NULL,
+ 0,
+ IDC_ARROW,
+ (HBRUSH)(COLOR_BACKGROUND+1),
+ FNID_DESKTOP,
+ ICLS_DESKTOP
+ },*/
+ { ((PWSTR)((ULONG_PTR)(WORD)(0x8003))),
+ CS_VREDRAW|CS_HREDRAW|CS_SAVEBITS,
+ NULL, // Use User32 procs
+ sizeof(LONG),
+ IDC_ARROW,
+ NULL,
+ FNID_SWITCH,
+ ICLS_SWITCH
+ },
+ { ((PWSTR)((ULONG_PTR)(WORD)(0x8000))),
+ CS_DBLCLKS|CS_SAVEBITS,
+ NULL, // Use User32 procs
+ sizeof(LONG),
+ IDC_ARROW,
+ (HBRUSH)(COLOR_MENU + 1),
+ FNID_MENU,
+ ICLS_MENU
+ },
+ { L"ScrollBar",
+ CS_DBLCLKS|CS_VREDRAW|CS_HREDRAW|CS_PARENTDC,
+ NULL, // Use User32 procs
+ 0,
+ IDC_ARROW,
+ NULL,
+ FNID_SCROLLBAR,
+ ICLS_SCROLLBAR
+ },
+ { ((PWSTR)((ULONG_PTR)(WORD)(0x8004))), // IconTitle is here for now...
+ 0,
+ NULL, // Use User32 procs
+ 0,
+ IDC_ARROW,
+ 0,
+ FNID_ICONTITLE,
+ ICLS_ICONTITLE
+ },
+ { L"Message",
+ CS_GLOBALCLASS,
+ NULL, // Use User32 procs
+ 0,
+ IDC_ARROW,
+ NULL,
+ FNID_MESSAGEWND,
+ ICLS_HWNDMESSAGE
+ }
+};
+
static struct
{
int FnId;
int ClsId;
} FnidToiCls[] =
-{
- { FNID_BUTTON, ICLS_BUTTON},
- { FNID_EDIT, ICLS_EDIT},
- { FNID_STATIC, ICLS_STATIC},
- { FNID_LISTBOX, ICLS_LISTBOX},
- { FNID_SCROLLBAR, ICLS_SCROLLBAR},
- { FNID_COMBOBOX, ICLS_COMBOBOX},
- { FNID_MDICLIENT, ICLS_MDICLIENT},
- { FNID_COMBOLBOX, ICLS_COMBOLBOX},
- { FNID_DIALOG, ICLS_DIALOG},
- { FNID_MENU, ICLS_MENU},
- { FNID_ICONTITLE, ICLS_ICONTITLE}
+{ /* Function Ids to Class indexes. */
+ { FNID_SCROLLBAR, ICLS_SCROLLBAR},
+ { FNID_ICONTITLE, ICLS_ICONTITLE},
+ { FNID_MENU, ICLS_MENU},
+ { FNID_DESKTOP, ICLS_DESKTOP},
+ { FNID_SWITCH, ICLS_SWITCH},
+ { FNID_MESSAGEWND, ICLS_HWNDMESSAGE},
+ { FNID_BUTTON, ICLS_BUTTON},
+ { FNID_COMBOBOX, ICLS_COMBOBOX},
+ { FNID_COMBOLBOX, ICLS_COMBOLBOX},
+ { FNID_DIALOG, ICLS_DIALOG},
+ { FNID_EDIT, ICLS_EDIT},
+ { FNID_LISTBOX, ICLS_LISTBOX},
+ { FNID_MDICLIENT, ICLS_MDICLIENT},
+ { FNID_STATIC, ICLS_STATIC},
+ { FNID_IME, ICLS_IME},
+ { FNID_GHOST, ICLS_GHOST},
+ { FNID_TOOLTIPS, ICLS_TOOLTIPS}
};
-static
BOOL
FASTCALL
-LockupFnIdToiCls(int FnId, int *iCls )
+LookupFnIdToiCls(int FnId, int *iCls )
{
int i;
- for ( i = 0; i < (sizeof(FnidToiCls)/2)/sizeof(int); i++)
+ for ( i = 0; i < ARRAYSIZE(FnidToiCls); i++)
{
if (FnidToiCls[i].FnId == FnId)
{
- *iCls = FnidToiCls[i].ClsId;
+ if (iCls) *iCls = FnidToiCls[i].ClsId;
return TRUE;
}
}
+ if (iCls) *iCls = 0;
return FALSE;
}
IntFreeClassMenuName(IN OUT PCLS Class)
{
/* free the menu name, if it was changed and allocated */
- if (Class->MenuName != NULL && Class->MenuNameIsString)
+ if (Class->lpszClientUnicodeMenuName != NULL && Class->MenuNameIsString)
{
- UserHeapFree(Class->MenuName);
- Class->MenuName = NULL;
- Class->AnsiMenuName = NULL;
+ UserHeapFree(Class->lpszClientUnicodeMenuName);
+ Class->lpszClientUnicodeMenuName = NULL;
+ Class->lpszClientAnsiMenuName = NULL;
}
}
static VOID
IntDestroyClass(IN OUT PCLS Class)
{
+ PDESKTOP pDesk;
/* there shouldn't be any clones anymore */
ASSERT(Class->cWndReferenceCount == 0);
ASSERT(Class->pclsClone == NULL);
if (Class->pclsBase == Class)
{
- PCALLPROC CallProc, NextCallProc;
+ PCALLPROCDATA CallProc, NextCallProc;
/* Destroy allocated callproc handles */
CallProc = Class->spcpdFirst;
while (CallProc != NULL)
{
- NextCallProc = CallProc->Next;
+ NextCallProc = CallProc->spcpdNext;
- CallProc->Next = NULL;
+ CallProc->spcpdNext = NULL;
DestroyCallProc(NULL,
CallProc);
IntFreeClassMenuName(Class);
}
+ pDesk = Class->rpdeskParent;
+ Class->rpdeskParent = NULL;
+
/* free the structure */
- if (Class->rpdeskParent != NULL)
+ if (pDesk != NULL)
{
- DesktopHeapFree(Class->rpdeskParent,
- Class);
+ DesktopHeapFree(pDesk, Class);
}
else
{
/* clean all process classes. all process windows must cleaned first!! */
-void FASTCALL DestroyProcessClasses(PW32PROCESS Process )
+void FASTCALL DestroyProcessClasses(PPROCESSINFO Process )
{
PCLS Class;
PPROCESSINFO pi = (PPROCESSINFO)Process;
-
+
if (pi != NULL)
{
/* free all local classes */
- Class = pi->LocalClassList;
+ Class = pi->pclsPrivateList;
while (Class != NULL)
{
- pi->LocalClassList = Class->pclsNext;
+ pi->pclsPrivateList = Class->pclsNext;
ASSERT(Class->pclsBase == Class);
IntDestroyClass(Class);
- Class = pi->LocalClassList;
+ Class = pi->pclsPrivateList;
}
/* free all global classes */
- Class = pi->GlobalClassList;
+ Class = pi->pclsPublicList;
while (Class != NULL)
{
- pi->GlobalClassList = Class->pclsNext;
+ pi->pclsPublicList = Class->pclsNext;
ASSERT(Class->pclsBase == Class);
IntDestroyClass(Class);
- Class = pi->GlobalClassList;
- }
-
- /* free all system classes */
- Class = pi->SystemClassList;
- while (Class != NULL)
- {
- pi->SystemClassList = Class->pclsNext;
-
- ASSERT(Class->pclsBase == Class);
- IntDestroyClass(Class);
-
- Class = pi->SystemClassList;
+ Class = pi->pclsPublicList;
}
}
}
else
AtomName = ClassName->Buffer;
- /* If an Atom, need to verify, if it was already added to the global atom list. */
- if (IS_ATOM(AtomName))
- {
- *pAtom = (RTL_ATOM)((ULONG_PTR)AtomName);
- Status = RtlQueryAtomInAtomTable( gAtomTable,
- *pAtom,
- NULL,
- NULL,
- NULL,
- NULL);
-
- if (NT_SUCCESS(Status)) return TRUE;
- }
-
Status = RtlAddAtomToAtomTable(gAtomTable,
AtomName,
pAtom);
Atom);
}
-PCALLPROC
-UserFindCallProc(IN PCLS Class,
- IN WNDPROC WndProc,
- IN BOOL bUnicode)
-{
- PCALLPROC CallProc;
-
- CallProc = Class->spcpdFirst;
- while (CallProc != NULL)
- {
- if (CallProc->WndProc == WndProc &&
- CallProc->Unicode == (UINT)bUnicode)
- {
- return CallProc;
- }
-
- CallProc = CallProc->Next;
- }
-
- return NULL;
-}
-
VOID
UserAddCallProcToClass(IN OUT PCLS Class,
- IN PCALLPROC CallProc)
+ IN PCALLPROCDATA CallProc)
{
PCLS BaseClass;
- ASSERT(CallProc->Next == NULL);
+ ASSERT(CallProc->spcpdNext == NULL);
BaseClass = Class->pclsBase;
- ASSERT(CallProc->Next == NULL);
- CallProc->Next = BaseClass->spcpdFirst;
+ ASSERT(CallProc->spcpdNext == NULL);
+ CallProc->spcpdNext = BaseClass->spcpdFirst;
BaseClass->spcpdFirst = CallProc;
/* Update all clones */
return TRUE;
}
-static WNDPROC
-IntGetClassWndProc(IN PCLS Class,
- IN PPROCESSINFO pi,
- IN BOOL Ansi)
+//
+// Same as User32:IntGetClsWndProc.
+//
+WNDPROC FASTCALL
+IntGetClassWndProc(PCLS Class, BOOL Ansi)
{
- ASSERT(UserIsEnteredExclusive() == TRUE);
-
- if (Class->System)
- {
- return (Ansi ? Class->WndProcExtra : Class->lpfnWndProc);
- }
- else
- {
- if (!Ansi == Class->Unicode)
- {
- return Class->lpfnWndProc;
- }
- else
- {
- PCLS BaseClass;
-
- /* make sure the call procedures are located on the desktop
- of the base class! */
- BaseClass = Class->pclsBase;
- Class = BaseClass;
+ INT i;
+ WNDPROC gcpd = NULL, Ret = NULL;
- if (Class->CallProc != NULL)
- {
- return GetCallProcHandle(Class->CallProc);
- }
+ if (Class->CSF_flags & CSF_SERVERSIDEPROC)
+ {
+ for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
+ {
+ if (GETPFNSERVER(i) == Class->lpfnWndProc)
+ {
+ if (Ansi)
+ Ret = GETPFNCLIENTA(i);
else
- {
- PCALLPROC NewCallProc;
-
- if (pi == NULL)
- return NULL;
-
- NewCallProc = UserFindCallProc(Class,
- Class->lpfnWndProc,
- Class->Unicode);
- if (NewCallProc == NULL)
- {
- NewCallProc = CreateCallProc(NULL,
- Class->lpfnWndProc,
- Class->Unicode,
- pi);
- if (NewCallProc == NULL)
- {
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- return NULL;
- }
-
- UserAddCallProcToClass(Class,
- NewCallProc);
- }
+ Ret = GETPFNCLIENTW(i);
+ }
+ }
+ return Ret;
+ }
+ Ret = Class->lpfnWndProc;
- Class->CallProc = NewCallProc;
+ if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
+ {
+ if (Ansi)
+ {
+ if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
+ Ret = GETPFNCLIENTA(Class->fnid);
+ }
+ else
+ {
+ if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
+ Ret = GETPFNCLIENTW(Class->fnid);
+ }
+ }
- /* update the clones */
- Class = Class->pclsClone;
- while (Class != NULL)
- {
- Class->CallProc = NewCallProc;
+ if ( Ret != Class->lpfnWndProc ||
+ Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
+ return Ret;
- Class = Class->pclsNext;
- }
+ gcpd = (WNDPROC)UserGetCPD( Class,
+ (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDClass,
+ (ULONG_PTR)Ret);
- return GetCallProcHandle(NewCallProc);
- }
- }
- }
+ return (gcpd ? gcpd : Ret);
}
-static WNDPROC
+
+static
+WNDPROC FASTCALL
IntSetClassWndProc(IN OUT PCLS Class,
IN WNDPROC WndProc,
IN BOOL Ansi)
{
- WNDPROC Ret;
-
- if (Class->System)
- {
- DPRINT1("Attempted to change window procedure of system window class 0x%p!\n", Class->atomClassName);
- SetLastWin32Error(ERROR_ACCESS_DENIED);
- return NULL;
- }
-
- /* update the base class first */
- Class = Class->pclsBase;
-
- /* 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);
- if (Ret == NULL)
- {
- return NULL;
- }
-
- /* update the class info */
- Class->Unicode = !Ansi;
- Class->lpfnWndProc = WndProc;
-
- /* update the clones */
- Class = Class->pclsClone;
- while (Class != NULL)
- {
- Class->Unicode = !Ansi;
- Class->lpfnWndProc = WndProc;
-
- Class = Class->pclsNext;
- }
-
- return Ret;
+ INT i;
+ PCALLPROCDATA pcpd;
+ WNDPROC Ret, chWndProc;
+
+ Ret = IntGetClassWndProc(Class, Ansi);
+
+ // If Server Side, downgrade to Client Side.
+ if (Class->CSF_flags & CSF_SERVERSIDEPROC)
+ {
+ if (Ansi) Class->CSF_flags |= CSF_ANSIPROC;
+ Class->CSF_flags &= ~CSF_SERVERSIDEPROC;
+ Class->Unicode = !Ansi;
+ }
+
+ if (!WndProc) WndProc = Class->lpfnWndProc;
+
+ chWndProc = WndProc;
+
+ // Check if CallProc handle and retrieve previous call proc address and set.
+ if (IsCallProcHandle(WndProc))
+ {
+ pcpd = UserGetObject(gHandleTable, WndProc, otCallProc);
+ if (pcpd) chWndProc = pcpd->pfnClientPrevious;
+ }
+
+ Class->lpfnWndProc = chWndProc;
+
+ // Clear test proc.
+ chWndProc = NULL;
+
+ // Switch from Client Side call to Server Side call if match. Ref: "deftest".
+ for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
+ {
+ if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
+ {
+ chWndProc = GETPFNSERVER(i);
+ break;
+ }
+ if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
+ {
+ chWndProc = GETPFNSERVER(i);
+ break;
+ }
+ }
+ // If match, set/reset to Server Side and clear ansi.
+ if (chWndProc)
+ {
+ Class->lpfnWndProc = chWndProc;
+ Class->Unicode = TRUE;
+ Class->CSF_flags &= ~CSF_ANSIPROC;
+ Class->CSF_flags |= CSF_SERVERSIDEPROC;
+ }
+ else
+ {
+ Class->Unicode = !Ansi;
+
+ if (Ansi)
+ Class->CSF_flags |= CSF_ANSIPROC;
+ else
+ Class->CSF_flags &= ~CSF_ANSIPROC;
+ }
+
+ /* update the clones */
+ chWndProc = Class->lpfnWndProc;
+
+ Class = Class->pclsClone;
+ while (Class != NULL)
+ {
+ Class->Unicode = !Ansi;
+ Class->lpfnWndProc = chWndProc;
+
+ Class = Class->pclsNext;
+ }
+
+ return Ret;
}
static PCLS
if (Class != NULL)
{
/* simply clone the class */
- RtlCopyMemory(Class,
- BaseClass,
- ClassSize);
+ RtlCopyMemory( Class, BaseClass, ClassSize);
+
+ DPRINT("Clone Class 0x%x hM 0x%x\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName);
+
+ /* restore module address if default user class Ref: Bug 4778 */
+ if ( Class->hModule != hModClient &&
+ Class->fnid <= FNID_GHOST &&
+ Class->fnid >= FNID_BUTTON )
+ {
+ Class->hModule = hModClient;
+ DPRINT("Clone Class 0x%x Reset hM 0x%x\n",Class, Class->hModule);
+ }
/* update some pointers and link the class */
Class->rpdeskParent = Desktop;
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
}
}
-
return Class;
}
IN PDESKTOP Desktop)
{
PCLS Class;
-
ASSERT(BaseClass->pclsBase == BaseClass);
Class = IntGetClassForDesktop(BaseClass,
return Class;
}
-static VOID
+static
+VOID
IntMakeCloneBaseClass(IN OUT PCLS Class,
IN OUT PCLS *BaseClassLink,
IN OUT PCLS *CloneLink)
ASSERT(Clone->pclsClone == NULL);
Clone->pclsBase = Class;
- if (!Class->System)
- Clone->CallProc = Class->CallProc;
-
Clone = Clone->pclsNext;
}
Class);
}
+
VOID
IntDereferenceClass(IN OUT PCLS Class,
IN PDESKTOPINFO Desktop,
BaseClass = Class->pclsBase;
- if (--Class->cWndReferenceCount == 0)
+ if (--Class->cWndReferenceCount <= 0)
{
if (BaseClass == Class)
{
ASSERT(Class->pclsBase == Class);
+ DPRINT("IntDereferenceClass 0x%x\n", Class);
/* check if there are clones of the class on other desktops,
link the first clone in if possible. If there are no clones
then leave the class on the desktop heap. It will get moved
to the shared heap when the thread detaches. */
if (BaseClass->pclsClone != NULL)
{
- if (BaseClass->System)
- PrevLink = &pi->SystemClassList;
- else if (BaseClass->Global)
- PrevLink = &pi->GlobalClassList;
+ if (BaseClass->Global)
+ PrevLink = &pi->pclsPublicList;
else
- PrevLink = &pi->LocalClassList;
+ PrevLink = &pi->pclsPrivateList;
CurrentClass = *PrevLink;
while (CurrentClass != BaseClass)
}
else
{
+ DPRINT("IntDereferenceClass1 0x%x\n", Class);
+
/* locate the cloned class and unlink it */
PrevLink = &BaseClass->pclsClone;
CurrentClass = BaseClass->pclsClone;
BOOL Ret = TRUE;
pi = GetW32ProcessInfo();
- if (pi == NULL)
- return TRUE;
/* check all local classes */
IntCheckDesktopClasses(Desktop,
- &pi->LocalClassList,
+ &pi->pclsPrivateList,
FreeOnFailure,
&Ret);
/* check all global classes */
IntCheckDesktopClasses(Desktop,
- &pi->GlobalClassList,
- FreeOnFailure,
- &Ret);
-
- /* check all system classes */
- IntCheckDesktopClasses(Desktop,
- &pi->SystemClassList,
+ &pi->pclsPublicList,
FreeOnFailure,
&Ret);
-
if (!Ret)
{
DPRINT1("Failed to move process classes from desktop 0x%p to the shared heap!\n", Desktop);
IntCreateClass(IN CONST WNDCLASSEXW* lpwcx,
IN PUNICODE_STRING ClassName,
IN PUNICODE_STRING MenuName,
- IN WNDPROC wpExtra,
+ IN DWORD fnID,
IN DWORD dwFlags,
IN PDESKTOP Desktop,
IN PPROCESSINFO pi)
SIZE_T ClassSize;
PCLS Class = NULL;
RTL_ATOM Atom;
+ WNDPROC WndProc;
PWSTR pszMenuName = NULL;
NTSTATUS Status = STATUS_SUCCESS;
- TRACE("lpwcx=%p ClassName=%wZ MenuName=%wZ wpExtra=%p dwFlags=%08x Desktop=%p pi=%p\n",
- lpwcx, ClassName, MenuName, wpExtra, dwFlags, Desktop, pi);
+ DPRINT("lpwcx=%p ClassName=%wZ MenuName=%wZ dwFlags=%08x Desktop=%p pi=%p\n",
+ lpwcx, ClassName, MenuName, dwFlags, Desktop, pi);
if (!IntRegisterClassAtom(ClassName,
&Atom))
if (Class != NULL)
{
- RtlZeroMemory(Class,
- ClassSize);
+ int iCls = 0;
+
+ RtlZeroMemory(Class, ClassSize);
Class->rpdeskParent = Desktop;
Class->pclsBase = Class;
Class->atomClassName = Atom;
+ Class->fnid = fnID;
+ Class->CSF_flags = dwFlags;
- if (dwFlags & CSF_SYSTEMCLASS)
+ if (LookupFnIdToiCls(Class->fnid, &iCls))
{
- dwFlags &= ~CSF_ANSIPROC;
- Class->WndProcExtra = wpExtra;
- Class->System = TRUE;
+ gpsi->atomSysClass[iCls] = Class->atomClassName;
}
_SEH2_TRY
/* need to protect with SEH since accessing the WNDCLASSEX structure
and string buffers might raise an exception! We don't want to
leak memory... */
+ // What?! If the user interface was written correctly this would not be an issue!
Class->lpfnWndProc = lpwcx->lpfnWndProc;
Class->style = lpwcx->style;
Class->cbclsExtra = lpwcx->cbClsExtra;
{
Class->MenuNameIsString = TRUE;
- Class->MenuName = pszMenuNameBuffer;
- RtlCopyMemory(Class->MenuName,
+ Class->lpszClientUnicodeMenuName = pszMenuNameBuffer;
+ RtlCopyMemory(Class->lpszClientUnicodeMenuName,
MenuName->Buffer,
MenuName->Length);
- Class->MenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
+ Class->lpszClientUnicodeMenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1;
}
else
- Class->MenuName = MenuName->Buffer;
+ Class->lpszClientUnicodeMenuName = MenuName->Buffer;
/* save an ansi copy of the string */
if (pszMenuNameBuffer != NULL)
{
ANSI_STRING AnsiString;
- Class->AnsiMenuName = (PSTR)pszMenuNameBuffer;
+ Class->lpszClientAnsiMenuName = (PSTR)pszMenuNameBuffer;
AnsiString.MaximumLength = RtlUnicodeStringToAnsiSize(MenuName);
- AnsiString.Buffer = Class->AnsiMenuName;
+ AnsiString.Buffer = Class->lpszClientAnsiMenuName;
Status = RtlUnicodeStringToAnsiString(&AnsiString,
MenuName,
FALSE);
}
}
else
- Class->AnsiMenuName = (PSTR)MenuName->Buffer;
+ Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
+
+ /* Save kernel use menu name and ansi class name */
+ Class->lpszMenuName = Class->lpszClientUnicodeMenuName; // Fixme!
+ //Class->lpszAnsiClassName = Fixme!
- if (!(dwFlags & CSF_ANSIPROC))
+ /* Server Side overrides class calling type (A/W)!
+ User32 whine test_builtinproc: "deftest"
+ built-in winproc - window A/W type automatically detected */
+ if (!(Class->CSF_flags & CSF_SERVERSIDEPROC))
+ {
+ int i;
+ WndProc = NULL;
+ /* Due to the wine class "deftest" and most likely no FNID to reference
+ from, sort through the Server Side list and compare proc addresses
+ for match. This method will be used in related code.
+ */
+ for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
+ { // Open Ansi or Unicode, just match, set and break.
+ if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
+ {
+ WndProc = GETPFNSERVER(i);
+ break;
+ }
+ if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
+ {
+ WndProc = GETPFNSERVER(i);
+ break;
+ }
+ }
+ if (WndProc)
+ { // If a hit, we are Server Side so set the right flags and proc.
+ Class->CSF_flags |= CSF_SERVERSIDEPROC;
+ Class->CSF_flags &= ~CSF_ANSIPROC;
+ Class->lpfnWndProc = WndProc;
+ }
+ }
+
+ if (!(Class->CSF_flags & CSF_ANSIPROC))
Class->Unicode = TRUE;
if (Class->style & CS_GLOBALCLASS)
{
if (Class->atomClassName == Atom &&
(hInstance == NULL || Class->hModule == hInstance) &&
- !Class->Destroying)
+ !(Class->CSF_flags & CSF_WOWDEFERDESTROY))
{
ASSERT(Class->pclsBase == Class);
{
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
- SetLastWin32Error(ERROR_CANNOT_FIND_WND_CLASS);
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
}
else
{
/* Step 1: try to find an exact match of locally registered classes */
Class = IntFindClass(Atom,
hInstance,
- &pi->LocalClassList,
+ &pi->pclsPrivateList,
Link);
if (Class != NULL)
- {
+ { DPRINT("Step 1: 0x%x\n",Class );
goto FoundClass;
}
is not relevant for global classes */
Class = IntFindClass(Atom,
NULL,
- &pi->GlobalClassList,
+ &pi->pclsPublicList,
Link);
if (Class != NULL)
- {
+ { DPRINT("Step 2: 0x%x 0x%x\n",Class, Class->hModule);
goto FoundClass;
}
/* Step 3: try to find any local class registered by user32 */
Class = IntFindClass(Atom,
- pi->hModUser,
- &pi->LocalClassList,
+ hModClient,
+ &pi->pclsPrivateList,
Link);
if (Class != NULL)
- {
+ { DPRINT("Step 3: 0x%x\n",Class );
goto FoundClass;
}
/* Step 4: try to find any global class registered by user32 */
Class = IntFindClass(Atom,
- pi->hModUser,
- &pi->GlobalClassList,
- Link);
- if (Class != NULL)
- {
- goto FoundClass;
- }
-
- /* Step 5: try to find a system class */
- Class = IntFindClass(Atom,
- NULL,
- &pi->SystemClassList,
+ hModClient,
+ &pi->pclsPublicList,
Link);
if (Class == NULL)
{
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
return (RTL_ATOM)0;
- }
+ }else{DPRINT("Step 4: 0x%x\n",Class );}
FoundClass:
*BaseClass = Class;
UserRegisterClass(IN CONST WNDCLASSEXW* lpwcx,
IN PUNICODE_STRING ClassName,
IN PUNICODE_STRING MenuName,
- IN WNDPROC wpExtra,
+ IN DWORD fnID,
IN DWORD dwFlags)
{
PTHREADINFO pti;
- PW32THREADINFO ti;
PPROCESSINFO pi;
PCLS Class;
RTL_ATOM ClassAtom;
/* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */
- pti = PsGetCurrentThreadWin32Thread();
- ti = GetW32ThreadInfo();
- if (ti == NULL || !ti->ppi->RegisteredSysClasses)
- {
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- return (RTL_ATOM)0;
- }
-
- pi = ti->ppi;
-
- /* try to find a previously registered class */
- ClassAtom = IntGetClassAtom(ClassName,
- lpwcx->hInstance,
- pi,
- &Class,
+ pti = GetW32ThreadInfo();
+
+ pi = pti->ppi;
+
+ // Need only to test for two conditions not four....... Fix more whine tests....
+ if ( IntGetAtomFromStringOrAtom( ClassName, &ClassAtom) &&
+ ClassAtom != (RTL_ATOM)0 &&
+ !(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass Server Sides
+ {
+ Class = IntFindClass( ClassAtom,
+ lpwcx->hInstance,
+ &pi->pclsPrivateList,
+ NULL);
+
+ if (Class != NULL && !Class->Global)
+ {
+ // local class already exists
+ DPRINT("Local Class 0x%p does already exist!\n", ClassAtom);
+ SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
+ return (RTL_ATOM)0;
+ }
+
+ if (lpwcx->style & CS_GLOBALCLASS)
+ {
+ Class = IntFindClass( ClassAtom,
+ NULL,
+ &pi->pclsPublicList,
NULL);
- if (ClassAtom != (RTL_ATOM)0)
- {
- if (lpwcx->style & CS_GLOBALCLASS)
- {
- // global classes shall not have same names as system classes
- if (Class->Global || Class->System)
- {
- DPRINT("Class 0x%p does already exist!\n", ClassAtom);
- SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
- return (RTL_ATOM)0;
- }
- }
- else if ( !Class->Global && !Class->System)
- {
- // local class already exists
- DPRINT("Class 0x%p does already exist!\n", ClassAtom);
- SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
- return (RTL_ATOM)0;
- }
+
+ if (Class != NULL && Class->Global)
+ {
+ DPRINT("Global Class 0x%p does already exist!\n", ClassAtom);
+ SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
+ return (RTL_ATOM)0;
+ }
+ }
}
Class = IntCreateClass(lpwcx,
ClassName,
MenuName,
- wpExtra,
+ fnID,
dwFlags,
pti->Desktop,
pi);
PCLS *List;
/* Register the class */
- if (Class->System)
- List = &pi->SystemClassList;
- else if (Class->Global)
- List = &pi->GlobalClassList;
+ if (Class->Global)
+ List = &pi->pclsPublicList;
else
- List = &pi->LocalClassList;
+ List = &pi->pclsPrivateList;
Class->pclsNext = *List;
(void)InterlockedExchangePointer((PVOID*)List,
Ret = Class->atomClassName;
}
+ else
+ {
+ DPRINT1("UserRegisterClass: Yes, that is right, you have no Class!\n");
+ }
return Ret;
}
BOOL
UserUnregisterClass(IN PUNICODE_STRING ClassName,
- IN HINSTANCE hInstance)
+ IN HINSTANCE hInstance,
+ OUT PCLSMENUNAME pClassMenuName)
{
PCLS *Link;
PPROCESSINFO pi;
PCLS Class;
pi = GetW32ProcessInfo();
- if (pi == NULL)
- {
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
- TRACE("UserUnregisterClass(%wZ)\n", ClassName);
+ DPRINT("UserUnregisterClass(%wZ, 0x%x)\n", ClassName, hInstance);
/* NOTE: Accessing the buffer in ClassName may raise an exception! */
ClassAtom = IntGetClassAtom(ClassName,
&Link);
if (ClassAtom == (RTL_ATOM)0)
{
+ DPRINT("UserUnregisterClass: No Class found.\n");
return FALSE;
}
if (Class->cWndReferenceCount != 0 ||
Class->pclsClone != NULL)
{
+ DPRINT("UserUnregisterClass: Class has a Window. Ct %d : Clone 0x%x\n", Class->cWndReferenceCount, Class->pclsClone);
SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
return FALSE;
}
if (NT_SUCCESS(IntDeregisterClassAtom(Class->atomClassName)))
{
+ DPRINT("Class 0x%x\n", Class);
+ DPRINT("UserUnregisterClass: Good Exit!\n");
/* finally free the resources */
IntDestroyClass(Class);
return TRUE;
}
- return FALSE;
+ DPRINT1("UserUnregisterClass: Can not deregister Class Atom.\n");
+ return FALSE;
}
INT
case GCLP_MENUNAME:
/* NOTE: Returns pointer in kernel heap! */
if (Ansi)
- Ret = (ULONG_PTR)Class->AnsiMenuName;
+ Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName;
else
- Ret = (ULONG_PTR)Class->MenuName;
+ Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName;
break;
case GCL_STYLE:
break;
case GCLP_WNDPROC:
- Ret = (ULONG_PTR)IntGetClassWndProc(Class,
- GetW32ProcessInfo(),
- Ansi);
+ Ret = (ULONG_PTR)IntGetClassWndProc(Class, Ansi);
break;
case GCW_ATOM:
{
/* update the base class */
IntFreeClassMenuName(Class);
- Class->MenuName = strBufW;
- Class->AnsiMenuName = AnsiString.Buffer;
+ Class->lpszClientUnicodeMenuName = strBufW;
+ Class->lpszClientAnsiMenuName = AnsiString.Buffer;
Class->MenuNameIsString = TRUE;
/* update the clones */
Class = Class->pclsClone;
while (Class != NULL)
{
- Class->MenuName = strBufW;
- Class->AnsiMenuName = AnsiString.Buffer;
+ Class->lpszClientUnicodeMenuName = strBufW;
+ Class->lpszClientAnsiMenuName = AnsiString.Buffer;
Class->MenuNameIsString = TRUE;
Class = Class->pclsNext;
/* update the base class */
IntFreeClassMenuName(Class);
- Class->MenuName = MenuName->Buffer;
- Class->AnsiMenuName = (PSTR)MenuName->Buffer;
+ Class->lpszClientUnicodeMenuName = MenuName->Buffer;
+ Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
Class->MenuNameIsString = FALSE;
/* update the clones */
Class = Class->pclsClone;
while (Class != NULL)
{
- Class->MenuName = MenuName->Buffer;
- Class->AnsiMenuName = (PSTR)MenuName->Buffer;
+ Class->lpszClientUnicodeMenuName = MenuName->Buffer;
+ Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
Class->MenuNameIsString = FALSE;
Class = Class->pclsNext;
if (!IntSetClassMenuName(Class,
Value))
{
- DPRINT("Setting the class menu name failed!\n");
+ DPRINT1("Setting the class menu name failed!\n");
}
/* FIXME - really return NULL? Wine does so... */
{
PPROCESSINFO pi;
+ if (!Class) return FALSE;
+
lpwcx->style = Class->style;
+ // If fnId is set, clear the global bit. See wine class test check_style.
+ if (Class->fnid)
+ lpwcx->style &= ~CS_GLOBALCLASS;
+
pi = GetW32ProcessInfo();
- lpwcx->lpfnWndProc = IntGetClassWndProc(Class,
- pi,
- Ansi);
+ lpwcx->lpfnWndProc = IntGetClassWndProc(Class, Ansi);
+
lpwcx->cbClsExtra = Class->cbclsExtra;
lpwcx->cbWndExtra = Class->cbwndExtra;
lpwcx->hIcon = Class->hIcon; /* FIXME - get handle from pointer */
lpwcx->hCursor = Class->hCursor; /* FIXME - get handle from pointer */
lpwcx->hbrBackground = Class->hbrBackground;
+ /* Copy non-string to user first. */
if (Ansi)
- ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->AnsiMenuName;
+ ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName;
else
- lpwcx->lpszMenuName = Class->MenuName;
+ lpwcx->lpszMenuName = Class->lpszClientUnicodeMenuName;
+/*
+ FIXME! CLSMENUNAME has the answers! Copy the already made buffers from there!
+ Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space.
+ lpszClientXxxMenuName should already be mapped to user space.
+ */
+ /* Copy string ptr to user. */
+ if ( Class->lpszClientUnicodeMenuName != NULL &&
+ Class->MenuNameIsString)
+ {
+ lpwcx->lpszMenuName = UserHeapAddressToUser(Ansi ?
+ (PVOID)Class->lpszClientAnsiMenuName :
+ (PVOID)Class->lpszClientUnicodeMenuName);
+ }
- if (Class->hModule == pi->hModUser)
+ if (hInstance == hModClient)
lpwcx->hInstance = NULL;
else
- lpwcx->hInstance = Class->hModule;
+ lpwcx->hInstance = hInstance;
- lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName); /* FIXME - return the string? */
+ /* FIXME - return the string? Okay! This is performed in User32!*/
+ //lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName);
lpwcx->hIconSm = Class->hIconSm; /* FIXME - get handle from pointer */
return TRUE;
}
+//
+//
+//
BOOL
-UserRegisterSystemClasses(IN ULONG Count,
- IN PREGISTER_SYSCLASS SystemClasses)
+FASTCALL
+UserRegisterSystemClasses(VOID)
{
- /* NOTE: This routine may raise exceptions! */
UINT i;
UNICODE_STRING ClassName, MenuName;
- PPROCESSINFO pi = GetW32ProcessInfo();
+ PPROCESSINFO ppi = GetW32ProcessInfo();
WNDCLASSEXW wc;
PCLS Class;
BOOL Ret = TRUE;
+ DWORD Flags = 0;
- if (pi->RegisteredSysClasses || pi->hModUser == NULL)
- return FALSE;
+ if (ppi->W32PF_flags & W32PF_CLASSESREGISTERED)
+ return TRUE;
+
+ if ( hModClient == NULL)
+ return FALSE;
+ RtlZeroMemory(&ClassName, sizeof(ClassName));
RtlZeroMemory(&MenuName, sizeof(MenuName));
- for (i = 0; i != Count; i++)
+ for (i = 0; i != ARRAYSIZE(DefaultServerClasses); i++)
{
- ClassName = ProbeForReadUnicodeString(&SystemClasses[i].ClassName);
- if (ClassName.Length != 0)
+ if (!IS_ATOM(DefaultServerClasses[i].ClassName))
{
- ProbeForRead(ClassName.Buffer,
- ClassName.Length,
- sizeof(WCHAR));
+ RtlInitUnicodeString(&ClassName, DefaultServerClasses[i].ClassName);
}
-
+ else
+ {
+ ClassName.Buffer = DefaultServerClasses[i].ClassName;
+ ClassName.Length = 0;
+ ClassName.MaximumLength = 0;
+ }
+
wc.cbSize = sizeof(wc);
- wc.style = SystemClasses[i].Style;
- wc.lpfnWndProc = SystemClasses[i].ProcW;
+ wc.style = DefaultServerClasses[i].Style;
+
+ Flags |= CSF_SERVERSIDEPROC;
+
+ if (DefaultServerClasses[i].ProcW)
+ {
+ wc.lpfnWndProc = DefaultServerClasses[i].ProcW;
+ wc.hInstance = hModuleWin;
+ }
+ else
+ {
+ wc.lpfnWndProc = GETPFNSERVER(DefaultServerClasses[i].fiId);
+ wc.hInstance = hModClient;
+ }
+
wc.cbClsExtra = 0;
- wc.cbWndExtra = SystemClasses[i].ExtraBytes;
- wc.hInstance = pi->hModUser;
+ wc.cbWndExtra = DefaultServerClasses[i].ExtraBytes;
wc.hIcon = NULL;
- wc.hCursor = SystemClasses[i].hCursor;
- wc.hbrBackground = SystemClasses[i].hBrush;
+ wc.hCursor = DefaultServerClasses[i].hCursor;
+ wc.hbrBackground = DefaultServerClasses[i].hBrush;
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName.Buffer;
wc.hIconSm = NULL;
- Class = IntCreateClass(&wc,
- &ClassName,
- &MenuName,
- SystemClasses[i].ProcA,
- CSF_SYSTEMCLASS,
- NULL,
- pi);
+ Class = IntCreateClass( &wc,
+ &ClassName,
+ &MenuName,
+ DefaultServerClasses[i].fiId,
+ Flags,
+ NULL,
+ ppi);
if (Class != NULL)
{
- int iCls;
-
- Class->fnid = SystemClasses[i].ClassId;
- if (LockupFnIdToiCls(Class->fnid, &iCls))
- {
- gpsi->atomSysClass[iCls] = Class->atomClassName;
- }
-
- ASSERT(Class->System);
- Class->pclsNext = pi->SystemClassList;
- (void)InterlockedExchangePointer((PVOID*)&pi->SystemClassList,
+ Class->pclsNext = ppi->pclsPublicList;
+ (void)InterlockedExchangePointer((PVOID*)&ppi->pclsPublicList,
Class);
+
+ ppi->dwRegisteredClasses |= ICLASS_TO_MASK(DefaultServerClasses[i].iCls);
}
else
{
Ret = FALSE;
}
}
-
- if (Ret)
- pi->RegisteredSysClasses = TRUE;
+ if (Ret) ppi->W32PF_flags |= W32PF_CLASSESREGISTERED;
return Ret;
}
WNDCLASSEXW CapturedClassInfo = {0};
UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0};
RTL_ATOM Ret = (RTL_ATOM)0;
- WNDPROC wpExtra = NULL;
+ PPROCESSINFO ppi = GetW32ProcessInfo();
if (Flags & ~(CSF_ANSIPROC))
{
+ DPRINT1("NtUserRegisterClassExWOW Bad Flags!\n");
SetLastWin32Error(ERROR_INVALID_FLAGS);
return Ret;
}
UserEnterExclusive();
+ DPRINT("NtUserRegisterClassExWOW ClsN %wZ\n",ClassName);
+
+ if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
+ {
+ UserRegisterSystemClasses();
+ }
+
_SEH2_TRY
{
/* Probe the parameters and basic parameter checks */
if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW))
{
+ DPRINT1("NtUserRegisterClassExWOW Wrong cbSize!\n");
goto InvalidParameter;
}
CapturedClassInfo.cbWndExtra < 0 ||
CapturedClassInfo.hInstance == NULL)
{
+ DPRINT1("NtUserRegisterClassExWOW Invalid Parameter Error!\n");
goto InvalidParameter;
}
{
if (!IS_ATOM(CapturedName.Buffer))
{
+ DPRINT1("NtUserRegisterClassExWOW ClassName Error!\n");
goto InvalidParameter;
}
}
else if (CapturedMenuName.Buffer != NULL &&
!IS_INTRESOURCE(CapturedMenuName.Buffer))
{
+ DPRINT1("NtUserRegisterClassExWOW MenuName Error!\n");
InvalidParameter:
SetLastWin32Error(ERROR_INVALID_PARAMETER);
_SEH2_LEAVE;
}
+
+ if (IsCallProcHandle(lpwcx->lpfnWndProc))
+ {// Never seen this yet, but I'm sure it's a little haxxy trick!
+ // If this pops up we know what todo!
+ DPRINT1("NtUserRegisterClassExWOW WndProc is CallProc!!\n");
+ }
+
+ DPRINT("NtUserRegisterClassExWOW MnuN %wZ\n",&CapturedMenuName);
+
/* Register the class */
Ret = UserRegisterClass(&CapturedClassInfo,
&CapturedName,
&CapturedMenuName,
- wpExtra,
+ fnID,
Flags);
-
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
+ DPRINT1("NtUserRegisterClassExWOW Exception Error!\n");
SetLastNtError(_SEH2_GetExceptionCode());
}
_SEH2_END;
-
+/*
+ if (!Ret)
+ {
+ DPRINT1("NtUserRegisterClassExWOW Null Return!\n");
+ }
+ */
UserLeave();
return Ret;
Offset,
Ansi);
- if (Ret != 0 && Offset == GCLP_MENUNAME && Window->Wnd->pcls->MenuNameIsString)
+ if ( Ret != 0 &&
+ Offset == GCLP_MENUNAME &&
+ Window->Wnd->pcls->MenuNameIsString)
{
Ret = (ULONG_PTR)UserHeapAddressToUser((PVOID)Ret);
}
UserEnterExclusive();
pi = GetW32ProcessInfo();
- if (pi == NULL)
- goto Cleanup;
Window = UserGetWindowObject(hWnd);
if (Window != NULL)
INT nIndex,
WORD wNewWord)
{
+/*
+ * NOTE: Obsoleted in 32-bit windows
+ */
return(0);
}
/* unregister the class */
Ret = UserUnregisterClass(&CapturedClassName,
- hInstance);
+ hInstance,
+ NULL); // Null for now~
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_END;
UserLeave();
-
return Ret;
}
LPWSTR *ppszMenuName,
BOOL Ansi)
{
- UNICODE_STRING CapturedClassName;
- PCLS Class;
- RTL_ATOM ClassAtom;
- PPROCESSINFO pi;
- BOOL Ret = FALSE;
-
- /* NOTE: need exclusive lock because getting the wndproc might require the
- creation of a call procedure handle */
- UserEnterExclusive();
-
- pi = GetW32ProcessInfo();
- if (pi == NULL)
- {
- ERR("GetW32ProcessInfo() returned NULL!\n");
- goto Cleanup;
- }
- _SEH2_TRY
- {
- /* probe the paramters */
- CapturedClassName = ProbeForReadUnicodeString(ClassName);
-
- if (CapturedClassName.Length == 0)
- TRACE("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi);
- else
- TRACE("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi);
-
- if (CapturedClassName.Length & 1)
- {
+ UNICODE_STRING CapturedClassName, SafeClassName;
+ WNDCLASSEXW Safewcexw;
+ PCLS Class;
+ RTL_ATOM ClassAtom = 0;
+ PPROCESSINFO ppi;
+ BOOL Ret = TRUE;
+
+ /* NOTE: need exclusive lock because getting the wndproc might require the
+ creation of a call procedure handle */
+ UserEnterExclusive();
+
+ ppi = GetW32ProcessInfo();
+
+ if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
+ {
+ UserRegisterSystemClasses();
+ }
+
+ _SEH2_TRY
+ {
+ /* probe the paramters */
+ CapturedClassName = ProbeForReadUnicodeString(ClassName);
+
+ if (CapturedClassName.Length == 0)
+ TRACE("hInst %p atom %04X lpWndClassEx %p Ansi %d\n", hInstance, CapturedClassName.Buffer, lpWndClassEx, Ansi);
+ else
+ TRACE("hInst %p class %wZ lpWndClassEx %p Ansi %d\n", hInstance, &CapturedClassName, lpWndClassEx, Ansi);
+
+ if (CapturedClassName.Length & 1)
+ {
+ goto InvalidParameter;
+ }
+
+ if (CapturedClassName.Length != 0)
+ {
+ ProbeForRead( CapturedClassName.Buffer,
+ CapturedClassName.Length,
+ sizeof(WCHAR));
+
+ RtlInitUnicodeString( &SafeClassName, CapturedClassName.Buffer);
+
+ SafeClassName.Buffer = ExAllocatePoolWithTag( PagedPool,
+ SafeClassName.MaximumLength,
+ TAG_STRING);
+ RtlCopyMemory( SafeClassName.Buffer,
+ CapturedClassName.Buffer,
+ SafeClassName.MaximumLength);
+ }
+ else
+ {
+ if (!IS_ATOM(CapturedClassName.Buffer))
+ {
+ ERR("NtUserGetClassInfo() got ClassName instead of Atom!\n");
goto InvalidParameter;
- }
+ }
- if (CapturedClassName.Length != 0)
- {
- ProbeForRead(CapturedClassName.Buffer,
- CapturedClassName.Length,
- sizeof(WCHAR));
- }
- else
- {
- if (!IS_ATOM(CapturedClassName.Buffer))
- {
- ERR("NtUserGetClassInfo() got ClassName instead of Atom!\n");
- goto InvalidParameter;
- }
- }
+ SafeClassName.Buffer = CapturedClassName.Buffer;
+ SafeClassName.Length = 0;
+ SafeClassName.MaximumLength = 0;
+ }
- if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW))
- {
+ if (ProbeForReadUint(&lpWndClassEx->cbSize) != sizeof(WNDCLASSEXW))
+ {
InvalidParameter:
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- _SEH2_LEAVE;
- }
-
- ProbeForWrite(lpWndClassEx,
- sizeof(WNDCLASSEXW),
- sizeof(ULONG));
-
- ClassAtom = IntGetClassAtom(&CapturedClassName,
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ Ret = FALSE;
+ _SEH2_LEAVE;
+ }
+
+ ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG));
+
+ RtlCopyMemory( &Safewcexw, lpWndClassEx, sizeof(WNDCLASSEXW));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ Ret = FALSE;
+ }
+ _SEH2_END;
+
+ // If null instance use client.
+ if (!hInstance) hInstance = hModClient;
+
+ if (Ret)
+ {
+ DPRINT("GetClassInfo(%wZ, 0x%x)\n", ClassName, hInstance);
+ ClassAtom = IntGetClassAtom( &SafeClassName,
hInstance,
- pi,
- &Class,
+ ppi,
+ &Class,
NULL);
- if (ClassAtom != (RTL_ATOM)0)
- {
- if (hInstance == NULL)
- hInstance = pi->hModUser;
-
- Ret = UserGetClassInfo(Class,
- lpWndClassEx,
- Ansi,
- hInstance);
-
- if (Ret)
- {
- lpWndClassEx->lpszClassName = CapturedClassName.Buffer;
- /* FIXME - handle Class->Desktop == NULL!!!!! */
-
- if (Class->MenuName != NULL && Class->MenuNameIsString)
- {
- lpWndClassEx->lpszMenuName = UserHeapAddressToUser(Ansi ?
- (PVOID)Class->AnsiMenuName :
- (PVOID)Class->MenuName);
- }
-
- /* Undocumented behavior! Return the class atom as a BOOL! */
- Ret = (BOOL)ClassAtom;
- }
- }
- else
- SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
+ if (ClassAtom != (RTL_ATOM)0)
+ {
+ if (hInstance == NULL) hInstance = hModClient;
+
+ Ret = UserGetClassInfo( Class,
+ &Safewcexw,
+ Ansi,
+ hInstance);
+ }
+ else
+ {
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
- }
- _SEH2_END;
-
-Cleanup:
- UserLeave();
- return Ret;
+ Ret = FALSE;
+ }
+ }
+ _SEH2_TRY
+ {
+ if (Ret)
+ {
+ /* Emulate Function. */
+ if (ppszMenuName) *ppszMenuName = (LPWSTR)Safewcexw.lpszMenuName;
+
+ RtlCopyMemory(lpWndClassEx, &Safewcexw, sizeof(WNDCLASSEXW));
+
+ // From Wine:
+ /* We must return the atom of the class here instead of just TRUE. */
+ /* Undocumented behavior! Return the class atom as a BOOL! */
+ Ret = (BOOL)ClassAtom;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ Ret = FALSE;
+ }
+ _SEH2_END;
+
+ if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
+ UserLeave();
+ return Ret;
}
-
INT APIENTRY
NtUserGetClassName (IN HWND hWnd,
OUT PUNICODE_STRING ClassName,
return Ret;
}
-DWORD APIENTRY
-NtUserGetWOWClass(DWORD Unknown0,
- DWORD Unknown1)
+/* Return Pointer to Class structure. */
+PCLS APIENTRY
+NtUserGetWOWClass(HINSTANCE hInstance,
+ PUNICODE_STRING ClassName)
{
- return(0);
+ UNICODE_STRING SafeClassName;
+ PPROCESSINFO pi;
+ PCLS Class = NULL;
+ RTL_ATOM ClassAtom = 0;
+ BOOL Hit = FALSE;
+
+ UserEnterExclusive();
+
+ pi = GetW32ProcessInfo();
+
+ _SEH2_TRY
+ {
+ if (ClassName->Length != 0)
+ {
+ ProbeForRead( ClassName->Buffer,
+ ClassName->Length,
+ sizeof(WCHAR));
+
+ RtlInitUnicodeString( &SafeClassName, ClassName->Buffer);
+
+ SafeClassName.Buffer = ExAllocatePoolWithTag( PagedPool,
+ SafeClassName.MaximumLength,
+ TAG_STRING);
+ RtlCopyMemory( SafeClassName.Buffer,
+ ClassName->Buffer,
+ SafeClassName.MaximumLength);
+ }
+ else
+ {
+ if (!IS_ATOM(ClassName->Buffer))
+ {
+ ERR("NtUserGetWOWClass() got ClassName instead of Atom!\n");
+ Hit = TRUE;
+ }
+ else
+ {
+ SafeClassName.Buffer = ClassName->Buffer;
+ SafeClassName.Length = 0;
+ SafeClassName.MaximumLength = 0;
+ }
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ Hit = TRUE;
+ }
+ _SEH2_END;
+
+ if (!Hit)
+ {
+ ClassAtom = IntGetClassAtom( &SafeClassName,
+ hInstance,
+ pi,
+ &Class,
+ NULL);
+ if (!ClassAtom)
+ {
+ SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
+ }
+ }
+
+ if (SafeClassName.Length) ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
+ UserLeave();
+//
+// Don't forget to use DesktopPtrToUser( ? ) with return pointer in user space.
+//
+ return Class;
}
/* EOF */