|
|
/******************************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();
}
|