Added support for minidump (read & write).

diff --git a/dlls/dbghelp/dbghelp.spec b/dlls/dbghelp/dbghelp.spec
index 8fdd97c..c3d0c95 100644
--- a/dlls/dbghelp/dbghelp.spec
+++ b/dlls/dbghelp/dbghelp.spec
@@ -20,8 +20,8 @@
 @ stdcall ImagehlpApiVersionEx(ptr)
 @ stdcall MakeSureDirectoryPathExists(str)
 @ stdcall MapDebugInformation(long str str long)
-@ stub MiniDumpReadDumpStream
-@ stub MiniDumpWriteDump
+@ stdcall MiniDumpReadDumpStream(ptr long ptr ptr ptr)
+@ stdcall MiniDumpWriteDump(ptr long ptr long long long long)
 @ stdcall SearchTreeForFile(str str str)
 @ stdcall StackWalk(long long long ptr ptr ptr ptr ptr ptr)
 @ stub StackWalk64
diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c
index bbc07c8..c3172b1 100644
--- a/dlls/dbghelp/elf_module.c
+++ b/dlls/dbghelp/elf_module.c
@@ -1278,9 +1278,11 @@
     struct process      pcs;
     struct elf_info     elf_info;
 
+    memset(&pcs, 0, sizeof(pcs));
     pcs.handle = hProc;
     elf_info.flags = ELF_INFO_DEBUG_HEADER;
     if (!elf_search_loader(&pcs, &elf_info)) return FALSE;
+    pcs.dbg_hdr_addr = elf_info.dbg_hdr_addr;
     return elf_enum_modules_internal(&pcs, cb, user);
 }
 
diff --git a/dlls/dbghelp/minidump.c b/dlls/dbghelp/minidump.c
index 67cb291..8a3adb0 100644
--- a/dlls/dbghelp/minidump.c
+++ b/dlls/dbghelp/minidump.c
@@ -24,74 +24,415 @@
 #define NONAMELESSSTRUCT
 
 #include "dbghelp_private.h"
+#include "ntstatus.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "winternl.h"
+#include "psapi.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
 
-#if 0
-/* hard to see how we can generate this very easily (how to grab latest exception
- * in a process ?)
+struct dump_memory
+{
+    ULONG                               base;
+    ULONG                               size;
+    ULONG                               rva;
+};
+
+struct dump_module
+{
+    unsigned                            is_elf;
+    ULONG                               base;
+    ULONG                               size;
+    char                                name[MAX_PATH];
+};
+
+struct dump_context
+{
+    /* process & thread information */
+    HANDLE                              hProcess;
+    DWORD                               pid;
+    void*                               pcs_buffer;
+    SYSTEM_PROCESS_INFORMATION*         spi;
+    /* module information */
+    struct dump_module*                 module;
+    unsigned                            num_module;
+    /* exception information */
+    /* output information */
+    MINIDUMP_TYPE                       type;
+    HANDLE                              hFile;
+    RVA                                 rva;
+    struct dump_memory*                 mem;
+    unsigned                            num_mem;
+    /* callback information */
+    MINIDUMP_CALLBACK_INFORMATION*      cb;
+};
+
+/******************************************************************
+ *		fetch_process_info
+ *
+ * reads system wide process information, and make spi point to the record
+ * for process of id 'pid'
  */
