Created dump.c as a central point for file dumping (includes header
analysis, utility funcs...).
Added support for dumping minidump files.

diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in
index 1f82fd7..18aac73 100644
--- a/tools/winedump/Makefile.in
+++ b/tools/winedump/Makefile.in
@@ -10,16 +10,18 @@
 
 C_SRCS = \
 	debug.c \
+	dump.c \
 	emf.c \
 	le.c \
 	lnk.c \
-	main.c  \
-	misc.c  \
-	msmangle.c  \
+	main.c \
+	minidump.c \
+	misc.c \
+	msmangle.c \
 	ne.c \
-	output.c  \
+	output.c \
 	pe.c \
-	search.c  \
+	search.c \
 	symbol.c
 
 all: $(PROGRAMS)
diff --git a/tools/winedump/debug.c b/tools/winedump/debug.c
index 0df9cf5..4eb67869 100644
--- a/tools/winedump/debug.c
+++ b/tools/winedump/debug.c
@@ -99,8 +99,6 @@
  *    (OMFDirHeader.cDir)
  */
 
-extern void			*PE_base;
-
 extern IMAGE_NT_HEADERS*        PE_nt_headers;
 
 static	void*		cv_base /* = 0 */;
@@ -509,14 +507,14 @@
    return nampnt;
 }
 
