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.
 
 
 
 
 
 

925 lines
19 KiB

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996
//
// File: cprinter.cxx
//
// Contents:
//
// History: 9-26-96 yihsins Created.
//
//----------------------------------------------------------------------------
#include "ldap.hxx"
#pragma hdrstop
HRESULT
ChangeSeparator(
LPWSTR pszDN
);
struct _propmap
{
LPTSTR pszADsProp;
LPTSTR pszLDAPProp;
} aPrintPropMapping[] =
{ { TEXT("Description"), TEXT("description") },
{ TEXT("PrintDevices"), TEXT("PortName") },
{ TEXT("Location"), TEXT("location") },
{ TEXT("HostComputer"), TEXT("serverName") },
{ TEXT("Model"), TEXT("DriverName") },
{ TEXT("StartTime"), TEXT("PrintStartTime") },
{ TEXT("UntilTime"), TEXT("PrintEndTime") },
{ TEXT("Priority"), TEXT("Priority") },
{ TEXT("BannerPage"), TEXT("PrintSeparatorfile") }
// { TEXT("NetAddresses"), TEXT("PrintNetworkAddress") },
};
#define UNCNAME TEXT("uNCName")
//
// Class CLDAPPrintQueue
//
// IADsExtension::PrivateGetIDsOfNames()/Invoke(), Operate() not included
DEFINE_IADsExtension_Implementation(CLDAPPrintQueue)
DEFINE_IPrivateDispatch_Implementation(CLDAPPrintQueue)
DEFINE_DELEGATING_IDispatch_Implementation(CLDAPPrintQueue)
DEFINE_CONTAINED_IADs_Implementation(CLDAPPrintQueue)
DEFINE_CONTAINED_IADsPutGet_Implementation(CLDAPPrintQueue,aPrintPropMapping)
CLDAPPrintQueue::CLDAPPrintQueue():
_pUnkOuter(NULL),
_pADs(NULL),
_fDispInitialized(FALSE),
_pDispMgr(NULL)
{
ENLIST_TRACKING(CLDAPPrintQueue);
}
CLDAPPrintQueue::~CLDAPPrintQueue()
{
delete _pDispMgr;
}
HRESULT
CLDAPPrintQueue:: CreatePrintQueue(
IUnknown *pUnkOuter,
REFIID riid,
LPVOID * ppvObj
)
{
CLDAPPrintQueue FAR * pPrintQueue = NULL;
IADs FAR * pADs = NULL;
CAggregateeDispMgr FAR * pDispMgr = NULL;
HRESULT hr = S_OK;
//
// our extension object only works in a provider (aggregator) environment
// environment
//
ASSERT(pUnkOuter);
ASSERT(ppvObj);
ASSERT(IsEqualIID(riid, IID_IUnknown));
pPrintQueue = new CLDAPPrintQueue();
if (pPrintQueue == NULL) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
//
// Reference Count = 1 from object tracker
//
//
// CAggregateeDispMgr to handle
// IADsExtension::PrivateGetIDsOfNames()/PrivatInovke()
//
pDispMgr = new CAggregateeDispMgr;
if (pDispMgr == NULL) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
pPrintQueue->_pDispMgr = pDispMgr;
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsPrintQueue,
(IADsPrintQueue *)pPrintQueue,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_ADs,
IID_IADsPrintQueueOperations,
(IADsPrintQueueOperations *)pPrintQueue,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
//
// Store the pointer to the pUnkOuter object to delegate all IUnknown
// calls to the aggregator AND DO NOT add ref this pointer
//
pPrintQueue->_pUnkOuter = pUnkOuter;
//
// Ccache pADs Pointer to delegate all IDispatch calls to
// the aggregator. But release immediately to avoid the aggregatee
// having a reference count on the aggregator -> cycle ref counting
//
hr = pUnkOuter->QueryInterface(
IID_IADs,
(void **)&pADs
);
//
// Our spec stated extesnion writers can expect the aggregator in our
// provider ot support IDispatch. If not, major bug.
//
ASSERT(SUCCEEDED(hr));
pADs->Release(); // see doc above pUnkOuter->QI
pPrintQueue->_pADs = pADs;
//
// pass non-delegating IUnknown back to the aggregator
//
*ppvObj = (INonDelegatingUnknown FAR *) pPrintQueue;
RRETURN(hr);
error:
if (pPrintQueue)
delete pPrintQueue;
*ppvObj = NULL;
RRETURN(hr);
}
/* IUnknown methods */
STDMETHODIMP
CLDAPPrintQueue::QueryInterface(
REFIID iid,
LPVOID FAR* ppv
)
{
HRESULT hr = S_OK;
hr = _pUnkOuter->QueryInterface(iid,ppv);
RRETURN(hr);
}
STDMETHODIMP
CLDAPPrintQueue::NonDelegatingQueryInterface(
REFIID iid,
LPVOID FAR* ppv
)
{
ASSERT(ppv);
if (IsEqualIID(iid, IID_IADsPrintQueue))
{
*ppv = (IADsPrintQueue FAR *) this;
} else if (IsEqualIID(iid, IID_IADsPrintQueueOperations)) {
*ppv = (IADsPrintQueueOperations FAR *) this;
} else if (IsEqualIID(iid, IID_IADsExtension)) {
*ppv = (IADsExtension FAR *) this;
} else if (IsEqualIID(iid, IID_IUnknown)) {
//
// probably not needed since our 3rd party extension does not stand
// alone and provider does not ask for this, but to be safe
//
*ppv = (INonDelegatingUnknown FAR *) this;
} else {
*ppv = NULL;
return E_NOINTERFACE;
}
//
// Delegating AddRef to aggregator for IADsExtesnion and.
// AddRef on itself for IPrivateUnknown. (both tested.)
//
((IUnknown *) (*ppv)) -> AddRef();
return S_OK;
}
/* IADs methods */
/* IADsPrintQueue methods */
STDMETHODIMP
CLDAPPrintQueue::get_PrinterPath(THIS_ BSTR FAR* retval)
{
GET_PROPERTY_BSTR((IADsPrintQueue *)this, uNCName );
}
STDMETHODIMP
CLDAPPrintQueue::put_PrinterPath(THIS_ BSTR bstruNCName)
{
PUT_PROPERTY_BSTR((IADsPrintQueue*)this, uNCName);
}
STDMETHODIMP
CLDAPPrintQueue::get_Model(THIS_ BSTR FAR* retval)
{
GET_PROPERTY_BSTR((IADsPrintQueue *)this, Model);
}
STDMETHODIMP
CLDAPPrintQueue::put_Model(THIS_ BSTR bstrModel)
{
PUT_PROPERTY_BSTR((IADsPrintQueue *)this, Model);
}
STDMETHODIMP
CLDAPPrintQueue::get_Datatype(THIS_ BSTR *retval)
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
STDMETHODIMP
CLDAPPrintQueue::put_Datatype(THIS_ BSTR bstrDatatype)
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
STDMETHODIMP
CLDAPPrintQueue::get_PrintProcessor(THIS_ BSTR FAR* retval)
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
STDMETHODIMP
CLDAPPrintQueue::put_PrintProcessor(THIS_ BSTR bstrPrintProcessor)
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
STDMETHODIMP
CLDAPPrintQueue::get_Description(THIS_ BSTR FAR* retval)
{
GET_PROPERTY_BSTR((IADsPrintQueue *)this, Description);
}
STDMETHODIMP
CLDAPPrintQueue::put_Description(THIS_ BSTR bstrDescription)
{
PUT_PROPERTY_BSTR((IADsPrintQueue *)this, Description);
}
STDMETHODIMP CLDAPPrintQueue::get_Location(THIS_ BSTR FAR* retval)
{
GET_PROPERTY_BSTR((IADsPrintQueue *)this, Location);
}
STDMETHODIMP CLDAPPrintQueue::put_Location(THIS_ BSTR bstrLocation)
{
PUT_PROPERTY_BSTR((IADsPrintQueue *)this, Location);
}
STDMETHODIMP
CLDAPPrintQueue::get_StartTime(THIS_ DATE FAR* retval)
{
GET_PROPERTY_LONGDATE((IADsPrintQueue *)this, StartTime);
}
STDMETHODIMP
CLDAPPrintQueue::put_StartTime(THIS_ DATE daStartTime)
{
PUT_PROPERTY_LONGDATE((IADsPrintQueue *)this, StartTime);
}
STDMETHODIMP
CLDAPPrintQueue::get_UntilTime(THIS_ DATE FAR* retval)
{
GET_PROPERTY_LONGDATE((IADsPrintQueue *)this, UntilTime);
}
STDMETHODIMP
CLDAPPrintQueue::put_UntilTime(THIS_ DATE daUntilTime)
{
PUT_PROPERTY_LONGDATE((IADsPrintQueue *)this, UntilTime);
}
STDMETHODIMP
CLDAPPrintQueue::get_DefaultJobPriority(THIS_ LONG FAR* retval)
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
STDMETHODIMP
CLDAPPrintQueue::put_DefaultJobPriority(THIS_ LONG lDefaultJobPriority)
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
STDMETHODIMP
CLDAPPrintQueue::get_Priority(THIS_ LONG FAR* retval)
{
GET_PROPERTY_LONG((IADsPrintQueue *)this, Priority);
}
STDMETHODIMP
CLDAPPrintQueue::put_Priority(THIS_ LONG lPriority)
{
PUT_PROPERTY_LONG((IADsPrintQueue *)this, Priority);
}
STDMETHODIMP
CLDAPPrintQueue::get_BannerPage(THIS_ BSTR FAR* retval)
{
GET_PROPERTY_BSTR((IADsPrintQueue *)this, BannerPage);
}
STDMETHODIMP
CLDAPPrintQueue::put_BannerPage(THIS_ BSTR bstrBannerPage)
{
PUT_PROPERTY_BSTR((IADsPrintQueue *)this, BannerPage);
}
STDMETHODIMP
CLDAPPrintQueue::get_PrintDevices(THIS_ VARIANT FAR* retval)
{
GET_PROPERTY_BSTRARRAY((IADsPrintQueue *)this,PrintDevices);
}
STDMETHODIMP
CLDAPPrintQueue::put_PrintDevices(THIS_ VARIANT vPrintDevices)
{
PUT_PROPERTY_BSTRARRAY((IADsPrintQueue *)this,PrintDevices);
}
STDMETHODIMP
CLDAPPrintQueue::get_NetAddresses(THIS_ VARIANT FAR* retval)
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
STDMETHODIMP
CLDAPPrintQueue::put_NetAddresses(THIS_ VARIANT vNetAddresses)
{
RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
}
/* IADsPrintQueueOperations methods */
STDMETHODIMP
CLDAPPrintQueue::get_Status(THIS_ long FAR* retval)
{
BOOL fSuccess = FALSE;
HRESULT hr = S_OK;
DWORD dwStatus = 0;
HANDLE hPrinter = NULL;
BSTR bstrPath = NULL ;
LPPRINTER_INFO_2 lpPrinterInfo2 = NULL;
DWORD dwBufferSize = 1024, dwNeeded ;
PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE |
READ_CONTROL};
//
// get the 'Path' property
//
hr = get_BSTR_Property(this->_pADs, UNCNAME, &bstrPath) ;
BAIL_IF_ERROR(hr);
//
// Do a GetPrinter call to bstrPath
//
fSuccess = OpenPrinter((LPTSTR)bstrPath,
&hPrinter,
&PrinterDefaults
);
if (!fSuccess) {
dwStatus = GetLastError();
if (dwStatus == ERROR_ACCESS_DENIED) {
PrinterDefaults.DesiredAccess = PRINTER_ACCESS_USE ;
fSuccess = OpenPrinter((LPTSTR)bstrPath,
&hPrinter,
&PrinterDefaults
);
}
}
if (!fSuccess) {
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_IF_ERROR(hr);
}
if (!(lpPrinterInfo2 = (LPPRINTER_INFO_2) AllocADsMem(dwBufferSize))) {
hr = HRESULT_FROM_WIN32(GetLastError()) ;
BAIL_IF_ERROR(hr);
}
fSuccess = GetPrinter(hPrinter,
2,
(LPBYTE) lpPrinterInfo2,
dwBufferSize,
&dwNeeded);
if (!fSuccess) {
dwStatus = GetLastError() ;
if (dwStatus == ERROR_INSUFFICIENT_BUFFER) {
lpPrinterInfo2 = (LPPRINTER_INFO_2) ReallocADsMem(
lpPrinterInfo2,
dwBufferSize,
dwNeeded) ;
if (!lpPrinterInfo2) {
hr = HRESULT_FROM_WIN32(GetLastError()) ;
BAIL_IF_ERROR(hr);
}
dwBufferSize = dwNeeded ;
fSuccess = GetPrinter(hPrinter,
2,
(LPBYTE) lpPrinterInfo2,
dwBufferSize,
&dwNeeded);
}
}
if (!fSuccess) {
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_IF_ERROR(hr);
}
*retval = lpPrinterInfo2->Status;
cleanup:
if (lpPrinterInfo2) {
FreeADsMem((LPBYTE)lpPrinterInfo2);
}
if (hPrinter) {
(void) ClosePrinter(hPrinter);
}
RRETURN(hr);
}
STDMETHODIMP
CLDAPPrintQueue::PrintJobs(
THIS_ IADsCollection * FAR* ppCollection
)
{
//
// The job collection object is created and it is passed the printer
// name. It uses this to create a printer object
//
HRESULT hr = S_OK;
BSTR bstrPath = NULL;
WCHAR *pszADsPath = NULL;
IADsPrintQueueOperations *pPrintQueueOps = NULL;
hr = get_BSTR_Property(_pADs, UNCNAME, &bstrPath) ;
BAIL_IF_ERROR(hr);
//
// UNCName has '\' as separators. Convert them to '/'s.
//
hr = ChangeSeparator(bstrPath);
BAIL_IF_ERROR(hr);
pszADsPath = (LPWSTR) AllocADsMem( ( wcslen(TEXT("WinNT://"))
+ wcslen( bstrPath + 2)
+ 1 ) * sizeof(WCHAR));
if ( pszADsPath == NULL )
{
hr = E_OUTOFMEMORY;
BAIL_IF_ERROR(hr);
}
wcscpy(pszADsPath, L"WinNT://");
wcscat(pszADsPath, bstrPath+2);
hr = ADsGetObject(
pszADsPath,
IID_IADsPrintQueueOperations,
(void **)&pPrintQueueOps
);
BAIL_IF_ERROR(hr);
hr = pPrintQueueOps->PrintJobs(ppCollection);
cleanup:
if (pPrintQueueOps){
pPrintQueueOps->Release();
}
if (bstrPath){
ADsFreeString(bstrPath);
}
if (pszADsPath){
FreeADsMem(pszADsPath);
}
RRETURN(hr);
}
//+------------------------------------------------------------------------
//
// Function: CLDAPPrintQueue::Pause
//
// Synopsis: Binds to real printer as specified in _bstrPrinterName
// and attempts to pause the real printer.
//
// Arguments: none
//
// Returns: HRESULT.
//
// Modifies: nothing
//
// History: 11-07-95 RamV Created
// Appropriated from Old NetOle Code.
//
//---------------------------------------------------------------------------
STDMETHODIMP
CLDAPPrintQueue::Pause(THIS)
{
HRESULT hr = S_OK;
BOOL fStatus = FALSE;
BSTR bstrPath = NULL ;
HANDLE hPrinter = NULL;
PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_ADMINISTER};
//
// get the 'Path' property
//
hr = get_BSTR_Property(this->_pADs, UNCNAME, &bstrPath) ;
BAIL_ON_FAILURE(hr);
//
// use Win32 to open the printer
//
fStatus = OpenPrinter(
(LPTSTR)bstrPath,
&hPrinter,
&PrinterDefaults);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto error;
}
fStatus = SetPrinter(hPrinter,
0,
NULL,
PRINTER_CONTROL_PAUSE);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
error:
if(hPrinter) {
(void) ClosePrinter(hPrinter);
}
if (bstrPath) {
ADsFreeString(bstrPath);
}
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CLDAPPrintQueue::Resume
//
// Synopsis: Binds to real printer as specified in _bstrPrinterName and
// attempts to resume the real printer.
//
// Arguments: void
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 11-07-95 RamV Created
// Appropriated from old NetOle Project
//----------------------------------------------------------------------------
STDMETHODIMP
CLDAPPrintQueue::Resume(THIS)
{
HRESULT hr = S_OK;
BOOL fStatus = FALSE;
BSTR bstrPath = NULL ;
HANDLE hPrinter = NULL;
PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_ADMINISTER};
//
// get the 'Path' property
//
hr = get_BSTR_Property(this->_pADs, UNCNAME, &bstrPath) ;
BAIL_ON_FAILURE(hr);
//
// use Win32 to open the printer
//
fStatus = OpenPrinter(
(LPTSTR)bstrPath,
&hPrinter,
&PrinterDefaults);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto error;
}
fStatus = SetPrinter(hPrinter,
0,
NULL,
PRINTER_CONTROL_RESUME);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
error:
if(hPrinter) {
(void) ClosePrinter(hPrinter);
}
if (bstrPath) {
ADsFreeString(bstrPath);
}
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CLDAPPrintQueue::Purge
//
// Synopsis: Binds to real printer as specified in _PrinterName and attempts
// to purge the real printer.
//
// Arguments: void
//
// Returns: HRESULT.
//
// Modifies:
//
// History: 11-07-95 RamV Created
// Appropriated from old NetOle Code
//----------------------------------------------------------------------------
STDMETHODIMP
CLDAPPrintQueue::Purge(THIS)
{
HRESULT hr = S_OK;
BOOL fStatus = FALSE;
BSTR bstrPath = NULL ;
HANDLE hPrinter = NULL;
PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_ADMINISTER};
//
// get the 'Path' property
//
hr = get_BSTR_Property(this->_pADs, UNCNAME, &bstrPath) ;
BAIL_ON_FAILURE(hr);
//
// use Win32 to open the printer
//
fStatus = OpenPrinter(
(LPTSTR)bstrPath,
&hPrinter,
&PrinterDefaults);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto error;
}
fStatus = SetPrinter(hPrinter,
0,
NULL,
PRINTER_CONTROL_PURGE);
if (!fStatus) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
error:
if(hPrinter) {
(void) ClosePrinter(hPrinter);
}
if (bstrPath) {
ADsFreeString(bstrPath);
}
RRETURN(hr);
}
STDMETHODIMP
CLDAPPrintQueue::ADSIInitializeDispatchManager(
long dwExtensionId
)
{
HRESULT hr = S_OK;
if (_fDispInitialized) {
RRETURN(E_FAIL);
}
hr = _pDispMgr->InitializeDispMgr(dwExtensionId);
if (SUCCEEDED(hr)) {
_fDispInitialized = TRUE;
}
RRETURN(hr);
}
STDMETHODIMP
CLDAPPrintQueue::ADSIInitializeObject(
THIS_ BSTR lpszUserName,
BSTR lpszPassword,
long lnReserved
)
{
CCredentials NewCredentials(lpszUserName, lpszPassword, lnReserved);
_Credentials = NewCredentials;
RRETURN(S_OK);
}
STDMETHODIMP
CLDAPPrintQueue::ADSIReleaseObject()
{
delete this;
RRETURN(S_OK);
}
//
// IADsExtension::Operate()
//
STDMETHODIMP
CLDAPPrintQueue::Operate(
THIS_ DWORD dwCode,
VARIANT varData1,
VARIANT varData2,
VARIANT varData3
)
{
HRESULT hr = S_OK;
switch (dwCode) {
case ADS_EXT_INITCREDENTIALS:
hr = InitCredentials(
&varData1,
&varData2,
&varData3
);
break;
default:
hr = E_FAIL;
break;
}
RRETURN(hr);
}
HRESULT
CLDAPPrintQueue::InitCredentials(
VARIANT * pvarUserName,
VARIANT * pvarPassword,
VARIANT * pvarFlags
)
{
BSTR bstrUser = NULL;
BSTR bstrPwd = NULL;
DWORD dwFlags = 0;
ASSERT(V_VT(pvarUserName) == VT_BSTR);
ASSERT(V_VT(pvarPassword) == VT_BSTR);
ASSERT(V_VT(pvarFlags) == VT_I4);
bstrUser = V_BSTR(pvarUserName);
bstrPwd = V_BSTR(pvarPassword);
dwFlags = V_I4(pvarFlags);
CCredentials NewCredentials(bstrUser, bstrPwd, dwFlags);
_Credentials = NewCredentials;
RRETURN(S_OK);
}