コード例 #1
0
        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);
            }
        }
コード例 #2
0
        private static void saveStorage(VsInterop.IStorage storage, string saveDirectory, string storageName, string storageExtension)
        {
            Trace.Assert(storage != null);
            Trace.Assert(!string.IsNullOrWhiteSpace(saveDirectory));

            VsInterop.IStorage sourceStorage = null;
            storage.OpenStorage(storageName, null, (uint)(STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE), IntPtr.Zero, 0, out sourceStorage);

            if (sourceStorage != null)
            {
                string savePath = saveDirectory + Path.DirectorySeparatorChar + storageName + (storageExtension == null ? string.Empty : storageExtension);
                Console.WriteLine(@"Extracting: ""{0}""", savePath);

                VsInterop.IStorage destinationStorage = null;
                HRESULT            hr = NativeMethods.StgCreateDocfile(savePath, STGM.STGM_WRITE | STGM.STGM_SHARE_EXCLUSIVE | STGM.STGM_CREATE, 0, out destinationStorage);
                if (HResultHelper.IsSucceeded(hr) && destinationStorage != null)
                {
                    sourceStorage.CopyTo(0, null, IntPtr.Zero, destinationStorage);
                }
                else
                {
                    throw new Exception(string.Format(@"Failed: StgCreateDocfile(): Failed to create storage ""{0}""", savePath));
                }
            }
            else
            {
                throw new Exception(string.Format(@"Failed: OpenStorage(): Failed to save storage ""{0}""", storageName));
            }
        }
コード例 #3
0
        private static bool isPatch(VsInterop.IStorage storage)
        {
            Trace.Assert(storage != null);

            Guid CLSID_MsiPatch = new Guid(@"{000c1086-0000-0000-c000-000000000046}");

            VsInterop.STATSTG[] stg = new VsInterop.STATSTG[1];
            storage.Stat(stg, (uint)VsInterop.STATFLAG.STATFLAG_NONAME);
            return(stg[0].clsid == CLSID_MsiPatch);
        }
コード例 #4
0
 public extern static uint StgOpenStorage(string pwcsName, VsInterop.IStorage pstgPriority, STGM grfMode, string[] snbExclude, int reserved, out VsInterop.IStorage ppstgOpen);
コード例 #5
0
        static void Main(string[] args)
        {
            string extractDir       = @"D:\HotfixDB\lab";
            bool   includeExtension = true;

            string msiFilePath = @"D:\HotfixDB\lab\NDP45-KB3127229-x64\NDP45-KB3127229.msp";

            VsInterop.IStorage rootStorage = null;
            HRESULT            hr          = NativeMethods.StgOpenStorage(msiFilePath, null, STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE, null, 0, out rootStorage);

            if (HResultHelper.IsSucceeded(hr) && rootStorage != null)
            {
                //
                // A Database and Patch Example
                // https://msdn.microsoft.com/en-us/library/aa367813(v=vs.85).aspx
                //
                // http://www.pinvoke.net/default.aspx/msi.msirecordsetstring
                // http://blogs.msdn.com/b/heaths/archive/2006/03/31/566288.aspx
                //
                MsiDbOpenPersist msiDbOpenPersist = MsiDbOpenPersist.MSIDBOPEN_READONLY;
                if (isPatch(rootStorage))
                {
                    msiDbOpenPersist = MsiDbOpenPersist.MSIDBOPEN_READONLY | MsiDbOpenPersist.MSIDBOPEN_PATCHFILE;
                }

                // Release COM object of root storage.
                Marshal.ReleaseComObject(rootStorage);

                IntPtr msiDatabaseHandle = IntPtr.Zero;
                uint   err = NativeMethods.MsiOpenDatabase(msiFilePath, new IntPtr((uint)msiDbOpenPersist), out msiDatabaseHandle);
                if (err == WinError.ERROR_SUCCESS)
                {
                    IntPtr msiViewHandle = IntPtr.Zero;
                    //err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Streams", out msiViewHandle);
                    err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Storages", out msiViewHandle);
                    //err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Tables", out msiViewHandle);
                    if (err == WinError.ERROR_SUCCESS)
                    {
                        err = NativeMethods.MsiViewExecute(msiViewHandle, IntPtr.Zero);
                        if (err == WinError.ERROR_SUCCESS)
                        {
                            while (true)
                            {
                                IntPtr msiRecordHandle = IntPtr.Zero;
                                err = NativeMethods.MsiViewFetch(msiViewHandle, out msiRecordHandle);
                                if (err != WinError.ERROR_SUCCESS)
                                {
                                    break;
                                }

                                saveStream(msiRecordHandle, extractDir, includeExtension);

                                NativeMethods.MsiCloseHandle(msiRecordHandle);
                            }
                        }
                    }

                    // Close MSI view handle.
                    if (msiViewHandle != IntPtr.Zero)
                    {
                        NativeMethods.MsiCloseHandle(msiViewHandle);
                    }
                }

                // Close MSI database handle.
                if (msiDatabaseHandle != IntPtr.Zero)
                {
                    NativeMethods.MsiCloseHandle(msiDatabaseHandle);
                }
            }
            else
            {
                throw new Exception(string.Format(@"Failed: StgOpenStorage(): Failed to open root storage ""{0}""", msiFilePath));
            }
        }
