Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

handtabl.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define HTIENTRY(szObjectType, structName, fnDestroy, dwAllocTag, bObjectCreateFlags)   {(FnDestroyUserObject)fnDestroy, (CONST DWORD)dwAllocTag, (CONST BYTE)(bObjectCreateFlags)}
#define CPAGEENTRIESINIT   4
#define DBGValidateHandleQuota()
#define DBGHMValidateFreeLists()
#define CHANDLEENTRIESINIT   200
#define CLOCKENTRIESINIT   100

Functions

void HMNullFnDestroy (PVOID pobj)
void HMDestroyUnlockedObject (PHE phe)
void HMRecordLock (PVOID ppobj, PVOID pobj, DWORD cLockObj)
BOOL HMUnrecordLock (PVOID ppobj, PVOID pobj)
VOID ShowLocks (PHE)
void HMInitHandleEntries (ULONG_PTR iheFirstFree)
BOOL HMInitHandleTable (PVOID pReadOnlySharedSectionBase)
BOOL HMGrowHandleTable ()
PVOID HMAllocObject (PTHREADINFO ptiOwner, PDESKTOP pdeskSrc, BYTE bType, DWORD size)
BOOL HMFreeObject (PVOID pobj)
BOOL HMMarkObjectDestroy (PVOID pobj)
BOOL HMDestroyObject (PVOID pobj)
PVOID HMUnlockObjectInternal (PVOID pobj)
PVOID FASTCALL HMAssignmentLock (PVOID *ppobj, PVOID pobj)
PVOID FASTCALL HMAssignmentUnlock (PVOID *ppobj)
PVOID ThreadUnlock1 (VOID)
VOID HMChangeOwnerThread (PVOID pobj, PTHREADINFO pti)
VOID HMChangeOwnerPheProcess (PHE phe, PTHREADINFO pti)
VOID DestroyThreadsObjects ()
void FixupCursor (PCURSOR pcur, PPROCESSINFO ppi)
VOID DestroyProcessesObjects (PPROCESSINFO ppi)
void MarkThreadsObjects (PTHREADINFO pti)
VOID _QueryUserHandles (LPDWORD paPids, DWORD dwNumInstances, DWORD dwResult[][TYPE_CTYPES])
void HMCleanupGrantedHandle (HANDLE h)

Variables

CONST HANDLETYPEINFO gahti [TYPE_CTYPES]
DWORD gcHandlePages
PHANDLEPAGE gpHandlePages


Define Documentation

#define CHANDLEENTRIESINIT   200
 

Definition at line 572 of file handtabl.c.

#define CLOCKENTRIESINIT   100
 

Definition at line 573 of file handtabl.c.

#define CPAGEENTRIESINIT   4
 

Definition at line 206 of file handtabl.c.

Referenced by HMGrowHandleTable(), and HMInitHandleTable().

 
#define DBGHMValidateFreeLists  ) 
 

Definition at line 455 of file handtabl.c.

Referenced by HMAllocObject(), HMFreeObject(), and HMInitHandleEntries().

 
#define DBGValidateHandleQuota  ) 
 

Definition at line 269 of file handtabl.c.

Referenced by DestroyProcessesObjects(), DestroyThreadsObjects(), HMAllocObject(), HMChangeOwnerPheProcess(), HMChangeOwnerThread(), and HMFreeObject().

#define HTIENTRY szObjectType,
structName,
fnDestroy,
dwAllocTag,
bObjectCreateFlags   )     {(FnDestroyUserObject)fnDestroy, (CONST DWORD)dwAllocTag, (CONST BYTE)(bObjectCreateFlags)}
 

Definition at line 23 of file handtabl.c.


Function Documentation

VOID _QueryUserHandles LPDWORD  paPids,
DWORD  dwNumInstances,
DWORD  dwResult[][TYPE_CTYPES]
 

Definition at line 2776 of file handtabl.c.

References tagSHAREDINFO::aheList, tagHANDLETYPEINFO::bObjectCreateFlags, _HANDLEENTRY::bType, DWORD, gahti, giheLast, gSharedInfo, OCF_PROCESSOWNED, OCF_THREADOWNED, _HANDLEENTRY::pOwner, QUC_PID_TOTAL, TYPE_CTYPES, and VOID().

02780 { 02781 PHE pheCurPos; // Current position in the table 02782 PHE pheMax; // address of last table entry 02783 DWORD index; 02784 DWORD pid; 02785 DWORD dwTotalCounters[TYPE_CTYPES]; // system wide counters 02786 02787 RtlZeroMemory(dwTotalCounters, TYPE_CTYPES*sizeof(DWORD)); 02788 RtlZeroMemory(dwResult, dwNumInstances*TYPE_CTYPES*sizeof(DWORD)); 02789 /* 02790 * Walk the handle table and update the counters 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 * Object is owned by process 02804 * some objects may not have an owner 02805 */ 02806 pid = HandleToUlong(((PPROCESSINFO)pheCurPos->pOwner)->Process->UniqueProcessId); 02807 } 02808 else if (gahti[pheCurPos->bType].bObjectCreateFlags & OCF_THREADOWNED) { 02809 /* 02810 * Object owned by thread 02811 */ 02812 pid = HandleToUlong(((PTHREADINFO)pheCurPos->pOwner)->pEThread->ThreadsProcess->UniqueProcessId); 02813 } 02814 } 02815 /* 02816 * search to see if we are interested in this process 02817 * unowned handles are reported for the "System" process whose pid is 0 02818 */ 02819 for (index = 0; index < dwNumInstances; index++) { 02820 02821 if (paPids[index] == pid) { 02822 dwResult[index][pheCurPos->bType]++; 02823 } 02824 } 02825 /* 02826 * update the totals 02827 */ 02828 dwTotalCounters[pheCurPos->bType]++; 02829 } 02830 02831 /* 02832 * search to see if we are interested in the totals 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 }

VOID DestroyProcessesObjects PPROCESSINFO  ppi  ) 
 

