// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "client/windows/crash_generation/minidump_generator.h"

#include <assert.h>
#include <avrfsdk.h>

#include <algorithm>
#include <iterator>
#include <list>
#include <vector>

#include "client/windows/common/auto_critical_section.h"
#include "common/scoped_ptr.h"
#include "common/windows/guid_string.h"

using std::wstring;

namespace {

// A helper class used to collect handle operations data. Unlike
// |MiniDumpWithHandleData| it records the operations for a single handle value
// only, making it possible to include this information to a minidump.
class HandleTraceData {
 public:
  HandleTraceData();
  ~HandleTraceData();

  // Collects the handle operations data and formats a user stream to be added
  // to the minidump.
  bool CollectHandleData(HANDLE process_handle,
                         EXCEPTION_POINTERS* exception_pointers);

  // Fills the user dump entry with a pointer to the collected handle operations
  // data. Returns |true| if the entry was initialized successfully, or |false|
  // if no trace data is available.
  bool GetUserStream(MINIDUMP_USER_STREAM* user_stream);

 private:
  // Reads the exception code from the client process's address space.
  // This routine assumes that the client process's pointer width matches ours.
  static bool ReadExceptionCode(HANDLE process_handle,
                                EXCEPTION_POINTERS* exception_pointers,
                                DWORD* exception_code);

  // Stores handle operations retrieved by VerifierEnumerateResource().
  static ULONG CALLBACK RecordHandleOperations(void* resource_description,
                                               void* enumeration_context,
                                               ULONG* enumeration_level);

  // Function pointer type for VerifierEnumerateResource, which is looked up
  // dynamically.
  typedef BOOL (WINAPI* VerifierEnumerateResourceType)(
      HANDLE Process,
      ULONG Flags,
      ULONG ResourceType,
      AVRF_RESOURCE_ENUMERATE_CALLBACK ResourceCallback,
      PVOID EnumerationContext);

  // Handle to dynamically loaded verifier.dll.
  HMODULE verifier_module_;

  // Pointer to the VerifierEnumerateResource function.
  VerifierEnumerateResourceType enumerate_resource_;

  // Handle value to look for.
  ULONG64 handle_;

  // List of handle operations for |handle_|.
  std::list<AVRF_HANDLE_OPERATION> operations_;

  // Minidump stream data.
  std::vector<char> stream_;
};

HandleTraceData::HandleTraceData()
    : verifier_module_(NULL),
      enumerate_resource_(NULL),
      handle_(NULL) {
}

HandleTraceData::~HandleTraceData() {
  if (verifier_module_) {
    FreeLibrary(verifier_module_);
  }
}

bool HandleTraceData::CollectHandleData(
    HANDLE process_handle,
    EXCEPTION_POINTERS* exception_pointers) {
  DWORD exception_code;
  if (!ReadExceptionCode(process_handle, exception_pointers, &exception_code)) {
    return false;
  }

  // Verify whether the execption is STATUS_INVALID_HANDLE. Do not record any
  // handle information if it is a different exception to keep the minidump
  // small.
  if (exception_code != STATUS_INVALID_HANDLE) {
    return true;
  }

  // Load verifier!VerifierEnumerateResource() dynamically.
  verifier_module_ = LoadLibrary(TEXT("verifier.dll"));
  if (!verifier_module_) {
    return false;
  }

  enumerate_resource_ = reinterpret_cast<VerifierEnumerateResourceType>(
      GetProcAddress(verifier_module_, "VerifierEnumerateResource"));
  if (!enumerate_resource_) {
    return false;
  }

  // STATUS_INVALID_HANDLE does not provide the offending handle value in
  // the exception parameters so we have to guess. At the moment we scan
  // the handle operations trace looking for the last invalid handle operation
  // and record only the operations for that handle value.
  if (enumerate_resource_(process_handle,
                          0,
                          AvrfResourceHandleTrace,
                          &RecordHandleOperations,
                          this) != ERROR_SUCCESS) {
    // The handle tracing must have not been enabled.
    return true;
  }

  // Now that |handle_| is initialized, purge all irrelevant operations.
  std::list<AVRF_HANDLE_OPERATION>::iterator i = operations_.begin();
  std::list<AVRF_HANDLE_OPERATION>::iterator i_end = operations_.end();
  while (i != i_end) {
    if (i->Handle == handle_) {
      ++i;
    } else {
      i = operations_.erase(i);
    }
  }

  // Convert the list of recorded operations to a minidump stream.
  stream_.resize(sizeof(MINIDUMP_HANDLE_OPERATION_LIST) +
      sizeof(AVRF_HANDLE_OPERATION) * operations_.size());

  MINIDUMP_HANDLE_OPERATION_LIST* stream_data =
      reinterpret_cast<MINIDUMP_HANDLE_OPERATION_LIST*>(
          &stream_.front());
  stream_data->SizeOfHeader = sizeof(MINIDUMP_HANDLE_OPERATION_LIST);
  stream_data->SizeOfEntry = sizeof(AVRF_HANDLE_OPERATION);
  stream_data->NumberOfEntries = static_cast<ULONG32>(operations_.size());
  stream_data->Reserved = 0;
  std::copy(operations_.begin(),
            operations_.end(),
#ifdef _MSC_VER
            stdext::checked_array_iterator<AVRF_HANDLE_OPERATION*>(
                reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1),
                operations_.size())
#else
            reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1)
#endif
            );

  return true;
}

