00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
#include "precomp.h"
00012
#pragma hdrstop
00013
00014
#pragma alloc_text(INIT, HMInitHandleTable)
00015
00016
#if DBG
00017
00018
#define HTIENTRY(szObjectType, structName, fnDestroy, dwAllocTag, bObjectCreateFlags) \
00019
{szObjectType, sizeof(structName), (FnDestroyUserObject)fnDestroy, (CONST DWORD)dwAllocTag, (CONST BYTE)(bObjectCreateFlags)}
00020
00021
#else // DBG
00022
00023 #define HTIENTRY(szObjectType, structName, fnDestroy, dwAllocTag, bObjectCreateFlags) \
00024
{(FnDestroyUserObject)fnDestroy, (CONST DWORD)dwAllocTag, (CONST BYTE)(bObjectCreateFlags)}
00025
00026
#endif // DBG
00027
00028 void HMNullFnDestroy(PVOID pobj)
00029 {
00030 RIPMSG1(RIP_WARNING,
"HM: No clean up function for %#p", pobj);
00031
HMDestroyObject(pobj);
00032
return;
00033 }
00034
00035
00036
00037
00038
00039
00040
#if DBG
00041
00042
00043
00044
00045
00046
00047
00048
00049
PERFHANDLEINFO gaPerfhti[
TYPE_CTYPES] = {0};
00050
PERFHANDLEINFO gaPrevhti[
TYPE_CTYPES] = {0};
00051
00052
#endif // DBG
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
#if (TYPE_FREE != 0)
00087
#error TYPE_FREE must be zero.
00088
#endif
00089
00090 CONST
HANDLETYPEINFO gahti[
TYPE_CTYPES] = {
00091
00092
HTIENTRY(
"Free",
HEAD,
00093
NULL,
00094 0,
00095 0),
00096
00097
00098
HTIENTRY(
"Window",
WND,
00099
xxxDestroyWindow,
00100 TAG_WINDOW,
00101
OCF_THREADOWNED |
OCF_USEPOOLQUOTA |
OCF_DESKTOPHEAP |
OCF_USEPOOLIFNODESKTOP |
OCF_VARIABLESIZE),
00102
00103
00104
HTIENTRY(
"Menu",
MENU,
00105
_DestroyMenu,
00106 0,
00107
OCF_PROCESSOWNED |
OCF_DESKTOPHEAP),
00108
00109
00110
HTIENTRY(
"Icon/Cursor",
CURSOR,
00111
DestroyUnlockedCursor,
00112 TAG_CURSOR,
00113
OCF_PROCESSOWNED |
OCF_MARKPROCESS |
OCF_USEPOOLQUOTA),
00114
00115
00116
HTIENTRY(
"WPI(SWP) structure",
SMWP,
00117
DestroySMWP,
00118 TAG_SWP,
00119
OCF_THREADOWNED |
OCF_USEPOOLQUOTA),
00120
00121
00122
HTIENTRY(
"Hook",
HOOK,
00123
FreeHook,
00124 0,
00125
OCF_THREADOWNED |
OCF_DESKTOPHEAP),
00126
00127
00128
HTIENTRY(
"Clipboard Data",
CLIPDATA,
00129
HMNullFnDestroy,
00130 TAG_CLIPBOARD,
00131
OCF_VARIABLESIZE),
00132
00133
00134
HTIENTRY(
"CallProcData",
CALLPROCDATA,
00135
HMDestroyObject,
00136 0,
00137
OCF_PROCESSOWNED |
OCF_DESKTOPHEAP),
00138
00139
00140
HTIENTRY(
"Accelerator",
ACCELTABLE,
00141
HMDestroyObject,
00142 TAG_ACCEL,
00143
OCF_PROCESSOWNED |
OCF_USEPOOLQUOTA |
OCF_VARIABLESIZE),
00144
00145
00146
HTIENTRY(
"DDE access",
SVR_INSTANCE_INFO,
00147
HMNullFnDestroy,
00148 TAG_DDE9,
00149
OCF_THREADOWNED |
OCF_USEPOOLQUOTA),
00150
00151
00152
HTIENTRY(
"DDE conv",
DDECONV,
00153
FreeDdeConv,
00154 TAG_DDEa,
00155
OCF_THREADOWNED |
OCF_USEPOOLQUOTA),
00156
00157
00158
HTIENTRY(
"DDE Transaction",
XSTATE,
00159
FreeDdeXact,
00160 TAG_DDEb,
00161
OCF_THREADOWNED |
OCF_USEPOOLQUOTA),
00162
00163
00164
HTIENTRY(
"Monitor",
MONITOR,
00165
DestroyMonitor,
00166 TAG_DISPLAYINFO,
00167
OCF_SHAREDHEAP),
00168
00169
00170
HTIENTRY(
"Keyboard Layout",
KL,
00171
DestroyKL,
00172 TAG_KBDLAYOUT,
00173 0),
00174
00175
00176
HTIENTRY(
"Keyboard File",
KBDFILE,
00177
DestroyKF,
00178 TAG_KBDFILE,
00179 0),
00180
00181
00182
HTIENTRY(
"WinEvent hook",
EVENTHOOK,
00183
DestroyEventHook,
00184 TAG_WINEVENT,
00185
OCF_THREADOWNED),
00186
00187
00188
00189
HTIENTRY(
"Timer",
TIMER,
00190
FreeTimer,
00191 TAG_TIMER,
00192 0),
00193
00194
00195
HTIENTRY(
"Input Context",
IMC,
00196
FreeInputContext,
00197 0,
00198
OCF_THREADOWNED |
OCF_DESKTOPHEAP),
00199 };
00200
00201
00202
00203
00204
00205
00206 #define CPAGEENTRIESINIT 4
00207
00208 DWORD gcHandlePages;
00209 PHANDLEPAGE gpHandlePages;
00210
00211
#if DBG
00212
PPAGED_LOOKASIDE_LIST LockRecordLookaside;
00213
00214
NTSTATUS InitLockRecordLookaside();
00215
void FreeLockRecord(
PLR plr);
00216
void InitGlobalThreadLockArray(DWORD dwIndex);
00217
#endif
00218
00219
void HMDestroyUnlockedObject(
PHE phe);
00220
void HMRecordLock(PVOID ppobj, PVOID pobj, DWORD cLockObj);
00221
BOOL HMUnrecordLock(PVOID ppobj, PVOID pobj);
00222
VOID ShowLocks(
PHE);
00223
00224
00225
00226
00227
00228
00229
00230
#ifdef VALIDATEHANDLEQUOTA
00231
void DBGValidateHandleQuota (
void)
00232 {
00233
BYTE bCreateFlags;
00234
DWORD dw;
00235
HANDLEENTRY * phe;
00236
00237
PPROCESSINFO ppiT =
gppiList;
00238
00239
while (ppiT !=
NULL) {
00240 ppiT->lHandles = 0;
00241 ppiT = ppiT->
ppiNextRunning;
00242 }
00243
00244 phe =
gSharedInfo.
aheList;
00245
for (dw = 0; dw <=
giheLast; dw++, phe++) {
00246
if (phe->
bType ==
TYPE_FREE) {
00247 UserAssert(phe->
pOwner == NULL);
00248
continue;
00249 }
00250 bCreateFlags =
gahti[phe->
bType].
bObjectCreateFlags;
00251
if (bCreateFlags &
OCF_PROCESSOWNED) {
00252 ((
PPROCESSINFO)phe->
pOwner)->lHandles++;
00253
continue;
00254 }
00255
if (bCreateFlags &
OCF_THREADOWNED) {
00256 ((
PTHREADINFO)phe->
pOwner)->ppi->lHandles++;
00257
continue;
00258 }
00259 UserAssert(phe->
pOwner == NULL);
00260 }
00261
00262 ppiT =
gppiList;
00263
while (ppiT !=
NULL) {
00264 UserAssert(ppiT->lHandles == ppiT->UserHandleCount);
00265 ppiT = ppiT->
ppiNextRunning;
00266 }
00267 }
00268
#else
00269 #define DBGValidateHandleQuota()
00270
#endif
00271
00272
00273
00274
00275
00276
00277
00278
#if DBG
00279
PHE DBGHMPheFromObject (PVOID p)
00280 {
00281
PHE phe =
_HMPheFromObject(p);
00282
00283 UserAssert(phe->
phead == p);
00284 UserAssert(
_HMObjectFromHandle(phe->
phead->
h) == p);
00285 UserAssert(phe->
wUniq ==
HMUniqFromHandle(phe->
phead->
h));
00286 UserAssert(phe->
bType <
TYPE_CTYPES);
00287 UserAssert((phe->
pOwner !=
NULL)
00288 || !(
gahti[phe->
bType].bObjectCreateFlags & (
OCF_PROCESSOWNED |
OCF_THREADOWNED)));
00289 UserAssert(!(phe->
bFlags & ~
HANDLEF_VALID));
00290
00291
return phe;
00292 }
00293
#endif
00294
00295
00296
00297
00298
00299
00300
00301
#if DBG
00302
PVOID DBGHMObjectFromHandle (HANDLE h)
00303 {
00304 PVOID p =
_HMObjectFromHandle(h);
00305
00306 UserAssert((h != NULL) ^ (p == NULL));
00307
if (p !=
NULL) {
00308 UserAssert(
HMIndexFromHandle(((
PHEAD)p)->h) ==
HMIndexFromHandle(h));
00309 UserAssert(p ==
HMRevalidateCatHandle(h));
00310
00311
00312
00313
00314
00315
if (
HMPheFromObject(p)->bFlags &
HANDLEF_DESTROY) {
00316 RIPMSG1(RIP_WARNING,
"HMObjectFromHandle: Object p %#p is destroyed",
00317 p);
00318 }
00319 }
00320
00321
return p;
00322 }
00323 PVOID DBGHMCatObjectFromHandle (HANDLE h)
00324 {
00325
00326
00327
00328
00329 PVOID p =
_HMObjectFromHandle(h);
00330
00331 UserAssert((h != NULL) ^ (p == NULL));
00332
if (p !=
NULL) {
00333 UserAssert(
HMIndexFromHandle(((
PHEAD)p)->h) ==
HMIndexFromHandle(h));
00334 UserAssert(p ==
HMRevalidateCatHandle(h));
00335 }
00336
00337
return p;
00338 }
00339
#endif
00340
00341
00342
00343
00344
00345
00346
00347
#if DBG
00348
void DBGValidatePtoH (PVOID p, HANDLE h)
00349 {
00350 UserAssert((h != NULL) ^ (p == NULL));
00351
if (h !=
NULL) {
00352 UserAssert(p ==
HMRevalidateCatHandle(h));
00353 }
00354 }
00355 HANDLE DBGPtoH (PVOID p)
00356 {
00357 HANDLE h =
_PtoH(p);
00358 DBGValidatePtoH(p, h);
00359
return h;
00360 }
00361 HANDLE DBGPtoHq (PVOID p)
00362 {
00363 HANDLE h;
00364 UserAssert(p != NULL);
00365 h =
_PtoHq(p);
00366 DBGValidatePtoH(p, h);
00367
return h;
00368 }
00369
#endif
00370
00371
00372
00373
00374
00375
00376
00377
#if DBG
00378
void DBGValidateHW(
PWND pwnd, HWND hwnd)
00379 {
00380 UserAssert((hwnd != NULL) ^ (pwnd == NULL));
00381
if (hwnd !=
NULL) {
00382 UserAssert(pwnd ==
HMValidateCatHandleNoSecure(hwnd, TYPE_WINDOW));
00383 }
00384 }
00385
void DBGValidateHWCCX(
PWND ccxPwnd, HWND hwnd,
PCLIENTINFO ccxPci)
00386 {
00387 UserAssert((hwnd != NULL) ^ (ccxPwnd == NULL));
00388
if (hwnd !=
NULL) {
00389 UserAssert(ccxPwnd ==
HMValidateCatHandleNoSecureCCX(hwnd, TYPE_WINDOW, ccxPci));
00390 }
00391 }
00392 HWND DBGHW (
PWND pwnd)
00393 {
00394 HWND hwnd =
_HW(pwnd);
00395 DBGValidateHW(pwnd, hwnd);
00396
return hwnd;
00397 }
00398 HWND DBGHWCCX (
PWND ccxPwnd)
00399 {
00400 HWND hwnd =
_HWCCX(ccxPwnd);
00401
PCLIENTINFO ccxPci =
_GETPTI(ccxPwnd)->pClientInfo;
00402
if (
KeIsAttachedProcess()) {
00403 UserAssert(
KeGetCurrentThread()->ApcState.Process == &(
_GETPTI(ccxPwnd)->ppi->Process->Pcb));
00404 }
else {
00405 UserAssert(
PpiCurrent() ==
_GETPTI(ccxPwnd)->ppi);
00406 }
00407 DBGValidateHWCCX(ccxPwnd, hwnd, ccxPci);
00408
return hwnd;
00409 }
00410 HWND DBGHWq (
PWND pwnd)
00411 {
00412 HWND hwnd;
00413 UserAssert(pwnd != NULL);
00414 hwnd =
_HWq(pwnd);
00415 DBGValidateHW(pwnd, hwnd);
00416
return hwnd;
00417 }
00418
#endif
00419
00420
00421
00422
00423
00424
00425
00426
#if DBG
00427
void DBGHMValidateFreeList (ULONG_PTR iheFreeNext, BOOL fEven)
00428 {
00429
PHE phe;
00430
do {
00431 UserAssert(fEven ^ !!(iheFreeNext & 0x1));
00432 UserAssert(iheFreeNext < gpsi->cHandleEntries);
00433 phe = &
gSharedInfo.
aheList[iheFreeNext];
00434 UserAssert(phe->
bType == TYPE_FREE);
00435 UserAssert(phe->
pOwner == NULL);
00436 UserAssert(phe->
bFlags == 0);
00437 iheFreeNext = (ULONG_PTR)phe->
phead;
00438 }
while (iheFreeNext != 0);
00439 }
00440
void DBGHMValidateFreeLists (
void)
00441 {
00442
DWORD dw;
00443
PHANDLEPAGE php =
gpHandlePages;
00444
00445
for (dw = 0; dw <
gcHandlePages; ++dw, ++php) {
00446
if (php->
iheFreeEven != 0) {
00447 DBGHMValidateFreeList(php->
iheFreeEven, TRUE);
00448 }
00449
if (php->
iheFreeOdd != 0) {
00450 DBGHMValidateFreeList(php->
iheFreeOdd, FALSE);
00451 }
00452 }
00453 }
00454
#else
00455 #define DBGHMValidateFreeLists()
00456
#endif
00457
00458
#if DBG
00459
00460
00461
00462
00463
00464
DWORD DbgDumpHandleTable(
00465 VOID)
00466 {
00467
DWORD dw;
00468
PHE phe;
00469
DWORD dwHandles = 0;
00470
00471 phe =
gSharedInfo.
aheList;
00472
00473
if (phe ==
NULL) {
00474 KdPrint((
"\nTERMSRV\nEmpty handle table\n"));
00475
return 0;
00476 }
00477
00478 KdPrint((
"\nTERMSRV\nDump the handle table\n"));
00479 KdPrint((
"---------------------------------------------------\n"));
00480 KdPrint((
" phead handle lock pOwner type flags\n"));
00481 KdPrint((
"---------------------------------------------------\n"));
00482
00483
for (dw = 0; dw <=
giheLast; dw++, phe++) {
00484
if (phe->
bType ==
TYPE_FREE) {
00485 UserAssert(phe->
pOwner ==
NULL);
00486
continue;
00487 }
00488
00489 KdPrint((
"%04d %08x %08x %08d %08x %04x %05x\n",
00490 dwHandles++,
00491 phe->
phead,
00492 phe->
phead->
h,
00493 phe->
phead->
cLockObj,
00494 phe->
pOwner,
00495 phe->
bType,
00496 phe->
bFlags));
00497 }
00498
00499 KdPrint((
"----------------------------------------------\n"));
00500 KdPrint((
"Number of handles left: %d\n", dwHandles));
00501 KdPrint((
"End of handle table\n"));
00502
00503 UserAssert(dwHandles == 0);
00504
00505
return dwHandles;
00506 }
00507
00508
00509
00510
00511
00512
VOID HMCleanUpHandleTable(
00513 VOID)
00514 {
00515 DbgDumpHandleTable();
00516
00517
if (LockRecordLookaside !=
NULL) {
00518
ExDeletePagedLookasideList(LockRecordLookaside);
00519 UserFreePool(LockRecordLookaside);
00520 }
00521 }
00522
#endif // DBG
00523
00524
00525
00526
00527
00528
00529 void HMInitHandleEntries (ULONG_PTR iheFirstFree)
00530 {
00531 ULONG_PTR ihe;
00532
PHE pheT;
00533
00534
00535
00536 RtlZeroMemory (&
gSharedInfo.
aheList[iheFirstFree],
00537 (
gpsi->
cHandleEntries - iheFirstFree) *
sizeof(
HANDLEENTRY));
00538
00539
00540
00541
00542 ihe = iheFirstFree;
00543
for (pheT = &
gSharedInfo.
aheList[ihe]; ihe <
gpsi->
cHandleEntries; ihe++, pheT++) {
00544 pheT->
phead = (
PHEAD)(ihe + 2);
00545
00546 pheT->
wUniq = 1;
00547 }
00548
00549
00550
00551
if (
gpsi->
cHandleEntries > iheFirstFree) {
00552 UserAssert(pheT - 1 >= &
gSharedInfo.
aheList[iheFirstFree]);
00553 (pheT - 1)->phead =
NULL;
00554 }
00555
if (
gpsi->
cHandleEntries > iheFirstFree + 1) {
00556 UserAssert(pheT - 2 >= &
gSharedInfo.
aheList[iheFirstFree]);
00557 (pheT - 2)->phead =
NULL;
00558 }
00559
00560
00561
00562
DBGHMValidateFreeLists();
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572 #define CHANDLEENTRIESINIT 200
00573 #define CLOCKENTRIESINIT 100
00574
00575 BOOL HMInitHandleTable(
00576 PVOID pReadOnlySharedSectionBase)
00577 {
00578
NTSTATUS Status;
00579 SIZE_T ulCommit;
00580
00581
00582
00583
00584
00585
00586
gpHandlePages = UserAllocPool(
00587
CPAGEENTRIESINIT *
sizeof(
HANDLEPAGE), TAG_SYSTEM);
00588
00589
if (
gpHandlePages ==
NULL)
00590
return FALSE;
00591
00592
#if DBG
00593
if (!
NT_SUCCESS(InitLockRecordLookaside()))
00594
return FALSE;
00595
#endif
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 ulCommit =
gpsi->
cbHandleTable =
PAGE_SIZE;
00607
Status =
CommitReadOnlyMemory(
ghSectionShared, &ulCommit, 0,
NULL);
00608
00609
if (!
NT_SUCCESS(
Status))
00610
return FALSE;
00611
00612
gSharedInfo.
aheList = pReadOnlySharedSectionBase;
00613
gpsi->
cHandleEntries =
gpsi->
cbHandleTable /
sizeof(
HANDLEENTRY);
00614
gcHandlePages = 1;
00615
00616
00617
00618
00619
00620
gpHandlePages[0].
iheFreeOdd = 1;
00621
gpHandlePages[0].
iheFreeEven = 2;
00622
gpHandlePages[0].
iheLimit =
gpsi->
cHandleEntries;
00623
00624
00625
00626
HMInitHandleEntries(0);
00627
00628
00629
00630
00631
00632
00633
00634
00635
gSharedInfo.
aheList[0].
phead =
NULL;
00636 UserAssert(
gSharedInfo.
aheList[0].
bType ==
TYPE_FREE);
00637 UserAssert(
gSharedInfo.
aheList[0].
wUniq == 1);
00638
00639
#if DBG
00640
00641
00642
00643 UserAssert(
gpsi->
cHandleEntries <=
HMINDEXBITS);
00644
00645
00646
00647
00648 UserAssert(
sizeof(
THROBJHEAD) ==
sizeof(
PROCOBJHEAD));
00649 UserAssert(
sizeof(
THRDESKHEAD) ==
sizeof(
PROCDESKHEAD));
00650 UserAssert(
sizeof(
THRDESKHEAD) ==
sizeof(
DESKOBJHEAD));
00651
00652
00653
00654
00655 {
00656
HANDLETYPEINFO * pahti = (
HANDLETYPEINFO *)
gahti;
00657
UINT uTypes =
TYPE_CTYPES;
00658
BYTE bObjectCreateFlags;
00659
while (uTypes-- != 0) {
00660 bObjectCreateFlags = pahti->
bObjectCreateFlags;
00661
00662
00663
00664 UserAssert(!((bObjectCreateFlags &
OCF_DESKTOPHEAP) && (bObjectCreateFlags &
OCF_MARKPROCESS)));
00665
00666
00667
00668 UserAssert(!((bObjectCreateFlags &
OCF_DESKTOPHEAP) && (bObjectCreateFlags &
OCF_SHAREDHEAP)));
00669 UserAssert(!((bObjectCreateFlags &
OCF_USEPOOLQUOTA) && (bObjectCreateFlags &
OCF_SHAREDHEAP)));
00670 UserAssert(!((bObjectCreateFlags &
OCF_THREADOWNED) && (bObjectCreateFlags &
OCF_PROCESSOWNED)));
00671 UserAssert(!(bObjectCreateFlags &
OCF_USEPOOLQUOTA)
00672 || !(bObjectCreateFlags &
OCF_DESKTOPHEAP)
00673 || (bObjectCreateFlags &
OCF_USEPOOLIFNODESKTOP));
00674
00675
00676
00677
00678 UserAssert(!(bObjectCreateFlags &
OCF_DESKTOPHEAP)
00679 || (bObjectCreateFlags & (
OCF_PROCESSOWNED |
OCF_THREADOWNED)));
00680
00681 UserAssert(!(bObjectCreateFlags &
OCF_MARKPROCESS)
00682 || (bObjectCreateFlags &
OCF_PROCESSOWNED));
00683
00684 UserAssert(!(bObjectCreateFlags &
OCF_USEPOOLIFNODESKTOP)
00685 || (bObjectCreateFlags &
OCF_DESKTOPHEAP));
00686
00687
00688 pahti++;
00689 }
00690 }
00691
#endif
00692
00693
return TRUE;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 BOOL HMGrowHandleTable()
00705 {
00706 ULONG_PTR i, iheFirstFree;
00707
PHE pheT;
00708 PVOID p;
00709
PHANDLEPAGE phpNew;
00710
DWORD dwCommitOffset;
00711 SIZE_T ulCommit;
00712
NTSTATUS Status;
00713
00714
00715
00716
00717 i =
gpsi->
cHandleEntries;
00718
if (i & ~
HMINDEXBITS)
00719
return FALSE;
00720
00721
00722
00723
00724 i =
gcHandlePages + 1;
00725
if (i >
CPAGEENTRIESINIT) {
00726
DWORD dwSize =
gcHandlePages *
sizeof(
HANDLEPAGE);
00727
00728 phpNew = UserReAllocPool(
00729
gpHandlePages, dwSize, dwSize +
sizeof(
HANDLEPAGE), TAG_SYSTEM);
00730
00731
if (phpNew ==
NULL)
00732
return FALSE;
00733
00734
gpHandlePages = phpNew;
00735 }
00736
00737
00738
00739
00740
00741 p = (
PBYTE)
gSharedInfo.
aheList +
gpsi->
cbHandleTable;
00742
00743
if (p >= Win32HeapGetHandle(
gpvSharedAlloc)) {
00744
return FALSE;
00745 }
00746
00747 dwCommitOffset = (ULONG)((
PBYTE)p - (
PBYTE)
gpvSharedBase);
00748
00749 ulCommit =
PAGE_SIZE;
00750
00751
Status =
CommitReadOnlyMemory(
ghSectionShared, &ulCommit, dwCommitOffset,
NULL);
00752
00753
if (!
NT_SUCCESS(
Status))
00754
return FALSE;
00755
00756 phpNew = &
gpHandlePages[
gcHandlePages++];
00757
00758
00759
00760
00761
00762 iheFirstFree =
gpsi->
cHandleEntries;
00763
if (
gpsi->
cHandleEntries & 0x1) {
00764 phpNew->
iheFreeOdd =
gpsi->
cHandleEntries;
00765 phpNew->
iheFreeEven =
gpsi->
cHandleEntries + 1;
00766 }
else {
00767 phpNew->
iheFreeEven =
gpsi->
cHandleEntries;
00768 phpNew->
iheFreeOdd =
gpsi->
cHandleEntries + 1;
00769 }
00770
gpsi->
cbHandleTable +=
PAGE_SIZE;
00771
00772
00773
00774
00775
gpsi->
cHandleEntries =
gpsi->
cbHandleTable /
sizeof(
HANDLEENTRY);
00776
if (
gpsi->
cHandleEntries & ~
HMINDEXBITS) {
00777
gpsi->
cHandleEntries = (
HMINDEXBITS + 1);
00778 }
00779
00780 phpNew->
iheLimit =
gpsi->
cHandleEntries;
00781
if (phpNew->
iheFreeEven >= phpNew->
iheLimit) {
00782 phpNew->
iheFreeEven = 0;
00783 }
00784
if (phpNew->
iheFreeOdd >= phpNew->
iheLimit) {
00785 phpNew->
iheFreeOdd = 0;
00786 }
00787
00788
HMInitHandleEntries(iheFirstFree);
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
if ((
gpsi->
cHandleEntries >
HMINDEXBITS)
00800 && (phpNew->
iheFreeOdd != 0)
00801 && (phpNew->
iheFreeOdd <=
HMINDEXBITS)) {
00802
00803 pheT = &
gSharedInfo.
aheList[
HMINDEXBITS];
00804
if (phpNew->
iheFreeOdd ==
HMINDEXBITS) {
00805 phpNew->
iheFreeOdd = (ULONG_PTR)pheT->
phead;
00806 }
else {
00807 UserAssert(pheT - 2 >= &
gSharedInfo.
aheList[iheFirstFree]);
00808 UserAssert((pheT - 2)->phead == (PVOID)
HMINDEXBITS);
00809 (pheT - 2)->phead = pheT->
phead;
00810 }
00811 pheT->
phead =
NULL;
00812 UserAssert(pheT->
bType ==
TYPE_FREE);
00813 UserAssert(pheT->
wUniq == 1);
00814 }
00815
00816
return TRUE;
00817 }
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 PVOID
HMAllocObject(
00829
PTHREADINFO ptiOwner,
00830
PDESKTOP pdeskSrc,
00831 BYTE bType,
00832 DWORD size)
00833 {
00834
DWORD i;
00835
PHEAD phead;
00836
PHE pheT;
00837 ULONG_PTR iheFree, *piheFreeHead;
00838
PHANDLEPAGE php;
00839
BYTE bCreateFlags;
00840
PPROCESSINFO ppiQuotaCharge =
NULL;
00841
BOOL fUsePoolIfNoDesktop;
00842
BOOL fEven;
00843
00844
CheckCritIn();
00845 bCreateFlags =
gahti[bType].
bObjectCreateFlags;
00846
00847
#if DBG
00848
00849
00850
00851
if (bCreateFlags &
OCF_VARIABLESIZE) {
00852 UserAssert(
gahti[bType].uSize <= size);
00853 }
else {
00854 UserAssert(
gahti[bType].uSize == size);
00855 }
00856
#endif
00857
00858
00859
00860
00861
if (bCreateFlags & (
OCF_PROCESSOWNED |
OCF_THREADOWNED)) {
00862 UserAssert(ptiOwner !=
NULL);
00863 ppiQuotaCharge = ptiOwner->
ppi;
00864
if (ppiQuotaCharge->UserHandleCount >=
gUserProcessHandleQuota) {
00865 RIPERR0(ERROR_NO_MORE_USER_HANDLES,
00866 RIP_WARNING,
00867
"USER: HMAllocObject: out of handle quota\n");
00868
return NULL;
00869 }
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 fEven = (bType ==
TYPE_WINDOW);
00882 piheFreeHead =
NULL;
00883
do {
00884 php =
gpHandlePages;
00885
for (i = 0; i <
gcHandlePages; ++i, ++php) {
00886
if (fEven) {
00887
if (php->
iheFreeEven != 0) {
00888 piheFreeHead = &php->
iheFreeEven;
00889
break;
00890 }
00891 }
else {
00892
if (php->
iheFreeOdd != 0) {
00893 piheFreeHead = &php->
iheFreeOdd;
00894
break;
00895 }
00896 }
00897 }
00898
00899
00900
00901 fEven = ((piheFreeHead ==
NULL) && !fEven);
00902 }
while (fEven);
00903
00904
00905
00906
if (piheFreeHead ==
NULL) {
00907
HMGrowHandleTable();
00908
00909
00910
00911
if (i ==
gcHandlePages) {
00912 RIPMSG0(RIP_WARNING,
"HMAllocObject: could not grow handle space");
00913
return NULL;
00914 }
00915
00916
00917
00918
00919 php = &
gpHandlePages[i];
00920 piheFreeHead = (bType ==
TYPE_WINDOW ? &php->
iheFreeEven : &php->
iheFreeOdd);
00921
if (*piheFreeHead == 0) {
00922 UserAssert(
gpsi->
cHandleEntries == (
HMINDEXBITS + 1));
00923 RIPMSG0(RIP_WARNING,
"HMAllocObject: handle table is full");
00924
return NULL;
00925 }
00926 }
00927
00928
00929
00930
00931 UserAssert(
HMIndexFromHandle(*piheFreeHead) !=
HMINDEXBITS);
00932
00933
00934
00935
if ((bCreateFlags &
OCF_DESKTOPHEAP) && pdeskSrc) {
00936 phead = (
PHEAD)
DesktopAlloc(pdeskSrc, size,
DTAG_HANDTABL);
00937
if (phead) {
00938
LockDesktop(&((
PDESKOBJHEAD)phead)->rpdesk, pdeskSrc, LDL_OBJ_DESK, (ULONG_PTR)phead);
00939 ((
PDESKOBJHEAD)phead)->pSelf = (
PBYTE)phead;
00940 }
00941 }
else if (bCreateFlags &
OCF_SHAREDHEAP) {
00942 UserAssert(!pdeskSrc);
00943 phead = (
PHEAD)
SharedAlloc(size);
00944 }
else {
00945 fUsePoolIfNoDesktop = !pdeskSrc && (bCreateFlags &
OCF_USEPOOLIFNODESKTOP);
00946 UserAssert(!(bCreateFlags &
OCF_DESKTOPHEAP) || fUsePoolIfNoDesktop);
00947
00948
if ((bCreateFlags &
OCF_USEPOOLQUOTA) && !fUsePoolIfNoDesktop) {
00949 phead = (
PHEAD)UserAllocPoolWithQuotaZInit(size,
gahti[bType].dwAllocTag);
00950 }
else {
00951 phead = (
PHEAD)UserAllocPoolZInit(size,
gahti[bType].dwAllocTag);
00952 }
00953 }
00954
00955
if (phead ==
NULL) {
00956 RIPERR0(ERROR_NOT_ENOUGH_MEMORY,
00957 RIP_WARNING,
00958
"USER: HMAllocObject: out of memory");
00959
return NULL;
00960 }
00961
00962
00963
00964
00965 iheFree = *piheFreeHead;
00966 pheT = &
gSharedInfo.
aheList[iheFree];
00967 *piheFreeHead = (ULONG_PTR)pheT->
phead;
00968
DBGHMValidateFreeLists();
00969
00970
00971
00972
if ((
DWORD)iheFree >
giheLast) {
00973
giheLast = (
DWORD)iheFree;
00974 }
00975
00976
00977
00978 pheT->
bType = bType;
00979 pheT->
phead = phead;
00980 UserAssert(pheT->
bFlags == 0);
00981
if (bCreateFlags &
OCF_PROCESSOWNED) {
00982
if ((ptiOwner->
TIF_flags &
TIF_16BIT) && (ptiOwner->
ptdb)) {
00983 ((
PPROCOBJHEAD)phead)->hTaskWow = ptiOwner->
ptdb->
hTaskWow;
00984 }
else {
00985 ((
PPROCOBJHEAD)phead)->hTaskWow = 0;
00986 }
00987 pheT->
pOwner = ptiOwner->
ppi;
00988
if (bCreateFlags &
OCF_MARKPROCESS) {
00989 ((
PPROCMARKHEAD)phead)->ppi = ptiOwner->
ppi;
00990 }
00991 }
else if (bCreateFlags &
OCF_THREADOWNED) {
00992 ((
PTHROBJHEAD)phead)->pti = pheT->
pOwner = ptiOwner;
00993 }
else {
00994
00995
00996
00997
00998 UserAssert(ptiOwner ==
NULL);
00999 UserAssert(pheT->
pOwner ==
NULL);
01000 }
01001
01002 phead->
h =
HMHandleFromIndex(iheFree);
01003
01004
if (ppiQuotaCharge) {
01005 ppiQuotaCharge->UserHandleCount++;
01006
DBGValidateHandleQuota();
01007 }
01008
01009
#if DBG
01010
01011
01012
01013
01014
01015 gaPerfhti[bType].
lTotalCount++;
01016 gaPerfhti[bType].
lCount++;
01017
if (gaPerfhti[bType].
lCount > gaPerfhti[bType].
lMaxCount) {
01018 gaPerfhti[bType].
lMaxCount = gaPerfhti[bType].
lCount;
01019 }
01020
if ((bCreateFlags &
OCF_DESKTOPHEAP) && (pdeskSrc !=
NULL)) {
01021 gaPerfhti[bType].
lSize +=
RtlSizeHeap(Win32HeapGetHandle(pdeskSrc->
pheapDesktop), 0, phead);
01022 }
else if (bCreateFlags &
OCF_SHAREDHEAP) {
01023 gaPerfhti[bType].
lSize +=
RtlSizeHeap(Win32HeapGetHandle(
gpvSharedAlloc), 0, phead);
01024 }
else {
01025
unsigned char notUsed;
01026 gaPerfhti[bType].
lSize +=
ExQueryPoolBlockSize(phead, ¬Used);
01027 }
01028
01029
#endif // DBG
01030
01031
01032
01033
01034
return pheT->
phead;
01035 }
01036
01037
01038
01039
#if 0
01040
#define HANDLEF_FREECHECK 0x80
01041
VOID CheckHMTable(
01042 PVOID pobj)
01043 {
01044
PHE pheT, pheMax;
01045
01046
if (
giheLast) {
01047 pheMax = &
gSharedInfo.
aheList[
giheLast];
01048
for (pheT =
gSharedInfo.
aheList; pheT <= pheMax; pheT++) {
01049
if (pheT->
bType ==
TYPE_FREE) {
01050
continue;
01051 }
01052
if (pheT->
phead == pobj && !(pheT->
bFlags & HANDLEF_FREECHECK)) {
01053 UserAssert(FALSE);
01054 }
01055 }
01056 }
01057 }
01058
#endif
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 BOOL HMFreeObject(
01070 PVOID pobj)
01071 {
01072
PHE pheT;
01073 WORD wUniqT;
01074
PHANDLEPAGE php;
01075
DWORD i;
01076 ULONG_PTR iheCurrent, *piheCurrentHead;
01077
BYTE bCreateFlags;
01078
PDESKTOP pdesk;
01079
PPROCESSINFO ppiQuotaCharge =
NULL;
01080
#if DBG
01081
PLR plrT, plrNextT;
01082
unsigned char notUsed;
01083
#endif
01084
01085 UserAssert(((
PHEAD)pobj)->cLockObj == 0);
01086 UserAssert(pobj ==
HtoPqCat(
PtoHq(pobj)));
01087
01088
01089
01090 pheT =
HMPheFromObject(pobj);
01091 bCreateFlags =
gahti[pheT->
bType].
bObjectCreateFlags;
01092
01093 UserAssertMsg1(pheT->
bType !=
TYPE_FREE,
01094
"Object already marked as freed!!! %#p", pobj);
01095
01096
01097
01098
01099
if (bCreateFlags &
OCF_PROCESSOWNED) {
01100 ppiQuotaCharge = (
PPROCESSINFO)pheT->
pOwner;
01101 UserAssert(ppiQuotaCharge !=
NULL);
01102 }
else if (bCreateFlags &
OCF_THREADOWNED) {
01103 ppiQuotaCharge = (
PPROCESSINFO)(((
PTHREADINFO)(pheT->
pOwner))->ppi);
01104 UserAssert(ppiQuotaCharge !=
NULL);
01105 }
else {
01106 ppiQuotaCharge =
NULL;
01107 }
01108
01109
if (ppiQuotaCharge !=
NULL) {
01110 ppiQuotaCharge->UserHandleCount--;
01111 }
01112
01113
if (pheT->
bFlags &
HANDLEF_GRANTED) {
01114
HMCleanupGrantedHandle(pheT->
phead->
h);
01115 pheT->
bFlags &= ~
HANDLEF_GRANTED;
01116 }
01117
01118
#if DBG
01119
01120
01121
01122 gaPerfhti[pheT->
bType].
lCount--;
01123
01124
if ((bCreateFlags &
OCF_DESKTOPHEAP) && ((
PDESKOBJHEAD)pobj)->rpdesk) {
01125 pdesk = ((
PDESKOBJHEAD)pobj)->rpdesk;
01126 gaPerfhti[pheT->
bType].
lSize -=
RtlSizeHeap(Win32HeapGetHandle(pdesk->
pheapDesktop), 0, pobj);
01127 }
else if (bCreateFlags &
OCF_SHAREDHEAP) {
01128 gaPerfhti[pheT->
bType].
lSize -=
RtlSizeHeap(Win32HeapGetHandle(
gpvSharedAlloc), 0, pobj);
01129 }
else {
01130 gaPerfhti[pheT->
bType].
lSize -=
ExQueryPoolBlockSize(pobj, ¬Used);
01131 }
01132
01133
#endif // DBG
01134
01135
if ((bCreateFlags &
OCF_DESKTOPHEAP)) {
01136
#if DBG
01137
BOOL bSuccess;
01138
#endif
01139
UserAssert(((
PDESKOBJHEAD)pobj)->rpdesk !=
NULL);
01140
01141 pdesk = ((
PDESKOBJHEAD)pobj)->rpdesk;
01142
UnlockDesktop(&((
PDESKOBJHEAD)pobj)->rpdesk, LDU_OBJ_DESK, (ULONG_PTR)pobj);
01143
01144
if (pheT->
bFlags &
HANDLEF_POOL) {
01145 UserFreePool(pobj);
01146 }
else {
01147
01148
#if DBG
01149
bSuccess =
01150
#endif
01151
DesktopFree(pdesk, pobj);
01152
#if DBG
01153
if (!bSuccess) {
01154
01155
01156
01157
01158 RIPMSG1(RIP_ERROR,
"Object already freed from desktop heap! %#p", pobj);
01159 }
01160
#endif
01161
}
01162
01163 }
else if (bCreateFlags &
OCF_SHAREDHEAP) {
01164
SharedFree(pobj);
01165 }
else {
01166 UserFreePool(pobj);
01167 }
01168
01169
#if DBG
01170
01171
01172
01173
for (plrT = pheT->plr; plrT !=
NULL; plrT = plrNextT) {
01174
01175
01176
01177
01178 plrNextT = plrT->
plrNext;
01179 FreeLockRecord((HANDLE)plrT);
01180 }
01181
#endif
01182
01183
01184
01185
01186
01187
01188 wUniqT = (WORD)((pheT->
wUniq + 1) &
HMUNIQBITS);
01189 RtlZeroMemory(pheT,
sizeof(
HANDLEENTRY));
01190 pheT->
wUniq = wUniqT;
01191
01192
01193
01194
01195
01196
01197 UserAssert(pheT->
bType ==
TYPE_FREE);
01198
01199
01200
01201
01202 php =
gpHandlePages;
01203 iheCurrent = pheT -
gSharedInfo.
aheList;
01204
for (i = 0; i <
gcHandlePages; ++i, ++php) {
01205
if (iheCurrent < php->
iheLimit) {
01206 piheCurrentHead = (iheCurrent & 0x1 ? &php->
iheFreeOdd : &php->
iheFreeEven);
01207 pheT->
phead = (
PHEAD)*piheCurrentHead;
01208 *piheCurrentHead = iheCurrent;
01209
DBGHMValidateFreeLists();
01210
break;
01211 }
01212 }
01213
01214
01215
01216 UserAssert(i <
gcHandlePages);
01217
01218 UserAssert(pheT->
pOwner ==
NULL);
01219
01220
DBGValidateHandleQuota();
01221
01222
return TRUE;
01223 }
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237 BOOL HMMarkObjectDestroy(
01238 PVOID pobj)
01239 {
01240
PHE phe;
01241
01242 phe =
HMPheFromObject(pobj);
01243
01244
#if DEBUGTAGS
01245
01246
01247
01248
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
01249
if (!(phe->
bFlags &
HANDLEF_DESTROY)) {
01250
HMRecordLock(
LOCKRECORD_MARKDESTROY, pobj, ((
PHEAD)pobj)->cLockObj);
01251 }
01252 }
01253
#endif
01254
01255
01256
01257
01258
01259 phe->
bFlags |=
HANDLEF_DESTROY;
01260
01261
01262
01263
01264
01265
01266
if (((
PHEAD)pobj)->cLockObj != 0) {
01267 phe->
bFlags &= ~
HANDLEF_INDESTROY;
01268
01269
01270
01271
01272
return FALSE;
01273 }
01274
01275
#if DBG
01276
01277
01278
01279 UserAssert(!(phe->
bFlags &
HANDLEF_MARKED_OK));
01280 phe->
bFlags |=
HANDLEF_MARKED_OK;
01281
#endif
01282
01283
01284
01285
01286
return TRUE;
01287 }
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299 BOOL HMDestroyObject(
01300 PVOID pobj)
01301 {
01302
01303
01304
01305
01306
01307
01308
01309
if (!
HMMarkObjectDestroy(pobj))
01310
return FALSE;
01311
01312
01313
01314
01315
01316
HMFreeObject(pobj);
01317
return TRUE;
01318 }
01319
01320
#if DBG
01321
01322
NTSTATUS
01323 InitLockRecordLookaside()
01324 {
01325 LockRecordLookaside = UserAllocPoolNonPaged(
sizeof(
PAGED_LOOKASIDE_LIST),
01326 TAG_LOOKASIDE);
01327
if (LockRecordLookaside ==
NULL) {
01328
return STATUS_NO_MEMORY;
01329 }
01330
01331
ExInitializePagedLookasideList(LockRecordLookaside,
01332 NULL,
01333 NULL,
01334 SESSION_POOL_MASK,
01335
sizeof(
LOCKRECORD),
01336 TAG_LOCKRECORD,
01337 1000);
01338
return STATUS_SUCCESS;
01339 }
01340
01341
PLR AllocLockRecord()
01342 {
01343
PLR plr;
01344
01345
01346
01347
01348
if ((plr =
ExAllocateFromPagedLookasideList(LockRecordLookaside)) ==
NULL) {
01349
return NULL;
01350 }
01351
01352 RtlZeroMemory(plr,
sizeof(*plr));
01353
01354
return plr;
01355 }
01356
01357
01358
void FreeLockRecord(
01359
PLR plr)
01360 {
01361
ExFreeToPagedLookasideList(LockRecordLookaside, plr);
01362 }
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
void HMRecordLock(
01374 PVOID ppobj,
01375 PVOID pobj,
01376 DWORD cLockObj)
01377 {
01378
PHE phe;
01379
PLR plr;
01380
int i;
01381 ULONG hash;
01382
01383 phe =
HMPheFromObject(pobj);
01384
01385
if ((plr = AllocLockRecord()) ==
NULL) {
01386 RIPMSG0(RIP_ERROR,
"HMRecordLock failed to allocate memory");
01387
return;
01388 }
01389
01390
01391
01392
01393 plr->
plrNext = phe->plr;
01394 phe->plr = plr;
01395
01396
01397
01398
01399
if (((
PHEAD)pobj)->cLockObj > cLockObj) {
01400
01401 RIPMSG3(RIP_WARNING,
"Unmatched lock. ppobj %#p pobj %#p cLockObj %d",
01402 ppobj, pobj, cLockObj);
01403
01404 i = (
int)cLockObj;
01405 i = -i;
01406 cLockObj = (
DWORD)i;
01407 }
01408
01409 plr->
ppobj = ppobj;
01410 plr->
cLockObj = cLockObj;
01411
01412 GetStackTrace(1,
01413 LOCKRECORD_STACK,
01414 plr->
trace,
01415 &hash);
01416
return;
01417 }
01418
#endif // DBG
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
#if DBG
01430
void HMLockObject(
01431 PVOID pobj)
01432 {
01433 HANDLE h;
01434 PVOID pobjValidate;
01435
01436
01437
01438
01439
01440
01441
01442 h =
HMPheFromObject(pobj)->phead->h;
01443 pobjValidate =
HMRevalidateCatHandle(h);
01444
if (!pobj || pobj != pobjValidate) {
01445 RIPMSG2(RIP_ERROR,
01446
"HMLockObject invalid object %#p, handle %#p",
01447 pobj, h);
01448
return;
01449 }
01450
01451
01452
01453
01454 ((
PHEAD)pobj)->cLockObj++;
01455
01456
if (((
PHEAD)pobj)->cLockObj == 0)
01457 RIPMSG1(RIP_ERROR,
"Object lock count has overflowed: %#p", pobj);
01458 }
01459
#endif // DBG
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472 PVOID
HMUnlockObjectInternal(
01473 PVOID pobj)
01474 {
01475
PHE phe;
01476
01477
01478
01479
01480
01481 phe =
HMPheFromObject(pobj);
01482
if (!(phe->
bFlags &
HANDLEF_DESTROY))
01483
return pobj;
01484
01485
01486
01487
01488
01489
01490
01491
if (phe->
bFlags &
HANDLEF_INDESTROY)
01492
return pobj;
01493
01494
HMDestroyUnlockedObject(phe);
01495
return NULL;
01496 }
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509 PVOID
FASTCALL HMAssignmentLock(
01510 PVOID *ppobj,
01511 PVOID pobj)
01512 {
01513 PVOID pobjOld;
01514
01515 pobjOld = *ppobj;
01516 *ppobj = pobj;
01517
01518
01519
01520
01521
if (pobjOld !=
NULL) {
01522
01523
01524
01525
01526
01527
01528
01529
if (pobjOld == pobj) {
01530
return pobjOld;
01531 }
01532
01533
#if DEBUGTAGS
01534
01535
01536
01537
01538
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
01539
if (!
HMUnrecordLock(ppobj, pobjOld)) {
01540
HMRecordLock(ppobj, pobjOld, ((
PHEAD)pobjOld)->cLockObj - 1);
01541 }
01542 }
01543
#endif
01544
01545 }
01546
01547
01548
if (pobj !=
NULL) {
01549 UserAssert(pobj ==
HMValidateCatHandleNoSecure(((
PHEAD)pobj)->h,
TYPE_GENERIC));
01550
if (
HMIsMarkDestroy(pobj)) {
01551 RIPERR2(ERROR_INVALID_PARAMETER,
01552 RIP_WARNING,
01553
"HMAssignmentLock, locking object %#p marked for destruction at %#p\n",
01554 pobj, ppobj);
01555 }
01556
#if DEBUGTAGS
01557
01558
01559
01560
01561
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
01562
HMRecordLock(ppobj, pobj, ((
PHEAD)pobj)->cLockObj + 1);
01563
if (
HMIsMarkDestroy(pobj)) {
01564
01565 RIPMSG2(RIP_WARNING,
01566
"Locking object %#p marked for destruction at %#p",
01567 pobj, ppobj);
01568 }
01569 }
01570
#endif
01571
HMLockObject(pobj);
01572 }
01573
01574
01575
01576
01577
01578
01579
01580
01581
if (pobjOld) {
01582 pobjOld =
HMUnlockObject(pobjOld);
01583 }
01584
01585
return pobjOld;
01586 }
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599 PVOID
FASTCALL HMAssignmentUnlock(
01600 PVOID *ppobj)
01601 {
01602 PVOID pobjOld;
01603
01604 pobjOld = *ppobj;
01605 *ppobj =
NULL;
01606
01607
01608
01609
01610
if (pobjOld !=
NULL) {
01611
01612
#if DEBUGTAGS
01613
01614
01615
01616
01617
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
01618
if (!
HMUnrecordLock(ppobj, pobjOld)) {
01619
HMRecordLock(ppobj, pobjOld, ((
PHEAD)pobjOld)->cLockObj - 1);
01620 }
01621 }
01622
#endif
01623
pobjOld =
HMUnlockObject(pobjOld);
01624 }
01625
01626
return pobjOld;
01627 }
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
#if DBG
01641
VOID IsValidThreadLock(
PTHREADINFO pti,
PTL ptl, ULONG_PTR dwLimit, BOOLEAN fHM)
01642 {
01643
01644
01645
01646
01647
01648 UserAssert((ULONG_PTR)ptl >= dwLimit);
01649 UserAssert((ULONG_PTR)ptl < (ULONG_PTR)KeGetCurrentThread()->StackBase);
01650
01651
01652
01653 UserAssert(ptl->pW32Thread == (PW32THREAD)pti);
01654
01655
01656
01657
if (fHM && (ptl->pobj !=
NULL)) {
01658
01659
01660
01661 UserAssert(ptl->pobj ==
HtoPqCat(
PtoHq(ptl->pobj)));
01662
if (((
PHEAD)ptl->pobj)->cLockObj >= 32000) {
01663 RIPMSG2(RIP_WARNING,
"IsValidThreadLock: Object %#p has %d locks", ptl->pobj, ((
PHEAD)ptl->pobj)->cLockObj);
01664 }
01665 }
01666
01667
01668
01669 UserAssert(ptl->ptl->ptl == ptl);
01670 }
01671
#endif
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
#if DBG
01682
ULONG ValidateThreadLocks(
PTL NewLock,
PTL OldLock, ULONG_PTR dwLimit, BOOLEAN fHM)
01683 {
01684
UINT uTLCount = 0;
01685
PTL ptlTopLock = OldLock;
01686
PTHREADINFO ptiCurrent;
01687
01688 BEGIN_REENTERCRIT();
01689
01690 ptiCurrent =
PtiCurrent();
01691
01692
01693
01694
01695
if (NewLock !=
NULL) {
01696 UserAssert(NewLock->next == OldLock);
01697 IsValidThreadLock(ptiCurrent, NewLock, dwLimit, fHM);
01698 uTLCount++;
01699 }
01700
01701
01702
01703
01704
01705
while (OldLock !=
NULL) {
01706
01707
01708
01709 UserAssert(NewLock != OldLock);
01710
01711
01712
01713 IsValidThreadLock(ptiCurrent, OldLock, dwLimit, fHM);
01714 uTLCount++;
01715 OldLock = OldLock->next;
01716 }
01717
01718
01719
01720
if (NewLock !=
NULL) {
01721 NewLock->uTLCount = uTLCount;
01722 }
else {
01723
if (ptlTopLock ==
NULL) {
01724 RIPMSG0(RIP_WARNING,
"ptlTopLock is NULL, the system will AV now");
01725 }
01726 UserAssert(uTLCount == ptlTopLock->uTLCount);
01727 }
01728
01729 END_REENTERCRIT();
01730
01731
return uTLCount;
01732 }
01733
#endif
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
#if DBG
01746
void
01747 CreateShadowTL(
PTL ptl)
01748 {
01749
PTL pTLNextFree;
01750
if (gFreeTLList->next ==
NULL) {
01751 UserAssert(gcThreadLocksArraysAllocated < MAX_THREAD_LOCKS_ARRAYS &&
01752
"No more room in gpaThreadLocksArrays! The system will bugcheck.");
01753 gFreeTLList->next = gpaThreadLocksArrays[gcThreadLocksArraysAllocated] =
01754 UserAllocPoolZInit(
sizeof(
TL)*MAX_THREAD_LOCKS, TAG_GLOBALTHREADLOCK);
01755
if (gFreeTLList->next ==
NULL) {
01756 UserAssert(
"Can't allocate memory for gpaThreadLocksArrays: the system will bugcheck soon!");
01757 }
01758 InitGlobalThreadLockArray(gcThreadLocksArraysAllocated);
01759 gcThreadLocksArraysAllocated++;
01760 }
01761 pTLNextFree = gFreeTLList->next;
01762 RtlCopyMemory(gFreeTLList, ptl,
sizeof(
TL));
01763 gFreeTLList->ptl = ptl;
01764 ptl->ptl = gFreeTLList;
01765 gFreeTLList = pTLNextFree;
01766 }
01767
#endif // DBG
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
#if DBG
01779
void
01780
ThreadLock(
01781 PVOID pobj,
01782
PTL ptl)
01783
01784 {
01785
01786
PTHREADINFO ptiCurrent;
01787 PVOID pfnT;
01788
01789
01790
01791
01792
01793
01794 UserAssert(((ULONG_PTR)&pfnT - (ULONG_PTR)
KeGetCurrentThread()->StackLimit) > KERNEL_STACK_MINIMUM_RESERVE);
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807 UserAssert(!(
PpiCurrent()->W32PF_Flags & W32PF_TERMINATED));
01808 ptiCurrent =
PtiCurrent();
01809 UserAssert(ptiCurrent);
01810
01811
01812
01813
01814
RtlGetCallersAddress(&ptl->pfnCaller, &pfnT);
01815 ptl->pW32Thread = (PW32THREAD)ptiCurrent;
01816
01817 ptl->next = ptiCurrent->
ptl;
01818 ptiCurrent->
ptl = ptl;
01819 ptl->pobj = pobj;
01820
if (pobj !=
NULL) {
01821
HMLockObject(pobj);
01822 }
01823 CreateShadowTL(ptl);
01824 ValidateThreadLocks(ptl, ptl->next, (ULONG_PTR)&pobj, TRUE);
01825
return;
01826 }
01827
#endif
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
#if DBG
01842
PVOID
01843
ThreadLockExchange(PVOID pobj,
PTL ptl)
01844 {
01845
PTHREADINFO ptiCurrent;
01846 PVOID pobjOld;
01847 PVOID pfnT;
01848
01849
01850
01851
01852
01853 UserAssert((ULONG_PTR)&pfnT - (ULONG_PTR)
KeGetCurrentThread()->StackLimit > KERNEL_STACK_MINIMUM_RESERVE);
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866 UserAssert(!(
PpiCurrent()->W32PF_Flags & W32PF_TERMINATED));
01867 ptiCurrent =
PtiCurrent();
01868 UserAssert(ptiCurrent);
01869
01870
01871
01872
01873
RtlGetCallersAddress(&ptl->pfnCaller, &pfnT);
01874 UserAssert(ptl->pW32Thread == (PW32THREAD)ptiCurrent);
01875
01876
01877
01878
01879 pobjOld = ptl->pobj;
01880
01881
01882
01883
01884
01885
01886 ptl->pobj = pobj;
01887
if (pobj !=
NULL) {
01888
HMLockObject(pobj);
01889 }
01890
01891
01892
01893
01894
if (pobjOld) {
01895 pobjOld =
HMUnlockObject((
PHEAD)pobjOld);
01896 }
01897
01898
01899
01900 ValidateThreadLocks(NULL, ptiCurrent->
ptl, (ULONG_PTR)&pobj, TRUE);
01901 {
01902
01903
01904
01905 UserAssert(ptl->ptl->ptl == ptl);
01906 UserAssert(ptl->ptl->pobj == pobjOld);
01907 ptl->ptl->pobj = pobj;
01908 ptl->ptl->pfnCaller = ptl->pfnCaller;
01909 }
01910
01911
return pobjOld;
01912 }
01913
#endif
01914
01915
01916
01917
01918
01919
01920
#pragma optimize("t", on)
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
#if DBG
01934
PVOID
01935
ThreadUnlock1(
01936
PTL ptlIn)
01937 #
else
01938 PVOID
01939 ThreadUnlock1(
01940 VOID)
01941 #endif
01942 {
01943
PHEAD phead;
01944
PTHREADINFO ptiCurrent;
01945
PTL ptl;
01946
01947 ptiCurrent =
PtiCurrent();
01948 ptl = ptiCurrent->
ptl;
01949 UserAssert(ptl !=
NULL);
01950
01951
01952
01953 ValidateThreadLocks(
NULL, ptl, (ULONG_PTR)&ptlIn,
TRUE);
01954
01955
01956
01957 UserAssert(ptlIn == ptl);
01958 ptiCurrent->
ptl = ptl->next;
01959
01960
01961
01962 phead = (
PHEAD)(ptl->pobj);
01963
if (phead !=
NULL) {
01964
01965
01966
01967
01968
01969 phead = (
PHEAD)
HMUnlockObject(phead);
01970 }
01971
#if DBG
01972
{
01973
01974
01975
01976 ptl->ptl->next = gFreeTLList;
01977 ptl->ptl->uTLCount += TL_FREED_PATTERN;
01978 gFreeTLList = ptl->ptl;
01979 }
01980
#endif
01981
return (PVOID)phead;
01982 }
01983
01984
01985
01986
01987
#pragma optimize("", on)
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
#if DBG
01999
void CheckLock(
02000 PVOID pobj)
02001 {
02002
PTHREADINFO ptiCurrent =
PtiCurrentShared();
02003
PTL ptl;
02004
02005
if (pobj ==
NULL) {
02006
return;
02007 }
02008
02009
02010
02011
02012 UserAssert(ptiCurrent != NULL);
02013 ValidateThreadLocks(NULL, ptiCurrent->
ptl, (ULONG_PTR)&pobj, TRUE);
02014
02015
for (ptl = ptiCurrent->
ptl; ptl !=
NULL; ptl=ptl->next) {
02016
if (ptl->pobj == pobj)
02017
return;
02018 }
02019
02020
02021
02022
02023
02024
if (
HMPheFromObject(pobj)->bFlags &
HANDLEF_DESTROY)
02025
return;
02026
02027 RIPMSG1(RIP_ERROR,
"Object not thread locked! %#p", pobj);
02028 }
02029
#endif
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069 void HMDestroyUnlockedObject(
02070
PHE phe)
02071 {
02072
BEGINATOMICCHECK();
02073
02074
02075
02076
02077
02078
02079 phe->
bFlags |=
HANDLEF_INDESTROY;
02080
02081
02082
02083
02084 (*
gahti[phe->
bType].
fnDestroy)(phe->
phead);
02085
02086
02087
02088
02089
02090
02091 UserAssert(!(phe->
bFlags &
HANDLEF_INDESTROY));
02092
02093
02094
02095
02096
02097 UserAssert((phe->
bType ==
TYPE_FREE)
02098 || ((phe->
bFlags &
HANDLEF_DESTROY) && (phe->
phead->
cLockObj > 0)));
02099
02100
ENDATOMICCHECK();
02101 }
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112 VOID HMChangeOwnerThread(
02113 PVOID pobj,
02114
PTHREADINFO pti)
02115 {
02116
PHE phe =
HMPheFromObject(pobj);
02117
PTHREADINFO ptiOld = ((
PTHROBJHEAD)(pobj))->pti;
02118
PWND pwnd;
02119
PPCLS ppcls;
02120
PPROCESSINFO ppi;
02121
02122 UserAssert(
HMObjectFlags(pobj) &
OCF_THREADOWNED);
02123 UserAssert(pti !=
NULL);
02124
02125 ((
PTHREADINFO)phe->
pOwner)->ppi->UserHandleCount--;
02126
02127 ((
PTHROBJHEAD)pobj)->pti = phe->
pOwner = pti;
02128
02129 ((
PTHREADINFO)phe->
pOwner)->
ppi->UserHandleCount++;
02130
02131
DBGValidateHandleQuota();
02132
02133
02134
02135
02136
switch (phe->
bType) {
02137
case TYPE_WINDOW:
02138
02139
02140
02141
02142 UserAssert(ptiOld->
cWindows > 0 || ptiOld == pti);
02143 pti->cWindows++;
02144 ptiOld->
cWindows--;
02145
02146 pwnd = (
PWND)pobj;
02147
02148
02149
02150
02151
if (
TestWF(pwnd,
WFVISIBLE) &&
FVisCountable(pwnd)) {
02152 pti->cVisWindows++;
02153 ptiOld->
cVisWindows--;
02154 }
02155
02156
02157
02158
02159
02160
if (pti->ppi != ptiOld->
ppi) {
02161
02162 ppcls =
GetClassPtr(pwnd->
pcls->
atomClassName, pti->ppi,
hModuleWin);
02163
02164
if (ppcls ==
NULL) {
02165
if (pwnd->
head.rpdesk)
02166 ppi = pwnd->
head.rpdesk->rpwinstaParent->pTerm->ptiDesktop->ppi;
02167
else
02168 ppi =
PpiCurrent();
02169 ppcls =
GetClassPtr(
gpsi->
atomSysClass[
ICLS_ICONTITLE], ppi,
hModuleWin);
02170 }
02171 UserAssert(ppcls);
02172
02173
02174
02175
02176
02177 UserAssert((*ppcls)->rpdeskParent == pwnd->
head.rpdesk ||
02178
TestWF(pwnd,
WFDESTROYED));
02179
02180
DereferenceClass(pwnd);
02181 pwnd->
pcls = *ppcls;
02182 pwnd->
pcls->
cWndReferenceCount++;
02183 }
02184
break;
02185
02186
case TYPE_HOOK:
02187
02188
02189
02190
02191
02192 UserAssert(!!(((
PHOOK)pobj)->flags &
HF_GLOBAL) ^ (((
PHOOK)pobj)->ptiHooked !=
NULL));
02193
if (((
PHOOK)pobj)->flags &
HF_GLOBAL) {
02194 UserAssert(pti ==
gptiRit);
02195
LockDesktop(&((
PHOOK)pobj)->rpdesk, ptiOld->
rpdesk, LDL_HOOK_DESK, 0);
02196 }
else {
02197
02198
02199
02200
02201 UserAssert(((
PHOOK)pobj)->ptiHooked != ptiOld);
02202 }
02203
break;
02204
02205
default:
02206
break;
02207 }
02208 }
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220 VOID HMChangeOwnerPheProcess(
02221
PHE phe,
02222
PTHREADINFO pti)
02223 {
02224
PPROCESSINFO ppiOwner = (
PPROCESSINFO)(phe->
pOwner);
02225 PVOID pobj = phe->
phead;
02226
02227 UserAssert(
HMObjectFlags(pobj) &
OCF_PROCESSOWNED);
02228 UserAssert(pti !=
NULL);
02229
02230
02231
02232 ppiOwner->UserHandleCount--;
02233
02234
02235
02236
if ((pti->
TIF_flags &
TIF_16BIT) && (pti->
ptdb)) {
02237 ((
PPROCOBJHEAD)pobj)->hTaskWow = pti->
ptdb->
hTaskWow;
02238 }
else {
02239 ((
PPROCOBJHEAD)pobj)->hTaskWow = 0;
02240 }
02241
02242
02243
02244
if (
gahti[phe->
bType].
bObjectCreateFlags &
OCF_MARKPROCESS) {
02245 ((
PPROCMARKHEAD)pobj)->ppi = pti->
ppi;
02246 }
02247
02248
02249
02250 phe->
pOwner = pti->
ppi;
02251
02252
02253
02254 ((
PPROCESSINFO)(phe->
pOwner))->UserHandleCount++;
02255
02256
02257
02258
if (phe->
bType ==
TYPE_CURSOR) {
02259 GreDecQuotaCount((PW32PROCESS)ppiOwner);
02260 GreIncQuotaCount((PW32PROCESS)phe->
pOwner);
02261
02262
if (((
PCURSOR)pobj)->hbmColor) {
02263 GreDecQuotaCount((PW32PROCESS)ppiOwner);
02264 GreIncQuotaCount((PW32PROCESS)phe->
pOwner);
02265 }
02266 }
02267
02268
DBGValidateHandleQuota();
02269 }
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284 VOID DestroyThreadsObjects()
02285 {
02286
PTHREADINFO ptiCurrent;
02287
HANDLEENTRY volatile * (*pphe);
02288
PHE pheT;
02289
DWORD i;
02290
02291 ptiCurrent =
PtiCurrent();
02292
DBGValidateHandleQuota();
02293
02294
02295
02296
02297
02298
02299
02300
02301
DestroyCacheDCEntries(ptiCurrent);
02302
02303
02304
02305
02306
while (ptiCurrent->
ptl !=
NULL) {
02307
02308 UserAssert((ULONG_PTR)ptiCurrent->
ptl > (ULONG_PTR)&i);
02309 UserAssert((ULONG_PTR)ptiCurrent->
ptl < (ULONG_PTR)
KeGetCurrentThread()->StackBase);
02310
ThreadUnlock(ptiCurrent->
ptl);
02311 }
02312
02313
02314
02315
02316
02317
02318
02319
02320 CleanupW32ThreadLocks((PW32THREAD)ptiCurrent);
02321
02322
02323
02324
02325
02326
02327
BEGINATOMICCHECK();
02328
02329
02330
02331
02332
02333
02334 pphe = &
gSharedInfo.
aheList;
02335
for (i = 0; i <=
giheLast; i++) {
02336
02337
02338
02339
02340
02341 pheT = (
PHE)((*pphe) + i);
02342
02343
02344
02345
02346
02347
if (pheT->
bType ==
TYPE_FREE)
02348
continue;
02349
02350
02351
02352
02353
02354
02355
if (
gahti[pheT->
bType].
bObjectCreateFlags &
OCF_PROCESSOWNED) {
02356
if (pheT->
bType ==
TYPE_MENU) {
02357
PWND pwnd = ((
PMENU)pheT->
phead)->spwndNotify;
02358
02359
if (pwnd !=
NULL &&
GETPTI(pwnd) == ptiCurrent)
02360
Unlock(&((
PMENU)pheT->
phead)->spwndNotify);
02361 }
02362
continue;
02363 }
02364
02365
02366
02367
02368
if ((
PTHREADINFO)pheT->
pOwner != ptiCurrent)
02369
continue;
02370
02371 UserAssert(
gahti[pheT->
bType].bObjectCreateFlags &
OCF_THREADOWNED);
02372
02373
02374
02375
02376
02377
if (pheT->
bFlags &
HANDLEF_DESTROY) {
02378
continue;
02379 }
02380
02381
02382
02383
02384
HMDestroyUnlockedObject(pheT);
02385 }
02386
02387
ENDATOMICCHECK();
02388
DBGValidateHandleQuota();
02389 }
02390
02391
#if DBG
02392
VOID ShowLocks(
02393
PHE phe)
02394 {
02395
PLR plr = phe->plr;
02396
INT c;
02397
02398 RIPMSG2(RIP_WARNING | RIP_THERESMORE,
02399
"Lock records for %s %#p:",
02400 gahti[phe->
bType].szObjectType, phe->
phead->
h);
02401
02402
02403
02404
02405
c = 0;
02406
while (plr !=
NULL) {
02407
char achPrint[80];
02408
02409
if (plr->
ppobj ==
LOCKRECORD_MARKDESTROY) {
02410 strcpy(achPrint,
"Destroyed with");
02411 }
else if ((
int)plr->
cLockObj <= 0) {
02412 strcpy(achPrint,
" Unlock");
02413 }
else {
02414
02415
02416
02417 {
02418
PLR plrUnlock;
02419
DWORD cT;
02420
DWORD cUnlock;
02421
02422 plrUnlock = phe->plr;
02423 cT = 0;
02424 cUnlock = (
DWORD)-1;
02425
02426
while (plrUnlock != plr) {
02427
if (plrUnlock->
ppobj == plr->
ppobj) {
02428
if ((
int)plrUnlock->
cLockObj <= 0) {
02429
02430 cUnlock = cT;
02431 }
else {
02432
02433
02434 cUnlock = (
DWORD)-1;
02435 }
02436 }
02437 plrUnlock = plrUnlock->
plrNext;
02438 cT++;
02439 }
02440
if (cUnlock == (
DWORD)-1) {
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
sprintf(achPrint,
"Unmatched Lock");
02454 }
else {
02455
sprintf(achPrint,
"lock #%ld", cUnlock);
02456 }
02457 }
02458 }
02459
02460 RIPMSG4(RIP_WARNING | RIP_NONAME | RIP_THERESMORE,
02461
" %s cLock=%d, pobj at %#p, code at %#p",
02462 achPrint,
02463
abs((
int)plr->
cLockObj),
02464 plr->
ppobj,
02465 plr->
trace[0]);
02466
02467 plr = plr->
plrNext;
02468
c++;
02469 }
02470
02471 RIPMSG1(RIP_WARNING | RIP_NONAME,
" 0x%lx records", c);
02472 }
02473
#endif
02474
02475 void FixupCursor(
02476
PCURSOR pcur,
02477
PPROCESSINFO ppi)
02478 {
02479
int i;
02480
PACON pacon = (
PACON)pcur;
02481
02482
if (pcur->head.ppi ==
NULL) {
02483 pcur->head.ppi = ppi;
02484 }
02485
02486
if (
pacon->CURSORF_flags &
CURSORF_ACON) {
02487
for (i = 0; i <
pacon->cpcur; i++) {
02488
02489 UserAssert(
pacon->aspcur[i]->CURSORF_flags &
CURSORF_ACONFRAME);
02490
02491
if (
pacon->aspcur[i]->head.ppi ==
NULL) {
02492
pacon->aspcur[i]->head.ppi = ppi;
02493 }
02494 }
02495 }
02496 }
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511 VOID DestroyProcessesObjects(
02512
PPROCESSINFO ppi)
02513 {
02514
PHE pheT, pheMax;
02515
BOOL bGlobal = (
ISTS() && ppi->Process ==
gpepCSRSS);
02516
02517
02518
02519
02520
02521
02522
DBGValidateHandleQuota();
02523 pheMax = &
gSharedInfo.
aheList[
giheLast];
02524
02525
for (pheT =
gSharedInfo.
aheList; pheT <= pheMax; pheT++) {
02526
02527
02528
02529
02530
02531
if (pheT->
bType ==
TYPE_FREE)
02532
continue;
02533
02534
02535
02536
02537
if (!(
gahti[pheT->
bType].
bObjectCreateFlags &
OCF_PROCESSOWNED) ||
02538 (
PPROCESSINFO)pheT->
pOwner != ppi)
02539
continue;
02540
02541
02542
02543
02544
02545
02546
if (pheT->
bFlags &
HANDLEF_DESTROY) {
02547
HMChangeOwnerPheProcess(pheT,
gptiRit);
02548
continue;
02549 }
02550
02551
if (bGlobal) {
02552
02553
02554
02555
02556
02557
if (pheT->
bType ==
TYPE_CURSOR) {
02558
FixupCursor((
PCURSOR)pheT->
phead, ppi);
02559 }
02560 }
02561
02562
02563
02564
02565
HMDestroyUnlockedObject(pheT);
02566
02567
02568
02569
02570
02571
02572
if (pheT->
bType !=
TYPE_FREE) {
02573
if (pheT->
bType ==
TYPE_CURSOR) {
02574 RIPMSG1(RIP_WARNING,
"About to zombie pcur %#p\n",
02575 pheT->
phead);
02576
02577
ZombieCursor((
PCURSOR)pheT->
phead);
02578 }
else {
02579
HMChangeOwnerPheProcess(pheT,
gptiRit);
02580 }
02581 }
02582 }
02583
DBGValidateHandleQuota();
02584 }
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595 void MarkThreadsObjects(
02596
PTHREADINFO pti)
02597 {
02598
PHE pheT, pheMax;
02599
02600 pheMax = &
gSharedInfo.
aheList[
giheLast];
02601
for (pheT =
gSharedInfo.
aheList; pheT <= pheMax; pheT++) {
02602
02603
02604
02605
02606
if (pheT->
bType ==
TYPE_FREE)
02607
continue;
02608
02609
02610
02611
02612
if (
gahti[pheT->
bType].
bObjectCreateFlags &
OCF_PROCESSOWNED ||
02613 (
PTHREADINFO)pheT->
pOwner != pti)
02614
continue;
02615
02616
#if DBG
02617
02618
02619
02620
if (
ISTS() && (pti ==
gptiRit || pti ==
gTermIO.
ptiDesktop)) {
02621 RIPMSG2(RIP_ERROR,
"pti %#p is RIT or DT. phe %#p\n", pti, pheT);
02622 }
02623
#endif
02624
02625
HMChangeOwnerThread(pheT->
phead,
gptiRit);
02626
02627
#if DEBUGTAGS
02628
02629
if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
02630
02631
02632
02633
if (pheT->
bFlags &
HANDLEF_DESTROY) {
02634 TAGMSG2(DBGTAG_TrackLocks,
02635
"Zombie %s %#p still locked",
02636
gahti[pheT->
bType].szObjectType, pheT->
phead->
h);
02637 }
else {
02638 TAGMSG1(DBGTAG_TrackLocks,
02639
"Thread object %#p not destroyed.\n",
02640 pheT->
phead->
h);
02641 }
02642
02643
ShowLocks(pheT);
02644 }
02645
02646
#endif // DEBUGTAGS
02647
}
02648 }
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
#if DBG
02669
02670
BOOL HMRelocateLockRecord(
02671 PVOID ppobjNew,
02672 LONG_PTR cbDelta)
02673 {
02674
PHE phe;
02675 PVOID ppobjOld = (
PBYTE)ppobjNew - cbDelta;
02676
PHEAD pobj;
02677
PLR plr;
02678
02679
if (ppobjNew ==
NULL) {
02680
return FALSE;
02681 }
02682
02683 pobj = *(
PHEAD *)ppobjNew;
02684
02685
if (pobj ==
NULL) {
02686
return FALSE;
02687 }
02688
02689 phe =
HMPheFromObject(pobj);
02690
if (phe->
phead != pobj) {
02691 RIPMSG3(RIP_WARNING,
02692
"HmRelocateLockRecord(%#p, %lx) - %#p is bad pobj\n",
02693 ppobjNew, cbDelta, pobj);
02694
02695
return FALSE;
02696 }
02697
02698 plr = phe->plr;
02699
02700
while (plr !=
NULL) {
02701
if (plr->
ppobj == ppobjOld) {
02702 (
PBYTE)(plr->
ppobj) += cbDelta;
02703
return TRUE;
02704 }
02705 plr = plr->
plrNext;
02706 }
02707
02708 RIPMSG2(RIP_WARNING,
02709
"HmRelocateLockRecord(%#p, %lx) - couldn't find lock record\n",
02710 ppobjNew, cbDelta);
02711
02712
ShowLocks(phe);
02713
return FALSE;
02714 }
02715
02716
02717
BOOL HMUnrecordLock(
02718 PVOID ppobj,
02719 PVOID pobj)
02720 {
02721
PHE phe;
02722
PLR plr;
02723
PLR *pplr;
02724
02725 phe =
HMPheFromObject(pobj);
02726
02727 pplr = &(phe->plr);
02728 plr = *pplr;
02729
02730
02731
02732
02733
while (plr !=
NULL) {
02734
if (plr->
ppobj == ppobj) {
02735
02736
02737
02738 *pplr = plr->
plrNext;
02739 plr->
plrNext =
NULL;
02740
02741
02742
02743
02744 FreeLockRecord(plr);
02745
return TRUE;
02746 }
02747 pplr = &(plr->
plrNext);
02748 plr = *pplr;
02749 }
02750
02751 RIPMSG2(RIP_WARNING,
"Could not find lock for ppobj %#p pobj %#p",
02752 ppobj, pobj);
02753
02754
return FALSE;
02755 }
02756
02757
#endif // DBG
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776 VOID _QueryUserHandles(
02777 LPDWORD paPids,
02778 DWORD dwNumInstances,
02779 DWORD dwResult[][TYPE_CTYPES])
02780 {
02781
PHE pheCurPos;
02782
PHE pheMax;
02783
DWORD index;
02784
DWORD pid;
02785
DWORD dwTotalCounters[
TYPE_CTYPES];
02786
02787 RtlZeroMemory(dwTotalCounters,
TYPE_CTYPES*
sizeof(
DWORD));
02788 RtlZeroMemory(dwResult, dwNumInstances*
TYPE_CTYPES*
sizeof(
DWORD));
02789
02790
02791
02792 pheMax = &
gSharedInfo.
aheList[
giheLast];
02793
for(pheCurPos =
gSharedInfo.
aheList; pheCurPos <= pheMax; pheCurPos++) {
02794
02795 UserAssert(pheCurPos->
bType <
TYPE_CTYPES);
02796
02797 pid = 0;
02798
02799
if (pheCurPos->
pOwner) {
02800
02801
if (
gahti[pheCurPos->
bType].
bObjectCreateFlags &
OCF_PROCESSOWNED) {
02802
02803
02804
02805
02806 pid = HandleToUlong(((
PPROCESSINFO)pheCurPos->
pOwner)->Process->UniqueProcessId);
02807 }
02808
else if (
gahti[pheCurPos->
bType].
bObjectCreateFlags &
OCF_THREADOWNED) {
02809
02810
02811
02812 pid = HandleToUlong(((
PTHREADINFO)pheCurPos->
pOwner)->pEThread->ThreadsProcess->UniqueProcessId);
02813 }
02814 }
02815
02816
02817
02818
02819
for (index = 0; index < dwNumInstances; index++) {
02820
02821
if (paPids[index] == pid) {
02822 dwResult[index][pheCurPos->
bType]++;
02823 }
02824 }
02825
02826
02827
02828 dwTotalCounters[pheCurPos->
bType]++;
02829 }
02830
02831
02832
02833
02834
for (index = 0; index < dwNumInstances; index++) {
02835
02836
if (paPids[index] ==
QUC_PID_TOTAL) {
02837
02838 RtlMoveMemory(dwResult[index], dwTotalCounters,
sizeof(dwTotalCounters));
02839 }
02840 }
02841
02842 }
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853 void HMCleanupGrantedHandle(
02854 HANDLE h)
02855 {
02856
PW32JOB pW32Job;
02857
02858 pW32Job =
gpJobsList;
02859
02860
while (pW32Job !=
NULL) {
02861 PULONG_PTR pgh;
02862
DWORD dw;
02863
02864 pgh = pW32Job->
pgh;
02865
02866
02867
02868
02869
for (dw = 0; dw < pW32Job->
ughCrt; dw++) {
02870
if (*(pgh + dw) == (ULONG_PTR)h) {
02871
02872
02873
02874
02875 RtlMoveMemory(pgh + dw,
02876 pgh + dw + 1,
02877 (pW32Job->
ughCrt - dw - 1) *
sizeof(*pgh));
02878
02879 (pW32Job->
ughCrt)--;
02880
02881
02882
02883
02884
02885
break;
02886 }
02887 }
02888
02889 pW32Job = pW32Job->
pNext;
02890 }
02891 }