/****************************************************************** PrintSys.CPP -- WMI provider class implementation Generated by Microsoft WMI Code Generation Engine TO DO: - See individual function headers - When linking, make sure you link to framedyd.lib & msvcrtd.lib (debug) or framedyn.lib & msvcrt.lib (retail). Description: ******************************************************************/ #include "pchealth.h" #include "PrintSys.h" ///////////////////////////////////////////////////////////////////////////// // tracing stuff #ifdef THIS_FILE #undef THIS_FILE #endif static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile #define TRACE_ID DCID_PRINTERDRIVER ///////////////////////////////////////////////////////////////////////////// // initialization CPrintSys MyPrintSysSet (PROVIDER_NAME_PRINTSYS, PCH_NAMESPACE) ; ///////////////////////////////////////////////////////////////////////////// // Property names const static WCHAR *c_wszGenDrv = L"GenDrv"; const static WCHAR *c_wszName = L"Name"; const static WCHAR *c_wszPath = L"Path"; const static WCHAR *c_wszUniDrv = L"UniDrv"; const static WCHAR *c_wszUsePrintMgrSpooling = L"UsePrintMgrSpooling"; ////////////////////////////////////////////////////////////////////////////// // construction / destruction // *************************************************************************** CPrintSys::CPrintSys (LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) : Provider(lpwszName, lpwszNameSpace) { m_pParamOut = NULL; m_pCurrent = NULL; m_pParamIn = NULL; m_lFlags = 0; } // *************************************************************************** CPrintSys::~CPrintSys() { } ////////////////////////////////////////////////////////////////////////////// // exposed methods // ***************************************************************************** HRESULT CPrintSys::EnumerateInstances(MethodContext *pMethodContext, long lFlags) { TraceFunctEnter("CPrintSys::EnumerateInstances"); HRESULT hr = WBEM_S_NO_ERROR; // Create a new instance of PCH_Printer Class based on the passed-in MethodContext CInstancePtr pPrintSysInst(CreateNewInstance(pMethodContext), false); hr = this->GetObject(pPrintSysInst, 0); TraceFunctLeave(); return hr; } // ***************************************************************************** HRESULT CPrintSys::ExecMethod (const CInstance& Instance, const BSTR bstrMethodName, CInstance *pInParams, CInstance *pOutParams, long lFlags) { return WBEM_E_PROVIDER_NOT_CAPABLE; } // ***************************************************************************** HRESULT CPrintSys::GetObject(CInstance* pInstance, long lFlags) { TraceFunctEnter("CPrintSys::GetObject"); HRESULT hr = WBEM_S_NO_ERROR; // Objects IWbemClassObjectPtr pFileObj = NULL; // Variants CComVariant varValue; CComVariant varNotAvail = L"Not Available"; // Strings CComBSTR bstrDriverWithPath; CComBSTR bstrDetails; CComBSTR bstrVersion = L"Version"; CComBSTR bstrFileSize = L"FileSize"; CComBSTR bstrModifiedDate = L"LastModified"; LPCTSTR lpctstrUniDriver = _T("unidrv.dll"); LPCTSTR lpctstrGenDriver = _T("gendrv.dll"); LPCTSTR lpctstrWindows = _T("Windows"); LPCTSTR lpctstrDevice = _T("Device"); 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_PATH + 1]; TCHAR tchPrinterKeyName[MAX_PATH + 1]; TCHAR *ptchToken; // Booleans BOOL fDriverFound = FALSE; BOOL fAttribFound = FALSE; // DWORDs DWORD dwSize; DWORD dwIndex; DWORD dwType; // Return Values; ULONG ulPrinterAttribs; LONG lRegRetVal; struct tm tm; WBEMTime wbemtime; HKEY hkeyPrinter = NULL; HKEY hkeyPrinters = NULL; FILETIME ft; // *** Set the properties associated with the default printer // In "win.ini" file under "Windows" section "Device" represents the default printer if(GetProfileString(lpctstrWindows, lpctstrDevice, "\0", tchBuffer, MAX_PATH) > 1) { // 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, _T(",")); if(ptchToken != NULL) { // ** name (token 1) varValue = ptchToken; if (pInstance->SetVariant(c_wszName, varValue) == FALSE) ErrorTrace(TRACE_ID, "SetVariant on Name failed."); // ** path (token 3) ptchToken = _tcstok(NULL, _T(",")); if(ptchToken != NULL) { // gotta skip the 2nd token cuz it's the printer dirver & we // don't give a rat's patoshki about it at this moment... ptchToken = _tcstok(NULL, _T(",")); if(ptchToken != NULL) { varValue = ptchToken; if (pInstance->SetVariant(c_wszPath, varValue) == FALSE) ErrorTrace(TRACE_ID, "Set Variant on Path failed."); } } } } // couldn't fetch the properties of the default printer, so shove in some // default values... else { // set Name to "Not Available" if (pInstance->SetVariant(c_wszName, varNotAvail) == FALSE) ErrorTrace(TRACE_ID, "Se Variant on Name failed."); // set Path to "Not Available" if (pInstance->SetVariant(c_wszPath, varValue) == FALSE) ErrorTrace(TRACE_ID, "Set Variant on Path failed."); } // *** Set the properties associated with using print manager spooling // First try to get the Spooling information from the registry which is // available if there are any installed printers // HKLM\system\CCS\Control\Print\Printers lRegRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpctstrPrintersHive, 0, KEY_READ, &hkeyPrinters); if(lRegRetVal == ERROR_SUCCESS) { // Enumerate the keys under this hive. ZeroMemory(&ft, sizeof(ft)); dwIndex = 0; dwSize = MAX_PATH; lRegRetVal = RegEnumKeyEx(hkeyPrinters, dwIndex, tchPrinterKeyName, &dwSize, NULL, NULL, NULL, &ft); 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 = sizeof(DWORD); lRegRetVal = RegQueryValueEx(hkeyPrinter, lpctstrAttributes, NULL, &dwType, (LPBYTE)&ulPrinterAttribs, &dwSize); if(lRegRetVal == ERROR_SUCCESS) { // if the PRINTER_ATTRIBUTE_DIRECT bit in ulPrinterAttribs // is set, then we have spooling... if((ulPrinterAttribs & PRINTER_ATTRIBUTE_DIRECT) != 0) varValue = VARIANT_FALSE; else varValue = VARIANT_TRUE; if (ulPrinterAttribs > 0) fAttribFound = TRUE; } } } } if (hkeyPrinter != NULL) { RegCloseKey(hkeyPrinter); hkeyPrinter = NULL; } if (hkeyPrinters != NULL) { RegCloseKey(hkeyPrinters); hkeyPrinters = NULL; } if(fAttribFound == FALSE) { // 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, _T("yes"), tchBuffer, MAX_PATH) > 1) { // if it's yes, then we have spooling... if(_tcsicmp(tchBuffer, lpctstrYes) == 0) varValue = VARIANT_TRUE; else varValue = VARIANT_FALSE; } } // Set the Spooling Property. if (pInstance->SetVariant(c_wszUsePrintMgrSpooling, varValue) == FALSE) ErrorTrace(TRACE_ID, "SetVariant on usePrintManagerSpooling failed."); // *** Set the properties associated with using print manager spooling // Get the complete path for unidrv.dll fDriverFound = getCompletePath(lpctstrUniDriver, bstrDriverWithPath); if(fDriverFound) { // Need to use GetCIMDataFile to get the unidriver properties if (SUCCEEDED(GetCIMDataFile(bstrDriverWithPath, &pFileObj))) { bstrDetails.Empty(); // Get the Version & append it to the value string... varValue.Clear(); hr = pFileObj->Get(bstrVersion, 0, &varValue, NULL, NULL); if(SUCCEEDED(hr)) { if(varValue.vt == VT_BSTR) { bstrDetails.Append(varValue.bstrVal); bstrDetails.Append(_T(" ")); } } // Get the FileSize & append it to the value string... varValue.Clear(); hr = pFileObj->Get(bstrFileSize, 0, &varValue, NULL, NULL); if(SUCCEEDED(hr)) { if(varValue.vt == VT_BSTR) { bstrDetails.Append(varValue.bstrVal); bstrDetails.Append(_T(" ")); } } // Get the date & time & append them to the value string... varValue.Clear(); hr = pFileObj->Get(bstrModifiedDate, 0, &varValue, NULL, NULL); if(SUCCEEDED(hr)) { if(varValue.vt == VT_BSTR) { WCHAR *pwsz; // there is a slight problem when WMI returns to us a // time that has a '*' in it. The WBEMTime class plain // refuses to deal with it. So change '*'s to '0's... for (pwsz = varValue.bstrVal; *pwsz != L'\0'; pwsz++) { if (*pwsz == L'*') *pwsz = L'0'; } wbemtime = varValue.bstrVal; if(wbemtime.GetStructtm(&tm)) { varValue = asctime(&tm); bstrDetails.Append(varValue.bstrVal); } } } // set the value varValue.vt = VT_BSTR; varValue.bstrVal = bstrDetails.Detach(); } // Since I don't seem to have unindrv.dll installed, I can't verify // this, but going by the other WMI providers, GetObject doesn't seem // to like it when u release objects fetched by it. So, I am not // going to release it. if (pFileObj != NULL) { // pFileObj->Release(); pFileObj = NULL; } } // the unidriver dll isn't present. Use a default value else { varValue.Clear(); varValue = lpctstrNoUniDrv; } // set the property if (pInstance->SetVariant(c_wszUniDrv, varValue) == FALSE) ErrorTrace(TRACE_ID, "SetVariant on UniDriver failed."); // *** Set the properties associated with using print manager spooling // Get the complete path for gendrv.dll bstrDriverWithPath.Empty(); fDriverFound = getCompletePath(lpctstrGenDriver, bstrDriverWithPath); if(fDriverFound) { bstrDetails.Empty(); // Need to use GetCIMDataFile to get the gen driver properties if(SUCCEEDED(GetCIMDataFile(bstrDriverWithPath, &pFileObj))) { // Get the Version & append it to the value string... varValue.Clear(); hr = pFileObj->Get(bstrVersion, 0, &varValue, NULL, NULL); if(SUCCEEDED(hr)) { if(varValue.vt == VT_BSTR) { bstrDetails.Append(varValue.bstrVal); bstrDetails.Append(_T(" ")); } } // Get the FileSize & append it to the value string... varValue.Clear(); hr = pFileObj->Get(bstrFileSize, 0, &varValue, NULL, NULL); if(SUCCEEDED(hr)) { if(varValue.vt == VT_BSTR) { bstrDetails.Append(varValue.bstrVal); bstrDetails.Append(_T(" ")); } } // Get the date & time & append them to the value string... varValue.Clear(); hr = pFileObj->Get(bstrModifiedDate, 0, &varValue, NULL, NULL); if(SUCCEEDED(hr)) { if(varValue.vt == VT_BSTR) { WCHAR *pwsz; // there is a slight problem when WMI returns to us a // time that has a '*' in it. The WBEMTime class plain // refuses to deal with it. So change '*'s to '0's... for (pwsz = varValue.bstrVal; *pwsz != L'\0'; pwsz++) { if (*pwsz == L'*') *pwsz = L'0'; } wbemtime = varValue.bstrVal; if(wbemtime.GetStructtm(&tm)) { varValue = asctime(&tm); bstrDetails.Append(varValue.bstrVal); } } } // set the value varValue.vt = VT_BSTR; varValue.bstrVal = bstrDetails.Detach(); } // Since I don't seem to have gendrv.dll installed, I can't verify // this, but going by the other WMI providers, GetObject doesn't seem // to like it when u release objects fetched by it. So, I am not // going to release it. if (pFileObj != NULL) { // pFileObj->Release(); pFileObj = NULL; } } // the gen driver dll is not present... else { varValue.Clear(); varValue = lpctstrNoGenDrv; } if (pInstance->SetVariant(c_wszGenDrv, varValue) == FALSE) ErrorTrace(TRACE_ID, "SetVariant on GenDrv failed."); // WOOHOO!! We can commit now hr = pInstance->Commit(); if(FAILED(hr)) ErrorTrace(TRACE_ID, "Error on commiting!"); TraceFunctLeave(); return hr; } // ***************************************************************************** HRESULT CPrintSys::ExecQuery(MethodContext *pMethodContext, CFrameworkQuery& Query, long lFlags) { return WBEM_E_PROVIDER_NOT_CAPABLE; } // ***************************************************************************** HRESULT CPrintSys::PutInstance(const CInstance& Instance, long lFlags) { return WBEM_E_PROVIDER_NOT_CAPABLE; } // ***************************************************************************** HRESULT CPrintSys::DeleteInstance(const CInstance& Instance, long lFlags) { return WBEM_E_PROVIDER_NOT_CAPABLE; }