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