source: trunk/src/oleaut32/safearray.c

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 38.3 KB
RevLine 
[4837]1/*************************************************************************
2 * OLE Automation
3 * SafeArray Implementation
4 *
5 * This file contains the implementation of the SafeArray interface.
6 *
7 * Copyright 1999 Sylvain St-Germain
[8450]8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
[4837]22 */
[8450]23#ifdef __WIN32OS2__
24#define HAVE_FLOAT_H
25#define WINE_LARGE_INTEGER
26#include "oleaut32.h"
27#endif
28
[4837]29#include <stdio.h>
30#include <string.h>
31#include "windef.h"
32#include "winerror.h"
33#include "winbase.h"
34#include "oleauto.h"
35#include "wine/obj_base.h"
[8450]36#include "wine/debug.h"
[4837]37
[8450]38WINE_DEFAULT_DEBUG_CHANNEL(ole);
[4837]39
[6944]40#define SYSDUPSTRING(str) SysAllocStringLen((str), SysStringLen(str))
41
[7916]42/* Locally used methods */
[9400]43static INT
[4837]44endOfDim(LONG *coor, SAFEARRAYBOUND *mat, LONG dim, LONG realDim);
45
[9400]46static ULONG
[4837]47calcDisplacement(LONG *coor, SAFEARRAYBOUND *mat, LONG dim);
48
[9400]49static BOOL
[4837]50isPointer(USHORT feature);
51
[9400]52static INT
[4837]53getFeatures(VARTYPE vt);
54
[9400]55static BOOL
[4837]56validCoordinate(LONG *coor, SAFEARRAY *psa);
57
[9400]58static BOOL
[4837]59resizeSafeArray(SAFEARRAY *psa, LONG lDelta);
60
[9400]61static BOOL
[4837]62validArg(SAFEARRAY *psa);
63
[9400]64static ULONG
[4837]65getArraySize(SAFEARRAY *psa);
66
[9400]67static HRESULT
[4837]68duplicateData(SAFEARRAY *psa, SAFEARRAY **ppsaOut);
69
70/* Association between VARTYPE and their size.
71 A size of zero is defined for the unsupported types. */
72
73#define VARTYPE_NOT_SUPPORTED 0
74static const ULONG VARTYPE_SIZE[] =
75{
76 /* this is taken from wtypes.h. Only [S]es are supported by the SafeArray */
[6944]77VARTYPE_NOT_SUPPORTED, /* VT_EMPTY [V] [P] nothing */
78VARTYPE_NOT_SUPPORTED, /* VT_NULL [V] [P] SQL style Nul */
792, /* VT_I2 [V][T][P][S] 2 byte signed int */
804, /* VT_I4 [V][T][P][S] 4 byte signed int */
814, /* VT_R4 [V][T][P][S] 4 byte real */
828, /* VT_R8 [V][T][P][S] 8 byte real */
[4837]838, /* VT_CY [V][T][P][S] currency */
[6944]848, /* VT_DATE [V][T][P][S] date */
85sizeof(BSTR), /* VT_BSTR [V][T][P][S] OLE Automation string*/
86sizeof(LPDISPATCH), /* VT_DISPATCH [V][T][P][S] IDispatch * */
[6711]874, /* VT_ERROR [V][T] [S] SCODE */
[6944]884, /* VT_BOOL [V][T][P][S] True=-1, False=0*/
89sizeof(VARIANT), /* VT_VARIANT [V][T][P][S] VARIANT * */
90sizeof(LPUNKNOWN), /* VT_UNKNOWN [V][T] [S] IUnknown * */
91sizeof(DECIMAL), /* VT_DECIMAL [V][T] [S] 16 byte fixed point */
[4837]92VARTYPE_NOT_SUPPORTED, /* no VARTYPE here..... */
[6711]93VARTYPE_NOT_SUPPORTED, /* VT_I1 [T] signed char */
[6944]941, /* VT_UI1 [V][T][P][S] unsigned char */
[6711]95VARTYPE_NOT_SUPPORTED, /* VT_UI2 [T][P] unsigned short */
96VARTYPE_NOT_SUPPORTED, /* VT_UI4 [T][P] unsigned short */
97VARTYPE_NOT_SUPPORTED, /* VT_I8 [T][P] signed 64-bit int */
98VARTYPE_NOT_SUPPORTED, /* VT_UI8 [T][P] unsigned 64-bit int */
99VARTYPE_NOT_SUPPORTED, /* VT_INT [T] signed machine int */
100VARTYPE_NOT_SUPPORTED, /* VT_UINT [T] unsigned machine int */
101VARTYPE_NOT_SUPPORTED, /* VT_VOID [T] C style void */
102VARTYPE_NOT_SUPPORTED, /* VT_HRESULT [T] Standard return type */
103VARTYPE_NOT_SUPPORTED, /* VT_PTR [T] pointer type */
104VARTYPE_NOT_SUPPORTED, /* VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)*/
105VARTYPE_NOT_SUPPORTED, /* VT_CARRAY [T] C style array */
106VARTYPE_NOT_SUPPORTED, /* VT_USERDEFINED [T] user defined type */
107VARTYPE_NOT_SUPPORTED, /* VT_LPSTR [T][P] null terminated string */
108VARTYPE_NOT_SUPPORTED, /* VT_LPWSTR [T][P] wide null term string */
109VARTYPE_NOT_SUPPORTED, /* VT_FILETIME [P] FILETIME */
110VARTYPE_NOT_SUPPORTED, /* VT_BLOB [P] Length prefixed bytes */
111VARTYPE_NOT_SUPPORTED, /* VT_STREAM [P] Name of stream follows */
112VARTYPE_NOT_SUPPORTED, /* VT_STORAGE [P] Name of storage follows */
113VARTYPE_NOT_SUPPORTED, /* VT_STREAMED_OBJECT[P] Stream contains an object*/
114VARTYPE_NOT_SUPPORTED, /* VT_STORED_OBJECT [P] Storage contains object*/
115VARTYPE_NOT_SUPPORTED, /* VT_BLOB_OBJECT [P] Blob contains an object*/
116VARTYPE_NOT_SUPPORTED, /* VT_CF [P] Clipboard format */
117VARTYPE_NOT_SUPPORTED, /* VT_CLSID [P] A Class ID */
118VARTYPE_NOT_SUPPORTED, /* VT_VECTOR [P] simple counted array */
119VARTYPE_NOT_SUPPORTED, /* VT_ARRAY [V] SAFEARRAY* */
120VARTYPE_NOT_SUPPORTED /* VT_BYREF [V] void* for local use */
[4837]121};
122
[7916]123static const int LAST_VARTYPE = sizeof(VARTYPE_SIZE)/sizeof(VARTYPE_SIZE[0]);
[4837]124
125
[10631]126/***********************************************************************
127 * SafeArrayCreateEx (OLEAUT32.42)
128*
129 * Create a new SafeArray.
130 *
131 * PARAMS
132 * vt [I] Type to store in the safe array
133 * cDims [I] Number of array dimensions
134 * rgsabound [I] Bounds of the array dimensions
135 * pvExtra [I] Extra data
136 *
137 * RETURNS
138 * Success: A pointer to a new array object.
139 * Failure: NULL, if any parameter is invalid or memory allocation fails.
140 *
141 * NOTES
142 * See SafeArray.
143 */
144SAFEARRAY* WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound, LPVOID pvExtra)
145#ifdef __WIN32OS2__
146{
147 FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
[21916]148 return NULL;
[10631]149}
150#else
151{
152 ULONG ulSize = 0;
153 IRecordInfo* iRecInfo = (IRecordInfo*)pvExtra;
154 SAFEARRAY* psa;
155
156 TRACE("(%d->%s,%d,%p,%p)\n", vt, debugstr_vt(vt), cDims, rgsabound, pvExtra);
157
158 if (vt == VT_RECORD)
159 {
160 if (!iRecInfo)
161 return NULL;
162 IRecordInfo_GetSize(iRecInfo, &ulSize);
163 }
164 psa = SAFEARRAY_Create(vt, cDims, rgsabound, ulSize);
165
166 if (pvExtra)
167 {
168 switch(vt)
169 {
170 case VT_RECORD:
171 SafeArraySetRecordInfo(psa, pvExtra);
172 break;
173 case VT_UNKNOWN:
174 case VT_DISPATCH:
175 SafeArraySetIID(psa, pvExtra);
176 break;
177 }
178 }
179 return psa;
180}
181#endif
182
183/***********************************************************************
184 * SafeArraySetIID (OLEAUT32.57)
185*
186 * Set the IID for a SafeArray.
187 *
188 * PARAMS
189 * psa [I] Array to set the IID from
190 * guid [I] IID
191 *
192 * RETURNS
193 * Success: S_OK. The IID is stored with the array
194 * Failure: An HRESULT error code indicating the error.
195 *
196 * NOTES
197 * See SafeArray.
198 */
199HRESULT WINAPI SafeArraySetIID(SAFEARRAY *psa, REFGUID guid)
200{
201 GUID* dest = (GUID*)psa;
202
203 TRACE("(%p,%s)\n", psa, debugstr_guid(guid));
204
205 if (!psa || !guid || !(psa->fFeatures & FADF_HAVEIID))
206 return E_INVALIDARG;
207
208 dest[-1] = *guid;
209 return S_OK;
210}
211
212
213/***********************************************************************
214 * SafeArrayGetIID (OLEAUT32.67)
215 *
216 * Get the IID from a SafeArray.
217 *
218 * PARAMS
219 * psa [I] Array to get the ID from
220 * pGuid [O] Destination for the IID
221 *
222 * RETURNS
223 * Success: S_OK. pRinfo contains the IID, or NULL if there was none.
224 * Failure: An HRESULT error code indicating the error.
225 *
226 * NOTES
227 * See SafeArray.
228 */
229HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid)
230{
231 GUID* src = (GUID*)psa;
232
233 TRACE("(%p,%p)\n", psa, pGuid);
234
235 if (!psa || !pGuid || !(psa->fFeatures & FADF_HAVEIID))
236 return E_INVALIDARG;
237
238 *pGuid = src[-1];
239 return S_OK;
240}
241
242
243/***********************************************************************
244 * SafeArraySetRecordInfo (OLEAUT32.45)
245 */
246#ifdef __WIN32OS2__
247HRESULT WINAPI SafeArraySetRecordInfo(void* pFixMe, void* pFixMe2)
248#else
249HRESULT WINAPI SafeArraySetRecordInfo(SAFEARRAY* psa, IRecordInfo * psaboundNew)
250#endif
251{
252 FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
253 return E_NOTIMPL;
254}
255
256
257/***********************************************************************
258 * SafeArrayGetRecordInfo (OLEAUT32.45)
259 */
260/* IRecordInfo helpers */
261#ifdef __WIN32OS2__
262HRESULT WINAPI SafeArrayGetRecordInfo(void* pFixMe, void** ppFixMe)
263#else
264HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY* psa,IRecordInfo** prinfo)
265#endif
266{
267 FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
268 return E_NOTIMPL;
269}
270
271
[4837]272/*************************************************************************
[6944]273 * SafeArrayAllocDescriptor (OLEAUT32.36)
[4837]274 * Allocate the appropriate amount of memory for the SafeArray descriptor
275 */
[9400]276HRESULT WINAPI SafeArrayAllocDescriptor(
277 UINT cDims,
278 SAFEARRAY **ppsaOut)
[4837]279{
280 SAFEARRAYBOUND *sab;
281 LONG allocSize = 0;
282
283 /* SAFEARRAY + SAFEARRAYBOUND * (cDims -1) ( -1 because there is already one
284 ( in SAFEARRAY struct */
285 allocSize = sizeof(**ppsaOut) + (sizeof(*sab) * (cDims-1));
286
287 /* Allocate memory for SAFEARRAY struc */
[9400]288 if(( (*ppsaOut)=HeapAlloc(
[4837]289 GetProcessHeap(), HEAP_ZERO_MEMORY, allocSize)) == NULL){
290 return(E_UNEXPECTED);
291 }
292 TRACE("SafeArray: %lu bytes allocated for descriptor.\n", allocSize);
293
294 return(S_OK);
295}
296
297/*************************************************************************
[9400]298 * SafeArrayAllocDescriptorEx (OLEAUT32.41)
[7916]299 * Allocate the appropriate amount of memory for the SafeArray descriptor
300 *
301 * This is a minimal implementation just to get things moving.
302 *
303 * The MSDN documentation on this doesn't tell us much.
304 */
[9400]305HRESULT WINAPI SafeArrayAllocDescriptorEx(
[7916]306 VARTYPE vt,
[9400]307 UINT cDims,
308 SAFEARRAY **ppsaOut)
[7916]309{
310 if ( (vt >= LAST_VARTYPE) ||
311 ( VARTYPE_SIZE[vt] == VARTYPE_NOT_SUPPORTED ) )
312 return E_UNEXPECTED;
313
314 return SafeArrayAllocDescriptor (cDims, ppsaOut);
315}
316
317/*************************************************************************
[6944]318 * SafeArrayAllocData (OLEAUT32.37)
[4837]319 * Allocate the appropriate amount of data for the SafeArray data
320 */
321HRESULT WINAPI SafeArrayAllocData(
[9400]322 SAFEARRAY *psa)
[4837]323{
324 ULONG ulWholeArraySize; /* to store the size of the whole thing */
325
[9400]326 if(! validArg(psa))
[4837]327 return E_INVALIDARG;
328
329 ulWholeArraySize = getArraySize(psa);
330
331 /* Allocate memory for the data itself */
[9400]332 if((psa->pvData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
[4837]333 psa->cbElements*ulWholeArraySize)) == NULL)
334 return(E_UNEXPECTED);
335
[9400]336 TRACE("SafeArray: %lu bytes allocated for data at %p (%lu objects).\n",
[4837]337 psa->cbElements*ulWholeArraySize, psa->pvData, ulWholeArraySize);
338
339 return(S_OK);
340}
341
342/*************************************************************************
[6944]343 * SafeArrayCreate (OLEAUT32.15)
[9400]344 * Create a SafeArray object by encapsulating AllocDescriptor and AllocData
[4837]345 */
346SAFEARRAY* WINAPI SafeArrayCreate(
[9400]347 VARTYPE vt,
348 UINT cDims,
[4837]349 SAFEARRAYBOUND *rgsabound)
350{
351 SAFEARRAY *psa;
352 HRESULT hRes;
353 USHORT cDim;
354
355 /* Validate supported VARTYPE */
356 if ( (vt >= LAST_VARTYPE) ||
357 ( VARTYPE_SIZE[vt] == VARTYPE_NOT_SUPPORTED ) )
358 return NULL;
359
360 /* Allocate memory for the array descriptor */
361 if( FAILED( hRes = SafeArrayAllocDescriptor(cDims, &psa)))
362 return NULL;
363
[9400]364 /* setup data members... */
[4837]365 psa->cDims = cDims;
366 psa->fFeatures = getFeatures(vt);
367 psa->cLocks = 0;
368 psa->pvData = NULL;
369 psa->cbElements= VARTYPE_SIZE[vt];
370
371 /* Invert the bounds ... */
372 for(cDim=0; cDim < psa->cDims; cDim++) {
373 psa->rgsabound[cDim].cElements = rgsabound[psa->cDims-cDim-1].cElements;
374 psa->rgsabound[cDim].lLbound = rgsabound[psa->cDims-cDim-1].lLbound;
375 }
376
[9400]377 /* allocate memory for the data... */
[4837]378 if( FAILED( hRes = SafeArrayAllocData(psa))) {
[9400]379 SafeArrayDestroyDescriptor(psa);
[4837]380 ERR("() : Failed to allocate the Safe Array data\n");
381 return NULL;
382 }
383
[9400]384 return(psa);
[4837]385}
386
387/*************************************************************************
[6944]388 * SafeArrayDestroyDescriptor (OLEAUT32.38)
[4837]389 * Frees the memory associated with the descriptor.
390 */
391HRESULT WINAPI SafeArrayDestroyDescriptor(
392 SAFEARRAY *psa)
393{
394 /* Check for lockness before to free... */
[9400]395 if(psa->cLocks > 0)
[4837]396 return DISP_E_ARRAYISLOCKED;
397
398 /* The array is unlocked, then, deallocate memory */
[9400]399 if(HeapFree( GetProcessHeap(), 0, psa) == FALSE)
[4837]400 return E_UNEXPECTED;
[9400]401
[4837]402 return(S_OK);
403}
404
405
406/*************************************************************************
[6944]407 * SafeArrayLock (OLEAUT32.21)
[4837]408 * Increment the lock counter
409 *
410 * Doc says (MSDN Library ) that psa->pvData should be made available (!= NULL)
[9400]411 * only when psa->cLocks is > 0... I don't get it since pvData is allocated
412 * before the array is locked, therefore
[4837]413 */
414HRESULT WINAPI SafeArrayLock(
415 SAFEARRAY *psa)
416{
[9400]417 if(! validArg(psa))
[4837]418 return E_INVALIDARG;
419
420 psa->cLocks++;
421
422 return(S_OK);
423}
424
425/*************************************************************************
[6944]426 * SafeArrayUnlock (OLEAUT32.22)
[4837]427 * Decrement the lock counter
428 */
429HRESULT WINAPI SafeArrayUnlock(
430 SAFEARRAY *psa)
431{
[9400]432 if(! validArg(psa))
[4837]433 return E_INVALIDARG;
434
[9400]435 if (psa->cLocks > 0)
[4837]436 psa->cLocks--;
437
438 return(S_OK);
439}
440
441
442/*************************************************************************
[6944]443 * SafeArrayPutElement (OLEAUT32.26)
[4837]444 * Set the data at the given coordinate
445 */
446HRESULT WINAPI SafeArrayPutElement(
[9400]447 SAFEARRAY *psa,
448 LONG *rgIndices,
[4837]449 void *pv)
450{
[9400]451 ULONG stepCountInSAData = 0; /* Number of array item to skip to get to
[4837]452 the desired one... */
453 PVOID elementStorageAddress = NULL; /* Adress to store the data */
454
455 /* Validate the index given */
[9400]456 if(! validCoordinate(rgIndices, psa))
[4837]457 return DISP_E_BADINDEX;
458 if(! validArg(psa))
459 return E_INVALIDARG;
460
461 if( SafeArrayLock(psa) == S_OK) {
462
463 /* Figure out the number of items to skip */
464 stepCountInSAData = calcDisplacement(rgIndices, psa->rgsabound, psa->cDims);
[9400]465
[4837]466 /* Figure out the number of byte to skip ... */
467 elementStorageAddress = (char *) psa->pvData+(stepCountInSAData*psa->cbElements);
[9400]468
[4837]469 if(isPointer(psa->fFeatures)) { /* increment ref count for this pointer */
470
[9400]471 *((PVOID*)elementStorageAddress) = *(PVOID*)pv;
[4837]472 IUnknown_AddRef( *(IUnknown**)pv);
473
[9400]474 } else {
[4837]475
476 if(psa->fFeatures == FADF_BSTR) { /* Create a new object */
[6944]477 BSTR pbstrReAllocStr = NULL;
478 if(pv &&
479 ((pbstrReAllocStr = SYSDUPSTRING( (OLECHAR*)pv )) == NULL)) {
[9400]480 SafeArrayUnlock(psa);
[4837]481 return E_OUTOFMEMORY;
[9400]482 } else
[4837]483 *((BSTR*)elementStorageAddress) = pbstrReAllocStr;
[6944]484 }
485 else if(psa->fFeatures == FADF_VARIANT) {
486 HRESULT hr = VariantCopy(elementStorageAddress, pv);
487 if (FAILED(hr)) {
488 SafeArrayUnlock(psa);
489 return hr;
490 }
491 }
492 else /* duplicate the memory */
[4837]493 memcpy(elementStorageAddress, pv, SafeArrayGetElemsize(psa) );
494 }
495
496 } else {
497 ERR("SafeArray: Cannot lock array....\n");
498 return E_UNEXPECTED; /* UNDOC error condition */
499 }
500
501 TRACE("SafeArray: item put at adress %p.\n",elementStorageAddress);
[9400]502 return SafeArrayUnlock(psa);
[4837]503}
504
505
506/*************************************************************************
[6944]507 * SafeArrayGetElement (OLEAUT32.25)
[4837]508 * Return the data element corresponding the the given coordinate
509 */
510HRESULT WINAPI SafeArrayGetElement(
[9400]511 SAFEARRAY *psa,
512 LONG *rgIndices,
[4837]513 void *pv)
514{
[9400]515 ULONG stepCountInSAData = 0; /* Number of array item to skip to get to
[4837]516 the desired one... */
517 PVOID elementStorageAddress = NULL; /* Adress to store the data */
518
[9400]519 if(! validArg(psa))
[4837]520 return E_INVALIDARG;
[9400]521
[4837]522 if(! validCoordinate(rgIndices, psa)) /* Validate the index given */
523 return(DISP_E_BADINDEX);
524
525 if( SafeArrayLock(psa) == S_OK) {
526
527 /* Figure out the number of items to skip */
528 stepCountInSAData = calcDisplacement(rgIndices, psa->rgsabound, psa->cDims);
[9400]529
[4837]530 /* Figure out the number of byte to skip ... */
531 elementStorageAddress = (char *) psa->pvData+(stepCountInSAData*psa->cbElements);
[9400]532
[4837]533 if( psa->fFeatures == FADF_BSTR) { /* reallocate the obj */
[6944]534 BSTR pbstrStoredStr = *(OLECHAR**)elementStorageAddress;
535 BSTR pbstrReturnedStr = NULL;
536 if( pbstrStoredStr &&
537 ((pbstrReturnedStr = SYSDUPSTRING( pbstrStoredStr )) == NULL) ) {
[4837]538 SafeArrayUnlock(psa);
539 return E_OUTOFMEMORY;
[9400]540 } else
541 *((BSTR*)pv) = pbstrReturnedStr;
[6944]542 }
543 else if( psa->fFeatures == FADF_VARIANT) {
[7916]544 HRESULT hr;
545 VariantInit(pv);
546 hr = VariantCopy(pv, elementStorageAddress);
[6944]547 if (FAILED(hr)) {
548 SafeArrayUnlock(psa);
549 return hr;
550 }
551 }
552 else if( isPointer(psa->fFeatures) ) /* simply copy the pointer */
[9400]553 *(PVOID*)pv = *((PVOID*)elementStorageAddress);
[4837]554 else /* copy the bytes */
[6944]555 memcpy(pv, elementStorageAddress, psa->cbElements );
[4837]556
557 } else {
558 ERR("SafeArray: Cannot lock array....\n");
559 return E_UNEXPECTED; /* UNDOC error condition */
560 }
561
[9400]562 return( SafeArrayUnlock(psa) );
[4837]563}
564
565/*************************************************************************
[6944]566 * SafeArrayGetUBound (OLEAUT32.19)
[4837]567 * return the UP bound for a given array dimension
568 */
569HRESULT WINAPI SafeArrayGetUBound(
[9400]570 SAFEARRAY *psa,
[4837]571 UINT nDim,
572 LONG *plUbound)
573{
[9400]574 if(! validArg(psa))
[4837]575 return E_INVALIDARG;
576
[9400]577 if(nDim > psa->cDims)
[4837]578 return DISP_E_BADINDEX;
579
[6944]580 if(0 == nDim)
581 return DISP_E_BADINDEX;
582
[9400]583 *plUbound = psa->rgsabound[nDim-1].lLbound +
[4837]584 psa->rgsabound[nDim-1].cElements - 1;
585
586 return S_OK;
587}
588
589/*************************************************************************
[6944]590 * SafeArrayGetLBound (OLEAUT32.20)
[9400]591 * Return the LO bound for a given array dimension
[4837]592 */
593HRESULT WINAPI SafeArrayGetLBound(
594 SAFEARRAY *psa,
[9400]595 UINT nDim,
[4837]596 LONG *plLbound)
597{
[9400]598 if(! validArg(psa))
[4837]599 return E_INVALIDARG;
600
[9400]601 if(nDim > psa->cDims)
[4837]602 return DISP_E_BADINDEX;
603
[6944]604 if(0 == nDim)
605 return DISP_E_BADINDEX;
[9400]606
[4837]607 *plLbound = psa->rgsabound[nDim-1].lLbound;
608 return S_OK;
609}
610
611/*************************************************************************
[6944]612 * SafeArrayGetDim (OLEAUT32.17)
[4837]613 * returns the number of dimension in the array
614 */
615UINT WINAPI SafeArrayGetDim(
616 SAFEARRAY * psa)
[9400]617{
[4837]618 /*
619 * A quick test in Windows shows that the behavior here for an invalid
620 * pointer is to return 0.
621 */
[9400]622 if(! validArg(psa))
[4837]623 return 0;
624
625 return psa->cDims;
626}
627
628/*************************************************************************
[6944]629 * SafeArrayGetElemsize (OLEAUT32.18)
[4837]630 * Return the size of the element in the array
631 */
632UINT WINAPI SafeArrayGetElemsize(
633 SAFEARRAY * psa)
[9400]634{
[4837]635 /*
636 * A quick test in Windows shows that the behavior here for an invalid
637 * pointer is to return 0.
638 */
[9400]639 if(! validArg(psa))
[4837]640 return 0;
641
642 return psa->cbElements;
643}
644
645/*************************************************************************
[6944]646 * SafeArrayAccessData (OLEAUT32.23)
[9400]647 * increment the access count and return the data
[4837]648 */
649HRESULT WINAPI SafeArrayAccessData(
[9400]650 SAFEARRAY *psa,
[4837]651 void **ppvData)
[9400]652{
[4837]653 HRESULT hRes;
654
[9400]655 if(! validArg(psa))
[4837]656 return E_INVALIDARG;
657
658 hRes = SafeArrayLock(psa);
659
660 switch (hRes) {
[9400]661 case S_OK:
[4837]662 (*ppvData) = psa->pvData;
663 break;
664 case E_INVALIDARG:
665 (*ppvData) = NULL;
666 return E_INVALIDARG;
667 }
[9400]668
[4837]669 return S_OK;
670}
671
672
673/*************************************************************************
[6944]674 * SafeArrayUnaccessData (OLEAUT32.24)
[4837]675 * Decrement the access count
676 */
677HRESULT WINAPI SafeArrayUnaccessData(
678 SAFEARRAY * psa)
[9400]679{
680 if(! validArg(psa))
[4837]681 return E_INVALIDARG;
682
683 return(SafeArrayUnlock(psa));
684}
685
[9400]686/************************************************************************
[6944]687 * SafeArrayPtrOfIndex (OLEAUT32.148)
[4837]688 * Return a pointer to the element at rgIndices
689 */
690HRESULT WINAPI SafeArrayPtrOfIndex(
[9400]691 SAFEARRAY *psa,
692 LONG *rgIndices,
[4837]693 void **ppvData)
[9400]694{
695 ULONG stepCountInSAData = 0; /* Number of array item to skip to get to
[4837]696 the desired one... */
697
[9400]698 if(! validArg(psa))
[4837]699 return E_INVALIDARG;
700
[9400]701 if(! validCoordinate(rgIndices, psa))
[4837]702 return DISP_E_BADINDEX;
703
[7916]704 /* Although it is dangerous to do this without having a lock, it is not
705 * illegal. Microsoft do warn of the danger.
706 */
707
[4837]708 /* Figure out the number of items to skip */
709 stepCountInSAData = calcDisplacement(rgIndices, psa->rgsabound, psa->cDims);
[9400]710
[4837]711 *ppvData = (char *) psa->pvData+(stepCountInSAData*psa->cbElements);
712
713 return S_OK;
714}
715
[9400]716/************************************************************************
[6944]717 * SafeArrayDestroyData (OLEAUT32.39)
[4837]718 * Frees the memory data bloc
719 */
720HRESULT WINAPI SafeArrayDestroyData(
721 SAFEARRAY *psa)
[9400]722{
[4837]723 HRESULT hRes;
724 ULONG ulWholeArraySize; /* count spot in array */
725 ULONG ulDataIter; /* to iterate the data space */
726
[9400]727 if(! validArg(psa))
[4837]728 return E_INVALIDARG;
729
[9400]730 if(psa->cLocks > 0)
[4837]731 return DISP_E_ARRAYISLOCKED;
732
733 ulWholeArraySize = getArraySize(psa);
734
735 if(isPointer(psa->fFeatures)) { /* release the pointers */
[6944]736 IUnknown *punk;
[4837]737
738 for(ulDataIter=0; ulDataIter < ulWholeArraySize; ulDataIter++) {
[9400]739 punk = *(IUnknown**)((char *) psa->pvData+(ulDataIter*(psa->cbElements)));
[4837]740
[9400]741 if( punk != NULL)
[4837]742 IUnknown_Release(punk);
743 }
744
[6944]745 }
746 else if(psa->fFeatures & FADF_BSTR) { /* deallocate the obj */
747 BSTR bstr;
[4837]748
749 for(ulDataIter=0; ulDataIter < ulWholeArraySize; ulDataIter++) {
750 bstr = *(BSTR*)((char *) psa->pvData+(ulDataIter*(psa->cbElements)));
751
[9400]752 if( bstr != NULL)
[4837]753 SysFreeString( bstr );
754 }
755 }
[6944]756 else if(psa->fFeatures & FADF_VARIANT) { /* deallocate the obj */
757
758 for(ulDataIter=0; ulDataIter < ulWholeArraySize; ulDataIter++) {
759 VariantClear((VARIANT*)((char *) psa->pvData+(ulDataIter*(psa->cbElements))));
760 }
761 }
[9400]762
763 /* check if this array is a Vector, in which case do not free the data
[4837]764 block since it has been allocated by AllocDescriptor and therefore
765 deserve to be freed by DestroyDescriptor */
766 if(!(psa->fFeatures & FADF_CREATEVECTOR)) { /* Set when we do CreateVector */
767
768 /* free the whole chunk */
769 if((hRes = HeapFree( GetProcessHeap(), 0, psa->pvData)) == 0) /*falied*/
770 return E_UNEXPECTED; /* UNDOC error condition */
771
772 psa->pvData = NULL;
773 }
[9400]774
[4837]775 return S_OK;
776}
777
[9400]778/************************************************************************
[6944]779 * SafeArrayCopyData (OLEAUT32.412)
[4837]780 * Copy the psaSource's data block into psaTarget if dimension and size
781 * permits it.
782 */
783HRESULT WINAPI SafeArrayCopyData(
784 SAFEARRAY *psaSource,
785 SAFEARRAY **psaTarget)
[9400]786{
[4837]787 USHORT cDimCount; /* looper */
788 LONG lDelta; /* looper */
[9400]789 IUnknown *punk;
[4837]790 ULONG ulWholeArraySize; /* Number of item in SA */
791 BSTR bstr;
792
[9400]793 if(! (validArg(psaSource) && validArg(*psaTarget)) )
[4837]794 return E_INVALIDARG;
795
796 if(SafeArrayGetDim(psaSource) != SafeArrayGetDim(*psaTarget))
797 return E_INVALIDARG;
798
[9400]799 ulWholeArraySize = getArraySize(psaSource);
[4837]800
801 /* The two arrays boundaries must be of same lenght */
802 for(cDimCount=0;cDimCount < psaSource->cDims; cDimCount++)
[9400]803 if( psaSource->rgsabound[cDimCount].cElements !=
[4837]804 (*psaTarget)->rgsabound[cDimCount].cElements)
805 return E_INVALIDARG;
806
[9400]807 if( isPointer((*psaTarget)->fFeatures) ) { /* the target contains ptr
[4837]808 that must be released */
809 for(lDelta=0;lDelta < ulWholeArraySize; lDelta++) {
810 punk = *(IUnknown**)
811 ((char *) (*psaTarget)->pvData + (lDelta * (*psaTarget)->cbElements));
812
[9400]813 if( punk != NULL)
[4837]814 IUnknown_Release(punk);
815 }
816
[6944]817 }
818 else if( (*psaTarget)->fFeatures & FADF_BSTR) { /* the target contain BSTR
[9400]819 that must be freed */
[4837]820 for(lDelta=0;lDelta < ulWholeArraySize; lDelta++) {
[9400]821 bstr =
[4837]822 *(BSTR*)((char *) (*psaTarget)->pvData + (lDelta * (*psaTarget)->cbElements));
823
[9400]824 if( bstr != NULL)
[4837]825 SysFreeString( bstr );
826 }
827 }
[6944]828 else if( (*psaTarget)->fFeatures & FADF_VARIANT) {
[4837]829
[6944]830 for(lDelta=0;lDelta < ulWholeArraySize; lDelta++) {
831 VariantClear((VARIANT*)((char *) (*psaTarget)->pvData + (lDelta * (*psaTarget)->cbElements)));
832 }
833 }
834
[4837]835 return duplicateData(psaSource, psaTarget);
836}
837
[9400]838/************************************************************************
[6944]839 * SafeArrayDestroy (OLEAUT32.16)
[4837]840 * Deallocates all memory reserved for the SafeArray
841 */
842HRESULT WINAPI SafeArrayDestroy(
843 SAFEARRAY * psa)
[9400]844{
[4837]845 HRESULT hRes;
846
[9400]847 if(! validArg(psa))
[4837]848 return E_INVALIDARG;
849
[9400]850 if(psa->cLocks > 0)
[4837]851 return DISP_E_ARRAYISLOCKED;
852
853 if((hRes = SafeArrayDestroyData( psa )) == S_OK)
854 if((hRes = SafeArrayDestroyDescriptor( psa )) == S_OK)
855 return S_OK;
856
857 return E_UNEXPECTED; /* UNDOC error condition */
858}
859
[9400]860/************************************************************************
[6944]861 * SafeArrayCopy (OLEAUT32.27)
[4837]862 * Make a dupplicate of a SafeArray
863 */
864HRESULT WINAPI SafeArrayCopy(
[9400]865 SAFEARRAY *psa,
[4837]866 SAFEARRAY **ppsaOut)
[9400]867{
[4837]868 HRESULT hRes;
869 DWORD dAllocSize;
870 ULONG ulWholeArraySize; /* size of the thing */
871
[9400]872 if(! validArg(psa))
[4837]873 return E_INVALIDARG;
874
875 if((hRes=SafeArrayAllocDescriptor(psa->cDims, ppsaOut)) == S_OK){
876
877 /* Duplicate the SAFEARRAY struc */
[9400]878 memcpy(*ppsaOut, psa,
[4837]879 sizeof(*psa)+(sizeof(*(psa->rgsabound))*(psa->cDims-1)));
880
881 (*ppsaOut)->pvData = NULL; /* do not point to the same data area */
882
883 /* make sure the new safe array doesn't have the FADF_CREATEVECTOR flag,
884 because the data has not been allocated with the descriptor. */
[9400]885 (*ppsaOut)->fFeatures &= ~FADF_CREATEVECTOR;
886
887 /* Get the allocated memory size for source and allocate it for target */
[4837]888 ulWholeArraySize = getArraySize(psa); /* Number of item in SA */
889 dAllocSize = ulWholeArraySize*psa->cbElements;
890
[9400]891 (*ppsaOut)->pvData =
[4837]892 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dAllocSize);
893 if( (*ppsaOut)->pvData != NULL) { /* HeapAlloc succeed */
894
895 if( (hRes=duplicateData(psa, ppsaOut)) != S_OK) { /* E_OUTOFMEMORY */
896 HeapFree(GetProcessHeap(), 0, (*ppsaOut)->pvData);
897 (*ppsaOut)->pvData = NULL;
898 SafeArrayDestroyDescriptor(*ppsaOut);
899 return hRes;
900 }
[9400]901
[4837]902 } else { /* failed to allocate or dupplicate... */
903 SafeArrayDestroyDescriptor(*ppsaOut);
904 return E_UNEXPECTED; /* UNDOC error condition */
905 }
906 } else { /* failed to allocate mem for descriptor */
907 return E_OUTOFMEMORY; /* UNDOC error condiftion */
908 }
909
910 return S_OK;
911}
912
[9400]913/************************************************************************
[6944]914 * SafeArrayCreateVector (OLEAUT32.411)
[9400]915 * Creates a one dimension safearray where the data is next to the
[4837]916 * SAFEARRAY structure.
917 */
918SAFEARRAY* WINAPI SafeArrayCreateVector(
[9400]919 VARTYPE vt,
920 LONG lLbound,
921 ULONG cElements)
922{
[4837]923 SAFEARRAY *psa;
924
925 /* Validate supported VARTYPE */
926 if ( (vt >= LAST_VARTYPE) ||
927 ( VARTYPE_SIZE[vt] == VARTYPE_NOT_SUPPORTED ) )
928 return NULL;
929
930 /* Allocate memory for the array descriptor and data contiguously */
[9400]931 if( FAILED( psa = HeapAlloc( GetProcessHeap(),
932 HEAP_ZERO_MEMORY,
[4837]933 (sizeof(*psa) + (VARTYPE_SIZE[vt] * cElements))))) {
934 return NULL;
935 }
[9400]936
937 /* setup data members... */
[4837]938 psa->cDims = 1; /* always and forever */
939 psa->fFeatures = getFeatures(vt) | FADF_CREATEVECTOR; /* undocumented flag used by Microsoft */
940 psa->cLocks = 0;
941 psa->pvData = (BYTE*)psa + sizeof(*psa);
942 psa->cbElements = VARTYPE_SIZE[vt];
943
944 psa->rgsabound[0].cElements = cElements;
945 psa->rgsabound[0].lLbound = lLbound;
946
[9400]947 return(psa);
948}
[4837]949
[9400]950/************************************************************************
[6944]951 * SafeArrayRedim (OLEAUT32.40)
[4837]952 * Changes the caracteristics of the last dimension of the SafeArray
953 */
954HRESULT WINAPI SafeArrayRedim(
[9400]955 SAFEARRAY *psa,
[4837]956 SAFEARRAYBOUND *psaboundNew)
[9400]957{
[4837]958 LONG lDelta; /* hold difference in size */
959 USHORT cDims=1; /* dims counter */
960
[9400]961 if( !validArg(psa) )
[4837]962 return E_INVALIDARG;
963
[9400]964 if( psa->cLocks > 0 )
[4837]965 return DISP_E_ARRAYISLOCKED;
966
[9400]967 if( psa->fFeatures & FADF_FIXEDSIZE )
[4837]968 return E_INVALIDARG;
969
[9400]970 if( SafeArrayLock(psa)==E_UNEXPECTED )
[4837]971 return E_UNEXPECTED;/* UNDOC error condition */
972
973 /* find the delta in number of array spot to apply to the new array */
974 lDelta = psaboundNew->cElements - psa->rgsabound[0].cElements;
975 for(; cDims < psa->cDims; cDims++)
976 /* delta in number of spot implied by modifying the last dimension */
977 lDelta *= psa->rgsabound[cDims].cElements;
978
[7916]979 TRACE("elements=%ld, Lbound=%ld (delta=%ld)\n", psaboundNew->cElements, psaboundNew->lLbound, lDelta);
980
[4837]981 if (lDelta == 0) { ;/* same size, maybe a change of lLbound, just set it */
982
983 } else /* need to enlarge (lDelta +) reduce (lDelta -) */
[9400]984 if(! resizeSafeArray(psa, lDelta))
[4837]985 return E_UNEXPECTED; /* UNDOC error condition */
986
[9400]987 /* the only modifyable dimension sits in [0] as the dimensions were reversed
[4837]988 at array creation time... */
989 psa->rgsabound[0].cElements = psaboundNew->cElements;
990 psa->rgsabound[0].lLbound = psaboundNew->lLbound;
991
992 return SafeArrayUnlock(psa);
993}
994
995/************************************************************************
996 * NOT WINDOWS API - SafeArray* Utility functions
997 ************************************************************************/
998
[9400]999/************************************************************************
[4837]1000 * Used to validate the SAFEARRAY type of arg
1001 */
1002static BOOL validArg(
[9400]1003 SAFEARRAY *psa)
[4837]1004{
1005 SAFEARRAYBOUND *sab;
1006 LONG psaSize = 0;
1007 LONG descSize = 0;
1008 LONG fullSize = 0;
1009
1010 /*
1011 * Let's check for the null pointer just in case.
1012 */
1013 if (psa == NULL)
1014 return FALSE;
1015
1016 /* Check whether the size of the chunk makes sense... That's the only thing
1017 I can think of now... */
[6944]1018
[4837]1019 psaSize = HeapSize(GetProcessHeap(), 0, psa);
1020 if (psaSize == -1)
1021 /* uh, foreign heap. Better don't mess with it ! */
1022 return TRUE;
1023
1024 /* size of the descriptor when the SA is not created with CreateVector */
1025 descSize = sizeof(*psa) + (sizeof(*sab) * (psa->cDims-1));
1026
1027 /* size of the descriptor + data when created with CreateVector */
1028 fullSize = sizeof(*psa) + (psa->cbElements * psa->rgsabound[0].cElements);
1029
1030 return((psaSize >= descSize) || (psaSize >= fullSize));
1031}
1032
[9400]1033/************************************************************************
[4837]1034 * Used to reallocate memory
1035 */
1036static BOOL resizeSafeArray(
[9400]1037 SAFEARRAY *psa,
[4837]1038 LONG lDelta)
1039{
1040 ULONG ulWholeArraySize; /* use as multiplicator */
[9400]1041 PVOID pvNewBlock = NULL;
[4837]1042 IUnknown *punk;
1043 BSTR bstr;
1044
1045 ulWholeArraySize = getArraySize(psa);
1046
1047 if(lDelta < 0) { /* array needs to be shorthen */
1048 if( isPointer(psa->fFeatures)) /* ptr that need to be released */
[6944]1049 for(;lDelta < 0; lDelta++) {
[6711]1050 punk = *(IUnknown**)
[4837]1051 ((char *) psa->pvData+((ulWholeArraySize+lDelta)*psa->cbElements));
[9400]1052
[4837]1053 if( punk != NULL )
1054 IUnknown_Release(punk);
[6711]1055 }
[4837]1056
1057 else if(psa->fFeatures & FADF_BSTR) /* BSTR that need to be freed */
[6944]1058 for(;lDelta < 0; lDelta++) {
[4837]1059 bstr = *(BSTR*)
1060 ((char *) psa->pvData+((ulWholeArraySize+lDelta)*psa->cbElements));
1061
1062 if( bstr != NULL )
1063 SysFreeString( bstr );
1064 }
[6944]1065 else if(psa->fFeatures & FADF_VARIANT)
1066 for(;lDelta < 0; lDelta++) {
1067 VariantClear((VARIANT*)((char *) psa->pvData+((ulWholeArraySize+lDelta)*psa->cbElements)));
1068 }
[4837]1069 }
1070
1071 if (!(psa->fFeatures & FADF_CREATEVECTOR))
1072 {
[9400]1073 /* Ok now, if we are enlarging the array, we *MUST* move the whole block
[4837]1074 pointed to by pvData. If we are shorthening the array, this move is
[9400]1075 optional but we do it anyway becuase the benefit is that we are
[4837]1076 releasing to the system the unused memory */
1077
[9400]1078 if((pvNewBlock = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, psa->pvData,
1079 (ulWholeArraySize + lDelta) * psa->cbElements)) == NULL)
[4837]1080 return FALSE; /* TODO If we get here it means:
1081 SHRINK situation : we've deleted the undesired
1082 data and did not release the memory
1083 GROWING situation: we've been unable to grow the array
1084 */
1085 }
1086 else
1087 {
[9400]1088 /* Allocate a new block, because the previous data has been allocated with
[4837]1089 the descriptor in SafeArrayCreateVector function. */
1090
[7916]1091 if((pvNewBlock = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
[9400]1092 ulWholeArraySize * psa->cbElements)) == NULL)
[4837]1093 return FALSE;
1094
1095 psa->fFeatures &= ~FADF_CREATEVECTOR;
1096 }
1097 /* reassign to the new block of data */
1098 psa->pvData = pvNewBlock;
1099 return TRUE;
1100}
1101
[9400]1102/************************************************************************
1103 * Used to set the fFeatures data member of the SAFEARRAY structure.
[4837]1104 */
1105static INT getFeatures(
[9400]1106 VARTYPE vt)
[4837]1107{
1108 switch(vt) {
[6944]1109 case VT_BSTR: return FADF_BSTR;
[4837]1110 case VT_UNKNOWN: return FADF_UNKNOWN;
1111 case VT_DISPATCH: return FADF_DISPATCH;
[6944]1112 case VT_VARIANT: return FADF_VARIANT;
[4837]1113 }
1114 return 0;
1115}
1116
[9400]1117/************************************************************************
1118 * Used to figure out if the fFeatures data member of the SAFEARRAY
1119 * structure contain any information about the type of data stored...
[4837]1120 */
1121static BOOL isPointer(
[9400]1122 USHORT feature)
[4837]1123{
1124 switch(feature) {
1125 case FADF_UNKNOWN: return TRUE; /* those are pointers */
1126 case FADF_DISPATCH: return TRUE;
1127 }
1128 return FALSE;
1129}
1130
[9400]1131/************************************************************************
1132 * Used to calculate the displacement when accessing or modifying
[4837]1133 * safearray data set.
1134 *
1135 * Parameters: - LONG *coor is the desired location in the multidimension
1136 * table. Ex for a 3 dim table: coor[] = {1,2,3};
1137 * - ULONG *mat is the format of the table. Ex for a 3 dim
1138 * table mat[] = {4,4,4};
1139 * - USHORT dim is the number of dimension of the SafeArray
1140 */
1141static ULONG calcDisplacement(
[9400]1142 LONG *coor,
1143 SAFEARRAYBOUND *mat,
1144 LONG dim)
[4837]1145{
1146 ULONG res = 0;
1147 LONG iterDim;
1148
[9400]1149 for(iterDim=0; iterDim<dim; iterDim++)
[4837]1150 /* the -mat[dim] bring coor[dim] relative to 0 for calculation */
[9400]1151 res += ((coor[iterDim]-mat[iterDim].lLbound) *
[4837]1152 endOfDim(coor, mat, iterDim+1, dim));
1153
1154 TRACE("SafeArray: calculated displacement is %lu.\n", res);
1155 return(res);
1156}
1157
[9400]1158/************************************************************************
1159 * Recursivity agent for calcDisplacement method. Used within Put and
[4837]1160 * Get methods.
1161 */
1162static INT endOfDim(
[9400]1163 LONG *coor,
1164 SAFEARRAYBOUND *mat,
1165 LONG dim,
1166 LONG realDim)
[4837]1167{
[9400]1168 if(dim==realDim)
[4837]1169 return 1;
[9400]1170 else
[4837]1171 return (endOfDim(coor, mat, dim+1, realDim) * mat[dim].cElements);
1172}
1173
1174
[9400]1175/************************************************************************
1176 * Method used to validate the coordinate received in Put and Get
[4837]1177 * methods.
1178 */
1179static BOOL validCoordinate(
[9400]1180 LONG *coor,
1181 SAFEARRAY *psa)
[4837]1182{
1183 INT iter=0;
1184 LONG lUBound;
1185 LONG lLBound;
1186 HRESULT hRes;
1187
[7916]1188 if (!psa->cDims) return FALSE;
[4837]1189 for(; iter<psa->cDims; iter++) {
[7916]1190 TRACE("coor[%d]=%ld\n", iter, coor[iter]);
[6944]1191 if((hRes = SafeArrayGetLBound(psa, (iter+1), &lLBound)) != S_OK)
[4837]1192 return FALSE;
[6944]1193 if((hRes = SafeArrayGetUBound(psa, (iter+1), &lUBound)) != S_OK)
[4837]1194 return FALSE;
[7916]1195
[9400]1196 if(lLBound > lUBound)
1197 return FALSE;
1198
[7916]1199 if((coor[iter] < lLBound) || (coor[iter] > lUBound))
[4837]1200 return FALSE;
1201 }
[7916]1202 return TRUE;
[9400]1203}
[4837]1204
[9400]1205/************************************************************************
[4837]1206 * Method used to calculate the number of cells of the SA
1207 */
1208static ULONG getArraySize(
[9400]1209 SAFEARRAY *psa)
[4837]1210{
[9400]1211 USHORT cCount;
[4837]1212 ULONG ulWholeArraySize = 1;
1213
1214 for(cCount=0; cCount < psa->cDims; cCount++) /* foreach dimensions... */
1215 ulWholeArraySize *= psa->rgsabound[cCount].cElements;
1216
[9400]1217 return ulWholeArraySize;
[4837]1218}
1219
1220
[9400]1221/************************************************************************
[4837]1222 * Method used to handle data space dupplication for Copy32 and CopyData32
1223 */
1224static HRESULT duplicateData(
[9400]1225 SAFEARRAY *psa,
1226 SAFEARRAY **ppsaOut)
[4837]1227{
1228 ULONG ulWholeArraySize; /* size of the thing */
1229 LONG lDelta;
1230
1231 ulWholeArraySize = getArraySize(psa); /* Number of item in SA */
[9400]1232
[4837]1233 SafeArrayLock(*ppsaOut);
1234
[9400]1235 if( isPointer(psa->fFeatures) ) { /* If datatype is object increment
[4837]1236 object's reference count */
[6944]1237 IUnknown *punk;
[4837]1238
1239 for(lDelta=0; lDelta < ulWholeArraySize; lDelta++) {
1240 punk = *(IUnknown**)((char *) psa->pvData+(lDelta * psa->cbElements));
1241
1242 if( punk != NULL)
1243 IUnknown_AddRef(punk);
1244 }
1245
1246 /* Copy the source array data into target array */
[9400]1247 memcpy((*ppsaOut)->pvData, psa->pvData,
[4837]1248 ulWholeArraySize*psa->cbElements);
1249
[6944]1250 }
[9400]1251 else if( psa->fFeatures & FADF_BSTR ) { /* if datatype is BSTR allocate
[6944]1252 the BSTR in the new array */
1253 BSTR pbstrReAllocStr = NULL;
[4837]1254
1255 for(lDelta=0; lDelta < ulWholeArraySize; lDelta++) {
[6944]1256 if(( pbstrReAllocStr = SYSDUPSTRING(
[4837]1257 *(BSTR*)((char *) psa->pvData+(lDelta * psa->cbElements)))) == NULL) {
1258
1259 SafeArrayUnlock(*ppsaOut);
1260 return E_OUTOFMEMORY;
1261 }
1262
[9400]1263 *((BSTR*)((char *) (*ppsaOut)->pvData+(lDelta * psa->cbElements))) =
[4837]1264 pbstrReAllocStr;
1265 }
1266
[6944]1267 }
1268 else if( psa->fFeatures & FADF_VARIANT ) {
[4837]1269
[6944]1270 for(lDelta=0; lDelta < ulWholeArraySize; lDelta++) {
1271 VariantCopy((VARIANT*)((char *) (*ppsaOut)->pvData+(lDelta * psa->cbElements)),
1272 (VARIANT*)((char *) psa->pvData+(lDelta * psa->cbElements)));
1273 }
1274
1275 }
1276 else { /* Simply copy the source array data into target array */
1277
[9400]1278 memcpy((*ppsaOut)->pvData, psa->pvData,
[4837]1279 ulWholeArraySize*psa->cbElements);
1280 }
1281
1282 SafeArrayUnlock(*ppsaOut);
1283
1284 return S_OK;
1285}
1286
1287
[9400]1288/************************************************************************
1289 * SafeArrayGetVartype (OLEAUT32.77)
[4837]1290 * Returns the VARTYPE stored in the given safearray
1291 */
[9400]1292HRESULT WINAPI SafeArrayGetVartype(
[4837]1293 SAFEARRAY* psa,
1294 VARTYPE* pvt)
1295{
1296 HRESULT hr = E_INVALIDARG;
1297 VARTYPE vt = VT_EMPTY;
1298
1299 /* const short VARTYPE_OFFSET = -4; */
1300
1301 if (psa->fFeatures & FADF_HAVEVARTYPE)
1302 {
1303 /* VT tag @ negative offset 4 in the array descriptor */
[6944]1304 FIXME("Returning VT_BSTR instead of VT_...\n");
[4837]1305 vt = VT_BSTR;
1306 }
1307 else if (psa->fFeatures & FADF_RECORD)
1308 {
1309 vt = VT_RECORD;
1310 }
[6944]1311 else if (psa->fFeatures & FADF_BSTR)
[4837]1312 {
[6944]1313 vt = VT_BSTR;
[4837]1314 }
1315 else if (psa->fFeatures & FADF_UNKNOWN)
1316 {
1317 vt = VT_UNKNOWN;
1318 }
[6944]1319 else if (psa->fFeatures & FADF_DISPATCH)
1320 {
1321 vt = VT_DISPATCH;
1322 }
1323 else if (psa->fFeatures & FADF_VARIANT)
1324 {
1325 vt = VT_VARIANT;
1326 }
[4837]1327
1328 if (vt != VT_EMPTY)
1329 {
1330 *pvt = vt;
1331 hr = S_OK;
1332 }
[6944]1333
1334 TRACE("HRESULT = %08lx\n", hr);
[4837]1335 return hr;
1336}
Note: See TracBrowser for help on using the repository browser.