bool HandleTraceData::GetUserStream(MINIDUMP_USER_STREAM* user_stream) {
  if (stream_.empty()) {
    return false;
  } else {
    user_stream->Type = HandleOperationListStream;
    user_stream->BufferSize = static_cast<ULONG>(stream_.size());
    user_stream->Buffer = &stream_.front();
    return true;
  }
}

bool HandleTraceData::ReadExceptionCode(
    HANDLE process_handle,
    EXCEPTION_POINTERS* exception_pointers,
    DWORD* exception_code) {
  EXCEPTION_POINTERS pointers;
  if (!ReadProcessMemory(process_handle,
                         exception_pointers,
                         &pointers,
                         sizeof(pointers),
                         NULL)) {
    return false;
  }

  if (!ReadProcessMemory(process_handle,
                         pointers.ExceptionRecord,
                         exception_code,
                         sizeof(*exception_code),
                         NULL)) {
    return false;
  }

  return true;
}

ULONG CALLBACK HandleTraceData::RecordHandleOperations(
    void* resource_description,
    void* enumeration_context,
    ULONG* enumeration_level) {
  AVRF_HANDLE_OPERATION* description =
      reinterpret_cast<AVRF_HANDLE_OPERATION*>(resource_description);
  HandleTraceData* self =
      reinterpret_cast<HandleTraceData*>(enumeration_context);

  // Remember the last invalid handle operation.
  if (description->OperationType == OperationDbBADREF) {
    self->handle_ = description->Handle;
  }

  // Record all handle operations.
  self->operations_.push_back(*description);

  *enumeration_level = HeapEnumerationEverything;
  return ERROR_SUCCESS;
}

}  // namespace

