Delete the stub manager outside of the apartment critical section
[wine.git] / tools / winedump / dump.c
blobf2c1af3b16b82aefb2a23f23d857a1171e79c53f
1 /*
2 * File dumping utility
4 * Copyright 2001,2005 Eric Pouech
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <time.h>
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34 #ifdef HAVE_SYS_STAT_H
35 # include <sys/stat.h>
36 #endif
37 #ifdef HAVE_SYS_MMAN_H
38 #include <sys/mman.h>
39 #endif
40 #include <fcntl.h>
42 #define NONAMELESSUNION
43 #define NONAMELESSSTRUCT
44 #include "windef.h"
45 #include "winbase.h"
46 #include "winedump.h"
47 #include "pe.h"
49 #ifndef O_BINARY
50 # define O_BINARY 0
51 #endif
53 static void* dump_base;
54 static unsigned long dump_total_len;
56 void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix )
58 unsigned int i, j;
60 printf( "%s%08x: ", prefix, 0 );
61 if (!ptr)
63 printf("NULL\n");
64 return;
66 for (i = 0; i < size; i++)
68 printf( "%02x%c", ptr[i], (i % 16 == 7) ? '-' : ' ' );
69 if ((i % 16) == 15)
71 printf( " " );
72 for (j = 0; j < 16; j++)
73 printf( "%c", isprint(ptr[i-15+j]) ? ptr[i-15+j] : '.' );
74 if (i < size-1) printf( "\n%s%08x: ", prefix, i + 1 );
77 if (i % 16)
79 printf( "%*s ", 3 * (16-(i%16)), "" );
80 for (j = 0; j < i % 16; j++)
81 printf( "%c", isprint(ptr[i-(i%16)+j]) ? ptr[i-(i%16)+j] : '.' );
83 printf( "\n" );
86 const char* get_time_str(DWORD _t)
88 time_t t = (time_t)_t;
89 const char *str = ctime(&t);
90 size_t len = strlen(str);
91 static char buf[128];
92 /* FIXME: I don't get the same values from MS' pedump running under Wine...
93 * I wonder if Wine isn't broken wrt to GMT settings...
95 if (len && str[len-1] == '\n') len--;
96 if (len >= sizeof(buf)) len = sizeof(buf) - 1;
97 memcpy( buf, str, len );
98 buf[len] = 0;
99 return buf;
102 unsigned int strlenW( const WCHAR *str )
104 const WCHAR *s = str;
105 while (*s) s++;
106 return s - str;
109 void dump_unicode_str( const WCHAR *str, int len )
111 if (len == -1) len = strlenW( str );
112 printf( "L\"");
113 while (len-- > 0 && *str)
115 WCHAR c = *str++;
116 switch (c)
118 case '\n': printf( "\\n" ); break;
119 case '\r': printf( "\\r" ); break;
120 case '\t': printf( "\\t" ); break;
121 case '"': printf( "\\\"" ); break;
122 case '\\': printf( "\\\\" ); break;
123 default:
124 if (c >= ' ' && c <= 126) putchar(c);
125 else printf( "\\u%04x",c);
128 printf( "\"" );
131 void* PRD(unsigned long prd, unsigned long len)
133 return (prd + len > dump_total_len) ? NULL : (char*)dump_base + prd;
136 unsigned long Offset(void* ptr)
138 if (ptr < dump_base) {printf("<<<<<ptr below\n");return 0;}
139 if ((char *)ptr >= (char*)dump_base + dump_total_len) {printf("<<<<<ptr above\n");return 0;}
140 return (char*)ptr - (char*)dump_base;
143 static void do_dump( enum FileSig sig, void* pmt )
145 if (sig == SIG_NE)
147 ne_dump( dump_base, dump_total_len );
148 return;
151 if (sig == SIG_LE)
153 le_dump( dump_base, dump_total_len );
154 return;
157 pe_dump(pmt);
160 static enum FileSig check_headers(void** pmt)
162 WORD* pw;
163 DWORD* pdw;
164 IMAGE_DOS_HEADER* dh;
165 enum FileSig sig;
167 pw = PRD(0, sizeof(WORD));
168 if (!pw) {printf("Can't get main signature, aborting\n"); return 0;}
170 *pmt = NULL;
171 switch (*pw)
173 case IMAGE_DOS_SIGNATURE:
174 sig = SIG_DOS;
175 dh = PRD(0, sizeof(IMAGE_DOS_HEADER));
176 if (dh && dh->e_lfanew >= sizeof(*dh)) /* reasonable DOS header ? */
178 /* the signature is the first DWORD */
179 pdw = PRD(dh->e_lfanew, sizeof(DWORD));
180 if (pdw)
182 if (*pdw == IMAGE_NT_SIGNATURE)
184 *pmt = PRD(dh->e_lfanew, sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER));
185 sig = SIG_PE;
187 else if (*(WORD *)pdw == IMAGE_OS2_SIGNATURE)
189 sig = SIG_NE;
191 else if (*(WORD *)pdw == IMAGE_VXD_SIGNATURE)
193 sig = SIG_LE;
195 else
197 printf("No PE Signature found\n");
200 else
202 printf("Can't get the extented signature, aborting\n");
205 break;
206 case 0x4944: /* "DI" */
207 sig = SIG_DBG;
208 break;
209 case 0x444D: /* "MD" */
210 pdw = PRD(0, sizeof(DWORD));
211 if (pdw && *pdw == 0x504D444D) /* "MDMP" */
212 sig = SIG_MDMP;
213 else
214 sig = SIG_UNKNOWN;
215 break;
216 default:
217 printf("No known main signature (%.2s/%x), aborting\n", (char*)pw, *pw);
218 sig = SIG_UNKNOWN;
221 return sig;
224 int dump_analysis(const char* name, void (*fn)(enum FileSig, void*), enum FileSig wanted_sig)
226 int fd;
227 enum FileSig effective_sig;
228 int ret = 1;
229 struct stat s;
230 void* pmt;
232 setbuf(stdout, NULL);
234 fd = open(name, O_RDONLY | O_BINARY);
235 if (fd == -1) fatal("Can't open file");
237 if (fstat(fd, &s) < 0) fatal("Can't get size");
238 dump_total_len = s.st_size;
240 #ifdef HAVE_MMAP
241 if ((dump_base = mmap(NULL, dump_total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
242 #endif
244 if (!(dump_base = malloc( dump_total_len ))) fatal( "Out of memory" );
245 if ((unsigned long)read( fd, dump_base, dump_total_len ) != dump_total_len) fatal( "Cannot read file" );
248 effective_sig = check_headers(&pmt);
250 if (effective_sig == SIG_UNKNOWN)
252 printf("Can't get a recognized file signature, aborting\n");
253 ret = 0;
255 else if (wanted_sig == SIG_UNKNOWN || wanted_sig == effective_sig)
257 switch (effective_sig)
259 case SIG_UNKNOWN: /* shouldn't happen... */
260 ret = 0; break;
261 case SIG_PE:
262 case SIG_NE:
263 case SIG_LE:
264 printf("Contents of \"%s\": %ld bytes\n\n", name, dump_total_len);
265 (*fn)(effective_sig, pmt);
266 break;
267 case SIG_DBG:
268 dump_separate_dbg();
269 break;
270 case SIG_DOS:
271 ret = 0; break;
272 case SIG_MDMP:
273 mdmp_dump();
274 break;
277 else
279 printf("Can't get a suitable file signature, aborting\n");
280 ret = 0;
283 if (ret) printf("Done dumping %s\n", name);
284 #ifdef HAVE_MMAP
285 if (munmap(dump_base, dump_total_len) == -1)
286 #endif
288 free( dump_base );
290 close(fd);
292 return ret;
295 void dump_file(const char* name)
297 dump_analysis(name, do_dump, SIG_UNKNOWN);