Array CrackSingleDimSafeArray(IntPtr psa)
        {
            uint cDims = OleAut32.SafeArrayGetDim(psa);

            if (cDims != 1)
            {
                throw new ArgumentException("Multi-dimensional SafeArrays not supported.");
            }

            int lBound = OleAut32.SafeArrayGetLBound(psa, 1U);
            int uBound = OleAut32.SafeArrayGetUBound(psa, 1U);

            int n = uBound - lBound + 1; // uBound is inclusive

            object[] array = new object[n];
            for (int i = lBound; i <= uBound; ++i)
            {
                array[i] = OleAut32.SafeArrayGetElement(psa, ref i);
            }

            return(array);
        }
        /// <summary>
        /// Set a safe array value
        /// </summary>
        /// <param name="array">The new value to set.</param>
        public void SetSafeArray(Array array)
        {
            const ushort vtUnknown = 13;
            IntPtr       psa       = OleAut32.SafeArrayCreateVector(vtUnknown, 0, (uint)array.Length);

            IntPtr pvData = OleAut32.SafeArrayAccessData(psa);

            try // to remember to release lock on data
            {
                for (int i = 0; i < array.Length; ++i)
                {
                    object obj  = array.GetValue(i);
                    IntPtr punk = (obj != null) ? Marshal.GetIUnknownForObject(obj) : IntPtr.Zero;
                    Marshal.WriteIntPtr(pvData, i * IntPtr.Size, punk);
                }
            }
            finally
            {
                OleAut32.SafeArrayUnaccessData(psa);
            }

            this.valueType = (ushort)VarEnum.VT_ARRAY | (ushort)VarEnum.VT_UNKNOWN;
            this.valueData = psa;
        }