1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/crash_upload_list_win.h" 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/stringprintf.h" 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h" 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/sys_string_conversions.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenCrashUploadListWin::CrashUploadListWin(Delegate* delegate) 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : CrashUploadList(delegate) {} 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid CrashUploadListWin::LoadCrashList() { 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<uint8> buffer(1024); 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HANDLE event_log = OpenEventLog(NULL, L"Application"); 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (event_log) { 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (true) { 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DWORD bytes_read; 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DWORD bytes_needed; 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BOOL success = 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ReadEventLog(event_log, 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 0, 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &buffer[0], 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen buffer.size(), 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &bytes_read, 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &bytes_needed); 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (success) { 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DWORD record_offset = 0; 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The ReadEventLog() API docs imply, but do not explicitly state that 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // partial records will not be returned. Use DCHECK() to affirm this. 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (record_offset < bytes_read) { 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(record_offset + sizeof(EVENTLOGRECORD) <= bytes_read); 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EVENTLOGRECORD* record = (EVENTLOGRECORD*)&buffer[record_offset]; 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(record_offset + record->Length <= bytes_read); 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsPossibleCrashLogRecord(record)) 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProcessPossibleCrashLogRecord(record); 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record_offset += record->Length; 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Resize buffer to the required minimum size. 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen buffer.resize(bytes_needed); 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Stop on any other error, including the expected case 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // of ERROR_HANDLE_EOF. 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(GetLastError() == ERROR_HANDLE_EOF); 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CloseEventLog(event_log); 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool CrashUploadListWin::IsPossibleCrashLogRecord( 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EVENTLOGRECORD* record) const { 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LPWSTR provider_name = (LPWSTR)((uint8*)record + sizeof(EVENTLOGRECORD)); 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return !wcscmp(L"Chrome", provider_name) && 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record->EventType == EVENTLOG_INFORMATION_TYPE && 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen record->NumStrings >= 1; 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid CrashUploadListWin::ProcessPossibleCrashLogRecord(EVENTLOGRECORD* record) { 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add the crash if the message matches the expected pattern. 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::wstring pattern_prefix(L"Id="); 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::wstring pattern_suffix(L"."); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring message((LPWSTR)((uint8*)record + record->StringOffset)); 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_t start_index = message.find(pattern_prefix); 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (start_index != std::wstring::npos) { 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen start_index += pattern_prefix.size(); 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_t end_index = message.find(pattern_suffix, start_index); 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (end_index != std::wstring::npos) { 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring crash_id = 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen message.substr(start_index, end_index - start_index); 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crashes().push_back( 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CrashInfo(base::SysWideToUTF8(crash_id), 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Time::FromDoubleT(record->TimeGenerated))); 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 81