NT4/private/windows/rover/filesync/core/clsiface.c
2020-09-30 17:12:29 +02:00

505 lines
9.3 KiB
C

/*
* 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. */
hr = CoCreateInstance(pcclsid, NULL, CLSCTX_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