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:
Royce Mitchell III 2003-07-25 23:02:21 +00:00
parent 8a66dfeaad
commit bf34364f74
9 changed files with 266 additions and 60 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
*/

View file

@ -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 );
}

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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)
{