Leaked source code of windows server 2003
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.
 
 
 
 
 
 

545 lines
13 KiB

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright 1998 - 2003 Microsoft Corporation. All Rights Reserved.
//
// FILE: Intrface.cpp
//
//
// PURPOSE: Interface for User Mode COM Customization DLL.
//
//
// Functions:
//
//
//
//
// PLATFORMS: Windows 2000, Windows XP, Windows Server 2003
//
//
#include "precomp.h"
#include <INITGUID.H>
#include <PRCOMOEM.H>
#include "oemps.h"
#include "debug.h"
#include "command.h"
#include "intrface.h"
// StrSafe.h needs to be included last
// to disallow bad string functions.
#include <STRSAFE.H>
////////////////////////////////////////////////////////
// Internal Globals
////////////////////////////////////////////////////////
static long g_cComponents; // Count of active components
static long g_cServerLocks; // Count of locks
////////////////////////////////////////////////////////////////////////////////
//
// IOemPS body
//
IOemPS::IOemPS()
{
VERBOSE(DLLTEXT("IOemPS::IOemPS() entered.\r\n"));
// Increment COM component count.
InterlockedIncrement(&g_cComponents);
InterlockedIncrement(&m_cRef);
m_pOEMHelp = NULL;
VERBOSE(DLLTEXT("IOemPS::IOemPS() leaving.\r\n"));
}
IOemPS::~IOemPS()
{
// Make sure that helper interface is released.
if(NULL != m_pOEMHelp)
{
m_pOEMHelp->Release();
m_pOEMHelp = NULL;
}
// If this instance of the object is being deleted, then the reference
// count should be zero.
assert(0 == m_cRef);
// Decrement COM compontent count.
InterlockedDecrement(&g_cComponents);
}
HRESULT __stdcall IOemPS::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(this);
VERBOSE(DLLTEXT("IOemPS::QueryInterface IUnknown.\r\n"));
}
else if (iid == IID_IPrintOemPS)
{
*ppv = static_cast<IPrintOemPS*>(this);
VERBOSE(DLLTEXT("IOemPS::QueryInterface IPrintOemPs.\r\n"));
}
else
{
#if DBG && defined(USERMODE_DRIVER)
TCHAR szOutput[80] = {0};
StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
VERBOSE(DLLTEXT("IOemPS::QueryInterface %s not supported.\r\n"), szOutput);
#endif
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall IOemPS::AddRef()
{
VERBOSE(DLLTEXT("IOemPS::AddRef() entry.\r\n"));
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall IOemPS::Release()
{
VERBOSE(DLLTEXT("IOemPS::Release() entry.\r\n"));
ASSERT( 0 != m_cRef);
ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
{
delete this;
}
return cRef;
}
HRESULT __stdcall IOemPS::GetInfo (
DWORD dwMode,
PVOID pBuffer,
DWORD cbSize,
PDWORD pcbNeeded)
{
VERBOSE(DLLTEXT("IOemPS::GetInfo(%d) entry.\r\n"), dwMode);
// Validate parameters.
if( (NULL == pcbNeeded)
||
( (OEMGI_GETSIGNATURE != dwMode)
&&
(OEMGI_GETVERSION != dwMode)
&&
(OEMGI_GETPUBLISHERINFO != dwMode)
)
)
{
ERR(DLLTEXT("IOemPS::GetInfo() exit pcbNeeded is NULL!\r\n"));
SetLastError(ERROR_INVALID_PARAMETER);
return E_FAIL;
}
// Set expected buffer size.
if(OEMGI_GETPUBLISHERINFO != dwMode)
{
*pcbNeeded = sizeof(DWORD);
}
else
{
*pcbNeeded = sizeof(PUBLISHERINFO);
return E_FAIL;
}
// Check buffer size is sufficient.
if((cbSize < *pcbNeeded) || (NULL == pBuffer))
{
ERR(DLLTEXT("IOemPS::GetInfo() exit insufficient buffer!\r\n"));
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return E_FAIL;
}
switch(dwMode)
{
// OEM DLL Signature
case OEMGI_GETSIGNATURE:
*(PDWORD)pBuffer = OEM_SIGNATURE;
break;
// OEM DLL version
case OEMGI_GETVERSION:
*(PDWORD)pBuffer = OEM_VERSION;
break;
case OEMGI_GETPUBLISHERINFO:
Dump((PPUBLISHERINFO)pBuffer);
// Fall through to default case.
// dwMode not supported.
default:
// Set written bytes to zero since nothing was written.
ERR(DLLTEXT("IOemPS::GetInfo() exit, mode not supported.\r\n"));
*pcbNeeded = 0;
SetLastError(ERROR_NOT_SUPPORTED);
return E_FAIL;
}
VERBOSE(DLLTEXT("IOemPS::GetInfo() exit S_OK, (*pBuffer is %#x).\r\n"), *(PDWORD)pBuffer);
return S_OK;
}
HRESULT __stdcall IOemPS::PublishDriverInterface(
IUnknown *pIUnknown)
{
VERBOSE(DLLTEXT("IOemPS::PublishDriverInterface() entry.\r\n"));
// Need to store pointer to Driver Helper functions, if we already haven't.
if (this->m_pOEMHelp == NULL)
{
HRESULT hResult;
// Get Interface to Helper Functions.
hResult = pIUnknown->QueryInterface(IID_IPrintOemDriverPS, (void** ) &(this->m_pOEMHelp));
if(!SUCCEEDED(hResult))
{
// Make sure that interface pointer reflects interface query failure.
this->m_pOEMHelp = NULL;
return E_FAIL;
}
}
return S_OK;
}
HRESULT __stdcall IOemPS::EnableDriver(DWORD dwDriverVersion,
DWORD cbSize,
PDRVENABLEDATA pded)
{
VERBOSE(DLLTEXT("IOemPS::EnableDriver() entry.\r\n"));
OEMEnableDriver(dwDriverVersion, cbSize, pded);
// Even if nothing is done, need to return S_OK so
// that DisableDriver() will be called, which releases
// the reference to the Printer Driver's interface.
// If error occurs, return E_FAIL.
return S_OK;
}
HRESULT __stdcall IOemPS::DisableDriver(VOID)
{
VERBOSE(DLLTEXT("IOemPS::DisaleDriver() entry.\r\n"));
OEMDisableDriver();
// Release reference to Printer Driver's interface.
if (this->m_pOEMHelp)
{
this->m_pOEMHelp->Release();
this->m_pOEMHelp = NULL;
}
return S_OK;
}
HRESULT __stdcall IOemPS::DisablePDEV(
PDEVOBJ pdevobj)
{
VERBOSE(DLLTEXT("IOemPS::DisablePDEV() entry.\r\n"));
OEMDisablePDEV(pdevobj);
return S_OK;
};
HRESULT __stdcall IOemPS::EnablePDEV(
PDEVOBJ pdevobj,
PWSTR pPrinterName,
ULONG cPatterns,
HSURF *phsurfPatterns,
ULONG cjGdiInfo,
GDIINFO *pGdiInfo,
ULONG cjDevInfo,
DEVINFO *pDevInfo,
DRVENABLEDATA *pded,
OUT PDEVOEM *pDevOem)
{
VERBOSE(DLLTEXT("IOemPS::EnablePDEV() entry.\r\n"));
*pDevOem = OEMEnablePDEV(pdevobj, pPrinterName, cPatterns, phsurfPatterns,
cjGdiInfo, pGdiInfo, cjDevInfo, pDevInfo, pded);
return (NULL != *pDevOem ? S_OK : E_FAIL);
}
HRESULT __stdcall IOemPS::ResetPDEV(
PDEVOBJ pdevobjOld,
PDEVOBJ pdevobjNew)
{
BOOL bResult;
VERBOSE(DLLTEXT("IOemPS::ResetPDEV() entry.\r\n"));
bResult = OEMResetPDEV(pdevobjOld, pdevobjNew);
return (bResult ? S_OK : E_FAIL);
}
HRESULT __stdcall IOemPS::DevMode(
DWORD dwMode,
POEMDMPARAM pOemDMParam)
{
VERBOSE(DLLTEXT("IOemPS:DevMode(%d, %#x) entry.\n"), dwMode, pOemDMParam);
return hrOEMDevMode(dwMode, pOemDMParam);
}
HRESULT __stdcall IOemPS::Command(
PDEVOBJ pdevobj,
DWORD dwIndex,
PVOID pData,
DWORD cbSize,
OUT DWORD *pdwResult)
{
HRESULT hResult = E_NOTIMPL;
VERBOSE(DLLTEXT("IOemPS::Command() entry.\r\n"));
hResult = PSCommand(pdevobj, dwIndex, pData, cbSize, m_pOEMHelp, pdwResult);
return hResult;
}
////////////////////////////////////////////////////////////////////////////////
//
// oem class factory
//
class IOemCF : public IClassFactory
{
public:
// *** IUnknown methods ***
STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
STDMETHOD_(ULONG,AddRef) (THIS);
STDMETHOD_(ULONG,Release) (THIS);
// *** IClassFactory methods ***
STDMETHOD(CreateInstance) (THIS_
LPUNKNOWN pUnkOuter,
REFIID riid,
LPVOID FAR* ppvObject);
STDMETHOD(LockServer) (THIS_ BOOL bLock);
// Constructor
IOemCF();
~IOemCF();
protected:
long m_cRef;
};
///////////////////////////////////////////////////////////
//
// Class factory body
//
IOemCF::IOemCF()
{
VERBOSE(DLLTEXT("IOemCF::IOemCF() entered.\r\n"));
InterlockedIncrement(&m_cRef);
}
IOemCF::~IOemCF()
{
VERBOSE(DLLTEXT("IOemCF::~IOemCF() entered.\r\n"));
// If this instance of the object is being deleted, then the reference
// count should be zero.
assert(0 == m_cRef);
}
HRESULT __stdcall IOemCF::QueryInterface(const IID& iid, void** ppv)
{
VERBOSE(DLLTEXT("IOemCF::QueryInterface entered.\r\n"));
if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
{
*ppv = static_cast<IOemCF*>(this);
}
else
{
#if DBG && defined(USERMODE_DRIVER)
TCHAR szOutput[80] = {0};
StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
WARNING(DLLTEXT("IOemCF::QueryInterface %s not supported.\r\n"), szOutput);
#endif
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
VERBOSE(DLLTEXT("IOemCF::QueryInterface leaving.\r\n"));
return S_OK;
}
ULONG __stdcall IOemCF::AddRef()
{
VERBOSE(DLLTEXT("IOemCF::AddRef() called.\r\n"));
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall IOemCF::Release()
{
VERBOSE(DLLTEXT("IOemCF::Release() called.\r\n"));
ASSERT( 0 != m_cRef);
ULONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
{
delete this;
}
return cRef;
}
// IClassFactory implementation
HRESULT __stdcall IOemCF::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
VERBOSE(DLLTEXT("Class factory: Create component.\r\n"));
// Cannot aggregate.
if (pUnknownOuter != NULL)
{
WARNING(DLLTEXT("Class factory: non-Null pUnknownOuter.\r\n"));
return CLASS_E_NOAGGREGATION;
}
// Create component.
IOemPS* pOemCP = new IOemPS;
if (pOemCP == NULL)
{
ERR(ERRORTEXT("Class factory: failed to allocate IOemPS.\r\n"));
return E_OUTOFMEMORY;
}
// Get the requested interface.
HRESULT hr = pOemCP->QueryInterface(iid, ppv);
// Release the IUnknown pointer.
// (If QueryInterface failed, component will delete itself.)
pOemCP->Release();
return hr;
}
// LockServer
HRESULT __stdcall IOemCF::LockServer(BOOL bLock)
{
VERBOSE(DLLTEXT("IOemCF::LockServer(%d) entered.\r\n"), bLock);
if (bLock)
{
InterlockedIncrement(&g_cServerLocks);
}
else
{
InterlockedDecrement(&g_cServerLocks);
}
VERBOSE(DLLTEXT("IOemCF::LockServer() leaving.\r\n"));
return S_OK;
}
//
// Registration functions
//
//
// Can DLL unload now?
//
STDAPI DllCanUnloadNow()
{
//
// To avoid leaving OEM DLL still in memory when Unidrv or Pscript drivers
// are unloaded, Unidrv and Pscript driver ignore the return value of
// DllCanUnloadNow of the OEM DLL, and always call FreeLibrary on the OEMDLL.
//
// If OEM DLL spins off a working thread that also uses the OEM DLL, the
// thread needs to call LoadLibrary and FreeLibraryAndExitThread, otherwise
// it may crash after Unidrv or Pscript calls FreeLibrary.
//
VERBOSE(DLLTEXT("DllCanUnloadNow entered.\r\n"));
if ((g_cComponents == 0) && (g_cServerLocks == 0))
{
return S_OK;
}
else
{
return S_FALSE;
}
}
//
// Get class factory
//
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
VERBOSE(DLLTEXT("DllGetClassObject: Create class factory entered.\r\n"));
// Can we create this component?
if (clsid != CLSID_OEMRENDER)
{
ERR(ERRORTEXT("DllGetClassObject: doesn't support clsid %#x!\r\n"), clsid);
return CLASS_E_CLASSNOTAVAILABLE;
}
// Create class factory.
IOemCF* pFontCF = new IOemCF; // Reference count set to 1
// in constructor
if (pFontCF == NULL)
{
ERR(ERRORTEXT("DllGetClassObject: memory allocation failed!\r\n"));
return E_OUTOFMEMORY;
}
// Get requested interface.
HRESULT hr = pFontCF->QueryInterface(iid, ppv);
pFontCF->Release();
VERBOSE(DLLTEXT("DllGetClassObject: Create class factory leaving.\r\n"));
return hr;
}