/******************************************************************** Copyright (c) 1999 Microsoft Corporation Module Name: PCH_Printer.CPP Abstract: WBEM provider class implementation for PCH_Printer class Revision History: Ghim-Sim Chua (gschua) 04/27/99 - Created ********************************************************************/ #include "pchealth.h" #include "PCH_Printer.h" ///////////////////////////////////////////////////////////////////////////// // tracing stuff #ifdef THIS_FILE #undef THIS_FILE #endif static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile #define TRACE_ID DCID_PRINTER #define MAX_STRING_LEN 1024 CPCH_Printer MyPCH_PrinterSet (PROVIDER_NAME_PCH_PRINTER, PCH_NAMESPACE) ; /////////////////////////////////////////////////////////////////////////////// //....Properties of PCHPrinter Class // const static WCHAR* pTimeStamp = L"TimeStamp" ; const static WCHAR* pChange = L"Change" ; const static WCHAR* pDefaultPrinter = L"DefaultPrinter" ; const static WCHAR* pGenDrv = L"GenDrv" ; const static WCHAR* pName = L"Name" ; const static WCHAR* pPath = L"Path" ; const static WCHAR* pUniDrv = L"UniDrv" ; const static WCHAR* pUsePrintMgrSpooling = L"UsePrintMgrSpooling" ; //***************************************************************************** // // Function Name : CPCH_Printer::EnumerateInstances // // Input Parameters : pMethodContext : Pointer to the MethodContext for // communication with WinMgmt. // // lFlags : Long that contains the flags described // in IWbemServices::CreateInstanceEnumAsync // Note that the following flags are handled // by (and filtered out by) WinMgmt: // WBEM_FLAG_DEEP // WBEM_FLAG_SHALLOW // WBEM_FLAG_RETURN_IMMEDIATELY // WBEM_FLAG_FORWARD_ONLY // WBEM_FLAG_BIDIRECTIONAL // Output Parameters : None // // Returns : WBEM_S_NO_ERROR // // // Synopsis : There is a single instance of this class on the machine // and this is returned.. // If there is no instances returns WBEM_S_NO_ERROR. // It is not an error to have no instances. // //***************************************************************************** HRESULT CPCH_Printer::EnumerateInstances(MethodContext* pMethodContext, long lFlags) { TraceFunctEnter("CPCH_Printer::EnumerateInstances"); // Begin Declarations................................................... HRESULT hRes = WBEM_S_NO_ERROR; // Instances CComPtr pPrinterEnumInst; // Objects IWbemClassObjectPtr pFileObj; IWbemClassObjectPtr pPrinterObj; // BUGBUG : WMI asserts if we use CComPtr // SystemTime SYSTEMTIME stUTCTime; // Variants CComVariant varValue; CComVariant varAttributes; CComVariant varSnapshot = "Snapshot"; CComVariant varNotAvail = "Not Available"; // Strings CComBSTR bstrUniDriverWithPath; CComBSTR bstrGenDriverWithPath; CComBSTR bstrUnidriverDetails; CComBSTR bstrGenDriverDetails; CComBSTR bstrAttributes = "attributes"; CComBSTR bstrPrinterQueryString; CComBSTR bstrVersion = "Version"; CComBSTR bstrFileSize = "FileSize"; CComBSTR bstrModifiedDate = "LastModified"; LPCTSTR lpctstrUniDriver = _T("unidrv.dll"); LPCTSTR lpctstrGenDriver = _T("gendrv.dll"); LPCTSTR lpctstrSpace = _T(" "); LPCTSTR lpctstrPrinterQuery = _T("Select DeviceID, DriverName, Attributes FROM win32_printer WHERE DriverName =\""); LPCTSTR lpctstrWindows = _T("Windows"); LPCTSTR lpctstrDevice = _T("Device"); LPCTSTR lpctstrComma = _T(","); LPCTSTR lpctstrSlash = _T("\""); LPCTSTR lpctstrNoUniDrv = _T("(unidrv.dll) = NotInstalled"); LPCTSTR lpctstrNoGenDrv = _T("(gendrv.dll) = NotInstalled"); LPCTSTR lpctstrPrintersHive = _T("System\\CurrentControlSet\\Control\\Print\\Printers"); LPCTSTR lpctstrYes = _T("yes"); LPCTSTR lpctstrAttributes = _T("Attributes"); LPCTSTR lpctstrSpooler = _T("Spooler"); TCHAR tchBuffer[MAX_STRING_LEN]; TCHAR tchPrinterKeyName[MAX_STRING_LEN]; TCHAR tchAttributesValue[MAX_PATH]; TCHAR *ptchToken; // Booleans BOOL fDriverFound; BOOL fCommit = FALSE; BOOL fAttribFound = FALSE; // DWORDs DWORD dwSize; DWORD dwIndex; DWORD dwType; DWORD dwAttributes; // Return Values; ULONG ulPrinterRetVal = 0; ULONG ulPrinterAttribs; LONG lRegRetVal; struct tm tm; WBEMTime wbemtimeUnidriver; WBEMTime wbemtimeGendriver; HKEY hkeyPrinter; HKEY hkeyPrinters; PFILETIME pFileTime = NULL; // End Declarations................................................... // Create a new instance of PCH_Printer Class based on the passed-in MethodContext CInstancePtr pPCHPrinterInstance(CreateNewInstance(pMethodContext), false); // Created a New Instance of PCH_PrinterInstance Successfully. ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // TIME STAMP // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // Get the date and time to update the TimeStamp Field GetSystemTime(&stUTCTime); hRes = pPCHPrinterInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime)); if (FAILED(hRes)) { // Could not Set the Time Stamp // Continue anyway ErrorTrace(TRACE_ID, "SetDateTime on Timestamp Field failed."); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // CHANGE // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// hRes = pPCHPrinterInstance->SetVariant(pChange, varSnapshot); if(FAILED(hRes)) { // Could not Set the Change Property // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on Change Field failed."); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // DEFAULTPRINTER // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // In "win.ini" file under "Windows" section "Device" represents the default printer if(GetProfileString(lpctstrWindows, lpctstrDevice, "\0", tchBuffer, MAX_PATH) > 1) { // If Found the Default Printer set the value to TRUE varValue = VARIANT_TRUE; hRes = pPCHPrinterInstance->SetVariant(pDefaultPrinter, varValue); if(FAILED(hRes)) { // Could not Set the Default Printer to TRUE // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on DefaultPrinter Field failed."); } // The Above GetProfileString returns "printerName", "PrinterDriver" and "PrinterPath" // seperated by commas. Ignore "PrinterDriver" and use the other two to set the properties. ptchToken = _tcstok(tchBuffer,lpctstrComma); if(ptchToken != NULL) { // Got the first Token i.e. name. Set this. ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // NAME // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// varValue = ptchToken; hRes = pPCHPrinterInstance->SetVariant(pName, varValue); if(FAILED(hRes)) { // Could not Set the Name // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on Name Field failed."); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // PATH // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // continue to get the next token and ignore ptchToken = _tcstok(NULL,lpctstrComma); if(ptchToken != NULL) { // If ptchToken is not equal to NULL, then continue to get the third token and set it to PATH Name Field ptchToken = _tcstok(NULL,lpctstrComma); if(ptchToken != NULL) { // Got the third token i.e. PATH Set this. varValue = ptchToken; hRes = pPCHPrinterInstance->SetVariant(pPath, varValue); if (FAILED(hRes)) { // Could not Set the Path property // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on PathName Field failed."); } } } } } else { // Could not get the default printer details. // Set the Name to "Not Available" hRes = pPCHPrinterInstance->SetVariant(pName, varNotAvail); if(FAILED(hRes)) { // Could not Set the Name // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on Name Field failed."); } // Set the default printer to false varValue = VARIANT_FALSE; hRes = pPCHPrinterInstance->SetVariant(pDefaultPrinter, varValue); if(FAILED(hRes)) { // Could not Set the Default Printer to FALSE // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on DefaultPrinter Field failed."); } // Proceed anyway! } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // USEPRINTMANAGERSPOOLING // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // First try to get the Spooling information from the registry. This is available in registry if there are // any installed printers. // This info. is present under HKLM\system\CCS\Control\Print\Printers lRegRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpctstrPrintersHive, 0, KEY_READ, &hkeyPrinters); if(lRegRetVal == ERROR_SUCCESS) { // Opened the Registry key. // Enumerate the keys under this hive. dwIndex = 0; dwSize = MAX_PATH; lRegRetVal = RegEnumKeyEx(hkeyPrinters, dwIndex, tchPrinterKeyName, &dwSize, NULL, NULL, NULL, pFileTime); if(lRegRetVal == ERROR_SUCCESS) { // There is atleast one printer installed. lRegRetVal = RegOpenKeyEx(hkeyPrinters, tchPrinterKeyName, 0, KEY_READ, &hkeyPrinter); if(lRegRetVal == ERROR_SUCCESS) { // Opened the first printer key // Query for , regname "Attributes" dwSize = MAX_PATH; lRegRetVal = RegQueryValueEx(hkeyPrinter, lpctstrAttributes , NULL, &dwType, (LPBYTE)&dwAttributes, &dwSize); if(lRegRetVal == ERROR_SUCCESS) { // Got the attributes // Check the type of the reg Value if(dwType == REG_DWORD) { /* // tchAttributesValue set to Attributes. Copy this to ulPrinterAttribs ulPrinterAttribs = atol(tchAttributesValue); if (ulPrinterAttribs > 0) { // From ulPrinterAttribs determine if spooling is present or not. // AND it with PRINTER_ATTRIBUTE_DIRECT if((ulPrinterAttribs & PRINTER_ATTRIBUTE_DIRECT) != 0) { // No spooling varValue = VARIANT_FALSE; } else { // Spooling : YES varValue = VARIANT_TRUE; } // Attribute Found fAttribFound = TRUE; } */ if((dwAttributes & PRINTER_ATTRIBUTE_DIRECT) != 0) { // No spooling varValue = VARIANT_FALSE; } else { // Spooling : YES varValue = VARIANT_TRUE; } // Attribute Found fAttribFound = TRUE; } } } } } if(!fAttribFound) { // If not get the "spooler" key value from the win.ini file. If the entry is not present default to "yes". if(GetProfileString(lpctstrWindows, lpctstrSpooler, "yes", tchBuffer, MAX_PATH) > 1) { // Got the spooler Details if(_tcsicmp(tchBuffer, lpctstrYes) == 0) { // Spooling : YES varValue = VARIANT_TRUE; } else { // No spooling varValue = VARIANT_FALSE; } } } // Set the Spooling Property. hRes = pPCHPrinterInstance->SetVariant(pUsePrintMgrSpooling, varValue); if(FAILED(hRes)) { // Could not Set the USEPRINTMANAGERSPOOLING // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on usePrintManagerSpooling Field failed."); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // UNIDRV // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// pFileObj = NULL; // Get the complete path for unidrv.dll fDriverFound = getCompletePath(lpctstrUniDriver, bstrUniDriverWithPath); if(fDriverFound) { // Unidrv.dll present. Pass the File with PathName to // GetCIMDataFile function to get the file properties. if (SUCCEEDED(GetCIMDataFile(bstrUniDriverWithPath, &pFileObj))) { // From the CIM_DataFile Object get the properties and append them // Get the Version varValue.Clear(); hRes = pFileObj->Get(bstrVersion, 0, &varValue, NULL, NULL); if(SUCCEEDED(hRes)) { // Got the Version. Append it to the bstrUnidriverDetails String if(varValue.vt == VT_BSTR) { bstrUnidriverDetails.Append(varValue.bstrVal); // Append Space bstrUnidriverDetails.Append(lpctstrSpace); } } // Get the FileSize varValue.Clear(); hRes = pFileObj->Get(bstrFileSize, 0, &varValue, NULL, NULL); if(SUCCEEDED(hRes)) { // Got the FileSize. Append it to the bstrUnidriverDetails String if(varValue.vt == VT_BSTR) { bstrUnidriverDetails.Append(varValue.bstrVal); // Append Space bstrUnidriverDetails.Append(lpctstrSpace); } } // Get the Date&Time varValue.Clear(); hRes = pFileObj->Get(bstrModifiedDate, 0, &varValue, NULL, NULL); if(SUCCEEDED(hRes)) { if(varValue.vt == VT_BSTR) { wbemtimeUnidriver = varValue.bstrVal; if(wbemtimeUnidriver.GetStructtm(&tm)) { // Got the time in tm Struct format // Convert it into a string varValue = asctime(&tm); //Append it to the bstrUnidriverDetails String bstrUnidriverDetails.Append(varValue.bstrVal); } } } // Copy the string into the varValue varValue.vt = VT_BSTR; varValue.bstrVal = bstrUnidriverDetails.Detach(); }// end of if succeeded CIM_DataFile } // end of if driver Found else { // unidrv.dll not present varValue.Clear(); varValue = lpctstrNoUniDrv; } hRes = pPCHPrinterInstance->SetVariant(pUniDrv, varValue); if(FAILED(hRes)) { // Could not Set the Unidriver property // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on Uni Driver Field failed."); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // GENDRV // ///////////////////////////////////////////////////////////////////////////////////////////////////////////// pFileObj = NULL; // Get the complete path for gendrv.dll fDriverFound = getCompletePath(lpctstrGenDriver, bstrGenDriverWithPath); if(fDriverFound) { // Gendrv.dll present. Pass the File with PathName to // GetCIMDataFile function to get the file properties. if(SUCCEEDED(GetCIMDataFile(bstrGenDriverWithPath, &pFileObj))) { // From the CIM_DataFile Object get the properties and append them // Get the Version varValue.Clear(); hRes = pFileObj->Get(bstrVersion, 0, &varValue, NULL, NULL); if(SUCCEEDED(hRes)) { // Got the Version. Append it to the bstrUnidriverDetails String if(varValue.vt == VT_BSTR) { bstrGenDriverDetails.Append(varValue.bstrVal); // Append Space bstrGenDriverDetails.Append(lpctstrSpace); } } // Get the FileSize varValue.Clear(); hRes = pFileObj->Get(bstrFileSize, 0, &varValue, NULL, NULL); if(SUCCEEDED(hRes)) { if(varValue.vt == VT_BSTR) { // Got the FileSize. Append it to the bstrUnidriverDetails String bstrGenDriverDetails.Append(varValue.bstrVal); // Append Space bstrGenDriverDetails.Append(lpctstrSpace); } } // Get the Date&Time varValue.Clear(); hRes = pFileObj->Get(bstrModifiedDate, 0, &varValue, NULL, NULL); if(SUCCEEDED(hRes)) { if(varValue.vt == VT_BSTR) { wbemtimeGendriver = varValue.bstrVal; if(wbemtimeGendriver.GetStructtm(&tm)) { // Got the time in tm Struct format // Convert it into a string varValue = asctime(&tm); bstrGenDriverDetails.Append(varValue.bstrVal); } } } // Copy the string into the varValue varValue.vt = VT_BSTR; varValue.bstrVal = bstrGenDriverDetails.Detach(); }// end of if succeeded CIM_DataFile } // end of if driver Found else { // gendrv.dll not present varValue.Clear(); varValue = lpctstrNoGenDrv; } hRes = pPCHPrinterInstance->SetVariant(pGenDrv, varValue); if(FAILED(hRes)) { // Could not Set the GenDrv Field // Continue anyway ErrorTrace(TRACE_ID, "Set Variant on GenDrv Field failed."); } // All the properties are set. hRes = pPCHPrinterInstance->Commit(); if(FAILED(hRes)) { // Could not Set the GenDrv Field // Continue anyway ErrorTrace(TRACE_ID, "Error on commiting!"); } TraceFunctLeave(); return hRes ; }