ReactOS  0.4.14-dev-41-g31d7680
safearray.c
Go to the documentation of this file.
1 /*************************************************************************
2  * OLE Automation - SafeArray
3  *
4  * This file contains the implementation of the SafeArray functions.
5  *
6  * Copyright 1999 Sylvain St-Germain
7  * Copyright 2002-2003 Marcus Meissner
8  * Copyright 2003 Jon Griffiths
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 /* Memory Layout of a SafeArray:
25  *
26  * -0x10: start of memory.
27  * -0x10: GUID for VT_DISPATCH and VT_UNKNOWN safearrays (if FADF_HAVEIID)
28  * -0x04: DWORD varianttype; (for all others, except VT_RECORD) (if FADF_HAVEVARTYPE)
29  * -0x4: IRecordInfo* iface; (if FADF_RECORD, for VT_RECORD (can be NULL))
30  * 0x00: SAFEARRAY,
31  * 0x10: SAFEARRAYBOUNDS[0...]
32  */
33 
34 #include "config.h"
35 
36 #include <string.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 
40 #define COBJMACROS
41 
42 #include "windef.h"
43 #include "winerror.h"
44 #include "winbase.h"
45 #include "variant.h"
46 #include "wine/debug.h"
47 
49 
50 /************************************************************************
51  * SafeArray {OLEAUT32}
52  *
53  * NOTES
54  * The SafeArray data type provides the underlying interface for Ole
55  * Automations arrays, used for example to represent array types in
56  * Visual Basic(tm) and to gather user defined parameters for invocation through
57  * an IDispatch interface.
58  *
59  * Safe arrays provide bounds checking and automatically manage the data
60  * types they contain, for example handing reference counting and copying
61  * of interface pointers. User defined types can be stored in arrays
62  * using the IRecordInfo interface.
63  *
64  * There are two types of SafeArray, normal and vectors. Normal arrays can have
65  * multiple dimensions and the data for the array is allocated separately from
66  * the array header. This is the most flexible type of array. Vectors, on the
67  * other hand, are fixed in size and consist of a single allocated block, and a
68  * single dimension.
69  *
70  * DATATYPES
71  * The following types of data can be stored within a SafeArray.
72  * Numeric:
73  *| VT_I1, VT_UI1, VT_I2, VT_UI2, VT_I4, VT_UI4, VT_I8, VT_UI8, VT_INT, VT_UINT,
74  *| VT_R4, VT_R8, VT_CY, VT_DECIMAL
75  * Interfaces:
76  *| VT_DISPATCH, VT_UNKNOWN, VT_RECORD
77  * Other:
78  *| VT_VARIANT, VT_INT_PTR, VT_UINT_PTR, VT_BOOL, VT_ERROR, VT_DATE, VT_BSTR
79  *
80  * FUNCTIONS
81  * BstrFromVector()
82  * VectorFromBstr()
83  */
84 
85 /* Undocumented hidden space before the start of a SafeArray descriptor */
86 #define SAFEARRAY_HIDDEN_SIZE sizeof(GUID)
87 
88 /* features listed here are not propagated to newly created array or data copy
89  created with SafeArrayCopy()/SafeArrayCopyData() */
91  FADF_AUTO |
92  FADF_STATIC |
93  FADF_EMBEDDED |
94  FADF_FIXEDSIZE |
96 
97 /* Allocate memory */
98 static inline void* SAFEARRAY_Malloc(ULONG size)
99 {
100  void *ret = CoTaskMemAlloc(size);
101  if (ret)
102  memset(ret, 0, size);
103  return ret;
104 }
105 
106 /* Free memory */
107 static inline void SAFEARRAY_Free(void *ptr)
108 {
110 }
111 
112 /* Get the size of a supported VT type (0 means unsupported) */
114 {
115  switch (vt)
116  {
117  case VT_I1:
118  case VT_UI1: return sizeof(BYTE);
119  case VT_BOOL:
120  case VT_I2:
121  case VT_UI2: return sizeof(SHORT);
122  case VT_I4:
123  case VT_UI4:
124  case VT_R4:
125  case VT_ERROR: return sizeof(LONG);
126  case VT_R8:
127  case VT_I8:
128  case VT_UI8: return sizeof(LONG64);
129  case VT_INT:
130  case VT_UINT: return sizeof(INT);
131  case VT_INT_PTR:
132  case VT_UINT_PTR: return sizeof(UINT_PTR);
133  case VT_CY: return sizeof(CY);
134  case VT_DATE: return sizeof(DATE);
135  case VT_BSTR: return sizeof(BSTR);
136  case VT_DISPATCH: return sizeof(LPDISPATCH);
137  case VT_VARIANT: return sizeof(VARIANT);
138  case VT_UNKNOWN: return sizeof(LPUNKNOWN);
139  case VT_DECIMAL: return sizeof(DECIMAL);
140  /* Note: Return a non-zero size to indicate vt is valid. The actual size
141  * of a UDT is taken from the result of IRecordInfo_GetSize().
142  */
143  case VT_RECORD: return 32;
144  }
145  return 0;
146 }
147 
148 /* Set the hidden data for an array */
150 {
151  /* Implementation data is stored in the 4 bytes before the header */
152  LPDWORD lpDw = (LPDWORD)psa;
153  lpDw[-1] = dw;
154 }
155 
156 /* Get the hidden data from an array */
158 {
159  LPDWORD lpDw = (LPDWORD)psa;
160  return lpDw[-1];
161 }
162 
163 /* Get the number of cells in a SafeArray */
165 {
166  const SAFEARRAYBOUND* psab = psa->rgsabound;
167  USHORT cCount = psa->cDims;
168  ULONG ulNumCells = 1;
169 
170  while (cCount--)
171  {
172  /* This is a valid bordercase. See testcases. -Marcus */
173  if (!psab->cElements)
174  return 0;
175  ulNumCells *= psab->cElements;
176  psab++;
177  }
178  return ulNumCells;
179 }
180 
181 /* Allocate a descriptor for an array */
183 {
184  char *ptr = SAFEARRAY_Malloc(ulSize + SAFEARRAY_HIDDEN_SIZE);
185 
186  if (!ptr)
187  {
188  *ppsaOut = NULL;
189  return E_OUTOFMEMORY;
190  }
191 
192  *ppsaOut = (SAFEARRAY*)(ptr + SAFEARRAY_HIDDEN_SIZE);
193  return S_OK;
194 }
195 
196 /* Set the features of an array */
198 {
199  /* Set the IID if we have one, otherwise set the type */
200  if (vt == VT_DISPATCH)
201  {
202  psa->fFeatures = FADF_HAVEIID;
204  }
205  else if (vt == VT_UNKNOWN)
206  {
207  psa->fFeatures = FADF_HAVEIID;
209  }
210  else if (vt == VT_RECORD)
211  psa->fFeatures = FADF_RECORD;
212  else
213  {
214  psa->fFeatures = FADF_HAVEVARTYPE;
216  }
217 }
218 
219 /* Create an array */
220 static SAFEARRAY* SAFEARRAY_Create(VARTYPE vt, UINT cDims, const SAFEARRAYBOUND *rgsabound, ULONG ulSize)
221 {
222  SAFEARRAY *psa = NULL;
223  unsigned int i;
224 
225  if (!rgsabound)
226  return NULL;
227 
229  {
230  switch (vt)
231  {
232  case VT_BSTR: psa->fFeatures |= FADF_BSTR; break;
233  case VT_UNKNOWN: psa->fFeatures |= FADF_UNKNOWN; break;
234  case VT_DISPATCH: psa->fFeatures |= FADF_DISPATCH; break;
235  case VT_VARIANT: psa->fFeatures |= FADF_VARIANT; break;
236  }
237 
238  for (i = 0; i < cDims; i++)
239  memcpy(psa->rgsabound + i, rgsabound + cDims - 1 - i, sizeof(SAFEARRAYBOUND));
240 
241  if (ulSize)
242  psa->cbElements = ulSize;
243 
244  if (!psa->cbElements || FAILED(SafeArrayAllocData(psa)))
245  {
247  psa = NULL;
248  }
249  }
250  return psa;
251 }
252 
253 /* Create an array as a vector */
254 static SAFEARRAY* SAFEARRAY_CreateVector(VARTYPE vt, LONG lLbound, ULONG cElements, ULONG ulSize)
255 {
256  SAFEARRAY *psa = NULL;
257 
258  if (ulSize || (vt == VT_RECORD))
259  {
260  /* Allocate the header and data together */
261  if (SUCCEEDED(SAFEARRAY_AllocDescriptor(sizeof(SAFEARRAY) + ulSize * cElements, &psa)))
262  {
264 
265  psa->cDims = 1;
266  psa->fFeatures |= FADF_CREATEVECTOR;
267  psa->pvData = &psa[1]; /* Data follows the header */
268  psa->cbElements = ulSize;
269  psa->rgsabound[0].cElements = cElements;
270  psa->rgsabound[0].lLbound = lLbound;
271 
272  switch (vt)
273  {
274  case VT_BSTR: psa->fFeatures |= FADF_BSTR; break;
275  case VT_UNKNOWN: psa->fFeatures |= FADF_UNKNOWN; break;
276  case VT_DISPATCH: psa->fFeatures |= FADF_DISPATCH; break;
277  case VT_VARIANT: psa->fFeatures |= FADF_VARIANT; break;
278  }
279  }
280  }
281  return psa;
282 }
283 
284 /* Free data items in an array */
286 {
287  if (psa->pvData && !(psa->fFeatures & FADF_DATADELETED))
288  {
289  ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
290 
291  if (ulStartCell > ulCellCount) {
292  FIXME("unexpected ulCellCount %d, start %d\n",ulCellCount,ulStartCell);
293  return E_UNEXPECTED;
294  }
295 
296  ulCellCount -= ulStartCell;
297 
298  if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
299  {
300  LPUNKNOWN *lpUnknown = (LPUNKNOWN *)psa->pvData + ulStartCell;
301 
302  while(ulCellCount--)
303  {
304  if (*lpUnknown)
305  IUnknown_Release(*lpUnknown);
306  lpUnknown++;
307  }
308  }
309  else if (psa->fFeatures & FADF_RECORD)
310  {
311  IRecordInfo *lpRecInfo;
312 
313  if (SUCCEEDED(SafeArrayGetRecordInfo(psa, &lpRecInfo)))
314  {
315  PBYTE pRecordData = psa->pvData;
316  while(ulCellCount--)
317  {
318  IRecordInfo_RecordClear(lpRecInfo, pRecordData);
319  pRecordData += psa->cbElements;
320  }
321  IRecordInfo_Release(lpRecInfo);
322  }
323  }
324  else if (psa->fFeatures & FADF_BSTR)
325  {
326  BSTR* lpBstr = (BSTR*)psa->pvData + ulStartCell;
327 
328  while(ulCellCount--)
329  {
330  SysFreeString(*lpBstr);
331  lpBstr++;
332  }
333  }
334  else if (psa->fFeatures & FADF_VARIANT)
335  {
336  VARIANT* lpVariant = (VARIANT*)psa->pvData + ulStartCell;
337 
338  while(ulCellCount--)
339  {
340  HRESULT hRet = VariantClear(lpVariant);
341 
342  if (FAILED(hRet)) FIXME("VariantClear of element failed!\n");
343  lpVariant++;
344  }
345  }
346  }
347  return S_OK;
348 }
349 
350 /* Copy data items from one array to another. Destination data is freed before copy. */
352 {
353  HRESULT hr = S_OK;
354 
355  if (!psa->pvData)
356  return S_OK;
357 
358  if (!dest->pvData || psa->fFeatures & FADF_DATADELETED)
359  return E_INVALIDARG;
360  else
361  {
362  ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
363 
364  dest->fFeatures = (dest->fFeatures & FADF_CREATEVECTOR) | (psa->fFeatures & ~ignored_copy_features);
365 
366  if (psa->fFeatures & FADF_VARIANT)
367  {
368  VARIANT *src_var = psa->pvData;
369  VARIANT *dest_var = dest->pvData;
370 
371  while(ulCellCount--)
372  {
373  HRESULT hRet;
374 
375  /* destination is cleared automatically */
376  hRet = VariantCopy(dest_var, src_var);
377  if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%08x, element %u\n", hRet, ulCellCount);
378  src_var++;
379  dest_var++;
380  }
381  }
382  else if (psa->fFeatures & FADF_BSTR)
383  {
384  BSTR *src_bstr = psa->pvData;
385  BSTR *dest_bstr = dest->pvData;
386 
387  while(ulCellCount--)
388  {
389  SysFreeString(*dest_bstr);
390  if (*src_bstr)
391  {
392  *dest_bstr = SysAllocStringByteLen((char*)*src_bstr, SysStringByteLen(*src_bstr));
393  if (!*dest_bstr)
394  return E_OUTOFMEMORY;
395  }
396  else
397  *dest_bstr = NULL;
398  src_bstr++;
399  dest_bstr++;
400  }
401  }
402  else if (psa->fFeatures & FADF_RECORD)
403  {
404  BYTE *dest_data = dest->pvData;
405  BYTE *src_data = psa->pvData;
407 
409  while (ulCellCount--)
410  {
411  /* RecordCopy() clears destination record */
412  hr = IRecordInfo_RecordCopy(record, src_data, dest_data);
413  if (FAILED(hr)) break;
414  src_data += psa->cbElements;
415  dest_data += psa->cbElements;
416  }
417 
419  /* This value is set to 32 bytes by default on descriptor creation,
420  update with actual structure size. */
421  dest->cbElements = psa->cbElements;
422  IRecordInfo_Release(record);
423  }
424  else if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
425  {
426  IUnknown **dest_unk = dest->pvData;
427  IUnknown **src_unk = psa->pvData;
428 
429  /* release old iface, addref new one */
430  while (ulCellCount--)
431  {
432  if (*dest_unk)
433  IUnknown_Release(*dest_unk);
434  *dest_unk = *src_unk;
435  if (*dest_unk)
436  IUnknown_AddRef(*dest_unk);
437  src_unk++;
438  dest_unk++;
439  }
440  }
441  else
442  {
443  /* Copy the data over */
444  memcpy(dest->pvData, psa->pvData, ulCellCount * psa->cbElements);
445  }
446 
447  if (psa->fFeatures & FADF_HAVEIID)
448  {
449  GUID guid;
452  }
453  else if (psa->fFeatures & FADF_HAVEVARTYPE)
454  {
456  }
457  }
458 
459  return hr;
460 }
461 
462 /*************************************************************************
463  * SafeArrayAllocDescriptor (OLEAUT32.36)
464  *
465  * Allocate and initialise a descriptor for a SafeArray.
466  *
467  * PARAMS
468  * cDims [I] Number of dimensions of the array
469  * ppsaOut [O] Destination for new descriptor
470  *
471  * RETURNS
472  * Success: S_OK. ppsaOut is filled with a newly allocated descriptor.
473  * Failure: An HRESULT error code indicating the error.
474  *
475  * NOTES
476  * See SafeArray.
477  */
479 {
480  LONG allocSize;
481  HRESULT hr;
482 
483  TRACE("(%d,%p)\n", cDims, ppsaOut);
484 
485  if (!cDims || cDims >= 0x10000) /* Maximum 65535 dimensions */
486  return E_INVALIDARG;
487 
488  if (!ppsaOut)
489  return E_POINTER;
490 
491  /* We need enough space for the header and its bounds */
492  allocSize = sizeof(SAFEARRAY) + sizeof(SAFEARRAYBOUND) * (cDims - 1);
493 
494  hr = SAFEARRAY_AllocDescriptor(allocSize, ppsaOut);
495  if (FAILED(hr))
496  return hr;
497 
498  (*ppsaOut)->cDims = cDims;
499 
500  TRACE("(%d): %u bytes allocated for descriptor.\n", cDims, allocSize);
501  return S_OK;
502 }
503 
504 /*************************************************************************
505  * SafeArrayAllocDescriptorEx (OLEAUT32.41)
506  *
507  * Allocate and initialise a descriptor for a SafeArray of a given type.
508  *
509  * PARAMS
510  * vt [I] The type of items to store in the array
511  * cDims [I] Number of dimensions of the array
512  * ppsaOut [O] Destination for new descriptor
513  *
514  * RETURNS
515  * Success: S_OK. ppsaOut is filled with a newly allocated descriptor.
516  * Failure: An HRESULT error code indicating the error.
517  *
518  * NOTES
519  * - This function does not check that vt is an allowed VARTYPE.
520  * - Unlike SafeArrayAllocDescriptor(), vt is associated with the array.
521  * See SafeArray.
522  */
524 {
525  ULONG cbElements;
526  HRESULT hRet;
527 
528  TRACE("(%d->%s,%d,%p)\n", vt, debugstr_vt(vt), cDims, ppsaOut);
529 
530  cbElements = SAFEARRAY_GetVTSize(vt);
531  if (!cbElements)
532  WARN("Creating a descriptor with an invalid VARTYPE!\n");
533 
534  hRet = SafeArrayAllocDescriptor(cDims, ppsaOut);
535 
536  if (SUCCEEDED(hRet))
537  {
538  SAFEARRAY_SetFeatures(vt, *ppsaOut);
539  (*ppsaOut)->cbElements = cbElements;
540  }
541  return hRet;
542 }
543 
544 /*************************************************************************
545  * SafeArrayAllocData (OLEAUT32.37)
546  *
547  * Allocate the data area of a SafeArray.
548  *
549  * PARAMS
550  * psa [I] SafeArray to allocate the data area of.
551  *
552  * RETURNS
553  * Success: S_OK. The data area is allocated and initialised.
554  * Failure: An HRESULT error code indicating the error.
555  *
556  * NOTES
557  * See SafeArray.
558  */
560 {
561  HRESULT hRet = E_INVALIDARG;
562 
563  TRACE("(%p)\n", psa);
564 
565  if (psa)
566  {
567  ULONG ulSize = SAFEARRAY_GetCellCount(psa);
568 
569  psa->pvData = SAFEARRAY_Malloc(ulSize * psa->cbElements);
570 
571  if (psa->pvData)
572  {
573  hRet = S_OK;
574  TRACE("%u bytes allocated for data at %p (%u objects).\n",
575  ulSize * psa->cbElements, psa->pvData, ulSize);
576  }
577  else
578  hRet = E_OUTOFMEMORY;
579  }
580  return hRet;
581 }
582 
583 /*************************************************************************
584  * SafeArrayCreate (OLEAUT32.15)
585  *
586  * Create a new SafeArray.
587  *
588  * PARAMS
589  * vt [I] Type to store in the safe array
590  * cDims [I] Number of array dimensions
591  * rgsabound [I] Bounds of the array dimensions
592  *
593  * RETURNS
594  * Success: A pointer to a new array object.
595  * Failure: NULL, if any parameter is invalid or memory allocation fails.
596  *
597  * NOTES
598  * Win32 allows arrays with 0 sized dimensions. This bug is not reproduced
599  * in the Wine implementation.
600  * See SafeArray.
601  */
603 {
604  TRACE("(%d->%s,%d,%p)\n", vt, debugstr_vt(vt), cDims, rgsabound);
605 
606  if (vt == VT_RECORD)
607  return NULL;
608 
609  return SAFEARRAY_Create(vt, cDims, rgsabound, 0);
610 }
611 
612 /*************************************************************************
613  * SafeArrayCreateEx (OLEAUT32.15)
614  *
615  * Create a new SafeArray.
616  *
617  * PARAMS
618  * vt [I] Type to store in the safe array
619  * cDims [I] Number of array dimensions
620  * rgsabound [I] Bounds of the array dimensions
621  * pvExtra [I] Extra data
622  *
623  * RETURNS
624  * Success: A pointer to a new array object.
625  * Failure: NULL, if any parameter is invalid or memory allocation fails.
626  *
627  * NOTES
628  * See SafeArray.
629  */
631 {
632  ULONG ulSize = 0;
633  IRecordInfo* iRecInfo = pvExtra;
634  SAFEARRAY* psa;
635 
636  TRACE("(%d->%s,%d,%p,%p)\n", vt, debugstr_vt(vt), cDims, rgsabound, pvExtra);
637 
638  if (vt == VT_RECORD)
639  {
640  if (!iRecInfo)
641  return NULL;
642  IRecordInfo_GetSize(iRecInfo, &ulSize);
643  }
644  psa = SAFEARRAY_Create(vt, cDims, rgsabound, ulSize);
645 
646  if (pvExtra)
647  {
648  switch(vt)
649  {
650  case VT_RECORD:
651  SafeArraySetRecordInfo(psa, pvExtra);
652  break;
653  case VT_UNKNOWN:
654  case VT_DISPATCH:
655  SafeArraySetIID(psa, pvExtra);
656  break;
657  }
658  }
659  return psa;
660 }
661 
662 /************************************************************************
663  * SafeArrayCreateVector (OLEAUT32.411)
664  *
665  * Create a one dimensional, contiguous SafeArray.
666  *
667  * PARAMS
668  * vt [I] Type to store in the safe array
669  * lLbound [I] Lower bound of the array
670  * cElements [I] Number of elements in the array
671  *
672  * RETURNS
673  * Success: A pointer to a new array object.
674  * Failure: NULL, if any parameter is invalid or memory allocation fails.
675  *
676  * NOTES
677  * See SafeArray.
678  */
680 {
681  TRACE("(%d->%s,%d,%d\n", vt, debugstr_vt(vt), lLbound, cElements);
682 
683  if (vt == VT_RECORD)
684  return NULL;
685 
686  return SAFEARRAY_CreateVector(vt, lLbound, cElements, SAFEARRAY_GetVTSize(vt));
687 }
688 
689 /************************************************************************
690  * SafeArrayCreateVectorEx (OLEAUT32.411)
691  *
692  * Create a one dimensional, contiguous SafeArray.
693  *
694  * PARAMS
695  * vt [I] Type to store in the safe array
696  * lLbound [I] Lower bound of the array
697  * cElements [I] Number of elements in the array
698  * pvExtra [I] Extra data
699  *
700  * RETURNS
701  * Success: A pointer to a new array object.
702  * Failure: NULL, if any parameter is invalid or memory allocation fails.
703  *
704  * NOTES
705  * See SafeArray.
706  */
708 {
709  ULONG ulSize;
710  IRecordInfo* iRecInfo = pvExtra;
711  SAFEARRAY* psa;
712 
713  TRACE("(%d->%s,%d,%d,%p\n", vt, debugstr_vt(vt), lLbound, cElements, pvExtra);
714 
715  if (vt == VT_RECORD)
716  {
717  if (!iRecInfo)
718  return NULL;
719  IRecordInfo_GetSize(iRecInfo, &ulSize);
720  }
721  else
722  ulSize = SAFEARRAY_GetVTSize(vt);
723 
724  psa = SAFEARRAY_CreateVector(vt, lLbound, cElements, ulSize);
725 
726  if (pvExtra)
727  {
728  switch(vt)
729  {
730  case VT_RECORD:
731  SafeArraySetRecordInfo(psa, iRecInfo);
732  break;
733  case VT_UNKNOWN:
734  case VT_DISPATCH:
735  SafeArraySetIID(psa, pvExtra);
736  break;
737  }
738  }
739  return psa;
740 }
741 
742 /*************************************************************************
743  * SafeArrayDestroyDescriptor (OLEAUT32.38)
744  *
745  * Destroy a SafeArray.
746  *
747  * PARAMS
748  * psa [I] SafeArray to destroy.
749  *
750  * RETURNS
751  * Success: S_OK. The resources used by the array are freed.
752  * Failure: An HRESULT error code indicating the error.
753  *
754  * NOTES
755  * See SafeArray.
756  */
758 {
759  TRACE("(%p)\n", psa);
760 
761  if (psa)
762  {
763  LPVOID lpv = (char*)psa - SAFEARRAY_HIDDEN_SIZE;
764 
765  if (psa->cLocks)
766  return DISP_E_ARRAYISLOCKED; /* Can't destroy a locked array */
767 
768  if (psa->fFeatures & FADF_RECORD)
770 
771  if (psa->fFeatures & FADF_CREATEVECTOR &&
772  !(psa->fFeatures & FADF_DATADELETED))
773  SAFEARRAY_DestroyData(psa, 0); /* Data not previously deleted */
774 
775  SAFEARRAY_Free(lpv);
776  }
777  return S_OK;
778 }
779 
780 /*************************************************************************
781  * SafeArrayLock (OLEAUT32.21)
782  *
783  * Increment the lock counter of a SafeArray.
784  *
785  * PARAMS
786  * psa [O] SafeArray to lock
787  *
788  * RETURNS
789  * Success: S_OK. The array lock is incremented.
790  * Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if too many locks
791  * are held on the array at once.
792  *
793  * NOTES
794  * In Win32 these locks are not thread safe.
795  * See SafeArray.
796  */
798 {
799  ULONG ulLocks;
800 
801  TRACE("(%p)\n", psa);
802 
803  if (!psa)
804  return E_INVALIDARG;
805 
806  ulLocks = InterlockedIncrement( (LONG*) &psa->cLocks);
807 
808  if (ulLocks > 0xffff) /* Maximum of 16384 locks at a time */
809  {
810  WARN("Out of locks!\n");
811  InterlockedDecrement( (LONG*) &psa->cLocks);
812  return E_UNEXPECTED;
813  }
814  return S_OK;
815 }
816 
817 /*************************************************************************
818  * SafeArrayUnlock (OLEAUT32.22)
819  *
820  * Decrement the lock counter of a SafeArray.
821  *
822  * PARAMS
823  * psa [O] SafeArray to unlock
824  *
825  * RETURNS
826  * Success: S_OK. The array lock is decremented.
827  * Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if no locks are
828  * held on the array.
829  *
830  * NOTES
831  * See SafeArray.
832  */
834 {
835  TRACE("(%p)\n", psa);
836 
837  if (!psa)
838  return E_INVALIDARG;
839 
840  if (InterlockedDecrement( (LONG*) &psa->cLocks) < 0)
841  {
842  WARN("Unlocked but no lock held!\n");
843  InterlockedIncrement( (LONG*) &psa->cLocks);
844  return E_UNEXPECTED;
845  }
846  return S_OK;
847 }
848 
849 /*************************************************************************
850  * SafeArrayPutElement (OLEAUT32.26)
851  *
852  * Put an item into a SafeArray.
853  *
854  * PARAMS
855  * psa [I] SafeArray to insert into
856  * rgIndices [I] Indices to insert at
857  * pvData [I] Data to insert
858  *
859  * RETURNS
860  * Success: S_OK. The item is inserted
861  * Failure: An HRESULT error code indicating the error.
862  *
863  * NOTES
864  * See SafeArray.
865  */
867 {
868  HRESULT hRet;
869 
870  TRACE("(%p,%p,%p)\n", psa, rgIndices, pvData);
871 
872  if (!psa || !rgIndices)
873  return E_INVALIDARG;
874 
875  hRet = SafeArrayLock(psa);
876 
877  if (SUCCEEDED(hRet))
878  {
879  PVOID lpvDest;
880 
881  hRet = SafeArrayPtrOfIndex(psa, rgIndices, &lpvDest);
882 
883  if (SUCCEEDED(hRet))
884  {
885  if (psa->fFeatures & FADF_VARIANT)
886  {
887  VARIANT* lpVariant = pvData;
888  VARIANT* lpDest = lpvDest;
889 
890  hRet = VariantCopy(lpDest, lpVariant);
891  if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet);
892  }
893  else if (psa->fFeatures & FADF_BSTR)
894  {
895  BSTR lpBstr = (BSTR)pvData;
896  BSTR* lpDest = lpvDest;
897 
898  SysFreeString(*lpDest);
899 
900  *lpDest = SysAllocStringByteLen((char*)lpBstr, SysStringByteLen(lpBstr));
901  if (!*lpDest)
902  hRet = E_OUTOFMEMORY;
903  }
904  else if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
905  {
906  IUnknown *lpUnknown = pvData;
907  IUnknown **lpDest = lpvDest;
908 
909  if (lpUnknown)
910  IUnknown_AddRef(lpUnknown);
911  if (*lpDest)
912  IUnknown_Release(*lpDest);
913  *lpDest = lpUnknown;
914  }
915  else if (psa->fFeatures & FADF_RECORD)
916  {
918 
920  hRet = IRecordInfo_RecordCopy(record, pvData, lpvDest);
921  IRecordInfo_Release(record);
922  } else
923  /* Copy the data over */
924  memcpy(lpvDest, pvData, psa->cbElements);
925  }
927  }
928  return hRet;
929 }
930 
931 
932 /*************************************************************************
933  * SafeArrayGetElement (OLEAUT32.25)
934  *
935  * Get an item from a SafeArray.
936  *
937  * PARAMS
938  * psa [I] SafeArray to get from
939  * rgIndices [I] Indices to get from
940  * pvData [O] Destination for data
941  *
942  * RETURNS
943  * Success: S_OK. The item data is returned in pvData.
944  * Failure: An HRESULT error code indicating the error.
945  *
946  * NOTES
947  * See SafeArray.
948  */
950 {
951  HRESULT hRet;
952 
953  TRACE("(%p,%p,%p)\n", psa, rgIndices, pvData);
954 
955  if (!psa || !rgIndices || !pvData)
956  return E_INVALIDARG;
957 
958  hRet = SafeArrayLock(psa);
959 
960  if (SUCCEEDED(hRet))
961  {
962  PVOID lpvSrc;
963 
964  hRet = SafeArrayPtrOfIndex(psa, rgIndices, &lpvSrc);
965 
966  if (SUCCEEDED(hRet))
967  {
968  if (psa->fFeatures & FADF_VARIANT)
969  {
970  VARIANT* lpVariant = lpvSrc;
971  VARIANT* lpDest = pvData;
972 
973  /* The original content of pvData is ignored. */
974  V_VT(lpDest) = VT_EMPTY;
975  hRet = VariantCopy(lpDest, lpVariant);
976  if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet);
977  }
978  else if (psa->fFeatures & FADF_BSTR)
979  {
980  BSTR* lpBstr = lpvSrc;
981  BSTR* lpDest = pvData;
982 
983  if (*lpBstr)
984  {
985  *lpDest = SysAllocStringByteLen((char*)*lpBstr, SysStringByteLen(*lpBstr));
986  if (!*lpBstr)
987  hRet = E_OUTOFMEMORY;
988  }
989  else
990  *lpDest = NULL;
991  }
992  else if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
993  {
994  IUnknown **src_unk = lpvSrc;
995  IUnknown **dest_unk = pvData;
996 
997  if (*src_unk)
998  IUnknown_AddRef(*src_unk);
999  *dest_unk = *src_unk;
1000  }
1001  else if (psa->fFeatures & FADF_RECORD)
1002  {
1004 
1006  hRet = IRecordInfo_RecordCopy(record, lpvSrc, pvData);
1007  IRecordInfo_Release(record);
1008  }
1009  else
1010  /* Copy the data over */
1011  memcpy(pvData, lpvSrc, psa->cbElements);
1012  }
1014  }
1015  return hRet;
1016 }
1017 
1018 /*************************************************************************
1019  * SafeArrayGetUBound (OLEAUT32.19)
1020  *
1021  * Get the upper bound for a given SafeArray dimension
1022  *
1023  * PARAMS
1024  * psa [I] Array to get dimension upper bound from
1025  * nDim [I] The dimension number to get the upper bound of
1026  * plUbound [O] Destination for the upper bound
1027  *
1028  * RETURNS
1029  * Success: S_OK. plUbound contains the dimensions upper bound.
1030  * Failure: An HRESULT error code indicating the error.
1031  *
1032  * NOTES
1033  * See SafeArray.
1034  */
1036 {
1037  TRACE("(%p,%d,%p)\n", psa, nDim, plUbound);
1038 
1039  if (!psa || !plUbound)
1040  return E_INVALIDARG;
1041 
1042  if(!nDim || nDim > psa->cDims)
1043  return DISP_E_BADINDEX;
1044 
1045  *plUbound = psa->rgsabound[psa->cDims - nDim].lLbound +
1046  psa->rgsabound[psa->cDims - nDim].cElements - 1;
1047 
1048  return S_OK;
1049 }
1050 
1051 /*************************************************************************
1052  * SafeArrayGetLBound (OLEAUT32.20)
1053  *
1054  * Get the lower bound for a given SafeArray dimension
1055  *
1056  * PARAMS
1057  * psa [I] Array to get dimension lower bound from
1058  * nDim [I] The dimension number to get the lower bound of
1059  * plLbound [O] Destination for the lower bound
1060  *
1061  * RETURNS
1062  * Success: S_OK. plUbound contains the dimensions lower bound.
1063  * Failure: An HRESULT error code indicating the error.
1064  *
1065  * NOTES
1066  * See SafeArray.
1067  */
1069 {
1070  TRACE("(%p,%d,%p)\n", psa, nDim, plLbound);
1071 
1072  if (!psa || !plLbound)
1073  return E_INVALIDARG;
1074 
1075  if(!nDim || nDim > psa->cDims)
1076  return DISP_E_BADINDEX;
1077 
1078  *plLbound = psa->rgsabound[psa->cDims - nDim].lLbound;
1079  return S_OK;
1080 }
1081 
1082 /*************************************************************************
1083  * SafeArrayGetDim (OLEAUT32.17)
1084  *
1085  * Get the number of dimensions in a SafeArray.
1086  *
1087  * PARAMS
1088  * psa [I] Array to get the dimensions of
1089  *
1090  * RETURNS
1091  * The number of array dimensions in psa, or 0 if psa is NULL.
1092  *
1093  * NOTES
1094  * See SafeArray.
1095  */
1097 {
1098  TRACE("(%p) returning %d\n", psa, psa ? psa->cDims : 0u);
1099  return psa ? psa->cDims : 0;
1100 }
1101 
1102 /*************************************************************************
1103  * SafeArrayGetElemsize (OLEAUT32.18)
1104  *
1105  * Get the size of an element in a SafeArray.
1106  *
1107  * PARAMS
1108  * psa [I] Array to get the element size from
1109  *
1110  * RETURNS
1111  * The size of a single element in psa, or 0 if psa is NULL.
1112  *
1113  * NOTES
1114  * See SafeArray.
1115  */
1117 {
1118  TRACE("(%p) returning %d\n", psa, psa ? psa->cbElements : 0u);
1119  return psa ? psa->cbElements : 0;
1120 }
1121 
1122 /*************************************************************************
1123  * SafeArrayAccessData (OLEAUT32.23)
1124  *
1125  * Lock a SafeArray and return a pointer to its data.
1126  *
1127  * PARAMS
1128  * psa [I] Array to get the data pointer from
1129  * ppvData [O] Destination for the arrays data pointer
1130  *
1131  * RETURNS
1132  * Success: S_OK. ppvData contains the arrays data pointer, and the array
1133  * is locked.
1134  * Failure: An HRESULT error code indicating the error.
1135  *
1136  * NOTES
1137  * See SafeArray.
1138  */
1140 {
1141  HRESULT hr;
1142 
1143  TRACE("(%p,%p)\n", psa, ppvData);
1144 
1145  if(!psa || !ppvData)
1146  return E_INVALIDARG;
1147 
1148  hr = SafeArrayLock(psa);
1149  *ppvData = SUCCEEDED(hr) ? psa->pvData : NULL;
1150 
1151  return hr;
1152 }
1153 
1154 
1155 /*************************************************************************
1156  * SafeArrayUnaccessData (OLEAUT32.24)
1157  *
1158  * Unlock a SafeArray after accessing its data.
1159  *
1160  * PARAMS
1161  * psa [I] Array to unlock
1162  *
1163  * RETURNS
1164  * Success: S_OK. The array is unlocked.
1165  * Failure: An HRESULT error code indicating the error.
1166  *
1167  * NOTES
1168  * See SafeArray.
1169  */
1171 {
1172  TRACE("(%p)\n", psa);
1173  return SafeArrayUnlock(psa);
1174 }
1175 
1176 /************************************************************************
1177  * SafeArrayPtrOfIndex (OLEAUT32.148)
1178  *
1179  * Get the address of an item in a SafeArray.
1180  *
1181  * PARAMS
1182  * psa [I] Array to get the items address from
1183  * rgIndices [I] Index of the item in the array
1184  * ppvData [O] Destination for item address
1185  *
1186  * RETURNS
1187  * Success: S_OK. ppvData contains a pointer to the item.
1188  * Failure: An HRESULT error code indicating the error.
1189  *
1190  * NOTES
1191  * This function does not lock the array.
1192  *
1193  * NOTES
1194  * See SafeArray.
1195  */
1196 HRESULT WINAPI SafeArrayPtrOfIndex(SAFEARRAY *psa, LONG *rgIndices, void **ppvData)
1197 {
1198  USHORT dim;
1199  ULONG cell = 0, dimensionSize = 1;
1200  SAFEARRAYBOUND* psab;
1201  LONG c1;
1202 
1203  TRACE("(%p,%p,%p)\n", psa, rgIndices, ppvData);
1204 
1205  /* The general formula for locating the cell number of an entry in an n
1206  * dimensional array (where cn = coordinate in dimension dn) is:
1207  *
1208  * c1 + c2 * sizeof(d1) + c3 * sizeof(d2) ... + cn * sizeof(c(n-1))
1209  *
1210  * We calculate the size of the last dimension at each step through the
1211  * dimensions to avoid recursing to calculate the last dimensions size.
1212  */
1213  if (!psa || !rgIndices || !ppvData)
1214  return E_INVALIDARG;
1215 
1216  psab = psa->rgsabound + psa->cDims - 1;
1217  c1 = *rgIndices++;
1218 
1219  if (c1 < psab->lLbound || c1 >= psab->lLbound + (LONG)psab->cElements)
1220  return DISP_E_BADINDEX; /* Initial index out of bounds */
1221 
1222  for (dim = 1; dim < psa->cDims; dim++)
1223  {
1224  dimensionSize *= psab->cElements;
1225 
1226  psab--;
1227 
1228  if (!psab->cElements ||
1229  *rgIndices < psab->lLbound ||
1230  *rgIndices >= psab->lLbound + (LONG)psab->cElements)
1231  return DISP_E_BADINDEX; /* Index out of bounds */
1232 
1233  cell += (*rgIndices - psab->lLbound) * dimensionSize;
1234  rgIndices++;
1235  }
1236 
1237  cell += (c1 - psa->rgsabound[psa->cDims - 1].lLbound);
1238 
1239  *ppvData = (char*)psa->pvData + cell * psa->cbElements;
1240  return S_OK;
1241 }
1242 
1243 /************************************************************************
1244  * SafeArrayDestroyData (OLEAUT32.39)
1245  *
1246  * Destroy the data associated with a SafeArray.
1247  *
1248  * PARAMS
1249  * psa [I] Array to delete the data from
1250  *
1251  * RETURNS
1252  * Success: S_OK. All items and the item data are freed.
1253  * Failure: An HRESULT error code indicating the error.
1254  *
1255  * NOTES
1256  * See SafeArray.
1257  */
1259 {
1260  HRESULT hr;
1261 
1262  TRACE("(%p)\n", psa);
1263 
1264  if (!psa)
1265  return E_INVALIDARG;
1266 
1267  if (psa->cLocks)
1268  return DISP_E_ARRAYISLOCKED; /* Can't delete a locked array */
1269 
1270  /* Delete the actual item data */
1272  if (FAILED(hr))
1273  return hr;
1274 
1275  if (psa->pvData)
1276  {
1277  if (psa->fFeatures & FADF_STATIC)
1278  {
1279  ZeroMemory(psa->pvData, SAFEARRAY_GetCellCount(psa) * psa->cbElements);
1280  return S_OK;
1281  }
1282  /* If this is not a vector, free the data memory block */
1283  if (!(psa->fFeatures & FADF_CREATEVECTOR))
1284  {
1285  SAFEARRAY_Free(psa->pvData);
1286  psa->pvData = NULL;
1287  }
1288  else
1289  psa->fFeatures |= FADF_DATADELETED; /* Mark the data deleted */
1290 
1291  }
1292  return S_OK;
1293 }
1294 
1295 /************************************************************************
1296  * SafeArrayCopyData (OLEAUT32.412)
1297  *
1298  * Copy all data from one SafeArray to another.
1299  *
1300  * PARAMS
1301  * psaSource [I] Source for copy
1302  * psaTarget [O] Destination for copy
1303  *
1304  * RETURNS
1305  * Success: S_OK. psaTarget contains a copy of psaSource.
1306  * Failure: An HRESULT error code indicating the error.
1307  *
1308  * NOTES
1309  * The two arrays must have the same number of dimensions and elements.
1310  *
1311  * NOTES
1312  * See SafeArray.
1313  */
1315 {
1316  int dim;
1317 
1318  TRACE("(%p,%p)\n", psaSource, psaTarget);
1319 
1320  if (!psaSource || !psaTarget ||
1321  psaSource->cDims != psaTarget->cDims ||
1322  psaSource->cbElements != psaTarget->cbElements)
1323  return E_INVALIDARG;
1324 
1325  /* Each dimension must be the same size */
1326  for (dim = psaSource->cDims - 1; dim >= 0 ; dim--)
1327  if (psaSource->rgsabound[dim].cElements !=
1328  psaTarget->rgsabound[dim].cElements)
1329  return E_INVALIDARG;
1330 
1331  return SAFEARRAY_CopyData(psaSource, psaTarget);
1332 }
1333 
1334 /************************************************************************
1335  * SafeArrayDestroy (OLEAUT32.16)
1336  *
1337  * Destroy a SafeArray.
1338  *
1339  * PARAMS
1340  * psa [I] Array to destroy
1341  *
1342  * RETURNS
1343  * Success: S_OK. All resources used by the array are freed.
1344  * Failure: An HRESULT error code indicating the error.
1345  *
1346  * NOTES
1347  * See SafeArray.
1348  */
1350 {
1351  TRACE("(%p)\n", psa);
1352 
1353  if(!psa)
1354  return S_OK;
1355 
1356  if(psa->cLocks > 0)
1357  return DISP_E_ARRAYISLOCKED;
1358 
1359  /* Native doesn't check to see if the free succeeds */
1362  return S_OK;
1363 }
1364 
1365 /************************************************************************
1366  * SafeArrayCopy (OLEAUT32.27)
1367  *
1368  * Make a duplicate of a SafeArray.
1369  *
1370  * PARAMS
1371  * psa [I] Source for copy
1372  * ppsaOut [O] Destination for new copy
1373  *
1374  * RETURNS
1375  * Success: S_OK. ppsaOut contains a copy of the array.
1376  * Failure: An HRESULT error code indicating the error.
1377  *
1378  * NOTES
1379  * See SafeArray.
1380  */
1382 {
1383  HRESULT hRet;
1384 
1385  TRACE("(%p,%p)\n", psa, ppsaOut);
1386 
1387  if (!ppsaOut)
1388  return E_INVALIDARG;
1389 
1390  *ppsaOut = NULL;
1391 
1392  if (!psa)
1393  return S_OK; /* Handles copying of NULL arrays */
1394 
1395  if (!psa->cbElements)
1396  return E_INVALIDARG;
1397 
1398  if (psa->fFeatures & (FADF_RECORD|FADF_HAVEIID|FADF_HAVEVARTYPE))
1399  {
1400  VARTYPE vt;
1401 
1402  hRet = SafeArrayGetVartype(psa, &vt);
1403  if (SUCCEEDED(hRet))
1404  hRet = SafeArrayAllocDescriptorEx(vt, psa->cDims, ppsaOut);
1405  }
1406  else
1407  {
1408  hRet = SafeArrayAllocDescriptor(psa->cDims, ppsaOut);
1409  if (SUCCEEDED(hRet))
1410  {
1411  (*ppsaOut)->fFeatures = psa->fFeatures & ~ignored_copy_features;
1412  (*ppsaOut)->cbElements = psa->cbElements;
1413  }
1414  }
1415 
1416  if (SUCCEEDED(hRet))
1417  {
1418  /* Copy dimension bounds */
1419  memcpy((*ppsaOut)->rgsabound, psa->rgsabound, psa->cDims * sizeof(SAFEARRAYBOUND));
1420 
1421  (*ppsaOut)->pvData = SAFEARRAY_Malloc(SAFEARRAY_GetCellCount(psa) * psa->cbElements);
1422  if (!(*ppsaOut)->pvData)
1423  {
1424  SafeArrayDestroyDescriptor(*ppsaOut);
1425  *ppsaOut = NULL;
1426  return E_OUTOFMEMORY;
1427  }
1428 
1429  hRet = SAFEARRAY_CopyData(psa, *ppsaOut);
1430  if (FAILED(hRet))
1431  {
1432  SAFEARRAY_Free((*ppsaOut)->pvData);
1433  SafeArrayDestroyDescriptor(*ppsaOut);
1434  *ppsaOut = NULL;
1435  return hRet;
1436  }
1437  }
1438 
1439  return hRet;
1440 }
1441 
1442 /************************************************************************
1443  * SafeArrayRedim (OLEAUT32.40)
1444  *
1445  * Changes the characteristics of the last dimension of a SafeArray
1446  *
1447  * PARAMS
1448  * psa [I] Array to change
1449  * psabound [I] New bound details for the last dimension
1450  *
1451  * RETURNS
1452  * Success: S_OK. psa is updated to reflect the new bounds.
1453  * Failure: An HRESULT error code indicating the error.
1454  *
1455  * NOTES
1456  * See SafeArray.
1457  */
1459 {
1460  SAFEARRAYBOUND *oldBounds;
1461  HRESULT hr;
1462 
1463  TRACE("(%p,%p)\n", psa, psabound);
1464 
1465  if (!psa || psa->fFeatures & FADF_FIXEDSIZE || !psabound)
1466  return E_INVALIDARG;
1467 
1468  if (psa->cLocks > 0)
1469  return DISP_E_ARRAYISLOCKED;
1470 
1471  hr = SafeArrayLock(psa);
1472  if (FAILED(hr))
1473  return hr;
1474 
1475  oldBounds = psa->rgsabound;
1476  oldBounds->lLbound = psabound->lLbound;
1477 
1478  if (psabound->cElements != oldBounds->cElements)
1479  {
1480  if (psabound->cElements < oldBounds->cElements)
1481  {
1482  /* Shorten the final dimension. */
1483  ULONG ulStartCell = psabound->cElements *
1484  (SAFEARRAY_GetCellCount(psa) / oldBounds->cElements);
1485  SAFEARRAY_DestroyData(psa, ulStartCell);
1486  }
1487  else
1488  {
1489  /* Lengthen the final dimension */
1490  ULONG ulOldSize, ulNewSize;
1491  PVOID pvNewData;
1492 
1493  ulOldSize = SAFEARRAY_GetCellCount(psa) * psa->cbElements;
1494  if (ulOldSize)
1495  ulNewSize = (ulOldSize / oldBounds->cElements) * psabound->cElements;
1496  else {
1497  int oldelems = oldBounds->cElements;
1498  oldBounds->cElements = psabound->cElements;
1499  ulNewSize = SAFEARRAY_GetCellCount(psa) * psa->cbElements;
1500  oldBounds->cElements = oldelems;
1501  }
1502 
1503  if (!(pvNewData = SAFEARRAY_Malloc(ulNewSize)))
1504  {
1506  return E_OUTOFMEMORY;
1507  }
1508 
1509  memcpy(pvNewData, psa->pvData, ulOldSize);
1510  SAFEARRAY_Free(psa->pvData);
1511  psa->pvData = pvNewData;
1512  }
1513  oldBounds->cElements = psabound->cElements;
1514  }
1515 
1517  return S_OK;
1518 }
1519 
1520 /************************************************************************
1521  * SafeArrayGetVartype (OLEAUT32.77)
1522  *
1523  * Get the type of the items in a SafeArray.
1524  *
1525  * PARAMS
1526  * psa [I] Array to get the type from
1527  * pvt [O] Destination for the type
1528  *
1529  * RETURNS
1530  * Success: S_OK. pvt contains the type of the items.
1531  * Failure: An HRESULT error code indicating the error.
1532  *
1533  * NOTES
1534  * See SafeArray.
1535  */
1537 {
1538  TRACE("(%p,%p)\n", psa, pvt);
1539 
1540  if (!psa || !pvt)
1541  return E_INVALIDARG;
1542 
1543  if (psa->fFeatures & FADF_RECORD)
1544  *pvt = VT_RECORD;
1545  else if ((psa->fFeatures & (FADF_HAVEIID|FADF_DISPATCH)) == (FADF_HAVEIID|FADF_DISPATCH))
1546  *pvt = VT_DISPATCH;
1547  else if (psa->fFeatures & FADF_HAVEIID)
1548  *pvt = VT_UNKNOWN;
1549  else if (psa->fFeatures & FADF_HAVEVARTYPE)
1550  {
1552  *pvt = vt;
1553  }
1554  else
1555  return E_INVALIDARG;
1556 
1557  return S_OK;
1558 }
1559 
1560 /************************************************************************
1561  * SafeArraySetRecordInfo (OLEAUT32.@)
1562  *
1563  * Set the record info for a SafeArray.
1564  *
1565  * PARAMS
1566  * psa [I] Array to set the record info for
1567  * pRinfo [I] Record info
1568  *
1569  * RETURNS
1570  * Success: S_OK. The record info is stored with the array.
1571  * Failure: An HRESULT error code indicating the error.
1572  *
1573  * NOTES
1574  * See SafeArray.
1575  */
1577 {
1579 
1580  TRACE("(%p,%p)\n", psa, pRinfo);
1581 
1582  if (!psa || !(psa->fFeatures & FADF_RECORD))
1583  return E_INVALIDARG;
1584 
1585  if (pRinfo)
1586  IRecordInfo_AddRef(pRinfo);
1587 
1588  if (dest[-1])
1589  IRecordInfo_Release(dest[-1]);
1590 
1591  dest[-1] = pRinfo;
1592  return S_OK;
1593 }
1594 
1595 /************************************************************************
1596  * SafeArrayGetRecordInfo (OLEAUT32.@)
1597  *
1598  * Get the record info from a SafeArray.
1599  *
1600  * PARAMS
1601  * psa [I] Array to get the record info from
1602  * pRinfo [O] Destination for the record info
1603  *
1604  * RETURNS
1605  * Success: S_OK. pRinfo contains the record info, or NULL if there was none.
1606  * Failure: An HRESULT error code indicating the error.
1607  *
1608  * NOTES
1609  * See SafeArray.
1610  */
1612 {
1613  IRecordInfo** src = (IRecordInfo**)psa;
1614 
1615  TRACE("(%p,%p)\n", psa, pRinfo);
1616 
1617  if (!psa || !pRinfo || !(psa->fFeatures & FADF_RECORD))
1618  return E_INVALIDARG;
1619 
1620  *pRinfo = src[-1];
1621 
1622  if (*pRinfo)
1623  IRecordInfo_AddRef(*pRinfo);
1624  return S_OK;
1625 }
1626 
1627 /************************************************************************
1628  * SafeArraySetIID (OLEAUT32.@)
1629  *
1630  * Set the IID for a SafeArray.
1631  *
1632  * PARAMS
1633  * psa [I] Array to set the IID from
1634  * guid [I] IID
1635  *
1636  * RETURNS
1637  * Success: S_OK. The IID is stored with the array
1638  * Failure: An HRESULT error code indicating the error.
1639  *
1640  * NOTES
1641  * See SafeArray.
1642  */
1644 {
1645  GUID* dest = (GUID*)psa;
1646 
1647  TRACE("(%p,%s)\n", psa, debugstr_guid(guid));
1648 
1649  if (!psa || !guid || !(psa->fFeatures & FADF_HAVEIID))
1650  return E_INVALIDARG;
1651 
1652  dest[-1] = *guid;
1653  return S_OK;
1654 }
1655 
1656 /************************************************************************
1657  * SafeArrayGetIID (OLEAUT32.@)
1658  *
1659  * Get the IID from a SafeArray.
1660  *
1661  * PARAMS
1662  * psa [I] Array to get the ID from
1663  * pGuid [O] Destination for the IID
1664  *
1665  * RETURNS
1666  * Success: S_OK. pRinfo contains the IID, or NULL if there was none.
1667  * Failure: An HRESULT error code indicating the error.
1668  *
1669  * NOTES
1670  * See SafeArray.
1671  */
1673 {
1674  GUID* src = (GUID*)psa;
1675 
1676  TRACE("(%p,%p)\n", psa, pGuid);
1677 
1678  if (!psa || !pGuid || !(psa->fFeatures & FADF_HAVEIID))
1679  return E_INVALIDARG;
1680 
1681  *pGuid = src[-1];
1682  return S_OK;
1683 }
1684 
1685 /************************************************************************
1686  * VectorFromBstr (OLEAUT32.@)
1687  *
1688  * Create a SafeArray Vector from the bytes of a BSTR.
1689  *
1690  * PARAMS
1691  * bstr [I] String to get bytes from
1692  * ppsa [O] Destination for the array
1693  *
1694  * RETURNS
1695  * Success: S_OK. ppsa contains the strings bytes as a VT_UI1 array.
1696  * Failure: An HRESULT error code indicating the error.
1697  *
1698  * NOTES
1699  * See SafeArray.
1700  */
1702 {
1703  SAFEARRAYBOUND sab;
1704 
1705  TRACE("(%p,%p)\n", bstr, ppsa);
1706 
1707  if (!ppsa)
1708  return E_INVALIDARG;
1709 
1710  sab.lLbound = 0;
1711  sab.cElements = SysStringByteLen(bstr);
1712 
1713  *ppsa = SAFEARRAY_Create(VT_UI1, 1, &sab, 0);
1714 
1715  if (*ppsa)
1716  {
1717  memcpy((*ppsa)->pvData, bstr, sab.cElements);
1718  return S_OK;
1719  }
1720  return E_OUTOFMEMORY;
1721 }
1722 
1723 /************************************************************************
1724  * BstrFromVector (OLEAUT32.@)
1725  *
1726  * Create a BSTR from a SafeArray.
1727  *
1728  * PARAMS
1729  * psa [I] Source array
1730  * pbstr [O] Destination for output BSTR
1731  *
1732  * RETURNS
1733  * Success: S_OK. pbstr contains the arrays data.
1734  * Failure: An HRESULT error code indicating the error.
1735  *
1736  * NOTES
1737  * psa must be a 1 dimensional array of a 1 byte type.
1738  *
1739  * NOTES
1740  * See SafeArray.
1741  */
1743 {
1744  TRACE("(%p,%p)\n", psa, pbstr);
1745 
1746  if (!pbstr)
1747  return E_INVALIDARG;
1748 
1749  *pbstr = NULL;
1750 
1751  if (!psa || psa->cbElements != 1 || psa->cDims != 1)
1752  return E_INVALIDARG;
1753 
1754  *pbstr = SysAllocStringByteLen(psa->pvData, psa->rgsabound[0].cElements);
1755  if (!*pbstr)
1756  return E_OUTOFMEMORY;
1757  return S_OK;
1758 }
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
static void SAFEARRAY_SetHiddenDWORD(SAFEARRAY *psa, DWORD dw)
Definition: safearray.c:149
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
Definition: safearray.c:164
ULONG cbElements
Definition: compat.h:1998
static const USHORT ignored_copy_features
Definition: safearray.c:90
UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa)
Definition: safearray.c:1096
struct tagVARIANT VARIANT
Definition: compat.h:2018
HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY *psa, IRecordInfo **pRinfo)
Definition: safearray.c:1611
Definition: compat.h:1939
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:422
Definition: compat.h:1955
HRESULT hr
Definition: shlfolder.c:183
Definition: scsiwmi.h:51
Definition: compat.h:1951
HRESULT WINAPI SafeArrayCopyData(SAFEARRAY *psaSource, SAFEARRAY *psaTarget)
Definition: safearray.c:1314
SAFEARRAYBOUND rgsabound[1]
Definition: compat.h:2001
#define WARN(fmt,...)
Definition: debug.h:111
static SAFEARRAY * SAFEARRAY_Create(VARTYPE vt, UINT cDims, const SAFEARRAYBOUND *rgsabound, ULONG ulSize)
Definition: safearray.c:220
#define INT
Definition: polytest.cpp:20
double DATE
Definition: compat.h:1894
#define ZeroMemory
Definition: winbase.h:1635
UINT WINAPI SysStringByteLen(BSTR str)
Definition: oleaut.c:218
HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:949
OLECHAR * BSTR
Definition: compat.h:1934
static void SAFEARRAY_SetFeatures(VARTYPE vt, SAFEARRAY *psa)
Definition: safearray.c:197
SAFEARRAY *WINAPI SafeArrayCreateVectorEx(VARTYPE vt, LONG lLbound, ULONG cElements, LPVOID pvExtra)
Definition: safearray.c:707
static void SAFEARRAY_Free(void *ptr)
Definition: safearray.c:107
#define DISP_E_ARRAYISLOCKED
Definition: winerror.h:2522
struct tagSAFEARRAY SAFEARRAY
const USHORT FADF_CREATEVECTOR
Definition: safearray.c:43
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const GUID * guid
HRESULT WINAPI SafeArraySetIID(SAFEARRAY *psa, REFGUID guid)
Definition: safearray.c:1643
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData)
Definition: safearray.c:1139
long LONG
Definition: pedump.c:60
short SHORT
Definition: pedump.c:59
static LPUNKNOWN
Definition: ndr_ole.c:49
static DWORD SAFEARRAY_GetHiddenDWORD(SAFEARRAY *psa)
Definition: safearray.c:157
#define FIXME(fmt,...)
Definition: debug.h:110
static PVOID ptr
Definition: dispmode.c:27
#define E_INVALIDARG
Definition: ddrawi.h:101
HRESULT WINAPI SafeArrayPtrOfIndex(SAFEARRAY *psa, LONG *rgIndices, void **ppvData)
Definition: safearray.c:1196
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3748
smooth NULL
Definition: ftsmooth.c:416
USHORT cDims
Definition: compat.h:1996
static HRESULT SAFEARRAY_AllocDescriptor(ULONG ulSize, SAFEARRAY **ppsaOut)
Definition: safearray.c:182
static HRESULT SAFEARRAY_CopyData(SAFEARRAY *psa, SAFEARRAY *dest)
Definition: safearray.c:351
#define debugstr_guid
Definition: kernel32.h:35
HRESULT WINAPI SafeArraySetRecordInfo(SAFEARRAY *psa, IRecordInfo *pRinfo)
Definition: safearray.c:1576
HRESULT WINAPI SafeArrayLock(SAFEARRAY *psa)
Definition: safearray.c:797
union tagCY CY
BSTR WINAPI DECLSPEC_HOTPATCH SysAllocStringByteLen(LPCSTR str, UINT len)
Definition: oleaut.c:431
HRESULT WINAPI SafeArrayUnlock(SAFEARRAY *psa)
Definition: safearray.c:833
int64_t LONG64
Definition: typedefs.h:66
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
SAFEARRAY *WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound, LPVOID pvExtra)
Definition: safearray.c:630
LONG HRESULT
Definition: typedefs.h:77
HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut)
Definition: safearray.c:1381
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:8
HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
Definition: safearray.c:1068
unsigned long DWORD
Definition: ntddk_ex.h:95
REFIID LPVOID DWORD dw
Definition: atlbase.h:40
HRESULT WINAPI SafeArrayAllocData(SAFEARRAY *psa)
Definition: safearray.c:559
#define SAFEARRAY_HIDDEN_SIZE
Definition: safearray.c:86
HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
Definition: safearray.c:1349
SAFEARRAY *WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
Definition: safearray.c:679
const GUID IID_IDispatch
HRESULT WINAPI BstrFromVector(SAFEARRAY *psa, BSTR *pbstr)
Definition: safearray.c:1742
int ret
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:651
#define LPDWORD
Definition: nt_native.h:46
Definition: compat.h:1940
#define InterlockedDecrement
Definition: armddk.h:52
WINE_DEFAULT_DEBUG_CHANNEL(variant)
HRESULT WINAPI VectorFromBstr(BSTR bstr, SAFEARRAY **ppsa)
Definition: safearray.c:1701
static HRESULT SAFEARRAY_DestroyData(SAFEARRAY *psa, ULONG ulStartCell)
Definition: safearray.c:285
#define V_VT(A)
Definition: oleauto.h:211
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned char BYTE
Definition: mem.h:68
HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound)
Definition: safearray.c:1458
GLenum src
Definition: glext.h:6340
Definition: compat.h:1942
HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa)
Definition: safearray.c:1258
struct tagDEC DECIMAL
HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa)
Definition: safearray.c:757
SAFEARRAY *WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
Definition: safearray.c:602
HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid)
Definition: safearray.c:1672
#define S_OK
Definition: intsafe.h:59
HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
Definition: safearray.c:1035
#define InterlockedIncrement
Definition: armddk.h:53
unsigned short USHORT
Definition: pedump.c:61
unsigned short VARTYPE
Definition: compat.h:1895
UINT WINAPI SafeArrayGetElemsize(SAFEARRAY *psa)
Definition: safearray.c:1116
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:274
HRESULT WINAPI SafeArrayAllocDescriptorEx(VARTYPE vt, UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:523
unsigned int UINT
Definition: ndis.h:50
HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY *psa, VARTYPE *pvt)
Definition: safearray.c:1536
static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
Definition: safearray.c:113
static SCRIPT_CACHE SCRIPT_ANALYSIS * psa
Definition: usp10.c:64
#define E_UNEXPECTED
Definition: winerror.h:2456
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:866
uint32_t * LPDWORD
Definition: typedefs.h:57
static void * SAFEARRAY_Malloc(ULONG size)
Definition: safearray.c:98
unsigned int ULONG
Definition: retypes.h:1
VARTYPE vt
Definition: safearray.c:331
static char * dest
Definition: rtl.c:135
static SAFEARRAY * SAFEARRAY_CreateVector(VARTYPE vt, LONG lLbound, ULONG cElements, ULONG ulSize)
Definition: safearray.c:254
#define DISP_E_BADINDEX
Definition: winerror.h:2520
HRESULT WINAPI SafeArrayAllocDescriptor(UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:478
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:751
#define E_POINTER
Definition: winerror.h:2365
#define memset(x, y, z)
Definition: compat.h:39
BYTE * PBYTE
Definition: pedump.c:66
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:406
Definition: compat.h:1941
HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa)
Definition: safearray.c:1170
Definition: compat.h:1938
#define SUCCEEDED(hr)
Definition: intsafe.h:57