mirror of https://github.com/lianthony/NT4.0
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.
277 lines
6.1 KiB
277 lines
6.1 KiB
#include "shellprv.h"
|
|
#pragma hdrstop
|
|
|
|
#pragma warning(disable: 4200) // zero-sized array in struct
|
|
|
|
//
|
|
// Member: WCommonUnknown::QueryInterface
|
|
//
|
|
HRESULT STDMETHODCALLTYPE WCommonUnknown_QueryInterface(void * punk, REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
PWCommonUnknown this = IToClassN(WCommonUnknown, unk, punk);
|
|
|
|
if (IsEqualIID(riid, this->riid) || IsEqualIID(riid, &IID_IUnknown))
|
|
{
|
|
*ppvObj = &(this->ck.unk);
|
|
this->ck.punkOuter->lpVtbl->AddRef(this->ck.punkOuter);
|
|
return NOERROR;
|
|
}
|
|
*ppvObj = NULL;
|
|
|
|
return(ResultFromScode(E_NOINTERFACE));
|
|
}
|
|
|
|
//
|
|
// Member: WCommonUnknown::AddRef
|
|
//
|
|
ULONG STDMETHODCALLTYPE WCommonUnknown_AddRef(void * punk)
|
|
{
|
|
PWCommonUnknown this = IToClassN(WCommonUnknown, unk, punk);
|
|
|
|
this->cRef++;
|
|
return(this->cRef);
|
|
}
|
|
|
|
|
|
//
|
|
// Thunk: WCommonKnown::QueryInterface
|
|
//
|
|
HRESULT STDMETHODCALLTYPE WCommonKnown_QueryInterface(void * punk, REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
PWCommonKnown this = IToClassN(WCommonKnown, unk, punk);
|
|
|
|
return(this->punkOuter->lpVtbl->QueryInterface(this->punkOuter, riid, ppvObj));
|
|
}
|
|
|
|
//
|
|
// Thunk: WCommonKnown::AddRef
|
|
//
|
|
ULONG STDMETHODCALLTYPE WCommonKnown_AddRef(void * punk)
|
|
{
|
|
PWCommonKnown this = IToClassN(WCommonKnown, unk, punk);
|
|
|
|
return(this->punkOuter->lpVtbl->AddRef(this->punkOuter));
|
|
}
|
|
|
|
|
|
//
|
|
// Thunk: WCommonKnown::Release
|
|
//
|
|
ULONG STDMETHODCALLTYPE WCommonKnown_Release(void * punk)
|
|
{
|
|
PWCommonKnown this = IToClassN(WCommonKnown, unk, punk);
|
|
|
|
return(this->punkOuter->lpVtbl->Release(this->punkOuter));
|
|
}
|
|
|
|
|
|
typedef struct _COMMOBJ_OBJ
|
|
{
|
|
COMMOBJ_OBJDESC sDesc;
|
|
IUnknown *punkAgg;
|
|
} COMMOBJ_OBJ;
|
|
|
|
typedef struct _CommObj
|
|
{
|
|
IUnknown unk;
|
|
UINT cRef;
|
|
COMMOBJ_DESTROYOBJECT lpfnDestroy;
|
|
COMMINFO cinfo;
|
|
int nObjs;
|
|
COMMOBJ_OBJ sObjs[];
|
|
} CommObj, *PCommObj;
|
|
|
|
ULONG STDMETHODCALLTYPE CommObj_AddRef(void * punk);
|
|
|
|
//
|
|
// Thunk: CommObj::QueryInterface
|
|
//
|
|
HRESULT STDMETHODCALLTYPE CommObj_QueryInterface(void * punk, REFIID riid, LPVOID *ppv)
|
|
{
|
|
PCommObj this = IToClassN(CommObj, unk, punk);
|
|
COMMOBJ_OBJ *pObj;
|
|
HRESULT hres;
|
|
int nObjs;
|
|
|
|
*ppv = NULL; // assume error
|
|
|
|
for (nObjs=this->nObjs-1, pObj=&this->sObjs[0]; ; --nObjs, ++pObj)
|
|
{
|
|
if (nObjs < 0)
|
|
{
|
|
if (IsEqualIID(riid, &IID_IUnknown))
|
|
{
|
|
CommObj_AddRef(punk);
|
|
*ppv = punk;
|
|
return(NOERROR);
|
|
}
|
|
else
|
|
{
|
|
return(ResultFromScode(E_NOINTERFACE));
|
|
}
|
|
}
|
|
|
|
if (IsEqualIID(riid, pObj->sDesc.riid))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pObj->punkAgg)
|
|
{
|
|
hres = pObj->sDesc.lpfnCreate(&(this->unk), &this->cinfo, riid, &pObj->punkAgg);
|
|
if (!SUCCEEDED(hres))
|
|
{
|
|
pObj->punkAgg = NULL;
|
|
return(hres);
|
|
}
|
|
}
|
|
|
|
// Note that this should inc our ref count
|
|
return(pObj->punkAgg->lpVtbl->QueryInterface(pObj->punkAgg, riid, ppv));
|
|
}
|
|
|
|
//
|
|
// Thunk: CommObj::AddRef
|
|
//
|
|
ULONG STDMETHODCALLTYPE CommObj_AddRef(void * punk)
|
|
{
|
|
PCommObj this = IToClassN(CommObj, unk, punk);
|
|
|
|
++this->cRef;
|
|
return(this->cRef);
|
|
}
|
|
|
|
|
|
//
|
|
// Thunk: CommObj::Release
|
|
//
|
|
ULONG STDMETHODCALLTYPE CommObj_Release(void * punk)
|
|
{
|
|
PCommObj this = IToClassN(CommObj, unk, punk);
|
|
int nObjs;
|
|
COMMOBJ_OBJ *pObj;
|
|
|
|
--this->cRef;
|
|
if (this->cRef > 0)
|
|
{
|
|
return(this->cRef);
|
|
}
|
|
|
|
for (nObjs=this->nObjs, pObj=&this->sObjs[0]; nObjs>0; --nObjs, ++pObj)
|
|
{
|
|
if (pObj->punkAgg)
|
|
{
|
|
pObj->punkAgg->lpVtbl->Release(pObj->punkAgg);
|
|
}
|
|
}
|
|
|
|
//
|
|
// These castings are OK, because we are initializing them.
|
|
//
|
|
Str_SetPtr(&(LPTSTR)this->cinfo.pszSubObject, NULL);
|
|
Str_SetPtr(&(LPTSTR)this->cinfo.pszContainer, NULL);
|
|
if (this->cinfo.pidl) {
|
|
ILFree((LPITEMIDLIST)this->cinfo.pidl);
|
|
}
|
|
|
|
if (this->lpfnDestroy)
|
|
{
|
|
this->lpfnDestroy(&this->cinfo);
|
|
}
|
|
|
|
LocalFree(this);
|
|
return 0;
|
|
}
|
|
|
|
|
|
#pragma data_seg(".text", "CODE")
|
|
IUnknownVtbl s_CommObjVtbl =
|
|
{
|
|
CommObj_QueryInterface,
|
|
CommObj_AddRef,
|
|
CommObj_Release,
|
|
};
|
|
#pragma data_seg()
|
|
|
|
|
|
//
|
|
// Create a generic aggregate object
|
|
//
|
|
HRESULT Common_CreateObject(LPCOMMINFO lpcinfo,
|
|
COMMOBJ_DESTROYOBJECT lpfnDestroy,
|
|
const COMMOBJ_OBJDESC *lpObjDescs, UINT nObjs, REFIID riid, LPVOID *ppv)
|
|
{
|
|
PCommObj this;
|
|
HRESULT hres;
|
|
COMMOBJ_OBJ *pObj;
|
|
|
|
this = (PCommObj)LocalAlloc(LPTR, SIZEOF(CommObj) + nObjs*SIZEOF(COMMOBJ_OBJ));
|
|
if (!this)
|
|
{
|
|
goto Error1;
|
|
}
|
|
|
|
//
|
|
// There castings are OK, because we are initializing them.
|
|
//
|
|
if (!Str_SetPtr(&(LPTSTR)this->cinfo.pszContainer, lpcinfo->pszContainer))
|
|
{
|
|
goto Error2;
|
|
}
|
|
if (!Str_SetPtr(&(LPTSTR)this->cinfo.pszSubObject, lpcinfo->pszSubObject))
|
|
{
|
|
goto Error3;
|
|
}
|
|
|
|
this->cRef = 1;
|
|
this->unk.lpVtbl = (IUnknownVtbl *) &s_CommObjVtbl;
|
|
|
|
this->nObjs = nObjs;
|
|
for (pObj=&this->sObjs[0]; nObjs>0; --nObjs, ++pObj, ++lpObjDescs)
|
|
{
|
|
pObj->sDesc = *lpObjDescs;
|
|
}
|
|
|
|
this->lpfnDestroy = lpfnDestroy;
|
|
this->cinfo.lpData = lpcinfo->lpData;
|
|
this->cinfo.rclsid = lpcinfo->rclsid;
|
|
this->cinfo.hwndOwner = lpcinfo->hwndOwner;
|
|
|
|
hres = CommObj_QueryInterface(&(this->unk), riid, ppv);
|
|
CommObj_Release(&(this->unk));
|
|
|
|
return(hres);
|
|
|
|
Error3:
|
|
Str_SetPtr(&(LPTSTR)this->cinfo.pszContainer, NULL);
|
|
Error2:
|
|
LocalFree(this);
|
|
Error1:
|
|
// Make sure this always gets called exactly once per call to this fn;
|
|
// either here or in the final release
|
|
lpfnDestroy(lpcinfo);
|
|
return(ResultFromScode(E_OUTOFMEMORY));
|
|
}
|
|
|
|
|
|
//
|
|
// Member: WCommonUnknown::QueryInterface
|
|
//
|
|
HRESULT STDMETHODCALLTYPE Common_ESF_QueryInterface(void * punk, REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
PWCommonUnknown this = IToClassN(WCommonUnknown, unk, punk);
|
|
|
|
if (IsEqualIID(riid, this->riid)
|
|
|| IsEqualIID(riid, &IID_IDelayedRelease)
|
|
|| IsEqualIID(riid, &IID_IUnknown))
|
|
{
|
|
*ppvObj = &(this->unk);
|
|
this->unk.lpVtbl->AddRef(&(this->unk));
|
|
return NOERROR;
|
|
}
|
|
|
|
*ppvObj = NULL;
|
|
return(ResultFromScode(E_NOINTERFACE));
|
|
}
|
|
|