/// <summary>
        /// Gets a list of column names or column-definition-strings for the
        /// associated view.
        /// </summary>
        /// <param name="view">the view to that defines the columns</param>
        /// <param name="types">true to return types (column definition strings),
        /// false to return names</param>
        /// <returns>list of column names or types</returns>
        private static IList <string> GetViewColumns(View view, bool types)
        {
            int  recordHandle;
            int  typesFlag = types ? 1 : 0;
            uint ret       = RemotableNativeMethods.MsiViewGetColumnInfo(
                (int)view.Handle, (uint)typesFlag, out recordHandle);

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }

            using (Record rec = new Record((IntPtr)recordHandle, true, null))
            {
                int            count       = rec.FieldCount;
                IList <string> columnsList = new List <string>(count);

                // Since we must be getting all strings of limited length,
                // this code is faster than calling rec.GetString(field).
                for (int field = 1; field <= count; field++)
                {
                    uint          bufSize = 256;
                    StringBuilder buf     = new StringBuilder((int)bufSize);
                    ret = RemotableNativeMethods.MsiRecordGetString((int)rec.Handle, (uint)field, buf, ref bufSize);
                    if (ret != 0)
                    {
                        throw InstallerException.ExceptionFromReturnCode(ret);
                    }
                    columnsList.Add(buf.ToString());
                }
                return(columnsList);
            }
        }