Definition at line 2511 of file handtabl.c.

References tagSHAREDINFO::aheList, _HANDLEENTRY::bFlags, tagHANDLETYPEINFO::bObjectCreateFlags, BOOL, _HANDLEENTRY::bType, DBGValidateHandleQuota, FixupCursor(), gahti, giheLast, gpepCSRSS, gptiRit, gSharedInfo, HANDLEF_DESTROY, HMChangeOwnerPheProcess(), HMDestroyUnlockedObject(), ISTS, OCF_PROCESSOWNED, _HANDLEENTRY::phead, _HANDLEENTRY::pOwner, TYPE_CURSOR, TYPE_FREE, VOID(), and ZombieCursor().

Referenced by xxxDestroyThreadInfo().

02513 { 02514 PHE pheT, pheMax; 02515 BOOL bGlobal = (ISTS() && ppi->Process == gpepCSRSS); 02516 02517 /* 02518 * Loop through the table destroying all objects created by the current 02519 * process. All objects will get destroyed in their proper order simply 02520 * because of the object locking. 02521 */ 02522 DBGValidateHandleQuota(); 02523 pheMax = &gSharedInfo.aheList[giheLast]; 02524 02525 for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) { 02526 02527 /* 02528 * Check against free before we look at ppi... because pq is stored 02529 * in the object itself, which won't be there if TYPE_FREE. 02530 */ 02531 if (pheT->bType == TYPE_FREE) 02532 continue; 02533 02534 /* 02535 * Destroy those objects created by this queue. 02536 */ 02537 if (!(gahti[pheT->bType].bObjectCreateFlags & OCF_PROCESSOWNED) || 02538 (PPROCESSINFO)pheT->pOwner != ppi) 02539 continue; 02540 02541 /* 02542 * Make sure this object isn't already marked to be destroyed - we'll 02543 * do no good if we try to destroy it now since it is locked. 02544 * Change the owner since the process is going away 02545 */ 02546 if (pheT->bFlags & HANDLEF_DESTROY) { 02547 HMChangeOwnerPheProcess(pheT, gptiRit); 02548 continue; 02549 } 02550 02551 if (bGlobal) { 02552 02553 /* 02554 * For global cursors set the ppi in the pcur 02555 * to be CSRSS 02556 */ 02557 if (pheT->bType == TYPE_CURSOR) { 02558 FixupCursor((PCURSOR)pheT->phead, ppi); 02559 } 02560 } 02561 02562 /* 02563 * Destroy this object. 02564 */ 02565 HMDestroyUnlockedObject(pheT); 02566 02567 /* 02568 * When the object is freed, the handle type is set to TYPE_FREE. 02569 * Zombie this object, since its process is going away and it couldn't 02570 * be freed. This may include unlinking it and resetting the owner. 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 } /* for loop */ 02583 DBGValidateHandleQuota(); 02584 }

VOID DestroyThreadsObjects  ) 
 

Definition at line 2284 of file handtabl.c.

References tagSHAREDINFO::aheList, BEGINATOMICCHECK, _HANDLEENTRY::bFlags, tagHANDLETYPEINFO::bObjectCreateFlags, _HANDLEENTRY::bType, DBGValidateHandleQuota, DestroyCacheDCEntries(), DWORD, ENDATOMICCHECK, gahti, GETPTI, giheLast, gSharedInfo, HANDLEF_DESTROY, HMDestroyUnlockedObject(), KeGetCurrentThread, NULL, OCF_PROCESSOWNED, OCF_THREADOWNED, _HANDLEENTRY::phead, _HANDLEENTRY::pOwner, PtiCurrent, tagTHREADINFO::ptl, ThreadUnlock, TYPE_FREE, TYPE_MENU, Unlock, and VOID().

Referenced by xxxDestroyThreadInfo().

02285 { 02286 PTHREADINFO ptiCurrent; 02287 HANDLEENTRY volatile * (*pphe); 02288 PHE pheT; 02289 DWORD i; 02290 02291 ptiCurrent = PtiCurrent(); 02292 DBGValidateHandleQuota(); 02293 02294 /* 02295 * Before any window destruction occurs, we need to destroy any dcs 02296 * in use in the dc cache. When a dc is checked out, it is marked owned, 02297 * which makes gdi's process cleanup code delete it when a process 02298 * goes away. We need to similarly destroy the cache entry of any dcs 02299 * in use by the exiting process. 02300 */ 02301 DestroyCacheDCEntries(ptiCurrent); 02302 02303 /* 02304 * Remove any thread locks that may exist for this thread. 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 * CleanupPool stuff must happen before handle table clean up (as it always has been). 02315 * This is because SMWPs can be HM objects and still be locked in ptlPool. 02316 * If the handle is destroyed first (and it's not locked) we would end up with a 02317 * bogus pointer in ptlPool. If ptlPool is cleaned up first, the handle will be freed 02318 * or properly preserved if locked. 02319 */ 02320 CleanupW32ThreadLocks((PW32THREAD)ptiCurrent); 02321 02322 /* 02323 * Eventhough HMDestroyUnlockedObject might call xxxDestroyWindow, the 02324 * following loop is not supposed to leave the critical section. We must 02325 * have called PatchThreadWindows before coming here. 02326 */ 02327 BEGINATOMICCHECK(); 02328 02329 /* 02330 * Loop through the table destroying all objects created by the current 02331 * thread. All objects will get destroyed in their proper order simply 02332 * because of the object locking. 02333 */ 02334 pphe = &gSharedInfo.aheList; 02335 for (i = 0; i <= giheLast; i++) { 02336 /* 02337 * This pointer is done this way because it can change when we leave 02338 * the critical section below. The above volatile ensures that we 02339 * always use the most current value 02340 */ 02341 pheT = (PHE)((*pphe) + i); 02342 02343 /* 02344 * Check against free before we look at pti... because pq is stored 02345 * in the object itself, which won't be there if TYPE_FREE. 02346 */ 02347 if (pheT->bType == TYPE_FREE) 02348 continue; 02349 02350 /* 02351 * If a menu refererences a window owned by this thread, unlock 02352 * the window. This is done to prevent calling xxxDestroyWindow 02353 * during process cleanup. 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 * Destroy those objects created by this queue. 02367 */ 02368 if ((PTHREADINFO)pheT->pOwner != ptiCurrent) 02369 continue; 02370 02371 UserAssert(gahti[pheT->bType].bObjectCreateFlags & OCF_THREADOWNED); 02372 02373 /* 02374 * Make sure this object isn't already marked to be destroyed - we'll 02375 * do no good if we try to destroy it now since it is locked. 02376 */ 02377 if (pheT->bFlags & HANDLEF_DESTROY) { 02378 continue; 02379 } 02380 02381 /* 02382 * Destroy this object. 02383 */ 02384 HMDestroyUnlockedObject(pheT); 02385 } 02386 02387 ENDATOMICCHECK(); 02388 DBGValidateHandleQuota(); 02389 }

