Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
c2d6a6b4
Commit
c2d6a6b4
authored
Dec 15, 2003
by
Jon Griffiths
Committed by
Alexandre Julliard
Dec 15, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rewrite: Support I8/UI8,RECORD.
Store array bounds in the same order as native. Add CreateEx, CreateVectorEx, VectorFromBstr, BstrFromVector.
parent
599b0b73
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1376 additions
and
981 deletions
+1376
-981
oleaut32.spec
dlls/oleaut32/oleaut32.spec
+4
-4
safearray.c
dlls/oleaut32/safearray.c
+1372
-977
No files found.
dlls/oleaut32/oleaut32.spec
View file @
c2d6a6b4
...
...
@@ -39,8 +39,8 @@
39 stdcall SafeArrayDestroyData(ptr)
40 stdcall SafeArrayRedim(ptr ptr)
41 stdcall SafeArrayAllocDescriptorEx(long long ptr)
42 st
ub SafeArrayCreateEx
43 st
ub SafeArrayCreateVectorEx
42 st
dcall SafeArrayCreateEx(long long ptr ptr)
43 st
dcall SafeArrayCreateVectorEx(long long long ptr)
44 stdcall SafeArraySetRecordInfo(ptr ptr)
45 stdcall SafeArrayGetRecordInfo(ptr ptr)
46 stdcall VarParseNumFromStr(wstr long long ptr ptr)
...
...
@@ -385,8 +385,8 @@
410 stdcall -private DllCanUnloadNow() OLEAUT32_DllCanUnloadNow
411 stdcall SafeArrayCreateVector(long long long)
412 stdcall SafeArrayCopyData(ptr ptr)
413 st
ub VectorFromBstr
414 st
ub BstrFromVector
413 st
dcall VectorFromBstr(ptr ptr)
414 st
dcall BstrFromVector(ptr ptr)
415 stdcall OleIconToCursor(long long)
416 stdcall OleCreatePropertyFrameIndirect(ptr)
417 stdcall OleCreatePropertyFrame(ptr long long ptr long ptr long ptr ptr long ptr)
...
...
dlls/oleaut32/safearray.c
View file @
c2d6a6b4
/*************************************************************************
* OLE Automation
* SafeArray Implementation
* OLE Automation - SafeArray
*
* This file contains the implementation of the SafeArray
interface
.
* This file contains the implementation of the SafeArray
functions
.
*
* Copyright 1999 Sylvain St-Germain
* Copyright 2003 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -23,1307 +23,1702 @@
/* Memory Layout of a SafeArray:
*
* -0x10: start of memory.
* -0x10: GUID
for VT_DISPATCH and VT_UNKNOWN safearrays (if FADF_HAVEIID)
* -0x10: GUID
for VT_DISPATCH and VT_UNKNOWN safearrays (if FADF_HAVEIID)
* -0x04: DWORD varianttype; (for all others, except VT_RECORD) (if FADF_HAVEVARTYPE)
* -0x4: IRecordInfo* iface;
(if FADF_RECORD, for VT_RECORD (can be NULL))
* -0x4: IRecordInfo* iface;
(if FADF_RECORD, for VT_RECORD (can be NULL))
* 0x00: SAFEARRAY,
* 0x10: SAFEARRAYBOUNDS[0...]
*/
#include "config.h"
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "windef.h"
#include "winerror.h"
#include "winbase.h"
#include "oleauto.h"
#include "wine/debug.h"
#include "variant.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
ole
);
#define SYSDUPSTRING(str) SysAllocStringLen((str), SysStringLen(str))
/************************************************************************
* SafeArray {OLEAUT32}
*
* NOTES
* The SafeArray data type provides the underlying interface for Ole
* Automations arrays, used for example to represent array types in
* Visual Basic(tm) and to gather user defined parameters for invocation through
* an IDispatch interface.
*
* Safe arrays provide bounds checking and automatically manage the data
* types they contain, for example handing reference counting and copying
* of interface pointers. User defined types can be stored in arrays
* using the IRecordInfo interface.
*
* There are two types of SafeArray, normal and vectors. Normal arrays can have
* multiple dimensions and the data for the array is allocated seperately from
* the array header. This is the most flexable type of array. Vectors, on the
* other hand, are fixed in size and consist of a single allocated block, and a
* single dimension.
*
* DATATYPES
* The following types of data can be stored within a SafeArray.
* Numeric:
*| VT_I1, VT_UI1, VT_I2, VT_UI2, VT_I4, VT_UI4, VT_I8, VT_UI8, VT_INT, VT_UINT,
*| VT_R4, VT_R8, VT_CY, VT_DECIMAL
* Interfaces:
*| VT_DISPATCH, VT_UNKNOWN, VT_RECORD
* Other:
*| VT_VARIANT, VT_INT_PTR, VT_UINT_PTR, VT_BOOL, VT_ERROR, VT_DATE, VT_BSTR
*
* FUNCTIONS
* BstrFromVector()
* VectorFromBstr()
*/
/* Undocumented hidden space before the start of a SafeArray descriptor */
#define SAFEARRAY_HIDDEN_SIZE sizeof(GUID)
/* Value returned by SAFEARRAY_GetCellCount if a dimension is invalid */
#define SAFEARRAY_INVALID_CELLS ~0UL
/* Allocate memory */
static
inline
LPVOID
SAFEARRAY_Malloc
(
ULONG
ulSize
)
{
/* FIXME: Memory should be allocated and freed using a per-thread IMalloc
* instance returned from CoGetMalloc().
*/
return
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
ulSize
);
}
/* Free memory */
static
inline
BOOL
SAFEARRAY_Free
(
LPVOID
lpData
)
{
return
HeapFree
(
GetProcessHeap
(),
0
,
lpData
);
}
/* Get the size of a supported VT type (0 means unsupported) */
static
DWORD
SAFEARRAY_GetVTSize
(
VARTYPE
vt
)
{
switch
(
vt
)
{
case
VT_I1
:
case
VT_UI1
:
return
sizeof
(
BYTE
);
case
VT_BOOL
:
case
VT_I2
:
case
VT_UI2
:
return
sizeof
(
SHORT
);
case
VT_I4
:
case
VT_UI4
:
case
VT_R4
:
case
VT_ERROR
:
return
sizeof
(
LONG
);
case
VT_R8
:
case
VT_I8
:
case
VT_UI8
:
return
sizeof
(
LONG64
);
case
VT_INT
:
case
VT_UINT
:
return
sizeof
(
INT
);
case
VT_INT_PTR
:
case
VT_UINT_PTR
:
return
sizeof
(
UINT_PTR
);
case
VT_CY
:
return
sizeof
(
CY
);
case
VT_DATE
:
return
sizeof
(
DATE
);
case
VT_BSTR
:
return
sizeof
(
BSTR
);
case
VT_DISPATCH
:
return
sizeof
(
LPDISPATCH
);
case
VT_VARIANT
:
return
sizeof
(
VARIANT
);
case
VT_UNKNOWN
:
return
sizeof
(
LPUNKNOWN
);
case
VT_DECIMAL
:
return
sizeof
(
DECIMAL
);
/* Note: Return a non-zero size to indicate vt is valid. The actual size
* of a UDT is taken from the result of IRecordInfo_GetSize().
*/
case
VT_RECORD
:
return
32
;
}
return
0
;
}
/* Set the hidden data for an array */
static
inline
void
SAFEARRAY_SetHiddenDWORD
(
SAFEARRAY
*
psa
,
DWORD
dw
)
{
/* Implementation data is stored in the 4 bytes before the header */
LPDWORD
lpDw
=
(
LPDWORD
)
psa
;
lpDw
[
-
1
]
=
dw
;
}
/* Get the hidden data from an array */
static
inline
DWORD
SAFEARRAY_GetHiddenDWORD
(
SAFEARRAY
*
psa
)
{
LPDWORD
lpDw
=
(
LPDWORD
)
psa
;
return
lpDw
[
-
1
];
}
/* Get the number of cells in a SafeArray */
static
ULONG
SAFEARRAY_GetCellCount
(
const
SAFEARRAY
*
psa
)
{
SAFEARRAYBOUND
*
psab
=
psa
->
rgsabound
;
USHORT
cCount
=
psa
->
cDims
;
ULONG
ulNumCells
=
1
;
/* Locally used methods */
static
ULONG
calcDisplacement
(
LONG
*
coor
,
SAFEARRAYBOUND
*
mat
,
LONG
dim
);
while
(
cCount
--
)
{
if
(
!
psab
->
cElements
)
{
ERR
(
"Dimension has size=0! Please report.
\n
"
);
return
SAFEARRAY_INVALID_CELLS
;
}
ulNumCells
*=
psab
->
cElements
;
psab
++
;
}
return
ulNumCells
;
}
static
BOOL
isPointer
(
USHORT
feature
);
/* Get the 0 based index of an index into a dimension */
static
inline
ULONG
SAFEARRAY_GetDimensionIndex
(
SAFEARRAYBOUND
*
psab
,
ULONG
ulIndex
)
{
return
ulIndex
-
psab
->
lLbound
;
}
static
INT
getFeatures
(
VARTYPE
vt
);
/* Get the size of a dimension in cells */
static
inline
ULONG
SAFEARRAY_GetDimensionCells
(
SAFEARRAY
*
psa
,
ULONG
ulDim
)
{
ULONG
size
=
psa
->
rgsabound
[
0
].
cElements
;
static
BOOL
validCoordinate
(
LONG
*
coor
,
SAFEARRAY
*
psa
);
while
(
ulDim
)
{
size
*=
psa
->
rgsabound
[
ulDim
].
cElements
;
ulDim
--
;
}
return
size
;
}
/* Allocate a descriptor for an array */
static
HRESULT
SAFEARRAY_AllocDescriptor
(
ULONG
ulSize
,
SAFEARRAY
**
ppsaOut
)
{
*
ppsaOut
=
(
SAFEARRAY
*
)((
char
*
)
SAFEARRAY_Malloc
(
ulSize
+
SAFEARRAY_HIDDEN_SIZE
)
+
SAFEARRAY_HIDDEN_SIZE
);
if
(
!*
ppsaOut
)
return
E_UNEXPECTED
;
return
S_OK
;
}
/* Set the features of an array */
static
void
SAFEARRAY_SetFeatures
(
VARTYPE
vt
,
SAFEARRAY
*
psa
)
{
/* Set the IID if we have one, otherwise set the type */
if
(
vt
==
VT_DISPATCH
)
{
psa
->
fFeatures
=
FADF_HAVEIID
;
SafeArraySetIID
(
psa
,
&
IID_IDispatch
);
}
else
if
(
vt
==
VT_UNKNOWN
)
{
psa
->
fFeatures
=
FADF_HAVEIID
;
SafeArraySetIID
(
psa
,
&
IID_IUnknown
);
}
else
if
(
vt
==
VT_RECORD
)
psa
->
fFeatures
=
FADF_RECORD
;
else
{
psa
->
fFeatures
=
FADF_HAVEVARTYPE
;
SAFEARRAY_SetHiddenDWORD
(
psa
,
vt
);
}
}
/* Create an array */
static
SAFEARRAY
*
SAFEARRAY_Create
(
VARTYPE
vt
,
UINT
cDims
,
SAFEARRAYBOUND
*
rgsabound
,
ULONG
ulSize
)
{
SAFEARRAY
*
psa
=
NULL
;
if
(
!
rgsabound
)
return
NULL
;
if
(
SUCCEEDED
(
SafeArrayAllocDescriptorEx
(
vt
,
cDims
,
&
psa
)))
{
switch
(
vt
)
{
case
VT_BSTR
:
psa
->
fFeatures
|=
FADF_BSTR
;
break
;
case
VT_UNKNOWN
:
psa
->
fFeatures
|=
FADF_UNKNOWN
;
break
;
case
VT_DISPATCH
:
psa
->
fFeatures
|=
FADF_DISPATCH
;
break
;
case
VT_VARIANT
:
psa
->
fFeatures
|=
FADF_VARIANT
;
break
;
}
memcpy
(
psa
->
rgsabound
,
rgsabound
,
cDims
*
sizeof
(
SAFEARRAYBOUND
));
if
(
ulSize
)
psa
->
cbElements
=
ulSize
;
if
(
FAILED
(
SafeArrayAllocData
(
psa
)))
{
SafeArrayDestroyDescriptor
(
psa
);
psa
=
NULL
;
}
}
return
psa
;
}
/* Create an array as a vector */
static
SAFEARRAY
*
SAFEARRAY_CreateVector
(
VARTYPE
vt
,
LONG
lLbound
,
ULONG
cElements
,
ULONG
ulSize
)
{
SAFEARRAY
*
psa
=
NULL
;
if
(
cElements
&&
(
vt
==
VT_RECORD
||
ulSize
))
{
/* Allocate the header and data together */
if
(
SUCCEEDED
(
SAFEARRAY_AllocDescriptor
(
sizeof
(
SAFEARRAY
)
+
ulSize
*
cElements
,
&
psa
)))
{
SAFEARRAY_SetFeatures
(
vt
,
psa
);
psa
->
cDims
=
1
;
psa
->
fFeatures
|=
FADF_CREATEVECTOR
;
psa
->
pvData
=
&
psa
[
1
];
/* Data follows the header */
psa
->
cbElements
=
ulSize
;
psa
->
rgsabound
[
0
].
cElements
=
cElements
;
psa
->
rgsabound
[
0
].
lLbound
=
lLbound
;
switch
(
vt
)
{
case
VT_BSTR
:
psa
->
fFeatures
|=
FADF_BSTR
;
break
;
case
VT_UNKNOWN
:
psa
->
fFeatures
|=
FADF_UNKNOWN
;
break
;
case
VT_DISPATCH
:
psa
->
fFeatures
|=
FADF_DISPATCH
;
break
;
case
VT_VARIANT
:
psa
->
fFeatures
|=
FADF_VARIANT
;
break
;
}
}
}
else
if
(
!
cElements
)
{
ERR
(
"Creating vector of size 0! Please report.
\n
"
);
}
return
psa
;
}
static
BOOL
resizeSafeArray
(
SAFEARRAY
*
psa
,
LONG
lDelta
);
/* Free data items in an array */
static
HRESULT
SAFEARRAY_DestroyData
(
SAFEARRAY
*
psa
,
ULONG
ulStartCell
)
{
if
(
psa
->
pvData
&&
!
(
psa
->
fFeatures
&
FADF_DATADELETED
))
{
ULONG
ulCellCount
=
SAFEARRAY_GetCellCount
(
psa
);
static
BOOL
validArg
(
SAFEARRAY
*
psa
)
;
if
(
ulCellCount
==
SAFEARRAY_INVALID_CELLS
||
ulStartCell
>
ulCellCount
)
return
E_UNEXPECTED
;
static
ULONG
getArraySize
(
SAFEARRAY
*
psa
);
ulCellCount
-=
ulStartCell
;
static
HRESULT
duplicateData
(
SAFEARRAY
*
psa
,
SAFEARRAY
*
ppsaOut
);
if
(
psa
->
fFeatures
&
(
FADF_UNKNOWN
|
FADF_DISPATCH
))
{
LPUNKNOWN
*
lpUnknown
=
(
LPUNKNOWN
*
)
psa
->
pvData
+
ulStartCell
*
psa
->
cbElements
;
/* Association between VARTYPE and their size.
A size of zero is defined for the unsupported types. */
while
(
ulCellCount
--
)
{
if
(
*
lpUnknown
)
IUnknown_Release
(
*
lpUnknown
);
lpUnknown
++
;
}
}
else
if
(
psa
->
fFeatures
&
(
FADF_RECORD
))
{
IRecordInfo
*
lpRecInfo
;
if
(
SUCCEEDED
(
SafeArrayGetRecordInfo
(
psa
,
&
lpRecInfo
)))
{
PBYTE
pRecordData
=
(
PBYTE
)
psa
->
pvData
;
while
(
ulCellCount
--
)
{
IRecordInfo_RecordClear
(
lpRecInfo
,
pRecordData
);
pRecordData
+=
psa
->
cbElements
;
}
IRecordInfo_Release
(
lpRecInfo
);
}
}
else
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
BSTR
*
lpBstr
=
(
BSTR
*
)
psa
->
pvData
+
ulStartCell
*
psa
->
cbElements
;
while
(
ulCellCount
--
)
{
if
(
*
lpBstr
)
SysFreeString
(
*
lpBstr
);
lpBstr
++
;
}
}
else
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
VARIANT
*
lpVariant
=
(
VARIANT
*
)
psa
->
pvData
+
ulStartCell
*
psa
->
cbElements
;
while
(
ulCellCount
--
)
{
VariantClear
(
lpVariant
);
lpVariant
++
;
}
}
}
return
S_OK
;
}
#define VARTYPE_NOT_SUPPORTED 0
static
const
ULONG
VARTYPE_SIZE
[]
=
/* Copy data items from one array to another */
static
HRESULT
SAFEARRAY_CopyData
(
SAFEARRAY
*
psa
,
SAFEARRAY
*
dest
)
{
/* this is taken from wtypes.h. Only [S]es are supported by the SafeArray */
VARTYPE_NOT_SUPPORTED
,
/* VT_EMPTY [V] [P] nothing */
VARTYPE_NOT_SUPPORTED
,
/* VT_NULL [V] [P] SQL style Nul */
2
,
/* VT_I2 [V][T][P][S] 2 byte signed int */
4
,
/* VT_I4 [V][T][P][S] 4 byte signed int */
4
,
/* VT_R4 [V][T][P][S] 4 byte real */
8
,
/* VT_R8 [V][T][P][S] 8 byte real */
8
,
/* VT_CY [V][T][P][S] currency */
8
,
/* VT_DATE [V][T][P][S] date */
sizeof
(
BSTR
),
/* VT_BSTR [V][T][P][S] OLE Automation string*/
sizeof
(
LPDISPATCH
),
/* VT_DISPATCH [V][T][P][S] IDispatch * */
4
,
/* VT_ERROR [V][T] [S] SCODE */
2
,
/* VT_BOOL [V][T][P][S] True=-1, False=0*/
sizeof
(
VARIANT
),
/* VT_VARIANT [V][T][P][S] VARIANT * */
sizeof
(
LPUNKNOWN
),
/* VT_UNKNOWN [V][T] [S] IUnknown * */
sizeof
(
DECIMAL
),
/* VT_DECIMAL [V][T] [S] 16 byte fixed point */
VARTYPE_NOT_SUPPORTED
,
/* no VARTYPE here..... */
1
,
/* VT_I1 [T] [S] signed char */
1
,
/* VT_UI1 [V][T][P][S] unsigned char */
2
,
/* VT_UI2 [T][P][S] unsigned short */
4
,
/* VT_UI4 [T][P][S] unsigned int */
VARTYPE_NOT_SUPPORTED
,
/* VT_I8 [T][P] signed 64-bit int */
VARTYPE_NOT_SUPPORTED
,
/* VT_UI8 [T][P] unsigned 64-bit int */
sizeof
(
INT
),
/* VT_INT [T] signed machine int */
sizeof
(
UINT
),
/* VT_UINT [T] unsigned machine int */
VARTYPE_NOT_SUPPORTED
,
/* VT_VOID [T] C style void */
VARTYPE_NOT_SUPPORTED
,
/* VT_HRESULT [T] Standard return type */
VARTYPE_NOT_SUPPORTED
,
/* VT_PTR [T] pointer type */
VARTYPE_NOT_SUPPORTED
,
/* VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)*/
VARTYPE_NOT_SUPPORTED
,
/* VT_CARRAY [T] C style array */
VARTYPE_NOT_SUPPORTED
,
/* VT_USERDEFINED [T] user defined type */
VARTYPE_NOT_SUPPORTED
,
/* VT_LPSTR [T][P] null terminated string */
VARTYPE_NOT_SUPPORTED
,
/* VT_LPWSTR [T][P] wide null term string */
VARTYPE_NOT_SUPPORTED
,
/* 32 */
VARTYPE_NOT_SUPPORTED
,
/* 33 */
VARTYPE_NOT_SUPPORTED
,
/* 34 */
VARTYPE_NOT_SUPPORTED
,
/* 35 */
VARTYPE_NOT_SUPPORTED
,
/* VT_RECORD record */
VARTYPE_NOT_SUPPORTED
,
/* 37 */
VARTYPE_NOT_SUPPORTED
,
/* 38 */
VARTYPE_NOT_SUPPORTED
,
/* 39 */
VARTYPE_NOT_SUPPORTED
,
/* 40 */
VARTYPE_NOT_SUPPORTED
,
/* 41 */
VARTYPE_NOT_SUPPORTED
,
/* 42 */
VARTYPE_NOT_SUPPORTED
,
/* 43 */
VARTYPE_NOT_SUPPORTED
,
/* 44 */
VARTYPE_NOT_SUPPORTED
,
/* 45 */
VARTYPE_NOT_SUPPORTED
,
/* 46 */
VARTYPE_NOT_SUPPORTED
,
/* 47 */
VARTYPE_NOT_SUPPORTED
,
/* 48 */
VARTYPE_NOT_SUPPORTED
,
/* 49 */
VARTYPE_NOT_SUPPORTED
,
/* 50 */
VARTYPE_NOT_SUPPORTED
,
/* 51 */
VARTYPE_NOT_SUPPORTED
,
/* 52 */
VARTYPE_NOT_SUPPORTED
,
/* 53 */
VARTYPE_NOT_SUPPORTED
,
/* 54 */
VARTYPE_NOT_SUPPORTED
,
/* 55 */
VARTYPE_NOT_SUPPORTED
,
/* 56 */
VARTYPE_NOT_SUPPORTED
,
/* 57 */
VARTYPE_NOT_SUPPORTED
,
/* 58 */
VARTYPE_NOT_SUPPORTED
,
/* 59 */
VARTYPE_NOT_SUPPORTED
,
/* 60 */
VARTYPE_NOT_SUPPORTED
,
/* 61 */
VARTYPE_NOT_SUPPORTED
,
/* 62 */
VARTYPE_NOT_SUPPORTED
,
/* 63 */
VARTYPE_NOT_SUPPORTED
,
/* VT_FILETIME [P] FILETIME */
VARTYPE_NOT_SUPPORTED
,
/* VT_BLOB [P] Length prefixed bytes */
VARTYPE_NOT_SUPPORTED
,
/* VT_STREAM [P] Name of stream follows */
VARTYPE_NOT_SUPPORTED
,
/* VT_STORAGE [P] Name of storage follows */
VARTYPE_NOT_SUPPORTED
,
/* VT_STREAMED_OBJECT[P] Stream contains an object*/
VARTYPE_NOT_SUPPORTED
,
/* VT_STORED_OBJECT [P] Storage contains object*/
VARTYPE_NOT_SUPPORTED
,
/* VT_BLOB_OBJECT [P] Blob contains an object*/
VARTYPE_NOT_SUPPORTED
,
/* VT_CF [P] Clipboard format */
VARTYPE_NOT_SUPPORTED
,
/* VT_CLSID [P] A Class ID */
};
static
const
int
LAST_VARTYPE
=
sizeof
(
VARTYPE_SIZE
)
/
sizeof
(
VARTYPE_SIZE
[
0
]);
if
(
!
psa
->
pvData
||
!
dest
->
pvData
||
psa
->
fFeatures
&
FADF_DATADELETED
)
return
E_INVALIDARG
;
else
{
ULONG
ulCellCount
=
SAFEARRAY_GetCellCount
(
psa
);
if
(
ulCellCount
==
SAFEARRAY_INVALID_CELLS
)
return
E_UNEXPECTED
;
dest
->
fFeatures
=
(
dest
->
fFeatures
&
FADF_CREATEVECTOR
)
|
(
psa
->
fFeatures
&
~
(
FADF_CREATEVECTOR
|
FADF_DATADELETED
));
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
VARIANT
*
lpVariant
=
(
VARIANT
*
)
psa
->
pvData
;
VARIANT
*
lpDest
=
(
VARIANT
*
)
dest
->
pvData
;
while
(
ulCellCount
--
)
{
VariantCopy
(
lpDest
,
lpVariant
);
lpVariant
++
;
lpDest
++
;
}
}
else
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
BSTR
*
lpBstr
=
(
BSTR
*
)
psa
->
pvData
;
BSTR
*
lpDest
=
(
BSTR
*
)
dest
->
pvData
;
while
(
ulCellCount
--
)
{
if
(
*
lpBstr
)
{
*
lpDest
=
SysAllocStringLen
(
*
lpBstr
,
SysStringLen
(
*
lpBstr
));
if
(
!*
lpDest
)
return
E_OUTOFMEMORY
;
}
else
*
lpDest
=
NULL
;
lpBstr
++
;
lpDest
++
;
}
}
else
{
/* Copy the data over */
memcpy
(
dest
->
pvData
,
psa
->
pvData
,
ulCellCount
*
psa
->
cbElements
);
if
(
psa
->
fFeatures
&
(
FADF_UNKNOWN
|
FADF_DISPATCH
))
{
LPUNKNOWN
*
lpUnknown
=
(
LPUNKNOWN
*
)
dest
->
pvData
;
while
(
ulCellCount
--
)
{
if
(
*
lpUnknown
)
IUnknown_AddRef
(
*
lpUnknown
);
lpUnknown
++
;
}
}
}
if
(
psa
->
fFeatures
&
FADF_RECORD
)
{
IRecordInfo
*
pRecInfo
=
NULL
;
SafeArrayGetRecordInfo
(
psa
,
&
pRecInfo
);
SafeArraySetRecordInfo
(
dest
,
pRecInfo
);
if
(
pRecInfo
)
{
/* Release because Get() adds a reference */
IRecordInfo_Release
(
pRecInfo
);
}
}
else
if
(
psa
->
fFeatures
&
FADF_HAVEIID
)
{
GUID
guid
;
SafeArrayGetIID
(
psa
,
&
guid
);
SafeArraySetIID
(
dest
,
&
guid
);
}
else
if
(
psa
->
fFeatures
&
FADF_HAVEVARTYPE
)
{
SAFEARRAY_SetHiddenDWORD
(
dest
,
SAFEARRAY_GetHiddenDWORD
(
psa
));
}
}
return
S_OK
;
}
/*************************************************************************
* SafeArrayAllocDescriptor (OLEAUT32.36)
* Allocate the appropriate amount of memory for the SafeArray descriptor
*
* Allocate and initialise a descriptor for a SafeArray.
*
* PARAMS
* cDims [I] Number of dimensions of the array
* ppsaOut [O] Destination for new descriptor
*
* RETURNS
* Success: S_OK. ppsaOut is filled with a newly allocated descriptor.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayAllocDescriptor
(
UINT
cDims
,
SAFEARRAY
**
ppsaOut
)
HRESULT
WINAPI
SafeArrayAllocDescriptor
(
UINT
cDims
,
SAFEARRAY
**
ppsaOut
)
{
SAFEARRAYBOUND
*
sab
;
LONG
allocSize
=
0
;
char
*
ptr
;
LONG
allocSize
;
if
(
!
cDims
||
cDims
>=
0x10000
)
/* 65536 appears to be the limit */
TRACE
(
"(%d,%p)
\n
"
,
cDims
,
ppsaOut
);
if
(
!
cDims
||
cDims
>=
0x10000
)
/* Maximum 65535 dimensions */
return
E_INVALIDARG
;
if
(
!
ppsaOut
)
return
E_POINTER
;
/* GUID + SAFEARRAY + SAFEARRAYBOUND * (cDims -1)
* ( -1 because there is already one ( in SAFEARRAY struct
*/
allocSize
=
sizeof
(
GUID
)
+
sizeof
(
**
ppsaOut
)
+
(
sizeof
(
*
sab
)
*
(
cDims
-
1
));
/* We need enough space for the header and its bounds */
allocSize
=
sizeof
(
SAFEARRAY
)
+
sizeof
(
SAFEARRAYBOUND
)
*
(
cDims
-
1
);
/* Allocate memory for SAFEARRAY struc */
ptr
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
allocSize
);
if
(
!
ptr
)
return
E_OUTOFMEMORY
;
*
ppsaOut
=
(
SAFEARRAY
*
)(
ptr
+
sizeof
(
GUID
));
(
*
ppsaOut
)
->
cDims
=
cDims
;
TRACE
(
"(%d): %lu bytes allocated for descriptor.
\n
"
,
cDims
,
allocSize
);
if
(
FAILED
(
SAFEARRAY_AllocDescriptor
(
allocSize
,
ppsaOut
)))
return
E_UNEXPECTED
;
return
(
S_OK
);
(
*
ppsaOut
)
->
cDims
=
cDims
;
TRACE
(
"(%d): %lu bytes allocated for descriptor.
\n
"
,
cDims
,
allocSize
);
return
S_OK
;
}
/*************************************************************************
* SafeArrayAllocDescriptorEx (OLEAUT32.41)
* Allocate the appropriate amount of memory for the SafeArray descriptor
* and also store information about the vartype before the returned pointer.
*
* Allocate and initialise a descriptor for a SafeArray of a given type.
*
* PARAMS
* vt [I] The type of items to store in the array
* cDims [I] Number of dimensions of the array
* ppsaOut [O] Destination for new descriptor
*
* RETURNS
* Success: S_OK. ppsaOut is filled with a newly allocated descriptor.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* - This function does not chack that vt is an allowed VARTYPE.
* - Unlike SafeArrayAllocDescriptor(), vt is associated with the array.
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayAllocDescriptorEx
(
VARTYPE
vt
,
UINT
cDims
,
SAFEARRAY
**
ppsaOut
)
HRESULT
WINAPI
SafeArrayAllocDescriptorEx
(
VARTYPE
vt
,
UINT
cDims
,
SAFEARRAY
**
ppsaOut
)
{
HRESULT
hres
;
hres
=
SafeArrayAllocDescriptor
(
cDims
,
ppsaOut
);
if
(
FAILED
(
hres
))
return
hres
;
switch
(
vt
)
{
case
VT_DISPATCH
:
(
*
ppsaOut
)
->
fFeatures
=
FADF_HAVEIID
;
SafeArraySetIID
(
*
ppsaOut
,
&
IID_IDispatch
);
break
;
case
VT_UNKNOWN
:
(
*
ppsaOut
)
->
fFeatures
=
FADF_HAVEIID
;
SafeArraySetIID
(
*
ppsaOut
,
&
IID_IUnknown
);
break
;
case
VT_RECORD
:
(
*
ppsaOut
)
->
fFeatures
=
FADF_RECORD
;
break
;
default:
(
*
ppsaOut
)
->
fFeatures
=
FADF_HAVEVARTYPE
;
((
DWORD
*
)
*
ppsaOut
)[
-
1
]
=
vt
;
break
;
ULONG
cbElements
;
HRESULT
hRet
=
E_UNEXPECTED
;
TRACE
(
"(%d->%s,%d,%p)
\n
"
,
vt
,
debugstr_vt
(
vt
),
cDims
,
ppsaOut
);
cbElements
=
SAFEARRAY_GetVTSize
(
vt
);
if
(
!
cbElements
)
WARN
(
"Creating a descriptor with an invalid VARTYPE!
\n
"
);
hRet
=
SafeArrayAllocDescriptor
(
cDims
,
ppsaOut
);
if
(
SUCCEEDED
(
hRet
))
{
SAFEARRAY_SetFeatures
(
vt
,
*
ppsaOut
);
(
*
ppsaOut
)
->
cbElements
=
cbElements
;
}
return
S_OK
;
return
hRet
;
}
/*************************************************************************
* SafeArrayAllocData (OLEAUT32.37)
* Allocate the appropriate amount of data for the SafeArray data
*
* Allocate the data area of a SafeArray.
*
* PARAMS
* psa [I] SafeArray to allocate the data area of.
*
* RETURNS
* Success: S_OK. The data area is allocated and initialised.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayAllocData
(
SAFEARRAY
*
psa
)
HRESULT
WINAPI
SafeArrayAllocData
(
SAFEARRAY
*
psa
)
{
ULONG
ulWholeArraySize
;
/* to store the size of the whole thing */
if
(
!
validArg
(
psa
))
return
E_INVALIDARG
;
ulWholeArraySize
=
getArraySize
(
psa
);
HRESULT
hRet
=
E_INVALIDARG
;
TRACE
(
"(%p)
\n
"
,
psa
);
if
(
psa
)
{
ULONG
ulSize
=
SAFEARRAY_GetCellCount
(
psa
);
/* Allocate memory for the data itself */
if
((
psa
->
pvData
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
psa
->
cbElements
*
ulWholeArraySize
))
==
NULL
)
return
(
E_UNEXPECTED
);
hRet
=
E_OUTOFMEMORY
;
TRACE
(
"SafeArray: %lu bytes allocated for data at %p (%lu objects).
\n
"
,
psa
->
cbElements
*
ulWholeArraySize
,
psa
->
pvData
,
ulWholeArraySize
);
if
(
ulSize
!=
SAFEARRAY_INVALID_CELLS
&&
psa
->
cbElements
)
{
psa
->
pvData
=
SAFEARRAY_Malloc
(
ulSize
*
psa
->
cbElements
);
return
(
S_OK
);
if
(
psa
->
pvData
)
{
hRet
=
S_OK
;
TRACE
(
"%lu bytes allocated for data at %p (%lu objects).
\n
"
,
ulSize
*
psa
->
cbElements
,
psa
->
pvData
,
ulSize
);
}
}
}
return
hRet
;
}
/*************************************************************************
* SafeArrayCreate (OLEAUT32.15)
* Create a SafeArray object by encapsulating AllocDescriptor and AllocData
*
* Create a new SafeArray.
*
* PARAMS
* vt [I] Type to store in the safe array
* cDims [I] Number of array dimensions
* rgsabound [I] Bounds of the array dimensions
*
* RETURNS
* Success: A pointer to a new array object.
* Failure: NULL, if any parameter is invalid or memory allocation fails.
*
* NOTES
* Win32 allows arrays with 0 sized dimensions. This bug is not reproduced
* in the Wine implementation.
* See SafeArray.
*/
SAFEARRAY
*
WINAPI
SafeArrayCreate
(
VARTYPE
vt
,
UINT
cDims
,
SAFEARRAYBOUND
*
rgsabound
)
SAFEARRAY
*
WINAPI
SafeArrayCreate
(
VARTYPE
vt
,
UINT
cDims
,
SAFEARRAYBOUND
*
rgsabound
)
{
SAFEARRAY
*
psa
;
HRESULT
hRes
;
USHORT
cDim
;
TRACE
(
"(%d->%s,%d,%p)
\n
"
,
vt
,
debugstr_vt
(
vt
),
cDims
,
rgsabound
);
TRACE
(
"(%d, %d, %p)
\n
"
,
vt
,
cDims
,
rgsabound
);
/* Validate supported VARTYPE */
if
(
(
vt
>=
LAST_VARTYPE
)
||
(
VARTYPE_SIZE
[
vt
]
==
VARTYPE_NOT_SUPPORTED
)
)
if
(
vt
==
VT_RECORD
)
return
NULL
;
/* Allocate memory for the array descriptor */
if
(
FAILED
(
hRes
=
SafeArrayAllocDescriptorEx
(
vt
,
cDims
,
&
psa
)))
return
NULL
;
return
SAFEARRAY_Create
(
vt
,
cDims
,
rgsabound
,
0
);
}
/* setup data members... */
psa
->
cDims
=
cDims
;
switch
(
vt
)
{
case
VT_BSTR
:
psa
->
fFeatures
|=
FADF_BSTR
;
break
;
case
VT_UNKNOWN
:
psa
->
fFeatures
|=
FADF_UNKNOWN
;
break
;
case
VT_DISPATCH
:
psa
->
fFeatures
|=
FADF_DISPATCH
;
break
;
case
VT_VARIANT
:
psa
->
fFeatures
|=
FADF_VARIANT
;
break
;
default:
break
;
/*************************************************************************
* SafeArrayCreateEx (OLEAUT32.15)
*
* Create a new SafeArray.
*
* PARAMS
* vt [I] Type to store in the safe array
* cDims [I] Number of array dimensions
* rgsabound [I] Bounds of the array dimensions
* pvExtra [I] Extra data
*
* RETURNS
* Success: A pointer to a new array object.
* Failure: NULL, if any parameter is invalid or memory allocation fails.
*
* NOTES
* See SafeArray.
*/
SAFEARRAY
*
WINAPI
SafeArrayCreateEx
(
VARTYPE
vt
,
UINT
cDims
,
SAFEARRAYBOUND
*
rgsabound
,
LPVOID
pvExtra
)
{
ULONG
ulSize
=
0
;
IRecordInfo
*
iRecInfo
=
(
IRecordInfo
*
)
pvExtra
;
SAFEARRAY
*
psa
;
TRACE
(
"(%d->%s,%d,%p,%p)
\n
"
,
vt
,
debugstr_vt
(
vt
),
cDims
,
rgsabound
,
pvExtra
);
if
(
vt
==
VT_RECORD
)
{
if
(
!
iRecInfo
)
return
NULL
;
IRecordInfo_GetSize
(
iRecInfo
,
&
ulSize
);
}
psa
->
cLocks
=
0
;
psa
->
pvData
=
NULL
;
psa
->
cbElements
=
VARTYPE_SIZE
[
vt
];
/* Invert the bounds ... */
for
(
cDim
=
0
;
cDim
<
psa
->
cDims
;
cDim
++
)
{
psa
->
rgsabound
[
cDim
].
cElements
=
rgsabound
[
psa
->
cDims
-
cDim
-
1
].
cElements
;
psa
->
rgsabound
[
cDim
].
lLbound
=
rgsabound
[
psa
->
cDims
-
cDim
-
1
].
lLbound
;
psa
=
SAFEARRAY_Create
(
vt
,
cDims
,
rgsabound
,
ulSize
);
if
(
pvExtra
)
{
switch
(
vt
)
{
case
VT_RECORD
:
SafeArraySetRecordInfo
(
psa
,
pvExtra
);
break
;
case
VT_UNKNOWN
:
case
VT_DISPATCH
:
SafeArraySetIID
(
psa
,
pvExtra
);
break
;
}
}
return
psa
;
}
/* allocate memory for the data... */
if
(
FAILED
(
hRes
=
SafeArrayAllocData
(
psa
)))
{
SafeArrayDestroyDescriptor
(
psa
);
ERR
(
"() : Failed to allocate the Safe Array data
\n
"
);
/************************************************************************
* SafeArrayCreateVector (OLEAUT32.411)
*
* Create a one dimensional, contigous SafeArray.
*
* PARAMS
* vt [I] Type to store in the safe array
* lLbound [I] Lower bound of the array
* cElements [I] Number of elements in the array
*
* RETURNS
* Success: A pointer to a new array object.
* Failure: NULL, if any parameter is invalid or memory allocation fails.
*
* NOTES
* See SafeArray.
*/
SAFEARRAY
*
WINAPI
SafeArrayCreateVector
(
VARTYPE
vt
,
LONG
lLbound
,
ULONG
cElements
)
{
TRACE
(
"(%d->%s,%ld,%ld
\n
"
,
vt
,
debugstr_vt
(
vt
),
lLbound
,
cElements
);
if
(
vt
==
VT_RECORD
)
return
NULL
;
return
SAFEARRAY_CreateVector
(
vt
,
lLbound
,
cElements
,
SAFEARRAY_GetVTSize
(
vt
));
}
/************************************************************************
* SafeArrayCreateVectorEx (OLEAUT32.411)
*
* Create a one dimensional, contigous SafeArray.
*
* PARAMS
* vt [I] Type to store in the safe array
* lLbound [I] Lower bound of the array
* cElements [I] Number of elements in the array
* pvExtra [I] Extra data
*
* RETURNS
* Success: A pointer to a new array object.
* Failure: NULL, if any parameter is invalid or memory allocation fails.
*
* NOTES
* See SafeArray.
*/
SAFEARRAY
*
WINAPI
SafeArrayCreateVectorEx
(
VARTYPE
vt
,
LONG
lLbound
,
ULONG
cElements
,
LPVOID
pvExtra
)
{
ULONG
ulSize
;
IRecordInfo
*
iRecInfo
=
(
IRecordInfo
*
)
pvExtra
;
SAFEARRAY
*
psa
;
TRACE
(
"(%d->%s,%ld,%ld,%p
\n
"
,
vt
,
debugstr_vt
(
vt
),
lLbound
,
cElements
,
pvExtra
);
if
(
vt
==
VT_RECORD
)
{
if
(
!
iRecInfo
)
return
NULL
;
IRecordInfo_GetSize
(
iRecInfo
,
&
ulSize
);
}
else
ulSize
=
SAFEARRAY_GetVTSize
(
vt
);
psa
=
SAFEARRAY_CreateVector
(
vt
,
lLbound
,
cElements
,
ulSize
);
return
(
psa
);
if
(
pvExtra
)
{
switch
(
vt
)
{
case
VT_RECORD
:
SafeArraySetRecordInfo
(
psa
,
iRecInfo
);
break
;
case
VT_UNKNOWN
:
case
VT_DISPATCH
:
SafeArraySetIID
(
psa
,
pvExtra
);
break
;
}
}
return
psa
;
}
/*************************************************************************
* SafeArrayDestroyDescriptor (OLEAUT32.38)
* Frees the memory associated with the descriptor.
*
* Destroy a SafeArray.
*
* PARAMS
* psa [I] SafeArray to destroy.
*
* RETURNS
* Success: S_OK. The resources used by the array are freed.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayDestroyDescriptor
(
SAFEARRAY
*
psa
)
HRESULT
WINAPI
SafeArrayDestroyDescriptor
(
SAFEARRAY
*
psa
)
{
LPVOID
ptr
;
TRACE
(
"(%p)
\n
"
,
psa
);
if
(
psa
)
{
LPVOID
lpv
=
(
char
*
)
psa
-
SAFEARRAY_HIDDEN_SIZE
;
/* Check for lockness before to free... */
if
(
psa
->
cLocks
>
0
)
return
DISP_E_ARRAYISLOCKED
;
if
(
psa
->
cLocks
)
return
DISP_E_ARRAYISLOCKED
;
/* Can't destroy a locked array */
/* The array is unlocked, then, deallocate memory */
ptr
=
((
IID
*
)
psa
)
-
1
;
if
(
HeapFree
(
GetProcessHeap
(),
0
,
ptr
)
==
FALSE
)
return
E_UNEXPECTED
;
return
(
S_OK
);
}
if
(
psa
->
fFeatures
&
FADF_RECORD
)
SafeArraySetRecordInfo
(
psa
,
NULL
)
;
if
(
psa
->
fFeatures
&
FADF_CREATEVECTOR
&&
!
(
psa
->
fFeatures
&
FADF_DATADELETED
))
SAFEARRAY_DestroyData
(
psa
,
0
);
/* Data not previously deleted */
if
(
!
SAFEARRAY_Free
(
lpv
))
return
E_UNEXPECTED
;
}
return
S_OK
;
}
/*************************************************************************
* SafeArrayLock (OLEAUT32.21)
* Increment the lock counter
*
* Doc says (MSDN Library ) that psa->pvData should be made available (!= NULL)
* only when psa->cLocks is > 0... I don't get it since pvData is allocated
* before the array is locked, therefore
* Increment the lock counter of a SafeArray.
*
* PARAMS
* psa [O] SafeArray to lock
*
* RETURNS
* Success: S_OK. The array lock is incremented.
* Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if too many locks
* are held on the array at once.
*
* NOTES
* In Win32 these locks are not thread safe.
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayLock
(
SAFEARRAY
*
psa
)
HRESULT
WINAPI
SafeArrayLock
(
SAFEARRAY
*
psa
)
{
if
(
!
validArg
(
psa
))
ULONG
ulLocks
;
TRACE
(
"(%p)
\n
"
,
psa
);
if
(
!
psa
)
return
E_INVALIDARG
;
psa
->
cLocks
++
;
ulLocks
=
InterlockedIncrement
(
&
psa
->
cLocks
)
;
return
(
S_OK
);
if
(
ulLocks
>
0xffff
)
/* Maximum of 16384 locks at a time */
{
WARN
(
"Out of locks!
\n
"
);
InterlockedDecrement
(
&
psa
->
cLocks
);
return
E_UNEXPECTED
;
}
return
S_OK
;
}
/*************************************************************************
* SafeArrayUnlock (OLEAUT32.22)
* Decrement the lock counter
*
* Decrement the lock counter of a SafeArray.
*
* PARAMS
* psa [O] SafeArray to unlock
*
* RETURNS
* Success: S_OK. The array lock is decremented.
* Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if no locks are
* held on the array.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayUnlock
(
SAFEARRAY
*
psa
)
HRESULT
WINAPI
SafeArrayUnlock
(
SAFEARRAY
*
psa
)
{
if
(
!
validArg
(
psa
))
TRACE
(
"(%p)
\n
"
,
psa
);
if
(
!
psa
)
return
E_INVALIDARG
;
if
(
psa
->
cLocks
>
0
)
psa
->
cLocks
--
;
return
(
S_OK
);
if
((
LONG
)
InterlockedDecrement
(
&
psa
->
cLocks
)
<
0
)
{
WARN
(
"Unlocked but no lock held!
\n
"
);
InterlockedIncrement
(
&
psa
->
cLocks
);
return
E_UNEXPECTED
;
}
return
S_OK
;
}
/*************************************************************************
* SafeArrayPutElement (OLEAUT32.26)
* Set the data at the given coordinate
*
* Put an item into a SafeArray.
*
* PARAMS
* psa [I] SafeArray to insert into
* rgIndices [I] Indices to insert at
* pvData [I] Data to insert
*
* RETURNS
* Success: S_OK. The item is inserted
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayPutElement
(
SAFEARRAY
*
psa
,
LONG
*
rgIndices
,
void
*
pv
)
HRESULT
WINAPI
SafeArrayPutElement
(
SAFEARRAY
*
psa
,
LONG
*
rgIndices
,
void
*
pvData
)
{
ULONG
stepCountInSAData
=
0
;
/* Number of array item to skip to get to
the desired one... */
PVOID
elementStorageAddress
=
NULL
;
/* Address to store the data */
HRESULT
hRet
;
/* Validate the index given */
if
(
!
validCoordinate
(
rgIndices
,
psa
))
return
DISP_E_BADINDEX
;
if
(
!
validArg
(
psa
))
return
E_INVALIDARG
;
TRACE
(
"(%p,%p,%p)
\n
"
,
psa
,
rgIndices
,
pvData
);
if
(
SafeArrayLock
(
psa
)
==
S_OK
)
{
if
(
!
psa
||
!
rgIndices
)
return
E_INVALIDARG
;
/* Figure out the number of items to skip */
stepCountInSAData
=
calcDisplacement
(
rgIndices
,
psa
->
rgsabound
,
psa
->
cDims
);
if
(
!
pvData
)
{
ERR
(
"Invalid pvData would crash under Win32!
\n
"
);
return
E_INVALIDARG
;
}
/* Figure out the number of byte to skip ... */
elementStorageAddress
=
(
char
*
)
psa
->
pvData
+
(
stepCountInSAData
*
psa
->
cbElements
);
hRet
=
SafeArrayLock
(
psa
);
if
(
isPointer
(
psa
->
fFeatures
))
{
/* increment ref count for this pointer */
if
(
SUCCEEDED
(
hRet
))
{
PVOID
lpvDest
;
*
((
PVOID
*
)
elementStorageAddress
)
=
*
(
PVOID
*
)
pv
;
IUnknown_AddRef
(
*
(
IUnknown
**
)
pv
);
hRet
=
SafeArrayPtrOfIndex
(
psa
,
rgIndices
,
&
lpvDest
);
}
else
{
if
(
SUCCEEDED
(
hRet
))
{
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
VARIANT
*
lpVariant
=
(
VARIANT
*
)
pvData
;
VARIANT
*
lpDest
=
(
VARIANT
*
)
lpvDest
;
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
/* Create a new object */
BSTR
pbstrReAllocStr
=
NULL
;
if
(
pv
&&
((
pbstrReAllocStr
=
SYSDUPSTRING
(
(
OLECHAR
*
)
pv
))
==
NULL
))
{
SafeArrayUnlock
(
psa
);
return
E_OUTOFMEMORY
;
}
else
*
((
BSTR
*
)
elementStorageAddress
)
=
pbstrReAllocStr
;
VariantClear
(
lpDest
);
VariantCopy
(
lpDest
,
lpVariant
);
}
else
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
HRESULT
hr
=
VariantCopy
(
elementStorageAddress
,
pv
);
if
(
FAILED
(
hr
))
{
SafeArrayUnlock
(
psa
);
return
hr
;
else
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
BSTR
*
lpBstr
=
(
BSTR
*
)
pvData
;
BSTR
*
lpDest
=
(
BSTR
*
)
lpvDest
;
if
(
*
lpDest
)
SysFreeString
(
*
lpDest
);
if
(
*
lpBstr
)
{
*
lpDest
=
SysAllocStringLen
(
*
lpBstr
,
SysStringLen
(
*
lpBstr
));
if
(
!*
lpDest
)
hRet
=
E_OUTOFMEMORY
;
}
else
*
lpDest
=
NULL
;
}
else
{
if
(
psa
->
fFeatures
&
(
FADF_UNKNOWN
|
FADF_DISPATCH
))
{
LPUNKNOWN
*
lpUnknown
=
(
LPUNKNOWN
*
)
pvData
;
LPUNKNOWN
*
lpDest
=
(
LPUNKNOWN
*
)
lpvDest
;
if
(
*
lpUnknown
)
IUnknown_AddRef
(
*
lpUnknown
);
if
(
*
lpDest
)
IUnknown_Release
(
*
lpDest
);
}
/* Copy the data over */
memcpy
(
lpvDest
,
pvData
,
psa
->
cbElements
);
}
else
/* duplicate the memory */
memcpy
(
elementStorageAddress
,
pv
,
SafeArrayGetElemsize
(
psa
)
);
}
}
else
{
ERR
(
"SafeArray: Cannot lock array....
\n
"
);
return
E_UNEXPECTED
;
/* UNDOC error condition */
SafeArrayUnlock
(
psa
);
}
TRACE
(
"SafeArray: item put at address %p.
\n
"
,
elementStorageAddress
);
return
SafeArrayUnlock
(
psa
);
return
hRet
;
}
/*************************************************************************
* SafeArrayGetElement (OLEAUT32.25)
* Return the data element corresponding the the given coordinate
*
* Get an item from a SafeArray.
*
* PARAMS
* psa [I] SafeArray to get from
* rgIndices [I] Indices to get from
* pvData [O] Destination for data
*
* RETURNS
* Success: S_OK. The item data is returned in pvData.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayGetElement
(
SAFEARRAY
*
psa
,
LONG
*
rgIndices
,
void
*
pv
)
HRESULT
WINAPI
SafeArrayGetElement
(
SAFEARRAY
*
psa
,
LONG
*
rgIndices
,
void
*
pvData
)
{
ULONG
stepCountInSAData
=
0
;
/* Number of array item to skip to get to
the desired one... */
PVOID
elementStorageAddress
=
NULL
;
/* Address to store the data */
HRESULT
hRet
;
if
(
!
validArg
(
psa
))
TRACE
(
"(%p,%p,%p)
\n
"
,
psa
,
rgIndices
,
pvData
);
if
(
!
psa
||
!
rgIndices
||
!
pvData
)
return
E_INVALIDARG
;
if
(
!
validCoordinate
(
rgIndices
,
psa
))
/* Validate the index given */
return
(
DISP_E_BADINDEX
);
hRet
=
SafeArrayLock
(
psa
);
if
(
SafeArrayLock
(
psa
)
==
S_OK
)
{
if
(
SUCCEEDED
(
hRet
))
{
PVOID
lpvSrc
;
/* Figure out the number of items to skip */
stepCountInSAData
=
calcDisplacement
(
rgIndices
,
psa
->
rgsabound
,
psa
->
cDims
);
hRet
=
SafeArrayPtrOfIndex
(
psa
,
rgIndices
,
&
lpvSrc
);
/* Figure out the number of byte to skip ... */
elementStorageAddress
=
(
char
*
)
psa
->
pvData
+
(
stepCountInSAData
*
psa
->
cbElements
);
if
(
SUCCEEDED
(
hRet
))
{
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
VARIANT
*
lpVariant
=
(
VARIANT
*
)
lpvSrc
;
VARIANT
*
lpDest
=
(
VARIANT
*
)
pvData
;
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
/* reallocate the obj */
BSTR
pbstrStoredStr
=
*
(
OLECHAR
**
)
elementStorageAddress
;
BSTR
pbstrReturnedStr
=
NULL
;
if
(
pbstrStoredStr
&&
((
pbstrReturnedStr
=
SYSDUPSTRING
(
pbstrStoredStr
))
==
NULL
)
)
{
SafeArrayUnlock
(
psa
);
return
E_OUTOFMEMORY
;
}
else
*
((
BSTR
*
)
pv
)
=
pbstrReturnedStr
;
}
else
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
HRESULT
hr
;
VariantInit
(
pv
);
hr
=
VariantCopy
(
pv
,
elementStorageAddress
);
if
(
FAILED
(
hr
))
{
SafeArrayUnlock
(
psa
);
return
hr
;
VariantCopy
(
lpDest
,
lpVariant
);
}
else
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
BSTR
*
lpBstr
=
(
BSTR
*
)
lpvSrc
;
BSTR
*
lpDest
=
(
BSTR
*
)
pvData
;
if
(
*
lpBstr
)
{
*
lpDest
=
SysAllocStringLen
(
*
lpBstr
,
SysStringLen
(
*
lpBstr
));
if
(
!*
lpBstr
)
hRet
=
E_OUTOFMEMORY
;
}
else
*
lpDest
=
NULL
;
}
else
{
if
(
psa
->
fFeatures
&
(
FADF_UNKNOWN
|
FADF_DISPATCH
))
{
LPUNKNOWN
*
lpUnknown
=
(
LPUNKNOWN
*
)
lpvSrc
;
if
(
*
lpUnknown
)
IUnknown_AddRef
(
*
lpUnknown
);
}
/* Copy the data over */
memcpy
(
pvData
,
lpvSrc
,
psa
->
cbElements
);
}
}
else
if
(
isPointer
(
psa
->
fFeatures
)
)
/* simply copy the pointer */
*
(
PVOID
*
)
pv
=
*
((
PVOID
*
)
elementStorageAddress
);
else
/* copy the bytes */
memcpy
(
pv
,
elementStorageAddress
,
psa
->
cbElements
);
}
else
{
ERR
(
"SafeArray: Cannot lock array....
\n
"
);
return
E_UNEXPECTED
;
/* UNDOC error condition */
SafeArrayUnlock
(
psa
);
}
return
(
SafeArrayUnlock
(
psa
)
);
return
hRet
;
}
/*************************************************************************
* SafeArrayGetUBound (OLEAUT32.19)
* return the UP bound for a given array dimension
* Note: [0] is the right most (least significant) array index!
*
* Get the upper bound for a given SafeArray dimension
*
* PARAMS
* psa [I] Array to get dimension upper bound from
* nDim [I] The dimension number to get the upper bound of
* plUbound [O] Destination for the upper bound
*
* RETURNS
* Success: S_OK. plUbound contains the dimensions upper bound.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayGetUBound
(
SAFEARRAY
*
psa
,
UINT
nDim
,
LONG
*
plUbound
)
HRESULT
WINAPI
SafeArrayGetUBound
(
SAFEARRAY
*
psa
,
UINT
nDim
,
LONG
*
plUbound
)
{
if
(
!
validArg
(
psa
))
TRACE
(
"(%p,%d,%p)
\n
"
,
psa
,
nDim
,
plUbound
);
if
(
!
psa
||
!
plUbound
)
return
E_INVALIDARG
;
if
(
nDim
>
psa
->
cDims
)
return
DISP_E_BADINDEX
;
if
(
0
==
nDim
)
if
(
!
nDim
||
nDim
>
psa
->
cDims
||
!
psa
->
rgsabound
[
nDim
-
1
].
cElements
)
return
DISP_E_BADINDEX
;
*
plUbound
=
psa
->
rgsabound
[
psa
->
cDims
-
nDim
].
lLbound
+
psa
->
rgsabound
[
psa
->
cDims
-
nDim
].
cElements
-
1
;
*
plUbound
=
psa
->
rgsabound
[
nDim
-
1
].
lLbound
+
psa
->
rgsabound
[
nDim
-
1
].
cElements
-
1
;
return
S_OK
;
}
/*************************************************************************
* SafeArrayGetLBound (OLEAUT32.20)
* Return the LO bound for a given array dimension
* Note: [0] is the right most (least significant) array index!
*
* Get the lower bound for a given SafeArray dimension
*
* PARAMS
* psa [I] Array to get dimension lower bound from
* nDim [I] The dimension number to get the lowe bound of
* plLbound [O] Destination for the lower bound
*
* RETURNS
* Success: S_OK. plUbound contains the dimensions lower bound.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayGetLBound
(
SAFEARRAY
*
psa
,
UINT
nDim
,
LONG
*
plLbound
)
HRESULT
WINAPI
SafeArrayGetLBound
(
SAFEARRAY
*
psa
,
UINT
nDim
,
LONG
*
plLbound
)
{
if
(
!
validArg
(
psa
))
return
E_INVALIDARG
;
TRACE
(
"(%p,%d,%p)
\n
"
,
psa
,
nDim
,
plLbound
);
if
(
nDim
>
psa
->
cDims
)
return
DISP_E_BADINDEX
;
if
(
!
psa
||
!
plLbound
)
return
E_INVALIDARG
;
if
(
0
==
nDim
)
if
(
!
nDim
||
nDim
>
psa
->
cDims
||
!
psa
->
rgsabound
[
nDim
-
1
].
cElements
)
return
DISP_E_BADINDEX
;
*
plLbound
=
psa
->
rgsabound
[
psa
->
cDims
-
nDim
].
lLbound
;
*
plLbound
=
psa
->
rgsabound
[
nDim
-
1
].
lLbound
;
return
S_OK
;
}
/*************************************************************************
* SafeArrayGetDim (OLEAUT32.17)
* returns the number of dimension in the array
*
* Get the number of dimensions in a SafeArray.
*
* PARAMS
* psa [I] Array to get the dimensions of
*
* RETURNS
* The number of array dimensions in psa, or 0 if psa is NULL.
*
* NOTES
* See SafeArray.
*/
UINT
WINAPI
SafeArrayGetDim
(
SAFEARRAY
*
psa
)
UINT
WINAPI
SafeArrayGetDim
(
SAFEARRAY
*
psa
)
{
/*
* A quick test in Windows shows that the behavior here for an invalid
* pointer is to return 0.
*/
if
(
!
validArg
(
psa
))
return
0
;
return
psa
->
cDims
;
TRACE
(
"(%p) returning %ld
\n
"
,
psa
,
psa
?
psa
->
cDims
:
0ul
);
return
psa
?
psa
->
cDims
:
0
;
}
/*************************************************************************
* SafeArrayGetElemsize (OLEAUT32.18)
* Return the size of the element in the array
*
* Get the size of an element in a SafeArray.
*
* PARAMS
* psa [I] Array to get the element size from
*
* RETURNS
* The size of a single element in psa, or 0 if psa is NULL.
*
* NOTES
* See SafeArray.
*/
UINT
WINAPI
SafeArrayGetElemsize
(
SAFEARRAY
*
psa
)
UINT
WINAPI
SafeArrayGetElemsize
(
SAFEARRAY
*
psa
)
{
/*
* A quick test in Windows shows that the behavior here for an invalid
* pointer is to return 0.
*/
if
(
!
validArg
(
psa
))
return
0
;
return
psa
->
cbElements
;
TRACE
(
"(%p) returning %ld
\n
"
,
psa
,
psa
?
psa
->
cbElements
:
0ul
);
return
psa
?
psa
->
cbElements
:
0
;
}
/*************************************************************************
* SafeArrayAccessData (OLEAUT32.23)
* increment the access count and return the data
*
* Lock a SafeArray and return a pointer to its data.
*
* PARAMS
* psa [I] Array to get the data pointer from
* ppvData [O] Destination for the arrays data pointer
*
* RETURNS
* Success: S_OK. ppvData contains the arrays data pointer, and the array
* is locked.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayAccessData
(
SAFEARRAY
*
psa
,
void
**
ppvData
)
HRESULT
WINAPI
SafeArrayAccessData
(
SAFEARRAY
*
psa
,
void
**
ppvData
)
{
HRESULT
hRes
;
TRACE
(
"(%p,%p)
\n
"
,
psa
,
ppvData
)
;
if
(
!
validArg
(
psa
)
)
if
(
!
psa
||
!
ppvData
)
return
E_INVALIDARG
;
hRes
=
SafeArrayLock
(
psa
);
switch
(
hRes
)
{
case
S_OK
:
(
*
ppvData
)
=
psa
->
pvData
;
break
;
case
E_INVALIDARG
:
(
*
ppvData
)
=
NULL
;
return
E_INVALIDARG
;
if
(
SUCCEEDED
(
SafeArrayLock
(
psa
)))
{
*
ppvData
=
psa
->
pvData
;
return
S_OK
;
}
return
S_OK
;
*
ppvData
=
NULL
;
return
E_UNEXPECTED
;
}
/*************************************************************************
* SafeArrayUnaccessData (OLEAUT32.24)
* Decrement the access count
*/
HRESULT
WINAPI
SafeArrayUnaccessData
(
SAFEARRAY
*
psa
)
{
if
(
!
validArg
(
psa
))
return
E_INVALIDARG
;
return
(
SafeArrayUnlock
(
psa
));
}
/************************************************************************
* SafeArrayPtrOfIndex (OLEAUT32.148)
* Return a pointer to the element at rgIndices
*
* Unlock a SafeArray after accessing its data.
*
* PARAMS
* psa [I] Array to unlock
*
* RETURNS
* Success: S_OK. The array is unlocked.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayPtrOfIndex
(
SAFEARRAY
*
psa
,
LONG
*
rgIndices
,
void
**
ppvData
)
HRESULT
WINAPI
SafeArrayUnaccessData
(
SAFEARRAY
*
psa
)
{
ULONG
stepCountInSAData
=
0
;
/* Number of array item to skip to get to
the desired one... */
if
(
!
validArg
(
psa
))
return
E_INVALIDARG
;
if
(
!
validCoordinate
(
rgIndices
,
psa
))
return
DISP_E_BADINDEX
;
/* Although it is dangerous to do this without having a lock, it is not
* illegal. Microsoft do warn of the danger.
*/
/* Figure out the number of items to skip */
stepCountInSAData
=
calcDisplacement
(
rgIndices
,
psa
->
rgsabound
,
psa
->
cDims
);
*
ppvData
=
(
char
*
)
psa
->
pvData
+
(
stepCountInSAData
*
psa
->
cbElements
);
return
S_OK
;
TRACE
(
"(%p)
\n
"
,
psa
);
return
SafeArrayUnlock
(
psa
);
}
/************************************************************************
* SafeArrayDestroyData (OLEAUT32.39)
* Frees the memory data bloc
* SafeArrayPtrOfIndex (OLEAUT32.148)
*
* Get the address of an item in a SafeArray.
*
* PARAMS
* psa [I] Array to get the items address from
* rgIndices [I] Index of the item in the array
* ppvData [O] Destination for item address
*
* RETURNS
* Success: S_OK. ppvData contains a pointer to the item.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* This function does not lock the array.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayDestroyData
(
SAFEARRAY
*
psa
)
HRESULT
WINAPI
SafeArrayPtrOfIndex
(
SAFEARRAY
*
psa
,
LONG
*
rgIndices
,
void
**
ppvData
)
{
HRESULT
hRes
;
ULONG
ulWholeArraySize
;
/* count spot in array */
ULONG
ulDataIter
;
/* to iterate the data space */
if
(
!
validArg
(
psa
))
USHORT
dim
;
ULONG
cell
=
0
,
dimensionSize
=
1
;
SAFEARRAYBOUND
*
psab
;
LONG
c1
;
TRACE
(
"(%p,%p,%p)
\n
"
,
psa
,
rgIndices
,
ppvData
);
/* The general formula for locating the cell number of an entry in an n
* dimensional array (where cn = coordinate in dimension dn) is:
*
* c1 + c2 * sizeof(d1) + c3 * sizeof(d2) ... + cn * sizeof(c(n-1))
*
* We calculate the size of the last dimension at each step through the
* dimensions to avoid recursing to calculate the last dimensions size.
*/
if
(
!
psa
||
!
rgIndices
||
!
ppvData
)
return
E_INVALIDARG
;
if
(
psa
->
cLocks
>
0
)
return
DISP_E_ARRAYISLOCKED
;
if
(
psa
->
pvData
==
NULL
)
return
S_OK
;
psab
=
psa
->
rgsabound
;
c1
=
*
rgIndices
++
;
ulWholeArraySize
=
getArraySize
(
psa
);
if
(
c1
<
psab
->
lLbound
||
c1
>=
psab
->
lLbound
+
(
LONG
)
psab
->
cElements
)
return
DISP_E_BADINDEX
;
/* Initial index out of bounds */
if
(
isPointer
(
psa
->
fFeatures
))
{
/* release the pointers */
IUnknown
*
punk
;
for
(
dim
=
1
;
dim
<
psa
->
cDims
;
dim
++
)
{
dimensionSize
*=
psab
->
cElements
;
for
(
ulDataIter
=
0
;
ulDataIter
<
ulWholeArraySize
;
ulDataIter
++
)
{
punk
=
*
(
IUnknown
**
)((
char
*
)
psa
->
pvData
+
(
ulDataIter
*
(
psa
->
cbElements
)));
psab
++
;
if
(
punk
!=
NULL
)
IUnknown_Release
(
punk
);
}
if
(
!
psab
->
cElements
||
*
rgIndices
<
psab
->
lLbound
||
*
rgIndices
>=
psab
->
lLbound
+
(
LONG
)
psab
->
cElements
)
return
DISP_E_BADINDEX
;
/* Index out of bounds */
cell
+=
(
*
rgIndices
-
psab
->
lLbound
)
*
dimensionSize
;
rgIndices
++
;
}
else
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
/* deallocate the obj */
BSTR
bstr
;
for
(
ulDataIter
=
0
;
ulDataIter
<
ulWholeArraySize
;
ulDataIter
++
)
{
bstr
=
*
(
BSTR
*
)((
char
*
)
psa
->
pvData
+
(
ulDataIter
*
(
psa
->
cbElements
)));
cell
+=
(
c1
-
psa
->
rgsabound
[
0
].
lLbound
);
if
(
bstr
!=
NULL
)
SysFreeString
(
bstr
);
}
}
else
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
/* deallocate the obj */
*
ppvData
=
(
char
*
)
psa
->
pvData
+
cell
*
psa
->
cbElements
;
return
S_OK
;
}
for
(
ulDataIter
=
0
;
ulDataIter
<
ulWholeArraySize
;
ulDataIter
++
)
{
VariantClear
((
VARIANT
*
)((
char
*
)
psa
->
pvData
+
(
ulDataIter
*
(
psa
->
cbElements
))));
}
}
/************************************************************************
* SafeArrayDestroyData (OLEAUT32.39)
*
* Destroy the data associated with a SafeArray.
*
* PARAMS
* psa [I] Array to delete the data from
*
* RETURNS
* Success: S_OK. All items and the item data are freed.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayDestroyData
(
SAFEARRAY
*
psa
)
{
TRACE
(
"(%p)
\n
"
,
psa
);
if
(
!
psa
)
return
E_INVALIDARG
;
/* check if this array is a Vector, in which case do not free the data
block since it has been allocated by AllocDescriptor and therefore
deserve to be freed by DestroyDescriptor */
if
(
!
(
psa
->
fFeatures
&
FADF_CREATEVECTOR
))
{
/* Set when we do CreateVector */
if
(
psa
->
cLocks
)
return
DISP_E_ARRAYISLOCKED
;
/* Cant delete a locked array */
/* free the whole chunk */
if
((
hRes
=
HeapFree
(
GetProcessHeap
(),
0
,
psa
->
pvData
))
==
0
)
/*failed*/
return
E_UNEXPECTED
;
/* UNDOC error condition */
if
(
psa
->
pvData
)
{
/* Delete the actual item data */
if
(
FAILED
(
SAFEARRAY_DestroyData
(
psa
,
0
)))
return
E_UNEXPECTED
;
/* If this is not a vector, free the data memory block */
if
(
!
(
psa
->
fFeatures
&
FADF_CREATEVECTOR
))
{
if
(
!
SAFEARRAY_Free
(
psa
->
pvData
))
return
E_UNEXPECTED
;
psa
->
pvData
=
NULL
;
}
else
psa
->
fFeatures
|=
FADF_DATADELETED
;
/* Mark the data deleted */
psa
->
pvData
=
NULL
;
}
return
S_OK
;
}
/************************************************************************
* SafeArrayCopyData (OLEAUT32.412)
* Copy the psaSource's data block into psaTarget if dimension and size
* permits it.
*
* Copy all data from one SafeArray to another.
*
* PARAMS
* psaSource [I] Source for copy
* psaTarget [O] Destination for copy
*
* RETURNS
* Success: S_OK. psaTarget contains a copy of psaSource.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* The two arrays must have the same number of dimensions and elements.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayCopyData
(
SAFEARRAY
*
psaSource
,
SAFEARRAY
*
psaTarget
)
HRESULT
WINAPI
SafeArrayCopyData
(
SAFEARRAY
*
psaSource
,
SAFEARRAY
*
psaTarget
)
{
USHORT
cDimCount
;
/* looper */
LONG
lDelta
;
/* looper */
IUnknown
*
punk
;
ULONG
ulWholeArraySize
;
/* Number of item in SA */
BSTR
bstr
;
if
(
!
(
validArg
(
psaSource
)
&&
validArg
(
psaTarget
))
)
return
E_INVALIDARG
;
int
dim
;
if
(
SafeArrayGetDim
(
psaSource
)
!=
SafeArrayGetDim
(
psaTarget
))
TRACE
(
"(%p,%p)
\n
"
,
psaSource
,
psaTarget
);
if
(
!
psaSource
||
!
psaTarget
||
psaSource
->
cDims
!=
psaTarget
->
cDims
||
psaSource
->
cbElements
!=
psaTarget
->
cbElements
)
return
E_INVALIDARG
;
ulWholeArraySize
=
getArraySize
(
psaSource
);
/* The two arrays boundaries must be of same length */
for
(
cDimCount
=
0
;
cDimCount
<
psaSource
->
cDims
;
cDimCount
++
)
if
(
psaSource
->
rgsabound
[
cDimCount
].
cElements
!=
psaTarget
->
rgsabound
[
cDimCount
].
cElements
)
/* Each dimension must be the same size */
for
(
dim
=
psaSource
->
cDims
-
1
;
dim
>=
0
;
dim
--
)
if
(
psaSource
->
rgsabound
[
dim
].
cElements
!=
psaTarget
->
rgsabound
[
dim
].
cElements
)
return
E_INVALIDARG
;
if
(
isPointer
(
psaTarget
->
fFeatures
)
)
{
/* the target contains ptr
that must be released */
for
(
lDelta
=
0
;
lDelta
<
ulWholeArraySize
;
lDelta
++
)
{
punk
=
*
(
IUnknown
**
)
((
char
*
)
psaTarget
->
pvData
+
(
lDelta
*
psaTarget
->
cbElements
));
if
(
punk
!=
NULL
)
IUnknown_Release
(
punk
);
}
}
else
if
(
psaTarget
->
fFeatures
&
FADF_BSTR
)
{
/* the target contain BSTR
that must be freed */
for
(
lDelta
=
0
;
lDelta
<
ulWholeArraySize
;
lDelta
++
)
{
bstr
=
*
(
BSTR
*
)((
char
*
)
psaTarget
->
pvData
+
(
lDelta
*
psaTarget
->
cbElements
));
if
(
bstr
!=
NULL
)
SysFreeString
(
bstr
);
}
}
else
if
(
psaTarget
->
fFeatures
&
FADF_VARIANT
)
{
for
(
lDelta
=
0
;
lDelta
<
ulWholeArraySize
;
lDelta
++
)
{
VariantClear
((
VARIANT
*
)((
char
*
)
psaTarget
->
pvData
+
(
lDelta
*
psaTarget
->
cbElements
)));
}
}
return
duplicateData
(
psaSource
,
psaTarget
);
if
(
SUCCEEDED
(
SAFEARRAY_DestroyData
(
psaTarget
,
0
))
&&
SUCCEEDED
(
SAFEARRAY_CopyData
(
psaSource
,
psaTarget
)))
return
S_OK
;
return
E_UNEXPECTED
;
}
/************************************************************************
* SafeArrayDestroy (OLEAUT32.16)
* Deallocates all memory reserved for the SafeArray
*
* Destroy a SafeArray.
*
* PARAMS
* psa [I] Array to destroy
*
* RETURNS
* Success: S_OK. All resources used by the array are freed.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayDestroy
(
SAFEARRAY
*
psa
)
HRESULT
WINAPI
SafeArrayDestroy
(
SAFEARRAY
*
psa
)
{
HRESULT
hRes
;
TRACE
(
"(%p)
\n
"
,
psa
)
;
if
(
!
validArg
(
psa
)
)
if
(
!
psa
)
return
E_INVALIDARG
;
if
(
psa
->
cLocks
>
0
)
return
DISP_E_ARRAYISLOCKED
;
if
((
hRes
=
SafeArrayDestroyData
(
psa
))
==
S_OK
)
if
((
hRes
=
SafeArrayDestroyDescriptor
(
psa
))
==
S_OK
)
return
S_OK
;
return
E_UNEXPECTED
;
/* UNDOC error condition */
/* Native doesn't check to see if the free succeeds */
SafeArrayDestroyData
(
psa
);
SafeArrayDestroyDescriptor
(
psa
);
return
S_OK
;
}
/************************************************************************
* SafeArrayCopy (OLEAUT32.27)
* Make a dupplicate of a SafeArray
*
* Make a duplicate of a SafeArray.
*
* PARAMS
* psa [I] Source for copy
* ppsaOut [O] Destination for new copy
*
* RETURNS
* Success: S_OK. ppsaOut contains a copy of the array.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayCopy
(
SAFEARRAY
*
psa
,
SAFEARRAY
**
ppsaOut
)
HRESULT
WINAPI
SafeArrayCopy
(
SAFEARRAY
*
psa
,
SAFEARRAY
**
ppsaOut
)
{
HRESULT
hRes
;
DWORD
dAllocSize
;
ULONG
ulWholeArraySize
;
/* size of the thing */
if
(
!
validArg
(
psa
))
return
E_INVALIDARG
;
HRESULT
hRet
;
if
((
hRes
=
SafeArrayAllocDescriptor
(
psa
->
cDims
,
ppsaOut
))
==
S_OK
){
TRACE
(
"(%p,%p)
\n
"
,
psa
,
ppsaOut
);
/* Duplicate the SAFEARRAY struct */
memcpy
(
*
ppsaOut
,
psa
,
sizeof
(
*
psa
)
+
(
sizeof
(
*
(
psa
->
rgsabound
))
*
(
psa
->
cDims
-
1
)));
if
(
!
ppsaOut
)
return
E_INVALIDARG
;
/* If the features that use storage before the SAFEARRAY struct are
* enabled, also copy this memory range. Flags have been copied already.
*/
if
(
psa
->
fFeatures
&
(
FADF_HAVEIID
|
FADF_HAVEVARTYPE
))
memcpy
(((
GUID
*
)
*
ppsaOut
)
-
1
,
((
GUID
*
)
psa
)
-
1
,
sizeof
(
GUID
));
*
ppsaOut
=
NULL
;
/* Copy the IRecordInfo* reference */
if
(
psa
->
fFeatures
&
FADF_RECORD
)
{
IRecordInfo
*
ri
;
if
(
!
psa
)
return
S_OK
;
/* Handles copying of NULL arrays */
ri
=
((
IRecordInfo
**
)
psa
)[
-
1
];
if
(
ri
)
{
((
IRecordInfo
**
)
*
ppsaOut
)[
-
1
]
=
ri
;
IRecordInfo_AddRef
(
ri
);
}
if
(
psa
->
fFeatures
&
(
FADF_RECORD
|
FADF_HAVEIID
|
FADF_HAVEVARTYPE
))
{
VARTYPE
vt
;
if
(
FAILED
(
SafeArrayGetVartype
(
psa
,
&
vt
)))
hRet
=
E_UNEXPECTED
;
else
hRet
=
SafeArrayAllocDescriptorEx
(
vt
,
psa
->
cDims
,
ppsaOut
);
}
else
{
hRet
=
SafeArrayAllocDescriptor
(
psa
->
cDims
,
ppsaOut
);
if
(
SUCCEEDED
(
hRet
))
{
(
*
ppsaOut
)
->
fFeatures
=
psa
->
fFeatures
&
~
FADF_CREATEVECTOR
;
(
*
ppsaOut
)
->
cbElements
=
psa
->
cbElements
;
}
}
(
*
ppsaOut
)
->
pvData
=
NULL
;
/* do not point to the same data area */
/* make sure the new safe array doesn't have the FADF_CREATEVECTOR flag,
because the data has not been allocated with the descriptor. */
(
*
ppsaOut
)
->
fFeatures
&=
~
FADF_CREATEVECTOR
;
/* Get the allocated memory size for source and allocate it for target */
ulWholeArraySize
=
getArraySize
(
psa
);
/* Number of item in SA */
dAllocSize
=
ulWholeArraySize
*
psa
->
cbElements
;
if
(
SUCCEEDED
(
hRet
))
{
/* Copy dimension bounds */
memcpy
((
*
ppsaOut
)
->
rgsabound
,
psa
->
rgsabound
,
psa
->
cDims
*
sizeof
(
SAFEARRAYBOUND
));
(
*
ppsaOut
)
->
pvData
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
dAllocSize
);
if
(
(
*
ppsaOut
)
->
pvData
!=
NULL
)
{
/* HeapAlloc succeed */
(
*
ppsaOut
)
->
pvData
=
SAFEARRAY_Malloc
(
SAFEARRAY_GetCellCount
(
psa
)
*
psa
->
cbElements
);
if
(
(
hRes
=
duplicateData
(
psa
,
*
ppsaOut
))
!=
S_OK
)
{
/* E_OUTOFMEMORY */
HeapFree
(
GetProcessHeap
(),
0
,
(
*
ppsaOut
)
->
pvData
);
(
*
ppsaOut
)
->
pvData
=
NULL
;
SafeArrayDestroyDescriptor
(
*
ppsaOut
);
return
hRes
;
}
if
((
*
ppsaOut
)
->
pvData
)
{
hRet
=
SAFEARRAY_CopyData
(
psa
,
*
ppsaOut
)
;
if
(
SUCCEEDED
(
hRet
))
return
hRet
;
}
else
{
/* failed to allocate or dupplicate... */
SafeArrayDestroyDescriptor
(
*
ppsaOut
);
return
E_UNEXPECTED
;
/* UNDOC error condition */
SAFEARRAY_Free
((
*
ppsaOut
)
->
pvData
);
}
}
else
{
/* failed to allocate mem for descriptor */
return
E_OUTOFMEMORY
;
/* UNDOC error condiftion */
SafeArrayDestroyDescriptor
(
*
ppsaOut
);
}
return
S_OK
;
}
/************************************************************************
* SafeArrayCreateVector (OLEAUT32.411)
* Creates a one dimension safearray where the data is next to the
* SAFEARRAY structure.
*/
SAFEARRAY
*
WINAPI
SafeArrayCreateVector
(
VARTYPE
vt
,
LONG
lLbound
,
ULONG
cElements
)
{
SAFEARRAY
*
psa
;
BYTE
*
ptr
;
TRACE
(
"%d, %ld, %ld
\n
"
,
vt
,
lLbound
,
cElements
);
/* Validate supported VARTYPE */
if
(
(
vt
>=
LAST_VARTYPE
)
||
(
VARTYPE_SIZE
[
vt
]
==
VARTYPE_NOT_SUPPORTED
)
)
return
NULL
;
/* Allocate memory for the array descriptor and data contiguously */
ptr
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
(
sizeof
(
GUID
)
+
sizeof
(
*
psa
)
+
(
VARTYPE_SIZE
[
vt
]
*
cElements
)));
if
(
!
ptr
)
return
NULL
;
psa
=
(
SAFEARRAY
*
)(
ptr
+
sizeof
(
GUID
));
/* setup data members... */
psa
->
cDims
=
1
;
/* always and forever */
psa
->
fFeatures
=
getFeatures
(
vt
)
|
FADF_CREATEVECTOR
;
/* undocumented flag used by Microsoft */
psa
->
cLocks
=
0
;
psa
->
pvData
=
(
BYTE
*
)
psa
+
sizeof
(
*
psa
);
psa
->
cbElements
=
VARTYPE_SIZE
[
vt
];
psa
->
rgsabound
[
0
].
cElements
=
cElements
;
psa
->
rgsabound
[
0
].
lLbound
=
lLbound
;
return
(
psa
);
*
ppsaOut
=
NULL
;
return
hRet
;
}
/************************************************************************
* SafeArrayRedim (OLEAUT32.40)
* Changes the caracteristics of the last dimension of the SafeArray
*
* Changes the characteristics of the last dimension of a SafeArray
*
* PARAMS
* psa [I] Array to change
* psabound [I] New bound details for the last dimension
*
* RETURNS
* Success: S_OK. psa is updated to reflect the new bounds.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayRedim
(
SAFEARRAY
*
psa
,
SAFEARRAYBOUND
*
psaboundNew
)
HRESULT
WINAPI
SafeArrayRedim
(
SAFEARRAY
*
psa
,
SAFEARRAYBOUND
*
psabound
)
{
LONG
lDelta
;
/* hold difference in size */
USHORT
cDims
=
1
;
/* dims counter */
SAFEARRAYBOUND
*
oldBounds
;
if
(
!
validArg
(
psa
)
)
TRACE
(
"(%p,%p)
\n
"
,
psa
,
psabound
);
if
(
!
psa
||
psa
->
fFeatures
&
FADF_FIXEDSIZE
||
!
psabound
||
!
psabound
->
cElements
)
return
E_INVALIDARG
;
if
(
psa
->
cLocks
>
0
)
if
(
psa
->
cLocks
>
0
)
return
DISP_E_ARRAYISLOCKED
;
if
(
psa
->
fFeatures
&
FADF_FIXEDSIZE
)
return
E_INVALIDARG
;
if
(
SafeArrayLock
(
psa
)
==
E_UNEXPECTED
)
return
E_UNEXPECTED
;
/* UNDOC error condition */
/* find the delta in number of array spot to apply to the new array */
lDelta
=
psaboundNew
->
cElements
-
psa
->
rgsabound
[
0
].
cElements
;
for
(;
cDims
<
psa
->
cDims
;
cDims
++
)
/* delta in number of spot implied by modifying the last dimension */
lDelta
*=
psa
->
rgsabound
[
cDims
].
cElements
;
if
(
FAILED
(
SafeArrayLock
(
psa
)))
return
E_UNEXPECTED
;
TRACE
(
"elements=%ld, Lbound=%ld (delta=%ld)
\n
"
,
psaboundNew
->
cElements
,
psaboundNew
->
lLbound
,
lDelta
);
oldBounds
=
&
psa
->
rgsabound
[
psa
->
cDims
-
1
];
oldBounds
->
lLbound
=
psabound
->
lLbound
;
if
(
lDelta
==
0
)
{
;
/* same size, maybe a change of lLbound, just set it */
if
(
psabound
->
cElements
!=
oldBounds
->
cElements
)
{
if
(
psabound
->
cElements
<
oldBounds
->
cElements
)
{
/* Shorten the final dimension. */
ULONG
ulStartCell
=
psa
->
cDims
==
1
?
0
:
SAFEARRAY_GetDimensionCells
(
psa
,
psa
->
cDims
-
1
);
}
else
/* need to enlarge (lDelta +) reduce (lDelta -) */
if
(
!
resizeSafeArray
(
psa
,
lDelta
))
return
E_UNEXPECTED
;
/* UNDOC error condition */
ulStartCell
+=
psabound
->
cElements
;
SAFEARRAY_DestroyData
(
psa
,
ulStartCell
);
}
else
{
/* Lengthen the final dimension */
ULONG
ulOldSize
,
ulNewSize
;
PVOID
pvNewData
;
ulOldSize
=
SAFEARRAY_GetCellCount
(
psa
);
ulNewSize
=
(
ulOldSize
/
oldBounds
->
cElements
)
*
psabound
->
cElements
;
if
(
ulOldSize
==
SAFEARRAY_INVALID_CELLS
||
!
(
pvNewData
=
SAFEARRAY_Malloc
(
ulNewSize
)))
{
SafeArrayUnlock
(
psa
);
return
E_UNEXPECTED
;
}
/* the only modifyable dimension sits in [0] as the dimensions were reversed
at array creation time... */
psa
->
rgsabound
[
0
].
cElements
=
psaboundNew
->
cElements
;
psa
->
rgsabound
[
0
].
lLbound
=
psaboundNew
->
lLbound
;
memcpy
(
pvNewData
,
psa
->
pvData
,
ulOldSize
);
SAFEARRAY_Free
(
psa
->
pvData
);
psa
->
pvData
=
pvNewData
;
}
oldBounds
->
cElements
=
psabound
->
cElements
;
}
return
SafeArrayUnlock
(
psa
);
SafeArrayUnlock
(
psa
);
return
S_OK
;
}
/************************************************************************
* NOT WINDOWS API - SafeArray* Utility functions
************************************************************************/
/************************************************************************
* Used to validate the SAFEARRAY type of arg
* SafeArrayGetVartype (OLEAUT32.77)
*
* Get the type of the items in a SafeArray.
*
* PARAMS
* psa [I] Array to get the type from
* pvt [O] Destination for the type
*
* RETURNS
* Success: S_OK. pvt contains the type of the items.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
static
BOOL
validArg
(
SAFEARRAY
*
psa
)
HRESULT
WINAPI
SafeArrayGetVartype
(
SAFEARRAY
*
psa
,
VARTYPE
*
pvt
)
{
SAFEARRAYBOUND
*
sab
;
LONG
psaSize
=
0
;
LONG
descSize
=
0
;
LONG
fullSize
=
0
;
/*
* Let's check for the null pointer just in case.
*/
if
(
psa
==
NULL
)
return
FALSE
;
/* Check whether the size of the chunk makes sense... That's the only thing
I can think of now... */
TRACE
(
"(%p,%p)
\n
"
,
psa
,
pvt
);
psaSize
=
HeapSize
(
GetProcessHeap
(),
0
,
((
IID
*
)
psa
)
-
1
);
if
(
psaSize
==
-
1
)
/* uh, foreign heap. Better don't mess with it ! */
return
TRUE
;
/* size of the descriptor when the SA is not created with CreateVector */
descSize
=
sizeof
(
GUID
)
+
sizeof
(
*
psa
)
+
(
sizeof
(
*
sab
)
*
(
psa
->
cDims
-
1
));
if
(
!
psa
||
!
pvt
)
return
E_INVALIDARG
;
/* size of the descriptor + data when created with CreateVector */
fullSize
=
sizeof
(
*
psa
)
+
(
psa
->
cbElements
*
psa
->
rgsabound
[
0
].
cElements
);
if
(
psa
->
fFeatures
&
FADF_RECORD
)
*
pvt
=
VT_RECORD
;
else
if
(
psa
->
fFeatures
&
FADF_HAVEIID
)
*
pvt
=
VT_UNKNOWN
;
else
if
(
psa
->
fFeatures
&
FADF_HAVEVARTYPE
)
{
VARTYPE
vt
=
SAFEARRAY_GetHiddenDWORD
(
psa
);
*
pvt
=
vt
;
}
else
return
E_INVALIDARG
;
return
((
psaSize
>=
descSize
)
||
(
psaSize
>=
fullSize
))
;
return
S_OK
;
}
/************************************************************************
* Used to reallocate memory
* SafeArraySetRecordInfo (OLEAUT32.@)
*
* Set the record info for a SafeArray.
*
* PARAMS
* psa [I] Array to set the record info for
* pRinfo [I] Record info
*
* RETURNS
* Success: S_OK. The record info is stored with the array.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
static
BOOL
resizeSafeArray
(
SAFEARRAY
*
psa
,
LONG
lDelta
)
HRESULT
WINAPI
SafeArraySetRecordInfo
(
SAFEARRAY
*
psa
,
IRecordInfo
*
pRinfo
)
{
ULONG
ulWholeArraySize
;
/* use as multiplicator */
PVOID
pvNewBlock
=
NULL
;
IUnknown
*
punk
;
BSTR
bstr
;
ulWholeArraySize
=
getArraySize
(
psa
);
if
(
lDelta
<
0
)
{
/* array needs to be shorthen */
if
(
isPointer
(
psa
->
fFeatures
))
/* ptr that need to be released */
for
(;
lDelta
<
0
;
lDelta
++
)
{
punk
=
*
(
IUnknown
**
)
((
char
*
)
psa
->
pvData
+
((
ulWholeArraySize
+
lDelta
)
*
psa
->
cbElements
));
if
(
punk
!=
NULL
)
IUnknown_Release
(
punk
);
}
else
if
(
psa
->
fFeatures
&
FADF_BSTR
)
/* BSTR that need to be freed */
for
(;
lDelta
<
0
;
lDelta
++
)
{
bstr
=
*
(
BSTR
*
)
((
char
*
)
psa
->
pvData
+
((
ulWholeArraySize
+
lDelta
)
*
psa
->
cbElements
));
if
(
bstr
!=
NULL
)
SysFreeString
(
bstr
);
}
else
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
for
(;
lDelta
<
0
;
lDelta
++
)
{
VariantClear
((
VARIANT
*
)((
char
*
)
psa
->
pvData
+
((
ulWholeArraySize
+
lDelta
)
*
psa
->
cbElements
)));
}
}
if
(
!
(
psa
->
fFeatures
&
FADF_CREATEVECTOR
))
{
/* Ok now, if we are enlarging the array, we *MUST* move the whole block
pointed to by pvData. If we are shorthening the array, this move is
optional but we do it anyway becuase the benefit is that we are
releasing to the system the unused memory */
if
((
pvNewBlock
=
HeapReAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
psa
->
pvData
,
(
ulWholeArraySize
+
lDelta
)
*
psa
->
cbElements
))
==
NULL
)
return
FALSE
;
/* TODO If we get here it means:
SHRINK situation : we've deleted the undesired
data and did not release the memory
GROWING situation: we've been unable to grow the array
*/
}
else
{
/* Allocate a new block, because the previous data has been allocated with
the descriptor in SafeArrayCreateVector function. */
IRecordInfo
**
dest
=
(
IRecordInfo
**
)
psa
;
if
((
pvNewBlock
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
ulWholeArraySize
*
psa
->
cbElements
))
==
NULL
)
return
FALSE
;
TRACE
(
"(%p,%p)
\n
"
,
psa
,
pRinfo
);
if
(
!
psa
||
!
(
psa
->
fFeatures
&
FADF_RECORD
))
return
E_INVALIDARG
;
psa
->
fFeatures
&=
~
FADF_CREATEVECTOR
;
}
/* reassign to the new block of data */
psa
->
pvData
=
pvNewBlock
;
return
TRUE
;
}
if
(
pRinfo
)
IRecordInfo_AddRef
(
pRinfo
);
/************************************************************************
* Used to set the fFeatures data member of the SAFEARRAY structure.
*/
static
INT
getFeatures
(
VARTYPE
vt
)
{
switch
(
vt
)
{
case
VT_BSTR
:
return
FADF_BSTR
;
case
VT_UNKNOWN
:
return
FADF_UNKNOWN
;
case
VT_DISPATCH
:
return
FADF_DISPATCH
;
case
VT_VARIANT
:
return
FADF_VARIANT
;
}
return
0
;
}
if
(
dest
[
-
1
])
IRecordInfo_Release
(
dest
[
-
1
]);
/************************************************************************
* Used to figure out if the fFeatures data member of the SAFEARRAY
* structure contain any information about the type of data stored...
*/
static
BOOL
isPointer
(
USHORT
feature
)
{
switch
(
feature
)
{
case
FADF_UNKNOWN
:
return
TRUE
;
/* those are pointers */
case
FADF_DISPATCH
:
return
TRUE
;
}
return
FALSE
;
dest
[
-
1
]
=
pRinfo
;
return
S_OK
;
}
/************************************************************************
* Used to calculate the displacement when accessing or modifying
* safearray data set.
*
* Parameters: - LONG *coor is the desired location in the multidimension
* table. Ex for a 3 dim table: coor[] = {1,2,3};
* - ULONG *mat is the format of the table. Ex for a 3 dim
* table mat[] = {4,4,4};
* - USHORT dim is the number of dimension of the SafeArray
* SafeArrayGetRecordInfo (OLEAUT32.@)
*
* Get the record info from a SafeArray.
*
* PARAMS
* psa [I] Array to get the record info from
* pRinfo [O] Destination for the record info
*
* RETURNS
* Success: S_OK. pRinfo contains the record info, or NULL if there was none.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
static
ULONG
calcDisplacement
(
LONG
*
coor
,
SAFEARRAYBOUND
*
mat
,
LONG
dim
)
HRESULT
WINAPI
SafeArrayGetRecordInfo
(
SAFEARRAY
*
psa
,
IRecordInfo
**
pRinfo
)
{
ULONG
res
=
0
;
LONG
iterDim
;
IRecordInfo
**
src
=
(
IRecordInfo
**
)
psa
;
TRACE
(
"
dims is %ld
\n
"
,
dim
);
TRACE
(
"
(%p,%p)
\n
"
,
psa
,
pRinfo
);
for
(
iterDim
=
dim
-
1
;
iterDim
>=
0
;
iterDim
--
)
{
TRACE
(
"%ld: lbound is %ld, adding %ld
\n
"
,
iterDim
,
mat
[
dim
-
iterDim
-
1
].
lLbound
,(
coor
[
iterDim
]
-
mat
[
dim
-
iterDim
-
1
].
lLbound
));
res
+=
(
coor
[
iterDim
]
-
mat
[
dim
-
iterDim
-
1
].
lLbound
);
if
(
!
psa
||
!
pRinfo
||
!
(
psa
->
fFeatures
&
FADF_RECORD
))
return
E_INVALIDARG
;
if
(
iterDim
>
0
)
res
*=
mat
[
dim
-
iterDim
].
cElements
;
}
*
pRinfo
=
src
[
-
1
];
TRACE
(
"SafeArray: calculated displacement is %lu.
\n
"
,
res
);
return
(
res
);
if
(
*
pRinfo
)
IRecordInfo_AddRef
(
*
pRinfo
);
return
S_OK
;
}
/************************************************************************
* Method used to validate the coordinate received in Put and Get
* methods.
* SafeArraySetIID (OLEAUT32.@)
*
* Set the IID for a SafeArray.
*
* PARAMS
* psa [I] Array to set the IID from
* guid [I] IID
*
* RETURNS
* Success: S_OK. The IID is stored with the array
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
static
BOOL
validCoordinate
(
LONG
*
coor
,
SAFEARRAY
*
psa
)
HRESULT
WINAPI
SafeArraySetIID
(
SAFEARRAY
*
psa
,
REFGUID
guid
)
{
INT
iter
=
0
;
LONG
lUBound
;
LONG
lLBound
;
HRESULT
hRes
;
if
(
!
psa
->
cDims
)
{
FIXME
(
"no dims?
\n
"
);
return
FALSE
;
}
for
(;
iter
<
psa
->
cDims
;
iter
++
)
{
TRACE
(
"coor[%d]=%ld
\n
"
,
iter
,
coor
[
iter
]);
if
((
hRes
=
SafeArrayGetLBound
(
psa
,
(
iter
+
1
),
&
lLBound
))
!=
S_OK
)
{
FIXME
(
"No lbound?
\n
"
);
return
FALSE
;
}
if
((
hRes
=
SafeArrayGetUBound
(
psa
,
(
iter
+
1
),
&
lUBound
))
!=
S_OK
)
{
FIXME
(
"No ubound?
\n
"
);
return
FALSE
;
}
if
(
lLBound
>
lUBound
)
{
FIXME
(
"lbound larger than ubound?
\n
"
);
return
FALSE
;
}
if
((
coor
[
iter
]
<
lLBound
)
||
(
coor
[
iter
]
>
lUBound
))
{
FIXME
(
"coordinate %ld not within %ld - %ld
\n
"
,
coor
[
iter
],
lLBound
,
lUBound
);
return
FALSE
;
}
}
return
TRUE
;
}
GUID
*
dest
=
(
GUID
*
)
psa
;
/************************************************************************
* Method used to calculate the number of cells of the SA
*/
static
ULONG
getArraySize
(
SAFEARRAY
*
psa
)
{
USHORT
cCount
;
ULONG
ulWholeArraySize
=
1
;
TRACE
(
"(%p,%s)
\n
"
,
psa
,
debugstr_guid
(
guid
));
for
(
cCount
=
0
;
cCount
<
psa
->
cDims
;
cCount
++
)
/* foreach dimensions... */
ulWholeArraySize
*=
psa
->
rgsabound
[
cCount
].
cElements
;
if
(
!
psa
||
!
guid
||
!
(
psa
->
fFeatures
&
FADF_HAVEIID
))
return
E_INVALIDARG
;
return
ulWholeArraySize
;
dest
[
-
1
]
=
*
guid
;
return
S_OK
;
}
/************************************************************************
* Method used to handle data space dupplication for Copy32 and CopyData32
* SafeArrayGetIID (OLEAUT32.@)
*
* Get the IID from a SafeArray.
*
* PARAMS
* psa [I] Array to get the ID from
* pGuid [O] Destination for the IID
*
* RETURNS
* Success: S_OK. pRinfo contains the IID, or NULL if there was none.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
static
HRESULT
duplicateData
(
SAFEARRAY
*
psa
,
SAFEARRAY
*
ppsaOut
)
HRESULT
WINAPI
SafeArrayGetIID
(
SAFEARRAY
*
psa
,
GUID
*
pGuid
)
{
ULONG
ulWholeArraySize
;
/* size of the thing */
LONG
lDelta
;
ulWholeArraySize
=
getArraySize
(
psa
);
/* Number of item in SA */
SafeArrayLock
(
ppsaOut
);
if
(
isPointer
(
psa
->
fFeatures
)
)
{
/* If datatype is object increment
object's reference count */
IUnknown
*
punk
;
for
(
lDelta
=
0
;
lDelta
<
ulWholeArraySize
;
lDelta
++
)
{
punk
=
*
(
IUnknown
**
)((
char
*
)
psa
->
pvData
+
(
lDelta
*
psa
->
cbElements
));
if
(
punk
!=
NULL
)
IUnknown_AddRef
(
punk
);
}
/* Copy the source array data into target array */
memcpy
(
ppsaOut
->
pvData
,
psa
->
pvData
,
ulWholeArraySize
*
psa
->
cbElements
);
}
else
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
/* if datatype is BSTR allocate
the BSTR in the new array */
BSTR
pbstrReAllocStr
=
NULL
;
GUID
*
src
=
(
GUID
*
)
psa
;
for
(
lDelta
=
0
;
lDelta
<
ulWholeArraySize
;
lDelta
++
)
{
if
((
pbstrReAllocStr
=
SYSDUPSTRING
(
*
(
BSTR
*
)((
char
*
)
psa
->
pvData
+
(
lDelta
*
psa
->
cbElements
))))
==
NULL
)
{
TRACE
(
"(%p,%p)
\n
"
,
psa
,
pGuid
);
SafeArrayUnlock
(
ppsaOut
);
return
E_OUTOFMEMORY
;
}
*
((
BSTR
*
)((
char
*
)
ppsaOut
->
pvData
+
(
lDelta
*
psa
->
cbElements
)))
=
pbstrReAllocStr
;
}
}
else
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
for
(
lDelta
=
0
;
lDelta
<
ulWholeArraySize
;
lDelta
++
)
{
VariantCopy
((
VARIANT
*
)((
char
*
)
ppsaOut
->
pvData
+
(
lDelta
*
psa
->
cbElements
)),
(
VARIANT
*
)((
char
*
)
psa
->
pvData
+
(
lDelta
*
psa
->
cbElements
)));
}
if
(
!
psa
||
!
pGuid
||
!
(
psa
->
fFeatures
&
FADF_HAVEIID
))
return
E_INVALIDARG
;
}
else
{
/* Simply copy the source array data into target array */
memcpy
(
ppsaOut
->
pvData
,
psa
->
pvData
,
ulWholeArraySize
*
psa
->
cbElements
);
}
SafeArrayUnlock
(
ppsaOut
);
*
pGuid
=
src
[
-
1
];
return
S_OK
;
}
/************************************************************************
* SafeArrayGetVartype (OLEAUT32.77)
* Returns the VARTYPE stored in the given safearray
* VectorFromBstr (OLEAUT32.@)
*
* Create a SafeArray Vector from the bytes of a BSTR.
*
* PARAMS
* bstr [I] String to get bytes from
* ppsa [O] Destination for the array
*
* RETURNS
* Success: S_OK. ppsa contains the strings bytes as a VT_UI1 array.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayGetVartype
(
SAFEARRAY
*
psa
,
VARTYPE
*
pvt
)
HRESULT
WINAPI
VectorFromBstr
(
BSTR
bstr
,
SAFEARRAY
**
ppsa
)
{
if
(
psa
->
fFeatures
&
FADF_HAVEVARTYPE
)
{
/* VT tag @ negative offset 4 in the array descriptor */
*
pvt
=
((
DWORD
*
)
psa
)[
-
1
];
return
S_OK
;
}
if
(
psa
->
fFeatures
&
FADF_RECORD
)
{
*
pvt
=
VT_RECORD
;
return
S_OK
;
}
SAFEARRAYBOUND
sab
;
if
(
psa
->
fFeatures
&
FADF_BSTR
)
{
*
pvt
=
VT_BSTR
;
return
S_OK
;
}
TRACE
(
"(%p,%p)
\n
"
,
bstr
,
ppsa
);
if
(
!
ppsa
)
return
E_INVALIDARG
;
if
(
psa
->
fFeatures
&
FADF_UNKNOWN
)
{
*
pvt
=
VT_UNKNOWN
;
return
S_OK
;
}
sab
.
lLbound
=
0
;
sab
.
cElements
=
SysStringByteLen
(
bstr
);
if
(
psa
->
fFeatures
&
FADF_DISPATCH
)
{
*
pvt
=
VT_UNKNOWN
;
/* Yes, checked against windows */
return
S_OK
;
}
*
ppsa
=
SAFEARRAY_Create
(
VT_UI1
,
1
,
&
sab
,
0
);
if
(
psa
->
fFeatures
&
FADF_VARIANT
)
{
*
pvt
=
VT_VARIANT
;
return
S_OK
;
}
if
(
psa
->
fFeatures
&
FADF_HAVEIID
)
if
(
*
ppsa
)
{
/* We could check the IID here, but Windows apparently does not
* do that and returns VT_UNKNOWN for VT_DISPATCH too.
*/
*
pvt
=
VT_UNKNOWN
;
memcpy
((
*
ppsa
)
->
pvData
,
bstr
,
sab
.
cElements
);
return
S_OK
;
}
WARN
(
"No vt found for safearray
\n
"
);
return
E_INVALIDARG
;
}
/************************************************************************
* SafeArraySetIID (OLEAUT32.57)
*/
HRESULT
WINAPI
SafeArraySetIID
(
SAFEARRAY
*
arr
,
REFIID
riid
)
{
IID
*
xiid
=
((
IID
*
)
arr
)
-
1
;
TRACE
(
"(%p, %s).
\n
"
,
arr
,
debugstr_guid
(
riid
));
if
(
!
arr
||
!
(
arr
->
fFeatures
&
FADF_HAVEIID
))
return
E_INVALIDARG
;
memcpy
(
xiid
,
riid
,
sizeof
(
GUID
));
return
S_OK
;
return
E_OUTOFMEMORY
;
}
/************************************************************************
* SafeArrayGetIID (OLEAUT32.67)
* BstrFromVector (OLEAUT32.@)
*
* Create a BSTR from a SafeArray.
*
* PARAMS
* psa [I] Source array
* pbstr [O] Destination for output BSTR
*
* RETURNS
* Success: S_OK. pbstr contains the arrays data.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* psa must be a 1 dimensional array of a 1 byte type.
*
* NOTES
* See SafeArray.
*/
HRESULT
WINAPI
SafeArrayGetIID
(
SAFEARRAY
*
arr
,
IID
*
riid
)
{
IID
*
xiid
=
((
IID
*
)
arr
)
-
1
;
TRACE
(
"(%p,
%s).
\n
"
,
arr
,
debugstr_guid
(
riid
)
);
HRESULT
WINAPI
BstrFromVector
(
SAFEARRAY
*
psa
,
BSTR
*
pbstr
)
{
TRACE
(
"(%p,
%p)
\n
"
,
psa
,
pbstr
);
if
(
!
arr
||
!
(
arr
->
fFeatures
&
FADF_HAVEIID
)
)
if
(
!
pbstr
)
return
E_INVALIDARG
;
memcpy
(
riid
,
xiid
,
sizeof
(
GUID
));
return
S_OK
;
}
/************************************************************************
* SafeArraySetRecordInfo (OLEAUT32.44)
*/
HRESULT
WINAPI
SafeArraySetRecordInfo
(
SAFEARRAY
*
arr
,
IRecordInfo
*
iface
)
{
LPRECORDINFO
oldiface
;
*
pbstr
=
NULL
;
if
(
!
arr
||
!
(
arr
->
fFeatures
&
FADF_RECORD
)
)
if
(
!
psa
||
psa
->
cbElements
!=
1
||
psa
->
cDims
!=
1
)
return
E_INVALIDARG
;
oldiface
=
((
IRecordInfo
**
)
arr
)[
-
1
];
if
(
oldiface
)
IRecordInfo_Release
(
oldiface
);
((
IRecordInfo
**
)
arr
)[
-
1
]
=
iface
;
if
(
iface
)
IRecordInfo_AddRef
(
iface
);
return
S_OK
;
}
/************************************************************************
* SafeArrayGetRecordInfo (OLEAUT32.45)
*/
HRESULT
WINAPI
SafeArrayGetRecordInfo
(
SAFEARRAY
*
arr
,
IRecordInfo
**
iface
)
{
if
(
!
arr
||
!
(
arr
->
fFeatures
&
FADF_RECORD
))
return
E_INVALIDARG
;
*
iface
=
((
IRecordInfo
**
)
arr
)[
-
1
];
if
(
*
iface
)
IRecordInfo_AddRef
(
*
iface
);
*
pbstr
=
SysAllocStringByteLen
(
psa
->
pvData
,
psa
->
rgsabound
[
0
].
cElements
);
if
(
!*
pbstr
)
return
E_OUTOFMEMORY
;
return
S_OK
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment