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); } } }