mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
tinus <[email protected]>:
Implement RegisterShellHookWindow svn path=/trunk/; revision=14041
This commit is contained in:
@@ -103,6 +103,11 @@ NtUserBuildPropList(
|
||||
DWORD BufferSize,
|
||||
DWORD *Count);
|
||||
|
||||
enum {
|
||||
HWND_ROUTINE_REGISTERSHELLHOOKWINDOW,
|
||||
HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW
|
||||
};
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserCallHwnd(
|
||||
|
||||
@@ -156,8 +156,7 @@ BOOL
|
||||
STDCALL
|
||||
DeregisterShellHookWindow(HWND hWnd)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
return NtUserCallHwnd(HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW, (DWORD)hWnd);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -167,8 +166,7 @@ BOOL
|
||||
STDCALL
|
||||
RegisterShellHookWindow(HWND hWnd)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
return NtUserCallHwnd(HWND_ROUTINE_REGISTERSHELLHOOKWINDOW, (DWORD)hWnd);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -68,6 +68,8 @@ typedef struct _DESKTOP_OBJECT
|
||||
HANDLE PrevActiveWindow;
|
||||
/* Thread blocking input */
|
||||
PVOID BlockInputThread;
|
||||
|
||||
LIST_ENTRY ShellHookWindows;
|
||||
} DESKTOP_OBJECT, *PDESKTOP_OBJECT;
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@ extern PWNDCLASS_OBJECT DesktopWindowClass;
|
||||
extern HDC ScreenDeviceContext;
|
||||
extern BOOL g_PaintDesktopVersion;
|
||||
|
||||
typedef struct _SHELL_HOOK_WINDOW
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
HWND hWnd;
|
||||
} SHELL_HOOK_WINDOW, *PSHELL_HOOK_WINDOW;
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
InitDesktopImpl(VOID);
|
||||
|
||||
@@ -79,6 +85,11 @@ IntParseDesktopPath(PEPROCESS Process,
|
||||
BOOL FASTCALL
|
||||
IntDesktopUpdatePerUserSettings(BOOL bEnable);
|
||||
|
||||
BOOL IntRegisterShellHookWindow(HWND hWnd);
|
||||
BOOL IntDeRegisterShellHookWindow(HWND hWnd);
|
||||
|
||||
VOID IntShellHookNotify(WPARAM Message, LPARAM lParam);
|
||||
|
||||
#define IntIsActiveDesktop(Desktop) \
|
||||
((Desktop)->WindowStation->ActiveDesktop == (Desktop))
|
||||
|
||||
|
||||
@@ -199,6 +199,9 @@ IntGetAncestor(PWINDOW_OBJECT Wnd, UINT Type);
|
||||
PWINDOW_OBJECT FASTCALL
|
||||
IntGetParent(PWINDOW_OBJECT Wnd);
|
||||
|
||||
PWINDOW_OBJECT FASTCALL
|
||||
IntGetOwner(PWINDOW_OBJECT Wnd);
|
||||
|
||||
PWINDOW_OBJECT FASTCALL
|
||||
IntGetParentObject(PWINDOW_OBJECT Wnd);
|
||||
|
||||
|
||||
@@ -534,6 +534,8 @@ NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
|
||||
void FASTCALL
|
||||
IntSetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset, LONG dwNewLong, BOOL Ansi)
|
||||
{
|
||||
PWINDOW_OBJECT Parent, Owner;
|
||||
|
||||
if ((int)Offset >= 0)
|
||||
{
|
||||
DPRINT("SetClassLong(%x, %d, %x)\n", WindowObject->Self, Offset, dwNewLong);
|
||||
@@ -562,6 +564,25 @@ IntSetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset, LONG dwNewLong, BOOL
|
||||
break;
|
||||
case GCL_HICON:
|
||||
WindowObject->Class->hIcon = (HICON)dwNewLong;
|
||||
Owner = IntGetOwner(WindowObject);
|
||||
Parent = IntGetParent(WindowObject);
|
||||
|
||||
if ((!Owner) && (!Parent))
|
||||
{
|
||||
IntShellHookNotify(HSHELL_REDRAW, (LPARAM) WindowObject->Self);
|
||||
}
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
IntReleaseWindowObject(Parent);
|
||||
}
|
||||
|
||||
if (Owner)
|
||||
{
|
||||
IntReleaseWindowObject(Owner);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case GCL_HICONSM:
|
||||
WindowObject->Class->hIconSm = (HICON)dwNewLong;
|
||||
|
||||
@@ -92,6 +92,7 @@ IntDesktopObjectCreate(PVOID ObjectBody,
|
||||
DPRINT("Creating desktop (0x%X) Name (%wZ)\n", Desktop, &UnicodeString);
|
||||
|
||||
KeInitializeSpinLock(&Desktop->Lock);
|
||||
InitializeListHead(&Desktop->ShellHookWindows);
|
||||
|
||||
Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
|
||||
|
||||
@@ -540,6 +541,147 @@ IntHideDesktop(PDESKTOP_OBJECT Desktop)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the Message to the windows registered for ShellHook
|
||||
* notifications. The lParam contents depend on the Message. See
|
||||
* MSDN for more details (RegisterShellHookWindow)
|
||||
*/
|
||||
VOID IntShellHookNotify(WPARAM Message, LPARAM lParam)
|
||||
{
|
||||
PDESKTOP_OBJECT Desktop = IntGetActiveDesktop();
|
||||
PLIST_ENTRY Entry, Entry2;
|
||||
PSHELL_HOOK_WINDOW Current;
|
||||
KIRQL OldLevel;
|
||||
|
||||
static UINT MsgType = 0;
|
||||
|
||||
if (!MsgType) {
|
||||
|
||||
/* Too bad, this doesn't work.*/
|
||||
#if 0
|
||||
UNICODE_STRING Str;
|
||||
RtlInitUnicodeString(&Str, L"SHELLHOOK");
|
||||
MsgType = NtUserRegisterWindowMessage(&Str);
|
||||
#endif
|
||||
MsgType = IntAddAtom(L"SHELLHOOK");
|
||||
|
||||
DPRINT("MsgType = %x\n", MsgType);
|
||||
if (!MsgType)
|
||||
DPRINT1("LastError: %x\n", GetLastNtError());
|
||||
}
|
||||
|
||||
if (!Desktop) {
|
||||
DPRINT1("IntShellHookNotify: No desktop!\n");
|
||||
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) {
|
||||
Current = CONTAINING_RECORD(Entry, SHELL_HOOK_WINDOW, ListEntry);
|
||||
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
|
||||
|
||||
DPRINT("Sending notify\n");
|
||||
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;
|
||||
}
|
||||
|
||||
if (Entry2 == Entry)
|
||||
Entry = Entry->Flink;
|
||||
else
|
||||
break;
|
||||
}
|
||||
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the window to the ShellHookWindows list. The windows
|
||||
* on that list get notifications that are important to shell
|
||||
* type applications.
|
||||
*
|
||||
* TODO: Validate the window? I'm not sure if sending these messages to
|
||||
* an unsuspecting application that is not your own is a nice thing to do.
|
||||
*/
|
||||
BOOL IntRegisterShellHookWindow(HWND hWnd)
|
||||
{
|
||||
PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
|
||||
PSHELL_HOOK_WINDOW Entry;
|
||||
KIRQL OldLevel;
|
||||
|
||||
DPRINT("IntRegisterShellHookWindow\n");
|
||||
|
||||
/* First deregister the window, so we can be sure it's never twice in the
|
||||
* list.
|
||||
*/
|
||||
IntDeRegisterShellHookWindow(hWnd);
|
||||
|
||||
Entry = ExAllocatePoolWithTag(NonPagedPool,
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the window from the ShellHookWindows list. The windows
|
||||
* on that list get notifications that are important to shell
|
||||
* type applications.
|
||||
*/
|
||||
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) {
|
||||
Current = CONTAINING_RECORD(Entry, SHELL_HOOK_WINDOW, ListEntry);
|
||||
if (Current->hWnd == hWnd) {
|
||||
RemoveEntryList(Entry);
|
||||
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
|
||||
ExFreePool(Entry);
|
||||
return TRUE;
|
||||
}
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&Desktop->Lock, OldLevel);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* NtUserCreateDesktop
|
||||
*
|
||||
|
||||
@@ -62,6 +62,8 @@ IntSendDeactivateMessages(HWND hWndPrev, HWND hWnd)
|
||||
VOID FASTCALL
|
||||
IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
|
||||
{
|
||||
PWINDOW_OBJECT Window, Owner, Parent;
|
||||
|
||||
if (hWnd)
|
||||
{
|
||||
/* Send palette messages */
|
||||
@@ -75,6 +77,22 @@ IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
|
||||
WinPosSetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
|
||||
|
||||
Window = IntGetWindowObject(hWnd);
|
||||
if (Window) {
|
||||
Owner = IntGetOwner(Window);
|
||||
if (!Owner) {
|
||||
Parent = IntGetParent(Window);
|
||||
if (!Parent)
|
||||
IntShellHookNotify(HSHELL_WINDOWACTIVATED, (LPARAM) hWnd);
|
||||
else
|
||||
IntReleaseWindowObject(Parent);
|
||||
} else {
|
||||
IntReleaseWindowObject(Owner);
|
||||
}
|
||||
|
||||
IntReleaseWindowObject(Window);
|
||||
}
|
||||
|
||||
/* FIXME: IntIsWindow */
|
||||
|
||||
IntPostOrSendMessage(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == NtUserGetForegroundWindow()), 0);
|
||||
|
||||
@@ -59,6 +59,17 @@ NtUserCallHwnd(
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1)
|
||||
{
|
||||
switch (Unknown0) {
|
||||
case HWND_ROUTINE_REGISTERSHELLHOOKWINDOW:
|
||||
if (IntIsWindow((HWND) Unknown1))
|
||||
return IntRegisterShellHookWindow((HWND) Unknown1);
|
||||
return FALSE;
|
||||
break;
|
||||
case HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW:
|
||||
if (IntIsWindow((HWND) Unknown1))
|
||||
return IntDeRegisterShellHookWindow((HWND) Unknown1);
|
||||
return FALSE;
|
||||
}
|
||||
UNIMPLEMENTED
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -147,6 +147,17 @@ IntGetParent(PWINDOW_OBJECT Wnd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PWINDOW_OBJECT FASTCALL
|
||||
IntGetOwner(PWINDOW_OBJECT Wnd)
|
||||
{
|
||||
HWND hWnd;
|
||||
|
||||
IntLockRelatives(Wnd);
|
||||
hWnd = Wnd->Owner;
|
||||
IntUnLockRelatives(Wnd);
|
||||
|
||||
return IntGetWindowObject(hWnd);
|
||||
}
|
||||
|
||||
PWINDOW_OBJECT FASTCALL
|
||||
IntGetParentObject(PWINDOW_OBJECT Wnd)
|
||||
@@ -205,6 +216,8 @@ IntWinListChildren(PWINDOW_OBJECT Window)
|
||||
*/
|
||||
static void IntSendDestroyMsg(HWND Wnd)
|
||||
{
|
||||
|
||||
PWINDOW_OBJECT Window, Owner, Parent;
|
||||
#if 0 /* FIXME */
|
||||
GUITHREADINFO info;
|
||||
|
||||
@@ -217,9 +230,28 @@ static void IntSendDestroyMsg(HWND Wnd)
|
||||
}
|
||||
#endif
|
||||
|
||||
Window = IntGetWindowObject(Wnd);
|
||||
if (Window) {
|
||||
Owner = IntGetOwner(Window);
|
||||
if (!Owner) {
|
||||
Parent = IntGetParent(Window);
|
||||
if (!Parent)
|
||||
IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM) Wnd);
|
||||
else
|
||||
IntReleaseWindowObject(Parent);
|
||||
} else {
|
||||
IntReleaseWindowObject(Owner);
|
||||
}
|
||||
|
||||
IntReleaseWindowObject(Window);
|
||||
}
|
||||
|
||||
/* The window could already be destroyed here */
|
||||
|
||||
/*
|
||||
* Send the WM_DESTROY to the window.
|
||||
*/
|
||||
|
||||
IntSendMessage(Wnd, WM_DESTROY, 0, 0);
|
||||
|
||||
/*
|
||||
@@ -284,6 +316,8 @@ static LRESULT IntDestroyWindow(PWINDOW_OBJECT Window,
|
||||
IntUnLockThreadWindows(Window->OwnerThread->Tcb.Win32Thread);
|
||||
|
||||
BelongsToThreadData = IntWndBelongsToThread(Window, ThreadData);
|
||||
|
||||
IntDeRegisterShellHookWindow(Window->Self);
|
||||
|
||||
if(SendMessages)
|
||||
{
|
||||
@@ -1417,6 +1451,8 @@ IntCreateWindowEx(DWORD dwExStyle,
|
||||
BOOL MenuChanged;
|
||||
BOOL ClassFound;
|
||||
|
||||
BOOL HasOwner;
|
||||
|
||||
ParentWindowHandle = PsGetWin32Thread()->Desktop->DesktopWindow;
|
||||
OwnerWindowHandle = NULL;
|
||||
|
||||
@@ -1542,9 +1578,11 @@ IntCreateWindowEx(DWORD dwExStyle,
|
||||
{
|
||||
WindowObject->Owner = OwnerWindowHandle;
|
||||
IntReleaseWindowObject(OwnerWindow);
|
||||
}
|
||||
else
|
||||
HasOwner = TRUE;
|
||||
} else {
|
||||
WindowObject->Owner = NULL;
|
||||
HasOwner = FALSE;
|
||||
}
|
||||
WindowObject->UserData = 0;
|
||||
if ((((DWORD)ClassObject->lpfnWndProcA & 0xFFFF0000) != 0xFFFF0000)
|
||||
&& (((DWORD)ClassObject->lpfnWndProcW & 0xFFFF0000) != 0xFFFF0000))
|
||||
@@ -1969,6 +2007,13 @@ IntCreateWindowEx(DWORD dwExStyle,
|
||||
(LPARAM)WindowObject->Self);
|
||||
}
|
||||
|
||||
if ((!hWndParent) && (!HasOwner)) {
|
||||
DPRINT("Sending CREATED notify\n");
|
||||
IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Handle);
|
||||
} else {
|
||||
DPRINT("Not sending CREATED notify, %x %d\n", ParentWindow, HasOwner);
|
||||
}
|
||||
|
||||
if (NULL != ParentWindow)
|
||||
{
|
||||
IntReleaseWindowObject(ParentWindow);
|
||||
@@ -4060,7 +4105,7 @@ NtUserWindowFromPoint(LONG X, LONG Y)
|
||||
BOOL STDCALL
|
||||
NtUserDefSetText(HWND WindowHandle, PUNICODE_STRING WindowText)
|
||||
{
|
||||
PWINDOW_OBJECT WindowObject;
|
||||
PWINDOW_OBJECT WindowObject, Parent, Owner;
|
||||
UNICODE_STRING SafeText;
|
||||
NTSTATUS Status;
|
||||
|
||||
@@ -4090,6 +4135,26 @@ NtUserDefSetText(HWND WindowHandle, PUNICODE_STRING WindowText)
|
||||
RtlFreeUnicodeString(&WindowObject->WindowName);
|
||||
|
||||
WindowObject->WindowName = SafeText;
|
||||
|
||||
/* Send shell notifications */
|
||||
|
||||
Owner = IntGetOwner(WindowObject);
|
||||
Parent = IntGetParent(WindowObject);
|
||||
|
||||
if ((!Owner) && (!Parent))
|
||||
{
|
||||
IntShellHookNotify(HSHELL_REDRAW, (LPARAM) WindowHandle);
|
||||
}
|
||||
|
||||
if (Owner)
|
||||
{
|
||||
IntReleaseWindowObject(Owner);
|
||||
}
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
IntReleaseWindowObject(Parent);
|
||||
}
|
||||
|
||||
IntReleaseWindowObject(WindowObject);
|
||||
return TRUE;
|
||||
|
||||
Reference in New Issue
Block a user