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