// 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/crash_generation_server.h"
#include <windows.h>
#include <cassert>
#include <list>
#include "client/windows/common/auto_critical_section.h"
#include "common/scoped_ptr.h"

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

namespace google_breakpad {

// Output buffer size.
static const size_t kOutBufferSize = 64;

// Input buffer size.
static const size_t kInBufferSize = 64;

// Access flags for the client on the dump request event.
static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE;

// Access flags for the client on the dump generated event.
static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE |
                                               SYNCHRONIZE;

// Access flags for the client on the mutex.
static const DWORD kMutexAccess = SYNCHRONIZE;

// Attribute flags for the pipe.
static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE |
                               PIPE_ACCESS_DUPLEX |
                               FILE_FLAG_OVERLAPPED;

// Mode for the pipe.
static const DWORD kPipeMode = PIPE_TYPE_MESSAGE |
                               PIPE_READMODE_MESSAGE |
                               PIPE_WAIT;

// For pipe I/O, execute the callback in the wait thread itself,
// since the callback does very little work. The callback executes
// the code for one of the states of the server state machine and
// the code for all of the states perform async I/O and hence
// finish very quickly.
static const ULONG kPipeIOThreadFlags = WT_EXECUTEINWAITTHREAD;

// Dump request threads will, most likely, generate dumps. That may
// take some time to finish, so specify WT_EXECUTELONGFUNCTION flag.
static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD |
                                             WT_EXECUTELONGFUNCTION;

static bool IsClientRequestValid(const ProtocolMessage& msg) {
  return msg.tag == MESSAGE_TAG_UPLOAD_REQUEST ||
         (msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST &&
          msg.id != 0 &&
          msg.thread_id != NULL &&
          msg.exception_pointers != NULL &&
          msg.assert_info != NULL);
}

#ifdef _DEBUG
static bool CheckForIOIncomplete(bool success) {
  // We should never get an I/O incomplete since we should not execute this
  // unless the operation has finished and the overlapped event is signaled. If
  // we do get INCOMPLETE, we have a bug in our code.
  return success ? false : (GetLastError() == ERROR_IO_INCOMPLETE);
}
#endif

CrashGenerationServer::CrashGenerationServer(
    const std::wstring& pipe_name,
    SECURITY_ATTRIBUTES* pipe_sec_attrs,
    OnClientConnectedCallback connect_callback,
    void* connect_context,
    OnClientDumpRequestCallback dump_callback,
    void* dump_context,
    OnClientExitedCallback exit_callback,
    void* exit_context,
    OnClientUploadRequestCallback upload_request_callback,
    void* upload_context,
    bool generate_dumps,
    const std::wstring* dump_path)
    : pipe_name_(pipe_name),
      pipe_sec_attrs_(pipe_sec_attrs),
      pipe_(NULL),
      pipe_wait_handle_(NULL),
      server_alive_handle_(NULL),
      connect_callback_(connect_callback),
      connect_context_(connect_context),
      dump_callback_(dump_callback),
      dump_context_(dump_context),
      exit_callback_(exit_callback),
      exit_context_(exit_context),
      upload_request_callback_(upload_request_callback),
      upload_context_(upload_context),
      generate_dumps_(generate_dumps),
      dump_path_(dump_path ? *dump_path : L""),
      server_state_(IPC_SERVER_STATE_UNINITIALIZED),
      shutting_down_(false),
      overlapped_(),
      client_info_(NULL),
      pre_fetch_custom_info_(true) {
  InitializeCriticalSection(&sync_);
}

// This should never be called from the OnPipeConnected callback.
// Otherwise the UnregisterWaitEx call below will cause a deadlock.
CrashGenerationServer::~CrashGenerationServer() {
  // New scope to release the lock automatically.
  {
    // Make sure no clients are added or removed beyond this point.
    // Before adding or removing any clients, the critical section
    // must be entered and the shutting_down_ flag checked. The
    // critical section is then exited only after the clients_ list
    // modifications are done and the list is in a consistent state.
    AutoCriticalSection lock(&sync_);

    // Indicate to existing threads that server is shutting down.
    shutting_down_ = true;
  }
  // No one will modify the clients_ list beyond this point -
  // not even from another thread.

  // Even if there are no current worker threads running, it is possible that
  // an I/O request is pending on the pipe right now but not yet done.
  // In fact, it's very likely this is the case unless we are in an ERROR
  // state. If we don't wait for the pending I/O to be done, then when the I/O
  // completes, it may write to invalid memory. AppVerifier will flag this
  // problem too. So we disconnect from the pipe and then wait for the server
  // to get into error state so that the pending I/O will fail and get
  // cleared.
  DisconnectNamedPipe(pipe_);
  int num_tries = 100;
  while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) {
    Sleep(10);
  }

  // Unregister wait on the pipe.
  if (pipe_wait_handle_) {
    // Wait for already executing callbacks to finish.
    UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE);
  }

  // Close the pipe to avoid further client connections.
  if (pipe_) {
    CloseHandle(pipe_);
  }

  // Request all ClientInfo objects to unregister all waits.
  // No need to enter the critical section because no one is allowed to modify
  // the clients_ list once the shutting_down_ flag is set.
  std::list<ClientInfo*>::iterator iter;
  for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
    ClientInfo* client_info = *iter;
    // Unregister waits. Wait for already executing callbacks to finish.
    // Unregister the client process exit wait first and only then unregister
    // the dump request wait.  The reason is that the OnClientExit callback
    // also unregisters the dump request wait and such a race (doing the same
    // unregistration from two threads) is undesirable.
    client_info->UnregisterProcessExitWait(true);
    client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending();

    // Destroying the ClientInfo here is safe because all wait operations for
    // this ClientInfo were unregistered and no pending or running callbacks
    // for this ClientInfo can possible exist (block_until_no_pending option
    // was used).
    delete client_info;
  }

  if (server_alive_handle_) {
    // Release the mutex before closing the handle so that clients requesting
    // dumps wait for a long time for the server to generate a dump.
    ReleaseMutex(server_alive_handle_);
    CloseHandle(server_alive_handle_);
  }

  if (overlapped_.hEvent) {
    CloseHandle(overlapped_.hEvent);
  }

  DeleteCriticalSection(&sync_);
}

bool CrashGenerationServer::Start() {
  if (server_state_ != IPC_SERVER_STATE_UNINITIALIZED) {
    return false;
  }

  server_state_ = IPC_SERVER_STATE_INITIAL;

  server_alive_handle_ = CreateMutex(NULL, TRUE, NULL);
  if (!server_alive_handle_) {
    return false;
  }

  // Event to signal the client connection and pipe reads and writes.
  overlapped_.hEvent = CreateEvent(NULL,   // Security descriptor.
                                   TRUE,   // Manual reset.
                                   FALSE,  // Initially nonsignaled.
                                   NULL);  // Name.
  if (!overlapped_.hEvent) {
    return false;
  }

  // Register a callback with the thread pool for the client connection.
  if (!RegisterWaitForSingleObject(&pipe_wait_handle_,
                                   overlapped_.hEvent,
                                   OnPipeConnected,
                                   this,
                                   INFINITE,
                                   kPipeIOThreadFlags)) {
    return false;
  }

  pipe_ = CreateNamedPipe(pipe_name_.c_str(),
                          kPipeAttr,
                          kPipeMode,
                          1,
                          kOutBufferSize,
                          kInBufferSize,
                          0,
                          pipe_sec_attrs_);
  if (pipe_ == INVALID_HANDLE_VALUE) {
    return false;
  }

  // Kick-start the state machine. This will initiate an asynchronous wait
  // for client connections.
  if (!SetEvent(overlapped_.hEvent)) {
    server_state_ = IPC_SERVER_STATE_ERROR;
    return false;
  }

  // If we are in error state, it's because we failed to start listening.
  return true;
}

// If the server thread serving clients ever gets into the
// ERROR state, reset the event, close the pipe and remain
// in the error state forever. Error state means something
// that we didn't account for has happened, and it's dangerous
// to do anything unknowingly.
void CrashGenerationServer::HandleErrorState() {
  assert(server_state_ == IPC_SERVER_STATE_ERROR);

  // If the server is shutting down anyway, don't clean up
  // here since shut down process will clean up.
  if (shutting_down_) {
    return;
  }

  if (pipe_wait_handle_) {
    UnregisterWait(pipe_wait_handle_);
    pipe_wait_handle_ = NULL;
  }

  if (pipe_) {
    CloseHandle(pipe_);
    pipe_ = NULL;
  }

  if (overlapped_.hEvent) {
    CloseHandle(overlapped_.hEvent);
    overlapped_.hEvent = NULL;
  }
}

// When the server thread serving clients is in the INITIAL state,
// try to connect to the pipe asynchronously. If the connection
// finishes synchronously, directly go into the CONNECTED state;
// otherwise go into the CONNECTING state. For any problems, go
// into the ERROR state.
void CrashGenerationServer::HandleInitialState() {
  assert(server_state_ == IPC_SERVER_STATE_INITIAL);

  if (!ResetEvent(overlapped_.hEvent)) {
    EnterErrorState();
    return;
  }

  bool success = ConnectNamedPipe(pipe_, &overlapped_) != FALSE;
  DWORD error_code = success ? ERROR_SUCCESS : GetLastError();

  // From MSDN, it is not clear that when ConnectNamedPipe is used
  // in an overlapped mode, will it ever return non-zero value, and
  // if so, in what cases.
  assert(!success);

  switch (error_code) {
    case ERROR_IO_PENDING:
      EnterStateWhenSignaled(IPC_SERVER_STATE_CONNECTING);
      break;

    case ERROR_PIPE_CONNECTED:
      EnterStateImmediately(IPC_SERVER_STATE_CONNECTED);
      break;

    default:
      EnterErrorState();
      break;
  }
}

// When the server thread serving the clients is in the CONNECTING state,
// try to get the result of the asynchronous connection request using
// the OVERLAPPED object. If the result indicates the connection is done,
// go into the CONNECTED state. If the result indicates I/O is still
// INCOMPLETE, remain in the CONNECTING state. For any problems,
// go into the DISCONNECTING state.
void CrashGenerationServer::HandleConnectingState() {
  assert(server_state_ == IPC_SERVER_STATE_CONNECTING);

  DWORD bytes_count = 0;
  bool success = GetOverlappedResult(pipe_,
                                     &overlapped_,
                                     &bytes_count,
                                     FALSE) != FALSE;
  DWORD error_code = success ? ERROR_SUCCESS : GetLastError();

  if (success) {
    EnterStateImmediately(IPC_SERVER_STATE_CONNECTED);
  } else if (error_code != ERROR_IO_INCOMPLETE) {
    EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  } else {
    // remain in CONNECTING state
  }
}

// When the server thread serving the clients is in the CONNECTED state,
// try to issue an asynchronous read from the pipe. If read completes
// synchronously or if I/O is pending then go into the READING state.
// For any problems, go into the DISCONNECTING state.
void CrashGenerationServer::HandleConnectedState() {
  assert(server_state_ == IPC_SERVER_STATE_CONNECTED);

  DWORD bytes_count = 0;
  memset(&msg_, 0, sizeof(msg_));
  bool success = ReadFile(pipe_,
                          &msg_,
                          sizeof(msg_),
                          &bytes_count,
                          &overlapped_) != FALSE;
  DWORD error_code = success ? ERROR_SUCCESS : GetLastError();

  // Note that the asynchronous read issued above can finish before the
  // code below executes. But, it is okay to change state after issuing
  // the asynchronous read. This is because even if the asynchronous read
  // is done, the callback for it would not be executed until the current
  // thread finishes its execution.
  if (success || error_code == ERROR_IO_PENDING) {
    EnterStateWhenSignaled(IPC_SERVER_STATE_READING);
  } else {
    EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  }
}

