reactos/dll/win32/ole32/dictionary.c

192 lines
4.9 KiB
C
Raw Normal View History

Sync to Wine-20050419: Juan Lang <juan_lang@yahoo.com> - Implement PropSys{Alloc|Free}String, and support BSTRs in PropVariant{Clear|Copy} using them. - Begin implementing IPropertyStorage. - Add traces, add unit tests for IPropertyStorage, and fix the problems they caught. - Implement FmtIdToPropStgName & PropStgNameToFmtId, with tests. - add write support to IPropertyStorage, with tests - misc. cleanups the tests turned up - Add a comment about byte order, change types to reduce casting and not cast away constness. Vincent Beron <vberon@mecano.gme.usherb.ca> - Change prototypes so gcc with some warnings doesn't bark. - Correct and complete some api documentation. Mike McCormack <mike@codeweavers.com> - Eliminate forward declarations, make functions static. - Eliminate casts of the return value of HeapAlloc. - Remove function prototypes, make functions static. - StgOpenStorage shouldn't open zero length storage files. - Remove unnecessary function prototypes. Robert Shearman <rob@codeweavers.com> - Add critsec debugging info. - Move the modal loop called during RPCs into CoWaitForMultipleHandles. - Use a mutex for long remoting calls to IRemUnknown methods. - Remove locking in apartment_disconnectproxies as it is not needed. - Use PostMessage instead of SendMessage so we can run the message loop or not as appropriate. - Rename apartment functions to become more object-oriented. - Rename register_ifstub to marshal_object to more accurately describe what it does. - Add new function, apartment_getoxid, to prepare for a possible future patch where remoting is started on demand. Jon Griffiths <jon_p_griffiths@yahoo.com> - Use LMEM_ flags for LocalAlloc(), not GMEM_ (GlobalAlloc). Francois Gouget <fgouget@free.fr> - Assorted spelling fixes. Huw Davies <huw@codeweavers.com> - Don't close reg key if the open failed. - WriteFmtUserTypeStg doesn't pull a CLSID from the registry - it's unclear when (if at all) this gets written. Alexandre Julliard <julliard@winehq.org> - Fixed a buffer overflow. Joris Huizer <jorishuizer@planet.nl> - A few memory checks avoiding memory leaks. Dmitry Timoshkov <dmitry@codeweavers.com> - Zero out an invalidated runningObjectTableInstance pointer. Dimitrie O. Paun <dpaun@rogers.com> - Remove the need for the non-standard (Close|Delete)MetaFile16(). Troy Rollo <wine@troy.rollo.name> - ix test for STGM_SHARE_EXCLUSIVE on nameless DocFiles. svn path=/trunk/; revision=15010
2005-05-05 18:16:09 +00:00
/* Simple dictionary implementation using a linked list.
* FIXME: a skip list would be faster.
*
* Copyright 2005 Juan Lang
*
* 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
Sync to Wine-20050419: Juan Lang <juan_lang@yahoo.com> - Implement PropSys{Alloc|Free}String, and support BSTRs in PropVariant{Clear|Copy} using them. - Begin implementing IPropertyStorage. - Add traces, add unit tests for IPropertyStorage, and fix the problems they caught. - Implement FmtIdToPropStgName & PropStgNameToFmtId, with tests. - add write support to IPropertyStorage, with tests - misc. cleanups the tests turned up - Add a comment about byte order, change types to reduce casting and not cast away constness. Vincent Beron <vberon@mecano.gme.usherb.ca> - Change prototypes so gcc with some warnings doesn't bark. - Correct and complete some api documentation. Mike McCormack <mike@codeweavers.com> - Eliminate forward declarations, make functions static. - Eliminate casts of the return value of HeapAlloc. - Remove function prototypes, make functions static. - StgOpenStorage shouldn't open zero length storage files. - Remove unnecessary function prototypes. Robert Shearman <rob@codeweavers.com> - Add critsec debugging info. - Move the modal loop called during RPCs into CoWaitForMultipleHandles. - Use a mutex for long remoting calls to IRemUnknown methods. - Remove locking in apartment_disconnectproxies as it is not needed. - Use PostMessage instead of SendMessage so we can run the message loop or not as appropriate. - Rename apartment functions to become more object-oriented. - Rename register_ifstub to marshal_object to more accurately describe what it does. - Add new function, apartment_getoxid, to prepare for a possible future patch where remoting is started on demand. Jon Griffiths <jon_p_griffiths@yahoo.com> - Use LMEM_ flags for LocalAlloc(), not GMEM_ (GlobalAlloc). Francois Gouget <fgouget@free.fr> - Assorted spelling fixes. Huw Davies <huw@codeweavers.com> - Don't close reg key if the open failed. - WriteFmtUserTypeStg doesn't pull a CLSID from the registry - it's unclear when (if at all) this gets written. Alexandre Julliard <julliard@winehq.org> - Fixed a buffer overflow. Joris Huizer <jorishuizer@planet.nl> - A few memory checks avoiding memory leaks. Dmitry Timoshkov <dmitry@codeweavers.com> - Zero out an invalidated runningObjectTableInstance pointer. Dimitrie O. Paun <dpaun@rogers.com> - Remove the need for the non-standard (Close|Delete)MetaFile16(). Troy Rollo <wine@troy.rollo.name> - ix test for STGM_SHARE_EXCLUSIVE on nameless DocFiles. svn path=/trunk/; revision=15010
2005-05-05 18:16:09 +00:00
*/
#include <assert.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "dictionary.h"
#include "wine/debug.h"
Sync to Wine-20050419: Juan Lang <juan_lang@yahoo.com> - Implement PropSys{Alloc|Free}String, and support BSTRs in PropVariant{Clear|Copy} using them. - Begin implementing IPropertyStorage. - Add traces, add unit tests for IPropertyStorage, and fix the problems they caught. - Implement FmtIdToPropStgName & PropStgNameToFmtId, with tests. - add write support to IPropertyStorage, with tests - misc. cleanups the tests turned up - Add a comment about byte order, change types to reduce casting and not cast away constness. Vincent Beron <vberon@mecano.gme.usherb.ca> - Change prototypes so gcc with some warnings doesn't bark. - Correct and complete some api documentation. Mike McCormack <mike@codeweavers.com> - Eliminate forward declarations, make functions static. - Eliminate casts of the return value of HeapAlloc. - Remove function prototypes, make functions static. - StgOpenStorage shouldn't open zero length storage files. - Remove unnecessary function prototypes. Robert Shearman <rob@codeweavers.com> - Add critsec debugging info. - Move the modal loop called during RPCs into CoWaitForMultipleHandles. - Use a mutex for long remoting calls to IRemUnknown methods. - Remove locking in apartment_disconnectproxies as it is not needed. - Use PostMessage instead of SendMessage so we can run the message loop or not as appropriate. - Rename apartment functions to become more object-oriented. - Rename register_ifstub to marshal_object to more accurately describe what it does. - Add new function, apartment_getoxid, to prepare for a possible future patch where remoting is started on demand. Jon Griffiths <jon_p_griffiths@yahoo.com> - Use LMEM_ flags for LocalAlloc(), not GMEM_ (GlobalAlloc). Francois Gouget <fgouget@free.fr> - Assorted spelling fixes. Huw Davies <huw@codeweavers.com> - Don't close reg key if the open failed. - WriteFmtUserTypeStg doesn't pull a CLSID from the registry - it's unclear when (if at all) this gets written. Alexandre Julliard <julliard@winehq.org> - Fixed a buffer overflow. Joris Huizer <jorishuizer@planet.nl> - A few memory checks avoiding memory leaks. Dmitry Timoshkov <dmitry@codeweavers.com> - Zero out an invalidated runningObjectTableInstance pointer. Dimitrie O. Paun <dpaun@rogers.com> - Remove the need for the non-standard (Close|Delete)MetaFile16(). Troy Rollo <wine@troy.rollo.name> - ix test for STGM_SHARE_EXCLUSIVE on nameless DocFiles. svn path=/trunk/; revision=15010
2005-05-05 18:16:09 +00:00
WINE_DEFAULT_DEBUG_CHANNEL(storage);
struct dictionary_entry
{
void *key;
void *value;
struct dictionary_entry *next;
};
struct dictionary
{
comparefunc comp;
destroyfunc destroy;
void *extra;
struct dictionary_entry *head;
UINT num_entries;
};
struct dictionary *dictionary_create(comparefunc c, destroyfunc d, void *extra)
{
struct dictionary *ret;
TRACE("(%p, %p, %p)\n", c, d, extra);
if (!c)
return NULL;
ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dictionary));
if (ret)
{
ret->comp = c;
ret->destroy = d;
ret->extra = extra;
ret->head = NULL;
ret->num_entries = 0;
}
TRACE("returning %p\n", ret);
return ret;
}
void dictionary_destroy(struct dictionary *d)
{
TRACE("(%p)\n", d);
if (d)
{
struct dictionary_entry *p;
for (p = d->head; p; )
{
struct dictionary_entry *next = p->next;
if (d->destroy)
d->destroy(p->key, p->value, d->extra);
HeapFree(GetProcessHeap(), 0, p);
p = next;
}
HeapFree(GetProcessHeap(), 0, d);
}
}
UINT dictionary_num_entries(struct dictionary *d)
{
return d ? d->num_entries : 0;
}
/* Returns the address of the pointer to the node containing k. (It returns
* the address of either h->head or the address of the next member of the
* prior node. It's useful when you want to delete.)
* Assumes h and prev are not NULL.
*/
static struct dictionary_entry **dictionary_find_internal(struct dictionary *d,
const void *k)
{
struct dictionary_entry **ret = NULL;
struct dictionary_entry *p;
assert(d);
/* special case for head containing the desired element */
if (d->head && d->comp(k, d->head->key, d->extra) == 0)
ret = &d->head;
for (p = d->head; !ret && p && p->next; p = p->next)
{
if (d->comp(k, p->next->key, d->extra) == 0)
ret = &p->next;
}
return ret;
}
void dictionary_insert(struct dictionary *d, const void *k, const void *v)
{
struct dictionary_entry **prior;
TRACE("(%p, %p, %p)\n", d, k, v);
if (!d)
return;
if ((prior = dictionary_find_internal(d, k)))
{
if (d->destroy)
d->destroy((*prior)->key, (*prior)->value, d->extra);
(*prior)->key = (void *)k;
(*prior)->value = (void *)v;
}
else
{
struct dictionary_entry *elem = HeapAlloc(GetProcessHeap(), 0,
sizeof(struct dictionary_entry));
Sync to Wine-20050419: Juan Lang <juan_lang@yahoo.com> - Implement PropSys{Alloc|Free}String, and support BSTRs in PropVariant{Clear|Copy} using them. - Begin implementing IPropertyStorage. - Add traces, add unit tests for IPropertyStorage, and fix the problems they caught. - Implement FmtIdToPropStgName & PropStgNameToFmtId, with tests. - add write support to IPropertyStorage, with tests - misc. cleanups the tests turned up - Add a comment about byte order, change types to reduce casting and not cast away constness. Vincent Beron <vberon@mecano.gme.usherb.ca> - Change prototypes so gcc with some warnings doesn't bark. - Correct and complete some api documentation. Mike McCormack <mike@codeweavers.com> - Eliminate forward declarations, make functions static. - Eliminate casts of the return value of HeapAlloc. - Remove function prototypes, make functions static. - StgOpenStorage shouldn't open zero length storage files. - Remove unnecessary function prototypes. Robert Shearman <rob@codeweavers.com> - Add critsec debugging info. - Move the modal loop called during RPCs into CoWaitForMultipleHandles. - Use a mutex for long remoting calls to IRemUnknown methods. - Remove locking in apartment_disconnectproxies as it is not needed. - Use PostMessage instead of SendMessage so we can run the message loop or not as appropriate. - Rename apartment functions to become more object-oriented. - Rename register_ifstub to marshal_object to more accurately describe what it does. - Add new function, apartment_getoxid, to prepare for a possible future patch where remoting is started on demand. Jon Griffiths <jon_p_griffiths@yahoo.com> - Use LMEM_ flags for LocalAlloc(), not GMEM_ (GlobalAlloc). Francois Gouget <fgouget@free.fr> - Assorted spelling fixes. Huw Davies <huw@codeweavers.com> - Don't close reg key if the open failed. - WriteFmtUserTypeStg doesn't pull a CLSID from the registry - it's unclear when (if at all) this gets written. Alexandre Julliard <julliard@winehq.org> - Fixed a buffer overflow. Joris Huizer <jorishuizer@planet.nl> - A few memory checks avoiding memory leaks. Dmitry Timoshkov <dmitry@codeweavers.com> - Zero out an invalidated runningObjectTableInstance pointer. Dimitrie O. Paun <dpaun@rogers.com> - Remove the need for the non-standard (Close|Delete)MetaFile16(). Troy Rollo <wine@troy.rollo.name> - ix test for STGM_SHARE_EXCLUSIVE on nameless DocFiles. svn path=/trunk/; revision=15010
2005-05-05 18:16:09 +00:00
if (!elem)
return;
elem->key = (void *)k;
elem->value = (void *)v;
elem->next = d->head;
d->head = elem;
d->num_entries++;
}
}
BOOL dictionary_find(struct dictionary *d, const void *k, void **value)
{
struct dictionary_entry **prior;
BOOL ret = FALSE;
TRACE("(%p, %p, %p)\n", d, k, value);
if (!d)
return FALSE;
if (!value)
return FALSE;
if ((prior = dictionary_find_internal(d, k)))
{
*value = (*prior)->value;
ret = TRUE;
}
TRACE("returning %d (%p)\n", ret, *value);
return ret;
}
void dictionary_remove(struct dictionary *d, const void *k)
{
struct dictionary_entry **prior, *temp;
TRACE("(%p, %p)\n", d, k);
if (!d)
return;
if ((prior = dictionary_find_internal(d, k)))
{
temp = *prior;
if (d->destroy)
d->destroy((*prior)->key, (*prior)->value, d->extra);
*prior = (*prior)->next;
HeapFree(GetProcessHeap(), 0, temp);
d->num_entries--;
}
}
void dictionary_enumerate(struct dictionary *d, enumeratefunc e, void *closure)
{
struct dictionary_entry *p;
TRACE("(%p, %p, %p)\n", d, e, closure);
if (!d)
return;
if (!e)
return;
for (p = d->head; p; p = p->next)
if (!e(p->key, p->value, d->extra, closure))
break;
}