CDISPMGR.CPP

/*++ 

Copyright (c) 1996 Microsoft Corporation

Module Name:

CDispMgr.c

Abstract:

Dispatch Manager implementation

Author:

Environment:

User mode

Revision History :

--*/
#include "adssmp.h"
#pragma hdrstop

DISPID
CDispatchMgr::getDISPID(DISPID InputDispId)
{
return(InputDispId & 0x0000FFFF);
}

DISPID
CDispatchMgr::getTypeinfoID(DISPID InputDispId)
{
return((InputDispId & 0x7fff0000) >> 16);
}

void *
CDispatchMgr::getInterfacePtr(DISPID TypeinfoID
)
{
PTYPEINFOENTRY pTypeInfoEntry = NULL;
pTypeInfoEntry = _pTypeInfoEntry;
while (pTypeInfoEntry) {
if (pTypeInfoEntry->TypeInfoId == TypeinfoID) {
return(pTypeInfoEntry->pInterfacePointer);
}
pTypeInfoEntry = pTypeInfoEntry->pNext;
}
return(NULL);
}

PTYPEINFOENTRY
CDispatchMgr::FindTypeInfoEntry(LONG TypeInfoId)
{
PTYPEINFOENTRY pTypeInfoEntry;

pTypeInfoEntry = _pTypeInfoEntry;
while (pTypeInfoEntry) {
if (pTypeInfoEntry->TypeInfoId == TypeInfoId) {
return(pTypeInfoEntry);
}
pTypeInfoEntry = pTypeInfoEntry->pNext;
}
return(NULL);
}



HRESULT
CDispatchMgr::AddTypeInfo(void FAR *ptypeinfo,
void * pIntfptr)
{
PTYPEINFOENTRY pTypeInfoEntry = NULL;
HRESULT hr;

if (pTypeInfoEntry =FindTypeInfo(ptypeinfo)) {
return(E_FAIL);
}
pTypeInfoEntry = (PTYPEINFOENTRY)LocalAlloc(LPTR,sizeof(TYPEINFOENTRY));
if (!pTypeInfoEntry) {
hr = E_OUTOFMEMORY;
BAIL_IF_ERROR(hr);
}

pTypeInfoEntry->ptypeinfo = ptypeinfo;
pTypeInfoEntry->TypeInfoId = gentypeinfoid();
pTypeInfoEntry->pInterfacePointer = pIntfptr;

pTypeInfoEntry->pNext = _pTypeInfoEntry;
_pTypeInfoEntry = pTypeInfoEntry;

RRETURN(S_OK);

cleanup:
RRETURN(hr);
}

STDMETHODIMP
CDispatchMgr::GetTypeInfoCount(unsigned int FAR* pctinfo)
{
RRETURN(E_NOTIMPL);
}

STDMETHODIMP
CDispatchMgr::GetTypeInfo(unsigned int itinfo, LCID lcid,
ITypeInfo FAR* FAR* pptinfo)
{
RRETURN(E_NOTIMPL);
}

