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

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. cachegpc.c
  5. Abstract:
  6. This module contains functions to cached the PLOTGPC
  7. Author:
  8. 15-Dec-1993 Wed 20:29:07 created
  9. [Environment:]
  10. GDI Device Driver - Plotter.
  11. [Notes:]
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #define DBG_PLOTFILENAME DbgCacheGPC
  17. #define DBG_CACHE_DATA 0x00000001
  18. #define DBG_CS 0x00000002
  19. #define DBG_FORCE_UPDATE 0x80000000
  20. DEFINE_DBGVAR(0);
  21. //
  22. // Local structrue and definitions only used in this module
  23. //
  24. typedef struct _CACHEDPLOTGPC {
  25. struct _CACHEDPLOTGPC *pNext;
  26. DWORD cRef;
  27. PPLOTGPC pPlotGPC;
  28. WCHAR wszFile[1];
  29. } CACHEDPLOTGPC, *PCACHEDPLOTGPC;
  30. #define MAX_CACHED_PLOTGPC 16
  31. DWORD cCachedGPC = 0;
  32. PCACHEDPLOTGPC pCHead = NULL;
  33. #if defined(UMODE) || defined(USERMODE_DRIVER)
  34. CRITICAL_SECTION CachedGPCDataCS;
  35. #define ACQUIREGPCSEM() EnterCriticalSection(&CachedGPCDataCS)
  36. #define RELEASEGPCSEM() LeaveCriticalSection(&CachedGPCDataCS)
  37. #define CREATEGPCSEM() InitializeCriticalSection(&CachedGPCDataCS)
  38. #define DELETEGPCSEM() DeleteCriticalSection(&CachedGPCDataCS)
  39. #else
  40. HSEMAPHORE hsemGPC = NULL;
  41. #define ACQUIREGPCSEM() EngAcquireSemaphore(hsemGPC)
  42. #define RELEASEGPCSEM() EngReleaseSemaphore(hsemGPC)
  43. #define CREATEGPCSEM() hsemGPC = EngCreateSemaphore()
  44. #define DELETEGPCSEM() EngDeleteSemaphore(hsemGPC)
  45. #endif
  46. BOOL
  47. InitCachedData(
  48. VOID
  49. )
  50. /*++
  51. Routine Description:
  52. This function initialized the GPC data cache
  53. Arguments:
  54. NONE
  55. Return Value:
  56. VOID
  57. Author:
  58. 12-May-1994 Thu 11:50:04 created
  59. Revision History:
  60. --*/
  61. {
  62. PLOTDBG(DBG_CS, ("InitCachedData: InitCriticalSection, Count=%ld, pCHead=%08lx",
  63. cCachedGPC, pCHead));
  64. cCachedGPC = 0;
  65. pCHead = NULL;
  66. try {
  67. CREATEGPCSEM();
  68. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  69. //
  70. // Critical section failed to get initialized.
  71. //
  72. return FALSE;
  73. }
  74. return TRUE;
  75. }
  76. VOID
  77. DestroyCachedData(
  78. VOID
  79. )
  80. /*++
  81. Routine Description:
  82. This function destroy all the cached information for PPRINTERINFO
  83. Arguments:
  84. VOID
  85. Return Value:
  86. VOID
  87. Author:
  88. 15-Dec-1993 Wed 20:30:16 38:27 created
  89. Revision History:
  90. --*/
  91. {
  92. try {
  93. PCACHEDPLOTGPC pTemp;
  94. PLOTDBG(DBG_CS, ("DestroyCachedData: EnterCriticalSection, TOT=%ld",
  95. cCachedGPC));
  96. ACQUIREGPCSEM();
  97. while (pCHead) {
  98. PLOTDBG(DBG_CACHE_DATA, ("!!!DESTROY cached pPlotGPC=[%p] %s",
  99. (DWORD_PTR)pCHead->pPlotGPC, pCHead->wszFile));
  100. PLOTASSERT(1, "DestroyCachedData: cCachedGPC <= 0, pCHead=%08lx",
  101. cCachedGPC > 0, pCHead);
  102. pTemp = pCHead;
  103. pCHead = pCHead->pNext;
  104. --cCachedGPC;
  105. LocalFree((HLOCAL)pTemp->pPlotGPC);
  106. LocalFree((HLOCAL)pTemp);
  107. }
  108. } finally {
  109. PLOTDBG(DBG_CS, ("DestroyCachedData: LeaveCriticalSection"));
  110. RELEASEGPCSEM();
  111. PLOTDBG(DBG_CS, ("DestroyCachedData: DeleteCriticalSection"));
  112. DELETEGPCSEM();
  113. }
  114. }
  115. BOOL
  116. UnGetCachedPlotGPC(
  117. PPLOTGPC pPlotGPC
  118. )
  119. /*++
  120. Routine Description:
  121. This function un-reference a used cached GPC object
  122. Arguments:
  123. pPlotGPC - Pointer to the cached GPC returned from GetCachedPlotGPC
  124. Return Value:
  125. BOOL
  126. Author:
  127. 10-May-1994 Tue 16:27:15 created
  128. Revision History:
  129. --*/
  130. {
  131. BOOL Ok = FALSE;
  132. try {
  133. PCACHEDPLOTGPC pCur;
  134. PLOTDBG(DBG_CS, ("UnGetCachedPlotGPC: EnterCriticalSection"));
  135. ACQUIREGPCSEM();
  136. pCur = pCHead;
  137. while (pCur) {
  138. if (pCur->pPlotGPC == pPlotGPC) {
  139. //
  140. // Found it, move that to the front and return pPlotGPC
  141. //
  142. PLOTDBG(DBG_CACHE_DATA, ("UnGetCachedPlotGPC: TOT=%ld, Found Cached pPlotGPC=%08lx, cRef=%ld->%ld, <%s>",
  143. cCachedGPC, pCur->pPlotGPC, pCur->cRef,
  144. pCur->cRef - 1, pCur->wszFile));
  145. if (pCur->cRef) {
  146. --(pCur->cRef);
  147. } else {
  148. PLOTWARN(("UnGetCachedPlotGPC(): Ref Count == 0 already???"));
  149. }
  150. Ok = TRUE;
  151. //
  152. // Exit Now
  153. //
  154. break;
  155. }
  156. pCur = pCur->pNext;
  157. }
  158. if (!Ok) {
  159. PLOTERR(("UnGetCachedPlotGPC(): pPlotGPC=%08lx not found!", pPlotGPC));
  160. }
  161. } finally {
  162. PLOTDBG(DBG_CS, ("UnGetCachedPlotGPC: LeaveCriticalSection"));
  163. RELEASEGPCSEM();
  164. }
  165. return(Ok);
  166. }
  167. PPLOTGPC
  168. GetCachedPlotGPC(
  169. LPWSTR pwDataFile
  170. )
  171. /*++
  172. Routine Description:
  173. This function return cached PlotGPC pointer, if not cached then it will
  174. add it to the cached, if cached data is full it will delete least used one
  175. first.
  176. Arguments:
  177. pwDataFile - Pointe to the data file
  178. Return Value:
  179. pPlotGPC, NULL if failed
  180. Author:
  181. 15-Dec-1993 Wed 20:30:25 created
  182. Revision History:
  183. --*/
  184. {
  185. PPLOTGPC pPlotGPC = NULL;
  186. try {
  187. PCACHEDPLOTGPC pCur;
  188. PCACHEDPLOTGPC pPrev;
  189. UINT Idx;
  190. PLOTDBG(DBG_CS, ("GetCachedPlotGPC: EnterCriticalSection"));
  191. ACQUIREGPCSEM();
  192. pCur = pCHead;
  193. pPrev = NULL;
  194. //
  195. // Traverse through the linked list, and exit when at end, remember if
  196. // we have more than 2 in the cached then we want to preserved last
  197. // pPrev, so we know the pPrev of the last one, (because we need to
  198. // delete last one)
  199. //
  200. while (pCur) {
  201. if (!_wcsicmp(pCur->wszFile, pwDataFile)) {
  202. //
  203. // Found it, move that to the front and return pPlotGPC
  204. //
  205. if (pPrev) {
  206. pPrev->pNext = pCur->pNext;
  207. pCur->pNext = pCHead;
  208. pCHead = pCur;
  209. }
  210. PLOTDBG(DBG_CACHE_DATA,
  211. ("GetCachedPlotGPC: TOT=%ld, FOUND [%08lx], cRef=%ld->%ld, <%s>",
  212. cCachedGPC, pCur->pPlotGPC, pCur->cRef,
  213. pCur->cRef + 1, pCur->wszFile));
  214. #if DBG
  215. if (DBG_PLOTFILENAME & DBG_FORCE_UPDATE) {
  216. LocalFree((HLOCAL)(pCur->pPlotGPC));
  217. pCur->pPlotGPC =
  218. pPlotGPC = ReadPlotGPCFromFile(pwDataFile);
  219. PLOTDBG(DBG_FORCE_UPDATE,
  220. ("GetCachedPlotGPC: ForceUpdate: pPlotGPC=%08lx: %s",
  221. pPlotGPC, pCur->wszFile));
  222. }
  223. #endif
  224. ++(pCur->cRef);
  225. pPlotGPC = pCur->pPlotGPC;
  226. break;
  227. }
  228. pPrev = pCur;
  229. pCur = pCur->pNext;
  230. }
  231. //
  232. // If we have too many entries in the cache then delete them to fit
  233. // into the MAX_CACHED_PLOTGPC, delete the oldest one first
  234. //
  235. if (cCachedGPC > MAX_CACHED_PLOTGPC) {
  236. PCACHEDPLOTGPC pFree[MAX_CACHED_PLOTGPC];
  237. pPrev = NULL;
  238. pCur = pCHead;
  239. Idx = 0;
  240. while ((pCur) && (Idx < MAX_CACHED_PLOTGPC)) {
  241. if (pCur->cRef == 0) {
  242. pFree[Idx++] = pPrev;
  243. }
  244. pPrev = pCur;
  245. pCur = pCur->pNext;
  246. }
  247. while ((cCachedGPC > MAX_CACHED_PLOTGPC) && (Idx--)) {
  248. if (pPrev = pFree[Idx]) {
  249. pCur = pPrev->pNext;
  250. pPrev->pNext = pPrev->pNext->pNext;
  251. } else {
  252. pCur = pCHead;
  253. pCHead = pCHead->pNext;
  254. }
  255. PLOTDBG(DBG_CACHE_DATA,
  256. ("Cached Full=%ld, DELETE: 1pCur=%08lx, pPlotGPC=%08lx <%s>",
  257. cCachedGPC, pCur, pCur->pPlotGPC, pCur->wszFile));
  258. --cCachedGPC;
  259. LocalFree((HLOCAL)pCur->pPlotGPC);
  260. LocalFree((HLOCAL)pCur);
  261. }
  262. }
  263. if (!pPlotGPC) {
  264. PLOTDBG(DBG_CACHE_DATA,("GPC cached NOT FOUND for %s", pwDataFile));
  265. //
  266. // Read the New pPlotGPC, and add that to the linked list, make
  267. // it as most recent used (at the Head)
  268. //
  269. if (pPlotGPC = ReadPlotGPCFromFile(pwDataFile)) {
  270. SIZE_T cchDataFile;
  271. cchDataFile = wcslen(pwDataFile) + 1;
  272. Idx = (UINT)((cchDataFile * sizeof(WCHAR)) +
  273. sizeof(CACHEDPLOTGPC));
  274. if (pCur = (PCACHEDPLOTGPC)LocalAlloc(LMEM_FIXED, Idx)) {
  275. //
  276. // Setting all the fields to the new NODE, and make this
  277. // node as the head of the linked list
  278. //
  279. if (SUCCEEDED(StringCchCopyW(pCur->wszFile, cchDataFile, pwDataFile)))
  280. {
  281. pCur->pNext = pCHead;
  282. pCur->cRef = 1;
  283. pCur->pPlotGPC = pPlotGPC;
  284. pCHead = pCur;
  285. //
  286. // Said we have one more in the cache
  287. //
  288. ++cCachedGPC;
  289. PLOTDBG(DBG_CACHE_DATA,
  290. ("GetCachedPlotGPC: TOT=%ld, cRef=0->1, ADD CACHED pPlotGPC=%08lx <%s>",
  291. cCachedGPC, pCur->pPlotGPC, pCur->wszFile));
  292. }
  293. else
  294. {
  295. PLOTERR(("GetCachedPlotGPC: StringCchCopyW failed"));
  296. LocalFree((HLOCAL)pCur);
  297. pCur = NULL;
  298. LocalFree((HLOCAL)pPlotGPC);
  299. pPlotGPC = NULL;
  300. }
  301. } else {
  302. PLOTERR(("GetCachedPlotGPC: LocalAlloc(%ld)) failed", Idx));
  303. LocalFree((HLOCAL)pPlotGPC);
  304. pPlotGPC = NULL;
  305. }
  306. } else {
  307. PLOTERR(("GetCachedPlotGPC: ReadPlotGPCFormFile(%s) failed",
  308. pwDataFile));
  309. }
  310. }
  311. } finally {
  312. PLOTDBG(DBG_CS, ("GetCachedPlotGPC: LeaveCriticalSection"));
  313. RELEASEGPCSEM();
  314. }
  315. return(pPlotGPC);
  316. }
  317. #ifdef UMODE
  318. PPLOTGPC
  319. hPrinterToPlotGPC(
  320. HANDLE hPrinter,
  321. LPWSTR pwDeviceName,
  322. size_t cchDeviceName
  323. )
  324. /*++
  325. Routine Description:
  326. This function return cached PlotGPC pointer and it also return the device
  327. name
  328. Arguments:
  329. hPrinter - Handle to the printer interested
  330. pwDataFile - Pointe to the data file
  331. pwDeviceName - Pointer to the dmDeviceName where the name will be
  332. stored if this pointer is not NULL
  333. Return Value:
  334. pPlotGPC, NULL if failed
  335. Author:
  336. 15-Dec-1993 Wed 20:30:25 created
  337. Revision History:
  338. --*/
  339. {
  340. DRIVER_INFO_2 *pDI2;
  341. PPLOTGPC pPlotGPC;
  342. if (!(pDI2 = (DRIVER_INFO_2 *)GetDriverInfo(hPrinter, 2))) {
  343. PLOTERR(("GetCachedPlotGPC: GetDriverInfo(DRIVER_INFO_2) failed"));
  344. return(NULL);
  345. }
  346. if (pwDeviceName) {
  347. size_t cchSize;
  348. if (cchDeviceName < CCHDEVICENAME)
  349. {
  350. cchSize = cchDeviceName;
  351. }
  352. else
  353. {
  354. cchSize = CCHDEVICENAME;
  355. }
  356. _WCPYSTR(pwDeviceName, pDI2->pName, cchSize);
  357. }
  358. pPlotGPC = GetCachedPlotGPC(pDI2->pDataFile);
  359. LocalFree((HLOCAL)pDI2);
  360. return(pPlotGPC);
  361. }
  362. #endif