mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
implementation of window enumeration. thread window enumeration appears to have a problem. Would someone who understands it better please fix it?
svn path=/trunk/; revision=5268
This commit is contained in:
parent
8a66dfeaad
commit
bf34364f74
9 changed files with 266 additions and 60 deletions
|
@ -7,7 +7,7 @@ PATH_TO_TOP = ../..
|
|||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
TEST_APPS = alive apc args atomtest bench bitblt button button2 \
|
||||
combo consume copymove count dump_shared_data edit event file \
|
||||
combo consume copymove count dump_shared_data edit enumwnd event file \
|
||||
gditest hello isotest lineclip lpc messagebox mstest mutex nptest pteb \
|
||||
regtest sectest shm thread tokentest vmtest winhello dibtest lock SampleWindow \
|
||||
hivetest shaptest wm_paint multiwin icontest suspend tests/volinfo terminate
|
||||
|
|
|
@ -65,16 +65,16 @@ STDCALL
|
|||
NtUserBlockInput(
|
||||
DWORD Unknown0);
|
||||
|
||||
DWORD
|
||||
ULONG
|
||||
STDCALL
|
||||
NtUserBuildHwndList(
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1,
|
||||
DWORD Unknown2,
|
||||
DWORD Unknown3,
|
||||
DWORD Unknown4,
|
||||
DWORD Unknown5,
|
||||
DWORD Unknown6);
|
||||
HDESK hDesktop,
|
||||
HWND hwndParent,
|
||||
BOOLEAN bChildren,
|
||||
ULONG dwThreadId,
|
||||
ULONG lParam,
|
||||
HWND* pWnd,
|
||||
ULONG nBufSize);
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
|
|
|
@ -119,6 +119,7 @@ copy apps\tests\shm\shmclt.exe %ROS_INSTALL%\bin
|
|||
copy apps\tests\lpc\lpcsrv.exe %ROS_INSTALL%\bin
|
||||
copy apps\tests\lpc\lpcclt.exe %ROS_INSTALL%\bin
|
||||
copy apps\tests\thread\thread.exe %ROS_INSTALL%\bin
|
||||
copy apps\tests\enumwnd\enumwnd.exe %ROS_INSTALL%\bin
|
||||
copy apps\tests\event\event.exe %ROS_INSTALL%\bin
|
||||
copy apps\tests\file\file.exe %ROS_INSTALL%\bin
|
||||
copy apps\tests\pteb\pteb.exe %ROS_INSTALL%\bin
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: desktop.c,v 1.15 2003/07/21 01:59:51 royce Exp $
|
||||
/* $Id: desktop.c,v 1.16 2003/07/25 23:02:21 royce Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS user32.dll
|
||||
|
@ -156,21 +156,6 @@ CreateDesktopW(LPCWSTR lpszDesktop,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
WINBOOL
|
||||
STDCALL
|
||||
EnumDesktopWindows(
|
||||
HDESK hDesktop,
|
||||
ENUMWINDOWSPROC lpfn,
|
||||
LPARAM lParam)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: window.c,v 1.46 2003/07/25 19:37:14 gdalsnes Exp $
|
||||
/* $Id: window.c,v 1.47 2003/07/25 23:02:21 royce Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS user32.dll
|
||||
|
@ -748,41 +748,128 @@ EndDeferWindowPos(HDWP hWinPosInfo)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
WINBOOL STDCALL
|
||||
EnumChildWindows(HWND hWndParent,
|
||||
ENUMWINDOWSPROC lpEnumFunc,
|
||||
LPARAM lParam)
|
||||
WINBOOL
|
||||
STATIC
|
||||
User32EnumWindows (
|
||||
HDESK hDesktop,
|
||||
HWND hWndparent,
|
||||
ENUMWINDOWSPROC lpfn,
|
||||
LPARAM lParam,
|
||||
DWORD dwThreadId,
|
||||
BOOL bChildren )
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
DWORD i, dwCount = 0;
|
||||
HWND* pHwnd = NULL;
|
||||
HANDLE hHeap;
|
||||
|
||||
if ( !lpfn )
|
||||
{
|
||||
SetLastError ( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* FIXME instead of always making two calls, should we use some
|
||||
sort of persistent buffer and only grow it ( requiring a 2nd
|
||||
call ) when the buffer wasn't already big enough? */
|
||||
/* first get how many window entries there are */
|
||||
SetLastError(0);
|
||||
dwCount = NtUserBuildHwndList (
|
||||
hDesktop, hWndparent, bChildren, dwThreadId, lParam, NULL, 0 );
|
||||
if ( !dwCount || GetLastError() )
|
||||
return FALSE;
|
||||
|
||||
/* allocate buffer to receive HWND handles */
|
||||
hHeap = GetProcessHeap();
|
||||
pHwnd = HeapAlloc ( hHeap, 0, sizeof(HWND)*(dwCount+1) );
|
||||
if ( !pHwnd )
|
||||
{
|
||||
SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* now call kernel again to fill the buffer this time */
|
||||
dwCount = NtUserBuildHwndList (
|
||||
hDesktop, hWndparent, bChildren, dwThreadId, lParam, pHwnd, dwCount );
|
||||
if ( !dwCount || GetLastError() )
|
||||
{
|
||||
if ( pHwnd )
|
||||
HeapFree ( hHeap, 0, pHwnd );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* call the user's callback function until we're done or
|
||||
they tell us to quit */
|
||||
for ( i = 0; i < dwCount; i++ )
|
||||
{
|
||||
/* FIXME I'm only getting NULLs from Thread Enumeration, and it's
|
||||
* probably because I'm not doing it right in NtUserBuildHwndList.
|
||||
* Once that's fixed, we shouldn't have to check for a NULL HWND
|
||||
* here
|
||||
*/
|
||||
if ( !(ULONG)pHwnd[i] ) /* don't enumerate a NULL HWND */
|
||||
continue;
|
||||
if ( !(*lpfn)( pHwnd[i], lParam ) )
|
||||
break;
|
||||
}
|
||||
if ( pHwnd )
|
||||
HeapFree ( hHeap, 0, pHwnd );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
WINBOOL STDCALL
|
||||
WINBOOL
|
||||
STDCALL
|
||||
EnumChildWindows(
|
||||
HWND hWndParent,
|
||||
ENUMWINDOWSPROC lpEnumFunc,
|
||||
LPARAM lParam)
|
||||
{
|
||||
if ( !hWndParent )
|
||||
hWndParent = GetDesktopWindow();
|
||||
return User32EnumWindows ( NULL, hWndParent, lpEnumFunc, lParam, 0, FALSE );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
WINBOOL
|
||||
STDCALL
|
||||
EnumThreadWindows(DWORD dwThreadId,
|
||||
ENUMWINDOWSPROC lpfn,
|
||||
LPARAM lParam)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
if ( !dwThreadId )
|
||||
dwThreadId = GetCurrentThreadId();
|
||||
return User32EnumWindows ( NULL, NULL, lpfn, lParam, dwThreadId, FALSE );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
WINBOOL STDCALL
|
||||
EnumWindows(ENUMWINDOWSPROC lpEnumFunc,
|
||||
LPARAM lParam)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
return User32EnumWindows ( NULL, NULL, lpEnumFunc, lParam, 0, FALSE );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
WINBOOL
|
||||
STDCALL
|
||||
EnumDesktopWindows(
|
||||
HDESK hDesktop,
|
||||
ENUMWINDOWSPROC lpfn,
|
||||
LPARAM lParam)
|
||||
{
|
||||
return User32EnumWindows ( hDesktop, NULL, lpfn, lParam, 0, FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ LRESULT CALLBACK
|
|||
W32kDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
PDESKTOP_OBJECT FASTCALL
|
||||
W32kGetActiveDesktop(VOID);
|
||||
PDESKTOP_OBJECT FASTCALL
|
||||
W32kGetDesktopObject ( HDESK hDesk );
|
||||
PUSER_MESSAGE_QUEUE FASTCALL
|
||||
W32kGetFocusMessageQueue(VOID);
|
||||
VOID FASTCALL
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: stubs.c,v 1.16 2003/07/20 05:32:19 jimtabor Exp $
|
||||
/* $Id: stubs.c,v 1.17 2003/07/25 23:02:21 royce Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -65,21 +65,6 @@ NtUserBlockInput(
|
|||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserBuildHwndList(
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1,
|
||||
DWORD Unknown2,
|
||||
DWORD Unknown3,
|
||||
DWORD Unknown4,
|
||||
DWORD Unknown5,
|
||||
DWORD Unknown6)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: window.c,v 1.67 2003/07/25 19:35:51 gdalsnes Exp $
|
||||
/* $Id: window.c,v 1.68 2003/07/25 23:02:21 royce Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -1998,4 +1998,143 @@ NtUserGetWindowThreadProcessId(HWND hWnd, LPDWORD UnsafePid)
|
|||
return tid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* As best as I can figure, this function is used by EnumWindows,
|
||||
* EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
|
||||
*
|
||||
* It's supposed to build a list of HWNDs to return to the caller.
|
||||
* We can figure out what kind of list by what parameters are
|
||||
* passed to us.
|
||||
*/
|
||||
ULONG
|
||||
STDCALL
|
||||
NtUserBuildHwndList(
|
||||
HDESK hDesktop,
|
||||
HWND hwndParent,
|
||||
BOOLEAN bChildren,
|
||||
ULONG dwThreadId,
|
||||
ULONG lParam,
|
||||
HWND* pWnd,
|
||||
ULONG nBufSize)
|
||||
{
|
||||
ULONG dwCount = 0;
|
||||
|
||||
/* FIXME handle bChildren */
|
||||
if ( hwndParent )
|
||||
{
|
||||
PWINDOW_OBJECT WindowObject = NULL;
|
||||
PLIST_ENTRY ChildListEntry;
|
||||
|
||||
WindowObject = W32kGetWindowObject ( hwndParent );
|
||||
if ( !WindowObject )
|
||||
{
|
||||
DPRINT("Bad window handle 0x%x\n", hWnd);
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ExAcquireFastMutex ( &WindowObject->ChildrenListLock );
|
||||
ChildListEntry = WindowObject->ChildrenListHead.Flink;
|
||||
while (ChildListEntry != &WindowObject->ChildrenListHead)
|
||||
{
|
||||
PWINDOW_OBJECT Child;
|
||||
Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT,
|
||||
SiblingListEntry);
|
||||
if ( pWnd && dwCount < nBufSize )
|
||||
pWnd[dwCount] = Child->Self;
|
||||
dwCount++;
|
||||
ChildListEntry = ChildListEntry->Flink;
|
||||
}
|
||||
ExReleaseFastMutex ( &WindowObject->ChildrenListLock );
|
||||
W32kReleaseWindowObject ( WindowObject );
|
||||
}
|
||||
else if ( dwThreadId )
|
||||
{
|
||||
NTSTATUS Status;
|
||||
struct _ETHREAD* Thread;
|
||||
struct _EPROCESS* ThreadsProcess;
|
||||
struct _W32PROCESS* Win32Process;
|
||||
struct _WINSTATION_OBJECT* WindowStation;
|
||||
PUSER_HANDLE_TABLE HandleTable;
|
||||
PLIST_ENTRY Current;
|
||||
PUSER_HANDLE_BLOCK Block = NULL;
|
||||
int i;
|
||||
|
||||
Status = PsLookupThreadByThreadId ( (PVOID)dwThreadId, &Thread );
|
||||
if ( !NT_SUCCESS(Status) || !Thread )
|
||||
{
|
||||
DPRINT("Bad ThreadId 0x%x\n", dwThreadId );
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
ThreadsProcess = Thread->ThreadsProcess;
|
||||
ASSERT(ThreadsProcess);
|
||||
Win32Process = ThreadsProcess->Win32Process;
|
||||
ASSERT(Win32Process);
|
||||
WindowStation = Win32Process->WindowStation;
|
||||
ASSERT(WindowStation);
|
||||
HandleTable = (PUSER_HANDLE_TABLE)(WindowStation->HandleTable);
|
||||
ASSERT(HandleTable);
|
||||
|
||||
ExAcquireFastMutex(&HandleTable->ListLock);
|
||||
|
||||
Current = HandleTable->ListHead.Flink;
|
||||
while ( Current != &HandleTable->ListHead )
|
||||
{
|
||||
Block = CONTAINING_RECORD(Current, USER_HANDLE_BLOCK, ListEntry);
|
||||
for ( i = 0; i < HANDLE_BLOCK_ENTRIES; i++ )
|
||||
{
|
||||
PVOID ObjectBody = Block->Handles[i].ObjectBody;
|
||||
if ( ObjectBody )
|
||||
{
|
||||
if ( pWnd && dwCount < nBufSize )
|
||||
{
|
||||
pWnd[dwCount] =
|
||||
(HWND)ObmReferenceObjectByPointer ( ObjectBody, otWindow );
|
||||
}
|
||||
dwCount++;
|
||||
}
|
||||
}
|
||||
Current = Current->Flink;
|
||||
}
|
||||
|
||||
ExReleaseFastMutex(&HandleTable->ListLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
PDESKTOP_OBJECT DesktopObject = NULL;
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY WindowListEntry;
|
||||
|
||||
if ( hDesktop )
|
||||
DesktopObject = W32kGetDesktopObject ( hDesktop );
|
||||
else
|
||||
DesktopObject = W32kGetActiveDesktop();
|
||||
if (!DesktopObject)
|
||||
{
|
||||
DPRINT("Bad desktop handle 0x%x\n", hDesktop );
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
KeAcquireSpinLock ( &DesktopObject->Lock, &OldIrql );
|
||||
WindowListEntry = DesktopObject->WindowListHead.Flink;
|
||||
while ( WindowListEntry != &DesktopObject->WindowListHead )
|
||||
{
|
||||
PWINDOW_OBJECT Child;
|
||||
Child = CONTAINING_RECORD(WindowListEntry, WINDOW_OBJECT,
|
||||
SiblingListEntry);
|
||||
if ( pWnd && dwCount < nBufSize )
|
||||
pWnd[dwCount] = Child->Self;
|
||||
dwCount++;
|
||||
WindowListEntry = WindowListEntry->Flink;
|
||||
}
|
||||
KeReleaseSpinLock ( &DesktopObject->Lock, OldIrql );
|
||||
}
|
||||
|
||||
return dwCount;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: winsta.c,v 1.17 2003/07/05 16:04:01 chorns Exp $
|
||||
/* $Id: winsta.c,v 1.18 2003/07/25 23:02:21 royce Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -74,6 +74,13 @@ W32kGetActiveDesktop(VOID)
|
|||
return(InputDesktop);
|
||||
}
|
||||
|
||||
PDESKTOP_OBJECT FASTCALL
|
||||
W32kGetDesktopObject ( HDESK hDesk )
|
||||
{
|
||||
/* FIXME - this obviously isn't right */
|
||||
return W32kGetActiveDesktop();
|
||||
}
|
||||
|
||||
PUSER_MESSAGE_QUEUE FASTCALL
|
||||
W32kGetFocusMessageQueue(VOID)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue