OSDN Git Service

Add IBugTraqProvider
[tortoisegit/TortoiseGitJp.git] / src / crashrpt / excprpt.cpp
1 ///////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 //  Module: excprpt.cpp\r
4 //\r
5 //    Desc: See excprpt.h\r
6 //\r
7 // Copyright (c) 2003 Michael Carruth\r
8 //\r
9 ///////////////////////////////////////////////////////////////////////////////\r
10 \r
11 \r
12 #include "stdafx.h"\r
13 #include "excprpt.h"\r
14 #include "utility.h"\r
15 \r
16 #include "StackTrace.h"\r
17 \r
18 //////////////////////////////////////////////////////////////////////\r
19 // Construction/Destruction\r
20 //////////////////////////////////////////////////////////////////////\r
21 \r
22 \r
23 //-----------------------------------------------------------------------------\r
24 // CExceptionReport::CExceptionReport\r
25 //\r
26 // \r
27 //\r
28 CExceptionReport::CExceptionReport(PEXCEPTION_POINTERS ExceptionInfo, BSTR message)\r
29 {\r
30    m_excpInfo = ExceptionInfo;\r
31    m_message = message;\r
32    TCHAR szModName[_MAX_FNAME + 1];\r
33    GetModuleFileName(NULL, szModName, _MAX_FNAME);\r
34    m_sModule = szModName;\r
35    m_sCommandLine = GetCommandLine();\r
36    m_frameNumber = 0;\r
37 }\r
38 \r
39 \r
40 //-----------------------------------------------------------------------------\r
41 // CExceptionReport::getCrashFile\r
42 //\r
43 // Creates the dump file returning the file name\r
44 //\r
45 string CExceptionReport::getCrashFile()\r
46 {\r
47    TCHAR buf[MAX_PATH] = {0};\r
48    _stprintf_s(buf, MAX_PATH, _T("%s\\%s.dmp"), _tgetenv("TEMP"), CUtility::getAppName().c_str());\r
49 \r
50    // Create the file\r
51    HANDLE hFile = CreateFile(\r
52       buf,\r
53       GENERIC_WRITE,\r
54       0,\r
55       NULL,\r
56       CREATE_ALWAYS,\r
57       FILE_ATTRIBUTE_NORMAL,\r
58       NULL);\r
59 \r
60    //\r
61    // Write the minidump to the file\r
62    //\r
63    if (hFile)\r
64    {\r
65       writeDumpFile(hFile, m_excpInfo, reinterpret_cast<void *>(this));\r
66    }\r
67 \r
68    // Close file\r
69    CloseHandle(hFile);\r
70 \r
71    return string(buf);\r
72 }\r
73 \r
74 \r
75 void CExceptionReport::writeDumpFile(HANDLE hFile, PEXCEPTION_POINTERS excpInfo, void *data)\r
76 {\r
77         if (excpInfo == NULL) {\r
78       // Generate exception to get proper context in dump\r
79            __try {\r
80                    RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);\r
81            } __except(writeDumpFile(hFile, GetExceptionInformation(), data), EXCEPTION_CONTINUE_EXECUTION) {\r
82            }\r
83         } else {\r
84       MINIDUMP_EXCEPTION_INFORMATION eInfo;\r
85       eInfo.ThreadId = GetCurrentThreadId();\r
86       eInfo.ExceptionPointers = excpInfo;\r
87       eInfo.ClientPointers = FALSE;\r
88 \r
89       MINIDUMP_CALLBACK_INFORMATION cbMiniDump;\r
90       cbMiniDump.CallbackRoutine = CExceptionReport::miniDumpCallback;\r
91       cbMiniDump.CallbackParam = data;\r
92 \r
93       MiniDumpWriteDump(\r
94          GetCurrentProcess(),\r
95          GetCurrentProcessId(),\r
96          hFile,\r
97          MiniDumpWithIndirectlyReferencedMemory,\r
98          excpInfo ? &eInfo : NULL,\r
99                  NULL,\r
100          &cbMiniDump);\r
101    }\r
102 }\r
103 \r
104 //-----------------------------------------------------------------------------\r
105 // CExceptionReport::getCrashLog\r
106 //\r
107 // Creates the XML log file returning the name\r
108 //\r
109 string CExceptionReport::getCrashLog()\r
110 {\r
111    string sFile;\r
112    MSXML2::IXMLDOMDocument *pDoc  = NULL;\r
113    MSXML2::IXMLDOMNode *root      = NULL;\r
114    MSXML2::IXMLDOMNode *node      = NULL;\r
115    MSXML2::IXMLDOMNode *newNode   = NULL;\r
116    BSTR rootName = ::SysAllocString(L"Exception");\r
117    VARIANT v;\r
118 \r
119    CoInitialize(NULL);\r
120 \r
121    // Create an empty XML document\r
122    CHECKHR(CoCreateInstance(\r
123       MSXML2::CLSID_DOMDocument, \r
124       NULL, \r
125       CLSCTX_INPROC_SERVER,\r
126       MSXML2::IID_IXMLDOMDocument, \r
127       (void**)&pDoc));\r
128 \r
129    // Create root node\r
130    root = CreateDOMNode(pDoc, MSXML2::NODE_ELEMENT, rootName);\r
131 \r
132    //\r
133    // Add exception record node\r
134    //\r
135    if (m_excpInfo)\r
136    {\r
137       node = CreateExceptionRecordNode(pDoc, m_excpInfo->ExceptionRecord);\r
138       CHECKHR(root->appendChild(node, &newNode));\r
139       // The XML Document should now own the node.\r
140       SAFERELEASE(node);\r
141       SAFERELEASE(newNode);\r
142    }\r
143 \r
144    //\r
145    // Add optional message node\r
146    //\r
147    if (m_message != NULL) {\r
148            node = CreateMsgNode(pDoc, m_message);\r
149            CHECKHR(root->appendChild(node, &newNode));\r
150            // The XML Document should now own the node.\r
151            SAFERELEASE(node);\r
152            SAFERELEASE(newNode);\r
153    }\r
154 \r
155    //\r
156    // Add processor node\r
157    //\r
158    node = CreateProcessorNode(pDoc);\r
159    CHECKHR(root->appendChild(node, &newNode));\r
160    // The XML Document should now own the node.\r
161    SAFERELEASE(node);\r
162    SAFERELEASE(newNode);\r
163 \r
164    //\r
165    // Add OS node\r
166    //\r
167    node = CreateOSNode(pDoc);\r
168    CHECKHR(root->appendChild(node, &newNode));\r
169    // The XML Document should now own the node.\r
170    SAFERELEASE(node);\r
171    SAFERELEASE(newNode);\r
172 \r
173    //\r
174    // Add modules node\r
175    //\r
176    node = CreateModulesNode(pDoc);\r
177    CHECKHR(root->appendChild(node, &newNode));\r
178    // The XML Document should now own the node.\r
179    SAFERELEASE(node);\r
180    SAFERELEASE(newNode);\r
181 \r
182    //\r
183    // Add stack walkback node\r
184    //\r
185    node = CreateWalkbackNode(pDoc, m_excpInfo != NULL ? m_excpInfo->ContextRecord : NULL);\r
186    CHECKHR(root->appendChild(node, &newNode));\r
187    // The XML Document should now own the node.\r
188    SAFERELEASE(node);\r
189    SAFERELEASE(newNode);\r
190 \r
191 \r
192    // Add the root to the doc\r
193    CHECKHR(pDoc->appendChild(root, NULL));\r
194 \r
195    //\r
196    // Create dat file name and save\r
197    //\r
198    TCHAR buf[MAX_PATH] = {0};\r
199    _tprintf_s(buf, _T("%s\\%s.xml"), getenv("TEMP"), CUtility::getAppName());\r
200    V_VT(&v) = VT_BSTR;\r
201    V_BSTR(&v) = CUtility::AllocSysString(buf);\r
202    pDoc->save(v);\r
203    SysFreeString(V_BSTR(&v));\r
204 \r
205 CleanUp:\r
206    SAFERELEASE(pDoc);\r
207    SAFERELEASE(root);\r
208    SAFERELEASE(node);\r
209    SAFERELEASE(newNode);\r
210    SysFreeString(rootName);\r
211 \r
212    CoUninitialize();\r
213 \r
214    return sFile;\r
215 }\r
216 \r
217 \r
218 //-----------------------------------------------------------------------------\r
219 // CExceptionReport::getNumSymbolFiles\r
220 //\r
221 // Returns the number of symbols files found\r
222 //\r
223 int CExceptionReport::getNumSymbolFiles()\r
224 {\r
225    return m_symFiles.size();\r
226 }\r
227 \r
228 \r
229 //-----------------------------------------------------------------------------\r
230 // CExceptionReport::getSymbolFile\r
231 //\r
232 // Returns the symbol file name given an index\r
233 //\r
234 string CExceptionReport::getSymbolFile(int index)\r
235 {\r
236    string ret;\r
237 \r
238    if (0 < index && index < (int)m_symFiles.size())\r
239       ret = m_symFiles[index];\r
240 \r
241    return ret;\r
242 }\r
243 \r
244 //-----------------------------------------------------------------------------\r
245 // CExceptionReport::CreateDOMNode\r
246 //\r
247 // Helper function \r
248 //\r
249 MSXML2::IXMLDOMNode*\r
250 CExceptionReport::CreateDOMNode(MSXML2::IXMLDOMDocument* pDoc, \r
251                                 int type, \r
252                                 BSTR bstrName)\r
253 {\r
254     MSXML2::IXMLDOMNode * node;\r
255     VARIANT vtype;\r
256 \r
257     vtype.vt = VT_I4;\r
258     V_I4(&vtype) = (int)type;\r
259 \r
260     pDoc->createNode(vtype, bstrName, NULL, &node);\r
261     return node;\r
262 }\r
263 \r
264 //-----------------------------------------------------------------------------\r
265 // CreateExceptionSymbolAttributes\r
266 //\r
267 // Create attributes in the exception record with the symbolic info, if available\r
268 //\r
269 void  CExceptionReport::CreateExceptionSymbolAttributes(DWORD_PTR /*address*/, const char * /*ImageName*/,\r
270                                                                           const char *FunctionName, DWORD_PTR functionDisp,\r
271                                                                           const char *Filename, DWORD LineNumber, DWORD lineDisp,\r
272                                                                           void *data)\r
273 {\r
274    string sAddr;\r
275    BSTR funcName                                        = ::SysAllocString(L"FunctionName");\r
276    BSTR funcDispName                            = ::SysAllocString(L"FunctionDisplacement");\r
277    BSTR fileName                                        = ::SysAllocString(L"Filename");\r
278    BSTR lineName                                        = ::SysAllocString(L"LineNumber");\r
279    BSTR lineDispName                            = ::SysAllocString(L"LineDisplacement");\r
280    CExceptionReport     *self = reinterpret_cast<CExceptionReport *>(data);\r
281 \r
282    VARIANT v;\r
283 \r
284    // don't need ImageName [module], as that is already done\r
285    if (FunctionName != NULL) {\r
286                 V_VT(&v) = VT_BSTR;\r
287                 V_BSTR(&v) = CUtility::AllocSysString(FunctionName);\r
288                 self->m_exception_element->setAttribute(funcName, v);\r
289                 // Recycle variant\r
290                 SysFreeString(V_BSTR(&v));\r
291                 TCHAR buf[MAX_PATH] = {0};\r
292                 _tprintf_s(buf, offsetFormat, functionDisp);\r
293                 V_VT(&v) = VT_BSTR;\r
294                 V_BSTR(&v) = CUtility::AllocSysString(buf);\r
295                 self->m_exception_element->setAttribute(funcDispName, v);\r
296                 // Recycle variant\r
297                 SysFreeString(V_BSTR(&v));\r
298    }\r
299 \r
300    if (Filename != NULL) {\r
301                 V_VT(&v) = VT_BSTR;\r
302                 V_BSTR(&v) = CUtility::AllocSysString(Filename);\r
303                 self->m_exception_element->setAttribute(fileName, v);\r
304                 // Recycle variant\r
305                 SysFreeString(V_BSTR(&v));\r
306 \r
307                 TCHAR buf[MAX_PATH] = {0};\r
308                 _tprintf_s(buf, _T("%d"), LineNumber);\r
309                 V_VT(&v) = VT_BSTR;\r
310                 V_BSTR(&v) = CUtility::AllocSysString(buf);\r
311                 self->m_exception_element->setAttribute(lineName, v);\r
312                 // Recycle variant\r
313                 SysFreeString(V_BSTR(&v));\r
314 \r
315                 _tprintf_s(buf, offsetFormat, lineDisp);\r
316                 V_VT(&v) = VT_BSTR;\r
317                 V_BSTR(&v) = CUtility::AllocSysString(buf);\r
318                 self->m_exception_element->setAttribute(lineDispName, v);\r
319                 // Recycle variant\r
320                 SysFreeString(V_BSTR(&v));\r
321    }\r
322    ::SysFreeString(funcName);\r
323    ::SysFreeString(funcDispName);\r
324    ::SysFreeString(fileName);\r
325    ::SysFreeString(lineName);\r
326    ::SysFreeString(lineDispName);\r
327 }\r
328 \r
329 //-----------------------------------------------------------------------------\r
330 // CExceptionReport::CreateExceptionRecordNode\r
331 //\r
332 //\r
333 //\r
334 MSXML2::IXMLDOMNode*\r
335 CExceptionReport::CreateExceptionRecordNode(MSXML2::IXMLDOMDocument* pDoc, \r
336                                             EXCEPTION_RECORD* pExceptionRecord)\r
337 {\r
338    MSXML2::IXMLDOMNode*     pNode    = NULL;\r
339    MSXML2::IXMLDOMElement*  pElement = NULL;\r
340    BSTR nodeName                    = ::SysAllocString(L"ExceptionRecord");\r
341    BSTR modName                     = ::SysAllocString(L"ModuleName");\r
342    BSTR codeName                    = ::SysAllocString(L"ExceptionCode");\r
343    BSTR descName                    = ::SysAllocString(L"ExceptionDescription");\r
344    BSTR addrName                    = ::SysAllocString(L"ExceptionAddress");\r
345    BSTR commandlineName                         = ::SysAllocString(L"CommandLine");\r
346    \r
347    VARIANT v;\r
348    string sAddr;\r
349 \r
350    // Create exception record node\r
351    pNode = CreateDOMNode(pDoc, MSXML2::NODE_ELEMENT, nodeName);\r
352 \r
353    // Get element interface\r
354    CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));\r
355 \r
356    //\r
357    // Set module name attribute\r
358    //\r
359    V_VT(&v)    = VT_BSTR;\r
360    V_BSTR(&v)  = CUtility::AllocSysString(m_sModule);\r
361    pElement->setAttribute(modName, v);\r
362    // Recycle variant\r
363    SysFreeString(V_BSTR(&v));\r
364 \r
365    //\r
366    // Set command line name attribute\r
367    //\r
368    V_VT(&v)    = VT_BSTR;\r
369    V_BSTR(&v)  = CUtility::AllocSysString(m_sCommandLine);\r
370    pElement->setAttribute(commandlineName, v);\r
371    // Recycle variant\r
372    SysFreeString(V_BSTR(&v));\r
373 \r
374    //\r
375    // Set exception code\r
376    //\r
377    TCHAR buf[MAX_PATH] = {0};\r
378    _tprintf_s(buf, _T("%#x"), pExceptionRecord->ExceptionCode);\r
379    m_sException = buf;\r
380    V_VT(&v)    = VT_BSTR;\r
381    V_BSTR(&v)  = CUtility::AllocSysString(buf);\r
382    pElement->setAttribute(codeName, v);\r
383    // Recycle variant\r
384    SysFreeString(V_BSTR(&v));\r
385 \r
386    //\r
387    // Set exception description\r
388    //\r
389    V_VT(&v)    = VT_BSTR;\r
390    switch (pExceptionRecord->ExceptionCode)\r
391    {\r
392    case EXCEPTION_ACCESS_VIOLATION:\r
393       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_ACCESS_VIOLATION");\r
394       break;\r
395    case EXCEPTION_DATATYPE_MISALIGNMENT:\r
396       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_DATATYPE_MISALIGNMENT");\r
397       break;\r
398    case EXCEPTION_BREAKPOINT:\r
399       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_BREAKPOINT");\r
400       break;\r
401    case EXCEPTION_SINGLE_STEP:\r
402       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_SINGLE_STEP");\r
403       break;\r
404    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:\r
405       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_ARRAY_BOUNDS_EXCEEDED");\r
406       break;\r
407    case EXCEPTION_FLT_DENORMAL_OPERAND:\r
408       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_FLT_DENORMAL_OPERAND");\r
409       break;\r
410    case EXCEPTION_FLT_DIVIDE_BY_ZERO:\r
411       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_FLT_DIVIDE_BY_ZERO");\r
412       break;\r
413    case EXCEPTION_FLT_INEXACT_RESULT:\r
414       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_FLT_INEXACT_RESULT");\r
415       break;\r
416    case EXCEPTION_FLT_INVALID_OPERATION:\r
417       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_FLT_INVALID_OPERATION");\r
418       break;\r
419    case EXCEPTION_FLT_OVERFLOW:\r
420       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_FLT_OVERFLOW");\r
421       break;\r
422    case EXCEPTION_FLT_STACK_CHECK:\r
423       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_FLT_STACK_CHECK");\r
424       break;\r
425    case EXCEPTION_FLT_UNDERFLOW:\r
426       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_FLT_UNDERFLOW");\r
427       break;\r
428    case EXCEPTION_INT_DIVIDE_BY_ZERO:\r
429       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_INT_DIVIDE_BY_ZERO");\r
430       break;\r
431    case EXCEPTION_INT_OVERFLOW:\r
432       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_INT_OVERFLOW");\r
433       break;\r
434    case EXCEPTION_PRIV_INSTRUCTION:\r
435       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_PRIV_INSTRUCTION");\r
436       break;\r
437    case EXCEPTION_IN_PAGE_ERROR:\r
438       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_IN_PAGE_ERROR");\r
439       break;\r
440    case EXCEPTION_ILLEGAL_INSTRUCTION:\r
441       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_ILLEGAL_INSTRUCTION");\r
442       break;\r
443    case EXCEPTION_NONCONTINUABLE_EXCEPTION:\r
444       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_NONCONTINUABLE_EXCEPTION");\r
445       break;\r
446    case EXCEPTION_STACK_OVERFLOW:\r
447       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_STACK_OVERFLOW");\r
448       break;\r
449    case EXCEPTION_INVALID_DISPOSITION:\r
450       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_INVALID_DISPOSITION");\r
451       break;\r
452    case EXCEPTION_GUARD_PAGE:\r
453       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_GUARD_PAGE");\r
454       break;\r
455    case EXCEPTION_INVALID_HANDLE:\r
456       V_BSTR(&v) = ::SysAllocString(L"EXCEPTION_INVALID_HANDLE");\r
457       break;\r
458    default:\r
459       V_BSTR(&v) = L"EXCEPTION_UNKNOWN";\r
460       break;\r
461    }\r
462    pElement->setAttribute(descName, v);\r
463    // Recycle variant\r
464    SysFreeString(V_BSTR(&v));\r
465 \r
466    //\r
467    // Set exception address\r
468    //\r
469    _tprintf_s(buf, _T("%#x"), pExceptionRecord->ExceptionAddress);\r
470    m_sAddress = sAddr;\r
471    V_VT(&v)    = VT_BSTR;\r
472    V_BSTR(&v)  = CUtility::AllocSysString(buf);\r
473    pElement->setAttribute(addrName, v);\r
474    // Recycle variant\r
475    SysFreeString(V_BSTR(&v));\r
476 \r
477    // Try to include symbolic information\r
478    m_exception_element = pElement;\r
479    AddressToSymbol(reinterpret_cast<DWORD_PTR>(pExceptionRecord->ExceptionAddress)-1,\r
480            CreateExceptionSymbolAttributes,\r
481            reinterpret_cast<void *>(this));\r
482 CleanUp:\r
483    ::SysFreeString(nodeName);\r
484    ::SysFreeString(modName);\r
485    ::SysFreeString(codeName);\r
486    ::SysFreeString(addrName);\r
487    SAFERELEASE(pElement);\r
488 \r
489    return pNode;\r
490 }\r
491 \r
492 //-----------------------------------------------------------------------------\r
493 // CExceptionReport::CreateProcessorNode\r
494 //\r
495 //\r
496 //\r
497 MSXML2::IXMLDOMNode*\r
498 CExceptionReport::CreateProcessorNode(MSXML2::IXMLDOMDocument* pDoc)\r
499 {\r
500    MSXML2::IXMLDOMNode*     pNode    = NULL;\r
501    MSXML2::IXMLDOMElement*  pElement = NULL;\r
502    BSTR nodeName                    = ::SysAllocString(L"Processor");\r
503    BSTR archName                    = ::SysAllocString(L"Architecture");\r
504    BSTR levelName                   = ::SysAllocString(L"Level");\r
505    BSTR numberName                  = ::SysAllocString(L"NumberOfProcessors");\r
506    SYSTEM_INFO si;\r
507    VARIANT v;\r
508 \r
509    // Create exception record node\r
510    pNode = CreateDOMNode(pDoc, MSXML2::NODE_ELEMENT, nodeName);\r
511 \r
512    // Get element interface\r
513    CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));\r
514 \r
515    //\r
516    // Get processor info\r
517    //\r
518    GetSystemInfo(&si);\r
519 \r
520    //\r
521    // Set architecture\r
522    //\r
523    V_VT(&v) = VT_BSTR;\r
524    switch (si.wProcessorArchitecture)\r
525    {\r
526    case PROCESSOR_ARCHITECTURE_INTEL:\r
527       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_INTEL");\r
528       break;\r
529    case PROCESSOR_ARCHITECTURE_MIPS:\r
530       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_MIPS");\r
531       break;\r
532    case PROCESSOR_ARCHITECTURE_ALPHA:\r
533       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_ALPHA");\r
534       break;\r
535    case PROCESSOR_ARCHITECTURE_PPC:\r
536       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_PPC");\r
537       break;\r
538    case PROCESSOR_ARCHITECTURE_SHX:\r
539       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_SHX");\r
540       break;\r
541    case PROCESSOR_ARCHITECTURE_ARM:\r
542       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_ARM");\r
543       break;\r
544    case PROCESSOR_ARCHITECTURE_IA64:\r
545       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_IA64");\r
546       break;\r
547    case PROCESSOR_ARCHITECTURE_ALPHA64:\r
548       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_ALPHA64");\r
549       break;\r
550    case PROCESSOR_ARCHITECTURE_AMD64:\r
551       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_AMD64");\r
552       break;\r
553    case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:\r
554       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_IA32_ON_WIN64");\r
555       break;\r
556    case PROCESSOR_ARCHITECTURE_UNKNOWN:\r
557       V_BSTR(&v) = ::SysAllocString(L"PROCESSOR_ARCHITECTURE_UNKNOWN");\r
558       break;\r
559    default:\r
560       V_BSTR(&v) = ::SysAllocString(L"Unknown");\r
561    }\r
562    pElement->setAttribute(archName, v);\r
563    // Recycle variant\r
564    SysFreeString(V_BSTR(&v));\r
565 \r
566    //\r
567    // Set level\r
568    //\r
569    V_VT(&v) = VT_BSTR;\r
570    if (PROCESSOR_ARCHITECTURE_INTEL == si.wProcessorArchitecture)\r
571    {\r
572       switch (si.wProcessorLevel)\r
573       {\r
574       case 3:\r
575          V_BSTR(&v) = ::SysAllocString(L"Intel 30386");\r
576          break;\r
577       case 4:\r
578          V_BSTR(&v) = ::SysAllocString(L"Intel 80486");\r
579          break;\r
580       case 5:\r
581          V_BSTR(&v) = ::SysAllocString(L"Intel Pentium");\r
582          break;\r
583       case 6:\r
584          V_BSTR(&v) = ::SysAllocString(L"Intel Pentium Pro or Pentium II");\r
585          break;\r
586       default:\r
587          V_BSTR(&v) = ::SysAllocString(L"Unknown");\r
588       }\r
589    }\r
590    pElement->setAttribute(levelName, v);\r
591    // Recycle variant\r
592    SysFreeString(V_BSTR(&v));\r
593 \r
594    //\r
595    // Set num of processors\r
596    //\r
597    V_VT(&v) = VT_I4;\r
598    V_I4(&v) = si.dwNumberOfProcessors;\r
599    pElement->setAttribute(numberName, v);\r
600 \r
601 CleanUp:\r
602    ::SysFreeString(nodeName);\r
603    ::SysFreeString(archName);\r
604    ::SysFreeString(levelName);\r
605    ::SysFreeString(numberName);\r
606    SAFERELEASE(pElement);\r
607 \r
608    return pNode;\r
609 }\r
610 \r
611 //-----------------------------------------------------------------------------\r
612 // CExceptionReport::CreateOSNode\r
613 //\r
614 //\r
615 //\r
616 MSXML2::IXMLDOMNode* \r
617 CExceptionReport::CreateOSNode(MSXML2::IXMLDOMDocument* pDoc)\r
618 {\r
619    MSXML2::IXMLDOMNode*     pNode    = NULL;\r
620    MSXML2::IXMLDOMElement*  pElement = NULL;\r
621    BSTR nodeName                    = ::SysAllocString(L"OperatingSystem");\r
622    BSTR majorName                   = ::SysAllocString(L"MajorVersion");\r
623    BSTR minorName                   = ::SysAllocString(L"MinorVersion");\r
624    BSTR buildName                   = ::SysAllocString(L"BuildNumber");\r
625    BSTR csdName                     = ::SysAllocString(L"CSDVersion");\r
626    OSVERSIONINFO oi;\r
627    VARIANT v;\r
628 \r
629    // Create exception record node\r
630    pNode = CreateDOMNode(pDoc, MSXML2::NODE_ELEMENT, nodeName);\r
631 \r
632    // Get element interface\r
633    CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));\r
634 \r
635    //\r
636    // Get OS info\r
637    //\r
638    oi.dwOSVersionInfoSize = sizeof(oi);\r
639    GetVersionEx(&oi);\r
640 \r
641    //\r
642    // Set major version\r
643    //\r
644    V_VT(&v) = VT_I4;\r
645    V_I4(&v) = oi.dwMajorVersion;\r
646    pElement->setAttribute(majorName, v);\r
647 \r
648    //\r
649    // Set minor version\r
650    //\r
651    V_VT(&v) = VT_I4;\r
652    V_I4(&v) = oi.dwMinorVersion;\r
653    pElement->setAttribute(minorName, v);\r
654 \r
655    //\r
656    // Set build version\r
657    //\r
658    V_VT(&v) = VT_I4;\r
659    V_I4(&v) = oi.dwBuildNumber;\r
660    pElement->setAttribute(buildName, v);\r
661 \r
662    //\r
663    // Set CSD version\r
664    //\r
665    V_VT(&v) = VT_BSTR;\r
666    V_BSTR(&v) = CUtility::AllocSysString(oi.szCSDVersion);\r
667    pElement->setAttribute(csdName, v);\r
668    ::SysFreeString(V_BSTR(&v));\r
669 \r
670 CleanUp:\r
671    ::SysFreeString(nodeName);\r
672    ::SysFreeString(majorName);\r
673    ::SysFreeString(minorName);\r
674    ::SysFreeString(buildName);\r
675    ::SysFreeString(csdName);\r
676    SAFERELEASE(pElement);\r
677 \r
678    return pNode;\r
679 }\r
680 \r
681 //-----------------------------------------------------------------------------\r
682 // CExceptionReport::CreateModulesNode\r
683 //\r
684 //\r
685 //\r
686 MSXML2::IXMLDOMNode* \r
687 CExceptionReport::CreateModulesNode(MSXML2::IXMLDOMDocument* pDoc)\r
688 {\r
689    MSXML2::IXMLDOMNode*     pNode    = NULL;\r
690    MSXML2::IXMLDOMNode*     pNode2   = NULL;\r
691    MSXML2::IXMLDOMNode*     pNewNode = NULL;\r
692    MSXML2::IXMLDOMElement*  pElement = NULL;\r
693    MSXML2::IXMLDOMElement*  pElement2= NULL;\r
694    BSTR nodeName                    = ::SysAllocString(L"Modules");\r
695    BSTR nodeName2                   = ::SysAllocString(L"Module");\r
696    BSTR fullPath                    = ::SysAllocString(L"FullPath");\r
697    BSTR baseAddrName                = ::SysAllocString(L"BaseAddress");\r
698    BSTR sizeName                    = ::SysAllocString(L"Size");\r
699    BSTR timeStampName               = ::SysAllocString(L"TimeStamp");\r
700    BSTR fileVerName                 = ::SysAllocString(L"FileVersion");\r
701    BSTR prodVerName                 = ::SysAllocString(L"ProductVersion");\r
702 \r
703    string sAddr;\r
704    VARIANT v;\r
705 \r
706 \r
707    // Create modules node\r
708    pNode = CreateDOMNode(pDoc, MSXML2::NODE_ELEMENT, nodeName);\r
709 \r
710    //\r
711    // Add module information (freeing storage as we go)\r
712    // \r
713    MINIDUMP_MODULE_CALLBACK item;\r
714    std::vector<MINIDUMP_MODULE_CALLBACK>::iterator iter;\r
715    for (iter = m_modules.begin(); iter != m_modules.end(); iter++)\r
716    {\r
717            item = *iter;\r
718       // Create module node\r
719       pNode2 = CreateDOMNode(pDoc, MSXML2::NODE_ELEMENT, nodeName2);\r
720 \r
721       // Get element interface\r
722       CHECKHR(pNode2->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));\r
723 \r
724       //\r
725       // Set full path\r
726       //\r
727       V_VT(&v) = VT_BSTR;\r
728           V_BSTR(&v) = SysAllocString(item.FullPath);\r
729       pElement->setAttribute(fullPath, v);\r
730       // Recycle variant\r
731       SysFreeString(V_BSTR(&v));\r
732 \r
733       //\r
734       // Set base address\r
735       //\r
736           TCHAR buf[MAX_PATH] = {0};\r
737           _tprintf_s(buf, addressFormat, item.BaseOfImage);\r
738       V_VT(&v) = VT_BSTR;\r
739           V_BSTR(&v) = CUtility::AllocSysString(buf);\r
740       pElement->setAttribute(baseAddrName, v);\r
741       // Recycle variant\r
742       SysFreeString(V_BSTR(&v));\r
743 \r
744       //\r
745       // Set module size\r
746       //\r
747           _tprintf_s(buf, sizeFormat, item.SizeOfImage);\r
748       V_VT(&v) = VT_BSTR;\r
749           V_BSTR(&v) = CUtility::AllocSysString(buf);\r
750       pElement->setAttribute(sizeName, v);\r
751       // Recycle variant\r
752       SysFreeString(V_BSTR(&v));\r
753 \r
754       //\r
755       // Set timestamp\r
756       //\r
757       FILETIME    ft = CUtility::getLastWriteFileTime(item.FullPath);\r
758       SYSTEMTIME  st = {0};\r
759 \r
760       FileTimeToSystemTime(&ft, &st);\r
761 \r
762           _tprintf_s(buf, _T("%02u/%02u/%04u %02u:%02u:%02u"), \r
763                   st.wMonth, \r
764                   st.wDay, \r
765                   st.wYear, \r
766                   st.wHour, \r
767                   st.wMinute, \r
768                   st.wSecond);\r
769 \r
770       V_VT(&v) = VT_BSTR;\r
771           V_BSTR(&v) = CUtility::AllocSysString(buf);\r
772       pElement->setAttribute(timeStampName, v);\r
773       // Recycle variant\r
774       SysFreeString(V_BSTR(&v));\r
775 \r
776       //\r
777       // Set file version\r
778       //\r
779           _tprintf_s(buf,"%d.%d.%d.%d", \r
780                   HIWORD(item.VersionInfo.dwFileVersionMS),\r
781                   LOWORD(item.VersionInfo.dwFileVersionMS),\r
782                   HIWORD(item.VersionInfo.dwFileVersionLS),\r
783                   LOWORD(item.VersionInfo.dwFileVersionLS));\r
784 \r
785           V_VT(&v) = VT_BSTR;\r
786           V_BSTR(&v) = CUtility::AllocSysString(buf);\r
787       pElement->setAttribute(fileVerName, v);\r
788       // Recycle variant\r
789       SysFreeString(V_BSTR(&v));\r
790 \r
791       //\r
792       // Set product version\r
793       //\r
794           _tprintf_s(buf, "%d.%d.%d.%d", \r
795                   HIWORD(item.VersionInfo.dwProductVersionMS),\r
796                   LOWORD(item.VersionInfo.dwProductVersionMS),\r
797                   HIWORD(item.VersionInfo.dwProductVersionLS),\r
798                   LOWORD(item.VersionInfo.dwProductVersionLS));\r
799 \r
800           V_VT(&v) = VT_BSTR;\r
801           V_BSTR(&v) = CUtility::AllocSysString(buf);\r
802       pElement->setAttribute(prodVerName, v);\r
803       // Recycle variant\r
804       SysFreeString(V_BSTR(&v));\r
805 \r
806       //\r
807       // Append module to modules\r
808       //\r
809       pNode->appendChild(pNode2, &pNewNode);\r
810       // The XML Document should now own the node.\r
811       SAFERELEASE(pNode2);\r
812       SAFERELEASE(pElement2);\r
813       SAFERELEASE(pNewNode);\r
814 \r
815           free(item.FullPath);\r
816    }\r
817    m_modules.clear();\r
818 \r
819 CleanUp:\r
820 \r
821    ::SysFreeString(nodeName);\r
822    ::SysFreeString(nodeName2);\r
823    ::SysFreeString(fullPath);\r
824    ::SysFreeString(baseAddrName);\r
825    ::SysFreeString(sizeName);\r
826    ::SysFreeString(timeStampName);\r
827    ::SysFreeString(fileVerName);\r
828    ::SysFreeString(prodVerName);\r
829    SAFERELEASE(pNode2);\r
830    SAFERELEASE(pNewNode);\r
831    SAFERELEASE(pElement);\r
832    SAFERELEASE(pElement2);\r
833 \r
834    return pNode;\r
835 }\r
836 \r
837 //-----------------------------------------------------------------------------\r
838 // CreateMsgNode\r
839 //\r
840 // Builds the application-defined message node\r
841 //\r
842 MSXML2::IXMLDOMNode * \r
843 CExceptionReport::CreateMsgNode(MSXML2::IXMLDOMDocument* pDoc, BSTR message)\r
844 {\r
845    MSXML2::IXMLDOMNode*     pNode    = NULL;\r
846    MSXML2::IXMLDOMElement*  pElement = NULL;\r
847    BSTR nodeName                    = ::SysAllocString(L"ApplicationDescription");\r
848 \r
849    // Create CrashDescription record node\r
850    pNode = CreateDOMNode(pDoc, MSXML2::NODE_ELEMENT, nodeName);\r
851 \r
852    // Get element interface\r
853    CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));\r
854 \r
855    pElement->put_text(message);\r
856 \r
857 CleanUp:\r
858    ::SysFreeString(nodeName);\r
859    SAFERELEASE(pElement);\r
860 \r
861    return pNode;\r
862 }\r
863 \r
864 //-----------------------------------------------------------------------------\r
865 // CreateWalkbackEntryNode\r
866 //\r
867 // Create a single node in the stack walback\r
868 //\r
869 void\r
870 CExceptionReport::CreateWalkbackEntryNode(DWORD_PTR address, const char *ImageName,\r
871                                                                           const char *FunctionName, DWORD_PTR functionDisp,\r
872                                                                           const char *Filename, DWORD LineNumber, DWORD lineDisp,\r
873                                                                           void *data)\r
874 {\r
875    MSXML2::IXMLDOMNode*     pNode    = NULL;\r
876    MSXML2::IXMLDOMElement*  pElement = NULL;\r
877    MSXML2::IXMLDOMNode*     pNewNode = NULL;\r
878    string sAddr;\r
879    BSTR nodeName                    = ::SysAllocString(L"Frame");\r
880    BSTR frameName                                       = ::SysAllocString(L"FrameNumber");\r
881    BSTR addrName                                        = ::SysAllocString(L"ReturnAddress");\r
882    BSTR moduleName                                      = ::SysAllocString(L"ModuleName");\r
883    BSTR funcName                                        = ::SysAllocString(L"FunctionName");\r
884    BSTR funcDispName                            = ::SysAllocString(L"FunctionDisplacement");\r
885    BSTR fileName                                        = ::SysAllocString(L"Filename");\r
886    BSTR lineName                                        = ::SysAllocString(L"LineNumber");\r
887    BSTR lineDispName                            = ::SysAllocString(L"LineDisplacement");\r
888    CExceptionReport     *self = reinterpret_cast<CExceptionReport *>(data);\r
889 \r
890    // Create frame record node\r
891    pNode = self->CreateDOMNode(self->m_stack_doc, MSXML2::NODE_ELEMENT, nodeName);\r
892 \r
893    // Get element interface\r
894    CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));\r
895 \r
896 \r
897    VARIANT v;\r
898 \r
899    self->m_frameNumber++;\r
900    TCHAR buf[MAX_PATH] = {0};\r
901    _tprintf_s(buf, _T("%d"), self->m_frameNumber);\r
902 \r
903    V_VT(&v) = VT_BSTR;\r
904    V_BSTR(&v) = CUtility::AllocSysString(buf);\r
905    pElement->setAttribute(frameName, v);\r
906    // Recycle variant\r
907    SysFreeString(V_BSTR(&v));\r
908 \r
909    _tprintf_s(buf, offsetFormat, address);\r
910    V_VT(&v) = VT_BSTR;\r
911    V_BSTR(&v) = CUtility::AllocSysString(buf);\r
912    pElement->setAttribute(addrName, v);\r
913    // Recycle variant\r
914    SysFreeString(V_BSTR(&v));\r
915 \r
916    if (ImageName != NULL) {\r
917                 V_VT(&v) = VT_BSTR;\r
918                 V_BSTR(&v) = CUtility::AllocSysString(ImageName);\r
919                 pElement->setAttribute(moduleName, v);\r
920                 // Recycle variant\r
921                 SysFreeString(V_BSTR(&v));\r
922    }\r
923 \r
924    if (FunctionName != NULL) {\r
925                 V_VT(&v) = VT_BSTR;\r
926                 V_BSTR(&v) = CUtility::AllocSysString(FunctionName);\r
927                 pElement->setAttribute(funcName, v);\r
928                 // Recycle variant\r
929                 SysFreeString(V_BSTR(&v));\r
930                 _tprintf_s(buf, offsetFormat, functionDisp);\r
931                 V_VT(&v) = VT_BSTR;\r
932                 V_BSTR(&v) = CUtility::AllocSysString(buf);\r
933                 pElement->setAttribute(funcDispName, v);\r
934                 // Recycle variant\r
935                 SysFreeString(V_BSTR(&v));\r
936    }\r
937 \r
938    if (Filename != NULL) {\r
939                 V_VT(&v) = VT_BSTR;\r
940                 V_BSTR(&v) = CUtility::AllocSysString(Filename);\r
941                 pElement->setAttribute(fileName, v);\r
942                 // Recycle variant\r
943                 SysFreeString(V_BSTR(&v));\r
944 \r
945                 _tprintf_s(buf, _T("%d"), LineNumber);\r
946                 V_VT(&v) = VT_BSTR;\r
947                 V_BSTR(&v) = CUtility::AllocSysString(buf);\r
948                 pElement->setAttribute(lineName, v);\r
949                 // Recycle variant\r
950                 SysFreeString(V_BSTR(&v));\r
951 \r
952                 _tprintf_s(buf, offsetFormat, lineDisp);\r
953                 V_VT(&v) = VT_BSTR;\r
954                 V_BSTR(&v) = CUtility::AllocSysString(buf);\r
955                 pElement->setAttribute(lineDispName, v);\r
956                 // Recycle variant\r
957                 SysFreeString(V_BSTR(&v));\r
958    }\r
959    // add to walkback element\r
960 \r
961    self->m_stack_element->appendChild(pNode, &pNewNode);\r
962    SAFERELEASE(pNewNode);\r
963    // The XML Document should now own the node.\r
964 CleanUp:\r
965    SAFERELEASE(pNode);\r
966    SAFERELEASE(pElement);\r
967    ::SysFreeString(nodeName);\r
968    ::SysFreeString(frameName);\r
969    ::SysFreeString(addrName);\r
970    ::SysFreeString(moduleName);\r
971    ::SysFreeString(funcName);\r
972    ::SysFreeString(funcDispName);\r
973    ::SysFreeString(fileName);\r
974    ::SysFreeString(lineName);\r
975    ::SysFreeString(lineDispName);\r
976 }\r
977 \r
978 //-----------------------------------------------------------------------------\r
979 // CreateWalkbackNode\r
980 //\r
981 // Builds the stack walkback list\r
982 //\r
983 MSXML2::IXMLDOMNode * \r
984 CExceptionReport::CreateWalkbackNode(MSXML2::IXMLDOMDocument* pDoc, CONTEXT *pContext)\r
985 {\r
986    MSXML2::IXMLDOMNode*     pNode    = NULL;\r
987 \r
988    MSXML2::IXMLDOMElement*  pElement = NULL;\r
989    BSTR nodeName                    = ::SysAllocString(L"CallStack");\r
990 \r
991    // Create CallStack record node\r
992    pNode = CreateDOMNode(pDoc, MSXML2::NODE_ELEMENT, nodeName);\r
993 \r
994    // Get element interface\r
995    CHECKHR(pNode->QueryInterface(MSXML2::IID_IXMLDOMElement, (void**)&pElement));\r
996 \r
997    // create the trace\r
998    //  set static variables for use by CreateWalkbackEntryNode\r
999    m_stack_element = pElement;\r
1000    m_stack_doc = pDoc;\r
1001    m_frameNumber = 0;\r
1002    // If no context is supplied, skip 1 frames:\r
1003    //  1 this function\r
1004    //  ??\r
1005    DoStackTrace(pContext == NULL ? 1 : 0, 9999, CreateWalkbackEntryNode, pContext, this);\r
1006 \r
1007 CleanUp:\r
1008    ::SysFreeString(nodeName);\r
1009    SAFERELEASE(pElement);\r
1010 \r
1011    return pNode;\r
1012 }\r
1013 \r
1014 //-----------------------------------------------------------------------------\r
1015 // CExceptionReport::miniDumpCallback\r
1016 //\r
1017 // Mini dump module callback.  Hit once for each module processed by\r
1018 // MiniDumpWriteDump.  Builds a linked list of all module names which is\r
1019 // eventually used to create the <modules> node in the XML log file.\r
1020 //\r
1021 BOOL CALLBACK \r
1022 CExceptionReport::miniDumpCallback(PVOID data,\r
1023                                    CONST PMINIDUMP_CALLBACK_INPUT CallbackInput,\r
1024                                    PMINIDUMP_CALLBACK_OUTPUT)\r
1025 {\r
1026    CExceptionReport *self = reinterpret_cast<CExceptionReport*>(data);\r
1027    if (ModuleCallback == CallbackInput->CallbackType)\r
1028    {\r
1029       MINIDUMP_MODULE_CALLBACK item;\r
1030 \r
1031       item = CallbackInput->Module;\r
1032       item.FullPath = _wcsdup(CallbackInput->Module.FullPath);\r
1033           self->m_modules.push_back(item);\r
1034    }\r
1035 \r
1036    return TRUE;\r
1037 }