// When the server thread serving the clients is in the READING state,
// try to get the result of the async read. If async read is done,
// go into the READ_DONE state. For any problems, go into the
// DISCONNECTING state.
void CrashGenerationServer::HandleReadingState() {
  assert(server_state_ == IPC_SERVER_STATE_READING);

  DWORD bytes_count = 0;
  bool success = GetOverlappedResult(pipe_,
                                     &overlapped_,
                                     &bytes_count,
                                     FALSE) != FALSE;
  if (success && bytes_count == sizeof(ProtocolMessage)) {
    EnterStateImmediately(IPC_SERVER_STATE_READ_DONE);
    return;
  }

  assert(!CheckForIOIncomplete(success));
  EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
}

// When the server thread serving the client is in the READ_DONE state,
// validate the client's request message, register the client by
// creating appropriate objects and prepare the response.  Then try to
// write the response to the pipe asynchronously. If that succeeds,
// go into the WRITING state. For any problems, go into the DISCONNECTING
// state.
void CrashGenerationServer::HandleReadDoneState() {
  assert(server_state_ == IPC_SERVER_STATE_READ_DONE);

  if (!IsClientRequestValid(msg_)) {
    EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
    return;
  }

  if (msg_.tag == MESSAGE_TAG_UPLOAD_REQUEST) {
    if (upload_request_callback_)
      upload_request_callback_(upload_context_, msg_.id);
    EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
    return;
  }

  scoped_ptr<ClientInfo> client_info(
      new ClientInfo(this,
                     msg_.id,
                     msg_.dump_type,
                     msg_.thread_id,
                     msg_.exception_pointers,
                     msg_.assert_info,
                     msg_.custom_client_info));

  if (!client_info->Initialize()) {
    EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
    return;
  }

  // Issues an asynchronous WriteFile call if successful.
  // Iff successful, assigns ownership of the client_info pointer to the server
  // instance, in which case we must be sure not to free it in this function.
  if (!RespondToClient(client_info.get())) {
    EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
    return;
  }

  // This is only valid as long as it can be found in the clients_ list
  client_info_ = client_info.release();

  // Note that the asynchronous write issued by RespondToClient function
  // can finish before  the code below executes. But it is okay to change
  // state after issuing the asynchronous write. This is because even if
  // the asynchronous write is done, the callback for it would not be
  // executed until the current thread finishes its execution.
  EnterStateWhenSignaled(IPC_SERVER_STATE_WRITING);
}

// When the server thread serving the clients is in the WRITING state,
// try to get the result of the async write. If the async write is done,
// go into the WRITE_DONE state. For any problems, go into the
// DISONNECTING state.
void CrashGenerationServer::HandleWritingState() {
  assert(server_state_ == IPC_SERVER_STATE_WRITING);

  DWORD bytes_count = 0;
  bool success = GetOverlappedResult(pipe_,
                                     &overlapped_,
                                     &bytes_count,
                                     FALSE) != FALSE;
  if (success) {
    EnterStateImmediately(IPC_SERVER_STATE_WRITE_DONE);
    return;
  }

  assert(!CheckForIOIncomplete(success));
  EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
}

// When the server thread serving the clients is in the WRITE_DONE state,
// try to issue an async read on the pipe. If the read completes synchronously
// or if I/O is still pending then go into the READING_ACK state. For any
// issues, go into the DISCONNECTING state.
void CrashGenerationServer::HandleWriteDoneState() {
  assert(server_state_ == IPC_SERVER_STATE_WRITE_DONE);

  DWORD bytes_count = 0;
  bool success = ReadFile(pipe_,
                           &msg_,
                           sizeof(msg_),
                           &bytes_count,
                           &overlapped_) != FALSE;
  DWORD error_code = success ? ERROR_SUCCESS : GetLastError();

  if (success) {
    EnterStateImmediately(IPC_SERVER_STATE_READING_ACK);
  } else if (error_code == ERROR_IO_PENDING) {
    EnterStateWhenSignaled(IPC_SERVER_STATE_READING_ACK);
  } else {
    EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
  }
}

