* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: Window classes
- * FILE: subsystems/win32/win32k/ntuser/class.c
+ * FILE: win32ss/user/ntuser/class.c
* PROGRAMER: Thomas Weidenmueller <w3seek@reactos.com>
*/
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserClass);
-BOOL FASTCALL IntClassDestroyIcon(HANDLE hCurIcon);
+static PWSTR ControlsList[] =
+{
+ L"Button",
+ L"Edit",
+ L"Static",
+ L"ListBox",
+ L"ScrollBar",
+ L"ComboBox",
+ L"MDIClient",
+ L"ComboLBox",
+ L"DDEMLEvent",
+ L"DDEMLMom",
+ L"DMGClass",
+ L"DDEMLAnsiClient",
+ L"DDEMLUnicodeClient",
+ L"DDEMLAnsiServer",
+ L"DDEMLUnicodeServer",
+ L"IME",
+ L"Ghost",
+};
+
static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom);
REGISTER_SYSCLASS DefaultServerClasses[] =
CS_GLOBALCLASS|CS_DBLCLKS,
NULL, // Use User32 procs
sizeof(ULONG)*2,
- (HICON)IDC_ARROW,
+ (HICON)OCR_NORMAL,
(HBRUSH)(COLOR_BACKGROUND),
FNID_DESKTOP,
ICLS_DESKTOP
CS_VREDRAW|CS_HREDRAW|CS_SAVEBITS,
NULL, // Use User32 procs
sizeof(LONG),
- (HICON)IDC_ARROW,
+ (HICON)OCR_NORMAL,
NULL,
FNID_SWITCH,
ICLS_SWITCH
CS_DBLCLKS|CS_SAVEBITS,
NULL, // Use User32 procs
sizeof(LONG),
- (HICON)IDC_ARROW,
+ (HICON)OCR_NORMAL,
(HBRUSH)(COLOR_MENU + 1),
FNID_MENU,
ICLS_MENU
CS_DBLCLKS|CS_VREDRAW|CS_HREDRAW|CS_PARENTDC,
NULL, // Use User32 procs
sizeof(SBWND)-sizeof(WND),
- (HICON)IDC_ARROW,
+ (HICON)OCR_NORMAL,
NULL,
FNID_SCROLLBAR,
ICLS_SCROLLBAR
CS_PARENTDC|CS_DBLCLKS,
NULL, // Use User32 procs
0,
- (HICON)IDC_ARROW,
+ (HICON)OCR_NORMAL,
0,
FNID_TOOLTIPS,
ICLS_TOOLTIPS
0,
NULL, // Use User32 procs
0,
- (HICON)IDC_ARROW,
+ (HICON)OCR_NORMAL,
0,
FNID_ICONTITLE,
ICLS_ICONTITLE
CS_GLOBALCLASS,
NULL, // Use User32 procs
0,
- (HICON)IDC_ARROW,
+ (HICON)OCR_NORMAL,
NULL,
FNID_MESSAGEWND,
ICLS_HWNDMESSAGE
NextCallProc = CallProc->spcpdNext;
CallProc->spcpdNext = NULL;
- DestroyCallProc(NULL,
- CallProc);
+ DestroyCallProc(CallProc);
CallProc = NextCallProc;
}
// Fixes running the static test then run class test issue.
// Some applications do not use UnregisterClass before exiting.
- // Keep from reusing the same atom with case insensitive
+ // Keep from reusing the same atom with case insensitive
// comparisons, remove registration of the atom if not zeroed.
if (Class->atomClassName)
IntDeregisterClassAtom(Class->atomClassName);
IntFreeClassMenuName(Class);
}
- if (Class->hIconSmIntern)
- IntClassDestroyIcon(Class->hIconSmIntern);
+ if (Class->spicn)
+ UserDereferenceObject(Class->spicn);
+ if (Class->spcur)
+ UserDereferenceObject(Class->spcur);
+ if (Class->spicnSm)
+ {
+ UserDereferenceObject(Class->spicnSm);
+ /* Destroy the icon if we own it */
+ if ((Class->CSF_flags & CSF_CACHEDSMICON)
+ && !(UserObjectInDestroy(UserHMGetHandle(Class->spicnSm))))
+ IntDestroyCurIconObject(Class->spicnSm);
+ }
pDesk = Class->rpdeskParent;
Class->rpdeskParent = NULL;
return TRUE;
}
+BOOL FASTCALL
+RegisterControlAtoms(VOID)
+{
+ RTL_ATOM Atom;
+ UNICODE_STRING ClassName;
+ INT i = 0;
+
+ while ( i < ICLS_DESKTOP)
+ {
+ RtlInitUnicodeString(&ClassName, ControlsList[i]);
+ if (IntRegisterClassAtom(&ClassName, &Atom))
+ {
+ gpsi->atomSysClass[i] = Atom;
+ TRACE("Reg Control Atom %ls: 0x%x\n", ControlsList[i], Atom);
+ }
+ i++;
+ }
+ return TRUE;
+}
+
static NTSTATUS
IntDeregisterClassAtom(IN RTL_ATOM Atom)
{
Class = DesktopHeapAlloc(Desktop,
ClassSize);
+
if (Class != NULL)
{
/* Simply clone the class */
RtlCopyMemory( Class, BaseClass, ClassSize);
+ /* Reference our objects */
+ if (Class->spcur)
+ UserReferenceObject(Class->spcur);
+ if (Class->spicn)
+ UserReferenceObject(Class->spicn);
+ if (Class->spicnSm)
+ UserReferenceObject(Class->spicnSm);
+
TRACE("Clone Class 0x%p hM 0x%p\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName);
/* Restore module address if default user class Ref: Bug 4778 */
NewClass->rpdeskParent = NULL;
NewClass->pclsBase = NewClass;
+ if (NewClass->spcur)
+ UserReferenceObject(NewClass->spcur);
+ if (NewClass->spicn)
+ UserReferenceObject(NewClass->spicn);
+ if (NewClass->spicnSm)
+ UserReferenceObject(NewClass->spicnSm);
+
/* Replace the class in the list */
(void)InterlockedExchangePointer((PVOID*)*ClassLinkPtr,
NewClass);
/* FIXME: The class was created before being connected
to a desktop. It is possible for the desktop window,
but should it be allowed for any other case? */
+ TRACE("This CLASS has no Desktop to heap from! Atom %u\n",Atom);
Class = UserHeapAlloc(ClassSize);
}
Class->fnid = fnID;
Class->CSF_flags = dwFlags;
- if (LookupFnIdToiCls(Class->fnid, &iCls))
+ if (LookupFnIdToiCls(Class->fnid, &iCls) && gpsi->atomSysClass[iCls] == 0)
{
gpsi->atomSysClass[iCls] = Class->atomClassName;
}
Class->cbclsExtra = lpwcx->cbClsExtra;
Class->cbwndExtra = lpwcx->cbWndExtra;
Class->hModule = lpwcx->hInstance;
- //// FIXME handles to pointers
- Class->hIcon = lpwcx->hIcon;
- Class->hIconSm = lpwcx->hIconSm;
- Class->hCursor = lpwcx->hCursor;
+ Class->spicn = lpwcx->hIcon ? UserGetCurIconObject(lpwcx->hIcon) : NULL;
+ Class->spcur = lpwcx->hCursor ? UserGetCurIconObject(lpwcx->hCursor) : NULL;
+ Class->spicnSm = lpwcx->hIconSm ? UserGetCurIconObject(lpwcx->hIconSm) : NULL;
////
Class->hbrBackground = lpwcx->hbrBackground;
return Class;
}
+_Success_(return)
BOOL
NTAPI
IntGetAtomFromStringOrAtom(
ASSERT(BaseClass != NULL);
- if (IntGetAtomFromStringOrAtom(ClassName,
- &Atom) &&
+ if (IntGetAtomFromStringOrAtom(ClassName, &Atom) &&
Atom != (RTL_ATOM)0)
{
PCLS Class;
FoundClass:
*BaseClass = Class;
}
+ else
+ {
+ Atom = 0;
+ }
return Atom;
}
return Ret;
}
-//// Do this for now in anticipation of new cursor icon code.
-BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT, PPROCESSINFO);
-
-BOOL FASTCALL
-IntClassDestroyIcon(HANDLE hCurIcon)
-{
- PCURICON_OBJECT CurIcon;
- BOOL Ret;
-
- if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
- {
-
- ERR("hCurIcon was not found!\n");
- return FALSE;
- }
- Ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
- /* Note: IntDestroyCurIconObject will remove our reference for us! */
- if (!Ret)
- {
- ERR("hCurIcon was not Destroyed!\n");
- }
- return Ret;
-}
-
ULONG_PTR
UserSetClassLongPtr(IN PCLS Class,
IN INT Index,
IN BOOL Ansi)
{
ULONG_PTR Ret = 0;
- HANDLE hIconSmIntern = NULL;
/* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */
break;
case GCLP_HCURSOR:
- /* FIXME: Get handle from pointer to CURSOR object */
- Ret = (ULONG_PTR)Class->hCursor;
- Class->hCursor = (HANDLE)NewLong;
+ {
+ PCURICON_OBJECT NewCursor = NULL;
+
+ if (NewLong)
+ {
+ NewCursor = UserGetCurIconObject((HCURSOR)NewLong);
+ if (!NewCursor)
+ {
+ EngSetLastError(ERROR_INVALID_CURSOR_HANDLE);
+ return 0;
+ }
+ }
+
+ if (Class->spcur)
+ {
+ Ret = (ULONG_PTR)UserHMGetHandle(Class->spcur);
+ UserDereferenceObject(Class->spcur);
+ }
+ else
+ {
+ Ret = 0;
+ }
+
+ if (Ret == NewLong)
+ {
+ /* It's a nop */
+ return Ret;
+ }
+
+ Class->spcur = NewCursor;
/* Update the clones */
Class = Class->pclsClone;
while (Class != NULL)
{
- Class->hCursor = (HANDLE)NewLong;
+ if (Class->spcur)
+ UserDereferenceObject(Class->spcur);
+ if (NewCursor)
+ UserReferenceObject(NewCursor);
+ Class->spcur = NewCursor;
Class = Class->pclsNext;
}
+
break;
+ }
// MSDN:
// hIconSm, A handle to a small icon that is associated with the window class.
// If this member is NULL, the system searches the icon resource specified by
// the hIcon member for an icon of the appropriate size to use as the small icon.
- //
+ //
case GCLP_HICON:
- /* FIXME: Get handle from pointer to ICON object */
- Ret = (ULONG_PTR)Class->hIcon;
- if (Class->hIcon == (HANDLE)NewLong) break;
- if (Ret && Class->hIconSmIntern)
+ {
+ PCURICON_OBJECT NewIcon = NULL;
+ PCURICON_OBJECT NewSmallIcon = NULL;
+
+ if (NewLong)
+ {
+ NewIcon = UserGetCurIconObject((HCURSOR)NewLong);
+ if (!NewIcon)
+ {
+ EngSetLastError(ERROR_INVALID_ICON_HANDLE);
+ return 0;
+ }
+ }
+
+ if (Class->spicn)
+ {
+ Ret = (ULONG_PTR)UserHMGetHandle(Class->spicn);
+ UserDereferenceObject(Class->spicn);
+ }
+ else
{
- IntClassDestroyIcon(Class->hIconSmIntern);
- Class->CSF_flags &= ~CSF_CACHEDSMICON;
- Class->hIconSmIntern = NULL;
+ Ret = 0;
}
- if (NewLong && !Class->hIconSm)
+
+ if (Ret == NewLong)
+ {
+ /* It's a nop */
+ return Ret;
+ }
+
+ if (Ret && (Class->CSF_flags & CSF_CACHEDSMICON))
{
- hIconSmIntern = Class->hIconSmIntern = co_IntCopyImage( (HICON)NewLong, IMAGE_ICON,
- UserGetSystemMetrics( SM_CXSMICON ),
- UserGetSystemMetrics( SM_CYSMICON ), 0 );
- Class->CSF_flags |= CSF_CACHEDSMICON;
+ /* We will change the small icon */
+ UserDereferenceObject(Class->spicnSm);
+ IntDestroyCurIconObject(Class->spicnSm);
+ Class->spicnSm = NULL;
+ Class->CSF_flags &= ~CSF_CACHEDSMICON;
}
- Class->hIcon = (HANDLE)NewLong;
+
+ if (NewLong && !Class->spicnSm)
+ {
+ /* Create the new small icon from the new large(?) one */
+ HICON SmallIconHandle = NULL;
+ if((NewIcon->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
+ == (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
+ {
+ SmallIconHandle = co_IntCopyImage(
+ (HICON)NewLong,
+ IMAGE_ICON,
+ UserGetSystemMetrics( SM_CXSMICON ),
+ UserGetSystemMetrics( SM_CYSMICON ),
+ LR_COPYFROMRESOURCE);
+ }
+ if (!SmallIconHandle)
+ {
+ /* Retry without copying from resource */
+ SmallIconHandle = co_IntCopyImage(
+ (HICON)NewLong,
+ IMAGE_ICON,
+ UserGetSystemMetrics( SM_CXSMICON ),
+ UserGetSystemMetrics( SM_CYSMICON ),
+ 0);
+ }
+ if (SmallIconHandle)
+ {
+ /* So use it */
+ NewSmallIcon = Class->spicnSm = UserGetCurIconObject(SmallIconHandle);
+ Class->CSF_flags |= CSF_CACHEDSMICON;
+ }
+ }
+
+ Class->spicn = NewIcon;
/* Update the clones */
Class = Class->pclsClone;
while (Class != NULL)
{
- Class->hIcon = (HANDLE)NewLong;
- Class->hIconSmIntern = hIconSmIntern;
+ if (Class->spicn)
+ UserDereferenceObject(Class->spicn);
+ if (NewIcon)
+ UserReferenceObject(NewIcon);
+ Class->spicn = NewIcon;
+ if (NewSmallIcon)
+ {
+ if (Class->spicnSm)
+ UserDereferenceObject(Class->spicnSm);
+ UserReferenceObject(NewSmallIcon);
+ Class->spicnSm = NewSmallIcon;
+ Class->CSF_flags |= CSF_CACHEDSMICON;
+ }
Class = Class->pclsNext;
}
break;
+ }
case GCLP_HICONSM:
- /* FIXME: Get handle from pointer to ICON object */
- Ret = (ULONG_PTR)Class->hIconSm;
- if (Class->hIconSm == (HANDLE)NewLong) break;
- if (Class->CSF_flags & CSF_CACHEDSMICON)
+ {
+ PCURICON_OBJECT NewSmallIcon = NULL;
+ BOOLEAN NewIconFromCache = FALSE;
+
+ if (NewLong)
{
- if (Class->hIconSmIntern)
- {
- IntClassDestroyIcon(Class->hIconSmIntern);
- Class->hIconSmIntern = NULL;
- }
- Class->CSF_flags &= ~CSF_CACHEDSMICON;
+ NewSmallIcon = UserGetCurIconObject((HCURSOR)NewLong);
+ if (!NewSmallIcon)
+ {
+ EngSetLastError(ERROR_INVALID_ICON_HANDLE);
+ return 0;
+ }
}
- if (Class->hIcon && !Class->hIconSmIntern)
+ else
{
- hIconSmIntern = Class->hIconSmIntern = co_IntCopyImage( Class->hIcon, IMAGE_ICON,
- UserGetSystemMetrics( SM_CXSMICON ),
- UserGetSystemMetrics( SM_CYSMICON ), 0 );
-
- if (hIconSmIntern) Class->CSF_flags |= CSF_CACHEDSMICON;
- //// FIXME: Very hacky here but it passes the tests....
- //// We should not kill a users handle!!!
- if (Class->hIconSm) IntClassDestroyIcon(Class->hIconSm); // Fixes 1013
- Ret = 0; // Fixes 1009
+ /* Create the new small icon from the large one */
+ HICON SmallIconHandle = NULL;
+ if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
+ == (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
+ {
+ SmallIconHandle = co_IntCopyImage(
+ UserHMGetHandle(Class->spicn),
+ IMAGE_ICON,
+ UserGetSystemMetrics( SM_CXSMICON ),
+ UserGetSystemMetrics( SM_CYSMICON ),
+ LR_COPYFROMRESOURCE);
+ }
+ if (!SmallIconHandle)
+ {
+ /* Retry without copying from resource */
+ SmallIconHandle = co_IntCopyImage(
+ UserHMGetHandle(Class->spicn),
+ IMAGE_ICON,
+ UserGetSystemMetrics( SM_CXSMICON ),
+ UserGetSystemMetrics( SM_CYSMICON ),
+ 0);
+ }
+ if (SmallIconHandle)
+ {
+ /* So use it */
+ NewSmallIcon = UserGetCurIconObject(SmallIconHandle);
+ NewIconFromCache = TRUE;
+ }
+ else
+ {
+ ERR("Failed getting a small icon for the class.\n");
+ }
+ }
+
+ if (Class->spicnSm)
+ {
+ if (Class->CSF_flags & CSF_CACHEDSMICON)
+ {
+ /* We must destroy the icon if we own it */
+ IntDestroyCurIconObject(Class->spicnSm);
+ Ret = 0;
+ }
+ else
+ {
+ Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm);
+ }
+ UserDereferenceObject(Class->spicnSm);
+ }
+ else
+ {
+ Ret = 0;
}
- Class->hIconSm = (HANDLE)NewLong;
+
+ if (NewIconFromCache)
+ Class->CSF_flags |= CSF_CACHEDSMICON;
+ else
+ Class->CSF_flags &= ~CSF_CACHEDSMICON;
+ Class->spicnSm = NewSmallIcon;
/* Update the clones */
Class = Class->pclsClone;
while (Class != NULL)
{
- Class->hIconSm = (HANDLE)NewLong;
- Class->hIconSmIntern = hIconSmIntern;
+ if (Class->spicnSm)
+ UserDereferenceObject(Class->spicnSm);
+ if (NewSmallIcon)
+ UserReferenceObject(NewSmallIcon);
+ if (NewIconFromCache)
+ Class->CSF_flags |= CSF_CACHEDSMICON;
+ else
+ Class->CSF_flags &= ~CSF_CACHEDSMICON;
+ Class->spicnSm = NewSmallIcon;
Class = Class->pclsNext;
}
- break;
+ }
+ break;
case GCLP_HMODULE:
Ret = (ULONG_PTR)Class->hModule;
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->hIcon = Class->spicn ? UserHMGetHandle(Class->spicn) : NULL;
+ lpwcx->hCursor = Class->spcur ? UserHMGetHandle(Class->spcur) : NULL;
+ lpwcx->hIconSm = Class->spicnSm ? UserHMGetHandle(Class->spicnSm) : NULL;
lpwcx->hbrBackground = Class->hbrBackground;
/* Copy non-string to user first. */
/* FIXME: Return the string? Okay! This is performed in User32! */
//lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName);
- /* FIXME: Get handle from pointer */
- lpwcx->hIconSm = Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern;
-
return TRUE;
}
//
-// ???
+// Register System Classes....
//
BOOL
FASTCALL
wc.cbClsExtra = 0;
wc.cbWndExtra = DefaultServerClasses[i].ExtraBytes;
wc.hIcon = NULL;
- wc.hCursor = DefaultServerClasses[i].hCursor;
+
+ //// System Cursors should be initilized!!!
+ wc.hCursor = NULL;
+ if (DefaultServerClasses[i].hCursor == (HICON)OCR_NORMAL)
+ {
+ if (SYSTEMCUR(ARROW) == NULL)
+ {
+ ERR("SYSTEMCUR(ARROW) == NULL, should not happen!!\n");
+ }
+ else
+ {
+ wc.hCursor = UserHMGetHandle(SYSTEMCUR(ARROW));
+ }
+ }
+
hBrush = DefaultServerClasses[i].hBrush;
if (hBrush <= (HBRUSH)COLOR_MENUBAR)
{
UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0};
RTL_ATOM Ret = (RTL_ATOM)0;
PPROCESSINFO ppi = GetW32ProcessInfo();
+ BOOL Exception = FALSE;
if (Flags & ~(CSF_ANSIPROC))
{
}
TRACE("NtUserRegisterClassExWOW MnuN %wZ\n",&CapturedMenuName);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ERR("NtUserRegisterClassExWOW Exception Error!\n");
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Exception = TRUE;
+ }
+ _SEH2_END;
+ if (!Exception)
+ {
/* Register the class */
Ret = UserRegisterClass(&CapturedClassInfo,
&CapturedName,
fnID,
Flags);
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- ERR("NtUserRegisterClassExWOW Exception Error!\n");
- SetLastNtError(_SEH2_GetExceptionCode());
- }
- _SEH2_END;
-/*
+
if (!Ret)
{
- ERR("NtUserRegisterClassExWOW Null Return!\n");
+ TRACE("NtUserRegisterClassExWOW Null Return!\n");
}
- */
+
UserLeave();
return Ret;
Offset,
dwNewLong,
Ansi);
+ switch(Offset)
+ {
+ case GCLP_HICONSM:
+ case GCLP_HICON:
+ {
+ if (Ret && Ret != dwNewLong)
+ UserPaintCaption(Window, DC_ICON);
+ }
+ }
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
// If null instance use client.
if (!hInstance) hInstance = hModClient;
- TRACE("GetClassInfo(%wZ, %p)\n", SafeClassName, hInstance);
+ TRACE("GetClassInfo(%wZ, %p)\n", &SafeClassName, hInstance);
/* NOTE: Need exclusive lock because getting the wndproc might require the
creation of a call procedure handle */