15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/crash/tools/crash_service.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sddl.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/windows/crash_generation/client_info.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/windows/crash_generation/crash_generation_server.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/windows/sender/crash_report_sender.h" 208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace breakpad { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kTestPipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kCrashReportURL[] = L"https://clients2.google.com/cr/report"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kCheckPointFile[] = L"crash_checkpoint.txt"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<std::wstring, std::wstring> CrashMap; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CustomInfoToMap(const google_breakpad::ClientInfo* client_info, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& reporter_tag, CrashMap* map) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) google_breakpad::CustomClientInfo info = client_info->GetCustomInfo(); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uintptr_t i = 0; i < info.count; ++i) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*map)[info.entries[i].name] = info.entries[i].value; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*map)[L"rept"] = reporter_tag; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !map->empty(); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WriteCustomInfoToFile(const std::wstring& dump_path, const CrashMap& map) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring file_path(dump_path); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t last_dot = file_path.rfind(L'.'); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_dot == std::wstring::npos) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_path.resize(last_dot); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_path += L".txt"; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wofstream file(file_path.c_str(), 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::ios_base::out | std::ios_base::app | std::ios::binary); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file.is_open()) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashMap::const_iterator pos; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (pos = map.begin(); pos != map.end(); ++pos) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring line = pos->first; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line += L':'; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line += pos->second; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line += L'\n'; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file.write(line.c_str(), static_cast<std::streamsize>(line.length())); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The window procedure task is to handle when a) the user logs off. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// b) the system shuts down or c) when the user closes the window. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LRESULT __stdcall CrashSvcWndProc(HWND hwnd, UINT message, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WPARAM wparam, LPARAM lparam) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (message) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_CLOSE: 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_ENDSESSION: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WM_DESTROY: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PostQuitMessage(0); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DefWindowProc(hwnd, message, wparam, lparam); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the main and only application window. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWND g_top_window = NULL; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateTopWindow(HINSTANCE instance, bool visible) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WNDCLASSEXW wcx = {0}; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wcx.cbSize = sizeof(wcx); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wcx.style = CS_HREDRAW | CS_VREDRAW; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wcx.lpfnWndProc = CrashSvcWndProc; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wcx.hInstance = instance; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wcx.lpszClassName = L"crash_svc_class"; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ATOM atom = ::RegisterClassExW(&wcx); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD style = visible ? WS_POPUPWINDOW | WS_VISIBLE : WS_OVERLAPPED; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window size is zero but being a popup window still shows in the 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // task bar and can be closed using the system menu or using task manager. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND window = CreateWindowExW(0, wcx.lpszClassName, L"crash service", style, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, NULL, instance, NULL); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::UpdateWindow(window); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "window handle is " << window; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_top_window = window; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple helper class to keep the process alive until the current request 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// finishes. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProcessingLock { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessingLock() { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::InterlockedIncrement(&op_count_); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ProcessingLock() { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::InterlockedDecrement(&op_count_); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsWorking() { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (op_count_ != 0); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static volatile LONG op_count_; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)volatile LONG ProcessingLock::op_count_ = 0; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This structure contains the information that the worker thread needs to 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// send a crash dump to the server. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DumpJobInfo { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD pid; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashService* self; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashMap map; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring dump_path; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpJobInfo(DWORD process_id, CrashService* service, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CrashMap& crash_map, const std::wstring& path) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : pid(process_id), self(service), map(crash_map), dump_path(path) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Command line switches: 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kMaxReports[] = "max-reports"; 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kNoWindow[] = "no-window"; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kReporterTag[] = "reporter"; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kDumpsDir[] = "dumps-dir"; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char CrashService::kPipeName[] = "pipe-name"; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)CrashService::CrashService() 1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : sender_(NULL), 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dumper_(NULL), 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requests_handled_(0), 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requests_sent_(0), 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clients_connected_(0), 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clients_terminated_(0) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrashService::~CrashService() { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(sending_); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete dumper_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete sender_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool CrashService::Initialize(const base::FilePath& operating_dir, 1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const base::FilePath& dumps_path) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using google_breakpad::CrashReportSender; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using google_breakpad::CrashGenerationServer; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring pipe_name = kTestPipeName; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_reports = -1; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The checkpoint file allows CrashReportSender to enforce the the maximum 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reports per day quota. Does not seem to serve any other purpose. 1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::FilePath checkpoint_path = operating_dir.Append(kCheckPointFile); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); 1828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::FilePath dumps_path_to_use = dumps_path; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch(kDumpsDir)) { 1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) dumps_path_to_use = 1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::FilePath(cmd_line.GetSwitchValueNative(kDumpsDir)); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can override the send reports quota with a command line switch. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch(kMaxReports)) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_reports = _wtoi(cmd_line.GetSwitchValueNative(kMaxReports).c_str()); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow the global pipe name to be overridden for better testability. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch(kPipeName)) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_name = cmd_line.GetSwitchValueNative(kPipeName); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN64 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_name += L"-x64"; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_reports > 0) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the http sender object. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sender_ = new CrashReportSender(checkpoint_path.value()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sender_->set_max_reports_per_day(max_reports); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_ATTRIBUTES security_attributes = {0}; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_ATTRIBUTES* security_attributes_actual = NULL; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_DESCRIPTOR* security_descriptor = 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<SECURITY_DESCRIPTOR*>( 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSecurityDescriptorForLowIntegrity()); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(security_descriptor != NULL); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) security_attributes.nLength = sizeof(security_attributes); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) security_attributes.lpSecurityDescriptor = security_descriptor; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) security_attributes.bInheritHandle = FALSE; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) security_attributes_actual = &security_attributes; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the OOP crash generator object. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dumper_ = new CrashGenerationServer(pipe_name, security_attributes_actual, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &CrashService::OnClientConnected, this, 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &CrashService::OnClientDumpRequest, this, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &CrashService::OnClientExited, this, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, NULL, 2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) true, &dumps_path_to_use.value()); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dumper_) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "could not create dumper"; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (security_attributes.lpSecurityDescriptor) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalFree(security_attributes.lpSecurityDescriptor); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateTopWindow(::GetModuleHandleW(NULL), 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !cmd_line.HasSwitch(kNoWindow))) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "could not create window"; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (security_attributes.lpSecurityDescriptor) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalFree(security_attributes.lpSecurityDescriptor); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reporter_tag_ = L"crash svc"; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_line.HasSwitch(kReporterTag)) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reporter_tag_ = cmd_line.GetSwitchValueNative(kReporterTag); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Log basic information. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "pipe name is " << pipe_name 2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) << "\ndumps at " << dumps_path_to_use.value(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sender_) { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "checkpoint is " << checkpoint_path.value() 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\nserver is " << kCrashReportURL 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\nmaximum " << sender_->max_reports_per_day() << " reports/day" 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\nreporter is " << reporter_tag_; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start servicing clients. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dumper_->Start()) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "could not start dumper"; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (security_attributes.lpSecurityDescriptor) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalFree(security_attributes.lpSecurityDescriptor); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (security_attributes.lpSecurityDescriptor) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalFree(security_attributes.lpSecurityDescriptor); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is throwaway code. We don't need to sync with the browser process 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // once Google Update is updated to a version supporting OOP crash handling. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create or open an event to signal the browser process that the crash 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // service is initialized. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE running_event = 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CreateEventW(NULL, TRUE, TRUE, L"g_chrome_crash_svc"); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the browser already had the event open, the CreateEvent call did not 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // signal it. We need to do it manually. 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetEvent(running_event); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashService::OnClientConnected(void* context, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const google_breakpad::ClientInfo* client_info) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessingLock lock; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "client start. pid = " << client_info->pid(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashService* self = static_cast<CrashService*>(context); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::InterlockedIncrement(&self->clients_connected_); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashService::OnClientExited(void* context, 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const google_breakpad::ClientInfo* client_info) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessingLock lock; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "client end. pid = " << client_info->pid(); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashService* self = static_cast<CrashService*>(context); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::InterlockedIncrement(&self->clients_terminated_); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!self->sender_) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we are instructed to send reports we need to exit if there are 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no more clients to service. The next client that runs will start us. 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only chrome.exe starts crash_service with a non-zero max_reports. 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (self->clients_connected_ > self->clients_terminated_) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (self->sender_->max_reports_per_day() > 0) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the other thread to send crashes, if applicable. The sender 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread takes the sending_ lock, so the sleep is just to give it a 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chance to start. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(1000); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(self->sending_); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some people can restart chrome very fast, check again if we have 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a new client before exiting for real. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (self->clients_connected_ == self->clients_terminated_) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "zero clients. exiting"; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::PostMessage(g_top_window, WM_CLOSE, 0, 0); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashService::OnClientDumpRequest(void* context, 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const google_breakpad::ClientInfo* client_info, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring* file_path) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessingLock lock; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file_path) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "dump with no file path"; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!client_info) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "dump with no client info"; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashService* self = static_cast<CrashService*>(context); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!self) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "dump with no context"; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrashMap map; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CustomInfoToMap(client_info, self->reporter_tag_, &map); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Move dump file to the directory under client breakpad dump location. 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath dump_location = base::FilePath(*file_path); 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CrashMap::const_iterator it = map.find(L"breakpad-dump-location"); 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != map.end()) { 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath alternate_dump_location = base::FilePath(it->second); 351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CreateDirectoryW(alternate_dump_location); 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alternate_dump_location = alternate_dump_location.Append( 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dump_location.BaseName()); 354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Move(dump_location, alternate_dump_location); 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dump_location = alternate_dump_location; 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DWORD pid = client_info->pid(); 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "dump for pid = " << pid << " is " << dump_location.value(); 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!WriteCustomInfoToFile(dump_location.value(), map)) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "could not write custom info file"; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!self->sender_) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the crash dump using a worker thread. This operation has retry 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // logic in case there is no internet connection at the time. 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DumpJobInfo* dump_job = new DumpJobInfo(pid, self, map, 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dump_location.value()); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::QueueUserWorkItem(&CrashService::AsyncSendDump, 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dump_job, WT_EXECUTELONGFUNCTION)) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "could not queue job"; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We are going to try sending the report several times. If we can't send, 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we sleep from one minute to several hours depending on the retry round. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned long CrashService::AsyncSendDump(void* context) { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpJobInfo* info = static_cast<DumpJobInfo*>(context); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring report_id = L"<unsent>"; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DWORD kOneMinute = 60*1000; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DWORD kOneHour = 60*kOneMinute; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DWORD kSleepSchedule[] = { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24*kOneHour, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8*kOneHour, 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4*kOneHour, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kOneHour, 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15*kOneMinute, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0}; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int retry_round = arraysize(kSleepSchedule) - 1; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(kSleepSchedule[retry_round]); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Take the server lock while sending. This also prevent early 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // termination of the service object. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(info->self->sending_); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "trying to send report for pid = " << info->pid; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) google_breakpad::ReportResult send_result 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = info->self->sender_->SendCrashReport(kCrashReportURL, info->map, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->dump_path, &report_id); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (send_result) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case google_breakpad::RESULT_FAILED: 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_id = L"<network issue>"; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case google_breakpad::RESULT_REJECTED: 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_id = L"<rejected>"; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++info->self->requests_handled_; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retry_round = 0; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case google_breakpad::RESULT_SUCCEEDED: 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++info->self->requests_sent_; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++info->self->requests_handled_; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retry_round = 0; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case google_breakpad::RESULT_THROTTLED: 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_id = L"<throttled>"; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_id = L"<unknown>"; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "dump for pid =" << info->pid << " crash2 id =" << report_id; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --retry_round; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (retry_round >= 0); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::DeleteFileW(info->dump_path.c_str())) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "could not delete " << info->dump_path; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete info; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CrashService::ProcessingLoop() { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MSG msg; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (GetMessage(&msg, NULL, 0, 0)) { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TranslateMessage(&msg); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DispatchMessage(&msg); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "session ending.."; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (ProcessingLock::IsWorking()) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(50); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "clients connected :" << clients_connected_ 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\nclients terminated :" << clients_terminated_ 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\ndumps serviced :" << requests_handled_ 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\ndumps reported :" << requests_sent_; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(msg.wParam); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PSECURITY_DESCRIPTOR CrashService::GetSecurityDescriptorForLowIntegrity() { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build the SDDL string for the label. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring sddl = L"S:(ML;;NW;;;S-1-16-4096)"; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD error = ERROR_SUCCESS; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PSECURITY_DESCRIPTOR sec_desc = NULL; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PACL sacl = NULL; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL sacl_present = FALSE; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL sacl_defaulted = FALSE; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl.c_str(), 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SDDL_REVISION, 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sec_desc, NULL)) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::GetSecurityDescriptorSacl(sec_desc, &sacl_present, &sacl, 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sacl_defaulted)) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sec_desc; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 4888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} // namespace breakpad 489