/****************************** 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 LocalAlloc. */ 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 are not * suppose to see. */ 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; iiawchNames; 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); }