817 lines
19 KiB
C++
817 lines
19 KiB
C++
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cprinter.cxx
|
|
|
|
Abstract:
|
|
Contains methods for PrintQueue object, GeneralInfo property set
|
|
and Operation property set for the Print Queue object for the Windows NT
|
|
provider
|
|
|
|
Author:
|
|
|
|
Ram Viswanathan (ramv) 11-09-95
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "winnt.hxx"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Class CWinNTPrintQueue Methods
|
|
//
|
|
|
|
DEFINE_IDispatch_ExtMgr_Implementation(CWinNTPrintQueue)
|
|
DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTPrintQueue)
|
|
DEFINE_IADs_TempImplementation(CWinNTPrintQueue);
|
|
DEFINE_IADs_PutGetImplementation(CWinNTPrintQueue,PrintQueueClass,gdwPrinterTableSize);
|
|
DEFINE_IADsPropertyList_Implementation(CWinNTPrintQueue, PrintQueueClass,gdwPrinterTableSize)
|
|
|
|
|
|
CWinNTPrintQueue::CWinNTPrintQueue()
|
|
{
|
|
_pszPrinterName = NULL;
|
|
_pDispMgr = NULL;
|
|
_pExtMgr = NULL;
|
|
_pPropertyCache = NULL;
|
|
ENLIST_TRACKING(CWinNTPrintQueue);
|
|
return;
|
|
|
|
}
|
|
|
|
CWinNTPrintQueue::~CWinNTPrintQueue()
|
|
{
|
|
delete _pExtMgr; // created last, destroyed first
|
|
|
|
delete _pDispMgr;
|
|
|
|
delete _pPropertyCache;
|
|
|
|
if(_pszPrinterName){
|
|
FreeADsStr(_pszPrinterName);
|
|
}
|
|
return;
|
|
}
|
|
|
|
HRESULT
|
|
CWinNTPrintQueue:: CreatePrintQueue(
|
|
LPTSTR pszADsParent,
|
|
DWORD dwParentId,
|
|
LPTSTR pszDomainName,
|
|
LPTSTR pszServerName,
|
|
LPTSTR pszPrinterName,
|
|
DWORD dwObjectState,
|
|
REFIID riid,
|
|
CWinNTCredentials& Credentials,
|
|
LPVOID * ppvoid
|
|
)
|
|
|
|
{
|
|
|
|
CWinNTPrintQueue *pPrintQueue = NULL;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Create the printer object
|
|
//
|
|
|
|
hr = AllocatePrintQueueObject(pszServerName,
|
|
pszPrinterName,
|
|
&pPrintQueue
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
ADsAssert(pPrintQueue->_pDispMgr);
|
|
|
|
|
|
//
|
|
// initialize the core object
|
|
//
|
|
|
|
hr = pPrintQueue->InitializeCoreObject(pszADsParent,
|
|
pszPrinterName,
|
|
PRINTER_CLASS_NAME,
|
|
PRINTER_SCHEMA_NAME,
|
|
CLSID_WinNTPrintQueue,
|
|
dwObjectState);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
pPrintQueue->_Credentials = Credentials;
|
|
hr = pPrintQueue->_Credentials.RefServer(pszServerName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
|
|
//
|
|
// Load ext mgr and extensions
|
|
//
|
|
|
|
hr = ADSILoadExtensionManager(
|
|
PRINTER_CLASS_NAME,
|
|
(IADsPrintQueue *) pPrintQueue,
|
|
pPrintQueue->_pDispMgr,
|
|
Credentials,
|
|
&pPrintQueue->_pExtMgr
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
ADsAssert(pPrintQueue->_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.
|
|
//
|
|
if(3 == pPrintQueue->_dwNumComponents) {
|
|
pPrintQueue->_CompClasses[0] = L"Domain";
|
|
pPrintQueue->_CompClasses[1] = L"Computer";
|
|
pPrintQueue->_CompClasses[2] = L"PrintQueue";
|
|
}
|
|
else if(2 == pPrintQueue->_dwNumComponents) {
|
|
// no workstation services
|
|
pPrintQueue->_CompClasses[0] = L"Computer";
|
|
pPrintQueue->_CompClasses[1] = L"PrintQueue";
|
|
}
|
|
else
|
|
BAIL_ON_FAILURE(hr = UMI_E_FAIL);
|
|
|
|
hr = pPrintQueue->InitUmiObject(
|
|
pPrintQueue->_Credentials,
|
|
PrintQueueClass,
|
|
gdwPrinterTableSize,
|
|
pPrintQueue->_pPropertyCache,
|
|
(IUnknown *)(INonDelegatingUnknown *) pPrintQueue,
|
|
pPrintQueue->_pExtMgr,
|
|
IID_IUnknown,
|
|
ppvoid
|
|
);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// 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 = pPrintQueue->QueryInterface(riid, (void **)ppvoid);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pPrintQueue->Release();
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
delete pPrintQueue;
|
|
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 CWinNTPrintQueue::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) CWinNTPrintQueue::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) CWinNTPrintQueue::Release(void)
|
|
{
|
|
if(_pUnkOuter != NULL)
|
|
RRETURN(_pUnkOuter->Release());
|
|
|
|
RRETURN(NonDelegatingRelease());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CWinNTPrintQueue::NonDelegatingQueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(!ppvObj)
|
|
{
|
|
RRETURN(E_POINTER);
|
|
}
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
{
|
|
*ppvObj = (IADsPrintQueue *)this;
|
|
}
|
|
|
|
else if (IsEqualIID(riid, IID_IDispatch))
|
|
{
|
|
*ppvObj = (IADsPrintQueue *)this;
|
|
}
|
|
|
|
else if (IsEqualIID(riid, IID_ISupportErrorInfo))
|
|
{
|
|
*ppvObj = (ISupportErrorInfo FAR *) this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IADsPropertyList))
|
|
{
|
|
*ppvObj = (IADsPropertyList *)this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IADs))
|
|
{
|
|
*ppvObj = (IADsPrintQueue FAR *) this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IADsPrintQueue))
|
|
{
|
|
*ppvObj = (IADsPrintQueue FAR *) this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IADsPrintQueueOperations))
|
|
{
|
|
*ppvObj = (IADsPrintQueueOperations 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
|
|
CWinNTPrintQueue::InterfaceSupportsErrorInfo(
|
|
THIS_ REFIID riid
|
|
)
|
|
{
|
|
if (IsEqualIID(riid, IID_IADs) ||
|
|
IsEqualIID(riid, IID_IADsPrintQueue) ||
|
|
IsEqualIID(riid, IID_IADsPrintQueueOperations) ||
|
|
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
|
|
CWinNTPrintQueue::SetInfo(THIS)
|
|
{
|
|
|
|
BOOL fStatus = FALSE;
|
|
LPPRINTER_INFO_2 lpPrinterInfo2 = NULL;
|
|
BOOL fPrinterAdded = FALSE;
|
|
POBJECTINFO pObjectInfo = NULL;
|
|
|
|
#if (!defined(BUILD_FOR_NT40))
|
|
|
|
LPPRINTER_INFO_7 lpPrinterInfo7 = NULL;
|
|
#endif
|
|
|
|
HRESULT hr;
|
|
|
|
if (GetObjectState() == ADS_OBJECT_UNBOUND) {
|
|
hr = WinNTAddPrinter();
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
SetObjectState(ADS_OBJECT_BOUND);
|
|
fPrinterAdded = TRUE;
|
|
}
|
|
|
|
//
|
|
// first do a getinfo to get properties that werent changed.
|
|
//
|
|
|
|
hr = GetPrinterInfo(&lpPrinterInfo2, _pszPrinterName);
|
|
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = MarshallAndSet(lpPrinterInfo2);
|
|
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
|
|
#if (!defined(BUILD_FOR_NT40))
|
|
hr = GetPrinterInfo7(&lpPrinterInfo7, _pszPrinterName);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
MarshallAndSet(lpPrinterInfo7);
|
|
}
|
|
else if(hr == HRESULT_FROM_WIN32(ERROR_INVALID_LEVEL))
|
|
// Level 7 is not supported on NT4. So, ignore this error.
|
|
hr = S_OK;
|
|
|
|
#endif
|
|
|
|
if(SUCCEEDED(hr))
|
|
_pPropertyCache->ClearModifiedFlags();
|
|
|
|
cleanup:
|
|
|
|
|
|
//
|
|
// If we added a printer and hr is set, we should delete it now
|
|
// as the SetInfo failed in subsequent operations.
|
|
//
|
|
if (FAILED(hr) && fPrinterAdded) {
|
|
|
|
//
|
|
// Build ObjectInfo first
|
|
//
|
|
BuildObjectInfo(
|
|
_ADsPath,
|
|
&pObjectInfo
|
|
);
|
|
//
|
|
// Call delete printer only if the pObjectInfo is valid
|
|
// We cannot do anything in the other case.
|
|
//
|
|
if (pObjectInfo) {
|
|
WinNTDeletePrinter(pObjectInfo);
|
|
FreeObjectInfo(pObjectInfo);
|
|
}
|
|
}
|
|
|
|
if(lpPrinterInfo2){
|
|
FreeADsMem((LPBYTE)lpPrinterInfo2);
|
|
}
|
|
|
|
#if (!defined(BUILD_FOR_NT40))
|
|
|
|
if (lpPrinterInfo7) {
|
|
FreeADsMem((LPBYTE)lpPrinterInfo7);
|
|
}
|
|
#endif
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetInfo(function overloaded: part of CoreADsObject as well
|
|
// as IADs).This function here is part of IADs
|
|
//
|
|
// 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
|
|
CWinNTPrintQueue::GetInfo(THIS)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
#if (!defined(BUILD_FOR_NT40))
|
|
|
|
hr = GetInfo(7,TRUE);
|
|
|
|
#endif
|
|
|
|
hr = GetInfo(2,TRUE);
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CWinNTPrintQueue::ImplicitGetInfo(THIS)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
#if (!defined(BUILD_FOR_NT40))
|
|
|
|
hr = GetInfo(7,FALSE);
|
|
|
|
#endif
|
|
|
|
hr = GetInfo(2,FALSE);
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetInfo (overloaded)
|
|
//
|
|
// Synopsis: Calls the IADs GetInfo, because the printer object has just
|
|
// one info level on which to retrieve info from.
|
|
//
|
|
// Arguments: dwApiLevel and fExplicit (Both Ignored)
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 01-05-96 RamV Created
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP
|
|
CWinNTPrintQueue::GetInfo(THIS_ DWORD dwApiLevel, BOOL fExplicit)
|
|
{
|
|
|
|
LPPRINTER_INFO_2 lpPrinterInfo2= NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
#if (!defined(BUILD_FOR_NT40))
|
|
|
|
LPPRINTER_INFO_7 lpPrinterInfo7 = NULL;
|
|
HRESULT hr7 = S_OK;
|
|
#endif
|
|
|
|
hr = GetPrinterInfo(&lpPrinterInfo2, _pszPrinterName);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = UnMarshall(lpPrinterInfo2,
|
|
fExplicit);
|
|
|
|
#if (!defined(BUILD_FOR_NT40))
|
|
|
|
hr7 = GetPrinterInfo7(&lpPrinterInfo7, _pszPrinterName);
|
|
|
|
if (SUCCEEDED(hr7)) {
|
|
|
|
hr7 = UnMarshall7(lpPrinterInfo7, fExplicit);
|
|
}
|
|
#endif
|
|
|
|
cleanup:
|
|
if(lpPrinterInfo2)
|
|
FreeADsMem((LPBYTE)lpPrinterInfo2);
|
|
|
|
#if (!defined(BUILD_FOR_NT40))
|
|
|
|
if (lpPrinterInfo7) {
|
|
FreeADsMem((LPBYTE)lpPrinterInfo7);
|
|
}
|
|
|
|
#endif
|
|
|
|
RRETURN_EXP_IF_ERR(hr);
|
|
|
|
}
|
|
|
|
//
|
|
// helper function WinNTAddPrinter
|
|
//
|
|
|
|
HRESULT
|
|
CWinNTPrintQueue::WinNTAddPrinter(void)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR szUncServerName[MAX_PATH];
|
|
TCHAR szServerName[MAX_PATH];
|
|
PRINTER_INFO_2 PrinterInfo2;
|
|
HANDLE hPrinter = NULL;
|
|
LPTSTR pszPrintDevices = NULL;
|
|
LPTSTR pszModel = NULL;
|
|
LPTSTR pszDatatype = NULL;
|
|
LPTSTR pszPrintProcessor = NULL;
|
|
LPTSTR pszPrinterName = NULL;
|
|
DWORD dwSyntaxId = 0;
|
|
DWORD dwNumValues = 0;
|
|
PNTOBJECT pNTObject = NULL;
|
|
|
|
memset(&PrinterInfo2, 0, sizeof(PRINTER_INFO_2));
|
|
|
|
hr = GetDelimitedStringPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("PrintDevices"),
|
|
&pszPrintDevices
|
|
);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
PrinterInfo2.pPortName = pszPrintDevices;
|
|
}
|
|
|
|
|
|
hr = GetLPTSTRPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("Model"),
|
|
&pszModel
|
|
);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
PrinterInfo2.pDriverName = pszModel;
|
|
}
|
|
|
|
|
|
hr = GetLPTSTRPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("PrinterName"),
|
|
&pszPrinterName
|
|
);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
PrinterInfo2.pPrinterName = pszPrinterName;
|
|
}
|
|
else {
|
|
|
|
PrinterInfo2.pPrinterName = (LPTSTR) _Name;
|
|
}
|
|
|
|
|
|
hr = GetLPTSTRPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("PrintProcessor"),
|
|
&pszPrintProcessor
|
|
);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
PrinterInfo2.pPrintProcessor = pszPrintProcessor;
|
|
}
|
|
|
|
|
|
hr = GetLPTSTRPropertyFromCache(
|
|
_pPropertyCache,
|
|
TEXT("Datatype"),
|
|
&pszDatatype
|
|
);
|
|
|
|
if(SUCCEEDED(hr)){
|
|
|
|
PrinterInfo2.pDatatype = pszDatatype;
|
|
}
|
|
|
|
|
|
hr = GetServerFromPath(_ADsPath, szServerName);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = MakeUncName(szServerName, szUncServerName);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
|
|
PrinterInfo2.pServerName = szServerName;
|
|
PrinterInfo2.pShareName = (LPTSTR)_Name;
|
|
PrinterInfo2.pComment = NULL;
|
|
PrinterInfo2.pLocation = NULL;
|
|
PrinterInfo2.pDevMode = NULL;
|
|
PrinterInfo2.pSepFile = NULL;
|
|
PrinterInfo2.pParameters = NULL;
|
|
PrinterInfo2.pSecurityDescriptor = NULL;
|
|
PrinterInfo2.Attributes = PRINTER_ATTRIBUTE_SHARED;
|
|
PrinterInfo2.Priority = 0;
|
|
PrinterInfo2.DefaultPriority = 0;
|
|
PrinterInfo2.StartTime = 0;
|
|
PrinterInfo2.UntilTime = 0;
|
|
PrinterInfo2.Status = 0;
|
|
PrinterInfo2.cJobs= 0;
|
|
PrinterInfo2.AveragePPM = 0;
|
|
|
|
//
|
|
// set properties on printer
|
|
//
|
|
|
|
hPrinter = AddPrinter(szUncServerName,
|
|
2,
|
|
(LPBYTE)&PrinterInfo2);
|
|
|
|
if(hPrinter == NULL){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
if(pszPrintDevices){
|
|
FreeADsStr(pszPrintDevices);
|
|
}
|
|
|
|
if(pszModel){
|
|
FreeADsStr(pszModel);
|
|
}
|
|
|
|
if(pszPrintProcessor){
|
|
FreeADsStr(pszPrintProcessor);
|
|
}
|
|
|
|
if(pszDatatype){
|
|
FreeADsStr(pszDatatype);
|
|
}
|
|
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CWinNTPrintQueue::AllocatePrintQueueObject(
|
|
LPTSTR pszServerName,
|
|
LPTSTR pszPrinterName,
|
|
CWinNTPrintQueue ** ppPrintQueue
|
|
)
|
|
{
|
|
CWinNTPrintQueue FAR * pPrintQueue = NULL;
|
|
HRESULT hr = S_OK;
|
|
TCHAR szUncServerName[MAX_PATH];
|
|
TCHAR szUncPrinterName [MAX_PATH];
|
|
CAggregatorDispMgr FAR * pDispMgr = NULL;
|
|
CPropertyCache FAR * pPropertyCache = NULL;
|
|
|
|
pPrintQueue = new CWinNTPrintQueue();
|
|
if (pPrintQueue == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
//
|
|
// Build the UNC form of printer name from the supplied information
|
|
//
|
|
|
|
if( (wcslen(pszServerName) + 3) > MAX_PATH) {
|
|
BAIL_ON_FAILURE(hr = E_INVALIDARG);
|
|
}
|
|
|
|
MakeUncName(pszServerName,
|
|
szUncServerName);
|
|
|
|
if( (wcslen(szUncServerName) + wcslen(pszPrinterName) + 2) > MAX_PATH) {
|
|
BAIL_ON_FAILURE(hr = E_INVALIDARG);
|
|
}
|
|
|
|
wcscpy(szUncPrinterName, szUncServerName);
|
|
wcscat(szUncPrinterName, TEXT("\\"));
|
|
wcscat(szUncPrinterName, pszPrinterName);
|
|
|
|
|
|
pPrintQueue->_pszPrinterName =
|
|
AllocADsStr(szUncPrinterName);
|
|
|
|
if(!(pPrintQueue->_pszPrinterName)){
|
|
hr = E_OUTOFMEMORY;
|
|
goto error;
|
|
}
|
|
|
|
pDispMgr = new CAggregatorDispMgr;
|
|
if (pDispMgr == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = LoadTypeInfoEntry(pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsPrintQueue,
|
|
(IADsPrintQueue *)pPrintQueue,
|
|
DISPID_REGULAR);
|
|
|
|
hr = LoadTypeInfoEntry(pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsPrintQueueOperations,
|
|
(IADsPrintQueueOperations *)pPrintQueue,
|
|
DISPID_REGULAR);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = LoadTypeInfoEntry(pDispMgr,
|
|
LIBID_ADs,
|
|
IID_IADsPropertyList,
|
|
(IADsPropertyList *)pPrintQueue,
|
|
DISPID_VALUE);
|
|
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = CPropertyCache::createpropertycache(
|
|
PrintQueueClass,
|
|
gdwPrinterTableSize,
|
|
(CCoreADsObject *)pPrintQueue,
|
|
&pPropertyCache
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pDispMgr->RegisterPropertyCache(
|
|
pPropertyCache
|
|
);
|
|
|
|
|
|
pPrintQueue->_pPropertyCache = pPropertyCache;
|
|
pPrintQueue->_pDispMgr = pDispMgr;
|
|
*ppPrintQueue = pPrintQueue;
|
|
|
|
RRETURN(hr);
|
|
|
|
error:
|
|
|
|
delete pPropertyCache;
|
|
delete pDispMgr;
|
|
delete pPrintQueue;
|
|
|
|
RRETURN(hr);
|
|
}
|