mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 04:20:46 +00:00
758 lines
19 KiB
C
758 lines
19 KiB
C
/*
|
|
* ReactOS W32 Subsystem
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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.
|
|
*/
|
|
/* $Id$
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* PURPOSE: Window classes
|
|
* FILE: subsys/win32k/ntuser/class.c
|
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
* REVISION HISTORY:
|
|
* 06-06-2001 CSH Created
|
|
*/
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <w32k.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
NTSTATUS FASTCALL
|
|
InitClassImpl(VOID)
|
|
{
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS FASTCALL
|
|
CleanupClassImpl(VOID)
|
|
{
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
BOOL FASTCALL
|
|
ClassReferenceClassByAtom(
|
|
PWNDCLASS_OBJECT* Class,
|
|
RTL_ATOM Atom,
|
|
HINSTANCE hInstance)
|
|
{
|
|
PWNDCLASS_OBJECT Current, BestMatch = NULL;
|
|
PLIST_ENTRY CurrentEntry;
|
|
PW32PROCESS Process = PsGetWin32Process();
|
|
|
|
CurrentEntry = Process->ClassListHead.Flink;
|
|
while (CurrentEntry != &Process->ClassListHead)
|
|
{
|
|
Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
|
|
|
|
if (Current->Atom == Atom && (hInstance == NULL || Current->hInstance == hInstance))
|
|
{
|
|
*Class = Current;
|
|
ObmReferenceObject(Current);
|
|
return TRUE;
|
|
}
|
|
|
|
if (Current->Atom == Atom && Current->Global)
|
|
BestMatch = Current;
|
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
}
|
|
|
|
if (BestMatch != NULL)
|
|
{
|
|
*Class = BestMatch;
|
|
ObmReferenceObject(BestMatch);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL FASTCALL
|
|
ClassReferenceClassByName(
|
|
PWNDCLASS_OBJECT *Class,
|
|
LPCWSTR ClassName,
|
|
HINSTANCE hInstance)
|
|
{
|
|
PWINSTATION_OBJECT WinStaObject;
|
|
NTSTATUS Status;
|
|
BOOL Found;
|
|
RTL_ATOM ClassAtom;
|
|
|
|
if (!ClassName || !PsGetWin32Thread()->Desktop)
|
|
return FALSE;
|
|
|
|
WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
|
|
|
|
Status = RtlLookupAtomInAtomTable(
|
|
WinStaObject->AtomTable,
|
|
(LPWSTR)ClassName,
|
|
&ClassAtom);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to lookup class atom!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
Found = ClassReferenceClassByAtom(Class, ClassAtom, hInstance);
|
|
|
|
return Found;
|
|
}
|
|
|
|
BOOL FASTCALL
|
|
ClassReferenceClassByNameOrAtom(
|
|
PWNDCLASS_OBJECT *Class,
|
|
LPCWSTR ClassNameOrAtom,
|
|
HINSTANCE hInstance)
|
|
{
|
|
BOOL Found;
|
|
|
|
if (IS_ATOM(ClassNameOrAtom))
|
|
Found = ClassReferenceClassByAtom(Class, (RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
|
|
else
|
|
Found = ClassReferenceClassByName(Class, ClassNameOrAtom, hInstance);
|
|
|
|
return Found;
|
|
}
|
|
|
|
DWORD STDCALL
|
|
NtUserGetClassInfo(
|
|
HINSTANCE hInstance,
|
|
LPCWSTR lpClassName,
|
|
LPWNDCLASSEXW lpWndClassEx,
|
|
BOOL Ansi,
|
|
DWORD unknown3)
|
|
{
|
|
PWNDCLASS_OBJECT Class;
|
|
RTL_ATOM Atom;
|
|
DECLARE_RETURN(DWORD);
|
|
|
|
if (IS_ATOM(lpClassName))
|
|
DPRINT("NtUserGetClassInfo - %x (%lx)\n", lpClassName, hInstance);
|
|
else
|
|
DPRINT("NtUserGetClassInfo - %S (%lx)\n", lpClassName, hInstance);
|
|
|
|
UserEnterExclusive();
|
|
|
|
if (!ClassReferenceClassByNameOrAtom(&Class, lpClassName, hInstance))
|
|
{
|
|
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
|
|
RETURN(0);
|
|
}
|
|
|
|
lpWndClassEx->cbSize = sizeof(WNDCLASSEXW);
|
|
lpWndClassEx->style = Class->style;
|
|
if (Ansi)
|
|
lpWndClassEx->lpfnWndProc = Class->lpfnWndProcA;
|
|
else
|
|
lpWndClassEx->lpfnWndProc = Class->lpfnWndProcW;
|
|
lpWndClassEx->cbClsExtra = Class->cbClsExtra;
|
|
lpWndClassEx->cbWndExtra = Class->cbWndExtra;
|
|
/* This is not typo, we're really not going to use Class->hInstance here. */
|
|
lpWndClassEx->hInstance = hInstance;
|
|
lpWndClassEx->hIcon = Class->hIcon;
|
|
lpWndClassEx->hCursor = Class->hCursor;
|
|
lpWndClassEx->hbrBackground = Class->hbrBackground;
|
|
if (Class->lpszMenuName.MaximumLength)
|
|
RtlCopyUnicodeString((PUNICODE_STRING)lpWndClassEx->lpszMenuName, &Class->lpszMenuName);
|
|
else
|
|
lpWndClassEx->lpszMenuName = Class->lpszMenuName.Buffer;
|
|
lpWndClassEx->lpszClassName = lpClassName;
|
|
lpWndClassEx->hIconSm = Class->hIconSm;
|
|
Atom = Class->Atom;
|
|
|
|
ObmDereferenceObject(Class);
|
|
|
|
RETURN(Atom);
|
|
|
|
CLEANUP:
|
|
DPRINT("Leave NtUserGetClassInfo, ret=%i\n",_ret_);
|
|
UserLeave();
|
|
END_CLEANUP;
|
|
}
|
|
|
|
ULONG FASTCALL
|
|
IntGetClassName(struct _WINDOW_OBJECT *WindowObject, LPWSTR lpClassName,
|
|
ULONG nMaxCount)
|
|
{
|
|
ULONG Length;
|
|
LPWSTR Name;
|
|
PWINSTATION_OBJECT WinStaObject;
|
|
NTSTATUS Status;
|
|
|
|
if(!PsGetWin32Thread()->Desktop)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
|
|
|
|
Length = 0;
|
|
Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,
|
|
WindowObject->Class->Atom, NULL, NULL, NULL, &Length);
|
|
Name = ExAllocatePoolWithTag(PagedPool, Length + sizeof(UNICODE_NULL), TAG_STRING);
|
|
Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable,
|
|
WindowObject->Class->Atom, NULL, NULL, Name, &Length);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("IntGetClassName: RtlQueryAtomInAtomTable failed\n");
|
|
return 0;
|
|
}
|
|
Length /= sizeof(WCHAR);
|
|
if (Length > nMaxCount)
|
|
{
|
|
Length = nMaxCount;
|
|
}
|
|
wcsncpy(lpClassName, Name, Length);
|
|
/* FIXME: Check buffer size before doing this! */
|
|
*(lpClassName + Length) = 0;
|
|
ExFreePool(Name);
|
|
|
|
return Length;
|
|
}
|
|
|
|
DWORD STDCALL
|
|
NtUserGetClassName (
|
|
HWND hWnd,
|
|
LPWSTR lpClassName,
|
|
ULONG nMaxCount)
|
|
{
|
|
PWINDOW_OBJECT WindowObject;
|
|
LONG Length;
|
|
DECLARE_RETURN(DWORD);
|
|
|
|
UserEnterShared();
|
|
|
|
WindowObject = IntGetWindowObject(hWnd);
|
|
if (WindowObject == NULL)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
RETURN(0);
|
|
}
|
|
Length = IntGetClassName(WindowObject, lpClassName, nMaxCount);
|
|
IntReleaseWindowObject(WindowObject);
|
|
RETURN(Length);
|
|
|
|
CLEANUP:
|
|
DPRINT("Leave NtUserGetClassName, ret=%i\n",_ret_);
|
|
UserLeave();
|
|
END_CLEANUP;
|
|
}
|
|
|
|
DWORD STDCALL
|
|
NtUserGetWOWClass(DWORD Unknown0,
|
|
DWORD Unknown1)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return(0);
|
|
}
|
|
|
|
PWNDCLASS_OBJECT FASTCALL
|
|
IntCreateClass(
|
|
CONST WNDCLASSEXW *lpwcx,
|
|
DWORD Flags,
|
|
WNDPROC wpExtra,
|
|
PUNICODE_STRING MenuName,
|
|
RTL_ATOM Atom)
|
|
{
|
|
PWNDCLASS_OBJECT ClassObject;
|
|
ULONG objectSize;
|
|
BOOL Global;
|
|
|
|
Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS) ? TRUE : FALSE;
|
|
|
|
/* Check for double registration of the class. */
|
|
if (PsGetWin32Process() != NULL)
|
|
{
|
|
if (ClassReferenceClassByAtom(&ClassObject, Atom, lpwcx->hInstance))
|
|
{
|
|
/*
|
|
* NOTE: We may also get a global class from
|
|
* ClassReferenceClassByAtom. This simple check
|
|
* prevents that we fail valid request.
|
|
*/
|
|
if (ClassObject->hInstance == lpwcx->hInstance)
|
|
{
|
|
SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
|
|
ObmDereferenceObject(ClassObject);
|
|
return(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
|
|
ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize);
|
|
if (ClassObject == 0)
|
|
{
|
|
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
|
|
return(NULL);
|
|
}
|
|
|
|
ClassObject->cbSize = lpwcx->cbSize;
|
|
ClassObject->style = lpwcx->style;
|
|
ClassObject->cbClsExtra = lpwcx->cbClsExtra;
|
|
ClassObject->cbWndExtra = lpwcx->cbWndExtra;
|
|
ClassObject->hInstance = lpwcx->hInstance;
|
|
ClassObject->hIcon = lpwcx->hIcon;
|
|
ClassObject->hCursor = lpwcx->hCursor;
|
|
ClassObject->hbrBackground = lpwcx->hbrBackground;
|
|
ClassObject->Unicode = !(Flags & REGISTERCLASS_ANSI);
|
|
ClassObject->Global = Global;
|
|
ClassObject->hIconSm = lpwcx->hIconSm;
|
|
ClassObject->Atom = Atom;
|
|
if (wpExtra == NULL) {
|
|
if (Flags & REGISTERCLASS_ANSI)
|
|
{
|
|
ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
|
|
ClassObject->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
|
|
}
|
|
else
|
|
{
|
|
ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
|
|
ClassObject->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
|
|
}
|
|
} else {
|
|
if (Flags & REGISTERCLASS_ANSI)
|
|
{
|
|
ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
|
|
ClassObject->lpfnWndProcW = wpExtra;
|
|
}
|
|
else
|
|
{
|
|
ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
|
|
ClassObject->lpfnWndProcA = wpExtra;
|
|
}
|
|
}
|
|
if (MenuName->Length == 0)
|
|
{
|
|
ClassObject->lpszMenuName.Length =
|
|
ClassObject->lpszMenuName.MaximumLength = 0;
|
|
ClassObject->lpszMenuName.Buffer = MenuName->Buffer;
|
|
}
|
|
else
|
|
{
|
|
ClassObject->lpszMenuName.Length =
|
|
ClassObject->lpszMenuName.MaximumLength = MenuName->MaximumLength;
|
|
ClassObject->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, ClassObject->lpszMenuName.MaximumLength, TAG_STRING);
|
|
RtlCopyUnicodeString(&ClassObject->lpszMenuName, MenuName);
|
|
}
|
|
/* Extra class data */
|
|
if (ClassObject->cbClsExtra != 0)
|
|
{
|
|
ClassObject->ExtraData = (PCHAR)(ClassObject + 1);
|
|
RtlZeroMemory(ClassObject->ExtraData, (ULONG)ClassObject->cbClsExtra);
|
|
}
|
|
else
|
|
{
|
|
ClassObject->ExtraData = NULL;
|
|
}
|
|
|
|
InitializeListHead(&ClassObject->ClassWindowsListHead);
|
|
|
|
return(ClassObject);
|
|
}
|
|
|
|
RTL_ATOM STDCALL
|
|
NtUserRegisterClassExWOW(
|
|
CONST WNDCLASSEXW* lpwcx,
|
|
PUNICODE_STRING ClassName,
|
|
PUNICODE_STRING ClassNameCopy,
|
|
PUNICODE_STRING MenuName,
|
|
WNDPROC wpExtra, /* FIXME: Windows uses this parameter for something different. */
|
|
DWORD Flags,
|
|
DWORD Unknown7)
|
|
|
|
/*
|
|
* FUNCTION:
|
|
* Registers a new class with the window manager
|
|
* ARGUMENTS:
|
|
* lpwcx = Win32 extended window class structure
|
|
* bUnicodeClass = Whether to send ANSI or unicode strings
|
|
* to window procedures
|
|
* wpExtra = Extra window procedure, if this is not null, its used for the second window procedure for standard controls.
|
|
* RETURNS:
|
|
* Atom identifying the new class
|
|
*/
|
|
{
|
|
WNDCLASSEXW SafeClass;
|
|
PWINSTATION_OBJECT WinStaObject;
|
|
PWNDCLASS_OBJECT ClassObject;
|
|
NTSTATUS Status;
|
|
RTL_ATOM Atom;
|
|
DECLARE_RETURN(RTL_ATOM);
|
|
|
|
DPRINT("Enter NtUserRegisterClassExWOW\n");
|
|
UserEnterExclusive();
|
|
|
|
if (!lpwcx)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
RETURN( (RTL_ATOM)0);
|
|
}
|
|
|
|
if (Flags & ~REGISTERCLASS_ALL)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_FLAGS);
|
|
RETURN( (RTL_ATOM)0);
|
|
}
|
|
|
|
Status = MmCopyFromCaller(&SafeClass, lpwcx, sizeof(WNDCLASSEXW));
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
RETURN( (RTL_ATOM)0);
|
|
}
|
|
|
|
/* Deny negative sizes */
|
|
if (lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
RETURN( (RTL_ATOM)0);
|
|
}
|
|
|
|
WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
|
|
|
|
if (ClassName->Length > 0)
|
|
{
|
|
DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
|
|
/* FIXME - Safely copy/verify the buffer first!!! */
|
|
Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
|
|
ClassName->Buffer,
|
|
&Atom);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed adding class name (%S) to atom table\n",
|
|
ClassName->Buffer);
|
|
SetLastNtError(Status);
|
|
RETURN((RTL_ATOM)0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Atom = (RTL_ATOM)(ULONG)ClassName->Buffer;
|
|
}
|
|
ClassObject = IntCreateClass(&SafeClass, Flags, wpExtra, MenuName, Atom);
|
|
if (ClassObject == NULL)
|
|
{
|
|
if (ClassName->Length)
|
|
{
|
|
RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Atom);
|
|
}
|
|
DPRINT("Failed creating window class object\n");
|
|
RETURN((RTL_ATOM)0);
|
|
}
|
|
|
|
InsertTailList(&PsGetWin32Process()->ClassListHead, &ClassObject->ListEntry);
|
|
|
|
RETURN(Atom);
|
|
|
|
CLEANUP:
|
|
DPRINT("Leave NtUserRegisterClassExWOW, ret=%i\n",_ret_);
|
|
UserLeave();
|
|
END_CLEANUP;
|
|
}
|
|
|
|
ULONG FASTCALL
|
|
IntGetClassLong(struct _WINDOW_OBJECT *WindowObject, ULONG Offset, BOOL Ansi)
|
|
{
|
|
LONG Ret;
|
|
|
|
if ((int)Offset >= 0)
|
|
{
|
|
DPRINT("GetClassLong(%x, %d)\n", WindowObject->Self, Offset);
|
|
if ((Offset + sizeof(LONG)) > WindowObject->Class->cbClsExtra)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
Ret = *((LONG *)(WindowObject->Class->ExtraData + Offset));
|
|
DPRINT("Result: %x\n", Ret);
|
|
return Ret;
|
|
}
|
|
|
|
switch (Offset)
|
|
{
|
|
case GCL_CBWNDEXTRA:
|
|
Ret = WindowObject->Class->cbWndExtra;
|
|
break;
|
|
case GCL_CBCLSEXTRA:
|
|
Ret = WindowObject->Class->cbClsExtra;
|
|
break;
|
|
case GCL_HBRBACKGROUND:
|
|
Ret = (ULONG)WindowObject->Class->hbrBackground;
|
|
break;
|
|
case GCL_HCURSOR:
|
|
Ret = (ULONG)WindowObject->Class->hCursor;
|
|
break;
|
|
case GCL_HICON:
|
|
Ret = (ULONG)WindowObject->Class->hIcon;
|
|
break;
|
|
case GCL_HICONSM:
|
|
Ret = (ULONG)WindowObject->Class->hIconSm;
|
|
break;
|
|
case GCL_HMODULE:
|
|
Ret = (ULONG)WindowObject->Class->hInstance;
|
|
break;
|
|
case GCL_MENUNAME:
|
|
Ret = (ULONG)WindowObject->Class->lpszMenuName.Buffer;
|
|
break;
|
|
case GCL_STYLE:
|
|
Ret = WindowObject->Class->style;
|
|
break;
|
|
case GCL_WNDPROC:
|
|
if (Ansi)
|
|
{
|
|
Ret = (ULONG)WindowObject->Class->lpfnWndProcA;
|
|
}
|
|
else
|
|
{
|
|
Ret = (ULONG)WindowObject->Class->lpfnWndProcW;
|
|
}
|
|
break;
|
|
default:
|
|
Ret = 0;
|
|
break;
|
|
}
|
|
return(Ret);
|
|
}
|
|
|
|
DWORD STDCALL
|
|
NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
|
|
{
|
|
PWINDOW_OBJECT WindowObject;
|
|
LONG Ret;
|
|
DECLARE_RETURN(DWORD);
|
|
|
|
DPRINT("Enter NtUserGetClassLong\n");
|
|
UserEnterExclusive();
|
|
|
|
WindowObject = IntGetWindowObject(hWnd);
|
|
if (WindowObject == NULL)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
RETURN(0);
|
|
}
|
|
Ret = IntGetClassLong(WindowObject, Offset, Ansi);
|
|
IntReleaseWindowObject(WindowObject);
|
|
RETURN(Ret);
|
|
|
|
CLEANUP:
|
|
DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_);
|
|
UserLeave();
|
|
END_CLEANUP;
|
|
}
|
|
|
|
void FASTCALL
|
|
co_IntSetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset, LONG dwNewLong, BOOL Ansi)
|
|
{
|
|
PWINDOW_OBJECT Parent, Owner;
|
|
|
|
if ((int)Offset >= 0)
|
|
{
|
|
DPRINT("SetClassLong(%x, %d, %x)\n", WindowObject->Self, Offset, dwNewLong);
|
|
if ((Offset + sizeof(LONG)) > WindowObject->Class->cbClsExtra)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
return;
|
|
}
|
|
*((LONG *)(WindowObject->Class->ExtraData + Offset)) = dwNewLong;
|
|
return;
|
|
}
|
|
|
|
switch (Offset)
|
|
{
|
|
case GCL_CBWNDEXTRA:
|
|
WindowObject->Class->cbWndExtra = dwNewLong;
|
|
break;
|
|
case GCL_CBCLSEXTRA:
|
|
WindowObject->Class->cbClsExtra = dwNewLong;
|
|
break;
|
|
case GCL_HBRBACKGROUND:
|
|
WindowObject->Class->hbrBackground = (HBRUSH)dwNewLong;
|
|
break;
|
|
case GCL_HCURSOR:
|
|
WindowObject->Class->hCursor = (HCURSOR)dwNewLong;
|
|
break;
|
|
case GCL_HICON:
|
|
WindowObject->Class->hIcon = (HICON)dwNewLong;
|
|
Owner = IntGetOwner(WindowObject);
|
|
Parent = IntGetParent(WindowObject);
|
|
|
|
if ((!Owner) && (!Parent))
|
|
{
|
|
co_IntShellHookNotify(HSHELL_REDRAW, (LPARAM) WindowObject->Self);
|
|
}
|
|
|
|
if (Parent)
|
|
{
|
|
IntReleaseWindowObject(Parent);
|
|
}
|
|
|
|
if (Owner)
|
|
{
|
|
IntReleaseWindowObject(Owner);
|
|
}
|
|
|
|
|
|
break;
|
|
case GCL_HICONSM:
|
|
WindowObject->Class->hIconSm = (HICON)dwNewLong;
|
|
break;
|
|
case GCL_HMODULE:
|
|
WindowObject->Class->hInstance = (HINSTANCE)dwNewLong;
|
|
break;
|
|
case GCL_MENUNAME:
|
|
if (WindowObject->Class->lpszMenuName.MaximumLength)
|
|
RtlFreeUnicodeString(&WindowObject->Class->lpszMenuName);
|
|
if (!IS_INTRESOURCE(dwNewLong))
|
|
{
|
|
WindowObject->Class->lpszMenuName.Length =
|
|
WindowObject->Class->lpszMenuName.MaximumLength = ((PUNICODE_STRING)dwNewLong)->MaximumLength;
|
|
WindowObject->Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, WindowObject->Class->lpszMenuName.MaximumLength, TAG_STRING);
|
|
RtlCopyUnicodeString(&WindowObject->Class->lpszMenuName, (PUNICODE_STRING)dwNewLong);
|
|
}
|
|
else
|
|
{
|
|
WindowObject->Class->lpszMenuName.Length =
|
|
WindowObject->Class->lpszMenuName.MaximumLength = 0;
|
|
WindowObject->Class->lpszMenuName.Buffer = (LPWSTR)dwNewLong;
|
|
}
|
|
break;
|
|
case GCL_STYLE:
|
|
WindowObject->Class->style = dwNewLong;
|
|
break;
|
|
case GCL_WNDPROC:
|
|
if (Ansi)
|
|
{
|
|
WindowObject->Class->lpfnWndProcA = (WNDPROC)dwNewLong;
|
|
WindowObject->Class->lpfnWndProcW = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,FALSE);
|
|
WindowObject->Class->Unicode = FALSE;
|
|
}
|
|
else
|
|
{
|
|
WindowObject->Class->lpfnWndProcW = (WNDPROC)dwNewLong;
|
|
WindowObject->Class->lpfnWndProcA = (WNDPROC) IntAddWndProcHandle((WNDPROC)dwNewLong,TRUE);
|
|
WindowObject->Class->Unicode = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
DWORD STDCALL
|
|
NtUserSetClassLong(HWND hWnd,
|
|
DWORD Offset,
|
|
LONG dwNewLong,
|
|
BOOL Ansi)
|
|
{
|
|
PWINDOW_OBJECT WindowObject;
|
|
LONG Ret;
|
|
DECLARE_RETURN(DWORD);
|
|
|
|
DPRINT("Enter NtUserSetClassLong\n");
|
|
UserEnterExclusive();
|
|
|
|
WindowObject = IntGetWindowObject(hWnd);
|
|
if (WindowObject == NULL)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
RETURN(0);
|
|
}
|
|
Ret = IntGetClassLong(WindowObject, Offset, Ansi);
|
|
co_IntSetClassLong(WindowObject, Offset, dwNewLong, Ansi);
|
|
IntReleaseWindowObject(WindowObject);
|
|
RETURN(Ret);
|
|
|
|
CLEANUP:
|
|
DPRINT("Leave NtUserSetClassLong, ret=%i\n",_ret_);
|
|
UserLeave();
|
|
END_CLEANUP;
|
|
}
|
|
|
|
DWORD STDCALL
|
|
NtUserSetClassWord(DWORD Unknown0,
|
|
DWORD Unknown1,
|
|
DWORD Unknown2)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return(0);
|
|
}
|
|
|
|
BOOL STDCALL
|
|
NtUserUnregisterClass(
|
|
LPCWSTR ClassNameOrAtom,
|
|
HINSTANCE hInstance,
|
|
DWORD Unknown)
|
|
{
|
|
PWNDCLASS_OBJECT Class;
|
|
PWINSTATION_OBJECT WinStaObject;
|
|
DECLARE_RETURN(BOOL);
|
|
|
|
DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
|
|
UserEnterExclusive();
|
|
|
|
if (!ClassNameOrAtom || !PsGetWin32Thread()->Desktop)
|
|
{
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
RETURN( FALSE);
|
|
}
|
|
|
|
WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
|
|
|
|
if (!ClassReferenceClassByNameOrAtom(&Class, ClassNameOrAtom, hInstance))
|
|
{
|
|
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
|
|
RETURN( FALSE);
|
|
}
|
|
|
|
if (Class->hInstance && Class->hInstance != hInstance)
|
|
{
|
|
ClassDereferenceObject(Class);
|
|
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
|
|
RETURN( FALSE);
|
|
}
|
|
|
|
if (!IsListEmpty(&Class->ClassWindowsListHead))
|
|
{
|
|
/* Dereference the ClassReferenceClassByNameOrAtom() call */
|
|
ObmDereferenceObject(Class);
|
|
SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
|
|
RETURN( FALSE);
|
|
}
|
|
|
|
/* Dereference the ClassReferenceClassByNameOrAtom() call */
|
|
ClassDereferenceObject(Class);
|
|
|
|
RemoveEntryList(&Class->ListEntry);
|
|
|
|
RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Class->Atom);
|
|
|
|
/* Free the object */
|
|
ClassDereferenceObject(Class);
|
|
|
|
RETURN( TRUE);
|
|
|
|
CLEANUP:
|
|
DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_);
|
|
UserLeave();
|
|
END_CLEANUP;
|
|
}
|
|
|
|
/* EOF */
|