-void	dump_coff(unsigned long coffbase, unsigned long len)
+void	dump_coff(unsigned long coffbase, unsigned long len, void* pmt)
 {
     PIMAGE_COFF_SYMBOLS_HEADER coff;
     PIMAGE_SYMBOL                 coff_sym;
     PIMAGE_SYMBOL                 coff_symbols;
     PIMAGE_LINENUMBER             coff_linetab;
     char                        * coff_strtab;
-    IMAGE_SECTION_HEADER *sectHead = (IMAGE_SECTION_HEADER*)((char*)PE_nt_headers + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader);
+    IMAGE_SECTION_HEADER        * sectHead = pmt;
     unsigned int i;
     const char                  * nampnt;
     int naux;
@@ -527,9 +525,9 @@
     coff_linetab = (PIMAGE_LINENUMBER) ((unsigned int) coff + coff->LvaToFirstLinenumber);
     coff_strtab = (char *) (coff_symbols + coff->NumberOfSymbols);
 
-    printf("\nDebug table: COFF format. modbase %p, coffbase %p\n", PE_base, coff);
+    printf("\nDebug table: COFF format. modbase %p, coffbase %p\n", PRD(0, 0), coff);
     printf("  ID  | seg:offs    [  abs   ] | symbol/function name\n");
-  for(i=0; i < coff->NumberOfSymbols; i++ )
+    for(i=0; i < coff->NumberOfSymbols; i++ )
     {
       coff_sym = coff_symbols + i;
       naux = coff_sym->NumberOfAuxSymbols;
diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c
new file mode 100644
index 0000000..4a269ab
--- /dev/null
+++ b/tools/winedump/dump.c
@@ -0,0 +1,297 @@
+/*
+ *	File dumping utility
+ *
+ * 	Copyright 2001,2005 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <time.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <fcntl.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winedump.h"
+#include "pe.h"
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+static void*			dump_base;
+static unsigned long		dump_total_len;
+
+void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix )
+{
+    unsigned int i, j;
+
+    printf( "%s", prefix );
+    if (!ptr)
+    {
+        printf("NULL\n");
+        return;
+    }
+    for (i = 0; i < size; i++)
+    {
+        printf( "%02x%c", ptr[i], (i % 16 == 7) ? '-' : ' ' );
+        if ((i % 16) == 15)
+        {
+            printf( " " );
+            for (j = 0; j < 16; j++)
+                printf( "%c", isprint(ptr[i-15+j]) ? ptr[i-15+j] : '.' );
+            if (i < size-1) printf( "\n%s", prefix );
+        }
+    }
+    if (i % 16)
+    {
+        printf( "%*s ", 3 * (16-(i%16)), "" );
+        for (j = 0; j < i % 16; j++)
+            printf( "%c", isprint(ptr[i-(i%16)+j]) ? ptr[i-(i%16)+j] : '.' );
+    }
+    printf( "\n" );
+}
+
+const char*	get_time_str(DWORD _t)
+{
+    time_t 	t = (time_t)_t;
+    static char	buf[128];
+
+    /* FIXME: I don't get the same values from MS' pedump running under Wine...
+     * I wonder if Wine isn't broken wrt to GMT settings...
+     */
+    strncpy(buf, ctime(&t), sizeof(buf));
+    buf[sizeof(buf) - 1] = '\0';
+    if (buf[strlen(buf)-1] == '\n')
+	buf[strlen(buf)-1] = '\0';
+    return buf;
+}
+
+unsigned int strlenW( const WCHAR *str )
+{
+    const WCHAR *s = str;
+    while (*s) s++;
+    return s - str;
+}
+
+void dump_unicode_str( const WCHAR *str, int len )
+{
+    if (len == -1) len = strlenW( str );
+    printf( "L\"");
+    while (len-- > 0 && *str)
+    {
+        WCHAR c = *str++;
+        switch (c)
+        {
+        case '\n': printf( "\\n" ); break;
+        case '\r': printf( "\\r" ); break;
+        case '\t': printf( "\\t" ); break;
+        case '"':  printf( "\\\"" ); break;
+        case '\\': printf( "\\\\" ); break;
+        default:
+            if (c >= ' ' && c <= 126) putchar(c);
+            else printf( "\\u%04x",c);
+        }
+    }
+    printf( "\"" );
+}
+
+void*	PRD(unsigned long prd, unsigned long len)
+{
+    return (prd + len > dump_total_len) ? NULL : (char*)dump_base + prd;
+}
+
+unsigned long Offset(void* ptr)
+{
+    if (ptr < dump_base) {printf("<<<<<ptr below\n");return 0;}
+    if ((char *)ptr >= (char*)dump_base + dump_total_len) {printf("<<<<<ptr above\n");return 0;}
+    return (char*)ptr - (char*)dump_base;
+}
+
+static	void	do_dump( enum FileSig sig, void* pmt )
+{
+    if (sig == SIG_NE)
+    {
+        ne_dump( dump_base, dump_total_len );
+        return;
+    }
+
+    if (sig == SIG_LE)
+    {
+        le_dump( dump_base, dump_total_len );
+        return;
+    }
+
+    pe_dump(pmt);
+}
+
+static	enum FileSig	check_headers(void** pmt)
+{
+    WORD*		pw;
+    DWORD*		pdw;
+    IMAGE_DOS_HEADER*	dh;
+    enum FileSig	sig;
+
+    pw = PRD(0, sizeof(WORD));
+    if (!pw) {printf("Can't get main signature, aborting\n"); return 0;}
+
+    *pmt = NULL;
+    switch (*pw)
+    {
+    case IMAGE_DOS_SIGNATURE:
+	sig = SIG_DOS;
+	dh = PRD(0, sizeof(IMAGE_DOS_HEADER));
+	if (dh && dh->e_lfanew >= sizeof(*dh)) /* reasonable DOS header ? */
+	{
+	    /* the signature is the first DWORD */
+	    pdw = PRD(dh->e_lfanew, sizeof(DWORD));
+	    if (pdw)
+	    {
+		if (*pdw == IMAGE_NT_SIGNATURE)
+		{
+		    *pmt = PRD(dh->e_lfanew, sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER));
+		    sig = SIG_PE;
+		}
+                else if (*(WORD *)pdw == IMAGE_OS2_SIGNATURE)
+                {
+                    sig = SIG_NE;
+                }
+		else if (*(WORD *)pdw == IMAGE_VXD_SIGNATURE)
+		{
+                    sig = SIG_LE;
+		}
+		else
+		{
+		    printf("No PE Signature found\n");
+		}
+	    }
+	    else
+	    {
+		printf("Can't get the extented signature, aborting\n");
+	    }
+	}
+	break;
+    case 0x4944: /* "DI" */
+	sig = SIG_DBG;
+	break;
+    case 0x444D: /* "MD" */
+        pdw = PRD(0, sizeof(DWORD));
+        if (pdw && *pdw == 0x504D444D) /* "MDMP" */
+            sig = SIG_MDMP;
+        else
+            sig = SIG_UNKNOWN;
+        break;
+    default:
+	printf("No known main signature (%.2s/%x), aborting\n", (char*)pw, *pw);
+	sig = SIG_UNKNOWN;
+    }
+
+    return sig;
+}
+
+int dump_analysis(const char* name, void (*fn)(enum FileSig, void*), enum FileSig wanted_sig)
+{
+    int			fd;
+    enum FileSig	effective_sig;
+    int			ret = 1;
+    struct stat		s;
+    void*               pmt;
+
+    setbuf(stdout, NULL);
+
+    fd = open(name, O_RDONLY | O_BINARY);
+    if (fd == -1) fatal("Can't open file");
+
+    if (fstat(fd, &s) < 0) fatal("Can't get size");
+    dump_total_len = s.st_size;
+
+#ifdef HAVE_MMAP
+    if ((dump_base = mmap(NULL, dump_total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
+#endif
+    {
+        if (!(dump_base = malloc( dump_total_len ))) fatal( "Out of memory" );
+        if ((unsigned long)read( fd, dump_base, dump_total_len ) != dump_total_len) fatal( "Cannot read file" );
+    }
+
+    effective_sig = check_headers(&pmt);
+
+    if (effective_sig == SIG_UNKNOWN)
+    {
+	printf("Can't get a recognized file signature, aborting\n");
+	ret = 0;
+    }
+    else if (wanted_sig == SIG_UNKNOWN || wanted_sig == effective_sig)
+    {
+	switch (effective_sig)
+	{
+	case SIG_UNKNOWN: /* shouldn't happen... */
+	    ret = 0; break;
+	case SIG_PE:
+	case SIG_NE:
+	case SIG_LE:
+	    printf("Contents of \"%s\": %ld bytes\n\n", name, dump_total_len);
+	    (*fn)(effective_sig, pmt);
+	    break;
+	case SIG_DBG:
+	    dump_separate_dbg();
+	    break;
+	case SIG_DOS:
+	    ret = 0; break;
+        case SIG_MDMP:
+            mdmp_dump();
+            break;
+	}
+    }
+    else
+    {
+	printf("Can't get a suitable file signature, aborting\n");
+	ret = 0;
+    }
+
+    if (ret) printf("Done dumping %s\n", name);
+#ifdef HAVE_MMAP
+    if (munmap(dump_base, dump_total_len) == -1)
+#endif
+    {
+        free( dump_base );
+    }
+    close(fd);
+
+    return ret;
+}
+
+void	dump_file(const char* name)
+{
+    dump_analysis(name, do_dump, SIG_UNKNOWN);
+}
diff --git a/tools/winedump/minidump.c b/tools/winedump/minidump.c
new file mode 100644
index 0000000..fa11b8b
--- /dev/null
+++ b/tools/winedump/minidump.c
@@ -0,0 +1,372 @@
+/*
+ *	MiniDump dumping utility
+ *
+ * 	Copyright 2005 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winver.h"
+#include "dbghelp.h"
+#include "winedump.h"
+
+static void dump_mdmp_data(const MINIDUMP_LOCATION_DESCRIPTOR* md, const char* pfx)
+{
+    if (md->DataSize)
+        dump_data(PRD(md->Rva, md->DataSize), md->DataSize, pfx);
+}
+
+static void dump_mdmp_string(DWORD rva)
+{
+    MINIDUMP_STRING*    ms = PRD(rva, sizeof(MINIDUMP_STRING));
+    if (ms)
+        dump_unicode_str( ms->Buffer, ms->Length / sizeof(WCHAR) );
+    else
+        printf("<<?>>");
+}
+
+static MINIDUMP_DIRECTORY* get_mdmp_dir(const MINIDUMP_HEADER* hdr, int str_idx)
+{
+    MINIDUMP_DIRECTORY* dir;
+    int                 i;
+
+    for (i = 0; i < hdr->NumberOfStreams; i++)
+    {
+        dir = PRD(hdr->StreamDirectoryRva + i * sizeof(MINIDUMP_DIRECTORY), 
+                  sizeof(MINIDUMP_DIRECTORY));
+        if (!dir) continue;
+        if (dir->StreamType == str_idx) return dir;
+    }
+    return NULL;
+}
+
+void mdmp_dump(void)
+{
+    MINIDUMP_HEADER*        hdr = (MINIDUMP_HEADER*)PRD(0, sizeof(MINIDUMP_HEADER));
+    ULONG                   idx, ndir = 0;
+    MINIDUMP_DIRECTORY*     dir;
+    void*                   stream;
+
+    if (!hdr)
+    {
+        printf("Cannot get Minidump header\n");
+        return;
+    }
+
+    printf("Signature: %lu (%.4s)\n", hdr->Signature, (char*)&hdr->Signature);
+    printf("Version: %lx\n", hdr->Version);
+    printf("NumberOfStreams: %lu\n", hdr->NumberOfStreams);
+    printf("StreamDirectoryRva: %lu\n", hdr->StreamDirectoryRva);
+    printf("CheckSum: %lu\n", hdr->CheckSum);
+    printf("TimeDateStamp: %s\n", get_time_str(hdr->u.TimeDateStamp));
+    printf("Flags: %llx\n", hdr->Flags);
+
+    for (idx = 0; idx <= LastReservedStream; idx++)
+    {
+        if (!(dir = get_mdmp_dir(hdr, idx))) continue;
+
+        stream = PRD(dir->Location.Rva, dir->Location.DataSize);
+        printf("Directory [%lu]: ", ndir++);
+        switch (dir->StreamType)
+        {
+        case ThreadListStream:
+        {
+            MINIDUMP_THREAD_LIST*   mtl = (MINIDUMP_THREAD_LIST*)stream;
+            MINIDUMP_THREAD*        mt = &mtl->Threads[0];
+            int                     i;
+
+            printf("Threads: %lu\n", mtl->NumberOfThreads);
+            for (i = 0; i < mtl->NumberOfThreads; i++, mt++)
+            {
+                printf("  Thread: #%d\n", i);
+                printf("    ThreadId: %lu\n", mt->ThreadId);
+                printf("    SuspendCount: %lu\n", mt->SuspendCount);
+                printf("    PriorityClass: %lu\n", mt->PriorityClass);
+                printf("    Priority: %lu\n", mt->Priority);
+                printf("    Teb: 0x%llx\n", mt->Teb);
+                printf("    Stack: 0x%llx-0x%llx\n", 
+                       mt->Stack.StartOfMemoryRange, 
+                       mt->Stack.StartOfMemoryRange + mt->Stack.Memory.DataSize);
+                dump_mdmp_data(&mt->Stack.Memory, "      ");
+                printf("    ThreadContext:\n");
+                dump_mdmp_data(&mt->ThreadContext, "      ");
+            }
+        }
+        break;
+        case ModuleListStream:
+        case 0xFFF0:
+        {
+            MINIDUMP_MODULE_LIST*   mml = (MINIDUMP_MODULE_LIST*)stream;
+            MINIDUMP_MODULE*        mm = &mml->Modules[0];
+            int                     i;
+            const char*             p1;
+            const char*             p2;
+
+            printf("Modules (%s): %lu\n",
+                   dir->StreamType == ModuleListStream ? "PE" : "ELF",
+                   mml->NumberOfModules);
+            for (i = 0; i < mml->NumberOfModules; i++, mm++)
+            {
+                printf("  Module #%d:\n", i);
+                printf("    BaseOfImage: 0x%llx\n", mm->BaseOfImage);
+                printf("    SizeOfImage: %lu\n", mm->SizeOfImage);
+                printf("    CheckSum: %lu\n", mm->CheckSum);
+                printf("    TimeDateStamp: %s\n", get_time_str(mm->TimeDateStamp));
+                printf("    ModuleName: ");
+                dump_mdmp_string(mm->ModuleNameRva);
+                printf("\n");
+                printf("    VersionInfo:\n");
+                printf("      dwSignature: %lx\n", mm->VersionInfo.dwSignature);
+                printf("      dwStrucVersion: %lx\n", 
+                       mm->VersionInfo.dwStrucVersion);
+                printf("      dwFileVersion: %d,%d,%d,%d\n", 
+                       HIWORD(mm->VersionInfo.dwFileVersionMS),
+                       LOWORD(mm->VersionInfo.dwFileVersionMS),
+                       HIWORD(mm->VersionInfo.dwFileVersionLS),
+                       LOWORD(mm->VersionInfo.dwFileVersionLS));
+                printf("      dwProductVersion %d,%d,%d,%d\n",
+                       HIWORD(mm->VersionInfo.dwProductVersionMS),
+                       LOWORD(mm->VersionInfo.dwProductVersionMS),
+                       HIWORD(mm->VersionInfo.dwProductVersionLS),
+                       LOWORD(mm->VersionInfo.dwProductVersionLS));
+                printf("      dwFileFlagsMask: %lu\n", 
+                       mm->VersionInfo.dwFileFlagsMask);
+                printf("      dwFileFlags: %s%s%s%s%s%s\n", 
+                       mm->VersionInfo.dwFileFlags & VS_FF_DEBUG ? "Debug " : "",
+                       mm->VersionInfo.dwFileFlags & VS_FF_INFOINFERRED ? "Inferred " : "",
+                       mm->VersionInfo.dwFileFlags & VS_FF_PATCHED ? "Patched " : "",
+                       mm->VersionInfo.dwFileFlags & VS_FF_PRERELEASE ? "PreRelease " : "",
+                       mm->VersionInfo.dwFileFlags & VS_FF_PRIVATEBUILD ? "PrivateBuild " : "",
+                       mm->VersionInfo.dwFileFlags & VS_FF_SPECIALBUILD ? "SpecialBuild " : "");
+                if (mm->VersionInfo.dwFileOS)
+                {
+                    switch (mm->VersionInfo.dwFileOS & 0x000F)
+                    {
+                    case VOS__BASE:     p1 = "_base"; break;
+                    case VOS__WINDOWS16:p1 = "16 bit Windows"; break;
+                    case VOS__PM16:     p1 = "16 bit Presentation Manager"; break;
+                    case VOS__PM32:     p1 = "32 bit Presentation Manager"; break;
+                    case VOS__WINDOWS32:p1 = "32 bit Windows"; break;
+                    default:            p1 = "---"; break;
+                    }
+                    switch (mm->VersionInfo.dwFileOS & 0xF0000)
+                    {
+                    case VOS_UNKNOWN:   p2 = "unknown"; break;
+                    case VOS_DOS:       p2 = "DOS"; break;
+                    case VOS_OS216:     p2 = "16 bit OS/2"; break;
+                    case VOS_OS232:     p2 = "32 bit OS/2"; break;
+                    case VOS_NT:        p2 = "Windows NT"; break;
+                    default:            p2 = "---"; break;
+                    }
+                    printf("      dwFileOS: %s running on %s\n", p1, p2);
+                }
+                else printf("      dwFileOS: 0\n");
+                switch (mm->VersionInfo.dwFileType)
+                {
+                case VFT_UNKNOWN:       p1 = "Unknown"; break;
+                case VFT_APP:           p1 = "Application"; break;
+                case VFT_DLL:           p1 = "DLL"; break;
+                case VFT_DRV:           p1 = "Driver"; break;
+                case VFT_FONT:          p1 = "Font"; break;
+                case VFT_VXD:           p1 = "VxD"; break;
+                case VFT_STATIC_LIB:    p1 = "Static Library"; break;
+                default:                p1 = "---"; break;
+                }
+                printf("      dwFileType: %s\n", p1);
+                printf("      dwFileSubtype: %lu\n",
+                       mm->VersionInfo.dwFileSubtype);
+                printf("      dwFileDate: %lx%08lx\n",
+                       mm->VersionInfo.dwFileDateMS, mm->VersionInfo.dwFileDateLS);
+                printf("    CvRecord: <%lu>\n", mm->CvRecord.DataSize);
+                dump_mdmp_data(&mm->CvRecord, "      ");
+                printf("    MiscRecord: <%lu>\n", mm->MiscRecord.DataSize);
+                dump_mdmp_data(&mm->MiscRecord, "      ");
+                printf("    Reserved0: %llu\n", mm->Reserved0);
+                printf("    Reserved1: %llu\n", mm->Reserved1);
+            }
+        }       
+        break;
+        case MemoryListStream:
+        {
+            MINIDUMP_MEMORY_LIST*   mml = (MINIDUMP_MEMORY_LIST*)stream;
+            MINIDUMP_MEMORY_DESCRIPTOR* mmd = &mml->MemoryRanges[0];
+            int                     i;
+
+            printf("Memory Ranges: %lu\n", mml->NumberOfMemoryRanges);
+            for (i = 0; i < mml->NumberOfMemoryRanges; i++, mmd++)
+            {
+                printf("  Memory Range #%d:\n", i);
+                printf("    Range: 0x%llx-0x%llx\n",
+                       mmd->StartOfMemoryRange, 
+                       mmd->StartOfMemoryRange + mmd->Memory.DataSize);
+                dump_mdmp_data(&mmd->Memory, "      ");
+            }   
+        }
+        break;
+        case SystemInfoStream:
+        {
+            MINIDUMP_SYSTEM_INFO*       msi = (MINIDUMP_SYSTEM_INFO*)stream;
+            char*                       str;
+            char                        tmp[128];
+
+            printf("System Information:\n");
+            switch (msi->ProcessorArchitecture)
+            {
+            case PROCESSOR_ARCHITECTURE_UNKNOWN: 
+                str = "Unknown";
+                break;
+            case PROCESSOR_ARCHITECTURE_INTEL:
+                strcpy(tmp, "Intel ");
+                switch (msi->ProcessorLevel)
+                {
+                case 3: str = "80386"; break;
+                case 4: str = "80486"; break;
+                case 5: str = "Pentium"; break;
+                case 6: str = "Pentium Pro/II"; break;
+                default: str = "???"; break;
+                }
+                strcat(tmp, str);
+                if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4)
+                {
+                    if (HIWORD(msi->ProcessorRevision) == 0xFF)
+                        sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIBYTE(LOWORD(msi->ProcessorRevision)), LOBYTE(LOWORD(msi->ProcessorRevision)));
+                    else
+                        sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision));
+                }
+                else sprintf(tmp + strlen(tmp), "-%d.%d", HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision));
+                str = tmp;
+                break;
+            case PROCESSOR_ARCHITECTURE_MIPS:
+                str = "Mips";
+                break;
+            case PROCESSOR_ARCHITECTURE_ALPHA:
+                str = "Alpha";
+                break;
+            case PROCESSOR_ARCHITECTURE_PPC:
+                str = "PowerPC";
+                break;
+            default:
+                str = "???";
+                break;
+            }
+            printf("  Processor: %s (#%d CPUs)\n", str, msi->u.s.NumberOfProcessors);
+            switch (msi->MajorVersion)
+            {
+            case 3:
+                switch (msi->MinorVersion)
+                {
+                case 51: str = "NT 3.51"; break;
+                default: str = "3-????"; break;
+                }
+                break;
+            case 4:
+                switch (msi->MinorVersion)
+                {
+                case 0: str = (msi->PlatformId == VER_PLATFORM_WIN32_NT) ? "NT 4.0" : "95"; break;
+                case 10: str = "98"; break;
+                case 90: str = "ME"; break;
+                default: str = "5-????"; break;
+                }
+                break;
+            case 5:
+                switch (msi->MinorVersion)
+                {
+                case 0: str = "2000"; break;
+                case 1: str = "XP"; break;
+                case 2: str = "Server 2003"; break;
+                default: str = "5-????"; break;
+                }
+                break;
+            default: str = "???"; break;
+            }
+            printf("  Version: Windows %s (%lu)\n", str, msi->BuildNumber);
+            printf("  PlatformId: %lu\n", msi->PlatformId);
+            printf("  CSD: ");
+            dump_mdmp_string(msi->CSDVersionRva);
+            printf("\n");
+            printf("  Reserved1: %lu\n", msi->u1.Reserved1);
+            if (msi->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+            {
+                printf("  x86.VendorId: %.12s\n", 
+                       (char*)&msi->Cpu.X86CpuInfo.VendorId[0]);
+                printf("  x86.VersionInformation: %lx\n", 
+                       msi->Cpu.X86CpuInfo.VersionInformation);
+                printf("  x86.FeatureInformation: %lx\n", 
+                       msi->Cpu.X86CpuInfo.FeatureInformation);
+                printf("  x86.AMDExtendedCpuFeatures: %lu\n", 
+                       msi->Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
+            }
+        }
+        break;
+        case MiscInfoStream:
+        {
+            MINIDUMP_MISC_INFO* mmi = (MINIDUMP_MISC_INFO*)stream;
+            printf("Misc Information\n");
+            printf("  Size: %lu\n", mmi->SizeOfInfo);
+            printf("  Flags: %s%s\n", 
+                   mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID ? "ProcessId " : "",
+                   mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES ? "ProcessTimes " : "");
+            if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID)
+                printf("  ProcessId: %lu\n", mmi->ProcessId);
+            if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES)
+            {
+                printf("  ProcessCreateTime: %lu\n", mmi->ProcessCreateTime);
+                printf("  ProcessUserTime: %lu\n", mmi->ProcessUserTime);
+                printf("  ProcessKernelTime: %lu\n", mmi->ProcessKernelTime);
+            }
+        }
+        break;
+        case ExceptionStream:
+        {
+            MINIDUMP_EXCEPTION_STREAM*  mes = (MINIDUMP_EXCEPTION_STREAM*)stream;
+            int                         i;
+
+            printf("Exception:\n");
+            printf("  ThreadId: %08lx\n", mes->ThreadId);
+            printf("  ExceptionRecord:\n");
+            printf("  ExceptionCode: %lu\n", mes->ExceptionRecord.ExceptionCode);
+            printf("  ExceptionFlags: %lu\n", mes->ExceptionRecord.ExceptionFlags);
+            printf("  ExceptionRecord: 0x%llx\n", 
+                   mes->ExceptionRecord.ExceptionRecord);
+            printf("  ExceptionAddress: 0x%llx\n",
+                   mes->ExceptionRecord.ExceptionAddress);
+            printf("  ExceptionNumberParameters: %lu\n",
+                   mes->ExceptionRecord.NumberParameters);
+            for (i = 0; i < mes->ExceptionRecord.NumberParameters; i++)
+            {
+                printf("    [%d]: 0x%llx\n", i, 
+                       mes->ExceptionRecord.ExceptionInformation[i]);
+            }
+            printf("  ThreadContext:\n");
+            dump_mdmp_data(&mes->ThreadContext, "    ");
+        }
+        break;
+
+        default:
+            printf("NIY %ld\n", dir->StreamType);
+            printf("  RVA: %lu\n", dir->Location.Rva);
+            printf("  Size: %lu\n", dir->Location.DataSize);
+            dump_mdmp_data(&dir->Location, "  ");
+            break;
+        }
+    }
+}
diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c
index f6f2a7c..062eafe 100644
--- a/tools/winedump/pe.c
+++ b/tools/winedump/pe.c
@@ -46,37 +46,7 @@
 #include "winedump.h"
 #include "pe.h"
 
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-void*			PE_base;
-unsigned long		PE_total_len;
-IMAGE_NT_HEADERS*	PE_nt_headers;
-
-enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_NE, SIG_LE};
-
-static inline unsigned int strlenW( const WCHAR *str )
-{
-    const WCHAR *s = str;
-    while (*s) s++;
-    return s - str;
-}
-
-char*	get_time_str(DWORD _t)
-{
-    time_t 	t = (time_t)_t;
-    static char	buf[128];
-
-    /* FIXME: I don't get the same values from MS' pedump running under Wine...
-     * I wonder if Wine isn't broken wrt to GMT settings...
-     */
-    strncpy(buf, ctime(&t), sizeof(buf));
-    buf[sizeof(buf) - 1] = '\0';
-    if (buf[strlen(buf)-1] == '\n')
-	buf[strlen(buf)-1] = '\0';
-    return buf;
-}
+static IMAGE_NT_HEADERS*	PE_nt_headers;
 
 static	const char* get_machine_str(DWORD mach)
 {
@@ -94,18 +64,6 @@
     return "???";
 }
 
-void*	PRD(unsigned long prd, unsigned long len)
-{
-    return (prd + len > PE_total_len) ? NULL : (char*)PE_base + prd;
-}
-
-unsigned long Offset(void* ptr)
-{
-    if (ptr < PE_base) {printf("<<<<<ptr below\n");return 0;}
-    if ((char *)ptr >= (char*)PE_base + PE_total_len) {printf("<<<<<ptr above\n");return 0;}
-    return (char*)ptr - (char*)PE_base;
-}
-
 static void*	RVA(unsigned long rva, unsigned long len)
 {
     IMAGE_SECTION_HEADER*	sectHead;
@@ -515,7 +473,8 @@
     case IMAGE_DEBUG_TYPE_UNKNOWN:
 	break;
     case IMAGE_DEBUG_TYPE_COFF:
-	dump_coff(idd->PointerToRawData, idd->SizeOfData);
+	dump_coff(idd->PointerToRawData, idd->SizeOfData, 
+                  (char*)PE_nt_headers + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader);
 	break;
     case IMAGE_DEBUG_TYPE_CODEVIEW:
 	dump_codeview(idd->PointerToRawData, idd->SizeOfData);
@@ -597,7 +556,7 @@
     printf(" }\n\n");
 }
 
-static void	dump_separate_dbg(void)
+void	dump_separate_dbg(void)
 {
     IMAGE_SEPARATE_DEBUG_HEADER*separateDebugHead = PRD(0, sizeof(separateDebugHead));
     unsigned			nb_dbg;
@@ -643,28 +602,6 @@
     }
 }
 
-static void dump_unicode_str( const WCHAR *str, int len )
-{
-    if (len == -1) for (len = 0; str[len]; len++) ;
-    printf( "L\"");
-    while (len-- > 0 && *str)
-    {
-        WCHAR c = *str++;
-        switch (c)
-        {
-        case '\n': printf( "\\n" ); break;
-        case '\r': printf( "\\r" ); break;
-        case '\t': printf( "\\t" ); break;
-        case '"':  printf( "\\\"" ); break;
-        case '\\': printf( "\\\\" ); break;
-        default:
-            if (c >= ' ' && c <= 126) putchar(c);
-            else printf( "\\u%04x",c);
-        }
-    }
-    printf( "\"" );
-}
-
 static const char *get_resource_type( unsigned int id )
 {
     static const char *types[] =
@@ -699,36 +636,6 @@
     return NULL;
 }
 
-void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix )
-{
-    unsigned int i, j;
-
-    printf( "%s", prefix );
-    if (!ptr)
-    {
-        printf("NULL\n");
-        return;
-    }
-    for (i = 0; i < size; i++)
-    {
-        printf( "%02x%c", ptr[i], (i % 16 == 7) ? '-' : ' ' );
-        if ((i % 16) == 15)
-        {
-            printf( " " );
-            for (j = 0; j < 16; j++)
-                printf( "%c", isprint(ptr[i-15+j]) ? ptr[i-15+j] : '.' );
-            if (i < size-1) printf( "\n%s", prefix );
-        }
-    }
-    if (i % 16)
-    {
-        printf( "%*s ", 3 * (16-(i%16)), "" );
-        for (j = 0; j < i % 16; j++)
-            printf( "%c", isprint(ptr[i-(i%16)+j]) ? ptr[i-(i%16)+j] : '.' );
-    }
-    printf( "\n" );
-}
-
 /* dump an ASCII string with proper escaping */
 static int dump_strA( const unsigned char *str, size_t len )
 {
@@ -944,22 +851,11 @@
     printf( "\n\n" );
 }
 
