fleshed out the connection point implementation, especially the enumerations part

This commit is contained in:
Eric J. Bowersox 2013-06-04 00:51:34 -06:00
parent a5aeeb2980
commit c728482744
14 changed files with 969 additions and 18 deletions

View File

@ -69,3 +69,20 @@ interface IServiceProvider : IUnknown
[unique] typedef IServiceProvider *PSERVICEPROVIDER; [unique] typedef IServiceProvider *PSERVICEPROVIDER;
HRESULT QueryService([in] REFGUID guidService, [in] REFIID riid, [out, iid_is(riid)] PPVOID ppvObject); HRESULT QueryService([in] REFGUID guidService, [in] REFIID riid, [out, iid_is(riid)] PPVOID ppvObject);
} }
/*------------------------
* IEnumUnknown interface
*------------------------
*/
[object, uuid(00000100-0000-0000-C000-000000000046), pointer_default(unique)]
interface IEnumUnknown: IUnknown
{
[unique] typedef IEnumUnknown *PENUMUNKNOWN;
HRESULT Next([in] UINT32 celt, [out, size_is(celt), length_is(*pceltFetched)] IUnknown **rgelt,
[out] UINT32 *pceltFetched);
HRESULT Skip([in] UINT32 celt);
HRESULT Reset(void);
HRESULT Clone([out] IEnumUnknown **ppEnum);
}

View File

@ -46,10 +46,10 @@
typedef struct tagRAWHEAPDATA typedef struct tagRAWHEAPDATA
{ {
UINT32 opaque[8]; UINT32 opaque[32]; /* opaque data, do not modify */
} RAWHEAPDATA, *PRAWHEAPDATA; } RAWHEAPDATA, *PRAWHEAPDATA;
typedef void (*PFNRAWHEAPDATAFREE)(PRAWHEAPDATA prhd); typedef void (*PFNRAWHEAPDATAFREE)(PRAWHEAPDATA prhd); /* function that optionally frees the heap data */
/*-------------------- /*--------------------
* External functions * External functions

View File

@ -51,8 +51,9 @@ typedef struct tagFIXEDCPDATA
PUNKNOWN punkOuter; /* outer unknown used for reference counts */ PUNKNOWN punkOuter; /* outer unknown used for reference counts */
REFIID riidConnection; /* IID of outgoing interface for this connection point */ REFIID riidConnection; /* IID of outgoing interface for this connection point */
IUnknown **ppSlots; /* pointer to actual slots used for connection point storage */ IUnknown **ppSlots; /* pointer to actual slots used for connection point storage */
INT32 ncpSize; /* number of connection points actually connected */ UINT32 ncpSize; /* number of connection points actually connected */
INT32 ncpCapacity; /* maximum number of connection points connectable */ UINT32 ncpCapacity; /* maximum number of connection points connectable */
IMalloc *pAllocator; /* pointer to allocator */
} FIXEDCPDATA, *PFIXEDCPDATA; } FIXEDCPDATA, *PFIXEDCPDATA;
/*--------------------- /*---------------------
@ -64,6 +65,7 @@ CDECL_BEGIN
/* QueryInterface helpers */ /* QueryInterface helpers */
extern HRESULT ObjHlpStandardQueryInterface_IConnectionPoint(IUnknown *pThis, REFIID riid, PPVOID ppvObject); extern HRESULT ObjHlpStandardQueryInterface_IConnectionPoint(IUnknown *pThis, REFIID riid, PPVOID ppvObject);
extern HRESULT ObjHlpStandardQueryInterface_IEnumConnections(IUnknown *pThis, REFIID riid, PPVOID ppvObject);
extern HRESULT ObjHlpStandardQueryInterface_IMalloc(IUnknown *pThis, REFIID riid, PPVOID ppvObject); extern HRESULT ObjHlpStandardQueryInterface_IMalloc(IUnknown *pThis, REFIID riid, PPVOID ppvObject);
extern HRESULT ObjHlpStandardQueryInterface_ISequentialStream(IUnknown *pThis, REFIID riid, PPVOID ppvObject); extern HRESULT ObjHlpStandardQueryInterface_ISequentialStream(IUnknown *pThis, REFIID riid, PPVOID ppvObject);
@ -72,7 +74,7 @@ extern UINT32 ObjHlpStaticAddRefRelease(IUnknown *pThis);
/* Connection point helpers */ /* Connection point helpers */
extern void ObjHlpFixedCpSetup(PFIXEDCPDATA pData, PUNKNOWN punkOuter, REFIID riidConnection, extern void ObjHlpFixedCpSetup(PFIXEDCPDATA pData, PUNKNOWN punkOuter, REFIID riidConnection,
IUnknown **ppSlots, INT32 nSlots); IUnknown **ppSlots, UINT32 nSlots, IMalloc *pAllocator);
extern void ObjHlpFixedCpTeardown(PFIXEDCPDATA pData); extern void ObjHlpFixedCpTeardown(PFIXEDCPDATA pData);
/* Other helpers */ /* Other helpers */

View File

@ -93,6 +93,10 @@
#define STG_S_CONSOLIDATIONFAILED SCODE_CAST(0x00030205) /* consolidation failed but commit OK */ #define STG_S_CONSOLIDATIONFAILED SCODE_CAST(0x00030205) /* consolidation failed but commit OK */
#define STG_S_CANNOTCONSOLIDATE SCODE_CAST(0x00030206) /* cannot consolidate but commit OK */ #define STG_S_CANNOTCONSOLIDATE SCODE_CAST(0x00030206) /* cannot consolidate but commit OK */
/* Connection success codes */
#define CONNECT_S_FIRST SCODE_CAST(0x00040200) /* first connection success code */
#define CONNECT_S_LAST SCODE_CAST(0x0004020F) /* last connection success code */
/* Memory manager success codes */ /* Memory manager success codes */
#define MEMMGR_S_NONZEROED SCODE_CAST(0x06010001) /* returned memory is non-zeroed */ #define MEMMGR_S_NONZEROED SCODE_CAST(0x06010001) /* returned memory is non-zeroed */
@ -158,6 +162,15 @@
#define STG_E_CSSINVALIDREGION SCODE_CAST(0x8003030A) /* region identifier mismatch */ #define STG_E_CSSINVALIDREGION SCODE_CAST(0x8003030A) /* region identifier mismatch */
#define STG_E_NOMOREREGIONRESETS SCODE_CAST(0x8003030B) /* can't reset drive region anymore */ #define STG_E_NOMOREREGIONRESETS SCODE_CAST(0x8003030B) /* can't reset drive region anymore */
/* Connection error codes */
#define CONNECT_E_FIRST SCODE_CAST(0x80040200) /* first connection error code */
#define CONNECT_E_LAST SCODE_CAST(0x8004020F) /* last connection error code */
#define CONNECT_E_NOCONNECTION (CONNECT_E_FIRST+0) /* no connection found */
#define CONNECT_E_ADVISELIMIT (CONNECT_E_FIRST+1) /* limit for number of connections reached */
#define CONNECT_E_CANNOTCONNECT (CONNECT_E_FIRST+2) /* connection attempt failed */
#define CONNECT_E_OVERRIDDEN (CONNECT_E_FIRST+3) /* interface overridden, must use derived */
/* Memory manager error codes */ /* Memory manager error codes */
#define MEMMGR_E_NOPGTBL SCODE_CAST(0x86010001) /* no page tables available */ #define MEMMGR_E_NOPGTBL SCODE_CAST(0x86010001) /* no page tables available */
#define MEMMGR_E_BADTTBFLG SCODE_CAST(0x86010002) /* bad TTB flags encountered */ #define MEMMGR_E_BADTTBFLG SCODE_CAST(0x86010002) /* bad TTB flags encountered */

View File

@ -32,8 +32,8 @@ MAKEFLAGS += -rR
CRBASEDIR := $(abspath ../..) CRBASEDIR := $(abspath ../..)
include $(CRBASEDIR)/armcompile.mk include $(CRBASEDIR)/armcompile.mk
LIB_OBJS = divide.o qdivrem.o heap_toplevel.o intlib.o objhelp.o objhelp_fixedcp.o rbtree.o str.o \ LIB_OBJS = divide.o qdivrem.o heap_toplevel.o intlib.o objhelp.o objhelp_enumconn.o objhelp_enumgeneric.o \
strcopymem.o strcomparemem.o strsetmem.o lib_guids.o objhelp_fixedcp.o rbtree.o str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o
all: kernel-lib.o all: kernel-lib.o

77
kernel/lib/enumconn.h Normal file
View File

@ -0,0 +1,77 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#ifndef __ENUMCONN_H_INCLUDED
#define __ENUMCONN_H_INCLUDED
#ifdef __COMROGUE_INTERNALS__
#ifndef __ASM__
#include <comrogue/types.h>
#include <comrogue/objectbase.h>
#include <comrogue/connpoint.h>
#include <comrogue/allocator.h>
/*---------------------------------------------------
* Data structures for implementing IEnumConnections
*---------------------------------------------------
*/
typedef struct tagENUMCONNDATA {
UINT32 uiRefCount; /* reference count */
UINT32 nConnectData; /* count of CONNECTDATA */
CONNECTDATA rgConnectData[0]; /* array of CONNECTDATA */
} ENUMCONNDATA, *PENUMCONNDATA;
typedef struct tagENUMCONN {
IEnumConnections enumConnections; /* interface pointer */
UINT32 uiRefCount; /* reference count */
UINT32 nCurrent; /* current pointer into array */
PENUMCONNDATA pPayload; /* payload array */
IMalloc *pAllocator; /* allocator pointer */
} ENUMCONN, *PENUMCONN;
/*---------------------------------------------------
* Functions for implementing IEnumConnections
*---------------------------------------------------
*/
extern PENUMCONNDATA _ObjHlpAllocateEnumConnData(IMalloc *pAllocator, UINT32 nCapacity);
extern void _ObjHlpAddToEnumConnData(PENUMCONNDATA pecd, IUnknown *pUnk, UINT32 uiCookie);
extern void _ObjHlpDiscardEnumConnData(PENUMCONNDATA pecd);
extern PENUMCONN _ObjHlpAllocateEnumConn(IMalloc *pAllocator, PENUMCONNDATA pecd, UINT32 nCurrent);
#endif /* __ASM__ */
#endif /* __COMROGUE_INTERNALS__ */
#endif /* __ENUMCONN_H_INCLUDED */

78
kernel/lib/enumgeneric.h Normal file
View File

@ -0,0 +1,78 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#ifndef __ENUMGENERIC_H_INCLUDED
#define __ENUMGENERIC_H_INCLUDED
#ifdef __COMROGUE_INTERNALS__
#ifndef __ASM__
#include <comrogue/types.h>
#include <comrogue/objectbase.h>
#include <comrogue/allocator.h>
/*---------------------------------------------------------------------------------------------------
* Data structures for implementing IEnumUnknown or any interface that enumerates interface pointers
*---------------------------------------------------------------------------------------------------
*/
typedef struct tagENUMGENERICDATA {
UINT32 uiRefCount; /* reference count */
UINT32 nObjects; /* count of IUnknown pointers */
PUNKNOWN rgObjects[0]; /* array of IUnknown pointers */
} ENUMGENERICDATA, *PENUMGENERICDATA;
typedef struct tagENUMGENERIC {
IEnumUnknown enumUnknown; /* interface pointer */
UINT32 uiRefCount; /* reference count */
REFIID riidActual; /* IID of actual interface */
UINT32 nCurrent; /* current pointer into array */
PENUMGENERICDATA pPayload; /* payload array */
IMalloc *pAllocator; /* allocator pointer */
} ENUMGENERIC, *PENUMGENERIC;
/*---------------------------------------------------------------------------------------------
* Functions for implementing IEnumUnknown or any interface that enumerates interface pointers
*---------------------------------------------------------------------------------------------
*/
extern PENUMGENERICDATA _ObjHlpAllocateEnumGenericData(IMalloc *pAllocator, UINT32 nCapacity);
extern void _ObjHlpAddToEnumGenericData(PENUMGENERICDATA pegd, IUnknown *pUnk);
extern void _ObjHlpDiscardEnumGenericData(PENUMGENERICDATA pecd);
extern PENUMGENERIC _ObjHlpAllocateEnumGeneric(IMalloc *pAllocator, REFIID riidActual, PENUMGENERICDATA pegd,
UINT32 nCurrent);
#endif /* __ASM__ */
#endif /* __COMROGUE_INTERNALS__ */
#endif /* __ENUMGENERIC_H_INCLUDED */

View File