void FixupCursor PCURSOR  pcur,
PPROCESSINFO  ppi
 

Definition at line 2475 of file handtabl.c.

References CURSORF_ACON, CURSORF_ACONFRAME, NULL, and pacon.

Referenced by DestroyProcessesObjects().

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 }

PVOID HMAllocObject PTHREADINFO  ptiOwner,
PDESKTOP  pdeskSrc,
BYTE  bType,
DWORD  size
 

Definition at line 828 of file handtabl.c.

References tagSHAREDINFO::aheList, _HANDLEENTRY::bFlags, tagHANDLETYPEINFO::bObjectCreateFlags, BOOL, _HANDLEENTRY::bType, BYTE, tagSERVERINFO::cHandleEntries, CheckCritIn, DBGHMValidateFreeLists, DBGValidateHandleQuota, DesktopAlloc(), DTAG_HANDTABL, DWORD, ExQueryPoolBlockSize(), gahti, gcHandlePages, giheLast, gpHandlePages, gpsi, gpvSharedAlloc, gSharedInfo, gUserProcessHandleQuota, _HEAD::h, HMGrowHandleTable(), HMHandleFromIndex, HMINDEXBITS, HMIndexFromHandle, tagTDB::hTaskWow, _HANDLEPAGE::iheFreeEven, _HANDLEPAGE::iheFreeOdd, tagPERFINFO::lCount, tagPERFINFO::lMaxCount, LockDesktop, tagPERFINFO::lSize, tagPERFINFO::lTotalCount, NULL, OCF_DESKTOPHEAP, OCF_MARKPROCESS, OCF_PROCESSOWNED, OCF_SHAREDHEAP, OCF_THREADOWNED, OCF_USEPOOLIFNODESKTOP, OCF_USEPOOLQUOTA, OCF_VARIABLESIZE, PBYTE, _HANDLEENTRY::phead, tagDESKTOP::pheapDesktop, _HANDLEENTRY::pOwner, tagTHREADINFO::ppi, PPROCMARKHEAD, tagTHREADINFO::ptdb, RtlSizeHeap(), SharedAlloc(), TIF_16BIT, tagTHREADINFO::TIF_flags, and TYPE_WINDOW.

Referenced by _BeginDeferWindowPos(), _ConvertMemHandle(), _CreateAcceleratorTable(), _CreateEmptyCursorObject(), _SetWinEventHook(), CreateInputContext(), CreateMonitor(), Createpxs(), GetCPD(), InternalCreateMenu(), InternalSetTimer(), LoadKeyboardLayoutFile(), NewConversation(), xxxCreateWindowEx(), xxxCsDdeInitialize(), xxxLoadKeyboardLayoutEx(), and zzzSetWindowsHookEx().

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 * Validate size 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 * Check for process handle quota 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 * Find the next free handle 00874 * Window handles must be even; hence we try first to use odd handles 00875 * for all other objects. 00876 * Old comment: 00877 * Some wow apps, like WinProj, require even Window handles so we'll 00878 * accomodate them; build a list of the odd handles so they won't get lost 00879 * 10/13/97: WinProj never fixed this; even the 32 bit version has the problem. 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 } /* for */ 00898 /* 00899 * If we couldn't find an odd handle, then search for an even one 00900 */ 00901 fEven = ((piheFreeHead == NULL) && !fEven); 00902 } while (fEven); 00903 /* 00904 * If there are no free handles we can use, grow the table 00905 */ 00906 if (piheFreeHead == NULL) { 00907 HMGrowHandleTable(); 00908 /* 00909 * If the table didn't grow, get out. 00910 */ 00911 if (i == gcHandlePages) { 00912 RIPMSG0(RIP_WARNING, "HMAllocObject: could not grow handle space"); 00913 return NULL; 00914 } 00915 /* 00916 * Because the handle page table may have moved, 00917 * recalc the page entry pointer. 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 * HMINDEXBITS is a reserved value that should never be in the free lists 00929 * (see HMGrowHandleTable()); 00930 */ 00931 UserAssert(HMIndexFromHandle(*piheFreeHead) != HMINDEXBITS); 00932 /* 00933 * Try to allocate the object. If this fails, bail out. 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 * We're going to use this handle so get it off its free list. 00963 * The free handle phead points to the next free handle. 00964 */ 00965 iheFree = *piheFreeHead; 00966 pheT = &gSharedInfo.aheList[iheFree]; 00967 *piheFreeHead = (ULONG_PTR)pheT->phead; 00968 DBGHMValidateFreeLists(); 00969 /* 00970 * Track high water mark for handle allocation. 00971 */ 00972 if ((DWORD)iheFree > giheLast) { 00973 giheLast = (DWORD)iheFree; 00974 } 00975 /* 00976 * Setup the handle contents, plus initialize the object header. 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 * The caller is wasting time if ptiOwner != NULL 00996 * The handle entry must already have pOwner == NULL. 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 * performance counter dumphmgr 01012 * dwPrevCount is used for the snapshot option 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, &notUsed); 01027 } 01028 01029 #endif // DBG 01030 01031 /* 01032 * Return a handle entry pointer. 01033 */ 01034 return pheT->phead; 01035 }

PVOID FASTCALL HMAssignmentLock PVOID *  ppobj,
PVOID  pobj
 

Definition at line 1509 of file handtabl.c.

References FASTCALL, HMIsMarkDestroy, HMLockObject, HMRecordLock(), HMUnlockObject, HMUnrecordLock(), HMValidateCatHandleNoSecure(), NULL, PHEAD, and TYPE_GENERIC.

01512 { 01513 PVOID pobjOld; 01514 01515 pobjOld = *ppobj; 01516 *ppobj = pobj; 01517 01518 /* 01519 * Unlocks the old, locks the new. 01520 */ 01521 if (pobjOld != NULL) { 01522 01523 /* 01524 * if we are locking in the same object that is there then 01525 * it is a no-op but we don't want to do the Unlock and the Lock 01526 * because the unlock could free object and the lock would lock 01527 * in a freed pointer; 6410. 01528 */ 01529 if (pobjOld == pobj) { 01530 return pobjOld; 01531 } 01532 01533 #if DEBUGTAGS 01534 01535 /* 01536 * Track assignment locks. 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 * Track assignment locks. 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 * This unlock has been moved from up above, so that we implement a 01576 * "lock before unlock" strategy. Just in case pobjOld was the 01577 * only object referencing pobj, pobj won't go away when we unlock 01578 * pobjNew -- it will have been locked above. 01579 */ 01580 01581 if (pobjOld) { 01582 pobjOld = HMUnlockObject(pobjOld); 01583 } 01584 01585 return pobjOld; 01586 }

PVOID FASTCALL HMAssignmentUnlock PVOID *  ppobj  ) 
 

Definition at line 1599 of file handtabl.c.

References FASTCALL, HMRecordLock(), HMUnlockObject, HMUnrecordLock(), and NULL.

01601 { 01602 PVOID pobjOld; 01603 01604 pobjOld = *ppobj; 01605 *ppobj = NULL; 01606 01607 /* 01608 * Unlocks the old, locks the new. 01609 */ 01610 if (pobjOld != NULL) { 01611 01612 #if DEBUGTAGS 01613 01614 /* 01615 * Track assignment locks. 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 }

VOID HMChangeOwnerPheProcess PHE  phe,
PTHREADINFO  pti
 

Definition at line 2220 of file handtabl.c.

References tagHANDLETYPEINFO::bObjectCreateFlags, _HANDLEENTRY::bType, DBGValidateHandleQuota, gahti, HMObjectFlags, tagTDB::hTaskWow, NULL, OCF_MARKPROCESS, OCF_PROCESSOWNED, _HANDLEENTRY::phead, _HANDLEENTRY::pOwner, tagTHREADINFO::ppi, tagTHREADINFO::ptdb, TIF_16BIT, tagTHREADINFO::TIF_flags, TYPE_CURSOR, and VOID().

Referenced by DestroyProcessesObjects().

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 * Dec current owner handle count 02231 */ 02232 ppiOwner->UserHandleCount--; 02233 /* 02234 * hTaskWow 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 * ppi 02243 */ 02244 if (gahti[phe->bType].bObjectCreateFlags & OCF_MARKPROCESS) { 02245 ((PPROCMARKHEAD)pobj)->ppi = pti->ppi; 02246 } 02247 /* 02248 * Set new owner in handle entry 02249 */ 02250 phe->pOwner = pti->ppi; 02251 /* 02252 * Inc new owner handle count 02253 */ 02254 ((PPROCESSINFO)(phe->pOwner))->UserHandleCount++; 02255 /* 02256 * If the handle is a cursor, adjust GDI cursor handle count 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 }

VOID HMChangeOwnerThread PVOID  pobj,
PTHREADINFO  pti
 

Definition at line 2112 of file handtabl.c.

References tagCLS::atomClassName, tagSERVERINFO::atomSysClass, _HANDLEENTRY::bType, tagTHREADINFO::cVisWindows, tagTHREADINFO::cWindows, tagCLS::cWndReferenceCount, DBGValidateHandleQuota, DereferenceClass(), FVisCountable(), GetClassPtr(), gpsi, gptiRit, tagWND::head, HF_GLOBAL, HMObjectFlags, hModuleWin, HMPheFromObject, ICLS_ICONTITLE, LockDesktop, NULL, OCF_THREADOWNED, tagWND::pcls, PHOOK, _HANDLEENTRY::pOwner, tagTHREADINFO::ppi, PpiCurrent, tagTHREADINFO::rpdesk, TestWF, TYPE_HOOK, TYPE_WINDOW, VOID(), WFDESTROYED, and WFVISIBLE.

Referenced by MarkThreadsObjects(), xxxCreateDesktop(), xxxCreateWindowStation(), xxxDestroyWindow(), xxxFreeWindow(), and xxxMNOpenHierarchy().

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 * If this is a window, update the window counts. 02135 */ 02136 switch (phe->bType) { 02137 case TYPE_WINDOW: 02138 /* 02139 * Desktop thread used to hit this assert in HYDRA 02140 * because pti == ptiOld 02141 */ 02142 UserAssert(ptiOld->cWindows > 0 || ptiOld == pti); 02143 pti->cWindows++; 02144 ptiOld->cWindows--; 02145 02146 pwnd = (PWND)pobj; 02147 02148 /* 02149 * Make sure thread visible window count is properly updated. 02150 */ 02151 if (TestWF(pwnd, WFVISIBLE) && FVisCountable(pwnd)) { 02152 pti->cVisWindows++; 02153 ptiOld->cVisWindows--; 02154 } 02155 02156 /* 02157 * If the owning process is changing, fix up 02158 * the window class. 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 * The window is either destroyed or the desktop of the class is 02175 * the same as the window's desktop 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 * If this is a global hook, remember this hook's desktop so we'll be 02189 * able to unlink it later (gptiRit might switch to a different desktop 02190 * at any time). 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 * This must be a hook on another thread or it was supposed to be 02199 * gone by now. 02200 */ 02201 UserAssert(((PHOOK)pobj)->ptiHooked != ptiOld); 02202 } 02203 break; 02204 02205 default: 02206 break; 02207 } 02208 }

void HMCleanupGrantedHandle HANDLE  h  ) 
 

