|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1999
//
// File: csdisp.cpp
//
// Contents: IDispatch helper functions
//
// History: 09-Dec-96 vich created
//
//--------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <stdlib.h>
#include "csdisp.h"
#ifndef DBG_DISPATCH
# define DBG_DISPATCH 0
#endif
TCHAR szRegKeyClsidValue[] = TEXT("");
HRESULT DispatchGetReturnValue( VARIANT *pvar, IN LONG Type, OUT VOID *pretval) { HRESULT hr = S_OK;
if (VT_EMPTY == pvar->vt) { hr = CERTSRV_E_PROPERTY_EMPTY; _JumpError2(hr, error, "VT_EMPTY", hr); } if (Type != pvar->vt) { DBGPRINT(( DBG_SS_CERTLIB, "pvar->vt=%x, expected %x\n", pvar->vt, Type)); hr = TYPE_E_WRONGTYPEKIND; _JumpError(hr, error, "pvar->vt != Type"); } switch (Type) { case VT_I4: *(LONG *) pretval = pvar->lVal; break;
case VT_DATE: *(DATE *) pretval = pvar->date; break;
case VT_BSTR: *(BSTR *) pretval = pvar->bstrVal; pvar->vt = VT_EMPTY; break;
case VT_DISPATCH: *(IDispatch **) pretval = pvar->pdispVal; pvar->vt = VT_EMPTY; break;
default: hr = E_INVALIDARG; goto error; }
error: return(hr); }
HRESULT DispatchSetErrorInfoSub( IN HRESULT hrError, OPTIONAL IN WCHAR const *pwszIDispatchMethod, OPTIONAL IN WCHAR const *pwszDescription, OPTIONAL IN WCHAR const *pwszSource, OPTIONAL IN IID const *piid, OPTIONAL IN WCHAR const *pwszHelpFile, IN DWORD dwHelpFileContext) { HRESULT hr; WCHAR const *pwszError = NULL; ICreateErrorInfo *pCreateErrorInfo = NULL; IErrorInfo *pErrorInfo = NULL;
#ifdef DBG_CERTSRV_DEBUG_PRINT
if (NULL != pwszIDispatchMethod || DbgIsSSActive(DBG_SS_CERTLIBI)) #else
if (NULL != pwszIDispatchMethod) #endif
{ pwszError = myGetErrorMessageText(hrError, TRUE); if (NULL != pwszIDispatchMethod) { CONSOLEPRINT1(( MAXDWORD, "IDispatch->Invoke(%ws) Exception:\n", pwszIDispatchMethod)); } else { CONSOLEPRINT0((MAXDWORD, "COM Error:\n")); }
CONSOLEPRINT5(( MAXDWORD, " Source=%ws\n Description=%ws\n HelpFile=%ws[%x]\n %ws\n", pwszSource, pwszDescription, pwszHelpFile, dwHelpFileContext, pwszError)); }
hr = CreateErrorInfo(&pCreateErrorInfo); _JumpIfError(hr, error, "CreateErrorInfo");
if (NULL != piid) { hr = pCreateErrorInfo->SetGUID(*piid); _PrintIfError(hr, "SetGUID"); } if (NULL != pwszSource) { hr = pCreateErrorInfo->SetSource(const_cast<WCHAR *>(pwszSource)); _PrintIfError(hr, "SetSource"); } if (NULL != pwszDescription) { hr = pCreateErrorInfo->SetDescription( const_cast<WCHAR *>(pwszDescription)); _PrintIfError(hr, "SetDescription"); } if (NULL != pwszHelpFile) { hr = pCreateErrorInfo->SetHelpFile(const_cast<WCHAR *>(pwszHelpFile)); _PrintIfError(hr, "SetHelpFile");
hr = pCreateErrorInfo->SetHelpContext(dwHelpFileContext); _PrintIfError(hr, "SetHelpContext"); }
hr = pCreateErrorInfo->QueryInterface( IID_IErrorInfo, (VOID **) &pErrorInfo); _JumpIfError(hr, error, "QueryInterface");
SetErrorInfo(0, pErrorInfo); hr = S_OK;
error: if (NULL != pwszError) { LocalFree(const_cast<WCHAR *>(pwszError)); } if (NULL != pErrorInfo) { pErrorInfo->Release(); } if (NULL != pCreateErrorInfo) { pCreateErrorInfo->Release(); } return(hr); }
HRESULT DispatchInvoke( IN DISPATCHINTERFACE *pDispatchInterface, IN LONG MethodIndex, IN DWORD cvar, IN VARIANT avar[], IN LONG Type, OUT VOID *pretval) { HRESULT hr; DISPATCHTABLE const *pdt; EXCEPINFO excepinfo; VARIANT varResult; DISPPARAMS parms; unsigned iArgErr; DISPID *adispid;
VariantInit(&varResult); CSASSERT(NULL != pDispatchInterface->pDispatchTable); CSASSERT((DWORD) MethodIndex < pDispatchInterface->m_cDispatchTable); pdt = &pDispatchInterface->pDispatchTable[MethodIndex];
adispid = &pDispatchInterface->m_adispid[pdt->idispid]; CSASSERT(NULL != pDispatchInterface->m_adispid); CSASSERT(pdt->idispid + pdt->cdispid <= pDispatchInterface->m_cdispid);
parms.rgvarg = avar; parms.rgdispidNamedArgs = &adispid[1]; parms.cArgs = pdt->cdispid - 1; parms.cNamedArgs = parms.cArgs;
if (parms.cArgs != cvar) { CSASSERT(parms.cArgs == cvar); hr = HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR); _JumpError(hr, error, "cvar"); }
CSASSERT(NULL != pDispatchInterface->pDispatch);
hr = pDispatchInterface->pDispatch->Invoke( adispid[0], IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &parms, &varResult, &excepinfo, &iArgErr);
if (S_OK != hr) { _PrintErrorStr(hr, "Invoke", pdt->apszNames[0]);
if (DISP_E_EXCEPTION == hr) { HRESULT hr2; IID const *piid;
if (FAILED(excepinfo.scode)) { hr = excepinfo.scode; } hr2 = DispatchSetErrorInfoSub( hr, pdt->apszNames[0], excepinfo.bstrDescription, excepinfo.bstrSource, pDispatchInterface->GetIID(), excepinfo.bstrHelpFile, excepinfo.dwHelpContext); _PrintIfError(hr2, "DispatchSetErrorInfoSub"); } goto error; }
if (CLSCTX_INPROC_SERVER != pDispatchInterface->m_ClassContext) { myRegisterMemAlloc(&varResult, 0, CSM_VARIANT); } if (NULL != pretval) { hr = DispatchGetReturnValue(&varResult, Type, pretval); _JumpIfErrorStr2( hr, error, "DispatchGetReturnValue", pdt->apszNames[0], CERTSRV_E_PROPERTY_EMPTY); }
error: VariantClear(&varResult); return(hr); }
HRESULT DispatchGetIds( IN IDispatch *pDispatch, IN DWORD cDispatchTable, IN OUT DISPATCHTABLE *pDispatchTable, IN OUT DISPATCHINTERFACE *pDispatchInterface) { HRESULT hr = S_OK; DISPATCHTABLE *pdt; DISPATCHTABLE *pdtEnd; DISPID *adispid = NULL; DWORD idispid;
pdtEnd = &pDispatchTable[cDispatchTable]; pDispatchInterface->m_cdispid = 0; for (pdt = pDispatchTable; pdt < pdtEnd; pdt++) { if (0 == pdt->idispid) { pdt->idispid = pDispatchInterface->m_cdispid; } CSASSERT(pdt->idispid == pDispatchInterface->m_cdispid); pDispatchInterface->m_cdispid += pdt->cdispid; }
adispid = (DISPID *) LocalAlloc( LMEM_FIXED, pDispatchInterface->m_cdispid * sizeof(adispid[0])); if (NULL == adispid) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); }
idispid = 0; for (pdt = pDispatchTable; pdt < pdtEnd; pdt++) { CSASSERT(idispid + pdt->cdispid <= pDispatchInterface->m_cdispid); hr = pDispatch->GetIDsOfNames( IID_NULL, pdt->apszNames, pdt->cdispid, LOCALE_SYSTEM_DEFAULT, &adispid[idispid]); #if DBG_CERTSRV
if (S_OK != hr || DBG_DISPATCH) { DWORD i;
DBGPRINT(( MAXDWORD, "GetIDsOfNames(%ws) --> %x, dispid=%x" szLPAREN, pdt->apszNames[0], hr, adispid[idispid])); for (i = 1; i < pdt->cdispid; i++) { DBGPRINT(( MAXDWORD, "%ws%x", i == 1? L"" : L", ", adispid[idispid + i])); } DBGPRINT((MAXDWORD, szRPAREN "\n")); } #endif
_JumpIfError(hr, error, "GetIDsOfNames");
idispid += pdt->cdispid; } pDispatchInterface->m_cDispatchTable = cDispatchTable; pDispatchInterface->pDispatchTable = pDispatchTable; pDispatchInterface->m_adispid = adispid; adispid = NULL;
error: if (NULL != adispid) { LocalFree(adispid); } return(hr); }
HRESULT DispatchSetup( IN DWORD Flags, IN DWORD ClassContext, OPTIONAL IN TCHAR const *pszProgID, // for IDispatch
OPTIONAL IN CLSID const *pclsid, // for COM
OPTIONAL IN IID const *piid, // for COM
IN DWORD cDispatchTable, // for IDispatch
IN OUT DISPATCHTABLE *pDispatchTable, IN OUT DISPATCHINTERFACE *pDispatchInterface) { HRESULT hr; CLSID clsid; pDispatchInterface->SetIID(piid); while (TRUE) { pDispatchInterface->pDispatch = NULL; pDispatchInterface->pUnknown = NULL; pDispatchInterface->m_adispid = NULL;
CSASSERT(NULL != pszProgID || DISPSETUP_COM == Flags); CSASSERT(NULL != pclsid || DISPSETUP_IDISPATCH == Flags); CSASSERT(NULL != piid || DISPSETUP_IDISPATCH == Flags);
if (DISPSETUP_IDISPATCH == Flags) { // use win32 version, not our own hack
hr = CLSIDFromProgID(pszProgID, &clsid);
_JumpIfError2( hr, error, "ClassNameToCLSID", HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
pclsid = &clsid; piid = &IID_IDispatch; }
hr = CoCreateInstance( *pclsid, NULL, // pUnkOuter
ClassContext, *piid, DISPSETUP_IDISPATCH == Flags? (VOID **) &pDispatchInterface->pDispatch : (VOID **) &pDispatchInterface->pUnknown); #if DBG_DISPATCH
printf("CoCreateInstance(%x) --> %x\n", Flags, hr); #endif
if (S_OK != hr) { if (DISPSETUP_COMFIRST != Flags) { _JumpError2(hr, error, "CoCreateInstance", E_NOINTERFACE); } Flags = DISPSETUP_IDISPATCH; continue; } pDispatchInterface->m_ClassContext = ClassContext; break; } if (DISPSETUP_IDISPATCH == Flags) { hr = DispatchGetIds( pDispatchInterface->pDispatch, cDispatchTable, pDispatchTable, pDispatchInterface); if (S_OK != hr) { DispatchRelease(pDispatchInterface); _JumpError(hr, error, "DispatchGetIds"); } }
error: return(hr); }
HRESULT DispatchSetup2( IN DWORD Flags, IN DWORD ClassContext, IN WCHAR const *pwszClass, // wszRegKeyAdminClsid
IN CLSID const *pclsid, IN DWORD cver, IN IID const * const *ppiid, // cver elements
IN DWORD const *pcDispatch, // cver elements
IN OUT DISPATCHTABLE *pDispatchTable, IN OUT DISPATCHINTERFACE *pDispatchInterface) { HRESULT hr = E_INVALIDARG;
CSASSERT(0 < cver); for ( ; 0 < cver; cver--, ppiid++, pcDispatch++) { hr = DispatchSetup( Flags, ClassContext, pwszClass, pclsid, *ppiid, *pcDispatch, pDispatchTable, pDispatchInterface); if (S_OK == hr) { pDispatchInterface->m_dwVersion = cver; pDispatchInterface->pDispatchTable = pDispatchTable; break; } if (1 == cver || (E_NOINTERFACE != hr && DISP_E_UNKNOWNNAME != hr)) { _JumpErrorStr(hr, error, "DispatchSetup", pwszClass); } _PrintErrorStr2(hr, "DispatchSetup", pwszClass, hr); }
error: return(hr); }
VOID DispatchRelease( IN OUT DISPATCHINTERFACE *pDispatchInterface) { if (NULL != pDispatchInterface->pDispatch) { pDispatchInterface->pDispatch->Release(); pDispatchInterface->pDispatch = NULL; } if (NULL != pDispatchInterface->pUnknown) { pDispatchInterface->pUnknown->Release(); pDispatchInterface->pUnknown = NULL; } if (NULL != pDispatchInterface->m_adispid) { LocalFree(pDispatchInterface->m_adispid); pDispatchInterface->m_adispid = NULL; } }
BOOL myConvertWszToBstr( OUT BSTR *pbstr, IN WCHAR const *pwc, IN LONG cb) { HRESULT hr; BSTR bstr;
do { bstr = NULL; if (NULL != pwc) { if (-1 == cb) { cb = wcslen(pwc) * sizeof(WCHAR); } bstr = SysAllocStringByteLen((char const *) pwc, cb); if (NULL == bstr) { hr = E_OUTOFMEMORY; break; } } if (NULL != *pbstr) { SysFreeString(*pbstr); } *pbstr = bstr; hr = S_OK; } while (FALSE); if (S_OK != hr) { SetLastError(hr); } return(S_OK == hr); }
BOOL myConvertSzToBstr( OUT BSTR *pbstr, IN CHAR const *pch, IN LONG cch) { HRESULT hr; BSTR bstr = NULL; LONG cwc = 0;
if (-1 == cch) { cch = strlen(pch); } CSASSERT(0 != cch); while (TRUE) { cwc = MultiByteToWideChar(GetACP(), 0, pch, cch, bstr, cwc); if (0 >= cwc) { hr = myHLastError(); _PrintError(hr, "MultiByteToWideChar"); if (NULL != bstr) { SysFreeString(bstr); } break; } if (NULL != bstr) { bstr[cwc] = L'\0'; if (NULL != *pbstr) { SysFreeString(*pbstr); } *pbstr = bstr; hr = S_OK; break; } bstr = SysAllocStringLen(NULL, cwc); if (NULL == bstr) { hr = E_OUTOFMEMORY; break; } } if (S_OK != hr) { SetLastError(hr); } return(S_OK == hr); }
HRESULT DecodeCertString( IN BSTR const bstrIn, IN DWORD Flags, OUT BYTE **ppbOut, OUT DWORD *pcbOut) { HRESULT hr; DWORD dwSize;
*ppbOut = NULL;
CSASSERT(CR_IN_BASE64HEADER == CRYPT_STRING_BASE64HEADER); CSASSERT(CR_IN_BASE64 == CRYPT_STRING_BASE64); CSASSERT(CR_IN_BINARY == CRYPT_STRING_BINARY);
switch (Flags) { case CRYPT_STRING_BASE64HEADER: case CRYPT_STRING_BASE64: case CRYPT_STRING_BASE64REQUESTHEADER: case CRYPT_STRING_HEX: case CRYPT_STRING_HEXASCII: case CRYPT_STRING_BASE64_ANY: case CRYPT_STRING_HEX_ANY: case CRYPT_STRING_BASE64X509CRLHEADER: case CRYPT_STRING_HEXADDR: case CRYPT_STRING_HEXASCIIADDR: CSASSERT(sizeof(WCHAR) * wcslen(bstrIn) == SysStringByteLen(bstrIn)); // FALLTHROUGH
case CRYPT_STRING_ANY: dwSize = (SysStringByteLen(bstrIn) + sizeof(WCHAR) - 1) / sizeof(WCHAR); break;
case CRYPT_STRING_BINARY: dwSize = SysStringByteLen(bstrIn); break;
default: hr = E_INVALIDARG; _JumpError(hr, error, "Flags"); } hr = myCryptStringToBinary( bstrIn, dwSize, Flags, ppbOut, pcbOut, NULL, NULL); _JumpIfError(hr, error, "myCryptStringToBinary");
if (CRYPT_STRING_ANY == Flags && (SysStringByteLen(bstrIn) & (sizeof(WCHAR) - 1))) { (*pcbOut)--; CSASSERT(SysStringByteLen(bstrIn) == *pcbOut); } hr = S_OK;
error: return(hr); }
HRESULT EncodeCertString( IN BYTE const *pbIn, IN DWORD cbIn, IN DWORD Flags, OUT BSTR *pbstrOut) { HRESULT hr = E_INVALIDARG; WCHAR *pwcCert = NULL; DWORD cbCert; BSTR strCert = NULL;
CSASSERT(CR_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER); CSASSERT(CR_OUT_BASE64 == CRYPT_STRING_BASE64); CSASSERT(CR_OUT_BINARY == CRYPT_STRING_BINARY); //CSASSERT(CR_OUT_BASE64REQUESTHEADER == CRYPT_STRING_BASE64REQUESTHEADER);
//CSASSERT(CR_OUT_HEX == CRYPT_STRING_HEX);
CSASSERT(CV_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER); CSASSERT(CV_OUT_BASE64 == CRYPT_STRING_BASE64); CSASSERT(CV_OUT_BINARY == CRYPT_STRING_BINARY); CSASSERT(CV_OUT_BASE64REQUESTHEADER == CRYPT_STRING_BASE64REQUESTHEADER); CSASSERT(CV_OUT_HEX == CRYPT_STRING_HEX); CSASSERT(CV_OUT_HEXASCII == CRYPT_STRING_HEXASCII); CSASSERT(CV_OUT_BASE64X509CRLHEADER == CRYPT_STRING_BASE64X509CRLHEADER); CSASSERT(CV_OUT_HEXADDR == CRYPT_STRING_HEXADDR); CSASSERT(CV_OUT_HEXASCIIADDR == CRYPT_STRING_HEXASCIIADDR);
if (NULL == pbIn || (~CR_OUT_ENCODEMASK & Flags)) { goto error; }
switch (CR_OUT_ENCODEMASK & Flags) { case CRYPT_STRING_BASE64HEADER: case CRYPT_STRING_BASE64: case CRYPT_STRING_BASE64REQUESTHEADER: case CRYPT_STRING_HEX: case CRYPT_STRING_HEXASCII: case CRYPT_STRING_BASE64X509CRLHEADER: case CRYPT_STRING_HEXADDR: case CRYPT_STRING_HEXASCIIADDR: hr = myCryptBinaryToString( pbIn, cbIn, CR_OUT_ENCODEMASK & Flags, &pwcCert); _JumpIfError(hr, error, "myCryptBinaryToString");
cbCert = sizeof(WCHAR) * wcslen(pwcCert); break;
case CRYPT_STRING_BINARY: pwcCert = (WCHAR *) pbIn; cbCert = cbIn; hr = S_OK; break;
default: goto error; } if (!ConvertWszToBstr(pbstrOut, pwcCert, cbCert)) { hr = E_OUTOFMEMORY; }
hr = S_OK; error: if (NULL != pwcCert && pwcCert != (WCHAR *) pbIn) { LocalFree(pwcCert); } return(hr); }
HRESULT DispatchSetErrorInfo( IN HRESULT hrError, IN WCHAR const *pwszDescription, OPTIONAL IN WCHAR const *pwszProgId, OPTIONAL IN IID const *piid) { HRESULT hr; WCHAR const *pwszError = NULL; WCHAR *pwszText = NULL;
if (NULL == pwszDescription) { hr = E_POINTER; _JumpError(hr, error, "NULL pointer"); } CSASSERT(FAILED(hrError)); pwszError = myGetErrorMessageText(hrError, TRUE); if (NULL == pwszError) { _PrintError(E_OUTOFMEMORY, "myGetErrorMessageText"); } else { pwszText = (WCHAR *) LocalAlloc( LMEM_FIXED, (wcslen(pwszDescription) + 1 + wcslen(pwszError) + 1) * sizeof(WCHAR)); if (NULL == pwszText) { _PrintError(E_OUTOFMEMORY, "LocalAlloc"); } else { wcscpy(pwszText, pwszDescription); wcscat(pwszText, L" "); wcscat(pwszText, pwszError); } } hr = DispatchSetErrorInfoSub( hrError, NULL, // pwszIDispatchMethod
NULL != pwszText? pwszText : const_cast<WCHAR *>(pwszDescription), pwszProgId, piid, NULL, // pwszHelpFile
0); // dwHelpFileContext
_PrintIfError(hr, "DispatchSetErrorInfoSub");
error: if (NULL != pwszText) { LocalFree(pwszText); } if (NULL != pwszError) { LocalFree(const_cast<WCHAR *>(pwszError)); } return(hrError); // return input error!
}
|