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.

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