@ -35,10 +35,15 @@
#ifndef __HEAP_INTERNALS_H_INCLUDED #ifndef __HEAP_INTERNALS_H_INCLUDED
#define __HEAP_INTERNALS_H_INCLUDED #define __HEAP_INTERNALS_H_INCLUDED
#ifdef __COMROGUE_INTERNALS__
#ifndef __ASM__
#include <comrogue/objectbase.h> #include <comrogue/objectbase.h>
#include <comrogue/connpoint.h> #include <comrogue/connpoint.h>
#include <comrogue/allocator.h> #include <comrogue/allocator.h>
#include <comrogue/heap.h> #include <comrogue/heap.h>
#include <comrogue/objhelp.h>
/*---------------------------------- /*----------------------------------
* The actual heap data declaration * The actual heap data declaration
@ -49,8 +54,17 @@ typedef struct tagHEAPDATA {
IMalloc mallocInterface; /* pointer to IMalloc interface - MUST BE FIRST! */ IMalloc mallocInterface; /* pointer to IMalloc interface - MUST BE FIRST! */
IConnectionPointContainer cpContainerInterface; /* pointer to IConnectionPointContainer interface */ IConnectionPointContainer cpContainerInterface; /* pointer to IConnectionPointContainer interface */
UINT32 uiRefCount; /* reference count */ UINT32 uiRefCount; /* reference count */
UINT32 uiFlags; /* flags word */
PFNRAWHEAPDATAFREE pfnFreeRawHeapData; /* pointer to function that frees the raw heap data, if any */ PFNRAWHEAPDATAFREE pfnFreeRawHeapData; /* pointer to function that frees the raw heap data, if any */
IChunkAllocator *pChunkAllocator; /* chunk allocator pointer */ IChunkAllocator *pChunkAllocator; /* chunk allocator pointer */
FIXEDCPDATA fcpMallocSpy; /* connection point for IMallocSpy */
FIXEDCPDATA fcpSequentialStream; /* connection point for ISequentialStream for debugging */
IMallocSpy *pMallocSpy; /* IMallocSpy interface for the allocator */
ISequentialStream *pDebugStream; /* debugging output stream */
} HEAPDATA, *PHEAPDATA; } HEAPDATA, *PHEAPDATA;
#endif /* __ASM__ */
#endif /* __COMROGUE_INTERNALS__ */
#endif /* __HEAP_INTERNALS_H_INCLUDED */ #endif /* __HEAP_INTERNALS_H_INCLUDED */

View File

