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// MDFileFormat.h
6//
7
8//
9// This file contains a set of helpers to verify and read the file format.
10// This code does not handle the paging of the data, or different types of
11// I/O. See the StgTiggerStorage and StgIO code for this level of support.
12//
13//*****************************************************************************
14#ifndef __MDFileFormat_h__
15#define __MDFileFormat_h__
16
17//*****************************************************************************
18// The signature ULONG is the first 4 bytes of the file format. The second
19// signature string starts the header containing the stream list. It is used
20// for an integrity check when reading the header in lieu of a more complicated
21// system.
22//*****************************************************************************
23#define STORAGE_MAGIC_SIG 0x424A5342 // BSJB
24
25
26
27//*****************************************************************************
28// These values get written to the signature at the front of the file. Changing
29// these values should not be done lightly because all old files will no longer
30// be supported. In a future revision if a format change is required, a
31// backwards compatible migration path must be provided.
32//*****************************************************************************
33
34#define FILE_VER_MAJOR 1
35#define FILE_VER_MINOR 1
36
37// These are the last legitimate 0.x version macros. The file format has
38// sinced move up to 1.x (see macros above). After COM+ 1.0/NT 5 RTM's, these
39// macros should no longer be required or ever seen.
40#define FILE_VER_MAJOR_v0 0
41
42#define FILE_VER_MINOR_v0 19
43
44
45#define MAXSTREAMNAME 32
46
47enum
48{
49 STGHDR_NORMAL = 0x00, // Normal default flags.
50 STGHDR_EXTRADATA = 0x01, // Additional data exists after header.
51};
52
53
54//*****************************************************************************
55// This is the formal signature area at the front of the file. This structure
56// is not allowed to change, the shim depends on it staying the same size.
57// Use the reserved pointer if it must extended.
58//*****************************************************************************
59struct STORAGESIGNATURE;
60typedef STORAGESIGNATURE UNALIGNED * PSTORAGESIGNATURE;
61
62#include "pshpack1.h"
63struct STORAGESIGNATURE
64{
65METADATA_FIELDS_PROTECTION:
66 ULONG lSignature; // "Magic" signature.
67 USHORT iMajorVer; // Major file version.
68 USHORT iMinorVer; // Minor file version.
69 ULONG iExtraData; // Offset to next structure of information
70 ULONG iVersionString; // Length of version string
71public:
72 BYTE pVersion[0]; // Version string
73 ULONG GetSignature()
74 {
75 return VAL32(lSignature);
76 }
77 void SetSignature(ULONG Signature)
78 {
79 lSignature = VAL32(Signature);
80 }
81
82 USHORT GetMajorVer()
83 {
84 return VAL16(iMajorVer);
85 }
86 void SetMajorVer(USHORT MajorVer)
87 {
88 iMajorVer = VAL16(MajorVer);
89 }
90
91 USHORT GetMinorVer()
92 {
93 return VAL16(iMinorVer);
94 }
95 void SetMinorVer(USHORT MinorVer)
96 {
97 iMinorVer = VAL16(MinorVer);
98 }
99
100 ULONG GetExtraDataOffset()
101 {
102 return VAL32(iExtraData);
103 }
104 void SetExtraDataOffset(ULONG ExtraDataOffset)
105 {
106 iExtraData = VAL32(ExtraDataOffset);
107 }
108
109 ULONG GetVersionStringLength()
110 {
111 return VAL32(iVersionString);
112 }
113 void SetVersionStringLength(ULONG VersionStringLength)
114 {
115 iVersionString = VAL32(VersionStringLength);
116 }
117};
118#include "poppack.h"
119
120
121//*****************************************************************************
122// The header of the storage format.
123//*****************************************************************************
124struct STORAGEHEADER;
125typedef STORAGEHEADER UNALIGNED * PSTORAGEHEADER;
126
127#include "pshpack1.h"
128struct STORAGEHEADER
129{
130METADATA_FIELDS_PROTECTION:
131 BYTE fFlags; // STGHDR_xxx flags.
132 BYTE pad;
133 USHORT iStreams; // How many streams are there.
134public:
135 BYTE GetFlags()
136 {
137 return fFlags;
138 }
139 void SetFlags(BYTE flags)
140 {
141 fFlags = flags;
142 }
143 void AddFlags(BYTE flags)
144 {
145 fFlags |= flags;
146 }
147
148
149 USHORT GetiStreams()
150 {
151 return VAL16(iStreams);
152 }
153 void SetiStreams(USHORT iStreamsCount)
154 {
155 iStreams = VAL16(iStreamsCount);
156 }
157};
158#include "poppack.h"
159
160
161//*****************************************************************************
162// Each stream is described by this struct, which includes the offset and size
163// of the data. The name is stored in ANSI null terminated.
164//*****************************************************************************
165struct STORAGESTREAM;
166typedef STORAGESTREAM UNALIGNED * PSTORAGESTREAM;
167
168#include "pshpack1.h"
169struct STORAGESTREAM
170{
171METADATA_FIELDS_PROTECTION:
172 ULONG iOffset; // Offset in file for this stream.
173 ULONG iSize; // Size of the file.
174 char rcName[MAXSTREAMNAME]; // Start of name, null terminated.
175public:
176 // Returns pointer to the next stream. Doesn't validate the structure.
177 inline PSTORAGESTREAM NextStream()
178 {
179 int iLen = (int)(strlen(rcName) + 1);
180 iLen = ALIGN4BYTE(iLen);
181 return ((PSTORAGESTREAM) (((BYTE*)this) + (sizeof(ULONG) * 2) + iLen));
182 }
183 // Returns pointer to the next stream.
184 // Returns NULL if the structure has invalid format.
185 inline PSTORAGESTREAM NextStream_Verify()
186 {
187 // Check existence of null-terminator in the name
188 if (memchr(rcName, 0, MAXSTREAMNAME) == NULL)
189 {
190 return NULL;
191 }
192 return NextStream();
193 }
194
195 inline ULONG GetStreamSize()
196 {
197 return (ULONG)(strlen(rcName) + 1 + (sizeof(STORAGESTREAM) - sizeof(rcName)));
198 }
199
200 inline char* GetName()
201 {
202 return rcName;
203 }
204 inline LPCWSTR GetName(__inout_ecount (iMaxSize) LPWSTR szName, int iMaxSize)
205 {
206 VERIFY(::WszMultiByteToWideChar(CP_ACP, 0, rcName, -1, szName, iMaxSize));
207 return (szName);
208 }
209 inline void SetName(LPCWSTR szName)
210 {
211 int size;
212 size = WszWideCharToMultiByte(CP_ACP, 0, szName, -1, rcName, MAXSTREAMNAME, 0, 0);
213 _ASSERTE(size > 0);
214 }
215
216 ULONG GetSize()
217 {
218 return VAL32(iSize);
219 }
220 void SetSize(ULONG Size)
221 {
222 iSize = VAL32(Size);
223 }
224
225 ULONG GetOffset()
226 {
227 return VAL32(iOffset);
228 }
229 void SetOffset(ULONG Offset)
230 {
231 iOffset = VAL32(Offset);
232 }
233};
234#include "poppack.h"
235
236
237class MDFormat
238{
239public:
240//*****************************************************************************
241// Verify the signature at the front of the file to see what type it is.
242//*****************************************************************************
243 static HRESULT VerifySignature(
244 PSTORAGESIGNATURE pSig, // The signature to check.
245 ULONG cbData); // Size of metadata.
246
247//*****************************************************************************
248// Skip over the header and find the actual stream data.
249// It doesn't perform any checks for buffer overflow - use GetFirstStream_Verify
250// instead.
251//*****************************************************************************
252 static PSTORAGESTREAM GetFirstStream(// Return pointer to the first stream.
253 PSTORAGEHEADER pHeader, // Return copy of header struct.
254 const void *pvMd); // Pointer to the full file.
255//*****************************************************************************
256// Skip over the header and find the actual stream data. Secure version of
257// GetFirstStream method.
258// The header is supposed to be verified by VerifySignature.
259//
260// Caller has to check available buffer size before using the first stream.
261//*****************************************************************************
262 static PSTORAGESTREAM GetFirstStream_Verify(// Return pointer to the first stream.
263 PSTORAGEHEADER pHeader, // Return copy of header struct.
264 const void *pvMd, // Pointer to the full file.
265 ULONG *pcbMd); // [in, out] Size of pvMd buffer (we don't want to read behind it)
266
267};
268
269#endif // __MDFileFormat_h__
270