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.
554 lines
24 KiB
554 lines
24 KiB
/********************************************************************
|
|
|
|
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<IEnumWbemClassObject> 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 ;
|
|
|
|
}
|