OSDN Git Service

Call CGitCall::OnEnd() when git.exe ended
[tortoisegit/TortoiseGitJp.git] / src / crashrpt / SymbolEngine.h
1 /*----------------------------------------------------------------------\r
2 "Debugging Applications" (Microsoft Press)\r
3 Copyright (c) 1997-2000 John Robbins -- All rights reserved.\r
4 ------------------------------------------------------------------------\r
5 This class is a paper-thin layer around the DBGHELP.DLL symbol engine.\r
6 \r
7 This class wraps only those functions that take the unique\r
8 HANDLE value. Other DBGHELP.DLL symbol engine functions are global in\r
9 scope, so I didn\92t wrap them with this class.\r
10 \r
11 ------------------------------------------------------------------------\r
12 Compilation Defines:\r
13 \r
14 DO_NOT_WORK_AROUND_SRCLINE_BUG - If defined, the class will NOT work\r
15                                  around the SymGetLineFromAddr bug where\r
16                                  PDB file lookups fail after the first\r
17                                  lookup.\r
18 USE_BUGSLAYERUTIL - If defined, the class will have another\r
19                     initialization method, BSUSymInitialize, which will\r
20                     use BSUSymInitialize from BUGSLAYERUTIL.DLL to\r
21                     initialize the symbol engine and allow the invade\r
22                     process flag to work for all Win32 operating systems.\r
23                     If you use this define, you must use\r
24                     BUGSLAYERUTIL.H to include this file.\r
25 ----------------------------------------------------------------------*/\r
26 \r
27 #ifndef _SYMBOLENGINE_H\r
28 #define _SYMBOLENGINE_H\r
29 \r
30 // You could include either IMAGEHLP.DLL or DBGHELP.DLL.\r
31 #include "imagehlp.h"\r
32 #include <tchar.h>\r
33 \r
34 // Include these in case the user forgets to link against them.\r
35 #pragma comment (lib,"dbghelp.lib")\r
36 #pragma comment (lib,"version.lib")\r
37 \r
38 // The great Bugslayer idea of creating wrapper classes on structures\r
39 // that have size fields came from fellow MSJ columnist, Paul DiLascia.\r
40 // Thanks, Paul!\r
41 \r
42 // I didn\92t wrap IMAGEHLP_SYMBOL because that is a variable-size\r
43 // structure.\r
44 \r
45 // The IMAGEHLP_MODULE wrapper class\r
46 struct CImageHlp_Module : public IMAGEHLP_MODULE\r
47 {\r
48     CImageHlp_Module ( )\r
49     {\r
50         memset ( this , NULL , sizeof ( IMAGEHLP_MODULE ) ) ;\r
51         SizeOfStruct = sizeof ( IMAGEHLP_MODULE ) ;\r
52     }\r
53 } ;\r
54 \r
55 // The IMAGEHLP_LINE wrapper class\r
56 struct CImageHlp_Line : public IMAGEHLP_LINE\r
57 {\r
58     CImageHlp_Line ( )\r
59     {\r
60         memset ( this , NULL , sizeof ( IMAGEHLP_LINE ) ) ;\r
61         SizeOfStruct = sizeof ( IMAGEHLP_LINE ) ;\r
62     }\r
63 } ;\r
64 \r
65 // The symbol engine class\r
66 class CSymbolEngine\r
67 {\r
68 /*----------------------------------------------------------------------\r
69                   Public Construction and Destruction\r
70 ----------------------------------------------------------------------*/\r
71 public      :\r
72     // To use this class, call the SymInitialize member function to\r
73     // initialize the symbol engine and then use the other member\r
74     // functions in place of their corresponding DBGHELP.DLL functions.\r
75     CSymbolEngine ( void )\r
76     {\r
77     }\r
78 \r
79     virtual ~CSymbolEngine ( void )\r
80     {\r
81     }\r
82 \r
83 /*----------------------------------------------------------------------\r
84                   Public Helper Information Functions\r
85 ----------------------------------------------------------------------*/\r
86 public      :\r
87 \r
88     // Returns the file version of DBGHELP.DLL being used.\r
89     //  To convert the return values into a readable format:\r
90     //  wsprintf ( szVer                  ,\r
91     //              ( "%d.%02d.%d.%d" ) ,\r
92     //             HIWORD ( dwMS )        ,\r
93     //             LOWORD ( dwMS )        ,\r
94     //             HIWORD ( dwLS )        ,\r
95     //             LOWORD ( dwLS )         ) ;\r
96     //  szVer will contain a string like: 5.00.1878.1\r
97     BOOL GetImageHlpVersion ( DWORD & dwMS , DWORD & dwLS )\r
98     {\r
99         return( GetInMemoryFileVersion (  ( "DBGHELP.DLL" ) ,\r
100                                          dwMS                 ,\r
101                                          dwLS                  ) ) ;\r
102     }\r
103 \r
104     BOOL GetDbgHelpVersion ( DWORD & dwMS , DWORD & dwLS )\r
105     {\r
106         return( GetInMemoryFileVersion (  ( "DBGHELP.DLL" ) ,\r
107                                          dwMS                 ,\r
108                                          dwLS                  ) ) ;\r
109     }\r
110 \r
111     // Returns the file version of the PDB reading DLLs\r
112     BOOL GetPDBReaderVersion ( DWORD & dwMS , DWORD & dwLS )\r
113     {\r
114         // First try MSDBI.DLL.\r
115         if ( TRUE == GetInMemoryFileVersion (  ( "MSDBI.DLL" ) ,\r
116                                               dwMS               ,\r
117                                               dwLS                ) )\r
118         {\r
119             return ( TRUE ) ;\r
120         }\r
121         else if ( TRUE == GetInMemoryFileVersion (  ( "MSPDB60.DLL" ),\r
122                                                    dwMS                ,\r
123                                                    dwLS               ))\r
124         {\r
125             return ( TRUE ) ;\r
126         }\r
127         // Just fall down to MSPDB50.DLL.\r
128         return ( GetInMemoryFileVersion (  ( "MSPDB50.DLL" ) ,\r
129                                           dwMS                 ,\r
130                                           dwLS                  ) ) ;\r
131     }\r
132 \r
133     // The worker function used by the previous two functions\r
134     BOOL GetInMemoryFileVersion ( LPCTSTR szFile ,\r
135                                   DWORD & dwMS   ,\r
136                                   DWORD & dwLS    )\r
137     {\r
138         HMODULE hInstIH = GetModuleHandle ( szFile ) ;\r
139 \r
140         // Get the full filename of the loaded version.\r
141         TCHAR szImageHlp[ MAX_PATH ] ;\r
142         GetModuleFileName ( hInstIH , szImageHlp , MAX_PATH ) ;\r
143 \r
144         dwMS = 0 ;\r
145         dwLS = 0 ;\r
146 \r
147         // Get the version information size.\r
148         DWORD dwVerInfoHandle ;\r
149         DWORD dwVerSize       ;\r
150 \r
151         dwVerSize = GetFileVersionInfoSize ( szImageHlp       ,\r
152                                              &dwVerInfoHandle  ) ;\r
153         if ( 0 == dwVerSize )\r
154         {\r
155             return ( FALSE ) ;\r
156         }\r
157 \r
158         // Got the version size, now get the version information.\r
159         LPVOID lpData = (LPVOID)new TCHAR [ dwVerSize ] ;\r
160         if ( FALSE == GetFileVersionInfo ( szImageHlp       ,\r
161                                            dwVerInfoHandle  ,\r
162                                            dwVerSize        ,\r
163                                            lpData            ) )\r
164         {\r
165             delete [] lpData ;\r
166             return ( FALSE ) ;\r
167         }\r
168 \r
169         VS_FIXEDFILEINFO * lpVerInfo ;\r
170         UINT uiLen ;\r
171         BOOL bRet = VerQueryValue ( lpData              ,\r
172                                      ( "\\" )         ,\r
173                                     (LPVOID*)&lpVerInfo ,\r
174                                     &uiLen               ) ;\r
175         if ( TRUE == bRet )\r
176         {\r
177             dwMS = lpVerInfo->dwFileVersionMS ;\r
178             dwLS = lpVerInfo->dwFileVersionLS ;\r
179         }\r
180 \r
181         delete [] lpData ;\r
182 \r
183         return ( bRet ) ;\r
184     }\r
185 \r
186 /*----------------------------------------------------------------------\r
187                    Public Initialization and Cleanup\r
188 ----------------------------------------------------------------------*/\r
189 public      :\r
190 \r
191     BOOL SymInitialize ( IN HANDLE   hProcess       ,\r
192                          IN LPSTR    UserSearchPath ,\r
193                          IN BOOL     fInvadeProcess  )\r
194     {\r
195         m_hProcess = hProcess ;\r
196         return ( ::SymInitialize ( hProcess       ,\r
197                                    UserSearchPath ,\r
198                                    fInvadeProcess  ) ) ;\r
199     }\r
200 \r
201 #ifdef USE_BUGSLAYERUTIL\r
202     BOOL BSUSymInitialize ( DWORD  dwPID          ,\r
203                             HANDLE hProcess       ,\r
204                             PSTR   UserSearchPath ,\r
205                             BOOL   fInvadeProcess  )\r
206     {\r
207         m_hProcess = hProcess ;\r
208         return ( ::BSUSymInitialize ( dwPID          ,\r
209                                       hProcess       ,\r
210                                       UserSearchPath ,\r
211                                       fInvadeProcess  ) ) ;\r
212     }\r
213 #endif  // USE_BUGSLAYERUTIL\r
214     BOOL SymCleanup ( void )\r
215     {\r
216         return ( ::SymCleanup ( m_hProcess ) ) ;\r
217     }\r
218 \r
219 /*----------------------------------------------------------------------\r
220                        Public Module Manipulation\r
221 ----------------------------------------------------------------------*/\r
222 public      :\r
223 \r
224     BOOL SymEnumerateModules ( IN PSYM_ENUMMODULES_CALLBACK\r
225                                                     EnumModulesCallback,\r
226                                IN PVOID             UserContext )\r
227     {\r
228         return ( ::SymEnumerateModules ( m_hProcess           ,\r
229                                          EnumModulesCallback  ,\r
230                                          UserContext           ) ) ;\r
231     }\r
232 \r
233     BOOL SymLoadModule ( IN  HANDLE hFile       ,\r
234                          IN  PSTR   ImageName   ,\r
235                          IN  PSTR   ModuleName  ,\r
236                          IN  DWORD_PTR  BaseOfDll   ,\r
237                          IN  DWORD  SizeOfDll    )\r
238     {\r
239         return ( ::SymLoadModule ( m_hProcess   ,\r
240                                    hFile        ,\r
241                                    ImageName    ,\r
242                                    ModuleName   ,\r
243                                    BaseOfDll    ,\r
244                                    SizeOfDll     ) != NULL) ;\r
245     }\r
246 \r
247     BOOL EnumerateLoadedModules ( IN PENUMLOADED_MODULES_CALLBACK\r
248                                               EnumLoadedModulesCallback,\r
249                                   IN PVOID         UserContext       )\r
250     {\r
251         return ( ::EnumerateLoadedModules ( m_hProcess                ,\r
252                                             EnumLoadedModulesCallback ,\r
253                                             UserContext              ));\r
254     }\r
255 \r
256     BOOL SymUnloadModule ( IN  DWORD_PTR BaseOfDll )\r
257     {\r
258         return ( ::SymUnloadModule ( m_hProcess , BaseOfDll ) ) ;\r
259     }\r
260 \r
261     BOOL SymGetModuleInfo ( IN  DWORD_PTR        dwAddr     ,\r
262                             OUT PIMAGEHLP_MODULE ModuleInfo  )\r
263     {\r
264         return ( ::SymGetModuleInfo ( m_hProcess    ,\r
265                                       dwAddr        ,\r
266                                       ModuleInfo     ) ) ;\r
267     }\r
268 \r
269     DWORD SymGetModuleBase ( IN DWORD_PTR dwAddr )\r
270     {\r
271         return ( ::SymGetModuleBase ( m_hProcess , dwAddr )  != NULL ) ;\r
272     }\r
273 \r
274 /*----------------------------------------------------------------------\r
275                        Public Symbol Manipulation\r
276 ----------------------------------------------------------------------*/\r
277 public      :\r
278 \r
279     BOOL SymEnumerateSymbols (IN DWORD_PTR          BaseOfDll,\r
280                               IN PSYM_ENUMSYMBOLS_CALLBACK\r
281                                                     EnumSymbolsCallback,\r
282                               IN PVOID                     UserContext )\r
283     {\r
284         return ( ::SymEnumerateSymbols ( m_hProcess          ,\r
285                                          BaseOfDll           ,\r
286                                          EnumSymbolsCallback ,\r
287                                          UserContext          ) ) ;\r
288     }\r
289 \r
290     BOOL SymGetSymFromAddr ( IN  DWORD_PTR           dwAddr          ,\r
291                              OUT PDWORD_PTR          pdwDisplacement ,\r
292                              OUT PIMAGEHLP_SYMBOL    Symbol           )\r
293     {\r
294         return ( ::SymGetSymFromAddr ( m_hProcess       ,\r
295                                        dwAddr           ,\r
296                                        pdwDisplacement  ,\r
297                                        Symbol            ) ) ;\r
298     }\r
299 \r
300     BOOL SymGetSymFromName ( IN  LPSTR            Name   ,\r
301                              OUT PIMAGEHLP_SYMBOL Symbol  )\r
302     {\r
303         return ( ::SymGetSymFromName ( m_hProcess ,\r
304                                        Name       ,\r
305                                        Symbol      ) ) ;\r
306     }\r
307 \r
308     BOOL SymGetSymNext ( IN OUT PIMAGEHLP_SYMBOL Symbol )\r
309     {\r
310         return ( ::SymGetSymNext ( m_hProcess , Symbol ) ) ;\r
311     }\r
312 \r
313     BOOL SymGetSymPrev ( IN OUT PIMAGEHLP_SYMBOL Symbol )\r
314     {\r
315         return ( ::SymGetSymPrev ( m_hProcess , Symbol ) ) ;\r
316     }\r
317 \r
318 /*----------------------------------------------------------------------\r
319                     Public Source Line Manipulation\r
320 ----------------------------------------------------------------------*/\r
321 public      :\r
322 \r
323     BOOL SymGetLineFromAddr ( IN  DWORD_PTR       dwAddr          ,\r
324                               OUT PDWORD          pdwDisplacement ,\r
325                               OUT PIMAGEHLP_LINE Line             )\r
326     {\r
327 \r
328 #ifdef DO_NOT_WORK_AROUND_SRCLINE_BUG\r
329         // Just pass along the values returned by the main function.\r
330         return ( ::SymGetLineFromAddr ( m_hProcess      ,\r
331                                         dwAddr          ,\r
332                                         pdwDisplacement ,\r
333                                         Line             ) ) ;\r
334 \r
335 #else\r
336         // The problem is that the symbol engine finds only those source\r
337         // line addresses (after the first lookup) that fall exactly on\r
338         // a zero displacement. I\92ll walk backward 100 bytes to\r
339         // find the line and return the proper displacement.\r
340         DWORD dwTempDis = 0 ;\r
341         while ( FALSE == ::SymGetLineFromAddr ( m_hProcess          ,\r
342                                                 dwAddr - dwTempDis  ,\r
343                                                 pdwDisplacement     ,\r
344                                                 Line                 ) )\r
345         {\r
346             dwTempDis += 1 ;\r
347             if ( 100 == dwTempDis )\r
348             {\r
349                 return ( FALSE ) ;\r
350             }\r
351         }\r
352         // I found it and the source line information is correct, so\r
353         // change the displacement if I had to search backward to find\r
354         // the source line.\r
355         if ( 0 != dwTempDis )\r
356         {\r
357             *pdwDisplacement = dwTempDis ;\r
358         }\r
359         return ( TRUE ) ;\r
360 #endif // DO_NOT_WORK_AROUND_SRCLINE_BUG\r
361     }\r
362 \r
363     BOOL SymGetLineFromName ( IN     LPSTR          ModuleName      ,\r
364                               IN     LPSTR          FileName        ,\r
365                               IN     DWORD          dwLineNumber    ,\r
366                               OUT    PLONG          plDisplacement  ,\r
367                               IN OUT PIMAGEHLP_LINE Line             )\r
368     {\r
369         return ( ::SymGetLineFromName ( m_hProcess       ,\r
370                                         ModuleName       ,\r
371                                         FileName         ,\r
372                                         dwLineNumber     ,\r
373                                         plDisplacement   ,\r
374                                         Line              ) ) ;\r
375     }\r
376 \r
377     BOOL SymGetLineNext ( IN OUT PIMAGEHLP_LINE Line )\r
378     {\r
379         return ( ::SymGetLineNext ( m_hProcess , Line ) ) ;\r
380     }\r
381 \r
382     BOOL SymGetLinePrev ( IN OUT PIMAGEHLP_LINE Line )\r
383     {\r
384         return ( ::SymGetLinePrev ( m_hProcess , Line ) ) ;\r
385     }\r
386 \r
387     BOOL SymMatchFileName ( IN  LPSTR   FileName        ,\r
388                             IN  LPSTR   Match           ,\r
389                             OUT LPSTR * FileNameStop    ,\r
390                             OUT LPSTR * MatchStop        )\r
391     {\r
392         return ( ::SymMatchFileName ( FileName       ,\r
393                                       Match          ,\r
394                                       FileNameStop   ,\r
395                                       MatchStop       ) ) ;\r
396     }\r
397 \r
398 /*----------------------------------------------------------------------\r
399                           Public Miscellaneous Members\r
400 ----------------------------------------------------------------------*/\r
401 public      :\r
402 \r
403     LPVOID SymFunctionTableAccess ( DWORD_PTR AddrBase )\r
404     {\r
405         return ( ::SymFunctionTableAccess ( m_hProcess , AddrBase ) ) ;\r
406     }\r
407 \r
408     BOOL SymGetSearchPath ( OUT LPSTR SearchPath        ,\r
409                             IN  DWORD SearchPathLength   )\r
410     {\r
411         return ( ::SymGetSearchPath ( m_hProcess       ,\r
412                                       SearchPath       ,\r
413                                       SearchPathLength  ) ) ;\r
414     }\r
415 \r
416     BOOL SymSetSearchPath ( IN LPSTR SearchPath )\r
417     {\r
418         return ( ::SymSetSearchPath ( m_hProcess , SearchPath ) ) ;\r
419     }\r
420 \r
421 /*    BOOL SymRegisterCallback ( IN PSYMBOL_REGISTERED_CALLBACK\r
422                                                        CallbackFunction,\r
423                                IN DWORD_PTR            UserContext    )\r
424     {\r
425         return ( ::SymRegisterCallback ( m_hProcess         ,\r
426                                          CallbackFunction   ,\r
427                                          UserContext         ) ) ;\r
428     }\r
429 */\r
430 \r
431 /*----------------------------------------------------------------------\r
432                          Protected Data Members\r
433 ----------------------------------------------------------------------*/\r
434 protected   :\r
435     // The unique value that will be used for this instance of the\r
436     // symbol engine. This value doesn\92t have to be an actual\r
437     // process value, just a unique value.\r
438     HANDLE      m_hProcess      ;\r
439 \r
440 } ;\r
441 \r
442 #endif      // _SYMBOLENGINE_H\r