コード例 #1
0
ファイル: Storage.cs プロジェクト: volt72/psmsi
        /// <summary>
        /// Opens an OLE storage file.
        /// </summary>
        /// <param name="path">Path to a storage file.</param>
        /// <returns>An instance of the <see cref="Storage"/> class.</returns>
        /// <exception cref="FileNotFoundException">The file path does not exist.</exception>
        /// <exception cref="InvalidDataException">The file is not an OLE storage file..</exception>
        /// <exception cref="Win32Exception">Windows errors returned by OLE storage.</exception>
        internal static Storage OpenStorage(string path)
        {
            // Make sure the file exists.
            if (!File.Exists(path))
            {
                throw new FileNotFoundException(path);
            }

            // Try to open the file as an OLE storage file.
            NativeMethods.IStorage stg = null;
            Guid iid = NativeMethods.IID_IStorage;

            int ret = NativeMethods.StgOpenStorageEx(path,
                                                     NativeMethods.STGM.STGM_READ | NativeMethods.STGM.STGM_SHARE_DENY_WRITE,
                                                     NativeMethods.STGFMT.STGFMT_STORAGE,
                                                     0,
                                                     IntPtr.Zero,
                                                     IntPtr.Zero,
                                                     ref iid, out stg);

            if (NativeMethods.STG_E_FILEALREADYEXISTS == ret)
            {
                // 0x80030050 is a rather odd error string, so return something more appropriate.
                var message = string.Format(CultureInfo.CurrentCulture, Properties.Resources.Error_InvalidStorage, path);
                throw new InvalidDataException(message, new Win32Exception(ret));
            }
            else if (0 != ret)
            {
                throw new Win32Exception(ret);
            }
            else
            {
                return(new Storage(stg));
            }
        }
コード例 #2
0
        private Storage(Stream storageStream, FileAccess fileAccess = FileAccess.Read)
        {
            NativeMethods.IStorage   memoryStorage      = null;
            NativeMethods.ILockBytes memoryStorageBytes = null;
            try
            {
                // Read stream into buffer
                var buffer = new byte[storageStream.Length];
                storageStream.Read(buffer, 0, buffer.Length);

                // Create a ILockBytes (unmanaged byte array) and write buffer into it
                NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true, out memoryStorageBytes);
                memoryStorageBytes.WriteAt(0, buffer, buffer.Length, null);

                // Ensure provided stream data is an IStorage
                if (NativeMethods.StgIsStorageILockBytes(memoryStorageBytes) != 0)
                {
                    // ReSharper disable once LocalizableElement
                    throw new ArgumentException("The provided stream is not a valid IStorage", "storageStream");
                }

                var accesMode = NativeMethods.STGM.READWRITE;
                FileAccess = fileAccess;

                switch (fileAccess)
                {
                case FileAccess.Read:
                    accesMode = NativeMethods.STGM.READ;
                    break;

                case FileAccess.Write:
                case FileAccess.ReadWrite:
                    accesMode = NativeMethods.STGM.READWRITE;
                    break;
                }

                // Open and load IStorage on the ILockBytes
                NativeMethods.StgOpenStorageOnILockBytes(memoryStorageBytes, null,
                                                         accesMode | NativeMethods.STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out memoryStorage);

                // ReSharper disable once DoNotCallOverridableMethodsInConstructor
                LoadStorage(memoryStorage);
            }
            catch
            {
                if (memoryStorage != null)
                {
                    Marshal.ReleaseComObject(memoryStorage);
                }

                throw;
            }
            finally
            {
                if (memoryStorageBytes != null)
                {
                    Marshal.ReleaseComObject(memoryStorageBytes);
                }
            }
        }
コード例 #3
0
        private static void ReadIStorageIntoStream(IntPtr handle, Stream stream)
        {
            //To handle a IStorage it needs to be written into a second unmanaged memory mapped storage
            //and then the data can be read from memory into a managed byte and returned as a MemoryStream

            NativeMethods.ILockBytes iLockBytes  = null;
            NativeMethods.IStorage   iStorageNew = null;
            IntPtr ptrRead = IntPtr.Zero;

            try
            {
                //Marshal pointer to an IStorage object
                NativeMethods.IStorage iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(handle);

                //Create an ILockBytes object on a HGlobal, then create a IStorage object on top of the ILockBytes object
                iLockBytes  = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true);
                iStorageNew = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0);

                //Copy the IStorage object into the new IStorage object
                iStorage.CopyTo(0, null, IntPtr.Zero, iStorageNew);
                iLockBytes.Flush();
                iStorageNew.Commit(0);

                //Get length of ILockBytes byte array
                System.Runtime.InteropServices.ComTypes.STATSTG stat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                iLockBytes.Stat(out stat, 1);
                long length = stat.cbSize;

                //Read bytes into stream
                ptrRead = Marshal.AllocCoTaskMem(sizeof(int));
                byte[] buffer = new byte[4096];     //4 KB buffer
                int    offset = 0;
                int    bytesRead;
                while (true)
                {
                    iLockBytes.ReadAt(offset, buffer, buffer.Length, ptrRead);
                    bytesRead = Marshal.ReadInt32(ptrRead);
                    if (bytesRead == 0)
                    {
                        break;
                    }
                    stream.Write(buffer, 0, bytesRead);
                    offset += bytesRead;
                }
            }
            finally
            {
                //Release all unmanaged objects
                Marshal.FreeCoTaskMem(ptrRead);
                if (iStorageNew != null)
                {
                    Marshal.ReleaseComObject(iStorageNew);
                }
                if (iLockBytes != null)
                {
                    Marshal.ReleaseComObject(iLockBytes);
                }
            }
        }
コード例 #4
0
 internal static extern int StgOpenStorageEx(
     string pwcsName,
     [MarshalAs(UnmanagedType.U4)] NativeMethods.STGM grfMode,
     [MarshalAs(UnmanagedType.U4)] NativeMethods.STGFMT stgfmt,
     [MarshalAs(UnmanagedType.U4)] int grfAttrs,
     IntPtr pStgOptions,
     IntPtr reserved2,
     ref Guid riid,
     out NativeMethods.IStorage ppObjectOpen);
