From 1ca120b165c2f2d9f521a04bfc31c7956d2ce422 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 17 Jul 2012 06:57:55 +0000 Subject: ContactsPlus, CountryFlags, CrashDumper: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1000 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/CrashDumper/src/bkstring.cpp | 188 ++ plugins/CrashDumper/src/bkstring.h | 278 ++ plugins/CrashDumper/src/crshdmp.cpp | 434 +++ plugins/CrashDumper/src/crshdmp_icons.cpp | 88 + plugins/CrashDumper/src/dumper.cpp | 745 +++++ plugins/CrashDumper/src/exhndlr.cpp | 207 ++ plugins/CrashDumper/src/resource.h | 34 + plugins/CrashDumper/src/sdkstuff.h | 124 + plugins/CrashDumper/src/ui.cpp | 327 +++ plugins/CrashDumper/src/upload.cpp | 292 ++ plugins/CrashDumper/src/utils.cpp | 836 ++++++ plugins/CrashDumper/src/utils.h | 177 ++ plugins/CrashDumper/src/vc6/dbghelp.h | 4532 +++++++++++++++++++++++++++++ plugins/CrashDumper/src/vc6/dbghelp.lib | Bin 0 -> 48054 bytes plugins/CrashDumper/src/version.h | 3 + 15 files changed, 8265 insertions(+) create mode 100644 plugins/CrashDumper/src/bkstring.cpp create mode 100644 plugins/CrashDumper/src/bkstring.h create mode 100644 plugins/CrashDumper/src/crshdmp.cpp create mode 100644 plugins/CrashDumper/src/crshdmp_icons.cpp create mode 100644 plugins/CrashDumper/src/dumper.cpp create mode 100644 plugins/CrashDumper/src/exhndlr.cpp create mode 100644 plugins/CrashDumper/src/resource.h create mode 100644 plugins/CrashDumper/src/sdkstuff.h create mode 100644 plugins/CrashDumper/src/ui.cpp create mode 100644 plugins/CrashDumper/src/upload.cpp create mode 100644 plugins/CrashDumper/src/utils.cpp create mode 100644 plugins/CrashDumper/src/utils.h create mode 100644 plugins/CrashDumper/src/vc6/dbghelp.h create mode 100644 plugins/CrashDumper/src/vc6/dbghelp.lib create mode 100644 plugins/CrashDumper/src/version.h (limited to 'plugins/CrashDumper/src') diff --git a/plugins/CrashDumper/src/bkstring.cpp b/plugins/CrashDumper/src/bkstring.cpp new file mode 100644 index 0000000000..418cb0bd83 --- /dev/null +++ b/plugins/CrashDumper/src/bkstring.cpp @@ -0,0 +1,188 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "bkstring.h" + +bkstring::~bkstring() { if (sizeAlloced) free(buf); } + + +void bkstring::reserve(size_type len) +{ + if (len >= sizeAlloced || sizeAlloced == 0) + { + if (sizeAlloced == 0) buf = NULL; + buf = (value_type*)realloc(buf, (len+1) * sizeof(value_type)); + if (sizeAlloced == 0) buf[0] = 0; + sizeAlloced = len+1; + } +} + +void bkstring::appendfmt(const value_type *fmt, ...) +{ + areserve(_tcslen(fmt)*2); + + va_list vararg; + va_start(vararg, fmt); + for (;;) + { + int len = _vsntprintf(buf + lenBuf, sizeAlloced - lenBuf - 1, fmt, vararg); + if (len < 0) + reserve(sizeAlloced + 256); + else + { + lenBuf += len; + buf[lenBuf] = 0; + break; + } + } + va_end(vararg); +} + +bkstring& bkstring::append(const value_type* _Ptr) +{ + size_type len = _tcslen(_Ptr); + areserve(len); + memcpy(buf+lenBuf, _Ptr, (len+1)*sizeof(value_type)); + lenBuf += len; + return *this; +} + +bkstring& bkstring::append(const value_type* _Ptr, size_type _Count) +{ + size_type len = min(_tcslen(_Ptr), _Count); + areserve(len); + memcpy(buf+lenBuf, _Ptr, len*sizeof(value_type)); + lenBuf += len; + buf[lenBuf] = 0; + return *this; +} + +bkstring& bkstring::append(const bkstring& _Str, size_type _Off, size_type _Count) +{ + size_type len = min(_Count, _Str.size() - _Off); + areserve(len); + memcpy(buf+lenBuf, _Str.c_str()+_Off, len*sizeof(value_type)); + lenBuf += len; + buf[lenBuf] = 0; + return *this; +} + +bkstring& bkstring::append(const bkstring& _Str) +{ + size_type len = _Str.size(); + areserve(len); + memcpy(buf+lenBuf, _Str.c_str(), len*sizeof(value_type)); + lenBuf += len; + buf[lenBuf] = 0; + return *this; +} + +bkstring& bkstring::append(size_type _Count, value_type _Ch) +{ + areserve(_Count); + for(size_type i=0; i<_Count; ++i) buf[lenBuf+i] = _Ch; + lenBuf += _Count; + buf[lenBuf] = 0; + return *this; +} + + +bkstring& bkstring::assign(const value_type* _Ptr, size_type _Count) +{ + reserve(_Count); + memcpy(buf, _Ptr, _Count*sizeof(value_type)); + buf[_Count] = 0; + lenBuf = _Count; + return *this; +} + +bkstring& bkstring::assign(const bkstring& _Str, size_type _Off, size_type _Count) +{ + size_type len = min(_Count, _Str.size() - _Off); + reserve(len); + memcpy(buf, _Str.c_str() + _Off, len*sizeof(value_type)); + lenBuf = len; + buf[len] = 0; + return *this; +} + +bkstring& bkstring::assign(size_type _Count, value_type _Ch) +{ + reserve(_Count); + for(size_type i=0; i<_Count; ++i) buf[i] = _Ch; + buf[_Count] = 0; + lenBuf = _Count; + return *this; +} + +bkstring::size_type bkstring::find(value_type _Ch, size_type _Off) const +{ + for (size_type i=_Off; i<=lenBuf; ++i) + if (buf[i] == _Ch) return i; + return (size_type)npos; +} + +bkstring::size_type bkstring::find(const value_type* _Ptr, size_type _Off) const +{ + if (_Off > lenBuf) return (size_type)npos; + + value_type* pstr = _tcsstr(buf+_Off, _Ptr); + return pstr ? pstr - buf : npos; +} + +bkstring::size_type bkstring::find_last_of(value_type _Ch, size_type _Off) const +{ + for (size_type i=(_Off == npos ? lenBuf : _Off); i--;) + if (buf[i] == _Ch) return i; + return (size_type)npos; +} + +bkstring& bkstring::insert(size_type _P0, const value_type* _Ptr, size_type _Count) +{ + size_type len = _tcslen(_Ptr); + if (_Count < len) len = _Count; + areserve(len); + value_type *p = buf + _P0; + memmove(p+len, p, (lenBuf-_P0+1)*sizeof(value_type)); + memcpy(p, _Ptr, _Count*sizeof(value_type)); + lenBuf += len; + return *this; +} + +bkstring& bkstring::insert(size_type _P0, size_type _Count, value_type _Ch) +{ + areserve(_Count); + value_type *p = buf + _P0; + memmove(p+_Count, p, (lenBuf-_P0+1)*sizeof(value_type)); + for(size_type i=0; i<_Count; ++i) p[i] = _Ch; + lenBuf += _Count; + return *this; +} + +bkstring& bkstring::erase(size_type _Pos, size_type _Count) +{ + if (_Pos < lenBuf) + { + const size_type len = min(lenBuf - _Pos, _Count); + value_type *p = buf + _Pos; + lenBuf -= len; + memmove(p, p+len, (lenBuf - _Pos)*sizeof(value_type)); + buf[lenBuf] = 0; + } + return *this; +} diff --git a/plugins/CrashDumper/src/bkstring.h b/plugins/CrashDumper/src/bkstring.h new file mode 100644 index 0000000000..88cb3bdfc4 --- /dev/null +++ b/plugins/CrashDumper/src/bkstring.h @@ -0,0 +1,278 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#define _CRT_SECURE_NO_WARNINGS + +#ifndef _BKSTRING_H_ +#define _BKSTRING_H_ + +#include +#include +#include +#include +#include + +#ifndef min +#define min(A, B) ((A) < (B) ? (A) : (B)) +#endif + +class bkstring +{ +public: + typedef size_t size_type; + typedef TCHAR value_type; + typedef value_type* iterator; + typedef const value_type* const_iterator; + +#if defined(_MSC_VER) && _MSC_VER > 1200 + static const size_type npos = size_type(-1); +#else + enum { npos = -1 }; +#endif + +private: + value_type* buf; + size_type sizeAlloced; + size_type lenBuf; + + void areserve(size_type len) { reserve(lenBuf + len); } + +public: + + explicit bkstring() : buf((TCHAR*)_T("")), sizeAlloced(0), lenBuf(0) + {} + + bkstring(const value_type* _Ptr, size_type _Count) : sizeAlloced(0), lenBuf(0) + { assign(_Ptr, _Count); } + + bkstring(const value_type* _Ptr) : sizeAlloced(0), lenBuf(0) + { assign(_Ptr); } + + bkstring(size_type _Count, value_type _Ch) : sizeAlloced(0), lenBuf(0) + { assign(_Count, _Ch); } + + bkstring(const bkstring& _Str) : sizeAlloced(0), lenBuf(0) + { assign(_Str); } + + bkstring(const bkstring& _Str, size_type _Off, size_type _Count) : sizeAlloced(0), lenBuf(0) + { assign(_Str, _Off, _Count); } + + ~bkstring(); + + size_type size(void) const { return lenBuf; } + const value_type* c_str(void) const { return buf; } + + void clear(void) { if (lenBuf) { lenBuf = 0; buf[0] = 0; } } + void insert(const value_type *txt); + void reserve(size_type len); + + bkstring& assign(const value_type* _Ptr) + { return assign(_Ptr, _tcslen(_Ptr)); } + + bkstring& assign(const bkstring& _Str) + { return assign(_Str, 0, (size_type)npos); } + + bkstring& assign(const value_type* _Ptr, size_type _Count); + bkstring& assign(const bkstring& _Str, size_type off, size_type _Count); + bkstring& assign(size_type _Count, value_type _Ch); + + bkstring& append(const value_type* _Ptr); + bkstring& append(const value_type* _Ptr, size_type _Count); + bkstring& append(const bkstring& _Str, size_type _Off, size_type _Count); + bkstring& append(const bkstring& _Str); + bkstring& append(size_type _Count, value_type _Ch); + + int compare(const bkstring& _Str) const + { return _tcscmp(buf, _Str.c_str()); } + + int compare(size_type _Pos1, size_type _Num1, const bkstring& _Str) const + { return _tcsncmp(&buf[_Pos1], _Str.c_str(), _Num1); } + + int compare(size_type _Pos1, size_type _Num1, const bkstring& _Str, size_type _Off, size_type _Count) const + { return _tcsncmp(&buf[_Pos1], _Str.c_str()+_Off, min(_Num1, _Count)); } + + int compare(const value_type* _Ptr) const + { return _tcscmp(buf, _Ptr); } + + int compare(size_type _Pos1, size_type _Num1, const value_type* _Ptr) const + { return _tcsncmp(&buf[_Pos1], _Ptr, _Num1); } + + int compare(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2) const + { return _tcsncmp(&buf[_Pos1], _Ptr, min(_Num1, _Num2)); } + + int comparei(const bkstring& _Str) const + { return _tcsicmp(buf, _Str.c_str()); } + + int comparei(size_type _Pos1, size_type _Num1, const bkstring& _Str) const + { return _tcsnicmp(&buf[_Pos1], _Str.c_str(), _Num1); } + + int comparei(size_type _Pos1, size_type _Num1, const bkstring& _Str, size_type _Off, size_type _Count) const + { return _tcsnicmp(&buf[_Pos1], _Str.c_str()+_Off, min(_Num1, _Count)); } + + int comparei(const value_type* _Ptr) const + { return _tcsicmp(buf, _Ptr); } + + int comparei(size_type _Pos1, size_type _Num1, const value_type* _Ptr) const + { return _tcsnicmp(&buf[_Pos1], _Ptr, _Num1); } + + int comparei(size_type _Pos1, size_type _Num1, const value_type* _Ptr, size_type _Num2) const + { return _tcsnicmp(&buf[_Pos1], _Ptr, min(_Num1, _Num2)); } + + bool empty(void) const { return lenBuf == 0; }; + bkstring& erase(size_type _Pos = 0, size_type _Count = npos); + + size_type find(value_type _Ch, size_type _Off = 0) const; + size_type find(const value_type* _Ptr, size_type _Off = 0) const; + size_type find(bkstring& _Str, size_type _Off = 0) const + { return find(_Str.c_str(), _Off); } + + size_type find_last_of(value_type _Ch, size_type _Off = npos) const; + + bkstring& insert(size_type _P0, const value_type* _Ptr) + { return insert(_P0, _Ptr, _tcslen(_Ptr)); } + + bkstring& insert(size_type _P0, const bkstring& _Str) + { return insert(_P0, _Str.c_str(), _Str.size()); }; + + bkstring& insert(size_type _P0, const value_type* _Ptr, size_type _Count); + bkstring& insert(size_type _P0, size_type _Count, value_type _Ch); + + bkstring substr(size_type _Off = 0, size_type _Count = npos) const + { return bkstring(*this, _Off, _Count); } + + bkstring& operator = (const bkstring& _Str) + { return assign(_Str); } + + bkstring& operator =(const value_type* _Ptr) + { return assign(_Ptr); } + + bkstring& operator = (const value_type _Ch) + { return assign(1, _Ch); } + + bkstring& operator +=(const bkstring& _Str) + { return append(_Str); } + + bkstring& operator += (const value_type* _Ptr) + { return append(_Ptr); } + + bkstring& operator += (const value_type _Ch) + { return append(1, _Ch); } + + value_type& operator[] (int ind) const + { return buf[ind]; } + + friend bkstring operator+ (const bkstring& _Str1, const bkstring& _Str2) + { bkstring s(_Str1); return s.append(_Str2); } + + friend bkstring operator+ (const bkstring& _Str1, const value_type* _Ptr2) + { bkstring s(_Str1); return s.append(_Ptr2); } + + friend bkstring operator+(const value_type* _Ptr1, const bkstring& _Str2) + { bkstring s(_Ptr1); return s.append(_Str2); } + + friend bkstring operator+ (const bkstring& _Str1, const value_type _Ch) + { bkstring s(_Str1); return s.append(1, _Ch); } + + friend bool operator==(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) == 0; } + + friend bool operator==(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) == 0; } + + friend bool operator==(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) == 0; } + + friend bool operator!=(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) != 0; } + + friend bool operator!=(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) != 0; } + + friend bool operator!=(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) != 0; } + + friend bool operator<(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) < 0; } + + friend bool operator<(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) < 0; } + + friend bool operator<(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) > 0; } + + friend bool operator>(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) > 0; } + + friend bool operator>(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) > 0; } + + friend bool operator>(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) < 0; } + + friend bool operator<=(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) <= 0; } + + friend bool operator<=(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) <= 0; } + + friend bool operator<=(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) >= 0; } + + friend bool operator>=(const bkstring& _Str1, const bkstring& _Str2) + { return _Str1.compare(_Str2) >= 0; } + + friend bool operator>=(const bkstring& _Str1, const value_type* _Ptr2) + { return _Str1.compare(_Ptr2) >= 0; } + + friend bool operator>=(const value_type* _Ptr1, const bkstring& _Str2) + { return _Str2.compare(_Ptr1) <= 0; } + + friend bool operator==(const value_type _Ch1, const bkstring& _Str2) + { return (_Str2.size() == 1) && (_Str2[0] == _Ch1); } + + friend bool operator==(const bkstring& _Str1, const value_type _Ch2) + { return (_Str1.size() == 1) && (_Str1[0] == _Ch2); } + + friend bool operator!=(const value_type _Ch1, const bkstring& _Str2) + { return (_Str2.size() != 1) || (_Str2[0] != _Ch1); } + + friend bool operator!=(const bkstring& _Str1, const value_type _Ch2) + { return (_Str1.size() != 1) || (_Str1[0] != _Ch2); } + + iterator begin(void) + { return buf; } + + const_iterator begin(void) const + { return buf; } + + iterator end(void) + { return buf + lenBuf; } + + const_iterator end(void) const + { return buf + lenBuf; } + + // Custom extentions + + void appendfmt(const value_type *fmt, ...); + + size_type sizebytes(void) const { return lenBuf * sizeof(value_type); } +}; + +//const bkstring::size_type bkstring::npos = -1; + +#endif diff --git a/plugins/CrashDumper/src/crshdmp.cpp b/plugins/CrashDumper/src/crshdmp.cpp new file mode 100644 index 0000000000..72ffac7f44 --- /dev/null +++ b/plugins/CrashDumper/src/crshdmp.cpp @@ -0,0 +1,434 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "utils.h" +#include +#include "m_folders.h" +#include "m_toptoolbar.h" +#include "version.h" + +int hLangpack; + +HINSTANCE hInst; +DWORD mirandaVersion; +LCID packlcid; +HANDLE hCrashLogFolder, hVerInfoFolder; +HMODULE hRichModule; + +TCHAR* vertxt; +TCHAR* profname; +TCHAR* profpath; + +TCHAR CrashLogFolder[MAX_PATH]; +TCHAR VersionInfoFolder[MAX_PATH]; + +bool servicemode; +bool clsdates; +bool dtsubfldr; + +static const PLUGININFOEX pluginInfoEx = +{ + sizeof(PLUGININFOEX), + "Crash Dumper", + __VERSION_DWORD, + "Crash Dumper for Miranda IM.", + "borkra", + "borkra@miranda-im.org", + "Copyright© 2008 - 2012 Boris Krasnovskiy All Rights Reserved", + "http://code.google.com/p/mirandaimplugins/downloads/list", + UNICODE_AWARE, + // {F62C1D7A-FFA4-4065-A251-4C9DD9101CC8} + { 0xf62c1d7a, 0xffa4, 0x4065, { 0xa2, 0x51, 0x4c, 0x9d, 0xd9, 0x10, 0x1c, 0xc8 } } +}; + +const PLUGININFOEX* GetPluginInfoEx(void) { return &pluginInfoEx; } + + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirVersion) +{ + ::mirandaVersion = mirVersion; + return (PLUGININFOEX*)&pluginInfoEx; +} + +#define MIID_CRASHDUMP { 0x36a31a50, 0xcb55, 0x46d0, { 0xab, 0x9c, 0x1e, 0xac, 0xfb, 0x24, 0x0, 0x2a } } + +// MirandaInterfaces - returns the protocol interface to the core +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_SERVICEMODE, MIID_CRASHDUMP, MIID_LAST }; + +HANDLE hHooks[5]; +HANDLE hServices[6]; + + +INT_PTR StoreVersionInfoToFile(WPARAM, LPARAM lParam) +{ + CreateDirectoryTree(VersionInfoFolder); + + TCHAR path[MAX_PATH]; + crs_sntprintf(path, MAX_PATH, TEXT("%s\\VersionInfo.txt"), VersionInfoFolder); + + HANDLE hDumpFile = CreateFile(path, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hDumpFile != INVALID_HANDLE_VALUE) + { + bkstring buffer; + + buffer.reserve(0x1800); + PrintVersionInfo(buffer, (unsigned int)lParam | VI_FLAG_PRNVAR); + + char* bufu = mir_utf8encodeT(buffer.c_str()); + WriteUtfFile(hDumpFile, bufu); + mir_free(bufu); + + CloseHandle(hDumpFile); + + ShowMessage(3, TranslateT("VersionInfo stored into file %s"), path); + } + else + ShowMessage(2, TranslateT("VersionInfo file %s is inaccessible"), path); + + return 0; +} + +INT_PTR StoreVersionInfoToClipboard(WPARAM, LPARAM lParam) +{ + bkstring buffer; + buffer.reserve(0x1800); + + WriteBBFile(buffer, true); + PrintVersionInfo(buffer, (unsigned int)lParam | VI_FLAG_PRNVAR | VI_FLAG_FORMAT); + WriteBBFile(buffer, false); + + StoreStringToClip(buffer); + + return 0; +} + +INT_PTR UploadVersionInfo(WPARAM, LPARAM lParam) +{ + bkstring buffer; + buffer.reserve(0x1800); + PrintVersionInfo(buffer); + + VerTrnsfr *trn = (VerTrnsfr*)mir_alloc(sizeof(VerTrnsfr)); + trn->buf = mir_utf8encodeT(buffer.c_str()); + trn->autot = lParam == 0xa1; + + mir_forkthread(VersionInfoUploadThread, trn); + + return 0; +} + + +INT_PTR ViewVersionInfo(WPARAM wParam, LPARAM) +{ + // unsigned *p = (unsigned*)0x15; + // *p = 324; + + if (hRichModule == NULL && GetModuleHandle(TEXT("Riched20.dll")) == NULL) + hRichModule = LoadLibrary(TEXT("Riched20.dll")); + + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_VIEWVERSION), NULL, + DlgProcView, wParam ? (VI_FLAG_PRNVAR | VI_FLAG_PRNDLL) : VI_FLAG_PRNVAR); + + return 0; +} + +INT_PTR OpenUrl(WPARAM wParam, LPARAM) +{ + switch (wParam) + { + case 0: + ShellExecute(NULL, TEXT("explore"), CrashLogFolder, NULL, NULL, SW_SHOW); + break; + + case 1: + OpenAuthUrl("http://%s.miranda-vi.org"); + break; + } + return 0; +} + +INT_PTR ServiceModeLaunch(WPARAM, LPARAM) +{ + servicemode = true; + return 0; +} + + +static int FoldersPathChanged(WPARAM, LPARAM) +{ + FOLDERSGETDATA fgd = {0}; + fgd.cbSize = sizeof(FOLDERSGETDATA); + fgd.nMaxPathSize = MAX_PATH; + fgd.szPathT = CrashLogFolder; + CallService(MS_FOLDERS_GET_PATH, (WPARAM) hCrashLogFolder, (LPARAM) &fgd); + + fgd.szPathT = VersionInfoFolder; + CallService(MS_FOLDERS_GET_PATH, (WPARAM) hVerInfoFolder, (LPARAM) &fgd); + return 0; +} + +int OptionsInit(WPARAM wParam, LPARAM) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + + odp.cbSize = sizeof(odp); + odp.position = -790000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.pszTitle = (char*)PluginName; + odp.pszGroup = LPGEN("Services"); + odp.flags = ODPF_BOLDGROUPS; + odp.pfnDlgProc = DlgProcOptions; + Options_AddPage(wParam, &odp); + + return 0; +} + +static int ToolbarModulesLoaded(WPARAM, LPARAM) +{ + TTBButton tbb = {0}; + tbb.cbSize = sizeof(TTBButton); + + tbb.pszService = MS_CRASHDUMPER_STORETOCLIP; + tbb.name = tbb.pszTooltipUp = LPGEN("Version Information To Clipboard"); + tbb.hIconHandleUp = GetIconHandle("storeToClip"); + tbb.dwFlags = TTBBF_VISIBLE; + TopToolbar_AddButton(&tbb); + + tbb.pszService = MS_CRASHDUMPER_STORETOFILE; + tbb.name = tbb.pszTooltipUp = LPGEN("Version Information To File"); + tbb.hIconHandleUp = GetIconHandle("storeToFile"); + tbb.dwFlags = 0; + TopToolbar_AddButton(&tbb); + + tbb.pszService = MS_CRASHDUMPER_VIEWINFO; + tbb.name = tbb.pszTooltipUp = LPGEN("Show Version Information"); + tbb.hIconHandleUp = GetIconHandle("showInfo"); + TopToolbar_AddButton(&tbb); + + tbb.pszService = MS_CRASHDUMPER_UPLOAD; + tbb.name = tbb.pszTooltipUp = LPGEN("Upload Version Information"); + tbb.hIconHandleUp = GetIconHandle("uploadInfo"); + TopToolbar_AddButton(&tbb); + return 0; +} + +static int ModulesLoaded(WPARAM, LPARAM) +{ + char temp[MAX_PATH]; + CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM)SIZEOF(temp), (LPARAM)temp); + crs_a2t(vertxt, temp); + + profname = Utils_ReplaceVarsT(_T("%miranda_profilename%.dat")); + if (ServiceExists(MS_FOLDERS_REGISTER_PATH)) + { + profpath = _T("%miranda_userdata%"); + } + else + { + profpath = Utils_ReplaceVarsT(_T("%miranda_userdata%")); + } + + crs_sntprintf(CrashLogFolder, MAX_PATH, TEXT("%s\\CrashLog"), profpath); + crs_sntprintf(VersionInfoFolder, MAX_PATH, TEXT("%s"), profpath); + + SetExceptionHandler(); + + hCrashLogFolder = FoldersRegisterCustomPathT(PluginName, "Crash Reports", CrashLogFolder); + hVerInfoFolder = FoldersRegisterCustomPathT(PluginName, "Version Information", VersionInfoFolder); + + FoldersPathChanged(0, 0); + + + + hHooks[2] = HookEvent(ME_FOLDERS_PATH_CHANGED, FoldersPathChanged); + if (hHooks[3] == NULL) hHooks[3] = HookEvent(ME_TTB_MODULELOADED, ToolbarModulesLoaded); + + UploadInit(); + + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + + mi.popupPosition = 2000089999; + mi.position = 2000089999; + mi.flags = CMIF_ROOTPOPUP | CMIF_ICONFROMICOLIB | CMIF_TCHAR; + mi.icolibItem = GetIconHandle("versionInfo"); + mi.ptszName = LPGENT("Version Information"); + mi.pszPopupName = (char *)-1; + HANDLE hMenuRoot = Menu_AddMainMenuItem(&mi); + + mi.flags = CMIF_CHILDPOPUP | CMIF_ICONFROMICOLIB | CMIF_TCHAR; + mi.pszPopupName = (char *)hMenuRoot; + mi.popupPosition = 0; + + mi.position = 2000089995; + mi.ptszName = LPGENT("Copy to clipboard"); + mi.icolibItem = GetIconHandle("storeToClip"); + mi.pszService = MS_CRASHDUMPER_STORETOCLIP; + Menu_AddMainMenuItem(&mi); + + mi.position = 2000089996; + mi.ptszName = LPGENT("Store to file"); + mi.icolibItem = GetIconHandle("storeToFile"); + mi.pszService = MS_CRASHDUMPER_STORETOFILE; + Menu_AddMainMenuItem(&mi); + + mi.position = 2000089997; + mi.ptszName = LPGENT("Show"); + mi.icolibItem = GetIconHandle("showInfo"); + mi.pszService = MS_CRASHDUMPER_VIEWINFO; + Menu_AddMainMenuItem(&mi); + + mi.popupPosition = 1; + mi.position = 2000089998; + mi.ptszName = LPGENT("Show with DLLs"); + mi.icolibItem = GetIconHandle("showInfo"); + mi.pszService = MS_CRASHDUMPER_VIEWINFO; + Menu_AddMainMenuItem(&mi); + + mi.popupPosition = 0; + mi.position = 2000089999; + mi.ptszName = LPGENT("Upload"); + mi.icolibItem = GetIconHandle("uploadInfo"); + mi.pszService = MS_CRASHDUMPER_UPLOAD; + Menu_AddMainMenuItem(&mi); + + mi.position = 2000099990; + mi.ptszName = LPGENT("Open crash report directory"); + mi.icolibItem = LoadSkinnedIconHandle(SKINICON_EVENT_FILE); + mi.pszService = MS_CRASHDUMPER_URL; + Menu_AddMainMenuItem(&mi); + + mi.popupPosition = 1; + mi.position = 2000099991; + mi.ptszName = LPGENT("Open miranda-vi.org"); + mi.icolibItem = LoadSkinnedIconHandle(SKINICON_EVENT_URL); + mi.pszService = MS_CRASHDUMPER_URL; + Menu_AddMainMenuItem(&mi); + + HOTKEYDESC hk = {0}; + hk.cbSize = sizeof(hk); + hk.pszSection = PluginName; + + hk.pszDescription = LPGEN("Copy Version Info to clipboard"); + hk.pszName = "CopyVerInfo"; + hk.pszService = MS_CRASHDUMPER_STORETOCLIP; + Hotkey_Register(&hk); + + hk.pszDescription = LPGEN("Show Version Info"); + hk.pszName = "ShowVerInfo"; + hk.pszService = MS_CRASHDUMPER_VIEWINFO; + Hotkey_Register(&hk); + + if (servicemode) ViewVersionInfo(0, 0); + else + { + if (DBGetContactSettingByte(NULL, PluginName, "UploadChanged", 0) && !ProcessVIHash(false)) + UploadVersionInfo(0, 0xa1); + } + + CheckForOtherCrashReportingPlugins(); + return 0; +} + +static int PreShutdown(WPARAM, LPARAM) +{ + unsigned i; + + DestroyAllWindows(); + UploadClose(); + + for (i=0; i. +*/ + +#include "utils.h" +#include + +struct _tag_iconList +{ + const char* szDescr; + const char* szName; + int defIconID; +} +static const iconList[] = +{ + { "Version Information", "versionInfo", IDI_VI }, + { "Copy To Clipboard", "storeToClip", IDI_VITOCLIP }, + { "Store to file", "storeToFile", IDI_VITOFILE }, + { "Show", "showInfo", IDI_VISHOW }, + { "Upload", "uploadInfo", IDI_VIUPLOAD }, +}; + +static HANDLE hIconLibItem[SIZEOF(iconList)]; + +void InitIcons(void) +{ + char szFile[MAX_PATH]; + char szSettingName[100]; + SKINICONDESC sid = {0}; + + sid.cbSize = sizeof(SKINICONDESC); + sid.pszDefaultFile = szFile; + sid.pszName = szSettingName; + sid.pszSection = (char*)PluginName; + + GetModuleFileNameA(hInst, szFile, MAX_PATH); + + for (unsigned i = 0; i < SIZEOF(iconList); i++) + { + mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", PluginName, iconList[i].szName); + + sid.pszDescription = (char*)iconList[i].szDescr; + sid.iDefaultIndex = -iconList[i].defIconID; + hIconLibItem[i] = Skin_AddIcon(&sid); + } +} + +HICON LoadIconEx(const char* name, bool big) +{ + char szSettingName[100]; + mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", PluginName, name); + return (HICON)CallService(MS_SKIN2_GETICON, big, (LPARAM)szSettingName); +} + +HANDLE GetIconHandle(const char* name) +{ + unsigned i; + for (i=0; i < SIZEOF(iconList); i++) + if (strcmp(iconList[i].szName, name) == 0) + return hIconLibItem[i]; + return NULL; +} + +void ReleaseIconEx(const char* name) +{ + char szSettingName[100]; + mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", PluginName, name); + CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)szSettingName); +} + +void ReleaseIconEx(HICON hIcon) +{ + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); +} diff --git a/plugins/CrashDumper/src/dumper.cpp b/plugins/CrashDumper/src/dumper.cpp new file mode 100644 index 0000000000..bae091a023 --- /dev/null +++ b/plugins/CrashDumper/src/dumper.cpp @@ -0,0 +1,745 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "utils.h" + +extern TCHAR* vertxt; +extern TCHAR* profname; +extern TCHAR* profpath; + + +void CreateMiniDump(HANDLE hDumpFile, PEXCEPTION_POINTERS exc_ptr) +{ + MINIDUMP_EXCEPTION_INFORMATION exceptionInfo; + exceptionInfo.ThreadId = GetCurrentThreadId(); + exceptionInfo.ExceptionPointers = exc_ptr; + exceptionInfo.ClientPointers = false; + + MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), + hDumpFile, MiniDumpNormal, &exceptionInfo, NULL, NULL); +} + + +void WriteBBFile(bkstring& buffer, bool hdr) +{ + static const TCHAR header[] = TEXT("[quote][size=1]"); + static const TCHAR footer[] = TEXT("[/size][/quote]"); + + buffer.append(hdr ? header : footer); +} + + +void WriteUtfFile(HANDLE hDumpFile, char* bufu) +{ + DWORD bytes; + + static const unsigned char bytemark[] = { 0xEF, 0xBB, 0xBF }; + WriteFile(hDumpFile, bytemark, 3, &bytes, NULL); + WriteFile(hDumpFile, bufu, (DWORD)strlen(bufu), &bytes, NULL); +} + + +BOOL CALLBACK LoadedModules64(LPCSTR, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext) +{ + bkstring& buffer = *(bkstring*)UserContext; + + const HMODULE hModule = (HMODULE)ModuleBase; + + TCHAR path[MAX_PATH]; + GetModuleFileName(hModule, path, MAX_PATH); + + buffer.appendfmt(TEXT("%s %p - %p"), path, (LPVOID)ModuleBase, (LPVOID)(ModuleBase + ModuleSize)); + + GetVersionInfo(hModule, buffer); + + TCHAR timebuf[30] = TEXT(""); + GetLastWriteTime(path, timebuf, 30); + + buffer.appendfmt(TEXT(" [%s]\r\n"), timebuf); + + return TRUE; +} + +typedef struct _FindData +{ + DWORD64 Offset; IMAGEHLP_MODULE64* pModule; +} FindData; + + +BOOL CALLBACK LoadedModulesFind64(LPCSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext) +{ + FindData* data = (FindData*)UserContext; + + if ((DWORD)(data->Offset - ModuleBase) < ModuleSize) + { + const size_t len = SIZEOF(data->pModule->ModuleName); + strncpy(data->pModule->ModuleName, ModuleName, len); + data->pModule->ModuleName[len-1] = 0; + + data->pModule->BaseOfImage = ModuleBase; + + const HMODULE hModule = (HMODULE)ModuleBase; + GetModuleFileNameA(hModule, data->pModule->LoadedImageName, SIZEOF(data->pModule->LoadedImageName)); + + return FALSE; + } + return TRUE; +} + + +void GetLinkedModulesInfo(TCHAR *moduleName, bkstring &buffer) +{ + HANDLE hDllFile = CreateFile(moduleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hDllFile == INVALID_HANDLE_VALUE) return; + + HANDLE hDllMapping = CreateFileMapping(hDllFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hDllMapping == INVALID_HANDLE_VALUE) + { + CloseHandle(hDllFile); + return; + } + + LPVOID dllAddr = MapViewOfFile(hDllMapping, FILE_MAP_READ, 0, 0, 0); + + + static const TCHAR format[] = TEXT(" Plugin statically linked to missing module: %S\r\n"); + + + __try + { + PIMAGE_NT_HEADERS nthdrs = ImageNtHeader(dllAddr); + + ULONG tableSize; + PIMAGE_IMPORT_DESCRIPTOR importData = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(dllAddr, FALSE, + IMAGE_DIRECTORY_ENTRY_IMPORT, &tableSize); + if (importData) + { + while (importData->Name) + { + char* moduleName = (char*)ImageRvaToVa(nthdrs, dllAddr, importData->Name, NULL); + if (!SearchPathA(NULL, moduleName, NULL, NULL, 0, NULL)) + { + buffer.appendfmt(format, moduleName); + } + importData++; //go to next record + } + } + + bool found = false; + PIMAGE_EXPORT_DIRECTORY exportData = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(dllAddr, FALSE, + IMAGE_DIRECTORY_ENTRY_EXPORT, &tableSize); + if (exportData) + { + ULONG* funcAddr = (ULONG*)ImageRvaToVa(nthdrs, dllAddr, exportData->AddressOfNames, NULL); + for(unsigned i=0; iNumberOfNames && !found; ++i) + { + char* funcName = (char*)ImageRvaToVa(nthdrs, dllAddr, funcAddr[i], NULL); + found = strcmp(funcName, "MirandaPluginInfoEx") == 0 || strcmp(funcName, "MirandaPluginInfo") == 0; + if (strcmp(funcName, "DatabasePluginInfo") == 0) + { + buffer.append(TEXT(" This dll is a Miranda database plugin, another database is active right now\r\n")); + found = true; + } + } + } + if (!found) + buffer.append(TEXT(" This dll is not a Miranda plugin and should be removed from plugins directory\r\n")); + } + __except(EXCEPTION_EXECUTE_HANDLER) {} + + UnmapViewOfFile(dllAddr); + CloseHandle(hDllMapping); + CloseHandle(hDllFile); +} + + +struct ListItem +{ + ListItem() : str(), next(NULL) {} + + bkstring str; + ListItem *next; +}; + +static void GetPluginsString(bkstring& buffer, unsigned& flags) +{ + buffer.appendfmt(TEXT("Service Mode: %s\r\n"), servicemode ? TEXT("Yes") : TEXT("No")); + + TCHAR path[MAX_PATH]; + GetModuleFileName(NULL, path, MAX_PATH); + + LPTSTR fname = _tcsrchr(path, TEXT('\\')); + if (fname == NULL) fname = path; + crs_sntprintf(fname, MAX_PATH-(fname-path), TEXT("\\plugins\\*.dll")); + + WIN32_FIND_DATA FindFileData; + HANDLE hFind = FindFirstFile(path, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) return; + + size_t count = 0, ucount = 0; + + bkstring ubuffer; + ListItem* dlllist = NULL; + + + static const TCHAR format[] = TEXT("%c %s v.%s%d.%d.%d.%d%s [%s] - %S %s\r\n"); + + + do + { + bool loaded = false; + crs_sntprintf(fname, MAX_PATH-(fname-path), TEXT("\\plugins\\%s"), FindFileData.cFileName); + HMODULE hModule = GetModuleHandle(path); + if (hModule == NULL && servicemode) + { + hModule = LoadLibrary(path); + loaded = true; + } + if (hModule == NULL) + { + if ((flags & VI_FLAG_PRNVAR) && IsPluginEnabled(FindFileData.cFileName)) + { + TCHAR timebuf[30] = TEXT(""); + GetLastWriteTime(&FindFileData.ftLastWriteTime, timebuf, 30); + + ubuffer.appendfmt(format, TEXT(' '), FindFileData.cFileName, + (flags & VI_FLAG_FORMAT) ? TEXT("[b]") : TEXT(""), + 0, 0, 0, 0, + (flags & VI_FLAG_FORMAT) ? TEXT("[/b]") : TEXT(""), + timebuf, "", TEXT("")); + + GetLinkedModulesInfo(path, ubuffer); + ubuffer.append(TEXT("\r\n")); + + ++ucount; + } + continue; + } + + PLUGININFOEX* pi = GetMirInfo(hModule); + if (pi != NULL) + { + TCHAR timebuf[30] = TEXT(""); + GetLastWriteTime(&FindFileData.ftLastWriteTime, timebuf, 30); + + bool ep = (size_t)pi->cbSize > sizeof(PLUGININFOEX); + const TCHAR *unica = (ep && ((PLUGININFOEX*)pi)->flags & 1) ? TEXT("|Unicode aware|") : TEXT(""); + + ListItem* lst = new ListItem; + DWORD ver = pi->version; + lst->str.appendfmt(format, ep ? TEXT('\xa4') : TEXT(' '), FindFileData.cFileName, + (flags & VI_FLAG_FORMAT) ? TEXT("[b]") : TEXT(""), + HIBYTE(HIWORD(ver)), LOBYTE(HIWORD(ver)), HIBYTE(LOWORD(ver)), LOBYTE(LOWORD(ver)), + (flags & VI_FLAG_FORMAT) ? TEXT("[/b]") : TEXT(""), + timebuf, pi->shortName ? pi->shortName : "", unica); + + ListItem* lsttmp = dlllist; + ListItem* lsttmppv = NULL; + while (lsttmp != NULL) + { + size_t sz = min(lsttmp->str.size(), lst->str.size()) - 2; + if (lsttmp->str.comparei(2, sz, lst->str, 2, sz) > 0) break; + lsttmppv = lsttmp; + lsttmp = lsttmp->next; + } + lst->next = lsttmp; + if (lsttmppv == NULL) + dlllist = lst; + else + lsttmppv->next = lst; + + if (_tcsicmp(FindFileData.cFileName, TEXT("weather.dll")) == 0) + flags |= VI_FLAG_WEATHER; + + ++count; + } + if (loaded) FreeLibrary(hModule); + } + while (FindNextFile(hFind, &FindFileData)); + FindClose(hFind); + + buffer.appendfmt(TEXT("\r\n%sActive Plugins (%u):%s\r\n"), + (flags & VI_FLAG_FORMAT) ? TEXT("[b]") : TEXT(""), count, (flags & VI_FLAG_FORMAT) ? TEXT("[/b]") : TEXT("")); + + ListItem* lsttmp = dlllist; + while (lsttmp != NULL) + { + buffer.append(lsttmp->str); + ListItem* lsttmp1 = lsttmp->next; + delete lsttmp; + lsttmp = lsttmp1; + } + + if (ucount) + { + buffer.appendfmt(TEXT("\r\n%sUnloadable Plugins (%u):%s\r\n"), + (flags & VI_FLAG_FORMAT) ? TEXT("[b]") : TEXT(""), ucount, (flags & VI_FLAG_FORMAT) ? TEXT("[/b]") : TEXT("")); + buffer.append(ubuffer); + } +} + + +struct ProtoCount +{ + char countse; + char countsd; + bool nloaded; +}; + +static void GetProtocolStrings(bkstring& buffer) +{ + PROTOACCOUNT **accList; + int accCount, protoCount; + int i, j; + + PROTOCOLDESCRIPTOR **protoList; + if (ProtoEnumAccounts(&accCount, &accList) == CALLSERVICE_NOTFOUND || (accCount > 0 && accList[0]->cbSize == 0)) + { + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&protoCount, (LPARAM)&protoList); + for (i = 0; i < protoCount; i++) + { + if (protoList[i]->type != PROTOTYPE_PROTOCOL) continue; + + TCHAR* nm; + crsi_a2t(nm, protoList[i]->szName); + buffer.appendfmt(TEXT(" 1 - %s\r\n"), nm); + } + } + else + { + CallService(MS_PROTO_ENUMPROTOS, (WPARAM)&protoCount, (LPARAM)&protoList); + + int protoCountMy = 0; + char** protoListMy = (char**)alloca((protoCount + accCount) * sizeof(char*)); + + for (i = 0; i < protoCount; i++) + { + if (protoList[i]->type != PROTOTYPE_PROTOCOL) continue; + protoListMy[protoCountMy++] = protoList[i]->szName; + } + + for (j = 0; j < accCount; j++) + { + for (i = 0; i < protoCountMy; i++) + { + if (strcmp(protoListMy[i], accList[j]->szProtoName) == 0) + break; + } + if (i == protoCountMy) + protoListMy[protoCountMy++] = accList[j]->szProtoName; + } + + ProtoCount *protos = (ProtoCount*)alloca(sizeof(ProtoCount) * protoCountMy); + memset(protos, 0, sizeof(ProtoCount) * protoCountMy); + + for (j = 0; j < accCount; j++) + { + for (i = 0; i < protoCountMy; i++) + { + if (strcmp(protoListMy[i], accList[j]->szProtoName) == 0) + { + protos[i].nloaded = accList[j]->bDynDisabled != 0; + if (IsAccountEnabled(accList[j])) + ++protos[i].countse; + else + ++protos[i].countsd; + break; + } + } + } + for (i = 0; i < protoCountMy; i++) + { + TCHAR* nm; + crsi_a2t(nm, protoListMy[i]); + buffer.appendfmt(TEXT("%-24s %d - Enabled %d - Disabled %sLoaded\r\n"), nm, protos[i].countse, + protos[i].countsd, protos[i].nloaded ? _T("Not ") : _T("")); + } + } +} + + +static void GetWeatherStrings(bkstring& buffer, unsigned flags) +{ + TCHAR path[MAX_PATH]; + GetModuleFileName(NULL, path, MAX_PATH); + + LPTSTR fname = _tcsrchr(path, TEXT('\\')); + if (fname == NULL) fname = path; + crs_sntprintf(fname, MAX_PATH-(fname-path), TEXT("\\plugins\\weather\\*.ini")); + + WIN32_FIND_DATA FindFileData; + HANDLE hFind = FindFirstFile(path, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) return; + + do + { + if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; + + crs_sntprintf(fname, MAX_PATH-(fname-path), TEXT("\\plugins\\weather\\%s"), FindFileData.cFileName); + HANDLE hDumpFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hDumpFile != INVALID_HANDLE_VALUE) + { + char buf[8192]; + + DWORD bytes = 0; + ReadFile(hDumpFile, buf, 8190, &bytes, NULL); + buf[bytes] = 0; + + char* ver = strstr(buf, "Version="); + if (ver != NULL) + { + char *endid = strchr(ver, '\r'); + if (endid != NULL) *endid = 0; + else + { + endid = strchr(ver, '\n'); + if (endid != NULL) *endid = 0; + } + ver += 8; + } + + char *id = strstr(buf, "Name="); + if (id != NULL) + { + char *endid = strchr(id, '\r'); + if (endid != NULL) *endid = 0; + else + { + endid = strchr(id, '\n'); + if (endid != NULL) *endid = 0; + } + id += 5; + } + + TCHAR timebuf[30] = TEXT(""); + GetLastWriteTime(&FindFileData.ftLastWriteTime, timebuf, 30); + + + static const TCHAR format[] = TEXT(" %s v.%s%S%s [%s] - %S\r\n"); + + buffer.appendfmt(format, FindFileData.cFileName, + (flags & VI_FLAG_FORMAT) ? TEXT("[b]") : TEXT(""), + ver, + (flags & VI_FLAG_FORMAT) ? TEXT("[/b]") : TEXT(""), + timebuf, id); + CloseHandle(hDumpFile); + } + } + while (FindNextFile(hFind, &FindFileData)); + FindClose(hFind); +} + + +static void GetIconStrings(bkstring& buffer) +{ + TCHAR path[MAX_PATH]; + GetModuleFileName(NULL, path, MAX_PATH); + + LPTSTR fname = _tcsrchr(path, TEXT('\\')); + if (fname == NULL) fname = path; + crs_sntprintf(fname, MAX_PATH-(fname-path), TEXT("\\Icons\\*.*")); + + WIN32_FIND_DATA FindFileData; + HANDLE hFind = FindFirstFile(path, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) return; + + do + { + if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; + + TCHAR timebuf[30] = TEXT(""); + GetLastWriteTime(&FindFileData.ftLastWriteTime, timebuf, 30); + + buffer.appendfmt(TEXT(" %s [%s]\r\n"), FindFileData.cFileName, timebuf); + } + while (FindNextFile(hFind, &FindFileData)); + FindClose(hFind); +} + + +void PrintVersionInfo(bkstring& buffer, unsigned flags) +{ + GetProcessorString(buffer); + buffer.append(TEXT("\r\n")); + + GetFreeMemoryString(buffer); + buffer.append(TEXT("\r\n")); + + GetOSDisplayString(buffer); + buffer.append(TEXT("\r\n")); + + GetInternetExplorerVersion(buffer); + buffer.append(TEXT("\r\n")); + + GetAdminString(buffer); + buffer.append(TEXT("\r\n")); + + GetLanguageString(buffer); + buffer.append(TEXT("\r\n")); + + TCHAR *profpathfull = Utils_ReplaceVarsT(profpath); + if (flags & VI_FLAG_PRNVAR) + { + GetFreeDiskString(profpathfull, buffer); + buffer.append(TEXT("\r\n")); + } + + buffer.appendfmt(TEXT("\r\nMiranda IM Version: %s"), vertxt); + GetWow64String(buffer); + buffer.append(TEXT("\r\n")); + + TCHAR path[MAX_PATH], mirtime[30]; + GetModuleFileName(NULL, path, MAX_PATH); + GetLastWriteTime(path, mirtime, 30); + buffer.appendfmt(TEXT("Build time: %s\r\n"), mirtime); + + TCHAR profpn[MAX_PATH]; + crs_sntprintf(profpn, SIZEOF(profpn), TEXT("%s\\%s"), profpathfull, profname); + + buffer.appendfmt(TEXT("Profile: %s\r\n"), profpn); + + if (flags & VI_FLAG_PRNVAR) + { + WIN32_FIND_DATA FindFileData; + + HANDLE hFind = FindFirstFile(profpn, &FindFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + FindClose(hFind); + + unsigned __int64 fsize = (unsigned __int64)FindFileData.nFileSizeHigh << 32 | FindFileData.nFileSizeLow; + buffer.appendfmt(TEXT("Profile size: %I64u Bytes\r\n"), fsize), + + GetLastWriteTime(&FindFileData.ftCreationTime, mirtime, 30); + buffer.appendfmt(TEXT("Profile creation date: %s\r\n"), mirtime); + } + } + mir_free(profpathfull); + + GetLanguagePackString(buffer); + buffer.append(TEXT("\r\n")); + + buffer.appendfmt(TEXT("Nightly: %s\r\n"), _tcsstr(vertxt, TEXT("alpha")) ? TEXT("Yes") : TEXT("No")); + buffer.appendfmt(TEXT("Unicode: %s\r\n"), _tcsstr(vertxt, TEXT("Unicode")) ? TEXT("Yes") : TEXT("No")); + + GetPluginsString(buffer, flags); + + if (flags & VI_FLAG_WEATHER) + { + buffer.appendfmt(TEXT("\r\n%sWeather ini files:%s\r\n-------------------------------------------------------------------------------\r\n"), + (flags & VI_FLAG_FORMAT) ? TEXT("[b]") : TEXT(""), + (flags & VI_FLAG_FORMAT) ? TEXT("[/b]") : TEXT("")); + GetWeatherStrings(buffer, flags); + } + + if (flags & VI_FLAG_PRNVAR && !servicemode) + { + buffer.appendfmt(TEXT("\r\n%sProtocols and Accounts:%s\r\n-------------------------------------------------------------------------------\r\n"), + (flags & VI_FLAG_FORMAT) ? TEXT("[b]") : TEXT(""), + (flags & VI_FLAG_FORMAT) ? TEXT("[/b]") : TEXT("")); + GetProtocolStrings(buffer); + } + + if (flags & VI_FLAG_PRNVAR) + { + buffer.appendfmt(TEXT("\r\n%sIcon Packs:%s\r\n-------------------------------------------------------------------------------\r\n"), + (flags & VI_FLAG_FORMAT) ? TEXT("[b]") : TEXT(""), + (flags & VI_FLAG_FORMAT) ? TEXT("[/b]") : TEXT("")); + GetIconStrings(buffer); + } + + if (flags & VI_FLAG_PRNDLL) + { + __try + { + buffer.append(TEXT("\r\nLoaded Modules:\r\n-------------------------------------------------------------------------------\r\n")); + EnumerateLoadedModules64(GetCurrentProcess(), LoadedModules64, &buffer); + } + __except(EXCEPTION_EXECUTE_HANDLER) {} + } + + if (flags & (VI_FLAG_PRNVAR | VI_FLAG_PRNDLL)) UnloadDbgHlp(); +} + + +void CreateCrashReport(HANDLE hDumpFile, PEXCEPTION_POINTERS exc_ptr, const TCHAR* msg) +{ + if (exc_ptr->ContextRecord == NULL || (exc_ptr->ContextRecord->ContextFlags & CONTEXT_CONTROL) == 0) + return; + + CONTEXT context = *exc_ptr->ContextRecord; + + STACKFRAME64 frame = {0}; + +#if defined(_AMD64_) +#define IMAGE_FILE_MACHINE IMAGE_FILE_MACHINE_AMD64 + frame.AddrPC.Offset = context.Rip; + frame.AddrFrame.Offset = context.Rbp; + frame.AddrStack.Offset = context.Rsp; +#elif defined(_IA64_) +#define IMAGE_FILE_MACHINE IMAGE_FILE_MACHINE_IA64 + frame.AddrPC.Offset = context.StIIP; + frame.AddrFrame.Offset = context.AddrBStore; + frame.AddrStack.Offset = context.SP; +#else +#define IMAGE_FILE_MACHINE IMAGE_FILE_MACHINE_I386 + frame.AddrPC.Offset = context.Eip; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrStack.Offset = context.Esp; +#endif + + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Mode = AddrModeFlat; + + const PLUGININFOEX *pluginInfoEx = GetPluginInfoEx(); + + bkstring buffer; + buffer.reserve(0x5000); + + TCHAR curtime[30]; + GetISO8061Time(NULL, curtime, 30); + + buffer.appendfmt(TEXT("Miranda Crash Report from %s. Crash Dumper v.%d.%d.%d.%d\r\n"), + curtime, + HIBYTE(HIWORD(pluginInfoEx->version)), LOBYTE(HIWORD(pluginInfoEx->version)), + HIBYTE(LOWORD(pluginInfoEx->version)), LOBYTE(LOWORD(pluginInfoEx->version))); + + size_t crashpos = buffer.size(); + + ReadableExceptionInfo(exc_ptr->ExceptionRecord, buffer); + buffer.append(TEXT("\r\n")); + + const HANDLE hProcess = GetCurrentProcess(); + + if (&SymSetOptions) + SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); + SymInitialize(hProcess, NULL, TRUE); + + buffer.append(TEXT("\r\nStack Trace:\r\n---------------------------------------------------------------\r\n")); + + for (int i=81; --i;) + { + /* + char symbuf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + 4] = {0}; + PSYMBOL_INFO pSym = (PSYMBOL_INFO)symbuf; + pSym->SizeOfStruct = sizeof(SYMBOL_INFO); + pSym->MaxNameLen = MAX_SYM_NAME; + */ + + char symbuf[sizeof(IMAGEHLP_SYMBOL64) + MAX_SYM_NAME * sizeof(TCHAR) + 4] = {0}; + PIMAGEHLP_SYMBOL64 pSym = (PIMAGEHLP_SYMBOL64)symbuf; + pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + pSym->MaxNameLength = MAX_SYM_NAME; + + IMAGEHLP_LINE64 Line = {0}; + Line.SizeOfStruct = sizeof(Line); + + IMAGEHLP_MODULE64 Module = {0}; + Module.SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2); + + char undName[MAX_SYM_NAME] = ""; + char undFullName[MAX_SYM_NAME] = ""; + + DWORD64 offsetFromSmybol = 0; + DWORD offsetFromLine = 0; + + if (!StackWalk64(IMAGE_FILE_MACHINE, hProcess, GetCurrentThread(), &frame, &context, + NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) break; + + if (frame.AddrPC.Offset == frame.AddrReturn.Offset) break; + + if (frame.AddrPC.Offset != 0) + { + if (SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offsetFromSmybol, pSym)) + // if (SymFromAddr(hProcess, frame.AddrPC.Offset, &offsetFromSmybol, pSym)) + { + UnDecorateSymbolName(pSym->Name, undName, MAX_SYM_NAME, UNDNAME_NAME_ONLY); + UnDecorateSymbolName(pSym->Name, undFullName, MAX_SYM_NAME, UNDNAME_COMPLETE); + } + + SymGetLineFromAddr64(hProcess, frame.AddrPC.Offset, &offsetFromLine, &Line); + SymGetModuleInfo64(hProcess, frame.AddrPC.Offset, &Module); + if (Module.ModuleName[0] == 0) + { + FindData data; + data.Offset = frame.AddrPC.Offset; + data.pModule = &Module; + EnumerateLoadedModules64(hProcess, LoadedModulesFind64, &data); + } + } + + const char* name; + if (undFullName[0] != 0) + name = undFullName; + else if (undName[0] != 0) + name = undName; + else if (pSym->Name[0] != 0) + name = pSym->Name; + else + name = "(function-name not available)"; + + const char *lineFileName = Line.FileName ? Line.FileName : "(filename not available)"; + const char *moduleName = Module.ModuleName[0] ? Module.ModuleName : "(module-name not available)"; + + if (crashpos != 0) + { + HMODULE hModule = (HMODULE)Module.BaseOfImage; + PLUGININFOEX *pi = GetMirInfo(hModule); + if (pi != NULL) + { + + static const TCHAR formatc[] = TEXT("\r\nLikely cause of the crash plugin: %S\r\n\r\n"); + + if (pi->shortName) + { + bkstring crashcause; + crashcause.appendfmt(formatc, pi->shortName); + buffer.insert(crashpos, crashcause); + } + crashpos = 0; + } + } + + + static const TCHAR formatd[] = TEXT("%p (%S %p): %S (%d): %S\r\n"); + + buffer.appendfmt(formatd, + (LPVOID)frame.AddrPC.Offset, moduleName, (LPVOID)Module.BaseOfImage, + lineFileName, Line.LineNumber, name); + } + SymCleanup(hProcess); + buffer.append(TEXT("\r\n")); + + PrintVersionInfo(buffer, VI_FLAG_PRNDLL); + + + int len = WideCharToMultiByte(CP_UTF8, 0, buffer.c_str(), -1, NULL, 0, NULL, NULL); + char* dst = (char*)(len > 8192 ? malloc(len) : alloca(len)); + WideCharToMultiByte(CP_UTF8, 0, buffer.c_str(), -1, dst, len, NULL, NULL); + + WriteUtfFile(hDumpFile, dst); + + if (len > 8192) free(dst); + + + if (msg && MessageBox(NULL, msg, TEXT("Miranda Crash Dumper"), MB_YESNO | MB_ICONERROR | MB_TASKMODAL | MB_DEFBUTTON2 | MB_TOPMOST) == IDYES) + StoreStringToClip(buffer); +} diff --git a/plugins/CrashDumper/src/exhndlr.cpp b/plugins/CrashDumper/src/exhndlr.cpp new file mode 100644 index 0000000000..93406efaa8 --- /dev/null +++ b/plugins/CrashDumper/src/exhndlr.cpp @@ -0,0 +1,207 @@ +#include "utils.h" +#include "crtdbg.h" + +static PVOID exchndlr, exchndlrv; +static pfnExceptionFilter threadfltr; +static PEXCEPTION_POINTERS lastptr; + +static HMODULE hKernel = GetModuleHandle(TEXT("kernel32.dll")); + +tAddVectoredExceptionHandler pAddVectoredExceptionHandler = (tAddVectoredExceptionHandler)GetProcAddress(hKernel, "AddVectoredExceptionHandler"); +tRemoveVectoredExceptionHandler pRemoveVectoredExceptionHandler = (tRemoveVectoredExceptionHandler)GetProcAddress(hKernel, "RemoveVectoredExceptionHandler"); +tRtlCaptureContext pRtlCaptureContext = (tRtlCaptureContext)GetProcAddress(hKernel, "RtlCaptureContext"); + +void SetExceptionHandler(void) +{ + // if (pAddVectoredExceptionHandler && !exchndlrv) + // exchndlrv = pAddVectoredExceptionHandler(0, myfilterv); + /*exchndlr = */ SetUnhandledExceptionFilter(myfilter); +} + +void RemoveExceptionHandler(void) +{ + if (pRemoveVectoredExceptionHandler && exchndlrv) + pRemoveVectoredExceptionHandler(exchndlrv); + SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)exchndlr); + exchndlr = NULL; + exchndlrv = NULL; +} + +void UnloadDbgHlp(void) +{ +#ifdef _MSC_VER +#if _MSC_VER > 1200 + __FUnloadDelayLoadedDLL2("dbghelp.dll"); +#else + __FUnloadDelayLoadedDLL("dbghelp.dll"); +#endif +#endif +} + +int myDebugFilter(unsigned int code, PEXCEPTION_POINTERS ep) +{ + if (code == VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) || + code == VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)) + { + PDelayLoadInfo dlld = (PDelayLoadInfo)ep->ExceptionRecord->ExceptionInformation[0]; + + char str[256]; + int off = mir_snprintf(str, SIZEOF(str), "dbghelp.dll v.5.0 or later required to provide a crash report\n"); + off += mir_snprintf(str+off, SIZEOF(str)-off, "Missing Module: %s ", dlld->szDll); + + if (dlld->dlp.fImportByName) + mir_snprintf(str+off, SIZEOF(str)-off, "Function: %s ", dlld->dlp.szProcName); + else + mir_snprintf(str+off, SIZEOF(str)-off, "Ordinal: %x ", dlld->dlp.dwOrdinal); + + MessageBoxA(NULL, str, "Miranda Crash Dumper", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST); + } + + return EXCEPTION_EXECUTE_HANDLER; +} + + +void myfilterWorker(PEXCEPTION_POINTERS exc_ptr, bool notify) +{ + TCHAR path[MAX_PATH]; + SYSTEMTIME st; + HANDLE hDumpFile = NULL; + + GetLocalTime(&st); + CreateDirectoryTree(CrashLogFolder); + + __try + { + if (dtsubfldr) + { + crs_sntprintf(path, MAX_PATH, TEXT("%s\\%02d.%02d.%02d"), CrashLogFolder, st.wYear, st.wMonth, st.wDay); + CreateDirectory(path, NULL); + crs_sntprintf(path, MAX_PATH, TEXT("%s\\%02d.%02d.%02d\\crash%02d%02d%02d%02d%02d%02d.mdmp"), CrashLogFolder, + st.wYear, st.wMonth, st.wDay, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); + } + else + { + crs_sntprintf(path, MAX_PATH, TEXT("%s\\crash%02d%02d%02d%02d%02d%02d.mdmp"), CrashLogFolder, + st.wYear, st.wMonth, st.wDay, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); + } + hDumpFile = CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + if (hDumpFile != INVALID_HANDLE_VALUE) + CreateMiniDump(hDumpFile, exc_ptr); + else if (GetLastError() != ERROR_ALREADY_EXISTS) + MessageBox(NULL, TranslateT("Crash Report write location is inaccesible"), + TEXT("Miranda Crash Dumper"), MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST); + + } + __except(EXCEPTION_EXECUTE_HANDLER) {} + + bool empty = GetFileSize(hDumpFile, NULL) == 0; + CloseHandle(hDumpFile); + if (empty) DeleteFile(path); + + __try + { + if (dtsubfldr) + { + crs_sntprintf(path, MAX_PATH, TEXT("%s\\%02d.%02d.%02d"), CrashLogFolder, st.wYear, st.wMonth, st.wDay); + CreateDirectory(path, NULL); + crs_sntprintf(path, MAX_PATH, TEXT("%s\\%02d.%02d.%02d\\crash%02d%02d%02d%02d%02d%02d.txt"), CrashLogFolder, + st.wYear, st.wMonth, st.wDay, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); + } + else + { + crs_sntprintf(path, MAX_PATH, TEXT("%s\\crash%02d%02d%02d%02d%02d%02d.txt"), CrashLogFolder, + st.wYear, st.wMonth, st.wDay, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); + } + hDumpFile = CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + + crs_sntprintf(path, MAX_PATH, TranslateT("Miranda crashed. Crash report stored in the folder:\n %s\n\n Would you like store it in the clipboard as well?"), CrashLogFolder); + + if (hDumpFile != INVALID_HANDLE_VALUE) + CreateCrashReport(hDumpFile, exc_ptr, notify ? path : NULL); + } + __except(myDebugFilter(GetExceptionCode(), GetExceptionInformation())) {} + + bool empty1 = GetFileSize(hDumpFile, NULL) == 0; + CloseHandle(hDumpFile); + if (empty1) DeleteFile(path); + + UnloadDbgHlp(); +} + +LONG WINAPI myfilter(PEXCEPTION_POINTERS exc_ptr) +{ + if (exc_ptr == lastptr) return EXCEPTION_EXECUTE_HANDLER; + lastptr = exc_ptr; + + myfilterWorker(exc_ptr, true); + + return exchndlr ? ((LPTOP_LEVEL_EXCEPTION_FILTER)exchndlr)(exc_ptr) : EXCEPTION_CONTINUE_SEARCH; +} + +LONG WINAPI myfilterv(PEXCEPTION_POINTERS exc_ptr) +{ + if (0xC0000000L <= exc_ptr->ExceptionRecord->ExceptionCode && 0xC0000500L >= exc_ptr->ExceptionRecord->ExceptionCode) + { + if (exc_ptr == lastptr) return EXCEPTION_EXECUTE_HANDLER; + lastptr = exc_ptr; + + myfilterWorker(exc_ptr, true); + } + return EXCEPTION_CONTINUE_SEARCH; +} + +DWORD MirandaThreadFilter(DWORD code, EXCEPTION_POINTERS* info) +{ + if (info != lastptr) + { + lastptr = info; + myfilterWorker(info, true); + } + return threadfltr(code, info); +} + +#if _MSC_VER >= 1400 +void InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, UINT_PTR) +{ + EXCEPTION_RECORD ExceptionRecord = {0}; + CONTEXT ContextRecord = {0}; + EXCEPTION_POINTERS info = { &ExceptionRecord, &ContextRecord }; + + if (pRtlCaptureContext) + pRtlCaptureContext(&ContextRecord); + else + { + ContextRecord.ContextFlags = CONTEXT_ALL; + GetThreadContext(GetCurrentThread(), &ContextRecord); + } + +#if defined(_AMD64_) + ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Rip; +#elif defined(_IA64_) + ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.BrRp; +#else + ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Eip; +#endif + + ExceptionRecord.ExceptionCode = STATUS_INVALID_CRUNTIME_PARAMETER; + ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + myfilterWorker(&info, true); +} +#endif + +void InitExceptionHandler(void) +{ +#if _MSC_VER >= 1400 + _set_invalid_parameter_handler(InvalidParameterHandler); +#endif + threadfltr = Miranda_SetExceptFilter(MirandaThreadFilter); + SetExceptionHandler(); +} + +void DestroyExceptionHandler(void) +{ + Miranda_SetExceptFilter(threadfltr); + RemoveExceptionHandler(); +} + diff --git a/plugins/CrashDumper/src/resource.h b/plugins/CrashDumper/src/resource.h new file mode 100644 index 0000000000..83d8a491e4 --- /dev/null +++ b/plugins/CrashDumper/src/resource.h @@ -0,0 +1,34 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by crshdmp.rc +// +#define IDD_VIEWVERSION 101 +#define IDR_CONTEXT 102 +#define IDI_VI 104 +#define IDI_VISHOW 105 +#define IDI_VITOCLIP 106 +#define IDI_VITOFILE 107 +#define IDI_VIUPLOAD 108 +#define IDD_OPTIONS 109 +#define IDC_VIEWVERSIONINFO 1001 +#define IDC_FILEVER 1003 +#define IDC_CLIPVER 1004 +#define IDC_USERNAME 1006 +#define IDC_PASSWORD 1007 +#define IDC_UPLOADCHN 1008 +#define IDC_CLASSICDATES 1009 +#define IDC_DATESUBFOLDER 1010 +#define IDM_COPY 40002 +#define IDM_COPYALL 40003 +#define IDM_SELECTALL 40004 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 110 +#define _APS_NEXT_COMMAND_VALUE 40005 +#define _APS_NEXT_CONTROL_VALUE 1011 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/CrashDumper/src/sdkstuff.h b/plugins/CrashDumper/src/sdkstuff.h new file mode 100644 index 0000000000..536a00bc40 --- /dev/null +++ b/plugins/CrashDumper/src/sdkstuff.h @@ -0,0 +1,124 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include + + +//#define DBGHELP_TRANSLATE_TCHAR + + +#ifndef __in_bcount_opt +#define __in_bcount_opt(x) +#endif + +#ifndef __out_bcount_opt +#define __out_bcount_opt(x) +#endif + +#include "dbghelp.h" + + +#ifndef PRODUCT_ULTIMATE + +#define PRODUCT_UNDEFINED 0x00000000 + +#define PRODUCT_ULTIMATE 0x00000001 +#define PRODUCT_HOME_BASIC 0x00000002 +#define PRODUCT_HOME_PREMIUM 0x00000003 +#define PRODUCT_ENTERPRISE 0x00000004 +#define PRODUCT_HOME_BASIC_N 0x00000005 +#define PRODUCT_BUSINESS 0x00000006 +#define PRODUCT_STANDARD_SERVER 0x00000007 +#define PRODUCT_DATACENTER_SERVER 0x00000008 +#define PRODUCT_SMALLBUSINESS_SERVER 0x00000009 +#define PRODUCT_ENTERPRISE_SERVER 0x0000000A +#define PRODUCT_STARTER 0x0000000B +#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C +#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D +#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E +#define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F +#define PRODUCT_BUSINESS_N 0x00000010 +#define PRODUCT_WEB_SERVER 0x00000011 +#define PRODUCT_CLUSTER_SERVER 0x00000012 +#define PRODUCT_HOME_SERVER 0x00000013 +#define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014 +#define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015 +#define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016 +#define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017 +#define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018 +#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019 + +#define PRODUCT_UNLICENSED 0xABCDABCD + +#define SM_TABLETPC 86 +#define SM_MEDIACENTER 87 +#define SM_STARTER 88 +#define SM_SERVERR2 89 + +#endif + +#ifndef VER_SUITE_STORAGE_SERVER +#define VER_SUITE_STORAGE_SERVER 0x00002000 +#define VER_SUITE_COMPUTE_SERVER 0x00004000 +#endif + +#ifndef PF_NX_ENABLED +#define PF_NX_ENABLED 12 +#endif + +typedef struct _IMAGEHLP_MODULE64_V2 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) + DWORD64 BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + CHAR ModuleName[32]; // module name + CHAR ImageName[256]; // image name + CHAR LoadedImageName[256]; // symbol file name +} IMAGEHLP_MODULE64_V2; + +typedef struct _IMAGEHLP_MODULEW64_V2 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) + DWORD64 BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + WCHAR ModuleName[32]; // module name + WCHAR ImageName[256]; // image name + WCHAR LoadedImageName[256]; // symbol file name +} IMAGEHLP_MODULEW64_V2; + +#ifdef DBGHELP_TRANSLATE_TCHAR +#define IMAGEHLP_MODULE64_V2 IMAGEHLP_MODULEW64_V2 +#endif + +typedef void (WINAPI *tGetNativeSystemInfo)(LPSYSTEM_INFO); +typedef BOOL (WINAPI *tGetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD); +typedef BOOL (WINAPI *tGlobalMemoryStatusEx)(LPMEMORYSTATUSEX lpBuffer); +typedef BOOL (WINAPI *tGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER); +typedef LANGID (WINAPI *tGetUserDefaultUILanguage)(void); +typedef LANGID (WINAPI *tGetSystemDefaultUILanguage)(void); +typedef BOOL (WINAPI *tIsWow64Process)(HANDLE, PBOOL); +typedef PVOID (WINAPI *tAddVectoredExceptionHandler)(ULONG FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler); +typedef ULONG (WINAPI *tRemoveVectoredExceptionHandler)(PVOID Handler); +typedef BOOL (WINAPI *tIsProcessorFeaturePresent)(DWORD ProcessorFeature); +typedef VOID (WINAPI *tRtlCaptureContext)(PCONTEXT ContextRecord); diff --git a/plugins/CrashDumper/src/ui.cpp b/plugins/CrashDumper/src/ui.cpp new file mode 100644 index 0000000000..00cf9c26cd --- /dev/null +++ b/plugins/CrashDumper/src/ui.cpp @@ -0,0 +1,327 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "utils.h" +#include +#include +#include + +HWND hViewWnd; +extern HINSTANCE hInst; + + +HDWP MyResizeWindow (HDWP hDwp, HWND hwndDlg, HWND hwndCtrl, int nHorizontalOffset, int nVerticalOffset, + int nWidthOffset, int nHeightOffset) +{ + POINT pt; + RECT rcinit; + + // get current bounding rectangle + GetWindowRect(hwndCtrl, &rcinit); + + // get current top left point + pt.x = rcinit.left; + pt.y = rcinit.top; + ScreenToClient(hwndDlg, &pt); + + return DeferWindowPos(hDwp, hwndCtrl, NULL, + pt.x + nHorizontalOffset, + pt.y + nVerticalOffset, + rcinit.right - rcinit.left + nWidthOffset, + rcinit.bottom - rcinit.top + nHeightOffset, + SWP_NOZORDER); +} + +BOOL MyResizeGetOffset(HWND hwndCtrl, int nWidth, int nHeight, int* nDx, int* nDy) +{ + RECT rcinit; + + // get current bounding rectangle + GetWindowRect(hwndCtrl, &rcinit); + + // calculate offsets + *nDx = nWidth - (rcinit.right - rcinit.left); + *nDy = nHeight - (rcinit.bottom - rcinit.top); + + return rcinit.bottom != rcinit.top && nHeight > 0; +} + +INT_PTR CALLBACK DlgProcView(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + if (hViewWnd == NULL) + { + hViewWnd = hwndDlg; + TranslateDialogDefault(hwndDlg); + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIconEx("versionInfo", true)); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIconEx("versionInfo")); + + CHARFORMAT2 chf; + chf.cbSize = sizeof(chf); + SendDlgItemMessage(hwndDlg, IDC_VIEWVERSIONINFO, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&chf); + _tcscpy(chf.szFaceName, TEXT("Courier New")); + SendDlgItemMessage(hwndDlg, IDC_VIEWVERSIONINFO, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&chf); + + bkstring buffer; + buffer.reserve(0x1800); + PrintVersionInfo(buffer, (unsigned int)lParam); + SetDlgItemText(hwndDlg, IDC_VIEWVERSIONINFO, buffer.c_str()); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); + + Utils_RestoreWindowPositionNoMove(hwndDlg, NULL, PluginName, "ViewInfo_"); + ShowWindow(hwndDlg, SW_SHOW); + } + else + DestroyWindow(hwndDlg); + break; + + case WM_SIZE: + { + int dx, dy, bsz; + HDWP hDwp; + RECT rc; + + GetWindowRect(GetDlgItem(hwndDlg, IDC_FILEVER), &rc); + bsz = rc.bottom - rc.top; + + if (MyResizeGetOffset(GetDlgItem(hwndDlg, IDC_VIEWVERSIONINFO), + LOWORD(lParam)-20, HIWORD(lParam)-30-bsz, &dx, &dy)) + { + hDwp = BeginDeferWindowPos(4); + hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_FILEVER), 0, dy, 0, 0); + hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_CLIPVER), dx/2, dy, 0, 0); + hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDCANCEL), dx, dy, 0, 0); + hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_VIEWVERSIONINFO), 0, 0, dx, dy); + EndDeferWindowPos(hDwp); + } + } + break; + + case WM_GETMINMAXINFO: + { + LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; + + // The minimum width in points + mmi->ptMinTrackSize.x = 350; + // The minimum height in points + mmi->ptMinTrackSize.y = 300; + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_CLIPVER: + CallService(MS_CRASHDUMPER_STORETOCLIP, 0, GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); + break; + + case IDC_FILEVER: + CallService(MS_CRASHDUMPER_STORETOFILE, 0, GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); + break; + + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_CONTEXTMENU: + { + HWND hView = GetDlgItem(hwndDlg, IDC_VIEWVERSIONINFO); + RECT rc; + GetWindowRect(hView, &rc); + + POINT pt; + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + if (PtInRect(&rc, pt)) + { + static const CHARRANGE all = { 0, -1 }; + + HMENU hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + HMENU hSubMenu = GetSubMenu(hMenu, 0); + TranslateMenu(hSubMenu); + + CHARRANGE sel; + SendMessage(hView, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) + EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + + switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) + { + case IDM_COPY: + SendMessage(hView, WM_COPY, 0, 0); + break; + + case IDM_COPYALL: + SendMessage(hView, EM_EXSETSEL, 0, (LPARAM)&all); + SendMessage(hView, WM_COPY, 0, 0); + SendMessage(hView, EM_EXSETSEL, 0, (LPARAM)&sel); + break; + + case IDM_SELECTALL: + SendMessage(hView, EM_EXSETSEL, 0, (LPARAM)&all); + break; + } + DestroyMenu(hMenu); + } + } + break; + + case WM_DESTROY: + hViewWnd = NULL; + ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0)); + ReleaseIconEx((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0)); + Utils_SaveWindowPosition(hwndDlg, NULL, PluginName, "ViewInfo_"); + if (servicemode) PostQuitMessage(0); + break; + } + return FALSE; +} + + +void DestroyAllWindows(void) +{ + if (hViewWnd != NULL) DestroyWindow(hViewWnd); + hViewWnd = NULL; +} + + +INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + + DBVARIANT dbv; + if (DBGetContactSettingString(NULL, PluginName, "Username", &dbv) == 0) + { + SetDlgItemTextA(hwndDlg, IDC_USERNAME, dbv.pszVal); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(NULL, PluginName, "Password", &dbv) == 0) + { + CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM)dbv.pszVal); + SetDlgItemTextA(hwndDlg, IDC_PASSWORD, dbv.pszVal); + DBFreeVariant(&dbv); + } + CheckDlgButton(hwndDlg, IDC_UPLOADCHN, DBGetContactSettingByte(NULL, PluginName, "UploadChanged", 0)); + CheckDlgButton(hwndDlg, IDC_CLASSICDATES, clsdates); + CheckDlgButton(hwndDlg, IDC_DATESUBFOLDER, dtsubfldr); + } + break; + + case WM_COMMAND: + if ((HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == BN_CLICKED) && (HWND)lParam == GetFocus()) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->code == (unsigned)PSN_APPLY) + { + char szSetting[100]; + GetDlgItemTextA(hwndDlg, IDC_USERNAME, szSetting, SIZEOF(szSetting)); + DBWriteContactSettingString(NULL, PluginName, "Username", szSetting); + + GetDlgItemTextA(hwndDlg, IDC_PASSWORD, szSetting, SIZEOF(szSetting)); + CallService(MS_DB_CRYPT_ENCODESTRING, SIZEOF(szSetting), (LPARAM)szSetting); + DBWriteContactSettingString(NULL, PluginName, "Password", szSetting); + + DBWriteContactSettingByte(NULL, PluginName, "UploadChanged", + (BYTE)IsDlgButtonChecked(hwndDlg, IDC_UPLOADCHN)); + + clsdates = IsDlgButtonChecked(hwndDlg, IDC_CLASSICDATES) == BST_CHECKED; + if (clsdates) + DBWriteContactSettingByte(NULL, PluginName, "ClassicDates", 1); + else + DBDeleteContactSetting(NULL, PluginName, "ClassicDates"); + dtsubfldr = IsDlgButtonChecked(hwndDlg, IDC_DATESUBFOLDER) == BST_CHECKED; + if (dtsubfldr) + DBWriteContactSettingByte(NULL, PluginName, "SubFolders", 1); + else + DBDeleteContactSetting(NULL, PluginName, "SubFolders"); + } + break; + } + return FALSE; +} + + +LRESULT CALLBACK DlgProcPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CONTEXTMENU: + PUDeletePopUp(hWnd); + break; + + case WM_COMMAND: + switch ((int)PUGetPluginData(hWnd)) + { + case 0: + OpenAuthUrl("http://www.miranda-vi.org/"); + break; + + case 1: + OpenAuthUrl("http://%s.miranda-vi.org/global"); + break; + + case 3: + TCHAR path[MAX_PATH]; + crs_sntprintf(path, MAX_PATH, TEXT("%s\\VersionInfo.txt"), VersionInfoFolder); + ShellExecute(NULL, TEXT("open"), path, NULL, NULL, SW_SHOW); + break; + + } + PUDeletePopUp(hWnd); + break; + + case UM_FREEPLUGINDATA: + ReleaseIconEx("versionInfo"); + break; + } + + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +void ShowMessage(int type, const TCHAR* format, ...) +{ + POPUPDATAT pi = {0}; + + va_list va; + va_start(va, format); + int len = _vsntprintf(pi.lptzText, SIZEOF(pi.lptzText)-1, format, va); + pi.lptzText[len] = 0; + va_end(va); + + if (ServiceExists(MS_POPUP_ADDPOPUPT)) + { + _tcscpy(pi.lptzContactName, TEXT(PluginName)); + pi.lchIcon = LoadIconEx("versionInfo"); + pi.PluginWindowProc = DlgProcPopup; + pi.PluginData = (void*)type; + + PUAddPopUpT(&pi); + } + else + MessageBox(NULL, pi.lptzText, TEXT(PluginName), MB_OK | MB_ICONINFORMATION); +} diff --git a/plugins/CrashDumper/src/upload.cpp b/plugins/CrashDumper/src/upload.cpp new file mode 100644 index 0000000000..498b5cb2f6 --- /dev/null +++ b/plugins/CrashDumper/src/upload.cpp @@ -0,0 +1,292 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "utils.h" +#include + +HANDLE hNetlibUser; + +static void arrayToHex(BYTE* data, size_t datasz, char* res) +{ + char* resptr = res; + for (unsigned i=0; i> 4); + *resptr++ = (char)((ch0 <= 9) ? ('0' + ch0) : (('a' - 10) + ch0)); + + const char ch1 = (char)(ch & 0xF); + *resptr++ = (char)((ch1 <= 9) ? ('0' + ch1) : (('a' - 10) + ch1)); + } + *resptr = '\0'; +} + +void GetLoginStr(char* user, size_t szuser, char* pass) +{ + DBVARIANT dbv; + + if (DBGetContactSettingString(NULL, PluginName, "Username", &dbv) == 0) + { + mir_snprintf(user, szuser, "%s", dbv.pszVal); + DBFreeVariant(&dbv); + } + else + user[0] = 0; + + if (DBGetContactSettingString(NULL, PluginName, "Password", &dbv) == 0) + { + CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM)dbv.pszVal); + + mir_md5_byte_t hash[16]; + mir_md5_state_t context; + + mir_md5_init(&context); + mir_md5_append(&context, (BYTE*)dbv.pszVal, (int)strlen(dbv.pszVal)); + mir_md5_finish(&context, hash); + + arrayToHex(hash, sizeof(hash), pass); + + DBFreeVariant(&dbv); + } + else + pass[0] = 0; +} + +void OpenAuthUrl(const char* url) +{ + char user[64], pass[40]; + GetLoginStr(user, sizeof(user), pass); + + if (user[0] && pass[0]) + { + char str[256]; + + mir_snprintf(str, sizeof(str), url, user); + char* eurl = (char*)CallService(MS_NETLIB_URLENCODE, 0, (LPARAM)str); + + mir_snprintf(str, sizeof(str), "http://www.miranda-vi.org/cdlogin?name=%s&pass=%s&redir=%s", user, pass, eurl); + CallService(MS_UTILS_OPENURL, 1, (LPARAM)str); + HeapFree(GetProcessHeap(), 0, eurl); + } + else + CallService(MS_UTILS_OPENURL, 1, (LPARAM)"http://www.miranda-vi.org/"); +} + +void CreateAuthString(char* auth) +{ + char user[64], pass[40]; + GetLoginStr(user, sizeof(user), pass); + + char str[110]; + int len = mir_snprintf(str, sizeof(str), "%s:%s", user, pass); + + strcpy(auth, "Basic "); + NETLIBBASE64 nlb = { auth+6, 250, (PBYTE)str, len }; + CallService(MS_NETLIB_BASE64ENCODE, 0, LPARAM(&nlb)); +} + + +bool InternetDownloadFile(const char *szUrl, VerTrnsfr* szReq) +{ + int result = 0xBADBAD; + char* szRedirUrl = NULL; + NETLIBHTTPREQUEST nlhr = {0}; + + // initialize the netlib request + nlhr.cbSize = sizeof(nlhr); + nlhr.requestType = REQUEST_POST; + nlhr.flags = NLHRF_HTTP11 | NLHRF_NODUMP; + nlhr.szUrl = (char*)szUrl; + + nlhr.headersCount = 6; + nlhr.headers=(NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount); + nlhr.headers[0].szName = "Connection"; + nlhr.headers[0].szValue = "close"; + nlhr.headers[1].szName = "Cache-Control"; + nlhr.headers[1].szValue = "no-cache"; + nlhr.headers[2].szName = "Pragma"; + nlhr.headers[2].szValue = "no-cache"; + nlhr.headers[3].szName = "Content-Type"; + nlhr.headers[3].szValue = "text/plain; charset=utf-8"; + nlhr.headers[4].szName = "AutoUpload"; + nlhr.headers[4].szValue = (char*)(szReq->autot ? "1" : "0"); + nlhr.headers[5].szName = "Authorization"; + + char auth[256]; + CreateAuthString(auth); + nlhr.headers[5].szValue = auth; + + nlhr.pData = szReq->buf; + nlhr.dataLength = (int)strlen(szReq->buf); + + while (result == 0xBADBAD) + { + // download the page + NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, + (WPARAM)hNetlibUser,(LPARAM)&nlhr); + + if (nlhrReply) + { + int i; + + // if the recieved code is 200 OK + switch(nlhrReply->resultCode) + { + case 200: + if (DBGetContactSettingByte(NULL, PluginName, "UploadChanged", 0)) + ProcessVIHash(true); + + for (i=nlhrReply->headersCount; i--; ) + { + if (_stricmp(nlhrReply->headers[i].szName, "OldPlugins") == 0) + { + i = atoi(nlhrReply->headers[i].szValue); + break; + } + } + + ShowMessage(1, TranslateT("VersionInfo upload successful,\n %d old plugins"), i); + result = 0; + break; + + case 401: + ShowMessage(0, TranslateT("Cannot upload VersionInfo. Incorrect username or password")); + result = 1; + break; + + case 510: + ShowMessage(0, TranslateT("Cannot upload VersionInfo. User is banned")); + result = 1; + break; + + case 511: + ShowMessage(0, TranslateT("Cannot upload VersionInfo. Daily upload limit exceeded")); + result = 1; + break; + + case 301: + case 302: + case 307: + // get the url for the new location and save it to szInfo + // look for the reply header "Location" + for (i=0; iheadersCount; i++) + { + if (!strcmp(nlhrReply->headers[i].szName, "Location")) + { + size_t rlen = 0; + if (nlhrReply->headers[i].szValue[0] == '/') + { + const char* szPath; + const char* szPref = strstr(szUrl, "://"); + szPref = szPref ? szPref + 3 : szUrl; + szPath = strchr(szPref, '/'); + rlen = szPath != NULL ? szPath - szUrl : strlen(szUrl); + } + + szRedirUrl = (char*)mir_realloc(szRedirUrl, + rlen + strlen(nlhrReply->headers[i].szValue)*3 + 1); + + strncpy(szRedirUrl, szUrl, rlen); + strcpy(szRedirUrl+rlen, nlhrReply->headers[i].szValue); + + nlhr.szUrl = szRedirUrl; + break; + } + } + break; + + default: + result = 1; + ShowMessage(0, TranslateT("Cannot upload VersionInfo. Unknown error")); + } + } + else + { + result = 1; + ShowMessage(0, TranslateT("Cannot upload VersionInfo. Host unreachable.")); + } + + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)nlhrReply); + } + + mir_free(szRedirUrl); + mir_free(nlhr.headers); + + return result == 0; +} + +void __cdecl VersionInfoUploadThread(void* arg) +{ + VerTrnsfr* trn = (VerTrnsfr*)arg; + InternetDownloadFile("http://www.miranda-vi.org/uploadpost", trn); + mir_free(trn->buf); + mir_free(trn); +} + + +void UploadInit(void) +{ + NETLIBUSER nlu = {0}; + nlu.cbSize = sizeof(nlu); + nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_NOHTTPSOPTION | NUF_TCHAR; + nlu.szSettingsModule = (char*)PluginName; + nlu.ptszDescriptiveName = TranslateT("Crash Dumper HTTP connections"); + hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); +} + +void UploadClose(void) +{ + Netlib_CloseHandle(hNetlibUser); +} + +bool ProcessVIHash(bool store) +{ + bkstring buffer; + buffer.reserve(0x1800); + PrintVersionInfo(buffer, 0); + + mir_md5_byte_t hash[16]; + mir_md5_state_t context; + + mir_md5_init(&context); + mir_md5_append(&context, (PBYTE)buffer.c_str(), (int)buffer.sizebytes()); + mir_md5_finish(&context, hash); + + char hashstr[40]; + arrayToHex(hash, sizeof(hash), hashstr); + + bool result; + if (store) + { + DBWriteContactSettingString(NULL, PluginName, "VIHash", hashstr); + result = true; + } + else + { + DBVARIANT dbv; + if (DBGetContactSettingString(NULL, PluginName, "VIHash", &dbv) == 0) + { + result = strcmp(hashstr, dbv.pszVal) == 0; + DBFreeVariant(&dbv); + } + else + result = false; + } + return result; +} diff --git a/plugins/CrashDumper/src/utils.cpp b/plugins/CrashDumper/src/utils.cpp new file mode 100644 index 0000000000..d4dced7d70 --- /dev/null +++ b/plugins/CrashDumper/src/utils.cpp @@ -0,0 +1,836 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "utils.h" +#include + +static HMODULE hKernel = GetModuleHandle(TEXT("kernel32.dll")); + +tGetNativeSystemInfo pGetNativeSystemInfo = (tGetNativeSystemInfo)GetProcAddress(hKernel, "GetNativeSystemInfo"); +tGetProductInfo pGetProductInfo = (tGetProductInfo) GetProcAddress(hKernel, "GetProductInfo"); +tGlobalMemoryStatusEx pGlobalMemoryStatusEx = (tGlobalMemoryStatusEx) GetProcAddress(hKernel, "GlobalMemoryStatusEx"); +tGetUserDefaultUILanguage pGetUserDefaultUILanguage = (tGetUserDefaultUILanguage) GetProcAddress(hKernel, "GetUserDefaultUILanguage"); +tGetSystemDefaultUILanguage pGetSystemDefaultUILanguage = (tGetSystemDefaultUILanguage) GetProcAddress(hKernel, "GetSystemDefaultUILanguage"); +tIsWow64Process pIsWow64Process = (tIsWow64Process) GetProcAddress(hKernel, "IsWow64Process"); +tIsProcessorFeaturePresent pIsProcessorFeaturePresent = (tIsProcessorFeaturePresent) GetProcAddress(hKernel, "IsProcessorFeaturePresent"); + + +tGetDiskFreeSpaceEx pGetDiskFreeSpaceEx = (tGetDiskFreeSpaceEx) GetProcAddress(hKernel, "GetDiskFreeSpaceExW"); + + + +void CheckForOtherCrashReportingPlugins(void) +{ + HMODULE hModule = GetModuleHandle(TEXT("attache.dll")); + if (hModule == NULL) + hModule = GetModuleHandle(TEXT("crashrpt.dll")); + if (hModule == NULL) + hModule = GetModuleHandle(TEXT("crashdmp.dll")); + + if (hModule == NULL) return; + + MessageBox(NULL, TranslateT("More then one crash reporting plugin installed. This will result in inability of creating crash reports"), + TEXT("Miranda Crash Dumper"), MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST); +} + +void GetOSDisplayString(bkstring& buffer) +{ + OSVERSIONINFOEX osvi = {0}; + SYSTEM_INFO si = {0}; + BOOL bOsVersionInfoEx; + DWORD dwType = 0; + + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO*)&osvi)) + return; + } + + // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. + pGetNativeSystemInfo = (tGetNativeSystemInfo)GetProcAddress(hKernel, "GetNativeSystemInfo"); + if (NULL != pGetNativeSystemInfo) pGetNativeSystemInfo(&si); + else GetSystemInfo(&si); + + if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && osvi.dwMajorVersion > 4) + { + buffer.append(TEXT("Operating System: Microsoft ")); + + // Test for the specific product. + if (osvi.dwMajorVersion == 6) + { + switch (osvi.dwMinorVersion) + { + case 0: + if (osvi.wProductType == VER_NT_WORKSTATION) + buffer.append(TEXT("Windows Vista ")); + else + buffer.append(TEXT("Windows Server 2008 ")); + break; + + case 1: + if (osvi.wProductType == VER_NT_WORKSTATION) + buffer.append(TEXT("Windows 7 ")); + else + buffer.append(TEXT("Windows Server 2008 R2 ")); + break; + + default: + if (osvi.wProductType == VER_NT_WORKSTATION) + buffer.append(TEXT("Windows 8 ")); + else + buffer.append(TEXT("Windows Server 2012 ")); + break; + } + + pGetProductInfo = (tGetProductInfo) GetProcAddress(hKernel, "GetProductInfo"); + if (pGetProductInfo != NULL) pGetProductInfo(6, 0, 0, 0, &dwType); + + switch(dwType) + { + case PRODUCT_ULTIMATE: + buffer.append(TEXT("Ultimate Edition")); + break; + case PRODUCT_HOME_PREMIUM: + buffer.append(TEXT("Home Premium Edition")); + break; + case PRODUCT_HOME_BASIC: + buffer.append(TEXT("Home Basic Edition")); + break; + case PRODUCT_ENTERPRISE: + buffer.append(TEXT("Enterprise Edition")); + break; + case PRODUCT_BUSINESS: + buffer.append(TEXT("Business Edition")); + break; + case PRODUCT_STARTER: + buffer.append(TEXT("Starter Edition")); + break; + case PRODUCT_CLUSTER_SERVER: + buffer.append(TEXT("Cluster Server Edition")); + break; + case PRODUCT_DATACENTER_SERVER: + buffer.append(TEXT("Datacenter Edition")); + break; + case PRODUCT_DATACENTER_SERVER_CORE: + buffer.append(TEXT("Datacenter Edition (core installation)")); + break; + case PRODUCT_ENTERPRISE_SERVER: + buffer.append(TEXT("Enterprise Edition")); + break; + case PRODUCT_ENTERPRISE_SERVER_CORE: + buffer.append(TEXT("Enterprise Edition (core installation)")); + break; + case PRODUCT_ENTERPRISE_SERVER_IA64: + buffer.append(TEXT("Enterprise Edition for Itanium-based Systems")); + break; + case PRODUCT_SMALLBUSINESS_SERVER: + buffer.append(TEXT("Small Business Server")); + break; + case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: + buffer.append(TEXT("Small Business Server Premium Edition")); + break; + case PRODUCT_STANDARD_SERVER: + buffer.append(TEXT("Standard Edition")); + break; + case PRODUCT_STANDARD_SERVER_CORE: + buffer.append(TEXT("Standard Edition (core installation)")); + break; + case PRODUCT_WEB_SERVER: + buffer.append(TEXT("Web Server Edition")); + break; + } + + if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) + buffer.append(TEXT(", 64-bit")); + else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL) + buffer.append(TEXT(", 32-bit")); + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + if (GetSystemMetrics(SM_SERVERR2)) + buffer.append(TEXT("Windows Server 2003 R2, ")); + else if (osvi.wSuiteMask==VER_SUITE_STORAGE_SERVER) + buffer.append(TEXT("Windows Storage Server 2003")); + else if (osvi.wProductType == VER_NT_WORKSTATION && + si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + buffer.append(TEXT("Windows XP Professional x64 Edition")); + else buffer.append(TEXT("Windows Server 2003, ")); + + // Test for the server type. + if (osvi.wProductType != VER_NT_WORKSTATION) + { + if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64) + { + if(osvi.wSuiteMask & VER_SUITE_DATACENTER) + buffer.append(TEXT("Datacenter Edition for Itanium-based Systems")); + else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + buffer.append(TEXT("Enterprise Edition for Itanium-based Systems")); + } + + else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) + { + if(osvi.wSuiteMask & VER_SUITE_DATACENTER) + buffer.append(TEXT("Datacenter x64 Edition")); + else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + buffer.append(TEXT("Enterprise x64 Edition")); + else buffer.append(TEXT("Standard x64 Edition")); + } + + else + { + if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) + buffer.append(TEXT("Compute Cluster Edition")); + else if(osvi.wSuiteMask & VER_SUITE_DATACENTER) + buffer.append(TEXT("Datacenter Edition")); + else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + buffer.append(TEXT("Enterprise Edition")); + else if (osvi.wSuiteMask & VER_SUITE_BLADE) + buffer.append(TEXT("Web Edition")); + else buffer.append(TEXT("Standard Edition")); + } + } + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + { + buffer.append(TEXT("Windows XP ")); + if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + buffer.append(TEXT("Home Edition")); + else + buffer.append(TEXT("Professional")); + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + buffer.append(TEXT("Windows 2000 ")); + + if (osvi.wProductType == VER_NT_WORKSTATION) + { + buffer.append(TEXT("Professional")); + } + else + { + if(osvi.wSuiteMask & VER_SUITE_DATACENTER) + buffer.append(TEXT("Datacenter Server")); + else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + buffer.append(TEXT("Advanced Server")); + else buffer.append(TEXT("Server")); + } + } + if (_tcslen(osvi.szCSDVersion) > 0) + { + buffer.append(TEXT(" ")); + buffer.append(osvi.szCSDVersion); + } + + buffer.appendfmt(TEXT(" (build %d)"), osvi.dwBuildNumber); + } + else + { + if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId) + { + buffer.append(TEXT("Microsoft Windows NT ")); + if (osvi.wProductType == VER_NT_WORKSTATION) + buffer.append(TEXT("Workstation 4.0 ")); + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + buffer.append(TEXT("Server 4.0, Enterprise Edition ")); + else + buffer.append(TEXT("Server 4.0 ")); + } + + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && osvi.dwMajorVersion == 4) + { + if (osvi.dwMinorVersion == 0) + { + buffer.append(TEXT("Microsoft Windows 95 ")); + if (osvi.szCSDVersion[1]==TEXT('C') || osvi.szCSDVersion[1]==TEXT('B')) + buffer.append(TEXT("OSR2 ")); + } + + if (osvi.dwMinorVersion == 10) + { + buffer.append(TEXT("Microsoft Windows 98 ")); + if (osvi.szCSDVersion[1]==TEXT('A') || osvi.szCSDVersion[1]==TEXT('B')) + buffer.append(TEXT("SE ")); + } + + if (osvi.dwMinorVersion == 90) + { + buffer.append(TEXT("Microsoft Windows Millennium Edition")); + } + buffer.appendfmt(TEXT("(build %d)"), LOWORD(osvi.dwBuildNumber)); + } + else if (osvi.dwPlatformId == VER_PLATFORM_WIN32s) + { + buffer.append(TEXT("Microsoft Win32s")); + } + } +} + +int GetTZOffset(void) +{ + TIME_ZONE_INFORMATION tzInfo = {0}; + DWORD type = GetTimeZoneInformation(&tzInfo); + + int offset = 0; + switch (type) + { + case TIME_ZONE_ID_DAYLIGHT: + offset = -(tzInfo.Bias + tzInfo.DaylightBias); + break; + + case TIME_ZONE_ID_STANDARD: + offset = -(tzInfo.Bias + tzInfo.StandardBias); + break; + + case TIME_ZONE_ID_UNKNOWN: + offset = -tzInfo.Bias; + break; + } + return offset; +} + +void GetISO8061Time(SYSTEMTIME* stLocal, LPTSTR lpszString, DWORD dwSize) +{ + SYSTEMTIME loctime; + if (stLocal == NULL) + { + stLocal = &loctime; + GetLocalTime(stLocal); + } + + if (clsdates) + { + GetDateFormat(LOCALE_INVARIANT, 0, stLocal, TEXT("d MMM yyyy"), lpszString, dwSize); + int dlen = (int)_tcslen(lpszString); + GetTimeFormat(LOCALE_INVARIANT, 0, stLocal, TEXT(" H:mm:ss"), lpszString+dlen, dwSize-dlen); + } + else + { + int offset = GetTZOffset(); + + // Build a string showing the date and time. + crs_sntprintf(lpszString, dwSize, TEXT("%d-%02d-%02d %02d:%02d:%02d%+03d%02d"), + stLocal->wYear, stLocal->wMonth, stLocal->wDay, + stLocal->wHour, stLocal->wMinute, stLocal->wSecond, + offset / 60, offset % 60); + } +} + +void GetLastWriteTime(FILETIME* ftime, LPTSTR lpszString, DWORD dwSize) +{ + FILETIME ftLocal; + SYSTEMTIME stLocal; + + // Convert the last-write time to local time. + FileTimeToLocalFileTime(ftime, &ftLocal); + FileTimeToSystemTime(&ftLocal, &stLocal); + + GetISO8061Time(&stLocal, lpszString, dwSize); +} + +void GetLastWriteTime(LPCTSTR fileName, LPTSTR lpszString, DWORD dwSize) +{ + WIN32_FIND_DATA FindFileData; + + HANDLE hFind = FindFirstFile(fileName, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) return; + FindClose(hFind); + + GetLastWriteTime(&FindFileData.ftLastWriteTime, lpszString, dwSize); +} + +typedef PLUGININFOEX * (__cdecl * Miranda_Plugin_Info) (DWORD mirandaVersion); + +PLUGININFOEX* GetMirInfo(HMODULE hModule) +{ + Miranda_Plugin_Info bpi = (Miranda_Plugin_Info)GetProcAddress(hModule, "MirandaPluginInfoEx"); + if (bpi == NULL) + return NULL; + + return bpi(mirandaVersion); +} + + +void GetInternetExplorerVersion(bkstring& buffer) +{ + HKEY hKey; + DWORD size; + + TCHAR ieVersion[1024] = {0}; + TCHAR ieBuild[512] = {0}; + TCHAR iVer[64] = {0}; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Internet Explorer"), 0, + KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + size = sizeof(ieBuild)/sizeof(ieBuild[0]); + if (RegQueryValueEx(hKey, TEXT("Build"), NULL, NULL, (LPBYTE) ieBuild, &size) != ERROR_SUCCESS) + ieBuild[0] = 0; + + size = sizeof(ieVersion)/sizeof(ieVersion[0]); + if (RegQueryValueEx(hKey, TEXT("Version"), NULL, NULL, (LPBYTE) ieVersion, &size) != ERROR_SUCCESS) + ieVersion[0] = 0; + + size = sizeof(iVer)/sizeof(iVer[0]); + if (RegQueryValueEx(hKey, TEXT("IVer"), NULL, NULL, (LPBYTE) iVer, &size) != ERROR_SUCCESS) + iVer[0] = 0; + + RegCloseKey(hKey); + } + + buffer.append(TEXT("Internet Explorer: ")); + if (ieVersion[0] == 0) + { + if (iVer[0] == 0) + buffer.append(TEXT("")); + else if (_tcscmp(iVer, TEXT("100")) == 0) + buffer.append(TEXT("1.0")); + else if (_tcscmp(iVer, TEXT("101")) == 0) + buffer.append(TEXT("NT")); + else if (_tcscmp(iVer, TEXT("102")) == 0) + buffer.append(TEXT("2.0")); + else if (_tcscmp(iVer, TEXT("103")) == 0) + buffer.append(TEXT("3.0")); + } + else + { + buffer.append(ieVersion); + } + if (ieBuild[0] != 0) + { + buffer.appendfmt(TEXT(" (build %s)"), ieBuild); + } +} + + +void TrimMultiSpaces(TCHAR* str) +{ + TCHAR *src = str, *dest = str; + bool trimst = false; + + for (;;) + { + if (*src == TEXT(' ')) + { + if (!trimst) + { + trimst = true; + *dest++ = *src; + } + } + else + { + trimst = false; + *dest++ = *src; + } + if (*src++ == 0) break; + } +} + +void GetProcessorString(bkstring& buffer) +{ + HKEY hKey; + DWORD size; + + TCHAR cpuIdent[512] = {0}; + TCHAR cpuName[512] = {0}; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Hardware\\Description\\System\\CentralProcessor\\0"), 0, + KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + size = sizeof(cpuName)/sizeof(cpuName[0]); + if (RegQueryValueEx(hKey, TEXT("ProcessorNameString"), NULL, NULL, (LPBYTE) cpuName, &size) != ERROR_SUCCESS) + _tcscpy(cpuName, TEXT("Unknown")); + + size = sizeof(cpuIdent)/sizeof(cpuIdent[0]); + if (RegQueryValueEx(hKey, TEXT("Identifier"), NULL, NULL, (LPBYTE) cpuIdent, &size) != ERROR_SUCCESS) + if (RegQueryValueEx(hKey, TEXT("VendorIdentifier"), NULL, NULL, (LPBYTE) cpuIdent, &size) != ERROR_SUCCESS) + _tcscpy(cpuIdent, TEXT("Unknown")); + + RegCloseKey(hKey); + } + TrimMultiSpaces(cpuName); + buffer.appendfmt(TEXT("CPU: %s [%s]"), cpuName, cpuIdent); + + if (pIsProcessorFeaturePresent && pIsProcessorFeaturePresent(PF_NX_ENABLED)) + buffer.append(TEXT(" [DEP Enabled]")); + + SYSTEM_INFO si = {0}; + GetSystemInfo(&si); + + if (si.dwNumberOfProcessors > 1) + buffer.appendfmt(TEXT(" [%u CPUs]"), si.dwNumberOfProcessors); +} + +void GetFreeMemoryString(bkstring& buffer) +{ + unsigned ram; + if (pGlobalMemoryStatusEx) + { + MEMORYSTATUSEX ms = {0}; + ms.dwLength = sizeof(ms); + pGlobalMemoryStatusEx(&ms); + ram = (unsigned int) ((ms.ullTotalPhys / (1024 * 1024)) + 1); + } + else + { + MEMORYSTATUS ms = {0}; + ZeroMemory(&ms, sizeof(ms)); + ms.dwLength = sizeof(ms); + GlobalMemoryStatus(&ms); + ram = (unsigned int)(ms.dwTotalPhys/(1024*1024))+1; + } + buffer.appendfmt(TEXT("Installed RAM: %u MBytes"), ram); +} + +void GetFreeDiskString(LPCTSTR dirname, bkstring& buffer) +{ + ULARGE_INTEGER tnb, tfb, fs = {0}; + if (pGetDiskFreeSpaceEx) + pGetDiskFreeSpaceEx(dirname, &fs, &tnb, &tfb); + else + { + DWORD SectorsPerCluster, BytesPerSector; + DWORD NumberOfFreeClusters, TotalNumberOfClusters; + + GetDiskFreeSpace(dirname, &SectorsPerCluster, &BytesPerSector, + &NumberOfFreeClusters, &TotalNumberOfClusters); + + fs.QuadPart = BytesPerSector * SectorsPerCluster; + fs.QuadPart *= NumberOfFreeClusters; + } + fs.QuadPart /= (1024*1024); + + buffer.appendfmt(TEXT("Free disk space on Miranda partition: %u MBytes"), fs.LowPart); +} + +void ReadableExceptionInfo(PEXCEPTION_RECORD excrec, bkstring& buffer) +{ + buffer.append(TEXT("Exception: ")); + + switch (excrec->ExceptionCode) + { + case EXCEPTION_BREAKPOINT: + buffer.append(TEXT("User Defined Breakpoint")); + break; + + case EXCEPTION_ACCESS_VIOLATION: + buffer.append(TEXT("Access Violation")); + break; + + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + buffer.append(TEXT("Array Bounds Exceeded")); + break; + + case EXCEPTION_DATATYPE_MISALIGNMENT: + buffer.append(TEXT("Datatype Misalignment")); + break; + + case EXCEPTION_FLT_DENORMAL_OPERAND: + buffer.append(TEXT("Floating Point denormlized operand")); + break; + + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + buffer.append(TEXT("Floating Point divide by 0")); + break; + + case EXCEPTION_FLT_INEXACT_RESULT: + buffer.append(TEXT("Floating Point inexact result")); + break; + + case EXCEPTION_FLT_INVALID_OPERATION: + buffer.append(TEXT("Floating Point invalid operation")); + break; + + case EXCEPTION_FLT_OVERFLOW: + buffer.append(TEXT("Floating Point overflow")); + break; + + case EXCEPTION_FLT_STACK_CHECK: + buffer.append(TEXT("Floating Point stack overflow/underflow")); + break; + + case EXCEPTION_FLT_UNDERFLOW: + buffer.append(TEXT("Floating Point underflow")); + break; + + case EXCEPTION_ILLEGAL_INSTRUCTION: + buffer.append(TEXT("Invalid instruction executed")); + break; + + case EXCEPTION_IN_PAGE_ERROR: + buffer.append(TEXT("Access to the not present page")); + break; + + case EXCEPTION_INT_DIVIDE_BY_ZERO: + buffer.append(TEXT("Integer divide by zero")); + break; + + case EXCEPTION_INT_OVERFLOW: + buffer.append(TEXT("Integer overflow")); + break; + + case EXCEPTION_PRIV_INSTRUCTION: + buffer.append(TEXT("Priveleged instruction executed")); + break; + + case EXCEPTION_STACK_OVERFLOW: + buffer.append(TEXT("Stack overflow")); + break; + + case 0xe06d7363: + buffer.append(TEXT("Unhandled C++ software exception")); + break; + + default: + buffer.appendfmt(TEXT("%x"), excrec->ExceptionCode); + break; + } + + buffer.appendfmt(TEXT(" at address %p."), excrec->ExceptionAddress); + + if (excrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION || + excrec->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) + { + switch(excrec->ExceptionInformation[0]) + { + case 0: + buffer.appendfmt(TEXT(" Reading from address %p."), (LPVOID)excrec->ExceptionInformation[1]); + break; + + case 1: + buffer.appendfmt(TEXT(" Writing to address %p."), (LPVOID)excrec->ExceptionInformation[1]); + break; + + case 8: + buffer.appendfmt(TEXT(" DEP at address %p."), (LPVOID)excrec->ExceptionInformation[1]); + break; + } + } +} + +void GetAdminString(bkstring& buffer) +{ + BOOL b; + __try + { + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + PSID AdministratorsGroup; + + b = AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup); + if (b) + { + if (!CheckTokenMembership(NULL, AdministratorsGroup, &b)) + b = FALSE; + FreeSid(AdministratorsGroup); + } + else + b = GetLastError() == ERROR_CALL_NOT_IMPLEMENTED; + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + b = TRUE; + } + + buffer.appendfmt(TEXT("Administrator privileges: %s"), b ? TEXT("Yes") : TEXT ("No")); +} + +void GetLanguageString(bkstring& buffer) +{ + TCHAR name1[256], name2[256], name3[256], name4[256]; + + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SENGLANGUAGE, name1, 256); + GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SENGLANGUAGE, name2, 256); + + if (pGetUserDefaultUILanguage && pGetSystemDefaultUILanguage) + { + GetLocaleInfo(MAKELCID(pGetUserDefaultUILanguage(), SORT_DEFAULT), LOCALE_SENGLANGUAGE, name3, 256); + GetLocaleInfo(MAKELCID(pGetSystemDefaultUILanguage(), SORT_DEFAULT), LOCALE_SENGLANGUAGE, name4, 256); + } + else + { + _tcscpy(name3, name1); + _tcscpy(name4, name2); + } + + buffer.appendfmt(TEXT("OS Languages: (UI | Locale (User/System)) : %s/%s | %s/%s"), name3, name4, name1, name2); +} + +void GetLanguagePackString(bkstring& buffer) +{ + buffer.append(TEXT("Language pack: ")); + if (packlcid == LOCALE_USER_DEFAULT) + buffer.append(TEXT("No language pack installed")); + else + { + TCHAR path[MAX_PATH] = TEXT("Locale id invalid"); + GetLocaleInfo(packlcid, LOCALE_SENGLANGUAGE, path, MAX_PATH); + buffer.append(path); + + GetLocaleInfo(packlcid, LOCALE_SISO3166CTRYNAME, path, MAX_PATH); + buffer.appendfmt(TEXT(" (%s) [%04x]"), path, packlcid); + + GetModuleFileName(NULL, path, MAX_PATH); + + LPTSTR fname = _tcsrchr(path, TEXT('\\')); + if (fname == NULL) fname = path; + crs_sntprintf(fname, MAX_PATH-(fname-path), TEXT("\\langpack_*.txt")); + + WIN32_FIND_DATA FindFileData; + HANDLE hFind = FindFirstFile(path, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) return; + FindClose(hFind); + + crs_sntprintf(fname, MAX_PATH-(fname-path), TEXT("\\%s"), FindFileData.cFileName); + HANDLE hDumpFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hDumpFile != INVALID_HANDLE_VALUE) + { + char buf[8192]; + + DWORD bytes = 0; + ReadFile(hDumpFile, buf, 8190, &bytes, NULL); + buf[bytes] = 0; + + char *id = strstr(buf, "FLID:"); + if (id != NULL) + { + char *endid = strchr(id, '\r'); + if (endid != NULL) *endid = 0; + + endid = strchr(id, '\n'); + if (endid != NULL) *endid = 0; + + TCHAR mirtime[30]; + GetLastWriteTime(path, mirtime, 30); + + TCHAR* tid; + crsi_a2t(tid, id+5); + buffer.appendfmt(TEXT(", %s, modified: %s"), tid, mirtime); + } + CloseHandle(hDumpFile); + } + } +} + +void GetWow64String(bkstring& buffer) +{ + BOOL wow64 = 0; + if (pIsWow64Process) + { + if (!pIsWow64Process(GetCurrentProcess(), &wow64)) + { + wow64 = 0; + } + } + if (wow64) buffer.append(TEXT(" [running inside WOW64]")); +} + + +bool CreateDirectoryTree(LPTSTR szDir) +{ + DWORD dwAttr = GetFileAttributes(szDir); + if (dwAttr != INVALID_FILE_ATTRIBUTES && (dwAttr & FILE_ATTRIBUTE_DIRECTORY)) + return true; + + TCHAR* pszSlash = _tcsrchr(szDir, TEXT('\\')); + if (pszSlash == NULL) + return false; + + *pszSlash = 0; + bool res = CreateDirectoryTree(szDir); + *pszSlash = TEXT('\\'); + + if (res) res = CreateDirectory(szDir, NULL) != 0; + + return res; +} + +int crs_sntprintf(TCHAR *buffer, size_t count, const TCHAR* fmt, ...) +{ + va_list va; + va_start(va, fmt); + + int len = _vsntprintf(buffer, count-1, fmt, va); + buffer[len] = 0; + + va_end(va); + return len; +} + +void GetVersionInfo(HMODULE hLib, bkstring& buffer) +{ + HRSRC hVersion = FindResource(hLib, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION); + if (hVersion != NULL) + { + HGLOBAL hGlobal = LoadResource(hLib, hVersion); + if (hGlobal != NULL) + { + LPVOID versionInfo = LockResource(hGlobal); + if (versionInfo != NULL) + { + int vl = *(unsigned short*)versionInfo; + unsigned *res = (unsigned*)versionInfo; + while (*res != 0xfeef04bd && ((char*)res - (char*)versionInfo) < vl) ++res; + + if (((char*)res - (char*)versionInfo) < vl) + { + VS_FIXEDFILEINFO *vsInfo = (VS_FIXEDFILEINFO*)res; + buffer.appendfmt(TEXT(" v.%u.%u.%u.%u"), + HIWORD(vsInfo->dwFileVersionMS), LOWORD(vsInfo->dwFileVersionMS), + HIWORD(vsInfo->dwFileVersionLS), LOWORD(vsInfo->dwFileVersionLS)); + } + } + FreeResource(hGlobal); + } + } +} + +void StoreStringToClip(bkstring& buffer) +{ + HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, buffer.sizebytes() + sizeof(TCHAR)); + LPSTR buf = (LPSTR)GlobalLock(hData); + + memcpy(buf, buffer.c_str(), buffer.sizebytes() + sizeof(TCHAR)); + + GlobalUnlock(hData); + + OpenClipboard(NULL); + EmptyClipboard(); + + + SetClipboardData(CF_UNICODETEXT, hData); + +} + +bool IsPluginEnabled(TCHAR* filename) +{ + char* fname; + crsi_t2a(fname, filename); + char* ext = strstr(_strlwr(fname), ".dll"); + bool res = ext && ext[4] == '\0' && DBGetContactSettingByte(NULL, "PluginDisable", fname, 0) == 0; + return res; +} diff --git a/plugins/CrashDumper/src/utils.h b/plugins/CrashDumper/src/utils.h new file mode 100644 index 0000000000..9089f57571 --- /dev/null +++ b/plugins/CrashDumper/src/utils.h @@ -0,0 +1,177 @@ +/* +Miranda Crash Dumper Plugin +Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#define _CRT_SECURE_NO_WARNINGS +#define MIRANDA_VER 0x0A00 + +#include +#include "sdkstuff.h" + +#ifdef _MSC_VER +#include +#endif + +#include + +#include "resource.h" + +#include + +#ifdef _MSC_VER + +#pragma warning( push ) +#pragma warning( disable : 4201 4100 ) +#include +#pragma warning( pop ) + +#else + +#include + +#endif + +#ifdef __GNUC__ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bkstring.h" + +#define MS_PROTO_ENUMPROTOS "Proto/EnumProtos" + +int crs_sntprintf(TCHAR *buffer, size_t count, const TCHAR* fmt, ...); + +#define crsi_u2a(dst, src) \ +{ \ + int cbLen = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL); \ + dst = (char*)alloca(cbLen+1); \ + WideCharToMultiByte(CP_ACP, 0, src, -1, dst, cbLen, NULL, NULL); \ +} + +#define crsi_a2u(dst, src, alloc) \ +{ \ + int cbLen = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); \ + dst = (wchar_t*)alloc(sizeof(wchar_t) * (cbLen+1)); \ + MultiByteToWideChar(CP_ACP, 0, src, -1, dst, cbLen); \ +} + + + +#define crsi_t2a(d,s) crsi_u2a(d,s) +#define crsi_a2t(d,s) crsi_a2u(d,s,alloca) +#define crs_a2t(d,s) crsi_a2u(d,s,mir_alloc) + + + +#define SIZEOF(X) (sizeof(X)/sizeof(X[0])) + +#define MS_CRASHDUMPER_STORETOFILE "CrashDmp/StoreVerInfoToFile" +#define MS_CRASHDUMPER_STORETOCLIP "CrashDmp/StoreVerInfoToClip" +#define MS_CRASHDUMPER_GETINFO "Versioninfo/GetInfo" +#define MS_CRASHDUMPER_VIEWINFO "CrashDmp/ViewInfo" +#define MS_CRASHDUMPER_UPLOAD "CrashDmp/UploadInfo" +#define MS_CRASHDUMPER_URL "CrashDmp/StartUrl" + +#define PluginName "Crash Dumper" + +#define VI_FLAG_FORMAT 1 +#define VI_FLAG_PRNVAR 2 +#define VI_FLAG_PRNDLL 4 +#define VI_FLAG_WEATHER 8 + +struct VerTrnsfr +{ + char* buf; + bool autot; +}; + +extern HMODULE hInst; +extern DWORD mirandaVersion; +extern LCID packlcid; +extern bool servicemode; +extern bool clsdates; +extern bool dtsubfldr; + +extern TCHAR CrashLogFolder[MAX_PATH]; +extern TCHAR VersionInfoFolder[MAX_PATH]; + +void WriteBBFile(bkstring& buffer, bool hdr); +void WriteUtfFile(HANDLE hDumpFile, char* bufu); +void UnloadDbgHlp(void); + +LONG WINAPI myfilter(PEXCEPTION_POINTERS exc_ptr); +LONG WINAPI myfilterv(PEXCEPTION_POINTERS exc_ptr); +DWORD MirandaThreadFilter(DWORD code, EXCEPTION_POINTERS* info); + +void GetOSDisplayString(bkstring& buffer); +void GetInternetExplorerVersion(bkstring& buffer); +void GetProcessorString(bkstring& buffer); +void GetFreeMemoryString(bkstring& buffer); +void GetFreeDiskString(LPCTSTR dirname, bkstring& buffer); +void GetAdminString(bkstring& buffer); +void GetLanguageString(bkstring& buffer); +void GetLanguagePackString(bkstring& buffer); +void GetWow64String(bkstring& buffer); +void GetVersionInfo(HMODULE hLib, bkstring& buffer); + +void GetISO8061Time(SYSTEMTIME* stLocal, LPTSTR lpszString, DWORD dwSize); + +void ReadableExceptionInfo(PEXCEPTION_RECORD excrec, bkstring& buffer); + +void GetLastWriteTime(LPCTSTR fileName, LPTSTR lpszString, DWORD dwSize); +void GetLastWriteTime(FILETIME* ftime, LPTSTR lpszString, DWORD dwSize); +bool CreateDirectoryTree(LPTSTR szDir); +void StoreStringToClip(bkstring& buffer); +void ShowMessage(int type, const TCHAR* format, ...); +bool IsPluginEnabled(TCHAR* filename); + +PLUGININFOEX* GetMirInfo(HMODULE hModule); +const PLUGININFOEX* GetPluginInfoEx(void); + +void CreateMiniDump (HANDLE hDumpFile, PEXCEPTION_POINTERS exc_ptr); +void CreateCrashReport(HANDLE hDumpFile, PEXCEPTION_POINTERS exc_ptr, const TCHAR* msg); +void PrintVersionInfo(bkstring& buffer, unsigned flags = VI_FLAG_PRNVAR); +bool ProcessVIHash(bool store); + +void InitExceptionHandler(void); +void DestroyExceptionHandler(void); +void SetExceptionHandler(void); +void RemoveExceptionHandler(void); +void CheckForOtherCrashReportingPlugins(void); + +INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK DlgProcView(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +void DestroyAllWindows(void); + +void UploadInit(void); +void UploadClose(void); +void OpenAuthUrl(const char* url); +void __cdecl VersionInfoUploadThread(void* arg); + +void InitIcons(void); +HICON LoadIconEx(const char* name, bool big = false); +HANDLE GetIconHandle(const char* name); +void ReleaseIconEx(const char* name); +void ReleaseIconEx(HICON hIcon); diff --git a/plugins/CrashDumper/src/vc6/dbghelp.h b/plugins/CrashDumper/src/vc6/dbghelp.h new file mode 100644 index 0000000000..d8a713060b --- /dev/null +++ b/plugins/CrashDumper/src/vc6/dbghelp.h @@ -0,0 +1,4532 @@ +/*++ BUILD Version: 0000 Increment this if a change has global effects + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + dbghelp.h + +Abstract: + + This module defines the prototypes and constants required for the image + help routines. + + Contains debugging support routines that are redistributable. + +Revision History: + +--*/ + +#ifndef _DBGHELP_ +#define _DBGHELP_ + +#if _MSC_VER > 1020 +#pragma once +#endif + + +// As a general principal always call the 64 bit version +// of every API, if a choice exists. The 64 bit version +// works great on 32 bit platforms, and is forward +// compatible to 64 bit platforms. + +#ifdef _WIN64 +#ifndef _IMAGEHLP64 +#define _IMAGEHLP64 +#endif +#endif + +// For those without specstrings.h +// Since there are different versions of this header, I need to +// individually test each item and define it if it is not around. + +#ifndef __in + #define __in +#endif +#ifndef __out + #define __out +#endif +#ifndef __inout + #define __inout +#endif +#ifndef __in_opt + #define __in_opt +#endif +#ifndef __out_opt + #define __out_opt +#endif +#ifndef __inout_opt + #define __inout_opt +#endif +#ifndef __in_ecount + #define __in_ecount(x) +#endif +#ifndef __out_ecount + #define __out_ecount(x) +#endif +#ifndef __inout_ecount + #define __inout_ecount(x) +#endif +#ifndef __in_bcount + #define __in_bcount(x) +#endif +#ifndef __out_bcount + #define __out_bcount(x) +#endif +#ifndef __inout_bcount + #define __inout_bcount(x) +#endif +#ifndef __out_xcount + #define __out_xcount(x) +#endif +#ifndef __deref_opt_out + #define __deref_opt_out +#endif +#ifndef __deref_out + #define __deref_out +#endif +#ifndef __out_ecount_opt + #define __out_ecount_opt(x) +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _IMAGEHLP_SOURCE_ + #define IMAGEAPI __stdcall + #define DBHLP_DEPRECIATED +#else + #define IMAGEAPI DECLSPEC_IMPORT __stdcall + #if (_MSC_VER >= 1300) && !defined(MIDL_PASS) + #define DBHLP_DEPRECIATED __declspec(deprecated) + #else + #define DBHLP_DEPRECIATED + #endif +#endif + +#define DBHLPAPI IMAGEAPI + +#define IMAGE_SEPARATION (64*1024) + +// Observant readers may notice that 2 new fields, +// 'fReadOnly' and 'Version' have been added to +// the LOADED_IMAGE structure after 'fDOSImage'. +// This does not change the size of the structure +// from previous headers. That is because while +// 'fDOSImage' is a byte, it is padded by the +// compiler to 4 bytes. So the 2 new fields are +// slipped into the extra space. + +typedef struct _LOADED_IMAGE { + PSTR ModuleName; + HANDLE hFile; + PUCHAR MappedAddress; +#ifdef _IMAGEHLP64 + PIMAGE_NT_HEADERS64 FileHeader; +#else + PIMAGE_NT_HEADERS32 FileHeader; +#endif + PIMAGE_SECTION_HEADER LastRvaSection; + ULONG NumberOfSections; + PIMAGE_SECTION_HEADER Sections; + ULONG Characteristics; + BOOLEAN fSystemImage; + BOOLEAN fDOSImage; + BOOLEAN fReadOnly; + UCHAR Version; + LIST_ENTRY Links; + ULONG SizeOfImage; +} LOADED_IMAGE, *PLOADED_IMAGE; + +#define MAX_SYM_NAME 2000 + + +// Error codes set by dbghelp functions. Call GetLastError +// to see them. +// Dbghelp also sets error codes found in winerror.h + +#define ERROR_IMAGE_NOT_STRIPPED 0x8800 // the image is not stripped. No dbg file available. +#define ERROR_NO_DBG_POINTER 0x8801 // image is stripped but there is no pointer to a dbg file +#define ERROR_NO_PDB_POINTER 0x8802 // image does not point to a pdb file + +typedef BOOL +(CALLBACK *PFIND_DEBUG_FILE_CALLBACK)( + __in HANDLE FileHandle, + __in PCSTR FileName, + __in PVOID CallerData + ); + +HANDLE +IMAGEAPI +SymFindDebugInfoFile( + __in HANDLE hProcess, + __in PCSTR FileName, + __out_ecount(MAX_PATH + 1) PSTR DebugFilePath, + __in_opt PFIND_DEBUG_FILE_CALLBACK Callback, + __in_opt PVOID CallerData + ); + +typedef BOOL +(CALLBACK *PFIND_DEBUG_FILE_CALLBACKW)( + __in HANDLE FileHandle, + __in PCWSTR FileName, + __in PVOID CallerData + ); + +HANDLE +IMAGEAPI +SymFindDebugInfoFileW( + __in HANDLE hProcess, + __in PCWSTR FileName, + __out_ecount(MAX_PATH + 1) PWSTR DebugFilePath, + __in_opt PFIND_DEBUG_FILE_CALLBACKW Callback, + __in_opt PVOID CallerData + ); + +HANDLE +IMAGEAPI +FindDebugInfoFile ( + __in PCSTR FileName, + __in PCSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PSTR DebugFilePath + ); + +HANDLE +IMAGEAPI +FindDebugInfoFileEx ( + __in PCSTR FileName, + __in PCSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PSTR DebugFilePath, + __in_opt PFIND_DEBUG_FILE_CALLBACK Callback, + __in_opt PVOID CallerData + ); + +HANDLE +IMAGEAPI +FindDebugInfoFileExW ( + __in PCWSTR FileName, + __in PCWSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PWSTR DebugFilePath, + __in_opt PFIND_DEBUG_FILE_CALLBACKW Callback, + __in_opt PVOID CallerData + ); + +typedef BOOL +(CALLBACK *PFINDFILEINPATHCALLBACK)( + PCSTR filename, + PVOID context + ); + +BOOL +IMAGEAPI +SymFindFileInPath( + __in HANDLE hprocess, + __in_opt PCSTR SearchPath, + __in PCSTR FileName, + __in_opt PVOID id, + __in DWORD two, + __in DWORD three, + __in DWORD flags, + __out_ecount(MAX_PATH + 1) PSTR FoundFile, + __in_opt PFINDFILEINPATHCALLBACK callback, + __in_opt PVOID context + ); + +typedef BOOL +(CALLBACK *PFINDFILEINPATHCALLBACKW)( + __in PCWSTR filename, + __in PVOID context + ); + +BOOL +IMAGEAPI +SymFindFileInPathW( + __in HANDLE hprocess, + __in_opt PCWSTR SearchPath, + __in PCWSTR FileName, + __in_opt PVOID id, + __in DWORD two, + __in DWORD three, + __in DWORD flags, + __out_ecount(MAX_PATH + 1) PWSTR FoundFile, + __in_opt PFINDFILEINPATHCALLBACKW callback, + __in_opt PVOID context + ); + +typedef BOOL +(CALLBACK *PFIND_EXE_FILE_CALLBACK)( + __in HANDLE FileHandle, + __in PCSTR FileName, + __in_opt PVOID CallerData + ); + +HANDLE +IMAGEAPI +SymFindExecutableImage( + __in HANDLE hProcess, + __in PCSTR FileName, + __out_ecount(MAX_PATH + 1) PSTR ImageFilePath, + __in PFIND_EXE_FILE_CALLBACK Callback, + __in PVOID CallerData + ); + +typedef BOOL +(CALLBACK *PFIND_EXE_FILE_CALLBACKW)( + __in HANDLE FileHandle, + __in PCWSTR FileName, + __in_opt PVOID CallerData + ); + +HANDLE +IMAGEAPI +SymFindExecutableImageW( + __in HANDLE hProcess, + __in PCWSTR FileName, + __out_ecount(MAX_PATH + 1) PWSTR ImageFilePath, + __in PFIND_EXE_FILE_CALLBACKW Callback, + __in PVOID CallerData + ); + +HANDLE +IMAGEAPI +FindExecutableImage( + __in PCSTR FileName, + __in PCSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PSTR ImageFilePath + ); + +HANDLE +IMAGEAPI +FindExecutableImageEx( + __in PCSTR FileName, + __in PCSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PSTR ImageFilePath, + __in_opt PFIND_EXE_FILE_CALLBACK Callback, + __in_opt PVOID CallerData + ); + +HANDLE +IMAGEAPI +FindExecutableImageExW( + __in PCWSTR FileName, + __in PCWSTR SymbolPath, + __out_ecount(MAX_PATH + 1) PWSTR ImageFilePath, + __in_opt PFIND_EXE_FILE_CALLBACKW Callback, + __in PVOID CallerData + ); + +PIMAGE_NT_HEADERS +IMAGEAPI +ImageNtHeader ( + __in PVOID Base + ); + +PVOID +IMAGEAPI +ImageDirectoryEntryToDataEx ( + __in PVOID Base, + __in BOOLEAN MappedAsImage, + __in USHORT DirectoryEntry, + __out PULONG Size, + __out_opt PIMAGE_SECTION_HEADER *FoundHeader + ); + +PVOID +IMAGEAPI +ImageDirectoryEntryToData ( + __in PVOID Base, + __in BOOLEAN MappedAsImage, + __in USHORT DirectoryEntry, + __out PULONG Size + ); + +PIMAGE_SECTION_HEADER +IMAGEAPI +ImageRvaToSection( + __in PIMAGE_NT_HEADERS NtHeaders, + __in PVOID Base, + __in ULONG Rva + ); + +PVOID +IMAGEAPI +ImageRvaToVa( + __in PIMAGE_NT_HEADERS NtHeaders, + __in PVOID Base, + __in ULONG Rva, + __in_opt OUT PIMAGE_SECTION_HEADER *LastRvaSection + ); + +#ifndef _WIN64 +// This api won't be ported to Win64 - Fix your code. + +typedef struct _IMAGE_DEBUG_INFORMATION { + LIST_ENTRY List; + DWORD ReservedSize; + PVOID ReservedMappedBase; + USHORT ReservedMachine; + USHORT ReservedCharacteristics; + DWORD ReservedCheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + + DWORD ReservedNumberOfSections; + PIMAGE_SECTION_HEADER ReservedSections; + + DWORD ReservedExportedNamesSize; + PSTR ReservedExportedNames; + + DWORD ReservedNumberOfFunctionTableEntries; + PIMAGE_FUNCTION_ENTRY ReservedFunctionTableEntries; + DWORD ReservedLowestFunctionStartingAddress; + DWORD ReservedHighestFunctionEndingAddress; + + DWORD ReservedNumberOfFpoTableEntries; + PFPO_DATA ReservedFpoTableEntries; + + DWORD SizeOfCoffSymbols; + PIMAGE_COFF_SYMBOLS_HEADER CoffSymbols; + + DWORD ReservedSizeOfCodeViewSymbols; + PVOID ReservedCodeViewSymbols; + + PSTR ImageFilePath; + PSTR ImageFileName; + PSTR ReservedDebugFilePath; + + DWORD ReservedTimeDateStamp; + + BOOL ReservedRomImage; + PIMAGE_DEBUG_DIRECTORY ReservedDebugDirectory; + DWORD ReservedNumberOfDebugDirectories; + + DWORD ReservedOriginalFunctionTableBaseAddress; + + DWORD Reserved[ 2 ]; + +} IMAGE_DEBUG_INFORMATION, *PIMAGE_DEBUG_INFORMATION; + + +PIMAGE_DEBUG_INFORMATION +IMAGEAPI +MapDebugInformation( + __in_opt HANDLE FileHandle, + __in PCSTR FileName, + __in_opt PCSTR SymbolPath, + __in ULONG ImageBase + ); + +BOOL +IMAGEAPI +UnmapDebugInformation( + __out_xcount(unknown) PIMAGE_DEBUG_INFORMATION DebugInfo + ); + +#endif + +BOOL +IMAGEAPI +SearchTreeForFile( + __in PCSTR RootPath, + __in PCSTR InputPathName, + __out_ecount(MAX_PATH + 1) PSTR OutputPathBuffer + ); + +BOOL +IMAGEAPI +SearchTreeForFileW( + __in PCWSTR RootPath, + __in PCWSTR InputPathName, + __out_ecount(MAX_PATH + 1) PWSTR OutputPathBuffer + ); + +typedef BOOL +(CALLBACK *PENUMDIRTREE_CALLBACK)( + __in PCSTR FilePath, + __in_opt PVOID CallerData + ); + +BOOL +IMAGEAPI +EnumDirTree( + __in_opt HANDLE hProcess, + __in PCSTR RootPath, + __in PCSTR InputPathName, + __out_ecount_opt(MAX_PATH + 1) PSTR OutputPathBuffer, + __in_opt PENUMDIRTREE_CALLBACK cb, + __in_opt PVOID data + ); + +typedef BOOL +(CALLBACK *PENUMDIRTREE_CALLBACKW)( + __in PCWSTR FilePath, + __in_opt PVOID CallerData + ); + +BOOL +IMAGEAPI +EnumDirTreeW( + __in_opt HANDLE hProcess, + __in PCWSTR RootPath, + __in PCWSTR InputPathName, + __out_ecount_opt(MAX_PATH + 1) PWSTR OutputPathBuffer, + __in_opt PENUMDIRTREE_CALLBACKW cb, + __in_opt PVOID data + ); + +BOOL +IMAGEAPI +MakeSureDirectoryPathExists( + __in PCSTR DirPath + ); + +// +// UnDecorateSymbolName Flags +// + +#define UNDNAME_COMPLETE (0x0000) // Enable full undecoration +#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001) // Remove leading underscores from MS extended keywords +#define UNDNAME_NO_MS_KEYWORDS (0x0002) // Disable expansion of MS extended keywords +#define UNDNAME_NO_FUNCTION_RETURNS (0x0004) // Disable expansion of return type for primary declaration +#define UNDNAME_NO_ALLOCATION_MODEL (0x0008) // Disable expansion of the declaration model +#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010) // Disable expansion of the declaration language specifier +#define UNDNAME_NO_MS_THISTYPE (0x0020) // NYI Disable expansion of MS keywords on the 'this' type for primary declaration +#define UNDNAME_NO_CV_THISTYPE (0x0040) // NYI Disable expansion of CV modifiers on the 'this' type for primary declaration +#define UNDNAME_NO_THISTYPE (0x0060) // Disable all modifiers on the 'this' type +#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080) // Disable expansion of access specifiers for members +#define UNDNAME_NO_THROW_SIGNATURES (0x0100) // Disable expansion of 'throw-signatures' for functions and pointers to functions +#define UNDNAME_NO_MEMBER_TYPE (0x0200) // Disable expansion of 'static' or 'virtual'ness of members +#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400) // Disable expansion of MS model for UDT returns +#define UNDNAME_32_BIT_DECODE (0x0800) // Undecorate 32-bit decorated names +#define UNDNAME_NAME_ONLY (0x1000) // Crack only the name for primary declaration; + // return just [scope::]name. Does expand template params +#define UNDNAME_NO_ARGUMENTS (0x2000) // Don't undecorate arguments to function +#define UNDNAME_NO_SPECIAL_SYMS (0x4000) // Don't undecorate special names (v-table, vcall, vector xxx, metatype, etc) + +DWORD +IMAGEAPI +WINAPI +UnDecorateSymbolName( + __in PCSTR name, + __out_ecount(maxStringLength) PSTR outputString, + __in DWORD maxStringLength, + __in DWORD flags + ); + +DWORD +IMAGEAPI +WINAPI +UnDecorateSymbolNameW( + __in PCWSTR name, + __out_ecount(maxStringLength) PWSTR outputString, + __in DWORD maxStringLength, + __in DWORD flags + ); + +// +// these values are used for synthesized file types +// that can be passed in as image headers instead of +// the standard ones from ntimage.h +// + +#define DBHHEADER_DEBUGDIRS 0x1 +#define DBHHEADER_CVMISC 0x2 + +typedef struct _MODLOAD_DATA { + DWORD ssize; // size of this struct + DWORD ssig; // signature identifying the passed data + PVOID data; // pointer to passed data + DWORD size; // size of passed data + DWORD flags; // options +} MODLOAD_DATA, *PMODLOAD_DATA; + +typedef struct _MODLOAD_CVMISC { + DWORD oCV; // ofset to the codeview record + size_t cCV; // size of the codeview record + DWORD oMisc; // offset to the misc record + size_t cMisc; // size of the misc record + DWORD dtImage; // datetime stamp of the image + DWORD cImage; // size of the image +} MODLOAD_CVMISC, *PMODLOAD_CVMISC; + +// +// StackWalking API +// + +typedef enum { + AddrMode1616, + AddrMode1632, + AddrModeReal, + AddrModeFlat +} ADDRESS_MODE; + +typedef struct _tagADDRESS64 { + DWORD64 Offset; + WORD Segment; + ADDRESS_MODE Mode; +} ADDRESS64, *LPADDRESS64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define ADDRESS ADDRESS64 +#define LPADDRESS LPADDRESS64 +#else +typedef struct _tagADDRESS { + DWORD Offset; + WORD Segment; + ADDRESS_MODE Mode; +} ADDRESS, *LPADDRESS; + +__inline +void +Address32To64( + __in LPADDRESS a32, + __out LPADDRESS64 a64 + ) +{ + a64->Offset = (ULONG64)(LONG64)(LONG)a32->Offset; + a64->Segment = a32->Segment; + a64->Mode = a32->Mode; +} + +__inline +void +Address64To32( + __in LPADDRESS64 a64, + __out LPADDRESS a32 + ) +{ + a32->Offset = (ULONG)a64->Offset; + a32->Segment = a64->Segment; + a32->Mode = a64->Mode; +} +#endif + +// +// This structure is included in the STACKFRAME structure, +// and is used to trace through usermode callbacks in a thread's +// kernel stack. The values must be copied by the kernel debugger +// from the DBGKD_GET_VERSION and WAIT_STATE_CHANGE packets. +// + +// +// New KDHELP structure for 64 bit system support. +// This structure is preferred in new code. +// +typedef struct _KDHELP64 { + + // + // address of kernel thread object, as provided in the + // WAIT_STATE_CHANGE packet. + // + DWORD64 Thread; + + // + // offset in thread object to pointer to the current callback frame + // in kernel stack. + // + DWORD ThCallbackStack; + + // + // offset in thread object to pointer to the current callback backing + // store frame in kernel stack. + // + DWORD ThCallbackBStore; + + // + // offsets to values in frame: + // + // address of next callback frame + DWORD NextCallback; + + // address of saved frame pointer (if applicable) + DWORD FramePointer; + + + // + // Address of the kernel function that calls out to user mode + // + DWORD64 KiCallUserMode; + + // + // Address of the user mode dispatcher function + // + DWORD64 KeUserCallbackDispatcher; + + // + // Lowest kernel mode address + // + DWORD64 SystemRangeStart; + + // + // Address of the user mode exception dispatcher function. + // Added in API version 10. + // + DWORD64 KiUserExceptionDispatcher; + + // + // Stack bounds, added in API version 11. + // + DWORD64 StackBase; + DWORD64 StackLimit; + + DWORD64 Reserved[5]; + +} KDHELP64, *PKDHELP64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define KDHELP KDHELP64 +#define PKDHELP PKDHELP64 +#else +typedef struct _KDHELP { + + // + // address of kernel thread object, as provided in the + // WAIT_STATE_CHANGE packet. + // + DWORD Thread; + + // + // offset in thread object to pointer to the current callback frame + // in kernel stack. + // + DWORD ThCallbackStack; + + // + // offsets to values in frame: + // + // address of next callback frame + DWORD NextCallback; + + // address of saved frame pointer (if applicable) + DWORD FramePointer; + + // + // Address of the kernel function that calls out to user mode + // + DWORD KiCallUserMode; + + // + // Address of the user mode dispatcher function + // + DWORD KeUserCallbackDispatcher; + + // + // Lowest kernel mode address + // + DWORD SystemRangeStart; + + // + // offset in thread object to pointer to the current callback backing + // store frame in kernel stack. + // + DWORD ThCallbackBStore; + + // + // Address of the user mode exception dispatcher function. + // Added in API version 10. + // + DWORD KiUserExceptionDispatcher; + + // + // Stack bounds, added in API version 11. + // + DWORD StackBase; + DWORD StackLimit; + + DWORD Reserved[5]; + +} KDHELP, *PKDHELP; + +__inline +void +KdHelp32To64( + __in PKDHELP p32, + __out PKDHELP64 p64 + ) +{ + p64->Thread = p32->Thread; + p64->ThCallbackStack = p32->ThCallbackStack; + p64->NextCallback = p32->NextCallback; + p64->FramePointer = p32->FramePointer; + p64->KiCallUserMode = p32->KiCallUserMode; + p64->KeUserCallbackDispatcher = p32->KeUserCallbackDispatcher; + p64->SystemRangeStart = p32->SystemRangeStart; + p64->KiUserExceptionDispatcher = p32->KiUserExceptionDispatcher; + p64->StackBase = p32->StackBase; + p64->StackLimit = p32->StackLimit; +} +#endif + +typedef struct _tagSTACKFRAME64 { + ADDRESS64 AddrPC; // program counter + ADDRESS64 AddrReturn; // return address + ADDRESS64 AddrFrame; // frame pointer + ADDRESS64 AddrStack; // stack pointer + ADDRESS64 AddrBStore; // backing store pointer + PVOID FuncTableEntry; // pointer to pdata/fpo or NULL + DWORD64 Params[4]; // possible arguments to the function + BOOL Far; // WOW far call + BOOL Virtual; // is this a virtual frame? + DWORD64 Reserved[3]; + KDHELP64 KdHelp; +} STACKFRAME64, *LPSTACKFRAME64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define STACKFRAME STACKFRAME64 +#define LPSTACKFRAME LPSTACKFRAME64 +#else +typedef struct _tagSTACKFRAME { + ADDRESS AddrPC; // program counter + ADDRESS AddrReturn; // return address + ADDRESS AddrFrame; // frame pointer + ADDRESS AddrStack; // stack pointer + PVOID FuncTableEntry; // pointer to pdata/fpo or NULL + DWORD Params[4]; // possible arguments to the function + BOOL Far; // WOW far call + BOOL Virtual; // is this a virtual frame? + DWORD Reserved[3]; + KDHELP KdHelp; + ADDRESS AddrBStore; // backing store pointer +} STACKFRAME, *LPSTACKFRAME; +#endif + + +typedef +BOOL +(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)( + __in HANDLE hProcess, + __in DWORD64 qwBaseAddress, + __out_bcount(nSize) PVOID lpBuffer, + __in DWORD nSize, + __out LPDWORD lpNumberOfBytesRead + ); + +typedef +PVOID +(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( + __in HANDLE ahProcess, + __in DWORD64 AddrBase + ); + +typedef +DWORD64 +(__stdcall *PGET_MODULE_BASE_ROUTINE64)( + __in HANDLE hProcess, + __in DWORD64 Address + ); + +typedef +DWORD64 +(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)( + __in HANDLE hProcess, + __in HANDLE hThread, + __in LPADDRESS64 lpaddr + ); + +BOOL +IMAGEAPI +StackWalk64( + __in DWORD MachineType, + __in HANDLE hProcess, + __in HANDLE hThread, + __inout LPSTACKFRAME64 StackFrame, + __inout PVOID ContextRecord, + __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, + __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, + __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, + __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) + +#define PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE64 +#define PFUNCTION_TABLE_ACCESS_ROUTINE PFUNCTION_TABLE_ACCESS_ROUTINE64 +#define PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE64 +#define PTRANSLATE_ADDRESS_ROUTINE PTRANSLATE_ADDRESS_ROUTINE64 + +#define StackWalk StackWalk64 + +#else + +typedef +BOOL +(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE)( + __in HANDLE hProcess, + __in DWORD lpBaseAddress, + __out_bcount(nSize) PVOID lpBuffer, + __in DWORD nSize, + __out PDWORD lpNumberOfBytesRead + ); + +typedef +PVOID +(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE)( + __in HANDLE hProcess, + __in DWORD AddrBase + ); + +typedef +DWORD +(__stdcall *PGET_MODULE_BASE_ROUTINE)( + __in HANDLE hProcess, + __in DWORD Address + ); + +typedef +DWORD +(__stdcall *PTRANSLATE_ADDRESS_ROUTINE)( + __in HANDLE hProcess, + __in HANDLE hThread, + __out LPADDRESS lpaddr + ); + +BOOL +IMAGEAPI +StackWalk( + DWORD MachineType, + __in HANDLE hProcess, + __in HANDLE hThread, + __inout LPSTACKFRAME StackFrame, + __inout PVOID ContextRecord, + __in_opt PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, + __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, + __in_opt PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, + __in_opt PTRANSLATE_ADDRESS_ROUTINE TranslateAddress + ); + +#endif + + +#define API_VERSION_NUMBER 11 + +typedef struct API_VERSION { + USHORT MajorVersion; + USHORT MinorVersion; + USHORT Revision; + USHORT Reserved; +} API_VERSION, *LPAPI_VERSION; + +LPAPI_VERSION +IMAGEAPI +ImagehlpApiVersion( + VOID + ); + +LPAPI_VERSION +IMAGEAPI +ImagehlpApiVersionEx( + __in LPAPI_VERSION AppVersion + ); + +DWORD +IMAGEAPI +GetTimestampForLoadedLibrary( + __in HMODULE Module + ); + +// +// typedefs for function pointers +// +typedef BOOL +(CALLBACK *PSYM_ENUMMODULES_CALLBACK64)( + __in PCSTR ModuleName, + __in DWORD64 BaseOfDll, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMMODULES_CALLBACKW64)( + __in PCWSTR ModuleName, + __in DWORD64 BaseOfDll, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PENUMLOADED_MODULES_CALLBACK64)( + __in PCSTR ModuleName, + __in DWORD64 ModuleBase, + __in ULONG ModuleSize, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PENUMLOADED_MODULES_CALLBACKW64)( + __in PCWSTR ModuleName, + __in DWORD64 ModuleBase, + __in ULONG ModuleSize, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64)( + __in PCSTR SymbolName, + __in DWORD64 SymbolAddress, + __in ULONG SymbolSize, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64W)( + __in PCWSTR SymbolName, + __in DWORD64 SymbolAddress, + __in ULONG SymbolSize, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYMBOL_REGISTERED_CALLBACK64)( + __in HANDLE hProcess, + __in ULONG ActionCode, + __in_opt ULONG64 CallbackData, + __in_opt ULONG64 UserContext + ); + +typedef +PVOID +(CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK)( + __in HANDLE hProcess, + __in DWORD AddrBase, + __in_opt PVOID UserContext + ); + +typedef +PVOID +(CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK64)( + __in HANDLE hProcess, + __in ULONG64 AddrBase, + __in ULONG64 UserContext + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) + +#define PSYM_ENUMMODULES_CALLBACK PSYM_ENUMMODULES_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACK PSYM_ENUMSYMBOLS_CALLBACK64 +#define PSYM_ENUMSYMBOLS_CALLBACKW PSYM_ENUMSYMBOLS_CALLBACK64W +#define PENUMLOADED_MODULES_CALLBACK PENUMLOADED_MODULES_CALLBACK64 +#define PSYMBOL_REGISTERED_CALLBACK PSYMBOL_REGISTERED_CALLBACK64 +#define PSYMBOL_FUNCENTRY_CALLBACK PSYMBOL_FUNCENTRY_CALLBACK64 + +#else + +typedef BOOL +(CALLBACK *PSYM_ENUMMODULES_CALLBACK)( + __in PCSTR ModuleName, + __in ULONG BaseOfDll, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK)( + __in PCSTR SymbolName, + __in ULONG SymbolAddress, + __in ULONG SymbolSize, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMSYMBOLS_CALLBACKW)( + __in PCWSTR SymbolName, + __in ULONG SymbolAddress, + __in ULONG SymbolSize, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PENUMLOADED_MODULES_CALLBACK)( + __in PCSTR ModuleName, + __in ULONG ModuleBase, + __in ULONG ModuleSize, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYMBOL_REGISTERED_CALLBACK)( + __in HANDLE hProcess, + __in ULONG ActionCode, + __in_opt PVOID CallbackData, + __in_opt PVOID UserContext + ); + +#endif + + +// values found in SYMBOL_INFO.Tag +// +// This was taken from cvconst.h and should +// not override any values found there. +// +// #define _NO_CVCONST_H_ if you don't +// have access to that file... + +#ifdef _NO_CVCONST_H + +// DIA enums + +enum SymTagEnum +{ + SymTagNull, + SymTagExe, + SymTagCompiland, + SymTagCompilandDetails, + SymTagCompilandEnv, + SymTagFunction, + SymTagBlock, + SymTagData, + SymTagAnnotation, + SymTagLabel, + SymTagPublicSymbol, + SymTagUDT, + SymTagEnum, + SymTagFunctionType, + SymTagPointerType, + SymTagArrayType, + SymTagBaseType, + SymTagTypedef, + SymTagBaseClass, + SymTagFriend, + SymTagFunctionArgType, + SymTagFuncDebugStart, + SymTagFuncDebugEnd, + SymTagUsingNamespace, + SymTagVTableShape, + SymTagVTable, + SymTagCustom, + SymTagThunk, + SymTagCustomType, + SymTagManagedType, + SymTagDimension, + SymTagMax +}; + +#endif + +// +// flags found in SYMBOL_INFO.Flags +// + +#define SYMFLAG_VALUEPRESENT 0x00000001 +#define SYMFLAG_REGISTER 0x00000008 +#define SYMFLAG_REGREL 0x00000010 +#define SYMFLAG_FRAMEREL 0x00000020 +#define SYMFLAG_PARAMETER 0x00000040 +#define SYMFLAG_LOCAL 0x00000080 +#define SYMFLAG_CONSTANT 0x00000100 +#define SYMFLAG_EXPORT 0x00000200 +#define SYMFLAG_FORWARDER 0x00000400 +#define SYMFLAG_FUNCTION 0x00000800 +#define SYMFLAG_VIRTUAL 0x00001000 +#define SYMFLAG_THUNK 0x00002000 +#define SYMFLAG_TLSREL 0x00004000 +#define SYMFLAG_SLOT 0x00008000 +#define SYMFLAG_ILREL 0x00010000 +#define SYMFLAG_METADATA 0x00020000 +#define SYMFLAG_CLR_TOKEN 0x00040000 + +// this resets SymNext/Prev to the beginning +// of the module passed in the address field + +#define SYMFLAG_RESET 0x80000000 + +// +// symbol type enumeration +// +typedef enum { + SymNone = 0, + SymCoff, + SymCv, + SymPdb, + SymExport, + SymDeferred, + SymSym, // .sym file + SymDia, + SymVirtual, + NumSymTypes +} SYM_TYPE; + +// +// symbol data structure +// + +typedef struct _IMAGEHLP_SYMBOL64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOL64) + DWORD64 Address; // virtual address including dll base address + DWORD Size; // estimated size of symbol, can be zero + DWORD Flags; // info about the symbols, see the SYMF defines + DWORD MaxNameLength; // maximum size of symbol name in 'Name' + CHAR Name[1]; // symbol name (null terminated string) +} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; + +typedef struct _IMAGEHLP_SYMBOL64_PACKAGE { + IMAGEHLP_SYMBOL64 sym; + CHAR name[MAX_SYM_NAME + 1]; +} IMAGEHLP_SYMBOL64_PACKAGE, *PIMAGEHLP_SYMBOL64_PACKAGE; + +typedef struct _IMAGEHLP_SYMBOLW64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOLW64) + DWORD64 Address; // virtual address including dll base address + DWORD Size; // estimated size of symbol, can be zero + DWORD Flags; // info about the symbols, see the SYMF defines + DWORD MaxNameLength; // maximum size of symbol name in 'Name' + WCHAR Name[1]; // symbol name (null terminated string) +} IMAGEHLP_SYMBOLW64, *PIMAGEHLP_SYMBOLW64; + +typedef struct _IMAGEHLP_SYMBOLW64_PACKAGE { + IMAGEHLP_SYMBOLW64 sym; + WCHAR name[MAX_SYM_NAME + 1]; +} IMAGEHLP_SYMBOLW64_PACKAGE, *PIMAGEHLP_SYMBOLW64_PACKAGE; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) + + #define IMAGEHLP_SYMBOL IMAGEHLP_SYMBOL64 + #define PIMAGEHLP_SYMBOL PIMAGEHLP_SYMBOL64 + #define IMAGEHLP_SYMBOL_PACKAGE IMAGEHLP_SYMBOL64_PACKAGE + #define PIMAGEHLP_SYMBOL_PACKAGE PIMAGEHLP_SYMBOL64_PACKAGE + #define IMAGEHLP_SYMBOLW IMAGEHLP_SYMBOLW64 + #define PIMAGEHLP_SYMBOLW PIMAGEHLP_SYMBOLW64 + #define IMAGEHLP_SYMBOLW_PACKAGE IMAGEHLP_SYMBOLW64_PACKAGE + #define PIMAGEHLP_SYMBOLW_PACKAGE PIMAGEHLP_SYMBOLW64_PACKAGE + +#else + + typedef struct _IMAGEHLP_SYMBOL { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOL) + DWORD Address; // virtual address including dll base address + DWORD Size; // estimated size of symbol, can be zero + DWORD Flags; // info about the symbols, see the SYMF defines + DWORD MaxNameLength; // maximum size of symbol name in 'Name' + CHAR Name[1]; // symbol name (null terminated string) + } IMAGEHLP_SYMBOL, *PIMAGEHLP_SYMBOL; + + typedef struct _IMAGEHLP_SYMBOL_PACKAGE { + IMAGEHLP_SYMBOL sym; + CHAR name[MAX_SYM_NAME + 1]; + } IMAGEHLP_SYMBOL_PACKAGE, *PIMAGEHLP_SYMBOL_PACKAGE; + + typedef struct _IMAGEHLP_SYMBOLW { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOLW) + DWORD Address; // virtual address including dll base address + DWORD Size; // estimated size of symbol, can be zero + DWORD Flags; // info about the symbols, see the SYMF defines + DWORD MaxNameLength; // maximum size of symbol name in 'Name' + WCHAR Name[1]; // symbol name (null terminated string) + } IMAGEHLP_SYMBOLW, *PIMAGEHLP_SYMBOLW; + + typedef struct _IMAGEHLP_SYMBOLW_PACKAGE { + IMAGEHLP_SYMBOLW sym; + WCHAR name[MAX_SYM_NAME + 1]; + } IMAGEHLP_SYMBOLW_PACKAGE, *PIMAGEHLP_SYMBOLW_PACKAGE; + +#endif + +// +// module data structure +// + +typedef struct _IMAGEHLP_MODULE64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) + DWORD64 BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + CHAR ModuleName[32]; // module name + CHAR ImageName[256]; // image name + CHAR LoadedImageName[256]; // symbol file name + // new elements: 07-Jun-2002 + CHAR LoadedPdbName[256]; // pdb file name + DWORD CVSig; // Signature of the CV record in the debug directories + CHAR CVData[MAX_PATH * 3]; // Contents of the CV record + DWORD PdbSig; // Signature of PDB + GUID PdbSig70; // Signature of PDB (VC 7 and up) + DWORD PdbAge; // DBI age of pdb + BOOL PdbUnmatched; // loaded an unmatched pdb + BOOL DbgUnmatched; // loaded an unmatched dbg + BOOL LineNumbers; // we have line number information + BOOL GlobalSymbols; // we have internal symbol information + BOOL TypeInfo; // we have type information + // new elements: 17-Dec-2003 + BOOL SourceIndexed; // pdb supports source server + BOOL Publics; // contains public symbols +} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64; + +typedef struct _IMAGEHLP_MODULEW64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) + DWORD64 BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + WCHAR ModuleName[32]; // module name + WCHAR ImageName[256]; // image name + // new elements: 07-Jun-2002 + WCHAR LoadedImageName[256]; // symbol file name + WCHAR LoadedPdbName[256]; // pdb file name + DWORD CVSig; // Signature of the CV record in the debug directories + WCHAR CVData[MAX_PATH * 3]; // Contents of the CV record + DWORD PdbSig; // Signature of PDB + GUID PdbSig70; // Signature of PDB (VC 7 and up) + DWORD PdbAge; // DBI age of pdb + BOOL PdbUnmatched; // loaded an unmatched pdb + BOOL DbgUnmatched; // loaded an unmatched dbg + BOOL LineNumbers; // we have line number information + BOOL GlobalSymbols; // we have internal symbol information + BOOL TypeInfo; // we have type information + // new elements: 17-Dec-2003 + BOOL SourceIndexed; // pdb supports source server + BOOL Publics; // contains public symbols +} IMAGEHLP_MODULEW64, *PIMAGEHLP_MODULEW64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define IMAGEHLP_MODULE IMAGEHLP_MODULE64 +#define PIMAGEHLP_MODULE PIMAGEHLP_MODULE64 +#define IMAGEHLP_MODULEW IMAGEHLP_MODULEW64 +#define PIMAGEHLP_MODULEW PIMAGEHLP_MODULEW64 +#else +typedef struct _IMAGEHLP_MODULE { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE) + DWORD BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + CHAR ModuleName[32]; // module name + CHAR ImageName[256]; // image name + CHAR LoadedImageName[256]; // symbol file name +} IMAGEHLP_MODULE, *PIMAGEHLP_MODULE; + +typedef struct _IMAGEHLP_MODULEW { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE) + DWORD BaseOfImage; // base load address of module + DWORD ImageSize; // virtual size of the loaded module + DWORD TimeDateStamp; // date/time stamp from pe header + DWORD CheckSum; // checksum from the pe header + DWORD NumSyms; // number of symbols in the symbol table + SYM_TYPE SymType; // type of symbols loaded + WCHAR ModuleName[32]; // module name + WCHAR ImageName[256]; // image name + WCHAR LoadedImageName[256]; // symbol file name +} IMAGEHLP_MODULEW, *PIMAGEHLP_MODULEW; +#endif + +// +// source file line data structure +// + +typedef struct _IMAGEHLP_LINE64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) + PVOID Key; // internal + DWORD LineNumber; // line number in file + PCHAR FileName; // full filename + DWORD64 Address; // first instruction of line +} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; + +typedef struct _IMAGEHLP_LINEW64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) + PVOID Key; // internal + DWORD LineNumber; // line number in file + PWSTR FileName; // full filename + DWORD64 Address; // first instruction of line +} IMAGEHLP_LINEW64, *PIMAGEHLP_LINEW64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define IMAGEHLP_LINE IMAGEHLP_LINE64 +#define PIMAGEHLP_LINE PIMAGEHLP_LINE64 +#else +typedef struct _IMAGEHLP_LINE { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE) + PVOID Key; // internal + DWORD LineNumber; // line number in file + PCHAR FileName; // full filename + DWORD Address; // first instruction of line +} IMAGEHLP_LINE, *PIMAGEHLP_LINE; + +typedef struct _IMAGEHLP_LINEW { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) + PVOID Key; // internal + DWORD LineNumber; // line number in file + PCHAR FileName; // full filename + DWORD64 Address; // first instruction of line +} IMAGEHLP_LINEW, *PIMAGEHLP_LINEW; +#endif + +// +// source file structure +// + +typedef struct _SOURCEFILE { + DWORD64 ModBase; // base address of loaded module + PCHAR FileName; // full filename of source +} SOURCEFILE, *PSOURCEFILE; + +typedef struct _SOURCEFILEW { + DWORD64 ModBase; // base address of loaded module + PWSTR FileName; // full filename of source +} SOURCEFILEW, *PSOURCEFILEW; + +// +// data structures used for registered symbol callbacks +// + +#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 +#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 +#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 +#define CBA_SYMBOLS_UNLOADED 0x00000004 +#define CBA_DUPLICATE_SYMBOL 0x00000005 +#define CBA_READ_MEMORY 0x00000006 +#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 +#define CBA_SET_OPTIONS 0x00000008 +#define CBA_EVENT 0x00000010 +#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 +#define CBA_DEBUG_INFO 0x10000000 +#define CBA_SRCSRV_INFO 0x20000000 +#define CBA_SRCSRV_EVENT 0x40000000 + +typedef struct _IMAGEHLP_CBA_READ_MEMORY { + DWORD64 addr; // address to read from + PVOID buf; // buffer to read to + DWORD bytes; // amount of bytes to read + DWORD *bytesread; // pointer to store amount of bytes read +} IMAGEHLP_CBA_READ_MEMORY, *PIMAGEHLP_CBA_READ_MEMORY; + +enum { + sevInfo = 0, + sevProblem, + sevAttn, + sevFatal, + sevMax // unused +}; + +#define EVENT_SRCSPEW_START 100 +#define EVENT_SRCSPEW 100 +#define EVENT_SRCSPEW_END 199 + +typedef struct _IMAGEHLP_CBA_EVENT { + DWORD severity; // values from sevInfo to sevFatal + DWORD code; // numerical code IDs the error + PCHAR desc; // may contain a text description of the error + PVOID object; // value dependant upon the error code +} IMAGEHLP_CBA_EVENT, *PIMAGEHLP_CBA_EVENT; + +typedef struct _IMAGEHLP_CBA_EVENTW { + DWORD severity; // values from sevInfo to sevFatal + DWORD code; // numerical code IDs the error + PCWSTR desc; // may contain a text description of the error + PVOID object; // value dependant upon the error code +} IMAGEHLP_CBA_EVENTW, *PIMAGEHLP_CBA_EVENTW; + +typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOAD64) + DWORD64 BaseOfImage; // base load address of module + DWORD CheckSum; // checksum from the pe header + DWORD TimeDateStamp; // date/time stamp from pe header + CHAR FileName[MAX_PATH]; // symbols file or image name + BOOLEAN Reparse; // load failure reparse + HANDLE hFile; // file handle, if passed + DWORD Flags; // +} IMAGEHLP_DEFERRED_SYMBOL_LOAD64, *PIMAGEHLP_DEFERRED_SYMBOL_LOAD64; + +typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOADW64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOADW64) + DWORD64 BaseOfImage; // base load address of module + DWORD CheckSum; // checksum from the pe header + DWORD TimeDateStamp; // date/time stamp from pe header + WCHAR FileName[MAX_PATH + 1]; // symbols file or image name + BOOLEAN Reparse; // load failure reparse + HANDLE hFile; // file handle, if passed + DWORD Flags; // +} IMAGEHLP_DEFERRED_SYMBOL_LOADW64, *PIMAGEHLP_DEFERRED_SYMBOL_LOADW64; + +#define DSLFLAG_MISMATCHED_PDB 0x1 +#define DSLFLAG_MISMATCHED_DBG 0x2 + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define IMAGEHLP_DEFERRED_SYMBOL_LOAD IMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#define PIMAGEHLP_DEFERRED_SYMBOL_LOAD PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 +#else +typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DEFERRED_SYMBOL_LOAD) + DWORD BaseOfImage; // base load address of module + DWORD CheckSum; // checksum from the pe header + DWORD TimeDateStamp; // date/time stamp from pe header + CHAR FileName[MAX_PATH]; // symbols file or image name + BOOLEAN Reparse; // load failure reparse + HANDLE hFile; // file handle, if passed +} IMAGEHLP_DEFERRED_SYMBOL_LOAD, *PIMAGEHLP_DEFERRED_SYMBOL_LOAD; +#endif + +typedef struct _IMAGEHLP_DUPLICATE_SYMBOL64 { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DUPLICATE_SYMBOL64) + DWORD NumberOfDups; // number of duplicates in the Symbol array + PIMAGEHLP_SYMBOL64 Symbol; // array of duplicate symbols + DWORD SelectedSymbol; // symbol selected (-1 to start) +} IMAGEHLP_DUPLICATE_SYMBOL64, *PIMAGEHLP_DUPLICATE_SYMBOL64; + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define IMAGEHLP_DUPLICATE_SYMBOL IMAGEHLP_DUPLICATE_SYMBOL64 +#define PIMAGEHLP_DUPLICATE_SYMBOL PIMAGEHLP_DUPLICATE_SYMBOL64 +#else +typedef struct _IMAGEHLP_DUPLICATE_SYMBOL { + DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_DUPLICATE_SYMBOL) + DWORD NumberOfDups; // number of duplicates in the Symbol array + PIMAGEHLP_SYMBOL Symbol; // array of duplicate symbols + DWORD SelectedSymbol; // symbol selected (-1 to start) +} IMAGEHLP_DUPLICATE_SYMBOL, *PIMAGEHLP_DUPLICATE_SYMBOL; +#endif + +// If dbghelp ever needs to display graphical UI, it will use this as the parent window. + +BOOL +IMAGEAPI +SymSetParentWindow( + __in HWND hwnd + ); + +PCHAR +IMAGEAPI +SymSetHomeDirectory( + __in_opt HANDLE hProcess, + __in_opt PCSTR dir + ); + +PWSTR +IMAGEAPI +SymSetHomeDirectoryW( + __in_opt HANDLE hProcess, + __in_opt PCWSTR dir + ); + +PCHAR +IMAGEAPI +SymGetHomeDirectory( + __in DWORD type, + __out_ecount(size) PSTR dir, + __in size_t size + ); + +PWSTR +IMAGEAPI +SymGetHomeDirectoryW( + __in DWORD type, + __out_ecount(size) PWSTR dir, + __in size_t size + ); + +enum { + hdBase = 0, // root directory for dbghelp + hdSym, // where symbols are stored + hdSrc, // where source is stored + hdMax // end marker +}; + +typedef struct _OMAP { + ULONG rva; + ULONG rvaTo; +} OMAP, *POMAP; + +BOOL +IMAGEAPI +SymGetOmaps( + __in HANDLE hProcess, + __in DWORD64 BaseOfDll, + __out POMAP *OmapTo, + __out PDWORD64 cOmapTo, + __out POMAP *OmapFrom, + __out PDWORD64 cOmapFrom + ); + +// +// options that are set/returned by SymSetOptions() & SymGetOptions() +// these are used as a mask +// +#define SYMOPT_CASE_INSENSITIVE 0x00000001 +#define SYMOPT_UNDNAME 0x00000002 +#define SYMOPT_DEFERRED_LOADS 0x00000004 +#define SYMOPT_NO_CPP 0x00000008 +#define SYMOPT_LOAD_LINES 0x00000010 +#define SYMOPT_OMAP_FIND_NEAREST 0x00000020 +#define SYMOPT_LOAD_ANYTHING 0x00000040 +#define SYMOPT_IGNORE_CVREC 0x00000080 +#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100 +#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200 +#define SYMOPT_EXACT_SYMBOLS 0x00000400 +#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800 +#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000 +#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000 +#define SYMOPT_PUBLICS_ONLY 0x00004000 +#define SYMOPT_NO_PUBLICS 0x00008000 +#define SYMOPT_AUTO_PUBLICS 0x00010000 +#define SYMOPT_NO_IMAGE_SEARCH 0x00020000 +#define SYMOPT_SECURE 0x00040000 +#define SYMOPT_NO_PROMPTS 0x00080000 +#define SYMOPT_OVERWRITE 0x00100000 +#define SYMOPT_IGNORE_IMAGEDIR 0x00200000 +#define SYMOPT_FLAT_DIRECTORY 0x00400000 +#define SYMOPT_FAVOR_COMPRESSED 0x00800000 +#define SYMOPT_ALLOW_ZERO_ADDRESS 0x01000000 +#define SYMOPT_DISABLE_SYMSRV_AUTODETECT 0x02000000 + +#define SYMOPT_DEBUG 0x80000000 + +DWORD +IMAGEAPI +SymSetOptions( + __in DWORD SymOptions + ); + +DWORD +IMAGEAPI +SymGetOptions( + VOID + ); + +BOOL +IMAGEAPI +SymCleanup( + __in HANDLE hProcess + ); + +BOOL +IMAGEAPI +SymMatchString( + __in PCSTR string, + __in PCSTR expression, + __in BOOL fCase + ); + +BOOL +IMAGEAPI +SymMatchStringA( + __in PCSTR string, + __in PCSTR expression, + __in BOOL fCase + ); + +BOOL +IMAGEAPI +SymMatchStringW( + __in PCWSTR string, + __in PCWSTR expression, + __in BOOL fCase + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMSOURCEFILES_CALLBACK)( + __in PSOURCEFILE pSourceFile, + __in_opt PVOID UserContext + ); + +// for backwards compatibility - don't use this +#define PSYM_ENUMSOURCFILES_CALLBACK PSYM_ENUMSOURCEFILES_CALLBACK + +BOOL +IMAGEAPI +SymEnumSourceFiles( + __in HANDLE hProcess, + __in ULONG64 ModBase, + __in_opt PCSTR Mask, + __in PSYM_ENUMSOURCEFILES_CALLBACK cbSrcFiles, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMSOURCEFILES_CALLBACKW)( + __in PSOURCEFILEW pSourceFile, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumSourceFilesW( + __in HANDLE hProcess, + __in ULONG64 ModBase, + __in_opt PCWSTR Mask, + __in PSYM_ENUMSOURCEFILES_CALLBACKW cbSrcFiles, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumerateModules64( + __in HANDLE hProcess, + __in PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumerateModulesW64( + __in HANDLE hProcess, + __in PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback, + __in_opt PVOID UserContext + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymEnumerateModules SymEnumerateModules64 +#else +BOOL +IMAGEAPI +SymEnumerateModules( + __in HANDLE hProcess, + __in PSYM_ENUMMODULES_CALLBACK EnumModulesCallback, + __in_opt PVOID UserContext + ); +#endif + +BOOL +IMAGEAPI +EnumerateLoadedModulesEx( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +EnumerateLoadedModulesExW( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +EnumerateLoadedModules64( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +EnumerateLoadedModulesW64( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, + __in_opt PVOID UserContext + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define EnumerateLoadedModules EnumerateLoadedModules64 +#else +BOOL +IMAGEAPI +EnumerateLoadedModules( + __in HANDLE hProcess, + __in PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback, + __in_opt PVOID UserContext + ); +#endif + +PVOID +IMAGEAPI +SymFunctionTableAccess64( + __in HANDLE hProcess, + __in DWORD64 AddrBase + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymFunctionTableAccess SymFunctionTableAccess64 +#else +PVOID +IMAGEAPI +SymFunctionTableAccess( + __in HANDLE hProcess, + __in DWORD AddrBase + ); +#endif + +BOOL +IMAGEAPI +SymGetUnwindInfo( + __in HANDLE hProcess, + __in DWORD64 Address, + __out_bcount_opt(*Size) PVOID Buffer, + __inout PULONG Size + ); + +BOOL +IMAGEAPI +SymGetModuleInfo64( + __in HANDLE hProcess, + __in DWORD64 qwAddr, + __out PIMAGEHLP_MODULE64 ModuleInfo + ); + +BOOL +IMAGEAPI +SymGetModuleInfoW64( + __in HANDLE hProcess, + __in DWORD64 qwAddr, + __out PIMAGEHLP_MODULEW64 ModuleInfo + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetModuleInfo SymGetModuleInfo64 +#define SymGetModuleInfoW SymGetModuleInfoW64 +#else +BOOL +IMAGEAPI +SymGetModuleInfo( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out PIMAGEHLP_MODULE ModuleInfo + ); + +BOOL +IMAGEAPI +SymGetModuleInfoW( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out PIMAGEHLP_MODULEW ModuleInfo + ); +#endif + +DWORD64 +IMAGEAPI +SymGetModuleBase64( + __in HANDLE hProcess, + __in DWORD64 qwAddr + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetModuleBase SymGetModuleBase64 +#else +DWORD +IMAGEAPI +SymGetModuleBase( + __in HANDLE hProcess, + __in DWORD dwAddr + ); +#endif + +typedef struct _SRCCODEINFO { + DWORD SizeOfStruct; // set to sizeof(SRCCODEINFO) + PVOID Key; // not used + DWORD64 ModBase; // base address of module this applies to + CHAR Obj[MAX_PATH + 1]; // the object file within the module + CHAR FileName[MAX_PATH + 1]; // full filename + DWORD LineNumber; // line number in file + DWORD64 Address; // first instruction of line +} SRCCODEINFO, *PSRCCODEINFO; + +typedef struct _SRCCODEINFOW { + DWORD SizeOfStruct; // set to sizeof(SRCCODEINFO) + PVOID Key; // not used + DWORD64 ModBase; // base address of module this applies to + WCHAR Obj[MAX_PATH + 1]; // the object file within the module + WCHAR FileName[MAX_PATH + 1]; // full filename + DWORD LineNumber; // line number in file + DWORD64 Address; // first instruction of line +} SRCCODEINFOW, *PSRCCODEINFOW; + +typedef BOOL +(CALLBACK *PSYM_ENUMLINES_CALLBACK)( + __in PSRCCODEINFO LineInfo, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumLines( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR Obj, + __in_opt PCSTR File, + __in PSYM_ENUMLINES_CALLBACK EnumLinesCallback, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMLINES_CALLBACKW)( + __in PSRCCODEINFOW LineInfo, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumLinesW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCWSTR Obj, + __in_opt PCWSTR File, + __in PSYM_ENUMLINES_CALLBACKW EnumLinesCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymGetLineFromAddr64( + __in HANDLE hProcess, + __in DWORD64 qwAddr, + __out PDWORD pdwDisplacement, + __out PIMAGEHLP_LINE64 Line64 + ); + +BOOL +IMAGEAPI +SymGetLineFromAddrW64( + __in HANDLE hProcess, + __in DWORD64 dwAddr, + __out PDWORD pdwDisplacement, + __out PIMAGEHLP_LINEW64 Line + ); + +BOOL +IMAGEAPI +SymEnumSourceLines( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR Obj, + __in_opt PCSTR File, + __in_opt DWORD Line, + __in DWORD Flags, + __in PSYM_ENUMLINES_CALLBACK EnumLinesCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumSourceLinesW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCWSTR Obj, + __in_opt PCWSTR File, + __in_opt DWORD Line, + __in DWORD Flags, + __in PSYM_ENUMLINES_CALLBACKW EnumLinesCallback, + __in_opt PVOID UserContext + ); + +// flags for SymEnumSourceLines + +#define ESLFLAG_FULLPATH 0x1 +#define ESLFLAG_NEAREST 0x2 +#define ESLFLAG_PREV 0x4 +#define ESLFLAG_NEXT 0x8 + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetLineFromAddr SymGetLineFromAddr64 +#define SymGetLineFromAddrW SymGetLineFromAddrW64 +#else +BOOL +IMAGEAPI +SymGetLineFromAddr( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out PDWORD pdwDisplacement, + __out PIMAGEHLP_LINE Line + ); + +BOOL +IMAGEAPI +SymGetLineFromAddrW( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out PDWORD pdwDisplacement, + __out PIMAGEHLP_LINEW Line + ); +#endif + +BOOL +IMAGEAPI +SymGetLineFromName64( + __in HANDLE hProcess, + __in_opt PCSTR ModuleName, + __in_opt PCSTR FileName, + __in DWORD dwLineNumber, + __out PLONG plDisplacement, + __inout PIMAGEHLP_LINE64 Line + ); + +BOOL +IMAGEAPI +SymGetLineFromNameW64( + __in HANDLE hProcess, + __in_opt PCWSTR ModuleName, + __in_opt PCWSTR FileName, + __in DWORD dwLineNumber, + __out PLONG plDisplacement, + __inout PIMAGEHLP_LINEW64 Line + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetLineFromName SymGetLineFromName64 +#else +BOOL +IMAGEAPI +SymGetLineFromName( + __in HANDLE hProcess, + __in_opt PCSTR ModuleName, + __in_opt PCSTR FileName, + __in DWORD dwLineNumber, + __out PLONG plDisplacement, + __inout PIMAGEHLP_LINE Line + ); +#endif + +BOOL +IMAGEAPI +SymGetLineNext64( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINE64 Line + ); + +BOOL +IMAGEAPI +SymGetLineNextW64( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINEW64 Line + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetLineNext SymGetLineNext64 +#else +BOOL +IMAGEAPI +SymGetLineNext( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINE Line + ); + +BOOL +IMAGEAPI +SymGetLineNextW( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINEW Line + ); +#endif + +BOOL +IMAGEAPI +SymGetLinePrev64( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINE64 Line + ); + +BOOL +IMAGEAPI +SymGetLinePrevW64( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINEW64 Line + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetLinePrev SymGetLinePrev64 +#else +BOOL +IMAGEAPI +SymGetLinePrev( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINE Line + ); + +BOOL +IMAGEAPI +SymGetLinePrevW( + __in HANDLE hProcess, + __inout PIMAGEHLP_LINEW Line + ); +#endif + +ULONG +IMAGEAPI +SymGetFileLineOffsets64( + __in HANDLE hProcess, + __in_opt PCSTR ModuleName, + __in PCSTR FileName, + __out_ecount(BufferLines) PDWORD64 Buffer, + __in ULONG BufferLines + ); + +BOOL +IMAGEAPI +SymMatchFileName( + __in PCSTR FileName, + __in PCSTR Match, + __deref_opt_out PSTR *FileNameStop, + __deref_opt_out PSTR *MatchStop + ); + +BOOL +IMAGEAPI +SymMatchFileNameW( + __in PCWSTR FileName, + __in PCWSTR Match, + __deref_opt_out PWSTR *FileNameStop, + __deref_opt_out PWSTR *MatchStop + ); + +BOOL +IMAGEAPI +SymGetSourceFile( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR Params, + __in PCSTR FileSpec, + __out_ecount(Size) PSTR FilePath, + __in DWORD Size + ); + +BOOL +IMAGEAPI +SymGetSourceFileW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCWSTR Params, + __in PCWSTR FileSpec, + __out_ecount(Size) PWSTR FilePath, + __in DWORD Size + ); + +BOOL +IMAGEAPI +SymGetSourceFileToken( + __in HANDLE hProcess, + __in ULONG64 Base, + __in PCSTR FileSpec, + __deref_out PVOID *Token, + __out DWORD *Size + ); + +BOOL +IMAGEAPI +SymGetSourceFileTokenW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in PCWSTR FileSpec, + __deref_out PVOID *Token, + __out DWORD *Size + ); + +BOOL +IMAGEAPI +SymGetSourceFileFromToken( + __in HANDLE hProcess, + __in PVOID Token, + __in_opt PCSTR Params, + __out_ecount(Size) PSTR FilePath, + __in DWORD Size + ); + +BOOL +IMAGEAPI +SymGetSourceFileFromTokenW( + __in HANDLE hProcess, + __in PVOID Token, + __in_opt PCWSTR Params, + __out_ecount(Size) PWSTR FilePath, + __in DWORD Size + ); + +BOOL +IMAGEAPI +SymGetSourceVarFromToken( + __in HANDLE hProcess, + __in PVOID Token, + __in_opt PCSTR Params, + __in PCSTR VarName, + __out_ecount(Size) PSTR Value, + __in DWORD Size + ); + +BOOL +IMAGEAPI +SymGetSourceVarFromTokenW( + __in HANDLE hProcess, + __in PVOID Token, + __in_opt PCWSTR Params, + __in PCWSTR VarName, + __out_ecount(Size) PWSTR Value, + __in DWORD Size + ); + +typedef BOOL (CALLBACK *PENUMSOURCEFILETOKENSCALLBACK)(__in PVOID token, __in size_t size); + +BOOL +IMAGEAPI +SymEnumSourceFileTokens( + __in HANDLE hProcess, + __in ULONG64 Base, + __in PENUMSOURCEFILETOKENSCALLBACK Callback + ); + +BOOL +IMAGEAPI +SymInitialize( + __in HANDLE hProcess, + __in_opt PCSTR UserSearchPath, + __in BOOL fInvadeProcess + ); + +BOOL +IMAGEAPI +SymInitializeW( + __in HANDLE hProcess, + __in_opt PCWSTR UserSearchPath, + __in BOOL fInvadeProcess + ); + +BOOL +IMAGEAPI +SymGetSearchPath( + __in HANDLE hProcess, + __out_ecount(SearchPathLength) PSTR SearchPath, + __in DWORD SearchPathLength + ); + +BOOL +IMAGEAPI +SymGetSearchPathW( + __in HANDLE hProcess, + __out_ecount(SearchPathLength) PWSTR SearchPath, + __in DWORD SearchPathLength + ); + +BOOL +IMAGEAPI +SymSetSearchPath( + __in HANDLE hProcess, + __in_opt PCSTR SearchPath + ); + +BOOL +IMAGEAPI +SymSetSearchPathW( + __in HANDLE hProcess, + __in_opt PCWSTR SearchPath + ); + +#define SLMFLAG_VIRTUAL 0x1 +#define SLMFLAG_ALT_INDEX 0x2 +#define SLMFLAG_NO_SYMBOLS 0x4 + +DWORD64 +IMAGEAPI +SymLoadModuleEx( + __in HANDLE hProcess, + __in_opt HANDLE hFile, + __in_opt PCSTR ImageName, + __in_opt PCSTR ModuleName, + __in DWORD64 BaseOfDll, + __in DWORD DllSize, + __in_opt PMODLOAD_DATA Data, + __in_opt DWORD Flags + ); + +DWORD64 +IMAGEAPI +SymLoadModuleExW( + __in HANDLE hProcess, + __in_opt HANDLE hFile, + __in_opt PCWSTR ImageName, + __in_opt PCWSTR ModuleName, + __in DWORD64 BaseOfDll, + __in DWORD DllSize, + __in_opt PMODLOAD_DATA Data, + __in_opt DWORD Flags + ); + +BOOL +IMAGEAPI +SymUnloadModule64( + __in HANDLE hProcess, + __in DWORD64 BaseOfDll + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymUnloadModule SymUnloadModule64 +#else +BOOL +IMAGEAPI +SymUnloadModule( + __in HANDLE hProcess, + __in DWORD BaseOfDll + ); +#endif + +BOOL +IMAGEAPI +SymUnDName64( + __in PIMAGEHLP_SYMBOL64 sym, // Symbol to undecorate + __out_ecount(UnDecNameLength) PSTR UnDecName, // Buffer to store undecorated name in + __in DWORD UnDecNameLength // Size of the buffer + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymUnDName SymUnDName64 +#else +BOOL +IMAGEAPI +SymUnDName( + __in PIMAGEHLP_SYMBOL sym, // Symbol to undecorate + __out_ecount(UnDecNameLength) PSTR UnDecName, // Buffer to store undecorated name in + __in DWORD UnDecNameLength // Size of the buffer + ); +#endif + +BOOL +IMAGEAPI +SymRegisterCallback64( + __in HANDLE hProcess, + __in PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, + __in ULONG64 UserContext + ); + +BOOL +IMAGEAPI +SymRegisterCallbackW64( + __in HANDLE hProcess, + __in PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, + __in ULONG64 UserContext + ); + +BOOL +IMAGEAPI +SymRegisterFunctionEntryCallback64( + __in HANDLE hProcess, + __in PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction, + __in ULONG64 UserContext + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymRegisterCallback SymRegisterCallback64 +#define SymRegisterFunctionEntryCallback SymRegisterFunctionEntryCallback64 +#else +BOOL +IMAGEAPI +SymRegisterCallback( + __in HANDLE hProcess, + __in PSYMBOL_REGISTERED_CALLBACK CallbackFunction, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymRegisterFunctionEntryCallback( + __in HANDLE hProcess, + __in PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction, + __in_opt PVOID UserContext + ); +#endif + + +typedef struct _IMAGEHLP_SYMBOL_SRC { + DWORD sizeofstruct; + DWORD type; + char file[MAX_PATH]; +} IMAGEHLP_SYMBOL_SRC, *PIMAGEHLP_SYMBOL_SRC; + +typedef struct _MODULE_TYPE_INFO { // AKA TYPTYP + USHORT dataLength; + USHORT leaf; + BYTE data[1]; +} MODULE_TYPE_INFO, *PMODULE_TYPE_INFO; + +typedef struct _SYMBOL_INFO { + ULONG SizeOfStruct; + ULONG TypeIndex; // Type Index of symbol + ULONG64 Reserved[2]; + ULONG Index; + ULONG Size; + ULONG64 ModBase; // Base Address of module comtaining this symbol + ULONG Flags; + ULONG64 Value; // Value of symbol, ValuePresent should be 1 + ULONG64 Address; // Address of symbol including base address of module + ULONG Register; // register holding value or pointer to value + ULONG Scope; // scope of the symbol + ULONG Tag; // pdb classification + ULONG NameLen; // Actual length of name + ULONG MaxNameLen; + CHAR Name[1]; // Name of symbol +} SYMBOL_INFO, *PSYMBOL_INFO; + +typedef struct _SYMBOL_INFO_PACKAGE { + SYMBOL_INFO si; + CHAR name[MAX_SYM_NAME + 1]; +} SYMBOL_INFO_PACKAGE, *PSYMBOL_INFO_PACKAGE; + +typedef struct _SYMBOL_INFOW { + ULONG SizeOfStruct; + ULONG TypeIndex; // Type Index of symbol + ULONG64 Reserved[2]; + ULONG Index; + ULONG Size; + ULONG64 ModBase; // Base Address of module comtaining this symbol + ULONG Flags; + ULONG64 Value; // Value of symbol, ValuePresent should be 1 + ULONG64 Address; // Address of symbol including base address of module + ULONG Register; // register holding value or pointer to value + ULONG Scope; // scope of the symbol + ULONG Tag; // pdb classification + ULONG NameLen; // Actual length of name + ULONG MaxNameLen; + WCHAR Name[1]; // Name of symbol +} SYMBOL_INFOW, *PSYMBOL_INFOW; + +typedef struct _SYMBOL_INFO_PACKAGEW { + SYMBOL_INFOW si; + WCHAR name[MAX_SYM_NAME + 1]; +} SYMBOL_INFO_PACKAGEW, *PSYMBOL_INFO_PACKAGEW; + +typedef struct _IMAGEHLP_STACK_FRAME +{ + ULONG64 InstructionOffset; + ULONG64 ReturnOffset; + ULONG64 FrameOffset; + ULONG64 StackOffset; + ULONG64 BackingStoreOffset; + ULONG64 FuncTableEntry; + ULONG64 Params[4]; + ULONG64 Reserved[5]; + BOOL Virtual; + ULONG Reserved2; +} IMAGEHLP_STACK_FRAME, *PIMAGEHLP_STACK_FRAME; + +typedef VOID IMAGEHLP_CONTEXT, *PIMAGEHLP_CONTEXT; + + +BOOL +IMAGEAPI +SymSetContext( + __in HANDLE hProcess, + __in PIMAGEHLP_STACK_FRAME StackFrame, + __in_opt PIMAGEHLP_CONTEXT Context + ); + +BOOL +IMAGEAPI +SymSetScopeFromAddr( + __in HANDLE hProcess, + __in ULONG64 Address + ); + +BOOL +IMAGEAPI +SymSetScopeFromIndex( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMPROCESSES_CALLBACK)( + __in HANDLE hProcess, + __in PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumProcesses( + __in PSYM_ENUMPROCESSES_CALLBACK EnumProcessesCallback, + __in PVOID UserContext + ); + +BOOL +IMAGEAPI +SymFromAddr( + __in HANDLE hProcess, + __in DWORD64 Address, + __out_opt PDWORD64 Displacement, + __inout PSYMBOL_INFO Symbol + ); + +BOOL +IMAGEAPI +SymFromAddrW( + __in HANDLE hProcess, + __in DWORD64 Address, + __out_opt PDWORD64 Displacement, + __inout PSYMBOL_INFOW Symbol + ); + +BOOL +IMAGEAPI +SymFromToken( + __in HANDLE hProcess, + __in DWORD64 Base, + __in DWORD Token, + __inout PSYMBOL_INFO Symbol + ); + +BOOL +IMAGEAPI +SymFromTokenW( + __in HANDLE hProcess, + __in DWORD64 Base, + __in DWORD Token, + __inout PSYMBOL_INFOW Symbol + ); + +BOOL +IMAGEAPI +SymNext( + __in HANDLE hProcess, + __inout PSYMBOL_INFO si + ); + +BOOL +IMAGEAPI +SymNextW( + __in HANDLE hProcess, + __inout PSYMBOL_INFOW siw + ); + +BOOL +IMAGEAPI +SymPrev( + __in HANDLE hProcess, + __inout PSYMBOL_INFO si + ); + +BOOL +IMAGEAPI +SymPrevW( + __in HANDLE hProcess, + __inout PSYMBOL_INFOW siw + ); + +// While SymFromName will provide a symbol from a name, +// SymEnumSymbols can provide the same matching information +// for ALL symbols with a matching name, even regular +// expressions. That way you can search across modules +// and differentiate between identically named symbols. + +BOOL +IMAGEAPI +SymFromName( + __in HANDLE hProcess, + __in PCSTR Name, + __inout PSYMBOL_INFO Symbol + ); + +BOOL +IMAGEAPI +SymFromNameW( + __in HANDLE hProcess, + __in PCWSTR Name, + __inout PSYMBOL_INFOW Symbol + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)( + __in PSYMBOL_INFO pSymInfo, + __in ULONG SymbolSize, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumSymbols( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCSTR Mask, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +typedef BOOL +(CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACKW)( + __in PSYMBOL_INFOW pSymInfo, + __in ULONG SymbolSize, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumSymbolsW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCWSTR Mask, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumSymbolsForAddr( + __in HANDLE hProcess, + __in DWORD64 Address, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumSymbolsForAddrW( + __in HANDLE hProcess, + __in DWORD64 Address, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +#define SYMSEARCH_MASKOBJS 0x01 // used internally to implement other APIs +#define SYMSEARCH_RECURSE 0X02 // recurse scopes +#define SYMSEARCH_GLOBALSONLY 0X04 // search only for global symbols +#define SYMSEARCH_ALLITEMS 0X08 // search for everything in the pdb, not just normal scoped symbols + +BOOL +IMAGEAPI +SymSearch( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt DWORD Index, + __in_opt DWORD SymTag, + __in_opt PCSTR Mask, + __in_opt DWORD64 Address, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext, + __in DWORD Options + ); + +BOOL +IMAGEAPI +SymSearchW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt DWORD Index, + __in_opt DWORD SymTag, + __in_opt PCWSTR Mask, + __in_opt DWORD64 Address, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext, + __in DWORD Options + ); + +BOOL +IMAGEAPI +SymGetScope( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index, + __inout PSYMBOL_INFO Symbol + ); + +BOOL +IMAGEAPI +SymGetScopeW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index, + __inout PSYMBOL_INFOW Symbol + ); + +BOOL +IMAGEAPI +SymFromIndex( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index, + __inout PSYMBOL_INFO Symbol + ); + +BOOL +IMAGEAPI +SymFromIndexW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in DWORD Index, + __inout PSYMBOL_INFOW Symbol + ); + +typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO { + TI_GET_SYMTAG, + TI_GET_SYMNAME, + TI_GET_LENGTH, + TI_GET_TYPE, + TI_GET_TYPEID, + TI_GET_BASETYPE, + TI_GET_ARRAYINDEXTYPEID, + TI_FINDCHILDREN, + TI_GET_DATAKIND, + TI_GET_ADDRESSOFFSET, + TI_GET_OFFSET, + TI_GET_VALUE, + TI_GET_COUNT, + TI_GET_CHILDRENCOUNT, + TI_GET_BITPOSITION, + TI_GET_VIRTUALBASECLASS, + TI_GET_VIRTUALTABLESHAPEID, + TI_GET_VIRTUALBASEPOINTEROFFSET, + TI_GET_CLASSPARENTID, + TI_GET_NESTED, + TI_GET_SYMINDEX, + TI_GET_LEXICALPARENT, + TI_GET_ADDRESS, + TI_GET_THISADJUST, + TI_GET_UDTKIND, + TI_IS_EQUIV_TO, + TI_GET_CALLING_CONVENTION, + TI_IS_CLOSE_EQUIV_TO, + TI_GTIEX_REQS_VALID, + TI_GET_VIRTUALBASEOFFSET, + TI_GET_VIRTUALBASEDISPINDEX, + TI_GET_IS_REFERENCE, + TI_GET_INDIRECTVIRTUALBASECLASS, + IMAGEHLP_SYMBOL_TYPE_INFO_MAX, +} IMAGEHLP_SYMBOL_TYPE_INFO; + +typedef struct _TI_FINDCHILDREN_PARAMS { + ULONG Count; + ULONG Start; + ULONG ChildId[1]; +} TI_FINDCHILDREN_PARAMS; + +BOOL +IMAGEAPI +SymGetTypeInfo( + __in HANDLE hProcess, + __in DWORD64 ModBase, + __in ULONG TypeId, + __in IMAGEHLP_SYMBOL_TYPE_INFO GetType, + __out PVOID pInfo + ); + +#define IMAGEHLP_GET_TYPE_INFO_UNCACHED 0x00000001 +#define IMAGEHLP_GET_TYPE_INFO_CHILDREN 0x00000002 + +typedef struct _IMAGEHLP_GET_TYPE_INFO_PARAMS { + IN ULONG SizeOfStruct; + IN ULONG Flags; + IN ULONG NumIds; + IN PULONG TypeIds; + IN ULONG64 TagFilter; + IN ULONG NumReqs; + IN IMAGEHLP_SYMBOL_TYPE_INFO* ReqKinds; + IN PULONG_PTR ReqOffsets; + IN PULONG ReqSizes; + IN ULONG_PTR ReqStride; + IN ULONG_PTR BufferSize; + OUT PVOID Buffer; + OUT ULONG EntriesMatched; + OUT ULONG EntriesFilled; + OUT ULONG64 TagsFound; + OUT ULONG64 AllReqsValid; + IN ULONG NumReqsValid; + OUT PULONG64 ReqsValid OPTIONAL; +} IMAGEHLP_GET_TYPE_INFO_PARAMS, *PIMAGEHLP_GET_TYPE_INFO_PARAMS; + +BOOL +IMAGEAPI +SymGetTypeInfoEx( + __in HANDLE hProcess, + __in DWORD64 ModBase, + __inout PIMAGEHLP_GET_TYPE_INFO_PARAMS Params + ); + +BOOL +IMAGEAPI +SymEnumTypes( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumTypesW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumTypesByName( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCSTR mask, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymEnumTypesByNameW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCWSTR mask, + __in PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +BOOL +IMAGEAPI +SymGetTypeFromName( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PCSTR Name, + __inout PSYMBOL_INFO Symbol + ); + +BOOL +IMAGEAPI +SymGetTypeFromNameW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PCWSTR Name, + __inout PSYMBOL_INFOW Symbol + ); + +BOOL +IMAGEAPI +SymAddSymbol( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PCSTR Name, + __in DWORD64 Address, + __in DWORD Size, + __in DWORD Flags + ); + +BOOL +IMAGEAPI +SymAddSymbolW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PCWSTR Name, + __in DWORD64 Address, + __in DWORD Size, + __in DWORD Flags + ); + +BOOL +IMAGEAPI +SymDeleteSymbol( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCSTR Name, + __in DWORD64 Address, + __in DWORD Flags + ); + +BOOL +IMAGEAPI +SymDeleteSymbolW( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in_opt PCWSTR Name, + __in DWORD64 Address, + __in DWORD Flags + ); + +BOOL +IMAGEAPI +SymRefreshModuleList( + __in HANDLE hProcess + ); + +BOOL +IMAGEAPI +SymAddSourceStream( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR StreamFile, + __in_bcount_opt(Size) PBYTE Buffer, + __in size_t Size + ); + +typedef BOOL (WINAPI *SYMADDSOURCESTREAM)(HANDLE, ULONG64, PCSTR, PBYTE, size_t); + +BOOL +IMAGEAPI +SymAddSourceStreamA( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCSTR StreamFile, + __in_bcount_opt(Size) PBYTE Buffer, + __in size_t Size + ); + +typedef BOOL (WINAPI *SYMADDSOURCESTREAMA)(HANDLE, ULONG64, PCSTR, PBYTE, size_t); + +BOOL +IMAGEAPI +SymAddSourceStreamW( + __in HANDLE hProcess, + __in ULONG64 Base, + __in_opt PCWSTR FileSpec, + __in_bcount_opt(Size) PBYTE Buffer, + __in size_t Size + ); + +BOOL +IMAGEAPI +SymSrvIsStoreW( + __in_opt HANDLE hProcess, + __in PCWSTR path + ); + +BOOL +IMAGEAPI +SymSrvIsStore( + __in_opt HANDLE hProcess, + __in PCSTR path + ); + +PCSTR +IMAGEAPI +SymSrvDeltaName( + __in HANDLE hProcess, + __in_opt PCSTR SymPath, + __in PCSTR Type, + __in PCSTR File1, + __in PCSTR File2 + ); + +PCWSTR +IMAGEAPI +SymSrvDeltaNameW( + __in HANDLE hProcess, + __in_opt PCWSTR SymPath, + __in PCWSTR Type, + __in PCWSTR File1, + __in PCWSTR File2 + ); + +PCSTR +IMAGEAPI +SymSrvGetSupplement( + __in HANDLE hProcess, + __in_opt PCSTR SymPath, + __in PCSTR Node, + __in PCSTR File + ); + +PCWSTR +IMAGEAPI +SymSrvGetSupplementW( + __in HANDLE hProcess, + __in_opt PCWSTR SymPath, + __in PCWSTR Node, + __in PCWSTR File + ); + +BOOL +IMAGEAPI +SymSrvGetFileIndexes( + __in PCSTR File, + __out GUID *Id, + __out PDWORD Val1, + __out_opt PDWORD Val2, + __in DWORD Flags + ); + +BOOL +IMAGEAPI +SymSrvGetFileIndexesW( + __in PCWSTR File, + __out GUID *Id, + __out PDWORD Val1, + __out_opt PDWORD Val2, + __in DWORD Flags + ); + +BOOL +IMAGEAPI +SymSrvGetFileIndexStringW( + __in HANDLE hProcess, + __in_opt PCWSTR SrvPath, + __in PCWSTR File, + __out_ecount(Size) PWSTR Index, + __in size_t Size, + __in DWORD Flags + ); + +BOOL +IMAGEAPI +SymSrvGetFileIndexString( + __in HANDLE hProcess, + __in_opt PCSTR SrvPath, + __in PCSTR File, + __out_ecount(Size) PSTR Index, + __in size_t Size, + __in DWORD Flags + ); + +typedef struct { + DWORD sizeofstruct; + char file[MAX_PATH +1]; + BOOL stripped; + DWORD timestamp; + DWORD size; + char dbgfile[MAX_PATH +1]; + char pdbfile[MAX_PATH + 1]; + GUID guid; + DWORD sig; + DWORD age; +} SYMSRV_INDEX_INFO, *PSYMSRV_INDEX_INFO; + +typedef struct { + DWORD sizeofstruct; + WCHAR file[MAX_PATH +1]; + BOOL stripped; + DWORD timestamp; + DWORD size; + WCHAR dbgfile[MAX_PATH +1]; + WCHAR pdbfile[MAX_PATH + 1]; + GUID guid; + DWORD sig; + DWORD age; +} SYMSRV_INDEX_INFOW, *PSYMSRV_INDEX_INFOW; + +BOOL +IMAGEAPI +SymSrvGetFileIndexInfo( + __in PCSTR File, + __out PSYMSRV_INDEX_INFO Info, + __in DWORD Flags + ); + +BOOL +IMAGEAPI +SymSrvGetFileIndexInfoW( + __in PCWSTR File, + __out PSYMSRV_INDEX_INFOW Info, + __in DWORD Flags + ); + +PCSTR +IMAGEAPI +SymSrvStoreSupplement( + __in HANDLE hProcess, + __in_opt PCSTR SrvPath, + __in PCSTR Node, + __in PCSTR File, + __in DWORD Flags + ); + +PCWSTR +IMAGEAPI +SymSrvStoreSupplementW( + __in HANDLE hProcess, + __in_opt PCWSTR SymPath, + __in PCWSTR Node, + __in PCWSTR File, + __in DWORD Flags + ); + +PCSTR +IMAGEAPI +SymSrvStoreFile( + __in HANDLE hProcess, + __in_opt PCSTR SrvPath, + __in PCSTR File, + __in DWORD Flags + ); + +PCWSTR +IMAGEAPI +SymSrvStoreFileW( + __in HANDLE hProcess, + __in_opt PCWSTR SrvPath, + __in PCWSTR File, + __in DWORD Flags + ); + +// used by SymGetSymbolFile's "Type" parameter + +enum { + sfImage = 0, + sfDbg, + sfPdb, + sfMpd, + sfMax +}; + +BOOL +IMAGEAPI +SymGetSymbolFile( + __in_opt HANDLE hProcess, + __in_opt PCSTR SymPath, + __in PCSTR ImageFile, + __in DWORD Type, + __out_ecount(cSymbolFile) PSTR SymbolFile, + __in size_t cSymbolFile, + __out_ecount(cDbgFile) PSTR DbgFile, + __in size_t cDbgFile + ); + +BOOL +IMAGEAPI +SymGetSymbolFileW( + __in_opt HANDLE hProcess, + __in_opt PCWSTR SymPath, + __in PCWSTR ImageFile, + __in DWORD Type, + __out_ecount(cSymbolFile) PWSTR SymbolFile, + __in size_t cSymbolFile, + __out_ecount(cDbgFile) PWSTR DbgFile, + __in size_t cDbgFile + ); + +// +// Full user-mode dump creation. +// + +typedef BOOL (WINAPI *PDBGHELP_CREATE_USER_DUMP_CALLBACK)( + __in DWORD DataType, + __in PVOID* Data, + __out LPDWORD DataLength, + __in_opt PVOID UserData + ); + +BOOL +WINAPI +DbgHelpCreateUserDump( + __in_opt LPCSTR FileName, + __in PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback, + __in_opt PVOID UserData + ); + +BOOL +WINAPI +DbgHelpCreateUserDumpW( + __in_opt LPCWSTR FileName, + __in PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback, + __in_opt PVOID UserData + ); + +// ----------------------------------------------------------------- +// The following 4 legacy APIs are fully supported, but newer +// ones are recommended. SymFromName and SymFromAddr provide +// much more detailed info on the returned symbol. + +BOOL +IMAGEAPI +SymGetSymFromAddr64( + __in HANDLE hProcess, + __in DWORD64 qwAddr, + __out_opt PDWORD64 pdwDisplacement, + __inout PIMAGEHLP_SYMBOL64 Symbol + ); + + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetSymFromAddr SymGetSymFromAddr64 +#else +BOOL +IMAGEAPI +SymGetSymFromAddr( + __in HANDLE hProcess, + __in DWORD dwAddr, + __out_opt PDWORD pdwDisplacement, + __inout PIMAGEHLP_SYMBOL Symbol + ); +#endif + +// While following two APIs will provide a symbol from a name, +// SymEnumSymbols can provide the same matching information +// for ALL symbols with a matching name, even regular +// expressions. That way you can search across modules +// and differentiate between identically named symbols. + +BOOL +IMAGEAPI +SymGetSymFromName64( + __in HANDLE hProcess, + __in PCSTR Name, + __inout PIMAGEHLP_SYMBOL64 Symbol + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetSymFromName SymGetSymFromName64 +#else +BOOL +IMAGEAPI +SymGetSymFromName( + __in HANDLE hProcess, + __in PCSTR Name, + __inout PIMAGEHLP_SYMBOL Symbol + ); +#endif + + +// Symbol server exports + +typedef BOOL (WINAPI *PSYMBOLSERVERPROC)(PCSTR, PCSTR, PVOID, DWORD, DWORD, PSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERPROCA)(PCSTR, PCSTR, PVOID, DWORD, DWORD, PSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERPROCW)(PCWSTR, PCWSTR, PVOID, DWORD, DWORD, PWSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERBYINDEXPROC)(PCSTR, PCSTR, PCSTR, PSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERBYINDEXPROCA)(PCSTR, PCSTR, PCSTR, PSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERBYINDEXPROCW)(PCWSTR, PCWSTR, PCWSTR, PWSTR); +typedef BOOL (WINAPI *PSYMBOLSERVEROPENPROC)(VOID); +typedef BOOL (WINAPI *PSYMBOLSERVERCLOSEPROC)(VOID); +typedef BOOL (WINAPI *PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR, ULONG64); +typedef BOOL (WINAPI *PSYMBOLSERVERSETOPTIONSWPROC)(UINT_PTR, ULONG64); +typedef BOOL (CALLBACK WINAPI *PSYMBOLSERVERCALLBACKPROC)(UINT_PTR action, ULONG64 data, ULONG64 context); +typedef UINT_PTR (WINAPI *PSYMBOLSERVERGETOPTIONSPROC)(); +typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROC)(PCSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROCA)(PCSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROCW)(PCWSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERGETVERSION)(LPAPI_VERSION); +typedef BOOL (WINAPI *PSYMBOLSERVERDELTANAME)(PCSTR, PVOID, DWORD, DWORD, PVOID, DWORD, DWORD, PSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERDELTANAMEW)(PCWSTR, PVOID, DWORD, DWORD, PVOID, DWORD, DWORD, PWSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERGETSUPPLEMENT)(PCSTR, PCSTR, PCSTR, PSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERGETSUPPLEMENTW)(PCWSTR, PCWSTR, PCWSTR, PWSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERSTORESUPPLEMENT)(PCSTR, PCSTR, PCSTR, PSTR, size_t, DWORD); +typedef BOOL (WINAPI *PSYMBOLSERVERSTORESUPPLEMENTW)(PCWSTR, PCWSTR, PCWSTR, PWSTR, size_t, DWORD); +typedef BOOL (WINAPI *PSYMBOLSERVERGETINDEXSTRING)(PVOID, DWORD, DWORD, PSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERGETINDEXSTRINGW)(PVOID, DWORD, DWORD, PWSTR, size_t); +typedef BOOL (WINAPI *PSYMBOLSERVERSTOREFILE)(PCSTR, PCSTR, PVOID, DWORD, DWORD, PSTR, size_t, DWORD); +typedef BOOL (WINAPI *PSYMBOLSERVERSTOREFILEW)(PCWSTR, PCWSTR, PVOID, DWORD, DWORD, PWSTR, size_t, DWORD); +typedef BOOL (WINAPI *PSYMBOLSERVERISSTORE)(PCSTR); +typedef BOOL (WINAPI *PSYMBOLSERVERISSTOREW)(PCWSTR); +typedef DWORD (WINAPI *PSYMBOLSERVERVERSION)(); +typedef BOOL (CALLBACK WINAPI *PSYMBOLSERVERMESSAGEPROC)(UINT_PTR action, ULONG64 data, ULONG64 context); + +#define SYMSRV_VERSION 2 + +#define SSRVOPT_CALLBACK 0x00000001 +#define SSRVOPT_DWORD 0x00000002 +#define SSRVOPT_DWORDPTR 0x00000004 +#define SSRVOPT_GUIDPTR 0x00000008 +#define SSRVOPT_OLDGUIDPTR 0x00000010 +#define SSRVOPT_UNATTENDED 0x00000020 +#define SSRVOPT_NOCOPY 0x00000040 +#define SSRVOPT_GETPATH 0x00000040 +#define SSRVOPT_PARENTWIN 0x00000080 +#define SSRVOPT_PARAMTYPE 0x00000100 +#define SSRVOPT_SECURE 0x00000200 +#define SSRVOPT_TRACE 0x00000400 +#define SSRVOPT_SETCONTEXT 0x00000800 +#define SSRVOPT_PROXY 0x00001000 +#define SSRVOPT_DOWNSTREAM_STORE 0x00002000 +#define SSRVOPT_OVERWRITE 0x00004000 +#define SSRVOPT_RESETTOU 0x00008000 +#define SSRVOPT_CALLBACKW 0x00010000 +#define SSRVOPT_FLAT_DEFAULT_STORE 0x00020000 +#define SSRVOPT_PROXYW 0x00040000 +#define SSRVOPT_MESSAGE 0x00080000 +#define SSRVOPT_SERVICE 0x00100000 // deprecated +#define SSRVOPT_FAVOR_COMPRESSED 0x00200000 +#define SSRVOPT_STRING 0x00400000 +#define SSRVOPT_WINHTTP 0x00800000 +#define SSRVOPT_WININET 0x01000000 + +#define SSRVOPT_MAX 0x0100000 + +#define SSRVOPT_RESET ((ULONG_PTR)-1) + + +#define NUM_SSRVOPTS 30 + +#define SSRVACTION_TRACE 1 +#define SSRVACTION_QUERYCANCEL 2 +#define SSRVACTION_EVENT 3 +#define SSRVACTION_EVENTW 4 +#define SSRVACTION_SIZE 5 + +#define SYMSTOREOPT_COMPRESS 0x01 +#define SYMSTOREOPT_OVERWRITE 0x02 +#define SYMSTOREOPT_RETURNINDEX 0x04 +#define SYMSTOREOPT_POINTER 0x08 +#define SYMSTOREOPT_ALT_INDEX 0x10 +#define SYMSTOREOPT_UNICODE 0x20 +#define SYMSTOREOPT_PASS_IF_EXISTS 0x40 + +#ifdef DBGHELP_TRANSLATE_TCHAR + #define SymInitialize SymInitializeW + #define SymAddSymbol SymAddSymbolW + #define SymDeleteSymbol SymDeleteSymbolW + #define SearchTreeForFile SearchTreeForFileW + #define UnDecorateSymbolName UnDecorateSymbolNameW + #define SymGetLineFromName64 SymGetLineFromNameW64 + #define SymGetLineFromAddr64 SymGetLineFromAddrW64 + #define SymGetLineNext64 SymGetLineNextW64 + #define SymGetLinePrev64 SymGetLinePrevW64 + #define SymFromName SymFromNameW + #define SymFindExecutableImage SymFindExecutableImageW + #define FindExecutableImageEx FindExecutableImageExW + #define SymSearch SymSearchW + #define SymEnumLines SymEnumLinesW + #define SymEnumSourceLines SymEnumSourceLinesW + #define SymGetTypeFromName SymGetTypeFromNameW + #define SymEnumSymbolsForAddr SymEnumSymbolsForAddrW + #define SymFromAddr SymFromAddrW + #define SymMatchString SymMatchStringW + #define SymEnumSourceFiles SymEnumSourceFilesW + #define SymEnumSymbols SymEnumSymbolsW + #define SymLoadModuleEx SymLoadModuleExW + #define SymSetSearchPath SymSetSearchPathW + #define SymGetSearchPath SymGetSearchPathW + #define EnumDirTree EnumDirTreeW + #define SymFromToken SymFromTokenW + #define SymFromIndex SymFromIndexW + #define SymGetScope SymGetScopeW + #define SymNext SymNextW + #define SymPrev SymPrevW + #define SymEnumTypes SymEnumTypesW + #define SymEnumTypesByName SymEnumTypesByNameW + #define SymRegisterCallback64 SymRegisterCallbackW64 + #define SymFindDebugInfoFile SymFindDebugInfoFileW + #define FindDebugInfoFileEx FindDebugInfoFileExW + #define SymFindFileInPath SymFindFileInPathW + #define SymEnumerateModules64 SymEnumerateModulesW64 + #define SymSetHomeDirectory SymSetHomeDirectoryW + #define SymGetHomeDirectory SymGetHomeDirectoryW + #define SymGetSourceFile SymGetSourceFileW + #define SymGetSourceFileToken SymGetSourceFileTokenW + #define SymGetSourceFileFromToken SymGetSourceFileFromTokenW + #define SymGetSourceVarFromToken SymGetSourceVarFromTokenW + #define SymGetSourceFileToken SymGetSourceFileTokenW + #define SymGetFileLineOffsets64 SymGetFileLineOffsetsW64 + #define SymFindFileInPath SymFindFileInPathW + #define SymMatchFileName SymMatchFileNameW + #define SymGetSourceFileFromToken SymGetSourceFileFromTokenW + #define SymGetSourceVarFromToken SymGetSourceVarFromTokenW + #define SymGetModuleInfo64 SymGetModuleInfoW64 + #define SymSrvIsStore SymSrvIsStoreW + #define SymSrvDeltaName SymSrvDeltaNameW + #define SymSrvGetSupplement SymSrvGetSupplementW + #define SymSrvStoreSupplement SymSrvStoreSupplementW + #define SymSrvGetFileIndexes SymSrvGetFileIndexes + #define SymSrvGetFileIndexString SymSrvGetFileIndexStringW + #define SymSrvStoreFile SymSrvStoreFileW + #define SymGetSymbolFile SymGetSymbolFileW + #define EnumerateLoadedModules64 EnumerateLoadedModulesW64 + #define EnumerateLoadedModulesEx EnumerateLoadedModulesExW + #define SymSrvGetFileIndexInfo SymSrvGetFileIndexInfoW + + #define IMAGEHLP_LINE64 IMAGEHLP_LINEW64 + #define PIMAGEHLP_LINE64 PIMAGEHLP_LINEW64 + #define SYMBOL_INFO SYMBOL_INFOW + #define PSYMBOL_INFO PSYMBOL_INFOW + #define SYMBOL_INFO_PACKAGE SYMBOL_INFO_PACKAGEW + #define PSYMBOL_INFO_PACKAGE PSYMBOL_INFO_PACKAGEW + #define FIND_EXE_FILE_CALLBACK FIND_EXE_FILE_CALLBACKW + #define PFIND_EXE_FILE_CALLBACK PFIND_EXE_FILE_CALLBACKW + #define SYM_ENUMERATESYMBOLS_CALLBACK SYM_ENUMERATESYMBOLS_CALLBACKW + #define PSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACKW + #define SRCCODEINFO SRCCODEINFOW + #define PSRCCODEINFO PSRCCODEINFOW + #define SOURCEFILE SOURCEFILEW + #define PSOURCEFILE PSOURCEFILEW + #define SYM_ENUMSOURECFILES_CALLBACK SYM_ENUMSOURCEFILES_CALLBACKW + #define PSYM_ENUMSOURCEFILES_CALLBACK PSYM_ENUMSOURECFILES_CALLBACKW + #define IMAGEHLP_CBA_EVENT IMAGEHLP_CBA_EVENTW + #define PIMAGEHLP_CBA_EVENT PIMAGEHLP_CBA_EVENTW + #define PENUMDIRTREE_CALLBACK PENUMDIRTREE_CALLBACKW + #define IMAGEHLP_DEFERRED_SYMBOL_LOAD64 IMAGEHLP_DEFERRED_SYMBOL_LOADW64 + #define PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 PIMAGEHLP_DEFERRED_SYMBOL_LOADW64 + #define PFIND_DEBUG_FILE_CALLBACK PFIND_DEBUG_FILE_CALLBACKW + #define PFINDFILEINPATHCALLBACK PFINDFILEINPATHCALLBACKW + #define IMAGEHLP_MODULE64 IMAGEHLP_MODULEW64 + #define PIMAGEHLP_MODULE64 PIMAGEHLP_MODULEW64 + #define SYMSRV_INDEX_INFO SYMSRV_INDEX_INFOW + #define PSYMSRV_INDEX_INFO PSYMSRV_INDEX_INFOW + + #define PSYMBOLSERVERPROC PSYMBOLSERVERPROCW + #define PSYMBOLSERVERPINGPROC PSYMBOLSERVERPINGPROCW +#endif + +// ----------------------------------------------------------------- +// The following APIs exist only for backwards compatibility +// with a pre-release version documented in an MSDN release. + +// You should use SymFindFileInPath if you want to maintain +// future compatibility. + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +FindFileInPath( + __in HANDLE hprocess, + __in PCSTR SearchPath, + __in PCSTR FileName, + __in PVOID id, + __in DWORD two, + __in DWORD three, + __in DWORD flags, + __out_ecount(MAX_PATH + 1) PSTR FilePath + ); + +// You should use SymFindFileInPath if you want to maintain +// future compatibility. + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +FindFileInSearchPath( + __in HANDLE hprocess, + __in PCSTR SearchPath, + __in PCSTR FileName, + __in DWORD one, + __in DWORD two, + __in DWORD three, + __out_ecount(MAX_PATH + 1) PSTR FilePath + ); + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumSym( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumerateSymbols64( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumerateSymbolsW64( + __in HANDLE hProcess, + __in ULONG64 BaseOfDll, + __in PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymEnumerateSymbols SymEnumerateSymbols64 +#define SymEnumerateSymbolsW SymEnumerateSymbolsW64 +#else +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumerateSymbols( + __in HANDLE hProcess, + __in ULONG BaseOfDll, + __in PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, + __in_opt PVOID UserContext + ); + +DBHLP_DEPRECIATED +BOOL +IMAGEAPI +SymEnumerateSymbolsW( + __in HANDLE hProcess, + __in ULONG BaseOfDll, + __in PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback, + __in_opt PVOID UserContext + ); +#endif + +// use SymLoadModuleEx + +DWORD64 +IMAGEAPI +SymLoadModule64( + __in HANDLE hProcess, + __in_opt HANDLE hFile, + __in_opt PCSTR ImageName, + __in_opt PCSTR ModuleName, + __in DWORD64 BaseOfDll, + __in DWORD SizeOfDll + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymLoadModule SymLoadModule64 +#else +DWORD +IMAGEAPI +SymLoadModule( + __in HANDLE hProcess, + __in_opt HANDLE hFile, + __in_opt PCSTR ImageName, + __in_opt PCSTR ModuleName, + __in DWORD BaseOfDll, + __in DWORD SizeOfDll + ); +#endif + +BOOL +IMAGEAPI +SymGetSymNext64( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOL64 Symbol + ); + +BOOL +IMAGEAPI +SymGetSymNextW64( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOLW64 Symbol + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetSymNext SymGetSymNext64 +#define SymGetSymNextW SymGetSymNextW64 +#else +BOOL +IMAGEAPI +SymGetSymNext( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOL Symbol + ); + +BOOL +IMAGEAPI +SymGetSymNextW( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOLW Symbol + ); +#endif + +BOOL +IMAGEAPI +SymGetSymPrev64( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOL64 Symbol + ); + +BOOL +IMAGEAPI +SymGetSymPrevW64( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOLW64 Symbol + ); + +#if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) +#define SymGetSymPrev SymGetSymPrev64 +#define SymGetSymPrevW SymGetSymPrevW64 +#else +BOOL +IMAGEAPI +SymGetSymPrev( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOL Symbol + ); + +BOOL +IMAGEAPI +SymGetSymPrevW( + __in HANDLE hProcess, + __inout PIMAGEHLP_SYMBOLW Symbol + ); +#endif + + +// These values should not be used. +// They have been replaced by SYMFLAG_ values. + +#define SYMF_OMAP_GENERATED 0x00000001 +#define SYMF_OMAP_MODIFIED 0x00000002 +#define SYMF_REGISTER 0x00000008 +#define SYMF_REGREL 0x00000010 +#define SYMF_FRAMEREL 0x00000020 +#define SYMF_PARAMETER 0x00000040 +#define SYMF_LOCAL 0x00000080 +#define SYMF_CONSTANT 0x00000100 +#define SYMF_EXPORT 0x00000200 +#define SYMF_FORWARDER 0x00000400 +#define SYMF_FUNCTION 0x00000800 +#define SYMF_VIRTUAL 0x00001000 +#define SYMF_THUNK 0x00002000 +#define SYMF_TLSREL 0x00004000 + +// These values should also not be used. +// They have been replaced by SYMFLAG_ values. + +#define IMAGEHLP_SYMBOL_INFO_VALUEPRESENT 1 +#define IMAGEHLP_SYMBOL_INFO_REGISTER SYMF_REGISTER // 0x0008 +#define IMAGEHLP_SYMBOL_INFO_REGRELATIVE SYMF_REGREL // 0x0010 +#define IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE SYMF_FRAMEREL // 0x0020 +#define IMAGEHLP_SYMBOL_INFO_PARAMETER SYMF_PARAMETER // 0x0040 +#define IMAGEHLP_SYMBOL_INFO_LOCAL SYMF_LOCAL // 0x0080 +#define IMAGEHLP_SYMBOL_INFO_CONSTANT SYMF_CONSTANT // 0x0100 +#define IMAGEHLP_SYMBOL_FUNCTION SYMF_FUNCTION // 0x0800 +#define IMAGEHLP_SYMBOL_VIRTUAL SYMF_VIRTUAL // 0x1000 +#define IMAGEHLP_SYMBOL_THUNK SYMF_THUNK // 0x2000 +#define IMAGEHLP_SYMBOL_INFO_TLSRELATIVE SYMF_TLSREL // 0x4000 + + +#include + +#if defined(_MSC_VER) +#if _MSC_VER >= 800 +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4200) /* Zero length array */ +#pragma warning(disable:4201) /* Nameless struct/union */ +#endif +#endif + +#define MINIDUMP_SIGNATURE ('PMDM') +#define MINIDUMP_VERSION (42899) +typedef DWORD RVA; +typedef ULONG64 RVA64; + +typedef struct _MINIDUMP_LOCATION_DESCRIPTOR { + ULONG32 DataSize; + RVA Rva; +} MINIDUMP_LOCATION_DESCRIPTOR; + +typedef struct _MINIDUMP_LOCATION_DESCRIPTOR64 { + ULONG64 DataSize; + RVA64 Rva; +} MINIDUMP_LOCATION_DESCRIPTOR64; + + +typedef struct _MINIDUMP_MEMORY_DESCRIPTOR { + ULONG64 StartOfMemoryRange; + MINIDUMP_LOCATION_DESCRIPTOR Memory; +} MINIDUMP_MEMORY_DESCRIPTOR, *PMINIDUMP_MEMORY_DESCRIPTOR; + +// DESCRIPTOR64 is used for full-memory minidumps where +// all of the raw memory is laid out sequentially at the +// end of the dump. There is no need for individual RVAs +// as the RVA is the base RVA plus the sum of the preceeding +// data blocks. +typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64 { + ULONG64 StartOfMemoryRange; + ULONG64 DataSize; +} MINIDUMP_MEMORY_DESCRIPTOR64, *PMINIDUMP_MEMORY_DESCRIPTOR64; + + +typedef struct _MINIDUMP_HEADER { + ULONG32 Signature; + ULONG32 Version; + ULONG32 NumberOfStreams; + RVA StreamDirectoryRva; + ULONG32 CheckSum; + union { + ULONG32 Reserved; + ULONG32 TimeDateStamp; + }; + ULONG64 Flags; +} MINIDUMP_HEADER, *PMINIDUMP_HEADER; + +// +// The MINIDUMP_HEADER field StreamDirectoryRva points to +// an array of MINIDUMP_DIRECTORY structures. +// + +typedef struct _MINIDUMP_DIRECTORY { + ULONG32 StreamType; + MINIDUMP_LOCATION_DESCRIPTOR Location; +} MINIDUMP_DIRECTORY, *PMINIDUMP_DIRECTORY; + + +typedef struct _MINIDUMP_STRING { + ULONG32 Length; // Length in bytes of the string + WCHAR Buffer [0]; // Variable size buffer +} MINIDUMP_STRING, *PMINIDUMP_STRING; + + + +// +// The MINIDUMP_DIRECTORY field StreamType may be one of the following types. +// Types will be added in the future, so if a program reading the minidump +// header encounters a stream type it does not understand it should ignore +// the data altogether. Any tag above LastReservedStream will not be used by +// the system and is reserved for program-specific information. +// + +typedef enum _MINIDUMP_STREAM_TYPE { + + UnusedStream = 0, + ReservedStream0 = 1, + ReservedStream1 = 2, + ThreadListStream = 3, + ModuleListStream = 4, + MemoryListStream = 5, + ExceptionStream = 6, + SystemInfoStream = 7, + ThreadExListStream = 8, + Memory64ListStream = 9, + CommentStreamA = 10, + CommentStreamW = 11, + HandleDataStream = 12, + FunctionTableStream = 13, + UnloadedModuleListStream = 14, + MiscInfoStream = 15, + MemoryInfoListStream = 16, + ThreadInfoListStream = 17, + HandleOperationListStream = 18, + + ceStreamNull = 0x8000, + ceStreamSystemInfo = 0x8001, + ceStreamException = 0x8002, + ceStreamModuleList = 0x8003, + ceStreamProcessList = 0x8004, + ceStreamThreadList = 0x8005, + ceStreamThreadContextList = 0x8006, + ceStreamThreadCallStackList = 0x8007, + ceStreamMemoryVirtualList = 0x8008, + ceStreamMemoryPhysicalList = 0x8009, + ceStreamBucketParameters = 0x800A, + + LastReservedStream = 0xffff + +} MINIDUMP_STREAM_TYPE; + + +// +// The minidump system information contains processor and +// Operating System specific information. +// + +// +// CPU information is obtained from one of two places. +// +// 1) On x86 computers, CPU_INFORMATION is obtained from the CPUID +// instruction. You must use the X86 portion of the union for X86 +// computers. +// +// 2) On non-x86 architectures, CPU_INFORMATION is obtained by calling +// IsProcessorFeatureSupported(). +// + +typedef union _CPU_INFORMATION { + + // + // X86 platforms use CPUID function to obtain processor information. + // + + struct { + + // + // CPUID Subfunction 0, register EAX (VendorId [0]), + // EBX (VendorId [1]) and ECX (VendorId [2]). + // + + ULONG32 VendorId [ 3 ]; + + // + // CPUID Subfunction 1, register EAX + // + + ULONG32 VersionInformation; + + // + // CPUID Subfunction 1, register EDX + // + + ULONG32 FeatureInformation; + + + // + // CPUID, Subfunction 80000001, register EBX. This will only + // be obtained if the vendor id is "AuthenticAMD". + // + + ULONG32 AMDExtendedCpuFeatures; + + } X86CpuInfo; + + // + // Non-x86 platforms use processor feature flags. + // + + struct { + + ULONG64 ProcessorFeatures [ 2 ]; + + } OtherCpuInfo; + +} CPU_INFORMATION, *PCPU_INFORMATION; + +typedef struct _MINIDUMP_SYSTEM_INFO { + + // + // ProcessorArchitecture, ProcessorLevel and ProcessorRevision are all + // taken from the SYSTEM_INFO structure obtained by GetSystemInfo( ). + // + + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + + union { + USHORT Reserved0; + struct { + UCHAR NumberOfProcessors; + UCHAR ProductType; + }; + }; + + // + // MajorVersion, MinorVersion, BuildNumber, PlatformId and + // CSDVersion are all taken from the OSVERSIONINFO structure + // returned by GetVersionEx( ). + // + + ULONG32 MajorVersion; + ULONG32 MinorVersion; + ULONG32 BuildNumber; + ULONG32 PlatformId; + + // + // RVA to a CSDVersion string in the string table. + // + + RVA CSDVersionRva; + + union { + ULONG32 Reserved1; + struct { + USHORT SuiteMask; + USHORT Reserved2; + }; + }; + + CPU_INFORMATION Cpu; + +} MINIDUMP_SYSTEM_INFO, *PMINIDUMP_SYSTEM_INFO; + + +// +// The minidump thread contains standard thread +// information plus an RVA to the memory for this +// thread and an RVA to the CONTEXT structure for +// this thread. +// + + +// +// ThreadId must be 4 bytes on all architectures. +// + +C_ASSERT (sizeof ( ((PPROCESS_INFORMATION)0)->dwThreadId ) == 4); + +typedef struct _MINIDUMP_THREAD { + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; +} MINIDUMP_THREAD, *PMINIDUMP_THREAD; + +// +// The thread list is a container of threads. +// + +typedef struct _MINIDUMP_THREAD_LIST { + ULONG32 NumberOfThreads; + MINIDUMP_THREAD Threads [0]; +} MINIDUMP_THREAD_LIST, *PMINIDUMP_THREAD_LIST; + + +typedef struct _MINIDUMP_THREAD_EX { + ULONG32 ThreadId; + ULONG32 SuspendCount; + ULONG32 PriorityClass; + ULONG32 Priority; + ULONG64 Teb; + MINIDUMP_MEMORY_DESCRIPTOR Stack; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; + MINIDUMP_MEMORY_DESCRIPTOR BackingStore; +} MINIDUMP_THREAD_EX, *PMINIDUMP_THREAD_EX; + +// +// The thread list is a container of threads. +// + +typedef struct _MINIDUMP_THREAD_EX_LIST { + ULONG32 NumberOfThreads; + MINIDUMP_THREAD_EX Threads [0]; +} MINIDUMP_THREAD_EX_LIST, *PMINIDUMP_THREAD_EX_LIST; + + +// +// The MINIDUMP_EXCEPTION is the same as EXCEPTION on Win64. +// + +typedef struct _MINIDUMP_EXCEPTION { + ULONG32 ExceptionCode; + ULONG32 ExceptionFlags; + ULONG64 ExceptionRecord; + ULONG64 ExceptionAddress; + ULONG32 NumberParameters; + ULONG32 __unusedAlignment; + ULONG64 ExceptionInformation [ EXCEPTION_MAXIMUM_PARAMETERS ]; +} MINIDUMP_EXCEPTION, *PMINIDUMP_EXCEPTION; + + +// +// The exception information stream contains the id of the thread that caused +// the exception (ThreadId), the exception record for the exception +// (ExceptionRecord) and an RVA to the thread context where the exception +// occured. +// + +typedef struct MINIDUMP_EXCEPTION_STREAM { + ULONG32 ThreadId; + ULONG32 __alignment; + MINIDUMP_EXCEPTION ExceptionRecord; + MINIDUMP_LOCATION_DESCRIPTOR ThreadContext; +} MINIDUMP_EXCEPTION_STREAM, *PMINIDUMP_EXCEPTION_STREAM; + + +// +// The MINIDUMP_MODULE contains information about a +// a specific module. It includes the CheckSum and +// the TimeDateStamp for the module so the module +// can be reloaded during the analysis phase. +// + +typedef struct _MINIDUMP_MODULE { + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; + VS_FIXEDFILEINFO VersionInfo; + MINIDUMP_LOCATION_DESCRIPTOR CvRecord; + MINIDUMP_LOCATION_DESCRIPTOR MiscRecord; + ULONG64 Reserved0; // Reserved for future use. + ULONG64 Reserved1; // Reserved for future use. +} MINIDUMP_MODULE, *PMINIDUMP_MODULE; + + +// +// The minidump module list is a container for modules. +// + +typedef struct _MINIDUMP_MODULE_LIST { + ULONG32 NumberOfModules; + MINIDUMP_MODULE Modules [ 0 ]; +} MINIDUMP_MODULE_LIST, *PMINIDUMP_MODULE_LIST; + + +// +// Memory Ranges +// + +typedef struct _MINIDUMP_MEMORY_LIST { + ULONG32 NumberOfMemoryRanges; + MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges [0]; +} MINIDUMP_MEMORY_LIST, *PMINIDUMP_MEMORY_LIST; + +typedef struct _MINIDUMP_MEMORY64_LIST { + ULONG64 NumberOfMemoryRanges; + RVA64 BaseRva; + MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges [0]; +} MINIDUMP_MEMORY64_LIST, *PMINIDUMP_MEMORY64_LIST; + + +// +// Support for user supplied exception information. +// + +typedef struct _MINIDUMP_EXCEPTION_INFORMATION { + DWORD ThreadId; + PEXCEPTION_POINTERS ExceptionPointers; + BOOL ClientPointers; +} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; + +typedef struct _MINIDUMP_EXCEPTION_INFORMATION64 { + DWORD ThreadId; + ULONG64 ExceptionRecord; + ULONG64 ContextRecord; + BOOL ClientPointers; +} MINIDUMP_EXCEPTION_INFORMATION64, *PMINIDUMP_EXCEPTION_INFORMATION64; + + +// +// Support for capturing system handle state at the time of the dump. +// + +// Per-handle object information varies according to +// the OS, the OS version, the processor type and +// so on. The minidump gives a minidump identifier +// to each possible data format for identification +// purposes but does not control nor describe the actual data. +typedef enum _MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE { + MiniHandleObjectInformationNone, + MiniThreadInformation1, + MiniMutantInformation1, + MiniMutantInformation2, + MiniProcessInformation1, + MiniProcessInformation2, + MiniHandleObjectInformationTypeMax +} MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE; + +typedef struct _MINIDUMP_HANDLE_OBJECT_INFORMATION { + RVA NextInfoRva; + ULONG32 InfoType; + ULONG32 SizeOfInfo; + // Raw information follows. +} MINIDUMP_HANDLE_OBJECT_INFORMATION; + +typedef struct _MINIDUMP_HANDLE_DESCRIPTOR { + ULONG64 Handle; + RVA TypeNameRva; + RVA ObjectNameRva; + ULONG32 Attributes; + ULONG32 GrantedAccess; + ULONG32 HandleCount; + ULONG32 PointerCount; +} MINIDUMP_HANDLE_DESCRIPTOR, *PMINIDUMP_HANDLE_DESCRIPTOR; + +typedef struct _MINIDUMP_HANDLE_DESCRIPTOR_2 { + ULONG64 Handle; + RVA TypeNameRva; + RVA ObjectNameRva; + ULONG32 Attributes; + ULONG32 GrantedAccess; + ULONG32 HandleCount; + ULONG32 PointerCount; + RVA ObjectInfoRva; + ULONG32 Reserved0; +} MINIDUMP_HANDLE_DESCRIPTOR_2, *PMINIDUMP_HANDLE_DESCRIPTOR_2; + +// The latest MINIDUMP_HANDLE_DESCRIPTOR definition. +typedef MINIDUMP_HANDLE_DESCRIPTOR_2 MINIDUMP_HANDLE_DESCRIPTOR_N; +typedef MINIDUMP_HANDLE_DESCRIPTOR_N *PMINIDUMP_HANDLE_DESCRIPTOR_N; + +typedef struct _MINIDUMP_HANDLE_DATA_STREAM { + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 NumberOfDescriptors; + ULONG32 Reserved; +} MINIDUMP_HANDLE_DATA_STREAM, *PMINIDUMP_HANDLE_DATA_STREAM; + +// Some operating systems can track the last operations +// performed on a handle. For example, Application Verifier +// can enable this for some versions of Windows. The +// handle operation list collects handle operations +// known for the dump target. +// Each entry is an AVRF_HANDLE_OPERATION. +typedef struct _MINIDUMP_HANDLE_OPERATION_LIST { + ULONG32 SizeOfHeader; + ULONG32 SizeOfEntry; + ULONG32 NumberOfEntries; + ULONG32 Reserved; +} MINIDUMP_HANDLE_OPERATION_LIST, *PMINIDUMP_HANDLE_OPERATION_LIST; + + +// +// Support for capturing dynamic function table state at the time of the dump. +// + +typedef struct _MINIDUMP_FUNCTION_TABLE_DESCRIPTOR { + ULONG64 MinimumAddress; + ULONG64 MaximumAddress; + ULONG64 BaseAddress; + ULONG32 EntryCount; + ULONG32 SizeOfAlignPad; +} MINIDUMP_FUNCTION_TABLE_DESCRIPTOR, *PMINIDUMP_FUNCTION_TABLE_DESCRIPTOR; + +typedef struct _MINIDUMP_FUNCTION_TABLE_STREAM { + ULONG32 SizeOfHeader; + ULONG32 SizeOfDescriptor; + ULONG32 SizeOfNativeDescriptor; + ULONG32 SizeOfFunctionEntry; + ULONG32 NumberOfDescriptors; + ULONG32 SizeOfAlignPad; +} MINIDUMP_FUNCTION_TABLE_STREAM, *PMINIDUMP_FUNCTION_TABLE_STREAM; + + +// +// The MINIDUMP_UNLOADED_MODULE contains information about a +// a specific module that was previously loaded but no +// longer is. This can help with diagnosing problems where +// callers attempt to call code that is no longer loaded. +// + +typedef struct _MINIDUMP_UNLOADED_MODULE { + ULONG64 BaseOfImage; + ULONG32 SizeOfImage; + ULONG32 CheckSum; + ULONG32 TimeDateStamp; + RVA ModuleNameRva; +} MINIDUMP_UNLOADED_MODULE, *PMINIDUMP_UNLOADED_MODULE; + + +// +// The minidump unloaded module list is a container for unloaded modules. +// + +typedef struct _MINIDUMP_UNLOADED_MODULE_LIST { + ULONG32 SizeOfHeader; + ULONG32 SizeOfEntry; + ULONG32 NumberOfEntries; +} MINIDUMP_UNLOADED_MODULE_LIST, *PMINIDUMP_UNLOADED_MODULE_LIST; + + +// +// The miscellaneous information stream contains a variety +// of small pieces of information. A member is valid if +// it's within the available size and its corresponding +// bit is set. +// + +#define MINIDUMP_MISC1_PROCESS_ID 0x00000001 +#define MINIDUMP_MISC1_PROCESS_TIMES 0x00000002 +#define MINIDUMP_MISC1_PROCESSOR_POWER_INFO 0x00000004 + +typedef struct _MINIDUMP_MISC_INFO { + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; +} MINIDUMP_MISC_INFO, *PMINIDUMP_MISC_INFO; + +typedef struct _MINIDUMP_MISC_INFO_2 { + ULONG32 SizeOfInfo; + ULONG32 Flags1; + ULONG32 ProcessId; + ULONG32 ProcessCreateTime; + ULONG32 ProcessUserTime; + ULONG32 ProcessKernelTime; + ULONG32 ProcessorMaxMhz; + ULONG32 ProcessorCurrentMhz; + ULONG32 ProcessorMhzLimit; + ULONG32 ProcessorMaxIdleState; + ULONG32 ProcessorCurrentIdleState; +} MINIDUMP_MISC_INFO_2, *PMINIDUMP_MISC_INFO_2; + +// The latest MINIDUMP_MISC_INFO definition. +typedef MINIDUMP_MISC_INFO_2 MINIDUMP_MISC_INFO_N; +typedef MINIDUMP_MISC_INFO_N* PMINIDUMP_MISC_INFO_N; + + +// +// The memory information stream contains memory region +// description information. This stream corresponds to +// what VirtualQuery would return for the process the +// dump was created for. +// + +typedef struct _MINIDUMP_MEMORY_INFO { + ULONG64 BaseAddress; + ULONG64 AllocationBase; + ULONG32 AllocationProtect; + ULONG32 __alignment1; + ULONG64 RegionSize; + ULONG32 State; + ULONG32 Protect; + ULONG32 Type; + ULONG32 __alignment2; +} MINIDUMP_MEMORY_INFO, *PMINIDUMP_MEMORY_INFO; + +typedef struct _MINIDUMP_MEMORY_INFO_LIST { + ULONG SizeOfHeader; + ULONG SizeOfEntry; + ULONG64 NumberOfEntries; +} MINIDUMP_MEMORY_INFO_LIST, *PMINIDUMP_MEMORY_INFO_LIST; + + +// +// The memory information stream contains memory region +// description information. This stream corresponds to +// what VirtualQuery would return for the process the +// dump was created for. +// + +// Thread dump writer status flags. +#define MINIDUMP_THREAD_INFO_ERROR_THREAD 0x00000001 +#define MINIDUMP_THREAD_INFO_WRITING_THREAD 0x00000002 +#define MINIDUMP_THREAD_INFO_EXITED_THREAD 0x00000004 +#define MINIDUMP_THREAD_INFO_INVALID_INFO 0x00000008 +#define MINIDUMP_THREAD_INFO_INVALID_CONTEXT 0x00000010 +#define MINIDUMP_THREAD_INFO_INVALID_TEB 0x00000020 + +typedef struct _MINIDUMP_THREAD_INFO { + ULONG32 ThreadId; + ULONG32 DumpFlags; + ULONG32 DumpError; + ULONG32 ExitStatus; + ULONG64 CreateTime; + ULONG64 ExitTime; + ULONG64 KernelTime; + ULONG64 UserTime; + ULONG64 StartAddress; + ULONG64 Affinity; +} MINIDUMP_THREAD_INFO, *PMINIDUMP_THREAD_INFO; + +typedef struct _MINIDUMP_THREAD_INFO_LIST { + ULONG SizeOfHeader; + ULONG SizeOfEntry; + ULONG NumberOfEntries; +} MINIDUMP_THREAD_INFO_LIST, *PMINIDUMP_THREAD_INFO_LIST; + + +// +// Support for arbitrary user-defined information. +// + +typedef struct _MINIDUMP_USER_RECORD { + ULONG32 Type; + MINIDUMP_LOCATION_DESCRIPTOR Memory; +} MINIDUMP_USER_RECORD, *PMINIDUMP_USER_RECORD; + + +typedef struct _MINIDUMP_USER_STREAM { + ULONG32 Type; + ULONG BufferSize; + PVOID Buffer; + +} MINIDUMP_USER_STREAM, *PMINIDUMP_USER_STREAM; + + +typedef struct _MINIDUMP_USER_STREAM_INFORMATION { + ULONG UserStreamCount; + PMINIDUMP_USER_STREAM UserStreamArray; +} MINIDUMP_USER_STREAM_INFORMATION, *PMINIDUMP_USER_STREAM_INFORMATION; + +// +// Callback support. +// + +typedef enum _MINIDUMP_CALLBACK_TYPE { + ModuleCallback, + ThreadCallback, + ThreadExCallback, + IncludeThreadCallback, + IncludeModuleCallback, + MemoryCallback, + CancelCallback, + WriteKernelMinidumpCallback, + KernelMinidumpStatusCallback, + RemoveMemoryCallback, + IncludeVmRegionCallback, + IoStartCallback, + IoWriteAllCallback, + IoFinishCallback, + ReadMemoryFailureCallback, + SecondaryFlagsCallback, +} MINIDUMP_CALLBACK_TYPE; + + +typedef struct _MINIDUMP_THREAD_CALLBACK { + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; +} MINIDUMP_THREAD_CALLBACK, *PMINIDUMP_THREAD_CALLBACK; + + +typedef struct _MINIDUMP_THREAD_EX_CALLBACK { + ULONG ThreadId; + HANDLE ThreadHandle; + CONTEXT Context; + ULONG SizeOfContext; + ULONG64 StackBase; + ULONG64 StackEnd; + ULONG64 BackingStoreBase; + ULONG64 BackingStoreEnd; +} MINIDUMP_THREAD_EX_CALLBACK, *PMINIDUMP_THREAD_EX_CALLBACK; + + +typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK { + ULONG ThreadId; +} MINIDUMP_INCLUDE_THREAD_CALLBACK, *PMINIDUMP_INCLUDE_THREAD_CALLBACK; + + +typedef enum _THREAD_WRITE_FLAGS { + ThreadWriteThread = 0x0001, + ThreadWriteStack = 0x0002, + ThreadWriteContext = 0x0004, + ThreadWriteBackingStore = 0x0008, + ThreadWriteInstructionWindow = 0x0010, + ThreadWriteThreadData = 0x0020, + ThreadWriteThreadInfo = 0x0040, +} THREAD_WRITE_FLAGS; + +typedef struct _MINIDUMP_MODULE_CALLBACK { + PWCHAR FullPath; + ULONG64 BaseOfImage; + ULONG SizeOfImage; + ULONG CheckSum; + ULONG TimeDateStamp; + VS_FIXEDFILEINFO VersionInfo; + PVOID CvRecord; + ULONG SizeOfCvRecord; + PVOID MiscRecord; + ULONG SizeOfMiscRecord; +} MINIDUMP_MODULE_CALLBACK, *PMINIDUMP_MODULE_CALLBACK; + + +typedef struct _MINIDUMP_INCLUDE_MODULE_CALLBACK { + ULONG64 BaseOfImage; +} MINIDUMP_INCLUDE_MODULE_CALLBACK, *PMINIDUMP_INCLUDE_MODULE_CALLBACK; + + +typedef enum _MODULE_WRITE_FLAGS { + ModuleWriteModule = 0x0001, + ModuleWriteDataSeg = 0x0002, + ModuleWriteMiscRecord = 0x0004, + ModuleWriteCvRecord = 0x0008, + ModuleReferencedByMemory = 0x0010, + ModuleWriteTlsData = 0x0020, + ModuleWriteCodeSegs = 0x0040, +} MODULE_WRITE_FLAGS; + + +typedef struct _MINIDUMP_IO_CALLBACK { + HANDLE Handle; + ULONG64 Offset; + PVOID Buffer; + ULONG BufferBytes; +} MINIDUMP_IO_CALLBACK, *PMINIDUMP_IO_CALLBACK; + + +typedef struct _MINIDUMP_READ_MEMORY_FAILURE_CALLBACK +{ + ULONG64 Offset; + ULONG Bytes; + HRESULT FailureStatus; +} MINIDUMP_READ_MEMORY_FAILURE_CALLBACK, + *PMINIDUMP_READ_MEMORY_FAILURE_CALLBACK; + + +typedef struct _MINIDUMP_CALLBACK_INPUT { + ULONG ProcessId; + HANDLE ProcessHandle; + ULONG CallbackType; + union { + HRESULT Status; + MINIDUMP_THREAD_CALLBACK Thread; + MINIDUMP_THREAD_EX_CALLBACK ThreadEx; + MINIDUMP_MODULE_CALLBACK Module; + MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread; + MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule; + MINIDUMP_IO_CALLBACK Io; + MINIDUMP_READ_MEMORY_FAILURE_CALLBACK ReadMemoryFailure; + ULONG SecondaryFlags; + }; +} MINIDUMP_CALLBACK_INPUT, *PMINIDUMP_CALLBACK_INPUT; + +typedef struct _MINIDUMP_CALLBACK_OUTPUT { + union { + ULONG ModuleWriteFlags; + ULONG ThreadWriteFlags; + ULONG SecondaryFlags; + struct { + ULONG64 MemoryBase; + ULONG MemorySize; + }; + struct { + BOOL CheckCancel; + BOOL Cancel; + }; + HANDLE Handle; + struct { + MINIDUMP_MEMORY_INFO VmRegion; + BOOL Continue; + }; + HRESULT Status; + }; +} MINIDUMP_CALLBACK_OUTPUT, *PMINIDUMP_CALLBACK_OUTPUT; + + +// +// A normal minidump contains just the information +// necessary to capture stack traces for all of the +// existing threads in a process. +// +// A minidump with data segments includes all of the data +// sections from loaded modules in order to capture +// global variable contents. This can make the dump much +// larger if many modules have global data. +// +// A minidump with full memory includes all of the accessible +// memory in the process and can be very large. A minidump +// with full memory always has the raw memory data at the end +// of the dump so that the initial structures in the dump can +// be mapped directly without having to include the raw +// memory information. +// +// Stack and backing store memory can be filtered to remove +// data unnecessary for stack walking. This can improve +// compression of stacks and also deletes data that may +// be private and should not be stored in a dump. +// Memory can also be scanned to see what modules are +// referenced by stack and backing store memory to allow +// omission of other modules to reduce dump size. +// In either of these modes the ModuleReferencedByMemory flag +// is set for all modules referenced before the base +// module callbacks occur. +// +// On some operating systems a list of modules that were +// recently unloaded is kept in addition to the currently +// loaded module list. This information can be saved in +// the dump if desired. +// +// Stack and backing store memory can be scanned for referenced +// pages in order to pick up data referenced by locals or other +// stack memory. This can increase the size of a dump significantly. +// +// Module paths may contain undesired information such as user names +// or other important directory names so they can be stripped. This +// option reduces the ability to locate the proper image later +// and should only be used in certain situations. +// +// Complete operating system per-process and per-thread information can +// be gathered and stored in the dump. +// +// The virtual address space can be scanned for various types +// of memory to be included in the dump. +// +// Code which is concerned with potentially private information +// getting into the minidump can set a flag that automatically +// modifies all existing and future flags to avoid placing +// unnecessary data in the dump. Basic data, such as stack +// information, will still be included but optional data, such +// as indirect memory, will not. +// +// When doing a full memory dump it's possible to store all +// of the enumerated memory region descriptive information +// in a memory information stream. +// +// Additional thread information beyond the basic thread +// structure can be collected if desired. +// +// A minidump with code segments includes all of the code +// and code-related sections from loaded modules in order +// to capture executable content. +// +// MiniDumpWithoutAuxiliaryState turns off any secondary, +// auxiliary-supported memory gathering. +// +// MiniDumpWithFullAuxiliaryState asks any present auxiliary +// data providers to include all of their state in the dump. +// The exact set of what is provided depends on the auxiliary. +// This can be quite large. +// + +typedef enum _MINIDUMP_TYPE { + MiniDumpNormal = 0x00000000, + MiniDumpWithDataSegs = 0x00000001, + MiniDumpWithFullMemory = 0x00000002, + MiniDumpWithHandleData = 0x00000004, + MiniDumpFilterMemory = 0x00000008, + MiniDumpScanMemory = 0x00000010, + MiniDumpWithUnloadedModules = 0x00000020, + MiniDumpWithIndirectlyReferencedMemory = 0x00000040, + MiniDumpFilterModulePaths = 0x00000080, + MiniDumpWithProcessThreadData = 0x00000100, + MiniDumpWithPrivateReadWriteMemory = 0x00000200, + MiniDumpWithoutOptionalData = 0x00000400, + MiniDumpWithFullMemoryInfo = 0x00000800, + MiniDumpWithThreadInfo = 0x00001000, + MiniDumpWithCodeSegs = 0x00002000, + MiniDumpWithoutAuxiliaryState = 0x00004000, + MiniDumpWithFullAuxiliaryState = 0x00008000, + + MiniDumpValidTypeFlags = 0x0000ffff, +} MINIDUMP_TYPE; + +// +// In addition to the primary flags provided to +// MiniDumpWriteDump there are additional, less +// frequently used options queried via the secondary +// flags callback. +// +// MiniSecondaryWithoutPowerInfo suppresses the minidump +// query that retrieves processor power information for +// MINIDUMP_MISC_INFO. +// + +typedef enum _MINIDUMP_SECONDARY_FLAGS { + MiniSecondaryWithoutPowerInfo = 0x00000001, + + MiniSecondaryValidFlags = 0x00000001, +} MINIDUMP_SECONDARY_FLAGS; + + +// +// The minidump callback should modify the FieldsToWrite parameter to reflect +// what portions of the specified thread or module should be written to the +// file. +// + +typedef +BOOL +(WINAPI * MINIDUMP_CALLBACK_ROUTINE) ( + IN PVOID CallbackParam, + IN CONST PMINIDUMP_CALLBACK_INPUT CallbackInput, + IN OUT PMINIDUMP_CALLBACK_OUTPUT CallbackOutput + ); + +typedef struct _MINIDUMP_CALLBACK_INFORMATION { + MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; + PVOID CallbackParam; +} MINIDUMP_CALLBACK_INFORMATION, *PMINIDUMP_CALLBACK_INFORMATION; + + + +//++ +// +// PVOID +// RVA_TO_ADDR( +// PVOID Mapping, +// ULONG Rva +// ) +// +// Routine Description: +// +// Map an RVA that is contained within a mapped file to it's associated +// flat address. +// +// Arguments: +// +// Mapping - Base address of mapped file containing the RVA. +// +// Rva - An Rva to fixup. +// +// Return Values: +// +// A pointer to the desired data. +// +//-- + +#define RVA_TO_ADDR(Mapping,Rva) ((PVOID)(((ULONG_PTR) (Mapping)) + (Rva))) + +BOOL +WINAPI +MiniDumpWriteDump( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL + IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL + ); + +BOOL +WINAPI +MiniDumpReadDumpStream( + IN PVOID BaseOfDump, + IN ULONG StreamNumber, + OUT PMINIDUMP_DIRECTORY * Dir, OPTIONAL + OUT PVOID * StreamPointer, OPTIONAL + OUT ULONG * StreamSize OPTIONAL + ); + +#if defined(_MSC_VER) +#if _MSC_VER >= 800 +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning(default:4200) /* Zero length array */ +#pragma warning(default:4201) /* Nameless struct/union */ +#endif +#endif +#endif + +#include + +#ifdef __cplusplus +} +#endif + + +#endif // _DBGHELP_ diff --git a/plugins/CrashDumper/src/vc6/dbghelp.lib b/plugins/CrashDumper/src/vc6/dbghelp.lib new file mode 100644 index 0000000000..5d50c3f74d Binary files /dev/null and b/plugins/CrashDumper/src/vc6/dbghelp.lib differ diff --git a/plugins/CrashDumper/src/version.h b/plugins/CrashDumper/src/version.h new file mode 100644 index 0000000000..776e30e404 --- /dev/null +++ b/plugins/CrashDumper/src/version.h @@ -0,0 +1,3 @@ +#define __FILEVERSION_STRING 0,0,4,21 +#define __VERSION_STRING "0.0.4.21" +#define __VERSION_DWORD PLUGIN_MAKE_VERSION(0, 0, 4, 21) -- cgit v1.2.3