1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//*****************************************************************************
5// StgIO.h
6//
7
8//
9// This module handles disk/memory i/o for a generic set of storage solutions,
10// including:
11// * File system handle (HFILE)
12// * IStream
13// * User supplied memory buffer (non-movable)
14//
15// The Read, Write, Seek, ... functions are all directed to the corresponding
16// method for each type of file, allowing the consumer to use one set of api's.
17//
18// File system data can be paged fully into memory in two scenarios:
19// read: Normal memory mapped file is created to manage paging.
20// write: A custom paging system provides storage for pages as required. This
21// data is invalidated when you call Rewrite on the file.
22//
23// Transactions and backups are handled in the existing file case only. The
24// Rewrite function can make a backup of the current contents, and the Restore
25// function can be used to recover the data into the current scope. The backup
26// file is flushed to disk (which is slower but safer) after the copy. The
27// Restore also flushed the recovered changes to disk. Worst case scenario you
28// get a crash after calling Rewrite but before Restore, in which case you will
29// have a foo.clb.txn file in the same directory as the source file, foo.clb in
30// this example.
31//<TODO>
32// @FUTURE: issues,
33// 1. For reading a .clb in an image, it would be great to memory map
34// only the portion of the file with the .clb in it.
35//</TODO>
36//*****************************************************************************
37#ifndef __STGIO_H_
38#define __STGIO_H_
39
40#define MAXSHMEM 32
41
42#define STGIO_READ 0x1
43#define STGIO_WRITE 0x2
44
45enum DBPROPMODE
46 { DBPROP_TMODEF_READ = 0x1,
47 DBPROP_TMODEF_WRITE = 0x2,
48 DBPROP_TMODEF_EXCLUSIVE = 0x4,
49 // Shared memory uses ole32.dll - we cannot depend on it in the standalone WinRT Read-Only DLL
50 DBPROP_TMODEF_SHAREDMEM = 0x8,
51 DBPROP_TMODEF_CREATE = 0x10,
52 DBPROP_TMODEF_FAILIFTHERE = 0x20,
53 DBPROP_TMODEF_SLOWSAVE = 0x100,
54 // Means it is OK to use LoadLibrary to map the file. Used by code:ofTrustedImage.
55 // We prefer that because it is shared with loader's image loading.
56 DBPROP_TMODEF_TRYLOADLIBRARY = 0x400,
57#if 0 // dead code
58 DBPROP_TMODEF_NOTXNBACKUPFILE = 0x200,
59 DBPROP_TMODEF_COMPLUS = 0x1000,
60 DBPROP_TMODEF_SMEMCREATE = 0x2000,
61 DBPROP_TMODEF_SMEMOPEN = 0x4000,
62 DBPROP_TMODEF_ALIGNBLOBS = 0x10000
63 DBPROP_TMODEF_RESERVED = 0x80000000,
64#endif
65 DBPROP_TMODEF_DFTWRITEMASK = 0x113,
66 DBPROP_TMODEF_DFTREADWRITEMASK = 0x103,
67 };
68
69
70// Types of IO we can handle.
71enum STGIOTYPE
72{
73 STGIO_NODATA = 0, // Currently not open.
74 STGIO_HFILE = 1, // File handle contains data.
75 STGIO_HMODULE = 2, // The file was loaded via LoadLibrary as module.
76 STGIO_STREAM = 3, // Stream pointer has data.
77 STGIO_MEM = 4, // In memory pointer has data.
78 // Shared memory uses ole32.dll - we cannot depend on it in the standalone WinRT Read-Only DLL
79 STGIO_SHAREDMEM = 5, // Shared memory handle.
80 STGIO_HFILEMEM = 6 // Handle open, but memory allocated.
81};
82
83class StgIO
84{
85 friend class CLiteWeightStgdbRW; // for low-level access to data for metainfo and such.
86 friend class TiggerStorage;
87public:
88 StgIO(
89 bool bAutoMap=true); // Memory map for read on open?
90
91 ~StgIO();
92
93//*****************************************************************************
94// Open the base file on top of: (a) file, (b) memory buffer, or (c) stream.
95// If create flag is specified, then this will create a new file with the
96// name supplied. No data is read from an opened file. You must call
97// MapFileToMem before doing direct pointer access to the contents.
98//*****************************************************************************
99 HRESULT Open( // Return code.
100 LPCWSTR szName, // Name of the storage.
101 int fFlags, // How to open the file.
102 const void *pbBuff, // Optional buffer for memory.
103 ULONG cbBuff, // Size of buffer.
104 IStream *pIStream, // Stream for input.
105 LPSECURITY_ATTRIBUTES pAttributes); // Security token.
106
107//*****************************************************************************
108// Shut down the file handles and allocated objects.
109//*****************************************************************************
110 void Close();
111
112//*****************************************************************************
113// Read data from the storage source. This will handle all types of backing
114// storage from mmf, streams, and file handles. No read ahead or MRU
115// caching is done.
116//*****************************************************************************
117 HRESULT Read( // Return code.
118 void *pbBuff, // Write buffer here.
119 ULONG cbBuff, // How much to read.
120 ULONG *pcbRead); // How much read.
121
122//*****************************************************************************
123// Write to disk. This function will cache up to a page of data in a buffer
124// and peridocially flush it on overflow and explicit request. This makes it
125// safe to do lots of small writes without too much performance overhead.
126//*****************************************************************************
127 HRESULT Write( // Return code.
128 const void *pbBuff, // Buffer to write.
129 ULONG cbWrite, // How much.
130 ULONG *pcbWritten); // Return how much written.
131
132//*****************************************************************************
133// Moves the file pointer to the new location. This handles the different
134// types of storage systems.
135//*****************************************************************************
136 HRESULT Seek( // New offset.
137 int lVal, // How much to move.
138 ULONG fMoveType); // Direction, use Win32 FILE_xxxx.
139
140//*****************************************************************************
141// Retrieves the current offset for the storage being used. This value is
142// tracked based on Read, Write, and Seek operations.
143//*****************************************************************************
144 ULONG GetCurrentOffset(); // Current offset.
145
146//*****************************************************************************
147// Map the file contents to a memory mapped file and return a pointer to the
148// data. For read/write with a backing store, map the file using an internal
149// paging system.
150//*****************************************************************************
151 HRESULT MapFileToMem( // Return code.
152 void *&ptr, // Return pointer to file data.
153 ULONG *pcbSize, // Return size of data.
154 LPSECURITY_ATTRIBUTES pAttributes=0); // Security token.
155
156//*****************************************************************************
157// Free the mapping object for shared memory but keep the rest of the internal
158// state intact.
159//*****************************************************************************
160 HRESULT ReleaseMappingObject(); // Return code.
161
162//*****************************************************************************
163// Resets the logical base address and size to the value given. This is for
164// cases like finding a section embedded in another format, like the .clb inside
165// of an image. GetPtrForMem, Read, and Seek will then behave as though only
166// data from pbStart to cbSize is valid.
167//*****************************************************************************
168 HRESULT SetBaseRange( // Return code.
169 void *pbStart, // Start of file data.
170 ULONG cbSize); // How big is the range.
171
172//*****************************************************************************
173// For read/write case, get a pointer to a chunk of the file at cbStart for
174// size cbSize. Return the pointer. This will page in parts of the file from
175// disk if not already loaded.
176//*****************************************************************************
177 HRESULT GetPtrForMem( // Return code.
178 ULONG cbStart, // Offset from beginning to load.
179 ULONG cbSize, // How much, rounded to page.
180 void *&ptr); // Return pointer on success.
181
182//*****************************************************************************
183// For cached writes, flush the cache to the data store.
184//*****************************************************************************
185 HRESULT FlushCache();
186
187//*****************************************************************************
188// Tells the file system to flush any cached data it may have. This is
189// expensive, but if successful guarantees you won't lose writes short of
190// a disk failure.
191//*****************************************************************************
192 HRESULT FlushFileBuffers();
193
194//*****************************************************************************
195// Called after a successful rewrite of an existing file. The in memory
196// backing store is no longer valid because all new data is in memory and
197// on disk. This is essentially the same state as created, so free up some
198// working set and remember this state.
199//*****************************************************************************
200 HRESULT ResetBackingStore(); // Return code.
201
202 FILETYPE GetFileType()
203 { return m_FileType; }
204
205 int IsReadOnly()
206 { return ((m_fFlags & STGIO_WRITE) == 0); }
207
208 ULONG GetFlags()
209 { return (m_fFlags); }
210
211 ULONG SetFlags(ULONG fFlags)
212 { m_fFlags = fFlags;
213 return (m_fFlags); }
214
215 ULONG GetDataSize()
216 { return (m_cbData); }
217
218 LONG AddRef()
219 {
220 return (++m_cRef);
221 }
222
223 LONG Release()
224 {
225 LONG cRef = --m_cRef;
226 if (cRef == 0)
227 delete this;
228 return (cRef);
229 }
230
231 int IsAlignedPtr(ULONG_PTR Value, int iAlignment);
232 MAPPINGTYPE GetMemoryMappedType()
233 { return m_mtMappedType;}
234
235
236//*****************************************************************************
237// Called to read the data into allocated memory and release the backing store.
238// Only available on read-only data.
239//*****************************************************************************
240 HRESULT LoadFileToMemory();
241
242
243private:
244 int IsBackingStore()
245 { return (m_rgPageMap != 0); }
246 int IsMemoryMapped()
247 { return ((m_hMapping != NULL) || (m_hModule != NULL)); }
248
249 void CtorInit();
250 HRESULT WriteToDisk(const void *pbBuff, ULONG cbWrite, ULONG *pcbWritten);
251 HRESULT ReadFromDisk(void *pbBuff, ULONG cbBuff, ULONG *pcbRead);
252 HRESULT CopyFileInternal(LPCWSTR szTo, int bFailIfThere, int bWriteThrough);
253 void FreePageMap();
254
255private:
256
257 // Flags and state data.
258 FILETYPE m_FileType; // Cached type of the file (based on extension).
259 LONG m_cRef; // Ref count on this object.
260 bool m_bWriteThrough : 1; // true for write through mode.
261 bool m_bRewrite : 1; // State check for rewrite mode.
262 bool m_bAutoMap : 1; // true to automatically memory map file.
263 bool m_bFreeMem : 1; // true to free allocated memory.
264
265 // Handles.
266 IStream * m_pIStream; // For save to stream instead of file.
267 HANDLE m_hFile; // The actual file with contents.
268 HANDLE m_hMapping; // Mapping handle.
269 HMODULE m_hModule; // If we load with LoadLibrary, this is the module (otherwise NULL).
270 void * m_pBaseData; // Base address for memory mapped file.
271 void * m_pData; // For memory mapped file read.
272 ULONG m_cbData; // Size of in memory data.
273 int m_fFlags; // Flags for open/create mode.
274 STGIOTYPE m_iType; // Where is the data.
275 MAPPINGTYPE m_mtMappedType; // How the file was memory mapped
276
277 // File cache information.
278 BYTE * m_rgBuff; // Cache buffer for writing.
279 ULONG m_cbBuff; // Current cache size.
280 ULONG m_cbOffset; // Current offset in file.
281
282 // Buffer read management.
283 static int m_iPageSize; // Size of an OS page.
284 static int m_iCacheSize; // How big a write back cache to use.
285 BYTE * m_rgPageMap; // Track loaded pages on read/write.
286
287}; // class StgIO
288
289#endif // __STGIO_H_
290