コード例 #5
0
        /// <summary>
        /// Processes sub streams and storages on the specified storage.
        /// </summary>
        /// <param name="storage"> The storage to get sub streams and storages for. </param>
        protected virtual void LoadStorage(NativeMethods.IStorage storage)
        {
            if (storage == null)
            {
                throw new ArgumentNullException("storage", "Storage can not be null");
            }

            _storage = storage;

            // Ensures memory is released
            ReferenceManager.AddItem(storage);
            NativeMethods.IEnumSTATSTG storageElementEnum = null;

            try
            {
                // Enum all elements of the storage
                storage.EnumElements(0, IntPtr.Zero, 0, out storageElementEnum);

                // Iterate elements
                while (true)
                {
                    // Get 1 element out of the COM enumerator
                    uint elementStatCount;
                    var  elementStats = new STATSTG[1];
                    storageElementEnum.Next(1, elementStats, out elementStatCount);

                    // Break loop if element not retrieved
                    if (elementStatCount != 1)
                    {
                        break;
                    }

                    var elementStat = elementStats[0];
                    switch (elementStat.type)
                    {
                    case 1:
                        // Element is a storage, add its statistics object to the storage dictionary
                        _subStorageStatistics.Add(elementStat.pwcsName, elementStat);
                        break;

                    case 2:
                        // Element is a stream, add its statistics object to the stream dictionary
                        _streamStatistics.Add(elementStat.pwcsName, elementStat);
                        break;
                    }
                }
            }
            finally
            {
                // Free memory
                if (storageElementEnum != null)
                {
                    Marshal.ReleaseComObject(storageElementEnum);
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Disposes this object
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                Disposing();
            }

            if (_storage == null)
            {
                return;
            }
            ReferenceManager.RemoveItem(_storage);
            Marshal.ReleaseComObject(_storage);
            _storage = null;
        }
コード例 #7
0
                public NativeMethods.IStorage GetStorage(string Path)
                {
                    if (STGRefs.ContainsKey(Path.ToUpper()))
                    {
                        return(STGRefs[Path.ToUpper()]);
                    }

                    NativeMethods.IStorage newStorage;
                    string[] chunks     = Path.Split('\\');
                    string   name       = chunks.Last();
                    string   parentPath = Path.Replace("\\" + name, "");

                    NativeMethods.IStorage parentStorage = GetStorage(parentPath);
                    parentStorage.OpenStorage(name, null, NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out newStorage);
                    STGRefs[Path.ToUpper()] = newStorage;
                    return(newStorage);
                }
コード例 #8
0
        /// <summary>
        /// Retrieves the data associated with the specified data format at the specified index.
        /// </summary>
        /// <param name="format">The format of the data to retrieve. See <see cref="T:System.Windows.Forms.DataFormats"></see> for predefined formats.</param>
        /// <param name="index">The index of the data to retrieve.</param>
        /// <returns>
        /// A <see cref="MemoryStream"/> containing the raw data for the specified data format at the specified index.
        /// </returns>
        public MemoryStream GetData(string format, int index)
        {
            //create a FORMATETC struct to request the data with
            FORMATETC formatetc = new FORMATETC();

            formatetc.cfFormat = (short)DataFormats.GetDataFormat(format).Id;
            formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT;
            formatetc.lindex   = index;
            formatetc.ptd      = new IntPtr(0);
            formatetc.tymed    = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL;

            //create STGMEDIUM to output request results into
            STGMEDIUM medium = new STGMEDIUM();

            //using the Com IDataObject interface get the data using the defined FORMATETC
            this.comUnderlyingDataObject.GetData(ref formatetc, out medium);

            //retrieve the data depending on the returned store type
            switch (medium.tymed)
            {
            case TYMED.TYMED_ISTORAGE:
                //to handle a IStorage it needs to be written into a second unmanaged
                //memory mapped storage and then the data can be read from memory into
                //a managed byte and returned as a MemoryStream

                NativeMethods.IStorage   iStorage   = null;
                NativeMethods.IStorage   iStorage2  = null;
                NativeMethods.ILockBytes iLockBytes = null;
                System.Runtime.InteropServices.ComTypes.STATSTG iLockBytesStat;
                try
                {
                    //marshal the returned pointer to a IStorage object
                    iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(medium.unionmember);
                    Marshal.Release(medium.unionmember);

                    //create a ILockBytes (unmanaged byte array) and then create a IStorage using the byte array as a backing store
                    iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true);
                    iStorage2  = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0);

                    //copy the returned IStorage into the new IStorage
                    iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2);
                    iLockBytes.Flush();
                    iStorage2.Commit(0);

                    //get the STATSTG of the ILockBytes to determine how many bytes were written to it
                    iLockBytesStat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                    iLockBytes.Stat(out iLockBytesStat, 1);
                    int iLockBytesSize = (int)iLockBytesStat.cbSize;

                    //read the data from the ILockBytes (unmanaged byte array) into a managed byte array
                    byte[] iLockBytesContent = new byte[iLockBytesSize];
                    iLockBytes.ReadAt(0, iLockBytesContent, iLockBytesContent.Length, null);

                    //wrapped the managed byte array into a memory stream and return it
                    return(new MemoryStream(iLockBytesContent));
                }
                finally
                {
                    //release all unmanaged objects
                    Marshal.ReleaseComObject(iStorage2);
                    Marshal.ReleaseComObject(iLockBytes);
                    Marshal.ReleaseComObject(iStorage);
                }

            case TYMED.TYMED_ISTREAM:
                //to handle a IStream it needs to be read into a managed byte and
                //returned as a MemoryStream

                IStream iStream = null;
                System.Runtime.InteropServices.ComTypes.STATSTG iStreamStat;
                try
                {
                    //marshal the returned pointer to a IStream object
                    iStream = (IStream)Marshal.GetObjectForIUnknown(medium.unionmember);
                    Marshal.Release(medium.unionmember);

                    //get the STATSTG of the IStream to determine how many bytes are in it
                    iStreamStat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                    iStream.Stat(out iStreamStat, 0);
                    int iStreamSize = (int)iStreamStat.cbSize;

                    //read the data from the IStream into a managed byte array
                    byte[] iStreamContent = new byte[iStreamSize];
                    iStream.Read(iStreamContent, iStreamContent.Length, IntPtr.Zero);

                    //wrapped the managed byte array into a memory stream and return it
                    return(new MemoryStream(iStreamContent));
                }
                finally
                {
                    //release all unmanaged objects
                    Marshal.ReleaseComObject(iStream);
                }

            case TYMED.TYMED_HGLOBAL:
                //to handle a HGlobal the exisitng "GetDataFromHGLOBLAL" method is invoked via
                //reflection

                return((MemoryStream)this.getDataFromHGLOBLALMethod.Invoke(this.oleUnderlyingDataObject, new object[] { DataFormats.GetDataFormat((short)formatetc.cfFormat).Name, medium.unionmember }));
            }

            return(null);
        }