-static	void	do_dump( enum FileSig sig )
+void pe_dump(void* pmt)
 {
     int	all = (globals.dumpsect != NULL) && strcmp(globals.dumpsect, "ALL") == 0;
 
-    if (sig == SIG_NE)
-    {
-        ne_dump( PE_base, PE_total_len );
-        return;
-    }
-
-    if (sig == SIG_LE)
-    {
-        le_dump( PE_base, PE_total_len );
-        return;
-    }
-
+    PE_nt_headers = pmt;
     if (globals.do_dumpheader)
     {
 	dump_pe_header();
@@ -994,142 +890,6 @@
     }
 }
 
-static	enum FileSig	check_headers(void)
-{
-    WORD*		pw;
-    DWORD*		pdw;
-    IMAGE_DOS_HEADER*	dh;
-    enum FileSig	sig;
-
-    pw = PRD(0, sizeof(WORD));
-    if (!pw) {printf("Can't get main signature, aborting\n"); return 0;}
-
-    switch (*pw)
-    {
-    case IMAGE_DOS_SIGNATURE:
-	sig = SIG_DOS;
-	dh = PRD(0, sizeof(IMAGE_DOS_HEADER));
-	if (dh && dh->e_lfanew >= sizeof(*dh)) /* reasonable DOS header ? */
-	{
-	    /* the signature is the first DWORD */
-	    pdw = PRD(dh->e_lfanew, sizeof(DWORD));
-	    if (pdw)
-	    {
-		if (*pdw == IMAGE_NT_SIGNATURE)
-		{
-		    PE_nt_headers = PRD(dh->e_lfanew, sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER));
-		    sig = SIG_PE;
-		}
-                else if (*(WORD *)pdw == IMAGE_OS2_SIGNATURE)
-                {
-                    sig = SIG_NE;
-                }
-		else if (*(WORD *)pdw == IMAGE_VXD_SIGNATURE)
-		{
-                    sig = SIG_LE;
-		}
-		else
-		{
-		    printf("No PE Signature found\n");
-		}
-	    }
-	    else
-	    {
-		printf("Can't get the extented signature, aborting\n");
-	    }
-	}
-	break;
-    case 0x4944: /* "DI" */
-	sig = SIG_DBG;
-	break;
-    default:
-	printf("No known main signature (%.2s/%x), aborting\n", (char*)pw, *pw);
-	sig = SIG_UNKNOWN;
-    }
-
-    return sig;
-}
-
-static int pe_analysis(const char* name, void (*fn)(enum FileSig), enum FileSig wanted_sig)
-{
-    int			fd;
-    enum FileSig	effective_sig;
-    int			ret = 1;
-    struct stat		s;
-
-    setbuf(stdout, NULL);
-
-    fd = open(name, O_RDONLY | O_BINARY);
-    if (fd == -1) fatal("Can't open file");
-
-    if (fstat(fd, &s) < 0) fatal("Can't get size");
-    PE_total_len = s.st_size;
-
-#ifdef HAVE_MMAP
-    if ((PE_base = mmap(NULL, PE_total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
-#endif
-    {
-        if (!(PE_base = malloc( PE_total_len ))) fatal( "Out of memory" );
-        if ((unsigned long)read( fd, PE_base, PE_total_len ) != PE_total_len) fatal( "Cannot read file" );
-    }
-
-    effective_sig = check_headers();
-
-    if (effective_sig == SIG_UNKNOWN)
-    {
-	printf("Can't get a recognized file signature, aborting\n");
-	ret = 0;
-    }
-    else if (wanted_sig == SIG_UNKNOWN || wanted_sig == effective_sig)
-    {
-	switch (effective_sig)
-	{
-	case SIG_UNKNOWN: /* shouldn't happen... */
-	    ret = 0; break;
-	case SIG_PE:
-	case SIG_NE:
-	case SIG_LE:
-	    printf("Contents of \"%s\": %ld bytes\n\n", name, PE_total_len);
-	    (*fn)(effective_sig);
-	    break;
-	case SIG_DBG:
-	    dump_separate_dbg();
-	    break;
-	case SIG_DOS:
-	    ret = 0; break;
-	}
-    }
-    else
-    {
-	printf("Can't get a suitable file signature, aborting\n");
-	ret = 0;
-    }
-
-    if (ret) printf("Done dumping %s\n", name);
-#ifdef HAVE_MMAP
-    if (munmap(PE_base, PE_total_len) == -1)
-#endif
-    {
-        free( PE_base );
-    }
-    close(fd);
-
-    return ret;
-}
-
-void	dump_file(const char* name)
-{
-    pe_analysis(name, do_dump, SIG_UNKNOWN);
-}
-
-#if 0
-int 	main(int argc, char* argv[])
-{
-    if (argc != 2) fatal("usage");
-    pe_analysis(argv[1], do_dump);
-}
-#endif
-
 typedef struct _dll_symbol {
     size_t	ordinal;
     char       *symbol;
@@ -1164,9 +924,9 @@
 }
 */
 
-static	void	do_grab_sym( enum FileSig sig )
+static	void	do_grab_sym( enum FileSig sig, void* pmt )
 {
-    IMAGE_EXPORT_DIRECTORY	*exportDir = get_dir(IMAGE_FILE_EXPORT_DIRECTORY);
+    IMAGE_EXPORT_DIRECTORY	*exportDir;
     unsigned			i, j;
     DWORD*			pName;
     DWORD*			pFunc;
@@ -1174,7 +934,8 @@
     char*			ptr;
     DWORD*			map;
 
-    if (!exportDir) return;
+    PE_nt_headers = pmt;
+    if (!(exportDir = get_dir(IMAGE_FILE_EXPORT_DIRECTORY))) return;
 
     pName = RVA(exportDir->AddressOfNames, exportDir->NumberOfNames * sizeof(DWORD));
     if (!pName) {printf("Can't grab functions' name table\n"); return;}
@@ -1242,7 +1003,7 @@
  */
 int dll_open (const char *dll_name)
 {
-    return pe_analysis(dll_name, do_grab_sym, SIG_PE);
+    return dump_analysis(dll_name, do_grab_sym, SIG_PE);
 }
 
 /*******************************************************************
diff --git a/tools/winedump/pe.h b/tools/winedump/pe.h
index a258b29..ef0a269 100644
--- a/tools/winedump/pe.h
+++ b/tools/winedump/pe.h
@@ -19,8 +19,7 @@
  */
 
 extern void		dump_codeview(unsigned long ptr, unsigned long len);
-extern void		dump_coff(unsigned long coffbase, unsigned long len);
+extern void		dump_coff(unsigned long coffbase, unsigned long len, void* sect_map);
 extern void		dump_frame_pointer_omission(unsigned long base, unsigned long len);
-extern void*		PRD(unsigned long prd, unsigned long len);
-extern unsigned long	Offset(void* ptr);
-extern char*		get_time_str(DWORD _t);
+extern void	        dump_separate_dbg(void);
+extern void             pe_dump(void*);
diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h
index ca5b2ce..144c8c4 100644
--- a/tools/winedump/winedump.h
+++ b/tools/winedump/winedump.h
@@ -89,6 +89,8 @@
   char  arg_flag [MAX_FUNCTION_ARGS];
   char *arg_text [MAX_FUNCTION_ARGS];
   char *arg_name [MAX_FUNCTION_ARGS];
+  unsigned int n_u_refs;
+  char *u_ref    [MAX_FUNCTION_ARGS];
 } parsed_symbol;
 
 /* FIXME: Replace with some hash such as GHashTable */
@@ -220,11 +222,23 @@
 
 char *str_toupper (char *str);
 
-void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix );
+/* file dumping functions */
+enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_NE, SIG_LE, SIG_MDMP};
 
-void ne_dump( const void *exe, size_t exe_size );
+void*		PRD(unsigned long prd, unsigned long len);
+unsigned long	Offset(void* ptr);
 
-void le_dump( const void *exe, size_t exe_size );
+typedef void (*file_dumper)(enum FileSig, void*);
+int             dump_analysis(const char*, file_dumper, enum FileSig);
+
+void            dump_data( const unsigned char *ptr, unsigned int size, const char *prefix );
+const char*	get_time_str( unsigned long );
+unsigned int    strlenW( const unsigned short *str );
+void            dump_unicode_str( const unsigned short *str, int len );
+
+void            ne_dump( const void *exe, size_t exe_size );
+void            le_dump( const void *exe, size_t exe_size );
+void            mdmp_dump( void );
 
 FILE *open_file (const char *name, const char *ext, const char *mode);