vbox: Handle different array representations of XPCOM and MSCOM

Add a vboxArray to hide the details from the general driver code.
This commit is contained in:
Matthias Bolte 2010-12-16 23:05:48 +01:00
parent 448347f8b0
commit d5b1933e56
5 changed files with 447 additions and 249 deletions

View File

@ -646,3 +646,110 @@ void
VBoxCGlueTerm(void)
{
}
/*
* In MSCOM an array is represented by a SAFEARRAY pointer. To access the items
* in the array the SafeArrayAccessData function is used to lock the array and
* get its contents. When the items aren't needed anymore the
* SafeArrayUnaccessData function is used to unlock the array. The pointer
* retuned by SafeArrayAccessData function becomes invalid. Finally the
* SafeArrayDestroy function is called to destroy the array, it also releases
* or frees all items in the array according to their type.
*/
typedef HRESULT __stdcall (*SafeArrayGetter)(void *self, SAFEARRAY **array);
typedef HRESULT __stdcall (*SafeArrayGetterWithArg)(void *self, void *arg, SAFEARRAY **array);
/*
* Call the getter with self as first argument and fill the array with the
* returned items.
*/
nsresult
vboxArrayGet(vboxArray *array, void *self, void *getter)
{
HRESULT hrc;
SAFEARRAY *safeArray = NULL;
void **items = NULL;
array->items = NULL;
array->count = 0;
array->handle = NULL;
hrc = ((SafeArrayGetter)getter)(self, &safeArray);
if (FAILED(hrc)) {
return hrc;
}
hrc = SafeArrayAccessData(safeArray, (void **)&items);
if (FAILED(hrc)) {
SafeArrayDestroy(safeArray);
return hrc;
}
array->items = items;
array->count = safeArray->rgsabound[0].cElements;
array->handle = safeArray;
return hrc;
}
/*
* Call the getter with self as first argument and arg as second argument
* and fill the array with the returned items.
*/
nsresult
vboxArrayGetWithArg(vboxArray *array, void *self, void *getter, void *arg)
{
HRESULT hrc;
SAFEARRAY *safeArray = NULL;
void **items = NULL;
array->items = NULL;
array->count = 0;
array->handle = NULL;
hrc = ((SafeArrayGetterWithArg)getter)(self, arg, &safeArray);
if (FAILED(hrc)) {
return hrc;
}
hrc = SafeArrayAccessData(safeArray, (void **)&items);
if (FAILED(hrc)) {
SafeArrayDestroy(safeArray);
return hrc;
}
array->items = items;
array->count = safeArray->rgsabound[0].cElements;
array->handle = safeArray;
return hrc;
}
/*
* Release all items in the array and reset it.
*
* SafeArrayDestroy is aware of the item's type and calls release or free
* for each item according to its type. Therefore, vboxArrayUnalloc and
* vboxArrayRelease are the same for MSCOM.
*/
void
vboxArrayRelease(vboxArray *array)
{
if (array->handle == NULL) {
return;
}
SafeArrayUnaccessData(array->handle);
SafeArrayDestroy(array->handle);
array->items = NULL;
array->count = 0;
array->handle = NULL;
}

View File

@ -30,4 +30,19 @@ extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions;
int VBoxCGlueInit(unsigned int *version);
void VBoxCGlueTerm(void);
typedef struct _vboxArray vboxArray;
struct _vboxArray {
void **items;
size_t count;
void *handle;
};
# define VBOX_ARRAY_INITIALIZER { NULL, 0, NULL }
nsresult vboxArrayGet(vboxArray *array, void *self, void *getter);
nsresult vboxArrayGetWithArg(vboxArray *array, void *self, void *getter, void *arg);
void vboxArrayRelease(vboxArray *array);
# define vboxArrayUnalloc vboxArrayRelease
#endif /* __VBOX_MSCOMGLUE_H__ */

View File

@ -253,3 +253,118 @@ VBoxCGlueTerm(void)
pVBoxFuncs_v2_2 = NULL;
g_pfnGetFunctions = NULL;
}
/*
* In XPCOM an array is represented by 1) a pointer to an array of pointers
* that point to the items and 2) an unsigned int representing the number of
* items in the array. When the items aren't needed anymore they are released
* or freed according to their type.
*/
typedef nsresult (*ArrayGetter)(void *self, PRUint32 *count, void ***items);
typedef nsresult (*ArrayGetterWithArg)(void *self, void *arg, PRUint32 *count, void ***items);
/*
* Call the getter with self as first argument and fill the array with the
* returned items.
*/
nsresult
vboxArrayGet(vboxArray *array, void *self, void *getter)
{
nsresult nsrc;
void **items = NULL;
PRUint32 count = 0;
array->items = NULL;
array->count = 0;
nsrc = ((ArrayGetter)getter)(self, &count, &items);
if (NS_FAILED(nsrc)) {
return nsrc;
}
array->items = items;
array->count = count;
return nsrc;
}
/*
* Call the getter with self as first argument and arg as second argument
* and fill the array with the returned items.
*/
nsresult
vboxArrayGetWithArg(vboxArray *array, void *self, void *getter, void *arg)
{
nsresult nsrc;
void **items = NULL;
PRUint32 count = 0;
array->items = NULL;
array->count = 0;
nsrc = ((ArrayGetterWithArg)getter)(self, arg, &count, &items);
if (NS_FAILED(nsrc)) {
return nsrc;
}
array->items = items;
array->count = count;
return nsrc;
}
/*
* Release all items in the array and reset it.
*/
void
vboxArrayRelease(vboxArray *array)
{
int i;
nsISupports *supports;
if (array->items == NULL) {
return;
}
for (i = 0; i < array->count; ++i) {
supports = array->items[i];
if (supports != NULL) {
supports->vtbl->Release(supports);
}
}
array->items = NULL;
array->count = 0;
}
/*
* Unalloc all items in the array and reset it.
*/
void
vboxArrayUnalloc(vboxArray *array)
{
int i;
void *item;
if (array->items == NULL) {
return;
}
for (i = 0; i < array->count; ++i) {
item = array->items[i];
if (item != NULL) {
pVBoxFuncs_v2_2->pfnComUnallocMem(item);
}
}
array->items = NULL;
array->count = 0;
}

View File

@ -38,4 +38,18 @@ extern PFNVBOXGETXPCOMCFUNCTIONS g_pfnGetFunctions;
int VBoxCGlueInit(unsigned int *version);
void VBoxCGlueTerm(void);
typedef struct _vboxArray vboxArray;
struct _vboxArray {
void **items;
size_t count;
};
# define VBOX_ARRAY_INITIALIZER { NULL, 0 }
nsresult vboxArrayGet(vboxArray *array, void *self, void *getter);
nsresult vboxArrayGetWithArg(vboxArray *array, void *self, void *getter, void *arg);
void vboxArrayRelease(vboxArray *array);
void vboxArrayUnalloc(vboxArray *array);
#endif

File diff suppressed because it is too large Load Diff