Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
Variant.cs733 linesDownload Raw Back to InteropServices
1// Licensed to the .NET Foundation under one or more agreements.2// The .NET Foundation licenses this file to you under the MIT license.3 4#nullable enable5 6using System.Diagnostics;7using System.Runtime.InteropServices;8 9namespace System.Management.Automation.InteropServices10{11    /// <summary>12    /// Variant is the basic COM type for late-binding. It can contain any other COM data type.13    /// This type definition precisely matches the unmanaged data layout so that the struct can be passed14    /// to and from COM calls.15    /// </summary>16    [StructLayout(LayoutKind.Explicit)]17    internal partial struct Variant18    {19#if DEBUG20        static Variant()21        {22            // Variant size is the size of 4 pointers (16 bytes) on a 32-bit processor,23            // and 3 pointers (24 bytes) on a 64-bit processor.24            int variantSize = Marshal.SizeOf(typeof(Variant));25            if (IntPtr.Size == 4)26            {27                Debug.Assert(variantSize == (4 * IntPtr.Size));28            }29            else30            {31                Debug.Assert(IntPtr.Size == 8);32                Debug.Assert(variantSize == (3 * IntPtr.Size));33            }34        }35#endif36 37        // Most of the data types in the Variant are carried in _typeUnion38        [FieldOffset(0)] private TypeUnion _typeUnion;39 40        // Decimal is the largest data type and it needs to use the space that is normally unused in TypeUnion._wReserved1, etc.41        // Hence, it is declared to completely overlap with TypeUnion. A Decimal does not use the first two bytes, and so42        // TypeUnion._vt can still be used to encode the type.43        [FieldOffset(0)] private decimal _decimal;44 45        [StructLayout(LayoutKind.Sequential)]46        private struct TypeUnion47        {48            public ushort _vt;49            public ushort _wReserved1;50            public ushort _wReserved2;51            public ushort _wReserved3;52 53            public UnionTypes _unionTypes;54        }55 56        [StructLayout(LayoutKind.Sequential)]57        private struct Record58        {59            public IntPtr _record;60            public IntPtr _recordInfo;61        }62 63        [StructLayout(LayoutKind.Explicit)]64        private struct UnionTypes65        {66            [FieldOffset(0)] public sbyte _i1;67            [FieldOffset(0)] public short _i2;68            [FieldOffset(0)] public int _i4;69            [FieldOffset(0)] public long _i8;70            [FieldOffset(0)] public byte _ui1;71            [FieldOffset(0)] public ushort _ui2;72            [FieldOffset(0)] public uint _ui4;73            [FieldOffset(0)] public ulong _ui8;74            [FieldOffset(0)] public int _int;75            [FieldOffset(0)] public uint _uint;76            [FieldOffset(0)] public short _bool;77            [FieldOffset(0)] public int _error;78            [FieldOffset(0)] public float _r4;79            [FieldOffset(0)] public double _r8;80            [FieldOffset(0)] public long _cy;81            [FieldOffset(0)] public double _date;82            [FieldOffset(0)] public IntPtr _bstr;83            [FieldOffset(0)] public IntPtr _unknown;84            [FieldOffset(0)] public IntPtr _dispatch;85            [FieldOffset(0)] public IntPtr _pvarVal;86            [FieldOffset(0)] public IntPtr _byref;87            [FieldOffset(0)] public Record _record;88        }89 90        /// <summary>91        /// Primitive types are the basic COM types. It includes valuetypes like ints, but also reference types92        /// like BStrs. It does not include composite types like arrays and user-defined COM types (IUnknown/IDispatch).93        /// </summary>94        public static bool IsPrimitiveType(VarEnum varEnum)95        {96            switch (varEnum)97            {98                case VarEnum.VT_I1:99                case VarEnum.VT_I2:100                case VarEnum.VT_I4:101                case VarEnum.VT_I8:102                case VarEnum.VT_UI1:103                case VarEnum.VT_UI2:104                case VarEnum.VT_UI4:105                case VarEnum.VT_UI8:106                case VarEnum.VT_INT:107                case VarEnum.VT_UINT:108                case VarEnum.VT_BOOL:109                case VarEnum.VT_ERROR:110                case VarEnum.VT_R4:111                case VarEnum.VT_R8:112                case VarEnum.VT_DECIMAL:113                case VarEnum.VT_CY:114                case VarEnum.VT_DATE:115                case VarEnum.VT_BSTR:116                    return true;117            }118 119            return false;120        }121 122        public unsafe void CopyFromIndirect(object value)123        {124            VarEnum vt = (VarEnum)(((int)this.VariantType) & ~((int)VarEnum.VT_BYREF));125 126            if (value == null)127            {128                if (vt == VarEnum.VT_DISPATCH || vt == VarEnum.VT_UNKNOWN || vt == VarEnum.VT_BSTR)129                {130                    *(IntPtr*)this._typeUnion._unionTypes._byref = IntPtr.Zero;131                }132                return;133            }134 135            if ((vt & VarEnum.VT_ARRAY) != 0)136            {137                Variant vArray;138                Marshal.GetNativeVariantForObject(value, (IntPtr)(void*)&vArray);139                *(IntPtr*)this._typeUnion._unionTypes._byref = vArray._typeUnion._unionTypes._byref;140                return;141            }142 143            switch (vt)144            {145                case VarEnum.VT_I1:146                    *(sbyte*)this._typeUnion._unionTypes._byref = (sbyte)value;147                    break;148 149                case VarEnum.VT_UI1:150                    *(byte*)this._typeUnion._unionTypes._byref = (byte)value;151                    break;152 153                case VarEnum.VT_I2:154                    *(short*)this._typeUnion._unionTypes._byref = (short)value;155                    break;156 157                case VarEnum.VT_UI2:158                    *(ushort*)this._typeUnion._unionTypes._byref = (ushort)value;159                    break;160 161                case VarEnum.VT_BOOL:162                    // VARIANT_TRUE  = -1163                    // VARIANT_FALSE = 0164                    *(short*)this._typeUnion._unionTypes._byref = (bool)value ? (short)-1 : (short)0;165                    break;166 167                case VarEnum.VT_I4:168                case VarEnum.VT_INT:169                    *(int*)this._typeUnion._unionTypes._byref = (int)value;170                    break;171 172                case VarEnum.VT_UI4:173                case VarEnum.VT_UINT:174                    *(uint*)this._typeUnion._unionTypes._byref = (uint)value;175                    break;176 177                case VarEnum.VT_ERROR:178                    *(int*)this._typeUnion._unionTypes._byref = ((ErrorWrapper)value).ErrorCode;179                    break;180 181                case VarEnum.VT_I8:182                    *(long*)this._typeUnion._unionTypes._byref = (long)value;183                    break;184 185                case VarEnum.VT_UI8:186                    *(ulong*)this._typeUnion._unionTypes._byref = (ulong)value;187                    break;188 189                case VarEnum.VT_R4:190                    *(float*)this._typeUnion._unionTypes._byref = (float)value;191                    break;192 193                case VarEnum.VT_R8:194                    *(double*)this._typeUnion._unionTypes._byref = (double)value;195                    break;196 197                case VarEnum.VT_DATE:198                    *(double*)this._typeUnion._unionTypes._byref = ((DateTime)value).ToOADate();199                    break;200 201                case VarEnum.VT_UNKNOWN:202                    *(IntPtr*)this._typeUnion._unionTypes._byref = Marshal.GetIUnknownForObject(value);203                    break;204 205                case VarEnum.VT_DISPATCH:206                    *(IntPtr*)this._typeUnion._unionTypes._byref = Marshal.GetComInterfaceForObject<object, IDispatch>(value);207                    break;208 209                case VarEnum.VT_BSTR:210                    *(IntPtr*)this._typeUnion._unionTypes._byref = Marshal.StringToBSTR((string)value);211                    break;212 213                case VarEnum.VT_CY:214                    *(long*)this._typeUnion._unionTypes._byref = decimal.ToOACurrency((decimal)value);215                    break;216 217                case VarEnum.VT_DECIMAL:218                    *(decimal*)this._typeUnion._unionTypes._byref = (decimal)value;219                    break;220 221                case VarEnum.VT_VARIANT:222                    Marshal.GetNativeVariantForObject(value, this._typeUnion._unionTypes._byref);223                    break;224 225                default:226                    throw new ArgumentException();227            }228        }229 230        /// <summary>231        /// Get the managed object representing the Variant.232        /// </summary>233        /// <returns></returns>234        public object? ToObject()235        {236            // Check the simple case upfront237            if (IsEmpty)238            {239                return null;240            }241 242            switch (VariantType)243            {244                case VarEnum.VT_NULL:245                    return DBNull.Value;246 247                case VarEnum.VT_I1: return AsI1;248                case VarEnum.VT_I2: return AsI2;249                case VarEnum.VT_I4: return AsI4;250                case VarEnum.VT_I8: return AsI8;251                case VarEnum.VT_UI1: return AsUi1;252                case VarEnum.VT_UI2: return AsUi2;253                case VarEnum.VT_UI4: return AsUi4;254                case VarEnum.VT_UI8: return AsUi8;255                case VarEnum.VT_INT: return AsInt;256                case VarEnum.VT_UINT: return AsUint;257                case VarEnum.VT_BOOL: return AsBool;258                case VarEnum.VT_ERROR: return AsError;259                case VarEnum.VT_R4: return AsR4;260                case VarEnum.VT_R8: return AsR8;261                case VarEnum.VT_DECIMAL: return AsDecimal;262                case VarEnum.VT_CY: return AsCy;263                case VarEnum.VT_DATE: return AsDate;264                case VarEnum.VT_BSTR: return AsBstr;265                case VarEnum.VT_UNKNOWN: return AsUnknown;266                case VarEnum.VT_DISPATCH: return AsDispatch;267 268                default:269                    unsafe270                    {271                        fixed (void* pThis = &this)272                        {273                            return Marshal.GetObjectForNativeVariant((System.IntPtr)pThis);274                        }275                    }276            }277        }278 279        /// <summary>280        /// Release any unmanaged memory associated with the Variant281        /// </summary>282        public void Clear()283        {284            // We do not need to call OLE32's VariantClear for primitive types or ByRefs285            // to save ourselves the cost of interop transition.286            // ByRef indicates the memory is not owned by the VARIANT itself while287            // primitive types do not have any resources to free up.288            // Hence, only safearrays, BSTRs, interfaces and user types are289            // handled differently.290            VarEnum vt = VariantType;291            if ((vt & VarEnum.VT_BYREF) != 0)292            {293                VariantType = VarEnum.VT_EMPTY;294            }295            else if (((vt & VarEnum.VT_ARRAY) != 0)296                    || (vt == VarEnum.VT_BSTR)297                    || (vt == VarEnum.VT_UNKNOWN)298                    || (vt == VarEnum.VT_DISPATCH)299                    || (vt == VarEnum.VT_VARIANT)300                    || (vt == VarEnum.VT_RECORD))301            {302                unsafe303                {304                    fixed (void* pThis = &this)305                    {306                        Interop.Windows.VariantClear((nint)pThis);307                    }308                }309 310                Debug.Assert(IsEmpty);311            }312            else313            {314                VariantType = VarEnum.VT_EMPTY;315            }316        }317 318        public VarEnum VariantType319        {320            get => (VarEnum)_typeUnion._vt;321            set => _typeUnion._vt = (ushort)value;322        }323 324        public bool IsEmpty => _typeUnion._vt == ((ushort)VarEnum.VT_EMPTY);325 326        public bool IsByRef => (_typeUnion._vt & ((ushort)VarEnum.VT_BYREF)) != 0;327 328        public void SetAsNULL()329        {330            Debug.Assert(IsEmpty);331            VariantType = VarEnum.VT_NULL;332        }333 334        // VT_I1335 336        public sbyte AsI1337        {338            get339            {340                Debug.Assert(VariantType == VarEnum.VT_I1);341                return _typeUnion._unionTypes._i1;342            }343 344            set345            {346                Debug.Assert(IsEmpty);347                VariantType = VarEnum.VT_I1;348                _typeUnion._unionTypes._i1 = value;349            }350        }351 352        // VT_I2353 354        public short AsI2355        {356            get357            {358                Debug.Assert(VariantType == VarEnum.VT_I2);359                return _typeUnion._unionTypes._i2;360            }361 362            set363            {364                Debug.Assert(IsEmpty);365                VariantType = VarEnum.VT_I2;366                _typeUnion._unionTypes._i2 = value;367            }368        }369 370        // VT_I4371 372        public int AsI4373        {374            get375            {376                Debug.Assert(VariantType == VarEnum.VT_I4);377                return _typeUnion._unionTypes._i4;378            }379 380            set381            {382                Debug.Assert(IsEmpty);383                VariantType = VarEnum.VT_I4;384                _typeUnion._unionTypes._i4 = value;385            }386        }387 388        // VT_I8389 390        public long AsI8391        {392            get393            {394                Debug.Assert(VariantType == VarEnum.VT_I8);395                return _typeUnion._unionTypes._i8;396            }397 398            set399            {400                Debug.Assert(IsEmpty);401                VariantType = VarEnum.VT_I8;402                _typeUnion._unionTypes._i8 = value;403            }404        }405 406        // VT_UI1407 408        public byte AsUi1409        {410            get411            {412                Debug.Assert(VariantType == VarEnum.VT_UI1);413                return _typeUnion._unionTypes._ui1;414            }415 416            set417            {418                Debug.Assert(IsEmpty);419                VariantType = VarEnum.VT_UI1;420                _typeUnion._unionTypes._ui1 = value;421            }422        }423 424        // VT_UI2425 426        public ushort AsUi2427        {428            get429            {430                Debug.Assert(VariantType == VarEnum.VT_UI2);431                return _typeUnion._unionTypes._ui2;432            }433 434            set435            {436                Debug.Assert(IsEmpty);437                VariantType = VarEnum.VT_UI2;438                _typeUnion._unionTypes._ui2 = value;439            }440        }441 442        // VT_UI4443 444        public uint AsUi4445        {446            get447            {448                Debug.Assert(VariantType == VarEnum.VT_UI4);449                return _typeUnion._unionTypes._ui4;450            }451 452            set453            {454                Debug.Assert(IsEmpty);455                VariantType = VarEnum.VT_UI4;456                _typeUnion._unionTypes._ui4 = value;457            }458        }459 460        // VT_UI8461 462        public ulong AsUi8463        {464            get465            {466                Debug.Assert(VariantType == VarEnum.VT_UI8);467                return _typeUnion._unionTypes._ui8;468            }469 470            set471            {472                Debug.Assert(IsEmpty);473                VariantType = VarEnum.VT_UI8;474                _typeUnion._unionTypes._ui8 = value;475            }476        }477 478        // VT_INT479 480        public int AsInt481        {482            get483            {484                Debug.Assert(VariantType == VarEnum.VT_INT);485                return _typeUnion._unionTypes._int;486            }487 488            set489            {490                Debug.Assert(IsEmpty);491                VariantType = VarEnum.VT_INT;492                _typeUnion._unionTypes._int = value;493            }494        }495 496        // VT_UINT497 498        public uint AsUint499        {500            get501            {502                Debug.Assert(VariantType == VarEnum.VT_UINT);503                return _typeUnion._unionTypes._uint;504            }505 506            set507            {508                Debug.Assert(IsEmpty);509                VariantType = VarEnum.VT_UINT;510                _typeUnion._unionTypes._uint = value;511            }512        }513 514        // VT_BOOL515 516        public bool AsBool517        {518            get519            {520                Debug.Assert(VariantType == VarEnum.VT_BOOL);521                return _typeUnion._unionTypes._bool != 0;522            }523 524            set525            {526                Debug.Assert(IsEmpty);527                // VARIANT_TRUE  = -1528                // VARIANT_FALSE = 0529                VariantType = VarEnum.VT_BOOL;530                _typeUnion._unionTypes._bool = value ? (short)-1 : (short)0;531            }532        }533 534        // VT_ERROR535 536        public int AsError537        {538            get539            {540                Debug.Assert(VariantType == VarEnum.VT_ERROR);541                return _typeUnion._unionTypes._error;542            }543 544            set545            {546                Debug.Assert(IsEmpty);547                VariantType = VarEnum.VT_ERROR;548                _typeUnion._unionTypes._error = value;549            }550        }551 552        // VT_R4553 554        public float AsR4555        {556            get557            {558                Debug.Assert(VariantType == VarEnum.VT_R4);559                return _typeUnion._unionTypes._r4;560            }561 562            set563            {564                Debug.Assert(IsEmpty);565                VariantType = VarEnum.VT_R4;566                _typeUnion._unionTypes._r4 = value;567            }568        }569 570        // VT_R8571 572        public double AsR8573        {574            get575            {576                Debug.Assert(VariantType == VarEnum.VT_R8);577                return _typeUnion._unionTypes._r8;578            }579 580            set581            {582                Debug.Assert(IsEmpty);583                VariantType = VarEnum.VT_R8;584                _typeUnion._unionTypes._r8 = value;585            }586        }587 588        // VT_DECIMAL589 590        public decimal AsDecimal591        {592            get593            {594                Debug.Assert(VariantType == VarEnum.VT_DECIMAL);595                // The first byte of Decimal is unused, but usually set to 0596                Variant v = this;597                v._typeUnion._vt = 0;598                return v._decimal;599            }600 601            set602            {603                Debug.Assert(IsEmpty);604                VariantType = VarEnum.VT_DECIMAL;605                _decimal = value;606                // _vt overlaps with _decimal, and should be set after setting _decimal607                _typeUnion._vt = (ushort)VarEnum.VT_DECIMAL;608            }609        }610 611        // VT_CY612 613        public decimal AsCy614        {615            get616            {617                Debug.Assert(VariantType == VarEnum.VT_CY);618                return decimal.FromOACurrency(_typeUnion._unionTypes._cy);619            }620 621            set622            {623                Debug.Assert(IsEmpty);624                VariantType = VarEnum.VT_CY;625                _typeUnion._unionTypes._cy = decimal.ToOACurrency(value);626            }627        }628 629        // VT_DATE630 631        public DateTime AsDate632        {633            get634            {635                Debug.Assert(VariantType == VarEnum.VT_DATE);636                return DateTime.FromOADate(_typeUnion._unionTypes._date);637            }638 639            set640            {641                Debug.Assert(IsEmpty);642                VariantType = VarEnum.VT_DATE;643                _typeUnion._unionTypes._date = value.ToOADate();644            }645        }646 647        // VT_BSTR648 649        public string AsBstr650        {651            get652            {653                Debug.Assert(VariantType == VarEnum.VT_BSTR);654                return (string)Marshal.PtrToStringBSTR(this._typeUnion._unionTypes._bstr);655            }656 657            set658            {659                Debug.Assert(IsEmpty);660                VariantType = VarEnum.VT_BSTR;661                this._typeUnion._unionTypes._bstr = Marshal.StringToBSTR(value);662            }663        }664 665        // VT_UNKNOWN666 667        public object? AsUnknown668        {669            get670            {671                Debug.Assert(VariantType == VarEnum.VT_UNKNOWN);672                if (_typeUnion._unionTypes._unknown == IntPtr.Zero)673                {674                    return null;675                }676                return Marshal.GetObjectForIUnknown(_typeUnion._unionTypes._unknown);677            }678 679            set680            {681                Debug.Assert(IsEmpty);682                VariantType = VarEnum.VT_UNKNOWN;683                if (value == null)684                {685                    _typeUnion._unionTypes._unknown = IntPtr.Zero;686                }687                else688                {689                    _typeUnion._unionTypes._unknown = Marshal.GetIUnknownForObject(value);690                }691            }692        }693 694        // VT_DISPATCH695 696        public object? AsDispatch697        {698            get699            {700                Debug.Assert(VariantType == VarEnum.VT_DISPATCH);701                if (_typeUnion._unionTypes._dispatch == IntPtr.Zero)702                {703                    return null;704                }705                return Marshal.GetObjectForIUnknown(_typeUnion._unionTypes._dispatch);706            }707 708            set709            {710                Debug.Assert(IsEmpty);711                VariantType = VarEnum.VT_DISPATCH;712                if (value == null)713                {714                    _typeUnion._unionTypes._dispatch = IntPtr.Zero;715                }716                else717                {718                    _typeUnion._unionTypes._dispatch = Marshal.GetComInterfaceForObject<object, IDispatch>(value);719                }720            }721        }722 723        public IntPtr AsByRefVariant724        {725            get726            {727                Debug.Assert(VariantType == (VarEnum.VT_BYREF | VarEnum.VT_VARIANT));728                return _typeUnion._unionTypes._pvarVal;729            }730        }731    }732}733