ReactOS 0.4.15-dev-7889-g76290a6
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 */
96static 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 */
105static 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{
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 */
218static 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 */
252static 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 {
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 */
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 {
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);
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{
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}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define NULL
Definition: types.h:112
double DATE
Definition: compat.h:2253
union tagCY CY
struct tagDEC DECIMAL
struct tagVARIANT VARIANT
Definition: compat.h:2377
OLECHAR * BSTR
Definition: compat.h:2293
unsigned short VARTYPE
Definition: compat.h:2254
struct tagSAFEARRAY SAFEARRAY
@ VT_UI8
Definition: compat.h:2315
@ VT_BSTR
Definition: compat.h:2303
@ VT_INT
Definition: compat.h:2316
@ VT_R4
Definition: compat.h:2299
@ VT_UINT_PTR
Definition: compat.h:2328
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_UI2
Definition: compat.h:2312
@ VT_DECIMAL
Definition: compat.h:2309
@ VT_ERROR
Definition: compat.h:2305
@ VT_R8
Definition: compat.h:2300
@ VT_CY
Definition: compat.h:2301
@ VT_VARIANT
Definition: compat.h:2307
@ VT_I8
Definition: compat.h:2314
@ VT_I1
Definition: compat.h:2310
@ VT_I4
Definition: compat.h:2298
@ VT_INT_PTR
Definition: compat.h:2327
@ VT_DATE
Definition: compat.h:2302
@ VT_BOOL
Definition: compat.h:2306
@ VT_I2
Definition: compat.h:2297
@ VT_UI4
Definition: compat.h:2313
@ VT_UINT
Definition: compat.h:2317
@ VT_EMPTY
Definition: compat.h:2295
@ VT_RECORD
Definition: compat.h:2326
@ VT_DISPATCH
Definition: compat.h:2304
@ VT_UI1
Definition: compat.h:2311
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:86
static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
Definition: safearray.c:162
HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
Definition: safearray.c:1033
HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa)
Definition: safearray.c:755
HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:947
static SAFEARRAY * SAFEARRAY_Create(VARTYPE vt, UINT cDims, const SAFEARRAYBOUND *rgsabound, ULONG ulSize)
Definition: safearray.c:218
static void SAFEARRAY_Free(void *ptr)
Definition: safearray.c:105
HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData)
Definition: safearray.c:1137
HRESULT WINAPI SafeArrayUnlock(SAFEARRAY *psa)
Definition: safearray.c:831
HRESULT WINAPI SafeArrayAllocDescriptorEx(VARTYPE vt, UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:521
HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa)
Definition: safearray.c:1168
HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut)
Definition: safearray.c:1379
static void SAFEARRAY_SetHiddenDWORD(SAFEARRAY *psa, DWORD dw)
Definition: safearray.c:147
HRESULT WINAPI VectorFromBstr(BSTR bstr, SAFEARRAY **ppsa)
Definition: safearray.c:1699
UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa)
Definition: safearray.c:1094
SAFEARRAY *WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
Definition: safearray.c:677
HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid)
Definition: safearray.c:1670
HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
Definition: safearray.c:1066
HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa)
Definition: safearray.c:1256
SAFEARRAY *WINAPI SafeArrayCreateVectorEx(VARTYPE vt, LONG lLbound, ULONG cElements, LPVOID pvExtra)
Definition: safearray.c:705
#define SAFEARRAY_HIDDEN_SIZE
Definition: safearray.c:84
UINT WINAPI SafeArrayGetElemsize(SAFEARRAY *psa)
Definition: safearray.c:1114
HRESULT WINAPI BstrFromVector(SAFEARRAY *psa, BSTR *pbstr)
Definition: safearray.c:1740
static HRESULT SAFEARRAY_DestroyData(SAFEARRAY *psa, ULONG ulStartCell)
Definition: safearray.c:283
HRESULT WINAPI SafeArrayAllocDescriptor(UINT cDims, SAFEARRAY **ppsaOut)
Definition: safearray.c:476
static HRESULT SAFEARRAY_CopyData(SAFEARRAY *psa, SAFEARRAY *dest)
Definition: safearray.c:349
HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY *psa, IRecordInfo **pRinfo)
Definition: safearray.c:1609
static void * SAFEARRAY_Malloc(ULONG size)
Definition: safearray.c:96
static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
Definition: safearray.c:111
HRESULT WINAPI SafeArrayPtrOfIndex(SAFEARRAY *psa, LONG *rgIndices, void **ppvData)
Definition: safearray.c:1194
HRESULT WINAPI SafeArraySetRecordInfo(SAFEARRAY *psa, IRecordInfo *pRinfo)
Definition: safearray.c:1574
SAFEARRAY *WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound, LPVOID pvExtra)
Definition: safearray.c:628
static HRESULT SAFEARRAY_AllocDescriptor(ULONG ulSize, SAFEARRAY **ppsaOut)
Definition: safearray.c:180
HRESULT WINAPI SafeArrayLock(SAFEARRAY *psa)
Definition: safearray.c:795
static DWORD SAFEARRAY_GetHiddenDWORD(SAFEARRAY *psa)
Definition: safearray.c:155
HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
Definition: safearray.c:1347
static const USHORT ignored_copy_features
Definition: safearray.c:88
HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound)
Definition: safearray.c:1456
SAFEARRAY *WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
Definition: safearray.c:600
HRESULT WINAPI SafeArrayCopyData(SAFEARRAY *psaSource, SAFEARRAY *psaTarget)
Definition: safearray.c:1312
HRESULT WINAPI SafeArrayAllocData(SAFEARRAY *psa)
Definition: safearray.c:557
HRESULT WINAPI SafeArraySetIID(SAFEARRAY *psa, REFGUID guid)
Definition: safearray.c:1641
HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY *psa, VARTYPE *pvt)
Definition: safearray.c:1534
static SAFEARRAY * SAFEARRAY_CreateVector(VARTYPE vt, LONG lLbound, ULONG cElements, ULONG ulSize)
Definition: safearray.c:252
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:864
static void SAFEARRAY_SetFeatures(VARTYPE vt, SAFEARRAY *psa)
Definition: safearray.c:195
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizeiptr size
Definition: glext.h:5919
GLenum src
Definition: glext.h:6340
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
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
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID LPVOID DWORD_PTR dw
Definition: atlbase.h:40
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define debugstr_guid
Definition: kernel32.h:35
const GUID * guid
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static char * dest
Definition: rtl.c:135
const USHORT FADF_CREATEVECTOR
Definition: safearray.c:43
static SCRIPT_CACHE SCRIPT_ANALYSIS * psa
Definition: usp10.c:64
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
unsigned int UINT
Definition: ndis.h:50
static LPUNKNOWN
Definition: ndr_ole.c:49
#define LPDWORD
Definition: nt_native.h:46
UINT WINAPI SysStringByteLen(BSTR str)
Definition: oleaut.c:215
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
BSTR WINAPI DECLSPEC_HOTPATCH SysAllocStringByteLen(LPCSTR str, UINT len)
Definition: oleaut.c:428
#define V_VT(A)
Definition: oleauto.h:211
const GUID IID_IDispatch
BYTE * PBYTE
Definition: pedump.c:66
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define INT
Definition: polytest.cpp:20
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
Definition: scsiwmi.h:51
SAFEARRAYBOUND rgsabound[1]
Definition: compat.h:2360
USHORT cDims
Definition: compat.h:2355
ULONG cbElements
Definition: compat.h:2357
int64_t LONG64
Definition: typedefs.h:68
uint32_t * LPDWORD
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:748
int ret
#define ZeroMemory
Definition: winbase.h:1712
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3749
#define WINAPI
Definition: msvc.h:6
#define DISP_E_ARRAYISLOCKED
Definition: winerror.h:2522
#define E_UNEXPECTED
Definition: winerror.h:2456
#define DISP_E_BADINDEX
Definition: winerror.h:2520
#define E_POINTER
Definition: winerror.h:2365
unsigned char BYTE
Definition: xxhash.c:193