コード例 #6
0
        static void Main(string[] args)
        {
            string extractDir       = @"F:\Takatano\Desktop\experiment\storages";
            bool   includeExtension = true;

            string msiFilePath = @"F:\Takatano\Projects\MsixEx\NDP45-KB3037581.msp";

            VsInterop.IStorage rootStorage = null;
            HRESULT            hr          = NativeMethods.StgOpenStorage(msiFilePath, null, STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE, null, 0, out rootStorage);

            if (HResultHelper.IsSucceeded(hr) && rootStorage != null)
            {
                //
                // もしかすると、この辺関係ないかも
                // (構造を維持して展開できれば、話は違うかも)
                //

                //VsInterop.IEnumSTATSTG enumStatStg = null;
                //rootStorage.EnumElements(0, IntPtr.Zero, 0, out enumStatStg);
                //if (enumStatStg != null)
                //{
                //    while (true)
                //    {
                //        VsInterop.STATSTG[] stg = new VsInterop.STATSTG[1];
                //        uint fetched;
                //        hr = (HRESULT)enumStatStg.Next(1, stg, out fetched);
                //        if (hr == HRESULT.S_FALSE)
                //        {
                //            break;
                //        }
                //        if (hr != HRESULT.S_OK)
                //        {
                //            throw new Exception(@"Failed: IEnumSTATSTG.Next(): Failed to enumerate next storage status");
                //        }

                //        Console.WriteLine(@"Name:{0}, Type:{1}", stg[0].pwcsName, stg[0].type);

                //        if ((VsInterop.STGTY)stg[0].type == VsInterop.STGTY.STGTY_STORAGE)
                //        {
                //            saveStorage(rootStorage, extractDir, stg[0].pwcsName, includeExtension ? @".mst" : null);
                //        }

                //        //if (stg.pwcsName)
                //        //{
                //        //    CoTaskMemFree(stg.pwcsName);    // これ必要なのかも, Marshal.FreeCoTaskMem(), string になっているし、不要かな。
                //        //    stg.pwcsName = NULL;
                //        //}
                //    }

                //    Marshal.ReleaseComObject(enumStatStg);
                //}

                //
                // A Database and Patch Example
                // https://msdn.microsoft.com/en-us/library/aa367813(v=vs.85).aspx
                //
                // http://www.pinvoke.net/default.aspx/msi.msirecordsetstring
                // http://blogs.msdn.com/b/heaths/archive/2006/03/31/566288.aspx
                //
                MsiDbOpenPersist msiDbOpenPersist = MsiDbOpenPersist.MSIDBOPEN_READONLY;
                if (isPatch(rootStorage))
                {
                    msiDbOpenPersist = MsiDbOpenPersist.MSIDBOPEN_READONLY | MsiDbOpenPersist.MSIDBOPEN_PATCHFILE;
                }

                // Release COM object of root storage.
                Marshal.ReleaseComObject(rootStorage);

                IntPtr msiDatabaseHandle = IntPtr.Zero;
                uint   err = NativeMethods.MsiOpenDatabase(msiFilePath, new IntPtr((uint)msiDbOpenPersist), out msiDatabaseHandle);
                if (err == WinError.ERROR_SUCCESS)
                {
                    IntPtr msiViewHandle = IntPtr.Zero;
                    err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Streams", out msiViewHandle);
                    if (err == WinError.ERROR_SUCCESS)
                    {
                        err = NativeMethods.MsiViewExecute(msiViewHandle, IntPtr.Zero);
                        if (err == WinError.ERROR_SUCCESS)
                        {
                            while (true)
                            {
                                IntPtr msiRecordHandle = IntPtr.Zero;
                                err = NativeMethods.MsiViewFetch(msiViewHandle, out msiRecordHandle);
                                if (err != WinError.ERROR_SUCCESS)
                                {
                                    break;
                                }

                                saveStream(msiRecordHandle, extractDir, includeExtension);

                                NativeMethods.MsiCloseHandle(msiRecordHandle);
                            }
                        }
                    }

                    // Close MSI view handle.
                    if (msiViewHandle != IntPtr.Zero)
                    {
                        NativeMethods.MsiCloseHandle(msiViewHandle);
                    }
                }

                // Close MSI database handle.
                if (msiDatabaseHandle != IntPtr.Zero)
                {
                    NativeMethods.MsiCloseHandle(msiDatabaseHandle);
                }
            }
            else
            {
                throw new Exception(string.Format(@"Failed: StgOpenStorage(): Failed to open root storage ""{0}""", msiFilePath));
            }
        }