ole32: Add a framework for implementing IEnum* interfaces.
This commit is contained in:
parent
918cf3261b
commit
127ae2bf8b
|
@ -18,6 +18,7 @@ C_SRCS = \
|
||||||
datacache.c \
|
datacache.c \
|
||||||
defaulthandler.c \
|
defaulthandler.c \
|
||||||
dictionary.c \
|
dictionary.c \
|
||||||
|
enumx.c \
|
||||||
errorinfo.c \
|
errorinfo.c \
|
||||||
filemoniker.c \
|
filemoniker.c \
|
||||||
ftmarshal.c \
|
ftmarshal.c \
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
* IEnum* implementation
|
||||||
|
*
|
||||||
|
* Copyright 2006 Mike McCormack
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define COBJMACROS
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "objbase.h"
|
||||||
|
#include "wine/list.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||||
|
|
||||||
|
typedef struct tagEnumSTATPROPSETSTG_impl
|
||||||
|
{
|
||||||
|
const void *vtbl;
|
||||||
|
LONG ref;
|
||||||
|
struct list elements;
|
||||||
|
struct list *current;
|
||||||
|
ULONG elem_size;
|
||||||
|
GUID riid;
|
||||||
|
} enumx_impl;
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_QueryInterface
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI enumx_QueryInterface(
|
||||||
|
enumx_impl *This,
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject)
|
||||||
|
{
|
||||||
|
if ( (This==0) || (ppvObject==0) )
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
*ppvObject = 0;
|
||||||
|
|
||||||
|
if (IsEqualGUID(&IID_IUnknown, riid) ||
|
||||||
|
IsEqualGUID(&This->riid, riid))
|
||||||
|
{
|
||||||
|
IUnknown_AddRef(((IUnknown*)This));
|
||||||
|
*ppvObject = This;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_AddRef
|
||||||
|
*/
|
||||||
|
ULONG WINAPI enumx_AddRef(enumx_impl *This)
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&This->ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_Release
|
||||||
|
*/
|
||||||
|
ULONG WINAPI enumx_Release(enumx_impl *This)
|
||||||
|
{
|
||||||
|
ULONG ref;
|
||||||
|
|
||||||
|
ref = InterlockedDecrement(&This->ref);
|
||||||
|
if (ref == 0)
|
||||||
|
{
|
||||||
|
while (!list_empty(&This->elements))
|
||||||
|
{
|
||||||
|
struct list *x = list_head(&This->elements);
|
||||||
|
list_remove(x);
|
||||||
|
HeapFree(GetProcessHeap(), 0, x);
|
||||||
|
}
|
||||||
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
|
}
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_Next
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI enumx_Next(enumx_impl *This, ULONG celt,
|
||||||
|
void *rgelt, ULONG *pceltFetched)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
ULONG count = 0;
|
||||||
|
|
||||||
|
TRACE("%p %lu %p\n", This, celt, pceltFetched);
|
||||||
|
|
||||||
|
if (This->current == NULL)
|
||||||
|
This->current = list_head(&This->elements);
|
||||||
|
p = rgelt;
|
||||||
|
while (count < celt && This->current && This->current != &This->elements)
|
||||||
|
{
|
||||||
|
memcpy(p, &This->current[1], This->elem_size);
|
||||||
|
p += This->elem_size;
|
||||||
|
This->current = This->current->next;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (pceltFetched)
|
||||||
|
*pceltFetched = count;
|
||||||
|
if (count < celt)
|
||||||
|
return S_FALSE;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_Skip
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI enumx_Skip(enumx_impl *This, ULONG celt)
|
||||||
|
{
|
||||||
|
ULONG count = 0;
|
||||||
|
|
||||||
|
TRACE("%p %lu\n", This, celt);
|
||||||
|
|
||||||
|
if (This->current == NULL)
|
||||||
|
This->current = list_head(&This->elements);
|
||||||
|
|
||||||
|
while (count < celt && This->current && This->current != &This->elements)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_Reset
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI enumx_Reset(enumx_impl *This)
|
||||||
|
{
|
||||||
|
TRACE("\n");
|
||||||
|
|
||||||
|
This->current = NULL;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_fnClone
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI enumx_Clone(
|
||||||
|
enumx_impl *iface,
|
||||||
|
enumx_impl **ppenum)
|
||||||
|
{
|
||||||
|
FIXME("\n");
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_allocate
|
||||||
|
*
|
||||||
|
* Allocate a generic enumerator
|
||||||
|
*/
|
||||||
|
enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size)
|
||||||
|
{
|
||||||
|
enumx_impl *enumx;
|
||||||
|
|
||||||
|
enumx = HeapAlloc(GetProcessHeap(), 0, sizeof *enumx);
|
||||||
|
if (enumx)
|
||||||
|
{
|
||||||
|
enumx->vtbl = vtbl;
|
||||||
|
enumx->ref = 1;
|
||||||
|
enumx->current = NULL;
|
||||||
|
enumx->elem_size = elem_size;
|
||||||
|
memcpy(&enumx->riid, riid, sizeof *riid);
|
||||||
|
list_init(&enumx->elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
return enumx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* enumx_add_element
|
||||||
|
*
|
||||||
|
* Add an element to the enumeration.
|
||||||
|
*/
|
||||||
|
void *enumx_add_element(enumx_impl *enumx, void *data)
|
||||||
|
{
|
||||||
|
struct list *element;
|
||||||
|
|
||||||
|
element = HeapAlloc(GetProcessHeap(), 0, sizeof *element + enumx->elem_size);
|
||||||
|
if (!element)
|
||||||
|
return NULL;
|
||||||
|
memcpy(&element[1], data, enumx->elem_size);
|
||||||
|
list_add_tail(&enumx->elements, element);
|
||||||
|
return &element[1];
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006 Mike McCormack
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __OLE_ENUM_H__
|
||||||
|
#define __OLE_ENUM_H__
|
||||||
|
|
||||||
|
typedef struct tagEnumSTATPROPSETSTG_impl enumx_impl;
|
||||||
|
|
||||||
|
extern HRESULT WINAPI enumx_QueryInterface(enumx_impl *, REFIID, void**);
|
||||||
|
extern ULONG WINAPI enumx_AddRef(enumx_impl *);
|
||||||
|
extern ULONG WINAPI enumx_Release(enumx_impl *);
|
||||||
|
extern HRESULT WINAPI enumx_Next(enumx_impl *, ULONG, void *, ULONG *);
|
||||||
|
extern HRESULT WINAPI enumx_Skip(enumx_impl *, ULONG);
|
||||||
|
extern HRESULT WINAPI enumx_Reset(enumx_impl *);
|
||||||
|
extern HRESULT WINAPI enumx_Clone(enumx_impl *, enumx_impl **);
|
||||||
|
extern enumx_impl *enumx_allocate(REFIID, const void *, ULONG);
|
||||||
|
extern void *enumx_add_element(enumx_impl *, void *);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue