-include/ndk/rtltypes.h: add MAX_ATOM_LEN define

-win32k: remove some NtUser syscalls and merge some NtUser syscalls
-crt/include/internal/file.h: correct spelling
-RtlAddAtomToAtomTable: check for max atom len
-RtlQueryAtomInAtomTable: fix bug. somehow lock wasnt always released.
-fix/reword windows classes impl. based on Wine. All but 2 winetests pass.
-ntoskrnl/rtl/atom.c: add fixme about global atom table
-remove desktop object lock
-dont link windows into the class object
-co_IntShellHookNotify: safely send notify messages
-misc win32k reorg/cleanup

svn path=/trunk/; revision=18022
This commit is contained in:
Gunnar Dalsnes 2005-09-24 02:50:02 +00:00
parent ff4f5a654b
commit 5fa3cc8c0f
23 changed files with 780 additions and 881 deletions

View file

@ -107,6 +107,8 @@
#define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag
#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo
#define MAX_ATOM_LEN 255 /* TCHARS not including nullterm */
/* List Macros */
static __inline
VOID

View file

@ -212,7 +212,6 @@ NtUserCallOneParam(
#define TWOPARAM_ROUTINE_UNKNOWN 0x54
#define TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS 0x55
#define TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW 0x56
#define TWOPARAM_ROUTINE_VALIDATERGN 0x57
#define TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID 0x58
#define TWOPARAM_ROUTINE_SETCARETPOS 0x60
#define TWOPARAM_ROUTINE_GETWINDOWINFO 0x61
@ -894,11 +893,6 @@ NtUserGetWOWClass(
DWORD Unknown0,
DWORD Unknown1);
BOOL
STDCALL
NtUserHideCaret(
HWND hWnd);
DWORD
STDCALL
NtUserImpersonateDdeClientWindow(
@ -935,20 +929,6 @@ NtUserInternalGetWindowText(
LPWSTR lpString,
INT nMaxCount);
DWORD
STDCALL
NtUserInvalidateRect(
HWND hWnd,
CONST RECT *lpRect,
BOOL bErase);
DWORD
STDCALL
NtUserInvalidateRgn(
HWND hWnd,
HRGN hRgn,
BOOL bErase);
BOOL
STDCALL
@ -1575,7 +1555,8 @@ NtUserSetWinEventHook(
BOOL
STDCALL
NtUserShowCaret(
HWND hWnd);
HWND hWnd,
BOOL bShow);
DWORD
STDCALL
@ -1681,9 +1662,6 @@ NtUserUpdateInstance(
DWORD Unknown1,
DWORD Unknown2);
BOOL STDCALL
NtUserUpdateWindow( HWND hWnd );
DWORD
STDCALL
NtUserUpdateLayeredWindow(
@ -1715,10 +1693,6 @@ STDCALL
NtUserValidateHandleSecure(
DWORD Unknown0);
VOID STDCALL
NtUserValidateRect(HWND Wnd, const RECT* Rect);
DWORD
STDCALL
NtUserVkKeyScanEx(

View file

@ -102,7 +102,7 @@ typedef struct _FDINFO
#define fdinfo_bucket_idx(i) ((i) >> FDINFO_ENTRIES_PER_BUCKET_SHIFT)
/* get position inside a bucket (0-31) from an fd */
#define fdinfo_bucket_entry_idx(i) ((i) & (FDINFO_ENTRIES_PER_BUCKET - 1))
/* get bucket ptr. (ptr. to fist fdinfo inside a bucket) from an fd */
/* get bucket ptr. (ptr. to first fdinfo inside a bucket) from an fd */
#define fdinfo_bucket(i) ( __pioinfo[fdinfo_bucket_idx(i)])
/* get fdinfo ptr. from an fd */
#define fdinfo(i) (fdinfo_bucket(i) + fdinfo_bucket_entry_idx(i))

View file

@ -347,6 +347,12 @@ RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable,
if (HashLink != NULL)
{
ULONG AtomNameLen = wcslen(AtomName);
if (AtomNameLen > MAX_ATOM_LEN)
{
Status = STATUS_INVALID_PARAMETER;
goto end;
}
Entry = RtlpAllocAtomTableEntry(sizeof(RTL_ATOM_TABLE_ENTRY) -
sizeof(Entry->Name) +
@ -390,7 +396,7 @@ RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable,
Status = STATUS_OBJECT_NAME_INVALID;
}
}
end:
RtlpUnlockAtomTable(AtomTable);
return Status;
@ -592,6 +598,8 @@ RtlQueryAtomInAtomTable(PRTL_ATOM_TABLE AtomTable,
PULONG NameLength)
{
ULONG Length;
BOOL Unlock = FALSE;
union
{
/* A RTL_ATOM_TABLE_ENTRY has a "WCHAR Name[1]" entry at the end.
@ -616,6 +624,7 @@ RtlQueryAtomInAtomTable(PRTL_ATOM_TABLE AtomTable,
else
{
RtlpLockAtomTable(AtomTable);
Unlock = TRUE;
Entry = RtlpGetAtomEntry(AtomTable,
(ULONG)((USHORT)Atom - 0xC000));
@ -676,10 +685,7 @@ RtlQueryAtomInAtomTable(PRTL_ATOM_TABLE AtomTable,
Status = STATUS_INVALID_HANDLE;
}
if (NULL != Entry && Entry != &NumberEntry.AtomTableEntry)
{
RtlpUnlockAtomTable(AtomTable);
}
if (Unlock) RtlpUnlockAtomTable(AtomTable);
return Status;
}

View file

@ -108,7 +108,7 @@ GetCaretPos(LPPOINT lpPoint)
BOOL STDCALL
HideCaret(HWND hWnd)
{
return (BOOL)NtUserHideCaret(hWnd);
return NtUserShowCaret(hWnd, FALSE);
}
@ -139,7 +139,7 @@ SetCaretPos(int X,
BOOL STDCALL
ShowCaret(HWND hWnd)
{
return (BOOL)NtUserShowCaret(hWnd);
return NtUserShowCaret(hWnd, TRUE);
}
/* EOF */

View file

@ -87,7 +87,14 @@ static BOOL GetClassInfoExCommon(
w.lpszMenuName = (LPCWSTR)&str2;
w.lpszClassName = (LPCWSTR)&str3;
/* get info about system classes? */
if (!hInst) hInst = User32Instance;
retval = (BOOL)NtUserGetClassInfo(hInst, str, &w, TRUE, 0);
w.hInstance = (hInst == User32Instance) ? 0 : hInst;
if ( !IS_ATOM(str) )
HEAP_free(str);

View file

@ -157,7 +157,7 @@ InvalidateRect(
CONST RECT *lpRect,
BOOL bErase)
{
return NtUserInvalidateRect( hWnd, lpRect, bErase );
return RedrawWindow( hWnd, lpRect, 0, RDW_INVALIDATE | (bErase ? RDW_ERASE : 0) );
}
@ -171,7 +171,7 @@ InvalidateRgn(
HRGN hRgn,
BOOL bErase)
{
return NtUserInvalidateRgn( hWnd, hRgn, bErase );
return RedrawWindow(hWnd, NULL, hRgn, RDW_INVALIDATE | (bErase ? RDW_ERASE : 0) );
}
@ -224,7 +224,7 @@ STDCALL
UpdateWindow(
HWND hWnd)
{
return NtUserUpdateWindow( hWnd );
return RedrawWindow( hWnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
}
@ -237,6 +237,8 @@ ValidateRect(
HWND hWnd,
CONST RECT *lpRect)
{
/* FIXME: should RDW_NOCHILDREN be included too? Ros used to,
but Wine dont so i removed it... */
return RedrawWindow(hWnd, lpRect, 0, RDW_VALIDATE);
}
@ -250,7 +252,9 @@ ValidateRgn(
HWND hWnd,
HRGN hRgn)
{
return NtUserValidateRgn(hWnd, hRgn);
/* FIXME: should RDW_NOCHILDREN be included too? Ros used to,
but Wine dont so i removed it... */
return RedrawWindow( hWnd, NULL, hRgn, RDW_VALIDATE );
}

View file

@ -221,7 +221,7 @@ CreateWindowExA(DWORD dwExStyle,
nHeight,
hWndParent,
hMenu,
hInstance,
hInstance,
lpParam,
SW_SHOW,
FALSE);
@ -304,7 +304,7 @@ CreateWindowExW(DWORD dwExStyle,
nHeight,
hWndParent,
hMenu,
hInstance,
hInstance,
lpParam,
SW_SHOW,
TRUE);

View file

@ -14,6 +14,7 @@
#define NDEBUG
#include <internal/debug.h>
/* PROTOTYPES ****************************************************************/
static PRTL_ATOM_TABLE RtlpGetGlobalAtomTable(VOID);
@ -38,6 +39,12 @@ RtlQueryAtomListInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
/* GLOBALS *******************************************************************/
/* FIXME: this is WRONG! The global atom table should live in the WinSta struct
* and accessed thru win32k callouts.
* NOTE: There is a session/win32k global atom table also, but its private to
* win32k. Its used for RegisterWindowMessage() and for window classes.
* -Gunnar
*/
static PRTL_ATOM_TABLE GlobalAtomTable = NULL;
/* FUNCTIONS *****************************************************************/

View file

@ -7,6 +7,7 @@
typedef struct _WNDCLASS_OBJECT
{
UINT cbSize;
LONG refs; /* windows using this class (is 0 after class creation) */
UINT style;
WNDPROC lpfnWndProcA;
WNDPROC lpfnWndProcW;
@ -21,10 +22,8 @@ typedef struct _WNDCLASS_OBJECT
HICON hIconSm;
BOOL Unicode;
BOOL Global;
LIST_ENTRY ListEntry;
LIST_ENTRY ListEntry; /* linked into owning process */
PCHAR ExtraData;
/* list of windows */
LIST_ENTRY ClassWindowsListHead;
} WNDCLASS_OBJECT, *PWNDCLASS_OBJECT;
NTSTATUS FASTCALL
@ -33,24 +32,26 @@ InitClassImpl(VOID);
NTSTATUS FASTCALL
CleanupClassImpl(VOID);
#define ClassDereferenceObject(ClassObj) \
ObmDereferenceObject(ClassObj)
void FASTCALL DestroyProcessClasses(PW32PROCESS Process );
BOOL FASTCALL
ClassReferenceClassByAtom(
PWNDCLASS_OBJECT* Class,
inline VOID FASTCALL
ClassDerefObject(PWNDCLASS_OBJECT Class);
inline VOID FASTCALL
ClassRefObject(PWNDCLASS_OBJECT Class);
PWNDCLASS_OBJECT FASTCALL
ClassGetClassByAtom(
RTL_ATOM Atom,
HINSTANCE hInstance);
BOOL FASTCALL
ClassReferenceClassByName(
PWNDCLASS_OBJECT *Class,
PWNDCLASS_OBJECT FASTCALL
ClassGetClassByName(
LPCWSTR ClassName,
HINSTANCE hInstance);
BOOL FASTCALL
ClassReferenceClassByNameOrAtom(
PWNDCLASS_OBJECT *Class,
PWNDCLASS_OBJECT FASTCALL
ClassGetClassByNameOrAtom(
LPCWSTR ClassNameOrAtom,
HINSTANCE hInstance);

View file

@ -11,7 +11,7 @@ typedef struct _DESKTOP_OBJECT
CSHORT Type;
CSHORT Size;
LIST_ENTRY ListEntry;
KSPIN_LOCK Lock;
UNICODE_STRING Name;
/* Pointer to the associated window station. */
struct _WINSTATION_OBJECT *WindowStation;

View file

@ -22,7 +22,7 @@ typedef struct _W32THREAD
typedef struct _W32PROCESS
{
LIST_ENTRY ClassListHead;
LIST_ENTRY ClassList;
LIST_ENTRY MenuListHead;
FAST_MUTEX PrivateFontListLock;
LIST_ENTRY PrivateFontListHead;

View file

@ -28,8 +28,6 @@ typedef struct _WINDOW_OBJECT
{
/* Pointer to the window class. */
PWNDCLASS_OBJECT Class;
/* entry in the window list of the class object */
LIST_ENTRY ClassListEntry;
/* Extended style. */
DWORD ExStyle;
/* Window name. */

View file

@ -70,7 +70,7 @@ Win32kProcessCallback(struct _EPROCESS *Process,
{
DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
InitializeListHead(&Win32Process->ClassListHead);
InitializeListHead(&Win32Process->ClassList);
InitializeListHead(&Win32Process->MenuListHead);
@ -99,7 +99,9 @@ Win32kProcessCallback(struct _EPROCESS *Process,
IntCleanupCurIcons(Process, Win32Process);
IntEngCleanupDriverObjs(Process, Win32Process);
CleanupMonitorImpl();
/* no process windows should exist at this point, or the function will assert! */
DestroyProcessClasses(Win32Process);
GDI_CleanupForProcess(Process);

View file

@ -9,17 +9,24 @@
* 10/15/2003 Created
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
/* DEFINES *****************************************************************/
#define MIN_CARETBLINKRATE 100
#define MAX_CARETBLINKRATE 10000
#define DEFAULT_CARETBLINKRATE 530
#define CARET_REGKEY L"\\Registry\\User\\.Default\\Control Panel\\Desktop"
#define CARET_VALUENAME L"CursorBlinkRate"
/* FUNCTIONS *****************************************************************/
static
BOOL FASTCALL
co_IntHideCaret(PTHRDCARETINFO CaretInfo)
{
@ -69,6 +76,7 @@ IntSetCaretBlinkTime(UINT uMSeconds)
return TRUE;
}
static
UINT FASTCALL
IntQueryCaretBlinkRate(VOID)
{
@ -134,6 +142,7 @@ IntQueryCaretBlinkRate(VOID)
return (UINT)Val;
}
static
UINT FASTCALL
IntGetCaretBlinkTime(VOID)
{
@ -158,6 +167,7 @@ IntGetCaretBlinkTime(VOID)
return Ret;
}
BOOL FASTCALL
co_IntSetCaretPos(int X, int Y)
{
@ -197,6 +207,8 @@ IntSwitchCaretShowing(PVOID Info)
return FALSE;
}
#if 0 //unused
static
VOID FASTCALL
co_IntDrawCaret(HWND hWnd)
{
@ -210,9 +222,79 @@ co_IntDrawCaret(HWND hWnd)
ThreadQueue->CaretInfo->Showing = 1;
}
}
#endif
BOOL FASTCALL co_UserHideCaret(PWINDOW_OBJECT Window OPTIONAL)
{
PUSER_MESSAGE_QUEUE ThreadQueue;
if (Window) ASSERT_REFS_CO(Window);
if(Window && Window->OwnerThread != PsGetCurrentThread())
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
if(Window && ThreadQueue->CaretInfo->hWnd != Window->hSelf)
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
if(ThreadQueue->CaretInfo->Visible)
{
IntKillTimer(ThreadQueue->CaretInfo->hWnd, IDCARETTIMER, TRUE);
co_IntHideCaret(ThreadQueue->CaretInfo);
ThreadQueue->CaretInfo->Visible = 0;
ThreadQueue->CaretInfo->Showing = 0;
}
return TRUE;
}
BOOL FASTCALL co_UserShowCaret(PWINDOW_OBJECT Window OPTIONAL)
{
PUSER_MESSAGE_QUEUE ThreadQueue;
if (Window) ASSERT_REFS_CO(Window);
if(Window && Window->OwnerThread != PsGetCurrentThread())
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
if(Window && ThreadQueue->CaretInfo->hWnd != Window->hSelf)
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
if(!ThreadQueue->CaretInfo->Visible)
{
ThreadQueue->CaretInfo->Visible = 1;
if(!ThreadQueue->CaretInfo->Showing)
{
co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
}
IntSetTimer(ThreadQueue->CaretInfo->hWnd, IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TRUE);
}
return TRUE;
}
/* SYSCALLS *****************************************************************/
BOOL
STDCALL
NtUserCreateCaret(
@ -317,105 +399,10 @@ CLEANUP:
}
BOOL FASTCALL co_UserHideCaret(PWINDOW_OBJECT Window OPTIONAL)
{
PUSER_MESSAGE_QUEUE ThreadQueue;
if (Window) ASSERT_REFS_CO(Window);
if(Window && Window->OwnerThread != PsGetCurrentThread())
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
if(Window && ThreadQueue->CaretInfo->hWnd != Window->hSelf)
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
if(ThreadQueue->CaretInfo->Visible)
{
IntKillTimer((Window ? Window->hSelf : 0), IDCARETTIMER, TRUE);
co_IntHideCaret(ThreadQueue->CaretInfo);
ThreadQueue->CaretInfo->Visible = 0;
ThreadQueue->CaretInfo->Showing = 0;
}
return TRUE;
}
BOOL
STDCALL
NtUserHideCaret(HWND hWnd OPTIONAL)
{
PWINDOW_OBJECT Window = NULL;
DECLARE_RETURN(BOOL);
BOOL ret;
DPRINT("Enter NtUserHideCaret\n");
UserEnterExclusive();
if(hWnd && !(Window = UserGetWindowObject(hWnd)))
{
RETURN(FALSE);
}
if (Window) UserRefObjectCo(Window);
ret = co_UserHideCaret(Window);
if (Window) UserDerefObjectCo(Window);
RETURN(ret);
CLEANUP:
DPRINT("Leave NtUserHideCaret, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
BOOL FASTCALL co_UserShowCaret(PWINDOW_OBJECT Window OPTIONAL)
{
PUSER_MESSAGE_QUEUE ThreadQueue;
if (Window) ASSERT_REFS_CO(Window);
if(Window && Window->OwnerThread != PsGetCurrentThread())
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
if(Window && ThreadQueue->CaretInfo->hWnd != Window->hSelf)
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
if(!ThreadQueue->CaretInfo->Visible)
{
ThreadQueue->CaretInfo->Visible = 1;
if(!ThreadQueue->CaretInfo->Showing)
{
co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
}
IntSetTimer((Window ? Window->hSelf : 0), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TRUE);
}
return TRUE;
}
BOOL
STDCALL
NtUserShowCaret(HWND hWnd OPTIONAL)
NtUserShowCaret(HWND hWnd OPTIONAL, BOOL bShow)
{
PWINDOW_OBJECT Window = NULL;
DECLARE_RETURN(BOOL);
@ -430,7 +417,12 @@ NtUserShowCaret(HWND hWnd OPTIONAL)
}
if (Window) UserRefObjectCo(Window);
ret = co_UserShowCaret(Window);
if (bShow)
ret = co_UserShowCaret(Window);
else
ret = co_UserHideCaret(Window);
if (Window) UserDerefObjectCo(Window);
RETURN(ret);

View file

@ -47,64 +47,85 @@ CleanupClassImpl(VOID)
return(STATUS_SUCCESS);
}
BOOL FASTCALL
ClassReferenceClassByAtom(
PWNDCLASS_OBJECT* Class,
RTL_ATOM Atom,
HINSTANCE hInstance)
/* return TRUE if class became destroyed */
inline VOID FASTCALL
ClassDerefObject(PWNDCLASS_OBJECT Class)
{
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;
ASSERT(Class->refs >= 1);
Class->refs--;
}
BOOL FASTCALL
ClassReferenceClassByName(
PWNDCLASS_OBJECT *Class,
LPCWSTR ClassName,
HINSTANCE hInstance)
inline VOID FASTCALL
ClassRefObject(PWNDCLASS_OBJECT Class)
{
PWINSTATION_OBJECT WinStaObject;
ASSERT(Class->refs >= 0);
Class->refs++;
}
VOID FASTCALL DestroyClass(PWNDCLASS_OBJECT Class)
{
PWINSTATION_OBJECT WinSta;
WinSta = PsGetWin32Thread()->Desktop->WindowStation;
ASSERT(Class->refs == 0);
RemoveEntryList(&Class->ListEntry);
//FIXME: release ATOM
RtlDeleteAtomFromAtomTable(WinSta->AtomTable, Class->Atom);
ExFreePool(Class);
}
/* clean all process classes. all process windows must cleaned first!! */
void FASTCALL DestroyProcessClasses(PW32PROCESS Process )
{
PWNDCLASS_OBJECT Class;
while (!IsListEmpty(&Process->ClassList))
{
Class = CONTAINING_RECORD(RemoveHeadList(&Process->ClassList), WNDCLASS_OBJECT, ListEntry);
DestroyClass(Class);
}
}
PWNDCLASS_OBJECT FASTCALL
ClassGetClassByAtom(RTL_ATOM Atom, HINSTANCE hInstance)
{
PWNDCLASS_OBJECT Class;
PW32PROCESS Process = PsGetWin32Process();
LIST_FOR_EACH(Class, &Process->ClassList, WNDCLASS_OBJECT, ListEntry)
{
if (Class->Atom != Atom) continue;
if (!hInstance || Class->Global || Class->hInstance == hInstance) return Class;
}
return NULL;
}
PWNDCLASS_OBJECT FASTCALL
ClassGetClassByName(LPCWSTR ClassName, HINSTANCE hInstance)
{
PWINSTATION_OBJECT WinSta;
NTSTATUS Status;
BOOL Found;
RTL_ATOM ClassAtom;
RTL_ATOM Atom;
if (!ClassName || !PsGetWin32Thread()->Desktop)
return FALSE;
WinStaObject = PsGetWin32Thread()->Desktop->WindowStation;
WinSta = PsGetWin32Thread()->Desktop->WindowStation;
Status = RtlLookupAtomInAtomTable(
WinStaObject->AtomTable,
WinSta->AtomTable,
(LPWSTR)ClassName,
&ClassAtom);
&Atom);
if (!NT_SUCCESS(Status))
{
@ -112,369 +133,136 @@ ClassReferenceClassByName(
return FALSE;
}
Found = ClassReferenceClassByAtom(Class, ClassAtom, hInstance);
return Found;
return ClassGetClassByAtom(Atom, hInstance);
}
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);
Length += sizeof(WCHAR);
Name = ExAllocatePoolWithTag(PagedPool, Length, 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 Window;
DECLARE_RETURN(DWORD);
UserEnterShared();
DPRINT("Enter NtUserGetClassName\n");
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(0);
}
RETURN( IntGetClassName(Window, lpClassName, nMaxCount));
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(
ClassGetClassByNameOrAtom(LPCWSTR ClassNameOrAtom, HINSTANCE hInstance)
{
if (!ClassNameOrAtom) return NULL;
if (IS_ATOM(ClassNameOrAtom))
return ClassGetClassByAtom((RTL_ATOM)((ULONG_PTR)ClassNameOrAtom), hInstance);
else
return ClassGetClassByName(ClassNameOrAtom, hInstance);
}
static
BOOL FASTCALL
IntRegisterClass(
CONST WNDCLASSEXW *lpwcx,
DWORD Flags,
WNDPROC wpExtra,
PUNICODE_STRING MenuName,
RTL_ATOM Atom)
{
PWNDCLASS_OBJECT ClassObject;
PWNDCLASS_OBJECT Class;
ULONG objectSize;
BOOL Global;
Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS) ? TRUE : FALSE;
ASSERT(lpwcx);
ASSERT(Atom);
ASSERT(lpwcx->hInstance);
Global = (Flags & REGISTERCLASS_SYSTEM) || (lpwcx->style & CS_GLOBALCLASS);
/* Check for double registration of the class. */
if (PsGetWin32Process() != NULL)
Class = ClassGetClassByAtom(Atom, lpwcx->hInstance);
if (Class && Global == Class->Global)
{
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);
}
}
/* can max have one class of each type (global/local) */
SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
return(FALSE);
}
objectSize = sizeof(WNDCLASS_OBJECT) + lpwcx->cbClsExtra;
ClassObject = ObmCreateObject(&gHandleTable, NULL, otClass, objectSize);
if (ClassObject == 0)
//FIXME: allocate in session heap (or possibly desktop heap)
Class = ExAllocatePool(PagedPool, objectSize);
if (!Class)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return(NULL);
return(FALSE);
}
RtlZeroMemory(Class, objectSize);
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;
Class->cbSize = lpwcx->cbSize;
Class->style = lpwcx->style;
Class->cbClsExtra = lpwcx->cbClsExtra;
Class->cbWndExtra = lpwcx->cbWndExtra;
Class->hInstance = lpwcx->hInstance;
Class->hIcon = lpwcx->hIcon;
Class->hCursor = lpwcx->hCursor;
Class->hbrBackground = lpwcx->hbrBackground;
Class->Unicode = !(Flags & REGISTERCLASS_ANSI);
Class->Global = Global;
Class->hIconSm = lpwcx->hIconSm;
Class->Atom = Atom;
if (wpExtra == NULL)
{
if (Flags & REGISTERCLASS_ANSI)
{
ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
ClassObject->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
Class->lpfnWndProcA = lpwcx->lpfnWndProc;
Class->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
}
else
{
ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
ClassObject->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
Class->lpfnWndProcW = lpwcx->lpfnWndProc;
Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
}
}
else
{
if (Flags & REGISTERCLASS_ANSI)
{
ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
ClassObject->lpfnWndProcW = wpExtra;
Class->lpfnWndProcA = lpwcx->lpfnWndProc;
Class->lpfnWndProcW = wpExtra;
}
else
{
ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
ClassObject->lpfnWndProcA = wpExtra;
Class->lpfnWndProcW = lpwcx->lpfnWndProc;
Class->lpfnWndProcA = wpExtra;
}
}
if (MenuName->Length == 0)
{
ClassObject->lpszMenuName.Length =
ClassObject->lpszMenuName.MaximumLength = 0;
ClassObject->lpszMenuName.Buffer = MenuName->Buffer;
Class->lpszMenuName.Length =
Class->lpszMenuName.MaximumLength = 0;
Class->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);
Class->lpszMenuName.Length =
Class->lpszMenuName.MaximumLength = MenuName->MaximumLength;
Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Class->lpszMenuName.MaximumLength, TAG_STRING);
RtlCopyUnicodeString(&Class->lpszMenuName, MenuName);
}
/* Extra class data */
if (ClassObject->cbClsExtra != 0)
if (Class->cbClsExtra)
Class->ExtraData = (PCHAR)(Class + 1);
if (Global)
{
ClassObject->ExtraData = (PCHAR)(ClassObject + 1);
RtlZeroMemory(ClassObject->ExtraData, (ULONG)ClassObject->cbClsExtra);
/* global classes go last (incl. system classes) */
InsertTailList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
}
else
{
ClassObject->ExtraData = NULL;
/* local classes have priority so we put them first */
InsertHeadList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
}
InitializeListHead(&ClassObject->ClassWindowsListHead);
return(ClassObject);
return TRUE;
}
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 *Window, ULONG Offset, BOOL Ansi)
IntGetClassLong(PWINDOW_OBJECT Window, ULONG Offset, BOOL Ansi)
{
LONG Ret;
@ -540,28 +328,7 @@ IntGetClassLong(struct _WINDOW_OBJECT *Window, ULONG Offset, BOOL Ansi)
return(Ret);
}
DWORD STDCALL
NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
{
PWINDOW_OBJECT Window;
DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserGetClassLong\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(0);
}
RETURN(IntGetClassLong(Window, Offset, Ansi));
CLEANUP:
DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
static
void FASTCALL
co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi)
{
@ -643,6 +410,144 @@ co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ans
break;
}
}
/* SYSCALLS *****************************************************************/
RTL_ATOM STDCALL
NtUserRegisterClassExWOW(
CONST WNDCLASSEXW* lpwcx,
PUNICODE_STRING ClassName,
PUNICODE_STRING ClassNameCopy,//huhuhuhu???
PUNICODE_STRING MenuName,
WNDPROC wpExtra,
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 WinSta;
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);
}
if (!lpwcx->hInstance)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( (RTL_ATOM)0);
}
WinSta = PsGetWin32Thread()->Desktop->WindowStation;
//FIXME: make ClassName ptr the atom, not buffer
if (ClassName->Length > 0)
{
DPRINT("NtUserRegisterClassExWOW(%S)\n", ClassName->Buffer);
/* FIXME - Safely copy/verify the buffer first!!! */
Status = RtlAddAtomToAtomTable(WinSta->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;
}
if (!Atom)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN(0);
}
if (!IntRegisterClass(&SafeClass, Flags, wpExtra, MenuName, Atom))
{
if (ClassName->Length)
{
RtlDeleteAtomFromAtomTable(WinSta->AtomTable, Atom);
}
DPRINT("Failed creating window class object\n");
RETURN((RTL_ATOM)0);
}
RETURN(Atom);
CLEANUP:
DPRINT("Leave NtUserRegisterClassExWOW, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD STDCALL
NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
{
PWINDOW_OBJECT Window;
DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserGetClassLong\n");
UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(0);
}
RETURN(IntGetClassLong(Window, Offset, Ansi));
CLEANUP:
DPRINT("Leave NtUserGetClassLong, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD STDCALL
NtUserSetClassLong(HWND hWnd,
@ -689,56 +594,50 @@ NtUserSetClassWord(DWORD Unknown0,
BOOL STDCALL
NtUserUnregisterClass(
LPCWSTR ClassNameOrAtom,
HINSTANCE hInstance,
HINSTANCE hInstance, /* can be 0 */
DWORD Unknown)
{
PWNDCLASS_OBJECT Class;
PWINSTATION_OBJECT WinSta;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
UserEnterExclusive();
if (!ClassNameOrAtom || !PsGetWin32Thread()->Desktop)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( FALSE);
}
WinSta = PsGetWin32Thread()->Desktop->WindowStation;
if (!ClassReferenceClassByNameOrAtom(&Class, ClassNameOrAtom, hInstance))
if (!ClassNameOrAtom)
{
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
RETURN( FALSE);
RETURN(FALSE);
}
if (Class->hInstance && Class->hInstance != hInstance)
if (!(Class = ClassGetClassByNameOrAtom(ClassNameOrAtom, hInstance)))
{
ClassDereferenceObject(Class);
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
RETURN( FALSE);
RETURN(FALSE);
}
if (!IsListEmpty(&Class->ClassWindowsListHead))
/* this was probably ment to prevent sysclass dereg
Seems wrong. Any class can have NULL hInst, not only sysclasses
*/
// if (Class->hInstance && Class->hInstance != hInstance)
// {
// SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST);
// RETURN( FALSE);
// }
if (Class->refs)
{
/* Dereference the ClassReferenceClassByNameOrAtom() call */
ObmDereferenceObject(Class);
/* NOTE: the class will not be freed when its refs become 0 ie. no more
* windows are using it. I dunno why that is but its how Windows does it (and Wine).
* The class will hang around until the process exit. -Gunnar
*/
SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
RETURN( FALSE);
RETURN(FALSE);
}
/* Dereference the ClassReferenceClassByNameOrAtom() call */
ClassDereferenceObject(Class);
RemoveEntryList(&Class->ListEntry);
RtlDeleteAtomFromAtomTable(WinSta->AtomTable, Class->Atom);
/* Free the object */
ClassDereferenceObject(Class);
RETURN( TRUE);
DestroyClass(Class);
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_);
@ -746,4 +645,119 @@ CLEANUP:
END_CLEANUP;
}
/* NOTE: for system classes hInstance is not NULL here, but User32Instance */
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 (!hInstance)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN(0);
}
if (!(Class = ClassGetClassByNameOrAtom(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. */
/* Well, i think its wrong so i changed it -Gunnar */
lpWndClassEx->hInstance = Class->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;
RETURN(Atom);
CLEANUP:
DPRINT("Leave NtUserGetClassInfo, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD STDCALL
NtUserGetClassName (
HWND hWnd,
LPWSTR lpClassName,
ULONG nMaxCount /* in TCHARS */
)
{
PWINDOW_OBJECT Window;
DECLARE_RETURN(DWORD);
PWINSTATION_OBJECT WinSta;
NTSTATUS Status;
UserEnterShared();
DPRINT("Enter NtUserGetClassName\n");
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(0);
}
WinSta = PsGetWin32Thread()->Desktop->WindowStation;
nMaxCount *= sizeof(WCHAR);
//FIXME: wrap in SEH to protect lpClassName access
Status = RtlQueryAtomInAtomTable(WinSta->AtomTable,
Window->Class->Atom, NULL, NULL,
lpClassName, &nMaxCount);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN(0);
}
RETURN(nMaxCount / sizeof(WCHAR));
CLEANUP:
DPRINT("Leave NtUserGetClassName, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD STDCALL
NtUserGetWOWClass(DWORD Unknown0,
DWORD Unknown1)
{
UNIMPLEMENTED;
return(0);
}
/* EOF */

View file

@ -95,30 +95,6 @@ PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
return CurIcon;
}
#if 0
static
PCURICON_OBJECT FASTCALL IntGetCurIconObject(HCURSOR hCursor)
{
PCURICON_OBJECT Cursor;
if (!hCursor) return NULL;
Cursor = (PCURICON_OBJECT)UserGetObject(&gHandleTable, hCursor, otCursorIcon);
if (!Cursor)
{
SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
return NULL;
}
ASSERT(USER_BODY_TO_HEADER(Cursor)->RefCount >= 0);
USER_BODY_TO_HEADER(Cursor)->RefCount++;
return Cursor;
}
#endif
#define COLORCURSORS_ALLOWED FALSE
HCURSOR FASTCALL
@ -355,21 +331,17 @@ static BOOLEAN FASTCALL
ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
{
PW32PROCESS Win32Process;
PLIST_ENTRY Search;
PCURICON_PROCESS Current;
Win32Process = PsGetWin32Process();
Search = CurIcon->ProcessList.Flink;
while (Search != &CurIcon->ProcessList)
LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
{
Current = CONTAINING_RECORD(Search, CURICON_PROCESS, ListEntry);
if (Current->Process == Win32Process)
{
/* Already registered for this process */
return TRUE;
}
Search = Search->Flink;
}
/* Not registered yet */
@ -388,14 +360,10 @@ PCURICON_OBJECT FASTCALL
IntFindExistingCurIconObject(PWINSTATION_OBJECT WinSta, HMODULE hModule,
HRSRC hRsrc, LONG cx, LONG cy)
{
PLIST_ENTRY CurrentEntry;
PCURICON_OBJECT CurIcon;
CurrentEntry = gCurIconList.Flink;
while (CurrentEntry != &gCurIconList)
LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
{
CurIcon = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry);
CurrentEntry = CurrentEntry->Flink;
// if(NT_SUCCESS(ObmReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
// ObmReferenceObject( CurIcon);
@ -460,7 +428,6 @@ IntDestroyCurIconObject(PWINSTATION_OBJECT WinSta, PCURICON_OBJECT CurIcon, BOOL
PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor;
BOOLEAN Ret;
PLIST_ENTRY Search;
PCURICON_PROCESS Current = NULL;
PW32PROCESS W32Process = PsGetWin32Process();
@ -483,18 +450,15 @@ IntDestroyCurIconObject(PWINSTATION_OBJECT WinSta, PCURICON_OBJECT CurIcon, BOOL
/* Now find this process in the list of processes referencing this object and
remove it from that list */
Search = CurIcon->ProcessList.Flink;
while (Search != &CurIcon->ProcessList)
LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
{
Current = CONTAINING_RECORD(Search, CURICON_PROCESS, ListEntry);
if (Current->Process == W32Process)
{
RemoveEntryList(&Current->ListEntry);
break;
}
Search = Search->Flink;
}
ASSERT(Search != &CurIcon->ProcessList);
RemoveEntryList(Search);
ExFreeToPagedLookasideList(&gProcessLookasideList, Current);
/* If there are still processes referencing this object we can't destroy it yet */
@ -541,9 +505,7 @@ VOID FASTCALL
IntCleanupCurIcons(struct _EPROCESS *Process, PW32PROCESS Win32Process)
{
PWINSTATION_OBJECT WinSta;
PLIST_ENTRY CurrentEntry;
PCURICON_OBJECT CurIcon;
PLIST_ENTRY ProcessEntry;
PCURICON_OBJECT CurIcon, tmp;
PCURICON_PROCESS ProcessData;
WinSta = IntGetWinStaObj();
@ -552,27 +514,19 @@ IntCleanupCurIcons(struct _EPROCESS *Process, PW32PROCESS Win32Process)
return;
}
CurrentEntry = gCurIconList.Flink;
while (CurrentEntry != &gCurIconList)
LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
{
CurIcon = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry);
CurrentEntry = CurrentEntry->Flink;
// ObmReferenceObject(CurIcon);
// if(NT_SUCCESS(ObmReferenceObjectByPointer(Object, otCursorIcon)))
{
ProcessEntry = CurIcon->ProcessList.Flink;
while (ProcessEntry != &CurIcon->ProcessList)
LIST_FOR_EACH(ProcessData, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
{
ProcessData = CONTAINING_RECORD(ProcessEntry, CURICON_PROCESS, ListEntry);
if (Win32Process == ProcessData->Process)
{
RemoveEntryList(&CurIcon->ListEntry);
IntDestroyCurIconObject(WinSta, CurIcon, TRUE);
break;
}
ProcessEntry = ProcessEntry->Flink;
}
// ObmDereferenceObject(Object);

View file

@ -96,18 +96,16 @@ IntDesktopObjectCreate(PVOID ObjectBody,
RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
KeInitializeSpinLock(&Desktop->Lock);
InitializeListHead(&Desktop->ShellHookWindows);
Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
/* Put the desktop on the window station's list of associcated desktops */
ExInterlockedInsertTailList(
// ExInterlocked
InsertTailList(
&Desktop->WindowStation->DesktopListHead,
&Desktop->ListEntry,
&Desktop->WindowStation->Lock);
&Desktop->ListEntry);//,
// &Desktop->WindowStation->Lock);
return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
}
@ -116,20 +114,41 @@ VOID STDCALL
IntDesktopObjectDelete(PVOID DeletedObject)
{
PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject;
KIRQL OldIrql;
DPRINT("Deleting desktop (0x%X)\n", Desktop);
/* Remove the desktop from the window station's list of associcated desktops */
KeAcquireSpinLock(&Desktop->WindowStation->Lock, &OldIrql);
RemoveEntryList(&Desktop->ListEntry);
KeReleaseSpinLock(&Desktop->WindowStation->Lock, OldIrql);
RtlFreeUnicodeString(&Desktop->Name);
}
/* PRIVATE FUNCTIONS **********************************************************/
static int GetSystemVersionString(LPWSTR buffer)
{
RTL_OSVERSIONINFOEXW versionInfo;
int len;
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
return 0;
if (versionInfo.dwMajorVersion <= 4)
len = swprintf(buffer,
L"ReactOS Version %d.%d %s Build %d",
versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
else
len = swprintf(buffer,
L"ReactOS %s (Build %d)",
versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
return len;
}
NTSTATUS FASTCALL
IntParseDesktopPath(PEPROCESS Process,
PUNICODE_STRING DesktopPath,
@ -562,6 +581,37 @@ IntHideDesktop(PDESKTOP_OBJECT Desktop)
#endif
}
static
HWND* FASTCALL
UserBuildShellHookHwndList(PDESKTOP_OBJECT Desktop)
{
ULONG entries=0;
PSHELL_HOOK_WINDOW Current;
HWND* list;
/* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
entries++;
if (!entries) return NULL;
list = ExAllocatePool(PagedPool, sizeof(HWND) * (entries + 1)); /* alloc one extra for nullterm */
if (list)
{
HWND* cursor = list;
LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
*cursor++ = Current->hWnd;
*cursor = NULL; /* nullterm list */
}
return list;
}
/*
* Send the Message to the windows registered for ShellHook
* notifications. The lParam contents depend on the Message. See
@ -570,9 +620,7 @@ IntHideDesktop(PDESKTOP_OBJECT Desktop)
VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
{
PDESKTOP_OBJECT Desktop = IntGetActiveDesktop();
PLIST_ENTRY Entry, Entry2;
PSHELL_HOOK_WINDOW Current;
KIRQL OldLevel;
HWND* HwndList;
static UINT MsgType = 0;
@ -599,43 +647,23 @@ VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
return;
}
/* We have to do some tricks because the list could change
* between calls, and we can't keep the lock during the call
*/
KeAcquireSpinLock(&Desktop->Lock, &OldLevel);
Entry = Desktop->ShellHookWindows.Flink;
while (Entry != &Desktop->ShellHookWindows)
HwndList = UserBuildShellHookHwndList(Desktop);
if (HwndList)
{
Current = CONTAINING_RECORD(Entry, SHELL_HOOK_WINDOW, ListEntry);
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
DPRINT("Sending notify\n");
co_IntPostOrSendMessage(Current->hWnd,
MsgType,
Message,
lParam);
/* Loop again to find the window we were sending to. If it doesn't
* exist anymore, we just stop. This could leave an infinite loop
* if a window is removed and readded to the list. That's quite
* unlikely though.
*/
KeAcquireSpinLock(&Desktop->Lock, &OldLevel);
Entry2 = Desktop->ShellHookWindows.Flink;
while (Entry2 != Entry &&
Entry2 != &Desktop->ShellHookWindows)
HWND* cursor = HwndList;
for (; *cursor; cursor++)
{
Entry2 = Entry2->Flink;
DPRINT("Sending notify\n");
co_IntPostOrSendMessage(*cursor,
MsgType,
Message,
lParam);
}
if (Entry2 == Entry)
Entry = Entry->Flink;
else
break;
ExFreePool(HwndList);
}
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
}
/*
@ -650,7 +678,6 @@ BOOL IntRegisterShellHookWindow(HWND hWnd)
{
PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
PSHELL_HOOK_WINDOW Entry;
KIRQL OldLevel;
DPRINT("IntRegisterShellHookWindow\n");
@ -659,20 +686,16 @@ BOOL IntRegisterShellHookWindow(HWND hWnd)
*/
IntDeRegisterShellHookWindow(hWnd);
Entry = ExAllocatePoolWithTag(NonPagedPool,
Entry = ExAllocatePoolWithTag(PagedPool,
sizeof(SHELL_HOOK_WINDOW),
TAG_WINSTA);
/* We have to walk this structure with while holding a spinlock, so we
* need NonPagedPool */
if (!Entry)
return FALSE;
Entry->hWnd = hWnd;
KeAcquireSpinLock(&Desktop->Lock, &OldLevel);
InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
return TRUE;
}
@ -685,31 +708,27 @@ BOOL IntRegisterShellHookWindow(HWND hWnd)
BOOL IntDeRegisterShellHookWindow(HWND hWnd)
{
PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
PLIST_ENTRY Entry;
PSHELL_HOOK_WINDOW Current;
KIRQL OldLevel;
KeAcquireSpinLock(&Desktop->Lock, &OldLevel);
Entry = Desktop->ShellHookWindows.Flink;
while (Entry != &Desktop->ShellHookWindows)
LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
{
Current = CONTAINING_RECORD(Entry, SHELL_HOOK_WINDOW, ListEntry);
if (Current->hWnd == hWnd)
{
RemoveEntryList(Entry);
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
ExFreePool(Entry);
RemoveEntryList(&Current->ListEntry);
ExFreePool(Current);
return TRUE;
}
Entry = Entry->Flink;
}
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
return FALSE;
}
/* SYSCALLS *******************************************************************/
/*
* NtUserCreateDesktop
*
@ -759,7 +778,7 @@ NtUserCreateDesktop(
CSR_API_MESSAGE Request;
DECLARE_RETURN(HDESK);
DPRINT("Enter CreateDesktop: %wZ\n", lpszDesktopName);
DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
UserEnterExclusive();
Status = IntValidateWindowStationHandle(
@ -1035,6 +1054,10 @@ NtUserOpenInputDesktop(
PDESKTOP_OBJECT Object;
NTSTATUS Status;
HDESK Desktop;
DECLARE_RETURN(HDESK);
DPRINT("Enter NtUserOpenInputDesktop\n");
UserEnterExclusive();
DPRINT("About to open input desktop\n");
@ -1049,7 +1072,7 @@ NtUserOpenInputDesktop(
if (!NT_SUCCESS(Status))
{
DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
return (HDESK)0;
RETURN((HDESK)0);
}
/* Create a new handle to the object */
@ -1068,11 +1091,16 @@ NtUserOpenInputDesktop(
if (NT_SUCCESS(Status))
{
DPRINT("Successfully opened input desktop\n");
return (HDESK)Desktop;
RETURN((HDESK)Desktop);
}
SetLastNtError(Status);
return (HDESK)0;
RETURN((HDESK)0);
CLEANUP:
DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
@ -1102,6 +1130,10 @@ NtUserCloseDesktop(HDESK hDesktop)
{
PDESKTOP_OBJECT Object;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserCloseDesktop\n");
UserEnterExclusive();
DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
@ -1114,7 +1146,7 @@ NtUserCloseDesktop(HDESK hDesktop)
if (!NT_SUCCESS(Status))
{
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
return FALSE;
RETURN(FALSE);
}
ObDereferenceObject(Object);
@ -1125,35 +1157,19 @@ NtUserCloseDesktop(HDESK hDesktop)
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
RETURN(FALSE);
}
return TRUE;
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
static int GetSystemVersionString(LPWSTR buffer)
{
RTL_OSVERSIONINFOEXW versionInfo;
int len;
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
return 0;
if (versionInfo.dwMajorVersion <= 4)
len = swprintf(buffer,
L"ReactOS Version %d.%d %s Build %d",
versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
else
len = swprintf(buffer,
L"ReactOS %s (Build %d)",
versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
return len;
}
/*
* NtUserPaintDesktop
@ -1179,6 +1195,10 @@ NtUserPaintDesktop(HDC hDC)
BOOL doPatBlt = TRUE;
PWINDOW_OBJECT WndDesktop;
int len;
DECLARE_RETURN(BOOL);
UserEnterExclusive();
DPRINT("Enter NtUserPaintDesktop\n");
PWINSTATION_OBJECT WinSta = PsGetWin32Thread()->Desktop->WindowStation;
@ -1186,7 +1206,7 @@ NtUserPaintDesktop(HDC hDC)
hWndDesktop = IntGetDesktopWindow();
if (!(WndDesktop = UserGetWindowObject(hWndDesktop)))
return FALSE;
RETURN(FALSE);
DesktopBrush = (HBRUSH)IntGetClassLong(WndDesktop, GCL_HBRBACKGROUND, FALSE); //fixme: verify retval
@ -1277,7 +1297,12 @@ NtUserPaintDesktop(HDC hDC)
}
}
return TRUE;
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
@ -1302,6 +1327,10 @@ NtUserSwitchDesktop(HDESK hDesktop)
{
PDESKTOP_OBJECT DesktopObject;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
UserEnterExclusive();
DPRINT("Enter NtUserSwitchDesktop\n");
DPRINT("About to switch desktop (0x%X)\n", hDesktop);
@ -1314,7 +1343,7 @@ NtUserSwitchDesktop(HDESK hDesktop)
if (!NT_SUCCESS(Status))
{
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
return FALSE;
RETURN(FALSE);
}
/*
@ -1326,7 +1355,7 @@ NtUserSwitchDesktop(HDESK hDesktop)
{
ObDereferenceObject(DesktopObject);
DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
return FALSE;
RETURN(FALSE);
}
/* FIXME: Fail if the desktop belong to an invisible window station */
@ -1344,7 +1373,12 @@ NtUserSwitchDesktop(HDESK hDesktop)
ObDereferenceObject(DesktopObject);
return TRUE;
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
@ -1376,18 +1410,22 @@ NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
PDESKTOP_OBJECT DesktopObject;
HDESK Ret, hThreadDesktop;
OBJECT_HANDLE_INFORMATION HandleInformation;
DECLARE_RETURN(HDESK);
UserEnterExclusive();
DPRINT("Enter NtUserGetThreadDesktop\n");
if(!dwThreadId)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
RETURN(0);
}
Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
if(!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
RETURN(0);
}
if(Thread->ThreadsProcess == PsGetCurrentProcess())
@ -1396,7 +1434,7 @@ NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
in the same context */
Ret = Thread->Tcb.Win32Thread->hDesktop;
ObDereferenceObject(Thread);
return Ret;
RETURN(Ret);
}
/* get the desktop handle and the desktop of the thread */
@ -1405,7 +1443,7 @@ NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
{
ObDereferenceObject(Thread);
DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
return NULL;
RETURN(NULL);
}
/* we could just use DesktopObject instead of looking up the handle, but latter
@ -1425,7 +1463,7 @@ NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
if(!NT_SUCCESS(Status))
{
ObDereferenceObject(Thread);
return NULL;
RETURN(NULL);
}
/* lookup our handle table if we can find a handle to the desktop object,
@ -1435,7 +1473,12 @@ NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
/* all done, we got a valid handle to the desktop */
ObDereferenceObject(DesktopObject);
ObDereferenceObject(Thread);
return Ret;
RETURN(Ret);
CLEANUP:
DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
@ -1451,7 +1494,11 @@ NtUserSetThreadDesktop(HDESK hDesktop)
PW32THREAD W32Thread;
PDESKTOP_OBJECT DesktopObject;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
UserEnterExclusive();
DPRINT("Enter NtUserSetThreadDesktop\n");
/* Validate the new desktop. */
Status = IntValidateDesktopHandle(
hDesktop,
@ -1462,7 +1509,7 @@ NtUserSetThreadDesktop(HDESK hDesktop)
if (!NT_SUCCESS(Status))
{
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
return FALSE;
RETURN(FALSE);
}
W32Thread = PsGetWin32Thread();
@ -1477,7 +1524,12 @@ NtUserSetThreadDesktop(HDESK hDesktop)
W32Thread->Desktop = DesktopObject;
W32Thread->hDesktop = hDesktop;
return TRUE;
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/* EOF */

View file

@ -510,21 +510,6 @@ NtUserCallTwoParam(
UNIMPLEMENTED
RETURN( 0);
case TWOPARAM_ROUTINE_VALIDATERGN:
{
PWINDOW_OBJECT Window = UserGetWindowObject((HWND) Param1);
BOOL ret;
if (!Window)
RETURN(FALSE);
UserRefObjectCo(Window);
ret = co_UserValidateRgn(Window, (HRGN) Param2);
UserDerefObjectCo(Window);
RETURN((DWORD) ret);
}
case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID:
if(!(Window = UserGetWindowObject((HWND)Param1)))

View file

@ -292,11 +292,12 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
{
for (phWnd = List; *phWnd; ++phWnd)
{
Window = IntGetWindowObject(*phWnd);
Window = UserGetWindowObject(*phWnd);
if (Window && (Window->Style & WS_VISIBLE))
{
UserRefObjectCo(Window);
co_IntPaintWindows(Window, Flags);
ObmDereferenceObject(Window);
UserDerefObjectCo(Window);
}
}
ExFreePool(List);
@ -414,31 +415,21 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) &&
((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN)))
{
HWND *List, *phWnd;
PWINDOW_OBJECT Child;
if ((List = IntWinListChildren(Window)))
for (Child = Window->FirstChild; Child; Child = Child->NextSibling)
{
for (phWnd = List; *phWnd; ++phWnd)
if (Child->Style & WS_VISIBLE)
{
if(!(Child = UserGetWindowObject(*phWnd)))
{
continue;
}
if (Child->Style & WS_VISIBLE)
{
/*
* Recursive call to update children UpdateRegion
*/
HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
IntInvalidateWindows(Child, hRgnTemp, Flags);
NtGdiDeleteObject(hRgnTemp);
}
/*
* Recursive call to update children UpdateRegion
*/
HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
IntInvalidateWindows(Child, hRgnTemp, Flags);
NtGdiDeleteObject(hRgnTemp);
}
ExFreePool(List);
}
}
@ -859,69 +850,6 @@ CLEANUP:
END_CLEANUP;
}
/*
* NtUserInvalidateRect
*
* Status
* @implemented
*/
DWORD STDCALL
NtUserInvalidateRect(HWND hWnd, CONST RECT *Rect, BOOL Erase)
{
return NtUserRedrawWindow(hWnd, Rect, 0, RDW_INVALIDATE | (Erase ? RDW_ERASE : 0));
}
/*
* NtUserInvalidateRgn
*
* Status
* @implemented
*/
DWORD STDCALL
NtUserInvalidateRgn(HWND hWnd, HRGN Rgn, BOOL Erase)
{
return NtUserRedrawWindow(hWnd, NULL, Rgn, RDW_INVALIDATE | (Erase ? RDW_ERASE : 0));
}
BOOL FASTCALL
co_UserValidateRgn(PWINDOW_OBJECT Window, HRGN hRgn)
{
return co_UserRedrawWindow(Window, NULL, hRgn, RDW_VALIDATE | RDW_NOCHILDREN);
}
/*
* NtUserValidateRgn
*
* Status
* @implemented
*/
BOOL STDCALL
NtUserValidateRgn(HWND hWnd, HRGN hRgn)
{
return NtUserRedrawWindow(hWnd, NULL, hRgn, RDW_VALIDATE | RDW_NOCHILDREN);
}
/*
* NtUserUpdateWindow
*
* Status
* @implemented
*/
BOOL STDCALL
NtUserUpdateWindow(HWND hWnd)
{
return NtUserRedrawWindow(hWnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
}
INT FASTCALL
co_UserGetUpdateRgn(PWINDOW_OBJECT Window, HRGN hRgn, BOOL bErase)

View file

@ -293,8 +293,12 @@ static void IntSendDestroyMsg(HWND hWnd)
* IntDestroyWindow
*
* Destroy storage associated to a window. "Internals" p.358
*
* This is the "functional" DestroyWindows function ei. all stuff
* done in CreateWindow is undone here and not in DestroyWindow:-P
*/
static LRESULT co_IntDestroyWindow(PWINDOW_OBJECT Window,
static LRESULT co_UserFreeWindow(PWINDOW_OBJECT Window,
PW32PROCESS ProcessData,
PW32THREAD ThreadData,
BOOLEAN SendMessages)
@ -343,7 +347,7 @@ static LRESULT co_IntDestroyWindow(PWINDOW_OBJECT Window,
IntSendDestroyMsg(Child->hSelf);
}
else
co_IntDestroyWindow(Child, ProcessData, ThreadData, SendMessages);
co_UserFreeWindow(Child, ProcessData, ThreadData, SendMessages);
UserDerefObject(Child);
}
@ -427,11 +431,8 @@ static LRESULT co_IntDestroyWindow(PWINDOW_OBJECT Window,
IntDestroyScrollBars(Window);
/* remove the window from the class object */
RemoveEntryList(&Window->ClassListEntry);
/* dereference the class */
ClassDereferenceObject(Window->Class);
ClassDerefObject(Window->Class);
Window->Class = NULL;
if(Window->WindowRegion)
@ -1331,13 +1332,13 @@ co_IntCreateWindowEx(DWORD dwExStyle,
BOOL bUnicodeWindow)
{
PWINSTATION_OBJECT WinSta;
PWNDCLASS_OBJECT Class;
PWNDCLASS_OBJECT Class = NULL;
PWINDOW_OBJECT Window = NULL;
PWINDOW_OBJECT ParentWindow = NULL, OwnerWindow;
HWND ParentWindowHandle;
HWND OwnerWindowHandle;
PMENU_OBJECT SystemMenu;
HANDLE Handle;
HWND hWnd;
POINT Pos;
SIZE Size;
#if 0
@ -1352,7 +1353,6 @@ co_IntCreateWindowEx(DWORD dwExStyle,
CBT_CREATEWNDW CbtCreate;
LRESULT Result;
BOOL MenuChanged;
BOOL ClassFound;
DECLARE_RETURN(HWND);
BOOL HasOwner;
@ -1398,8 +1398,8 @@ co_IntCreateWindowEx(DWORD dwExStyle,
/* FIXME: parent must belong to the current process */
/* Check the class. */
ClassFound = ClassReferenceClassByNameOrAtom(&Class, ClassName->Buffer, hInstance);
if (!ClassFound)
Class = ClassGetClassByNameOrAtom(ClassName->Buffer, hInstance);
if (!Class)
{
if (IS_ATOM(ClassName->Buffer))
{
@ -1414,55 +1414,52 @@ co_IntCreateWindowEx(DWORD dwExStyle,
RETURN((HWND)0);
}
ClassRefObject(Class);
/* Check the window station. */
if (PsGetWin32Thread()->Desktop == NULL)
{
ClassDereferenceObject(Class);
DPRINT("Thread is not attached to a desktop! Cannot create window!\n");
RETURN( (HWND)0);
}
WinSta = PsGetWin32Thread()->Desktop->WindowStation;
//FIXME: Reference thread/desktop instead
ObReferenceObjectByPointer(WinSta, KernelMode, ExWindowStationObjectType, 0);
/* Create the window object. */
Window = (PWINDOW_OBJECT)
ObmCreateObject(&gHandleTable, &Handle,
ObmCreateObject(&gHandleTable, (PHANDLE)&hWnd,
otWindow, sizeof(WINDOW_OBJECT) + Class->cbWndExtra
);
DPRINT("Created object with handle %X\n", Handle);
DPRINT("Created object with handle %X\n", hWnd);
if (!Window)
{
ObDereferenceObject(WinSta);
ClassDereferenceObject(Class);
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
RETURN( (HWND)0);
}
UserRefObjectCo(Window);
ObDereferenceObject(WinSta);
if (NULL == PsGetWin32Thread()->Desktop->DesktopWindow)
{
/* If there is no desktop window yet, we must be creating it */
PsGetWin32Thread()->Desktop->DesktopWindow = Handle;
PsGetWin32Thread()->Desktop->DesktopWindow = hWnd;
}
/*
* Fill out the structure describing it.
*/
Window->Class = Class;
InsertTailList(&Class->ClassWindowsListHead, &Window->ClassListEntry);
Window->SystemMenu = (HMENU)0;
Window->ContextHelpId = 0;
Window->IDMenu = 0;
Window->Instance = hInstance;
Window->hSelf = Handle;
Window->hSelf = hWnd;
if (0 != (dwStyle & WS_CHILD))
{
Window->IDMenu = (UINT) hMenu;
@ -1505,19 +1502,11 @@ co_IntCreateWindowEx(DWORD dwExStyle,
Window->LastChild = NULL;
Window->PrevSibling = NULL;
Window->NextSibling = NULL;
Window->ExtraDataSize = Class->cbWndExtra;
/* extra window data */
if (Class->cbWndExtra != 0)
{
if (Class->cbWndExtra)
Window->ExtraData = (PCHAR)(Window + 1);
Window->ExtraDataSize = Class->cbWndExtra;
RtlZeroMemory(Window->ExtraData, Window->ExtraDataSize);
}
else
{
Window->ExtraData = NULL;
Window->ExtraDataSize = 0;
}
InitializeListHead(&Window->PropListHead);
InitializeListHead(&Window->WndObjListHead);
@ -1530,7 +1519,6 @@ co_IntCreateWindowEx(DWORD dwExStyle,
TAG_STRING);
if (NULL == Window->WindowName.Buffer)
{
ClassDereferenceObject(Class);
DPRINT1("Failed to allocate mem for window name\n");
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
RETURN( NULL);
@ -1612,13 +1600,10 @@ co_IntCreateWindowEx(DWORD dwExStyle,
Cs.dwExStyle = dwExStyle;
CbtCreate.lpcs = &Cs;
CbtCreate.hwndInsertAfter = HWND_TOP;
if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) Handle, (LPARAM) &CbtCreate))
if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) &CbtCreate))
{
/* FIXME - Delete window object and remove it from the thread windows list */
/* FIXME - delete allocated DCE */
ClassDereferenceObject(Class);
DPRINT1("CBT-hook returned !0\n");
RETURN( (HWND) NULL);
}
@ -1827,7 +1812,6 @@ co_IntCreateWindowEx(DWORD dwExStyle,
if (Result == (LRESULT)-1)
{
/* FIXME: Cleanup. */
ClassDereferenceObject(Class);
DPRINT("IntCreateWindowEx(): send CREATE message failed.\n");
RETURN((HWND)0);
}
@ -1911,7 +1895,7 @@ co_IntCreateWindowEx(DWORD dwExStyle,
if ((!hWndParent) && (!HasOwner))
{
DPRINT("Sending CREATED notify\n");
co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Handle);
co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)hWnd);
}
else
{
@ -1934,14 +1918,14 @@ co_IntCreateWindowEx(DWORD dwExStyle,
co_WinPosShowWindow(Window, dwShowMode);
}
DPRINT("IntCreateWindow(): = %X\n", Handle);
DPRINT("IntCreateWindow(): = %X\n", hWnd);
DPRINT("WindowObject->SystemMenu = 0x%x\n", Window->SystemMenu);
RETURN((HWND)Handle);
RETURN(hWnd);
CLEANUP:
if (Window) UserDerefObjectCo(Window);
if (ParentWindow) UserDerefObjectCo(ParentWindow);
if (!_ret_ && Class) ClassDerefObject(Class); /* only deref if failure (return 0) */
END_CLEANUP;
}
@ -2164,7 +2148,7 @@ BOOLEAN FASTCALL co_UserDestroyWindow(PWINDOW_OBJECT Window)
}
/* Destroy the window storage */
co_IntDestroyWindow(Window, PsGetWin32Process(), PsGetWin32Thread(), TRUE);
co_UserFreeWindow(Window, PsGetWin32Process(), PsGetWin32Thread(), TRUE);
return TRUE;
}
@ -4208,14 +4192,6 @@ NtUserUpdateLayeredWindow(DWORD Unknown0,
}
/*
* @implemented
*/
VOID STDCALL
NtUserValidateRect(HWND hWnd, const RECT* Rect)
{
return (VOID)NtUserRedrawWindow(hWnd, Rect, 0, RDW_VALIDATE | RDW_NOCHILDREN);
}
/*

View file

@ -107,6 +107,8 @@ IntWinStaObjectOpen(OB_OPEN_REASON Reason,
PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)ObjectBody;
NTSTATUS Status;
DPRINT1("IntWinStaObjectOpen\n");
if (Reason == ObCreateHandle)
{
DPRINT("Creating window station (0x%X)\n", WinSta);
@ -115,10 +117,10 @@ IntWinStaObjectOpen(OB_OPEN_REASON Reason,
InitializeListHead(&WinSta->DesktopListHead);
DPRINT1("Create winsta atomtable\n");
WinSta->AtomTable = NULL;
Status = RtlCreateAtomTable(37, &WinSta->AtomTable);
if (!NT_SUCCESS(Status)) DPRINT1("Error creating atom table\n");
WinSta->SystemMenuTemplate = (HANDLE)0;
DPRINT("Window station successfully created.\n");

View file

@ -417,15 +417,12 @@ NtUserGetWindowPlacement 2
NtUserGetWindowLong 3
NtUserGetWindowRect 2
NtUserGetWOWClass 2
NtUserHideCaret 1
NtUserHiliteMenuItem 4
NtUserImpersonateDdeClientWindow 2
NtUserInitializeClientPfnArrays 4
NtUserInitTask 11
NtUserInsertMenuItem 4
NtUserInternalGetWindowText 3
NtUserInvalidateRect 3
NtUserInvalidateRgn 3
NtUserIsClipboardFormatAvailable 1
NtUserKillSystemTimer 2
NtUserKillTimer 2
@ -523,7 +520,7 @@ NtUserSetWindowsHookEx 6
NtUserSetWindowStationUser 4
NtUserSetWindowWord 3
NtUserSetWinEventHook 8
NtUserShowCaret 1
NtUserShowCaret 2
NtUserShowScrollBar 3
NtUserShowWindow 2
NtUserShowWindowAsync 2
@ -544,12 +541,10 @@ NtUserUnregisterClass 3
NtUserUnregisterHotKey 2
NtUserUpdateInputContext 3
NtUserUpdateInstance 3
NtUserUpdateWindow 1
NtUserUpdateLayeredWindow 9
NtUserUpdatePerUserSystemParameters 2
NtUserUserHandleGrantAccess 3
NtUserValidateHandleSecure 1
NtUserValidateRect 2
NtUserVkKeyScanEx 3
NtUserWaitForInputIdle 3
NtUserWaitForMsgAndEvent 1