Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Unified Diff: base/debug.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/debug.h ('k') | base/debug_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/debug.cc
diff --git a/base/debug.cc b/base/debug.cc
deleted file mode 100644
index b0b53bda3b090c1919ddcf96592fcb18f6d3d5ca..0000000000000000000000000000000000000000
--- a/base/debug.cc
+++ /dev/null
@@ -1,1195 +0,0 @@
-// Copyright 2003-2009 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-//
-// Debug functions
-
-#include "omaha/base/debug.h"
-
-#include <dbghelp.h>
-#include <wtsapi32.h>
-#include <atlstr.h>
-#ifdef _DEBUG
-#include <atlcom.h>
-#define STRSAFE_NO_DEPRECATE
-#include <strsafe.h>
-#endif
-#include <stdlib.h>
-#include <signal.h>
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "omaha/base/app_util.h"
-#include "omaha/base/clipboard.h"
-#include "omaha/base/commontypes.h"
-#include "omaha/base/constants.h"
-#include "omaha/base/const_addresses.h"
-#include "omaha/base/const_config.h"
-#include "omaha/base/const_debug.h"
-#include "omaha/base/const_timeouts.h"
-#include "omaha/base/file.h"
-#include "omaha/base/logging.h"
-#include "omaha/base/module_utils.h"
-#include "omaha/base/omaha_version.h"
-#include "omaha/base/reg_key.h"
-#include "omaha/base/safe_format.h"
-#include "omaha/base/scope_guard.h"
-#include "omaha/base/scoped_ptr_address.h"
-#include "omaha/base/string.h"
-#include "omaha/base/system.h"
-#include "omaha/base/synchronized.h"
-#include "omaha/base/time.h"
-#include "omaha/base/utils.h"
-#include "omaha/base/vistautil.h"
-#include "omaha/base/vista_utils.h"
-
-namespace omaha {
-
-#ifdef _DEBUG
-#define kSprintfBuffers (100) // number of buffers for SPRINTF
-#else
-#define kSprintfBuffers (3) // number of buffers for SPRINTF
-#endif
-
-// pad SPRINTF buffer to check for overruns
-#if SHIPPING
-#define kSprintfBufferOverrunPadding 0
-#else // !SHIPPING
-#ifdef DEBUG
-#define kSprintfBufferOverrunPadding 20000
-#else
-#define kSprintfBufferOverrunPadding 1024
-#endif // DEBUG
-#endif // SHIPPING
-
-#ifdef _DEBUG
-const TCHAR* const kErrorRequestToSendFormat =
- _T("*** Please hit Ignore to continue and send error information to the ")
- _T("%s team ***\n*** These details have been pasted to the clipboard ***");
-
-// Max length of report summary string.
-const int kMaxReportSummaryLen = 1024 * 100;
-#endif // DEBUG
-
-#define kReportIdsLock kLockPrefix \
- _T("Report_Ids_Lock_57146B01-6A07-4b8d-A1D8-0C3AFC3B2F9B")
-
-SELECTANY bool g_always_assert = false;
-SELECTANY TCHAR *g_additional_status_ping_info = NULL;
-
-#define kSprintfMaxLen (1024 + 2) // max length that wvsprintf writes is 1024
-static bool g_initialized_sprintf = false;
-static volatile LONG g_sprintf_interlock = 0;
-static int g_current_sprintf_buffer = 0;
-static TCHAR *g_sprintf_buffer = NULL;
-static TCHAR *g_sprintf_buffers[kSprintfBuffers];
-SELECTANY volatile LONG g_debugassertrecursioncheck = 0;
-static int g_total_reports = 0;
-
-SELECTANY ReportIds g_report_ids;
-
-// Builds a full path name out of the given filename. If the filename is
-// a relative path, it is appended to the debug directory. Otherwise, if the
-// filename is a full path, it returns it as the full debug filename.
-static CString MakeFullDebugFilename(const TCHAR *filename) {
- CString full_name;
- if (lstrlen(filename) <= 2 || filename[1] != _T(':')) {
- full_name = GetDebugDirectory();
- full_name += L"\\";
- }
- full_name += filename;
- return full_name;
-}
-
-
-// Displays the assert box. Due to session isolation, MB_SERVICE_NOTIFICATION
-// flag does not work for Vista services. In this case, use WTS to display
-// a message box in the active console session.
-void ShowAssertDialog(const TCHAR *message, const TCHAR *title) {
- int ret = 0;
- OSVERSIONINFOEX osviex = {sizeof(OSVERSIONINFOEX), 0};
- const bool is_vista_or_greater =
- ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&osviex)) &&
- osviex.dwMajorVersion >= 6;
- bool is_system_process = false;
- if (is_vista_or_greater &&
- SUCCEEDED(IsSystemProcess(&is_system_process)) &&
- is_system_process) {
- DWORD session_id = System::WTSGetActiveConsoleSessionId();
- if (session_id == kInvalidSessionId) {
- session_id = WTS_CURRENT_SESSION;
- }
- DWORD response = 0;
- ::WTSSendMessage(WTS_CURRENT_SERVER_HANDLE,
- session_id,
- const_cast<TCHAR*>(title),
- _tcslen(title) * sizeof(TCHAR),
- const_cast<TCHAR*>(message),
- _tcslen(message) * sizeof(TCHAR),
- MB_ABORTRETRYIGNORE | MB_ICONERROR,
- 0,
- &response,
- true);
- ret = response;
- } else {
- ret = ::MessageBoxW(NULL,
- message,
- title,
- MB_ABORTRETRYIGNORE |
- MB_ICONERROR |
- MB_SERVICE_NOTIFICATION);
- }
-
- switch (ret) {
- case IDABORT:
- // Terminate the process if the user chose 'Abort'. Calling ExitProcess
- // here results in calling the destructors for static objects which can
- // result in deadlocks.
- raise(SIGABRT);
- break;
-
- case IDRETRY:
- // Break if the user chose "Retry".
- __debugbreak();
- break;
- default:
- // By default we ignore the message.
- break;
- }
-}
-
-DebugObserver* g_debug_observer = NULL;
-
-// replaces the debug observer, returns the previous value.
-DebugObserver* SetDebugObserver(DebugObserver* observer) {
- DebugObserver* old_value = g_debug_observer;
- g_debug_observer = observer;
- return old_value;
-}
-
-DebugObserver* PeekDebugObserver() {
- return g_debug_observer;
-}
-
-int SehSendMinidump(unsigned int code,
- struct _EXCEPTION_POINTERS *ep,
- time64 time_between_minidumps) {
- if (code == EXCEPTION_BREAKPOINT)
- return EXCEPTION_CONTINUE_SEARCH;
-
- if (::IsDebuggerPresent())
- return EXCEPTION_CONTINUE_SEARCH;
-
- OutputDebugString(L"**SehSendMinidump**\r\n");
-
- if (g_debug_observer) {
- return g_debug_observer->SehSendMinidump(code, ep, time_between_minidumps);
- }
-
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-#if defined(_DEBUG) || defined(ASSERT_IN_RELEASE)
-CallInterceptor<DebugAssertFunctionType> debug_assert_interceptor;
-
-// Replaces the debug assert function; returns the old value.
-DebugAssertFunctionType* ReplaceDebugAssertFunction(
- DebugAssertFunctionType* replacement) {
- return debug_assert_interceptor.ReplaceFunction(replacement);
-}
-
-void OnAssert(const char *expr, const TCHAR *msg,
- const char *filename, int32 linenumber) {
- if (g_debug_observer) {
- g_debug_observer->OnAssert(expr, msg, filename, linenumber);
- }
-}
-#endif
-
-#if defined(_DEBUG)
-CString OnDebugReport(uint32 id,
- bool is_report,
- ReportType type,
- const char *expr,
- const TCHAR *message,
- const char *filename,
- int32 linenumber,
- DebugReportKind debug_report_kind) {
- CString trace;
- if (g_debug_observer) {
- trace = g_debug_observer->OnDebugReport(id, is_report,
- type, expr, message, filename,
- linenumber, debug_report_kind);
- }
- return trace;
-}
-
-void SendExceptionReport(const TCHAR *log_file, const TCHAR *filename, int line,
- const TCHAR *type, uint32 id, bool offline) {
- if (g_debug_observer) {
- g_debug_observer->SendExceptionReport(log_file, filename, line,
- type, id, offline);
- }
-}
-#endif
-
-
-#ifdef _DEBUG // won't compile since _CrtDbgReport isn't defined.
-
-#include <crtdbg.h> // NOLINT
-static CString g_report_summary;
-
-// dump summary of reports on exit
-SELECTANY ReportSummaryGenerator g_report_summary_generator;
-
-ReportSummaryGenerator::~ReportSummaryGenerator() {
- DumpReportSummary();
-}
-
-void ReportSummaryGenerator::DumpReportSummary() {
- if (g_total_reports) {
- ::OutputDebugString(L"REPORT SUMMARY:\r\n");
- ::OutputDebugString(SPRINTF(L"%d total reports\r\n", g_total_reports));
- ::OutputDebugString(g_report_summary);
- } else {
- ::OutputDebugString(L"NO REPORTS!!\r\n");
- }
-}
-
-TCHAR *ReportSummaryGenerator::GetReportSummary() {
- TCHAR *s = new TCHAR[kMaxReportSummaryLen];
- if (s) {
- s[0] = 0;
- if (g_total_reports) {
- SafeStrCat(s, L"REPORT SUMMARY:\r\n\r\n", kMaxReportSummaryLen);
- SafeStrCat(s,
- SPRINTF(L"%d total reports\r\n\r\n", g_total_reports),
- kMaxReportSummaryLen);
- SafeStrCat(s,
- g_report_summary.
- Left(kMaxReportSummaryLen - lstrlen(s) - 1).GetString(),
- kMaxReportSummaryLen);
- CString report_string = g_report_ids.DebugReportString();
- ReplaceCString(report_string, L"&", L"\r\n");
- SafeStrCat(s,
- report_string.
- Left(kMaxReportSummaryLen - lstrlen(s) - 1).GetString(),
- kMaxReportSummaryLen);
- } else {
- SafeStrCat(s, L"NO REPORTS!!\r\n", kMaxReportSummaryLen);
- }
- }
-
- return s;
-}
-
-static CAtlMap<CString, uint32> g_reports_done;
-
-#endif // _DEBUG
-
-#ifdef _DEBUG
-
-void TraceError(DWORD error) {
- HLOCAL mem = NULL;
- ::FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- static_cast<LPVOID>(_AtlBaseModule.GetResourceInstance()),
- error,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
- reinterpret_cast<TCHAR*>(&mem),
- 0,
- NULL);
-
- TCHAR* str = reinterpret_cast<TCHAR*>(::LocalLock(mem));
- ::OutputDebugString(str);
- REPORT(false, R_ERROR, (str), 3968294226);
- ::LocalFree(mem);
-}
-
-// ban ASSERT/VERIFY/REPORT to prevent recursion
-#undef ASSERT
-#undef VERIFY
-#undef REPORT
-
-// TODO(omaha): fix static initialization order below.
-// The initialization order of static variables is not deterministic per C++
-// standard and it depends completely on the compiler implementation.
-// For VC++ compiler we are using, it seems to work as expected.
-// One real fix is to put all definitons of static variables inside a class and
-// define a boolean variable in this class to indicate that all necessary
-// static initializations have been done.
-//
-// The follow definition is used to detect whether we get the exception
-// during initializing static variables. If this is the case, DebugReport()
-// will not function and will throw an exception because some of its refering
-// static variables are not initialized yet (i.e. g_reports_done).
-const int kTestInitStaticVariablesDoneValue = 1234;
-struct TestInitStaticVariablesDone {
- int value;
- TestInitStaticVariablesDone() : value(kTestInitStaticVariablesDoneValue) {}
-};
-static TestInitStaticVariablesDone test_var;
-
-bool DebugReport(unsigned int id,
- ReportType type,
- const char *expr,
- const TCHAR *message,
- const char *filename,
- int linenumber,
- DebugReportKind debug_report_kind) {
- int recursion_count = ::InterlockedIncrement(&g_debugassertrecursioncheck);
- ON_SCOPE_EXIT(::InterlockedDecrement, &g_debugassertrecursioncheck);
- if (recursion_count > 1) {
- ::OutputDebugString(_T("recursive debugreport skipped\n"));
- return 1;
- }
-
- if (debug_assert_interceptor.interceptor()) {
- // call replacement function (typically used for unit tests)
- // Note that I'm doing this inside the in_assert block for paranoia;
- // it's not really necessary and perhaps the wrong choice.
- debug_assert_interceptor.interceptor()(expr, CT2A(message), filename,
- linenumber);
- return true;
- }
-
-
- // Check whether we have already finished initializing all static variables
- // needed for executing DebugReport(). If not, bail out.
- if (test_var.value != kTestInitStaticVariablesDoneValue) {
- CString debug_msg;
- SafeCStringFormat(&debug_msg, _T("%hs:%d - %s - %S"),
- filename, linenumber, message, expr);
- debug_msg.Append(_T("\n\nException occurs while initializing ")
- _T("static variables needed for DebugReport"));
- ShowAssertDialog(debug_msg, _T("DebugReport"));
- return true;
- }
-
- bool is_assert = debug_report_kind == DEBUGREPORT_ASSERT;
- bool is_report = debug_report_kind == DEBUGREPORT_REPORT;
- bool is_abort = debug_report_kind == DEBUGREPORT_ABORT;
-
- if (is_report)
- g_total_reports++;
-
- g_report_ids.ReleaseReport(id);
-
- if (type == R_FATAL) {
- if (is_report) {
- // Treat as ASSERT
- is_report = false;
- is_assert = true;
- }
- }
-
- bool always_assert = g_always_assert;
-
- if (always_assert) {
- is_report = false;
- is_assert = true;
- }
-
- if (!message) {
- message = _T("");
- }
-
- // log to debugger
- TCHAR *debug_string;
- // ::OutputDebugString(DEBUG_LOG_SEPARATOR);
- ::OutputDebugString(is_report ? _T("REPORT: ") :
- (is_assert ? _T("ASSERT: ") : _T("ABORT: ")));
-
- CFixedStringT<CString, 1024> proc_name = app_util::GetAppName();
-
- // last %s now %s skip %d
- const TCHAR* format = message && *message ?
- _T("[%hs:%d][%hs][%s]") : _T("[%hs:%d][%hs]");
- debug_string = SPRINTF(format, filename, linenumber, expr, message);
-
- // String_Int64ToString(g_last_report_time, 10),
- // String_Int64ToString(time, 10), skip_report));
-
- // ::OutputDebugString(DEBUG_LOG_SEPARATOR);
- // ::OutputDebugString(_T("\n"));
-
-#ifdef LOGGING
- // Log the reports via the logging system to all loggers.
- CString what = is_report ? _T("REPORT") :
- is_assert ? _T("ASSERT") : _T("ABORT");
- LC_LOG(LC_LOGGING, LEVEL_ERROR, (_T("[%s]%s"), what, debug_string));
-#else
- ::OutputDebugString(debug_string);
- ::OutputDebugString(_T("\n"));
-#endif
-
- // skip sending strack trace for duplicate reports
- CString report_id;
- SafeCStringFormat(&report_id, _T("%hs:%d"), filename, linenumber);
-
- uint32 prev_reports = 0;
- if (g_reports_done.Lookup(report_id, prev_reports) && is_report) {
- prev_reports++;
- g_reports_done.SetAt(report_id, prev_reports);
- ::OutputDebugString(SPRINTF(_T("skipping duplicate report %s %d\n"),
- report_id.GetString(),
- prev_reports));
- return 1;
- }
-
- prev_reports++;
- g_reports_done.SetAt(report_id, prev_reports);
-
- g_report_summary.Append(debug_string);
- g_report_summary.Append(L" (");
- g_report_summary.Append(itostr(id));
- g_report_summary.Append(L")");
- g_report_summary.Append(L"\r\n");
-
- // ::OutputDebugString(_T("log to file\n"));
-
- // log to file
- CString path_name(MakeFullDebugFilename(kCiDebugLogFile));
- HANDLE h = CreateFile(path_name,
- GENERIC_WRITE | GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- HANDLE assert_file = INVALID_HANDLE_VALUE;
- if (is_assert) {
- path_name = MakeFullDebugFilename(kCiAssertOccurredFile);
- assert_file = CreateFile(path_name,
- GENERIC_WRITE,
- 0,
- 0,
- OPEN_ALWAYS,
- FILE_FLAG_WRITE_THROUGH,
- NULL);
- }
-
- HANDLE abort_file = INVALID_HANDLE_VALUE;
- if (is_abort) {
- path_name = MakeFullDebugFilename(kCiAbortOccurredFile);
- abort_file = CreateFile(path_name,
- GENERIC_WRITE,
- 0,
- 0,
- OPEN_ALWAYS,
- FILE_FLAG_WRITE_THROUGH,
- NULL);
- }
-
- if (h != INVALID_HANDLE_VALUE ||
- assert_file != INVALID_HANDLE_VALUE ||
- abort_file != INVALID_HANDLE_VALUE) {
- // more convenient for now to have this in UTF8
- char *utf8_buffer = new char[(lstrlen(debug_string)*2) + 1];
- if (utf8_buffer) {
- int conv_bytes = WideCharToMultiByte(CP_UTF8,
- 0,
- debug_string,
- lstrlen(debug_string),
- utf8_buffer,
- (lstrlen(debug_string) * 2) + 1,
- NULL,
- NULL);
-
- if (conv_bytes) {
- DWORD bytes_written;
- BOOL result;
-
- if (h != INVALID_HANDLE_VALUE) {
- SetFilePointer(h, 0, NULL, FILE_END);
- result = ::WriteFile(h,
- (LPCVOID)utf8_buffer,
- conv_bytes,
- &bytes_written,
- NULL);
- result = ::WriteFile(h,
- (LPCVOID)DEBUG_LOG_SEPARATOR_CHAR,
- strlen(DEBUG_LOG_SEPARATOR_CHAR),
- &bytes_written,
- NULL);
- }
- if (assert_file != INVALID_HANDLE_VALUE) {
- result = ::WriteFile(assert_file,
- (LPCVOID)utf8_buffer,
- conv_bytes,
- &bytes_written,
- NULL);
- }
- if (abort_file != INVALID_HANDLE_VALUE) {
- result = ::WriteFile(abort_file,
- (LPCVOID)utf8_buffer,
- conv_bytes,
- &bytes_written,
- NULL);
- }
- }
-
- delete [] utf8_buffer;
- }
- }
-
- if (h != INVALID_HANDLE_VALUE) {
- ::CloseHandle(h);
- }
- if (assert_file != INVALID_HANDLE_VALUE) {
- ::CloseHandle(assert_file);
- }
- if (abort_file != INVALID_HANDLE_VALUE) {
- ::CloseHandle(abort_file);
- }
-
- CString stack_trace = OnDebugReport(id, is_report, type, expr, message,
- filename, linenumber, debug_report_kind);
-
- if (is_report) {
- return 1;
- }
-
- ::OutputDebugString(L"show assert dialog\r\n");
- ::OutputDebugString(stack_trace.GetString());
-
- CString process_path;
- GetModuleFileName(NULL, &process_path);
-
- static TCHAR clipboard_string[4096] = {0};
- lstrcpyn(clipboard_string,
- SPRINTF(L"%ls (pid=%i)\r\n%hs:%d\r\n\r\n%hs\r\n%s\r\n\r\n",
- process_path,
- ::GetCurrentProcessId(),
- filename,
- linenumber,
- expr,
- message),
- arraysize(clipboard_string));
- stack_trace = stack_trace.Left(
- arraysize(clipboard_string) - lstrlen(clipboard_string) - 1);
- SafeStrCat(clipboard_string, stack_trace, arraysize(clipboard_string));
- SetClipboard(clipboard_string);
-
- stack_trace = stack_trace.Left(kMaxStackTraceDialogLen);
-
- CString assert_text;
- SafeCStringFormat(&assert_text,
- _T("Assertion (%ls) failed!\r\n\r\nProcess: %d ")
- _T("(0x%08X)\r\nThread %d (0x%08X)\r\nProgram: %ls\r\n")
- _T("Version: %s\r\nFile: %hs\r\nLine: %d\r\n\r\n"),
- debug_report_kind == DEBUGREPORT_ASSERT ?
- L"Assert" : (debug_report_kind == DEBUGREPORT_ABORT ?
- L"Abort" : L"Report"),
- ::GetCurrentProcessId(), ::GetCurrentProcessId(), ::GetCurrentThreadId(),
- ::GetCurrentThreadId(), process_path, omaha::GetVersionString(), filename,
- linenumber);
-
- CString error_request_to_send;
- SafeCStringFormat(&error_request_to_send, kErrorRequestToSendFormat, kAppName);
-
- if (lstrlen(message) > 0) {
- SafeCStringAppendFormat(&assert_text,
- _T("Expression: %hs\r\nMessage: %s\r\n\r\n%s\r\n\r\n%s"),
- expr,
- message,
- stack_trace,
- error_request_to_send);
- } else {
- SafeCStringAppendFormat(&assert_text,
- _T("Expression: %hs\r\n\r\n%s\r\n\r\n%s"),
- expr, stack_trace, error_request_to_send);
- }
-
- ShowAssertDialog(assert_text, CString(filename));
- return 1;
-}
-
-#endif // #ifdef _DEBUG
-
-
-ReportIds::ReportIds() {
- data_.report_counts_num = 0;
- NamedObjectAttributes lock_attr;
- GetNamedObjectAttributes(kReportIdsLock,
- vista_util::IsUserAdmin(),
- &lock_attr);
- InitializeWithSecAttr(lock_attr.name, &lock_attr.sa);
-}
-
-ReportIds::~ReportIds() {
- // don't attempt to write out reports from low integrity mode.
- //
- // TODO(omaha): save reports from a low integrity process (specifically IE
- // which does some extra special magic to thwart this) --
- // possible by launch a process or a broker, etc.
- if (vista::IsProcessProtected()) {
- return;
- }
-
- if (data_.report_counts_num != 0) {
- // Back the report IDs to the registry
- __mutexBlock(this) {
- ReportData *reports_in_config = NULL;
- if (LoadReportData(&reports_in_config)) {
- MergeReports(reports_in_config, &data_);
- SaveReportData(reports_in_config);
-
- byte *data = reinterpret_cast<byte*>(reports_in_config);
- delete [] data;
- } else {
- // There's no data in the registry, so just fill it up with this
- // component's data.
- SaveReportData(&data_);
- }
- }
- }
-}
-
-const TCHAR* const GetRegKeyShared() {
- return vista_util::IsUserAdmin() ? _T("HKLM\\") kCiRegKeyShared :
- _T("HKCU\\") kCiRegKeyShared;
-}
-
-void ReportIds::ResetReportsAfterPing() {
- // We will lose reports from TRS between the time DebugReportString was called
- // and now. We'll also lose reports from non TRS components if they exit in
- // between this time. Not important.
- data_.report_counts_num = 0;
- __mutexBlock(this) {
- RegKey::DeleteValue(GetRegKeyShared(), kRegValueReportIds);
- }
-}
-
-void ReportIds::MergeReports(ReportData *data1, const ReportData *data2) {
- // Loop through each report ID from data2. If we find it already, increment
- // the report's count in data1. Otherwise, if there's enough space, add the
- // report ID to data1.
- uint32 i, j;
- for (i = 0; i < data2->report_counts_num; ++i) {
- bool duplicate_report = false;
- for (j = 0; j < data1->report_counts_num; ++j) {
- if (data1->report_ids[j] == data2->report_ids[i]) {
- // uint16 is promoted to int.
- data1->report_counts[j] = static_cast<uint16>(
- data1->report_counts[j] + data2->report_counts[i]);
- duplicate_report = true;
- }
- }
-
- if (!duplicate_report && j < kMaxUniqueReports) {
- data1->report_ids[j] = data2->report_ids[i];
- data1->report_counts[j] = data2->report_counts[i];
- data1->report_counts_num++;
- }
- }
-}
-
-bool ReportIds::LoadReportData(ReportData **data) {
- DWORD byte_count = 0;
- *data = NULL;
- HRESULT hr = RegKey::GetValue(GetRegKeyShared(),
- kRegValueReportIds,
- reinterpret_cast<byte**>(data),
- &byte_count);
- if (SUCCEEDED(hr)) {
- if (byte_count == sizeof(ReportData)) {
- return true;
- } else {
- delete[] data;
- data = NULL;
- return false;
- }
- } else {
- return false;
- }
-}
-
-void ReportIds::SaveReportData(ReportData *data) {
- if (data->report_counts_num) {
- RegKey::SetValue(GetRegKeyShared(),
- kRegValueReportIds,
- reinterpret_cast<byte*>(data),
- sizeof(ReportData));
- }
-}
-
-bool ReportIds::ReleaseReport(uint32 id) {
- uint32 max = data_.report_counts_num;
-
- // If two threads call simultaneously, might miss one of an existing report
- // here; not important.
-
- uint32 i = 0;
- for (i = 0; i < max; ++i) {
- if (data_.report_ids[i] == id) {
- data_.report_counts[i]++;
- return true;
- }
- }
-
- // If two threads call simultaneously, might overwrite first of another
- // report; not important.
-
- if (i < kMaxUniqueReports) {
- data_.report_ids[i] = id;
- data_.report_counts[i] = 1;
- data_.report_counts_num = i + 1; // Set only after setting ids and count;
- // don't use ++
- }
-
-#ifdef _DEBUG
- OutputDebugString(SPRINTF(_T("release report %u\n"), id));
-#endif
- // must return true (return value of REPORT)
- return true;
-}
-
-// caller deletes the string
-TCHAR *ReportIds::DebugReportString() {
- TCHAR *s = new TCHAR[(kMaxUniqueReports * kMaxReportCountString) + 1];
- if (!s) { return NULL; }
- s[0] = '\0';
-
-#if 0
- // this version if we use a hash table for the report counts:
- uint32 id;
- uint16 count;
- hr = g_reports->First(&found, &id, &count);
- while (SUCCEEDED(hr) && found) {
- if (count) {
- SafeCStringAppendFormat(&status_info, _T("%d=%d"),
- id,
- static_cast<uint32>(count));
- }
-
- hr = g_reports->Next(&found, &id, &count);
- }
-#endif
-
- // The registry will contain the REPORTs from other components, so get that
- // list and merge it with TRS'.
- __mutexBlock(this) {
- ReportData *reports_in_config = NULL;
- if (LoadReportData(&reports_in_config)) {
- MergeReports(&data_, reports_in_config);
-
- byte *data = reinterpret_cast<byte*>(reports_in_config);
- delete[] data;
- }
- }
-
- TCHAR *current_pos = s;
- for (uint32 i = 0; i < data_.report_counts_num; i++) {
- if (data_.report_counts[i]) {
- // should be no chance of overflow, ok to use wsprintf
- int n = wsprintf(current_pos,
- _T("%u:%u,"),
- data_.report_ids[i],
- static_cast<uint32>(data_.report_counts[i]));
- current_pos += n;
- }
- }
-
- return s;
-}
-
-// A simple helper function whose sole purpose is
-// to isolate the dtor from SPRINTF which uses try/except.
-// app_util::GetAppName returns a CString and dtor's
-// aren't allowed in functions with try/except when
-// the /EHsc flag is set.
-void FillInSprintfErrorString(const TCHAR * format, TCHAR * error_string) {
- wsprintf(error_string, L"SPRINTF buffer overrun %ls %hs %ls",
- app_util::GetAppName(), omaha::GetVersionString(), format);
-}
-
-// following is currently included in release build
-// return string from format+arglist; for debugging
-TCHAR * __cdecl SPRINTF(const TCHAR * format, ...) {
- while (::InterlockedCompareExchange(&g_sprintf_interlock, 1, 0) == 1) {
- // while (::InterlockedIncrement(&g_sprintf_interlock)>1) {
- // ::InterlockedDecrement(&g_sprintf_interlock);
- // Don't process APCs here.
- // Can lead to infinite recursion, for example: filecap->logging->filecap...
- Sleep(0);
- }
-
- g_current_sprintf_buffer++;
- if (g_current_sprintf_buffer >= kSprintfBuffers) {
- g_current_sprintf_buffer = 0;
- }
-
- TCHAR *sprintf_buf = NULL;
-
- if (!g_initialized_sprintf) { // initialize buffers
- g_sprintf_buffer = new TCHAR[
- ((kSprintfMaxLen + 1) * kSprintfBuffers) +
- kSprintfBufferOverrunPadding];
- TCHAR* buffer = g_sprintf_buffer;
- if (!buffer) { goto cleanup; }
- for (int i = 0; i < kSprintfBuffers; ++i) {
- g_sprintf_buffers[i] = buffer;
- buffer += kSprintfMaxLen + 1;
- }
-
-#if !SHIPPING
- for (int i = ((kSprintfMaxLen+1) * kSprintfBuffers);
- i < ((kSprintfMaxLen + 1) * kSprintfBuffers) +
- kSprintfBufferOverrunPadding;
- ++i) {
- g_sprintf_buffer[i] = 1;
- }
-#endif
-
- // InitializeCriticalSection(&g_sprintf_critical_section);
- g_initialized_sprintf = true;
- }
-
- sprintf_buf = g_sprintf_buffers[g_current_sprintf_buffer];
-
- // EnterCriticalSection(&g_sprintf_critical_section);
-
- __try {
- // create the formatted CString
- va_list vl;
- va_start(vl, format);
-#ifdef DEBUG
- StringCbVPrintfW(sprintf_buf, kSprintfMaxLen, format, vl);
-#else
- wvsprintfW(sprintf_buf, format, vl);
-#endif
- va_end(vl);
-
-#if !SHIPPING
- for (int i = ((kSprintfMaxLen+1) * kSprintfBuffers);
- i < ((kSprintfMaxLen+1) * kSprintfBuffers) +
- kSprintfBufferOverrunPadding;
- ++i) {
- if (g_sprintf_buffer[i] != 1) {
- TCHAR error_string[1024];
- FillInSprintfErrorString(format, error_string);
- MessageBox(NULL,
- error_string,
- error_string,
- MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
- break;
- }
- }
-#endif
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- lstrcpyn(sprintf_buf, _T("sprintf failure"), kSprintfMaxLen);
- }
-
- // LeaveCriticalSection(&g_sprintf_critical_section);
-
- cleanup:
-
- ::InterlockedDecrement(&g_sprintf_interlock);
- return sprintf_buf;
-}
-
-#if 0
- TCHAR * __cdecl SPRINTF(const TCHAR * format, ...) {
- ASSERT(format, (L""));
-
- g_current_sprintf_buffer++;
- if (g_current_sprintf_buffer >= kSprintfBuffers) {
- g_current_sprintf_buffer = 0;
- }
-
- TCHAR *sprintf_buf = sprintf_buffers[g_current_sprintf_buffer];
- CFixedStringT<CString, kSprintfMaxLen> out;
-
- va_list argptr;
- va_start(argptr, format);
- out.FormatV(format, argptr);
- va_end(argptr);
-
- // copy to fixed return buffers
- SafeStrCat(sprintf_buf,
- out.GetBufferSetLength(kSprintfMaxLen),
- g_current_sprintf_buffer);
- sprintf_buf[kSprintfMaxLen] = '\0';
-
- return sprintf_buf;
-}
-#endif
-
-// Cleanup allocated memory
-class SprintfCleaner {
- public:
- SprintfCleaner() {}
-
- ~SprintfCleaner() {
- while (::InterlockedCompareExchange(&g_sprintf_interlock, 1, 0) == 1) {
- Sleep(0);
- }
-
- if (g_initialized_sprintf) {
- delete[] g_sprintf_buffer;
- for (int i = 0; i < kSprintfBuffers; ++i) {
- g_sprintf_buffers[i] = NULL;
- }
- g_initialized_sprintf = false;
- }
-
- ::InterlockedDecrement(&g_sprintf_interlock);
- }
-
- private:
- DISALLOW_EVIL_CONSTRUCTORS(SprintfCleaner);
-};
-
-static SprintfCleaner cleaner;
-
-// This is for our testers to find asserts in release mode.
-#if !defined(_DEBUG) && defined(ASSERT_IN_RELEASE)
-bool ReleaseAssert(const char *expr,
- const TCHAR *msg,
- const char *filename,
- int32 linenumber) {
- ASSERT(filename, (L""));
- ASSERT(msg, (L""));
- ASSERT(expr, (L""));
-
- if (debug_assert_interceptor.interceptor()) {
- // call replacement function (typically used for unit tests)
- // Note that I'm doing this inside the in_assert block for paranoia;
- // it's not really necessary and perhaps the wrong choice.
- debug_assert_interceptor.interceptor()(expr,
- CT2CA(msg),
- filename,
- linenumber);
- return true;
- }
-
- OnAssert(expr, msg, filename, linenumber);
-
- // Also put up a message box.
- TCHAR error_string[1024] = {0};
- wsprintf(error_string,
- L"App: %ls\r\n"
- L"Expr: %hs\r\n"
- L"File: %hs\r\n"
- L"Line: %d\r\n"
- L"Version: %hs\r\n"
- L"Message: ",
- app_util::GetAppName(),
- expr,
- filename,
- linenumber,
- VER_TIMESTAMP_STR_FILE);
- SafeStrCat(error_string, msg, arraysize(error_string));
- SafeStrCat(error_string,
- L"\r\n\r\n*** This message has been copied to the clipboard. ***",
- arraysize(error_string));
- SetClipboard(error_string);
-
- TCHAR title_string[1024];
- wsprintf(title_string, L"%s ASSERT %s %hs",
- kAppName, app_util::GetAppName(), VER_TIMESTAMP_STR_FILE);
- MessageBox(NULL,
- error_string,
- title_string,
- MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
- return true;
-}
-#endif
-
-#if defined(_DEBUG)
-void DebugAbort(const TCHAR *msg,
- const char* filename,
- int32 linenumber,
- bool do_abort) {
- DebugReport(0, R_FATAL, "", msg, filename, linenumber, DEBUGREPORT_ABORT);
- if (do_abort) {
- abort();
- }
-}
-#else
-void ReleaseAbort(const TCHAR *msg,
- const char* filename,
- int32 linenumber,
- bool do_abort) {
- // Send info to the server.
-#if defined(ASSERT_IN_RELEASE)
- OnAssert("", msg, filename, linenumber);
-#endif
-
- // Also put up a message box.
- TCHAR error_string[1024] = {0};
- wsprintf(error_string,
- L"App: %ls\r\n"
- L"File: %hs\r\n"
- L"Line: %d\r\n"
- L"Version: %hs\r\n"
- L"Message: ",
- app_util::GetAppName(),
- filename,
- linenumber,
- omaha::GetVersionString());
- SafeStrCat(error_string, msg, arraysize(error_string));
- SafeStrCat(error_string,
- L"\r\n\r\n*** This message has been copied to the clipboard. ***",
- arraysize(error_string));
- SetClipboard(error_string);
-
- TCHAR title_string[1024];
- wsprintf(title_string,
- L"%s ABORT %s %hs",
- kAppName,
- app_util::GetAppName(),
- omaha::GetVersionString());
- MessageBox(NULL,
- error_string,
- title_string,
- MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
-
- if (do_abort) {
- abort();
- }
-}
-#endif
-
-
-#ifdef _DEBUG
-
-void DumpInterface(IUnknown* unknown) {
- if (!unknown)
- return;
-
- OutputDebugString(_T("------------------------------------------------\r\n"));
-
- // Open the HKCR\Interfaces key where the IIDs of marshalable interfaces
- // are stored.
- RegKey key;
- if (SUCCEEDED(key.Open(HKEY_CLASSES_ROOT, _T("Interface"), KEY_READ))) {
- TCHAR name[_MAX_PATH + 1] = {0};
- DWORD name_size = _MAX_PATH;
- DWORD index = 0;
- FILETIME last_written;
-
- //
- // Enumerate through the IIDs and see if the object supports it
- // by calling QueryInterface.
- //
- while (::RegEnumKeyEx(key.Key(),
- index++,
- name,
- &name_size,
- NULL,
- NULL,
- NULL,
- &last_written) == ERROR_SUCCESS) {
- // Convert the string to an IID
- IID iid;
- HRESULT hr = StringToGuidSafe(name, &iid);
-
- CComPtr<IUnknown> test;
- if (unknown->QueryInterface(iid,
- reinterpret_cast<void**>(&test)) == S_OK) {
- //
- // The object supports this interface.
- // See if we can get a human readable name for the interface
- // If not, the name buffer already contains the string
- // representation of the IID, which we'll use as a fallback.
- //
- RegKey sub_key;
- if (sub_key.Open(key.Key(), name, KEY_READ) == S_OK) {
- scoped_array<TCHAR> display;
- // If this fails, we should still have the IID
- if (sub_key.GetValue(NULL, address(display)) == S_OK)
- lstrcpyn(name, display.get(), _MAX_PATH);
- }
-
- CString fmt;
- SafeCStringFormat(&fmt, _T(" %s\r\n"), name);
- OutputDebugString(fmt);
- }
-
- ZeroMemory(name, arraysize(name));
- name_size = _MAX_PATH;
- }
- }
-
- OutputDebugString(_T("------------------------------------------------\r\n"));
-}
-#endif
-
-// TODO(omaha): the implementation below is using CStrings so it is not very
-// conservative in terms of memory allocations.
-int SehNoMinidump(unsigned int code, struct _EXCEPTION_POINTERS *,
- const char *filename, int32 linenumber, bool show_message) {
- if (code == EXCEPTION_BREAKPOINT)
- return EXCEPTION_CONTINUE_SEARCH;
-
- uint32 latest_cl = 0;
-#ifdef VERSION_LATEST_CL
- latest_cl = VERSION_LATEST_CL;
-#endif
-
- if (show_message) {
- TCHAR message[1025] = {0};
- wsprintf(message,
- _T("Exception %x in %s %s %u\r\n\r\n%hs:%d\r\n"),
- code,
- app_util::GetAppName(),
- omaha::GetVersionString(),
- latest_cl,
- filename,
- linenumber);
-
- SetClipboard(message);
- uint32 type = MB_ABORTRETRYIGNORE |
- MB_ICONERROR |
- MB_SERVICE_NOTIFICATION |
- MB_SETFOREGROUND |
- MB_TOPMOST;
- int ret = ::MessageBox(NULL, message, _T("Exception"), type);
- switch (ret) {
- case IDABORT:
- // Kamikaze if the user chose 'abort'
- ::ExitProcess(static_cast<UINT>(-1));
- break;
-
- case IDRETRY:
- // Break if the user chose "retry"
- __debugbreak();
- break;
-
- default:
- // By default we ignore the message
- break;
- }
- }
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-CString GetDebugDirectory() {
- CString debug_dir;
- CString system_drive = GetEnvironmentVariableAsString(_T("SystemDrive"));
- if (!system_drive.IsEmpty()) {
- debug_dir += system_drive;
- debug_dir += L"\\";
- }
- debug_dir += kCiDebugDirectory;
- return debug_dir;
-}
-
-} // namespace omaha
-
« no previous file with comments | « base/debug.h ('k') | base/debug_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698