@ -41,6 +41,8 @@
#include <comrogue/internals/seg.h> #include <comrogue/internals/seg.h>
#include "heap_internals.h" #include "heap_internals.h"
#define PHDFLAGS_DELETING 0x80000000 /* deleting the heap */
/*------------------------ /*------------------------
* IMalloc implementation * IMalloc implementation
*------------------------ *------------------------
@ -105,8 +107,11 @@ static UINT32 malloc_Release(IUnknown *pThis)
PFNRAWHEAPDATAFREE pfnFree; /* pointer to "free" function */ PFNRAWHEAPDATAFREE pfnFree; /* pointer to "free" function */
rc = --(phd->uiRefCount); rc = --(phd->uiRefCount);
if (rc == 0) if ((rc == 0) && !(phd->uiFlags & PHDFLAGS_DELETING))
{ {
phd->uiFlags |= PHDFLAGS_DELETING;
ObjHlpFixedCpTeardown(&(phd->fcpMallocSpy));
ObjHlpFixedCpTeardown(&(phd->fcpSequentialStream));
IUnknown_Release(phd->pChunkAllocator); IUnknown_Release(phd->pChunkAllocator);
if (phd->pfnFreeRawHeapData) if (phd->pfnFreeRawHeapData)
{ {
@ -218,12 +223,26 @@ static UINT32 cpc_Release(IUnknown *pThis)
static HRESULT cpc_EnumConnectionPoints(IConnectionPointContainer *pThis, IEnumConnectionPoints **ppEnum) static HRESULT cpc_EnumConnectionPoints(IConnectionPointContainer *pThis, IEnumConnectionPoints **ppEnum)
{ {
PHEAPDATA phd = (PHEAPDATA)HeapDataPtr(pThis); /* pointer to heap data */
return E_NOTIMPL; /* TODO */ return E_NOTIMPL; /* TODO */
} }
static HRESULT cpc_FindConnectionPoint(IConnectionPointContainer *pThis, REFIID riid, IConnectionPoint **ppCP) static HRESULT cpc_FindConnectionPoint(IConnectionPointContainer *pThis, REFIID riid, IConnectionPoint **ppCP)
{ {
return E_NOTIMPL; /* TODO */ PHEAPDATA phd = (PHEAPDATA)HeapDataPtr(pThis); /* pointer to heap data */
if (!ppCP)
return E_POINTER;
*ppCP = NULL;
if (IsEqualIID(riid, &IID_IMallocSpy))
*ppCP = (IConnectionPoint *)(&(phd->fcpMallocSpy));
else if (IsEqualIID(riid, &IID_ISequentialStream))
*ppCP = (IConnectionPoint *)(&(phd->fcpSequentialStream));
else
return CONNECT_E_NOCONNECTION;
IUnknown_AddRef(*ppCP);
return S_OK;
} }
/* The IConnectionPointContainer vtable. */ /* The IConnectionPointContainer vtable. */
@ -272,9 +291,13 @@ HRESULT HeapCreate(PRAWHEAPDATA prhd, PFNRAWHEAPDATAFREE pfnFree, IChunkAllocato
phd->mallocInterface.pVTable = &vtblMalloc; phd->mallocInterface.pVTable = &vtblMalloc;
phd->cpContainerInterface.pVTable = &vtblConnectionPointContainer; phd->cpContainerInterface.pVTable = &vtblConnectionPointContainer;
phd->uiRefCount = 1; phd->uiRefCount = 1;
phd->uiFlags = 0;
phd->pfnFreeRawHeapData = pfnFree; phd->pfnFreeRawHeapData = pfnFree;
phd->pChunkAllocator = pChunkAllocator; phd->pChunkAllocator = pChunkAllocator;
IUnknown_AddRef(phd->pChunkAllocator); IUnknown_AddRef(phd->pChunkAllocator);
ObjHlpFixedCpSetup(&(phd->fcpMallocSpy), (PUNKNOWN)phd, &IID_IMallocSpy, (IUnknown **)(&(phd->pMallocSpy)), 1, NULL);
ObjHlpFixedCpSetup(&(phd->fcpSequentialStream), (PUNKNOWN)phd, &IID_ISequentialStream,
(IUnknown **)(&(phd->pDebugStream)), 1, NULL);
*ppHeap = (IMalloc *)phd; *ppHeap = (IMalloc *)phd;
return S_OK; return S_OK;

View File

@ -94,6 +94,7 @@ HRESULT ObjHlpStandardQueryInterface_ ## iface (IUnknown *pThis, REFIID riid, PP
} }
MAKE_BASE_QI(IConnectionPoint) MAKE_BASE_QI(IConnectionPoint)
MAKE_BASE_QI(IEnumConnections)
MAKE_BASE_QI(IMalloc) MAKE_BASE_QI(IMalloc)
MAKE_BASE_QI(ISequentialStream) MAKE_BASE_QI(ISequentialStream)

View File

@ -0,0 +1,319 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#include <comrogue/types.h>
#include <comrogue/intlib.h>
#include <comrogue/str.h>
#include <comrogue/objectbase.h>
#include <comrogue/connpoint.h>
#include <comrogue/allocator.h>
#include <comrogue/objhelp.h>
#include "enumconn.h"
/*-------------------------------------------
* IEnumConnections interface implementation
*-------------------------------------------
*/
/*
* Adds a reference to the enumerator object.
*
* Parameters:
* - pThis = Pointer to the enumerator object (actually its IEnumConnections interface pointer).
*
* Returns:
* The new reference count on the object.
*/
static UINT32 enumConn_AddRef(IUnknown *pThis)
{
return ++(((PENUMCONN)pThis)->uiRefCount);
}
/*
* Removes a reference from the enumerator object. The object is freed when its reference count reaches 0.
*
* Parameters:
* - pThis = Pointer to the enumerator object (actually its IEnumConnections interface pointer).
*
* Returns:
* The new reference count on the object.
*/
static UINT32 enumConn_Release(IUnknown *pThis)
{
register PENUMCONN pec = (PENUMCONN)pThis; /* pointer to actual data block */
register UINT32 rc; /* return from this function */
IMalloc *pAllocator; /* temporary for allocator */
PENUMCONNDATA pecd; /* temporary for underlying connections data block */
rc = --(pec->uiRefCount);
if (rc == 0)
{ /* save off allocator before deallocating */
pAllocator = pec->pAllocator;
IUnknown_AddRef(pAllocator);
/* save off payload too */
pecd = pec->pPayload;
/* erase enumerator */
IUnknown_Release(pec->pAllocator);
IMalloc_Free(pAllocator, pec);
if (--(pecd->uiRefCount) == 0)
{ /* we need to erase the data block too */
_ObjHlpDiscardEnumConnData(pecd);
IMalloc_Free(pAllocator, pecd);
}
IUnknown_Release(pAllocator); /* release temporary reference we added */
}
return rc;
}
/*
* Retrieves the next number of connections in the enumeration sequence.
*
* Parameters:
* - pThis = Pointer to the enumerator object (actually its IEnumConnections interface pointer).
* - cConnections = Number of connections to be retrieved. If there are more than this many connections
* in the enumeration sequence, this many are returned.
* - rgcd = Array of enumerated items which will be filled in by this function. Note that the caller is
* responsible for releasing all interface pointers returned as a result of this call.
* - pcFetched = Pointer to a variable which will receive the number of connections retrieved. This value will
* always be less than or equal to cConnections.
*
* Returns:
* - S_OK = All the connections requested were retrieved. *pcFetched is equal to cConnections.
* - S_FALSE = Not all the connections requested could be retrieved. *pcFetched is less than cConnections.
* - Other = An error result.
*/
static HRESULT enumConn_Next(IEnumConnections *pThis, UINT32 cConnections, PCONNECTDATA rgcd, UINT32 *pcFetched)
{
register PENUMCONN pec = (PENUMCONN)pThis; /* pointer to data block */
register UINT32 i; /* loop counter */
if (cConnections == 0)
{ /* nothing to retrieve */
if (pcFetched)
*pcFetched = 0;
return S_OK;
}
if (!pcFetched)
return E_POINTER; /* invalid pointer */
/* get number of items to fetch */
*pcFetched = intMin(pec->pPayload->nConnectData - pec->nCurrent, cConnections);
for (i = 0; i < *pcFetched; i++)
{ /* fetch the items */
rgcd[i].pUnk = pec->pPayload->rgConnectData[i + pec->nCurrent].pUnk;
IUnknown_AddRef(rgcd[i].pUnk);
rgcd[i].uiCookie = pec->pPayload->rgConnectData[i + pec->nCurrent].uiCookie;
}
pec->nCurrent += *pcFetched; /* advance pointer */
return (*pcFetched == cConnections) ? S_OK : S_FALSE;
}
/*
* Skips over the next number of connections in the enumeration sequence.
*
* Parameters:
* - pThis = Pointer to the enumerator object (actually its IEnumConnections interface pointer).
* - cConnections = Number of connections to be skipped. If there are fewer than this many connections
* in the enumeration sequence, we skip straight to the end.
*
* Returns:
* - S_OK = We were able to skip over all the specified items.
* - S_FALSE = We were not able to skip over all the specified items. The current position of the enumeration
* is at the end of the sequence.
*/
static HRESULT enumConn_Skip(IEnumConnections *pThis, UINT32 cConnections)
{
register PENUMCONN pec = (PENUMCONN)pThis; /* pointer to data block */
register HRESULT rc = S_OK; /* return from this function */
pec->nCurrent += cConnections;
if (pec->nCurrent > pec->pPayload->nConnectData)
{ /* clamp current pointer and return FALSE */
pec->nCurrent = pec->pPayload->nConnectData;
rc = S_FALSE;
}
return rc;
}
/*
* Resets the enumeration sequence to the beginning.
*
* Parameters:
* - pThis = Pointer to the enumerator object (actually its IEnumConnections interface pointer).
*
* Returns:
* S_OK.
*/
static HRESULT enumConn_Reset(IEnumConnections *pThis)
{
((PENUMCONN)pThis)->nCurrent = 0;
return S_OK;
}
/*
* Creates a new enumerator with the same state as the current one.
*
* Parameters:
* - pThis = Pointer to the enumerator object (actually its IEnumConnections interface pointer).
* - ppEnum = Pointer to variable to receive the new enumerator object. The caller is responsible for releasing
* this pointer.
*
* Returns:
* - S_OK = Success.
* - E_INVALIDARG = The pointer argument is not valid.
* - E_OUTOFMEMORY = The memory for a new enumerator could not be allocated.
*/
static HRESULT enumConn_Clone(IEnumConnections *pThis, IEnumConnections **ppEnum)
{
register PENUMCONN pec = (PENUMCONN)pThis; /* pointer to data block */
register PENUMCONN pecNew; /* pointer to new enumerator */
if (!ppEnum) /* no pointer? */
return E_INVALIDARG;
*ppEnum = NULL;
pecNew = _ObjHlpAllocateEnumConn(pec->pAllocator, pec->pPayload, pec->nCurrent);
if (!pecNew) /* failed to allocate? */
return E_OUTOFMEMORY;
IUnknown_QueryInterface((IUnknown *)pecNew, &IID_IEnumConnections, (PPVOID)ppEnum);
return S_OK;
}
/* The VTable for the IEnumConnections interface. */
static const SEG_RODATA struct IEnumConnectionsVTable vtblEnumConnections =
{
.QueryInterface = ObjHlpStandardQueryInterface_IEnumConnections,
.AddRef = enumConn_AddRef,
.Release = enumConn_Release,
.Next = enumConn_Next,
.Skip = enumConn_Skip,
.Reset = enumConn_Reset,
.Clone = enumConn_Clone
};
/*-----------------------------------
* IEnumConnections helper functions
*-----------------------------------
*/
/*
* Allocate the "inner" connection data object for an enumerator.
*
* Parameters:
* - pAllocator = Allocator to use to allocate the memory.
* - nCapacity = Number of slots to allocate for the connection data.
*
* Returns:
* - NULL = The data object could not be allocated.
* - Other = Pointer to the new data object. Its reference count is 0 and it contains no elements.
*/
PENUMCONNDATA _ObjHlpAllocateEnumConnData(IMalloc *pAllocator, UINT32 nCapacity)
{
register PENUMCONNDATA rc; /* return from this function */
register SIZE_T cbReturn = sizeof(ENUMCONNDATA) + (nCapacity * sizeof(CONNECTDATA)); /* bytes to allocate */
rc = (PENUMCONNDATA)(IMalloc_Alloc(pAllocator, cbReturn));
if (rc != NULL)
{
StrSetMem(rc, 0, cbReturn);
rc->uiRefCount = 0;
rc->nConnectData = 0;
}
return rc;
}
/*
* Add an element to the specified "inner" connection data object. Used when building the object.
*
* Parameters:
* - pecd = Pointer to the connection data object.
* - pUnk = IUnknown pointer to add to the "next" slot. A reference is added to this pointer.
* - uiCookie = Cookie value to add to the "next" slot.
*
* Returns:
* Nothing.
*/
void _ObjHlpAddToEnumConnData(PENUMCONNDATA pecd, IUnknown *pUnk, UINT32 uiCookie)
{
pecd->rgConnectData[pecd->nConnectData].pUnk = pUnk;
IUnknown_AddRef(pecd->rgConnectData[pecd->nConnectData].pUnk);
pecd->rgConnectData[pecd->nConnectData].uiCookie = uiCookie;
pecd->nConnectData++;
}
/*
* Discards the contents of an "inner" connection data object by releasing all the interface pointers
* it contains.
*
* Parameters:
* - pecd = Pointer to the connection data object.
*
* Returns:
* Nothing.
*/
void _ObjHlpDiscardEnumConnData(PENUMCONNDATA pecd)
{
register UINT32 i; /* loop counter */
for (i = 0; i < pecd->nConnectData; i++)
IUnknown_Release(pecd->rgConnectData[i].pUnk);
}
/*
* Allocates a new "enumerator" data object.
*
* Parameters:
* - pAllocator = Allocator to use to allocate the memory.
* - pecd = Pointer to the "inner" connection data object to be used.
* - nCurrent = Value to set the "current" element pointer to.
*
* Returns:
* - NULL = The enumerator object could not be allocated.
* - Other = Pointer to the new enumerator object. Its reference count is 0.
*/
PENUMCONN _ObjHlpAllocateEnumConn(IMalloc *pAllocator, PENUMCONNDATA pecd, UINT32 nCurrent)
{
register PENUMCONN rc; /* return from this function */
rc = (PENUMCONN)(IMalloc_Alloc(pAllocator, sizeof(ENUMCONN)));
if (rc)
{ /* initialize all the fields */
rc->enumConnections.pVTable = &vtblEnumConnections;
rc->uiRefCount = 0;
rc->nCurrent = nCurrent;
rc->pPayload = pecd;
pecd->uiRefCount++;
rc->pAllocator = pAllocator;
IUnknown_AddRef(rc->pAllocator);
}
return rc;
}

View File

@ -0,0 +1,222 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#include <comrogue/types.h>
#include <comrogue/intlib.h>
#include <comrogue/str.h>
#include <comrogue/objectbase.h>
#include <comrogue/allocator.h>
#include <comrogue/objhelp.h>
#include <comrogue/stdobj.h>
#include "enumgeneric.h"
/*---------------------------------------
* IEnumUnknown interface implementation
*---------------------------------------
*/
static HRESULT enumGeneric_QueryInterface(IUnknown *pThis, REFIID riid, PPVOID ppvObject)
{
PENUMGENERIC peg = (PENUMGENERIC)pThis;
if (!ppvObject)
return E_POINTER;
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, peg->riidActual))
{
*ppvObject = pThis;
IUnknown_AddRef((PUNKNOWN)(*ppvObject));
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
static UINT32 enumGeneric_AddRef(IUnknown *pThis)
{
return ++(((PENUMGENERIC)pThis)->uiRefCount);
}
static UINT32 enumGeneric_Release(IUnknown *pThis)
{
register PENUMGENERIC peg = (PENUMGENERIC)pThis; /* pointer to actual data block */
register UINT32 rc; /* return from this function */
IMalloc *pAllocator; /* temporary for allocator */
PENUMGENERICDATA pegd; /* temporary for underlying objects data block */
rc = --(peg->uiRefCount);
if (rc == 0)
{ /* save off allocator before deallocating */
pAllocator = peg->pAllocator;
IUnknown_AddRef(pAllocator);
/* save off payload too */
pegd = peg->pPayload;
/* erase enumerator */
IUnknown_Release(peg->pAllocator);
IMalloc_Free(pAllocator, peg);
if (--(pegd->uiRefCount) == 0)
{ /* we need to erase the data block too */
_ObjHlpDiscardEnumGenericData(pegd);
IMalloc_Free(pAllocator, pegd);
}
IUnknown_Release(pAllocator); /* release temporary reference we added */
}
return rc;
}
static HRESULT enumGeneric_Next(IEnumUnknown *pThis, UINT32 celt, IUnknown **rgelt, UINT32 *pceltFetched)
{
register PENUMGENERIC peg = (PENUMGENERIC)pThis; /* pointer to data block */
register UINT32 i; /* loop counter */
if (celt == 0)
{ /* nothing to retrieve */
if (pceltFetched)
*pceltFetched = 0;
return S_OK;
}
if (!pceltFetched)
return E_POINTER; /* invalid pointer */
/* get number of items to fetch */
*pceltFetched = intMin(peg->pPayload->nObjects - peg->nCurrent, celt);
for (i = 0; i < *pceltFetched; i++)
{ /* fetch the items */
rgelt[i] = peg->pPayload->rgObjects[i + peg->nCurrent];
IUnknown_AddRef(rgelt[i]);
}
peg->nCurrent += *pceltFetched; /* advance pointer */
return (*pceltFetched == celt) ? S_OK : S_FALSE;
}
static HRESULT enumGeneric_Skip(IEnumUnknown *pThis, UINT32 celt)
{
register PENUMGENERIC peg = (PENUMGENERIC)pThis; /* pointer to data block */
register HRESULT rc = S_OK; /* return from this function */
peg->nCurrent += celt;
if (peg->nCurrent > peg->pPayload->nObjects)
{ /* clamp current pointer and return FALSE */
peg->nCurrent = peg->pPayload->nObjects;
rc = S_FALSE;
}
return rc;
}
static HRESULT enumGeneric_Reset(IEnumUnknown *pThis)
{
((PENUMGENERIC)pThis)->nCurrent = 0;
return S_OK;
}
static HRESULT enumGeneric_Clone(IEnumUnknown *pThis, IEnumUnknown **ppEnum)
{
register PENUMGENERIC peg = (PENUMGENERIC)pThis; /* pointer to data block */
register PENUMGENERIC pegNew; /* pointer to new enumerator */
if (!ppEnum) /* no pointer? */
return E_INVALIDARG;
*ppEnum = NULL;
pegNew = _ObjHlpAllocateEnumGeneric(peg->pAllocator, peg->riidActual, peg->pPayload, peg->nCurrent);
if (!pegNew) /* failed to allocate? */
return E_OUTOFMEMORY;
IUnknown_QueryInterface((IUnknown *)pegNew, peg->riidActual, (PPVOID)ppEnum);
return S_OK;
}
static const SEG_RODATA struct IEnumUnknownVTable vtblEnum =
{
.QueryInterface = enumGeneric_QueryInterface,
.AddRef = enumGeneric_AddRef,
.Release = enumGeneric_Release,
.Next = enumGeneric_Next,
.Skip = enumGeneric_Skip,
.Reset = enumGeneric_Reset,
.Clone = enumGeneric_Clone
};
/*---------------------------------
* IEnum[Generic] helper functions
*---------------------------------
*/
PENUMGENERICDATA _ObjHlpAllocateEnumGenericData(IMalloc *pAllocator, UINT32 nCapacity)
{
register PENUMGENERICDATA rc; /* return from this function */
register SIZE_T cbReturn = sizeof(ENUMGENERICDATA) + (nCapacity * sizeof(PUNKNOWN)); /* bytes to allocate */
rc = (PENUMGENERICDATA)(IMalloc_Alloc(pAllocator, cbReturn));
if (rc != NULL)
{
StrSetMem(rc, 0, cbReturn);
rc->uiRefCount = 0;
rc->nObjects = 0;
}
return rc;
}
void _ObjHlpAddToEnumGenericData(PENUMGENERICDATA pegd, IUnknown *pUnk)
{
pegd->rgObjects[pegd->nObjects] = pUnk;
IUnknown_AddRef(pegd->rgObjects[pegd->nObjects]);
pegd->nObjects++;
}
void _ObjHlpDiscardEnumGenericData(PENUMGENERICDATA pegd)
{
register UINT32 i; /* loop counter */
for (i = 0; i < pegd->nObjects; i++)
IUnknown_Release(pegd->rgObjects[i]);
}
PENUMGENERIC _ObjHlpAllocateEnumGeneric(IMalloc *pAllocator, REFIID riidActual, PENUMGENERICDATA pegd,
UINT32 nCurrent)
{
register PENUMGENERIC rc; /* return from this function */
rc = (PENUMGENERIC)(IMalloc_Alloc(pAllocator, sizeof(ENUMGENERIC)));
if (rc)
{ /* initialize all the fields */
rc->enumUnknown.pVTable = &vtblEnum;
rc->uiRefCount = 0;
rc->riidActual = riidActual;
rc->nCurrent = nCurrent;
rc->pPayload = pegd;
pegd->uiRefCount++;
rc->pAllocator = pAllocator;
IUnknown_AddRef(rc->pAllocator);
}
return rc;
}

View File

@ -34,22 +34,54 @@
#include <comrogue/str.h> #include <comrogue/str.h>
#include <comrogue/connpoint.h> #include <comrogue/connpoint.h>
#include <comrogue/objhelp.h> #include <comrogue/objhelp.h>
#include "enumconn.h"
/* Mask we XOR with the index of the slot plus 1. */
#define FIXEDCP_MASK 0x4669782A /* "Fix*" */
/*--------------------------------------------- /*---------------------------------------------
* IConnectionPoint vtable and implementations * IConnectionPoint vtable and implementations
*--------------------------------------------- *---------------------------------------------
*/ */
/*
* Adds a reference to the connection point object.
*
* Parameters:
* - pThis = Pointer to the connection point object (actually its IConnectionPoint interface pointer).
*
* Returns:
* The new reference count on the object.
*/
static UINT32 fixedcp_AddRef(IUnknown *pThis) static UINT32 fixedcp_AddRef(IUnknown *pThis)
{ {
return IUnknown_AddRef(((PFIXEDCPDATA)pThis)->punkOuter); return IUnknown_AddRef(((PFIXEDCPDATA)pThis)->punkOuter);
} }
/*
* Removes a reference from the connection point object. The object is freed when its reference count reaches 0.
*
* Parameters:
* - pThis = Pointer to the connection point object (actually its IConnectionPoint interface pointer).
*
* Returns:
* The new reference count on the object.
*/
static UINT32 fixedcp_Release(IUnknown *pThis) static UINT32 fixedcp_Release(IUnknown *pThis)
{ {
return IUnknown_Release(((PFIXEDCPDATA)pThis)->punkOuter); return IUnknown_Release(((PFIXEDCPDATA)pThis)->punkOuter);
} }
/*
* Retrieves the IID of the outgoing interface managed by this connection point.
*
* Parameters:
* - pThis = Pointer to the connection point object (actually its IConnectionPoint interface pointer).
* - pIID = Pointer to buffer to receive the IID of the outgoing interface managed by this connection point.
*
* Returns:
* Standard HRESULT success/failure indicator.
*/
static HRESULT fixedcp_GetConnectionInterface(IConnectionPoint *pThis, IID *pIID) static HRESULT fixedcp_GetConnectionInterface(IConnectionPoint *pThis, IID *pIID)
{ {
if (!pIID) if (!pIID)
@ -58,7 +90,18 @@ static HRESULT fixedcp_GetConnectionInterface(IConnectionPoint *pThis, IID *pIID
return S_OK; return S_OK;
} }
static HRESULT fixedcp_GetConnectionPointContainer(IConnectionPoint *pThis, IConnectionPointContainer *ppCPC) /*
* Retrieves the IConnectionPointContainer interface for this connection point's parent connectable object.
*
* Parameters:
* - pThis = Pointer to the connection point object (actually its IConnectionPoint interface pointer).
* - ppCPC = Pointer to variable to receive the IConnectionPointContainer interface. The caller is responsible
* for releasing this interface pointer.
*
* Returns:
* Standard HRESULT success/failure indicator.
*/
static HRESULT fixedcp_GetConnectionPointContainer(IConnectionPoint *pThis, IConnectionPointContainer **ppCPC)
{ {
register HRESULT rc; /* return from underlying QI */ register HRESULT rc; /* return from underlying QI */
@ -68,19 +111,132 @@ static HRESULT fixedcp_GetConnectionPointContainer(IConnectionPoint *pThis, ICon
return rc; return rc;
} }
/*
* Establishes a connection between the connection point and an event sink interface.
*
* Parameters:
* - pThis = Pointer to the connection point object (actually its IConnectionPoint interface pointer).
* - punkSink = Pointer to the event sink interface to attach.
* - puiCookie = Pointer to a variable to receive a "cookie" that can later be used with the Unadvise method
* on this interface to delete the connection.
*
* Returns:
* - S_OK = Connection established; *puiCookie contains the connection cookie.
* - E_POINTER = Either punkSink or puiCookie is invalid.
* - CONNECT_E_ADVISELIMIT = The connection point cannot accept any more connections.
* - CONNECT_E_CANNOTCONNECT = The event sink does not support the correct interface.
*/
static HRESULT fixedcp_Advise(IConnectionPoint *pThis, IUnknown *punkSink, UINT32 *puiCookie) static HRESULT fixedcp_Advise(IConnectionPoint *pThis, IUnknown *punkSink, UINT32 *puiCookie)
{ {
return E_NOTIMPL; /* TODO */ register PFIXEDCPDATA pData; /* pointer to actual data block */
register UINT32 i; /* index of slot to put sink in */
IUnknown *punkActualSink = NULL; /* actual sink pointer */
if (!punkSink || !puiCookie)
return E_POINTER; /* bogus */
*puiCookie = 0;
pData = (PFIXEDCPDATA)pThis;
if (pData->ncpSize == pData->ncpCapacity)
return CONNECT_E_ADVISELIMIT; /* too many connections */
if (FAILED(IUnknown_QueryInterface(punkSink, pData->riidConnection, (PPVOID)(&punkActualSink))))
return CONNECT_E_CANNOTCONNECT; /* cannot QI for our interface */
for (i = 0; i < pData->ncpCapacity; i++)
{ /* search for a slot */
if (!(pData->ppSlots[i]))
{ /* found slot, store sink */
pData->ppSlots[i] = punkActualSink;
*puiCookie = (UINT32)((i + 1) ^ FIXEDCP_MASK);
pData->ncpSize++;
return S_OK;
}
}
/* slot not found?!? */
IUnknown_Release(punkActualSink);
return E_UNEXPECTED;
} }
/*
* Terminates a previously-established connection between the connection point and an event sink interface.
*
* Parameters:
* - pThis = Pointer to the connection point object (actually its IConnectionPoint interface pointer).
* - uiCookie = Cookie previously returned by the Advise method on this interface.
*
* Returns:
* - S_OK = Connection was terminated successfully.
* - E_POINTER = The cookie value is invalid.
*/
static HRESULT fixedcp_Unadvise(IConnectionPoint *pThis, UINT32 uiCookie) static HRESULT fixedcp_Unadvise(IConnectionPoint *pThis, UINT32 uiCookie)
{ {
return E_NOTIMPL; /* TODO */ register PFIXEDCPDATA pData = (PFIXEDCPDATA)pThis; /* pointer to actual data block */
register UINT32 i; /* index of slot sink is in */
/* Decode the cookie value */
i = (UINT32)(uiCookie ^ FIXEDCP_MASK) - 1;
if ((i < 0) || (i >= pData->ncpCapacity) || !(pData->ppSlots[i]))
return E_POINTER;
/* Free up the slot */
IUnknown_Release(pData->ppSlots[i]);
pData->ppSlots[i] = NULL;
pData->ncpSize--;
return S_OK;
} }
/*
* Creates an enumerator object to iterate through the current connections on this connection point.
*
* Parameters:
* - pThis = Pointer to the connection point object (actually its IConnectionPoint interface pointer).
* - ppEnum = Pointer to variable to receive the enumerator object interface. The caller is responsible for
* releasing this object when it's no longer needed.
*
* Returns:
* - S_OK = Created the enumerator successfully.
* - E_NOTIMPL = Enumeration is not supported.
* - E_POINTER = ppEnum was not a valid pointer.
* - E_OUTOFMEMORY = Could not allocate the enumerator.
*/
static HRESULT fixedcp_EnumConnections(IConnectionPoint *pThis, IEnumConnections **ppEnum) static HRESULT fixedcp_EnumConnections(IConnectionPoint *pThis, IEnumConnections **ppEnum)
{ {
return E_NOTIMPL; /* TODO */ register PFIXEDCPDATA pData = (PFIXEDCPDATA)pThis; /* pointer to actual data block */
PENUMCONNDATA pecd; /* pointer to enumeration data */
PENUMCONN pec; /* pointer to enumerator */
register UINT32 i; /* loop counter */
if (!(pData->pAllocator))
return E_NOTIMPL; /* enumeration not implemented */
if (!ppEnum)
return E_POINTER; /* bad return pointer */
*ppEnum = NULL;
/* Allocate a data block. */
pecd = _ObjHlpAllocateEnumConnData(pData->pAllocator, pData->ncpSize);
if (!pecd)
return E_OUTOFMEMORY;
/* Fill the allocated data block. */
for (i = 0; i < pData->ncpCapacity; i++)
if (pData->ppSlots[i])
_ObjHlpAddToEnumConnData(pecd, pData->ppSlots[i], (UINT32)((i + 1) ^ FIXEDCP_MASK));
/* Allocate the enumerator. */
pec = _ObjHlpAllocateEnumConn(pData->pAllocator, pecd, 0);
if (pec)
{ /* QI it for our return value */
IUnknown_QueryInterface((IUnknown *)pec, &IID_IEnumConnections, (PPVOID)ppEnum);
return S_OK;
}
/* unable to allocate enumerator - bug out */
_ObjHlpDiscardEnumConnData(pecd);
IMalloc_Free(pData->pAllocator, pecd);
return E_OUTOFMEMORY;
} }
/* VTable for the fixed-size connection point implementation. */ /* VTable for the fixed-size connection point implementation. */
@ -101,8 +257,23 @@ static const SEG_RODATA struct IConnectionPointVTable vtblFixedCP =
*----------------------------------------------- *-----------------------------------------------
*/ */
/*
* Sets up a fixed-size connection point object.
*
* Parameters:
* - pData = Pointer to the data block to initialize.
* - punkOuter = Pointer to "outer unknown" for the connection point, which must implement IConnectionPointContainer.
* - riidConnection = Reference to the IID of the outgoing event interface.
* - ppSlots = Pointer to the array of IUnknown "slots" used by this connection point.
* - nSlots = Number of slots to allocate.
* - pAllocator = Pointer to a memory allocator to use to allocate enumerators. This may be NULL if you don't
* want to support enumeration.
*
* Returns:
* Nothing.
*/
void ObjHlpFixedCpSetup(PFIXEDCPDATA pData, PUNKNOWN punkOuter, REFIID riidConnection, void ObjHlpFixedCpSetup(PFIXEDCPDATA pData, PUNKNOWN punkOuter, REFIID riidConnection,
IUnknown **ppSlots, INT32 nSlots) IUnknown **ppSlots, UINT32 nSlots, IMalloc *pAllocator)
{ {
pData->connectionPointInterface.pVTable = &vtblFixedCP; pData->connectionPointInterface.pVTable = &vtblFixedCP;
pData->punkOuter = punkOuter; pData->punkOuter = punkOuter;
@ -110,15 +281,29 @@ void ObjHlpFixedCpSetup(PFIXEDCPDATA pData, PUNKNOWN punkOuter, REFIID riidConne
pData->ppSlots = ppSlots; pData->ppSlots = ppSlots;
pData->ncpSize = 0; pData->ncpSize = 0;
pData->ncpCapacity = nSlots; pData->ncpCapacity = nSlots;
pData->pAllocator = pAllocator;
if (pData->pAllocator)
IUnknown_AddRef(pData->pAllocator);
StrSetMem(ppSlots, 0, nSlots * sizeof(IUnknown *)); StrSetMem(ppSlots, 0, nSlots * sizeof(IUnknown *));
} }
/*
* Tears down a fixed-size connection-point object.
*
* Parameters:
* - pData = Pointer to the data block to destroy.
*
* Returns:
* Nothing.
*/
void ObjHlpFixedCpTeardown(PFIXEDCPDATA pData) void ObjHlpFixedCpTeardown(PFIXEDCPDATA pData)
{ {
register INT32 i; /* loop counter */ register UINT32 i; /* loop counter */
for (i = 0; i < pData->ncpCapacity; i++) for (i = 0; i < pData->ncpCapacity; i++)
if (pData->ppSlots[i]) if (pData->ppSlots[i])
IUnknown_Release(pData->ppSlots[i]); IUnknown_Release(pData->ppSlots[i]);
if (pData->pAllocator)
IUnknown_Release(pData->pAllocator);
StrSetMem(pData, 0, sizeof(FIXEDCPDATA)); StrSetMem(pData, 0, sizeof(FIXEDCPDATA));
} }

View File

@ -82,7 +82,7 @@ INT32 RbtStdCompareByValue(TREEKEY k1, TREEKEY k2)
static PRBTREENODE rotate_left(PRBTREENODE ptn) static PRBTREENODE rotate_left(PRBTREENODE ptn)
{ {
register PRBTREENODE ptnNewRoot = rbtNodeRight(ptn); register PRBTREENODE ptnNewRoot = rbtNodeRight(ptn);
ASSERT(ptnNewRoot); //ASSERT(ptnNewRoot);
rbtSetNodeRight(ptn, ptnNewRoot->ptnLeft); rbtSetNodeRight(ptn, ptnNewRoot->ptnLeft);
ptnNewRoot->ptnLeft = ptn; ptnNewRoot->ptnLeft = ptn;
rbtSetNodeColor(ptnNewRoot, rbtNodeColor(ptn)); rbtSetNodeColor(ptnNewRoot, rbtNodeColor(ptn));
@ -103,7 +103,7 @@ static PRBTREENODE rotate_left(PRBTREENODE ptn)
static PRBTREENODE rotate_right(PRBTREENODE ptn) static PRBTREENODE rotate_right(PRBTREENODE ptn)
{ {
register PRBTREENODE ptnNewRoot = ptn->ptnLeft; register PRBTREENODE ptnNewRoot = ptn->ptnLeft;
ASSERT(ptnNewRoot); //ASSERT(ptnNewRoot);
ptn->ptnLeft = rbtNodeRight(ptnNewRoot); ptn->ptnLeft = rbtNodeRight(ptnNewRoot);
rbtSetNodeRight(ptnNewRoot, ptn); rbtSetNodeRight(ptnNewRoot, ptn);
rbtSetNodeColor(ptnNewRoot, rbtNodeColor(ptn)); rbtSetNodeColor(ptnNewRoot, rbtNodeColor(ptn));
@ -172,7 +172,7 @@ static PRBTREENODE insert_under(PRBTREE ptree, PRBTREENODE ptnCurrent, PRBTREENO
if (!ptnCurrent) if (!ptnCurrent)
return ptnNew; /* degenerate case */ return ptnNew; /* degenerate case */
cmp = (*(ptree->pfnTreeCompare))(ptnNew->treekey, ptnCurrent->treekey); cmp = (*(ptree->pfnTreeCompare))(ptnNew->treekey, ptnCurrent->treekey);
ASSERT(cmp != 0); //ASSERT(cmp != 0);
if (cmp < 0) if (cmp < 0)
ptnCurrent->ptnLeft = insert_under(ptree, ptnCurrent->ptnLeft, ptnNew); ptnCurrent->ptnLeft = insert_under(ptree, ptnCurrent->ptnLeft, ptnNew);
else else