コード例 #9
0
ファイル: Storage.cs プロジェクト: volt72/psmsi
 private Storage(NativeMethods.IStorage stg)
 {
     this.storage = stg;
     this.classId = Guid.Empty;
 }
コード例 #10
0
ファイル: Storage.cs プロジェクト: volt72/psmsi
 /// <summary>
 /// Closes the OLE storage file.
 /// </summary>
 public void Dispose()
 {
     this.storage = null;
     GC.SuppressFinalize(this);
 }
コード例 #11
0
ファイル: Storage.cs プロジェクト: heaths/psmsi
 /// <summary>
 /// Closes the OLE storage file.
 /// </summary>
 public void Dispose()
 {
     this.storage = null;
     GC.SuppressFinalize(this);
 }
コード例 #12
0
ファイル: Storage.cs プロジェクト: iraychen/MSGReader
        /// <summary>
        /// Processes sub streams and storages on the specified storage.
        /// </summary>
        /// <param name="storage"> The storage to get sub streams and storages for. </param>
        protected virtual void LoadStorage(NativeMethods.IStorage storage)
        {
            if (storage == null)
                throw new ArgumentNullException("storage", "Storage can not be null"); 
            
            _storage = storage;

            // Ensures memory is released
            ReferenceManager.AddItem(storage);
            NativeMethods.IEnumSTATSTG storageElementEnum = null;

            try
            {
                // Enum all elements of the storage
                storage.EnumElements(0, IntPtr.Zero, 0, out storageElementEnum);

                // Iterate elements
                while (true)
                {
                    // Get 1 element out of the COM enumerator
                    uint elementStatCount;
                    var elementStats = new STATSTG[1];
                    storageElementEnum.Next(1, elementStats, out elementStatCount);

                    // Break loop if element not retrieved
                    if (elementStatCount != 1)
                        break;

                    var elementStat = elementStats[0];
                    switch (elementStat.type)
                    {
                        case 1:
                            // Element is a storage, add its statistics object to the storage dictionary
                            _subStorageStatistics.Add(elementStat.pwcsName, elementStat);
                            break;

                        case 2:
                            // Element is a stream, add its statistics object to the stream dictionary
                            _streamStatistics.Add(elementStat.pwcsName, elementStat);
                            break;
                    }
                }
            }
            finally
            {
                // Free memory
                if (storageElementEnum != null)
                    Marshal.ReleaseComObject(storageElementEnum);
            }
        }
