Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

930 lines
21 KiB

/*++
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);
}