STDMETHODIMP
CDispatchMgr::GetIDsOfNames(REFIID iid, LPWSTR FAR* rgszNames,
unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
{
PTYPEINFOENTRY pTypeInfo = NULL;
HRESULT hr;

pTypeInfo = _pTypeInfoEntry;
while (pTypeInfo) {
hr = DispGetIDsOfNames(((ITypeInfo *)pTypeInfo->ptypeinfo),
rgszNames,
cNames,
rgdispid
);
if (SUCCEEDED(hr)) {
generate_newids(pTypeInfo->TypeInfoId,
rgdispid,
cNames
);
RRETURN(hr);
}
pTypeInfo = pTypeInfo->pNext;
}
RRETURN(E_FAIL);
}

STDMETHODIMP
CDispatchMgr::Invoke(DISPID dispidMember, REFIID iid, LCID lcid,
unsigned short wFlags, DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo,
unsigned int FAR* puArgErr)
{
RRETURN(TypeInfoInvoke(dispidMember,
iid,
lcid,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr
));
}

void
CDispatchMgr::generate_newids(LONG TypeInfoId,
DISPID FAR* rgdispid, unsigned int cNames)
{
unsigned int i = 0;
for (i = 0; i < cNames; i++ ) {
rgdispid[i] = (DISPID)(((unsigned int)TypeInfoId << 16) | rgdispid[i]);
}
}

STDMETHODIMP
CDispatchMgr::TypeInfoInvoke(DISPID dispidMember, REFIID iid, LCID lcid,
unsigned short wFlags, DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo,
unsigned int FAR* puArgErr)
{

void * pInterfacePtr = NULL;
DISPID dispid;
DISPID typeinfoid;
ITypeInfo *pTypeInfo;
HRESULT hr = S_OK;

if (dispidMember <= 0) {
dispid = dispidMember;
switch (dispid) {
case -4:
if (_pDispidNewEnum) {
pTypeInfo = (ITypeInfo *)_pDispidNewEnum->ptypeinfo;
pInterfacePtr = _pDispidNewEnum->pInterfacePointer;
break;

}else {
hr = DISP_E_BADINDEX;
BAIL_IF_ERROR(hr);

}
break;

default:
hr = DISP_E_BADINDEX;
BAIL_IF_ERROR(hr);

}

}else {
typeinfoid = getTypeinfoID(dispidMember);
dispid = getDISPID(dispidMember);
pInterfacePtr = getInterfacePtr(typeinfoid);
hr = getTypeInfo(typeinfoid, &pTypeInfo);
BAIL_IF_ERROR(hr);
}

hr = DispInvoke(pInterfacePtr,
pTypeInfo,
dispid,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr
);
return hr;

cleanup:

RRETURN(hr);
}


HRESULT
CDispatchMgr::getTypeInfo(DISPID typeinfoid, ITypeInfo FAR * FAR * ppTypeInfo)
{
PTYPEINFOENTRY pTypeInfoEntry;
pTypeInfoEntry = _pTypeInfoEntry;
while (pTypeInfoEntry) {
if (pTypeInfoEntry->TypeInfoId == typeinfoid) {
*ppTypeInfo = (ITypeInfo FAR *)pTypeInfoEntry->ptypeinfo;
RRETURN(S_OK);
}
pTypeInfoEntry = pTypeInfoEntry->pNext;
}
RRETURN(E_FAIL);
}

CDispatchMgr::CDispatchMgr()
{
_pTypeInfoEntry = NULL;
_pDispidNewEnum = NULL;
_dwTypeInfoId = 0;
}

CDispatchMgr::~CDispatchMgr()
{
PTYPEINFOENTRY pTypeInfoEntry = NULL;
PTYPEINFOENTRY pTemp = NULL;
ITypeInfo *pTypeInfo = NULL;

pTypeInfoEntry = _pTypeInfoEntry;

while (pTypeInfoEntry) {

pTemp = pTypeInfoEntry;

pTypeInfo = (ITypeInfo *)pTypeInfoEntry->ptypeinfo;
pTypeInfo->Release();

pTypeInfoEntry = pTemp->pNext;

LocalFree(pTemp);
}
}

HRESULT
CDispatchMgr::MarkAsNewEnum(void *pTypeInfo)
{
PTYPEINFOENTRY pTypeInfoEntry;

if (!pTypeInfo) {
RRETURN(E_FAIL);
}
if (!(pTypeInfoEntry = FindTypeInfo(pTypeInfo))) {
RRETURN(E_FAIL);
}
_pDispidNewEnum = pTypeInfoEntry;
RRETURN(S_OK);
}



PTYPEINFOENTRY
CDispatchMgr::FindTypeInfo(void *pTypeInfo)
{
PTYPEINFOENTRY pTypeInfoEntry;

pTypeInfoEntry = _pTypeInfoEntry;
while (pTypeInfoEntry) {
if (pTypeInfoEntry->ptypeinfo == pTypeInfo) {
return(pTypeInfoEntry);
}
pTypeInfoEntry = pTypeInfoEntry->pNext;
}
return(NULL);
}

LONG
CDispatchMgr::gentypeinfoid()
{
return (_dwTypeInfoId++);
}