コード例 #13
0
                public Storage(IStorage RootStorage)
                {
                    this.RootStorage = RootStorage;

                    STGRefs["ROOT"] = this.RootStorage;
                }
コード例 #14
0
        public MemoryStream GetData(string format, int index)
        {
            FORMATETC formatetc = new FORMATETC()
            {
                cfFormat = (short)DataFormats.GetDataFormat(format).Id,
                dwAspect = DVASPECT.DVASPECT_CONTENT,
                lindex   = index,
                ptd      = new IntPtr(0),
                tymed    = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL
            };
            STGMEDIUM medium = new STGMEDIUM();

            this.comUnderlyingDataObject.GetData(ref formatetc, out medium);

            switch (medium.tymed)
            {
            case TYMED.TYMED_ISTORAGE:
                NativeMethods.IStorage   iStorage   = null;
                NativeMethods.IStorage   iStorage2  = null;
                NativeMethods.ILockBytes iLockBytes = null;
                System.Runtime.InteropServices.ComTypes.STATSTG iLockBytesStat;
                try
                {
                    iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(medium.unionmember);
                    Marshal.Release(medium.unionmember);

                    iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true);
                    iStorage2  = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0);

                    iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2);
                    iLockBytes.Flush();
                    iStorage2.Commit(0);

                    iLockBytesStat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                    iLockBytes.Stat(out iLockBytesStat, 1);
                    int iLockBytesSize = (int)iLockBytesStat.cbSize;

                    byte[] iLockBytesContent = new byte[iLockBytesSize];
                    iLockBytes.ReadAt(0, iLockBytesContent, iLockBytesContent.Length, null);

                    return(new MemoryStream(iLockBytesContent));
                }
                finally
                {
                    Marshal.ReleaseComObject(iStorage2);
                    Marshal.ReleaseComObject(iLockBytes);
                    Marshal.ReleaseComObject(iStorage);
                }

            case TYMED.TYMED_ISTREAM:
                IStream iStream = null;
                System.Runtime.InteropServices.ComTypes.STATSTG iStreamStat;
                try
                {
                    iStream = (IStream)Marshal.GetObjectForIUnknown(medium.unionmember);
                    Marshal.Release(medium.unionmember);

                    iStreamStat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                    iStream.Stat(out iStreamStat, 0);
                    int iStreamSize = (int)iStreamStat.cbSize;

                    byte[] iStreamContent = new byte[iStreamSize];
                    iStream.Read(iStreamContent, iStreamContent.Length, IntPtr.Zero);

                    return(new MemoryStream(iStreamContent));
                }
                finally
                {
                    Marshal.ReleaseComObject(iStream);
                }

            case TYMED.TYMED_HGLOBAL:
                return((MemoryStream)this.getDataFromHGLOBALMethod.Invoke(this.oleUnderlyingDataObject, new object[] { DataFormats.GetDataFormat((short)formatetc.cfFormat).Name, medium.unionmember }));
            }

            return(null);
        }
コード例 #15
0
 private Storage(NativeMethods.IStorage storage)
 {
     // ReSharper disable once DoNotCallOverridableMethodsInConstructor
     LoadStorage(storage);
 }
コード例 #16
0
ファイル: Storage.cs プロジェクト: iraychen/MSGReader
        /// <summary>
        /// Disposes this object
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
                Disposing();

            if (_storage == null) return;
            ReferenceManager.RemoveItem(_storage);
            Marshal.ReleaseComObject(_storage);
            _storage = null;
        }