namespace google_breakpad {

MinidumpGenerator::MinidumpGenerator(
    const std::wstring& dump_path,
    const HANDLE process_handle,
    const DWORD process_id,
    const DWORD thread_id,
    const DWORD requesting_thread_id,
    EXCEPTION_POINTERS* exception_pointers,
    MDRawAssertionInfo* assert_info,
    const MINIDUMP_TYPE dump_type,
    const bool is_client_pointers)
    : dbghelp_module_(NULL),
      rpcrt4_module_(NULL),
      dump_path_(dump_path),
      process_handle_(process_handle),
      process_id_(process_id),
      thread_id_(thread_id),
      requesting_thread_id_(requesting_thread_id),
      exception_pointers_(exception_pointers),
      assert_info_(assert_info),
      dump_type_(dump_type),
      is_client_pointers_(is_client_pointers),
      dump_file_(INVALID_HANDLE_VALUE),
      full_dump_file_(INVALID_HANDLE_VALUE),
      dump_file_is_internal_(false),
      full_dump_file_is_internal_(false),
      additional_streams_(NULL),
      callback_info_(NULL),
      write_dump_(NULL),
      create_uuid_(NULL) {
  InitializeCriticalSection(&module_load_sync_);
  InitializeCriticalSection(&get_proc_address_sync_);
}

MinidumpGenerator::~MinidumpGenerator() {
  if (dump_file_is_internal_ && dump_file_ != INVALID_HANDLE_VALUE) {
    CloseHandle(dump_file_);
  }

  if (full_dump_file_is_internal_ && full_dump_file_ != INVALID_HANDLE_VALUE) {
    CloseHandle(full_dump_file_);
  }

  if (dbghelp_module_) {
    FreeLibrary(dbghelp_module_);
  }

  if (rpcrt4_module_) {
    FreeLibrary(rpcrt4_module_);
  }

  DeleteCriticalSection(&get_proc_address_sync_);
  DeleteCriticalSection(&module_load_sync_);
}

bool MinidumpGenerator::WriteMinidump() {
  bool full_memory_dump = (dump_type_ & MiniDumpWithFullMemory) != 0;
  if (dump_file_ == INVALID_HANDLE_VALUE ||
      (full_memory_dump && full_dump_file_ == INVALID_HANDLE_VALUE)) {
    return false;
  }

  MiniDumpWriteDumpType write_dump = GetWriteDump();
  if (!write_dump) {
    return false;
  }

  MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = NULL;
  MINIDUMP_EXCEPTION_INFORMATION dump_exception_info;

  // Setup the exception information object only if it's a dump
  // due to an exception.
  if (exception_pointers_) {
    dump_exception_pointers = &dump_exception_info;
    dump_exception_info.ThreadId = thread_id_;
    dump_exception_info.ExceptionPointers = exception_pointers_;
    dump_exception_info.ClientPointers = is_client_pointers_;
  }

  // Add an MDRawBreakpadInfo stream to the minidump, to provide additional
  // information about the exception handler to the Breakpad processor.
  // The information will help the processor determine which threads are
  // relevant. The Breakpad processor does not require this information but
  // can function better with Breakpad-generated dumps when it is present.
  // The native debugger is not harmed by the presence of this information.
  MDRawBreakpadInfo breakpad_info = {0};
  if (!is_client_pointers_) {
    // Set the dump thread id and requesting thread id only in case of
    // in-process dump generation.
    breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
                             MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
    breakpad_info.dump_thread_id = thread_id_;
    breakpad_info.requesting_thread_id = requesting_thread_id_;
  }

  int additional_streams_count = additional_streams_ ?
      additional_streams_->UserStreamCount : 0;
  scoped_array<MINIDUMP_USER_STREAM> user_stream_array(
      new MINIDUMP_USER_STREAM[3 + additional_streams_count]);
  user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM;
  user_stream_array[0].BufferSize = sizeof(breakpad_info);
  user_stream_array[0].Buffer = &breakpad_info;

  MINIDUMP_USER_STREAM_INFORMATION user_streams;
  user_streams.UserStreamCount = 1;
  user_streams.UserStreamArray = user_stream_array.get();

  MDRawAssertionInfo* actual_assert_info = assert_info_;
  MDRawAssertionInfo client_assert_info = {{0}};

  if (assert_info_) {
    // If the assertion info object lives in the client process,
    // read the memory of the client process.
    if (is_client_pointers_) {
      SIZE_T bytes_read = 0;
      if (!ReadProcessMemory(process_handle_,
                             assert_info_,
                             &client_assert_info,
                             sizeof(client_assert_info),
                             &bytes_read)) {
        if (dump_file_is_internal_)
          CloseHandle(dump_file_);
        if (full_dump_file_is_internal_ &&
            full_dump_file_ != INVALID_HANDLE_VALUE)
          CloseHandle(full_dump_file_);
        return false;
      }

      if (bytes_read != sizeof(client_assert_info)) {
        if (dump_file_is_internal_)
          CloseHandle(dump_file_);
        if (full_dump_file_is_internal_ &&
            full_dump_file_ != INVALID_HANDLE_VALUE)
          CloseHandle(full_dump_file_);
        return false;
      }

      actual_assert_info  = &client_assert_info;
    }

    user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM;
    user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo);
    user_stream_array[1].Buffer = actual_assert_info;
    ++user_streams.UserStreamCount;
  }

  if (additional_streams_) {
    for (size_t i = 0;
         i < additional_streams_->UserStreamCount;
         i++, user_streams.UserStreamCount++) {
      user_stream_array[user_streams.UserStreamCount].Type =
          additional_streams_->UserStreamArray[i].Type;
      user_stream_array[user_streams.UserStreamCount].BufferSize =
          additional_streams_->UserStreamArray[i].BufferSize;
      user_stream_array[user_streams.UserStreamCount].Buffer =
          additional_streams_->UserStreamArray[i].Buffer;
    }
  }

  // If the process is terminated by STATUS_INVALID_HANDLE exception store
  // the trace of operations for the offending handle value. Do nothing special
  // if the client already requested the handle trace to be stored in the dump.
  HandleTraceData handle_trace_data;
  if (exception_pointers_ && (dump_type_ & MiniDumpWithHandleData) == 0) {
    if (!handle_trace_data.CollectHandleData(process_handle_,
                                             exception_pointers_)) {
      if (dump_file_is_internal_)
        CloseHandle(dump_file_);
      if (full_dump_file_is_internal_ &&
          full_dump_file_ != INVALID_HANDLE_VALUE)
        CloseHandle(full_dump_file_);
      return false;
    }
  }

