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.
 
 
 
 
 
 

619 lines
12 KiB

/*++
Copyright (c) 1990-2003 Microsoft Corporation
Module Name:
cachegpc.c
Abstract:
This module contains functions to cached the PLOTGPC
Author:
15-Dec-1993 Wed 20:29:07 created
[Environment:]
GDI Device Driver - Plotter.
[Notes:]
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define DBG_PLOTFILENAME DbgCacheGPC
#define DBG_CACHE_DATA 0x00000001
#define DBG_CS 0x00000002
#define DBG_FORCE_UPDATE 0x80000000
DEFINE_DBGVAR(0);
//
// Local structrue and definitions only used in this module
//
typedef struct _CACHEDPLOTGPC {
struct _CACHEDPLOTGPC *pNext;
DWORD cRef;
PPLOTGPC pPlotGPC;
WCHAR wszFile[1];
} CACHEDPLOTGPC, *PCACHEDPLOTGPC;
#define MAX_CACHED_PLOTGPC 16
DWORD cCachedGPC = 0;
PCACHEDPLOTGPC pCHead = NULL;
#if defined(UMODE) || defined(USERMODE_DRIVER)
CRITICAL_SECTION CachedGPCDataCS;
#define ACQUIREGPCSEM() EnterCriticalSection(&CachedGPCDataCS)
#define RELEASEGPCSEM() LeaveCriticalSection(&CachedGPCDataCS)
#define CREATEGPCSEM() InitializeCriticalSection(&CachedGPCDataCS)
#define DELETEGPCSEM() DeleteCriticalSection(&CachedGPCDataCS)
#else
HSEMAPHORE hsemGPC = NULL;
#define ACQUIREGPCSEM() EngAcquireSemaphore(hsemGPC)
#define RELEASEGPCSEM() EngReleaseSemaphore(hsemGPC)
#define CREATEGPCSEM() hsemGPC = EngCreateSemaphore()
#define DELETEGPCSEM() EngDeleteSemaphore(hsemGPC)
#endif
BOOL
InitCachedData(
VOID
)
/*++
Routine Description:
This function initialized the GPC data cache
Arguments:
NONE
Return Value:
VOID
Author:
12-May-1994 Thu 11:50:04 created
Revision History:
--*/
{
PLOTDBG(DBG_CS, ("InitCachedData: InitCriticalSection, Count=%ld, pCHead=%08lx",
cCachedGPC, pCHead));
cCachedGPC = 0;
pCHead = NULL;
try {
CREATEGPCSEM();
} except ( EXCEPTION_EXECUTE_HANDLER ) {
//
// Critical section failed to get initialized.
//
return FALSE;
}
return TRUE;
}
VOID
DestroyCachedData(
VOID
)
/*++
Routine Description:
This function destroy all the cached information for PPRINTERINFO
Arguments:
VOID
Return Value:
VOID
Author:
15-Dec-1993 Wed 20:30:16 38:27 created
Revision History:
--*/
{
try {
PCACHEDPLOTGPC pTemp;
PLOTDBG(DBG_CS, ("DestroyCachedData: EnterCriticalSection, TOT=%ld",
cCachedGPC));
ACQUIREGPCSEM();
while (pCHead) {
PLOTDBG(DBG_CACHE_DATA, ("!!!DESTROY cached pPlotGPC=[%p] %s",
(DWORD_PTR)pCHead->pPlotGPC, pCHead->wszFile));
PLOTASSERT(1, "DestroyCachedData: cCachedGPC <= 0, pCHead=%08lx",
cCachedGPC > 0, pCHead);
pTemp = pCHead;
pCHead = pCHead->pNext;
--cCachedGPC;
LocalFree((HLOCAL)pTemp->pPlotGPC);
LocalFree((HLOCAL)pTemp);
}
} finally {
PLOTDBG(DBG_CS, ("DestroyCachedData: LeaveCriticalSection"));
RELEASEGPCSEM();
PLOTDBG(DBG_CS, ("DestroyCachedData: DeleteCriticalSection"));
DELETEGPCSEM();
}
}
BOOL
UnGetCachedPlotGPC(
PPLOTGPC pPlotGPC
)
/*++
Routine Description:
This function un-reference a used cached GPC object
Arguments:
pPlotGPC - Pointer to the cached GPC returned from GetCachedPlotGPC
Return Value:
BOOL
Author:
10-May-1994 Tue 16:27:15 created
Revision History:
--*/
{
BOOL Ok = FALSE;
try {
PCACHEDPLOTGPC pCur;
PLOTDBG(DBG_CS, ("UnGetCachedPlotGPC: EnterCriticalSection"));
ACQUIREGPCSEM();
pCur = pCHead;
while (pCur) {
if (pCur->pPlotGPC == pPlotGPC) {
//
// Found it, move that to the front and return pPlotGPC
//
PLOTDBG(DBG_CACHE_DATA, ("UnGetCachedPlotGPC: TOT=%ld, Found Cached pPlotGPC=%08lx, cRef=%ld->%ld, <%s>",
cCachedGPC, pCur->pPlotGPC, pCur->cRef,
pCur->cRef - 1, pCur->wszFile));
if (pCur->cRef) {
--(pCur->cRef);
} else {
PLOTWARN(("UnGetCachedPlotGPC(): Ref Count == 0 already???"));
}
Ok = TRUE;
//
// Exit Now
//
break;
}
pCur = pCur->pNext;
}
if (!Ok) {
PLOTERR(("UnGetCachedPlotGPC(): pPlotGPC=%08lx not found!", pPlotGPC));
}
} finally {
PLOTDBG(DBG_CS, ("UnGetCachedPlotGPC: LeaveCriticalSection"));
RELEASEGPCSEM();
}
return(Ok);
}
PPLOTGPC
GetCachedPlotGPC(
LPWSTR pwDataFile
)
/*++
Routine Description:
This function return cached PlotGPC pointer, if not cached then it will
add it to the cached, if cached data is full it will delete least used one
first.
Arguments:
pwDataFile - Pointe to the data file
Return Value:
pPlotGPC, NULL if failed
Author:
15-Dec-1993 Wed 20:30:25 created
Revision History:
--*/
{
PPLOTGPC pPlotGPC = NULL;
try {
PCACHEDPLOTGPC pCur;
PCACHEDPLOTGPC pPrev;
UINT Idx;
PLOTDBG(DBG_CS, ("GetCachedPlotGPC: EnterCriticalSection"));
ACQUIREGPCSEM();
pCur = pCHead;
pPrev = NULL;
//
// Traverse through the linked list, and exit when at end, remember if
// we have more than 2 in the cached then we want to preserved last
// pPrev, so we know the pPrev of the last one, (because we need to
// delete last one)
//
while (pCur) {
if (!_wcsicmp(pCur->wszFile, pwDataFile)) {
//
// Found it, move that to the front and return pPlotGPC
//
if (pPrev) {
pPrev->pNext = pCur->pNext;
pCur->pNext = pCHead;
pCHead = pCur;
}
PLOTDBG(DBG_CACHE_DATA,
("GetCachedPlotGPC: TOT=%ld, FOUND [%08lx], cRef=%ld->%ld, <%s>",
cCachedGPC, pCur->pPlotGPC, pCur->cRef,
pCur->cRef + 1, pCur->wszFile));
#if DBG
if (DBG_PLOTFILENAME & DBG_FORCE_UPDATE) {
LocalFree((HLOCAL)(pCur->pPlotGPC));
pCur->pPlotGPC =
pPlotGPC = ReadPlotGPCFromFile(pwDataFile);
PLOTDBG(DBG_FORCE_UPDATE,
("GetCachedPlotGPC: ForceUpdate: pPlotGPC=%08lx: %s",
pPlotGPC, pCur->wszFile));
}
#endif
++(pCur->cRef);
pPlotGPC = pCur->pPlotGPC;
break;
}
pPrev = pCur;
pCur = pCur->pNext;
}
//
// If we have too many entries in the cache then delete them to fit
// into the MAX_CACHED_PLOTGPC, delete the oldest one first
//
if (cCachedGPC > MAX_CACHED_PLOTGPC) {
PCACHEDPLOTGPC pFree[MAX_CACHED_PLOTGPC];
pPrev = NULL;
pCur = pCHead;
Idx = 0;
while ((pCur) && (Idx < MAX_CACHED_PLOTGPC)) {
if (pCur->cRef == 0) {
pFree[Idx++] = pPrev;
}
pPrev = pCur;
pCur = pCur->pNext;
}
while ((cCachedGPC > MAX_CACHED_PLOTGPC) && (Idx--)) {
if (pPrev = pFree[Idx]) {
pCur = pPrev->pNext;
pPrev->pNext = pPrev->pNext->pNext;
} else {
pCur = pCHead;
pCHead = pCHead->pNext;
}
PLOTDBG(DBG_CACHE_DATA,
("Cached Full=%ld, DELETE: 1pCur=%08lx, pPlotGPC=%08lx <%s>",
cCachedGPC, pCur, pCur->pPlotGPC, pCur->wszFile));
--cCachedGPC;
LocalFree((HLOCAL)pCur->pPlotGPC);
LocalFree((HLOCAL)pCur);
}
}
if (!pPlotGPC) {
PLOTDBG(DBG_CACHE_DATA,("GPC cached NOT FOUND for %s", pwDataFile));
//
// Read the New pPlotGPC, and add that to the linked list, make
// it as most recent used (at the Head)
//
if (pPlotGPC = ReadPlotGPCFromFile(pwDataFile)) {
SIZE_T cchDataFile;
cchDataFile = wcslen(pwDataFile) + 1;
Idx = (UINT)((cchDataFile * sizeof(WCHAR)) +
sizeof(CACHEDPLOTGPC));
if (pCur = (PCACHEDPLOTGPC)LocalAlloc(LMEM_FIXED, Idx)) {
//
// Setting all the fields to the new NODE, and make this
// node as the head of the linked list
//
if (SUCCEEDED(StringCchCopyW(pCur->wszFile, cchDataFile, pwDataFile)))
{
pCur->pNext = pCHead;
pCur->cRef = 1;
pCur->pPlotGPC = pPlotGPC;
pCHead = pCur;
//
// Said we have one more in the cache
//
++cCachedGPC;
PLOTDBG(DBG_CACHE_DATA,
("GetCachedPlotGPC: TOT=%ld, cRef=0->1, ADD CACHED pPlotGPC=%08lx <%s>",
cCachedGPC, pCur->pPlotGPC, pCur->wszFile));
}
else
{
PLOTERR(("GetCachedPlotGPC: StringCchCopyW failed"));
LocalFree((HLOCAL)pCur);
pCur = NULL;
LocalFree((HLOCAL)pPlotGPC);
pPlotGPC = NULL;
}
} else {
PLOTERR(("GetCachedPlotGPC: LocalAlloc(%ld)) failed", Idx));
LocalFree((HLOCAL)pPlotGPC);
pPlotGPC = NULL;
}
} else {
PLOTERR(("GetCachedPlotGPC: ReadPlotGPCFormFile(%s) failed",
pwDataFile));
}
}
} finally {
PLOTDBG(DBG_CS, ("GetCachedPlotGPC: LeaveCriticalSection"));
RELEASEGPCSEM();
}
return(pPlotGPC);
}
#ifdef UMODE
PPLOTGPC
hPrinterToPlotGPC(
HANDLE hPrinter,
LPWSTR pwDeviceName,
size_t cchDeviceName
)
/*++
Routine Description:
This function return cached PlotGPC pointer and it also return the device
name
Arguments:
hPrinter - Handle to the printer interested
pwDataFile - Pointe to the data file
pwDeviceName - Pointer to the dmDeviceName where the name will be
stored if this pointer is not NULL
Return Value:
pPlotGPC, NULL if failed
Author:
15-Dec-1993 Wed 20:30:25 created
Revision History:
--*/
{
DRIVER_INFO_2 *pDI2;
PPLOTGPC pPlotGPC;
if (!(pDI2 = (DRIVER_INFO_2 *)GetDriverInfo(hPrinter, 2))) {
PLOTERR(("GetCachedPlotGPC: GetDriverInfo(DRIVER_INFO_2) failed"));
return(NULL);
}
if (pwDeviceName) {
size_t cchSize;
if (cchDeviceName < CCHDEVICENAME)
{
cchSize = cchDeviceName;
}
else
{
cchSize = CCHDEVICENAME;
}
_WCPYSTR(pwDeviceName, pDI2->pName, cchSize);
}
pPlotGPC = GetCachedPlotGPC(pDI2->pDataFile);
LocalFree((HLOCAL)pDI2);
return(pPlotGPC);
}
#endif