00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include "precomp.h"
00015
#pragma hdrstop
00016
00017 PBWL pbwlCache;
00018
00019
#if DBG
00020
PBWL pbwlCachePrev;
00021
#endif
00022
00023
PBWL InternalBuildHwndList(
PBWL pbwl,
PWND pwnd, UINT flags);
00024
PBWL InternalBuildHwndOwnerList(
PBWL pbwl,
PWND pwndStart,
PWND pwndOwner);
00025
#ifdef FE_IME
00026
PBWL InternalRebuildHwndListForIMEClass(
PBWL pbwl, BOOL fRemoveChild);
00027
PWND InternalGetIMEOwner(HWND hwnd, BOOL fRetIMEWnd);
00028
#endif
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 BOOL xxxInternalEnumWindow(
00041
PWND pwndNext,
00042
WNDENUMPROC_PWND lpfn,
00043 LPARAM lParam,
00044 UINT flags)
00045 {
00046 HWND *phwnd;
00047
PWND pwnd;
00048
PBWL pbwl;
00049
BOOL fSuccess;
00050
TL tlpwnd;
00051
00052
CheckLock(pwndNext);
00053
00054
if ((pbwl =
BuildHwndList(pwndNext, flags,
NULL)) ==
NULL)
00055
return FALSE;
00056
00057 fSuccess =
TRUE;
00058
for (phwnd = pbwl->
rghwnd; *phwnd != (HWND)1; phwnd++) {
00059
00060
00061
00062
00063
if ((pwnd =
RevalidateHwnd(*phwnd)) !=
NULL) {
00064
00065
00066
00067
00068
ThreadLockAlways(pwnd, &tlpwnd);
00069 fSuccess = (*lpfn)(pwnd, lParam);
00070
ThreadUnlock(&tlpwnd);
00071
if (!fSuccess)
00072
break;
00073 }
00074 }
00075
00076
FreeHwndList(pbwl);
00077
00078
return fSuccess;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #define CHWND_BWLCREATE 32
00090
00091 PBWL BuildHwndList(
00092
PWND pwnd,
00093 UINT flags,
00094
PTHREADINFO pti)
00095 {
00096
PBWL pbwl;
00097
00098
CheckCritIn();
00099
00100
if ((pbwl =
pbwlCache) !=
NULL) {
00101
00102
00103
00104
00105
#if DBG
00106
pbwlCachePrev =
pbwlCache;
00107
#endif
00108
pbwlCache =
NULL;
00109
00110
#if DBG
00111
{
00112
PBWL pbwlT;
00113
00114
00115
00116
for (pbwlT =
gpbwlList; pbwlT !=
NULL; pbwlT = pbwlT->
pbwlNext) {
00117 UserAssert(pbwlT != pbwl);
00118 }
00119 }
00120
#endif
00121
}
else {
00122
00123
00124
00125
00126 pbwl = (
PBWL)UserAllocPool(
sizeof(
BWL) +
sizeof(
PWND) *
CHWND_BWLCREATE,
00127 TAG_WINDOWLIST);
00128
if (pbwl ==
NULL)
00129
return NULL;
00130
00131 pbwl->
phwndMax = &pbwl->
rghwnd[
CHWND_BWLCREATE - 1];
00132 }
00133 pbwl->
phwndNext = pbwl->
rghwnd;
00134
00135
00136
00137
00138
00139
00140 pbwl->
ptiOwner = pti;
00141
00142
#ifdef OWNERLIST
00143
if (flags &
BWL_ENUMOWNERLIST) {
00144 pbwl =
InternalBuildHwndOwnerList(pbwl, pwnd,
NULL);
00145 }
else {
00146 pbwl =
InternalBuildHwndList(pbwl, pwnd, flags);
00147 }
00148
#else
00149
pbwl =
InternalBuildHwndList(pbwl, pwnd, flags);
00150
#endif
00151
00152
00153
00154
00155
00156
if (pbwl->
phwndNext >= pbwl->
phwndMax) {
00157 UserAssert(pbwl->
phwndNext == pbwl->
phwndMax);
00158
00159
00160
00161
00162
00163
00164
00165
00166 UserFreePool(pbwl);
00167
return NULL;
00168 }
00169
00170
00171
00172
00173 *pbwl->
phwndNext = (HWND)1;
00174
00175
#ifdef FE_IME
00176
if (flags &
BWL_ENUMIMELAST) {
00177 UserAssert(
IS_IME_ENABLED());
00178
00179
00180
00181
00182
00183
00184 pbwl = InternalRebuildHwndListForIMEClass(pbwl,
00185 (flags &
BWL_REMOVEIMECHILD) ==
BWL_REMOVEIMECHILD);
00186 }
00187
#endif
00188
00189
00190
00191
00192 pbwl->
ptiOwner =
PtiCurrent();
00193 pbwl->
pbwlNext =
gpbwlList;
00194
gpbwlList = pbwl;
00195
00196
00197
00198
00199
00200 UserAssert(
pbwlCache ==
NULL);
00201
00202
return pbwl;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 BOOL ExpandWindowList(
00214
PBWL *ppbwl)
00215 {
00216
PBWL pbwl;
00217
PBWL pbwlT;
00218 HWND *phwnd;
00219
00220 pbwl = *ppbwl;
00221 phwnd = pbwl->
phwndNext;
00222
00223
00224
00225
00226 phwnd = (HWND *)((
BYTE *)phwnd - (
BYTE *)pbwl);
00227
00228
00229
00230
00231
00232
00233 pbwlT = (
PBWL)UserReAllocPool((HANDLE)pbwl,
00234 PtrToUlong(phwnd) +
sizeof(
PWND),
00235 PtrToUlong(phwnd) + (
BWL_CHWNDMORE + 1) *
sizeof(
PWND),
00236 TAG_WINDOWLIST);
00237
00238
00239
00240
00241
if (pbwlT !=
NULL)
00242 pbwl = pbwlT;
00243
00244
00245
00246
00247 phwnd = (HWND *)((ULONG_PTR)pbwl + (ULONG_PTR)phwnd);
00248
00249
00250
00251
00252
if (pbwlT ==
NULL) {
00253 RIPMSG0(RIP_WARNING,
"ExpandWindowList: out of memory.");
00254
return FALSE;
00255 }
00256
00257
00258
00259
00260 pbwl->phwndNext = phwnd;
00261 pbwl->phwndMax = phwnd +
BWL_CHWNDMORE;
00262
00263 *ppbwl = pbwl;
00264
00265
return TRUE;
00266 }
00267
00268
#ifdef OWNERLIST
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
PBWL InternalBuildHwndOwnerList(
00280
PBWL pbwl,
00281
PWND pwndStart,
00282
PWND pwndOwner)
00283 {
00284
PWND pwndT;
00285
00286
00287
00288
00289
for (pwndT = pwndStart; pwndT !=
NULL; pwndT = pwndT->
spwndNext) {
00290
00291
00292
00293
00294
if (pwndT->
spwndOwner != pwndOwner)
00295
continue;
00296
00297
00298
00299
00300
00301
if (!
TestWF(pwndT, WFSYSMENU))
00302
continue;
00303
00304
00305
00306
00307 pbwl =
InternalBuildHwndOwnerList(pbwl, pwndStart, pwndT);
00308
00309
00310
00311
00312
00313
if (pbwl->
phwndNext >= pbwl->
phwndMax) {
00314 UserAssert(pbwl->
phwndNext == pbwl->
phwndMax);
00315
return pbwl;
00316 }
00317 UserAssert(pbwl->
phwndNext < pbwl->
phwndMax);
00318 }
00319
00320
00321
00322
00323
if (pwndOwner !=
NULL) {
00324 UserAssert(pbwl->
phwndNext < pbwl->
phwndMax);
00325 *pbwl->
phwndNext =
HWq(pwndOwner);
00326 pbwl->
phwndNext++;
00327
if (pbwl->
phwndNext == pbwl->
phwndMax) {
00328
if (!
ExpandWindowList(&pbwl))
00329
return pbwl;
00330 }
00331 }
00332
00333
return pbwl;
00334 }
00335
00336
#endif
00337
00338
00339
00340
00341
00342
00343
00344
00345 #define BWLGROW 8
00346
00347 PBWL InternalBuildHwndList(
00348
PBWL pbwl,
00349
PWND pwnd,
00350 UINT flags)
00351 {
00352
00353
00354
00355
00356
00357
00358
00359
while (pwnd !=
NULL) {
00360
00361
00362
00363
if (pbwl->
ptiOwner ==
NULL || pbwl->
ptiOwner ==
GETPTI(pwnd)) {
00364 UserAssert(pbwl->
phwndNext < pbwl->
phwndMax);
00365 *pbwl->
phwndNext =
HWq(pwnd);
00366 pbwl->
phwndNext++;
00367
if (pbwl->
phwndNext == pbwl->
phwndMax) {
00368
#if EMULATE_EXPAND_FAILURE
00369
static int n = 0;
00370
if (++
n % 32 == 0) {
00371 RIPMSG0(RIP_WARNING,
"InternalBuildHwndList: emulating ExpandWindowList failure.");
00372
break;
00373 }
00374
#endif
00375
if (!
ExpandWindowList(&pbwl))
00376
break;
00377 }
00378 }
00379
00380
00381
00382
00383
if ((flags &
BWL_ENUMCHILDREN) && pwnd->
spwndChild !=
NULL) {
00384 pbwl =
InternalBuildHwndList(pbwl, pwnd->
spwndChild,
BWL_ENUMLIST |
BWL_ENUMCHILDREN);
00385
00386
00387
00388
00389
if (pbwl->
phwndNext >= pbwl->
phwndMax) {
00390 UserAssert(pbwl->
phwndNext == pbwl->
phwndMax);
00391 RIPMSG1(RIP_WARNING,
"InternalBuildHwndList: failed to expand BWL in enumerating children. pbwl=%#p", pbwl);
00392
break;
00393 }
00394 UserAssert(pbwl->
phwndNext < pbwl->
phwndMax);
00395 }
00396
00397
00398
00399
00400
if (!(flags &
BWL_ENUMLIST))
00401
break;
00402
00403 pwnd = pwnd->
spwndNext;
00404 }
00405
00406
return pbwl;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 void FreeHwndList(
00418
PBWL pbwl)
00419 {
00420
PBWL *ppbwl;
00421
PBWL pbwlT;
00422
00423
CheckCritIn();
00424
00425
00426
00427
00428 UserAssert(pbwl !=
pbwlCache);
00429
00430
00431
00432
00433
for (ppbwl = &
gpbwlList; *ppbwl !=
NULL; ppbwl = &(*ppbwl)->
pbwlNext) {
00434
if (*ppbwl == pbwl) {
00435 *ppbwl = pbwl->
pbwlNext;
00436
00437
00438
00439
00440
00441
if (
pbwlCache ==
NULL) {
00442
pbwlCache = pbwl;
00443 }
else if ((pbwl->
phwndMax - pbwl->
rghwnd) >
00444 (
pbwlCache->
phwndMax -
pbwlCache->
rghwnd)) {
00445 pbwlT =
pbwlCache;
00446
pbwlCache = pbwl;
00447 UserFreePool((HANDLE)pbwlT);
00448 }
else {
00449 UserFreePool((HANDLE)pbwl);
00450 }
00451
return;
00452 }
00453 }
00454
00455
00456
00457
00458 UserAssert(
FALSE);
00459 }
00460
00461
#ifdef FE_IME
00462
00463
PBWL InternalRebuildHwndListForIMEClass(
00464
PBWL pbwl,
00465 BOOL fRemoveChild)
00466 {
00467
PHWND phwndIME, phwndIMECur, phwnd, phwndCur;
00468
DWORD dwSize = (
DWORD)((
BYTE *)pbwl->
phwndMax - (
BYTE *)pbwl) +
sizeof(HWND);
00469
00470 phwndIMECur = phwndIME = (
PHWND)UserAllocPool(dwSize, TAG_WINDOWLIST);
00471
if (phwndIME ==
NULL) {
00472 RIPMSG0(RIP_WARNING,
"RebuildHwndListForIMEClass: invalid phwndIME");
00473
return pbwl;
00474 }
00475
00476 phwndCur = pbwl->
rghwnd;
00477
00478
for (phwnd = pbwl->
rghwnd; *phwnd != (HWND)1; phwnd++) {
00479
PWND pwndIMEOwner;
00480
00481
00482
00483
00484
if (pwndIMEOwner = InternalGetIMEOwner(*phwnd, fRemoveChild)) {
00485
try {
00486
if (!fRemoveChild ||
00487 (pwndIMEOwner->
pcls->
atomClassName ==
gpsi->
atomSysClass[
ICLS_IME] &&
00488 ((
PIMEWND)pwndIMEOwner)->pimeui !=
NULL &&
00489 !
ProbeAndReadStructure(((
PIMEWND)pwndIMEOwner)->pimeui,
IMEUI).fChildThreadDef))
00490 {
00491 *phwndIMECur++ = *phwnd;
00492 }
00493 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
00494 }
00495 }
else {
00496 *phwndCur++ = *phwnd;
00497 }
00498 }
00499
00500
00501 *phwndIMECur =
NULL;
00502
00503 phwndIMECur = phwndIME;
00504
while(*phwndIMECur !=
NULL)
00505 *phwndCur++ = *phwndIMECur++;
00506
00507
if (*phwndCur != (HWND)1) {
00508 RIPMSG0(RIP_WARNING,
"RebuildHwndListForIMEClass: Where is terminator?");
00509 *phwndCur = (HWND)1;
00510 }
00511
00512 UserFreePool((HANDLE)phwndIME);
00513
return pbwl;
00514 }
00515
00516
PWND InternalGetIMEOwner(
00517 HWND hwnd,
00518 BOOL fRetIMEWnd)
00519 {
00520
PWND pwnd, pwndT, pwndIME;
00521
00522 pwnd =
RevalidateHwnd(hwnd);
00523
if (pwnd ==
NULL)
00524
return NULL;
00525
00526
for (pwndT = pwnd; pwndT !=
NULL; pwndT = pwndT->
spwndOwner) {
00527
if (
TestCF(pwndT,CFIME) ||
00528 pwndT->
pcls->
atomClassName ==
gpsi->
atomSysClass[
ICLS_IME]) {
00529
00530
if (!fRetIMEWnd)
00531
return pwndT;
00532
00533 pwndIME = pwndT;
00534
00535
while (pwndT && (pwndT->pcls->atomClassName !=
gpsi->
atomSysClass[
ICLS_IME]))
00536 pwndT = pwndT->
spwndOwner;
00537
00538
if (pwndT)
00539 pwndIME = pwndT;
00540
else
00541 RIPMSG0(RIP_WARNING,
"Can't find IME Class window");
00542
00543
return pwndIME;
00544 }
00545 }
00546
00547
return NULL;
00548 }
00549
00550
#endif