Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
CabinetNativeApi.cs684 linesDownload Raw Back to help
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.IO;5using System.Runtime.InteropServices;6 7using Microsoft.Win32.SafeHandles;8 9namespace System.Management.Automation.Internal10{11    internal class CabinetExtractor : ICabinetExtractor12    {13        /// <summary>14        /// GC handle which prevents garbage collector from collecting this delegate.15        /// </summary>16        private CabinetNativeApi.FdiAllocDelegate _allocDelegate;17        private GCHandle _fdiAllocHandle;18        private CabinetNativeApi.FdiFreeDelegate _freeDelegate;19        private GCHandle _fdiFreeHandle;20        private CabinetNativeApi.FdiOpenDelegate _openDelegate;21        private GCHandle _fdiOpenHandle;22        private CabinetNativeApi.FdiReadDelegate _readDelegate;23        private GCHandle _fdiReadHandle;24        private CabinetNativeApi.FdiWriteDelegate _writeDelegate;25        private GCHandle _fdiWriteHandle;26        private CabinetNativeApi.FdiCloseDelegate _closeDelegate;27        private GCHandle _fdiCloseHandle;28        private CabinetNativeApi.FdiSeekDelegate _seekDelegate;29        private GCHandle _fdiSeekHandle;30        private CabinetNativeApi.FdiNotifyDelegate _notifyDelegate;31        private GCHandle _fdiNotifyHandle;32 33        internal CabinetNativeApi.FdiContextHandle fdiContext; // HFDI34 35        internal CabinetExtractor()36        {37            CabinetNativeApi.FdiERF err = new CabinetNativeApi.FdiERF();38 39            populateDelegates();40 41            // marshal the delegate to a unmanaged function pointer so that AppDomain reference is stored correctly.42            fdiContext = CabinetNativeApi.FDICreate(43                Marshal.GetFunctionPointerForDelegate(_allocDelegate),44                Marshal.GetFunctionPointerForDelegate(_freeDelegate),45                Marshal.GetFunctionPointerForDelegate(_openDelegate),46                Marshal.GetFunctionPointerForDelegate(_readDelegate),47                Marshal.GetFunctionPointerForDelegate(_writeDelegate),48                Marshal.GetFunctionPointerForDelegate(_closeDelegate),49                Marshal.GetFunctionPointerForDelegate(_seekDelegate),50                CabinetNativeApi.FdiCreateCpuType.Cpu80386,51                err);52        }53 54        #region IDisposable Methods55 56        /// <summary>57        /// Flag: Has Dispose already been called?58        /// </summary>59        private bool _disposed = false;60 61        /// <summary>62        /// Protected implementation of Dispose pattern.63        /// </summary>64        /// <param name="disposing"></param>65        protected override void Dispose(bool disposing)66        {67            if (_disposed)68            {69                return;70            }71 72            // Free managed objects within 'if (disposing)' if needed73            fdiContext?.Dispose();74            // Free unmanaged objects here75            this.CleanUpDelegates();76 77            _disposed = true;78 79            // Call base class implementation in case it has resources to release80            base.Dispose(disposing);81        }82 83        /// <summary>84        /// Finalizes an instance of the <see cref="CabinetExtractor"/> class.85        /// </summary>86        ~CabinetExtractor()87        {88            Dispose(false);89        }90 91        #endregion92 93        internal override bool Extract(string cabinetName, string srcPath, string destPath)94        {95            IntPtr nativeDestPath = Marshal.StringToHGlobalAnsi(destPath);96 97            bool result = CabinetNativeApi.FDICopy(98                fdiContext,99                cabinetName,100                srcPath,101                0,                    // Not used102                Marshal.GetFunctionPointerForDelegate(_notifyDelegate),103                IntPtr.Zero,104                nativeDestPath);105 106            Marshal.FreeHGlobal(nativeDestPath);107 108            return result;109        }110 111        /// <summary>112        /// Creates delegates for the FDI* operation functions.113        /// </summary>114        private void populateDelegates()115        {116            // if a delegate is re-located by a garbage collection, it will not affect117            // the underlaying managed callback, so Alloc is used to add a reference118            // to the delegate, allowing relocation of the delegate, but preventing119            // disposal. Using GCHandle without pinning reduces fragmentation potential120            // of the managed heap.121            _allocDelegate = new CabinetNativeApi.FdiAllocDelegate(CabinetNativeApi.FdiAlloc);122            _fdiAllocHandle = GCHandle.Alloc(_allocDelegate);123 124            _freeDelegate = new CabinetNativeApi.FdiFreeDelegate(CabinetNativeApi.FdiFree);125            _fdiFreeHandle = GCHandle.Alloc(_freeDelegate);126 127            _openDelegate = new CabinetNativeApi.FdiOpenDelegate(CabinetNativeApi.FdiOpen);128            _fdiOpenHandle = GCHandle.Alloc(_openDelegate);129 130            _readDelegate = new CabinetNativeApi.FdiReadDelegate(CabinetNativeApi.FdiRead);131            _fdiReadHandle = GCHandle.Alloc(_readDelegate);132 133            _writeDelegate = new CabinetNativeApi.FdiWriteDelegate(CabinetNativeApi.FdiWrite);134            _fdiWriteHandle = GCHandle.Alloc(_writeDelegate);135 136            _closeDelegate = new CabinetNativeApi.FdiCloseDelegate(CabinetNativeApi.FdiClose);137            _fdiCloseHandle = GCHandle.Alloc(_closeDelegate);138 139            _seekDelegate = new CabinetNativeApi.FdiSeekDelegate(CabinetNativeApi.FdiSeek);140            _fdiSeekHandle = GCHandle.Alloc(_seekDelegate);141 142            _notifyDelegate = new CabinetNativeApi.FdiNotifyDelegate(CabinetNativeApi.FdiNotify);143            _fdiNotifyHandle = GCHandle.Alloc(_notifyDelegate);144        }145 146        /// <summary>147        /// Frees all the delegate handles.148        /// </summary>149        private void CleanUpDelegates()150        {151            // Free GCHandles so that the memory they point to may be unpinned (garbage collected)152            if (_fdiAllocHandle.IsAllocated)153            {154                _fdiAllocHandle.Free();155                _fdiFreeHandle.Free();156                _fdiOpenHandle.Free();157                _fdiReadHandle.Free();158                _fdiWriteHandle.Free();159                _fdiCloseHandle.Free();160                _fdiSeekHandle.Free();161                _fdiNotifyHandle.Free();162            }163        }164    }165 166    // CabinetExtractor loader implementation167    internal class CabinetExtractorLoader : ICabinetExtractorLoader168    {169        private static CabinetExtractor s_extractorInstance;170        private static CabinetExtractorLoader s_instance;171        private static double s_created = 0;172 173        internal static CabinetExtractorLoader GetInstance()174        {175            if (System.Threading.Interlocked.CompareExchange(ref s_created, 1, 0) == 0)176            {177                s_instance = new CabinetExtractorLoader();178                s_extractorInstance = new CabinetExtractor();179            }180 181            return s_instance;182        }183 184        internal override ICabinetExtractor GetCabinetExtractor()185        {186            return s_extractorInstance;187        }188    }189 190    internal static class CabinetNativeApi191    {192        #region Delegates and function definitions193 194        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]195        internal delegate IntPtr FdiAllocDelegate(int size);196 197        internal static IntPtr FdiAlloc(int size)198        {199            try200            {201                return Marshal.AllocHGlobal(size);202            }203            catch (OutOfMemoryException)204            {205                return IntPtr.Zero;206            }207        }208 209        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]210        internal delegate void FdiFreeDelegate(IntPtr memblock);211 212        internal static void FdiFree(IntPtr memblock)213        {214            Marshal.FreeHGlobal(memblock);215        }216 217        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]218        internal delegate IntPtr FdiOpenDelegate(219            [MarshalAs(UnmanagedType.LPStr)] string filename,220            int oflag,221            int pmode);222 223        internal static IntPtr FdiOpen(string filename, int oflag, int pmode)224        {225            FileMode mode = CabinetNativeApi.ConvertOpflagToFileMode(oflag);226 227            FileAccess access = CabinetNativeApi.ConvertPermissionModeToFileAccess(pmode);228            FileShare share = CabinetNativeApi.ConvertPermissionModeToFileShare(pmode);229 230            // This method is used for opening the cab file as well as saving the extracted files.231            // When we are opening the cab file we only need read permissions.232            // We force read permissions so that non-elevated users can extract cab files.233            if (mode == FileMode.Open || mode == FileMode.OpenOrCreate)234            {235                access = FileAccess.Read;236                share = FileShare.Read;237            }238 239            try240            {241                FileStream stream = new FileStream(filename, mode, access, share);242 243                if (stream == null)244                {245                    return new IntPtr(-1);246                }247 248                return GCHandle.ToIntPtr(GCHandle.Alloc(stream));249            }250            catch (IOException)251            {252                return new IntPtr(-1);253            }254        }255 256        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]257        internal delegate int FdiReadDelegate(258            IntPtr fp,259            [In, Out]260            [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2, ArraySubType = UnmanagedType.U1)]261            byte[] buffer,262            int count);263 264        internal static int FdiRead(IntPtr fp, byte[] buffer, int count)265        {266            GCHandle handle = GCHandle.FromIntPtr(fp);267            FileStream stream = (FileStream)handle.Target;268 269            int numCharactersRead = 0;270            try271            {272                numCharactersRead = stream.Read(buffer, 0, count);273            }274            catch (ArgumentNullException) { numCharactersRead = -1; }275            catch (ArgumentOutOfRangeException) { numCharactersRead = -1; }276            catch (NotSupportedException) { numCharactersRead = -1; }277            catch (IOException) { numCharactersRead = -1; }278            catch (ArgumentException) { numCharactersRead = -1; }279            catch (ObjectDisposedException) { numCharactersRead = -1; }280 281            return numCharactersRead;282        }283 284        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]285        internal delegate int FdiWriteDelegate(286            IntPtr fp,287            [In]288            [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2, ArraySubType = UnmanagedType.U1)]289            byte[] buffer,290            int count);291 292        internal static int FdiWrite(IntPtr fp, byte[] buffer, int count)293        {294            GCHandle handle = GCHandle.FromIntPtr(fp);295            FileStream stream = (FileStream)handle.Target;296 297            int numCharactersWritten = 0;298            try299            {300                stream.Write(buffer, 0, count);301                numCharactersWritten = count; // Write doesn't return the number of bytes written. Per MSDN, if it succeeds, it will have written count bytes.302            }303            catch (ArgumentNullException) { numCharactersWritten = -1; }304            catch (ArgumentOutOfRangeException) { numCharactersWritten = -1; }305            catch (NotSupportedException) { numCharactersWritten = -1; }306            catch (IOException) { numCharactersWritten = -1; }307            catch (ArgumentException) { numCharactersWritten = -1; }308            catch (ObjectDisposedException) { numCharactersWritten = -1; }309 310            return numCharactersWritten;311        }312 313        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]314        internal delegate int FdiCloseDelegate(IntPtr fp);315 316        internal static int FdiClose(IntPtr fp)317        {318            GCHandle handle = GCHandle.FromIntPtr(fp);319            FileStream stream = (FileStream)handle.Target;320 321            if (stream == null)322            {323                return -1;324            }325            else326            {327                stream.Dispose();328                return 0;329            }330        }331 332        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]333        internal delegate int FdiSeekDelegate(IntPtr fp, int offset, int origin);334 335        internal static int FdiSeek(IntPtr fp, int offset, int origin)336        {337            GCHandle handle = GCHandle.FromIntPtr(fp);338            FileStream stream = (FileStream)handle.Target;339 340            SeekOrigin seekOrigin = CabinetNativeApi.ConvertOriginToSeekOrigin(origin);341            long status = 0;342            try343            {344                status = stream.Seek(offset, seekOrigin);345            }346            catch (NotSupportedException) { status = -1; }347            catch (IOException) { status = -1; }348            catch (ArgumentException) { status = -1; }349            catch (ObjectDisposedException) { status = -1; }350 351            return (int)status;352        }353 354        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]355        internal delegate IntPtr FdiNotifyDelegate(FdiNotificationType fdint, FdiNotification fdin);356 357        // Handles FDI notification358        internal static IntPtr FdiNotify(FdiNotificationType fdint, FdiNotification fdin)359        {360            switch (fdint)361            {362                case FdiNotificationType.FdintCOPY_FILE:363                    {364                        // TODO: Should I catch exceptions for the new functions?365 366                        // Copy target directory367                        string destPath = Marshal.PtrToStringAnsi(fdin.pv);368 369                        // Split the path to a filename and path370                        string fileName = Path.GetFileName(fdin.psz1);371                        string remainingPsz1Path = Path.GetDirectoryName(fdin.psz1);372                        destPath = Path.Combine(destPath, remainingPsz1Path);373 374                        Directory.CreateDirectory(destPath); // Creates all intermediate directories if necessary.375 376                        // Create the file377                        string absoluteFilePath = Path.Combine(destPath, fileName);378                        return CabinetNativeApi.FdiOpen(absoluteFilePath, (int)OpFlags.Create, (int)(PermissionMode.Read | PermissionMode.Write)); // TODO: OK to ignore _O_SEQUENTIAL, WrOnly, and _O_BINARY?379                    }380                case FdiNotificationType.FdintCLOSE_FILE_INFO:381                    {382                        // Close the file383                        CabinetNativeApi.FdiClose(fdin.hf);384 385                        // Set the file attributes386                        string destPath = Marshal.PtrToStringAnsi(fdin.pv);387                        string absoluteFilePath = Path.Combine(destPath, fdin.psz1);388 389                        IntPtr hFile = PlatformInvokes.CreateFile(390                            absoluteFilePath,391                            PlatformInvokes.FileDesiredAccess.GenericRead | PlatformInvokes.FileDesiredAccess.GenericWrite,392                            PlatformInvokes.FileShareMode.Read,393                            IntPtr.Zero,394                            PlatformInvokes.FileCreationDisposition.OpenExisting,395                            PlatformInvokes.FileAttributes.Normal,396                            IntPtr.Zero);397 398                        if (hFile != IntPtr.Zero)399                        {400                            PlatformInvokes.FILETIME ftFile = new PlatformInvokes.FILETIME();401                            if (PlatformInvokes.DosDateTimeToFileTime(fdin.date, fdin.time, ftFile))402                            {403                                PlatformInvokes.FILETIME ftLocal = new PlatformInvokes.FILETIME();404                                if (PlatformInvokes.LocalFileTimeToFileTime(ftFile, ftLocal))405                                {406                                    PlatformInvokes.SetFileTime(hFile, ftLocal, null, ftLocal);407                                }408                            }409 410                            PlatformInvokes.CloseHandle(hFile);411                        }412 413                        PlatformInvokes.SetFileAttributesW(414                            absoluteFilePath,415                            (PlatformInvokes.FileAttributes)fdin.attribs & (PlatformInvokes.FileAttributes.ReadOnly | PlatformInvokes.FileAttributes.Hidden | PlatformInvokes.FileAttributes.System | PlatformInvokes.FileAttributes.Archive));416 417                        // Call notification function418                        return new IntPtr(1);419                    }420            }421 422            return new IntPtr(0);423        }424 425        #endregion426 427        #region Helper methods for non-trivial conversions428 429        /// <summary>430        /// Converts an unmanaged define into a known managed value.431        /// </summary>432        /// <param name="origin">Defined in stdio.h.</param>433        /// <returns>The appropriate System.IO.SeekOrigin value.</returns>434        internal static SeekOrigin ConvertOriginToSeekOrigin(int origin)435        {436            switch (origin)437            {438                case 0x0: // SEEK_SET439                    return SeekOrigin.Begin;440                case 0x1: // SEEK_CUR441                    return SeekOrigin.Current;442                case 0x2: // SEEK_END443                    return SeekOrigin.End;444                default:445                    return SeekOrigin.Current;446            }447        }448 449        /// <summary>450        /// Converts an unmanaged define into a known managed type.451        /// </summary>452        /// <param name="oflag">Operation mode defined in fcntl.h.</param>453        /// <returns>The appropriate System.IO.FileMode type.</returns>454        internal static FileMode ConvertOpflagToFileMode(int oflag)455        {456            // Note: This is not done in a switch because the order of tests matters.457 458            if ((oflag & (int)(OpFlags.Create | OpFlags.Excl)) == (int)(OpFlags.Create | OpFlags.Excl))459            {460                return FileMode.CreateNew;461            }462            else if ((oflag & (int)(OpFlags.Create | OpFlags.Truncate)) == (int)(OpFlags.Create | OpFlags.Truncate))463            {464                return FileMode.OpenOrCreate;465            }466            else if ((oflag & (int)OpFlags.Append) != 0)467            {468                return FileMode.Append;469            }470            else if ((oflag & (int)OpFlags.Create) != 0)471            {472                return FileMode.Create;473            }474            else if ((oflag & (int)OpFlags.RdWr) != 0)475            {476                return FileMode.Open;477            }478            else if ((oflag & (int)OpFlags.Truncate) != 0)479            {480                return FileMode.Truncate;481            }482            else483            {484                return FileMode.OpenOrCreate; // This seemed the safest way to handled unrecognized types485            }486        }487 488        /// <summary>489        /// Converts an unmanaged define into a known managed type.490        /// </summary>491        /// <param name="pmode">Permission mode defined in stat.h.</param>492        /// <returns>The appropriate System.IO.FileAccess type.</returns>493        internal static FileAccess ConvertPermissionModeToFileAccess(int pmode)494        {495            // Note: This is not done in a switch because the order of tests matters.496 497            if ((pmode & (int)(PermissionMode.Read | PermissionMode.Write)) == (int)(PermissionMode.Read | PermissionMode.Write))498            {499                return FileAccess.ReadWrite;500            }501            else if ((pmode & (int)PermissionMode.Read) != 0)502            {503                return FileAccess.Read;504            }505            else if ((pmode & (int)PermissionMode.Write) != 0)506            {507                return FileAccess.Write;508            }509            else510            {511                return FileAccess.Read;512            }513        }514 515        /// <summary>516        /// Converts an unmanaged define into a known managed type.517        /// </summary>518        /// <param name="pmode">Permission mode defined in stat.h.</param>519        /// <returns>The appropriate System.IO.FileShare type.</returns>520        internal static FileShare ConvertPermissionModeToFileShare(int pmode)521        {522            // Note: This is not done in a switch because the order of tests matters.523 524            if ((pmode & (int)(PermissionMode.Read | PermissionMode.Write)) == (int)(PermissionMode.Read | PermissionMode.Write))525            {526                return FileShare.ReadWrite;527            }528            else if ((pmode & (int)PermissionMode.Read) != 0)529            {530                return FileShare.Read;531            }532            else if ((pmode & (int)PermissionMode.Write) != 0)533            {534                return FileShare.Write;535            }536            else537            {538                return FileShare.Read;539            }540        }541 542        #endregion543 544        #region IO classes, structures, and enums545 546        [Flags]547        internal enum PermissionMode : int548        {549            None = 0x0000,550            Write = 0x0080,551            Read = 0x0100552        }553 554        [Flags]555        internal enum OpFlags : int556        {557            RdOnly = 0x0000,558            WrOnly = 0x0001,559            RdWr = 0x0002,560            Append = 0x0008,561            Create = 0x0100,562            Truncate = 0x0200,563            Excl = 0x0400564        }565 566        internal enum FdiCreateCpuType : int567        {568            CpuUnknown = -1,569            Cpu80286 = 0,570            Cpu80386 = 1571        }572 573        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]574        internal class FdiNotification575        {576            internal int cb; // LONG577            internal string psz1; // char FAR *578            internal string psz2; // char FAR *579            internal string psz3; // char FAR *580            internal IntPtr pv; // void FAR * // In this case, it is the destination path581            internal IntPtr hf; // INT_PTR582            internal short date; // USHORT583            internal short time; // USHORT584            internal short attribs; // USHORT585            internal short setID; // USHORT586            internal short iCabinet; // USHORT587            internal short iFolder; // USHORT588            internal int fdie; // FDIERROR589        }590 591        internal enum FdiNotificationType : int592        {593            FdintCABINET_INFO = 0x0,594            FdintPARTIAL_FILE = 0x1,595            FdintCOPY_FILE = 0x2,596            FdintCLOSE_FILE_INFO = 0x3,597            FdintNEXT_CABINET = 0x4,598            FdintENUMERATE = 0x5599        }600 601        [StructLayout(LayoutKind.Sequential)]602        internal class FdiERF603        {604            internal int erfOper;605            internal int erfType;606            internal bool fError;607        }608 609        internal sealed class FdiContextHandle : SafeHandleZeroOrMinusOneIsInvalid610        {611            private FdiContextHandle()612                : base(true)613            {614            }615 616            protected override bool ReleaseHandle()617            {618                return CabinetNativeApi.FDIDestroy(this.handle);619            }620        }621 622        #endregion623 624        #region PInvoke Definitions625 626        /// <summary>627        /// Creates an FDI context.628        /// </summary>629        /// <param name="pfnalloc">_In_ PFNALLOC - Memory allocation delegate.</param>630        /// <param name="pfnfree">_In_ PFNFREE - Memory free delegate.</param>631        /// <param name="pfnopen">_In_ PFNOPEN - File open delegate.</param>632        /// <param name="pfnread">_In_ PFNREAD - File read delegate.</param>633        /// <param name="pfnwrite">_In_ PFNWRITE - File write delegate.</param>634        /// <param name="pfnclose">_In_ PFNCLOSE - File close delegate.</param>635        /// <param name="pfnseek">_In_ PFNSEEK - File seek delegate.</param>636        /// <param name="cpuType">_In_ int - CPU type.</param>637        /// <param name="erf">_Inout_ PERF - Error structure containing error information.</param>638        /// <returns></returns>639        [DllImport("cabinet.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]640        internal static extern FdiContextHandle FDICreate(641            IntPtr pfnalloc,642            IntPtr pfnfree,643            IntPtr pfnopen,644            IntPtr pfnread,645            IntPtr pfnwrite,646            IntPtr pfnclose,647            IntPtr pfnseek,648            CabinetNativeApi.FdiCreateCpuType cpuType,649            FdiERF erf);650 651        /// <summary>652        /// Extracts files from cabinets.653        /// </summary>654        /// <param name="hfdi">_In_ HFDI - A valid FDI context handle returned by FDICreate.</param>655        /// <param name="pszCabinet">_In_ LPSTR - The name of the cabinet file.</param>656        /// <param name="pszCabPath">_In_ LPSTR - The path to the cabinet file excluding the file name.</param>657        /// <param name="flags">_In_ int - Not defined.</param>658        /// <param name="pfnfdin">_In_ PFNFDINOTIFY - Pointer to the notification callback delegate.</param>659        /// <param name="pfnfdid">_In_ PFNFDIDECRYPT - Not used.</param>660        /// <param name="pvUser">_In_opt_ void FAR * - Path string passed to the notification function.</param>661        /// <returns></returns>662        [DllImport("cabinet.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, SetLastError = true, BestFitMapping = false)]663        internal static extern bool FDICopy(664            FdiContextHandle hfdi,665            [MarshalAs(UnmanagedType.LPStr)] string pszCabinet,666            [MarshalAs(UnmanagedType.LPStr)] string pszCabPath,667            int flags,668            IntPtr pfnfdin,669            IntPtr pfnfdid,670            IntPtr pvUser);671 672        /// <summary>673        /// Deletes an open FDI context.674        /// </summary>675        /// <param name="hfdi">_In_ HFDI - The FDI context handle to destroy.</param>676        /// <returns></returns>677        [DllImport("cabinet.dll", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]678        internal static extern bool FDIDestroy(679            IntPtr hfdi);680 681        #endregion682    }683}684