private static NativeMethods.MsiOpenDbPersistenceMode getMsiOpenDbPersistenceMode(string mspFilePath)
        {
            Debug.Assert(!string.IsNullOrWhiteSpace(mspFilePath));

            // Open root storage.
            VsInterop.IStorage rootStorage = null;
            uint hr = NativeMethods.StgOpenStorage(mspFilePath, null, NativeMethods.STGM.STGM_READ | NativeMethods.STGM.STGM_SHARE_EXCLUSIVE, null, 0, out rootStorage);

            if (HResultHelper.IsFailed(hr) || rootStorage == null)
            {
                throw new Win32Exception((int)hr, string.Format(@"Failed: StgOpenStorage(): Failed to open root storage ""{0}""", mspFilePath));
            }

            try
            {
                // Decide to persistance mode.
                NativeMethods.MsiOpenDbPersistenceMode persistenceMode = NativeMethods.MsiOpenDbPersistenceMode.MSIDBOPEN_READONLY;
                if (isPatch(rootStorage))
                {
                    persistenceMode = NativeMethods.MsiOpenDbPersistenceMode.MSIDBOPEN_READONLY | NativeMethods.MsiOpenDbPersistenceMode.MSIDBOPEN_PATCHFILE;
                }
                return(persistenceMode);
            }
            finally
            {
                // Release COM object of root storage.
                Marshal.ReleaseComObject(rootStorage);
            }
        }
        private void extractCabFiles()
        {
            // Open the MSI database.
            NativeMethods.MsiOpenDbPersistenceMode persistenceMode = getMsiOpenDbPersistenceMode(SourcePackagePath);
            IntPtr msiDatabaseHandle = IntPtr.Zero;
            uint   err = NativeMethods.MsiOpenDatabase(SourcePackagePath, new IntPtr((uint)persistenceMode), out msiDatabaseHandle);

            if (err != WinError.ERROR_SUCCESS)
            {
                throw new Win32Exception((int)err, string.Format(@"Failed: MsiOpenDatabase(): Failed to open MSI database ""{0}""", SourcePackagePath));
            }

            try
            {
                // Create the view from query.
                IntPtr msiViewHandle = IntPtr.Zero;
                err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Streams", out msiViewHandle);
                if (err != WinError.ERROR_SUCCESS)
                {
                    throw new Win32Exception((int)err, string.Format(@"Failed: MsiDatabaseOpenView(): Failed to open view ""{0}""", SourcePackagePath));
                }

                try
                {
                    // Execute the view query for fetching streams.
                    err = NativeMethods.MsiViewExecute(msiViewHandle, IntPtr.Zero);
                    if (err != WinError.ERROR_SUCCESS)
                    {
                        throw new Win32Exception((int)err, string.Format(@"Failed: MsiViewExecute(): ""{0}""", SourcePackagePath));
                    }

                    while (true)
                    {
                        // Fetch the stream from view.
                        IntPtr msiRecordHandle = IntPtr.Zero;
                        err = NativeMethods.MsiViewFetch(msiViewHandle, out msiRecordHandle);
                        if (err != WinError.ERROR_SUCCESS)
                        {
                            break;
                        }

                        try
                        {
                            // Save stream to file.
                            saveStream(msiRecordHandle, DestinationDirectoryPath, true);
                        }
                        finally
                        {
                            // Close MSI record handle.
                            NativeMethods.MsiCloseHandle(msiRecordHandle);
                        }
                    }
                }
                finally
                {
                    // Close MSI view handle.
                    if (msiViewHandle != IntPtr.Zero)
                    {
                        NativeMethods.MsiCloseHandle(msiViewHandle);
                    }
                }
            }
            finally
            {
                // Close MSI database handle.
                if (msiDatabaseHandle != IntPtr.Zero)
                {
                    NativeMethods.MsiCloseHandle(msiDatabaseHandle);
                }
            }
        }