Reading minidump files, part 2 of 4: Using MiniDumpReadDumpStream

All code is available on my CodePlex project.

In the first post in this series I discussed memory mapped files and how to access them in C#. Now that we have those sorted we can move on to calling MiniDumpReadDumpStream() to read information out of a minidump file.

Here’s a reminder from the last post on what the method signature of

MiniDumpReadDumpStream

looks like (from MSDN):

BOOL WINAPI MiniDumpReadDumpStream(
    _In_ PVOID BaseOfDump,
    _In_ ULONG StreamNumber,
    _Out_ PMINIDUMP_DIRECTORY *Dir,
    _Out_ PVOID *StreamPointer,
    _Out_ ULONG *StreamSize
);

BaseOfDump [in] A pointer to the base of the mapped minidump file. The file should have been mapped into memory using the MapViewOfFile function.
StreamNumber [in] The type of data to be read from the minidump file. This member can be one of the values in the MINIDUMP_STREAM_TYPE enumeration.
Dir [out] A pointer to a MINIDUMP_DIRECTORY structure.
StreamPointer [out] A pointer to the beginning of the minidump stream. The format of this stream depends on the value of StreamNumber. For more information, see MINIDUMP_STREAM_TYPE.
StreamSize [out] The size of the stream pointed to by StreamPointer, in bytes.

To call

MiniDumpReadDumpStream()

we’ll tell it where to read from (BaseOfDump), what we want it to read (StreamNumber) and where we want the read information saved (StreamPointer and StreamSize). Don’t worry about “Dir” for now, we won’t be using it.

I covered BaseOfDump in the previous post so you can read up on it there. For the purposes of this article all we need to know is that PVOID maps to IntPtr in C# (don’t forget I’ve put a page up here with all of the C++/C# type mappings).

We use the second parameter, StreamNumber, to tell MiniDumpReadDumpStream() which stream of information we want to read.

Minidump files contain “streams” of information, similar to tables in a database. We can access the different streams by passing in different values to StreamNumber using the MINIDUMP_STREAM_TYPE enumeration. You’ll recall that when I spoke about MiniDumpWriteDump we had to specify what information to save using the DumpType parameter. Your choice of flags for DumpType will control what streams were saved in the minidump file and thus which ones you can read using StreamNumber. As an example: you can’t read the MINIDUMP_STREAM_TYPE.ThreadInfoListStream stream if you didn’t include MINIDUMP_TYPE.MiniDumpWithThreadInfo in your DumpType parameter.

From an interop point of view StreamNumber is a ULONG which is defined as a “32-bit unsigned integer”. Looking at our C# data types we see uint is also “Unsigned 32-bit integer”, so we’ll use it.

The values you can pass in are defined in the MINIDUMP_STREAM_TYPE enumeration. Here’s my mapped C# version:

public enum MINIDUMP_STREAM_TYPE : uint
{
    UnusedStream = 0,
    ReservedStream0 = 1,
    ReservedStream1 = 2,
    ThreadListStream = 3,
    ModuleListStream = 4,
    MemoryListStream = 5,
    ExceptionStream = 6,
    SystemInfoStream = 7,
    ThreadExListStream = 8,
    Memory64ListStream = 9,
    CommentStreamA = 10,
    CommentStreamW = 11,
    HandleDataStream = 12,
    FunctionTableStream = 13,
    UnloadedModuleListStream = 14,
    MiscInfoStream = 15,
    MemoryInfoListStream = 16,
    ThreadInfoListStream = 17,
    HandleOperationListStream = 18,
    LastReservedStream = 0xffff
}

Before I talk about the next 3 parameters (Dir, StreamPointer and StreamSize) there’s one very important thing to note about all of them: they’re all [Out] pointer parameters. Up until now all of the functions we’ve called have had [In] parameters – they only read values from us. If they returned anything it was a return value. None of them have returned information in their parameters. This time around these parameters will be returning information to us. Well that’s the simple version. I’m not going to go into the differences between out and ref now, if anyone wants details you’re welecome to ask and I’ll try and explain it. For now, suffice to say we need to pass each of the 3 using the ref keyword.

Dir is of type MINIDUMP_DIRECTORY and is a custom DbgHelp structure. It also contains a field of type MINIDUMP_LOCATION_DESCRIPTOR. Here are both of their definitions.

typedef struct _MINIDUMP_LOCATION_DESCRIPTOR {
  ULONG32 DataSize;
  RVA     Rva;
} MINIDUMP_LOCATION_DESCRIPTOR;

typedef struct _MINIDUMP_DIRECTORY {
  ULONG32                      StreamType;
  MINIDUMP_LOCATION_DESCRIPTOR Location;
} MINIDUMP_DIRECTORY, *PMINIDUMP_DIRECTORY;

I’m not going to explain either of them yet, as they’re not important for the moment. As far as mapping the types go: ULONG32 is an unsigned 32 integer (we’ll use UInt32) and RVA (defined in DbhHelp.h line 3697) is a DWORD, so uint for us.

The C# versions are as follows:

public struct MINIDUMP_LOCATION_DESCRIPTOR
{
    public UInt32 DataSize;
    public uint Rva;
}

public struct MINIDUMP_DIRECTORY
{
    public UInt32 StreamType;
    public MINIDUMP_LOCATION_DESCRIPTOR Location;
}

The last 2 parameters, StreamPointer and StreamSize tell us where the information was saved and how many bytes were saved. I’ll explain StreamPointer in more detail next time when I discuss how to interpret the information we get back. For now we just need to know that PVOID maps to IntPtr and ULONG maps to uint.

Here is the final version of our PInvoke mapping for MiniDumpReadDumpStream():

[DllImport("dbghelp.dll", SetLastError = true)]
public static extern bool MiniDumpReadDumpStream(IntPtr BaseOfDump,
        uint StreamNumber,
        ref MINIDUMP_DIRECTORY Dir,
        ref IntPtr StreamPointer,
        ref uint StreamSize);

Next time we’ll invoke the function and read one of the information streams (MINIDUMP_STREAM_TYPE.ModuleListStream)!

About these ads
This entry was posted in Crash Dumps and tagged , , , . Bookmark the permalink.

5 Responses to Reading minidump files, part 2 of 4: Using MiniDumpReadDumpStream

  1. Pingback: Reading minidump files part 3 of 4: Reading stream data returned from MiniDumpReadDumpStream | Greg's Blog

  2. DY says:

    very helpful :) !!

  3. Pingback: Reading minidump files, part 1 of 4: Accessing memory mapped files from C# | Greg's Blog

  4. Pingback: Reading minidump files, part 4 of 4: Putting it all together | Greg's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s