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

  1. /****************************** Module Header ******************************\
  2. * Module Name: clenum
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * For enumeration functions
  7. *
  8. * 04-27-91 ScottLu Created.
  9. \***************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #define IEP_UNICODE 0x1 // Convert Atom to unicode string (vs ANSI)
  13. #define IEP_ENUMEX 0x2 // Pass lParam back to callback function (vs no lParam)
  14. HWND *phwndCache = NULL;
  15. /***************************************************************************\
  16. * InternalEnumWindows
  17. *
  18. * Calls server and gets back a window list. This list is enumerated, for each
  19. * window the callback address is called (into the application), until either
  20. * end-of-list is reached or FALSE is return ed. lParam is passed into the
  21. * callback function for app reference.
  22. *
  23. *
  24. * If any windows are returned (cHwnd > 0) the caller is responsible for
  25. * freeing the window buffer when done with the list
  26. *
  27. * 04-27-91 ScottLu Created.
  28. \***************************************************************************/
  29. DWORD BuildHwndList(
  30. HDESK hdesk,
  31. HWND hwndNext,
  32. BOOL fEnumChildren,
  33. DWORD idThread,
  34. HWND **pphwndFirst)
  35. {
  36. UINT cHwnd;
  37. HWND *phwndFirst;
  38. NTSTATUS Status;
  39. int cTries;
  40. /*
  41. * Allocate a buffer to hold the names.
  42. */
  43. cHwnd = 64;
  44. phwndFirst = (HWND *)InterlockedExchangePointer(&(PVOID)phwndCache, 0);
  45. if (phwndFirst == NULL) {
  46. phwndFirst = UserLocalAlloc(0, cHwnd * sizeof(HWND));
  47. if (phwndFirst == NULL) {
  48. return 0;
  49. }
  50. }
  51. Status = NtUserBuildHwndList(hdesk,
  52. hwndNext,
  53. fEnumChildren,
  54. idThread,
  55. cHwnd,
  56. phwndFirst,
  57. &cHwnd);
  58. /*
  59. * If the buffer wasn't big enough, reallocate the buffer and try again.
  60. */
  61. cTries = 0;
  62. while (Status == STATUS_BUFFER_TOO_SMALL) {
  63. UserLocalFree(phwndFirst);
  64. /*
  65. * If we can't seem to get it right, call it quits.
  66. */
  67. if (cTries++ == 10) {
  68. return 0;
  69. }
  70. phwndFirst = UserLocalAlloc(0, cHwnd * sizeof(HWND));
  71. if (phwndFirst == NULL) {
  72. return 0;
  73. }
  74. Status = NtUserBuildHwndList(hdesk,
  75. hwndNext,
  76. fEnumChildren,
  77. idThread,
  78. cHwnd,
  79. phwndFirst,
  80. &cHwnd);
  81. }
  82. if (!NT_SUCCESS(Status) || cHwnd <= 1) {
  83. UserLocalFree(phwndFirst);
  84. return 0;
  85. }
  86. *pphwndFirst = phwndFirst;
  87. return cHwnd - 1;
  88. }
  89. BOOL InternalEnumWindows(
  90. HDESK hdesk,
  91. HWND hwnd,
  92. WNDENUMPROC lpfn,
  93. LPARAM lParam,
  94. DWORD idThread,
  95. BOOL fEnumChildren)
  96. {
  97. UINT i;
  98. UINT cHwnd;
  99. HWND *phwndT;
  100. HWND *phwndFirst;
  101. BOOL fSuccess = TRUE;
  102. /*
  103. * Get the hwnd list. It is returned in a block of memory allocated with
  104. * UserLocalAlloc.
  105. */
  106. if ((cHwnd = BuildHwndList(hdesk, hwnd, fEnumChildren, idThread,
  107. &phwndFirst)) == -1) {
  108. return FALSE;
  109. }
  110. /*
  111. * In Win 3.1 it was not an error if there were no windows in the thread.
  112. */
  113. if (cHwnd == 0) {
  114. if (idThread == 0) {
  115. return FALSE;
  116. } else {
  117. return TRUE;
  118. }
  119. }
  120. /*
  121. * Loop through the windows, call the function pointer back for each
  122. * one. End loop if either FALSE is return ed or the end-of-list is
  123. * reached.
  124. */
  125. phwndT = phwndFirst;
  126. for (i = 0; i < cHwnd; i++) {
  127. /*
  128. * Call ValidateHwnd instead of RevalidateHwnd so that restricted
  129. * processes don't see handles they aren't supposed to.
  130. */
  131. if (ValidateHwnd(*phwndT)) {
  132. if (!(fSuccess = (*lpfn)(*phwndT, lParam))) {
  133. break;
  134. }
  135. }
  136. phwndT++;
  137. }
  138. /*
  139. * Free up buffer and return status - TRUE if entire list was enumerated,
  140. * FALSE otherwise.
  141. */
  142. phwndT = (HWND *)InterlockedExchangePointer(&(PVOID)phwndCache, phwndFirst);
  143. if (phwndT != NULL) {
  144. UserLocalFree(phwndT);
  145. }
  146. return fSuccess;
  147. }
  148. /***************************************************************************\
  149. * EnumWindows
  150. *
  151. * Enumerates all top-level windows. Calls back lpfn with each hwnd until
  152. * either end-of-list or FALSE is return ed. lParam is passed into callback
  153. * function for app reference.
  154. *
  155. * 04-27-91 ScottLu Created.
  156. \***************************************************************************/
  157. FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, EnumWindows, WNDENUMPROC, lpfn, LPARAM, lParam)
  158. BOOL WINAPI EnumWindows(
  159. WNDENUMPROC lpfn,
  160. LPARAM lParam)
  161. {
  162. return InternalEnumWindows(NULL, NULL, lpfn, lParam, 0L, FALSE);
  163. }
  164. /***************************************************************************\
  165. * EnumChildWindows
  166. *
  167. * Enumerates all children of the passed in window. Calls back lpfn with each
  168. * hwnd until either end-of-list or FALSE is return ed. lParam is passed into
  169. * callback function for app reference.
  170. *
  171. * 04-27-91 ScottLu Created.
  172. \***************************************************************************/
  173. FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumChildWindows, HWND, hwnd, WNDENUMPROC, lpfn, LPARAM, lParam)
  174. BOOL WINAPI EnumChildWindows(
  175. HWND hwnd,
  176. WNDENUMPROC lpfn,
  177. LPARAM lParam)
  178. {
  179. return InternalEnumWindows(NULL, hwnd, lpfn, lParam, 0L, TRUE);
  180. }
  181. /***************************************************************************\
  182. * EnumThreadWindows
  183. *
  184. * Enumerates all top level windows created by idThread. Calls back lpfn with
  185. * each hwnd until either end-of-list or FALSE is return ed. lParam is passed
  186. * into callback function for app reference.
  187. *
  188. * 06-23-91 ScottLu Created.
  189. \***************************************************************************/
  190. FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EnumThreadWindows, DWORD, idThread, WNDENUMPROC, lpfn, LPARAM, lParam)
  191. BOOL EnumThreadWindows(
  192. DWORD idThread,
  193. WNDENUMPROC lpfn,
  194. LPARAM lParam)
  195. {
  196. return InternalEnumWindows(NULL, NULL, lpfn, lParam, idThread, FALSE);
  197. }
  198. /***************************************************************************\
  199. * EnumDesktopWindows
  200. *
  201. * Enumerates all top level windows on the desktop specified by hdesk.
  202. * Calls back lpfn with each hwnd until either end-of-list or FALSE
  203. * is returned. lParam is passed into callback function for app reference.
  204. *
  205. * 10-10-94 JimA Created.
  206. \***************************************************************************/
  207. FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EnumDesktopWindows, HDESK, hdesk, WNDENUMPROC, lpfn, LPARAM, lParam)
  208. BOOL EnumDesktopWindows(
  209. HDESK hdesk,
  210. WNDENUMPROC lpfn,
  211. LPARAM lParam)
  212. {
  213. return InternalEnumWindows(hdesk, NULL, lpfn, lParam, 0, FALSE);
  214. }
  215. /***************************************************************************\
  216. * InternalEnumProps
  217. *
  218. * Calls server and gets back a list of props for the specified window.
  219. * The callback address is called (into the application), until either
  220. * end-of-list is reached or FALSE is return ed.
  221. * lParam is passed into the callback function for app reference when
  222. * IEP_ENUMEX is set. Atoms are turned into UNICODE string if IEP_UNICODE
  223. * is set.
  224. *
  225. * 22-Jan-1992 JohnC Created.
  226. \***************************************************************************/
  227. #define MAX_ATOM_SIZE 512
  228. #define ISSTRINGATOM(atom) ((WORD)(atom) >= 0xc000)
  229. INT InternalEnumProps(
  230. HWND hwnd,
  231. PROPENUMPROC lpfn,
  232. LPARAM lParam,
  233. UINT flags)
  234. {
  235. DWORD ii;
  236. DWORD cPropSets;
  237. PPROPSET pPropSet;
  238. WCHAR awch[MAX_ATOM_SIZE];
  239. PVOID pKey;
  240. INT iRetVal;
  241. DWORD cchName;
  242. NTSTATUS Status;
  243. int cTries;
  244. /*
  245. * Allocate a buffer to hold the names.
  246. */
  247. cPropSets = 32;
  248. pPropSet = UserLocalAlloc(0, cPropSets * sizeof(PROPSET));
  249. if (pPropSet == NULL) {
  250. return -1;
  251. }
  252. Status = NtUserBuildPropList(hwnd, cPropSets, pPropSet, &cPropSets);
  253. /*
  254. * If the buffer wasn't big enough, reallocate the buffer and try again.
  255. */
  256. cTries = 0;
  257. while (Status == STATUS_BUFFER_TOO_SMALL) {
  258. UserLocalFree(pPropSet);
  259. /*
  260. * If we can't seem to get it right, call it quits.
  261. */
  262. if (cTries++ == 10) {
  263. return -1;
  264. }
  265. pPropSet = UserLocalAlloc(0, cPropSets * sizeof(PROPSET));
  266. if (pPropSet == NULL) {
  267. return -1;
  268. }
  269. Status = NtUserBuildPropList(hwnd, cPropSets, pPropSet, &cPropSets);
  270. }
  271. if (!NT_SUCCESS(Status)) {
  272. UserLocalFree(pPropSet);
  273. return -1;
  274. }
  275. for (ii = 0; ii < cPropSets; ii++) {
  276. if (ISSTRINGATOM(pPropSet[ii].atom)) {
  277. pKey = (PVOID)awch;
  278. if (flags & IEP_UNICODE) {
  279. cchName = GlobalGetAtomNameW(pPropSet[ii].atom,
  280. (LPWSTR)pKey,
  281. MAX_ATOM_SIZE);
  282. } else {
  283. cchName = GlobalGetAtomNameA(pPropSet[ii].atom,
  284. (LPSTR)pKey,
  285. sizeof(awch));
  286. }
  287. /*
  288. * If cchName is zero, we must assume that the property belongs
  289. * to another process. Because we can't get the name, just skip
  290. * it.
  291. */
  292. if (cchName == 0) {
  293. continue;
  294. }
  295. } else {
  296. pKey = (PVOID)pPropSet[ii].atom;
  297. }
  298. if (flags & IEP_ENUMEX) {
  299. iRetVal = (*(PROPENUMPROCEX)lpfn)(hwnd, pKey,
  300. pPropSet[ii].hData, lParam);
  301. } else {
  302. iRetVal = (*lpfn)(hwnd, pKey, pPropSet[ii].hData);
  303. }
  304. if (!iRetVal) {
  305. break;
  306. }
  307. }
  308. UserLocalFree(pPropSet);
  309. return iRetVal;
  310. }
  311. /***************************************************************************\
  312. * EnumProps
  313. *
  314. * This function enumerates all entries in the property list of the specified
  315. * window. It enumerates the entries by passing them, one by one, to the
  316. * callback function specified by lpEnumFunc. EnumProps continues until the
  317. * last entry is enumerated or the callback function return s zero.
  318. *
  319. * 22-Jan-1992 JohnC Created.
  320. \***************************************************************************/
  321. FUNCLOG2(LOG_GENERAL, INT, WINAPI, EnumPropsA, HWND, hwnd, PROPENUMPROCA, lpfn)
  322. INT WINAPI EnumPropsA(
  323. HWND hwnd,
  324. PROPENUMPROCA lpfn)
  325. {
  326. return InternalEnumProps(hwnd, (PROPENUMPROC)lpfn, 0, 0);
  327. }
  328. FUNCLOG2(LOG_GENERAL, INT, WINAPI, EnumPropsW, HWND, hwnd, PROPENUMPROCW, lpfn)
  329. INT WINAPI EnumPropsW(
  330. HWND hwnd,
  331. PROPENUMPROCW lpfn)
  332. {
  333. return InternalEnumProps(hwnd, (PROPENUMPROC)lpfn, 0, IEP_UNICODE);
  334. }
  335. /***************************************************************************\
  336. * EnumPropsEx
  337. *
  338. * This function enumerates all entries in the property list of the specified
  339. * window. It enumerates the entries by passing them, one by one, to the
  340. * callback function specified by lpEnumFunc. EnumProps continues until the
  341. * last entry is enumerated or the callback function return s zero.
  342. *
  343. * 22-Jan-1992 JohnC Created.
  344. \***************************************************************************/
  345. FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumPropsExA, HWND, hwnd, PROPENUMPROCEXA, lpfn, LPARAM, lParam)
  346. BOOL WINAPI EnumPropsExA(
  347. HWND hwnd,
  348. PROPENUMPROCEXA lpfn,
  349. LPARAM lParam)
  350. {
  351. return InternalEnumProps(hwnd, (PROPENUMPROC)lpfn, lParam, IEP_ENUMEX);
  352. }
  353. FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumPropsExW, HWND, hwnd, PROPENUMPROCEXW, lpfn, LPARAM, lParam)
  354. BOOL WINAPI EnumPropsExW(
  355. HWND hwnd,
  356. PROPENUMPROCEXW lpfn,
  357. LPARAM lParam)
  358. {
  359. return InternalEnumProps(hwnd, (PROPENUMPROC)lpfn, lParam, IEP_UNICODE|IEP_ENUMEX);
  360. }
  361. BOOL InternalEnumObjects(
  362. HWINSTA hwinsta,
  363. NAMEENUMPROCW lpfn,
  364. LPARAM lParam,
  365. BOOL fAnsi)
  366. {
  367. PNAMELIST pNameList;
  368. DWORD i;
  369. UINT cbData;
  370. PWCHAR pwch;
  371. PCHAR pch;
  372. CHAR achTmp[MAX_PATH];
  373. BOOL iRetVal;
  374. NTSTATUS Status;
  375. int cTries;
  376. /*
  377. * Allocate a buffer to hold the names. The size of the buffer is
  378. * determined by the maximum size for a window station name defined
  379. * in ntstubs.c.
  380. */
  381. cbData = STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR);
  382. pNameList = UserLocalAlloc(0, cbData);
  383. if (pNameList == NULL) {
  384. return FALSE;
  385. }
  386. Status = NtUserBuildNameList(hwinsta, cbData, pNameList, &cbData);
  387. /*
  388. * If the buffer wasn't big enough, reallocate the buffer and try again.
  389. */
  390. cTries = 0;
  391. while (Status == STATUS_BUFFER_TOO_SMALL) {
  392. UserLocalFree(pNameList);
  393. /*
  394. * If we can't seem to get it right, call it quits.
  395. */
  396. if (cTries++ == 10) {
  397. return FALSE;
  398. }
  399. pNameList = UserLocalAlloc(0, cbData);
  400. if (pNameList == NULL) {
  401. return FALSE;
  402. }
  403. Status = NtUserBuildNameList(hwinsta, cbData, pNameList, &cbData);
  404. }
  405. if (!NT_SUCCESS(Status)) {
  406. UserLocalFree(pNameList);
  407. return FALSE;
  408. }
  409. pwch = pNameList->awchNames;
  410. pch = achTmp;
  411. for (i = 0; i < pNameList->cNames; i++) {
  412. if (fAnsi) {
  413. if (WCSToMB(pwch, -1, &pch, sizeof(achTmp), FALSE) ==
  414. sizeof(achTmp)) {
  415. /*
  416. * The buffer may have overflowed, so force it to be
  417. * allocated.
  418. */
  419. if (WCSToMB(pwch, -1, &pch, -1, TRUE) == 0) {
  420. iRetVal = FALSE;
  421. break;
  422. }
  423. }
  424. iRetVal = (*(NAMEENUMPROCA)lpfn)(pch, lParam);
  425. if (pch != achTmp) {
  426. UserLocalFree(pch);
  427. pch = achTmp;
  428. }
  429. } else {
  430. iRetVal = (*(NAMEENUMPROCW)lpfn)(pwch, lParam);
  431. }
  432. if (!iRetVal) {
  433. break;
  434. }
  435. pwch = pwch + wcslen(pwch) + 1;
  436. }
  437. UserLocalFree(pNameList);
  438. return iRetVal;
  439. }
  440. FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, EnumWindowStationsA, WINSTAENUMPROCA, lpEnumFunc, LPARAM, lParam)
  441. BOOL WINAPI EnumWindowStationsA(
  442. WINSTAENUMPROCA lpEnumFunc,
  443. LPARAM lParam)
  444. {
  445. return InternalEnumObjects(NULL, (NAMEENUMPROCW)lpEnumFunc, lParam, TRUE);
  446. }
  447. FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, EnumWindowStationsW, WINSTAENUMPROCW, lpEnumFunc, LPARAM, lParam)
  448. BOOL WINAPI EnumWindowStationsW(
  449. WINSTAENUMPROCW lpEnumFunc,
  450. LPARAM lParam)
  451. {
  452. return InternalEnumObjects(NULL, (NAMEENUMPROCW)lpEnumFunc, lParam, FALSE);
  453. }
  454. FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumDesktopsA, HWINSTA, hwinsta, DESKTOPENUMPROCA, lpEnumFunc, LPARAM, lParam)
  455. BOOL WINAPI EnumDesktopsA(
  456. HWINSTA hwinsta,
  457. DESKTOPENUMPROCA lpEnumFunc,
  458. LPARAM lParam)
  459. {
  460. return InternalEnumObjects(hwinsta, (NAMEENUMPROCW)lpEnumFunc, lParam, TRUE);
  461. }
  462. FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, EnumDesktopsW, HWINSTA, hwinsta, DESKTOPENUMPROCW, lpEnumFunc, LPARAM, lParam)
  463. BOOL WINAPI EnumDesktopsW(
  464. HWINSTA hwinsta,
  465. DESKTOPENUMPROCW lpEnumFunc,
  466. LPARAM lParam)
  467. {
  468. return InternalEnumObjects(hwinsta, (NAMEENUMPROCW)lpEnumFunc, lParam, FALSE);
  469. }