Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

382 lines
9.0 KiB

/****************************** Module Header ******************************\
* Module Name: enumwin.c
*
* Copyright (c) 1985-91, Microsoft Corporation
*
* Contains the EnumWindows API, BuildHwndList and related functions.
*
* History:
* 10-20-90 darrinm Created.
* ??-??-?? ianja Added Revalidation code
* 02-19-91 JimA Added enum access checks
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
PBWL pbwlCache = NULL;
#if DBG
PBWL pbwlCachePrev = NULL;
#endif
PBWL InternalBuildHwndList(PBWL pbwl, PWND pwnd, UINT flags);
PBWL InternalBuildHwndOwnerList(PBWL pbwl, PWND pwndStart, PWND pwndOwner);
/***************************************************************************\
* xxxInternalEnumWindow
*
* History:
* 10-20-90 darrinm Ported from Win 3.0 sources.
* 02-06-91 IanJa rename: the call to lpfn can leave the critsect.
* 02-19-91 JimA Added enum access check
\***************************************************************************/
BOOL xxxInternalEnumWindow(
PWND pwndNext,
WNDENUMPROC_PWND lpfn,
LONG lParam,
UINT flags)
{
HWND *phwnd;
PWND pwnd;
PBWL pbwl;
BOOL fSuccess;
TL tlpwnd;
CheckLock(pwndNext);
if ((pbwl = BuildHwndList(pwndNext, flags, NULL)) == NULL)
return FALSE;
fSuccess = TRUE;
for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
/*
* Lock the window before we pass it off to the app.
*/
if ((pwnd = RevalidateHwnd(*phwnd)) != NULL) {
/*
* Call the application.
*/
ThreadLockAlways(pwnd, &tlpwnd);
fSuccess = (*lpfn)(pwnd, lParam);
ThreadUnlock(&tlpwnd);
if (!fSuccess)
break;
}
}
FreeHwndList(pbwl);
return fSuccess;
}
/***************************************************************************\
* BuildHwndList
*
* History:
* 10-20-90 darrinm Ported from Win 3.0 sources.
\***************************************************************************/
#define CHWND_BWLCREATE 32
PBWL BuildHwndList(
PWND pwnd,
UINT flags,
PTHREADINFO pti)
{
PBWL pbwl;
CheckCritIn();
if ((pbwl = pbwlCache) != NULL) {
/*
* We're using the cache now; zero it out.
*/
#if DBG
pbwlCachePrev = pbwlCache;
#endif
pbwlCache = NULL;
} else {
/*
* sizeof(BWL) includes the first element of array.
*/
pbwl = (PBWL)UserAllocPool(sizeof(BWL) + sizeof(PWND) * CHWND_BWLCREATE,
TAG_WINDOWLIST);
if (pbwl == NULL)
return NULL;
pbwl->phwndMax = &pbwl->rghwnd[CHWND_BWLCREATE - 1];
}
pbwl->phwndNext = pbwl->rghwnd;
/*
* We'll use ptiOwner as temporary storage for the thread we're
* scanning for. It will get reset to the proper thing at the bottom
* of this routine.
*/
pbwl->ptiOwner = pti;
#ifdef OWNERLIST
if (flags & BWL_ENUMOWNERLIST) {
pbwl = InternalBuildHwndOwnerList(pbwl, pwnd, NULL);
} else {
pbwl = InternalBuildHwndList(pbwl, pwnd, flags);
}
#else
pbwl = InternalBuildHwndList(pbwl, pwnd, flags);
#endif
/*
* Stick in the terminator.
*/
*pbwl->phwndNext = (HWND)1;
/*
* Finally link this guy into the list.
*/
pbwl->ptiOwner = PtiCurrent();
pbwl->pbwlNext = pbwlList;
pbwlList = pbwl;
/*
* We should have given out the cache if it was available
*/
UserAssert(pbwlCache == NULL);
return pbwl;
}
/***************************************************************************\
* ExpandWindowList
*
* This routine expands a window list.
*
* 01-16-92 ScottLu Created.
\***************************************************************************/
BOOL ExpandWindowList(
PBWL *ppbwl)
{
PBWL pbwl;
PBWL pbwlT;
HWND *phwnd;
pbwl = *ppbwl;
phwnd = pbwl->phwndNext;
/*
* Map phwnd to an offset.
*/
phwnd = (HWND *)((BYTE *)phwnd - (BYTE *)pbwl);
/*
* Increase size of BWL by 8 slots. (8 + 1) is
* added since phwnd is "sizeof(HWND)" less
* than actual size of handle.
*/
pbwlT = (PBWL)UserReAllocPool((HANDLE)pbwl,
(DWORD)phwnd + sizeof(PWND),
(DWORD)phwnd + (BWL_CHWNDMORE + 1) * sizeof(PWND),
TAG_WINDOWLIST);
/*
* Did alloc succeed?
*/
if (pbwlT != NULL)
pbwl = pbwlT; /* Yes, use new block. */
/*
* Map phwnd back into a pointer.
*/
phwnd = (HWND *)((DWORD)pbwl + (DWORD)phwnd);
/*
* Did ReAlloc() fail?
*/
if (pbwlT == NULL) {
RIPMSG0(RIP_WARNING, "ExpandWindowList: out of memory.");
return FALSE;
}
/*
* Reset phwndMax.
*/
pbwl->phwndNext = phwnd;
pbwl->phwndMax = phwnd + BWL_CHWNDMORE;
*ppbwl = pbwl;
return TRUE;
}
#ifdef OWNERLIST
/***************************************************************************\
* InternalBuildHwndOwnerList
*
* Builds an hwnd list sorted by owner. Ownees go first. Shutdown uses this for
* WM_CLOSE messages.
*
* 01-16-93 ScottLu Created.
\***************************************************************************/
PBWL InternalBuildHwndOwnerList(
PBWL pbwl,
PWND pwndStart,
PWND pwndOwner)
{
PWND pwndT;
/*
* Put ownees first in the list.
*/
for (pwndT = pwndStart; pwndT != NULL; pwndT = pwndT->spwndNext) {
/*
* Not the ownee we're looking for? Continue.
*/
if (pwndT->spwndOwner != pwndOwner)
continue;
/*
* Only top level windows that have system menus (the ones that can
* receive a WM_CLOSE message).
*/
if (!TestWF(pwndT, WFSYSMENU))
continue;
/*
* Add it and its ownees to our list.
*/
pbwl = InternalBuildHwndOwnerList(pbwl, pwndStart, pwndT);
}
/*
* Finally add this owner to our list.
*/
if (pwndOwner != NULL) {
*pbwl->phwndNext = HWq(pwndOwner);
pbwl->phwndNext++;
if (pbwl->phwndNext == pbwl->phwndMax) {
if (!ExpandWindowList(&pbwl))
return pbwl;
}
}
return pbwl;
}
#endif
/***************************************************************************\
* InternalBuildHwndList
*
* History:
* 10-20-90 darrinm Ported from Win 3.0 sources.
\***************************************************************************/
#define BWLGROW 8
PBWL InternalBuildHwndList(
PBWL pbwl,
PWND pwnd,
UINT flags)
{
/*
* NOTE: pbwl->phwndNext is used as a place to keep
* the phwnd across calls to InternalBuildHwndList().
* This is OK since we don't link pbwl into the list
* of pbwl's until after we've finished enumerating windows.
*/
while (pwnd != NULL) {
/*
* Make sure it matches the thread id, if there is one.
*/
if (pbwl->ptiOwner == NULL || pbwl->ptiOwner == GETPTI(pwnd)) {
*pbwl->phwndNext = HWq(pwnd);
pbwl->phwndNext++;
if (pbwl->phwndNext == pbwl->phwndMax) {
if (!ExpandWindowList(&pbwl))
break;
}
}
/*
* Should we step through the Child windows?
*/
if ((flags & BWL_ENUMCHILDREN) && pwnd->spwndChild != NULL) {
pbwl = InternalBuildHwndList(pbwl, pwnd->spwndChild, BWL_ENUMLIST | BWL_ENUMCHILDREN);
}
/*
* Are we enumerating only one window?
*/
if (!(flags & BWL_ENUMLIST))
break;
pwnd = pwnd->spwndNext;
}
return pbwl;
}
/***************************************************************************\
* FreeHwndList
*
* History:
* 10-20-90 darrinm Ported from Win 3.0 sources.
\***************************************************************************/
void FreeHwndList(
PBWL pbwl)
{
PBWL *ppbwl;
PBWL pbwlT;
CheckCritIn();
/*
* We should never have an active bwl that is the free cached bwl
*/
UserAssert(pbwl != pbwlCache);
/*
* Unlink this bwl from the list.
*/
for (ppbwl = &pbwlList; *ppbwl != NULL; ppbwl = &(*ppbwl)->pbwlNext) {
if (*ppbwl == pbwl) {
*ppbwl = pbwl->pbwlNext;
/*
* If the cache is empty or this pbwl is larger than the
* cached one, save the pbwl there.
*/
if (pbwlCache == NULL) {
pbwlCache = pbwl;
} else if ((pbwl->phwndMax - pbwl->rghwnd) >
(pbwlCache->phwndMax - pbwlCache->rghwnd)) {
pbwlT = pbwlCache;
pbwlCache = pbwl;
UserFreePool((HANDLE)pbwlT);
} else {
UserFreePool((HANDLE)pbwl);
}
return;
}
}
/*
* Assert if we couldn't find the pbwl in the list...
*/
UserAssert(FALSE);
}