// When the server thread serving the clients is in the READING_ACK state,
// try to get result of async read. Go into the DISCONNECTING state.
void CrashGenerationServer::HandleReadingAckState() {
  assert(server_state_ == IPC_SERVER_STATE_READING_ACK);

  DWORD bytes_count = 0;
  bool success = GetOverlappedResult(pipe_,
                                     &overlapped_,
                                     &bytes_count,
                                     FALSE) != FALSE;
  if (success) {
    // The connection handshake with the client is now complete; perform
    // the callback.
    if (connect_callback_) {
      // Note that there is only a single copy of the ClientInfo of the
      // currently connected client.  However it is being referenced from
      // two different places:
      //  - the client_info_ member
      //  - the clients_ list
      // The lifetime of this ClientInfo depends on the lifetime of the
      // client process - basically it can go away at any time.
      // However, as long as it is referenced by the clients_ list it
      // is guaranteed to be valid. Enter the critical section and check
      // to see whether the client_info_ can be found in the list.
      // If found, execute the callback and only then leave the critical
      // section.
      AutoCriticalSection lock(&sync_);

      bool client_is_still_alive = false;
      std::list<ClientInfo*>::iterator iter;
      for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
        if (client_info_ == *iter) {
          client_is_still_alive = true;
          break;
        }
      }

      if (client_is_still_alive) {
        connect_callback_(connect_context_, client_info_);
      }
    }
  } else {
    assert(!CheckForIOIncomplete(success));
  }

  EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
}

// When the server thread serving the client is in the DISCONNECTING state,
// disconnect from the pipe and reset the event. If anything fails, go into
// the ERROR state. If it goes well, go into the INITIAL state and set the
// event to start all over again.
void CrashGenerationServer::HandleDisconnectingState() {
  assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING);

  // Done serving the client.
  client_info_ = NULL;

  overlapped_.Internal = NULL;
  overlapped_.InternalHigh = NULL;
  overlapped_.Offset = 0;
  overlapped_.OffsetHigh = 0;
  overlapped_.Pointer = NULL;

  if (!ResetEvent(overlapped_.hEvent)) {
    EnterErrorState();
    return;
  }

  if (!DisconnectNamedPipe(pipe_)) {
    EnterErrorState();
    return;
  }

  // If the server is shutting down do not connect to the
  // next client.
  if (shutting_down_) {
    return;
  }

  EnterStateImmediately(IPC_SERVER_STATE_INITIAL);
}

void CrashGenerationServer::EnterErrorState() {
  SetEvent(overlapped_.hEvent);
  server_state_ = IPC_SERVER_STATE_ERROR;
}

void CrashGenerationServer::EnterStateWhenSignaled(IPCServerState state) {
  server_state_ = state;
}

void CrashGenerationServer::EnterStateImmediately(IPCServerState state) {
  server_state_ = state;

  if (!SetEvent(overlapped_.hEvent)) {
    server_state_ = IPC_SERVER_STATE_ERROR;
  }
}

bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info,
                                         ProtocolMessage* reply) const {
  reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE;
  reply->id = GetCurrentProcessId();

  if (CreateClientHandles(client_info, reply)) {
    return true;
  }

  // Closing of remote handles (belonging to a different process) can
  // only be done through DuplicateHandle.
  if (reply->dump_request_handle) {
    DuplicateHandle(client_info.process_handle(),  // hSourceProcessHandle
                    reply->dump_request_handle,    // hSourceHandle
                    NULL,                          // hTargetProcessHandle
                    0,                             // lpTargetHandle
                    0,                             // dwDesiredAccess
                    FALSE,                         // bInheritHandle
                    DUPLICATE_CLOSE_SOURCE);       // dwOptions
    reply->dump_request_handle = NULL;
  }

  if (reply->dump_generated_handle) {
    DuplicateHandle(client_info.process_handle(),  // hSourceProcessHandle
                    reply->dump_generated_handle,  // hSourceHandle
                    NULL,                          // hTargetProcessHandle
                    0,                             // lpTargetHandle
                    0,                             // dwDesiredAccess
                    FALSE,                         // bInheritHandle
                    DUPLICATE_CLOSE_SOURCE);       // dwOptions
    reply->dump_generated_handle = NULL;
  }

  if (reply->server_alive_handle) {
    DuplicateHandle(client_info.process_handle(),  // hSourceProcessHandle
                    reply->server_alive_handle,    // hSourceHandle
                    NULL,                          // hTargetProcessHandle
                    0,                             // lpTargetHandle
                    0,                             // dwDesiredAccess
                    FALSE,                         // bInheritHandle
                    DUPLICATE_CLOSE_SOURCE);       // dwOptions
    reply->server_alive_handle = NULL;
  }

  return false;
}

