Source code of Windows XP (NT5)
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.

514 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. localspl.cxx
  6. Abstract:
  7. Localspl specific support routines for performance.
  8. Author:
  9. Albert Ting (AlbertT) 19-Dec-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. //
  15. // Define INDEX_FROM_PERFKEY if you want to retrieve the counter/help
  16. // offsets from the registry instead of hardcoded values in ntprfctr.h.
  17. //
  18. #include "perf.hxx"
  19. #include "lspldata.hxx"
  20. #include "splapip.h"
  21. #include "winsprlp.h"
  22. #ifndef INDEX_FROM_PERFKEY
  23. #include "ntprfctr.h"
  24. #endif
  25. /********************************************************************
  26. Globals
  27. ********************************************************************/
  28. LPCTSTR gszAppName = TEXT( "SpoolerCtrs" );
  29. #ifdef INDEX_FROM_PERFKEY
  30. LPCTSTR gszLocalsplPerformanceKey = TEXT( "SYSTEM\\CurrentControlSet\\Services\\spooler\\Performance" );
  31. #endif
  32. BOOL gbInitialized = FALSE;
  33. LPCWSTR gszTotal = L"_Total";
  34. UINT gcbBufferHint = 0x800;
  35. const UINT kBufferHintPad = 0x200;
  36. DWORD
  37. Pfp_dwBuildPrinterInstanceFromInfo(
  38. PPRINTER_INFO_STRESS pInfo,
  39. PBYTE* ppData,
  40. PDWORD pcbDataLeft,
  41. PLSPL_COUNTER_DATA *pplcd OPTIONAL
  42. );
  43. DWORD
  44. Pfp_dwBuildPrinterInstanceFromLCD(
  45. LPCWSTR pszName,
  46. PLSPL_COUNTER_DATA plcdSource,
  47. PBYTE* ppData,
  48. PDWORD pcbDataLeft
  49. );
  50. /********************************************************************
  51. Required support routines
  52. ********************************************************************/
  53. DWORD
  54. Pf_dwClientOpen(
  55. LPCWSTR pszDeviceNames,
  56. PPERF_DATA_DEFINITION *pppdd
  57. )
  58. /*++
  59. Routine Description:
  60. Localspl specific intialization of the client data.
  61. Arguments:
  62. pszDeviceNames - Passed in from performance apis.
  63. Return Value:
  64. Status code.
  65. --*/
  66. {
  67. DWORD Status = ERROR_SUCCESS;
  68. *pppdd = reinterpret_cast<PPERF_DATA_DEFINITION>( &LsplDataDefinition );
  69. //
  70. // If not initialized before,
  71. //
  72. if( !gbInitialized )
  73. {
  74. //
  75. // Fix up the indicies in our ObjectType and CounterDefinitions.
  76. //
  77. #ifdef INDEX_FROM_PERFKEY
  78. Status = Pf_dwFixIndiciesFromPerfKey( gszLocalsplPerformanceKey,
  79. *pppdd );
  80. #else
  81. Pf_vFixIndiciesFromIndex( LSPL_FIRST_COUNTER_INDEX,
  82. LSPL_FIRST_HELP_INDEX,
  83. *pppdd );
  84. Status = ERROR_SUCCESS;
  85. #endif
  86. if( Status == ERROR_SUCCESS )
  87. {
  88. gbInitialized = TRUE;
  89. }
  90. }
  91. return Status;
  92. }
  93. DWORD
  94. Pf_dwClientCollect(
  95. PBYTE *ppData,
  96. PDWORD pcbDataLeft,
  97. PDWORD pcNumInstances
  98. )
  99. /*++
  100. Routine Description:
  101. Localspl specific collection of data.
  102. Arguments:
  103. Return Value:
  104. Status code.
  105. --*/
  106. {
  107. PPRINTER_INFO_STRESS pInfoBase;
  108. DWORD cbNeeded;
  109. DWORD cReturned;
  110. DWORD Error = ERROR_SUCCESS;
  111. BOOL bStatus;
  112. PBYTE pData = *ppData;
  113. DWORD cbDataLeft = *pcbDataLeft;
  114. pInfoBase = static_cast<PPRINTER_INFO_STRESS>(
  115. LocalAlloc( LMEM_FIXED, gcbBufferHint ));
  116. if( !pInfoBase )
  117. {
  118. Error = GetLastError();
  119. goto Cleanup;
  120. }
  121. //
  122. // Read the data via EnumPrinters(). We enumerate all the local printers and
  123. // any cluster printers hosted by the local machine.
  124. //
  125. bStatus = EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME | PRINTER_ENUM_CLUSTER,
  126. NULL,
  127. STRESSINFOLEVEL,
  128. reinterpret_cast<PBYTE>( pInfoBase ),
  129. gcbBufferHint,
  130. &cbNeeded,
  131. &cReturned );
  132. if( !bStatus && GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  133. {
  134. //
  135. // Reallocate the buffer and update the hint.
  136. //
  137. gcbBufferHint = cbNeeded + kBufferHintPad;
  138. LocalFree( static_cast<HLOCAL>( pInfoBase ));
  139. pInfoBase = reinterpret_cast<PPRINTER_INFO_STRESS>(
  140. LocalAlloc( LMEM_FIXED, gcbBufferHint ));
  141. if( !pInfoBase )
  142. {
  143. Error = GetLastError();
  144. goto Cleanup;
  145. }
  146. bStatus = EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME | PRINTER_ENUM_CLUSTER,
  147. NULL,
  148. STRESSINFOLEVEL,
  149. reinterpret_cast<PBYTE>( pInfoBase ),
  150. gcbBufferHint,
  151. &cbNeeded,
  152. &cReturned );
  153. }
  154. if( !bStatus )
  155. {
  156. Error = GetLastError();
  157. goto Cleanup;
  158. }
  159. //
  160. // Update the hint.
  161. //
  162. gcbBufferHint = cbNeeded + kBufferHintPad;
  163. UINT i;
  164. PPRINTER_INFO_STRESS pInfo;
  165. LSPL_COUNTER_DATA lcdTotal;
  166. PLSPL_COUNTER_DATA plcd;
  167. ZeroMemory( &lcdTotal, sizeof( lcdTotal ));
  168. for( i=0, pInfo = pInfoBase; i< cReturned; ++i, ++pInfo )
  169. {
  170. Error = Pfp_dwBuildPrinterInstanceFromInfo( pInfo,
  171. &pData,
  172. &cbDataLeft,
  173. &plcd );
  174. if( Error != ERROR_SUCCESS ){
  175. goto Cleanup;
  176. }
  177. //
  178. // Add up the total.
  179. //
  180. lcdTotal.liTotalJobs.QuadPart += plcd->liTotalJobs.QuadPart;
  181. lcdTotal.liTotalBytes.QuadPart += plcd->liTotalBytes.QuadPart;
  182. lcdTotal.liTotalPagesPrinted.QuadPart+= plcd->liTotalPagesPrinted.QuadPart;
  183. lcdTotal.dwJobs += plcd->dwJobs;
  184. lcdTotal.dwMaxRef += plcd->dwMaxRef;
  185. lcdTotal.dwSpooling += plcd->dwSpooling;
  186. lcdTotal.dwMaxSpooling += plcd->dwMaxSpooling;
  187. lcdTotal.dwRef += plcd->dwRef;
  188. lcdTotal.dwErrorOutOfPaper += plcd->dwErrorOutOfPaper;
  189. lcdTotal.dwErrorNotReady += plcd->dwErrorNotReady;
  190. lcdTotal.dwJobError += plcd->dwJobError;
  191. //
  192. // Only include EnumerateNetworkPrinters and dwAddNetPrinters
  193. // once,d since they are really globals (per-server not per-printer).
  194. //
  195. if( i == 0 )
  196. {
  197. lcdTotal.dwEnumerateNetworkPrinters = plcd->dwEnumerateNetworkPrinters;
  198. lcdTotal.dwAddNetPrinters = plcd->dwAddNetPrinters;
  199. }
  200. }
  201. //
  202. // Add the last one.
  203. //
  204. Error = Pfp_dwBuildPrinterInstanceFromLCD( gszTotal,
  205. &lcdTotal,
  206. &pData,
  207. &cbDataLeft );
  208. Cleanup:
  209. if( pInfoBase )
  210. {
  211. LocalFree( static_cast<HLOCAL>( pInfoBase ));
  212. }
  213. if( Error == ERROR_SUCCESS )
  214. {
  215. //
  216. // Update the pointers. We will return cReturned+1 instances since
  217. // we built an artifical "_Total" instance.
  218. //
  219. *ppData = pData;
  220. *pcbDataLeft = cbDataLeft;
  221. *pcNumInstances = cReturned + 1;
  222. return ERROR_SUCCESS;
  223. }
  224. return Error;
  225. }
  226. VOID
  227. Pf_vClientClose(
  228. VOID
  229. )
  230. /*++
  231. Routine Description:
  232. Localspl specific closure of data.
  233. Arguments:
  234. Return Value:
  235. --*/
  236. {
  237. //
  238. // Nothing to do since it is name based.
  239. //
  240. }
  241. /********************************************************************
  242. Helper functions.
  243. ********************************************************************/
  244. DWORD
  245. Pfp_dwBuildPrinterInstanceFromInfo(
  246. IN PPRINTER_INFO_STRESS pInfo,
  247. IN OUT PBYTE* ppData,
  248. IN OUT PDWORD pcbDataLeft,
  249. OUT PLSPL_COUNTER_DATA *pplcd OPTIONAL
  250. )
  251. /*++
  252. Routine Description:
  253. Add a single pInfo structure to the performance data block.
  254. Arguments:
  255. pInfo - Input data.
  256. ppData - On entry, pointer to buffer. On exit, holds the next
  257. available space in buffer. If an error is returned, this
  258. value is random.
  259. pcbDataLeft - On entry, size of buffer. On exit, remaining size
  260. of buffer. If an error is returned, this value is random.
  261. pplcd - Optional; on success returns pointer to lcd.
  262. Return Value:
  263. ERROR_SUCCESS - Success, else failure code.
  264. --*/
  265. {
  266. DWORD Error;
  267. //
  268. // Add the instance definitions
  269. //
  270. Error = Pf_dwBuildInstance( 0,
  271. 0,
  272. static_cast<DWORD>( PERF_NO_UNIQUE_ID ),
  273. pInfo->pPrinterName,
  274. ppData,
  275. pcbDataLeft );
  276. if( Error != ERROR_SUCCESS )
  277. {
  278. goto Fail;
  279. }
  280. //
  281. // Check if there's enough space for our counter data.
  282. //
  283. if( *pcbDataLeft < sizeof( LSPL_COUNTER_DATA ))
  284. {
  285. Error = ERROR_MORE_DATA;
  286. goto Fail;
  287. }
  288. //
  289. // Convert ppData to a LSPL_COUNTER_DATA and copy everything over.
  290. //
  291. PLSPL_COUNTER_DATA plcd;
  292. plcd = reinterpret_cast<PLSPL_COUNTER_DATA>( *ppData );
  293. plcd->CounterBlock.ByteLength = sizeof( LSPL_COUNTER_DATA );
  294. plcd->liTotalJobs.HighPart = 0;
  295. plcd->liTotalBytes.HighPart = pInfo->dwHighPartTotalBytes;
  296. plcd->liTotalPagesPrinted.HighPart = 0;
  297. plcd->liTotalJobs.LowPart = pInfo->cTotalJobs;
  298. plcd->liTotalBytes.LowPart = pInfo->cTotalBytes;
  299. plcd->liTotalPagesPrinted.LowPart = pInfo->cTotalPagesPrinted;
  300. plcd->dwJobs = pInfo->cJobs;
  301. plcd->dwMaxRef = pInfo->MaxcRef;
  302. plcd->dwSpooling = pInfo->cSpooling;
  303. plcd->dwMaxSpooling = pInfo->cMaxSpooling;
  304. plcd->dwRef = pInfo->cRef;
  305. plcd->dwErrorOutOfPaper = pInfo->cErrorOutOfPaper;
  306. plcd->dwErrorNotReady = pInfo->cErrorNotReady;
  307. plcd->dwJobError = pInfo->cJobError;
  308. plcd->dwEnumerateNetworkPrinters = pInfo->cEnumerateNetworkPrinters;
  309. plcd->dwAddNetPrinters = pInfo->cAddNetPrinters;
  310. //
  311. // Update the counters.
  312. //
  313. *ppData += sizeof( LSPL_COUNTER_DATA );
  314. *pcbDataLeft -= sizeof( LSPL_COUNTER_DATA );
  315. if( pplcd )
  316. {
  317. *pplcd = plcd;
  318. }
  319. Fail:
  320. return Error;
  321. }
  322. DWORD
  323. Pfp_dwBuildPrinterInstanceFromLCD(
  324. IN LPCWSTR pszName,
  325. IN PLSPL_COUNTER_DATA plcdSource,
  326. IN OUT PBYTE* ppData,
  327. IN OUT PDWORD pcbDataLeft
  328. )
  329. /*++
  330. Routine Description:
  331. Add a single LCD structure to the performance data block.
  332. Arguments:
  333. pszName - Name of the block.
  334. plcd - Pointer to the LCD block to copy.
  335. ppData - On entry, pointer to buffer. On exit, holds the next
  336. available space in buffer. If an error is returned, this
  337. value is random.
  338. pcbDataLeft - On entry, size of buffer. On exit, remaining size
  339. of buffer. If an error is returned, this value is random.
  340. Return Value:
  341. ERROR_SUCCESS - Success, else failure code.
  342. --*/
  343. {
  344. DWORD Error;
  345. //
  346. // Add the instance definitions
  347. //
  348. Error = Pf_dwBuildInstance( 0,
  349. 0,
  350. static_cast<DWORD>( PERF_NO_UNIQUE_ID ),
  351. pszName,
  352. ppData,
  353. pcbDataLeft );
  354. if( Error != ERROR_SUCCESS )
  355. {
  356. goto Fail;
  357. }
  358. //
  359. // Check if there's enough space for our counter data.
  360. //
  361. if( *pcbDataLeft < sizeof( LSPL_COUNTER_DATA ))
  362. {
  363. Error = ERROR_MORE_DATA;
  364. goto Fail;
  365. }
  366. //
  367. // Convert ppData to a LSPL_COUNTER_DATA and copy everything over.
  368. //
  369. PLSPL_COUNTER_DATA plcd;
  370. plcd = reinterpret_cast<PLSPL_COUNTER_DATA>( *ppData );
  371. CopyMemory( plcd, plcdSource, sizeof( LSPL_COUNTER_DATA ));
  372. plcd->CounterBlock.ByteLength = sizeof( LSPL_COUNTER_DATA );
  373. //
  374. // Update the counters.
  375. //
  376. *ppData += sizeof( LSPL_COUNTER_DATA );
  377. *pcbDataLeft -= sizeof( LSPL_COUNTER_DATA );
  378. Fail:
  379. return Error;
  380. }