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.
506 lines
10 KiB
506 lines
10 KiB
/*
|
|
* 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
|
|
|