Leaked source code of windows server 2003
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.
 
 
 
 
 
 

558 lines
16 KiB

/****************************** Module Header ******************************\
* Module Name: clenum
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* For enumeration functions
*
* 04-27-91 ScottLu Created.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
#define IEP_UNICODE 0x1 // Convert Atom to unicode string (vs ANSI)
#define IEP_ENUMEX 0x2 // Pass lParam back to callback function (vs no lParam)
HWND *phwndCache = NULL;
/***************************************************************************\
* InternalEnumWindows
*
* Calls server and gets back a window list. This list is enumerated, for each
* window the callback address is called (into the application), until either
* end-of-list is reached or FALSE is return ed. lParam is passed into the
* callback function for app reference.
*
*
* If any windows are returned (cHwnd > 0) the caller is responsible for
* freeing the window buffer when done with the list
*
* 04-27-91 ScottLu Created.
\***************************************************************************/
DWORD BuildHwndList(
HDESK hdesk,
HWND hwndNext,
BOOL fEnumChildren,
DWORD idThread,
HWND **pphwndFirst)
{
UINT cHwnd;
HWND *phwndFirst;
NTSTATUS Status;
int cTries;
/*
* Allocate a buffer to hold the names.
*/
cHwnd = 64;
phwndFirst = (HWND *)InterlockedExchangePointer(&(PVOID)phwndCache, 0);
if (phwndFirst == NULL) {
phwndFirst = UserLocalAlloc(0, cHwnd * sizeof(HWND));
if (phwndFirst == NULL) {
return 0;
}
}
Status = NtUserBuildHwndList(hdesk,
hwndNext,
fEnumChildren,
idThread,
cHwnd,
phwndFirst,
&cHwnd);
/*
* If the buffer wasn't big enough, reallocate the buffer and try again.
*/
cTries = 0;
while (Status == STATUS_BUFFER_TOO_SMALL) {
UserLocalFree(phwndFirst);
/*
* If we can't seem to get it right, call it quits.
*/
if (cTries++ == 10) {
return 0;
}
phwndFirst = UserLocalAlloc(0, cHwnd * sizeof(HWND));
if (phwndFirst == NULL) {
return 0;
}
Status = NtUserBuildHwndList(hdesk,
hwndNext,
fEnumChildren,
idThread,
cHwnd,
phwndFirst,
&cHwnd);
}
if (!NT_SUCCESS(Status) || cHwnd <= 1) {
UserLocalFree(phwndFirst);
return 0;
}
*pphwndFirst = phwndFirst;
return cHwnd - 1;
}
BOOL InternalEnumWindows(
HDESK hdesk,
HWND hwnd,
WNDENUMPROC lpfn,
LPARAM lParam,
DWORD idThread,
BOOL fEnumChildren)
{
UINT i;
UINT cHwnd;
HWND *phwndT;
HWND *phwndFirst;
BOOL fSuccess = TRUE;
/*
* Get the hwnd list. It is returned in a block of memory allocated with
* UserLocalAlloc.
*/
if ((cHwnd = BuildHwndList(hdesk, hwnd, fEnumChildren, idThread,
&phwndFirst)) == -1) {
return FALSE;
}
/*
* In Win 3.1 it was not an error if there were no windows in the thread.
*/
if (cHwnd == 0) {
if (idThread == 0) {
return FALSE;
} else {
return TRUE;
}
}
/*
* Loop through the windows, call the function pointer back for each
* one. End loop if either FALSE is return ed or the end-of-list is
* reached.
*/
phwndT = phwndFirst;
for (i = 0; i < cHwnd; i++) {
/*
* Call ValidateHwnd instead of RevalidateHwnd so that restricted
* processes don't see handles they aren't supposed to.
*/
if (ValidateHwnd(*phwndT)) {
if (!(fSuccess = (*lpfn)(*phwndT, lParam))) {
break;
}
}
phwndT++;
}
/*
* Free up buffer and return status - TRUE if entire list was enumerated,
* FALSE otherwise.
*/
phwndT = (HWND *)InterlockedExchangePointer(&(PVOID)phwndCache, phwndFirst);
if (phwndT != NULL) {
UserLocalFree(phwndT);
}
return fSuccess;
}
/***************************************************************************\
* EnumWindows
*
* Enumerates all top-level windows. Calls back lpfn with each hwnd until
* either end-of-list or FALSE is return ed. lParam is passed into callback
* function for app reference.
*
* 04-27-91 ScottLu Created.
\***************************************************************************/
FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, EnumWindows, WNDENUMPROC, lpfn, LPARAM, lParam)
BOOL WINAPI EnumWindows(
WNDENUMPROC lpfn,
LPARAM lParam)
{
return InternalEnumWindows(NULL, NULL, lpfn, lParam, 0L, FALSE);
}
/***************************************************************************\
* EnumChildWindows
*
* Enumerates all children of the passed in window. Calls back lpfn with each
* hwnd until either end-of-list or FALSE is return ed. lParam is passed into
* callback function for app reference.
*
* 04-27-91 ScottLu Created.
\***************************************************************************/
FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumChildWindows, HWND, hwnd, WNDENUMPROC, lpfn, LPARAM, lParam)
BOOL WINAPI EnumChildWindows(
HWND hwnd,
WNDENUMPROC lpfn,
LPARAM lParam)
{
return InternalEnumWindows(NULL, hwnd, lpfn, lParam, 0L, TRUE);
}
/***************************************************************************\
* EnumThreadWindows
*
* Enumerates all top level windows created by idThread. Calls back lpfn with
* each hwnd until either end-of-list or FALSE is return ed. lParam is passed
* into callback function for app reference.
*
* 06-23-91 ScottLu Created.
\***************************************************************************/
FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EnumThreadWindows, DWORD, idThread, WNDENUMPROC, lpfn, LPARAM, lParam)
BOOL EnumThreadWindows(
DWORD idThread,
WNDENUMPROC lpfn,
LPARAM lParam)
{
return InternalEnumWindows(NULL, NULL, lpfn, lParam, idThread, FALSE);
}
/***************************************************************************\
* EnumDesktopWindows
*
* Enumerates all top level windows on the desktop specified by hdesk.
* Calls back lpfn with each hwnd until either end-of-list or FALSE
* is returned. lParam is passed into callback function for app reference.
*
* 10-10-94 JimA Created.
\***************************************************************************/
FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EnumDesktopWindows, HDESK, hdesk, WNDENUMPROC, lpfn, LPARAM, lParam)
BOOL EnumDesktopWindows(
HDESK hdesk,
WNDENUMPROC lpfn,
LPARAM lParam)
{
return InternalEnumWindows(hdesk, NULL, lpfn, lParam, 0, FALSE);
}
/***************************************************************************\
* InternalEnumProps
*
* Calls server and gets back a list of props for the specified window.
* The callback address is called (into the application), until either
* end-of-list is reached or FALSE is return ed.
* lParam is passed into the callback function for app reference when
* IEP_ENUMEX is set. Atoms are turned into UNICODE string if IEP_UNICODE
* is set.
*
* 22-Jan-1992 JohnC Created.
\***************************************************************************/
#define MAX_ATOM_SIZE 512
#define ISSTRINGATOM(atom) ((WORD)(atom) >= 0xc000)
INT InternalEnumProps(
HWND hwnd,
PROPENUMPROC lpfn,
LPARAM lParam,
UINT flags)
{
DWORD ii;
DWORD cPropSets;
PPROPSET pPropSet;
WCHAR awch[MAX_ATOM_SIZE];
PVOID pKey;
INT iRetVal;
DWORD cchName;
NTSTATUS Status;
int cTries;
/*
* Allocate a buffer to hold the names.
*/
cPropSets = 32;
pPropSet = UserLocalAlloc(0, cPropSets * sizeof(PROPSET));
if (pPropSet == NULL) {
return -1;
}
Status = NtUserBuildPropList(hwnd, cPropSets, pPropSet, &cPropSets);
/*
* If the buffer wasn't big enough, reallocate the buffer and try again.
*/
cTries = 0;
while (Status == STATUS_BUFFER_TOO_SMALL) {
UserLocalFree(pPropSet);
/*
* If we can't seem to get it right, call it quits.
*/
if (cTries++ == 10) {
return -1;
}
pPropSet = UserLocalAlloc(0, cPropSets * sizeof(PROPSET));
if (pPropSet == NULL) {
return -1;
}
Status = NtUserBuildPropList(hwnd, cPropSets, pPropSet, &cPropSets);
}
if (!NT_SUCCESS(Status)) {
UserLocalFree(pPropSet);
return -1;
}
for (ii = 0; ii < cPropSets; ii++) {
if (ISSTRINGATOM(pPropSet[ii].atom)) {
pKey = (PVOID)awch;
if (flags & IEP_UNICODE) {
cchName = GlobalGetAtomNameW(pPropSet[ii].atom,
(LPWSTR)pKey,
MAX_ATOM_SIZE);
} else {
cchName = GlobalGetAtomNameA(pPropSet[ii].atom,
(LPSTR)pKey,
sizeof(awch));
}
/*
* If cchName is zero, we must assume that the property belongs
* to another process. Because we can't get the name, just skip
* it.
*/
if (cchName == 0) {
continue;
}
} else {
pKey = (PVOID)pPropSet[ii].atom;
}
if (flags & IEP_ENUMEX) {
iRetVal = (*(PROPENUMPROCEX)lpfn)(hwnd, pKey,
pPropSet[ii].hData, lParam);
} else {
iRetVal = (*lpfn)(hwnd, pKey, pPropSet[ii].hData);
}
if (!iRetVal) {
break;
}
}
UserLocalFree(pPropSet);
return iRetVal;
}
/***************************************************************************\
* EnumProps
*
* This function enumerates all entries in the property list of the specified
* window. It enumerates the entries by passing them, one by one, to the
* callback function specified by lpEnumFunc. EnumProps continues until the
* last entry is enumerated or the callback function return s zero.
*
* 22-Jan-1992 JohnC Created.
\***************************************************************************/
FUNCLOG2(LOG_GENERAL, INT, WINAPI, EnumPropsA, HWND, hwnd, PROPENUMPROCA, lpfn)
INT WINAPI EnumPropsA(
HWND hwnd,
PROPENUMPROCA lpfn)
{
return InternalEnumProps(hwnd, (PROPENUMPROC)lpfn, 0, 0);
}
FUNCLOG2(LOG_GENERAL, INT, WINAPI, EnumPropsW, HWND, hwnd, PROPENUMPROCW, lpfn)
INT WINAPI EnumPropsW(
HWND hwnd,
PROPENUMPROCW lpfn)
{
return InternalEnumProps(hwnd, (PROPENUMPROC)lpfn, 0, IEP_UNICODE);
}
/***************************************************************************\
* EnumPropsEx
*
* This function enumerates all entries in the property list of the specified
* window. It enumerates the entries by passing them, one by one, to the
* callback function specified by lpEnumFunc. EnumProps continues until the
* last entry is enumerated or the callback function return s zero.
*
* 22-Jan-1992 JohnC Created.
\***************************************************************************/
FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumPropsExA, HWND, hwnd, PROPENUMPROCEXA, lpfn, LPARAM, lParam)
BOOL WINAPI EnumPropsExA(
HWND hwnd,
PROPENUMPROCEXA lpfn,
LPARAM lParam)
{
return InternalEnumProps(hwnd, (PROPENUMPROC)lpfn, lParam, IEP_ENUMEX);
}
FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumPropsExW, HWND, hwnd, PROPENUMPROCEXW, lpfn, LPARAM, lParam)
BOOL WINAPI EnumPropsExW(
HWND hwnd,
PROPENUMPROCEXW lpfn,
LPARAM lParam)
{
return InternalEnumProps(hwnd, (PROPENUMPROC)lpfn, lParam, IEP_UNICODE|IEP_ENUMEX);
}
BOOL InternalEnumObjects(
HWINSTA hwinsta,
NAMEENUMPROCW lpfn,
LPARAM lParam,
BOOL fAnsi)
{
PNAMELIST pNameList;
DWORD i;
UINT cbData;
PWCHAR pwch;
PCHAR pch;
CHAR achTmp[MAX_PATH];
BOOL iRetVal;
NTSTATUS Status;
int cTries;
/*
* Allocate a buffer to hold the names. The size of the buffer is
* determined by the maximum size for a window station name defined
* in ntstubs.c.
*/
cbData = STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR);
pNameList = UserLocalAlloc(0, cbData);
if (pNameList == NULL) {
return FALSE;
}
Status = NtUserBuildNameList(hwinsta, cbData, pNameList, &cbData);
/*
* If the buffer wasn't big enough, reallocate the buffer and try again.
*/
cTries = 0;
while (Status == STATUS_BUFFER_TOO_SMALL) {
UserLocalFree(pNameList);
/*
* If we can't seem to get it right, call it quits.
*/
if (cTries++ == 10) {
return FALSE;
}
pNameList = UserLocalAlloc(0, cbData);
if (pNameList == NULL) {
return FALSE;
}
Status = NtUserBuildNameList(hwinsta, cbData, pNameList, &cbData);
}
if (!NT_SUCCESS(Status)) {
UserLocalFree(pNameList);
return FALSE;
}
pwch = pNameList->awchNames;
pch = achTmp;
for (i = 0; i < pNameList->cNames; i++) {
if (fAnsi) {
if (WCSToMB(pwch, -1, &pch, sizeof(achTmp), FALSE) ==
sizeof(achTmp)) {
/*
* The buffer may have overflowed, so force it to be
* allocated.
*/
if (WCSToMB(pwch, -1, &pch, -1, TRUE) == 0) {
iRetVal = FALSE;
break;
}
}
iRetVal = (*(NAMEENUMPROCA)lpfn)(pch, lParam);
if (pch != achTmp) {
UserLocalFree(pch);
pch = achTmp;
}
} else {
iRetVal = (*(NAMEENUMPROCW)lpfn)(pwch, lParam);
}
if (!iRetVal) {
break;
}
pwch = pwch + wcslen(pwch) + 1;
}
UserLocalFree(pNameList);
return iRetVal;
}
FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, EnumWindowStationsA, WINSTAENUMPROCA, lpEnumFunc, LPARAM, lParam)
BOOL WINAPI EnumWindowStationsA(
WINSTAENUMPROCA lpEnumFunc,
LPARAM lParam)
{
return InternalEnumObjects(NULL, (NAMEENUMPROCW)lpEnumFunc, lParam, TRUE);
}
FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, EnumWindowStationsW, WINSTAENUMPROCW, lpEnumFunc, LPARAM, lParam)
BOOL WINAPI EnumWindowStationsW(
WINSTAENUMPROCW lpEnumFunc,
LPARAM lParam)
{
return InternalEnumObjects(NULL, (NAMEENUMPROCW)lpEnumFunc, lParam, FALSE);
}
FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumDesktopsA, HWINSTA, hwinsta, DESKTOPENUMPROCA, lpEnumFunc, LPARAM, lParam)
BOOL WINAPI EnumDesktopsA(
HWINSTA hwinsta,
DESKTOPENUMPROCA lpEnumFunc,
LPARAM lParam)
{
return InternalEnumObjects(hwinsta, (NAMEENUMPROCW)lpEnumFunc, lParam, TRUE);
}
FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumDesktopsW, HWINSTA, hwinsta, DESKTOPENUMPROCW, lpEnumFunc, LPARAM, lParam)
BOOL WINAPI EnumDesktopsW(
HWINSTA hwinsta,
DESKTOPENUMPROCW lpEnumFunc,
LPARAM lParam)
{
return InternalEnumObjects(hwinsta, (NAMEENUMPROCW)lpEnumFunc, lParam, FALSE);
}