-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_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag
#define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo #define NLS_OEM_LEAD_BYTE_INFO NlsOemLeadByteInfo
#define MAX_ATOM_LEN 255 /* TCHARS not including nullterm */
/* List Macros */ /* List Macros */
static __inline static __inline
VOID VOID

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -157,7 +157,7 @@ InvalidateRect(
CONST RECT *lpRect, CONST RECT *lpRect,
BOOL bErase) 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, HRGN hRgn,
BOOL bErase) BOOL bErase)
{ {
return NtUserInvalidateRgn( hWnd, hRgn, bErase ); return RedrawWindow(hWnd, NULL, hRgn, RDW_INVALIDATE | (bErase ? RDW_ERASE : 0) );
} }
@ -224,7 +224,7 @@ STDCALL
UpdateWindow( UpdateWindow(
HWND hWnd) HWND hWnd)
{ {
return NtUserUpdateWindow( hWnd ); return RedrawWindow( hWnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN );
} }
@ -237,6 +237,8 @@ ValidateRect(
HWND hWnd, HWND hWnd,
CONST RECT *lpRect) 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); return RedrawWindow(hWnd, lpRect, 0, RDW_VALIDATE);
} }
@ -250,7 +252,9 @@ ValidateRgn(
HWND hWnd, HWND hWnd,
HRGN hRgn) 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, nHeight,
hWndParent, hWndParent,
hMenu, hMenu,
hInstance, hInstance,
lpParam, lpParam,
SW_SHOW, SW_SHOW,
FALSE); FALSE);
@ -304,7 +304,7 @@ CreateWindowExW(DWORD dwExStyle,
nHeight, nHeight,
hWndParent, hWndParent,
hMenu, hMenu,
hInstance, hInstance,
lpParam, lpParam,
SW_SHOW, SW_SHOW,
TRUE); TRUE);

View file