Definition at line 2853 of file handtabl.c.

References DWORD, gpJobsList, NULL, tagW32JOB::pgh, tagW32JOB::pNext, and tagW32JOB::ughCrt.

Referenced by HMFreeObject().

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 * search for the handle in the array. 02868 */ 02869 for (dw = 0; dw < pW32Job->ughCrt; dw++) { 02870 if (*(pgh + dw) == (ULONG_PTR)h) { 02871 02872 /* 02873 * found the handle granted to this process 02874 */ 02875 RtlMoveMemory(pgh + dw, 02876 pgh + dw + 1, 02877 (pW32Job->ughCrt - dw - 1) * sizeof(*pgh)); 02878 02879 (pW32Job->ughCrt)--; 02880 02881 /* 02882 * we should shrink the array also 02883 */ 02884 02885 break; 02886 } 02887 } 02888 02889 pW32Job = pW32Job->pNext; 02890 } 02891 }

BOOL HMDestroyObject PVOID  pobj  ) 
 

Definition at line 1299 of file handtabl.c.

References BOOL, FALSE, HMFreeObject(), HMMarkObjectDestroy(), and TRUE.

Referenced by HMNullFnDestroy().

01301 { 01302 /* 01303 * First mark the object for destruction. This tells the locking code 01304 * that we want to destroy this object when the lock count goes to 0. 01305 * If this returns FALSE, we can't destroy the object yet (and can't get 01306 * rid of security yet either.) 01307 */ 01308 01309 if (!HMMarkObjectDestroy(pobj)) 01310 return FALSE; 01311 01312 /* 01313 * Ok to destroy... Free the handle (which will free the object 01314 * and the handle). 01315 */ 01316 HMFreeObject(pobj); 01317 return TRUE; 01318 }

void HMDestroyUnlockedObject PHE  phe  ) 
 

Definition at line 2069 of file handtabl.c.

References BEGINATOMICCHECK, _HANDLEENTRY::bFlags, _HANDLEENTRY::bType, _HEAD::cLockObj, ENDATOMICCHECK, tagHANDLETYPEINFO::fnDestroy, gahti, HANDLEF_DESTROY, HANDLEF_INDESTROY, _HANDLEENTRY::phead, and TYPE_FREE.

02071 { 02072 BEGINATOMICCHECK(); 02073 02074 /* 02075 * Remember that we're destroying this object so we don't try to destroy 02076 * it again when the lock count goes from != 0 to 0 (especially true 02077 * for thread locks). 02078 */ 02079 phe->bFlags |= HANDLEF_INDESTROY; 02080 02081 /* 02082 * This'll call the destroy handler for this object type. 02083 */ 02084 (*gahti[phe->bType].fnDestroy)(phe->phead); 02085 02086 /* 02087 * HANDLEF_INDESTROY is supposed to be cleared either by HMMarkObjectDestroy 02088 * or by HMFreeObject; the destroy handler was supposed to call at least 02089 * the former. 02090 */ 02091 UserAssert(!(phe->bFlags & HANDLEF_INDESTROY)); 02092 02093 /* 02094 * If the object wasn't freed, it must be marked as destroyed 02095 * and must have a lock count 02096 */ 02097 UserAssert((phe->bType == TYPE_FREE) 02098 || ((phe->bFlags & HANDLEF_DESTROY) && (phe->phead->cLockObj > 0))); 02099 02100 ENDATOMICCHECK(); 02101 }

BOOL HMFreeObject PVOID  pobj  ) 
 

Definition at line 1069 of file handtabl.c.

References tagSHAREDINFO::aheList, _HANDLEENTRY::bFlags, tagHANDLETYPEINFO::bObjectCreateFlags, BOOL, _HANDLEENTRY::bType, BYTE, DBGHMValidateFreeLists, DBGValidateHandleQuota, DesktopFree, DWORD, ExQueryPoolBlockSize(), gahti, gcHandlePages, gpHandlePages, gpvSharedAlloc, gSharedInfo, _HEAD::h, HANDLEF_GRANTED, HANDLEF_POOL, HMCleanupGrantedHandle(), HMPheFromObject, HMUNIQBITS, HtoPqCat, _HANDLEPAGE::iheFreeEven, _HANDLEPAGE::iheFreeOdd, _HANDLEPAGE::iheLimit, tagPERFINFO::lCount, tagPERFINFO::lSize, NULL, OCF_DESKTOPHEAP, OCF_PROCESSOWNED, OCF_SHAREDHEAP, OCF_THREADOWNED, _HANDLEENTRY::phead, tagDESKTOP::pheapDesktop, _LOCKRECORD::plrNext, _HANDLEENTRY::pOwner, PtoHq, RtlSizeHeap(), SharedFree(), TRUE, TYPE_FREE, UnlockDesktop, and _HANDLEENTRY::wUniq.

