ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

safearray.c
Go to the documentation of this file.
00001 /*************************************************************************
00002  * OLE Automation - SafeArray
00003  *
00004  * This file contains the implementation of the SafeArray functions.
00005  *
00006  * Copyright 1999 Sylvain St-Germain
00007  * Copyright 2002-2003 Marcus Meissner
00008  * Copyright 2003 Jon Griffiths
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00023  */
00024 /* Memory Layout of a SafeArray:
00025  *
00026  * -0x10: start of memory.
00027  * -0x10: GUID for VT_DISPATCH and VT_UNKNOWN safearrays (if FADF_HAVEIID)
00028  * -0x04: DWORD varianttype; (for all others, except VT_RECORD) (if FADF_HAVEVARTYPE)
00029  *  -0x4: IRecordInfo* iface;  (if FADF_RECORD, for VT_RECORD (can be NULL))
00030  *  0x00: SAFEARRAY,
00031  *  0x10: SAFEARRAYBOUNDS[0...]
00032  */
00033 
00034 #include "config.h"
00035 
00036 #include <string.h>
00037 #include <stdarg.h>
00038 #include <stdio.h>
00039 
00040 #define COBJMACROS
00041 
00042 #include "windef.h"
00043 #include "winerror.h"
00044 #include "winbase.h"
00045 #include "variant.h"
00046 #include "wine/debug.h"
00047 
00048 WINE_DEFAULT_DEBUG_CHANNEL(variant);
00049 
00050 /************************************************************************
00051  * SafeArray {OLEAUT32}
00052  *
00053  * NOTES
00054  * The SafeArray data type provides the underlying interface for Ole
00055  * Automations arrays, used for example to represent array types in
00056  * Visual Basic(tm) and to gather user defined parameters for invocation through
00057  * an IDispatch interface.
00058  *
00059  * Safe arrays provide bounds checking and automatically manage the data
00060  * types they contain, for example handing reference counting and copying
00061  * of interface pointers. User defined types can be stored in arrays
00062  * using the IRecordInfo interface.
00063  *
00064  * There are two types of SafeArray, normal and vectors. Normal arrays can have
00065  * multiple dimensions and the data for the array is allocated separately from
00066  * the array header. This is the most flexible type of array. Vectors, on the
00067  * other hand, are fixed in size and consist of a single allocated block, and a
00068  * single dimension.
00069  *
00070  * DATATYPES
00071  * The following types of data can be stored within a SafeArray.
00072  * Numeric:
00073  *|  VT_I1, VT_UI1, VT_I2, VT_UI2, VT_I4, VT_UI4, VT_I8, VT_UI8, VT_INT, VT_UINT,
00074  *|  VT_R4, VT_R8, VT_CY, VT_DECIMAL
00075  * Interfaces:
00076  *|  VT_DISPATCH, VT_UNKNOWN, VT_RECORD
00077  * Other:
00078  *|  VT_VARIANT, VT_INT_PTR, VT_UINT_PTR, VT_BOOL, VT_ERROR, VT_DATE, VT_BSTR
00079  *
00080  * FUNCTIONS
00081  *  BstrFromVector()
00082  *  VectorFromBstr()
00083  */
00084 
00085 /* Undocumented hidden space before the start of a SafeArray descriptor */
00086 #define SAFEARRAY_HIDDEN_SIZE sizeof(GUID)
00087 
00088 /* Allocate memory */
00089 static inline LPVOID SAFEARRAY_Malloc(ULONG ulSize)
00090 {
00091   /* FIXME: Memory should be allocated and freed using a per-thread IMalloc
00092    *        instance returned from CoGetMalloc().
00093    */
00094   return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulSize);
00095 }
00096 
00097 /* Free memory */
00098 static inline BOOL SAFEARRAY_Free(LPVOID lpData)
00099 {
00100   return HeapFree(GetProcessHeap(), 0, lpData);
00101 }
00102 
00103 /* Get the size of a supported VT type (0 means unsupported) */
00104 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
00105 {
00106   switch (vt)
00107   {
00108     case VT_I1:
00109     case VT_UI1:      return sizeof(BYTE);
00110     case VT_BOOL:
00111     case VT_I2:
00112     case VT_UI2:      return sizeof(SHORT);
00113     case VT_I4:
00114     case VT_UI4:
00115     case VT_R4:
00116     case VT_ERROR:    return sizeof(LONG);
00117     case VT_R8:
00118     case VT_I8:
00119     case VT_UI8:      return sizeof(LONG64);
00120     case VT_INT:
00121     case VT_UINT:     return sizeof(INT);
00122     case VT_INT_PTR:
00123     case VT_UINT_PTR: return sizeof(UINT_PTR);
00124     case VT_CY:       return sizeof(CY);
00125     case VT_DATE:     return sizeof(DATE);
00126     case VT_BSTR:     return sizeof(BSTR);
00127     case VT_DISPATCH: return sizeof(LPDISPATCH);
00128     case VT_VARIANT:  return sizeof(VARIANT);
00129     case VT_UNKNOWN:  return sizeof(LPUNKNOWN);
00130     case VT_DECIMAL:  return sizeof(DECIMAL);
00131     /* Note: Return a non-zero size to indicate vt is valid. The actual size
00132      * of a UDT is taken from the result of IRecordInfo_GetSize().
00133      */
00134     case VT_RECORD:   return 32;
00135   }
00136   return 0;
00137 }
00138 
00139 /* Set the hidden data for an array */
00140 static inline void SAFEARRAY_SetHiddenDWORD(SAFEARRAY* psa, DWORD dw)
00141 {
00142   /* Implementation data is stored in the 4 bytes before the header */
00143   LPDWORD lpDw = (LPDWORD)psa;
00144   lpDw[-1] = dw;
00145 }
00146 
00147 /* Get the hidden data from an array */
00148 static inline DWORD SAFEARRAY_GetHiddenDWORD(SAFEARRAY* psa)
00149 {
00150   LPDWORD lpDw = (LPDWORD)psa;
00151   return lpDw[-1];
00152 }
00153 
00154 /* Get the number of cells in a SafeArray */
00155 static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa)
00156 {
00157   const SAFEARRAYBOUND* psab = psa->rgsabound;
00158   USHORT cCount = psa->cDims;
00159   ULONG ulNumCells = 1;
00160 
00161   while (cCount--)
00162   {
00163     /* This is a valid bordercase. See testcases. -Marcus */
00164     if (!psab->cElements)
00165       return 0;
00166     ulNumCells *= psab->cElements;
00167     psab++;
00168   }
00169   return ulNumCells;
00170 }
00171 
00172 /* Allocate a descriptor for an array */
00173 static HRESULT SAFEARRAY_AllocDescriptor(ULONG ulSize, SAFEARRAY **ppsaOut)
00174 {
00175   *ppsaOut = (SAFEARRAY*)((char*)SAFEARRAY_Malloc(ulSize + SAFEARRAY_HIDDEN_SIZE) + SAFEARRAY_HIDDEN_SIZE);
00176 
00177   if (!*ppsaOut)
00178     return E_UNEXPECTED;
00179 
00180   return S_OK;
00181 }
00182 
00183 /* Set the features of an array */
00184 static void SAFEARRAY_SetFeatures(VARTYPE vt, SAFEARRAY *psa)
00185 {
00186   /* Set the IID if we have one, otherwise set the type */
00187   if (vt == VT_DISPATCH)
00188   {
00189     psa->fFeatures = FADF_HAVEIID;
00190     SafeArraySetIID(psa, &IID_IDispatch);
00191   }
00192   else if (vt == VT_UNKNOWN)
00193   {
00194     psa->fFeatures = FADF_HAVEIID;
00195     SafeArraySetIID(psa, &IID_IUnknown);
00196   }
00197   else if (vt == VT_RECORD)
00198     psa->fFeatures = FADF_RECORD;
00199   else
00200   {
00201     psa->fFeatures = FADF_HAVEVARTYPE;
00202     SAFEARRAY_SetHiddenDWORD(psa, vt);
00203   }
00204 }
00205 
00206 /* Create an array */
00207 static SAFEARRAY* SAFEARRAY_Create(VARTYPE vt, UINT cDims, const SAFEARRAYBOUND *rgsabound, ULONG ulSize)
00208 {
00209   SAFEARRAY *psa = NULL;
00210   unsigned int i;
00211 
00212   if (!rgsabound)
00213     return NULL;
00214 
00215   if (SUCCEEDED(SafeArrayAllocDescriptorEx(vt, cDims, &psa)))
00216   {
00217     switch (vt)
00218     {
00219       case VT_BSTR:     psa->fFeatures |= FADF_BSTR; break;
00220       case VT_UNKNOWN:  psa->fFeatures |= FADF_UNKNOWN; break;
00221       case VT_DISPATCH: psa->fFeatures |= FADF_DISPATCH; break;
00222       case VT_VARIANT:  psa->fFeatures |= FADF_VARIANT; break;
00223     }
00224 
00225     for (i = 0; i < cDims; i++)
00226       memcpy(psa->rgsabound + i, rgsabound + cDims - 1 - i, sizeof(SAFEARRAYBOUND));
00227 
00228     if (ulSize)
00229       psa->cbElements = ulSize;
00230 
00231     if (!psa->cbElements || FAILED(SafeArrayAllocData(psa)))
00232     {
00233       SafeArrayDestroyDescriptor(psa);
00234       psa = NULL;
00235     }
00236   }
00237   return psa;
00238 }
00239 
00240 /* Create an array as a vector */
00241 static SAFEARRAY* SAFEARRAY_CreateVector(VARTYPE vt, LONG lLbound, ULONG cElements, ULONG ulSize)
00242 {
00243   SAFEARRAY *psa = NULL;
00244 
00245   if (ulSize || (vt == VT_RECORD))
00246   {
00247     /* Allocate the header and data together */
00248     if (SUCCEEDED(SAFEARRAY_AllocDescriptor(sizeof(SAFEARRAY) + ulSize * cElements, &psa)))
00249     {
00250       SAFEARRAY_SetFeatures(vt, psa);
00251 
00252       psa->cDims = 1;
00253       psa->fFeatures |= FADF_CREATEVECTOR;
00254       psa->pvData = &psa[1]; /* Data follows the header */
00255       psa->cbElements = ulSize;
00256       psa->rgsabound[0].cElements = cElements;
00257       psa->rgsabound[0].lLbound = lLbound;
00258 
00259       switch (vt)
00260       {
00261         case VT_BSTR:     psa->fFeatures |= FADF_BSTR; break;
00262         case VT_UNKNOWN:  psa->fFeatures |= FADF_UNKNOWN; break;
00263         case VT_DISPATCH: psa->fFeatures |= FADF_DISPATCH; break;
00264         case VT_VARIANT:  psa->fFeatures |= FADF_VARIANT; break;
00265       }
00266     }
00267   }
00268   return psa;
00269 }
00270 
00271 /* Free data items in an array */
00272 static HRESULT SAFEARRAY_DestroyData(SAFEARRAY *psa, ULONG ulStartCell)
00273 {
00274   if (psa->pvData && !(psa->fFeatures & FADF_DATADELETED))
00275   {
00276     ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
00277 
00278     if (ulStartCell > ulCellCount) {
00279       FIXME("unexpted ulcellcount %d, start %d\n",ulCellCount,ulStartCell);
00280       return E_UNEXPECTED;
00281     }
00282 
00283     ulCellCount -= ulStartCell;
00284 
00285     if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
00286     {
00287       LPUNKNOWN *lpUnknown = (LPUNKNOWN *)psa->pvData + ulStartCell;
00288 
00289       while(ulCellCount--)
00290       {
00291         if (*lpUnknown)
00292           IUnknown_Release(*lpUnknown);
00293         lpUnknown++;
00294       }
00295     }
00296     else if (psa->fFeatures & (FADF_RECORD))
00297     {
00298       IRecordInfo *lpRecInfo;
00299 
00300       if (SUCCEEDED(SafeArrayGetRecordInfo(psa, &lpRecInfo)))
00301       {
00302         PBYTE pRecordData = psa->pvData;
00303         while(ulCellCount--)
00304         {
00305           IRecordInfo_RecordClear(lpRecInfo, pRecordData);
00306           pRecordData += psa->cbElements;
00307         }
00308         IRecordInfo_Release(lpRecInfo);
00309       }
00310     }
00311     else if (psa->fFeatures & FADF_BSTR)
00312     {
00313       BSTR* lpBstr = (BSTR*)psa->pvData + ulStartCell;
00314 
00315       while(ulCellCount--)
00316       {
00317         SysFreeString(*lpBstr);
00318         lpBstr++;
00319       }
00320     }
00321     else if (psa->fFeatures & FADF_VARIANT)
00322     {
00323       VARIANT* lpVariant = (VARIANT*)psa->pvData + ulStartCell;
00324 
00325       while(ulCellCount--)
00326       {
00327         HRESULT hRet = VariantClear(lpVariant);
00328 
00329         if (FAILED(hRet)) FIXME("VariantClear of element failed!\n");
00330         lpVariant++;
00331       }
00332     }
00333   }
00334   return S_OK;
00335 }
00336 
00337 /* Copy data items from one array to another */
00338 static HRESULT SAFEARRAY_CopyData(SAFEARRAY *psa, SAFEARRAY *dest)
00339 {
00340   if (!psa->pvData)
00341     return S_OK;
00342   else if (!dest->pvData || psa->fFeatures & FADF_DATADELETED)
00343     return E_INVALIDARG;
00344   else
00345   {
00346     ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
00347 
00348     dest->fFeatures = (dest->fFeatures & FADF_CREATEVECTOR) |
00349                       (psa->fFeatures & ~(FADF_CREATEVECTOR|FADF_DATADELETED));
00350 
00351     if (psa->fFeatures & FADF_VARIANT)
00352     {
00353       VARIANT* lpVariant = psa->pvData;
00354       VARIANT* lpDest = dest->pvData;
00355 
00356       while(ulCellCount--)
00357       {
00358         HRESULT hRet;
00359 
00360         hRet = VariantCopy(lpDest, lpVariant);
00361         if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet);
00362         lpVariant++;
00363         lpDest++;
00364       }
00365     }
00366     else if (psa->fFeatures & FADF_BSTR)
00367     {
00368       BSTR* lpBstr = psa->pvData;
00369       BSTR* lpDest = dest->pvData;
00370 
00371       while(ulCellCount--)
00372       {
00373         if (*lpBstr)
00374         {
00375           *lpDest = SysAllocStringByteLen((char*)*lpBstr, SysStringByteLen(*lpBstr));
00376           if (!*lpDest)
00377             return E_OUTOFMEMORY;
00378         }
00379         else
00380           *lpDest = NULL;
00381         lpBstr++;
00382         lpDest++;
00383       }
00384     }
00385     else
00386     {
00387       /* Copy the data over */
00388       memcpy(dest->pvData, psa->pvData, ulCellCount * psa->cbElements);
00389 
00390       if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
00391       {
00392         LPUNKNOWN *lpUnknown = dest->pvData;
00393 
00394         while(ulCellCount--)
00395         {
00396           if (*lpUnknown)
00397             IUnknown_AddRef(*lpUnknown);
00398           lpUnknown++;
00399         }
00400       }
00401     }
00402 
00403     if (psa->fFeatures & FADF_RECORD)
00404     {
00405       IRecordInfo* pRecInfo = NULL;
00406 
00407       SafeArrayGetRecordInfo(psa, &pRecInfo);
00408       SafeArraySetRecordInfo(dest, pRecInfo);
00409 
00410       if (pRecInfo)
00411       {
00412         /* Release because Get() adds a reference */
00413         IRecordInfo_Release(pRecInfo);
00414       }
00415     }
00416     else if (psa->fFeatures & FADF_HAVEIID)
00417     {
00418       GUID guid;
00419       SafeArrayGetIID(psa, &guid);
00420       SafeArraySetIID(dest, &guid);
00421     }
00422     else if (psa->fFeatures & FADF_HAVEVARTYPE)
00423     {
00424       SAFEARRAY_SetHiddenDWORD(dest, SAFEARRAY_GetHiddenDWORD(psa));
00425     }
00426   }
00427   return S_OK;
00428 }
00429 
00430 /*************************************************************************
00431  *      SafeArrayAllocDescriptor (OLEAUT32.36)
00432  *
00433  * Allocate and initialise a descriptor for a SafeArray.
00434  *
00435  * PARAMS
00436  *  cDims   [I] Number of dimensions of the array
00437  *  ppsaOut [O] Destination for new descriptor
00438  *
00439  * RETURNS
00440  * Success: S_OK. ppsaOut is filled with a newly allocated descriptor.
00441  * Failure: An HRESULT error code indicating the error.
00442  *
00443  * NOTES
00444  * See SafeArray.
00445  */
00446 HRESULT WINAPI SafeArrayAllocDescriptor(UINT cDims, SAFEARRAY **ppsaOut)
00447 {
00448   LONG allocSize;
00449 
00450   TRACE("(%d,%p)\n", cDims, ppsaOut);
00451   
00452   if (!cDims || cDims >= 0x10000) /* Maximum 65535 dimensions */
00453     return E_INVALIDARG;
00454 
00455   if (!ppsaOut)
00456     return E_POINTER;
00457 
00458   /* We need enough space for the header and its bounds */
00459   allocSize = sizeof(SAFEARRAY) + sizeof(SAFEARRAYBOUND) * (cDims - 1);
00460 
00461   if (FAILED(SAFEARRAY_AllocDescriptor(allocSize, ppsaOut)))
00462     return E_UNEXPECTED;
00463 
00464   (*ppsaOut)->cDims = cDims;
00465 
00466   TRACE("(%d): %u bytes allocated for descriptor.\n", cDims, allocSize);
00467   return S_OK;
00468 }
00469 
00470 /*************************************************************************
00471  *      SafeArrayAllocDescriptorEx (OLEAUT32.41)
00472  *
00473  * Allocate and initialise a descriptor for a SafeArray of a given type.
00474  *
00475  * PARAMS
00476  *  vt      [I] The type of items to store in the array
00477  *  cDims   [I] Number of dimensions of the array
00478  *  ppsaOut [O] Destination for new descriptor
00479  *
00480  * RETURNS
00481  *  Success: S_OK. ppsaOut is filled with a newly allocated descriptor.
00482  *  Failure: An HRESULT error code indicating the error.
00483  *
00484  * NOTES
00485  *  - This function does not check that vt is an allowed VARTYPE.
00486  *  - Unlike SafeArrayAllocDescriptor(), vt is associated with the array.
00487  *  See SafeArray.
00488  */
00489 HRESULT WINAPI SafeArrayAllocDescriptorEx(VARTYPE vt, UINT cDims, SAFEARRAY **ppsaOut)
00490 {
00491   ULONG cbElements;
00492   HRESULT hRet = E_UNEXPECTED;
00493 
00494   TRACE("(%d->%s,%d,%p)\n", vt, debugstr_vt(vt), cDims, ppsaOut);
00495     
00496   cbElements = SAFEARRAY_GetVTSize(vt);
00497   if (!cbElements)
00498     WARN("Creating a descriptor with an invalid VARTYPE!\n");
00499 
00500   hRet = SafeArrayAllocDescriptor(cDims, ppsaOut);
00501 
00502   if (SUCCEEDED(hRet))
00503   {
00504     SAFEARRAY_SetFeatures(vt, *ppsaOut);
00505     (*ppsaOut)->cbElements = cbElements;
00506   }
00507   return hRet;
00508 }
00509 
00510 /*************************************************************************
00511  *      SafeArrayAllocData (OLEAUT32.37)
00512  *
00513  * Allocate the data area of a SafeArray.
00514  *
00515  * PARAMS
00516  *  psa [I] SafeArray to allocate the data area of.
00517  *
00518  * RETURNS
00519  *  Success: S_OK. The data area is allocated and initialised.
00520  *  Failure: An HRESULT error code indicating the error.
00521  *
00522  * NOTES
00523  *  See SafeArray.
00524  */
00525 HRESULT WINAPI SafeArrayAllocData(SAFEARRAY *psa)
00526 {
00527   HRESULT hRet = E_INVALIDARG;
00528   
00529   TRACE("(%p)\n", psa);
00530   
00531   if (psa)
00532   {
00533     ULONG ulSize = SAFEARRAY_GetCellCount(psa);
00534 
00535     psa->pvData = SAFEARRAY_Malloc(ulSize * psa->cbElements);
00536 
00537     if (psa->pvData)
00538     {
00539       hRet = S_OK;
00540       TRACE("%u bytes allocated for data at %p (%u objects).\n",
00541             ulSize * psa->cbElements, psa->pvData, ulSize);
00542     }
00543     else
00544       hRet = E_OUTOFMEMORY;
00545   }
00546   return hRet;
00547 }
00548 
00549 /*************************************************************************
00550  *      SafeArrayCreate (OLEAUT32.15)
00551  *
00552  * Create a new SafeArray.
00553  *
00554  * PARAMS
00555  *  vt        [I] Type to store in the safe array
00556  *  cDims     [I] Number of array dimensions
00557  *  rgsabound [I] Bounds of the array dimensions
00558  *
00559  * RETURNS
00560  *  Success: A pointer to a new array object.
00561  *  Failure: NULL, if any parameter is invalid or memory allocation fails.
00562  *
00563  * NOTES
00564  *  Win32 allows arrays with 0 sized dimensions. This bug is not reproduced
00565  *  in the Wine implementation.
00566  *  See SafeArray.
00567  */
00568 SAFEARRAY* WINAPI SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound)
00569 {
00570   TRACE("(%d->%s,%d,%p)\n", vt, debugstr_vt(vt), cDims, rgsabound);
00571 
00572   if (vt == VT_RECORD)
00573     return NULL;
00574 
00575   return SAFEARRAY_Create(vt, cDims, rgsabound, 0);
00576 }
00577 
00578 /*************************************************************************
00579  *      SafeArrayCreateEx (OLEAUT32.15)
00580  *
00581  * Create a new SafeArray.
00582  *
00583  * PARAMS
00584  *  vt        [I] Type to store in the safe array
00585  *  cDims     [I] Number of array dimensions
00586  *  rgsabound [I] Bounds of the array dimensions
00587  *  pvExtra   [I] Extra data
00588  *
00589  * RETURNS
00590  *  Success: A pointer to a new array object.
00591  *  Failure: NULL, if any parameter is invalid or memory allocation fails.
00592  *
00593  * NOTES
00594  * See SafeArray.
00595  */
00596 SAFEARRAY* WINAPI SafeArrayCreateEx(VARTYPE vt, UINT cDims, SAFEARRAYBOUND *rgsabound, LPVOID pvExtra)
00597 {
00598   ULONG ulSize = 0;
00599   IRecordInfo* iRecInfo = pvExtra;
00600   SAFEARRAY* psa;
00601  
00602   TRACE("(%d->%s,%d,%p,%p)\n", vt, debugstr_vt(vt), cDims, rgsabound, pvExtra);
00603  
00604   if (vt == VT_RECORD)
00605   {
00606     if  (!iRecInfo)
00607       return NULL;
00608     IRecordInfo_GetSize(iRecInfo, &ulSize);
00609   }
00610   psa = SAFEARRAY_Create(vt, cDims, rgsabound, ulSize);
00611 
00612   if (pvExtra)
00613   {
00614     switch(vt)
00615     {
00616       case VT_RECORD:
00617         SafeArraySetRecordInfo(psa, pvExtra);
00618         break;
00619       case VT_UNKNOWN:
00620       case VT_DISPATCH:
00621         SafeArraySetIID(psa, pvExtra);
00622         break;
00623     }
00624   }
00625   return psa;
00626 }
00627 
00628 /************************************************************************
00629  *      SafeArrayCreateVector (OLEAUT32.411)
00630  *
00631  * Create a one dimensional, contiguous SafeArray.
00632  *
00633  * PARAMS
00634  *  vt        [I] Type to store in the safe array
00635  *  lLbound   [I] Lower bound of the array
00636  *  cElements [I] Number of elements in the array
00637  *
00638  * RETURNS
00639  *  Success: A pointer to a new array object.
00640  *  Failure: NULL, if any parameter is invalid or memory allocation fails.
00641  *
00642  * NOTES
00643  * See SafeArray.
00644  */
00645 SAFEARRAY* WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
00646 {
00647   TRACE("(%d->%s,%d,%d\n", vt, debugstr_vt(vt), lLbound, cElements);
00648     
00649   if (vt == VT_RECORD)
00650     return NULL;
00651 
00652   return SAFEARRAY_CreateVector(vt, lLbound, cElements, SAFEARRAY_GetVTSize(vt));
00653 }
00654 
00655 /************************************************************************
00656  *      SafeArrayCreateVectorEx (OLEAUT32.411)
00657  *
00658  * Create a one dimensional, contiguous SafeArray.
00659  *
00660  * PARAMS
00661  *  vt        [I] Type to store in the safe array
00662  *  lLbound   [I] Lower bound of the array
00663  *  cElements [I] Number of elements in the array
00664  *  pvExtra   [I] Extra data
00665  *
00666  * RETURNS
00667  *  Success: A pointer to a new array object.
00668  *  Failure: NULL, if any parameter is invalid or memory allocation fails.
00669  *
00670  * NOTES
00671  * See SafeArray.
00672  */
00673 SAFEARRAY* WINAPI SafeArrayCreateVectorEx(VARTYPE vt, LONG lLbound, ULONG cElements, LPVOID pvExtra)
00674 {
00675   ULONG ulSize;
00676   IRecordInfo* iRecInfo = pvExtra;
00677   SAFEARRAY* psa;
00678 
00679  TRACE("(%d->%s,%d,%d,%p\n", vt, debugstr_vt(vt), lLbound, cElements, pvExtra);
00680  
00681   if (vt == VT_RECORD)
00682   {
00683     if  (!iRecInfo)
00684       return NULL;
00685     IRecordInfo_GetSize(iRecInfo, &ulSize);
00686   }
00687   else
00688     ulSize = SAFEARRAY_GetVTSize(vt);
00689 
00690   psa = SAFEARRAY_CreateVector(vt, lLbound, cElements, ulSize);
00691 
00692   if (pvExtra)
00693   {
00694     switch(vt)
00695     {
00696       case VT_RECORD:
00697         SafeArraySetRecordInfo(psa, iRecInfo);
00698         break;
00699       case VT_UNKNOWN:
00700       case VT_DISPATCH:
00701         SafeArraySetIID(psa, pvExtra);
00702         break;
00703     }
00704   }
00705   return psa;
00706 }
00707 
00708 /*************************************************************************
00709  *      SafeArrayDestroyDescriptor (OLEAUT32.38)
00710  *
00711  * Destroy a SafeArray.
00712  *
00713  * PARAMS
00714  *  psa [I] SafeArray to destroy.
00715  *
00716  * RETURNS
00717  *  Success: S_OK. The resources used by the array are freed.
00718  *  Failure: An HRESULT error code indicating the error.
00719  *
00720  * NOTES
00721  * See SafeArray.
00722  */
00723 HRESULT WINAPI SafeArrayDestroyDescriptor(SAFEARRAY *psa)
00724 {
00725   TRACE("(%p)\n", psa);
00726     
00727   if (psa)
00728   {
00729     LPVOID lpv = (char*)psa - SAFEARRAY_HIDDEN_SIZE;
00730 
00731     if (psa->cLocks)
00732       return DISP_E_ARRAYISLOCKED; /* Can't destroy a locked array */
00733 
00734     if (psa->fFeatures & FADF_RECORD)
00735       SafeArraySetRecordInfo(psa, NULL);
00736 
00737     if (psa->fFeatures & FADF_CREATEVECTOR &&
00738         !(psa->fFeatures & FADF_DATADELETED))
00739         SAFEARRAY_DestroyData(psa, 0); /* Data not previously deleted */
00740 
00741     if (!SAFEARRAY_Free(lpv))
00742       return E_UNEXPECTED;
00743   }
00744   return S_OK;
00745 }
00746 
00747 /*************************************************************************
00748  *      SafeArrayLock (OLEAUT32.21)
00749  *
00750  * Increment the lock counter of a SafeArray.
00751  *
00752  * PARAMS
00753  *  psa [O] SafeArray to lock
00754  *
00755  * RETURNS
00756  *  Success: S_OK. The array lock is incremented.
00757  *  Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if too many locks
00758  *           are held on the array at once.
00759  *
00760  * NOTES
00761  *  In Win32 these locks are not thread safe.
00762  *  See SafeArray.
00763  */
00764 HRESULT WINAPI SafeArrayLock(SAFEARRAY *psa)
00765 {
00766   ULONG ulLocks;
00767 
00768   TRACE("(%p)\n", psa);
00769     
00770   if (!psa)
00771     return E_INVALIDARG;
00772 
00773   ulLocks = InterlockedIncrement( (LONG*) &psa->cLocks);
00774 
00775   if (ulLocks > 0xffff) /* Maximum of 16384 locks at a time */
00776   {
00777     WARN("Out of locks!\n");
00778     InterlockedDecrement( (LONG*) &psa->cLocks);
00779     return E_UNEXPECTED;
00780   }
00781   return S_OK;
00782 }
00783 
00784 /*************************************************************************
00785  *      SafeArrayUnlock (OLEAUT32.22)
00786  *
00787  * Decrement the lock counter of a SafeArray.
00788  *
00789  * PARAMS
00790  *  psa [O] SafeArray to unlock
00791  *
00792  * RETURNS
00793  *  Success: S_OK. The array lock is decremented.
00794  *  Failure: E_INVALIDARG if psa is NULL, or E_UNEXPECTED if no locks are
00795  *           held on the array.
00796  *
00797  * NOTES
00798  * See SafeArray.
00799  */
00800 HRESULT WINAPI SafeArrayUnlock(SAFEARRAY *psa)
00801 {
00802   TRACE("(%p)\n", psa);
00803   
00804   if (!psa)
00805     return E_INVALIDARG;
00806 
00807   if (InterlockedDecrement( (LONG*) &psa->cLocks) < 0)
00808   {
00809     WARN("Unlocked but no lock held!\n");
00810     InterlockedIncrement( (LONG*) &psa->cLocks);
00811     return E_UNEXPECTED;
00812   }
00813   return S_OK;
00814 }
00815 
00816 /*************************************************************************
00817  *      SafeArrayPutElement (OLEAUT32.26)
00818  *
00819  * Put an item into a SafeArray.
00820  *
00821  * PARAMS
00822  *  psa       [I] SafeArray to insert into
00823  *  rgIndices [I] Indices to insert at
00824  *  pvData    [I] Data to insert
00825  *
00826  * RETURNS
00827  *  Success: S_OK. The item is inserted
00828  *  Failure: An HRESULT error code indicating the error.
00829  *
00830  * NOTES
00831  * See SafeArray.
00832  */
00833 HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
00834 {
00835   HRESULT hRet;
00836 
00837   TRACE("(%p,%p,%p)\n", psa, rgIndices, pvData);
00838 
00839   if (!psa || !rgIndices)
00840     return E_INVALIDARG;
00841 
00842   hRet = SafeArrayLock(psa);
00843 
00844   if (SUCCEEDED(hRet))
00845   {
00846     PVOID lpvDest;
00847 
00848     hRet = SafeArrayPtrOfIndex(psa, rgIndices, &lpvDest);
00849 
00850     if (SUCCEEDED(hRet))
00851     {
00852       if (psa->fFeatures & FADF_VARIANT)
00853       {
00854         VARIANT* lpVariant = pvData;
00855         VARIANT* lpDest = lpvDest;
00856 
00857         hRet = VariantClear(lpDest);
00858         if (FAILED(hRet)) FIXME("VariantClear failed with 0x%x\n", hRet);
00859         hRet = VariantCopy(lpDest, lpVariant);
00860         if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet);
00861       }
00862       else if (psa->fFeatures & FADF_BSTR)
00863       {
00864         BSTR  lpBstr = (BSTR)pvData;
00865         BSTR* lpDest = lpvDest;
00866 
00867         SysFreeString(*lpDest);
00868 
00869         *lpDest = SysAllocStringByteLen((char*)lpBstr, SysStringByteLen(lpBstr));
00870         if (!*lpDest)
00871           hRet = E_OUTOFMEMORY;
00872       }
00873       else
00874       {
00875         if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
00876         {
00877           LPUNKNOWN  lpUnknown = pvData;
00878           LPUNKNOWN *lpDest = lpvDest;
00879 
00880           if (lpUnknown)
00881             IUnknown_AddRef(lpUnknown);
00882           if (*lpDest)
00883             IUnknown_Release(*lpDest);
00884       *lpDest = lpUnknown;
00885         } else {
00886           /* Copy the data over */
00887           memcpy(lpvDest, pvData, psa->cbElements);
00888     }
00889       }
00890     }
00891     SafeArrayUnlock(psa);
00892   }
00893   return hRet;
00894 }
00895 
00896 
00897 /*************************************************************************
00898  *      SafeArrayGetElement (OLEAUT32.25)
00899  *
00900  * Get an item from a SafeArray.
00901  *
00902  * PARAMS
00903  *  psa       [I] SafeArray to get from
00904  *  rgIndices [I] Indices to get from
00905  *  pvData    [O] Destination for data
00906  *
00907  * RETURNS
00908  *  Success: S_OK. The item data is returned in pvData.
00909  *  Failure: An HRESULT error code indicating the error.
00910  *
00911  * NOTES
00912  * See SafeArray.
00913  */
00914 HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
00915 {
00916   HRESULT hRet;
00917 
00918   TRACE("(%p,%p,%p)\n", psa, rgIndices, pvData);
00919     
00920   if (!psa || !rgIndices || !pvData)
00921     return E_INVALIDARG;
00922 
00923   hRet = SafeArrayLock(psa);
00924 
00925   if (SUCCEEDED(hRet))
00926   {
00927     PVOID lpvSrc;
00928 
00929     hRet = SafeArrayPtrOfIndex(psa, rgIndices, &lpvSrc);
00930 
00931     if (SUCCEEDED(hRet))
00932     {
00933       if (psa->fFeatures & FADF_VARIANT)
00934       {
00935         VARIANT* lpVariant = lpvSrc;
00936         VARIANT* lpDest = pvData;
00937 
00938         /* The original content of pvData is ignored. */
00939         V_VT(lpDest) = VT_EMPTY;
00940         hRet = VariantCopy(lpDest, lpVariant);
00941     if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%x\n", hRet);
00942       }
00943       else if (psa->fFeatures & FADF_BSTR)
00944       {
00945         BSTR* lpBstr = lpvSrc;
00946         BSTR* lpDest = pvData;
00947 
00948         if (*lpBstr)
00949         {
00950           *lpDest = SysAllocStringByteLen((char*)*lpBstr, SysStringByteLen(*lpBstr));
00951           if (!*lpBstr)
00952             hRet = E_OUTOFMEMORY;
00953         }
00954         else
00955           *lpDest = NULL;
00956       }
00957       else
00958       {
00959         if (psa->fFeatures & (FADF_UNKNOWN|FADF_DISPATCH))
00960         {
00961           LPUNKNOWN *lpUnknown = lpvSrc;
00962 
00963           if (*lpUnknown)
00964             IUnknown_AddRef(*lpUnknown);
00965         }
00966         /* Copy the data over */
00967         memcpy(pvData, lpvSrc, psa->cbElements);
00968       }
00969     }
00970     SafeArrayUnlock(psa);
00971   }
00972   return hRet;
00973 }
00974 
00975 /*************************************************************************
00976  *      SafeArrayGetUBound (OLEAUT32.19)
00977  *
00978  * Get the upper bound for a given SafeArray dimension
00979  *
00980  * PARAMS
00981  *  psa      [I] Array to get dimension upper bound from
00982  *  nDim     [I] The dimension number to get the upper bound of
00983  *  plUbound [O] Destination for the upper bound
00984  *
00985  * RETURNS
00986  *  Success: S_OK. plUbound contains the dimensions upper bound.
00987  *  Failure: An HRESULT error code indicating the error.
00988  *
00989  * NOTES
00990  * See SafeArray.
00991  */
00992 HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
00993 {
00994   TRACE("(%p,%d,%p)\n", psa, nDim, plUbound);
00995     
00996   if (!psa || !plUbound)
00997     return E_INVALIDARG;
00998 
00999   if(!nDim || nDim > psa->cDims)
01000     return DISP_E_BADINDEX;
01001 
01002   *plUbound = psa->rgsabound[psa->cDims - nDim].lLbound +
01003               psa->rgsabound[psa->cDims - nDim].cElements - 1;
01004 
01005   return S_OK;
01006 }
01007 
01008 /*************************************************************************
01009  *      SafeArrayGetLBound (OLEAUT32.20)
01010  *
01011  * Get the lower bound for a given SafeArray dimension
01012  *
01013  * PARAMS
01014  *  psa      [I] Array to get dimension lower bound from
01015  *  nDim     [I] The dimension number to get the lowe bound of
01016  *  plLbound [O] Destination for the lower bound
01017  *
01018  * RETURNS
01019  *  Success: S_OK. plUbound contains the dimensions lower bound.
01020  *  Failure: An HRESULT error code indicating the error.
01021  *
01022  * NOTES
01023  * See SafeArray.
01024  */
01025 HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
01026 {
01027   TRACE("(%p,%d,%p)\n", psa, nDim, plLbound);
01028 
01029   if (!psa || !plLbound)
01030     return E_INVALIDARG;
01031 
01032   if(!nDim || nDim > psa->cDims)
01033     return DISP_E_BADINDEX;
01034 
01035   *plLbound = psa->rgsabound[psa->cDims - nDim].lLbound;
01036   return S_OK;
01037 }
01038 
01039 /*************************************************************************
01040  *      SafeArrayGetDim (OLEAUT32.17)
01041  *
01042  * Get the number of dimensions in a SafeArray.
01043  *
01044  * PARAMS
01045  *  psa [I] Array to get the dimensions of
01046  *
01047  * RETURNS
01048  *  The number of array dimensions in psa, or 0 if psa is NULL.
01049  *
01050  * NOTES
01051  * See SafeArray.
01052  */
01053 UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa)
01054 {
01055   TRACE("(%p) returning %d\n", psa, psa ? psa->cDims : 0u);  
01056   return psa ? psa->cDims : 0;
01057 }
01058 
01059 /*************************************************************************
01060  *      SafeArrayGetElemsize (OLEAUT32.18)
01061  *
01062  * Get the size of an element in a SafeArray.
01063  *
01064  * PARAMS
01065  *  psa [I] Array to get the element size from
01066  *
01067  * RETURNS
01068  *  The size of a single element in psa, or 0 if psa is NULL.
01069  *
01070  * NOTES
01071  * See SafeArray.
01072  */
01073 UINT WINAPI SafeArrayGetElemsize(SAFEARRAY *psa)
01074 {
01075   TRACE("(%p) returning %d\n", psa, psa ? psa->cbElements : 0u);
01076   return psa ? psa->cbElements : 0;
01077 }
01078 
01079 /*************************************************************************
01080  *      SafeArrayAccessData (OLEAUT32.23)
01081  *
01082  * Lock a SafeArray and return a pointer to its data.
01083  *
01084  * PARAMS
01085  *  psa     [I] Array to get the data pointer from
01086  *  ppvData [O] Destination for the arrays data pointer
01087  *
01088  * RETURNS
01089  *  Success: S_OK. ppvData contains the arrays data pointer, and the array
01090  *           is locked.
01091  *  Failure: An HRESULT error code indicating the error.
01092  *
01093  * NOTES
01094  * See SafeArray.
01095  */
01096 HRESULT WINAPI SafeArrayAccessData(SAFEARRAY *psa, void **ppvData)
01097 {
01098   TRACE("(%p,%p)\n", psa, ppvData);
01099 
01100   if(!psa || !ppvData)
01101     return E_INVALIDARG;
01102 
01103   if (SUCCEEDED(SafeArrayLock(psa)))
01104   {
01105     *ppvData = psa->pvData;
01106     return S_OK;
01107   }
01108   *ppvData = NULL;
01109   return E_UNEXPECTED;
01110 }
01111 
01112 
01113 /*************************************************************************
01114  *      SafeArrayUnaccessData (OLEAUT32.24)
01115  *
01116  * Unlock a SafeArray after accessing its data.
01117  *
01118  * PARAMS
01119  *  psa     [I] Array to unlock
01120  *
01121  * RETURNS
01122  *  Success: S_OK. The array is unlocked.
01123  *  Failure: An HRESULT error code indicating the error.
01124  *
01125  * NOTES
01126  * See SafeArray.
01127  */
01128 HRESULT WINAPI SafeArrayUnaccessData(SAFEARRAY *psa)
01129 {
01130   TRACE("(%p)\n", psa);
01131   return SafeArrayUnlock(psa);
01132 }
01133 
01134 /************************************************************************
01135  *      SafeArrayPtrOfIndex (OLEAUT32.148)
01136  *
01137  * Get the address of an item in a SafeArray.
01138  *
01139  * PARAMS
01140  *  psa       [I] Array to get the items address from
01141  *  rgIndices [I] Index of the item in the array
01142  *  ppvData   [O] Destination for item address
01143  *
01144  * RETURNS
01145  *  Success: S_OK. ppvData contains a pointer to the item.
01146  *  Failure: An HRESULT error code indicating the error.
01147  *
01148  * NOTES
01149  *  This function does not lock the array.
01150  *
01151  * NOTES
01152  * See SafeArray.
01153  */
01154 HRESULT WINAPI SafeArrayPtrOfIndex(SAFEARRAY *psa, LONG *rgIndices, void **ppvData)
01155 {
01156   USHORT dim;
01157   ULONG cell = 0, dimensionSize = 1;
01158   SAFEARRAYBOUND* psab;
01159   LONG c1;
01160 
01161   TRACE("(%p,%p,%p)\n", psa, rgIndices, ppvData);
01162   
01163   /* The general formula for locating the cell number of an entry in an n
01164    * dimensional array (where cn = coordinate in dimension dn) is:
01165    *
01166    * c1 + c2 * sizeof(d1) + c3 * sizeof(d2) ... + cn * sizeof(c(n-1))
01167    *
01168    * We calculate the size of the last dimension at each step through the
01169    * dimensions to avoid recursing to calculate the last dimensions size.
01170    */
01171   if (!psa || !rgIndices || !ppvData)
01172     return E_INVALIDARG;
01173 
01174   psab = psa->rgsabound + psa->cDims - 1;
01175   c1 = *rgIndices++;
01176 
01177   if (c1 < psab->lLbound || c1 >= psab->lLbound + (LONG)psab->cElements)
01178     return DISP_E_BADINDEX; /* Initial index out of bounds */
01179 
01180   for (dim = 1; dim < psa->cDims; dim++)
01181   {
01182     dimensionSize *= psab->cElements;
01183 
01184     psab--;
01185 
01186     if (!psab->cElements ||
01187         *rgIndices < psab->lLbound ||
01188         *rgIndices >= psab->lLbound + (LONG)psab->cElements)
01189     return DISP_E_BADINDEX; /* Index out of bounds */
01190 
01191     cell += (*rgIndices - psab->lLbound) * dimensionSize;
01192     rgIndices++;
01193   }
01194 
01195   cell += (c1 - psa->rgsabound[psa->cDims - 1].lLbound);
01196 
01197   *ppvData = (char*)psa->pvData + cell * psa->cbElements;
01198   return S_OK;
01199 }
01200 
01201 /************************************************************************
01202  *      SafeArrayDestroyData (OLEAUT32.39)
01203  *
01204  * Destroy the data associated with a SafeArray.
01205  *
01206  * PARAMS
01207  *  psa [I] Array to delete the data from
01208  *
01209  * RETURNS
01210  *  Success: S_OK. All items and the item data are freed.
01211  *  Failure: An HRESULT error code indicating the error.
01212  *
01213  * NOTES
01214  * See SafeArray.
01215  */
01216 HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa)
01217 {
01218   TRACE("(%p)\n", psa);
01219   
01220   if (!psa)
01221     return E_INVALIDARG;
01222 
01223   if (psa->cLocks)
01224     return DISP_E_ARRAYISLOCKED; /* Can't delete a locked array */
01225 
01226   /* Delete the actual item data */
01227   if (FAILED(SAFEARRAY_DestroyData(psa, 0)))
01228     return E_UNEXPECTED;
01229 
01230   if (psa->pvData)
01231   {
01232     if (psa->fFeatures & FADF_STATIC)
01233     {
01234       ZeroMemory(psa->pvData, SAFEARRAY_GetCellCount(psa) * psa->cbElements);
01235       return S_OK;
01236     }
01237     /* If this is not a vector, free the data memory block */
01238     if (!(psa->fFeatures & FADF_CREATEVECTOR))
01239     {
01240       if (!SAFEARRAY_Free(psa->pvData))
01241         return E_UNEXPECTED;
01242       psa->pvData = NULL;
01243     }
01244     else
01245       psa->fFeatures |= FADF_DATADELETED; /* Mark the data deleted */
01246 
01247   }
01248   return S_OK;
01249 }
01250 
01251 /************************************************************************
01252  *      SafeArrayCopyData (OLEAUT32.412)
01253  *
01254  * Copy all data from one SafeArray to another.
01255  *
01256  * PARAMS
01257  *  psaSource [I] Source for copy
01258  *  psaTarget [O] Destination for copy
01259  *
01260  * RETURNS
01261  *  Success: S_OK. psaTarget contains a copy of psaSource.
01262  *  Failure: An HRESULT error code indicating the error.
01263  *
01264  * NOTES
01265  *  The two arrays must have the same number of dimensions and elements.
01266  *
01267  * NOTES
01268  * See SafeArray.
01269  */
01270 HRESULT WINAPI SafeArrayCopyData(SAFEARRAY *psaSource, SAFEARRAY *psaTarget)
01271 {
01272   int dim;
01273 
01274   TRACE("(%p,%p)\n", psaSource, psaTarget);
01275   
01276   if (!psaSource || !psaTarget ||
01277       psaSource->cDims != psaTarget->cDims ||
01278       psaSource->cbElements != psaTarget->cbElements)
01279     return E_INVALIDARG;
01280 
01281   /* Each dimension must be the same size */
01282   for (dim = psaSource->cDims - 1; dim >= 0 ; dim--)
01283     if (psaSource->rgsabound[dim].cElements !=
01284        psaTarget->rgsabound[dim].cElements)
01285       return E_INVALIDARG;
01286 
01287   if (SUCCEEDED(SAFEARRAY_DestroyData(psaTarget, 0)) &&
01288       SUCCEEDED(SAFEARRAY_CopyData(psaSource, psaTarget)))
01289     return S_OK;
01290   return E_UNEXPECTED;
01291 }
01292 
01293 /************************************************************************
01294  *      SafeArrayDestroy (OLEAUT32.16)
01295  *
01296  * Destroy a SafeArray.
01297  *
01298  * PARAMS
01299  *  psa [I] Array to destroy
01300  *
01301  * RETURNS
01302  *  Success: S_OK. All resources used by the array are freed.
01303  *  Failure: An HRESULT error code indicating the error.
01304  *
01305  * NOTES
01306  * See SafeArray.
01307  */
01308 HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
01309 {
01310   TRACE("(%p)\n", psa);
01311 
01312   if(!psa)
01313     return S_OK;
01314 
01315   if(psa->cLocks > 0)
01316     return DISP_E_ARRAYISLOCKED;
01317 
01318   /* Native doesn't check to see if the free succeeds */
01319   SafeArrayDestroyData(psa);
01320   SafeArrayDestroyDescriptor(psa);
01321   return S_OK;
01322 }
01323 
01324 /************************************************************************
01325  *      SafeArrayCopy (OLEAUT32.27)
01326  *
01327  * Make a duplicate of a SafeArray.
01328  *
01329  * PARAMS
01330  *  psa     [I] Source for copy
01331  *  ppsaOut [O] Destination for new copy
01332  *
01333  * RETURNS
01334  *  Success: S_OK. ppsaOut contains a copy of the array.
01335  *  Failure: An HRESULT error code indicating the error.
01336  *
01337  * NOTES
01338  * See SafeArray.
01339  */
01340 HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut)
01341 {
01342   HRESULT hRet;
01343 
01344   TRACE("(%p,%p)\n", psa, ppsaOut);
01345 
01346   if (!ppsaOut)
01347     return E_INVALIDARG;
01348 
01349   *ppsaOut = NULL;
01350 
01351   if (!psa)
01352     return S_OK; /* Handles copying of NULL arrays */
01353 
01354   if (!psa->cbElements)
01355   {
01356     ERR("not copying an array of 0 elements\n");
01357     return E_INVALIDARG;
01358   }
01359 
01360   if (psa->fFeatures & (FADF_RECORD|FADF_HAVEIID|FADF_HAVEVARTYPE))
01361   {
01362     VARTYPE vt;
01363     if (FAILED(SafeArrayGetVartype(psa, &vt)))
01364       hRet = E_UNEXPECTED;
01365     else
01366       hRet = SafeArrayAllocDescriptorEx(vt, psa->cDims, ppsaOut);
01367   }
01368   else
01369   {
01370     hRet = SafeArrayAllocDescriptor(psa->cDims, ppsaOut);
01371     if (SUCCEEDED(hRet))
01372     {
01373       (*ppsaOut)->fFeatures = psa->fFeatures & ~FADF_CREATEVECTOR;
01374       (*ppsaOut)->cbElements = psa->cbElements;
01375     }
01376   }
01377 
01378   if (SUCCEEDED(hRet))
01379   {
01380     /* Copy dimension bounds */
01381     memcpy((*ppsaOut)->rgsabound, psa->rgsabound, psa->cDims * sizeof(SAFEARRAYBOUND));
01382 
01383     (*ppsaOut)->pvData = SAFEARRAY_Malloc(SAFEARRAY_GetCellCount(psa) * psa->cbElements);
01384 
01385     if ((*ppsaOut)->pvData)
01386     {
01387       hRet = SAFEARRAY_CopyData(psa, *ppsaOut);
01388  
01389       if (SUCCEEDED(hRet))
01390         return hRet;
01391 
01392       SAFEARRAY_Free((*ppsaOut)->pvData);
01393     }
01394     SafeArrayDestroyDescriptor(*ppsaOut);
01395   }
01396   *ppsaOut = NULL;
01397   return hRet;
01398 }
01399 
01400 /************************************************************************
01401  *      SafeArrayRedim (OLEAUT32.40)
01402  *
01403  * Changes the characteristics of the last dimension of a SafeArray
01404  *
01405  * PARAMS
01406  *  psa      [I] Array to change
01407  *  psabound [I] New bound details for the last dimension
01408  *
01409  * RETURNS
01410  *  Success: S_OK. psa is updated to reflect the new bounds.
01411  *  Failure: An HRESULT error code indicating the error.
01412  *
01413  * NOTES
01414  * See SafeArray.
01415  */
01416 HRESULT WINAPI SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psabound)
01417 {
01418   SAFEARRAYBOUND *oldBounds;
01419 
01420   TRACE("(%p,%p)\n", psa, psabound);
01421   
01422   if (!psa || psa->fFeatures & FADF_FIXEDSIZE || !psabound)
01423     return E_INVALIDARG;
01424 
01425   if (psa->cLocks > 0)
01426     return DISP_E_ARRAYISLOCKED;
01427 
01428   if (FAILED(SafeArrayLock(psa)))
01429     return E_UNEXPECTED;
01430 
01431   oldBounds = psa->rgsabound;
01432   oldBounds->lLbound = psabound->lLbound;
01433 
01434   if (psabound->cElements != oldBounds->cElements)
01435   {
01436     if (psabound->cElements < oldBounds->cElements)
01437     {
01438       /* Shorten the final dimension. */
01439       ULONG ulStartCell = psabound->cElements *
01440                           (SAFEARRAY_GetCellCount(psa) / oldBounds->cElements);
01441       SAFEARRAY_DestroyData(psa, ulStartCell);
01442     }
01443     else
01444     {
01445       /* Lengthen the final dimension */
01446       ULONG ulOldSize, ulNewSize;
01447       PVOID pvNewData;
01448 
01449       ulOldSize = SAFEARRAY_GetCellCount(psa) * psa->cbElements;
01450       if (ulOldSize)
01451         ulNewSize = (ulOldSize / oldBounds->cElements) * psabound->cElements;
01452       else {
01453     int oldelems = oldBounds->cElements;
01454     oldBounds->cElements = psabound->cElements;
01455         ulNewSize = SAFEARRAY_GetCellCount(psa) * psa->cbElements;
01456     oldBounds->cElements = oldelems;
01457       }
01458 
01459       if (!(pvNewData = SAFEARRAY_Malloc(ulNewSize)))
01460       {
01461         SafeArrayUnlock(psa);
01462         return E_UNEXPECTED;
01463       }
01464 
01465       memcpy(pvNewData, psa->pvData, ulOldSize);
01466       SAFEARRAY_Free(psa->pvData);
01467       psa->pvData = pvNewData;
01468     }
01469     oldBounds->cElements = psabound->cElements;
01470   }
01471 
01472   SafeArrayUnlock(psa);
01473   return S_OK;
01474 }
01475 
01476 /************************************************************************
01477  *      SafeArrayGetVartype (OLEAUT32.77)
01478  *
01479  * Get the type of the items in a SafeArray.
01480  *
01481  * PARAMS
01482  *  psa [I] Array to get the type from
01483  *  pvt [O] Destination for the type
01484  *
01485  * RETURNS
01486  *  Success: S_OK. pvt contains the type of the items.
01487  *  Failure: An HRESULT error code indicating the error.
01488  *
01489  * NOTES
01490  * See SafeArray.
01491  */
01492 HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY* psa, VARTYPE* pvt)
01493 {
01494   TRACE("(%p,%p)\n", psa, pvt);
01495 
01496   if (!psa || !pvt)
01497     return E_INVALIDARG;
01498 
01499   if (psa->fFeatures & FADF_RECORD)
01500     *pvt = VT_RECORD;
01501   else if ((psa->fFeatures & (FADF_HAVEIID|FADF_DISPATCH)) == (FADF_HAVEIID|FADF_DISPATCH))
01502     *pvt = VT_DISPATCH;
01503   else if (psa->fFeatures & FADF_HAVEIID)
01504     *pvt = VT_UNKNOWN;
01505   else if (psa->fFeatures & FADF_HAVEVARTYPE)
01506   {
01507     VARTYPE vt = SAFEARRAY_GetHiddenDWORD(psa);
01508     *pvt = vt;
01509   }
01510   else
01511     return E_INVALIDARG;
01512 
01513   return S_OK;
01514 }
01515 
01516 /************************************************************************
01517  *      SafeArraySetRecordInfo (OLEAUT32.@)
01518  *
01519  * Set the record info for a SafeArray.
01520  *
01521  * PARAMS
01522  *  psa    [I] Array to set the record info for
01523  *  pRinfo [I] Record info
01524  *
01525  * RETURNS
01526  *  Success: S_OK. The record info is stored with the array.
01527  *  Failure: An HRESULT error code indicating the error.
01528  *
01529  * NOTES
01530  * See SafeArray.
01531  */
01532 HRESULT WINAPI SafeArraySetRecordInfo(SAFEARRAY *psa, IRecordInfo *pRinfo)
01533 {
01534   IRecordInfo** dest = (IRecordInfo**)psa;
01535 
01536   TRACE("(%p,%p)\n", psa, pRinfo);
01537   
01538   if (!psa || !(psa->fFeatures & FADF_RECORD))
01539     return E_INVALIDARG;
01540 
01541   if (pRinfo)
01542     IRecordInfo_AddRef(pRinfo);
01543 
01544   if (dest[-1])
01545     IRecordInfo_Release(dest[-1]);
01546 
01547   dest[-1] = pRinfo;
01548   return S_OK;
01549 }
01550 
01551 /************************************************************************
01552  *      SafeArrayGetRecordInfo (OLEAUT32.@)
01553  *
01554  * Get the record info from a SafeArray.
01555  *
01556  * PARAMS
01557  *  psa    [I] Array to get the record info from
01558  *  pRinfo [O] Destination for the record info
01559  *
01560  * RETURNS
01561  *  Success: S_OK. pRinfo contains the record info, or NULL if there was none.
01562  *  Failure: An HRESULT error code indicating the error.
01563  *
01564  * NOTES
01565  * See SafeArray.
01566  */
01567 HRESULT WINAPI SafeArrayGetRecordInfo(SAFEARRAY *psa, IRecordInfo **pRinfo)
01568 {
01569   IRecordInfo** src = (IRecordInfo**)psa;
01570 
01571   TRACE("(%p,%p)\n", psa, pRinfo);
01572 
01573   if (!psa || !pRinfo || !(psa->fFeatures & FADF_RECORD))
01574     return E_INVALIDARG;
01575 
01576   *pRinfo = src[-1];
01577 
01578   if (*pRinfo)
01579     IRecordInfo_AddRef(*pRinfo);
01580   return S_OK;
01581 }
01582 
01583 /************************************************************************
01584  *      SafeArraySetIID (OLEAUT32.@)
01585  *
01586  * Set the IID for a SafeArray.
01587  *
01588  * PARAMS
01589  *  psa  [I] Array to set the IID from
01590  *  guid [I] IID
01591  *
01592  * RETURNS
01593  *  Success: S_OK. The IID is stored with the array
01594  *  Failure: An HRESULT error code indicating the error.
01595  *
01596  * NOTES
01597  * See SafeArray.
01598  */
01599 HRESULT WINAPI SafeArraySetIID(SAFEARRAY *psa, REFGUID guid)
01600 {
01601   GUID* dest = (GUID*)psa;
01602 
01603   TRACE("(%p,%s)\n", psa, debugstr_guid(guid));
01604 
01605   if (!psa || !guid || !(psa->fFeatures & FADF_HAVEIID))
01606     return E_INVALIDARG;
01607 
01608   dest[-1] = *guid;
01609   return S_OK;
01610 }
01611 
01612 /************************************************************************
01613  *      SafeArrayGetIID (OLEAUT32.@)
01614  *
01615  * Get the IID from a SafeArray.
01616  *
01617  * PARAMS
01618  *  psa   [I] Array to get the ID from
01619  *  pGuid [O] Destination for the IID
01620  *
01621  * RETURNS
01622  *  Success: S_OK. pRinfo contains the IID, or NULL if there was none.
01623  *  Failure: An HRESULT error code indicating the error.
01624  *
01625  * NOTES
01626  * See SafeArray.
01627  */
01628 HRESULT WINAPI SafeArrayGetIID(SAFEARRAY *psa, GUID *pGuid)
01629 {
01630   GUID* src = (GUID*)psa;
01631 
01632   TRACE("(%p,%p)\n", psa, pGuid);
01633 
01634   if (!psa || !pGuid || !(psa->fFeatures & FADF_HAVEIID))
01635     return E_INVALIDARG;
01636 
01637   *pGuid = src[-1];
01638   return S_OK;
01639 }
01640 
01641 /************************************************************************
01642  *      VectorFromBstr (OLEAUT32.@)
01643  *
01644  * Create a SafeArray Vector from the bytes of a BSTR.
01645  *
01646  * PARAMS
01647  *  bstr [I] String to get bytes from
01648  *  ppsa [O] Destination for the array
01649  *
01650  * RETURNS
01651  *  Success: S_OK. ppsa contains the strings bytes as a VT_UI1 array.
01652  *  Failure: An HRESULT error code indicating the error.
01653  *
01654  * NOTES
01655  * See SafeArray.
01656  */
01657 HRESULT WINAPI VectorFromBstr(BSTR bstr, SAFEARRAY **ppsa)
01658 {
01659   SAFEARRAYBOUND sab;
01660 
01661   TRACE("(%p,%p)\n", bstr, ppsa);
01662   
01663   if (!ppsa)
01664     return E_INVALIDARG;
01665 
01666   sab.lLbound = 0;
01667   sab.cElements = SysStringByteLen(bstr);
01668 
01669   *ppsa = SAFEARRAY_Create(VT_UI1, 1, &sab, 0);
01670 
01671   if (*ppsa)
01672   {
01673     memcpy((*ppsa)->pvData, bstr, sab.cElements);
01674     return S_OK;
01675   }
01676   return E_OUTOFMEMORY;
01677 }
01678 
01679 /************************************************************************
01680  *      BstrFromVector (OLEAUT32.@)
01681  *
01682  * Create a BSTR from a SafeArray.
01683  *
01684  * PARAMS
01685  *  psa   [I] Source array
01686  *  pbstr [O] Destination for output BSTR
01687  *
01688  * RETURNS
01689  *  Success: S_OK. pbstr contains the arrays data.
01690  *  Failure: An HRESULT error code indicating the error.
01691  *
01692  * NOTES
01693  *  psa must be a 1 dimensional array of a 1 byte type.
01694  *
01695  * NOTES
01696  * See SafeArray.
01697  */
01698 HRESULT WINAPI BstrFromVector(SAFEARRAY *psa, BSTR *pbstr)
01699 {
01700   TRACE("(%p,%p)\n", psa, pbstr);
01701 
01702   if (!pbstr)
01703     return E_INVALIDARG;
01704 
01705   *pbstr = NULL;
01706 
01707   if (!psa || psa->cbElements != 1 || psa->cDims != 1)
01708     return E_INVALIDARG;
01709 
01710   *pbstr = SysAllocStringByteLen(psa->pvData, psa->rgsabound[0].cElements);
01711   if (!*pbstr)
01712     return E_OUTOFMEMORY;
01713   return S_OK;
01714 }

Generated on Sat May 26 2012 04:24:16 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.