windows-nt/Source/XPSP1/NT/ds/adsi/winnt/cenumjob.cxx
2020-09-26 16:20:57 +08:00

1012 lines
22 KiB
C++

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
cenumjob.cxx
Abstract:
Contains methods for implementing the Enumeration of print jobs on a
printer. Has methods for the CWinNTPrintJobsCollection object
as well as the CWinNTJobsEnumVar object.
Author:
Ram Viswanathan (ramv) 11-28-95
Revision History:
--*/
#include "winnt.hxx"
#pragma hdrstop
CWinNTPrintJobsCollection::CWinNTPrintJobsCollection()
{
_pDispMgr = NULL;
_pCJobsEnumVar = NULL;
ENLIST_TRACKING(CWinNTPrintJobsCollection);
}
CWinNTPrintJobsCollection::~CWinNTPrintJobsCollection()
{
DWORD fStatus;
//
// close the printer and destroy sub objects
//
if(_pszADsPrinterPath){
FreeADsStr(_pszADsPrinterPath);
}
if(_pszPrinterName){
FreeADsStr(_pszPrinterName);
}
if (_hPrinter){
fStatus = ClosePrinter(_hPrinter);
}
delete _pDispMgr;
}
HRESULT
CWinNTPrintJobsCollection::Create(LPWSTR pszADsPrinterPath,
CWinNTCredentials& Credentials,
CWinNTPrintJobsCollection
** ppCWinNTPrintJobsCollection )
{
BOOL fStatus = FALSE, LastError;
HANDLE hPrinter = NULL;
PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE| READ_CONTROL};
HRESULT hr;
CWinNTPrintJobsCollection *pCWinNTJobsCollection = NULL;
POBJECTINFO pObjectInfo = NULL;
TCHAR szUncPrinterName[MAX_PATH];
//
// create the jobs collection object
//
pCWinNTJobsCollection = new CWinNTPrintJobsCollection();
if(pCWinNTJobsCollection == NULL) {
hr = E_OUTOFMEMORY;
goto error;
}
hr = BuildObjectInfo(pszADsPrinterPath,
&pObjectInfo
);
BAIL_ON_FAILURE(hr);
pCWinNTJobsCollection->_Credentials = Credentials;
hr = pCWinNTJobsCollection->_Credentials.RefServer(
pObjectInfo->ComponentArray[1]);
BAIL_ON_FAILURE(hr);
hr = PrinterNameFromObjectInfo(pObjectInfo,
szUncPrinterName
);
BAIL_ON_FAILURE(hr);
pCWinNTJobsCollection->_pszPrinterName =
AllocADsStr(szUncPrinterName);
if(!(pCWinNTJobsCollection->_pszPrinterName)){
hr = E_OUTOFMEMORY;
goto error;
}
pCWinNTJobsCollection->_pszADsPrinterPath =
AllocADsStr(pszADsPrinterPath);
if(!(pCWinNTJobsCollection->_pszADsPrinterPath)){
hr = E_OUTOFMEMORY;
goto error;
}
//
// open printer and set the handle to the appropriate value
//
fStatus = OpenPrinter(szUncPrinterName,
&hPrinter,
&PrinterDefaults
);
if (!fStatus) {
LastError = GetLastError();
switch (LastError) {
case ERROR_ACCESS_DENIED:
{
PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE};
fStatus = OpenPrinter(szUncPrinterName,
&hPrinter,
&PrinterDefaults
);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
break;
}
default:
hr = HRESULT_FROM_WIN32(GetLastError());
break;
}
}
BAIL_ON_FAILURE(hr);
pCWinNTJobsCollection->_hPrinter = hPrinter;
pCWinNTJobsCollection->_pDispMgr = new CAggregatorDispMgr;
if (pCWinNTJobsCollection->_pDispMgr == NULL){
hr = E_OUTOFMEMORY;
goto error;
}
hr = LoadTypeInfoEntry(pCWinNTJobsCollection->_pDispMgr,
LIBID_ADs,
IID_IADsCollection,
(IADsCollection *)pCWinNTJobsCollection,
DISPID_NEWENUM
);
BAIL_ON_FAILURE(hr);
*ppCWinNTPrintJobsCollection =pCWinNTJobsCollection;
if(pObjectInfo){
FreeObjectInfo(pObjectInfo);
}
RRETURN(hr);
error:
delete pCWinNTJobsCollection;
if(pObjectInfo){
FreeObjectInfo(pObjectInfo);
}
RRETURN_EXP_IF_ERR(hr);
}
/* IUnknown methods for jobs collection object */
STDMETHODIMP
CWinNTPrintJobsCollection::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
{
if(!ppvObj)
{
RRETURN(E_POINTER);
}
if (IsEqualIID(riid, IID_IUnknown))
{
*ppvObj = this;
}
else if (IsEqualIID(riid, IID_IDispatch))
{
*ppvObj = (IDispatch *)this;
}
else if (IsEqualIID(riid, IID_ISupportErrorInfo))
{
*ppvObj = (ISupportErrorInfo FAR *) this;
}
else if (IsEqualIID(riid, IID_IADsCollection))
{
*ppvObj = (IADsCollection FAR *)this;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
((LPUNKNOWN)*ppvObj)->AddRef();
RRETURN(S_OK);
}
/* ISupportErrorInfo method */
STDMETHODIMP
CWinNTPrintJobsCollection::InterfaceSupportsErrorInfo(
THIS_ REFIID riid
)
{
if (IsEqualIID(riid, IID_IADsCollection)) {
RRETURN(S_OK);
} else {
RRETURN(S_FALSE);
}
}
DEFINE_IDispatch_Implementation(CWinNTPrintJobsCollection);
/* IADsCollection methods */
STDMETHODIMP
CWinNTPrintJobsCollection::get__NewEnum(THIS_ IUnknown * FAR* retval)
{
HRESULT hr;
CWinNTJobsEnumVar *pCJobsEnumVar = NULL;
if(!retval){
RRETURN_EXP_IF_ERR(E_POINTER);
}
*retval = NULL;
hr = CWinNTJobsEnumVar::Create(_hPrinter,
_pszADsPrinterPath,
_Credentials,
&pCJobsEnumVar);
if (FAILED(hr)) {
goto error;
}
ADsAssert(pCJobsEnumVar);
_pCJobsEnumVar = pCJobsEnumVar;
hr = _pCJobsEnumVar->QueryInterface(IID_IUnknown,
(void **)retval
);
BAIL_ON_FAILURE(hr);
_pCJobsEnumVar->Release();
RRETURN(S_OK);
error:
delete pCJobsEnumVar;
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTPrintJobsCollection::GetObject(THIS_ BSTR bstrJobName,
VARIANT *pvar)
{
HRESULT hr;
DWORD dwJobId;
IDispatch *pDispatch = NULL;
if(!bstrJobName || !pvar){
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
}
dwJobId = (DWORD)_wtol(bstrJobName);
hr = CWinNTPrintJob::CreatePrintJob(_pszADsPrinterPath,
dwJobId,
ADS_OBJECT_BOUND,
IID_IDispatch,
_Credentials,
(void **)&pDispatch);
BAIL_IF_ERROR(hr);
//
// stick this IDispatch pointer into caller provided variant
//
VariantInit(pvar);
V_VT(pvar) = VT_DISPATCH;
V_DISPATCH(pvar) = pDispatch;
cleanup:
RRETURN_EXP_IF_ERR(hr);
}
STDMETHODIMP
CWinNTPrintJobsCollection::Add(THIS_ BSTR bstrName, VARIANT varNewItem)
{
RRETURN_EXP_IF_ERR(E_NOTIMPL);
}
STDMETHODIMP
CWinNTPrintJobsCollection::Remove(THIS_ BSTR bstrJobName)
{
DWORD dwJobId;
HRESULT hr = S_OK;
HANDLE hPrinter = NULL;
BOOL fStatus = FALSE;
PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE};
if(! bstrJobName){
RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
}
//
// convert the job name into a jobid
//
dwJobId = (DWORD)_wtol(bstrJobName);
fStatus = OpenPrinter((LPTSTR)_pszPrinterName,
&hPrinter,
&PrinterDefaults
);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto cleanup;
}
//
// use JOB_CONTROL_DELETE instead of JOB_CONTROL_CANCEL as DELETE works
// even when a print job has been restarted while CANCEL won't
//
fStatus = SetJob (hPrinter,
dwJobId,
0,
NULL,
JOB_CONTROL_DELETE
);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto cleanup;
}
cleanup:
if (hPrinter) {
ClosePrinter(hPrinter);
}
RRETURN (hr);
}
//
// CWinNTJobsEnumVar methods follow
//
//+---------------------------------------------------------------------------
//
// Function: CWinNTJobsEnumVar::CWinNTJobsEnumVar
//
// Synopsis:
//
//
// Arguments:
//
//
// Returns:
//
// Modifies:
//
// History: 11-22-95 RamV Created.
//
//----------------------------------------------------------------------------
CWinNTJobsEnumVar::CWinNTJobsEnumVar()
{
_pszADsPrinterPath = NULL;
_pSafeArray = NULL;
_cElements = 0;
_lLBound = 0;
_lCurrentPosition = _lLBound;
ENLIST_TRACKING(CWinNTJobsEnumVar);
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTJobsEnumVar::~CWinNTJobsEnumVar
//
// Synopsis:
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 11-22-95 RamV Created.
//
//----------------------------------------------------------------------------
CWinNTJobsEnumVar::~CWinNTJobsEnumVar()
{
if (_pSafeArray != NULL)
SafeArrayDestroy(_pSafeArray);
_pSafeArray = NULL;
if(_pszADsPrinterPath){
FreeADsStr(_pszADsPrinterPath);
}
}
HRESULT CWinNTJobsEnumVar::Create(HANDLE hPrinter,
LPTSTR szADsPrinterPath,
CWinNTCredentials& Credentials,
CWinNTJobsEnumVar ** ppCJobsEnumVar)
{
//
// This function uses the handle to the printer to query for the
// number of jobs(cJobs) on the printer, It uses the returned value
// to create a safearray of cJobs number of Job Objects.
//
HRESULT hr;
BOOL fStatus = FALSE;
PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE| READ_CONTROL};
OBJECTINFO ObjectInfo;
CLexer Lexer(szADsPrinterPath);
CWinNTJobsEnumVar FAR* pCJobsEnumVar = NULL;
*ppCJobsEnumVar = NULL;
memset((void*)&ObjectInfo, 0, sizeof(OBJECTINFO));
pCJobsEnumVar = new CWinNTJobsEnumVar();
if (pCJobsEnumVar == NULL){
hr = E_OUTOFMEMORY;
goto error;
}
pCJobsEnumVar->_pszADsPrinterPath = AllocADsStr(szADsPrinterPath);
if (!(pCJobsEnumVar->_pszADsPrinterPath)){
hr = E_OUTOFMEMORY;
goto error;
}
hr = Object(&Lexer, &ObjectInfo);
BAIL_ON_FAILURE(hr);
pCJobsEnumVar->_Credentials = Credentials;
// We want the next-to-last element in the array.
ADsAssert(ObjectInfo.NumComponents >= 2);
hr = pCJobsEnumVar->_Credentials.RefServer(
ObjectInfo.ComponentArray[(ObjectInfo.NumComponents - 1) - 1]);
BAIL_ON_FAILURE(hr);
//
// Fill in the safearray with relevant information here
//
hr = FillSafeArray(hPrinter, szADsPrinterPath, pCJobsEnumVar->_Credentials,
pCJobsEnumVar);
BAIL_ON_FAILURE(hr);
*ppCJobsEnumVar = pCJobsEnumVar;
//
// Free the objectInfo data
//
FreeObjectInfo( &ObjectInfo, TRUE );
RRETURN(S_OK);
error:
//
// Free the objectInfo data
//
FreeObjectInfo( &ObjectInfo, TRUE );
delete pCJobsEnumVar;
RRETURN_EXP_IF_ERR(hr);
}
//+------------------------------------------------------------------------
//
// Function: CWinNTJobsEnumVar::QueryInterface
//
// Synopsis:
//
// Arguments: [iid]
// [ppv]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 11-22-95 RamV Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTJobsEnumVar::QueryInterface(REFIID iid, void FAR* FAR* ppv)
{
if(!ppv){
RRETURN(E_POINTER);
}
*ppv = NULL;
if (iid == IID_IUnknown )
{
*ppv = this;
}
else if(iid == IID_IEnumVARIANT)
{
*ppv = (IEnumVARIANT *)this;
}
else
{
return E_NOINTERFACE;
}
AddRef();
RRETURN(S_OK);
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTJobsEnumVar::Next
//
// Synopsis: Returns cElements number of requested Job objects in the
// array supplied in pvar.
//
// Arguments: [cElements] -- The number of elements requested by client
// [pvar] -- ptr to array of VARIANTs to for return objects
// [pcElementFetched] -- if non-NULL, then number of elements
// -- actually returned is placed here
//
// Returns: HRESULT -- S_OK if number of elements requested are returned
// -- S_FALSE if number of elements is < requested
//
// Modifies:
//
// History: 11-27-95 RamV Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTJobsEnumVar::Next(ULONG ulNumElementsRequested,
VARIANT FAR* pvar,
ULONG FAR* pulNumFetched)
{
HRESULT hresult;
ULONG l;
LONG lNewCurrent;
ULONG lNumFetched;
if (pulNumFetched != NULL)
*pulNumFetched = 0;
//
// Initialize the elements to be returned
//
for (l=0; l<ulNumElementsRequested; l++)
VariantInit(&pvar[l]);
//
// Get each element and place it into the return array
// Don't request more than we have
//
for (lNewCurrent=_lCurrentPosition, lNumFetched=0;
lNewCurrent<(LONG)(_lLBound+_cElements) &&
lNumFetched < ulNumElementsRequested;
lNewCurrent++, lNumFetched++){
hresult = SafeArrayGetElement(_pSafeArray, &lNewCurrent,
&pvar[lNumFetched]);
//
// Something went wrong!!!
//
if (FAILED(hresult)){
for (l=0; l<ulNumElementsRequested; l++)
VariantClear(&pvar[l]);
ADsAssert(hresult == S_FALSE);
return(S_FALSE);
} // End of If Failed
}
//
// Tell the caller how many we got (which may be less than the number
// requested), and save the current position
//
if (pulNumFetched != NULL)
*pulNumFetched = lNumFetched;
_lCurrentPosition = lNewCurrent;
//
// If we're returning less than they asked for return S_FALSE, but
// they still have the data (S_FALSE is a success code)
//
return (lNumFetched < ulNumElementsRequested) ?
S_FALSE
: S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTJobsEnumVar::Skip
//
// Synopsis:
//
// Arguments: [cElements]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 11-22-95 RamV Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTJobsEnumVar::Skip(ULONG cElements)
{
//
// Skip the number of elements requested
//
_lCurrentPosition += cElements;
//
// if we went outside of the boundaries unskip
//
if (_lCurrentPosition > (LONG)(_lLBound +_cElements)){
_lCurrentPosition = _lLBound +_cElements;
return (S_FALSE);
}
else
RRETURN(S_OK);
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTJobsEnumVar::Reset
//
// Synopsis:
//
// Arguments: []
//
// Returns: HRESULT
//
// Modifies:
//
// History:
//
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTJobsEnumVar::Reset()
{
//
//Just move the CurrentPosition to the lower array boundary
//
_lCurrentPosition = _lLBound;
RRETURN(S_OK);
}
//+---------------------------------------------------------------------------
//
// Function: CWinNTJobsEnumVar::Clone
//
// Synopsis:
//
// Arguments: [pCollection]
// [ppEnumVariant]
//
// Returns: HRESULT
//
// Modifies:
//
// History: 11-22-95 RamV Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP
CWinNTJobsEnumVar::Clone(IEnumVARIANT FAR* FAR* ppenum)
{
RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
}
HRESULT FillSafeArray(HANDLE hPrinter,
LPTSTR szPrinterPath,
CWinNTCredentials& Credentials,
CWinNTJobsEnumVar *pJobsEnumVar )
{
BOOL fStatus = FALSE;
DWORD dwPassed =0, dwNeeded = 0;
DWORD dwcJobs; // Number of jobs in print queue
LPPRINTER_INFO_2 pPrinterInfo2;
DWORD dwError = 0, LastError =0;
LPBYTE pMem = NULL;
LPBYTE lpbJobs = NULL;
DWORD cbBuf =0;
DWORD dwReturned =0;
CWinNTPrintJob *pCWinNTPrintJob = NULL;
SAFEARRAYBOUND sabound[1];
IDispatch *pDispatch;
VARIANT v;
LONG l;
HRESULT hr = S_OK;
LPJOB_INFO_1 lpJobInfo1 = NULL;
if(hPrinter == NULL){
RRETURN_EXP_IF_ERR(HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE));
}
VariantInit(&v);
//
// First Get info from printer to determine the number of jobs.
// AjayR: 10-01-99. We always expect this call to fail but tell
// us how much memory is needed !!!
//
fStatus = GetPrinter(hPrinter,
2,
(LPBYTE)pMem,
dwPassed,
&dwNeeded
);
if (!fStatus) {
LastError = GetLastError();
switch (LastError) {
case ERROR_INSUFFICIENT_BUFFER:
if (pMem){
FreeADsMem(pMem);
}
dwPassed = dwNeeded;
pMem = (LPBYTE)AllocADsMem(dwPassed);
if (!pMem) {
hr = E_OUTOFMEMORY;
break;
}
fStatus = GetPrinter(hPrinter,
2,
(LPBYTE)pMem,
dwPassed,
&dwNeeded
);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
break;
default:
hr = HRESULT_FROM_WIN32(GetLastError());;
break;
}
}
if(FAILED(hr))
goto error;
pPrinterInfo2 =(LPPRINTER_INFO_2)pMem;
dwcJobs = pPrinterInfo2->cJobs;
fStatus = MyEnumJobs(hPrinter,
0, // First job you want
dwcJobs,
1, //Job Info level
&lpbJobs,
&cbBuf,
&dwReturned
);
if(!fStatus){
hr =HRESULT_FROM_WIN32(GetLastError());
goto error;
}
//
// Use the array bound as the number of jobs returned, not
// the number of jobs you requested, this may have changed!
//
sabound[0].cElements = dwReturned;
sabound[0].lLbound = 0;
//
// Create a one dimensional SafeArray
//
pJobsEnumVar->_pSafeArray = SafeArrayCreate(VT_VARIANT, 1, sabound);
if (pJobsEnumVar->_pSafeArray == NULL){
hr = E_OUTOFMEMORY;
goto error;
}
//
// for each of the Jobs retrieved create the appropriate structure
//
for(l=0; l<(LONG)dwReturned; l++){
lpJobInfo1 = (LPJOB_INFO_1)(lpbJobs +l*sizeof(JOB_INFO_1));
hr = CWinNTPrintJob::CreatePrintJob(
szPrinterPath,
lpJobInfo1->JobId,
ADS_OBJECT_BOUND,
IID_IDispatch,
Credentials,
(void **)&pDispatch
);
if(FAILED(hr)){
break;
}
VariantInit(&v);
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = pDispatch;
//
// Stick the caller provided data into the end of the SafeArray
//
hr = SafeArrayPutElement(pJobsEnumVar->_pSafeArray, &l, &v);
VariantClear(&v);
if (FAILED(hr)){
break;
}
pJobsEnumVar->_cElements++;
}
BAIL_ON_FAILURE(hr);
if (pMem) {
FreeADsMem(pMem);
}
if(lpbJobs){
FreeADsMem(lpbJobs);
}
RRETURN(S_OK);
error:
if (pMem) {
FreeADsMem(pMem);
}
//
// Free the buffer you just allocated
//
if (lpbJobs){
FreeADsMem(lpbJobs);
}
//
// Destroy the safearray
//
if(pJobsEnumVar->_pSafeArray != NULL)
SafeArrayDestroy(pJobsEnumVar->_pSafeArray);
VariantClear(&v);
RRETURN_EXP_IF_ERR(hr);
}
BOOL
MyEnumJobs(HANDLE hPrinter,
DWORD dwFirstJob,
DWORD dwNoJobs,
DWORD dwLevel,
LPBYTE *lplpbJobs,
DWORD *pcbBuf,
LPDWORD lpdwReturned
)
{
BOOL fStatus = FALSE;
DWORD dwNeeded = 0;
DWORD dwError = 0;
fStatus = EnumJobs(hPrinter,
dwFirstJob,
dwNoJobs,
dwLevel,
*lplpbJobs,
*pcbBuf,
&dwNeeded,
lpdwReturned
);
if (!fStatus) {
if ((dwError = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) {
if (*lplpbJobs) {
FreeADsMem( *lplpbJobs );
}
*lplpbJobs = (LPBYTE)AllocADsMem(dwNeeded);
if (!*lplpbJobs) {
*pcbBuf = 0;
return(FALSE);
}
*pcbBuf = dwNeeded;
fStatus = EnumJobs(hPrinter,
dwFirstJob,
dwNoJobs,
dwLevel,
*lplpbJobs,
*pcbBuf,
&dwNeeded,
lpdwReturned
);
if (!fStatus) {
return(FALSE);
}else {
return(TRUE);
}
}else {
return(FALSE);
}
}else {
return(TRUE);
}
}