Referenced by _BeginDeferWindowPos(), _ConvertMemHandle(), _CreateAcceleratorTable(), _DestroyMenu(), DestroyEmptyCursorObject(), DestroyEventHook(), DestroyKF(), DestroyKL(), DestroyMonitor(), DestroySMWP(), FreeDdeConv(), FreeDdeXact(), FreeHook(), FreeInputContext(), FreeTimer(), HMDestroyObject(), InternalSetTimer(), LoadKeyboardLayoutFile(), MungeClipData(), NewConversation(), NtUserDestroyAcceleratorTable(), UT_FreeCBFormat(), xxxCreateWindowEx(), xxxCsDdeInitialize(), xxxDestroyThreadDDEObject(), xxxFreeWindow(), xxxGetDummyDib(), xxxGetDummyDibV5(), and zzzSetWindowsHookEx().

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 * Free the object first. 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 * decr process handle use 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 * performance counters 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, &notUsed); 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 * We would hit this assert in HYDRA trying to free the 01156 * mother desktop window which was allocated out of pool 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 * Go through and delete the lock records, if they exist. 01172 */ 01173 for (plrT = pheT->plr; plrT != NULL; plrT = plrNextT) { 01174 01175 /* 01176 * Remember the next one before freeing this one. 01177 */ 01178 plrNextT = plrT->plrNext; 01179 FreeLockRecord((HANDLE)plrT); 01180 } 01181 #endif 01182 01183 /* 01184 * Clear the handle contents. Need to remember the uniqueness across 01185 * the clear. Also, advance uniqueness on free so that uniqueness checking 01186 * against old handles also fails. 01187 */ 01188 wUniqT = (WORD)((pheT->wUniq + 1) & HMUNIQBITS); 01189 RtlZeroMemory(pheT, sizeof(HANDLEENTRY)); 01190 pheT->wUniq = wUniqT; 01191 01192 /* 01193 * Change the handle type to TYPE_FREE so we know what type this handle 01194 * is. (TYPE_FREE is defined as zero) 01195 */ 01196 /* pheT->bType = TYPE_FREE; */ 01197 UserAssert(pheT->bType == TYPE_FREE); 01198 01199 /* 01200 * Put the handle on the free list of the appropriate page. 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 * We must have found it. 01215 */ 01216 UserAssert(i < gcHandlePages); 01217 01218 UserAssert(pheT->pOwner == NULL); 01219 01220 DBGValidateHandleQuota(); 01221 01222 return TRUE; 01223 }

BOOL HMGrowHandleTable  ) 
 

Definition at line 704 of file handtabl.c.

References tagSHAREDINFO::aheList, BOOL, _HANDLEENTRY::bType, tagSERVERINFO::cbHandleTable, tagSERVERINFO::cHandleEntries, CommitReadOnlyMemory(), CPAGEENTRIESINIT, DWORD, FALSE, gcHandlePages, ghSectionShared, gpHandlePages, gpsi, gpvSharedAlloc, gpvSharedBase, gSharedInfo, HMINDEXBITS, HMInitHandleEntries(), _HANDLEPAGE::iheFreeEven, _HANDLEPAGE::iheFreeOdd, _HANDLEPAGE::iheLimit, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, PBYTE, _HANDLEENTRY::phead, Status, TRUE, TYPE_FREE, and _HANDLEENTRY::wUniq.

Referenced by HMAllocObject().

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 * If we've run out of handle space, fail. 00716 */ 00717 i = gpsi->cHandleEntries; 00718 if (i & ~HMINDEXBITS) 00719 return FALSE; 00720 00721 /* 00722 * Grow the page table if need be. 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 * Commit some more pages to the table. First find the 00739 * address where the commitment needs to be. 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 * Update the global information to include the new 00760 * page. 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 * Check for handle overflow 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 * HMINDEXBITS has a special meaning. We used to handle this in HMAllocObject. 00792 * Now we handle it here right after adding that handle to the table. 00793 * Old Comment: 00794 * Reserve this table entry so that PW(HMINDEXBITS) maps to a 00795 * NULL pointer. Set it to TYPE_FREE so the cleanup code doesn't think 00796 * it is allocated. Set wUniq to 1 so that RevalidateHandles on HMINDEXBITS 00797 * will fail. 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 }

void HMInitHandleEntries ULONG_PTR  iheFirstFree  ) 
 

Definition at line 529 of file handtabl.c.

References tagSHAREDINFO::aheList, tagSERVERINFO::cHandleEntries, DBGHMValidateFreeLists, gpsi, gSharedInfo, NULL, _HANDLEENTRY::phead, and _HANDLEENTRY::wUniq.

Referenced by HMGrowHandleTable(), and HMInitHandleTable().

00530 { 00531 ULONG_PTR ihe; 00532 PHE pheT; 00533 /* 00534 * Zero out all the new entries 00535 */ 00536 RtlZeroMemory (&gSharedInfo.aheList[iheFirstFree], 00537 (gpsi->cHandleEntries - iheFirstFree) * sizeof(HANDLEENTRY)); 00538 /* 00539 * Link them together. 00540 * Each free odd/even entry points to the next odd/even free entry. 00541 */ 00542 ihe = iheFirstFree; 00543 for (pheT = &gSharedInfo.aheList[ihe]; ihe < gpsi->cHandleEntries; ihe++, pheT++) { 00544 pheT->phead = (PHEAD)(ihe + 2); 00545 /* pheT->bType = TYPE_FREE; */ 00546 pheT->wUniq = 1; 00547 } 00548 /* 00549 * Terminate the lists. 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 * Let's check that we got it right 00561 */ 00562 DBGHMValidateFreeLists(); 00563 }

BOOL HMInitHandleTable PVOID  pReadOnlySharedSectionBase  ) 
 

Definition at line 575 of file handtabl.c.

References tagSHAREDINFO::aheList, tagHANDLETYPEINFO::bObjectCreateFlags, BOOL, _HANDLEENTRY::bType, BYTE, tagSERVERINFO::cbHandleTable, tagSERVERINFO::cHandleEntries, CommitReadOnlyMemory(), CPAGEENTRIESINIT, DESKOBJHEAD, FALSE, gahti, gcHandlePages, ghSectionShared, gpHandlePages, gpsi, gSharedInfo, HANDLEPAGE, HMINDEXBITS, HMInitHandleEntries(), _HANDLEPAGE::iheFreeEven, _HANDLEPAGE::iheFreeOdd, _HANDLEPAGE::iheLimit, NT_SUCCESS, NTSTATUS(), NULL, OCF_DESKTOPHEAP, OCF_MARKPROCESS, OCF_PROCESSOWNED, OCF_SHAREDHEAP, OCF_THREADOWNED, OCF_USEPOOLIFNODESKTOP, OCF_USEPOOLQUOTA, PAGE_SIZE, _HANDLEENTRY::phead, PROCDESKHEAD, PROCOBJHEAD, Status, THRDESKHEAD, TRUE, TYPE_CTYPES, TYPE_FREE, UINT, and _HANDLEENTRY::wUniq.

Referenced by Win32UserInitialize().

00577 { 00578 NTSTATUS Status; 00579 SIZE_T ulCommit; 00580 00581 /* 00582 * Allocate the handle page array. Make it big enough 00583 * for 4 pages, which should be sufficient for nearly 00584 * all instances. 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 * Allocate the array. We have the space from 00599 * NtCurrentPeb()->ReadOnlySharedMemoryBase to 00600 * NtCurrentPeb()->ReadOnlySharedMemoryHeap reserved for 00601 * the handle table. All we need to do is commit the pages. 00602 * 00603 * Compute the minimum size of the table. The allocation will 00604 * round this up to the next page size. 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 * Initialize the handlepage info. Handle 0 is reserved so even free list 00618 * starts at 2. 00619 */ 00620 gpHandlePages[0].iheFreeOdd = 1; 00621 gpHandlePages[0].iheFreeEven = 2; 00622 gpHandlePages[0].iheLimit = gpsi->cHandleEntries; 00623 /* 00624 * Initialize the handle entries. 00625 */ 00626 HMInitHandleEntries(0); 00627 /* 00628 * PW(NULL) (ie, handle 0) must map to a NULL pointer. 00629 * Old comment: 00630 * Reserve the first handle table entry so that PW(NULL) maps to a 00631 * NULL pointer. Set it to TYPE_FREE so the cleanup code doesn't think 00632 * it is allocated. Set wUniq to 1 so that RevalidateHandles on NULL 00633 * will fail. 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 * Make sure we don't need to add the special case to handle HMINDEXBITS in this function. 00642 */ 00643 UserAssert(gpsi->cHandleEntries <= HMINDEXBITS); 00644 /* 00645 * PDESKOBJHEAD won't do the right casting unless these structs have 00646 * the same size. 00647 */ 00648 UserAssert(sizeof(THROBJHEAD) == sizeof(PROCOBJHEAD)); 00649 UserAssert(sizeof(THRDESKHEAD) == sizeof(PROCDESKHEAD)); 00650 UserAssert(sizeof(THRDESKHEAD) == sizeof(DESKOBJHEAD)); 00651 /* 00652 * Validate type flags to make sure that assumptions made 00653 * throughout HM code are OK. 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 * Illegal flag combinations 00663 */ 00664 UserAssert(!((bObjectCreateFlags & OCF_DESKTOPHEAP) && (bObjectCreateFlags & OCF_MARKPROCESS))); 00665 /* 00666 * Pointless (and probably illegal) flag combinations 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 * Required flag combinations 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 } /* while (uTypes-- != 0) */ 00690 } 00691 #endif 00692 00693 return TRUE; 00694 }

BOOL HMMarkObjectDestroy PVOID  pobj  ) 
 

Definition at line 1237 of file handtabl.c.

References _HANDLEENTRY::bFlags, BOOL, FALSE, HANDLEF_DESTROY, HANDLEF_INDESTROY, HANDLEF_MARKED_OK, HMPheFromObject, HMRecordLock(), LOCKRECORD_MARKDESTROY, and TRUE.

Referenced by _DestroyCursor(), _DestroyMenu(), DestroyEventHook(), DestroyKF(), DestroyMonitor(), DestroySMWP(), FreeDdeConv(), FreeDdeXact(), FreeHook(), FreeInputContext(), FreeTimer(), FreeWindowStation(), HMDestroyObject(), NtUserDestroyAcceleratorTable(), UnlockAndFreeCPDs(), Win32kNtUserCleanup(), xxxDestroyThreadDDEObject(), xxxFreeWindow(), xxxInternalUnloadKeyboardLayout(), and xxxLoadKeyboardLayoutEx().

01239 { 01240 PHE phe; 01241 01242 phe = HMPheFromObject(pobj); 01243 01244 #if DEBUGTAGS 01245 /* 01246 * Record where the object was marked for destruction. 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 * Set the destroy flag so our unlock code will know we're trying to 01257 * destroy this object. 01258 */ 01259 phe->bFlags |= HANDLEF_DESTROY; 01260 01261 /* 01262 * If this object can't be destroyed, then CLEAR the HANDLEF_INDESTROY 01263 * flag - because this object won't be currently "in destruction"! 01264 * (if we didn't clear it, when it was unlocked it wouldn't get destroyed). 01265 */ 01266 if (((PHEAD)pobj)->cLockObj != 0) { 01267 phe->bFlags &= ~HANDLEF_INDESTROY; 01268 01269 /* 01270 * Return FALSE because we can't destroy this object. 01271 */ 01272 return FALSE; 01273 } 01274 01275 #if DBG 01276 /* 01277 * Ensure that this function only returns TRUE once. 01278 */ 01279 UserAssert(!(phe->bFlags & HANDLEF_MARKED_OK)); 01280 phe->bFlags |= HANDLEF_MARKED_OK; 01281 #endif 01282 01283 /* 01284 * Return TRUE because Lock count is zero - ok to destroy this object. 01285 */ 01286 return TRUE; 01287 }

void HMNullFnDestroy PVOID  pobj  ) 
 