コード例 #17
0
        private static void ReadIStorageIntoStream(IntPtr handle, Stream stream)
        {
            //To handle a IStorage it needs to be written into a second unmanaged memory mapped storage
            //and then the data can be read from memory into a managed byte and returned as a MemoryStream

            NativeMethods.IStorage   iStorage   = null;
            NativeMethods.IStorage   iStorage2  = null;
            NativeMethods.ILockBytes iLockBytes = null;
            System.Runtime.InteropServices.ComTypes.STATSTG iLockBytesStat;
            try
            {
                //Marshal the returned pointer to a IStorage object
                iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(handle);
                Marshal.Release(handle);

                //Create a ILockBytes (unmanaged byte array) and then create a IStorage using the byte array as a backing store
                iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true);
                iStorage2  = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0);

                //Copy the returned IStorage into the new IStorage
                iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2);
                iLockBytes.Flush();
                iStorage2.Commit(0);

                //Get the STATSTG of the ILockBytes to determine how many bytes were written to it
                iLockBytesStat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                iLockBytes.Stat(out iLockBytesStat, 1);
                int iLockBytesSize = (int)iLockBytesStat.cbSize;

                //Read the data from the ILockBytes (unmanaged byte array) into a managed byte array
                //byte[] iLockBytesContent = new byte[iLockBytesSize];
                //iLockBytes.ReadAt(0, iLockBytesContent, iLockBytesContent.Length, null);

                //Read bytes into stream
                IntPtr ptrRead = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int)));
                byte[] buffer  = new byte[1024];
                int    offset  = 0;
                int    bytesRead;
                while (true)
                {
                    iLockBytes.ReadAt(offset, buffer, buffer.Length, ptrRead);
                    bytesRead = Marshal.ReadInt32(ptrRead);
                    if (bytesRead == 0)
                    {
                        break;
                    }
                    stream.Write(buffer, 0, bytesRead);
                    offset += bytesRead;
                }
                stream.Seek(0, SeekOrigin.Begin);

                //Wrap the managed byte array into a memory stream and return it
                //return new MemoryStream(iLockBytesContent);
            }
            finally
            {
                //release all unmanaged objects
                Marshal.ReleaseComObject(iStorage2);
                Marshal.ReleaseComObject(iLockBytes);
                Marshal.ReleaseComObject(iStorage);
            }
        }
コード例 #18
0
        /// <summary>
        /// Processes sub streams and storages on the specified storage.
        /// </summary>
        /// <param name="storage">The storage to get sub streams and storages for.</param>
        protected virtual void LoadStorage(NativeMethods.IStorage storage)
        {
            this.storage = storage;

            //ensures memory is released
            ReferenceManager.AddItem(this.storage);

            NativeMethods.IEnumSTATSTG storageElementEnum = null;
            try
            {
                //enum all elements of the storage
                storage.EnumElements(0, IntPtr.Zero, 0, out storageElementEnum);

                //iterate elements
                while (true)
                {
                    //get 1 element out of the com enumerator
                    uint elementStatCount;
                    ComTypes.STATSTG[] elementStats = new ComTypes.STATSTG[1];
                    storageElementEnum.Next(1, elementStats, out elementStatCount);

                    //break loop if element not retrieved
                    if (elementStatCount != 1)
                    {
                        break;
                    }

                    ComTypes.STATSTG elementStat = elementStats[0];
                    switch (elementStat.type)
                    {
                        case 1:
                            //element is a storage. add its statistics object to the storage dictionary
                            subStorageStatistics.Add(elementStat.pwcsName, elementStat);
                            break;

                        case 2:
                            //element is a stream. add its statistics object to the stream dictionary
                            streamStatistics.Add(elementStat.pwcsName, elementStat);
                            break;
                    }
                }
            }
            finally
            {
                //free memory
                if (storageElementEnum != null)
                {
                    Marshal.ReleaseComObject(storageElementEnum);
                }
            }
        }
コード例 #19
0
ファイル: Storage.cs プロジェクト: heaths/psmsi
 private Storage(NativeMethods.IStorage stg)
 {
     this.storage = stg;
     this.classId = Guid.Empty;
 }