-static  void    DumpException(struct process* pcs, HANDLE hFile, RVA* rva)
+static BOOL fetch_process_info(struct dump_context* dc)
+{
+    ULONG       buf_size = 0x1000;
+    NTSTATUS    nts;
+
+    dc->pcs_buffer = NULL;
+    if (!(dc->pcs_buffer = HeapAlloc(GetProcessHeap(), 0, buf_size))) return FALSE;
+    for (;;)
+    {
+        nts = NtQuerySystemInformation(SystemProcessInformation, 
+                                       dc->pcs_buffer, buf_size, NULL);
+        if (nts != STATUS_INFO_LENGTH_MISMATCH) break;
+        dc->pcs_buffer = HeapReAlloc(GetProcessHeap(), 0, dc->pcs_buffer, 
+                                     buf_size *= 2);
+        if (!dc->pcs_buffer) return FALSE;
+    }
+
+    if (nts == STATUS_SUCCESS)
+    {
+        dc->spi = dc->pcs_buffer;
+        for (;;)
+        {
+            if (dc->spi->dwProcessID == dc->pid) return TRUE;
+            if (!dc->spi->dwOffset) break;
+            dc->spi = (SYSTEM_PROCESS_INFORMATION*)     
+                ((char*)dc->spi + dc->spi->dwOffset);
+        }
+    }
+    HeapFree(GetProcessHeap(), 0, dc->pcs_buffer);
+    dc->pcs_buffer = NULL;
+    dc->spi = NULL;
+    return FALSE;
+}
+
+/******************************************************************
+ *		fetch_thread_info
+ *
+ * fetches some information about thread of id 'tid'
+ */
+static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx,
+                              MINIDUMP_THREAD* mdThd, CONTEXT* ctx)
+{
+    NT_TIB                      tib;
+    DWORD                       tid = dc->spi->ti[thd_idx].dwThreadID;
+    HANDLE                      hThread;
+    THREAD_BASIC_INFORMATION    tbi;
+
+    memset(ctx, 0, sizeof(*ctx));
+
+    mdThd->ThreadId = dc->spi->ti[thd_idx].dwThreadID;
+    mdThd->SuspendCount = 0;
+    mdThd->Teb = 0;
+    mdThd->Stack.StartOfMemoryRange = 0;
+    mdThd->Stack.Memory.DataSize = 0;
+    mdThd->Stack.Memory.Rva = 0;
+    mdThd->ThreadContext.DataSize = 0;
+    mdThd->ThreadContext.Rva = 0;
+    mdThd->PriorityClass = dc->spi->ti[thd_idx].dwBasePriority; /* FIXME */
+    mdThd->Priority = dc->spi->ti[thd_idx].dwCurrentPriority;
+
+    if ((hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid)) == NULL)
+    {
+        FIXME("Couldn't open thread %lu (%lu)\n", 
+              dc->spi->ti[thd_idx].dwThreadID, GetLastError());
+        return FALSE;
+    }
+    
+    if (NtQueryInformationThread(hThread, ThreadBasicInformation,
+                                 &tbi, sizeof(tbi), NULL) == STATUS_SUCCESS)
+    {
+        mdThd->Teb = (ULONG_PTR)tbi.TebBaseAddress;
+        if (tbi.ExitStatus == STILL_ACTIVE && tid != GetCurrentThreadId() &&
+            (mdThd->SuspendCount = SuspendThread(hThread)) != (DWORD)-1)
+        {
+            mdThd->SuspendCount--;
+            ctx->ContextFlags = CONTEXT_FULL;
+            if (!GetThreadContext(hThread, ctx))
+                memset(ctx, 0, sizeof(*ctx));
+
+            if (ReadProcessMemory(dc->hProcess, tbi.TebBaseAddress, 
+                                  &tib, sizeof(tib), NULL))
+            {
+#ifdef __i386__
+                /* limiting the stack dumping to the size actually used */
+                if (ctx->Esp)
+                    mdThd->Stack.StartOfMemoryRange = (ctx->Esp - 4);
+                else
+                    mdThd->Stack.StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
+                mdThd->Stack.Memory.DataSize = (ULONG_PTR)tib.StackBase - 
+                    mdThd->Stack.StartOfMemoryRange;
+#else
+#error unsupported CPU                            
+#endif
+            }
+            ResumeThread(hThread);
+        }
+    }
+    CloseHandle(hThread);
+    return TRUE;
+}
+
+/******************************************************************
+ *		add_module
+ *
+ * Add a module to a dump context
+ */
+static BOOL add_module(struct dump_context* dc, const char* name,
+                       DWORD base, DWORD size, BOOL is_elf)
+{
+    if (!dc->module)
+        dc->module = HeapAlloc(GetProcessHeap(), 0, ++dc->num_module * sizeof(*dc->module));
+    else
+        dc->module = HeapReAlloc(GetProcessHeap(), 0, dc->module, ++dc->num_module * sizeof(*dc->module));
+    if (!dc->module) return FALSE;
+    if (is_elf ||
+        !GetModuleFileNameExA(dc->hProcess, (HMODULE)base, 
+                              dc->module[dc->num_module - 1].name,
+                              sizeof(dc->module[dc->num_module - 1].name)))
+        lstrcpynA(dc->module[dc->num_module - 1].name, name,
+                  sizeof(dc->module[dc->num_module - 1].name));
+    dc->module[dc->num_module - 1].base = base;
+    dc->module[dc->num_module - 1].size = size;
+    dc->module[dc->num_module - 1].is_elf = is_elf;
+
+    return TRUE;
+}
+
+/******************************************************************
+ *		fetch_pe_module_info_cb
+ *
+ * Callback for accumulating in dump_context a PE modules set
+ */
+static BOOL WINAPI fetch_pe_module_info_cb(char* name, DWORD base, DWORD size,
+                                           void* user)
+{
+    return add_module((struct dump_context*)user, name, base, size, FALSE);
+}
+
+/******************************************************************
+ *		fetch_elf_module_info_cb
+ *
+ * Callback for accumulating in dump_context a ELF modules set
+ */
+static BOOL fetch_elf_module_info_cb(const char* name, unsigned long base, 
+                                     void* user)
+{
+    return add_module((struct dump_context*)user, name, 
+                      base, 0 /* FIXME */, TRUE);
+}
+
+static void fetch_module_info(struct dump_context* dc)
+{
+    WINE_FIXME("--> %p\n", dc->hProcess);
+    EnumerateLoadedModules(dc->hProcess, fetch_pe_module_info_cb, dc);
+    /* Since we include ELF modules in a separate stream from the regular PE ones,
+     * we can always include those ELF modules (they don't eat lots of space)
+     * And it's always a good idea to have a trace of the loaded ELF modules for
+     * a given application in a post mortem debugging condition.
+     */
+    elf_enum_modules(dc->hProcess, fetch_elf_module_info_cb, dc);
+}
+
+/******************************************************************
+ *		add_memory_block
+ *
+ * Add a memory block to be dumped in a minidump
+ * If rva is non 0, it's the rva in the minidump where has to be stored
+ * also the rva of the memory block when written (this allows to reference
+ * a memory block from outside the list of memory blocks).
+ */
+static void add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva)
+{
+    if (dc->mem)
+        dc->mem = HeapReAlloc(GetProcessHeap(), 0, dc->mem, 
+                              ++dc->num_mem * sizeof(*dc->mem));
+    else
+        dc->mem = HeapAlloc(GetProcessHeap(), 0, ++dc->num_mem * sizeof(*dc->mem));
+    if (dc->mem)
+    {
+        dc->mem[dc->num_mem - 1].base = base;
+        dc->mem[dc->num_mem - 1].size = size;
+        dc->mem[dc->num_mem - 1].rva  = rva;
+    }
+    else dc->num_mem = 0;
+}
+
+/******************************************************************
+ *		writeat
+ *
+ * Writes a chunk of data at a given position in the minidump
+ */
+static void writeat(struct dump_context* dc, RVA rva, void* data, unsigned size)
+{
+    DWORD       written;
+
+    SetFilePointer(dc->hFile, rva, NULL, FILE_BEGIN);
+    WriteFile(dc->hFile, data, size, &written, NULL);
+}
+
+/******************************************************************
+ *		append
+ *
+ * writes a new chunk of data to the minidump, increasing the current
+ * rva in dc
+ */
+static void append(struct dump_context* dc, void* data, unsigned size)
+{
+    writeat(dc, dc->rva, data, size);
+    dc->rva += size;
+}
+
+/******************************************************************
+ *		dump_exception_info
+ *
+ * Write in File the exception information from pcs
+ */
+static  void    dump_exception_info(struct dump_context* dc,
+                                    const MINIDUMP_EXCEPTION_INFORMATION* except)
 {
     MINIDUMP_EXCEPTION_STREAM   mdExcpt;
+    EXCEPTION_RECORD            rec, *prec;
+    CONTEXT                     ctx, *pctx;
+    int                         i;
 
-    mdExcpt.ThreadId = DEBUG_CurrThread->tid;
+    mdExcpt.ThreadId = except->ThreadId;
     mdExcpt.__alignment = 0;
-    mdExcpt.ExceptionRecord.
+    if (except->ClientPointers)
+    {
+        EXCEPTION_POINTERS      ep;
 
-    ULONG                       ExceptionCode;
-    ULONG                       ExceptionFlags;
-    ULONGLONG                   ExceptionRecord;
-    ULONGLONG                   ExceptionAddress;
-    ULONG                       NumberParameters;
-    ULONG                        __unusedAlignment;
-    ULONGLONG                   ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+        ReadProcessMemory(dc->hProcess, 
+                          except->ExceptionPointers, &ep, sizeof(ep), NULL);
+        ReadProcessMemory(dc->hProcess, 
+                          ep.ExceptionRecord, &rec, sizeof(rec), NULL);
+        ReadProcessMemory(dc->hProcess, 
+                          ep.ContextRecord, &ctx, sizeof(ctx), NULL);
+        prec = &rec;
+        pctx = &ctx;
+        
+    }
+    else
+    {
+        prec = except->ExceptionPointers->ExceptionRecord;
+        pctx = except->ExceptionPointers->ContextRecord;
+    }
+    mdExcpt.ExceptionRecord.ExceptionCode = prec->ExceptionCode;
+    mdExcpt.ExceptionRecord.ExceptionFlags = prec->ExceptionFlags;
+    mdExcpt.ExceptionRecord.ExceptionRecord = (DWORD_PTR)prec->ExceptionRecord;
+    mdExcpt.ExceptionRecord.ExceptionAddress = (DWORD_PTR)prec->ExceptionAddress;
+    mdExcpt.ExceptionRecord.NumberParameters = prec->NumberParameters;
+    mdExcpt.ExceptionRecord.__unusedAlignment = 0;
+    for (i = 0; i < mdExcpt.ExceptionRecord.NumberParameters; i++)
+        mdExcpt.ExceptionRecord.ExceptionInformation[i] = (DWORD_PTR)prec->ExceptionInformation[i];
+    mdExcpt.ThreadContext.DataSize = sizeof(*pctx);
+    mdExcpt.ThreadContext.Rva = dc->rva + sizeof(mdExcpt);
+
+    append(dc, &mdExcpt, sizeof(mdExcpt));
+    append(dc, pctx, sizeof(*pctx));
 }
-#endif
 
 /******************************************************************
  *		dump_modules
  *
  * Write in File the modules from pcs
  */
-static  void    dump_modules(struct process* pcs, HANDLE hFile, RVA* rva)
+static  void    dump_modules(struct dump_context* dc, BOOL dump_elf)
 {
     MINIDUMP_MODULE             mdModule;
     MINIDUMP_MODULE_LIST        mdModuleList;
-    DWORD                       written;
-    struct module*              module = NULL;
+    char                        tmp[1024];
+    MINIDUMP_STRING*            ms = (MINIDUMP_STRING*)tmp;
+    ULONG                       i, nmod;
+    RVA                         rva_base;
+    DWORD                       flags_out;
+
+    for (i = nmod = 0; i < dc->num_module; i++)
+    {
+        if ((dc->module[i].is_elf && dump_elf) || (!dc->module[i].is_elf && !dump_elf))
+            nmod++;
+    }
 
     mdModuleList.NumberOfModules = 0;
-    for (module = pcs->lmodules; module; module = module->next)
-        mdModuleList.NumberOfModules++;
-    WriteFile(hFile, &mdModuleList.NumberOfModules, 
-              sizeof(mdModuleList.NumberOfModules), &written, NULL);
-    *rva += sizeof(mdModuleList.NumberOfModules) +      
-        sizeof(mdModule) * mdModuleList.NumberOfModules;
-    for (module = pcs->lmodules; module; module = module->next)
+    /* reserve space for mdModuleList
+     * FIXME: since we don't support 0 length arrays, we cannot use the
+     * size of mdModuleList
+     * FIXME: if we don't ask for all modules in cb, we'll get a hole in the file
+     */
+    rva_base = dc->rva;
+    dc->rva += sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod;
+    for (i = 0; i < dc->num_module; i++)
     {
-        mdModule.BaseOfImage = (DWORD)module->module.BaseOfImage;
-        mdModule.SizeOfImage = module->module.ImageSize;
-        mdModule.CheckSum = module->module.CheckSum;
-        mdModule.TimeDateStamp = module->module.TimeDateStamp;
-        mdModule.ModuleNameRva = *rva;
-        *rva += strlen(module->module.ModuleName) + 1;
-        memset(&mdModule.VersionInfo, 0, sizeof(mdModule.VersionInfo)); /* FIXME */
-        mdModule.CvRecord.DataSize = 0; /* FIXME */
-        mdModule.CvRecord.Rva = 0; /* FIXME */
-        mdModule.MiscRecord.DataSize = 0; /* FIXME */
-        mdModule.MiscRecord.Rva = 0; /* FIXME */
-        mdModule.Reserved0 = 0;
-        mdModule.Reserved1 = 0;
-        WriteFile(hFile, &mdModule, sizeof(mdModule), &written, NULL);
+        if ((dc->module[i].is_elf && !dump_elf) || (!dc->module[i].is_elf && dump_elf))
+            continue;
+
+        flags_out = ModuleWriteModule | ModuleWriteMiscRecord | ModuleWriteCvRecord;
+        if (dc->type & MiniDumpWithDataSegs)
+            flags_out |= ModuleWriteDataSeg;
+        if (dc->type & MiniDumpWithProcessThreadData)
+            flags_out |= ModuleWriteTlsData;
+        if (dc->type & MiniDumpWithCodeSegs)
+            flags_out |= ModuleWriteCodeSegs;
+        ms->Length = MultiByteToWideChar(CP_ACP, 0, 
+                                         dc->module[i].name, -1,
+                                         NULL, 0) * sizeof(WCHAR);
+        if (sizeof(ULONG) + ms->Length > sizeof(tmp))
+            FIXME("Buffer overflow!!!\n");
+        MultiByteToWideChar(CP_ACP, 0, dc->module[i].name, -1,
+                            ms->Buffer, ms->Length);
+
+        if (dc->cb)
+        {
+            MINIDUMP_CALLBACK_INPUT     cbin;
+            MINIDUMP_CALLBACK_OUTPUT    cbout;
+
+            cbin.ProcessId = dc->pid;
+            cbin.ProcessHandle = dc->hProcess;
+            cbin.CallbackType = ModuleCallback;
+
+            cbin.u.Module.FullPath = ms->Buffer;
+            cbin.u.Module.BaseOfImage = dc->module[i].base;
+            cbin.u.Module.SizeOfImage = dc->module[i].size;
+            cbin.u.Module.CheckSum = 0; /* FIXME */
+            cbin.u.Module.TimeDateStamp = 0; /* FIXME */
+            memset(&cbin.u.Module.VersionInfo, 0, sizeof(cbin.u.Module.VersionInfo));
+            cbin.u.Module.CvRecord = NULL;
+            cbin.u.Module.SizeOfCvRecord = 0;
+            cbin.u.Module.MiscRecord = NULL;
+            cbin.u.Module.SizeOfMiscRecord = 0;
+
+            cbout.u.ModuleWriteFlags = flags_out;
+            if (!dc->cb->CallbackRoutine(dc->cb->CallbackParam, &cbin, &cbout))
+                continue;
+            flags_out &= cbout.u.ModuleWriteFlags;
+        }
+        if (flags_out & ModuleWriteModule)
+        {
+            mdModule.BaseOfImage = dc->module[i].base;
+            mdModule.SizeOfImage = dc->module[i].size;
+            mdModule.CheckSum = 0; /* FIXME */
+            mdModule.TimeDateStamp = 0; /* FIXME */
+            mdModule.ModuleNameRva = dc->rva;
+            ms->Length -= sizeof(WCHAR);
+            append(dc, ms, sizeof(ULONG) + ms->Length);
+            memset(&mdModule.VersionInfo, 0, sizeof(mdModule.VersionInfo)); /* FIXME */
+            mdModule.CvRecord.DataSize = 0; /* FIXME */
+            mdModule.CvRecord.Rva = 0; /* FIXME */
+            mdModule.MiscRecord.DataSize = 0; /* FIXME */
+            mdModule.MiscRecord.Rva = 0; /* FIXME */
+            mdModule.Reserved0 = 0; /* FIXME */
+            mdModule.Reserved1 = 0; /* FIXME */
+            writeat(dc,
+                    rva_base + sizeof(mdModuleList.NumberOfModules) + 
+                        mdModuleList.NumberOfModules++ * sizeof(mdModule), 
+                    &mdModule, sizeof(mdModule));
+        }
     }
-    for (module = pcs->lmodules; module; module = module->next)
-    {
-        WriteFile(hFile, module->module.ModuleName, 
-                  strlen(module->module.ModuleName) + 1, &written, NULL);
-        FIXME("CV and misc records not written\n");
-    }
+    writeat(dc, rva_base, &mdModuleList.NumberOfModules, 
+            sizeof(mdModuleList.NumberOfModules));
 }
 
 /******************************************************************
@@ -99,34 +440,39 @@
  *
  * Dumps into File the information about the system
  */