bool CrashGenerationServer::CreateClientHandles(const ClientInfo& client_info,
                                                ProtocolMessage* reply) const {
  HANDLE current_process = GetCurrentProcess();
  if (!DuplicateHandle(current_process,
                       client_info.dump_requested_handle(),
                       client_info.process_handle(),
                       &reply->dump_request_handle,
                       kDumpRequestEventAccess,
                       FALSE,
                       0)) {
    return false;
  }

  if (!DuplicateHandle(current_process,
                       client_info.dump_generated_handle(),
                       client_info.process_handle(),
                       &reply->dump_generated_handle,
                       kDumpGeneratedEventAccess,
                       FALSE,
                       0)) {
    return false;
  }

  if (!DuplicateHandle(current_process,
                       server_alive_handle_,
                       client_info.process_handle(),
                       &reply->server_alive_handle,
                       kMutexAccess,
                       FALSE,
                       0)) {
    return false;
  }

  return true;
}

bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) {
  ProtocolMessage reply;
  if (!PrepareReply(*client_info, &reply)) {
    return false;
  }

  DWORD bytes_count = 0;
  bool success = WriteFile(pipe_,
                            &reply,
                            sizeof(reply),
                            &bytes_count,
                            &overlapped_) != FALSE;
  DWORD error_code = success ? ERROR_SUCCESS : GetLastError();

  if (!success && error_code != ERROR_IO_PENDING) {
    return false;
  }

  // Takes over ownership of client_info. We MUST return true if AddClient
  // succeeds.
  return AddClient(client_info);
}

// The server thread servicing the clients runs this method. The method
// implements the state machine described in ReadMe.txt along with the
// helper methods HandleXXXState.
void CrashGenerationServer::HandleConnectionRequest() {
  // If the server is shutting down, get into ERROR state, reset the event so
  // more workers don't run and return immediately.
  if (shutting_down_) {
    server_state_ = IPC_SERVER_STATE_ERROR;
    ResetEvent(overlapped_.hEvent);
    return;
  }

  switch (server_state_) {
    case IPC_SERVER_STATE_ERROR:
      HandleErrorState();
      break;

    case IPC_SERVER_STATE_INITIAL:
      HandleInitialState();
      break;

    case IPC_SERVER_STATE_CONNECTING:
      HandleConnectingState();
      break;

    case IPC_SERVER_STATE_CONNECTED:
      HandleConnectedState();
      break;

    case IPC_SERVER_STATE_READING:
      HandleReadingState();
      break;

    case IPC_SERVER_STATE_READ_DONE:
      HandleReadDoneState();
      break;

    case IPC_SERVER_STATE_WRITING:
      HandleWritingState();
      break;

    case IPC_SERVER_STATE_WRITE_DONE:
      HandleWriteDoneState();
      break;

    case IPC_SERVER_STATE_READING_ACK:
      HandleReadingAckState();
      break;

    case IPC_SERVER_STATE_DISCONNECTING:
      HandleDisconnectingState();
      break;

    default:
      assert(false);
      // This indicates that we added one more state without
      // adding handling code.
      server_state_ = IPC_SERVER_STATE_ERROR;
      break;
  }
}

