windows-nt/Source/XPSP1/NT/printscan/print/spooler/spoolss/bidispl/request.cpp
2020-09-26 16:20:57 +08:00

575 lines
13 KiB
C++

/*****************************************************************************\
* MODULE: request.cpp
*
* PURPOSE: Implementation of COM interface for BidiSpooler
*
* Copyright (C) 2000 Microsoft Corporation
*
* History:
*
* 03/07/00 Weihai Chen (weihaic) Created
*
\*****************************************************************************/
#include "precomp.h"
#include "priv.h"
//
// Constructor
//
TBidiRequest::TBidiRequest() :
m_cRef(1),
m_kDataType (BIDI_NULL),
m_dwDataSize (0),
m_pbData (NULL),
m_pSchema (NULL),
m_bValid (FALSE)
{
InterlockedIncrement(&g_cComponents) ;
m_bValid = m_CritSec.bValid () && m_ResponseDataList.bValid ();
DBGMSG(DBG_TRACE,("TBidiRequest Created\n"));
}
//
// Destructor
//
TBidiRequest::~TBidiRequest()
{
InterlockedDecrement(&g_cComponents) ;
if (m_pSchema)
delete [] m_pSchema;
DBGMSG(DBG_TRACE,("TBidiRequest Dstroy self\n"));
}
//
// IUnknown implementation
//
STDMETHODIMP
TBidiRequest::QueryInterface(
REFIID iid,
PVOID* ppv)
{
HRESULT hr = S_OK;
DBGMSG(DBG_TRACE,("Enter TBidiRequest QI\n"));
if (iid == IID_IUnknown) {
*ppv = static_cast<IBidiRequest*>(this) ;
}
else if (iid == IID_IBidiRequest) {
*ppv = static_cast<IBidiRequest*>(this) ;
}
else if (iid == IID_IBidiRequestSpl) {
*ppv = static_cast<IBidiRequestSpl*>(this) ;
}
else {
*ppv = NULL ;
hr = E_NOINTERFACE ;
}
if (*ppv) {
reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
}
DBGMSG(DBG_TRACE,("Leave TBidiRequest QI hr=%x\n", hr));
return hr ;
}
STDMETHODIMP_ (ULONG)
TBidiRequest::AddRef()
{
DBGMSG(DBG_TRACE,("Enter TBidiRequest::AddRef ref= %d\n", m_cRef));
return InterlockedIncrement(&m_cRef) ;
}
STDMETHODIMP_ (ULONG)
TBidiRequest::Release()
{
DBGMSG(DBG_TRACE,("Enter TBidiRequest::Release ref= %d\n", m_cRef));
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this ;
return 0 ;
}
return m_cRef ;
}
STDMETHODIMP
TBidiRequest::SetSchema(
LPCWSTR pszSchema)
{
HRESULT hr (E_FAIL);
DBGMSG(DBG_TRACE,("Enter SetSchema %ws\n", pszSchema));
if (m_bValid) {
TAutoCriticalSection CritSec (m_CritSec);
if (CritSec.bValid ()) {
if (m_pSchema) {
delete[] m_pSchema;
m_pSchema = NULL;
}
if (pszSchema) {
m_pSchema = new WCHAR [lstrlen (pszSchema) + 1];
if (m_pSchema) {
lstrcpy (m_pSchema, pszSchema);
hr = S_OK;
}
}
else
SetLastError (ERROR_INVALID_PARAMETER);
}
if (FAILED (hr)) {
hr = LastError2HRESULT();
}
}
else
hr = E_HANDLE;
return hr;
}
STDMETHODIMP
TBidiRequest::SetInputData(
IN CONST DWORD dwType,
IN CONST BYTE *pData,
IN CONST UINT uSize)
{
HRESULT hr (S_OK);
DBGMSG(DBG_TRACE,("Enter SetInputData dwType=%d\n", dwType));
if (m_bValid) {
// Verify data type and its size
switch (dwType) {
case BIDI_NULL:
if (uSize)
hr = E_INVALIDARG;
break;
case BIDI_INT:
if (uSize != sizeof (ULONG)) {
hr = E_INVALIDARG;
}
break;
case BIDI_FLOAT:
if (uSize != sizeof (FLOAT)) {
hr = E_INVALIDARG;
}
break;
case BIDI_BOOL:
if (uSize != sizeof (BOOL)) {
hr = E_INVALIDARG;
}
break;
case BIDI_ENUM:
case BIDI_STRING:
case BIDI_TEXT:
if (uSize != sizeof (WCHAR) * (lstrlen (reinterpret_cast<LPCWSTR> (pData)) + 1)) {
hr = E_INVALIDARG;
}
break;
case BIDI_BLOB:
hr = S_OK;
break;
default:
hr = E_INVALIDARG;
}
if (hr == S_OK) {
TAutoCriticalSection CritSec (m_CritSec);
if (CritSec.bValid ()) {
if (m_pbData) {
delete [] m_pbData;
m_pbData = NULL;
}
m_kDataType = (BIDI_TYPE) dwType;
m_dwDataSize = uSize;
if (uSize > 0) {
m_pbData = new BYTE [uSize];
if (m_pbData) {
CopyMemory (m_pbData, pData, uSize);
hr = S_OK;
}
else
hr = E_OUTOFMEMORY;
}
else
hr = S_OK;
}
else {
hr = LastError2HRESULT();
}
}
}
else
hr = E_HANDLE;
return hr;
}
STDMETHODIMP
TBidiRequest::GetResult(
HRESULT *phr)
{
HRESULT hr;
DBGMSG(DBG_TRACE,("Enter GetResult\n"));
if (m_bValid) {
if (phr) {
TAutoCriticalSection CritSec (m_CritSec);
if (CritSec.bValid ()) {
*phr = m_hr;
hr = S_OK;
}
else
hr = LastError2HRESULT();
}
else {
hr = E_POINTER;
}
}
else
hr = E_HANDLE;
return hr;
}
STDMETHODIMP
TBidiRequest::GetOutputData(
DWORD dwIndex,
LPWSTR *ppszSchema,
PDWORD pdwType,
PBYTE *ppData,
PULONG puSize)
{
HRESULT hr (E_FAIL);
DBGMSG(DBG_TRACE,("Enter GetOutputData\n"));
if (m_bValid) {
if (ppszSchema && ppData && pdwType && puSize) {
TAutoCriticalSection CritSec (m_CritSec);
PBYTE pData = NULL;
LPWSTR pszSchema = NULL;
DWORD dwType = 0;
DWORD dwSize = 0;
if (CritSec.bValid ()) {
TResponseData * pRespData = m_ResponseDataList.GetItemFromIndex (dwIndex);
if (pRespData) {
LPCTSTR pszRespSchema = pRespData->GetSchema ();
if (pszRespSchema) {
pszSchema = (LPWSTR) CoTaskMemAlloc (( 1 + lstrlen (pszRespSchema)) * sizeof (TCHAR));
if (pszSchema) {
lstrcpy (pszSchema, pszRespSchema);
}
else
goto Cleanup;
}
else
pszSchema = NULL;
dwType = pRespData->GetType ();
dwSize = pRespData->GetSize ();
if (dwSize == 0) {
hr = S_OK;
}
else {
pData = (PBYTE) CoTaskMemAlloc (dwSize);
if (pData) {
CopyMemory (pData, pRespData->GetData (), dwSize);
hr = S_OK;
}
}
}
else {
SetLastError (ERROR_INVALID_DATA);
}
}
Cleanup:
if (FAILED (hr)) {
hr = LastError2HRESULT ();
if (pszSchema) {
CoTaskMemFree (pszSchema);
pszSchema = NULL;
}
if (pData) {
CoTaskMemFree (pData);
pData = NULL;
}
}
else {
*ppszSchema = pszSchema;
*ppData = pData;
*pdwType = dwType;
*puSize = dwSize;
}
}
else
hr = E_POINTER;
}
else
hr = E_HANDLE;
return hr;
}
STDMETHODIMP
TBidiRequest::GetEnumCount(
OUT PDWORD pdwTotal)
{
HRESULT hr;
DBGMSG(DBG_TRACE,("Enter GetOutputData\n"));
if (m_bValid) {
if (pdwTotal) {
TAutoCriticalSection CritSec (m_CritSec);
if (CritSec.bValid ()) {
BOOL bRet;
bRet = m_ResponseDataList.GetTotalNode (pdwTotal);
if (bRet) {
hr = S_OK;
}
else
hr = LastError2HRESULT();
}
else
hr = LastError2HRESULT();
}
else {
hr = E_POINTER;
}
}
else
hr = E_HANDLE;
return hr;
}
STDMETHODIMP
TBidiRequest::GetSchema (
OUT LPWSTR *ppszSchema)
{
HRESULT hr;
LPWSTR pStr;
DBGMSG(DBG_TRACE,("Enter GetSchema\n"));
if (m_bValid) {
if (ppszSchema) {
TAutoCriticalSection CritSec (m_CritSec);
if (CritSec.bValid ()) {
if (m_pSchema) {
pStr = (LPWSTR) CoTaskMemAlloc (( 1 + lstrlen (m_pSchema)) * sizeof (WCHAR));
if (pStr) {
lstrcpy (pStr, m_pSchema);
*ppszSchema = pStr;
hr = S_OK;
}
else
hr = E_OUTOFMEMORY;
}
else {
*ppszSchema = NULL;
hr = S_OK;
}
}
else
hr = LastError2HRESULT();
}
else {
hr = E_POINTER;
}
}
else
hr = E_HANDLE;
return hr;
}
STDMETHODIMP
TBidiRequest::GetInputData (
OUT PDWORD pdwType,
OUT PBYTE *ppData,
OUT PULONG puSize)
{
HRESULT hr;
DBGMSG(DBG_TRACE,("Enter GetInputData\n"));
if (m_bValid) {
if (pdwType && ppData && puSize) {
TAutoCriticalSection CritSec (m_CritSec);
if (CritSec.bValid ()) {
*pdwType = m_kDataType;
if (m_pbData) {
*ppData = (PBYTE) CoTaskMemAlloc (m_dwDataSize);
if (*ppData) {
CopyMemory (*ppData, m_pbData, m_dwDataSize);
*puSize = m_dwDataSize;
hr = S_OK;
}
else
hr = E_OUTOFMEMORY;
}
else {
*ppData = NULL;
*puSize = 0;
hr = S_OK;
}
}
else
hr = LastError2HRESULT();
}
else
hr = E_POINTER;
}
else
hr = E_HANDLE;
return hr;
}
STDMETHODIMP
TBidiRequest::SetResult (
IN CONST HRESULT hrReq)
{
HRESULT hr;
DBGMSG(DBG_TRACE,("Enter SetResult\n"));
if (m_bValid) {
TAutoCriticalSection CritSec (m_CritSec);
if (CritSec.bValid ()) {
m_hr = hrReq;
hr = S_OK;
}
else
hr = LastError2HRESULT();
}
else
hr = E_HANDLE;
return hr;
}
STDMETHODIMP
TBidiRequest::AppendOutputData (
IN CONST LPCWSTR pszSchema,
IN CONST DWORD dwType,
IN CONST BYTE *pData,
IN CONST ULONG uSize)
{
HRESULT hr (E_FAIL);
BOOL bRet;
DBGMSG(DBG_TRACE,("Enter AppendOutputData\n"));
if (m_bValid) {
TResponseData *pRespData = NULL;
pRespData = new TResponseData (pszSchema, dwType, pData, uSize);
bRet = pRespData && pRespData->bValid ();
if (bRet) {
TAutoCriticalSection CritSec (m_CritSec);
if (CritSec.bValid ()) {
bRet = m_ResponseDataList.AppendItem (pRespData);
if (bRet) {
hr = S_OK;
}
}
}
if (FAILED (hr)) {
hr = LastError2HRESULT();
if (pRespData) {
delete (pRespData);
}
}
}
else
hr = E_HANDLE;
return hr;
}