|
|
/*
* clsiface.c - Class interface cache ADT module. */
/*
*/
/* Headers
**********/
#include "project.h"
#pragma hdrstop
#include "oleutil.h"
/* Constants
************/
/* class interface cache pointer array allocation parameters */
#define NUM_START_CLS_IFACES (0)
#define NUM_CLS_IFACES_TO_ADD (16)
/* Types
********/
/* class interface cache */
typedef struct _clsifacecache { HPTRARRAY hpa; } CLSIFACECACHE; DECLARE_STANDARD_TYPES(CLSIFACECACHE);
/* class interface */
typedef struct _clsiface { /* class ID */
PCCLSID pcclsid;
/* interface ID */
PCIID pciid;
/* interface */
PVOID pvInterface; } CLSIFACE; DECLARE_STANDARD_TYPES(CLSIFACE);
/* class interface search structure for ClassInterfaceSearchCmp() */
typedef struct _clsifacesearchinfo { /* class ID */
PCCLSID pcclsid;
/* interface ID */
PCIID pciid; } CLSIFACESEARCHINFO; DECLARE_STANDARD_TYPES(CLSIFACESEARCHINFO);
/***************************** Private Functions *****************************/
/* Module Prototypes
********************/
PRIVATE_CODE BOOL CreateClassInterfacePtrArray(PHPTRARRAY); PRIVATE_CODE void DestroyClassInterfacePtrArray(HPTRARRAY); PRIVATE_CODE HRESULT CreateClassInterface(PCCLSIFACECACHE, PCCLSID, PCIID, PCLSIFACE *); PRIVATE_CODE void DestroyClassInterface(PCLSIFACE); PRIVATE_CODE COMPARISONRESULT ClassInterfaceSortCmp(PCVOID, PCVOID); PRIVATE_CODE COMPARISONRESULT ClassInterfaceSearchCmp(PCVOID, PCVOID);
#ifdef DEBUG
PRIVATE_CODE BOOL IsValidPCCLSIFACECACHE(PCCLSIFACECACHE); PRIVATE_CODE BOOL IsValidPCCLSIFACE(PCCLSIFACE); PRIVATE_CODE BOOL IsValidPCCLSIFACESEARCHINFO(PCCLSIFACESEARCHINFO);
#endif
/*
** CreateClassInterfacePtrArray() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL CreateClassInterfacePtrArray(PHPTRARRAY phpa) { NEWPTRARRAY npa;
ASSERT(IS_VALID_WRITE_PTR(phpa, HPTRARRAY));
npa.aicInitialPtrs = NUM_START_CLS_IFACES; npa.aicAllocGranularity = NUM_CLS_IFACES_TO_ADD; npa.dwFlags = NPA_FL_SORTED_ADD;
return(CreatePtrArray(&npa, phpa)); }
/*
** DestroyClassInterfacePtrArray() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE void DestroyClassInterfacePtrArray(HPTRARRAY hpa) { ARRAYINDEX aicPtrs; ARRAYINDEX ai;
ASSERT(IS_VALID_HANDLE(hpa, PTRARRAY));
/* First free all class interfaces in array. */
aicPtrs = GetPtrCount(hpa);
for (ai = 0; ai < aicPtrs; ai++) DestroyClassInterface(GetPtr(hpa, ai));
/* Now wipe out the array. */
DestroyPtrArray(hpa);
return; }
/*
** CreateClassInterface() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE HRESULT CreateClassInterface(PCCLSIFACECACHE pccic, PCCLSID pcclsid, PCIID pciid, PCLSIFACE *ppci) { HRESULT hr;
ASSERT(IS_VALID_STRUCT_PTR(pccic, CCLSIFACECACHE)); ASSERT(IS_VALID_STRUCT_PTR(pcclsid, CCLSID)); ASSERT(IS_VALID_STRUCT_PTR(pciid, CIID)); ASSERT(IS_VALID_WRITE_PTR(ppci, PCLSIFACE));
if (AllocateMemory(sizeof(**ppci), ppci)) { /* Use inproc servers and local servers. */
// Security: Per the comment above removing CLSCTS_SERVER and
// replacing with just inproc and local (no remote).
hr = CoCreateInstance(pcclsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, pciid, &((*ppci)->pvInterface));
if (SUCCEEDED(hr)) { ARRAYINDEX ai;
(*ppci)->pcclsid = pcclsid; (*ppci)->pciid = pciid;
if (! AddPtr(pccic->hpa, ClassInterfaceSortCmp, *ppci, &ai)) { hr = E_OUTOFMEMORY; CREATECLASSINTERFACE_BAIL: FreeMemory(*ppci); } } else { WARNING_OUT((TEXT("CreateClassInterface(): CoCreateInstance() failed, returning %s."), GetHRESULTString(hr)));
goto CREATECLASSINTERFACE_BAIL; } } else hr = E_OUTOFMEMORY;
ASSERT(FAILED(hr) || IS_VALID_STRUCT_PTR(*ppci, CCLSIFACE));
return(hr); }
/*
** DestroyClassInterface() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE void DestroyClassInterface(PCLSIFACE pci) { ASSERT(IS_VALID_STRUCT_PTR(pci, CCLSIFACE));
((PCIUnknown)(pci->pvInterface))->lpVtbl->Release(pci->pvInterface); FreeMemory(pci);
return; }
/*
** ClassInterfaceSortCmp() ** ** Pointer comparison function used to sort an array of pointers to class ** interfaces. ** ** Arguments: pcci1 - pointer to first class interface ** pcci2 - pointer to second class interface ** ** Returns: ** ** Side Effects: none ** ** The class interfaces are sorted by: ** 1) CLSID ** 2) IID */ PRIVATE_CODE COMPARISONRESULT ClassInterfaceSortCmp(PCVOID pcci1, PCVOID pcci2) { COMPARISONRESULT cr;
ASSERT(IS_VALID_STRUCT_PTR(pcci1, CCLSIFACE)); ASSERT(IS_VALID_STRUCT_PTR(pcci2, CCLSIFACE));
cr = CompareClassIDs(((PCCLSIFACE)pcci1)->pcclsid, ((PCCLSIFACE)pcci2)->pcclsid);
if (cr == CR_EQUAL) cr = CompareInterfaceIDs(((PCCLSIFACE)pcci1)->pciid, ((PCCLSIFACE)pcci2)->pciid);
return(cr); }
/*
** ClassInterfaceSearchCmp() ** ** Pointer comparison function used to search an array of pointers to class ** interfaces. ** ** Arguments: pccisi - pointer to class interface search information ** pcci - pointer to class interface to examine ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE COMPARISONRESULT ClassInterfaceSearchCmp(PCVOID pccisi, PCVOID pcci) { COMPARISONRESULT cr;
ASSERT(IS_VALID_STRUCT_PTR(pccisi, CCLSIFACESEARCHINFO)); ASSERT(IS_VALID_STRUCT_PTR(pcci, CCLSIFACE));
cr = CompareClassIDs(((PCCLSIFACESEARCHINFO)pccisi)->pcclsid, ((PCCLSIFACE)pcci)->pcclsid);
if (cr == CR_EQUAL) cr = CompareInterfaceIDs(((PCCLSIFACESEARCHINFO)pccisi)->pciid, ((PCCLSIFACE)pcci)->pciid);
return(cr); }
#ifdef DEBUG
/*
** IsValidPCCLSIFACECACHE() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL IsValidPCCLSIFACECACHE(PCCLSIFACECACHE pccic) { return(IS_VALID_READ_PTR(pccic, CLSIFACECACHE) && IS_VALID_HANDLE(pccic->hpa, PTRARRAY)); }
/*
** IsValidPCCLSIFACE() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL IsValidPCCLSIFACE(PCCLSIFACE pcci) { return(IS_VALID_READ_PTR(pcci, CCLSIFACE) && IS_VALID_STRUCT_PTR(pcci->pcclsid, CCLSID) && IS_VALID_STRUCT_PTR(pcci->pciid, CIID) && IS_VALID_STRUCT_PTR(pcci->pvInterface, CInterface)); }
/*
** IsValidPCCLSIFACESEARCHINFO() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL IsValidPCCLSIFACESEARCHINFO(PCCLSIFACESEARCHINFO pccisi) { return(IS_VALID_READ_PTR(pccisi, CCLSIFACESEARCHINFO) && IS_VALID_STRUCT_PTR(pccisi->pcclsid, CCLSID) && IS_VALID_STRUCT_PTR(pccisi->pciid, CIID)); }
#endif
/****************************** Public Functions *****************************/
/*
** CreateClassInterfaceCache() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL CreateClassInterfaceCache(PHCLSIFACECACHE phcic) { BOOL bResult = FALSE; PCLSIFACECACHE pcic;
ASSERT(IS_VALID_WRITE_PTR(phcic, HCLSIFACECACHE));
if (AllocateMemory(sizeof(*pcic), &pcic)) { if (CreateClassInterfacePtrArray(&(pcic->hpa))) { *phcic = (HCLSIFACECACHE)pcic; bResult = TRUE; } else FreeMemory(pcic); }
ASSERT(! bResult || IS_VALID_HANDLE(*phcic, CLSIFACECACHE));
return(bResult); }
/*
** DestroyClassInterfaceCache() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE void DestroyClassInterfaceCache(HCLSIFACECACHE hcic) { ASSERT(IS_VALID_HANDLE(hcic, CLSIFACECACHE));
DestroyClassInterfacePtrArray(((PCLSIFACECACHE)hcic)->hpa); FreeMemory(hcic);
return; }
/*
** GetClassInterface() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none ** ** N.b., this function assumes that pcclsid and pciid are valid until hcic is ** destroyed with DestroyClassInterfaceCache(). */ PUBLIC_CODE HRESULT GetClassInterface(HCLSIFACECACHE hcic, PCCLSID pcclsid, PCIID pciid, PVOID *ppvInterface) { HRESULT hr; CLSIFACESEARCHINFO cisi; ARRAYINDEX ai; PCLSIFACE pci;
ASSERT(IS_VALID_HANDLE(hcic, CLSIFACECACHE));
/* Is this class interface already in the cache? */
cisi.pcclsid = pcclsid; cisi.pciid = pciid;
if (SearchSortedArray(((PCCLSIFACECACHE)hcic)->hpa, &ClassInterfaceSearchCmp, &cisi, &ai)) { /* Yes. Use it. */
pci = GetPtr(((PCCLSIFACECACHE)hcic)->hpa, ai);
hr = S_OK; } else /* No. Add it. */ hr = CreateClassInterface((PCCLSIFACECACHE)hcic, pcclsid, pciid, &pci);
if (SUCCEEDED(hr)) { ASSERT(IS_VALID_STRUCT_PTR(pci, CCLSIFACE));
*ppvInterface = pci->pvInterface; }
ASSERT(FAILED(hr) || IS_VALID_STRUCT_PTR(*ppvInterface, CInterface));
return(hr); }
#ifdef DEBUG
/*
** IsValidHCLSIFACECACHE() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL IsValidHCLSIFACECACHE(HCLSIFACECACHE hcic) { return(IS_VALID_STRUCT_PTR((PCCLSIFACECACHE)hcic, CCLSIFACECACHE)); }
#endif
|