bool CrashGenerationServer::AddClient(ClientInfo* client_info) {
  HANDLE request_wait_handle = NULL;
  if (!RegisterWaitForSingleObject(&request_wait_handle,
                                   client_info->dump_requested_handle(),
                                   OnDumpRequest,
                                   client_info,
                                   INFINITE,
                                   kDumpRequestThreadFlags)) {
    return false;
  }

  client_info->set_dump_request_wait_handle(request_wait_handle);

  // OnClientEnd will be called when the client process terminates.
  HANDLE process_wait_handle = NULL;
  if (!RegisterWaitForSingleObject(&process_wait_handle,
                                   client_info->process_handle(),
                                   OnClientEnd,
                                   client_info,
                                   INFINITE,
                                   WT_EXECUTEONLYONCE)) {
    return false;
  }

  client_info->set_process_exit_wait_handle(process_wait_handle);

  // New scope to hold the lock for the shortest time.
  {
    AutoCriticalSection lock(&sync_);
    if (shutting_down_) {
      // If server is shutting down, don't add new clients
      return false;
    }
    clients_.push_back(client_info);
  }

  return true;
}

// static
void CALLBACK CrashGenerationServer::OnPipeConnected(void* context, BOOLEAN) {
  assert(context);

  CrashGenerationServer* obj =
      reinterpret_cast<CrashGenerationServer*>(context);
  obj->HandleConnectionRequest();
}

// static
void CALLBACK CrashGenerationServer::OnDumpRequest(void* context, BOOLEAN) {
  assert(context);
  ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);

  CrashGenerationServer* crash_server = client_info->crash_server();
  assert(crash_server);
  if (crash_server->pre_fetch_custom_info_) {
    client_info->PopulateCustomInfo();
  }
  crash_server->HandleDumpRequest(*client_info);

  ResetEvent(client_info->dump_requested_handle());
}

// static
void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) {
  assert(context);
  ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);

  CrashGenerationServer* crash_server = client_info->crash_server();
  assert(crash_server);

  crash_server->HandleClientProcessExit(client_info);
}

void CrashGenerationServer::HandleClientProcessExit(ClientInfo* client_info) {
  assert(client_info);

  // Must unregister the dump request wait operation and wait for any
  // dump requests that might be pending to finish before proceeding
  // with the client_info cleanup.
  client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending();

  if (exit_callback_) {
    exit_callback_(exit_context_, client_info);
  }

  // Start a new scope to release lock automatically.
  {
    AutoCriticalSection lock(&sync_);
    if (shutting_down_) {
      // The crash generation server is shutting down and as part of the
      // shutdown process it will delete all clients from the clients_ list.
      return;
    }
    clients_.remove(client_info);
  }

  // Explicitly unregister the process exit wait using the non-blocking method.
  // Otherwise, the destructor will attempt to unregister it using the blocking
  // method which will lead to a deadlock because it is being called from the
  // callback of the same wait operation
  client_info->UnregisterProcessExitWait(false);

  delete client_info;
}

void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) {
  bool execute_callback = true;
  // Generate the dump only if it's explicitly requested by the
  // server application; otherwise the server might want to generate
  // dump in the callback.
  std::wstring dump_path;
  if (generate_dumps_) {
    if (!GenerateDump(client_info, &dump_path)) {
      // client proccess terminated or some other error
      execute_callback = false;
    }
  }

  if (dump_callback_ && execute_callback) {
    std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path;
    dump_callback_(dump_context_, &client_info, ptr_dump_path);
  }

  SetEvent(client_info.dump_generated_handle());
}

bool CrashGenerationServer::GenerateDump(const ClientInfo& client,
                                         std::wstring* dump_path) {
  assert(client.pid() != 0);
  assert(client.process_handle());

  // We have to get the address of EXCEPTION_INFORMATION from
  // the client process address space.
  EXCEPTION_POINTERS* client_ex_info = NULL;
  if (!client.GetClientExceptionInfo(&client_ex_info)) {
    return false;
  }

  DWORD client_thread_id = 0;
  if (!client.GetClientThreadId(&client_thread_id)) {
    return false;
  }

  MinidumpGenerator dump_generator(dump_path_,
                                   client.process_handle(),
                                   client.pid(),
                                   client_thread_id,
                                   GetCurrentThreadId(),
                                   client_ex_info,
                                   client.assert_info(),
                                   client.dump_type(),
                                   true);
  if (!dump_generator.GenerateDumpFile(dump_path)) {
    return false;
  }
  return dump_generator.WriteMinidump();
}

}  // namespace google_breakpad