-static  void    dump_system_info(struct process* pcs, HANDLE hFile, RVA* rva)
+static  void    dump_system_info(struct dump_context* dc)
 {
     MINIDUMP_SYSTEM_INFO        mdSysInfo;
     SYSTEM_INFO                 sysInfo;
-    OSVERSIONINFOA              osInfo;
+    OSVERSIONINFOW              osInfo;
     DWORD                       written;
+    ULONG                       slen;
 
     GetSystemInfo(&sysInfo);
-    GetVersionExA(&osInfo);
+    osInfo.dwOSVersionInfoSize = sizeof(osInfo);
+    GetVersionExW(&osInfo);
 
     mdSysInfo.ProcessorArchitecture = sysInfo.u.s.wProcessorArchitecture;
     mdSysInfo.ProcessorLevel = sysInfo.wProcessorLevel;
     mdSysInfo.ProcessorRevision = sysInfo.wProcessorRevision;
-    mdSysInfo.Reserved0 = 0;
-
+    mdSysInfo.u.s.NumberOfProcessors = sysInfo.dwNumberOfProcessors;
+    mdSysInfo.u.s.ProductType = VER_NT_WORKSTATION; /* FIXME */
     mdSysInfo.MajorVersion = osInfo.dwMajorVersion;
     mdSysInfo.MinorVersion = osInfo.dwMinorVersion;
     mdSysInfo.BuildNumber = osInfo.dwBuildNumber;
     mdSysInfo.PlatformId = osInfo.dwPlatformId;
 
-    mdSysInfo.CSDVersionRva = *rva + sizeof(mdSysInfo);
-    mdSysInfo.Reserved1 = 0;
+    mdSysInfo.CSDVersionRva = dc->rva + sizeof(mdSysInfo);
+    mdSysInfo.u1.Reserved1 = 0;
 
-    WriteFile(hFile, &mdSysInfo, sizeof(mdSysInfo), &written, NULL);
-    *rva += sizeof(mdSysInfo);
-    WriteFile(hFile, osInfo.szCSDVersion, strlen(osInfo.szCSDVersion) + 1, 
-              &written, NULL);
-    *rva += strlen(osInfo.szCSDVersion) + 1;
+    memset(&mdSysInfo.Cpu, 0, sizeof(mdSysInfo.Cpu));
+
+    append(dc, &mdSysInfo, sizeof(mdSysInfo));
+
+    slen = lstrlenW(osInfo.szCSDVersion) * sizeof(WCHAR);
+    WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL);
+    WriteFile(dc->hFile, osInfo.szCSDVersion, slen, &written, NULL);
+    dc->rva += sizeof(ULONG) + slen;
 }
 
 /******************************************************************
@@ -134,36 +480,140 @@
  *
  * Dumps into File the information about running threads
  */
-static  void    dump_threads(struct process* pcs, HANDLE hFile, RVA* rva)
+static  void    dump_threads(struct dump_context* dc)
 {
-#if 0
     MINIDUMP_THREAD             mdThd;
     MINIDUMP_THREAD_LIST        mdThdList;
-    DWORD                       written;
-    DBG_THREAD*                 thd;
+    unsigned                    i;
+    RVA                         rva_base;
+    DWORD                       flags_out;
+    CONTEXT                     ctx;
 
-    mdThdList.NumberOfThreads = pcs->num_threads;
-    WriteFile(hFile, &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads), 
-              &written, NULL);
-    *rva += sizeof(mdThdList.NumberOfThreads) + 
-        mdThdList.NumberOfThreads * sizeof(mdThd);
-    for (thd = pcs->threads; thd; thd = thd->next)
+    mdThdList.NumberOfThreads = 0;
+
+    rva_base = dc->rva;
+    dc->rva += sizeof(mdThdList.NumberOfThreads) +
+        dc->spi->dwThreadCount * sizeof(mdThd);
+
+    for (i = 0; i < dc->spi->dwThreadCount; i++)
     {
-        mdThd.ThreadId = thd->tid;
-        mdThd.SuspendCount = 0; /* FIXME */
-        mdThd.PriorityClass = 0; /* FIXME */
-        mdThd.Priority = 0; /* FIXME */
-        mdThd.Teb = 0; /* FIXME */
-        mdThd.Stack.StartOfMemoryRange = 0; /* FIXME */
-        mdThd.Stack.Memory.DataSize = 0; /* FIXME */
-        mdThd.Stack.Memory.Rva = 0; /* FIXME */
-        mdThd.ThreadContext.DataSize = 0;/* FIXME */
-        mdThd.ThreadContext.Rva = 0; /* FIXME */
+        fetch_thread_info(dc, i, &mdThd, &ctx);
 
-        WriteFile(hFile, &mdThd, sizeof(mdThd), &written, NULL);
-        FIXME("Stack & thread context not written\n");
+        flags_out = ThreadWriteThread | ThreadWriteStack | ThreadWriteContext |
+            ThreadWriteInstructionWindow;
+        if (dc->type & MiniDumpWithProcessThreadData)
+            flags_out |= ThreadWriteThreadData;
+        if (dc->type & MiniDumpWithThreadInfo)
+            flags_out |= ThreadWriteThreadInfo;
+
+        if (dc->cb)
+        {
+            MINIDUMP_CALLBACK_INPUT     cbin;
+            MINIDUMP_CALLBACK_OUTPUT    cbout;
+
+            cbin.ProcessId = dc->pid;
+            cbin.ProcessHandle = dc->hProcess;
+            cbin.CallbackType = ThreadCallback;
+            cbin.u.Thread.ThreadId = dc->spi->ti[i].dwThreadID;
+            cbin.u.Thread.ThreadHandle = 0; /* FIXME */
+            memcpy(&cbin.u.Thread.Context, &ctx, sizeof(CONTEXT));
+            cbin.u.Thread.SizeOfContext = sizeof(CONTEXT);
+            cbin.u.Thread.StackBase = mdThd.Stack.StartOfMemoryRange;
+            cbin.u.Thread.StackEnd = mdThd.Stack.StartOfMemoryRange +
+                mdThd.Stack.Memory.DataSize;
+
+            cbout.u.ThreadWriteFlags = flags_out;
+            if (!dc->cb->CallbackRoutine(dc->cb->CallbackParam, &cbin, &cbout))
+                continue;
+            flags_out &= cbout.u.ThreadWriteFlags;
+        }
+        if (flags_out & ThreadWriteThread)
+        {
+            if (ctx.ContextFlags && (flags_out & ThreadWriteContext))
+            {
+                mdThd.ThreadContext.Rva = dc->rva;
+                mdThd.ThreadContext.DataSize = sizeof(CONTEXT);
+                append(dc, &ctx, sizeof(CONTEXT));
+            }
+            if (mdThd.Stack.Memory.DataSize && (flags_out & ThreadWriteStack))
+            {
+                add_memory_block(dc, mdThd.Stack.StartOfMemoryRange,
+                                 mdThd.Stack.Memory.DataSize,
+                                 rva_base + sizeof(mdThdList.NumberOfThreads) +
+                                     mdThdList.NumberOfThreads * sizeof(mdThd) +
+                                     FIELD_OFFSET(MINIDUMP_THREAD, Stack.Memory.Rva));
+            }
+            writeat(dc, 
+                    rva_base + sizeof(mdThdList.NumberOfThreads) +
+                        mdThdList.NumberOfThreads * sizeof(mdThd),
+                    &mdThd, sizeof(mdThd));
+            mdThdList.NumberOfThreads++;
+        }
+        if (ctx.ContextFlags && (flags_out & ThreadWriteInstructionWindow))
+        {
+            /* FIXME: - Native dbghelp also dumps 0x80 bytes around EIP
+             *        - also crop values across module boundaries, 
+             *        - and don't make it i386 dependent 
+             */
+            /* add_memory_block(dc, ctx.Eip - 0x80, ctx.Eip + 0x80, 0); */
+        }
     }
-#endif
+    writeat(dc, rva_base,
+            &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads));
+}
+
+/******************************************************************
+ *		dump_memory_info
+ *
+ * dumps information about the memory of the process (stack of the threads)
+ */
+static void dump_memory_info(struct dump_context* dc)
+{
+    MINIDUMP_MEMORY_LIST        mdMemList;
+    MINIDUMP_MEMORY_DESCRIPTOR  mdMem;
+    DWORD                       written;
+    unsigned                    i, pos, len;
+    RVA                         rva_base;
+    char                        tmp[1024];
+
+    mdMemList.NumberOfMemoryRanges = dc->num_mem;
+    append(dc, &mdMemList.NumberOfMemoryRanges,
+           sizeof(mdMemList.NumberOfMemoryRanges));
+    rva_base = dc->rva;
+    dc->rva += mdMemList.NumberOfMemoryRanges * sizeof(mdMem);
+
+    for (i = 0; i < dc->num_mem; i++)
+    {
+        mdMem.StartOfMemoryRange = dc->mem[i].base;
+        mdMem.Memory.Rva = dc->rva;
+        mdMem.Memory.DataSize = dc->mem[i].size;
+        SetFilePointer(dc->hFile, dc->rva, NULL, FILE_BEGIN);
+        for (pos = 0; pos < dc->mem[i].size; pos += sizeof(tmp))
+        {
+            len = min(dc->mem[i].size - pos, sizeof(tmp));
+            if (ReadProcessMemory(dc->hProcess, 
+                                  (void*)(ULONG)(dc->mem[i].base + pos), 
+                                  tmp, len, NULL))
+                WriteFile(dc->hFile, tmp, len, &written, NULL);
+        }
+        dc->rva += mdMem.Memory.DataSize;
+        writeat(dc, rva_base + i * sizeof(mdMem), &mdMem, sizeof(mdMem));
+        if (dc->mem[i].rva)
+        {
+            writeat(dc, dc->mem[i].rva, &mdMem.Memory.Rva, sizeof(mdMem.Memory.Rva));
+        }
+    }
+}
+
+static void dump_misc_info(struct dump_context* dc)
+{
+    MINIDUMP_MISC_INFO  mmi;
+
+    mmi.SizeOfInfo = sizeof(mmi);
+    mmi.Flags1 = MINIDUMP_MISC1_PROCESS_ID;
+    mmi.ProcessId = dc->pid;
+    /* FIXME: create/user/kernel time */
+    append(dc, &mmi, sizeof(mmi));
 }
 
 /******************************************************************
@@ -171,28 +621,34 @@
  *
  *
  */
-BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
+BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile,
                               MINIDUMP_TYPE DumpType,
                               PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
                               PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
                               PMINIDUMP_CALLBACK_INFORMATION CallbackParam)
 {
-    struct process*     pcs;
     MINIDUMP_HEADER     mdHead;
     MINIDUMP_DIRECTORY  mdDir;
-    DWORD               currRva, written;
-    DWORD               i, nStream, addStream;
-    RVA                 rva;
+    DWORD               i, nStreams, idx_stream;
+    struct dump_context dc;
 
-    pcs = process_find_by_handle(hProcess);
-    if (!pcs) return FALSE; /* FIXME: should try to load it ??? */
+    dc.hProcess = hProcess;
+    dc.hFile = hFile;
+    dc.pid = pid;
+    dc.module = NULL;
+    dc.num_module = 0;
+    dc.cb = CallbackParam;
+    dc.type = DumpType;
+    dc.mem = NULL;
+    dc.num_mem = 0;
+    dc.rva = 0;
+
+    if (!fetch_process_info(&dc)) return FALSE;
+    fetch_module_info(&dc);
 
     /* 1) init */
-
-    nStream = UserStreamParam ? UserStreamParam->UserStreamCount : 0;
-    addStream = 0;
-    if (DumpType & MiniDumpNormal)
-        addStream += 3; /* sure ? thread stack back trace */
+    nStreams = 6 + (ExceptionParam ? 1 : 0) +
+        (UserStreamParam ? UserStreamParam->UserStreamCount : 0);
 
     if (DumpType & MiniDumpWithDataSegs)
         FIXME("NIY MiniDumpWithDataSegs\n");
@@ -206,61 +662,123 @@
         FIXME("NIY MiniDumpScanMemory\n");
 
     /* 2) write header */
-    rva = sizeof(mdHead);
     mdHead.Signature = MINIDUMP_SIGNATURE;
     mdHead.Version = MINIDUMP_VERSION;
-    mdHead.NumberOfStreams = nStream + addStream;
-    mdHead.StreamDirectoryRva = rva;
+    mdHead.NumberOfStreams = nStreams;
+    mdHead.StreamDirectoryRva = sizeof(mdHead);
     mdHead.u.TimeDateStamp = time(NULL);
     mdHead.Flags = DumpType;
-    WriteFile(hFile, &mdHead, sizeof(mdHead), &written, NULL);
-    
+    append(&dc, &mdHead, sizeof(mdHead));
+
     /* 3) write stream directories */
-    rva += (nStream + addStream) * sizeof(mdDir);
+    dc.rva += nStreams * sizeof(mdDir);
+    idx_stream = 0;
+
     /* 3.1) write data stream directories */
-    currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
-    SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
-    mdDir.StreamType = ModuleListStream;
-    mdDir.Location.Rva = rva;
-    dump_modules(pcs, hFile, &rva);
-    mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
-    SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
-    WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
 
-    currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
-    SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
     mdDir.StreamType = ThreadListStream;
-    mdDir.Location.Rva = rva;
-    dump_threads(pcs, hFile, &rva);
-    mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
-    SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
-    WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
+    mdDir.Location.Rva = dc.rva;
+    dump_threads(&dc);
+    mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+    writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), 
+            &mdDir, sizeof(mdDir));
 
-    currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
-    SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
+    mdDir.StreamType = ModuleListStream;
+    mdDir.Location.Rva = dc.rva;
+    dump_modules(&dc, FALSE);
+    mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+    writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+            &mdDir, sizeof(mdDir));
+
+    mdDir.StreamType = 0xfff0; /* FIXME: this is part of MS reserved streams */
+    mdDir.Location.Rva = dc.rva;
+    dump_modules(&dc, TRUE);
+    mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+    writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+            &mdDir, sizeof(mdDir));
+
+    mdDir.StreamType = MemoryListStream;
+    mdDir.Location.Rva = dc.rva;
+    dump_memory_info(&dc);
+    mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+    writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+            &mdDir, sizeof(mdDir));
+
     mdDir.StreamType = SystemInfoStream;
-    mdDir.Location.Rva = rva;
-    dump_system_info(pcs, hFile, &rva);
-    mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
-    SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
-    WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
+    mdDir.Location.Rva = dc.rva;
+    dump_system_info(&dc);
+    mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+    writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+            &mdDir, sizeof(mdDir));
 
-    /* 3.2) write user define stream */
-    for (i = 0; i < nStream; i++)
+    mdDir.StreamType = MiscInfoStream;
+    mdDir.Location.Rva = dc.rva;
+    dump_misc_info(&dc);
+    mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+    writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+            &mdDir, sizeof(mdDir));
+
+    /* 3.2) write exception information (if any) */
+    if (ExceptionParam)
     {
-        mdDir.StreamType = UserStreamParam->UserStreamArray[i].Type;
-        mdDir.Location.DataSize = UserStreamParam->UserStreamArray[i].BufferSize;
-        mdDir.Location.Rva = rva;
-        WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
-        currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
-        SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
-        WriteFile(hFile, 
-                  UserStreamParam->UserStreamArray[i].Buffer, 
-                  UserStreamParam->UserStreamArray[i].BufferSize, 
-                  &written, NULL);
-        rva += UserStreamParam->UserStreamArray[i].BufferSize;
-        SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
+        mdDir.StreamType = ExceptionStream;
+        mdDir.Location.Rva = dc.rva;
+        dump_exception_info(&dc, ExceptionParam);
+        mdDir.Location.DataSize = dc.rva - mdDir.Location.Rva;
+        writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+                &mdDir, sizeof(mdDir));
     }
 
+    /* 3.3) write user defined streams (if any) */
+    if (UserStreamParam)
+    {
+        for (i = 0; i < UserStreamParam->UserStreamCount; i++)
+        {
+            mdDir.StreamType = UserStreamParam->UserStreamArray[i].Type;
+            mdDir.Location.DataSize = UserStreamParam->UserStreamArray[i].BufferSize;
+            mdDir.Location.Rva = dc.rva;
+            writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir),
+                    &mdDir, sizeof(mdDir));
+            append(&dc, UserStreamParam->UserStreamArray[i].Buffer, 
+                   UserStreamParam->UserStreamArray[i].BufferSize);
+        }
+    }
+
+    HeapFree(GetProcessHeap(), 0, dc.pcs_buffer);
+    HeapFree(GetProcessHeap(), 0, dc.mem);
+    HeapFree(GetProcessHeap(), 0, dc.module);
+
     return TRUE;
 }
+
+/******************************************************************
+ *		MiniDumpReadDumpStream (DEBUGHLP.@)
+ *
+ *
+ */
+BOOL WINAPI MiniDumpReadDumpStream(void* base, ULONG str_idx,
+                                   PMINIDUMP_DIRECTORY* pdir,
+                                   void** stream, ULONG* size)
+{
+    MINIDUMP_HEADER*    mdHead = (MINIDUMP_HEADER*)base;
+
+    if (mdHead->Signature == MINIDUMP_SIGNATURE)
+    {
+        MINIDUMP_DIRECTORY* dir;
+        int                 i;
+
+        dir = (MINIDUMP_DIRECTORY*)((char*)base + mdHead->StreamDirectoryRva);
+        for (i = 0; i < mdHead->NumberOfStreams; i++, dir++)
+        {
+            if (dir->StreamType == str_idx)
+            {
+                *pdir = dir;
+                *stream = (char*)base + dir->Location.Rva;
+                *size = dir->Location.DataSize;
+                return TRUE;
+            }
+        }
+    }
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+}
diff --git a/include/dbghelp.h b/include/dbghelp.h
index 45c64c9..aa7bff3 100644
--- a/include/dbghelp.h
+++ b/include/dbghelp.h
@@ -250,7 +250,7 @@
 
 /* DebugHelp */
 
-#define MINIDUMP_SIGNATURE 0x4D444D50 /* 'PMDM' */
+#define MINIDUMP_SIGNATURE 0x504D444D /* 'MDMP' */
 #define MINIDUMP_VERSION   (42899)
 
 typedef DWORD   RVA;
@@ -258,12 +258,21 @@
 
 typedef enum _MINIDUMP_TYPE 
 {
-    MiniDumpNormal         = 0x0000,
-    MiniDumpWithDataSegs   = 0x0001,
-    MiniDumpWithFullMemory = 0x0002,
-    MiniDumpWithHandleData = 0x0004,
-    MiniDumpFilterMemory   = 0x0008,
-    MiniDumpScanMemory     = 0x0010
+    MiniDumpNormal                              = 0x0000,
+    MiniDumpWithDataSegs                        = 0x0001,
+    MiniDumpWithFullMemory                      = 0x0002,
+    MiniDumpWithHandleData                      = 0x0004,
+    MiniDumpFilterMemory                        = 0x0008,
+    MiniDumpScanMemory                          = 0x0010,
+    MiniDumpWithUnloadedModules                 = 0x0020,
+    MiniDumpWithIndirectlyReferencedMemory      = 0x0040,
+    MiniDumpFilterModulePaths                   = 0x0080,
+    MiniDumpWithProcessThreadData               = 0x0100,
+    MiniDumpWithPrivateReadWriteMemory          = 0x0200,
+    MiniDumpWithoutOptionalData                 = 0x0400,
+    MiniDumpWithFullMemoryInfo                  = 0x0800,
+    MiniDumpWithThreadInfo                      = 0x1000,
+    MiniDumpWithCodeSegs                        = 0x2000
 } MINIDUMP_TYPE;
 
 typedef enum _MINIDUMP_CALLBACK_TYPE
@@ -273,6 +282,7 @@
     ThreadExCallback,
     IncludeThreadCallback,
     IncludeModuleCallback,
+    MemoryCallback,
 } MINIDUMP_CALLBACK_TYPE;
 
 typedef struct _MINIDUMP_THREAD_CALLBACK
@@ -281,7 +291,7 @@
     HANDLE                      ThreadHandle;
     CONTEXT                     Context;
     ULONG                       SizeOfContext;
-    ULONGLONG                   StackBase;
+    ULONG64                     StackBase;
     ULONG64                     StackEnd;
 } MINIDUMP_THREAD_CALLBACK, *PMINIDUMP_THREAD_CALLBACK;
 
@@ -291,10 +301,10 @@
     HANDLE                      ThreadHandle;
     CONTEXT                     Context;
     ULONG                       SizeOfContext;
-    ULONGLONG                   StackBase;
-    ULONGLONG                   StackEnd;
-    ULONGLONG                   BackingStoreBase;
-    ULONGLONG                   BackingStoreEnd;
+    ULONG64                     StackBase;
+    ULONG64                     StackEnd;
+    ULONG64                     BackingStoreBase;
+    ULONG64                     BackingStoreEnd;
 } MINIDUMP_THREAD_EX_CALLBACK, *PMINIDUMP_THREAD_EX_CALLBACK;
 
 typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK
@@ -308,13 +318,15 @@
     ThreadWriteStack             = 0x0002,
     ThreadWriteContext           = 0x0004,
     ThreadWriteBackingStore      = 0x0008,
-    ThreadWriteInstructionWindow = 0x0010
+    ThreadWriteInstructionWindow = 0x0010,
+    ThreadWriteThreadData        = 0x0020,
+    ThreadWriteThreadInfo        = 0x0040
 } THREAD_WRITE_FLAGS;
 
 typedef struct _MINIDUMP_MODULE_CALLBACK 
 {
     PWCHAR                      FullPath;
-    ULONGLONG                   BaseOfImage;
+    ULONG64                     BaseOfImage;
     ULONG                       SizeOfImage;
     ULONG                       CheckSum;
     ULONG                       TimeDateStamp;
@@ -336,7 +348,9 @@
     ModuleWriteDataSeg       = 0x0002,
     ModuleWriteMiscRecord    = 0x0004,
     ModuleWriteCvRecord      = 0x0008,
-    ModuleReferencedByMemory = 0x0010
+    ModuleReferencedByMemory = 0x0010,
+    ModuleWriteTlsData       = 0x0020,
+    ModuleWriteCodeSegs      = 0x0040,
 } MODULE_WRITE_FLAGS;
 
 typedef struct _MINIDUMP_CALLBACK_INPUT 
@@ -351,7 +365,7 @@
         MINIDUMP_MODULE_CALLBACK        Module;
         MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread;
         MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule;
-    } u;
+    } DUMMYUNIONNAME;
 } MINIDUMP_CALLBACK_INPUT, *PMINIDUMP_CALLBACK_INPUT;
 
 typedef struct _MINIDUMP_CALLBACK_OUTPUT
@@ -360,12 +374,15 @@
     {
         ULONG                           ModuleWriteFlags;
         ULONG                           ThreadWriteFlags;
-    } u;
+        struct
+        {
+            ULONG64                     MemoryBase;
+            ULONG                       MemorySize;
+        } DUMMYSTRUCTNAME;
+    } DUMMYUNIONNAME;
 } MINIDUMP_CALLBACK_OUTPUT, *PMINIDUMP_CALLBACK_OUTPUT;
 
-typedef BOOL (WINAPI* MINIDUMP_CALLBACK_ROUTINE)(PVOID CallbackParam,
-                                                 const PMINIDUMP_CALLBACK_INPUT CallbackInput,
-                                                 PMINIDUMP_CALLBACK_OUTPUT CallbackOutput);
+typedef BOOL (WINAPI* MINIDUMP_CALLBACK_ROUTINE)(PVOID, const PMINIDUMP_CALLBACK_INPUT, PMINIDUMP_CALLBACK_OUTPUT);
 
 typedef struct _MINIDUMP_CALLBACK_INFORMATION 
 {
@@ -389,11 +406,11 @@
 {
     ULONG                       ExceptionCode;
     ULONG                       ExceptionFlags;
-    ULONGLONG                   ExceptionRecord;
-    ULONGLONG                   ExceptionAddress;
+    ULONG64                     ExceptionRecord;
+    ULONG64                     ExceptionAddress;
     ULONG                       NumberParameters;
     ULONG                        __unusedAlignment;
-    ULONGLONG                   ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+    ULONG64                     ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
 } MINIDUMP_EXCEPTION, *PMINIDUMP_EXCEPTION;
 
 typedef struct _MINIDUMP_EXCEPTION_INFORMATION
@@ -422,19 +439,38 @@
     {
         DWORD                           Reserved;
         DWORD                           TimeDateStamp;
-    } u;
-    ULONGLONG                   Flags;
+    } DUMMYUNIONNAME;
+    ULONG64                     Flags;
 } MINIDUMP_HEADER, *PMINIDUMP_HEADER;
 
 typedef struct _MINIDUMP_MEMORY_DESCRIPTOR 
 {
-    ULONGLONG                   StartOfMemoryRange;
+    ULONG64                     StartOfMemoryRange;
     MINIDUMP_LOCATION_DESCRIPTOR Memory;
 } MINIDUMP_MEMORY_DESCRIPTOR, *PMINIDUMP_MEMORY_DESCRIPTOR;
 
