/* 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 "stdafx.h" CMPlugin g_plugin; LCID packlcid; HANDLE hVerInfoFolder; HMODULE hMsftedit; wchar_t* vertxt; wchar_t* profname; wchar_t* profpath; wchar_t CrashLogFolder[MAX_PATH], VersionInfoFolder[MAX_PATH]; CDlgBase *pViewDialog = nullptr; ///////////////////////////////////////////////////////////////////////////////////////// PLUGININFOEX pluginInfoEx = { sizeof(PLUGININFOEX), __PLUGIN_NAME, PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), __DESCRIPTION, __AUTHOR, __COPYRIGHT, __AUTHORWEB, UNICODE_AWARE, // {F62C1D7A-FFA4-4065-A251-4C9DD9101CC8} { 0xf62c1d7a, 0xffa4, 0x4065, { 0xa2, 0x51, 0x4c, 0x9d, 0xd9, 0x10, 0x1c, 0xc8 } } }; CMPlugin::CMPlugin() : PLUGIN(MODULENAME, pluginInfoEx), bCatchCrashes(MODULENAME, "CatchCrashes", 1), bClassicDates(MODULENAME, "ClassicDates", 1), bUseSubFolder(MODULENAME, "SubFolders", 1), bSuccessPopups(MODULENAME, "SuccessPopups", 1), bUploadChanged(MODULENAME, "UploadChanged", 0) { } ///////////////////////////////////////////////////////////////////////////////////////// // MirandaInterfaces - returns the protocol interface to the core extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_SERVICEMODE, MIID_LAST }; ///////////////////////////////////////////////////////////////////////////////////////// INT_PTR StoreVersionInfoToFile(WPARAM, LPARAM lParam) { CreateDirectoryTreeW(VersionInfoFolder); wchar_t path[MAX_PATH]; mir_snwprintf(path, L"%s\\VersionInfo.txt", VersionInfoFolder); HANDLE hDumpFile = CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (hDumpFile != INVALID_HANDLE_VALUE) { CMStringW buffer; PrintVersionInfo(buffer, (unsigned int)lParam | VI_FLAG_PRNVAR); WriteUtfFile(hDumpFile, T2Utf(buffer.c_str())); CloseHandle(hDumpFile); ShowMessage(3, TranslateT("Version Info stored into file %s"), path); } else ShowMessage(2, TranslateT("Version Info file %s is inaccessible"), path); return 0; } INT_PTR StoreVersionInfoToClipboard(WPARAM, LPARAM lParam) { CMStringW buffer; 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) { CMStringW buffer; PrintVersionInfo(buffer); VerTrnsfr *trn = (VerTrnsfr*)mir_alloc(sizeof(VerTrnsfr)); trn->buf = mir_utf8encodeW(buffer.c_str()); trn->autot = lParam == 0xa1; mir_forkthread(VersionInfoUploadThread, trn); return 0; } INT_PTR GetVersionInfo(WPARAM wParam, LPARAM lParam) { int result = 1; //failure if (lParam != NULL) { CMStringW buffer; PrintVersionInfo(buffer, (unsigned int)wParam); char **retData = (char **)lParam; *retData = mir_utf8encodeW(buffer.c_str()); if (*retData) result = 0; //success } return result; } INT_PTR OpenUrl(WPARAM wParam, LPARAM) { switch (wParam) { case 0: ShellExecute(nullptr, L"explore", CrashLogFolder, nullptr, nullptr, SW_SHOW); break; case 1: OpenAuthUrl("https://vi.miranda-ng.org/detail/%s"); break; } return 0; } INT_PTR CopyLinkToClipboard(WPARAM, LPARAM) { ptrW tmp(g_plugin.getWStringA("Username")); if (tmp != NULL) { wchar_t buffer[MAX_PATH]; mir_snwprintf(buffer, L"https://vi.miranda-ng.org/detail/%s", tmp); int bufLen = (sizeof(buffer) + 1) * sizeof(wchar_t); HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, bufLen); LPSTR buf = (LPSTR)GlobalLock(hData); memcpy(buf, buffer, bufLen); OpenClipboard(nullptr); EmptyClipboard(); if (SetClipboardData(CF_UNICODETEXT, hData) == nullptr) GlobalFree(hData); CloseClipboard(); } return 0; } INT_PTR ServiceModeLaunch(WPARAM, LPARAM) { g_plugin.bServiceMode = true; ViewVersionInfo(1, 0); return SERVICE_ONLYDB; } static int FoldersPathChanged(WPARAM, LPARAM) { FoldersGetCustomPathW(hVerInfoFolder, VersionInfoFolder, MAX_PATH, L""); return 0; } static int ToolbarModulesLoaded(WPARAM, LPARAM) { TTBButton ttb = {}; ttb.pszService = MS_CRASHDUMPER_STORETOCLIP; ttb.name = ttb.pszTooltipUp = LPGEN("Version Information To Clipboard"); ttb.hIconHandleUp = g_plugin.getIconHandle(IDI_VITOCLIP); ttb.dwFlags = TTBBF_VISIBLE; g_plugin.addTTB(&ttb); ttb.pszService = MS_CRASHDUMPER_STORETOFILE; ttb.name = ttb.pszTooltipUp = LPGEN("Version Information To File"); ttb.hIconHandleUp = g_plugin.getIconHandle(IDI_VITOFILE); ttb.dwFlags = 0; g_plugin.addTTB(&ttb); ttb.pszService = MS_CRASHDUMPER_VIEWINFO; ttb.name = ttb.pszTooltipUp = LPGEN("Show Version Information"); ttb.hIconHandleUp = g_plugin.getIconHandle(IDI_VISHOW); g_plugin.addTTB(&ttb); ttb.pszService = MS_CRASHDUMPER_UPLOAD; ttb.name = ttb.pszTooltipUp = LPGEN("Upload Version Information"); ttb.hIconHandleUp = g_plugin.getIconHandle(IDI_VIUPLOAD); g_plugin.addTTB(&ttb); return 0; } static int ModulesLoaded(WPARAM, LPARAM) { char temp[MAX_PATH]; Miranda_GetVersionText(temp, _countof(temp)); crs_a2t(vertxt, temp); if (ServiceExists(MS_FOLDERS_REGISTER_PATH)) { replaceStrW(profpath, L"%miranda_userdata%"); // Removed because it isn't available on Load() // hCrashLogFolder = FoldersRegisterCustomPathW(MODULENAME, LPGEN("Crash Reports"), CrashLogFolder); hVerInfoFolder = FoldersRegisterCustomPathW(MODULENAME, LPGEN("Version Information"), VersionInfoFolder); HookEvent(ME_FOLDERS_PATH_CHANGED, FoldersPathChanged); FoldersPathChanged(0, 0); } CMenuItem mi(&g_plugin); mi.root = g_plugin.addRootMenu(MO_MAIN, LPGENW("Version Information"), 2000089999, g_plugin.getIconHandle(IDI_VI)); Menu_ConfigureItem(mi.root, MCI_OPT_UID, "9A7A9C76-7FD8-4C05-B402-6C46060C2D78"); SET_UID(mi, 0x52930e40, 0xb2ee, 0x4433, 0xad, 0x77, 0xf5, 0x42, 0xe, 0xf6, 0x57, 0xc1); mi.position = 2000089995; mi.name.a = LPGEN("Copy to clipboard"); mi.hIcolibItem = g_plugin.getIconHandle(IDI_VITOCLIP); mi.pszService = MS_CRASHDUMPER_STORETOCLIP; Menu_AddMainMenuItem(&mi); SET_UID(mi, 0x54109094, 0x494e, 0x4535, 0x9c, 0x3a, 0xf6, 0x9e, 0x9a, 0xf7, 0xcd, 0xbe); mi.position = 2000089996; mi.name.a = LPGEN("Store to file"); mi.hIcolibItem = g_plugin.getIconHandle(IDI_VITOFILE); mi.pszService = MS_CRASHDUMPER_STORETOFILE; Menu_AddMainMenuItem(&mi); SET_UID(mi, 0x4004f9ee, 0x2c5a, 0x420a, 0xb1, 0x54, 0x3e, 0x47, 0xc1, 0xde, 0x46, 0xec); mi.position = 2000089997; mi.name.a = LPGEN("Show"); mi.hIcolibItem = g_plugin.getIconHandle(IDI_VISHOW); mi.pszService = MS_CRASHDUMPER_VIEWINFO; Menu_AddMainMenuItem(&mi); SET_UID(mi, 0x8526469a, 0x8ab4, 0x4dd4, 0xad, 0xbf, 0x51, 0xfd, 0x71, 0x10, 0xd3, 0x3c); mi.position = 2000089998; mi.name.a = LPGEN("Show with DLLs"); mi.hIcolibItem = g_plugin.getIconHandle(IDI_VIUPLOAD); mi.pszService = MS_CRASHDUMPER_VIEWINFO; Menu_ConfigureItem(Menu_AddMainMenuItem(&mi), MCI_OPT_EXECPARAM, 1); SET_UID(mi, 0xc6e3b558, 0xe1e8, 0x4cce, 0x96, 0x8, 0xc6, 0x89, 0x1b, 0x79, 0xf3, 0x7e); mi.position = 2000089999; mi.name.a = LPGEN("Upload"); mi.hIcolibItem = g_plugin.getIconHandle(IDI_VIUPLOAD); mi.pszService = MS_CRASHDUMPER_UPLOAD; Menu_AddMainMenuItem(&mi); SET_UID(mi, 0xa23da95a, 0x7624, 0x4343, 0x8c, 0xc0, 0xa6, 0x16, 0xbc, 0x30, 0x13, 0x8c); mi.position = 2000089999; mi.name.a = LPGEN("Copy link to clipboard"); mi.hIcolibItem = g_plugin.getIconHandle(IDI_LINKTOCLIP);//need icon mi.pszService = MS_CRASHDUMPER_URLTOCLIP; Menu_AddMainMenuItem(&mi); if (g_plugin.bCatchCrashes && !g_plugin.bNeedRestart) { SET_UID(mi, 0xecae52f2, 0xd601, 0x4f85, 0x87, 0x9, 0xec, 0x8e, 0x84, 0xfe, 0x1b, 0x3c); mi.position = 2000099990; mi.name.a = LPGEN("Open crash report directory"); mi.hIcolibItem = Skin_GetIconHandle(SKINICON_EVENT_FILE); mi.pszService = MS_CRASHDUMPER_URL; Menu_AddMainMenuItem(&mi); } SET_UID(mi, 0x6b19be3, 0xfb7d, 0x457d, 0x85, 0xde, 0xe0, 0x26, 0x4c, 0x87, 0x35, 0xf4); mi.position = 2000099991; mi.name.a = LPGEN("Open online Version Info"); mi.hIcolibItem = Skin_GetIconHandle(SKINICON_EVENT_URL); mi.pszService = MS_CRASHDUMPER_URL; Menu_ConfigureItem(Menu_AddMainMenuItem(&mi), MCI_OPT_EXECPARAM, 1); HOTKEYDESC hk = {}; hk.szSection.a = MODULENAME; hk.szDescription.a = LPGEN("Copy Version Info to clipboard"); hk.pszName = "CopyVerInfo"; hk.pszService = MS_CRASHDUMPER_STORETOCLIP; g_plugin.addHotkey(&hk); hk.szDescription.a = LPGEN("Show Version Info"); hk.pszName = "ShowVerInfo"; hk.pszService = MS_CRASHDUMPER_VIEWINFO; g_plugin.addHotkey(&hk); UploadInit(); if (g_plugin.bCatchCrashes && !g_plugin.bNeedRestart) SetExceptionHandler(); HookEvent(ME_TTB_MODULELOADED, ToolbarModulesLoaded); if (g_plugin.bServiceMode) ViewVersionInfo(0, 0); else if (g_plugin.bUploadChanged && !ProcessVIHash(false)) UploadVersionInfo(0, 0xa1); return 0; } static int PreShutdown(WPARAM, LPARAM) { UploadClose(); return 0; } int CMPlugin::Load() { hMsftedit = LoadLibrary(L"Msftedit.dll"); if (hMsftedit == nullptr) return 1; profname = Utils_ReplaceVarsW(L"%miranda_profilename%.dat"); profpath = Utils_ReplaceVarsW(L"%miranda_userdata%"); if (g_plugin.bCatchCrashes && !g_plugin.bNeedRestart) mir_snwprintf(CrashLogFolder, L"%s\\CrashLog", profpath); wcsncpy_s(VersionInfoFolder, profpath, _TRUNCATE); HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); HookEvent(ME_OPT_INITIALISE, OptionsInit); HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown); packlcid = (LCID)Langpack_GetDefaultLocale(); InitIcons(); if (g_plugin.bCatchCrashes && !g_plugin.bNeedRestart) InitExceptionHandler(); CreateServiceFunction(MS_CRASHDUMPER_STORETOFILE, StoreVersionInfoToFile); CreateServiceFunction(MS_CRASHDUMPER_STORETOCLIP, StoreVersionInfoToClipboard); CreateServiceFunction(MS_CRASHDUMPER_VIEWINFO, ViewVersionInfo); CreateServiceFunction(MS_CRASHDUMPER_GETINFO, GetVersionInfo); CreateServiceFunction(MS_CRASHDUMPER_UPLOAD, UploadVersionInfo); CreateServiceFunction(MS_CRASHDUMPER_URL, OpenUrl); CreateServiceFunction(MS_SERVICEMODE_LAUNCH, ServiceModeLaunch); CreateServiceFunction(MS_CRASHDUMPER_URLTOCLIP, CopyLinkToClipboard); return 0; } ///////////////////////////////////////////////////////////////////////////////////////// int CMPlugin::Unload() { if ((g_plugin.bCatchCrashes && !g_plugin.bNeedRestart) || (!g_plugin.bCatchCrashes && g_plugin.bNeedRestart)) DestroyExceptionHandler(); mir_free(profpath); mir_free(profname); mir_free(vertxt); FreeLibrary(hMsftedit); return 0; }