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