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.

391 lines
10 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. prnt_lm.c
  5. Abstract:
  6. This file contains the routines which actually call Lan Manager and
  7. retrieve the contents of the print queue table, including cacheing.
  8. Environment:
  9. User Mode - Win32
  10. Revision History:
  11. 10-May-1996 DonRyan
  12. Removed banner from Technology Dynamics, Inc.
  13. --*/
  14. //--------------------------- WINDOWS DEPENDENCIES --------------------------
  15. //--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
  16. #ifdef WIN32
  17. #include <windows.h>
  18. #include <winspool.h>
  19. #endif
  20. #include <tchar.h>
  21. #include <string.h>
  22. #include <search.h>
  23. #include <stdlib.h>
  24. #include <time.h>
  25. //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
  26. #include "mib.h"
  27. #include "mibfuncs.h"
  28. #include "prnt_tbl.h"
  29. #include "lmcache.h"
  30. //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
  31. //--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
  32. //--------------------------- PRIVATE CONSTANTS -----------------------------
  33. #define SafeBufferFree(x) if(NULL != x) NetApiBufferFree( x )
  34. #define SafeFree(x) if(NULL != x) SnmpUtilMemFree( x )
  35. //--------------------------- PRIVATE STRUCTS -------------------------------
  36. //--------------------------- PRIVATE VARIABLES -----------------------------
  37. //--------------------------- PRIVATE PROTOTYPES ----------------------------
  38. //--------------------------- PRIVATE PROCEDURES ----------------------------
  39. int __cdecl prnt_entry_cmp(
  40. IN const PRINTQ_ENTRY *A,
  41. IN const PRINTQ_ENTRY *B
  42. ) ;
  43. void build_prnt_entry_oids( );
  44. //--------------------------- PUBLIC PROCEDURES -----------------------------
  45. //
  46. // MIB_prnt_lmget
  47. // Retrieve print queue table information from Lan Manager.
  48. // If not cached, sort it and then
  49. // cache it.
  50. //
  51. // Notes:
  52. //
  53. // Return Codes:
  54. // SNMPAPI_NOERROR
  55. // SNMPAPI_ERROR
  56. //
  57. // Error Codes:
  58. // None.
  59. //
  60. SNMPAPI MIB_prntq_lmget(
  61. )
  62. {
  63. DWORD entriesread = 0; // init number of table entries read
  64. DWORD bytesNeeded = 0; // init size needed
  65. DWORD dwLastError = ERROR_SUCCESS; // init last error to no error
  66. LPBYTE bufptr;
  67. unsigned lmCode;
  68. unsigned i;
  69. PRINTER_INFO_2 *DataTable;
  70. PRINTQ_ENTRY *MIB_PrintQTableElement ;
  71. int First_of_this_block;
  72. time_t curr_time ;
  73. BOOL result;
  74. SNMPAPI nResult = SNMPAPI_NOERROR;
  75. time(&curr_time); // get the time
  76. //
  77. //
  78. // If cached, return piece of info.
  79. //
  80. //
  81. if((NULL != cache_table[C_PRNT_TABLE].bufptr) &&
  82. (curr_time <
  83. (cache_table[C_PRNT_TABLE].acquisition_time
  84. + cache_expire[C_PRNT_TABLE] ) ) )
  85. { // it has NOT expired!
  86. goto Exit ; // the global table is valid
  87. }
  88. //
  89. // remember to free the existing data
  90. //
  91. MIB_PrintQTableElement = MIB_PrintQTable.Table ;
  92. // iterate over the whole table
  93. for(i=0; i<MIB_PrintQTable.Len ;i++)
  94. {
  95. // free any alloc'ed elements of the structure
  96. SnmpUtilOidFree(&(MIB_PrintQTableElement->Oid));
  97. SafeFree(MIB_PrintQTableElement->svPrintQName.stream);
  98. MIB_PrintQTableElement ++ ; // increment table entry
  99. }
  100. SafeFree(MIB_PrintQTable.Table) ; // free the base Table
  101. MIB_PrintQTable.Table = NULL ; // just for safety
  102. MIB_PrintQTable.Len = 0 ; // just for safety
  103. //
  104. //
  105. // Do network call to gather information and put it in a nice array
  106. //
  107. //
  108. // call it with zero length buffer to get the size
  109. //
  110. result = EnumPrinters(
  111. PRINTER_ENUM_SHARED |
  112. PRINTER_ENUM_LOCAL, // what type to enum
  113. NULL, // local server
  114. 2, // level
  115. NULL, // where to put it
  116. 0, // max of above
  117. &bytesNeeded, // additional bytes req'd
  118. &entriesread ); // how many we got this time
  119. if (result)
  120. {
  121. // When there is no table entries from spooler *and* spooler is
  122. // running, we'll be here.
  123. SNMPDBG((
  124. SNMP_LOG_TRACE,
  125. "SNMP: LMMIB2: EnumPrinters returns TRUE, bytesNeeded=0x%08lx\n",
  126. bytesNeeded
  127. ));
  128. goto Exit; // get out with 0 entries in the table
  129. }
  130. // Assert: result == FALSE
  131. dwLastError = GetLastError(); // save last error
  132. SNMPDBG((
  133. SNMP_LOG_TRACE,
  134. "SNMP: LMMIB2: EnumPrinters returns FALSE, bytesNeeded=0x%08lx, dwLastError=0x%08lx\n",
  135. bytesNeeded, dwLastError
  136. ));
  137. if (ERROR_INSUFFICIENT_BUFFER != dwLastError)
  138. {
  139. //
  140. // EnumPrinters Failed and the last error is not
  141. // ERROR_INSUFFICIENT_BUFFER, we'll bail out with 0 entries in the
  142. // table.
  143. // For example, if spooler service was down, we will be here.
  144. //
  145. SNMPDBG((
  146. SNMP_LOG_TRACE,
  147. "SNMP: LMMIB2: EnumPrinters failed, lasterror != ERROR_INSUFFICIENT_BUFFER, bytesNeeded=%d\n",
  148. bytesNeeded
  149. ));
  150. goto Exit; // get out with 0 entries in the table, so getnext will work
  151. }
  152. // Assert: dwLastError == ERROR_INSUFFICIENT_BUFFER
  153. bufptr = SnmpUtilMemAlloc(bytesNeeded); // SnmpUtilMemAlloc the buffer
  154. if(NULL==bufptr)
  155. {
  156. nResult = SNMPAPI_ERROR;
  157. goto Exit ; // can't allocate memory, error out
  158. }
  159. // then read the rest of it
  160. // call it again
  161. result = EnumPrinters(
  162. PRINTER_ENUM_SHARED |
  163. PRINTER_ENUM_LOCAL, // what type to enum
  164. NULL, // local server
  165. 2, // level
  166. bufptr, // where to put it
  167. bytesNeeded, // max of above
  168. &bytesNeeded, // additional bytes req'd
  169. &entriesread ); // how many we got this time
  170. if (!result) {
  171. // Signal error
  172. SafeFree( bufptr );
  173. nResult = SNMPAPI_ERROR;
  174. goto Exit;
  175. }
  176. DataTable = (PRINTER_INFO_2 *) bufptr ;
  177. if(0 == MIB_PrintQTable.Len) { // 1st time, alloc the whole table
  178. // alloc the table space
  179. MIB_PrintQTable.Table = SnmpUtilMemAlloc(entriesread *
  180. sizeof(PRINTQ_ENTRY) );
  181. // prefix bug 445181
  182. if (MIB_PrintQTable.Table == NULL) {
  183. // free the table
  184. SafeFree( bufptr ) ;
  185. // Signal error
  186. nResult = SNMPAPI_ERROR;
  187. goto Exit;
  188. }
  189. }
  190. MIB_PrintQTableElement = MIB_PrintQTable.Table ;
  191. for(i=0; i<entriesread; i++) { // once for each entry in the buffer
  192. // increment the entry number
  193. MIB_PrintQTable.Len ++;
  194. // Stuff the data into each item in the table
  195. // client name
  196. MIB_PrintQTableElement->svPrintQName.dynamic = TRUE;
  197. #ifdef UNICODE
  198. if (SnmpUtilUnicodeToUTF8(
  199. &MIB_PrintQTableElement->svPrintQName.stream,
  200. DataTable->pPrinterName,
  201. TRUE))
  202. {
  203. MIB_PrintQTableElement->svPrintQName.stream = NULL;
  204. MIB_PrintQTableElement->svPrintQName.length = 0;
  205. }
  206. else
  207. {
  208. MIB_PrintQTableElement->svPrintQName.length =
  209. strlen (MIB_PrintQTableElement->svPrintQName.stream);
  210. }
  211. #else
  212. MIB_PrintQTableElement->svPrintQName.stream = SnmpUtilMemAlloc (
  213. strlen( DataTable->pPrinterName ) + 1 ) ;
  214. MIB_PrintQTableElement->svPrintQName.length =
  215. strlen( DataTable->pPrinterName ) ;
  216. memcpy( MIB_PrintQTableElement->svPrintQName.stream,
  217. DataTable->pPrinterName,
  218. strlen( DataTable->pPrinterName ) ) ;
  219. #endif
  220. // number of connections
  221. MIB_PrintQTableElement->svPrintQNumJobs =
  222. DataTable->cJobs;
  223. MIB_PrintQTableElement ++ ; // and table entry
  224. DataTable ++ ; // advance pointer to next sess entry in buffer
  225. } // for each entry in the data table
  226. // free all of the printer enum data
  227. if(NULL!=bufptr) // free the table
  228. SnmpUtilMemFree( bufptr ) ;
  229. // iterate over the table populating the Oid field
  230. build_prnt_entry_oids();
  231. // Sort the table information using MSC QuickSort routine
  232. qsort( &MIB_PrintQTable.Table[0], MIB_PrintQTable.Len,
  233. sizeof(PRINTQ_ENTRY), prnt_entry_cmp );
  234. //
  235. //
  236. // Cache table
  237. //
  238. //
  239. if(0 != MIB_PrintQTable.Len) {
  240. cache_table[C_PRNT_TABLE].acquisition_time = curr_time ;
  241. cache_table[C_PRNT_TABLE].bufptr = bufptr ;
  242. }
  243. //
  244. //
  245. // Return piece of information requested in global table
  246. //
  247. //
  248. Exit:
  249. return nResult;
  250. } // MIB_prnt_get
  251. //
  252. // MIB_prnt_cmp
  253. // Routine for sorting the session table.
  254. //
  255. // Notes:
  256. //
  257. // Return Codes:
  258. // SNMPAPI_NOERROR
  259. // SNMPAPI_ERROR
  260. //
  261. // Error Codes:
  262. // None.
  263. //
  264. int __cdecl prnt_entry_cmp(
  265. IN const PRINTQ_ENTRY *A,
  266. IN const PRINTQ_ENTRY *B
  267. )
  268. {
  269. // Compare the OID's
  270. return SnmpUtilOidCmp( (AsnObjectIdentifier *)&A->Oid,
  271. (AsnObjectIdentifier *)&B->Oid );
  272. } // MIB_prnt_cmp
  273. //
  274. // None.
  275. //
  276. void build_prnt_entry_oids(
  277. )
  278. {
  279. AsnOctetString OSA ;
  280. PRINTQ_ENTRY *PrintQEntry ;
  281. unsigned i;
  282. // start pointer at 1st guy in the table
  283. PrintQEntry = MIB_PrintQTable.Table ;
  284. // now iterate over the table, creating an oid for each entry
  285. for( i=0; i<MIB_PrintQTable.Len ; i++) {
  286. // for each entry in the session table
  287. OSA.stream = PrintQEntry->svPrintQName.stream ;
  288. OSA.length = PrintQEntry->svPrintQName.length ;
  289. OSA.dynamic = TRUE;
  290. // Make the entry's OID from string index
  291. MakeOidFromStr( &OSA, &PrintQEntry->Oid );
  292. PrintQEntry++; // point to the next guy in the table
  293. } // for
  294. } // build_prnt_entry_oids
  295. //-------------------------------- END --------------------------------------