From dbde9e7104b907bbbaea17e21247d8cafc8b3a4c Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Sat, 14 Oct 2017 16:12:07 -0700 Subject: Massive refactoring to introduce the concept of IBackend --- .../Ole32/Storage.cs | 437 +++++++++++++++++++++ 1 file changed, 437 insertions(+) create mode 100644 src/WixToolset.Core.WindowsInstaller/Ole32/Storage.cs (limited to 'src/WixToolset.Core.WindowsInstaller/Ole32') diff --git a/src/WixToolset.Core.WindowsInstaller/Ole32/Storage.cs b/src/WixToolset.Core.WindowsInstaller/Ole32/Storage.cs new file mode 100644 index 00000000..c6a43bc4 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Ole32/Storage.cs @@ -0,0 +1,437 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Ole32 +{ + using System; + using System.Runtime.InteropServices; + using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; + using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG; + + /// + /// Specifies the access mode to use when opening, creating, or deleting a storage object. + /// + internal enum StorageMode + { + /// + /// Indicates that the object is read-only, meaning that modifications cannot be made. + /// + Read = 0x0, + + /// + /// Enables you to save changes to the object, but does not permit access to its data. + /// + Write = 0x1, + + /// + /// Enables access and modification of object data. + /// + ReadWrite = 0x2, + + /// + /// Specifies that subsequent openings of the object are not denied read or write access. + /// + ShareDenyNone = 0x40, + + /// + /// Prevents others from subsequently opening the object in Read mode. + /// + ShareDenyRead = 0x30, + + /// + /// Prevents others from subsequently opening the object for Write or ReadWrite access. + /// + ShareDenyWrite = 0x20, + + /// + /// Prevents others from subsequently opening the object in any mode. + /// + ShareExclusive = 0x10, + + /// + /// Opens the storage object with exclusive access to the most recently committed version. + /// + Priority = 0x40000, + + /// + /// Indicates that an existing storage object or stream should be removed before the new object replaces it. + /// + Create = 0x1000, + } + + /// + /// Wrapper for the compound storage file APIs. + /// + internal sealed class Storage : IDisposable + { + private bool disposed; + private IStorage storage; + + /// + /// Instantiate a new Storage. + /// + /// The native storage interface. + private Storage(IStorage storage) + { + this.storage = storage; + } + + /// + /// Storage destructor. + /// + ~Storage() + { + this.Dispose(); + } + + /// + /// The IEnumSTATSTG interface enumerates an array of STATSTG structures. + /// + [ComImport, Guid("0000000d-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumSTATSTG + { + /// + /// Gets a specified number of STATSTG structures. + /// + /// The number of STATSTG structures requested. + /// An array of STATSTG structures returned. + /// The number of STATSTG structures retrieved in the rgelt parameter. + /// The error code. + [PreserveSig] + uint Next(uint celt, [MarshalAs(UnmanagedType.LPArray), Out] STATSTG[] rgelt, out uint pceltFetched); + + /// + /// Skips a specified number of STATSTG structures in the enumeration sequence. + /// + /// The number of STATSTG structures to skip. + void Skip(uint celt); + + /// + /// Resets the enumeration sequence to the beginning of the STATSTG structure array. + /// + void Reset(); + + /// + /// Creates a new enumerator that contains the same enumeration state as the current STATSTG structure enumerator. + /// + /// The cloned IEnumSTATSTG interface. + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSTATSTG Clone(); + } + + /// + /// The IStorage interface supports the creation and management of structured storage objects. + /// + [ComImport, Guid("0000000b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IStorage + { + /// + /// Creates and opens a stream object with the specified name contained in this storage object. + /// + /// The name of the newly created stream. + /// Specifies the access mode to use when opening the newly created stream. + /// Reserved for future use; must be zero. + /// Reserved for future use; must be zero. + /// On return, pointer to the location of the new IStream interface pointer. + void CreateStream(string pwcsName, uint grfMode, uint reserved1, uint reserved2, out IStream ppstm); + + /// + /// Opens an existing stream object within this storage object using the specified access permissions in grfMode. + /// + /// The name of the stream to open. + /// Reserved for future use; must be NULL. + /// Specifies the access mode to be assigned to the open stream. + /// Reserved for future use; must be zero. + /// A pointer to IStream pointer variable that receives the interface pointer to the newly opened stream object. + void OpenStream(string pwcsName, IntPtr reserved1, uint grfMode, uint reserved2, out IStream ppstm); + + /// + /// Creates and opens a new storage object nested within this storage object with the specified name in the specified access mode. + /// + /// The name of the newly created storage object. + /// A value that specifies the access mode to use when opening the newly created storage object. + /// Reserved for future use; must be zero. + /// Reserved for future use; must be zero. + /// A pointer, when successful, to the location of the IStorage pointer to the newly created storage object. + void CreateStorage(string pwcsName, uint grfMode, uint reserved1, uint reserved2, out IStorage ppstg); + + /// + /// Opens an existing storage object with the specified name in the specified access mode. + /// + /// The name of the storage object to open. + /// Must be NULL. + /// Specifies the access mode to use when opening the storage object. + /// Must be NULL. + /// Reserved for future use; must be zero. + /// When successful, pointer to the location of an IStorage pointer to the opened storage object. + void OpenStorage(string pwcsName, IStorage pstgPriority, uint grfMode, IntPtr snbExclude, uint reserved, out IStorage ppstg); + + /// + /// Copies the entire contents of an open storage object to another storage object. + /// + /// The number of elements in the array pointed to by rgiidExclude. + /// An array of interface identifiers (IIDs) that either the caller knows about and does not want + /// copied or that the storage object does not support, but whose state the caller will later explicitly copy. + /// A string name block (refer to SNB) that specifies a block of storage or stream objects that are not to be copied to the destination. + /// A pointer to the open storage object into which this storage object is to be copied. + void CopyTo(uint ciidExclude, IntPtr rgiidExclude, IntPtr snbExclude, IStorage pstgDest); + + /// + /// Copies or moves a substorage or stream from this storage object to another storage object. + /// + /// The name of the element in this storage object to be moved or copied. + /// IStorage pointer to the destination storage object. + /// The new name for the element in its new storage object. + /// Specifies whether the operation should be a move (STGMOVE_MOVE) or a copy (STGMOVE_COPY). + void MoveElementTo(string pwcsName, IStorage pstgDest, string pwcsNewName, uint grfFlags); + + /// + /// Reflects changes for a transacted storage object to the parent level. + /// + /// Controls how the changes are committed to the storage object. + void Commit(uint grfCommitFlags); + + /// + /// Discards all changes that have been made to the storage object since the last commit operation. + /// + void Revert(); + + /// + /// Returns an enumerator object that can be used to enumerate the storage and stream objects contained within this storage object. + /// + /// Reserved for future use; must be zero. + /// Reserved for future use; must be NULL. + /// Reserved for future use; must be zero. + /// Pointer to IEnumSTATSTG* pointer variable that receives the interface pointer to the new enumerator object. + void EnumElements(uint reserved1, IntPtr reserved2, uint reserved3, out IEnumSTATSTG ppenum); + + /// + /// Removes the specified storage or stream from this storage object. + /// + /// The name of the storage or stream to be removed. + void DestroyElement(string pwcsName); + + /// + /// Renames the specified storage or stream in this storage object. + /// + /// The name of the substorage or stream to be changed. + /// The new name for the specified substorage or stream. + void RenameElement(string pwcsOldName, string pwcsNewName); + + /// + /// Sets the modification, access, and creation times of the indicated storage element, if supported by the underlying file system. + /// + /// The name of the storage object element whose times are to be modified. + /// Either the new creation time for the element or NULL if the creation time is not to be modified. + /// Either the new access time for the element or NULL if the access time is not to be modified. + /// Either the new modification time for the element or NULL if the modification time is not to be modified. + void SetElementTimes(string pwcsName, FILETIME pctime, FILETIME patime, FILETIME pmtime); + + /// + /// Assigns the specified CLSID to this storage object. + /// + /// The CLSID that is to be associated with the storage object. + void SetClass(Guid clsid); + + /// + /// Stores up to 32 bits of state information in this storage object. + /// + /// Specifies the new values of the bits to set. + /// A binary mask indicating which bits in grfStateBits are significant in this call. + void SetStateBits(uint grfStateBits, uint grfMask); + + /// + /// Returns the STATSTG structure for this open storage object. + /// + /// On return, pointer to a STATSTG structure where this method places information about the open storage object. + /// Specifies that some of the members in the STATSTG structure are not returned, thus saving a memory allocation operation. + void Stat(out STATSTG pstatstg, uint grfStatFlag); + } + + /// + /// The IStream interface lets you read and write data to stream objects. + /// + [ComImport, Guid("0000000c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IStream + { + /// + /// Reads a specified number of bytes from the stream object into memory starting at the current seek pointer. + /// + /// A pointer to the buffer which the stream data is read into. + /// The number of bytes of data to read from the stream object. + /// A pointer to a ULONG variable that receives the actual number of bytes read from the stream object. + void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbRead); + + /// + /// Writes a specified number of bytes into the stream object starting at the current seek pointer. + /// + /// A pointer to the buffer that contains the data that is to be written to the stream. + /// The number of bytes of data to attempt to write into the stream. + /// A pointer to a ULONG variable where this method writes the actual number of bytes written to the stream object. + void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten); + + /// + /// Changes the seek pointer to a new location relative to the beginning of the stream, the end of the stream, or the current seek pointer. + /// + /// The displacement to be added to the location indicated by the dwOrigin parameter. + /// The origin for the displacement specified in dlibMove. + /// A pointer to the location where this method writes the value of the new seek pointer from the beginning of the stream. + void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition); + + /// + /// Changes the size of the stream object. + /// + /// Specifies the new size of the stream as a number of bytes. + void SetSize(long libNewSize); + + /// + /// Copies a specified number of bytes from the current seek pointer in the stream to the current seek pointer in another stream. + /// + /// A pointer to the destination stream. + /// The number of bytes to copy from the source stream. + /// A pointer to the location where this method writes the actual number of bytes read from the source. + /// A pointer to the location where this method writes the actual number of bytes written to the destination. + void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten); + + /// + /// Ensures that any changes made to a stream object open in transacted mode are reflected in the parent storage object. + /// + /// Controls how the changes for the stream object are committed. + void Commit(int grfCommitFlags); + + /// + /// Discards all changes that have been made to a transacted stream since the last call to IStream::Commit. + /// + void Revert(); + + /// + /// Restricts access to a specified range of bytes in the stream. + /// + /// Integer that specifies the byte offset for the beginning of the range. + /// Integer that specifies the length of the range, in bytes, to be restricted. + /// Specifies the restrictions being requested on accessing the range. + void LockRegion(long libOffset, long cb, int dwLockType); + + /// + /// Removes the access restriction on a range of bytes previously restricted with IStream::LockRegion. + /// + /// Specifies the byte offset for the beginning of the range. + /// Specifies, in bytes, the length of the range to be restricted. + /// Specifies the access restrictions previously placed on the range. + void UnlockRegion(long libOffset, long cb, int dwLockType); + + /// + /// Retrieves the STATSTG structure for this stream. + /// + /// Pointer to a STATSTG structure where this method places information about this stream object. + /// Specifies that this method does not return some of the members in the STATSTG structure, thus saving a memory allocation operation. + void Stat(out STATSTG pstatstg, int grfStatFlag); + + /// + /// Creates a new stream object that references the same bytes as the original stream but provides a separate seek pointer to those bytes. + /// + /// When successful, pointer to the location of an IStream pointer to the new stream object. + void Clone(out IStream ppstm); + } + + /// + /// Creates a new compound file storage object. + /// + /// The compound file being created. + /// Specifies the access mode to use when opening the new storage object. + /// The created Storage object. + public static Storage CreateDocFile(string storageFile, StorageMode mode) + { + IStorage storage = NativeMethods.StgCreateDocfile(storageFile, (uint)mode, 0); + + return new Storage(storage); + } + + /// + /// Opens an existing root storage object in the file system. + /// + /// The file that contains the storage object to open. + /// Specifies the access mode to use to open the storage object. + /// The created Storage object. + public static Storage Open(string storageFile, StorageMode mode) + { + IStorage storage = NativeMethods.StgOpenStorage(storageFile, IntPtr.Zero, (uint)mode, IntPtr.Zero, 0); + + return new Storage(storage); + } + + /// + /// Copies the entire contents of this open storage object into another Storage object. + /// + /// The destination Storage object. + public void CopyTo(Storage destinationStorage) + { + this.storage.CopyTo(0, IntPtr.Zero, IntPtr.Zero, destinationStorage.storage); + } + + /// + /// Opens an existing Storage object with the specified name according to the specified access mode. + /// + /// The name of the Storage object. + /// The opened Storage object. + public Storage OpenStorage(string name) + { + IStorage subStorage; + + this.storage.OpenStorage(name, null, (uint)(StorageMode.Read | StorageMode.ShareExclusive), IntPtr.Zero, 0, out subStorage); + + return new Storage(subStorage); + } + + /// + /// Disposes the managed and unmanaged objects in this object. + /// + public void Dispose() + { + if (!this.disposed) + { + Marshal.ReleaseComObject(this.storage); + + this.disposed = true; + } + + GC.SuppressFinalize(this); + } + + /// + /// The native methods. + /// + private sealed class NativeMethods + { + /// + /// Protect the constructor since this class only contains static methods. + /// + private NativeMethods() + { + } + + /// + /// Creates a new compound file storage object. + /// + /// The name for the compound file being created. + /// Specifies the access mode to use when opening the new storage object. + /// Reserved for future use; must be zero. + /// A pointer to the location of the IStorage pointer to the new storage object. + [DllImport("ole32.dll", PreserveSig = false)] + [return: MarshalAs(UnmanagedType.Interface)] + internal static extern IStorage StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, uint grfMode, uint reserved); + + /// + /// Opens an existing root storage object in the file system. + /// + /// The file that contains the storage object to open. + /// Most often NULL. + /// Specifies the access mode to use to open the storage object. + /// If not NULL, pointer to a block of elements in the storage to be excluded as the storage object is opened. + /// Indicates reserved for future use; must be zero. + /// A pointer to a IStorage* pointer variable that receives the interface pointer to the opened storage. + [DllImport("ole32.dll", PreserveSig = false)] + [return: MarshalAs(UnmanagedType.Interface)] + internal static extern IStorage StgOpenStorage([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, IntPtr pstgPriority, uint grfMode, IntPtr snbExclude, uint reserved); + } + } +} -- cgit v1.2.3-55-g6feb