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.

553 lines
24 KiB

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. PCH_Printer.CPP
  5. Abstract:
  6. WBEM provider class implementation for PCH_Printer class
  7. Revision History:
  8. Ghim-Sim Chua (gschua) 04/27/99
  9. - Created
  10. ********************************************************************/
  11. #include "pchealth.h"
  12. #include "PCH_Printer.h"
  13. /////////////////////////////////////////////////////////////////////////////
  14. // tracing stuff
  15. #ifdef THIS_FILE
  16. #undef THIS_FILE
  17. #endif
  18. static char __szTraceSourceFile[] = __FILE__;
  19. #define THIS_FILE __szTraceSourceFile
  20. #define TRACE_ID DCID_PRINTER
  21. #define MAX_STRING_LEN 1024
  22. CPCH_Printer MyPCH_PrinterSet (PROVIDER_NAME_PCH_PRINTER, PCH_NAMESPACE) ;
  23. ///////////////////////////////////////////////////////////////////////////////
  24. //....Properties of PCHPrinter Class
  25. //
  26. const static WCHAR* pTimeStamp = L"TimeStamp" ;
  27. const static WCHAR* pChange = L"Change" ;
  28. const static WCHAR* pDefaultPrinter = L"DefaultPrinter" ;
  29. const static WCHAR* pGenDrv = L"GenDrv" ;
  30. const static WCHAR* pName = L"Name" ;
  31. const static WCHAR* pPath = L"Path" ;
  32. const static WCHAR* pUniDrv = L"UniDrv" ;
  33. const static WCHAR* pUsePrintMgrSpooling = L"UsePrintMgrSpooling" ;
  34. //*****************************************************************************
  35. //
  36. // Function Name : CPCH_Printer::EnumerateInstances
  37. //
  38. // Input Parameters : pMethodContext : Pointer to the MethodContext for
  39. // communication with WinMgmt.
  40. //
  41. // lFlags : Long that contains the flags described
  42. // in IWbemServices::CreateInstanceEnumAsync
  43. // Note that the following flags are handled
  44. // by (and filtered out by) WinMgmt:
  45. // WBEM_FLAG_DEEP
  46. // WBEM_FLAG_SHALLOW
  47. // WBEM_FLAG_RETURN_IMMEDIATELY
  48. // WBEM_FLAG_FORWARD_ONLY
  49. // WBEM_FLAG_BIDIRECTIONAL
  50. // Output Parameters : None
  51. //
  52. // Returns : WBEM_S_NO_ERROR
  53. //
  54. //
  55. // Synopsis : There is a single instance of this class on the machine
  56. // and this is returned..
  57. // If there is no instances returns WBEM_S_NO_ERROR.
  58. // It is not an error to have no instances.
  59. //
  60. //*****************************************************************************
  61. HRESULT CPCH_Printer::EnumerateInstances(MethodContext* pMethodContext,
  62. long lFlags)
  63. {
  64. TraceFunctEnter("CPCH_Printer::EnumerateInstances");
  65. // Begin Declarations...................................................
  66. HRESULT hRes = WBEM_S_NO_ERROR;
  67. // Instances
  68. CComPtr<IEnumWbemClassObject> pPrinterEnumInst;
  69. // Objects
  70. IWbemClassObjectPtr pFileObj;
  71. IWbemClassObjectPtr pPrinterObj; // BUGBUG : WMI asserts if we use CComPtr
  72. // SystemTime
  73. SYSTEMTIME stUTCTime;
  74. // Variants
  75. CComVariant varValue;
  76. CComVariant varAttributes;
  77. CComVariant varSnapshot = "Snapshot";
  78. CComVariant varNotAvail = "Not Available";
  79. // Strings
  80. CComBSTR bstrUniDriverWithPath;
  81. CComBSTR bstrGenDriverWithPath;
  82. CComBSTR bstrUnidriverDetails;
  83. CComBSTR bstrGenDriverDetails;
  84. CComBSTR bstrAttributes = "attributes";
  85. CComBSTR bstrPrinterQueryString;
  86. CComBSTR bstrVersion = "Version";
  87. CComBSTR bstrFileSize = "FileSize";
  88. CComBSTR bstrModifiedDate = "LastModified";
  89. LPCTSTR lpctstrUniDriver = _T("unidrv.dll");
  90. LPCTSTR lpctstrGenDriver = _T("gendrv.dll");
  91. LPCTSTR lpctstrSpace = _T(" ");
  92. LPCTSTR lpctstrPrinterQuery = _T("Select DeviceID, DriverName, Attributes FROM win32_printer WHERE DriverName =\"");
  93. LPCTSTR lpctstrWindows = _T("Windows");
  94. LPCTSTR lpctstrDevice = _T("Device");
  95. LPCTSTR lpctstrComma = _T(",");
  96. LPCTSTR lpctstrSlash = _T("\"");
  97. LPCTSTR lpctstrNoUniDrv = _T("(unidrv.dll) = NotInstalled");
  98. LPCTSTR lpctstrNoGenDrv = _T("(gendrv.dll) = NotInstalled");
  99. LPCTSTR lpctstrPrintersHive = _T("System\\CurrentControlSet\\Control\\Print\\Printers");
  100. LPCTSTR lpctstrYes = _T("yes");
  101. LPCTSTR lpctstrAttributes = _T("Attributes");
  102. LPCTSTR lpctstrSpooler = _T("Spooler");
  103. TCHAR tchBuffer[MAX_STRING_LEN];
  104. TCHAR tchPrinterKeyName[MAX_STRING_LEN];
  105. TCHAR tchAttributesValue[MAX_PATH];
  106. TCHAR *ptchToken;
  107. // Booleans
  108. BOOL fDriverFound;
  109. BOOL fCommit = FALSE;
  110. BOOL fAttribFound = FALSE;
  111. // DWORDs
  112. DWORD dwSize;
  113. DWORD dwIndex;
  114. DWORD dwType;
  115. DWORD dwAttributes;
  116. // Return Values;
  117. ULONG ulPrinterRetVal = 0;
  118. ULONG ulPrinterAttribs;
  119. LONG lRegRetVal;
  120. struct tm tm;
  121. WBEMTime wbemtimeUnidriver;
  122. WBEMTime wbemtimeGendriver;
  123. HKEY hkeyPrinter;
  124. HKEY hkeyPrinters;
  125. PFILETIME pFileTime = NULL;
  126. // End Declarations...................................................
  127. // Create a new instance of PCH_Printer Class based on the passed-in MethodContext
  128. CInstancePtr pPCHPrinterInstance(CreateNewInstance(pMethodContext), false);
  129. // Created a New Instance of PCH_PrinterInstance Successfully.
  130. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. // TIME STAMP //
  132. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  133. // Get the date and time to update the TimeStamp Field
  134. GetSystemTime(&stUTCTime);
  135. hRes = pPCHPrinterInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime));
  136. if (FAILED(hRes))
  137. {
  138. // Could not Set the Time Stamp
  139. // Continue anyway
  140. ErrorTrace(TRACE_ID, "SetDateTime on Timestamp Field failed.");
  141. }
  142. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  143. // CHANGE //
  144. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. hRes = pPCHPrinterInstance->SetVariant(pChange, varSnapshot);
  146. if(FAILED(hRes))
  147. {
  148. // Could not Set the Change Property
  149. // Continue anyway
  150. ErrorTrace(TRACE_ID, "Set Variant on Change Field failed.");
  151. }
  152. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  153. // DEFAULTPRINTER //
  154. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  155. // In "win.ini" file under "Windows" section "Device" represents the default printer
  156. if(GetProfileString(lpctstrWindows, lpctstrDevice, "\0", tchBuffer, MAX_PATH) > 1)
  157. {
  158. // If Found the Default Printer set the value to TRUE
  159. varValue = VARIANT_TRUE;
  160. hRes = pPCHPrinterInstance->SetVariant(pDefaultPrinter, varValue);
  161. if(FAILED(hRes))
  162. {
  163. // Could not Set the Default Printer to TRUE
  164. // Continue anyway
  165. ErrorTrace(TRACE_ID, "Set Variant on DefaultPrinter Field failed.");
  166. }
  167. // The Above GetProfileString returns "printerName", "PrinterDriver" and "PrinterPath"
  168. // seperated by commas. Ignore "PrinterDriver" and use the other two to set the properties.
  169. ptchToken = _tcstok(tchBuffer,lpctstrComma);
  170. if(ptchToken != NULL)
  171. {
  172. // Got the first Token i.e. name. Set this.
  173. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174. // NAME //
  175. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. varValue = ptchToken;
  177. hRes = pPCHPrinterInstance->SetVariant(pName, varValue);
  178. if(FAILED(hRes))
  179. {
  180. // Could not Set the Name
  181. // Continue anyway
  182. ErrorTrace(TRACE_ID, "Set Variant on Name Field failed.");
  183. }
  184. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  185. // PATH //
  186. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  187. // continue to get the next token and ignore
  188. ptchToken = _tcstok(NULL,lpctstrComma);
  189. if(ptchToken != NULL)
  190. {
  191. // If ptchToken is not equal to NULL, then continue to get the third token and set it to PATH Name Field
  192. ptchToken = _tcstok(NULL,lpctstrComma);
  193. if(ptchToken != NULL)
  194. {
  195. // Got the third token i.e. PATH Set this.
  196. varValue = ptchToken;
  197. hRes = pPCHPrinterInstance->SetVariant(pPath, varValue);
  198. if (FAILED(hRes))
  199. {
  200. // Could not Set the Path property
  201. // Continue anyway
  202. ErrorTrace(TRACE_ID, "Set Variant on PathName Field failed.");
  203. }
  204. }
  205. }
  206. }
  207. }
  208. else
  209. {
  210. // Could not get the default printer details.
  211. // Set the Name to "Not Available"
  212. hRes = pPCHPrinterInstance->SetVariant(pName, varNotAvail);
  213. if(FAILED(hRes))
  214. {
  215. // Could not Set the Name
  216. // Continue anyway
  217. ErrorTrace(TRACE_ID, "Set Variant on Name Field failed.");
  218. }
  219. // Set the default printer to false
  220. varValue = VARIANT_FALSE;
  221. hRes = pPCHPrinterInstance->SetVariant(pDefaultPrinter, varValue);
  222. if(FAILED(hRes))
  223. {
  224. // Could not Set the Default Printer to FALSE
  225. // Continue anyway
  226. ErrorTrace(TRACE_ID, "Set Variant on DefaultPrinter Field failed.");
  227. }
  228. // Proceed anyway!
  229. }
  230. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  231. // USEPRINTMANAGERSPOOLING //
  232. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  233. // First try to get the Spooling information from the registry. This is available in registry if there are
  234. // any installed printers.
  235. // This info. is present under HKLM\system\CCS\Control\Print\Printers
  236. lRegRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpctstrPrintersHive, 0, KEY_READ, &hkeyPrinters);
  237. if(lRegRetVal == ERROR_SUCCESS)
  238. {
  239. // Opened the Registry key.
  240. // Enumerate the keys under this hive.
  241. dwIndex = 0;
  242. dwSize = MAX_PATH;
  243. lRegRetVal = RegEnumKeyEx(hkeyPrinters, dwIndex, tchPrinterKeyName, &dwSize, NULL, NULL, NULL, pFileTime);
  244. if(lRegRetVal == ERROR_SUCCESS)
  245. {
  246. // There is atleast one printer installed.
  247. lRegRetVal = RegOpenKeyEx(hkeyPrinters, tchPrinterKeyName, 0, KEY_READ, &hkeyPrinter);
  248. if(lRegRetVal == ERROR_SUCCESS)
  249. {
  250. // Opened the first printer key
  251. // Query for , regname "Attributes"
  252. dwSize = MAX_PATH;
  253. lRegRetVal = RegQueryValueEx(hkeyPrinter, lpctstrAttributes , NULL, &dwType, (LPBYTE)&dwAttributes, &dwSize);
  254. if(lRegRetVal == ERROR_SUCCESS)
  255. {
  256. // Got the attributes
  257. // Check the type of the reg Value
  258. if(dwType == REG_DWORD)
  259. {
  260. /*
  261. // tchAttributesValue set to Attributes. Copy this to ulPrinterAttribs
  262. ulPrinterAttribs = atol(tchAttributesValue);
  263. if (ulPrinterAttribs > 0)
  264. {
  265. // From ulPrinterAttribs determine if spooling is present or not.
  266. // AND it with PRINTER_ATTRIBUTE_DIRECT
  267. if((ulPrinterAttribs & PRINTER_ATTRIBUTE_DIRECT) != 0)
  268. {
  269. // No spooling
  270. varValue = VARIANT_FALSE;
  271. }
  272. else
  273. {
  274. // Spooling : YES
  275. varValue = VARIANT_TRUE;
  276. }
  277. // Attribute Found
  278. fAttribFound = TRUE;
  279. }
  280. */
  281. if((dwAttributes & PRINTER_ATTRIBUTE_DIRECT) != 0)
  282. {
  283. // No spooling
  284. varValue = VARIANT_FALSE;
  285. }
  286. else
  287. {
  288. // Spooling : YES
  289. varValue = VARIANT_TRUE;
  290. }
  291. // Attribute Found
  292. fAttribFound = TRUE;
  293. }
  294. }
  295. }
  296. }
  297. }
  298. if(!fAttribFound)
  299. {
  300. // If not get the "spooler" key value from the win.ini file. If the entry is not present default to "yes".
  301. if(GetProfileString(lpctstrWindows, lpctstrSpooler, "yes", tchBuffer, MAX_PATH) > 1)
  302. {
  303. // Got the spooler Details
  304. if(_tcsicmp(tchBuffer, lpctstrYes) == 0)
  305. {
  306. // Spooling : YES
  307. varValue = VARIANT_TRUE;
  308. }
  309. else
  310. {
  311. // No spooling
  312. varValue = VARIANT_FALSE;
  313. }
  314. }
  315. }
  316. // Set the Spooling Property.
  317. hRes = pPCHPrinterInstance->SetVariant(pUsePrintMgrSpooling, varValue);
  318. if(FAILED(hRes))
  319. {
  320. // Could not Set the USEPRINTMANAGERSPOOLING
  321. // Continue anyway
  322. ErrorTrace(TRACE_ID, "Set Variant on usePrintManagerSpooling Field failed.");
  323. }
  324. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  325. // UNIDRV //
  326. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  327. pFileObj = NULL;
  328. // Get the complete path for unidrv.dll
  329. fDriverFound = getCompletePath(lpctstrUniDriver, bstrUniDriverWithPath);
  330. if(fDriverFound)
  331. {
  332. // Unidrv.dll present. Pass the File with PathName to
  333. // GetCIMDataFile function to get the file properties.
  334. if (SUCCEEDED(GetCIMDataFile(bstrUniDriverWithPath, &pFileObj)))
  335. {
  336. // From the CIM_DataFile Object get the properties and append them
  337. // Get the Version
  338. varValue.Clear();
  339. hRes = pFileObj->Get(bstrVersion, 0, &varValue, NULL, NULL);
  340. if(SUCCEEDED(hRes))
  341. {
  342. // Got the Version. Append it to the bstrUnidriverDetails String
  343. if(varValue.vt == VT_BSTR)
  344. {
  345. bstrUnidriverDetails.Append(varValue.bstrVal);
  346. // Append Space
  347. bstrUnidriverDetails.Append(lpctstrSpace);
  348. }
  349. }
  350. // Get the FileSize
  351. varValue.Clear();
  352. hRes = pFileObj->Get(bstrFileSize, 0, &varValue, NULL, NULL);
  353. if(SUCCEEDED(hRes))
  354. {
  355. // Got the FileSize. Append it to the bstrUnidriverDetails String
  356. if(varValue.vt == VT_BSTR)
  357. {
  358. bstrUnidriverDetails.Append(varValue.bstrVal);
  359. // Append Space
  360. bstrUnidriverDetails.Append(lpctstrSpace);
  361. }
  362. }
  363. // Get the Date&Time
  364. varValue.Clear();
  365. hRes = pFileObj->Get(bstrModifiedDate, 0, &varValue, NULL, NULL);
  366. if(SUCCEEDED(hRes))
  367. {
  368. if(varValue.vt == VT_BSTR)
  369. {
  370. wbemtimeUnidriver = varValue.bstrVal;
  371. if(wbemtimeUnidriver.GetStructtm(&tm))
  372. {
  373. // Got the time in tm Struct format
  374. // Convert it into a string
  375. varValue = asctime(&tm);
  376. //Append it to the bstrUnidriverDetails String
  377. bstrUnidriverDetails.Append(varValue.bstrVal);
  378. }
  379. }
  380. }
  381. // Copy the string into the varValue
  382. varValue.vt = VT_BSTR;
  383. varValue.bstrVal = bstrUnidriverDetails.Detach();
  384. }// end of if succeeded CIM_DataFile
  385. } // end of if driver Found
  386. else
  387. {
  388. // unidrv.dll not present
  389. varValue.Clear();
  390. varValue = lpctstrNoUniDrv;
  391. }
  392. hRes = pPCHPrinterInstance->SetVariant(pUniDrv, varValue);
  393. if(FAILED(hRes))
  394. {
  395. // Could not Set the Unidriver property
  396. // Continue anyway
  397. ErrorTrace(TRACE_ID, "Set Variant on Uni Driver Field failed.");
  398. }
  399. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  400. // GENDRV //
  401. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  402. pFileObj = NULL;
  403. // Get the complete path for gendrv.dll
  404. fDriverFound = getCompletePath(lpctstrGenDriver, bstrGenDriverWithPath);
  405. if(fDriverFound)
  406. {
  407. // Gendrv.dll present. Pass the File with PathName to
  408. // GetCIMDataFile function to get the file properties.
  409. if(SUCCEEDED(GetCIMDataFile(bstrGenDriverWithPath, &pFileObj)))
  410. {
  411. // From the CIM_DataFile Object get the properties and append them
  412. // Get the Version
  413. varValue.Clear();
  414. hRes = pFileObj->Get(bstrVersion, 0, &varValue, NULL, NULL);
  415. if(SUCCEEDED(hRes))
  416. {
  417. // Got the Version. Append it to the bstrUnidriverDetails String
  418. if(varValue.vt == VT_BSTR)
  419. {
  420. bstrGenDriverDetails.Append(varValue.bstrVal);
  421. // Append Space
  422. bstrGenDriverDetails.Append(lpctstrSpace);
  423. }
  424. }
  425. // Get the FileSize
  426. varValue.Clear();
  427. hRes = pFileObj->Get(bstrFileSize, 0, &varValue, NULL, NULL);
  428. if(SUCCEEDED(hRes))
  429. {
  430. if(varValue.vt == VT_BSTR)
  431. {
  432. // Got the FileSize. Append it to the bstrUnidriverDetails String
  433. bstrGenDriverDetails.Append(varValue.bstrVal);
  434. // Append Space
  435. bstrGenDriverDetails.Append(lpctstrSpace);
  436. }
  437. }
  438. // Get the Date&Time
  439. varValue.Clear();
  440. hRes = pFileObj->Get(bstrModifiedDate, 0, &varValue, NULL, NULL);
  441. if(SUCCEEDED(hRes))
  442. {
  443. if(varValue.vt == VT_BSTR)
  444. {
  445. wbemtimeGendriver = varValue.bstrVal;
  446. if(wbemtimeGendriver.GetStructtm(&tm))
  447. {
  448. // Got the time in tm Struct format
  449. // Convert it into a string
  450. varValue = asctime(&tm);
  451. bstrGenDriverDetails.Append(varValue.bstrVal);
  452. }
  453. }
  454. }
  455. // Copy the string into the varValue
  456. varValue.vt = VT_BSTR;
  457. varValue.bstrVal = bstrGenDriverDetails.Detach();
  458. }// end of if succeeded CIM_DataFile
  459. } // end of if driver Found
  460. else
  461. {
  462. // gendrv.dll not present
  463. varValue.Clear();
  464. varValue = lpctstrNoGenDrv;
  465. }
  466. hRes = pPCHPrinterInstance->SetVariant(pGenDrv, varValue);
  467. if(FAILED(hRes))
  468. {
  469. // Could not Set the GenDrv Field
  470. // Continue anyway
  471. ErrorTrace(TRACE_ID, "Set Variant on GenDrv Field failed.");
  472. }
  473. // All the properties are set.
  474. hRes = pPCHPrinterInstance->Commit();
  475. if(FAILED(hRes))
  476. {
  477. // Could not Set the GenDrv Field
  478. // Continue anyway
  479. ErrorTrace(TRACE_ID, "Error on commiting!");
  480. }
  481. TraceFunctLeave();
  482. return hRes ;
  483. }