mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-21 20:15:17 +00:00
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:
parent
448347f8b0
commit
d5b1933e56
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user