2 * File minidump.c - management of dumps (read & write)
4 * Copyright (C) 2004, 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
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
26 #include "dbghelp_private.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp
);
32 /* hard to see how we can generate this very easily (how to grab latest exception
35 static void DumpException(struct process
* pcs
, HANDLE hFile
, RVA
* rva
)
37 MINIDUMP_EXCEPTION_STREAM mdExcpt
;
39 mdExcpt
.ThreadId
= DEBUG_CurrThread
->tid
;
40 mdExcpt
.__alignment
= 0;
41 mdExcpt
.ExceptionRecord
.
45 ULONGLONG ExceptionRecord
;
46 ULONGLONG ExceptionAddress
;
47 ULONG NumberParameters
;
48 ULONG __unusedAlignment
;
49 ULONGLONG ExceptionInformation
[EXCEPTION_MAXIMUM_PARAMETERS
];
53 /******************************************************************
56 * Write in File the modules from pcs
58 static void dump_modules(struct process
* pcs
, HANDLE hFile
, RVA
* rva
)
60 MINIDUMP_MODULE mdModule
;
61 MINIDUMP_MODULE_LIST mdModuleList
;
63 struct module
* module
= NULL
;
65 mdModuleList
.NumberOfModules
= 0;
66 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
67 mdModuleList
.NumberOfModules
++;
68 WriteFile(hFile
, &mdModuleList
.NumberOfModules
,
69 sizeof(mdModuleList
.NumberOfModules
), &written
, NULL
);
70 *rva
+= sizeof(mdModuleList
.NumberOfModules
) +
71 sizeof(mdModule
) * mdModuleList
.NumberOfModules
;
72 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
74 mdModule
.BaseOfImage
= (DWORD
)module
->module
.BaseOfImage
;
75 mdModule
.SizeOfImage
= module
->module
.ImageSize
;
76 mdModule
.CheckSum
= module
->module
.CheckSum
;
77 mdModule
.TimeDateStamp
= module
->module
.TimeDateStamp
;
78 mdModule
.ModuleNameRva
= *rva
;
79 *rva
+= strlen(module
->module
.ModuleName
) + 1;
80 memset(&mdModule
.VersionInfo
, 0, sizeof(mdModule
.VersionInfo
)); /* FIXME */
81 mdModule
.CvRecord
.DataSize
= 0; /* FIXME */
82 mdModule
.CvRecord
.Rva
= 0; /* FIXME */
83 mdModule
.MiscRecord
.DataSize
= 0; /* FIXME */
84 mdModule
.MiscRecord
.Rva
= 0; /* FIXME */
85 mdModule
.Reserved0
= 0;
86 mdModule
.Reserved1
= 0;
87 WriteFile(hFile
, &mdModule
, sizeof(mdModule
), &written
, NULL
);
89 for (module
= pcs
->lmodules
; module
; module
= module
->next
)
91 WriteFile(hFile
, module
->module
.ModuleName
,
92 strlen(module
->module
.ModuleName
) + 1, &written
, NULL
);
93 FIXME("CV and misc records not written\n");
97 /******************************************************************
100 * Dumps into File the information about the system
102 static void dump_system_info(struct process
* pcs
, HANDLE hFile
, RVA
* rva
)
104 MINIDUMP_SYSTEM_INFO mdSysInfo
;
106 OSVERSIONINFOA osInfo
;
109 GetSystemInfo(&sysInfo
);
110 GetVersionExA(&osInfo
);
112 mdSysInfo
.ProcessorArchitecture
= sysInfo
.u
.s
.wProcessorArchitecture
;
113 mdSysInfo
.ProcessorLevel
= sysInfo
.wProcessorLevel
;
114 mdSysInfo
.ProcessorRevision
= sysInfo
.wProcessorRevision
;
115 mdSysInfo
.Reserved0
= 0;
117 mdSysInfo
.MajorVersion
= osInfo
.dwMajorVersion
;
118 mdSysInfo
.MinorVersion
= osInfo
.dwMinorVersion
;
119 mdSysInfo
.BuildNumber
= osInfo
.dwBuildNumber
;
120 mdSysInfo
.PlatformId
= osInfo
.dwPlatformId
;
122 mdSysInfo
.CSDVersionRva
= *rva
+ sizeof(mdSysInfo
);
123 mdSysInfo
.Reserved1
= 0;
125 WriteFile(hFile
, &mdSysInfo
, sizeof(mdSysInfo
), &written
, NULL
);
126 *rva
+= sizeof(mdSysInfo
);
127 WriteFile(hFile
, osInfo
.szCSDVersion
, strlen(osInfo
.szCSDVersion
) + 1,
129 *rva
+= strlen(osInfo
.szCSDVersion
) + 1;
132 /******************************************************************
135 * Dumps into File the information about running threads
137 static void dump_threads(struct process
* pcs
, HANDLE hFile
, RVA
* rva
)
140 MINIDUMP_THREAD mdThd
;
141 MINIDUMP_THREAD_LIST mdThdList
;
145 mdThdList
.NumberOfThreads
= pcs
->num_threads
;
146 WriteFile(hFile
, &mdThdList
.NumberOfThreads
, sizeof(mdThdList
.NumberOfThreads
),
148 *rva
+= sizeof(mdThdList
.NumberOfThreads
) +
149 mdThdList
.NumberOfThreads
* sizeof(mdThd
);
150 for (thd
= pcs
->threads
; thd
; thd
= thd
->next
)
152 mdThd
.ThreadId
= thd
->tid
;
153 mdThd
.SuspendCount
= 0; /* FIXME */
154 mdThd
.PriorityClass
= 0; /* FIXME */
155 mdThd
.Priority
= 0; /* FIXME */
156 mdThd
.Teb
= 0; /* FIXME */
157 mdThd
.Stack
.StartOfMemoryRange
= 0; /* FIXME */
158 mdThd
.Stack
.Memory
.DataSize
= 0; /* FIXME */
159 mdThd
.Stack
.Memory
.Rva
= 0; /* FIXME */
160 mdThd
.ThreadContext
.DataSize
= 0;/* FIXME */
161 mdThd
.ThreadContext
.Rva
= 0; /* FIXME */
163 WriteFile(hFile
, &mdThd
, sizeof(mdThd
), &written
, NULL
);
164 FIXME("Stack & thread context not written\n");
169 /******************************************************************
170 * MiniDumpWriteDump (DEBUGHLP.@)
174 BOOL WINAPI
MiniDumpWriteDump(HANDLE hProcess
, DWORD ProcessId
, HANDLE hFile
,
175 MINIDUMP_TYPE DumpType
,
176 PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam
,
177 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam
,
178 PMINIDUMP_CALLBACK_INFORMATION CallbackParam
)
181 MINIDUMP_HEADER mdHead
;
182 MINIDUMP_DIRECTORY mdDir
;
183 DWORD currRva
, written
;
184 DWORD i
, nStream
, addStream
;
187 pcs
= process_find_by_handle(hProcess
);
188 if (!pcs
) return FALSE
; /* FIXME: should try to load it ??? */
192 nStream
= UserStreamParam
? UserStreamParam
->UserStreamCount
: 0;
194 if (DumpType
& MiniDumpNormal
)
195 addStream
+= 3; /* sure ? thread stack back trace */
197 if (DumpType
& MiniDumpWithDataSegs
)
198 FIXME("NIY MiniDumpWithDataSegs\n");
199 if (DumpType
& MiniDumpWithFullMemory
)
200 FIXME("NIY MiniDumpWithFullMemory\n");
201 if (DumpType
& MiniDumpWithHandleData
)
202 FIXME("NIY MiniDumpWithHandleData\n");
203 if (DumpType
& MiniDumpFilterMemory
)
204 FIXME("NIY MiniDumpFilterMemory\n");
205 if (DumpType
& MiniDumpScanMemory
)
206 FIXME("NIY MiniDumpScanMemory\n");
208 /* 2) write header */
209 rva
= sizeof(mdHead
);
210 mdHead
.Signature
= MINIDUMP_SIGNATURE
;
211 mdHead
.Version
= MINIDUMP_VERSION
;
212 mdHead
.NumberOfStreams
= nStream
+ addStream
;
213 mdHead
.StreamDirectoryRva
= rva
;
214 mdHead
.u
.TimeDateStamp
= time(NULL
);
215 mdHead
.Flags
= DumpType
;
216 WriteFile(hFile
, &mdHead
, sizeof(mdHead
), &written
, NULL
);
218 /* 3) write stream directories */
219 rva
+= (nStream
+ addStream
) * sizeof(mdDir
);
220 /* 3.1) write data stream directories */
221 currRva
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
);
222 SetFilePointer(hFile
, rva
, NULL
, FILE_BEGIN
);
223 mdDir
.StreamType
= ModuleListStream
;
224 mdDir
.Location
.Rva
= rva
;
225 dump_modules(pcs
, hFile
, &rva
);
226 mdDir
.Location
.DataSize
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
) - mdDir
.Location
.Rva
;
227 SetFilePointer(hFile
, currRva
, NULL
, FILE_BEGIN
);
228 WriteFile(hFile
, &mdDir
, sizeof(mdDir
), &written
, NULL
);
230 currRva
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
);
231 SetFilePointer(hFile
, rva
, NULL
, FILE_BEGIN
);
232 mdDir
.StreamType
= ThreadListStream
;
233 mdDir
.Location
.Rva
= rva
;
234 dump_threads(pcs
, hFile
, &rva
);
235 mdDir
.Location
.DataSize
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
) - mdDir
.Location
.Rva
;
236 SetFilePointer(hFile
, currRva
, NULL
, FILE_BEGIN
);
237 WriteFile(hFile
, &mdDir
, sizeof(mdDir
), &written
, NULL
);
239 currRva
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
);
240 SetFilePointer(hFile
, rva
, NULL
, FILE_BEGIN
);
241 mdDir
.StreamType
= SystemInfoStream
;
242 mdDir
.Location
.Rva
= rva
;
243 dump_system_info(pcs
, hFile
, &rva
);
244 mdDir
.Location
.DataSize
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
) - mdDir
.Location
.Rva
;
245 SetFilePointer(hFile
, currRva
, NULL
, FILE_BEGIN
);
246 WriteFile(hFile
, &mdDir
, sizeof(mdDir
), &written
, NULL
);
248 /* 3.2) write user define stream */
249 for (i
= 0; i
< nStream
; i
++)
251 mdDir
.StreamType
= UserStreamParam
->UserStreamArray
[i
].Type
;
252 mdDir
.Location
.DataSize
= UserStreamParam
->UserStreamArray
[i
].BufferSize
;
253 mdDir
.Location
.Rva
= rva
;
254 WriteFile(hFile
, &mdDir
, sizeof(mdDir
), &written
, NULL
);
255 currRva
= SetFilePointer(hFile
, 0, NULL
, FILE_CURRENT
);
256 SetFilePointer(hFile
, rva
, NULL
, FILE_BEGIN
);
258 UserStreamParam
->UserStreamArray
[i
].Buffer
,
259 UserStreamParam
->UserStreamArray
[i
].BufferSize
,
261 rva
+= UserStreamParam
->UserStreamArray
[i
].BufferSize
;
262 SetFilePointer(hFile
, currRva
, NULL
, FILE_BEGIN
);