aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.Native/Ole32/Storage.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.Native/Ole32/Storage.cs')
-rw-r--r--src/WixToolset.Core.Native/Ole32/Storage.cs377
1 files changed, 377 insertions, 0 deletions
diff --git a/src/WixToolset.Core.Native/Ole32/Storage.cs b/src/WixToolset.Core.Native/Ole32/Storage.cs
new file mode 100644
index 00000000..3e4c6af2
--- /dev/null
+++ b/src/WixToolset.Core.Native/Ole32/Storage.cs
@@ -0,0 +1,377 @@
1// 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.
2
3namespace WixToolset.Core.Native.Ole32
4{
5 using System;
6 using System.Runtime.InteropServices;
7 using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
8 using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG;
9
10 /// <summary>
11 /// Wrapper for the compound storage file APIs.
12 /// </summary>
13 internal class Storage : IDisposable
14 {
15 private readonly IStorage storage;
16 private bool disposed;
17
18 /// <summary>
19 /// Instantiate a new Storage.
20 /// </summary>
21 /// <param name="storage">The native storage interface.</param>
22 private Storage(IStorage storage)
23 {
24 this.storage = storage;
25 }
26
27 /// <summary>
28 /// Storage destructor.
29 /// </summary>
30 ~Storage()
31 {
32 this.Dispose();
33 }
34
35 /// <summary>
36 /// The IEnumSTATSTG interface enumerates an array of STATSTG structures.
37 /// </summary>
38 [ComImport, Guid("0000000d-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
39 private interface IEnumSTATSTG
40 {
41 /// <summary>
42 /// Gets a specified number of STATSTG structures.
43 /// </summary>
44 /// <param name="celt">The number of STATSTG structures requested.</param>
45 /// <param name="rgelt">An array of STATSTG structures returned.</param>
46 /// <param name="pceltFetched">The number of STATSTG structures retrieved in the rgelt parameter.</param>
47 /// <returns>The error code.</returns>
48 [PreserveSig]
49 uint Next(uint celt, [MarshalAs(UnmanagedType.LPArray), Out] STATSTG[] rgelt, out uint pceltFetched);
50
51 /// <summary>
52 /// Skips a specified number of STATSTG structures in the enumeration sequence.
53 /// </summary>
54 /// <param name="celt">The number of STATSTG structures to skip.</param>
55 void Skip(uint celt);
56
57 /// <summary>
58 /// Resets the enumeration sequence to the beginning of the STATSTG structure array.
59 /// </summary>
60 void Reset();
61
62 /// <summary>
63 /// Creates a new enumerator that contains the same enumeration state as the current STATSTG structure enumerator.
64 /// </summary>
65 /// <returns>The cloned IEnumSTATSTG interface.</returns>
66 [return: MarshalAs(UnmanagedType.Interface)]
67 IEnumSTATSTG Clone();
68 }
69
70 /// <summary>
71 /// The IStorage interface supports the creation and management of structured storage objects.
72 /// </summary>
73 [ComImport, Guid("0000000b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
74 private interface IStorage
75 {
76 /// <summary>
77 /// Creates and opens a stream object with the specified name contained in this storage object.
78 /// </summary>
79 /// <param name="pwcsName">The name of the newly created stream.</param>
80 /// <param name="grfMode">Specifies the access mode to use when opening the newly created stream.</param>
81 /// <param name="reserved1">Reserved for future use; must be zero.</param>
82 /// <param name="reserved2">Reserved for future use; must be zero.</param>
83 /// <param name="ppstm">On return, pointer to the location of the new IStream interface pointer.</param>
84 void CreateStream(string pwcsName, uint grfMode, uint reserved1, uint reserved2, out IStream ppstm);
85
86 /// <summary>
87 /// Opens an existing stream object within this storage object using the specified access permissions in grfMode.
88 /// </summary>
89 /// <param name="pwcsName">The name of the stream to open.</param>
90 /// <param name="reserved1">Reserved for future use; must be NULL.</param>
91 /// <param name="grfMode">Specifies the access mode to be assigned to the open stream.</param>
92 /// <param name="reserved2">Reserved for future use; must be zero.</param>
93 /// <param name="ppstm">A pointer to IStream pointer variable that receives the interface pointer to the newly opened stream object.</param>
94 void OpenStream(string pwcsName, IntPtr reserved1, uint grfMode, uint reserved2, out IStream ppstm);
95
96 /// <summary>
97 /// Creates and opens a new storage object nested within this storage object with the specified name in the specified access mode.
98 /// </summary>
99 /// <param name="pwcsName">The name of the newly created storage object.</param>
100 /// <param name="grfMode">A value that specifies the access mode to use when opening the newly created storage object.</param>
101 /// <param name="reserved1">Reserved for future use; must be zero.</param>
102 /// <param name="reserved2">Reserved for future use; must be zero.</param>
103 /// <param name="ppstg">A pointer, when successful, to the location of the IStorage pointer to the newly created storage object.</param>
104 void CreateStorage(string pwcsName, uint grfMode, uint reserved1, uint reserved2, out IStorage ppstg);
105
106 /// <summary>
107 /// Opens an existing storage object with the specified name in the specified access mode.
108 /// </summary>
109 /// <param name="pwcsName">The name of the storage object to open.</param>
110 /// <param name="pstgPriority">Must be NULL.</param>
111 /// <param name="grfMode">Specifies the access mode to use when opening the storage object.</param>
112 /// <param name="snbExclude">Must be NULL.</param>
113 /// <param name="reserved">Reserved for future use; must be zero.</param>
114 /// <param name="ppstg">When successful, pointer to the location of an IStorage pointer to the opened storage object.</param>
115 void OpenStorage(string pwcsName, IStorage pstgPriority, uint grfMode, IntPtr snbExclude, uint reserved, out IStorage ppstg);
116
117 /// <summary>
118 /// Copies the entire contents of an open storage object to another storage object.
119 /// </summary>
120 /// <param name="ciidExclude">The number of elements in the array pointed to by rgiidExclude.</param>
121 /// <param name="rgiidExclude">An array of interface identifiers (IIDs) that either the caller knows about and does not want
122 /// copied or that the storage object does not support, but whose state the caller will later explicitly copy.</param>
123 /// <param name="snbExclude">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.</param>
124 /// <param name="pstgDest">A pointer to the open storage object into which this storage object is to be copied.</param>
125 void CopyTo(uint ciidExclude, IntPtr rgiidExclude, IntPtr snbExclude, IStorage pstgDest);
126
127 /// <summary>
128 /// Copies or moves a substorage or stream from this storage object to another storage object.
129 /// </summary>
130 /// <param name="pwcsName">The name of the element in this storage object to be moved or copied.</param>
131 /// <param name="pstgDest">IStorage pointer to the destination storage object.</param>
132 /// <param name="pwcsNewName">The new name for the element in its new storage object.</param>
133 /// <param name="grfFlags">Specifies whether the operation should be a move (STGMOVE_MOVE) or a copy (STGMOVE_COPY).</param>
134 void MoveElementTo(string pwcsName, IStorage pstgDest, string pwcsNewName, uint grfFlags);
135
136 /// <summary>
137 /// Reflects changes for a transacted storage object to the parent level.
138 /// </summary>
139 /// <param name="grfCommitFlags">Controls how the changes are committed to the storage object.</param>
140 void Commit(uint grfCommitFlags);
141
142 /// <summary>
143 /// Discards all changes that have been made to the storage object since the last commit operation.
144 /// </summary>
145 void Revert();
146
147 /// <summary>
148 /// Returns an enumerator object that can be used to enumerate the storage and stream objects contained within this storage object.
149 /// </summary>
150 /// <param name="reserved1">Reserved for future use; must be zero.</param>
151 /// <param name="reserved2">Reserved for future use; must be NULL.</param>
152 /// <param name="reserved3">Reserved for future use; must be zero.</param>
153 /// <param name="ppenum">Pointer to IEnumSTATSTG* pointer variable that receives the interface pointer to the new enumerator object.</param>
154 void EnumElements(uint reserved1, IntPtr reserved2, uint reserved3, out IEnumSTATSTG ppenum);
155
156 /// <summary>
157 /// Removes the specified storage or stream from this storage object.
158 /// </summary>
159 /// <param name="pwcsName">The name of the storage or stream to be removed.</param>
160 void DestroyElement(string pwcsName);
161
162 /// <summary>
163 /// Renames the specified storage or stream in this storage object.
164 /// </summary>
165 /// <param name="pwcsOldName">The name of the substorage or stream to be changed.</param>
166 /// <param name="pwcsNewName">The new name for the specified substorage or stream.</param>
167 void RenameElement(string pwcsOldName, string pwcsNewName);
168
169 /// <summary>
170 /// Sets the modification, access, and creation times of the indicated storage element, if supported by the underlying file system.
171 /// </summary>
172 /// <param name="pwcsName">The name of the storage object element whose times are to be modified.</param>
173 /// <param name="pctime">Either the new creation time for the element or NULL if the creation time is not to be modified.</param>
174 /// <param name="patime">Either the new access time for the element or NULL if the access time is not to be modified.</param>
175 /// <param name="pmtime">Either the new modification time for the element or NULL if the modification time is not to be modified.</param>
176 void SetElementTimes(string pwcsName, FILETIME pctime, FILETIME patime, FILETIME pmtime);
177
178 /// <summary>
179 /// Assigns the specified CLSID to this storage object.
180 /// </summary>
181 /// <param name="clsid">The CLSID that is to be associated with the storage object.</param>
182 void SetClass(Guid clsid);
183
184 /// <summary>
185 /// Stores up to 32 bits of state information in this storage object.
186 /// </summary>
187 /// <param name="grfStateBits">Specifies the new values of the bits to set.</param>
188 /// <param name="grfMask">A binary mask indicating which bits in grfStateBits are significant in this call.</param>
189 void SetStateBits(uint grfStateBits, uint grfMask);
190
191 /// <summary>
192 /// Returns the STATSTG structure for this open storage object.
193 /// </summary>
194 /// <param name="pstatstg">On return, pointer to a STATSTG structure where this method places information about the open storage object.</param>
195 /// <param name="grfStatFlag">Specifies that some of the members in the STATSTG structure are not returned, thus saving a memory allocation operation.</param>
196 void Stat(out STATSTG pstatstg, uint grfStatFlag);
197 }
198
199 /// <summary>
200 /// The IStream interface lets you read and write data to stream objects.
201 /// </summary>
202 [ComImport, Guid("0000000c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
203 private interface IStream
204 {
205 /// <summary>
206 /// Reads a specified number of bytes from the stream object into memory starting at the current seek pointer.
207 /// </summary>
208 /// <param name="pv">A pointer to the buffer which the stream data is read into.</param>
209 /// <param name="cb">The number of bytes of data to read from the stream object.</param>
210 /// <param name="pcbRead">A pointer to a ULONG variable that receives the actual number of bytes read from the stream object.</param>
211 void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbRead);
212
213 /// <summary>
214 /// Writes a specified number of bytes into the stream object starting at the current seek pointer.
215 /// </summary>
216 /// <param name="pv">A pointer to the buffer that contains the data that is to be written to the stream.</param>
217 /// <param name="cb">The number of bytes of data to attempt to write into the stream.</param>
218 /// <param name="pcbWritten">A pointer to a ULONG variable where this method writes the actual number of bytes written to the stream object.</param>
219 void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten);
220
221 /// <summary>
222 /// 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.
223 /// </summary>
224 /// <param name="dlibMove">The displacement to be added to the location indicated by the dwOrigin parameter.</param>
225 /// <param name="dwOrigin">The origin for the displacement specified in dlibMove.</param>
226 /// <param name="plibNewPosition">A pointer to the location where this method writes the value of the new seek pointer from the beginning of the stream.</param>
227 void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition);
228
229 /// <summary>
230 /// Changes the size of the stream object.
231 /// </summary>
232 /// <param name="libNewSize">Specifies the new size of the stream as a number of bytes.</param>
233 void SetSize(long libNewSize);
234
235 /// <summary>
236 /// Copies a specified number of bytes from the current seek pointer in the stream to the current seek pointer in another stream.
237 /// </summary>
238 /// <param name="pstm">A pointer to the destination stream.</param>
239 /// <param name="cb">The number of bytes to copy from the source stream.</param>
240 /// <param name="pcbRead">A pointer to the location where this method writes the actual number of bytes read from the source.</param>
241 /// <param name="pcbWritten">A pointer to the location where this method writes the actual number of bytes written to the destination.</param>
242 void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);
243
244 /// <summary>
245 /// Ensures that any changes made to a stream object open in transacted mode are reflected in the parent storage object.
246 /// </summary>
247 /// <param name="grfCommitFlags">Controls how the changes for the stream object are committed.</param>
248 void Commit(int grfCommitFlags);
249
250 /// <summary>
251 /// Discards all changes that have been made to a transacted stream since the last call to IStream::Commit.
252 /// </summary>
253 void Revert();
254
255 /// <summary>
256 /// Restricts access to a specified range of bytes in the stream.
257 /// </summary>
258 /// <param name="libOffset">Integer that specifies the byte offset for the beginning of the range.</param>
259 /// <param name="cb">Integer that specifies the length of the range, in bytes, to be restricted.</param>
260 /// <param name="dwLockType">Specifies the restrictions being requested on accessing the range.</param>
261 void LockRegion(long libOffset, long cb, int dwLockType);
262
263 /// <summary>
264 /// Removes the access restriction on a range of bytes previously restricted with IStream::LockRegion.
265 /// </summary>
266 /// <param name="libOffset">Specifies the byte offset for the beginning of the range.</param>
267 /// <param name="cb">Specifies, in bytes, the length of the range to be restricted.</param>
268 /// <param name="dwLockType">Specifies the access restrictions previously placed on the range.</param>
269 void UnlockRegion(long libOffset, long cb, int dwLockType);
270
271 /// <summary>
272 /// Retrieves the STATSTG structure for this stream.
273 /// </summary>
274 /// <param name="pstatstg">Pointer to a STATSTG structure where this method places information about this stream object.</param>
275 /// <param name="grfStatFlag">Specifies that this method does not return some of the members in the STATSTG structure, thus saving a memory allocation operation.</param>
276 void Stat(out STATSTG pstatstg, int grfStatFlag);
277
278 /// <summary>
279 /// Creates a new stream object that references the same bytes as the original stream but provides a separate seek pointer to those bytes.
280 /// </summary>
281 /// <param name="ppstm">When successful, pointer to the location of an IStream pointer to the new stream object.</param>
282 void Clone(out IStream ppstm);
283 }
284
285 /// <summary>
286 /// Creates a new compound file storage object.
287 /// </summary>
288 /// <param name="storageFile">The compound file being created.</param>
289 /// <param name="mode">Specifies the access mode to use when opening the new storage object.</param>
290 /// <returns>The created Storage object.</returns>
291 public static Storage CreateDocFile(string storageFile, StorageMode mode)
292 {
293 var storage = NativeMethods.StgCreateDocfile(storageFile, (uint)mode, 0);
294
295 return new Storage(storage);
296 }
297
298 /// <summary>
299 /// Opens an existing root storage object in the file system.
300 /// </summary>
301 /// <param name="storageFile">The file that contains the storage object to open.</param>
302 /// <param name="mode">Specifies the access mode to use to open the storage object.</param>
303 /// <returns>The created Storage object.</returns>
304 public static Storage Open(string storageFile, StorageMode mode)
305 {
306 var storage = NativeMethods.StgOpenStorage(storageFile, IntPtr.Zero, (uint)mode, IntPtr.Zero, 0);
307
308 return new Storage(storage);
309 }
310
311 /// <summary>
312 /// Copies the entire contents of this open storage object into another Storage object.
313 /// </summary>
314 /// <param name="destinationStorage">The destination Storage object.</param>
315 public void CopyTo(Storage destinationStorage)
316 {
317 this.storage.CopyTo(0, IntPtr.Zero, IntPtr.Zero, destinationStorage.storage);
318 }
319
320 /// <summary>
321 /// Opens an existing Storage object with the specified name according to the specified access mode.
322 /// </summary>
323 /// <param name="name">The name of the Storage object.</param>
324 /// <returns>The opened Storage object.</returns>
325 public Storage OpenStorage(string name)
326 {
327 this.storage.OpenStorage(name, null, (uint)(StorageMode.Read | StorageMode.ShareExclusive), IntPtr.Zero, 0, out var subStorage);
328
329 return new Storage(subStorage);
330 }
331
332 /// <summary>
333 /// Disposes the managed and unmanaged objects in this object.
334 /// </summary>
335 public void Dispose()
336 {
337 if (!this.disposed)
338 {
339 Marshal.ReleaseComObject(this.storage);
340
341 this.disposed = true;
342 }
343
344 GC.SuppressFinalize(this);
345 }
346
347 /// <summary>
348 /// The native methods.
349 /// </summary>
350 private static class NativeMethods
351 {
352 /// <summary>
353 /// Creates a new compound file storage object.
354 /// </summary>
355 /// <param name="pwcsName">The name for the compound file being created.</param>
356 /// <param name="grfMode">Specifies the access mode to use when opening the new storage object.</param>
357 /// <param name="reserved">Reserved for future use; must be zero.</param>
358 /// <returns>A pointer to the location of the IStorage pointer to the new storage object.</returns>
359 [DllImport("ole32.dll", PreserveSig = false)]
360 [return: MarshalAs(UnmanagedType.Interface)]
361 internal static extern IStorage StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, uint grfMode, uint reserved);
362
363 /// <summary>
364 /// Opens an existing root storage object in the file system.
365 /// </summary>
366 /// <param name="pwcsName">The file that contains the storage object to open.</param>
367 /// <param name="pstgPriority">Most often NULL.</param>
368 /// <param name="grfMode">Specifies the access mode to use to open the storage object.</param>
369 /// <param name="snbExclude">If not NULL, pointer to a block of elements in the storage to be excluded as the storage object is opened.</param>
370 /// <param name="reserved">Indicates reserved for future use; must be zero.</param>
371 /// <returns>A pointer to a IStorage* pointer variable that receives the interface pointer to the opened storage.</returns>
372 [DllImport("ole32.dll", PreserveSig = false)]
373 [return: MarshalAs(UnmanagedType.Interface)]
374 internal static extern IStorage StgOpenStorage([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, IntPtr pstgPriority, uint grfMode, IntPtr snbExclude, uint reserved);
375 }
376 }
377}