1 /*************************************************************************
3 * SafeArray Implementation
5 * This file contains the implementation of the SafeArray interface.
7 * Copyright 1999 Sylvain St-Germain
16 #include "wine/obj_base.h"
17 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(ole)
21 /* Localy used methods */
23 endOfDim(LONG *coor, SAFEARRAYBOUND *mat, LONG dim, LONG realDim);
26 calcDisplacement(LONG *coor, SAFEARRAYBOUND *mat, LONG dim);
29 isPointer(USHORT feature);
32 getFeatures(VARTYPE vt);
35 validCoordinate(LONG *coor, SAFEARRAY *psa);
38 resizeSafeArray(SAFEARRAY *psa, LONG lDelta);
41 validArg(SAFEARRAY *psa);
44 getArraySize(SAFEARRAY *psa);
47 duplicateData(SAFEARRAY *psa, SAFEARRAY **ppsaOut);
49 /* Association between VARTYPE and their size.
50 A size of zero is defined for the unsupported types. */
52 #define VARTYPE_NOT_SUPPORTED 0
53 const static ULONG VARTYPE_SIZE[] =
55 /* this is taken from wtypes.h. Only [S]es are supported by the SafeArray */
56 VARTYPE_NOT_SUPPORTED, /* VT_EMPTY [V] [P] nothing */
57 VARTYPE_NOT_SUPPORTED, /* VT_NULL [V] [P] SQL style Nul */
58 2, /* VT_I2 [V][T][P][S] 2 byte signed int */
59 4, /* VT_I4 [V][T][P][S] 4 byte signed int */
60 4, /* VT_R4 [V][T][P][S] 4 byte real */
61 8, /* VT_R8 [V][T][P][S] 8 byte real */
62 8, /* VT_CY [V][T][P][S] currency */
63 8, /* VT_DATE [V][T][P][S] date */
64 4, /* VT_BSTR [V][T][P][S] OLE Automation string*/
65 4, /* VT_DISPATCH [V][T][P][S] IDispatch * */
66 4, /* VT_ERROR [V][T] [S] SCODE */
67 4, /* VT_BOOL [V][T][P][S] True=-1, False=0*/
68 24, /* VT_VARIANT [V][T][P][S] VARIANT * */
69 4, /* VT_UNKNOWN [V][T] [S] IUnknown * */
70 16, /* VT_DECIMAL [V][T] [S] 16 byte fixed point */
71 VARTYPE_NOT_SUPPORTED, /* no VARTYPE here..... */
72 VARTYPE_NOT_SUPPORTED, /* VT_I1 [T] signed char */
73 1, /* VT_UI1 [V][T][P][S] unsigned char */
74 VARTYPE_NOT_SUPPORTED, /* VT_UI2 [T][P] unsigned short */
75 VARTYPE_NOT_SUPPORTED, /* VT_UI4 [T][P] unsigned short */
76 VARTYPE_NOT_SUPPORTED, /* VT_I8 [T][P] signed 64-bit int */
77 VARTYPE_NOT_SUPPORTED, /* VT_UI8 [T][P] unsigned 64-bit int */
78 VARTYPE_NOT_SUPPORTED, /* VT_INT [T] signed machine int */
79 VARTYPE_NOT_SUPPORTED, /* VT_UINT [T] unsigned machine int */
80 VARTYPE_NOT_SUPPORTED, /* VT_VOID [T] C style void */
81 VARTYPE_NOT_SUPPORTED, /* VT_HRESULT [T] Standard return type */
82 VARTYPE_NOT_SUPPORTED, /* VT_PTR [T] pointer type */
83 VARTYPE_NOT_SUPPORTED, /* VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)*/
84 VARTYPE_NOT_SUPPORTED, /* VT_CARRAY [T] C style array */
85 VARTYPE_NOT_SUPPORTED, /* VT_USERDEFINED [T] user defined type */
86 VARTYPE_NOT_SUPPORTED, /* VT_LPSTR [T][P] null terminated string */
87 VARTYPE_NOT_SUPPORTED, /* VT_LPWSTR [T][P] wide null term string */
88 VARTYPE_NOT_SUPPORTED, /* VT_FILETIME [P] FILETIME */
89 VARTYPE_NOT_SUPPORTED, /* VT_BLOB [P] Length prefixed bytes */
90 VARTYPE_NOT_SUPPORTED, /* VT_STREAM [P] Name of stream follows */
91 VARTYPE_NOT_SUPPORTED, /* VT_STORAGE [P] Name of storage follows */
92 VARTYPE_NOT_SUPPORTED, /* VT_STREAMED_OBJECT[P] Stream contains an object*/
93 VARTYPE_NOT_SUPPORTED, /* VT_STORED_OBJECT [P] Storage contains object*/
94 VARTYPE_NOT_SUPPORTED, /* VT_BLOB_OBJECT [P] Blob contains an object*/
95 VARTYPE_NOT_SUPPORTED, /* VT_CF [P] Clipboard format */
96 VARTYPE_NOT_SUPPORTED, /* VT_CLSID [P] A Class ID */
97 VARTYPE_NOT_SUPPORTED, /* VT_VECTOR [P] simple counted array */
98 VARTYPE_NOT_SUPPORTED, /* VT_ARRAY [V] SAFEARRAY* */
99 VARTYPE_NOT_SUPPORTED /* VT_BYREF [V] void* for local use */
102 const static int LAST_VARTYPE = sizeof(VARTYPE_SIZE)/sizeof(ULONG);
105 /*************************************************************************
106 * SafeArrayAllocDescriptor
107 * Allocate the appropriate amount of memory for the SafeArray descriptor
109 HRESULT WINAPI SafeArrayAllocDescriptor(
116 /* SAFEARRAY + SAFEARRAYBOUND * (cDims -1) ( -1 because there is already one
117 ( in SAFEARRAY struct */
118 allocSize = sizeof(**ppsaOut) + (sizeof(*sab) * (cDims-1));
120 /* Allocate memory for SAFEARRAY struc */
121 if(( (*ppsaOut)=HeapAlloc(
122 GetProcessHeap(), HEAP_ZERO_MEMORY, allocSize)) == NULL){
123 return(E_UNEXPECTED);
125 TRACE("SafeArray: %lu bytes allocated for descriptor.\n", allocSize);
130 /*************************************************************************
132 * Allocate the appropriate amount of data for the SafeArray data
134 HRESULT WINAPI SafeArrayAllocData(
137 ULONG ulWholeArraySize; /* to store the size of the whole thing */
142 ulWholeArraySize = getArraySize(psa);
144 /* Allocate memory for the data itself */
145 if((psa->pvData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
146 psa->cbElements*ulWholeArraySize)) == NULL)
147 return(E_UNEXPECTED);
149 TRACE("SafeArray: %lu bytes allocated for data at %p (%lu objects).\n",
150 psa->cbElements*ulWholeArraySize, psa->pvData, ulWholeArraySize);
155 /*************************************************************************
157 * Create a SafeArray object by encapsulating AllocDescriptor and AllocData
159 SAFEARRAY* WINAPI SafeArrayCreate(
162 SAFEARRAYBOUND *rgsabound)
168 /* Validate supported VARTYPE */
169 if ( (vt >= LAST_VARTYPE) ||
170 ( VARTYPE_SIZE[vt] == VARTYPE_NOT_SUPPORTED ) )
173 /* Allocate memory for the array descriptor */
174 if( FAILED( hRes = SafeArrayAllocDescriptor(cDims, &psa)))
177 /* setup data members... */
179 psa->fFeatures = getFeatures(vt);
182 psa->cbElements= VARTYPE_SIZE[vt];
184 /* Invert the bounds ... */
185 for(cDim=0; cDim < psa->cDims; cDim++) {
186 psa->rgsabound[cDim].cElements = rgsabound[psa->cDims-cDim-1].cElements;
187 psa->rgsabound[cDim].lLbound = rgsabound[psa->cDims-cDim-1].lLbound;
190 /* allocate memory for the data... */
191 if( FAILED( hRes = SafeArrayAllocData(psa))) {
192 SafeArrayDestroyDescriptor(psa);
193 ERR("() : Failed to allocate the Safe Array data\n");
200 /*************************************************************************
201 * SafeArrayDestroyDescriptor
202 * Frees the memory associated with the descriptor.
204 HRESULT WINAPI SafeArrayDestroyDescriptor(
207 /* Check for lockness before to free... */
209 return DISP_E_ARRAYISLOCKED;
211 /* The array is unlocked, then, deallocate memory */
212 if(HeapFree( GetProcessHeap(), 0, psa) == FALSE)
219 /*************************************************************************
221 * Increment the lock counter
223 * Doc says (MSDN Library ) that psa->pvData should be made available (!= NULL)
224 * only when psa->cLocks is > 0... I don't get it since pvData is allocated
225 * before the array is locked, therefore
227 HRESULT WINAPI SafeArrayLock(
238 /*************************************************************************
240 * Decrement the lock counter
242 HRESULT WINAPI SafeArrayUnlock(
255 /*************************************************************************
256 * SafeArrayPutElement
257 * Set the data at the given coordinate
259 HRESULT WINAPI SafeArrayPutElement(
264 ULONG stepCountInSAData = 0; /* Number of array item to skip to get to
265 the desired one... */
266 PVOID elementStorageAddress = NULL; /* Adress to store the data */
267 BSTR pbstrReAllocStr = NULL; /* BSTR reallocated */
269 /* Validate the index given */
270 if(! validCoordinate(rgIndices, psa))
271 return DISP_E_BADINDEX;
275 if( SafeArrayLock(psa) == S_OK) {
277 /* Figure out the number of items to skip */
278 stepCountInSAData = calcDisplacement(rgIndices, psa->rgsabound, psa->cDims);
280 /* Figure out the number of byte to skip ... */
281 elementStorageAddress = (char *) psa->pvData+(stepCountInSAData*psa->cbElements);
283 if(isPointer(psa->fFeatures)) { /* increment ref count for this pointer */
285 *((VOID**)elementStorageAddress) = *(VOID**)pv;
286 IUnknown_AddRef( *(IUnknown**)pv);
290 if(psa->fFeatures == FADF_BSTR) { /* Create a new object */
292 if((pbstrReAllocStr = SysAllocString( (OLECHAR*)pv )) == NULL) {
293 SafeArrayUnlock(psa);
294 return E_OUTOFMEMORY;
296 *((BSTR*)elementStorageAddress) = pbstrReAllocStr;
298 } else /* dupplicate the memory */
299 memcpy(elementStorageAddress, pv, SafeArrayGetElemsize(psa) );
303 ERR("SafeArray: Cannot lock array....\n");
304 return E_UNEXPECTED; /* UNDOC error condition */
307 TRACE("SafeArray: item put at adress %p.\n",elementStorageAddress);
308 return SafeArrayUnlock(psa);
312 /*************************************************************************
313 * SafeArrayGetElement
314 * Return the data element corresponding the the given coordinate
316 HRESULT WINAPI SafeArrayGetElement(
321 ULONG stepCountInSAData = 0; /* Number of array item to skip to get to
322 the desired one... */
323 PVOID elementStorageAddress = NULL; /* Adress to store the data */
324 BSTR pbstrReturnedStr = NULL; /* BSTR reallocated */
329 if(! validCoordinate(rgIndices, psa)) /* Validate the index given */
330 return(DISP_E_BADINDEX);
332 if( SafeArrayLock(psa) == S_OK) {
334 /* Figure out the number of items to skip */
335 stepCountInSAData = calcDisplacement(rgIndices, psa->rgsabound, psa->cDims);
337 /* Figure out the number of byte to skip ... */
338 elementStorageAddress = (char *) psa->pvData+(stepCountInSAData*psa->cbElements);
340 if( psa->fFeatures == FADF_BSTR) { /* reallocate the obj */
341 if( (pbstrReturnedStr =
342 SysAllocString( *(OLECHAR**)elementStorageAddress )) == NULL) {
343 SafeArrayUnlock(psa);
344 return E_OUTOFMEMORY;
346 *((BSTR*)pv) = pbstrReturnedStr;
348 } else if( isPointer(psa->fFeatures) ) /* simply copy the pointer */
349 pv = *((PVOID*)elementStorageAddress);
350 else /* copy the bytes */
351 memcpy(pv, elementStorageAddress, SafeArrayGetElemsize(psa) );
354 ERR("SafeArray: Cannot lock array....\n");
355 return E_UNEXPECTED; /* UNDOC error condition */
358 return( SafeArrayUnlock(psa) );
361 /*************************************************************************
363 * return the UP bound for a given array dimension
365 HRESULT WINAPI SafeArrayGetUBound(
373 if(nDim > psa->cDims)
374 return DISP_E_BADINDEX;
376 *plUbound = psa->rgsabound[nDim-1].lLbound +
377 psa->rgsabound[nDim-1].cElements - 1;
382 /*************************************************************************
384 * Return the LO bound for a given array dimension
386 HRESULT WINAPI SafeArrayGetLBound(
394 if(nDim > psa->cDims)
395 return DISP_E_BADINDEX;
397 *plLbound = psa->rgsabound[nDim-1].lLbound;
401 /*************************************************************************
403 * returns the number of dimension in the array
405 UINT WINAPI SafeArrayGetDim(
409 * A quick test in Windows shows that the behavior here for an invalid
410 * pointer is to return 0.
418 /*************************************************************************
419 * SafeArrayGetElemsize
420 * Return the size of the element in the array
422 UINT WINAPI SafeArrayGetElemsize(
426 * A quick test in Windows shows that the behavior here for an invalid
427 * pointer is to return 0.
432 return psa->cbElements;
435 /*************************************************************************
436 * SafeArrayAccessData
437 * increment the access count and return the data
439 HRESULT WINAPI SafeArrayAccessData(
448 hRes = SafeArrayLock(psa);
452 (*ppvData) = psa->pvData;
463 /*************************************************************************
464 * SafeArrayUnaccessData
465 * Decrement the access count
467 HRESULT WINAPI SafeArrayUnaccessData(
473 return(SafeArrayUnlock(psa));
476 /************************************************************************
477 * SafeArrayPtrOfIndex
478 * Return a pointer to the element at rgIndices
480 HRESULT WINAPI SafeArrayPtrOfIndex(
485 ULONG stepCountInSAData = 0; /* Number of array item to skip to get to
486 the desired one... */
491 if(! validCoordinate(rgIndices, psa))
492 return DISP_E_BADINDEX;
494 /* Figure out the number of items to skip */
495 stepCountInSAData = calcDisplacement(rgIndices, psa->rgsabound, psa->cDims);
497 *ppvData = (char *) psa->pvData+(stepCountInSAData*psa->cbElements);
502 /************************************************************************
503 * SafeArrayDestroyData
504 * Frees the memory data bloc
506 HRESULT WINAPI SafeArrayDestroyData(
510 ULONG ulWholeArraySize; /* count spot in array */
511 ULONG ulDataIter; /* to iterate the data space */
519 return DISP_E_ARRAYISLOCKED;
521 ulWholeArraySize = getArraySize(psa);
523 if(isPointer(psa->fFeatures)) { /* release the pointers */
525 for(ulDataIter=0; ulDataIter < ulWholeArraySize; ulDataIter++) {
526 punk = *(IUnknown**)((char *) psa->pvData+(ulDataIter*(psa->cbElements)));
529 IUnknown_Release(punk);
532 } else if(psa->fFeatures & FADF_BSTR) { /* deallocate the obj */
534 for(ulDataIter=0; ulDataIter < ulWholeArraySize; ulDataIter++) {
535 bstr = *(BSTR*)((char *) psa->pvData+(ulDataIter*(psa->cbElements)));
538 SysFreeString( bstr );
542 /* check if this array is a Vector, in which case do not free the data
543 block since it has been allocated by AllocDescriptor and therefore
544 deserve to be freed by DestroyDescriptor */
545 if(!(psa->fFeatures & FADF_CREATEVECTOR)) { /* Set when we do CreateVector */
547 /* free the whole chunk */
548 if((hRes = HeapFree( GetProcessHeap(), 0, psa->pvData)) == 0) /*falied*/
549 return E_UNEXPECTED; /* UNDOC error condition */
557 /************************************************************************
559 * Copy the psaSource's data block into psaTarget if dimension and size
562 HRESULT WINAPI SafeArrayCopyData(
563 SAFEARRAY *psaSource,
564 SAFEARRAY **psaTarget)
566 USHORT cDimCount; /* looper */
567 LONG lDelta; /* looper */
569 ULONG ulWholeArraySize; /* Number of item in SA */
572 if(! (validArg(psaSource) && validArg(*psaTarget)) )
575 if(SafeArrayGetDim(psaSource) != SafeArrayGetDim(*psaTarget))
578 ulWholeArraySize = getArraySize(psaSource);
580 /* The two arrays boundaries must be of same lenght */
581 for(cDimCount=0;cDimCount < psaSource->cDims; cDimCount++)
582 if( psaSource->rgsabound[cDimCount].cElements !=
583 (*psaTarget)->rgsabound[cDimCount].cElements)
586 if( isPointer((*psaTarget)->fFeatures) ) { /* the target contains ptr
587 that must be released */
588 for(lDelta=0;lDelta < ulWholeArraySize; lDelta++) {
590 ((char *) (*psaTarget)->pvData + (lDelta * (*psaTarget)->cbElements));
593 IUnknown_Release(punk);
596 } else if( (*psaTarget)->fFeatures & FADF_BSTR) { /* the target contain BSTR
597 that must be freed */
598 for(lDelta=0;lDelta < ulWholeArraySize; lDelta++) {
600 *(BSTR*)((char *) (*psaTarget)->pvData + (lDelta * (*psaTarget)->cbElements));
603 SysFreeString( bstr );
607 return duplicateData(psaSource, psaTarget);
610 /************************************************************************
612 * Deallocates all memory reserved for the SafeArray
614 HRESULT WINAPI SafeArrayDestroy(
623 return DISP_E_ARRAYISLOCKED;
625 if((hRes = SafeArrayDestroyData( psa )) == S_OK)
626 if((hRes = SafeArrayDestroyDescriptor( psa )) == S_OK)
629 return E_UNEXPECTED; /* UNDOC error condition */
632 /************************************************************************
634 * Make a dupplicate of a SafeArray
636 HRESULT WINAPI SafeArrayCopy(
642 ULONG ulWholeArraySize; /* size of the thing */
647 if((hRes=SafeArrayAllocDescriptor(psa->cDims, ppsaOut)) == S_OK){
649 /* Duplicate the SAFEARRAY struc */
650 memcpy(*ppsaOut, psa,
651 sizeof(*psa)+(sizeof(*(psa->rgsabound))*(psa->cDims-1)));
653 (*ppsaOut)->pvData = NULL; /* do not point to the same data area */
655 /* make sure the new safe array doesn't have the FADF_CREATEVECTOR flag,
656 because the data has not been allocated with the descriptor. */
657 (*ppsaOut)->fFeatures &= ~FADF_CREATEVECTOR;
659 /* Get the allocated memory size for source and allocate it for target */
660 ulWholeArraySize = getArraySize(psa); /* Number of item in SA */
661 dAllocSize = ulWholeArraySize*psa->cbElements;
664 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dAllocSize);
665 if( (*ppsaOut)->pvData != NULL) { /* HeapAlloc succeed */
667 if( (hRes=duplicateData(psa, ppsaOut)) != S_OK) { /* E_OUTOFMEMORY */
668 HeapFree(GetProcessHeap(), 0, (*ppsaOut)->pvData);
669 (*ppsaOut)->pvData = NULL;
670 SafeArrayDestroyDescriptor(*ppsaOut);
674 } else { /* failed to allocate or dupplicate... */
675 SafeArrayDestroyDescriptor(*ppsaOut);
676 return E_UNEXPECTED; /* UNDOC error condition */
678 } else { /* failed to allocate mem for descriptor */
679 return E_OUTOFMEMORY; /* UNDOC error condiftion */
685 /************************************************************************
686 * SafeArrayCreateVector
687 * Creates a one dimension safearray where the data is next to the
688 * SAFEARRAY structure.
690 SAFEARRAY* WINAPI SafeArrayCreateVector(
697 /* Validate supported VARTYPE */
698 if ( (vt >= LAST_VARTYPE) ||
699 ( VARTYPE_SIZE[vt] == VARTYPE_NOT_SUPPORTED ) )
702 /* Allocate memory for the array descriptor and data contiguously */
703 if( FAILED( psa = HeapAlloc( GetProcessHeap(),
705 (sizeof(*psa) + (VARTYPE_SIZE[vt] * cElements))))) {
709 /* setup data members... */
710 psa->cDims = 1; /* always and forever */
711 psa->fFeatures = getFeatures(vt) | FADF_CREATEVECTOR; /* undocumented flag used by Microsoft */
713 psa->pvData = (BYTE*)psa + sizeof(*psa);
714 psa->cbElements = VARTYPE_SIZE[vt];
716 psa->rgsabound[0].cElements = cElements;
717 psa->rgsabound[0].lLbound = lLbound;
722 /************************************************************************
724 * Changes the caracteristics of the last dimension of the SafeArray
726 HRESULT WINAPI SafeArrayRedim(
728 SAFEARRAYBOUND *psaboundNew)
730 LONG lDelta; /* hold difference in size */
731 USHORT cDims=1; /* dims counter */
736 if( psa->cLocks > 0 )
737 return DISP_E_ARRAYISLOCKED;
739 if( psa->fFeatures & FADF_FIXEDSIZE )
742 if( SafeArrayLock(psa)==E_UNEXPECTED )
743 return E_UNEXPECTED;/* UNDOC error condition */
745 /* find the delta in number of array spot to apply to the new array */
746 lDelta = psaboundNew->cElements - psa->rgsabound[0].cElements;
747 for(; cDims < psa->cDims; cDims++)
748 /* delta in number of spot implied by modifying the last dimension */
749 lDelta *= psa->rgsabound[cDims].cElements;
751 if (lDelta == 0) { ;/* same size, maybe a change of lLbound, just set it */
753 } else /* need to enlarge (lDelta +) reduce (lDelta -) */
754 if(! resizeSafeArray(psa, lDelta))
755 return E_UNEXPECTED; /* UNDOC error condition */
757 /* the only modifyable dimension sits in [0] as the dimensions were reversed
758 at array creation time... */
759 psa->rgsabound[0].cElements = psaboundNew->cElements;
760 psa->rgsabound[0].lLbound = psaboundNew->lLbound;
762 return SafeArrayUnlock(psa);
765 /************************************************************************
766 * NOT WINDOWS API - SafeArray* Utility functions
767 ************************************************************************/
769 /************************************************************************
770 * Used to validate the SAFEARRAY type of arg
772 static BOOL validArg(
781 * Let's check for the null pointer just in case.
786 /* Check whether the size of the chunk make sens... That's the only thing
787 I can think of now... */
789 psaSize = HeapSize(GetProcessHeap(), 0, psa);
791 /* size of the descriptor when the SA is not created with CreateVector */
792 descSize = sizeof(*psa) + (sizeof(*sab) * (psa->cDims-1));
794 /* size of the descriptor + data when created with CreateVector */
795 fullSize = sizeof(*psa) + (psa->cbElements * psa->rgsabound[0].cElements);
797 return((psaSize >= descSize) || (psaSize >= fullSize));
800 /************************************************************************
801 * Used to reallocate memory
803 static BOOL resizeSafeArray(
807 ULONG ulWholeArraySize; /* use as multiplicator */
808 PVOID pvNewBlock = NULL;
812 ulWholeArraySize = getArraySize(psa);
814 if(lDelta < 0) { /* array needs to be shorthen */
815 if( isPointer(psa->fFeatures)) /* ptr that need to be released */
816 for(;lDelta < 0; lDelta++) {
818 ((char *) psa->pvData+((ulWholeArraySize+lDelta)*psa->cbElements));
821 IUnknown_Release(punk);
824 else if(psa->fFeatures & FADF_BSTR) /* BSTR that need to be freed */
825 for(;lDelta < 0; lDelta++) {
827 ((char *) psa->pvData+((ulWholeArraySize+lDelta)*psa->cbElements));
830 SysFreeString( bstr );
834 if (!(psa->fFeatures & FADF_CREATEVECTOR))
836 /* Ok now, if we are enlarging the array, we *MUST* move the whole block
837 pointed to by pvData. If we are shorthening the array, this move is
838 optional but we do it anyway becuase the benefit is that we are
839 releasing to the system the unused memory */
841 if((pvNewBlock = HeapReAlloc(GetProcessHeap(), 0, psa->pvData,
842 (ulWholeArraySize + lDelta) * psa->cbElements)) == NULL)
843 return FALSE; /* TODO If we get here it means:
844 SHRINK situation : we've deleted the undesired
845 data and did not release the memory
846 GROWING situation: we've been unable to grow the array
851 /* Allocate a new block, because the previous data has been allocated with
852 the descriptor in SafeArrayCreateVector function. */
854 if((pvNewBlock = HeapAlloc(GetProcessHeap(), 0,
855 ulWholeArraySize * psa->cbElements)) == NULL)
858 psa->fFeatures &= ~FADF_CREATEVECTOR;
860 /* reassign to the new block of data */
861 psa->pvData = pvNewBlock;
865 /************************************************************************
866 * Used to set the fFeatures data member of the SAFEARRAY structure.
868 static INT getFeatures(
872 case VT_UNKNOWN: return FADF_UNKNOWN;
873 case VT_DISPATCH: return FADF_DISPATCH;
874 case VT_BSTR: return FADF_BSTR;
879 /************************************************************************
880 * Used to figure out if the fFeatures data member of the SAFEARRAY
881 * structure contain any information about the type of data stored...
883 static BOOL isPointer(
887 case FADF_UNKNOWN: return TRUE; /* those are pointers */
888 case FADF_DISPATCH: return TRUE;
893 /************************************************************************
894 * Used to calculate the displacement when accessing or modifying
895 * safearray data set.
897 * Parameters: - LONG *coor is the desired location in the multidimension
898 * table. Ex for a 3 dim table: coor[] = {1,2,3};
899 * - ULONG *mat is the format of the table. Ex for a 3 dim
900 * table mat[] = {4,4,4};
901 * - USHORT dim is the number of dimension of the SafeArray
903 static ULONG calcDisplacement(
911 for(iterDim=0; iterDim<dim; iterDim++)
912 /* the -mat[dim] bring coor[dim] relative to 0 for calculation */
913 res += ((coor[iterDim]-mat[iterDim].lLbound) *
914 endOfDim(coor, mat, iterDim+1, dim));
916 TRACE("SafeArray: calculated displacement is %lu.\n", res);
920 /************************************************************************
921 * Recursivity agent for calcDisplacement method. Used within Put and
933 return (endOfDim(coor, mat, dim+1, realDim) * mat[dim].cElements);
937 /************************************************************************
938 * Method used to validate the coordinate received in Put and Get
941 static BOOL validCoordinate(
950 for(; iter<psa->cDims; iter++) {
951 if((hRes = SafeArrayGetLBound(psa, iter, &lLBound)) != S_OK)
953 if((hRes = SafeArrayGetUBound(psa, iter, &lUBound)) != S_OK)
956 if(lLBound == lUBound)
959 if((coor[iter] >= lLBound) && (coor[iter] <= lUBound))
967 /************************************************************************
968 * Method used to calculate the number of cells of the SA
970 static ULONG getArraySize(
974 ULONG ulWholeArraySize = 1;
976 for(cCount=0; cCount < psa->cDims; cCount++) /* foreach dimensions... */
977 ulWholeArraySize *= psa->rgsabound[cCount].cElements;
979 return ulWholeArraySize;
983 /************************************************************************
984 * Method used to handle data space dupplication for Copy32 and CopyData32
986 static HRESULT duplicateData(
990 ULONG ulWholeArraySize; /* size of the thing */
993 BSTR pbstrReAllocStr = NULL; /* BSTR reallocated */
995 ulWholeArraySize = getArraySize(psa); /* Number of item in SA */
997 SafeArrayLock(*ppsaOut);
999 if( isPointer(psa->fFeatures) ) { /* If datatype is object increment
1000 object's reference count */
1002 for(lDelta=0; lDelta < ulWholeArraySize; lDelta++) {
1003 punk = *(IUnknown**)((char *) psa->pvData+(lDelta * psa->cbElements));
1006 IUnknown_AddRef(punk);
1009 /* Copy the source array data into target array */
1010 memcpy((*ppsaOut)->pvData, psa->pvData,
1011 ulWholeArraySize*psa->cbElements);
1013 } else if( psa->fFeatures & FADF_BSTR ) { /* if datatype is BSTR allocate
1014 the BSTR in the new array */
1016 for(lDelta=0; lDelta < ulWholeArraySize; lDelta++) {
1017 if(( pbstrReAllocStr = SysAllocString(
1018 *(BSTR*)((char *) psa->pvData+(lDelta * psa->cbElements)))) == NULL) {
1020 SafeArrayUnlock(*ppsaOut);
1021 return E_OUTOFMEMORY;
1024 *((BSTR*)((char *) (*ppsaOut)->pvData+(lDelta * psa->cbElements))) =
1028 } else { /* Simply copy the source array data into target array */
1030 memcpy((*ppsaOut)->pvData, psa->pvData,
1031 ulWholeArraySize*psa->cbElements);
1034 SafeArrayUnlock(*ppsaOut);
1040 /************************************************************************
1041 * SafeArrayGetVarType
1042 * Returns the VARTYPE stored in the given safearray
1044 HRESULT WINAPI SafeArrayGetVarType(
1048 HRESULT hr = E_INVALIDARG;
1049 VARTYPE vt = VT_EMPTY;
1051 /* const short VARTYPE_OFFSET = -4; */
1053 if (psa->fFeatures & FADF_HAVEVARTYPE)
1055 /* VT tag @ negative offset 4 in the array descriptor */
1056 FIXME("Returning VT_BSTR instead of VT_...");
1059 else if (psa->fFeatures & FADF_RECORD)
1063 else if (psa->fFeatures & FADF_DISPATCH)
1067 else if (psa->fFeatures & FADF_UNKNOWN)
1078 TRACE("HRESULT = %08lx", hr);