1 /*************************************************************************
3 * SafeArray Implementation
5 * This file contains the implementation of the SafeArray interface.
7 * Copyright 1999 Sylvain St-Germain
18 #include "wine/obj_base.h"
20 /* Localy used methods */
22 endOfDim(LONG
*coor
, SAFEARRAYBOUND
*mat
, LONG dim
, LONG realDim
);
25 calcDisplacement(LONG
*coor
, SAFEARRAYBOUND
*mat
, LONG dim
);
28 isPointer(USHORT feature
);
31 getFeatures(VARTYPE vt
);
34 validCoordinate(LONG
*coor
, SAFEARRAY
*psa
);
37 resizeSafeArray(SAFEARRAY
*psa
, LONG lDelta
);
40 validArg(SAFEARRAY
*psa
);
43 getArraySize(SAFEARRAY
*psa
);
46 duplicateData(SAFEARRAY
*psa
, SAFEARRAY
**ppsaOut
);
48 /* Association between VARTYPE and their size.
49 A size of zero is defined for the unsupported types. */
51 #define VARTYPE_NOT_SUPPORTED 0
52 static ULONG VARTYPE_SIZE
[43] =
54 /* this is taken from wtypes.h. Only [S]es are supported by the SafeArray */
55 VARTYPE_NOT_SUPPORTED
, /* VT_EMPTY [V] [P] nothing */
56 VARTYPE_NOT_SUPPORTED
, /* VT_NULL [V] [P] SQL style Nul */
57 2, /* VT_I2 [V][T][P][S] 2 byte signed int */
58 4, /* VT_I4 [V][T][P][S] 4 byte signed int */
59 4, /* VT_R4 [V][T][P][S] 4 byte real */
60 8, /* VT_R8 [V][T][P][S] 8 byte real */
61 8, /* VT_CY [V][T][P][S] currency */
62 8, /* VT_DATE [V][T][P][S] date */
63 4, /* VT_BSTR [V][T][P][S] OLE Automation string*/
64 4, /* VT_DISPATCH [V][T][P][S] IDispatch * */
65 4, /* VT_ERROR [V][T] [S] SCODE */
66 4, /* VT_BOOL [V][T][P][S] True=-1, False=0*/
67 24, /* VT_VARIANT [V][T][P][S] VARIANT * */
68 4, /* VT_UNKNOWN [V][T] [S] IUnknown * */
69 16, /* VT_DECIMAL [V][T] [S] 16 byte fixed point */
70 VARTYPE_NOT_SUPPORTED
, /* VT_I1 [T] signed char */
71 1, /* VT_UI1 [V][T][P][S] unsigned char */
72 VARTYPE_NOT_SUPPORTED
, /* VT_UI2 [T][P] unsigned short */
73 VARTYPE_NOT_SUPPORTED
, /* VT_UI4 [T][P] unsigned short */
74 VARTYPE_NOT_SUPPORTED
, /* VT_I8 [T][P] signed 64-bit int */
75 VARTYPE_NOT_SUPPORTED
, /* VT_UI8 [T][P] unsigned 64-bit int */
76 VARTYPE_NOT_SUPPORTED
, /* VT_INT [T] signed machine int */
77 VARTYPE_NOT_SUPPORTED
, /* VT_UINT [T] unsigned machine int */
78 VARTYPE_NOT_SUPPORTED
, /* VT_VOID [T] C style void */
79 VARTYPE_NOT_SUPPORTED
, /* VT_HRESULT [T] Standard return type */
80 VARTYPE_NOT_SUPPORTED
, /* VT_PTR [T] pointer type */
81 VARTYPE_NOT_SUPPORTED
, /* VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)*/
82 VARTYPE_NOT_SUPPORTED
, /* VT_CARRAY [T] C style array */
83 VARTYPE_NOT_SUPPORTED
, /* VT_USERDEFINED [T] user defined type */
84 VARTYPE_NOT_SUPPORTED
, /* VT_LPSTR [T][P] null terminated string */
85 VARTYPE_NOT_SUPPORTED
, /* VT_LPWSTR [T][P] wide null term string */
86 VARTYPE_NOT_SUPPORTED
, /* VT_FILETIME [P] FILETIME */
87 VARTYPE_NOT_SUPPORTED
, /* VT_BLOB [P] Length prefixed bytes */
88 VARTYPE_NOT_SUPPORTED
, /* VT_STREAM [P] Name of stream follows */
89 VARTYPE_NOT_SUPPORTED
, /* VT_STORAGE [P] Name of storage follows */
90 VARTYPE_NOT_SUPPORTED
, /* VT_STREAMED_OBJECT[P] Stream contains an object*/
91 VARTYPE_NOT_SUPPORTED
, /* VT_STORED_OBJECT [P] Storage contains object*/
92 VARTYPE_NOT_SUPPORTED
, /* VT_BLOB_OBJECT [P] Blob contains an object*/
93 VARTYPE_NOT_SUPPORTED
, /* VT_CF [P] Clipboard format */
94 VARTYPE_NOT_SUPPORTED
, /* VT_CLSID [P] A Class ID */
95 VARTYPE_NOT_SUPPORTED
, /* VT_VECTOR [P] simple counted array */
96 VARTYPE_NOT_SUPPORTED
, /* VT_ARRAY [V] SAFEARRAY* */
97 VARTYPE_NOT_SUPPORTED
/* VT_BYREF [V] void* for local use */
100 /*************************************************************************
101 * Allocate the appropriate amount of memory for the SafeArray descriptor
103 HRESULT WINAPI
SafeArrayAllocDescriptor(
110 /* SAFEARRAY + SAFEARRAYBOUND * (cDims -1) ( -1 because there is already one
111 ( in SAFEARRAY struct */
112 allocSize
= sizeof(**ppsaOut
) + (sizeof(*sab
) * (cDims
-1));
114 /* Allocate memory for SAFEARRAY struc */
115 if(( (*ppsaOut
)=HeapAlloc(
116 GetProcessHeap(), HEAP_ZERO_MEMORY
, allocSize
)) == NULL
){
117 return(E_UNEXPECTED
);
119 TRACE(ole
,"SafeArray: %lu bytes allocated for descriptor.\n", allocSize
);
124 /*************************************************************************
125 * Allocate the appropriate amount of data for the SafeArray data
127 HRESULT WINAPI
SafeArrayAllocData(
130 ULONG ulWholeArraySize
; /* to store the size of the whole thing */
135 ulWholeArraySize
= getArraySize(psa
);
137 /* Allocate memory for the data itself */
138 if((psa
->pvData
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
139 psa
->cbElements
*ulWholeArraySize
)) == NULL
)
140 return(E_UNEXPECTED
);
142 TRACE(ole
, "SafeArray: %lu bytes allocated for data at %p (%lu objects).\n",
143 psa
->cbElements
*ulWholeArraySize
, psa
->pvData
, ulWholeArraySize
);
148 /*************************************************************************
149 * Create a SafeArray object by encapsulating AllocDescriptor and AllocData
151 SAFEARRAY
* WINAPI
SafeArrayCreate(
154 SAFEARRAYBOUND
*rgsabound
)
160 /* Validate supported VARTYPE */
161 if ( VARTYPE_SIZE
[vt
] == VARTYPE_NOT_SUPPORTED
)
164 /* Allocate memory for the array descriptor */
165 if( FAILED( hRes
= SafeArrayAllocDescriptor(cDims
, &psa
)))
168 /* setup data members... */
170 psa
->fFeatures
= getFeatures(vt
);
173 psa
->cbElements
= VARTYPE_SIZE
[vt
];
175 /* Invert the bounds ... */
176 for(cDim
=0; cDim
< psa
->cDims
; cDim
++) {
177 psa
->rgsabound
[cDim
].cElements
= rgsabound
[psa
->cDims
-cDim
-1].cElements
;
178 psa
->rgsabound
[cDim
].lLbound
= rgsabound
[psa
->cDims
-cDim
-1].lLbound
;
181 /* allocate memory for the data... */
182 if( FAILED( hRes
= SafeArrayAllocData(psa
))) {
183 SafeArrayDestroyDescriptor(psa
);
190 /*************************************************************************
191 * Frees the memory associated with the descriptor.
193 HRESULT WINAPI
SafeArrayDestroyDescriptor(
196 /* Check for lockness before to free... */
198 return DISP_E_ARRAYISLOCKED
;
200 /* The array is unlocked, then, deallocate memory */
201 if(HeapFree( GetProcessHeap(), 0, psa
) == FALSE
)
208 /*************************************************************************
209 * Increment the lock counter
211 * Doc says (MSDN Library ) that psa->pvData should be made available (!= NULL)
212 * only when psa->cLocks is > 0... I don't get it since pvData is allocated
213 * before the array is locked, therefore
215 HRESULT WINAPI
SafeArrayLock(
226 /*************************************************************************
227 * Decrement the lock counter
229 HRESULT WINAPI
SafeArrayUnlock(
242 /*************************************************************************
243 * Set the data at the given coordinate
245 HRESULT WINAPI
SafeArrayPutElement(
250 ULONG stepCountInSAData
= 0; /* Number of array item to skip to get to
251 the desired one... */
252 PVOID elementStorageAddress
= NULL
; /* Adress to store the data */
253 BSTR pbstrReAllocStr
= NULL
; /* BSTR reallocated */
255 /* Validate the index given */
256 if(! validCoordinate(rgIndices
, psa
))
257 return DISP_E_BADINDEX
;
261 if( SafeArrayLock(psa
) == S_OK
) {
263 /* Figure out the number of items to skip */
264 stepCountInSAData
= calcDisplacement(rgIndices
, psa
->rgsabound
, psa
->cDims
);
266 /* Figure out the number of byte to skip ... */
267 elementStorageAddress
= psa
->pvData
+(stepCountInSAData
*psa
->cbElements
);
269 if(isPointer(psa
->fFeatures
)) { /* increment ref count for this pointer */
271 *((VOID
**)elementStorageAddress
) = *(VOID
**)pv
;
272 IUnknown_AddRef( *(IUnknown
**)pv
);
276 if(psa
->fFeatures
== FADF_BSTR
) { /* Create a new object */
278 if((pbstrReAllocStr
= SysAllocString( (OLECHAR
*)pv
)) == NULL
) {
279 SafeArrayUnlock(psa
);
280 return E_OUTOFMEMORY
;
282 *((BSTR
*)elementStorageAddress
) = pbstrReAllocStr
;
284 } else /* dupplicate the memory */
285 memcpy(elementStorageAddress
, pv
, SafeArrayGetElemsize(psa
) );
289 ERR(ole
, "SafeArray: Cannot lock array....\n");
290 return E_UNEXPECTED
; /* UNDOC error condition */
293 TRACE(ole
,"SafeArray: item put at adress %p.\n",elementStorageAddress
);
294 return SafeArrayUnlock(psa
);
298 /*************************************************************************
299 * Return the data element corresponding the the given coordinate
301 HRESULT WINAPI
SafeArrayGetElement(
306 ULONG stepCountInSAData
= 0; /* Number of array item to skip to get to
307 the desired one... */
308 PVOID elementStorageAddress
= NULL
; /* Adress to store the data */
309 BSTR pbstrReturnedStr
= NULL
; /* BSTR reallocated */
314 if(! validCoordinate(rgIndices
, psa
)) /* Validate the index given */
315 return(DISP_E_BADINDEX
);
317 if( SafeArrayLock(psa
) == S_OK
) {
319 /* Figure out the number of items to skip */
320 stepCountInSAData
= calcDisplacement(rgIndices
, psa
->rgsabound
, psa
->cDims
);
322 /* Figure out the number of byte to skip ... */
323 elementStorageAddress
= psa
->pvData
+(stepCountInSAData
*psa
->cbElements
);
325 if( psa
->fFeatures
== FADF_BSTR
) { /* reallocate the obj */
326 if( (pbstrReturnedStr
=
327 SysAllocString( *(OLECHAR
**)elementStorageAddress
)) == NULL
) {
328 SafeArrayUnlock(psa
);
329 return E_OUTOFMEMORY
;
331 *((BSTR
*)pv
) = pbstrReturnedStr
;
333 } else if( isPointer(psa
->fFeatures
) ) /* simply copy the pointer */
334 pv
= *((PVOID
*)elementStorageAddress
);
335 else /* copy the bytes */
336 memcpy(pv
, elementStorageAddress
, SafeArrayGetElemsize(psa
) );
339 ERR(ole
, "SafeArray: Cannot lock array....\n");
340 return E_UNEXPECTED
; /* UNDOC error condition */
343 return( SafeArrayUnlock(psa
) );
346 /*************************************************************************
347 * return the UP bound for a given array dimension
349 HRESULT WINAPI
SafeArrayGetUBound(
357 if(nDim
> psa
->cDims
)
358 return DISP_E_BADINDEX
;
360 *plUbound
= psa
->rgsabound
[nDim
].lLbound
+
361 psa
->rgsabound
[nDim
].cElements
- 1;
366 /*************************************************************************
367 * Return the LO bound for a given array dimension
369 HRESULT WINAPI
SafeArrayGetLBound(
377 if(nDim
> psa
->cDims
)
378 return DISP_E_BADINDEX
;
380 *plLbound
= psa
->rgsabound
[nDim
].lLbound
;
384 /*************************************************************************
385 * returns the number of dimension in the array
387 UINT WINAPI
SafeArrayGetDim(
393 /*************************************************************************
394 * Return the size of the element in the array
396 UINT WINAPI
SafeArrayGetElemsize(
399 return psa
->cbElements
;
402 /*************************************************************************
403 * increment the access count and return the data
405 HRESULT WINAPI
SafeArrayAccessData(
414 hRes
= SafeArrayLock(psa
);
418 (*ppvData
) = psa
->pvData
;
429 /*************************************************************************
430 * Decrement the access count
432 HRESULT WINAPI
SafeArrayUnaccessData(
438 return(SafeArrayUnlock(psa
));
441 /************************************************************************
442 * Return a pointer to the element at rgIndices
444 HRESULT WINAPI
SafeArrayPtrOfIndex(
449 ULONG stepCountInSAData
= 0; /* Number of array item to skip to get to
450 the desired one... */
455 if(! validCoordinate(rgIndices
, psa
))
456 return DISP_E_BADINDEX
;
458 /* Figure out the number of items to skip */
459 stepCountInSAData
= calcDisplacement(rgIndices
, psa
->rgsabound
, psa
->cDims
);
461 *ppvData
= psa
->pvData
+(stepCountInSAData
*psa
->cbElements
);
466 /************************************************************************
467 * Frees the memory data bloc
469 HRESULT WINAPI
SafeArrayDestroyData(
473 ULONG ulWholeArraySize
; /* count spot in array */
474 ULONG ulDataIter
; /* to iterate the data space */
482 return DISP_E_ARRAYISLOCKED
;
484 ulWholeArraySize
= getArraySize(psa
);
486 if(isPointer(psa
->fFeatures
)) { /* release the pointers */
488 for(ulDataIter
=0; ulDataIter
< ulWholeArraySize
; ulDataIter
++) {
489 punk
= *(IUnknown
**)(psa
->pvData
+(ulDataIter
*(psa
->cbElements
)));
492 IUnknown_Release(punk
);
495 } else if(psa
->fFeatures
& FADF_BSTR
) { /* deallocate the obj */
497 for(ulDataIter
=0; ulDataIter
< ulWholeArraySize
; ulDataIter
++) {
498 bstr
= *(BSTR
*)(psa
->pvData
+(ulDataIter
*(psa
->cbElements
)));
501 SysFreeString( bstr
);
505 /* check if this array is a Vector, in which case do not free the data
506 block since it has been allocated by AllocDescriptor and therefore
507 deserve to be freed by DestroyDescriptor */
508 if(!(psa
->fFeatures
& FADF_FIXEDSIZE
)) { /* Set when we do CreateVector */
510 /* free the whole chunk */
511 if((hRes
= HeapFree( GetProcessHeap(), 0, psa
->pvData
)) == 0) /*falied*/
512 return E_UNEXPECTED
; /* UNDOC error condition */
520 /************************************************************************
521 * Copy the psaSource's data block into psaTarget if dimension and size
524 HRESULT WINAPI
SafeArrayCopyData(
525 SAFEARRAY
*psaSource
,
526 SAFEARRAY
**psaTarget
)
528 USHORT cDimCount
; /* looper */
529 LONG lDelta
; /* looper */
531 ULONG ulWholeArraySize
; /* Number of item in SA */
534 if(! (validArg(psaSource
) && validArg(*psaTarget
)) )
537 if(SafeArrayGetDim(psaSource
) != SafeArrayGetDim(*psaTarget
))
540 ulWholeArraySize
= getArraySize(psaSource
);
542 /* The two arrays boundaries must be of same lenght */
543 for(cDimCount
=0;cDimCount
< psaSource
->cDims
; cDimCount
++)
544 if( psaSource
->rgsabound
[cDimCount
].cElements
!=
545 (*psaTarget
)->rgsabound
[cDimCount
].cElements
)
548 if( isPointer((*psaTarget
)->fFeatures
) ) { /* the target contains ptr
549 that must be released */
550 for(lDelta
=0;lDelta
< ulWholeArraySize
; lDelta
++) {
552 ((*psaTarget
)->pvData
+ (lDelta
* (*psaTarget
)->cbElements
));
555 IUnknown_Release(punk
);
558 } else if( (*psaTarget
)->fFeatures
& FADF_BSTR
) { /* the target contain BSTR
559 that must be freed */
560 for(lDelta
=0;lDelta
< ulWholeArraySize
; lDelta
++) {
562 *(BSTR
*)((*psaTarget
)->pvData
+ (lDelta
* (*psaTarget
)->cbElements
));
565 SysFreeString( bstr
);
569 return duplicateData(psaSource
, psaTarget
);
572 /************************************************************************
573 * Deallocates all memory reserved for the SafeArray
575 HRESULT WINAPI
SafeArrayDestroy(
584 return DISP_E_ARRAYISLOCKED
;
586 if((hRes
= SafeArrayDestroyData( psa
)) == S_OK
)
587 if((hRes
= SafeArrayDestroyDescriptor( psa
)) == S_OK
)
590 return E_UNEXPECTED
; /* UNDOC error condition */
593 /************************************************************************
594 * Make a dupplicate of a SafeArray
596 HRESULT WINAPI
SafeArrayCopy(
606 if((hRes
=SafeArrayAllocDescriptor(psa
->cDims
, ppsaOut
)) == S_OK
){
608 /* Duplicate the SAFEARRAY struc */
609 memcpy(*ppsaOut
, psa
,
610 sizeof(*psa
)+(sizeof(*(psa
->rgsabound
))*(psa
->cDims
-1)));
612 (*ppsaOut
)->pvData
= NULL
; /* do not point to the same data area */
614 /* Get the allocated memory size for source and allocate it for target */
615 dAllocSize
= HeapSize(GetProcessHeap(), 0, psa
->pvData
);
617 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dAllocSize
);
619 if( (*ppsaOut
)->pvData
!= NULL
) { /* HeapAlloc succeed */
621 if( (hRes
=duplicateData(psa
, ppsaOut
)) != S_OK
) { /* E_OUTOFMEMORY */
622 HeapFree(GetProcessHeap(), 0, (*ppsaOut
)->pvData
);
623 (*ppsaOut
)->pvData
= NULL
;
624 SafeArrayDestroyDescriptor(*ppsaOut
);
628 } else { /* failed to allocate or dupplicate... */
629 SafeArrayDestroyDescriptor(*ppsaOut
);
630 return E_UNEXPECTED
; /* UNDOC error condition */
632 } else { /* failed to allocate mem for descriptor */
633 return E_OUTOFMEMORY
; /* UNDOC error condiftion */
639 /************************************************************************
640 * Creates a one dimension safearray where the data is next to the
641 * SAFEARRAY structure.
643 SAFEARRAY
* WINAPI
SafeArrayCreateVector(
650 /* Validate supported VARTYPE */
651 if ( VARTYPE_SIZE
[vt
] == VARTYPE_NOT_SUPPORTED
)
654 /* Allocate memory for the array descriptor and data contiguously */
655 if( FAILED( psa
= HeapAlloc( GetProcessHeap(),
657 (sizeof(*psa
) + (VARTYPE_SIZE
[vt
] * cElements
))))) {
661 /* setup data members... */
662 psa
->cDims
= 1; /* always and forever */
663 psa
->fFeatures
= getFeatures(vt
) | FADF_FIXEDSIZE
;
665 psa
->pvData
= psa
+sizeof(*psa
);
666 psa
->cbElements
= VARTYPE_SIZE
[vt
];
668 psa
->rgsabound
[0].cElements
= cElements
;
669 psa
->rgsabound
[0].lLbound
= lLbound
;
674 /************************************************************************
675 * Changes the caracteristics of the last dimension of the SafeArray
677 HRESULT WINAPI
SafeArrayRedim(
679 SAFEARRAYBOUND
*psaboundNew
)
681 LONG lDelta
; /* hold difference in size */
682 USHORT cDims
=1; /* dims counter */
687 if( psa
->cLocks
> 0 )
688 return DISP_E_ARRAYISLOCKED
;
690 if( psa
->fFeatures
& FADF_FIXEDSIZE
)
693 if( SafeArrayLock(psa
)==E_UNEXPECTED
)
694 return E_UNEXPECTED
;/* UNDOC error condition */
696 /* find the delta in number of array spot to apply to the new array */
697 lDelta
= psaboundNew
->cElements
- psa
->rgsabound
[0].cElements
;
698 for(; cDims
< psa
->cDims
; cDims
++)
699 /* delta in number of spot implied by modifying the last dimension */
700 lDelta
*= psa
->rgsabound
[cDims
].cElements
;
702 if (lDelta
== 0) { ;/* same size, maybe a change of lLbound, just set it */
704 } else /* need to enlarge (lDelta +) reduce (lDelta -) */
705 if(! resizeSafeArray(psa
, lDelta
))
706 return E_UNEXPECTED
; /* UNDOC error condition */
708 /* the only modifyable dimension sits in [0] as the dimensions were reversed
709 at array creation time... */
710 psa
->rgsabound
[0].cElements
= psaboundNew
->cElements
;
711 psa
->rgsabound
[0].lLbound
= psaboundNew
->lLbound
;
713 return SafeArrayUnlock(psa
);
716 /************************************************************************
717 * NOT WINDOWS API - SafeArray* Utility functions
718 ************************************************************************/
720 /************************************************************************
721 * Used to validate the SAFEARRAY type of arg
723 static BOOL
validArg(
731 /* Check whether the size of the chunk make sens... That's the only thing
732 I can think of now... */
734 psaSize
= HeapSize(GetProcessHeap(), 0, psa
);
736 /* size of the descriptor when the SA is not created with CreateVector */
737 descSize
= sizeof(*psa
) + (sizeof(*sab
) * (psa
->cDims
-1));
739 /* size of the descriptor + data when created with CreateVector */
740 fullSize
= sizeof(*psa
) + (psa
->cbElements
* psa
->rgsabound
[0].cElements
);
742 return((psaSize
== descSize
) | (psaSize
== fullSize
));
745 /************************************************************************
746 * Used to reallocate memory
748 static BOOL
resizeSafeArray(
752 ULONG ulWholeArraySize
; /* use as multiplicator */
753 PVOID pvNewBlock
= NULL
;
757 ulWholeArraySize
= getArraySize(psa
);
759 if(lDelta
< 0) { /* array needs to be shorthen */
760 if( isPointer(psa
->fFeatures
)) /* ptr that need to be released */
761 for(;lDelta
< 0; lDelta
++) {
763 (psa
->pvData
+((ulWholeArraySize
+lDelta
)*psa
->cbElements
));
766 IUnknown_Release(punk
);
769 else if(psa
->fFeatures
& FADF_BSTR
) /* BSTR that need to be freed */
770 for(;lDelta
< 0; lDelta
++) {
772 (psa
->pvData
+((ulWholeArraySize
+lDelta
)*psa
->cbElements
));
775 SysFreeString( bstr
);
779 /* Ok now, if we are enlarging the array, we *MUST* move the whole block
780 pointed to by pvData. If we are shorthening the array, this move is
781 optional but we do it anyway becuase the benefit is that we are
782 releasing to the system the unused memory */
784 if((pvNewBlock
= HeapReAlloc(GetProcessHeap(), 0, psa
->pvData
,
785 (ulWholeArraySize
+ lDelta
) * psa
->cbElements
)) == NULL
)
786 return FALSE
; /* TODO If we get here it means:
787 SHRINK situation : we've deleted the undesired
788 data and did not release the memory
789 GROWING situation: we've been unable to grow the array
792 /* reassign to the new block of data */
793 psa
->pvData
= pvNewBlock
;
797 /************************************************************************
798 * Used to set the fFeatures data member of the SAFEARRAY structure.
800 static INT
getFeatures(
804 case VT_UNKNOWN
: return FADF_UNKNOWN
;
805 case VT_DISPATCH
: return FADF_DISPATCH
;
806 case VT_BSTR
: return FADF_BSTR
;
811 /************************************************************************
812 * Used to figure out if the fFeatures data member of the SAFEARRAY
813 * structure contain any information about the type of data stored...
815 static BOOL
isPointer(
819 case FADF_UNKNOWN
: return TRUE
; /* those are pointers */
820 case FADF_DISPATCH
: return TRUE
;
825 /************************************************************************
826 * Used to calculate the displacement when accessing or modifying
827 * safearray data set.
829 * Parameters: - LONG *coor is the desired location in the multidimension
830 * table. Ex for a 3 dim table: coor[] = {1,2,3};
831 * - ULONG *mat is the format of the table. Ex for a 3 dim
832 * table mat[] = {4,4,4};
833 * - USHORT dim is the number of dimension of the SafeArray
835 static ULONG
calcDisplacement(
843 for(iterDim
=0; iterDim
<dim
; iterDim
++)
844 /* the -mat[dim] bring coor[dim] relative to 0 for calculation */
845 res
+= ((coor
[iterDim
]-mat
[iterDim
].lLbound
) *
846 endOfDim(coor
, mat
, iterDim
+1, dim
));
848 TRACE(ole
, "SafeArray: calculated displacement is %lu.\n", res
);
852 /************************************************************************
853 * Recursivity agent for calcDisplacement method. Used within Put and
865 return (endOfDim(coor
, mat
, dim
+1, realDim
) * mat
[dim
].cElements
);
869 /************************************************************************
870 * Method used to validate the coordinate received in Put and Get
873 static BOOL
validCoordinate(
882 for(; iter
<psa
->cDims
; iter
++) {
883 if((hRes
= SafeArrayGetLBound(psa
, iter
, &lLBound
)) != S_OK
)
885 if((hRes
= SafeArrayGetUBound(psa
, iter
, &lUBound
)) != S_OK
)
888 if(lLBound
== lUBound
)
891 if((coor
[iter
] >= lLBound
) && (coor
[iter
] <= lUBound
))
899 /************************************************************************
900 * Method used to calculate the number of cells of the SA
902 static ULONG
getArraySize(
906 ULONG ulWholeArraySize
= 1;
908 for(cCount
=0; cCount
< psa
->cDims
; cCount
++) /* foreach dimensions... */
909 ulWholeArraySize
*= psa
->rgsabound
[cCount
].cElements
;
911 return ulWholeArraySize
;
915 /************************************************************************
916 * Method used to handle data space dupplication for Copy32 and CopyData32
918 static HRESULT
duplicateData(
922 ULONG ulWholeArraySize
; /* size of the thing */
925 BSTR pbstrReAllocStr
= NULL
; /* BSTR reallocated */
927 ulWholeArraySize
= getArraySize(psa
); /* Number of item in SA */
929 SafeArrayLock(*ppsaOut
);
931 if( isPointer(psa
->fFeatures
) ) { /* If datatype is object increment
932 object's reference count */
934 for(lDelta
=0; lDelta
< ulWholeArraySize
; lDelta
++) {
935 punk
= *(IUnknown
**)(psa
->pvData
+(lDelta
* psa
->cbElements
));
938 IUnknown_AddRef(punk
);
941 /* Copy the source array data into target array */
942 memcpy((*ppsaOut
)->pvData
, psa
->pvData
,
943 ulWholeArraySize
*psa
->cbElements
);
945 } else if( psa
->fFeatures
& FADF_BSTR
) { /* if datatype is BSTR allocate
946 the BSTR in the new array */
948 for(lDelta
=0; lDelta
< ulWholeArraySize
; lDelta
++) {
949 if(( pbstrReAllocStr
= SysAllocString(
950 *(BSTR
*)(psa
->pvData
+(lDelta
* psa
->cbElements
)))) == NULL
) {
952 SafeArrayUnlock(*ppsaOut
);
953 return E_OUTOFMEMORY
;
956 *((BSTR
*)((*ppsaOut
)->pvData
+(lDelta
* psa
->cbElements
))) =
960 } else { /* Simply copy the source array data into target array */
962 memcpy((*ppsaOut
)->pvData
, psa
->pvData
,
963 ulWholeArraySize
*psa
->cbElements
);
966 SafeArrayUnlock(*ppsaOut
);