Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1489 lines
37 KiB

/******************************Module*Header*******************************\
* Module Name: muclean.cxx
*
* Cleanup module for WIN32K.SYS GRE
*
* Copyright (c) 1998-1999 Microsoft Corporation
*
\**************************************************************************/
#include "precomp.hxx"
#include "muclean.hxx"
#include "verifier.hxx"
#if DBG
ULONG
DbgPrint(
PCH Format,
...
);
#define DBGPRINT(x) DbgPrint x
#if DBGTRACE
#define TRACE0(x) DbgPrint x
#define TRACE1(x) DbgPrint x
#else
#define TRACE0(x)
#define TRACE1(x)
#endif
#else
#define DBGPRINT(x)
#define TRACE0(x)
#define TRACE1(x)
#endif
/*
* External variables we must cleanup
*/
// hmgrapi.cxx
extern PLARGE_INTEGER gpLockShortDelay;
extern PVOID *gpTmpGlobalFree;
extern PVOID gpTmpGlobal;
extern "C" HFASTMUTEX ghfmMemory;
extern PVOID gpHmgrSharedHandleSection;
// drvsup.cxx
extern PLDEV gpldevDrivers;
extern PBYTE gpRGBXlate;
// invcmap.cxx
extern PBYTE gpDefITable;
/*
* Our global data for tracking lists
*/
LIST_ENTRY MultiUserGreEngAllocList;
HSEMAPHORE MultiUserEngAllocListLock = NULL;
#if DBG
LIST_ENTRY DebugGreMapViewList;
HSEMAPHORE DebugGreMapViewListLock = NULL;
#endif
/*
* The EngLoadModule tracking list
*/
LIST_ENTRY GreEngLoadModuleAllocList;
HSEMAPHORE GreEngLoadModuleAllocListLock = NULL;
BOOL FASTCALL NtGdiCloseProcess(W32PID,CLEANUPTYPE);
/*
* Forward references
*/
VOID MultiUserCleanupPathAlloc();
VOID MultiUserGreCleanupEngResources();
VOID MultiUserGreHmgOwnAll(W32PID);
VOID MultiUserGreCleanupDrivers();
VOID MultiUserGreCleanupAllFonts();
VOID MultiUserGreDeleteXLATE();
VOID vCleanUpFntCache(VOID);
// drvsup.cxx
extern VOID MultiUserDrvCleanupGraphicsDeviceList();
// fontsup.cxx
extern VOID MultiUserGreDeleteScripts();
/*
* Debug only
*/
#if DBG
// Hydra session id (see ntuser\kernel\globals.c).
extern "C" ULONG gSessionId;
VOID DebugGreCleanupMapView();
VOID MultiUserGreHmgDbgScan(BOOL, BOOL);
char *gpszHmgrType[] = {
"ObjectType ", // 0x00
"DC_TYPE ", // 0x01
"DD_DIRECTDRAW_TYPE", // 0x02
"DD_SURFACE_TYPE ", // 0x03
"RGN_TYPE ", // 0x04
"SURF_TYPE ", // 0x05
"CLIENTOBJ_TYPE ", // 0x06
"PATH_TYPE ", // 0x07
"PAL_TYPE ", // 0x08
"ICMLCS_TYPE ", // 0x09
"LFONT_TYPE ", // 0x0a
"RFONT_TYPE ", // 0x0b
"PFE_TYPE ", // 0x0c
"PFT_TYPE ", // 0x0d
"ICMCXF_TYPE ", // 0x0e
"SPRITE_TYPE ", // 0x0f
"BRUSH_TYPE ", // 0x10
"D3D_HANDLE_TYPE ", // 0x11
"DD_VIDEOPORT_TYPE ", // 0x12
"SPACE_TYPE ", // 0x13
"DD_MOTIONCOMP_TYPE", // 0x14
"META_TYPE ", // 0x15
"EFSTATE_TYPE ", // 0x16
"BMFD_TYPE ", // 0x17
"VTFD_TYPE ", // 0x18
"TTFD_TYPE ", // 0x19
"RC_TYPE ", // 0x1a
"TEMP_TYPE ", // 0x1b
"DRVOBJ_TYPE ", // 0x1c
"DCIOBJ_TYPE ", // 0x1d
"SPOOL_TYPE " // 0x1e
};
#endif
/*
* Can put these initialization functions in the INIT segment.
*/
extern "C" {
BOOL GreEngLoadModuleTrackInit();
BOOL MultiUserGreCleanupInit();
}
#pragma alloc_text(INIT, MultiUserGreCleanupInit)
#pragma alloc_text(INIT, GreEngLoadModuleTrackInit)
extern "C" HSEMAPHORE ghsemBMFD;
extern "C" HSEMAPHORE ghsemVTFD;
extern "C" CP_GLYPHSET *gpcpGlyphsets;
extern "C" CP_GLYPHSET *gpcpVTFD;
extern void vCleanupPrintKViewList();
/******************************Public*Routine******************************\
* GreEngLoadModuleTrackInit
*
* Initializes the EngLoadModule tracking list
*
* Arguments:
*
* Return Value:
*
* History:
*
* 21-Apr-1998 -by- Ori Gershony [orig]
*
\**************************************************************************/
extern "C"
BOOL
GreEngLoadModuleTrackInit()
{
InitializeListHead(&GreEngLoadModuleAllocList);
GreEngLoadModuleAllocListLock = GreCreateSemaphoreNonTracked();
return (GreEngLoadModuleAllocListLock != NULL);
}
/*****************************************************************************
*
* MultiUserGreCleanupInit
*
* Init the GRE cleanup code
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
extern "C"
BOOL
MultiUserGreCleanupInit()
{
InitializeListHead(&MultiUserGreEngAllocList);
#if DBG
InitializeListHead(&DebugGreMapViewList);
#endif
MultiUserEngAllocListLock = GreCreateSemaphoreNonTracked();
#if DBG
DebugGreMapViewListLock = GreCreateSemaphoreNonTracked();
#endif
#if DBG
return ((MultiUserEngAllocListLock != NULL) &&
(DebugGreMapViewListLock != NULL));
#else
return (MultiUserEngAllocListLock != NULL);
#endif
}
/*****************************************************************************
*
* MultiUserNtGreCleanup
*
* This performs the main additional cleanup processing
* of kernel mode GRE. This supports the unloading of the
* win32k.sys kernel module on WinFrame.
*
* Our concern here is non-paged pool and kernel resource
* objects. Paged pool is not a problem since a WINSTATION SPACE
* paged pool allocator is used which destroys all pageable memory
* allocated by win32k.sys and its video and printer drivers when
* the WINSTATION SPACE is deleted.
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
extern PPAGED_LOOKASIDE_LIST pHmgLookAsideList[];
extern "C" PVOID LastNlsTableBuffer;
VOID CleanUpEUDC(VOID);
extern "C"
BOOL
MultiUserNtGreCleanup()
{
NTSTATUS ntstatus;
W32PID pid = W32GetCurrentPID();
//
// Assign ownership of all handle manager objects to cleanup process.
// Must be done first.
//
MultiUserGreHmgOwnAll(pid);
GdiMultiUserFontCleanup();
//
// Use the process termination code to delete the majority of objects
// (all except some font related objects).
//
if(gpentHmgr!=NULL) {
NtGdiCloseProcess(pid, CLEANUP_SESSION);
}
if (gpfsTable)
{
VFREEMEM(gpfsTable);
gpfsTable = NULL;
}
if (MAPPER::SignatureTable)
{
VFREEMEM(MAPPER::SignatureTable);
MAPPER::SignatureTable = NULL;
}
// Clean up LastNlsTableBuffer
if (LastNlsTableBuffer)
{
VFREEMEM(LastNlsTableBuffer);
LastNlsTableBuffer = NULL;
}
//
// Cleanup the scripts (created by InitializeScripts during
// InitializeGre).
//
MultiUserGreDeleteScripts();
//
// Cleanup the XLATE cache (created by vInitXLATE during
// InitializeGre).
//
MultiUserGreDeleteXLATE();
//
// Cleanup RBRUSH caches.
//
if (gpCachedEngbrush)
{
//
// Engine brush cache is just one deep (refer to
// EngRealizeBrush in engbrush.cxx).
//
VFREEMEM(gpCachedEngbrush);
}
if (gpCachedDbrush)
{
//
// Device brush cache is just one deep (refer to
// BRUSHOBJ__pvAllocRbrush in brushddi.cxx).
//
VFREEMEM(gpCachedDbrush);
}
if (gpRGBXlate)
{
VFREEMEM(gpRGBXlate);
gpRGBXlate = NULL;
}
if(gpDefITable)
{
VFREEMEM(gpDefITable);
gpDefITable = NULL;
}
//
// Cleanup driver objects.
//
MultiUserGreCleanupDrivers();
#ifdef _PER_SESSION_GDEVLIST_
//
// Currently, the graphics device list (see drvsup.cxx) is allocated
// per-Hydra session. AndreVa has proposed that they be allocated
// globally. He's probably right, but until this changes we need to
// clean them up during Hydra shutdown.
//
// To enable cleanup of the per-Hydra graphics device lists (i.e.,
// the function MultiUserDrvCleanupGraphicsDeviceList in drvsup.cxx),
// define _PER_SESSION_GDEVLIST_ in muclean.hxx.
//
MultiUserDrvCleanupGraphicsDeviceList();
#endif
//
// Handle manager should be empty at this point.
//
#if DBG
if (gpentHmgr != NULL) {
MultiUserGreHmgDbgScan(TRUE, TRUE);
}
#endif
//
// Cleanup random pool allocations.
//
if (gpLockShortDelay)
{
GdiFreePool(gpLockShortDelay);
gpLockShortDelay = NULL;
}
if (gpTmpGlobal)
{
GdiFreePool(gpTmpGlobal);
gpTmpGlobal = NULL;
}
if (gpTmpGlobalFree)
{
GdiFreePool(gpTmpGlobalFree);
gpTmpGlobalFree = NULL;
}
//
// Call the C++ "friend" function for cleanup
//
MultiUserCleanupPathAlloc();
//
// These must be last since they catch all the
// leftover NT kernel resource objects that were
// not released by the above code.
//
// The reason this is done is that these objects
// can be created as the result of embedded classes
// that stay around.
//
// Also every printer driver also can call EngCreateSemaphore
// and leak it.
//
//
// Cleanup the tracked resources.
//
MultiUserGreCleanupEngResources();
#if DBG
//
// On free builds, we track and cleanup only the views
// allocated by drivers (i.e., through the Eng
// helper functions).
//
// However, on debug builds we will track all views
// to help find engine leaks. The functions below
// will cleanup, but they will also assert.
//
DebugGreCleanupMapView();
#endif
//
// Cleanup watchdog's association list mutex.
//
GreDeleteFastMutex(gAssociationListMutex);
gAssociationListMutex = NULL;
//
// Cleanup the HMGR look aside buffer mutex.
//
GreDeleteFastMutex(ghfmMemory);
ghfmMemory = NULL;
if (gpGdiSharedMemory)
{
ntstatus = Win32UnmapViewInSessionSpace(gpGdiSharedMemory);
gpGdiSharedMemory = NULL;
}
if (gpHmgrSharedHandleSection)
{
Win32DestroySection(gpHmgrSharedHandleSection);
gpHmgrSharedHandleSection = NULL;
}
//
// Free the HMGR lookaside lists.
//
for (int i = 0; i <= MAX_TYPE; i++)
{
if (pHmgLookAsideList[i] != NULL)
{
ExDeletePagedLookasideList(pHmgLookAsideList[i]);
GdiFreePool(pHmgLookAsideList[i]);
pHmgLookAsideList[i]=NULL;
}
}
return(TRUE);
}
/*****************************************************************************
*
* MultiUserCleanupPathAlloc
*
* Friend function to cleanup a PATHALLOC object's
* class global state.
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
VOID
MultiUserCleanupPathAlloc()
{
// pathobj.cxx
if (PATHALLOC::hsemFreelist)
{
GreDeleteSemaphore(PATHALLOC::hsemFreelist);
PATHALLOC::hsemFreelist = NULL;
}
//
// Release the PATHALLOC freelist.
//
while (PATHALLOC::freelist)
{
PATHALLOC *ppa = PATHALLOC::freelist;
PATHALLOC::freelist = ppa->ppanext;
VFREEMEM(ppa);
}
return;
}
/******************************Public*Routine******************************\
* MultiUserGreTrackAddEngResource
*
* Add an entry associated with an EngAllocMem.
*
* WARNING:
* EngInitializeSafeSemaphore calls GreCreateSemaphore which in turn calls
* this function. Since EngInitializeSafeSemaphore does this with the
* HMGR global lock (MLOCKFAST) held, this function must never call any
* anything that grabs MLOCKFAST. If this becomes necessary in the future,
* EngInitializeSafeSemaphore must be rewritten.
*
* History:
* 19-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreTrackAddEngResource(
PENGTRACKHDR peth,
ULONG ulType
)
{
PLIST_ENTRY Entry = (PLIST_ENTRY) peth;
//setting to 0 would be a waste of time
//peth->ulReserved = 0;
peth->ulType = ulType;
if(MultiUserEngAllocListLock) GreAcquireSemaphore(MultiUserEngAllocListLock);
InsertTailList(&MultiUserGreEngAllocList, Entry);
if(MultiUserEngAllocListLock) GreReleaseSemaphore(MultiUserEngAllocListLock);
}
/******************************Public*Routine******************************\
* MultiUserGreTrackRemoveEngResource
*
* Add an entry associated with an EngAllocMem.
*
* WARNING:
* EngDeleteSafeSemaphore calls GreDeleteSemaphore which in turn calls
* this function. Since EngDeleteSafeSemaphore does this with the
* HMGR global lock (MLOCKFAST) held, this function must never call any
* anything that grabs MLOCKFAST. If this becomes necessary in the future,
* EngDeleteSafeSemaphore must be rewritten.
*
* History:
* 19-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreTrackRemoveEngResource(
PENGTRACKHDR peth
)
{
PLIST_ENTRY Entry = (PLIST_ENTRY) peth;
if(MultiUserEngAllocListLock) GreAcquireSemaphore(MultiUserEngAllocListLock);
RemoveEntryList(Entry);
if(MultiUserEngAllocListLock) GreReleaseSemaphore(MultiUserEngAllocListLock);
}
/******************************Public*Routine******************************\
* MultiUserGreCleanupEngResources
*
* Cleanup the tracked EngAlloc objects and tracked (Gre and Eng) semaphores.
*
* WARNING: This must not invoke any code which uses tracked semaphores. If
* it is inevitable, the semaphores in question must be changed
* to non-tracked semaphores (and cleaned up explicitly).
*
* WARNING: This function is called late in MultiUserGreCleanupEngResources.
* Be careful to avoid using structures that have already been
* cleaned up.
*
* History:
* 19-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreCleanupEngResources()
{
volatile PLIST_ENTRY pNextEntry;
if(MultiUserEngAllocListLock)
{
pNextEntry = MultiUserGreEngAllocList.Flink;
while (pNextEntry != &MultiUserGreEngAllocList)
{
//
// Resource starts after the ENGTRACKHDR.
//
PVOID pvVictim = (PVOID) (((ENGTRACKHDR *) pNextEntry) + 1);
//
// Invoke the appropriate deletion function based on type.
//
switch (((ENGTRACKHDR *) pNextEntry)->ulType)
{
case ENGTRACK_ALLOCMEM:
EngFreeMem(pvVictim);
break;
case ENGTRACK_SEMAPHORE:
case ENGTRACK_DRIVER_SEMAPHORE:
GreDeleteSemaphore((HSEMAPHORE)pvVictim);
break;
case ENGTRACK_VERIFIERALLOCMEM:
VerifierEngFreeMem(pvVictim);
break;
default:
#if DBG
DbgPrint("MultiUserGreCleanupEngResources: "
"unrecognized type 0x%08lx\n",
((ENGTRACKHDR *) pNextEntry)->ulType);
RIP("MultiUserGreCleanupEngResources: possible leak detected\n");
#endif
break;
}
//
// Restart at the begining of the list since our
// entry got deleted.
//
pNextEntry = MultiUserGreEngAllocList.Flink;
}
}
//
// Now delete all objects on the GreEngLoadModuleAllocList.
//
if(GreEngLoadModuleAllocListLock)
{
while (GreEngLoadModuleAllocList.Flink != &GreEngLoadModuleAllocList)
{
//
// Free the module after setting the reference count to 1 (to eliminate
// looping cRef times).
//
((PENGLOADMODULEHDR)(GreEngLoadModuleAllocList.Flink))->cRef = 1;
EngFreeModule ((HANDLE) (((PENGLOADMODULEHDR)(GreEngLoadModuleAllocList.Flink)) + 1));
}
}
//
// Delete the list locks.
//
GreDeleteSemaphoreNonTracked(MultiUserEngAllocListLock);
MultiUserEngAllocListLock = NULL;
GreDeleteSemaphoreNonTracked(GreEngLoadModuleAllocListLock);
GreEngLoadModuleAllocListLock = NULL;
}
/*****************************Exported*Routine*****************************\
* MultiUserGreHmgOwnAll
*
* Set owner of all objects in handle manager to specified process. Used
* for multi-user (Hydra) shutdown of GRE.
*
* WARNING:
*
* Caller beware! This is very evil code. It ignores the current owner
* and the lock counts. Acceptable for shutdown code, but definitely
* unsafe for any other purpose.
*
* History:
* 03-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreHmgOwnAll(
W32PID pid)
{
PENTRYOBJ pentTmp;
UINT uiIndex = 1; // 1 is the first valid index
UINT cObj = 0;
//
// Don't bother with locks. We're shutting down, so nobody else
// is here!
//
// MLOCKFAST mo;
//
// Scan through the entire handle manager table and set owner for
// all valid objects.
//
if(gpentHmgr==NULL) {
WARNING("MultiUserGreHmgOwnAll: gpentHmgr is NULL\n");
return;
}
for (uiIndex = 1; uiIndex < gcMaxHmgr; uiIndex++)
{
pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
if ((pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))
{
//
// Since this is shutdown, don't bother with lock counts and
// such.
//
SET_OBJECTOWNER_PID(pentTmp->ObjectOwner, pid);
cObj++;
}
}
//
// Reset handle quota count to number objects now owned
// (not really that important for shutdown, but it supresses
// many warnings).
//
PW32PROCESS pw32Current = W32GetCurrentProcess();
if (pw32Current)
{
pw32Current->GDIHandleCount = cObj;
}
}
/******************************Public*Routine******************************\
* MultiUserGreCleanupHmgRemoveAllLocks
*
* For all objects of the specified type, all locks are removed and the
* object is marked as deletable. If the DEF_TYPE is specified, all valid
* objects are modified.
*
* WARNING:
*
* Caller beware! This is very evil code. It ignores the current owner
* and the lock counts. Acceptable for shutdown code, but definitely
* unsafe for any other purpose.
*
* History:
* 07-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreCleanupHmgRemoveAllLocks(OBJTYPE type)
{
PENTRYOBJ pentTmp;
UINT uiIndex = 1; // 1 is the first valid index
//
// Don't bother with locks. We're shutting down, so nobody else
// is here!
//
// MLOCKFAST mo;
//
// Scan through the entire handle manager table zap the share count
// and lock flag for all objects that belong to specified W32PID.
//
for (uiIndex = 1; uiIndex < gcMaxHmgr; uiIndex++)
{
pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
if (
((type != DEF_TYPE) && (type == pentTmp->Objt)) ||
((type == DEF_TYPE) &&
(pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))
)
{
ASSERTGDI((OBJECTOWNER_PID(pentTmp->ObjectOwner) == W32GetCurrentPID()),
"MultiUserGreCleanupHmgRemoveAllLocks: "
"found unowned object still in hmgr table\n");
pentTmp->ObjectOwner.Share.Lock = 0;
pentTmp->einfo.pobj->ulShareCount = 0;
pentTmp->Flags &= ~HMGR_ENTRY_UNDELETABLE;
}
}
}
/******************************Public*Routine******************************\
* MultiUserGreCleanupHmgOwnRemoveAllLocks
*
* For all objects of the specified type owned by current process,all locks
* are removed and the object is marked as deletable. If the DEF_TYPE is
* specified, all valid objects are modified.
*
* WARNING:
*
* Caller beware! This is very evil code. It ignores the current owner
* and the lock counts. Acceptable for shutdown code, but definitely
* unsafe for any other purpose.
*
* History:
* 01-Aug-2001 -by- Pravin Santiago [pravins]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreCleanupHmgOwnRemoveAllLocks(OBJTYPE type)
{
PENTRYOBJ pentTmp;
UINT uiIndex = 1; // 1 is the first valid index
//
// Got to take the Handle manager lock
//
MLOCKFAST mo;
//
// Scan through the entire handle manager table zap the share count
// and lock flag for all objects that belong to specified W32PID.
//
for (uiIndex = 1; uiIndex < gcMaxHmgr; uiIndex++)
{
pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
if (
(((type != DEF_TYPE) && (type == pentTmp->Objt)) ||
((type == DEF_TYPE) &&
(pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))) &&
((OBJECTOWNER_PID(pentTmp->ObjectOwner) == W32GetCurrentPID()))
)
{
pentTmp->ObjectOwner.Share.Lock = 0;
pentTmp->einfo.pobj->ulShareCount = 0;
pentTmp->Flags &= ~HMGR_ENTRY_UNDELETABLE;
}
}
}
/******************************Public*Routine******************************\
* bCleanupFontHash
* bCleanupFontTable
*
* For MultiUserNtGreCleanup (Hydra) cleanup.
*
* Worker functions for MultiUserGreCleanupAllFonts.
*
* Returns:
* TRUE if successful, FALSE otherwise.
*
* History:
* 06-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL bCleanupFontHash(FONTHASH **ppfh)
{
BOOL bResult = FALSE;
FHOBJ fho(ppfh);
if (fho.bValid())
{
fho.vFree();
bResult = TRUE;
}
return bResult;
}
BOOL bCleanupFontTable(PFT **pppft)
{
BOOL bResult = FALSE;
PFT *ppft = *pppft;
PUBLIC_PFTOBJ pfto(ppft);
if (pfto.bValid())
{
//
// Unload any fonts still in the table.
//
bResult = pfto.bUnloadAllButPermanentFonts(TRUE);
//
// Remove the font hash tables if they exist (for device fonts, the
// font hash tables exist off the PFF rather than the PFT).
//
if (ppft->pfhFace)
{
bResult &= bCleanupFontHash(&ppft->pfhFace);
}
if (ppft->pfhFamily)
{
bResult &= bCleanupFontHash(&ppft->pfhFamily);
}
if (ppft->pfhUFI)
{
bResult &= bCleanupFontHash(&ppft->pfhUFI);
}
//
// Finally, delete the font table.
//
bResult &= pfto.bDelete();
*pppft = NULL;
}
return bResult;
}
/******************************Public*Routine******************************\
* MultiUserGreCleanupAllFonts
*
* For MultiUserNtGreCleanup (Hydra) cleanup.
*
* Delete the font tables and hash tables.
*
* History:
* 06-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID MultiUserGreCleanupAllFonts()
{
BOOL bResult;
//
// Note: since this should only be called during win32k shutdown,
// don't bother with grabbing the semaphore.
//
//GreAcquireSemaphore(ghsemPublicPFT);
{
// Hydra
// Saw the case where gpPFTPublic was not initialized on Hydra system
//ASSERTGDI(gpPFTPublic, "MultiUserGreCleanupAllFonts: invalid gpPFTPublic\n");
//ASSERTGDI(gpPFTPublic, "MultiUserGreCleanupAllFonts: invalid gpPFTDevice\n");
//
// Handle private table. Note that private table can be lazily
// created, so we have to check gpPFTPrivate.
//
if (gpPFTPrivate)
{
//
// Delete the private font table.
//
bResult = bCleanupFontTable(&gpPFTPrivate);
}
// Hydra
// Saw the case where gpPFTPublic was not initialized
if (gpPFTPublic)
{
//
// Delete the public font table.
//
bResult = bCleanupFontTable(&gpPFTPublic);
}
// Hydra
// saw the case where gpPFTDevice was not intialized on Hydra system
if (gpPFTDevice)
{
//
// Delete the device font table.
//
bResult = bCleanupFontTable(&gpPFTDevice);
}
// Clean up the gpPrintKViewList
if (gpPrintKViewList)
{
vCleanupPrintKViewList();
}
}
// Clean up FD_GLYPHSET for VTFD and BMFD.
// Here is the cheapest way to do some garbage collection.
GreAcquireSemaphore(ghsemVTFD);
if (gpcpVTFD)
{
CP_GLYPHSET *pcpNext, *pcpCurrent;
pcpCurrent = gpcpVTFD;
while(pcpCurrent)
{
pcpNext = pcpCurrent->pcpNext;
VFREEMEM(pcpCurrent);
pcpCurrent = pcpNext;
}
gpcpVTFD = NULL;
}
GreReleaseSemaphore(ghsemVTFD);
GreAcquireSemaphore(ghsemBMFD);
if (gpcpGlyphsets)
{
CP_GLYPHSET *pcpNext, *pcpCurrent;
pcpCurrent = gpcpGlyphsets;
while(pcpCurrent)
{
pcpNext = pcpCurrent->pcpNext;
VFREEMEM(pcpCurrent);
pcpCurrent = pcpNext;
}
gpcpGlyphsets = NULL;
}
GreReleaseSemaphore(ghsemBMFD);
//GreReleaseSemaphore(ghsemPublicPFT);
}
/******************************Public*Routine******************************\
* MultiUserGreCleanupDrivers
*
* Cleanup the ppdev and lpdev driver lists.
*
* History:
* 07-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreCleanupDrivers()
{
//
// Note: since this should only be called during win32k shutdown,
// don't bother with grabbing the semaphore.
//
//GreAcquireSemaphore(ghsemDriverMgmt);
//
// Remove all PDEVs from the global list.
//
volatile PDEV *ppdevCur;
while (ppdevCur = gppdevList)
{
//
// Force reference count to 1, so PDEV will be deleted.
//
ppdevCur->cPdevRefs = 1;
ppdevCur->cPdevOpenRefs = 1;
//
// Unload the pdev (PDEVOBJ::vUnreferencePdev will update gppdevList).
//
PDEVOBJ pdo((HDEV) ppdevCur);
ASSERTGDI(pdo.bValid(), "MultiUserGreCleanupDrivers: invalid pdev\n");
pdo.vUnreferencePdev(CLEANUP_SESSION);
}
//
// Cleanup direct draw driver before force unload.
//
DxDdCleanupDxGraphics();
//
// Remove all LDEVs from the global list.
//
volatile PLDEV pldevCur;
while (pldevCur = gpldevDrivers)
{
//
// Force reference count to 1, so LDEV will be deleted.
//
pldevCur->cldevRefs = 1;
ldevUnloadImage(pldevCur);
}
//GreReleaseSemaphore(ghsemDriverMgmt);
}
/******************************Public*Routine******************************\
* MultiUserGreDeleteXLATE
*
* For MultiUserNtGreCleanup (Hydra) cleanup.
*
* Delete the XLATE cache.
*
* History:
* 09-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreDeleteXLATE()
{
ULONG ulEntry;
for (ulEntry = 0; ulEntry < XLATE_CACHE_SIZE; ulEntry++)
{
if (xlateTable[ulEntry].pxlate)
VFREEMEM(xlateTable[ulEntry].pxlate);
}
}
VOID
GreFreeSemaphoresForCurrentThread(
VOID
)
{
//
// Walk the list of tracked semaphores, and release any held by this
// thread.
//
if (MultiUserEngAllocListLock) {
GreAcquireSemaphore(MultiUserEngAllocListLock);
PENGTRACKHDR EngTrackHdr;
EngTrackHdr = (PENGTRACKHDR) MultiUserGreEngAllocList.Flink;
while (EngTrackHdr->list.Flink != &MultiUserGreEngAllocList) {
if (EngTrackHdr->ulType == ENGTRACK_DRIVER_SEMAPHORE) {
HSEMAPHORE hsem = (HSEMAPHORE)(EngTrackHdr + 1);
if (GreIsSemaphoreOwnedByCurrentThread(hsem)) {
//
// The current thread was holding a semaphore. Release
// it using the same technique the driver would have used.
//
EngReleaseSemaphore(hsem);
}
}
EngTrackHdr = (PENGTRACKHDR)EngTrackHdr->list.Flink;
}
GreReleaseSemaphore(MultiUserEngAllocListLock);
}
}
#if DBG
/******************************Public*Routine******************************\
* MultiUserGreHmgDbgScan
*
* Dumps the current handle manager contents.
*
* History:
* 07-Feb-1998 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
VOID
MultiUserGreHmgDbgScan(BOOL bDumpTable, BOOL bCheckEmpty)
{
PENTRYOBJ pentTmp;
UINT uiIndex = 1; // 1 is the first valid index
UINT cObj = 0;
BOOL bTitle = FALSE;
ASSERTGDI((gpentHmgr != NULL),
"gpentHmgr MUST be != NULL");
for (uiIndex = 1; uiIndex < gcMaxHmgr; uiIndex++)
{
pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
if ((pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))
{
cObj++;
}
}
if (bCheckEmpty && cObj)
{
DbgPrint("\n"
"*****************************************\n");
DbgPrint(" MultiUserGreHmgDbgScan\n\n");
DbgPrint(" TERMSRV session id = 0x%08lx\n", gSessionId);
DbgPrint(" Cleanup process pid = 0x%08lx\n", W32GetCurrentPID());
DbgPrint("\n"
"*****************************************\n");
}
//
// Scan through the entire handle manager table and set owner for
// all valid objects.
//
for (uiIndex = 1; uiIndex < gcMaxHmgr && (bDumpTable && cObj != 0); uiIndex++)
{
pentTmp = (PENTRYOBJ) &gpentHmgr[uiIndex];
if ((pentTmp->Objt > DEF_TYPE) && (pentTmp->Objt <= MAX_TYPE))
{
//
// Since this is shutdown, don't bother with lock counts and
// such.
//
if (!bTitle)
{
DbgPrint("------------------\t------ ------ ----\n");
DbgPrint( "%s\tpid count lock\n", gpszHmgrType[0]);
DbgPrint("------------------\t------ ------ ----\n");
bTitle = TRUE;
}
DbgPrint("%s\t0x%04x 0x%04x %ld\n",
gpszHmgrType[pentTmp->Objt],
OBJECTOWNER_PID(pentTmp->ObjectOwner),
pentTmp->einfo.pobj->ulShareCount,
pentTmp->ObjectOwner.Share.Lock
);
}
}
if (bTitle )
{
DbgPrint("------------------\t------ ------ ----\n");
}
if (bCheckEmpty && (cObj != 0))
{
DbgPrint("MultiUserGreHmgDbgScan: %ld objects in hmgr table\n", cObj);
RIP("MultiUserGreHmgDbgScan: object leak detected\n");
}
}
/*****************************************************************************
*
* DebugGreTrackAddMapView
*
* Track GRE's Map View's for cleanup purposes
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
VOID
DebugGreTrackAddMapView(
PVOID ViewBase
)
{
PLIST_ENTRY Entry;
PVOID Atom;
if(DebugGreMapViewListLock) GreAcquireSemaphore(DebugGreMapViewListLock);
Atom = (PVOID) PALLOCNOZ(sizeof(PVOID)+sizeof(LIST_ENTRY), 'mesG');
if (Atom)
{
*(PVOID *)Atom = ViewBase;
Entry = (PLIST_ENTRY)(((PCHAR)Atom) + sizeof(PVOID));
InsertTailList(&DebugGreMapViewList, Entry);
}
if(DebugGreMapViewListLock) GreReleaseSemaphore(DebugGreMapViewListLock);
return;
}
/*****************************************************************************
*
* DebugGreTrackRemoveMapView
*
* Remove the GRE Map View from the list
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
VOID
DebugGreTrackRemoveMapView(
PVOID ViewBase
)
{
#if !defined(_GDIPLUS_)
PLIST_ENTRY NextEntry;
PVOID Atom;
if(DebugGreMapViewListLock) GreAcquireSemaphore(DebugGreMapViewListLock);
NextEntry = DebugGreMapViewList.Flink;
while (NextEntry != &DebugGreMapViewList)
{
Atom = (PVOID)(((PCHAR)NextEntry) - sizeof(PVOID));
if (ViewBase == *(PVOID *)Atom)
{
RemoveEntryList(NextEntry);
VFREEMEM(Atom);
break;
}
NextEntry = NextEntry->Flink;
}
if(DebugGreMapViewListLock) GreReleaseSemaphore(DebugGreMapViewListLock);
return;
#endif // !_GDIPLUS_
}
/*****************************************************************************
*
* DebugGreCleanupMapView
*
* Cleanup the tracked Map View's
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
VOID
DebugGreCleanupMapView()
{
volatile PLIST_ENTRY NextEntry;
PVOID ViewBase;
PVOID Atom;
if(DebugGreMapViewListLock)
{
if (!IsListEmpty(&DebugGreMapViewList))
{
DbgPrint("DebugGreCleanupMapView: DebugGreMapViewList 0x%08lx not empty\n", &DebugGreMapViewList);
RIP("DebugGreCleanupMapView: leak detected\n");
}
//
// Cleanup every mapped view tracked in the list.
//
NextEntry = DebugGreMapViewList.Flink;
while (NextEntry != &DebugGreMapViewList)
{
// We can not use CONTAINING_RECORD since we are
// not within a single C structure.
RemoveEntryList(NextEntry);
Atom = (PVOID)(((PCHAR)NextEntry) - sizeof(PVOID));
ViewBase = *(PVOID *)Atom;
DbgPrint("DebugGreCleanupMapView: cleanup Map View %x\n", ViewBase);
MmUnmapViewInSessionSpace(ViewBase);
GdiFreePool(Atom);
// Restart at the begining of the list since our
// entry got deleted
NextEntry = DebugGreMapViewList.Flink;
}
}
//
// Free the list semaphore.
//
GreDeleteSemaphoreNonTracked(DebugGreMapViewListLock);
DebugGreMapViewListLock = NULL;
return;
}
#endif
/******************************Public*Routine******************************\
* GdiMultiUserFontCleanup
*
* Deletes all the fonts from the system font tables.
*
* This is only called by user when CSRSS goes away on a Hydra terminal.
*
*
* History:
* 29-Sept-1998 -by- Xudong Wu [tessiew]
* Wrote it.
\**************************************************************************/
VOID
GdiMultiUserFontCleanup()
{
if(!gpPFTPublic)
return;
#ifdef FE_SB
CleanUpEUDC();
#endif
//
// Cleanup the rest of the font stuff (font tables, font hash tables,
// font files, font substitution table, font mapper).
//
MultiUserGreCleanupAllFonts();
vCleanUpFntCache();
}