Sample Code
Windows Driver Samples/ MSPLOT Plotter Driver Sample/ C++/ lib/ cachegpc.c/
/*++ 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( LPCWSTR 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 _Success_(return != NULL) PPLOTGPC hPrinterToPlotGPC( HANDLE hPrinter, _Out_writes_opt_(cchDeviceName) 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 pwDeviceName - Pointer to the dmDeviceName where the name will be stored if this pointer is not NULL cchDeviceName - Number of characters possible in pwDeviceName (incl 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 destination buffer size is bigger than CCHDEVICENAME // then fill only CCHDEVICENAME characters, if not fill full buffer. if (cchDeviceName < CCHDEVICENAME) { cchSize = cchDeviceName; } else { cchSize = CCHDEVICENAME; } _WCPYSTR_FILL_TRAIL_WITH_NULL(pwDeviceName, cchSize, pDI2->pName); } pPlotGPC = GetCachedPlotGPC(pDI2->pDataFile); LocalFree((HLOCAL)pDI2); return(pPlotGPC); } #endif
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials