Add cyrillic glyphs to Wine System.
[wine] / dlls / dbghelp / minidump.c
1 /*
2  * File minidump.c - management of dumps (read & write)
3  *
4  * Copyright (C) 2004, Eric Pouech
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <time.h>
22
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
25
26 #include "dbghelp_private.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
30
31 #if 0
32 /* hard to see how we can generate this very easily (how to grab latest exception
33  * in a process ?)
34  */
35 static  void    DumpException(struct process* pcs, HANDLE hFile, RVA* rva)
36 {
37     MINIDUMP_EXCEPTION_STREAM   mdExcpt;
38
39     mdExcpt.ThreadId = DEBUG_CurrThread->tid;
40     mdExcpt.__alignment = 0;
41     mdExcpt.ExceptionRecord.
42
43     ULONG                       ExceptionCode;
44     ULONG                       ExceptionFlags;
45     ULONGLONG                   ExceptionRecord;
46     ULONGLONG                   ExceptionAddress;
47     ULONG                       NumberParameters;
48     ULONG                        __unusedAlignment;
49     ULONGLONG                   ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
50 }
51 #endif
52
53 /******************************************************************
54  *              dump_modules
55  *
56  * Write in File the modules from pcs
57  */
58 static  void    dump_modules(struct process* pcs, HANDLE hFile, RVA* rva)
59 {
60     MINIDUMP_MODULE             mdModule;
61     MINIDUMP_MODULE_LIST        mdModuleList;
62     DWORD                       written;
63     struct module*              module = NULL;
64
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)
73     {
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);
88     }
89     for (module = pcs->lmodules; module; module = module->next)
90     {
91         WriteFile(hFile, module->module.ModuleName, 
92                   strlen(module->module.ModuleName) + 1, &written, NULL);
93         FIXME("CV and misc records not written\n");
94     }
95 }
96
97 /******************************************************************
98  *              dump_system_info
99  *
100  * Dumps into File the information about the system
101  */
102 static  void    dump_system_info(struct process* pcs, HANDLE hFile, RVA* rva)
103 {
104     MINIDUMP_SYSTEM_INFO        mdSysInfo;
105     SYSTEM_INFO                 sysInfo;
106     OSVERSIONINFOA              osInfo;
107     DWORD                       written;
108
109     GetSystemInfo(&sysInfo);
110     GetVersionExA(&osInfo);
111
112     mdSysInfo.ProcessorArchitecture = sysInfo.u.s.wProcessorArchitecture;
113     mdSysInfo.ProcessorLevel = sysInfo.wProcessorLevel;
114     mdSysInfo.ProcessorRevision = sysInfo.wProcessorRevision;
115     mdSysInfo.Reserved0 = 0;
116
117     mdSysInfo.MajorVersion = osInfo.dwMajorVersion;
118     mdSysInfo.MinorVersion = osInfo.dwMinorVersion;
119     mdSysInfo.BuildNumber = osInfo.dwBuildNumber;
120     mdSysInfo.PlatformId = osInfo.dwPlatformId;
121
122     mdSysInfo.CSDVersionRva = *rva + sizeof(mdSysInfo);
123     mdSysInfo.Reserved1 = 0;
124
125     WriteFile(hFile, &mdSysInfo, sizeof(mdSysInfo), &written, NULL);
126     *rva += sizeof(mdSysInfo);
127     WriteFile(hFile, osInfo.szCSDVersion, strlen(osInfo.szCSDVersion) + 1, 
128               &written, NULL);
129     *rva += strlen(osInfo.szCSDVersion) + 1;
130 }
131
132 /******************************************************************
133  *              dump_threads
134  *
135  * Dumps into File the information about running threads
136  */
137 static  void    dump_threads(struct process* pcs, HANDLE hFile, RVA* rva)
138 {
139 #if 0
140     MINIDUMP_THREAD             mdThd;
141     MINIDUMP_THREAD_LIST        mdThdList;
142     DWORD                       written;
143     DBG_THREAD*                 thd;
144
145     mdThdList.NumberOfThreads = pcs->num_threads;
146     WriteFile(hFile, &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads), 
147               &written, NULL);
148     *rva += sizeof(mdThdList.NumberOfThreads) + 
149         mdThdList.NumberOfThreads * sizeof(mdThd);
150     for (thd = pcs->threads; thd; thd = thd->next)
151     {
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 */
162
163         WriteFile(hFile, &mdThd, sizeof(mdThd), &written, NULL);
164         FIXME("Stack & thread context not written\n");
165     }
166 #endif
167 }
168
169 /******************************************************************
170  *              MiniDumpWriteDump (DEBUGHLP.@)
171  *
172  *
173  */
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)
179 {
180     struct process*     pcs;
181     MINIDUMP_HEADER     mdHead;
182     MINIDUMP_DIRECTORY  mdDir;
183     DWORD               currRva, written;
184     DWORD               i, nStream, addStream;
185     RVA                 rva;
186
187     pcs = process_find_by_handle(hProcess);
188     if (!pcs) return FALSE; /* FIXME: should try to load it ??? */
189
190     /* 1) init */
191
192     nStream = UserStreamParam ? UserStreamParam->UserStreamCount : 0;
193     addStream = 0;
194     if (DumpType & MiniDumpNormal)
195         addStream += 3; /* sure ? thread stack back trace */
196
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");
207
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);
217     
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);
229
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);
238
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);
247
248     /* 3.2) write user define stream */
249     for (i = 0; i < nStream; i++)
250     {
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);
257         WriteFile(hFile, 
258                   UserStreamParam->UserStreamArray[i].Buffer, 
259                   UserStreamParam->UserStreamArray[i].BufferSize, 
260                   &written, NULL);
261         rva += UserStreamParam->UserStreamArray[i].BufferSize;
262         SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
263     }
264
265     return TRUE;
266 }