Type
|
Field
|
Description
|
---|---|---|
BYTE
|
fFlags
|
Reserved; set to 0
|
BYTE
|
[padding]
| |
WORD
|
iStreams
|
Number of streams
|
Type
|
Field
|
Description
|
---|---|---|
DWORD
|
iOffset
|
Offset in the file for this stream.
|
DWORD
|
iSize
|
Size of the stream in bytes.
|
char[32 ]
|
rcName
|
Name of the stream; a zero-terminated
ASCII string no longer than 31 characters (plus zero terminator). The name might be shorter, in which case the size of the stream header is correspondingly reduced, padded to the 4-byte boundary. |
So let's get to it. I got those structures from the .NET IL Assembler book Chapter 5, which is all about the Metadata Tables. A Whole Chapter. I don't think I will get through it this post, but I will try and get it fully covered this week. Anyway, the first bit is dead easy. Here it is:
In the Stream Headers, the rcName is another variable length string. But it is bound, so I can easily use the standard struct deserialization to load the data. The only tricky part will be to find out where to start! Ok, I know that the Storage Header follows the Storage Signature which is pointed to by the CLRHeader, so let's just grab that and add in the length of the pVersion which is stored in the iVersionString. Easy enough.
Well, I didn't read the part above closely enough. I skipped right over the 'the size of the stream header is correspondingly reduced' part. I pulled the first of the 5 with no problem, but the rest were trash. So, another encapsulated struct. But this time I don't have a length, just a max length. I will just need to loop and keep going until I read a 0.
That almost worked. I need to read chunks of 4 bytes (the padding remember?) and then it works fine. Here is my implementation:
Well, I learned a bit and was able to re-use a new (to me) technique which means I might be able to retain it. That will do for tonight, more tomorrow.
Keep reaching for the heights.