|
|
/*++
Copyright (c) 1995-1996 Microsoft Corporation
Module Name:
cjob.cxx
Abstract: Contains methods for Print Job object and its property sets for the Windows NT provider. Objects whose methods are supported here are
CWinNTPrintJob, CWinNTPrintJob and CWinNTPrintJob.
Author:
Ram Viswanathan (ramv) 11-18-95
Revision History:
--*/
#include "winnt.hxx"
#pragma hdrstop
#define INITGUID
//
// class CWinNTPrintJob Methods
//
DEFINE_IDispatch_ExtMgr_Implementation(CWinNTPrintJob); DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTPrintJob); DEFINE_IADs_TempImplementation(CWinNTPrintJob); DEFINE_IADs_PutGetImplementation(CWinNTPrintJob, PrintJobClass,gdwJobTableSize); DEFINE_IADsPropertyList_Implementation(CWinNTPrintJob, PrintJobClass,gdwJobTableSize)
CWinNTPrintJob::CWinNTPrintJob() { _pDispMgr = NULL; _pExtMgr = NULL; _hprinter = NULL; _lJobId = 0; _pszPrinterName = NULL; _pszPrinterPath = NULL; _pPropertyCache = NULL; ENLIST_TRACKING(CWinNTPrintJob); return;
}
CWinNTPrintJob::~CWinNTPrintJob() {
if(_pszPrinterName){ FreeADsStr(_pszPrinterName); }
if(_pszPrinterPath){ FreeADsStr(_pszPrinterPath); }
_hprinter = NULL;
delete _pExtMgr; // created last, destroyed first
delete _pDispMgr; delete _pPropertyCache;
return; }
HRESULT CWinNTPrintJob::CreatePrintJob( LPTSTR pszPrinterPath, LONG lJobId, DWORD dwObjectState, REFIID riid, CWinNTCredentials& Credentials, LPVOID *ppvoid ) { CWinNTPrintJob *pCWinNTPrintJob = NULL; HRESULT hr; TCHAR szJobName[MAX_LONG_LENGTH]; POBJECTINFO pObjectInfo = NULL; TCHAR szUncPrinterName[MAX_PATH];
//
// Create the job object
//
hr = AllocatePrintJobObject(pszPrinterPath, &pCWinNTPrintJob ); BAIL_ON_FAILURE(hr);
ADsAssert(pCWinNTPrintJob->_pDispMgr);
//
// convert the JobId that we have into a string that we move
// into the Name field
//
_ltow(lJobId, szJobName, 10);
hr = pCWinNTPrintJob->InitializeCoreObject(pszPrinterPath, szJobName, PRINTJOB_CLASS_NAME, PRINTJOB_SCHEMA_NAME, CLSID_WinNTPrintJob, dwObjectState);
BAIL_ON_FAILURE(hr);
hr = BuildObjectInfo(pszPrinterPath, &pObjectInfo);
BAIL_ON_FAILURE(hr);
hr = PrinterNameFromObjectInfo(pObjectInfo, szUncPrinterName); BAIL_ON_FAILURE(hr);
pCWinNTPrintJob->_Credentials = Credentials; hr = pCWinNTPrintJob->_Credentials.RefServer( pObjectInfo->ComponentArray[1]); BAIL_ON_FAILURE(hr);
pCWinNTPrintJob->_pszPrinterName = AllocADsStr(szUncPrinterName);
if(!(pCWinNTPrintJob->_pszPrinterName)){ hr = E_OUTOFMEMORY; goto error; }
pCWinNTPrintJob->_lJobId = lJobId;
hr = SetLPTSTRPropertyInCache(pCWinNTPrintJob->_pPropertyCache, TEXT("HostPrintQueue"), pszPrinterPath, TRUE );
//
// Load ext mgr and extensions
//
hr = ADSILoadExtensionManager( PRINTJOB_CLASS_NAME, (IADsPrintJob *) pCWinNTPrintJob, pCWinNTPrintJob->_pDispMgr, Credentials, &pCWinNTPrintJob->_pExtMgr ); BAIL_ON_FAILURE(hr);
ADsAssert(pCWinNTPrintJob->_pExtMgr);
// check if the call is from UMI
if(Credentials.GetFlags() & ADS_AUTH_RESERVED) { //
// we do not pass riid to InitUmiObject below. This is because UMI object
// does not support IDispatch. There are several places in ADSI code where
// riid passed into this function is defaulted to IID_IDispatch -
// IADsContainer::Create for example. To handle these cases, we always
// request IID_IUnknown from the UMI object. Subsequent code within UMI
// will QI for the appropriate interface.
//
// Printjob objects have "" as their ADsPath. Just set the class for
// iddentification purposes.
pCWinNTPrintJob->_CompClasses[0] = L"PrintJob";
hr = pCWinNTPrintJob->InitUmiObject( pCWinNTPrintJob->_Credentials, PrintJobClass, gdwJobTableSize, pCWinNTPrintJob->_pPropertyCache, (IUnknown *)(INonDelegatingUnknown *) pCWinNTPrintJob, pCWinNTPrintJob->_pExtMgr, IID_IUnknown, ppvoid );
BAIL_ON_FAILURE(hr);
FreeObjectInfo(pObjectInfo);
//
// UMI object was created and the interface was obtained successfully.
// UMI object now has a reference to the inner unknown of IADs, since
// the call to Release() below is not going to be made in this case.
//
RRETURN(hr); }
hr = pCWinNTPrintJob->QueryInterface( riid,(void **)ppvoid);
BAIL_ON_FAILURE(hr);
pCWinNTPrintJob->Release(); FreeObjectInfo(pObjectInfo);
RRETURN(hr);
error:
FreeObjectInfo(pObjectInfo); delete pCWinNTPrintJob; RRETURN (hr); }
HRESULT CWinNTPrintJob::AllocatePrintJobObject( LPTSTR pszPrinterPath, CWinNTPrintJob ** ppPrintJob ) { CWinNTPrintJob FAR * pPrintJob = NULL; HRESULT hr = S_OK;
pPrintJob = new CWinNTPrintJob(); if (pPrintJob == NULL) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr);
pPrintJob->_pszPrinterPath = AllocADsStr(pszPrinterPath);
if(!(pPrintJob->_pszPrinterPath)){ hr = E_OUTOFMEMORY; goto error; }
pPrintJob->_pDispMgr = new CAggregatorDispMgr;
if (pPrintJob->_pDispMgr == NULL) { hr = E_OUTOFMEMORY; } BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry( pPrintJob->_pDispMgr, LIBID_ADs, IID_IADsPrintJob, (IADsPrintJob *)pPrintJob, DISPID_REGULAR ); BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry( pPrintJob->_pDispMgr, LIBID_ADs, IID_IADsPrintJobOperations, (IADsPrintJobOperations *)pPrintJob, DISPID_REGULAR ); BAIL_ON_FAILURE(hr);
hr = LoadTypeInfoEntry( pPrintJob->_pDispMgr, LIBID_ADs, IID_IADsPropertyList, (IADsPropertyList *)pPrintJob, DISPID_VALUE ); BAIL_ON_FAILURE(hr);
hr = CPropertyCache::createpropertycache( PrintJobClass, gdwJobTableSize, (CCoreADsObject *)pPrintJob, &(pPrintJob->_pPropertyCache) ); BAIL_ON_FAILURE(hr);
(pPrintJob->_pDispMgr)->RegisterPropertyCache( pPrintJob->_pPropertyCache );
*ppPrintJob = pPrintJob;
RRETURN(hr);
error:
//
// direct memeber assignement assignement at pt of creation, so
// do NOT delete _pPropertyCache or _pDisMgr here to avoid attempt
// of deletion again in pPrintJob destructor and AV
//
delete pPrintJob;
RRETURN_EXP_IF_ERR(hr);
}
/* IUnknown methods for printer object */
//----------------------------------------------------------------------------
// Function: QueryInterface
//
// Synopsis: If this object is aggregated within another object, then
// all calls will delegate to the outer object. Otherwise, the
// non-delegating QI is called
//
// Arguments:
//
// iid interface requested
// ppInterface Returns pointer to interface requested. NULL if interface
// is not supported.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer
//
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTPrintJob::QueryInterface( REFIID iid, LPVOID *ppInterface ) { if(_pUnkOuter != NULL) RRETURN(_pUnkOuter->QueryInterface( iid, ppInterface ));
RRETURN(NonDelegatingQueryInterface( iid, ppInterface )); }
//----------------------------------------------------------------------------
// Function: AddRef
//
// Synopsis: IUnknown::AddRef. If this object is aggregated within
// another, all calls will delegate to the outer object.
// Otherwise, the non-delegating AddRef is called
//
// Arguments:
//
// None
//
// Returns: New reference count
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CWinNTPrintJob::AddRef(void) { if(_pUnkOuter != NULL) RRETURN(_pUnkOuter->AddRef());
RRETURN(NonDelegatingAddRef()); }
//----------------------------------------------------------------------------
// Function: Release
//
// Synopsis: IUnknown::Release. If this object is aggregated within
// another, all calls will delegate to the outer object.
// Otherwise, the non-delegating Release is called
//
// Arguments:
//
// None
//
// Returns: New reference count
//
// Modifies: Nothing
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CWinNTPrintJob::Release(void) { if(_pUnkOuter != NULL) RRETURN(_pUnkOuter->Release());
RRETURN(NonDelegatingRelease()); }
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTPrintJob::NonDelegatingQueryInterface(REFIID riid, LPVOID FAR* ppvObj) { HRESULT hr = S_OK;
if(!ppvObj){ RRETURN(E_POINTER); }
if (IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (IADsPrintJob *)this; } else if (IsEqualIID(riid, IID_IDispatch)) { *ppvObj = (IADsPrintJob *)this; } else if (IsEqualIID(riid, IID_ISupportErrorInfo)) { *ppvObj = (ISupportErrorInfo FAR *)this; } else if (IsEqualIID(riid, IID_IADs)) { *ppvObj = (IADsPrintJob FAR *) this; } else if (IsEqualIID(riid, IID_IADsPropertyList)) { *ppvObj = (IADsPropertyList FAR *) this; } else if (IsEqualIID(riid, IID_IADsPrintJob)) { *ppvObj = (IADsPrintJob FAR *) this; } else if (IsEqualIID(riid, IID_IADsPrintJobOperations)) { *ppvObj = (IADsPrintJobOperations FAR *) this; } else if( (_pDispatch != NULL) && IsEqualIID(riid, IID_IADsExtension) ) { *ppvObj = (IADsExtension *) this; } else if (_pExtMgr) { RRETURN( _pExtMgr->QueryInterface(riid, ppvObj)); } else { *ppvObj = NULL; RRETURN(E_NOINTERFACE); } ((LPUNKNOWN)*ppvObj)->AddRef(); RRETURN(S_OK); }
/* ISupportErrorInfo method */ STDMETHODIMP CWinNTPrintJob::InterfaceSupportsErrorInfo( THIS_ REFIID riid ) { if (IsEqualIID(riid, IID_IADs) || IsEqualIID(riid, IID_IADsPrintJob) || IsEqualIID(riid, IID_IADsPrintJobOperations) |\ IsEqualIID(riid, IID_IADsPropertyList)) { RRETURN(S_OK); } else { RRETURN(S_FALSE); } }
//+-----------------------------------------------------------------
//
// Function: SetInfo
//
// Synopsis: Binds to real printer as specified in _PrinterName and attempts
// to set the real printer.
//
// Arguments: void
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 11/08/95 RamV Created
// part of code appropriated from NetOle project
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTPrintJob::SetInfo(THIS) { BOOL fStatus = FALSE; LPJOB_INFO_2 lpJobInfo2 = NULL; HRESULT hr;
//
// do a getinfo to refresh those properties that arent being set
//
hr = GetJobInfo(2, (LPBYTE*)&lpJobInfo2, _pszPrinterName, _lJobId);
BAIL_IF_ERROR(hr);
hr = MarshallAndSet(lpJobInfo2, _pszPrinterName, _lJobId); BAIL_IF_ERROR(hr);
if(SUCCEEDED(hr)) _pPropertyCache->ClearModifiedFlags();
cleanup: if(lpJobInfo2){ FreeADsMem((LPBYTE)lpJobInfo2); } RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP CWinNTPrintJob::GetInfo(THIS_ DWORD dwApiLevel, BOOL fExplicit) { LPJOB_INFO_1 lpJobInfo1 = NULL; LPJOB_INFO_2 lpJobInfo2 = NULL; HRESULT hr = S_OK;
switch (dwApiLevel) { case 1: hr = GetJobInfo(dwApiLevel, (LPBYTE*)&lpJobInfo1, _pszPrinterName, _lJobId );
BAIL_IF_ERROR(hr);
hr = UnMarshallLevel1(lpJobInfo1, fExplicit ); BAIL_IF_ERROR(hr); break;
case 2: hr = GetJobInfo(dwApiLevel, (LPBYTE *)&lpJobInfo2, _pszPrinterName, _lJobId );
BAIL_IF_ERROR(hr);
hr = UnMarshallLevel2(lpJobInfo2, fExplicit ); BAIL_IF_ERROR(hr); break;
default: hr = E_FAIL; break;
}
cleanup:
if (lpJobInfo1) { FreeADsMem(lpJobInfo1); }
if (lpJobInfo2) { FreeADsMem(lpJobInfo2); }
RRETURN_EXP_IF_ERR(hr); }
//+---------------------------------------------------------------------------
//
// Function: GetInfo
//
// Synopsis: Binds to real printer as specified in _PrinterName and attempts
// to get information from the real printer.
//
// Arguments: void
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 11/08/95 RamV Created
// part of code appropriated from NetOle project
//----------------------------------------------------------------------------
STDMETHODIMP CWinNTPrintJob::GetInfo(THIS) { RRETURN(GetInfo(2, TRUE)); }
STDMETHODIMP CWinNTPrintJob::ImplicitGetInfo(THIS) { RRETURN(GetInfo(2, FALSE)); }
STDMETHODIMP CWinNTPrintJob::get_Description(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsPrintJob *)this, Description); }
STDMETHODIMP CWinNTPrintJob::put_Description(THIS_ BSTR bstrDescription) { PUT_PROPERTY_BSTR((IADsPrintJob *)this, Description); }
STDMETHODIMP CWinNTPrintJob::get_HostPrintQueue(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsPrintJob *)this, HostPrintQueue); }
STDMETHODIMP CWinNTPrintJob::get_User(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsPrintJob *)this, User); }
STDMETHODIMP CWinNTPrintJob::get_UserPath(THIS_ BSTR FAR* retval) { RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED); }
STDMETHODIMP CWinNTPrintJob::put_Priority(THIS_ LONG lPriority) { PUT_PROPERTY_LONG((IADsPrintJob *)this, Priority); }
STDMETHODIMP CWinNTPrintJob::get_Priority(THIS_ LONG FAR* retval) { GET_PROPERTY_LONG((IADsPrintJob *)this, Priority); }
STDMETHODIMP CWinNTPrintJob::get_TimeSubmitted(THIS_ DATE FAR* retval) { GET_PROPERTY_DATE((IADsPrintJob *)this, TimeSubmitted); }
STDMETHODIMP CWinNTPrintJob::get_TotalPages(THIS_ LONG FAR* retval) { GET_PROPERTY_LONG((IADsPrintJob *)this, TotalPages); }
STDMETHODIMP CWinNTPrintJob::put_StartTime(THIS_ DATE daStartTime) { PUT_PROPERTY_DATE((IADsPrintJob *)this, StartTime); }
STDMETHODIMP CWinNTPrintJob::get_StartTime(THIS_ DATE FAR* retval) { GET_PROPERTY_DATE((IADsPrintJob *)this, StartTime); }
STDMETHODIMP CWinNTPrintJob::put_UntilTime(THIS_ DATE daUntilTime) { PUT_PROPERTY_DATE((IADsPrintJob *)this, UntilTime); }
STDMETHODIMP CWinNTPrintJob::get_UntilTime(THIS_ DATE FAR* retval) { GET_PROPERTY_DATE((IADsPrintJob *)this, UntilTime); }
STDMETHODIMP CWinNTPrintJob::get_Size(THIS_ LONG FAR* retval) { GET_PROPERTY_LONG((IADsPrintJob *)this, Size); }
STDMETHODIMP CWinNTPrintJob::put_Notify(THIS_ BSTR bstrNotify) { PUT_PROPERTY_BSTR((IADsPrintJob *)this, Notify); }
STDMETHODIMP CWinNTPrintJob::get_Notify(THIS_ BSTR FAR* retval) { GET_PROPERTY_BSTR((IADsPrintJob *)this, Notify); }
STDMETHODIMP CWinNTPrintJob::put_NotifyPath(THIS_ BSTR bstrNotify) { RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED); }
STDMETHODIMP CWinNTPrintJob::get_NotifyPath(THIS_ BSTR FAR* retval) { RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED); }
STDMETHODIMP CWinNTPrintJob::put_Position(THIS_ LONG lPosition) { PUT_PROPERTY_LONG((IADsPrintJob *)this, Position); }
STDMETHODIMP CWinNTPrintJob::get_Position(THIS_ LONG FAR* retval) { GET_PROPERTY_LONG((IADsPrintJob *)this, Position); }
STDMETHODIMP CWinNTPrintJob::get_PagesPrinted(THIS_ LONG FAR* retval) { GET_PROPERTY_LONG((IADsPrintJob *)this, PagesPrinted); }
STDMETHODIMP CWinNTPrintJob::get_TimeElapsed(THIS_ LONG FAR* retval) { GET_PROPERTY_LONG((IADsPrintJob *)this, TimeElapsed); }
//+------------------------------------------------------------------------
//
// Function: CWinNTPrintJob::Pause
//
// Synopsis: Binds to real printer as specified in _lpszPrinterName and attempts
// to pause this job.
//
// Arguments: none
//
// Returns: HRESULT.
//
// Modifies: nothing
//
// History: 11-07-95 RamV Created
//
//---------------------------------------------------------------------------
STDMETHODIMP CWinNTPrintJob::Pause(THIS) {
BOOL fStatus = FALSE; PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE}; HANDLE hPrinter = NULL; HRESULT hr = S_OK;
//
// we need to open the printer with the right printer
// defaults in order to perform the operations that we
// have here
//
fStatus = OpenPrinter((LPTSTR)_pszPrinterName, &hPrinter, &PrinterDefaults );
if (!fStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; }
fStatus = SetJob (hPrinter, _lJobId, 0, NULL, JOB_CONTROL_PAUSE );
if (!fStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; }
cleanup: fStatus = ClosePrinter(hPrinter); RRETURN_EXP_IF_ERR(hr); }
STDMETHODIMP CWinNTPrintJob::Resume(THIS) { BOOL fStatus = FALSE; PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE}; HANDLE hPrinter = NULL; HRESULT hr = S_OK;
//
// we need to open the printer with the right printer
// defaults in order to perform the operations that we
// have here
//
fStatus = OpenPrinter((LPTSTR)_pszPrinterName, &hPrinter, &PrinterDefaults );
if (!fStatus) { hr =HRESULT_FROM_WIN32(GetLastError()); goto cleanup; }
fStatus = SetJob (hPrinter, _lJobId, 0, NULL, JOB_CONTROL_RESUME );
if (!fStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup;
}
cleanup: fStatus = ClosePrinter(hPrinter); RRETURN_EXP_IF_ERR(hr); }
STDMETHODIMP CWinNTPrintJob::Remove(THIS) { BOOL fStatus = FALSE; PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE}; HANDLE hPrinter = NULL; HRESULT hr = S_OK;
fStatus = OpenPrinter((LPTSTR)_pszPrinterName, &hPrinter, &PrinterDefaults );
if (!fStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; }
//
// se JOB_CONTROL_DELETE instead of JOB_CONTROL_CANCEL as DELETE works
// even when a print job has been restarted while CANCLE won't
//
fStatus = SetJob (hPrinter, _lJobId, 0, NULL, JOB_CONTROL_DELETE );
if (!fStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup;
}
cleanup: fStatus = ClosePrinter(hPrinter); RRETURN_EXP_IF_ERR(hr); }
STDMETHODIMP CWinNTPrintJob::get_Status(THIS_ long FAR* retval) { HRESULT hr =S_OK; LPJOB_INFO_1 lpJobInfo1 = NULL; BOOL found; DWORD dwStatus;
if(!retval){ RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER); }
hr = GetJobInfo(1, (LPBYTE*)&lpJobInfo1, _pszPrinterName, _lJobId);
BAIL_IF_ERROR(hr);
//
// instead of a conversion routine, just return the WinNT
// Status code
//
*retval = lpJobInfo1->Status;
cleanup: if(lpJobInfo1){ FreeADsMem((LPBYTE)lpJobInfo1); } RRETURN_EXP_IF_ERR(hr); }
|