@ -14,6 +14,7 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
/* PROTOTYPES ****************************************************************/ /* PROTOTYPES ****************************************************************/
static PRTL_ATOM_TABLE RtlpGetGlobalAtomTable(VOID); static PRTL_ATOM_TABLE RtlpGetGlobalAtomTable(VOID);
@ -38,6 +39,12 @@ RtlQueryAtomListInAtomTable(IN PRTL_ATOM_TABLE AtomTable,
/* GLOBALS *******************************************************************/ /* 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; static PRTL_ATOM_TABLE GlobalAtomTable = NULL;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/

View file

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

View file

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

View file

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

View file

@ -28,8 +28,6 @@ typedef struct _WINDOW_OBJECT
{ {
/* Pointer to the window class. */ /* Pointer to the window class. */
PWNDCLASS_OBJECT Class; PWNDCLASS_OBJECT Class;
/* entry in the window list of the class object */
LIST_ENTRY ClassListEntry;
/* Extended style. */ /* Extended style. */
DWORD ExStyle; DWORD ExStyle;
/* Window name. */ /* 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()); DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
InitializeListHead(&Win32Process->ClassListHead); InitializeListHead(&Win32Process->ClassList);
InitializeListHead(&Win32Process->MenuListHead); InitializeListHead(&Win32Process->MenuListHead);
@ -100,6 +100,8 @@ Win32kProcessCallback(struct _EPROCESS *Process,
IntEngCleanupDriverObjs(Process, Win32Process); IntEngCleanupDriverObjs(Process, Win32Process);
CleanupMonitorImpl(); CleanupMonitorImpl();
/* no process windows should exist at this point, or the function will assert! */
DestroyProcessClasses(Win32Process);
GDI_CleanupForProcess(Process); GDI_CleanupForProcess(Process);

View file

@ -9,17 +9,24 @@
* 10/15/2003 Created * 10/15/2003 Created
*/ */
/* INCLUDES ******************************************************************/
#include <w32k.h> #include <w32k.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* DEFINES *****************************************************************/
#define MIN_CARETBLINKRATE 100 #define MIN_CARETBLINKRATE 100
#define MAX_CARETBLINKRATE 10000 #define MAX_CARETBLINKRATE 10000
#define DEFAULT_CARETBLINKRATE 530 #define DEFAULT_CARETBLINKRATE 530
#define CARET_REGKEY L"\\Registry\\User\\.Default\\Control Panel\\Desktop" #define CARET_REGKEY L"\\Registry\\User\\.Default\\Control Panel\\Desktop"
#define CARET_VALUENAME L"CursorBlinkRate" #define CARET_VALUENAME L"CursorBlinkRate"
/* FUNCTIONS *****************************************************************/
static
BOOL FASTCALL BOOL FASTCALL
co_IntHideCaret(PTHRDCARETINFO CaretInfo) co_IntHideCaret(PTHRDCARETINFO CaretInfo)
{ {
@ -69,6 +76,7 @@ IntSetCaretBlinkTime(UINT uMSeconds)
return TRUE; return TRUE;
} }
static
UINT FASTCALL UINT FASTCALL
IntQueryCaretBlinkRate(VOID) IntQueryCaretBlinkRate(VOID)
{ {
@ -134,6 +142,7 @@ IntQueryCaretBlinkRate(VOID)
return (UINT)Val; return (UINT)Val;
} }
static
UINT FASTCALL UINT FASTCALL
IntGetCaretBlinkTime(VOID) IntGetCaretBlinkTime(VOID)
{ {
@ -158,6 +167,7 @@ IntGetCaretBlinkTime(VOID)
return Ret; return Ret;
} }
BOOL FASTCALL BOOL FASTCALL
co_IntSetCaretPos(int X, int Y) co_IntSetCaretPos(int X, int Y)
{ {
@ -197,6 +207,8 @@ IntSwitchCaretShowing(PVOID Info)
return FALSE; return FALSE;
} }
#if 0 //unused
static
VOID FASTCALL VOID FASTCALL
co_IntDrawCaret(HWND hWnd) co_IntDrawCaret(HWND hWnd)
{ {
@ -210,9 +222,79 @@ co_IntDrawCaret(HWND hWnd)
ThreadQueue->CaretInfo->Showing = 1; 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 BOOL
STDCALL STDCALL
NtUserCreateCaret( 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 BOOL
STDCALL STDCALL
NtUserHideCaret(HWND hWnd OPTIONAL) NtUserShowCaret(HWND hWnd OPTIONAL, BOOL bShow)
{
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)
{ {
PWINDOW_OBJECT Window = NULL; PWINDOW_OBJECT Window = NULL;
DECLARE_RETURN(BOOL); DECLARE_RETURN(BOOL);
@ -430,7 +417,12 @@ NtUserShowCaret(HWND hWnd OPTIONAL)
} }
if (Window) UserRefObjectCo(Window); if (Window) UserRefObjectCo(Window);
ret = co_UserShowCaret(Window);
if (bShow)
ret = co_UserShowCaret(Window);
else
ret = co_UserHideCaret(Window);
if (Window) UserDerefObjectCo(Window); if (Window) UserDerefObjectCo(Window);
RETURN(ret); RETURN(ret);

View file

@ -47,64 +47,85 @@ CleanupClassImpl(VOID)
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
BOOL FASTCALL
ClassReferenceClassByAtom( /* return TRUE if class became destroyed */
PWNDCLASS_OBJECT* Class, inline VOID FASTCALL
RTL_ATOM Atom, ClassDerefObject(PWNDCLASS_OBJECT Class)
HINSTANCE hInstance)
{ {
PWNDCLASS_OBJECT Current, BestMatch = NULL; ASSERT(Class->refs >= 1);
PLIST_ENTRY CurrentEntry; Class->refs--;
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( inline VOID FASTCALL
PWNDCLASS_OBJECT *Class, ClassRefObject(PWNDCLASS_OBJECT Class)
LPCWSTR ClassName,
HINSTANCE hInstance)
{ {
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; NTSTATUS Status;
BOOL Found; RTL_ATOM Atom;
RTL_ATOM ClassAtom;
if (!ClassName || !PsGetWin32Thread()->Desktop) if (!ClassName || !PsGetWin32Thread()->Desktop)
return FALSE; return FALSE;
WinStaObject = PsGetWin32Thread()->Desktop->WindowStation; WinSta = PsGetWin32Thread()->Desktop->WindowStation;
Status = RtlLookupAtomInAtomTable( Status = RtlLookupAtomInAtomTable(
WinStaObject->AtomTable, WinSta->AtomTable,
(LPWSTR)ClassName, (LPWSTR)ClassName,
&ClassAtom); &Atom);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -112,369 +133,136 @@ ClassReferenceClassByName(
return FALSE; return FALSE;
} }
Found = ClassReferenceClassByAtom(Class, ClassAtom, hInstance); return ClassGetClassByAtom(Atom, 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);
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 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, CONST WNDCLASSEXW *lpwcx,
DWORD Flags, DWORD Flags,
WNDPROC wpExtra, WNDPROC wpExtra,
PUNICODE_STRING MenuName, PUNICODE_STRING MenuName,
RTL_ATOM Atom) RTL_ATOM Atom)
{ {
PWNDCLASS_OBJECT ClassObject; PWNDCLASS_OBJECT Class;
ULONG objectSize; ULONG objectSize;
BOOL Global; 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. */ /* 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)) /* can max have one class of each type (global/local) */
{ SetLastWin32Error(ERROR_CLASS_ALREADY_EXISTS);
/* return(FALSE);
* 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; 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); SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return(NULL); return(FALSE);
} }
RtlZeroMemory(Class, objectSize);
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;
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 (wpExtra == NULL)
{ {
if (Flags & REGISTERCLASS_ANSI) if (Flags & REGISTERCLASS_ANSI)
{ {
ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc; Class->lpfnWndProcA = lpwcx->lpfnWndProc;
ClassObject->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE); Class->lpfnWndProcW = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,FALSE);
} }
else else
{ {
ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc; Class->lpfnWndProcW = lpwcx->lpfnWndProc;
ClassObject->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE); Class->lpfnWndProcA = (WNDPROC)IntAddWndProcHandle(lpwcx->lpfnWndProc,TRUE);
} }
} }
else else
{ {
if (Flags & REGISTERCLASS_ANSI) if (Flags & REGISTERCLASS_ANSI)
{ {
ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc; Class->lpfnWndProcA = lpwcx->lpfnWndProc;
ClassObject->lpfnWndProcW = wpExtra; Class->lpfnWndProcW = wpExtra;
} }
else else
{ {
ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc; Class->lpfnWndProcW = lpwcx->lpfnWndProc;
ClassObject->lpfnWndProcA = wpExtra; Class->lpfnWndProcA = wpExtra;
} }
} }
if (MenuName->Length == 0) if (MenuName->Length == 0)
{ {
ClassObject->lpszMenuName.Length = Class->lpszMenuName.Length =
ClassObject->lpszMenuName.MaximumLength = 0; Class->lpszMenuName.MaximumLength = 0;
ClassObject->lpszMenuName.Buffer = MenuName->Buffer; Class->lpszMenuName.Buffer = MenuName->Buffer;
} }
else else
{ {
ClassObject->lpszMenuName.Length = Class->lpszMenuName.Length =
ClassObject->lpszMenuName.MaximumLength = MenuName->MaximumLength; Class->lpszMenuName.MaximumLength = MenuName->MaximumLength;
ClassObject->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, ClassObject->lpszMenuName.MaximumLength, TAG_STRING); Class->lpszMenuName.Buffer = ExAllocatePoolWithTag(PagedPool, Class->lpszMenuName.MaximumLength, TAG_STRING);
RtlCopyUnicodeString(&ClassObject->lpszMenuName, MenuName); RtlCopyUnicodeString(&Class->lpszMenuName, MenuName);
} }
/* Extra class data */ /* Extra class data */
if (ClassObject->cbClsExtra != 0) if (Class->cbClsExtra)
Class->ExtraData = (PCHAR)(Class + 1);
if (Global)
{ {
ClassObject->ExtraData = (PCHAR)(ClassObject + 1); /* global classes go last (incl. system classes) */
RtlZeroMemory(ClassObject->ExtraData, (ULONG)ClassObject->cbClsExtra); InsertTailList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
} }
else else
{ {
ClassObject->ExtraData = NULL; /* local classes have priority so we put them first */
InsertHeadList(&PsGetWin32Process()->ClassList, &Class->ListEntry);
} }
InitializeListHead(&ClassObject->ClassWindowsListHead); return TRUE;
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 ULONG FASTCALL
IntGetClassLong(struct _WINDOW_OBJECT *Window, ULONG Offset, BOOL Ansi) IntGetClassLong(PWINDOW_OBJECT Window, ULONG Offset, BOOL Ansi)
{ {
LONG Ret; LONG Ret;
@ -540,28 +328,7 @@ IntGetClassLong(struct _WINDOW_OBJECT *Window, ULONG Offset, BOOL Ansi)
return(Ret); return(Ret);
} }
DWORD STDCALL static
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;
}
void FASTCALL void FASTCALL
co_IntSetClassLong(PWINDOW_OBJECT Window, ULONG Offset, LONG dwNewLong, BOOL Ansi) 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; 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 DWORD STDCALL
NtUserSetClassLong(HWND hWnd, NtUserSetClassLong(HWND hWnd,
@ -689,56 +594,50 @@ NtUserSetClassWord(DWORD Unknown0,
BOOL STDCALL BOOL STDCALL
NtUserUnregisterClass( NtUserUnregisterClass(
LPCWSTR ClassNameOrAtom, LPCWSTR ClassNameOrAtom,
HINSTANCE hInstance, HINSTANCE hInstance, /* can be 0 */
DWORD Unknown) DWORD Unknown)
{ {
PWNDCLASS_OBJECT Class; PWNDCLASS_OBJECT Class;
PWINSTATION_OBJECT WinSta;
DECLARE_RETURN(BOOL); DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom); DPRINT("Enter NtUserUnregisterClass(%S)\n", ClassNameOrAtom);
UserEnterExclusive(); UserEnterExclusive();
if (!ClassNameOrAtom || !PsGetWin32Thread()->Desktop) if (!ClassNameOrAtom)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
RETURN( FALSE);
}
WinSta = PsGetWin32Thread()->Desktop->WindowStation;
if (!ClassReferenceClassByNameOrAtom(&Class, ClassNameOrAtom, hInstance))
{ {
SetLastWin32Error(ERROR_CLASS_DOES_NOT_EXIST); 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); 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 */ /* NOTE: the class will not be freed when its refs become 0 ie. no more
ObmDereferenceObject(Class); * 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); SetLastWin32Error(ERROR_CLASS_HAS_WINDOWS);
RETURN( FALSE); RETURN(FALSE);
} }
/* Dereference the ClassReferenceClassByNameOrAtom() call */ DestroyClass(Class);
ClassDereferenceObject(Class);
RemoveEntryList(&Class->ListEntry); RETURN(TRUE);
RtlDeleteAtomFromAtomTable(WinSta->AtomTable, Class->Atom);
/* Free the object */
ClassDereferenceObject(Class);
RETURN( TRUE);
CLEANUP: CLEANUP:
DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_); DPRINT("Leave NtUserUnregisterClass, ret=%i\n",_ret_);
@ -746,4 +645,119 @@ CLEANUP:
END_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 */ /* EOF */

View file

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

View file

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

View file

@ -510,21 +510,6 @@ NtUserCallTwoParam(
UNIMPLEMENTED UNIMPLEMENTED
RETURN( 0); 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: case TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID:
if(!(Window = UserGetWindowObject((HWND)Param1))) if(!(Window = UserGetWindowObject((HWND)Param1)))

View file

@ -292,11 +292,12 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
{ {
for (phWnd = List; *phWnd; ++phWnd) for (phWnd = List; *phWnd; ++phWnd)
{ {
Window = IntGetWindowObject(*phWnd); Window = UserGetWindowObject(*phWnd);
if (Window && (Window->Style & WS_VISIBLE)) if (Window && (Window->Style & WS_VISIBLE))
{ {
UserRefObjectCo(Window);
co_IntPaintWindows(Window, Flags); co_IntPaintWindows(Window, Flags);
ObmDereferenceObject(Window); UserDerefObjectCo(Window);
} }
} }
ExFreePool(List); ExFreePool(List);
@ -414,31 +415,21 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) && if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) &&
((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN))) ((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN)))
{ {
HWND *List, *phWnd;
PWINDOW_OBJECT Child; 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))) /*
{ * Recursive call to update children UpdateRegion
continue; */
} HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
if (Child->Style & WS_VISIBLE) 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; 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 INT FASTCALL
co_UserGetUpdateRgn(PWINDOW_OBJECT Window, HRGN hRgn, BOOL bErase) co_UserGetUpdateRgn(PWINDOW_OBJECT Window, HRGN hRgn, BOOL bErase)

View file

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

View file

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