  bool result_full_memory = true;
  if (full_memory_dump) {
    result_full_memory = write_dump(
        process_handle_,
        process_id_,
        full_dump_file_,
        static_cast<MINIDUMP_TYPE>((dump_type_ & (~MiniDumpNormal))
                                    | MiniDumpWithHandleData),
        exception_pointers_ ? &dump_exception_info : NULL,
        &user_streams,
        NULL) != FALSE;
  }

  // Add handle operations trace stream to the minidump if it was collected.
  if (handle_trace_data.GetUserStream(
          &user_stream_array[user_streams.UserStreamCount])) {
    ++user_streams.UserStreamCount;
  }

  bool result_minidump = write_dump(
      process_handle_,
      process_id_,
      dump_file_,
      static_cast<MINIDUMP_TYPE>((dump_type_ & (~MiniDumpWithFullMemory))
                                  | MiniDumpNormal),
      exception_pointers_ ? &dump_exception_info : NULL,
      &user_streams,
      callback_info_) != FALSE;

  return result_minidump && result_full_memory;
}

bool MinidumpGenerator::GenerateDumpFile(wstring* dump_path) {
  // The dump file was already set by handle or this function was previously
  // called.
  if (dump_file_ != INVALID_HANDLE_VALUE) {
    return false;
  }

  wstring dump_file_path;
  if (!GenerateDumpFilePath(&dump_file_path)) {
    return false;
  }

  dump_file_ = CreateFile(dump_file_path.c_str(),
                          GENERIC_WRITE,
                          0,
                          NULL,
                          CREATE_NEW,
                          FILE_ATTRIBUTE_NORMAL,
                          NULL);
  if (dump_file_ == INVALID_HANDLE_VALUE) {
    return false;
  }

  dump_file_is_internal_ = true;
  *dump_path = dump_file_path;
  return true;
}

bool MinidumpGenerator::GenerateFullDumpFile(wstring* full_dump_path) {
  // A full minidump was not requested.
  if ((dump_type_ & MiniDumpWithFullMemory) == 0) {
    return false;
  }

  // The dump file was already set by handle or this function was previously
  // called.
  if (full_dump_file_ != INVALID_HANDLE_VALUE) {
    return false;
  }

  wstring full_dump_file_path;
  if (!GenerateDumpFilePath(&full_dump_file_path)) {
    return false;
  }
  full_dump_file_path.resize(full_dump_file_path.size() - 4);  // strip .dmp
  full_dump_file_path.append(TEXT("-full.dmp"));

  full_dump_file_ = CreateFile(full_dump_file_path.c_str(),
                               GENERIC_WRITE,
                               0,
                               NULL,
                               CREATE_NEW,
                               FILE_ATTRIBUTE_NORMAL,
                               NULL);
  if (full_dump_file_ == INVALID_HANDLE_VALUE) {
    return false;
  }

  full_dump_file_is_internal_ = true;
  *full_dump_path = full_dump_file_path;
  return true;
}

HMODULE MinidumpGenerator::GetDbghelpModule() {
  AutoCriticalSection lock(&module_load_sync_);
  if (!dbghelp_module_) {
    dbghelp_module_ = LoadLibrary(TEXT("dbghelp.dll"));
  }

  return dbghelp_module_;
}

MinidumpGenerator::MiniDumpWriteDumpType MinidumpGenerator::GetWriteDump() {
  AutoCriticalSection lock(&get_proc_address_sync_);
  if (!write_dump_) {
    HMODULE module = GetDbghelpModule();
    if (module) {
      FARPROC proc = GetProcAddress(module, "MiniDumpWriteDump");
      write_dump_ = reinterpret_cast<MiniDumpWriteDumpType>(proc);
    }
  }

  return write_dump_;
}

HMODULE MinidumpGenerator::GetRpcrt4Module() {
  AutoCriticalSection lock(&module_load_sync_);
  if (!rpcrt4_module_) {
    rpcrt4_module_ = LoadLibrary(TEXT("rpcrt4.dll"));
  }

  return rpcrt4_module_;
}

MinidumpGenerator::UuidCreateType MinidumpGenerator::GetCreateUuid() {
  AutoCriticalSection lock(&module_load_sync_);
  if (!create_uuid_) {
    HMODULE module = GetRpcrt4Module();
    if (module) {
      FARPROC proc = GetProcAddress(module, "UuidCreate");
      create_uuid_ = reinterpret_cast<UuidCreateType>(proc);
    }
  }

  return create_uuid_;
}

bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) {
  UUID id = {0};

  UuidCreateType create_uuid = GetCreateUuid();
  if (!create_uuid) {
    return false;
  }

  create_uuid(&id);
  wstring id_str = GUIDString::GUIDToWString(&id);

  *file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp");
  return true;
}

}  // namespace google_breakpad
