/******************************************************************
   PrintJob.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 "PrintJob.h"


/////////////////////////////////////////////////////////////////////////////
//  tracing stuff

#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__;
#define THIS_FILE __szTraceSourceFile
#define TRACE_ID    DCID_PRINTERDRIVER


/////////////////////////////////////////////////////////////////////////////
//  initialization

CPrintJob MyPrintJobSet (PROVIDER_NAME_PRINTJOB, PCH_NAMESPACE) ;


/////////////////////////////////////////////////////////////////////////////
//  Property names

// PCH 
const static WCHAR *c_wszName          = L"Name";
const static WCHAR *c_wszPagesPrinted  = L"PagesPrinted";
const static WCHAR *c_wszSize          = L"Size";
const static WCHAR *c_wszStatus        = L"Status";
const static WCHAR *c_wszTimeSubmitted = L"TimeSubmitted";
const static WCHAR *c_wszUser          = L"User";
const static WCHAR *c_wszDocument      = L"Document";

// WMI
const static WCHAR *c_wszNotify        = L"Notify";
const static WCHAR *c_wszJobStatus     = L"JobStatus";

//////////////////////////////////////////////////////////////////////////////
// construction / destruction

// ***************************************************************************
CPrintJob::CPrintJob(LPCWSTR lpwszName, LPCWSTR lpwszNameSpace) :
    Provider(lpwszName, lpwszNameSpace)
{
}

// ***************************************************************************
CPrintJob::~CPrintJob()
{
}


//////////////////////////////////////////////////////////////////////////////
// internal methods

// ****************************************************************************
HRESULT CPrintJob::GetInstanceData(IWbemClassObjectPtr pObj, 
                                   CInstance *pInstance)
{

    // ** Name
    CopyProperty(pObj, c_wszName, pInstance, c_wszName);

    // ** Pages Printed
    CopyProperty(pObj, c_wszPagesPrinted, pInstance, c_wszPagesPrinted);
    
    // ** Size     
    CopyProperty(pObj, c_wszSize, pInstance, c_wszSize);
    
    // ** JobStatus
    CopyProperty(pObj, c_wszJobStatus, pInstance, c_wszStatus);
        
    // ** TimeSubmitted
    CopyProperty(pObj, c_wszTimeSubmitted, pInstance, c_wszTimeSubmitted);

    // ** User
    CopyProperty(pObj, c_wszNotify, pInstance, c_wszUser);

    // ** Document
    CopyProperty(pObj, c_wszDocument, pInstance, c_wszDocument);

    return NOERROR;
}


//////////////////////////////////////////////////////////////////////////////
// exposed methods

// ***************************************************************************
HRESULT CPrintJob::EnumerateInstances(MethodContext *pMethodContext, long lFlags)
{
    TraceFunctEnter("CPCH_PrintJob::EnumerateInstances");

    IEnumWbemClassObject    *pEnumInst = NULL;
    IWbemClassObjectPtr     pObj = NULL;
    CComBSTR                bstrQuery;   
    HRESULT                 hr = WBEM_S_NO_ERROR;
    ULONG                   ulRetVal;
    TCHAR                   wszUser[1024];
    DWORD                   cchUser = sizeof(wszUser) / sizeof(TCHAR);

    GetUserName(wszUser, &cchUser);


    // Execute the query
    bstrQuery = L"select Name, document, Notify, Size, JobStatus, TimeSubmitted, PagesPrinted from Win32_printJob";
    hr = ExecWQLQuery(&pEnumInst, bstrQuery);
    if (FAILED(hr))
        goto done;

    // enumerate the instances from Win32_PrintJob
    while(pEnumInst->Next(WBEM_INFINITE, 1, &pObj, &ulRetVal) == WBEM_S_NO_ERROR)
    {
        // Create a new instance based on the passed-in MethodContext
        CInstancePtr pInstance(CreateNewInstance(pMethodContext), FALSE);

        // since the old code didn't care if this failed, neither do I.
        hr = GetInstanceData(pObj, pInstance);
        
        // commit instance
        hr = pInstance->Commit();
        if (FAILED(hr))
            ErrorTrace(TRACE_ID, "Error committing instance");

        // Ok, so WMI does not follow it's own docs on how GetObject
        //  works.  According to them, we should release this object here.  But
        //  if I try, winmgmt GPFs.
        // pObj->Release();
        pObj = NULL;
    }

done:
    if (pEnumInst != NULL)
        pEnumInst->Release();

    TraceFunctLeave();
    return hr;
}

// *****************************************************************************
HRESULT CPrintJob::ExecMethod(const CInstance& Instance,
                              const BSTR bstrMethodName,
                              CInstance *pInParams, CInstance *pOutParams,
                              long lFlags)
{
    return (WBEM_E_PROVIDER_NOT_CAPABLE);
}

// *****************************************************************************
HRESULT CPrintJob::GetObject(CInstance* pInstance, long lFlags) 
{ 
    TraceFunctEnter("CPrintJob::GetObject");

    IWbemClassObjectPtr pObj = NULL;
    CComBSTR            bstrPath;
    HRESULT             hr = NOERROR;
    VARIANT             var;
    TCHAR               szDefault[MAX_PATH];
    TCHAR               *pchToken, *szDefName = NULL;
    DWORD               i;

    VariantInit(&var);

    if (pInstance == NULL)
    {
        hr = E_INVALIDARG;
        goto done;
    }

    // get the name of the printer
    if (pInstance->GetVariant(c_wszName, var) == FALSE)
    {
        ErrorTrace(TRACE_ID, "Unable to fetch printer name");
        hr = E_FAIL;
        goto done;
    }

    if (V_VT(&var) != VT_BSTR)
    {
        hr = VariantChangeType(&var, &var, 0, VT_BSTR);
        if (FAILED(hr))
        {
            ErrorTrace(TRACE_ID, "VariantChangeType failed: 0x%08x", hr);
            goto done;
        }
    }
   
    // get the default printer & path 
    if(GetProfileString(_T("Windows"), _T("Device"), "\0", szDefault, 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.
        pchToken = _tcstok(szDefault, _T(","));
        if(pchToken != NULL)
        {
            // ** default name
            szDefName = pchToken;
        }
    }
    
    // build the path to the object
    bstrPath = L"\\\\.\\root\\cimv2:Win32_PrintJob.Name=\"";
    bstrPath.Append(V_BSTR(&var));
    bstrPath.Append("\"");

    // fetch it
    hr = GetCIMObj(bstrPath, &pObj, lFlags);
    if (FAILED(hr))
        goto done;

    // populate the CInstance object
    hr = GetInstanceData(pObj, pInstance);
    if (FAILED(hr))
        goto done;
    
    //  All the properties are set. Commit the instance
    hr = pInstance->Commit();
    if(FAILED(hr))
        ErrorTrace(TRACE_ID, "Could not commit instance: 0x%08x", hr);

done:
    VariantClear(&var);

    // Ok, so WMI does not follow it's own docs on how GetObject
    //  works.  According to them, we should release this object here.  But
    //  if I try, winmgmt GPFs.
    // if (pObj != NULL)
    //    pObj->Release();

    TraceFunctLeave();
    return hr; 
}

// *****************************************************************************
HRESULT CPrintJob::ExecQuery(MethodContext *pMethodContext, 
                            CFrameworkQuery& Query, long lFlags) 
{ 
    return WBEM_E_PROVIDER_NOT_CAPABLE; 
}

// *****************************************************************************
HRESULT CPrintJob::PutInstance(const CInstance& Instance, long lFlags)
{ 
    return WBEM_E_PROVIDER_NOT_CAPABLE; 
}

// *****************************************************************************
HRESULT CPrintJob::DeleteInstance(const CInstance& Instance, long lFlags)
{ 
    return WBEM_E_PROVIDER_NOT_CAPABLE; 
}
