/*****************************************************************************\ * 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(this) ; } else if (iid == IID_IBidiRequest) { *ppv = static_cast(this) ; } else if (iid == IID_IBidiRequestSpl) { *ppv = static_cast(this) ; } else { *ppv = NULL ; hr = E_NOINTERFACE ; } if (*ppv) { reinterpret_cast(*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) { DWORD dwLen = lstrlen (pszSchema) + 1; m_pSchema = new WCHAR [dwLen]; if (m_pSchema) { hr = StringCchCopy (m_pSchema, dwLen, pszSchema); } } 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 (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) { DWORD dwLen = ( 1 + lstrlen (pszRespSchema)) * sizeof (TCHAR); pszSchema = (LPWSTR) CoTaskMemAlloc (dwLen); if (pszSchema) { StringCbCopy (pszSchema, dwLen, 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) { DWORD dwLen = ( 1 + lstrlen (m_pSchema)) * sizeof (WCHAR); pStr = (LPWSTR) CoTaskMemAlloc (dwLen); if (pStr) { hr = StringCbCopy (pStr, dwLen, m_pSchema); if (SUCCEEDED(hr)) *ppszSchema = pStr; else { *ppszSchema = NULL; CoTaskMemFree (pStr); } } 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; }