+typedef struct _MINIDUMP_MEMORY_LIST
+{
+    ULONG                       NumberOfMemoryRanges;
+    MINIDUMP_MEMORY_DESCRIPTOR  MemoryRanges[1]; /* FIXME: 0-sized array not supported */
+} MINIDUMP_MEMORY_LIST, *PMINIDUMP_MEMORY_LIST;
+
+#define MINIDUMP_MISC1_PROCESS_ID       0x00000001
+#define MINIDUMP_MISC1_PROCESS_TIMES    0x00000002
+
+typedef struct _MINIDUMP_MISC_INFO
+{
+    ULONG                       SizeOfInfo;
+    ULONG                       Flags1;
+    ULONG                       ProcessId;
+    ULONG                       ProcessCreateTime;
+    ULONG                       ProcessUserTime;
+    ULONG                       ProcessKernelTime;
+} MINIDUMP_MISC_INFO, *PMINIDUMP_MISC_INFO;
+
 typedef struct _MINIDUMP_MODULE
 {
-    ULONGLONG                   BaseOfImage;
+    ULONG64                     BaseOfImage;
     ULONG                       SizeOfImage;
     ULONG                       CheckSum;
     ULONG                       TimeDateStamp;
@@ -442,8 +478,8 @@
     VS_FIXEDFILEINFO            VersionInfo;
     MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
     MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
-    ULONGLONG                   Reserved0;
-    ULONGLONG                   Reserved1;
+    ULONG64                     Reserved0;
+    ULONG64                     Reserved1;
 } MINIDUMP_MODULE, *PMINIDUMP_MODULE;
 
 typedef struct _MINIDUMP_MODULE_LIST 
@@ -452,6 +488,76 @@
     MINIDUMP_MODULE             Modules[1]; /* FIXME: 0-sized array not supported */
 } MINIDUMP_MODULE_LIST, *PMINIDUMP_MODULE_LIST;
 
+typedef struct _MINIDUMP_STRING
+{
+    ULONG                       Length;
+    WCHAR                       Buffer[1]; /* FIXME: O-sized array not supported */
+} MINIDUMP_STRING, *PMINIDUMP_STRING;
+
+typedef struct _MINIDUMP_SYSTEM_INFO
+{
+    USHORT                      ProcessorArchitecture;
+    USHORT                      ProcessorLevel;
+    USHORT                      ProcessorRevision;
+    union
+    {
+        USHORT                          Reserved0;
+        struct
+        {
+            UCHAR                       NumberOfProcessors;
+            UCHAR                       ProductType;
+        } DUMMYSTRUCTNAME;
+    } DUMMYUNIONNAME;
+
+    ULONG                       MajorVersion;
+    ULONG                       MinorVersion;
+    ULONG                       BuildNumber;
+    ULONG                       PlatformId;
+
+    RVA                         CSDVersionRva;
+    union
+    {
+        ULONG                           Reserved1;
+        struct
+        {
+            USHORT                      SuiteMask;
+            USHORT                      Reserved2;
+        } DUMMYSTRUCTNAME;
+    } DUMMYUNIONNAME1;
+    union _CPU_INFORMATION 
+    {
+        struct 
+        {
+            ULONG                       VendorId[3];
+            ULONG                       VersionInformation;
+            ULONG                       FeatureInformation;
+            ULONG                       AMDExtendedCpuFeatures;
+        } X86CpuInfo;
+        struct 
+        {
+            ULONG64                     ProcessorFeatures[2];
+        } OtherCpuInfo;
+    } Cpu;
+
+} MINIDUMP_SYSTEM_INFO, *PMINIDUMP_SYSTEM_INFO;
+
+typedef struct _MINIDUMP_THREAD
+{
+    ULONG                       ThreadId;
+    ULONG                       SuspendCount;
+    ULONG                       PriorityClass;
+    ULONG                       Priority;
+    ULONG64                     Teb;
+    MINIDUMP_MEMORY_DESCRIPTOR  Stack;
+    MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
+} MINIDUMP_THREAD, *PMINIDUMP_THREAD;
+
+typedef struct _MINIDUMP_THREAD_LIST
+{
+    ULONG                       NumberOfThreads;
+    MINIDUMP_THREAD             Threads[1]; /* FIXME: no support of 0 sized array */
+} MINIDUMP_THREAD_LIST, *PMINIDUMP_THREAD_LIST;
+
 typedef struct _MINIDUMP_USER_STREAM
 {
     ULONG                       Type;
@@ -481,61 +587,20 @@
     CommentStreamW              = 11,
     HandleDataStream            = 12,
     FunctionTableStream         = 13,
+    UnloadedModuleListStream    = 14,
+    MiscInfoStream              = 15,
+    MemoryInfoListStream        = 16,
+    ThreadInfoListStream        = 17,
 
     LastReservedStream          = 0xffff
 } MINIDUMP_STREAM_TYPE;
 
-typedef struct _MINIDUMP_SYSTEM_INFO
-{
-    USHORT                      ProcessorArchitecture;
-    USHORT                      ProcessorLevel;
-    USHORT                      ProcessorRevision;
-    USHORT                      Reserved0;
-
-    ULONG                       MajorVersion;
-    ULONG                       MinorVersion;
-    ULONG                       BuildNumber;
-    ULONG                       PlatformId;
-
-    RVA                         CSDVersionRva;
-    ULONG                       Reserved1;
-    union _CPU_INFORMATION 
-    {
-        struct 
-        {
-            ULONG                       VendorId[3];
-            ULONG                       VersionInformation;
-            ULONG                       FeatureInformation;
-            ULONG                       AMDExtendedCpuFeatures;
-        } X86CpuInfo;
-        struct 
-        {
-            ULONGLONG                   ProcessorFeatures[2];
-        } OtherCpuInfo;
-    } Cpu;
-
-} MINIDUMP_SYSTEM_INFO, *PMINIDUMP_SYSTEM_INFO;
-
-typedef struct _MINIDUMP_THREAD
-{
-    ULONG                       ThreadId;
-    ULONG                       SuspendCount;
-    ULONG                       PriorityClass;
-    ULONG                       Priority;
-    ULONGLONG                   Teb;
-    MINIDUMP_MEMORY_DESCRIPTOR  Stack;
-    MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
-} MINIDUMP_THREAD, *PMINIDUMP_THREAD;
-
-typedef struct _MINIDUMP_THREAD_LIST
-{
-    ULONG                       NumberOfThreads;
-    MINIDUMP_THREAD             Threads[1]; /* FIXME: no support of 0 sized array */
-} MINIDUMP_THREAD_LIST, *PMINIDUMP_THREAD_LIST;
-
-BOOL WINAPI MiniDumpWriteDump(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,const PMINIDUMP_EXCEPTION_INFORMATION,
-                              const PMINIDUMP_USER_STREAM_INFORMATION,const PMINIDUMP_CALLBACK_INFORMATION);
-BOOL WINAPI MiniDumpReadDumpStream(PVOID,ULONG,PMINIDUMP_DIRECTORY*,PVOID*,ULONG*);
+BOOL WINAPI MiniDumpWriteDump(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
+                              const PMINIDUMP_EXCEPTION_INFORMATION,
+                              const PMINIDUMP_USER_STREAM_INFORMATION,
+                              const PMINIDUMP_CALLBACK_INFORMATION);
+BOOL WINAPI MiniDumpReadDumpStream(PVOID, ULONG, PMINIDUMP_DIRECTORY*, PVOID*,
+                                   ULONG*);
 
 
 /*************************