Home | History | Annotate | Download | only in chrome_frame
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome_frame/crash_server_init.h"
      6 
      7 #include <sddl.h>
      8 #include <Shlobj.h>
      9 #include <stdlib.h>
     10 #include "version.h"  // NOLINT
     11 
     12 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
     13 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
     14 const wchar_t kSystemPrincipalSid[] = L"S-1-5-18";
     15 
     16 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
     17     MiniDumpWithProcessThreadData |  // Get PEB and TEB.
     18     MiniDumpWithUnloadedModules |  // Get unloaded modules when available.
     19     MiniDumpWithIndirectlyReferencedMemory);  // Get memory referenced by stack.
     20 
     21 extern "C" IMAGE_DOS_HEADER __ImageBase;
     22 
     23 // Builds a string representation of the user's SID and places it in user_sid.
     24 bool GetUserSidString(std::wstring* user_sid) {
     25   bool success = false;
     26   if (user_sid) {
     27     struct {
     28       TOKEN_USER token_user;
     29       BYTE buffer[SECURITY_MAX_SID_SIZE];
     30     } token_info_buffer;
     31 
     32     HANDLE token = NULL;
     33     if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
     34       DWORD out_size;
     35       if (GetTokenInformation(token, TokenUser, &token_info_buffer.token_user,
     36                               sizeof(token_info_buffer), &out_size)) {
     37         wchar_t* user_sid_value = NULL;
     38         if (token_info_buffer.token_user.User.Sid &&
     39             ConvertSidToStringSid(token_info_buffer.token_user.User.Sid,
     40                                   &user_sid_value)) {
     41           *user_sid = user_sid_value;
     42           LocalFree(user_sid_value);
     43           user_sid_value = NULL;
     44           success = true;
     45         }
     46       }
     47       CloseHandle(token);
     48     }
     49   }
     50 
     51   return success;
     52 }
     53 
     54 bool IsRunningSystemInstall() {
     55   wchar_t exe_path[MAX_PATH * 2] = {0};
     56   GetModuleFileName(reinterpret_cast<HMODULE>(&__ImageBase),
     57                     exe_path,
     58                     _countof(exe_path));
     59 
     60   bool is_system = false;
     61 
     62   wchar_t program_files_path[MAX_PATH] = {0};
     63   if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
     64                                 SHGFP_TYPE_CURRENT, program_files_path))) {
     65     if (wcsstr(exe_path, program_files_path) == exe_path) {
     66       is_system = true;
     67     }
     68   }
     69 
     70   return is_system;
     71 }
     72 
     73 google_breakpad::CustomClientInfo* GetCustomInfo() {
     74   static google_breakpad::CustomInfoEntry ver_entry(
     75       L"ver", TEXT(CHROME_VERSION_STRING));
     76   static google_breakpad::CustomInfoEntry prod_entry(L"prod", L"ChromeFrame");
     77   static google_breakpad::CustomInfoEntry plat_entry(L"plat", L"Win32");
     78   static google_breakpad::CustomInfoEntry type_entry(L"ptype", L"chrome_frame");
     79   static google_breakpad::CustomInfoEntry entries[] = {
     80       ver_entry, prod_entry, plat_entry, type_entry };
     81   static google_breakpad::CustomClientInfo custom_info = {
     82       entries, ARRAYSIZE(entries) };
     83   return &custom_info;
     84 }
     85 
     86 google_breakpad::ExceptionHandler* InitializeCrashReporting(
     87     CrashReportingMode mode) {
     88   wchar_t temp_path[MAX_PATH + 1] = {0};
     89   DWORD path_len = ::GetTempPath(MAX_PATH, temp_path);
     90 
     91   std::wstring pipe_name;
     92   if (mode == HEADLESS) {
     93     // This flag is used for testing, connect to the test crash service.
     94     pipe_name = kChromePipeName;
     95   } else {
     96     // Otherwise, build a pipe name corresponding to either user or
     97     // system-level Omaha.
     98     pipe_name = kGoogleUpdatePipeName;
     99     if (IsRunningSystemInstall()) {
    100       pipe_name += kSystemPrincipalSid;
    101     } else {
    102       std::wstring user_sid;
    103       if (GetUserSidString(&user_sid)) {
    104         pipe_name += user_sid;
    105       } else {
    106         // We don't think we're a system install, but we couldn't get the
    107         // user SID. Try connecting to the system-level crash service as a
    108         // last ditch effort.
    109         pipe_name += kSystemPrincipalSid;
    110       }
    111     }
    112   }
    113 
    114   google_breakpad::ExceptionHandler* breakpad =
    115       new google_breakpad::ExceptionHandler(
    116           temp_path, NULL, NULL, NULL,
    117           google_breakpad::ExceptionHandler::HANDLER_ALL, kLargerDumpType,
    118           pipe_name.c_str(), GetCustomInfo());
    119 
    120   return breakpad;
    121 }
    122