Definition at line 28 of file handtabl.c.

References HMDestroyObject().

00029 { 00030 RIPMSG1(RIP_WARNING, "HM: No clean up function for %#p", pobj); 00031 HMDestroyObject(pobj); 00032 return; 00033 }

void HMRecordLock PVOID  ppobj,
PVOID  pobj,
DWORD  cLockObj
 

Referenced by HMAssignmentLock(), HMAssignmentUnlock(), and HMMarkObjectDestroy().

PVOID HMUnlockObjectInternal PVOID  pobj  ) 
 

Definition at line 1472 of file handtabl.c.

References _HANDLEENTRY::bFlags, HANDLEF_DESTROY, HANDLEF_INDESTROY, HMDestroyUnlockedObject(), HMPheFromObject, and NULL.

01474 { 01475 PHE phe; 01476 01477 /* 01478 * The object is not reference counted. If the object is not a zombie, 01479 * return success because the object is still around. 01480 */ 01481 phe = HMPheFromObject(pobj); 01482 if (!(phe->bFlags & HANDLEF_DESTROY)) 01483 return pobj; 01484 01485 /* 01486 * We're destroying the object based on an unlock... Make sure it isn't 01487 * currently being destroyed! (It is valid to have lock counts go from 01488 * 0 to != 0 to 0 during destruction... don't want recursion into 01489 * the destroy routine. 01490 */ 01491 if (phe->bFlags & HANDLEF_INDESTROY) 01492 return pobj; 01493 01494 HMDestroyUnlockedObject(phe); 01495 return NULL; 01496 }

BOOL HMUnrecordLock PVOID  ppobj,
PVOID  pobj
 

Referenced by HMAssignmentLock(), and HMAssignmentUnlock().

void MarkThreadsObjects PTHREADINFO  pti  ) 
 

Definition at line 2595 of file handtabl.c.

References tagSHAREDINFO::aheList, _HANDLEENTRY::bFlags, tagHANDLETYPEINFO::bObjectCreateFlags, _HANDLEENTRY::bType, gahti, giheLast, gptiRit, gSharedInfo, gTermIO, _HEAD::h, HANDLEF_DESTROY, HMChangeOwnerThread(), ISTS, OCF_PROCESSOWNED, _HANDLEENTRY::phead, _HANDLEENTRY::pOwner, tagTERMINAL::ptiDesktop, ShowLocks(), and TYPE_FREE.

Referenced by xxxDestroyThreadInfo().

02597 { 02598 PHE pheT, pheMax; 02599 02600 pheMax = &gSharedInfo.aheList[giheLast]; 02601 for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) { 02602 /* 02603 * Check against free before we look at pti... because pti is stored 02604 * in the object itself, which won't be there if TYPE_FREE. 02605 */ 02606 if (pheT->bType == TYPE_FREE) 02607 continue; 02608 02609 /* 02610 * Change ownership! 02611 */ 02612 if (gahti[pheT->bType].bObjectCreateFlags & OCF_PROCESSOWNED || 02613 (PTHREADINFO)pheT->pOwner != pti) 02614 continue; 02615 02616 #if DBG 02617 /* 02618 * This is just to make sure that RIT or DT never get here 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 * Object still around: print warning message. 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 }

VOID ShowLocks PHE   ) 
 

Referenced by MarkThreadsObjects().

PVOID ThreadUnlock1 VOID   ) 
 

Definition at line 1939 of file handtabl.c.

References HMUnlockObject, NULL, PtiCurrent, tagTHREADINFO::ptl, and TRUE.

01942 { 01943 PHEAD phead; 01944 PTHREADINFO ptiCurrent; 01945 PTL ptl; 01946 01947 ptiCurrent = PtiCurrent(); 01948 ptl = ptiCurrent->ptl; 01949 UserAssert(ptl != NULL); 01950 /* 01951 * Validate the thread lock list. 01952 */ 01953 ValidateThreadLocks(NULL, ptl, (ULONG_PTR)&ptlIn, TRUE); 01954 /* 01955 * Make sure the caller wants to unlock the top lock. 01956 */ 01957 UserAssert(ptlIn == ptl); 01958 ptiCurrent->ptl = ptl->next; 01959 /* 01960 * If the object address is not NULL, then unlock the object. 01961 */ 01962 phead = (PHEAD)(ptl->pobj); 01963 if (phead != NULL) { 01964 01965 /* 01966 * Unlock the object. 01967 */ 01968 01969 phead = (PHEAD)HMUnlockObject(phead); 01970 } 01971 #if DBG 01972 { 01973 /* 01974 * Remove the corresponding element from gFreeTLList 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 }


Variable Documentation

CONST HANDLETYPEINFO gahti[TYPE_CTYPES]
 

Definition at line 90 of file handtabl.c.

Referenced by _QueryUserHandles(), _WOWCleanup(), DestroyHandleTableObjects(), DestroyProcessesObjects(), DestroyProcessInfo(), DestroyThreadsObjects(), HMAllocObject(), HMChangeOwnerPheProcess(), HMDestroyUnlockedObject(), HMFreeObject(), HMInitHandleTable(), IsHandleEntrySecure(), and MarkThreadsObjects().

DWORD gcHandlePages
 

Definition at line 208 of file handtabl.c.

Referenced by HMAllocObject(), HMFreeObject(), HMGrowHandleTable(), and HMInitHandleTable().

PHANDLEPAGE gpHandlePages
 

Definition at line 209 of file handtabl.c.

Referenced by HMAllocObject(), HMFreeObject(), HMGrowHandleTable(), HMInitHandleTable(), and Win32KDriverUnload().


Generated on Sat May 15 19:44:02 2004 for test by doxygen 1.3.7