<commit_before>#include "frame.h"

#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <algorithm>
#include <memory>

#include "util/time.h"

namespace tinyco {

std::unordered_map<int, Thread *> Frame::io_wait_map_;  // wait on io
std::list<Thread *> Frame::thread_runnable_;
std::list<Thread *> Frame::thread_free_;       // like memory pool
std::vector<Thread *> Frame::thread_pending_;  // sleeping thread
Thread *Frame::main_thread_ = NULL;
Thread *Frame::running_thread_ = NULL;
struct event_base *Frame::base = NULL;
uint64_t Frame::last_loop_ts_ = 0;

struct ThreadPendingTimeComp {
  bool operator()(Thread *&a, Thread *&b) {
    return a->GetWakeupTime() < b->GetWakeupTime();
  }
};

bool Frame::Init() {
  auto m = new Thread;
  m->Init();
  m->SetContext(MainThreadLoop, NULL);
  main_thread_ = m;

  base = event_base_new();
  return true;
}

bool Frame::Fini() {
  delete running_thread_;
  running_thread_ = NULL;

  delete main_thread_;
  main_thread_ = NULL;

  for (auto it = thread_runnable_.begin(); it != thread_runnable_.end(); it++) {
    delete (*it);
  }

  for (auto it = thread_free_.begin(); it != thread_free_.end(); it++) {
    delete (*it);
  }

  for (auto it = io_wait_map_.begin(); it != io_wait_map_.end();) {
    delete (((it++)->second));
  }

  if (base) event_base_free(base);
  return true;
}

int Frame::MainThreadLoop(void *arg) {
  struct timeval timeout;
  while (true) {
    UpdateLoopTimestamp();
    auto timeout = GetEventLoopTimeout();
    EventLoop(timeout);
    WakeupPendingThread();
    Schedule();
  }
}

Thread *Frame::PopPendingTop() {
  auto *t = *thread_pending_.begin();
  thread_pending_.erase(thread_pending_.begin());
  make_heap(thread_pending_.begin(), thread_pending_.end(),
            ThreadPendingTimeComp());
  return t;
}

void Frame::WakeupPendingThread() {
  auto nowms = GetLastLoopTimestamp();
  if (!thread_pending_.empty()) {
    auto n = *thread_pending_.begin();
    auto sz = thread_pending_.size();
    while (sz-- && n->GetWakeupTime() <= nowms) {
      n = PopPendingTop();
      n->Pending(0);
      n->SetState(Thread::TS_RUNNABLE);
      thread_runnable_.push_back(n);

      n = *thread_pending_.begin();
    }
  }
}

timeval Frame::GetEventLoopTimeout() {
  auto nowms = GetLastLoopTimestamp();
  struct timeval timeout = {0, 100000};
  if (!thread_pending_.empty()) {
    auto mint = *thread_pending_.begin();

    // thread need to be wake up
    if (mint->GetWakeupTime() < nowms) {
      timeout.tv_usec = 0;
      return timeout;
    }

    int delta = mint->GetWakeupTime() - nowms;
    timeout.tv_sec = delta / 1000llu;
    timeout.tv_usec = (delta - timeout.tv_sec * 1000llu) * 1000llu;
  }
  return timeout;
}

int Frame::EventLoop(const timeval &tv) {
  event_base_loopexit(base, &tv);
  return event_base_loop(base, 0);
}

int Frame::UdpSendAndRecv(const std::string &sendbuf,
                          struct sockaddr_in &dest_addr, std::string *recvbuf) {
  int ret = 0;
  char recvbuf_[65536] = {0};
  auto recvlen = sizeof(recvbuf_);
  int fd = socket(AF_INET, SOCK_DGRAM, 0);
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags < 0) return -1;
  flags = flags | O_NONBLOCK;
  fcntl(fd, F_SETFL, flags);

  if ((ret = sendto(fd, sendbuf.c_str(), sendbuf.size(), 0,
                    (struct sockaddr *)&dest_addr, sizeof(dest_addr))) < 0) {
    return -1;
  }

  socklen_t sockaddr_len = sizeof(dest_addr);
  if ((ret = recvfrom(fd, recvbuf_, sizeof(recvbuf_), 0,
                      (struct sockaddr *)&dest_addr, &sockaddr_len)) < 0) {
    if (errno == EAGAIN || errno == EWOULDBLOCK)
      return -2;
    else
      return -2;
  }

  if (ret > 0) {
    recvbuf->assign(recvbuf_, ret);
  }

  return 0;
}

int Frame::TcpSendAndRecv(const void *sendbuf, size_t sendlen, void *recvbuf,
                          size_t *recvlen, IsCompleteBase *is_complete) {
  int nsend = 0;
  int fd = socket(AF_INET, SOCK_DGRAM, 0);
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags < 0) return -1;
  flags = flags | O_NONBLOCK;
  fcntl(fd, F_SETFL, flags);

  while (nsend == sendlen) {
    int ret = send(fd, static_cast<const char *>(sendbuf) + nsend,
                   sendlen - nsend, 0);
    if (ret > 0) {
      nsend += ret;
    }
    if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
      continue;
    } else if (ret < 0) {
      return -1;
    } else if (0 == ret) {
      return -1;
    }
  }

  size_t recvd = 0;
  while (true) {
    int ret = recv(fd, recvbuf, *recvlen, 0);
    if (ret > 0) {
      recvd += ret;
      // ok
      if (is_complete->CheckPkg(static_cast<char *>(recvbuf), recvd) == 0) {
        *recvlen = recvd;
        return 0;
      }

      continue;
    } else if (0 == ret) {  // reset by peer
      return -2;
    } else if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
      continue;
    } else {
      return -2;
    }
  }
  return 0;
}

int Frame::accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
  int fd = -1;
  struct event ev;
  while (fd < 0) {
    fd = ::accept(sockfd, addr, addrlen);
    if (fd < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {

        event_assign(&ev, base, sockfd, EV_READ, SocketReadOrWrite, &ev);
        event_add(&ev, NULL);
        io_wait_map_[sockfd] = running_thread_;
        running_thread_->Schedule();
        running_thread_->SetState(Thread::TS_STOP);
        Schedule();
      } else {
        return -1;
      }
    }
  }

  return fd;
}

int Frame::connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
  struct event ev;
  int ret = ::connect(sockfd, addr, addrlen);
  if (EINPROGRESS == errno) {
    event_assign(&ev, base, sockfd, EV_WRITE, SocketReadOrWrite, &ev);
    event_add(&ev, NULL);  // add timeout
    io_wait_map_[sockfd] = running_thread_;
    running_thread_->Schedule();
    running_thread_->SetState(Thread::TS_STOP);
    Schedule();

    if (ev.ev_res & EV_TIMEOUT) {
      return -1;
    } else if (ev.ev_res != EV_WRITE) {
      return -1;
    }
  } else {
    return -1;
  }

  return 0;
}

int Frame::send(int sockfd, const void *buf, size_t len, int flags) {
  struct event ev;
  size_t nsend = 0;
  while (nsend < len) {
    int ret =
        ::send(sockfd, static_cast<const char *>(buf) + nsend, len - nsend, 0);
    if (ret > 0) {
      nsend += ret;
    } else if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
      event_assign(&ev, base, sockfd, EV_WRITE, SocketReadOrWrite, &ev);
      event_add(&ev, NULL);
      io_wait_map_[sockfd] = running_thread_;
      running_thread_->Schedule();
      running_thread_->SetState(Thread::TS_STOP);
      Schedule();

      if (ev.ev_res & EV_TIMEOUT) {
        return -2;
        break;
      } else if (ev.ev_res & EV_WRITE) {
        continue;
      }
      return -1;
    } else if (ret < 0) {
      return -1;
    } else if (0 == ret) {
      return 0;
    }
  }

  return nsend;
}

int Frame::recv(int sockfd, void *buf, size_t len, int flags) {
  size_t recvd = 0;
  struct event ev;
  int ret = 0;
  while (true) {
    ret = ::recv(sockfd, buf, len, flags);
    if (ret > 0) {
      recvd += ret;
      return recvd;
    } else if (0 == ret) {  // reset by peer
      return 0;
    } else if (ret < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
        event_assign(&ev, base, sockfd, EV_READ | EV_CLOSED, SocketReadOrWrite,
                     &ev);
        event_add(&ev, NULL);
        io_wait_map_[sockfd] = running_thread_;
        running_thread_->Schedule();
        running_thread_->SetState(Thread::TS_STOP);
        Schedule();

        if (ev.ev_res & EV_TIMEOUT) {
          return -2;  // return timeout errcode
        } else if (ev.ev_res & EV_CLOSED) {
          return 0;
        } else if (ev.ev_res & EV_READ) {
          continue;
        }
      }

      break;
    }
  }

  return ret;
}

int Frame::sendto(int sockfd, const void *buf, size_t len, int flags,
                  const struct sockaddr *dest_addr, socklen_t addrlen) {
  return ::sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}

ssize_t Frame::recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen) {
  struct event ev;
  int ret = 0;
  while (true) {
    int ret =
        ::recvfrom(sockfd, buf, len, 0, (struct sockaddr *)src_addr, addrlen);
    if (ret > 0) {
      return ret;
    } else if (0 == ret) {
      return 0;
    } else if (ret < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
        event_assign(&ev, base, sockfd, EV_READ | EV_CLOSED, SocketReadOrWrite,
                     &ev);
        event_add(&ev, NULL);
        io_wait_map_[sockfd] = running_thread_;
        running_thread_->Schedule();
        running_thread_->SetState(Thread::TS_STOP);
        Schedule();

        if (ev.ev_res & EV_TIMEOUT) {
          return -2;  // return timeout errcode
        } else if (ev.ev_res & EV_CLOSED) {
          return 0;
        } else if (ev.ev_res & EV_READ) {
          continue;
        }
      }

      break;
    }
  }

  return ret;
}

void Frame::SocketReadOrWrite(int fd, short events, void *arg) {
  int ret = event_del(static_cast<event *>(arg));

  thread_runnable_.push_back(io_wait_map_[fd]);
  io_wait_map_.erase(fd);
  event_base_loopbreak(Frame::base);
}

int HandleProcess(void *arg) {
  auto *w = static_cast<Work *>(arg);
  w->Run();
  LOG_DEBUG("run ret=%d", w->Run());
  delete w;

  // recycle the thread
  Frame::RecycleRunningThread();
  Frame::Schedule();
  return 0;
}

void Frame::RecycleRunningThread() {
  thread_free_.push_back(running_thread_);
  running_thread_ = NULL;
}

int Frame::CreateThread(Work *w) {
  // work will be deleted by HandleProcess()
  // thread should not be deleted before deleting work
  auto *t = new Thread;
  t->Init();
  t->SetContext(HandleProcess, w);
  thread_runnable_.push_back(t);
}

int Frame::Schedule() {
  if (thread_runnable_.empty()) {
    main_thread_->RestoreContext();
  } else {
    running_thread_ = *(thread_runnable_.begin());
    thread_runnable_.pop_front();
    running_thread_->RestoreContext();
  }
  return 0;
}

void Frame::Sleep(uint32_t ms) {
  if (running_thread_) {
    running_thread_->Pending(time::mstime() + ms);
    running_thread_->SetState(Thread::TS_STOP);
    thread_pending_.push_back(running_thread_);
    running_thread_->Schedule();
    running_thread_ = NULL;
  }

  Schedule();
}

void Frame::PendThread(Thread *t) {
  thread_pending_.push_back(t);
  make_heap(thread_pending_.begin(), thread_pending_.end(),
            ThreadPendingTimeComp());
}

void Frame::UpdateLoopTimestamp() { last_loop_ts_ = time::mstime(); }
}
<commit_msg>bugfixed<commit_after>#include "frame.h"

#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <algorithm>
#include <memory>

#include "util/time.h"

namespace tinyco {

std::unordered_map<int, Thread *> Frame::io_wait_map_;  // wait on io
std::list<Thread *> Frame::thread_runnable_;
std::list<Thread *> Frame::thread_free_;       // like memory pool
std::vector<Thread *> Frame::thread_pending_;  // sleeping thread
Thread *Frame::main_thread_ = NULL;
Thread *Frame::running_thread_ = NULL;
struct event_base *Frame::base = NULL;
uint64_t Frame::last_loop_ts_ = 0;

struct ThreadPendingTimeComp {
  bool operator()(Thread *&a, Thread *&b) {
    return a->GetWakeupTime() < b->GetWakeupTime();
  }
};

bool Frame::Init() {
  auto m = new Thread;
  m->Init();
  m->SetContext(MainThreadLoop, NULL);
  main_thread_ = m;

  base = event_base_new();
  return true;
}

bool Frame::Fini() {
  delete running_thread_;
  running_thread_ = NULL;

  delete main_thread_;
  main_thread_ = NULL;

  for (auto it = thread_runnable_.begin(); it != thread_runnable_.end(); it++) {
    delete (*it);
  }

  for (auto it = thread_free_.begin(); it != thread_free_.end(); it++) {
    delete (*it);
  }

  for (auto it = io_wait_map_.begin(); it != io_wait_map_.end();) {
    delete (((it++)->second));
  }

  if (base) event_base_free(base);
  return true;
}

int Frame::MainThreadLoop(void *arg) {
  struct timeval timeout;
  while (true) {
    UpdateLoopTimestamp();
    auto timeout = GetEventLoopTimeout();
    EventLoop(timeout);
    WakeupPendingThread();
    Schedule();
  }
}

Thread *Frame::PopPendingTop() {
  auto *t = *thread_pending_.begin();
  thread_pending_.erase(thread_pending_.begin());
  make_heap(thread_pending_.begin(), thread_pending_.end(),
            ThreadPendingTimeComp());
  return t;
}

void Frame::WakeupPendingThread() {
  auto nowms = GetLastLoopTimestamp();
  if (!thread_pending_.empty()) {
    auto n = *thread_pending_.begin();
    auto sz = thread_pending_.size();
    while (sz-- && n->GetWakeupTime() <= nowms) {
      n = PopPendingTop();
      n->Pending(0);
      n->SetState(Thread::TS_RUNNABLE);
      thread_runnable_.push_back(n);

      n = *thread_pending_.begin();
    }
  }
}

timeval Frame::GetEventLoopTimeout() {
  auto nowms = GetLastLoopTimestamp();
  struct timeval timeout = {0, 100000};
  if (!thread_pending_.empty()) {
    auto mint = *thread_pending_.begin();

    // thread need to be wake up
    if (mint->GetWakeupTime() < nowms) {
      timeout.tv_usec = 0;
      return timeout;
    }

    int delta = mint->GetWakeupTime() - nowms;
    timeout.tv_sec = delta / 1000llu;
    timeout.tv_usec = (delta - timeout.tv_sec * 1000llu) * 1000llu;
  }
  return timeout;
}

int Frame::EventLoop(const timeval &tv) {
  event_base_loopexit(base, &tv);
  return event_base_loop(base, 0);
}

int Frame::UdpSendAndRecv(const std::string &sendbuf,
                          struct sockaddr_in &dest_addr, std::string *recvbuf) {
  int ret = 0;
  char recvbuf_[65536] = {0};
  auto recvlen = sizeof(recvbuf_);
  int fd = socket(AF_INET, SOCK_DGRAM, 0);
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags < 0) return -1;
  flags = flags | O_NONBLOCK;
  fcntl(fd, F_SETFL, flags);

  if ((ret = sendto(fd, sendbuf.c_str(), sendbuf.size(), 0,
                    (struct sockaddr *)&dest_addr, sizeof(dest_addr))) < 0) {
    return -1;
  }

  socklen_t sockaddr_len = sizeof(dest_addr);
  if ((ret = recvfrom(fd, recvbuf_, sizeof(recvbuf_), 0,
                      (struct sockaddr *)&dest_addr, &sockaddr_len)) < 0) {
    if (errno == EAGAIN || errno == EWOULDBLOCK)
      return -2;
    else
      return -2;
  }

  if (ret > 0) {
    recvbuf->assign(recvbuf_, ret);
  }

  return 0;
}

int Frame::TcpSendAndRecv(const void *sendbuf, size_t sendlen, void *recvbuf,
                          size_t *recvlen, IsCompleteBase *is_complete) {
  int nsend = 0;
  int fd = socket(AF_INET, SOCK_DGRAM, 0);
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags < 0) return -1;
  flags = flags | O_NONBLOCK;
  fcntl(fd, F_SETFL, flags);

  while (nsend == sendlen) {
    int ret = send(fd, static_cast<const char *>(sendbuf) + nsend,
                   sendlen - nsend, 0);
    if (ret > 0) {
      nsend += ret;
    }
    if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
      continue;
    } else if (ret < 0) {
      return -1;
    } else if (0 == ret) {
      return -1;
    }
  }

  size_t recvd = 0;
  while (true) {
    int ret = recv(fd, recvbuf, *recvlen, 0);
    if (ret > 0) {
      recvd += ret;
      // ok
      if (is_complete->CheckPkg(static_cast<char *>(recvbuf), recvd) == 0) {
        *recvlen = recvd;
        return 0;
      }

      continue;
    } else if (0 == ret) {  // reset by peer
      return -2;
    } else if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
      continue;
    } else {
      return -2;
    }
  }
  return 0;
}

int Frame::accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
  int fd = -1;
  struct event ev;
  while (fd < 0) {
    fd = ::accept(sockfd, addr, addrlen);
    if (fd < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {

        event_assign(&ev, base, sockfd, EV_READ, SocketReadOrWrite, &ev);
        event_add(&ev, NULL);
        io_wait_map_[sockfd] = running_thread_;
        running_thread_->Schedule();
        running_thread_->SetState(Thread::TS_STOP);
        Schedule();
      } else {
        return -1;
      }
    }
  }

  return fd;
}

int Frame::connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
  struct event ev;
  int ret = ::connect(sockfd, addr, addrlen);
  if (EINPROGRESS == errno) {
    event_assign(&ev, base, sockfd, EV_WRITE, SocketReadOrWrite, &ev);
    event_add(&ev, NULL);  // add timeout
    io_wait_map_[sockfd] = running_thread_;
    running_thread_->Schedule();
    running_thread_->SetState(Thread::TS_STOP);
    Schedule();

    if (ev.ev_res & EV_TIMEOUT) {
      return -1;
    } else if (ev.ev_res != EV_WRITE) {
      return -1;
    }
  } else {
    return -1;
  }

  return 0;
}

int Frame::send(int sockfd, const void *buf, size_t len, int flags) {
  struct event ev;
  size_t nsend = 0;
  while (nsend < len) {
    int ret =
        ::send(sockfd, static_cast<const char *>(buf) + nsend, len - nsend, 0);
    if (ret > 0) {
      nsend += ret;
    } else if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
      event_assign(&ev, base, sockfd, EV_WRITE, SocketReadOrWrite, &ev);
      event_add(&ev, NULL);
      io_wait_map_[sockfd] = running_thread_;
      running_thread_->Schedule();
      running_thread_->SetState(Thread::TS_STOP);
      Schedule();

      if (ev.ev_res & EV_TIMEOUT) {
        return -2;
        break;
      } else if (ev.ev_res & EV_WRITE) {
        continue;
      }
      return -1;
    } else if (ret < 0) {
      return -1;
    } else if (0 == ret) {
      return 0;
    }
  }

  return nsend;
}

int Frame::recv(int sockfd, void *buf, size_t len, int flags) {
  size_t recvd = 0;
  struct event ev;
  int ret = 0;
  while (true) {
    ret = ::recv(sockfd, buf, len, flags);
    if (ret > 0) {
      recvd += ret;
      return recvd;
    } else if (0 == ret) {  // reset by peer
      return 0;
    } else if (ret < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
        event_assign(&ev, base, sockfd, EV_READ | EV_CLOSED, SocketReadOrWrite,
                     &ev);
        event_add(&ev, NULL);
        io_wait_map_[sockfd] = running_thread_;
        running_thread_->Schedule();
        running_thread_->SetState(Thread::TS_STOP);
        Schedule();

        if (ev.ev_res & EV_TIMEOUT) {
          return -2;  // return timeout errcode
        } else if (ev.ev_res & EV_CLOSED) {
          return 0;
        } else if (ev.ev_res & EV_READ) {
          continue;
        }
      }

      break;
    }
  }

  return ret;
}

int Frame::sendto(int sockfd, const void *buf, size_t len, int flags,
                  const struct sockaddr *dest_addr, socklen_t addrlen) {
  return ::sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}

ssize_t Frame::recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen) {
  struct event ev;
  int ret = 0;
  while (true) {
    int ret =
        ::recvfrom(sockfd, buf, len, 0, (struct sockaddr *)src_addr, addrlen);
    if (ret > 0) {
      return ret;
    } else if (0 == ret) {
      return 0;
    } else if (ret < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
        event_assign(&ev, base, sockfd, EV_READ | EV_CLOSED, SocketReadOrWrite,
                     &ev);
        event_add(&ev, NULL);
        io_wait_map_[sockfd] = running_thread_;
        running_thread_->Schedule();
        running_thread_->SetState(Thread::TS_STOP);
        Schedule();

        if (ev.ev_res & EV_TIMEOUT) {
          return -2;  // return timeout errcode
        } else if (ev.ev_res & EV_CLOSED) {
          return 0;
        } else if (ev.ev_res & EV_READ) {
          continue;
        }
      }

      break;
    }
  }

  return ret;
}

void Frame::SocketReadOrWrite(int fd, short events, void *arg) {
  int ret = event_del(static_cast<event *>(arg));

  thread_runnable_.push_back(io_wait_map_[fd]);
  io_wait_map_.erase(fd);
  event_base_loopbreak(Frame::base);
}

int HandleProcess(void *arg) {
  auto *w = static_cast<Work *>(arg);
  LOG_DEBUG("run ret=%d", w->Run());
  delete w;

  // recycle the thread
  Frame::RecycleRunningThread();
  Frame::Schedule();
  return 0;
}

void Frame::RecycleRunningThread() {
  thread_free_.push_back(running_thread_);
  running_thread_ = NULL;
}

int Frame::CreateThread(Work *w) {
  // work will be deleted by HandleProcess()
  // thread should not be deleted before deleting work
  auto *t = new Thread;
  t->Init();
  t->SetContext(HandleProcess, w);
  thread_runnable_.push_back(t);
}

int Frame::Schedule() {
  if (thread_runnable_.empty()) {
    main_thread_->RestoreContext();
  } else {
    running_thread_ = *(thread_runnable_.begin());
    thread_runnable_.pop_front();
    running_thread_->RestoreContext();
  }
  return 0;
}

void Frame::Sleep(uint32_t ms) {
  if (running_thread_) {
    running_thread_->Pending(time::mstime() + ms);
    running_thread_->SetState(Thread::TS_STOP);
    thread_pending_.push_back(running_thread_);
    running_thread_->Schedule();
    running_thread_ = NULL;
  }

  Schedule();
}

void Frame::PendThread(Thread *t) {
  thread_pending_.push_back(t);
  make_heap(thread_pending_.begin(), thread_pending_.end(),
            ThreadPendingTimeComp());
}

void Frame::UpdateLoopTimestamp() { last_loop_ts_ = time::mstime(); }
}
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <af/array.h>
#include <af/lapack.h>
#include "error.hpp"

namespace af
{
    void lu(array &out, array &pivot, const array &in, const bool is_lapack_piv)
    {
        out = in.copy();
        af_array p = 0;
        AF_THROW(af_lu_inplace(&p, out.get(), is_lapack_piv));
        pivot = array(p);
    }

    void lu(array &lower, array &upper, array &pivot, const array &in)
    {
        af_array l = 0, u = 0, p = 0;
        AF_THROW(af_lu(&l, &u, &p, in.get()));
        lower = array(l);
        upper = array(u);
        pivot = array(p);
    }

    void luInPlace(array &pivot, array &in, const bool is_lapack_piv)
    {
        af_array p = 0;
        AF_THROW(af_lu_inplace(&p, in.get(), is_lapack_piv));
        pivot = array(p);
    }

    void qr(array &out, array &tau, const array &in)
    {
        out = in.copy();
        af_array t = 0;
        AF_THROW(af_qr_inplace(&t, out.get()));
        tau = array(t);
    }

    void qr(array &q, array &r, array &tau, const array &in)
    {
        af_array q_ = 0, r_ = 0, t_ = 0;
        AF_THROW(af_qr(&q_, &r_, &t_, in.get()));
        q = array(q_);
        r = array(r_);
        tau = array(t_);
    }

    void qrInPlace(array &tau, array &in)
    {
        af_array t = 0;
        AF_THROW(af_qr_inplace(&t, in.get()));
        tau = array(t);
    }

    int cholesky(array &out, const array &in, const bool is_upper)
    {
        int info = 0;
        af_array res;
        AF_THROW(af_cholesky(&res, &info, in.get(), is_upper));
        out = array(res);
        return info;
    }

    int choleskyInPlace(array &in, const bool is_upper)
    {
        int info = 0;
        AF_THROW(af_cholesky_inplace(&info, in.get(), is_upper));
        return info;
    }

    array solve(const array &a, const array &b, const matProp options)
    {
        af_array out;
        AF_THROW(af_solve(&out, a.get(), b.get(), options));
        return array(out);
    }

    array solveLU(const array &a, const array &piv,
                  const array &b, const matProp options)
    {
        af_array out;
        AF_THROW(af_solve_lu(&out, a.get(), piv.get(), b.get(), options));
        return array(out);
    }

    array inverse(const array &in, const matProp options)
    {
        af_array out;
        AF_THROW(af_inverse(&out, in.get(), options));
        return array(out);
    }

    uint rank(const array &in, const double tol)
    {
        uint r = 0;
        AF_THROW(af_rank(&r, in.get(), tol));
        return r;
    }

#define INSTANTIATE_DET(TR, TC)                     \
    template<> AFAPI                                \
    TR det(const array &in)                         \
    {                                               \
        double real;                                \
        double imag;                                \
        AF_THROW(af_det(&real, &imag, in.get()));   \
        return real;                                \
    }                                               \
    template<> AFAPI                                \
    TC det(const array &in)                         \
    {                                               \
        double real;                                \
        double imag;                                \
        AF_THROW(af_det(&real, &imag, in.get()));   \
        TC out((TR)real, (TR)imag);                 \
        return out;                                 \
    }                                               \

    INSTANTIATE_DET(float, af_cfloat)
    INSTANTIATE_DET(double, af_cdouble)

    double norm(const array &in, const normType type,
                const double p, const double q)
    {
        double out;
        AF_THROW(af_norm(&out, in.get(), type, p, q));
        return out;
    }
}
<commit_msg>More uint to unsigned<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <af/array.h>
#include <af/lapack.h>
#include "error.hpp"

namespace af
{
    void lu(array &out, array &pivot, const array &in, const bool is_lapack_piv)
    {
        out = in.copy();
        af_array p = 0;
        AF_THROW(af_lu_inplace(&p, out.get(), is_lapack_piv));
        pivot = array(p);
    }

    void lu(array &lower, array &upper, array &pivot, const array &in)
    {
        af_array l = 0, u = 0, p = 0;
        AF_THROW(af_lu(&l, &u, &p, in.get()));
        lower = array(l);
        upper = array(u);
        pivot = array(p);
    }

    void luInPlace(array &pivot, array &in, const bool is_lapack_piv)
    {
        af_array p = 0;
        AF_THROW(af_lu_inplace(&p, in.get(), is_lapack_piv));
        pivot = array(p);
    }

    void qr(array &out, array &tau, const array &in)
    {
        out = in.copy();
        af_array t = 0;
        AF_THROW(af_qr_inplace(&t, out.get()));
        tau = array(t);
    }

    void qr(array &q, array &r, array &tau, const array &in)
    {
        af_array q_ = 0, r_ = 0, t_ = 0;
        AF_THROW(af_qr(&q_, &r_, &t_, in.get()));
        q = array(q_);
        r = array(r_);
        tau = array(t_);
    }

    void qrInPlace(array &tau, array &in)
    {
        af_array t = 0;
        AF_THROW(af_qr_inplace(&t, in.get()));
        tau = array(t);
    }

    int cholesky(array &out, const array &in, const bool is_upper)
    {
        int info = 0;
        af_array res;
        AF_THROW(af_cholesky(&res, &info, in.get(), is_upper));
        out = array(res);
        return info;
    }

    int choleskyInPlace(array &in, const bool is_upper)
    {
        int info = 0;
        AF_THROW(af_cholesky_inplace(&info, in.get(), is_upper));
        return info;
    }

    array solve(const array &a, const array &b, const matProp options)
    {
        af_array out;
        AF_THROW(af_solve(&out, a.get(), b.get(), options));
        return array(out);
    }

    array solveLU(const array &a, const array &piv,
                  const array &b, const matProp options)
    {
        af_array out;
        AF_THROW(af_solve_lu(&out, a.get(), piv.get(), b.get(), options));
        return array(out);
    }

    array inverse(const array &in, const matProp options)
    {
        af_array out;
        AF_THROW(af_inverse(&out, in.get(), options));
        return array(out);
    }

    unsigned rank(const array &in, const double tol)
    {
        unsigned r = 0;
        AF_THROW(af_rank(&r, in.get(), tol));
        return r;
    }

#define INSTANTIATE_DET(TR, TC)                     \
    template<> AFAPI                                \
    TR det(const array &in)                         \
    {                                               \
        double real;                                \
        double imag;                                \
        AF_THROW(af_det(&real, &imag, in.get()));   \
        return real;                                \
    }                                               \
    template<> AFAPI                                \
    TC det(const array &in)                         \
    {                                               \
        double real;                                \
        double imag;                                \
        AF_THROW(af_det(&real, &imag, in.get()));   \
        TC out((TR)real, (TR)imag);                 \
        return out;                                 \
    }                                               \

    INSTANTIATE_DET(float, af_cfloat)
    INSTANTIATE_DET(double, af_cdouble)

    double norm(const array &in, const normType type,
                const double p, const double q)
    {
        double out;
        AF_THROW(af_norm(&out, in.get(), type, p, q));
        return out;
    }
}
<|endoftext|>


<commit_before>#include "hooks.h"
#include "undocumented.h"
#include "ssdt.h"
#include "hider.h"
#include "misc.h"
#include "pe.h"
#include "log.h"
#include "eprocess.h"

static HOOK hNtQueryInformationProcess=0;
static HOOK hNtQueryObject=0;
static HOOK hNtQuerySystemInformation=0;
static HOOK hNtClose=0;
static HOOK hNtSetInformationThread=0;
static HOOK hNtSetContextThread=0;
static HOOK hNtContinue=0;

static NTSTATUS NTAPI HookNtSetInformationThread(
    IN HANDLE ThreadHandle,
    IN THREADINFOCLASS ThreadInformationClass,
    IN PVOID ThreadInformation,
    IN ULONG ThreadInformationLength)
{
    if(ThreadInformationClass==ThreadHideFromDebugger)
    {
        ULONG pid=(ULONG)PsGetCurrentProcessId();
        if(HiderIsHidden(pid, HideThreadHideFromDebugger))
        {
            Log("[TITANHIDE] ThreadHideFromDebugger by %d\n", pid);
            //Taken from: http://newgre.net/idastealth
            PKTHREAD Object;
            NTSTATUS status=ObReferenceObjectByHandle(ThreadHandle, 0, NULL, KernelMode, (PVOID*)&Object, NULL);
            if(NT_SUCCESS(status))
            {
                ObDereferenceObject(Object);
                return STATUS_SUCCESS;
            }
            else
                return status;
        }
    }
    return Undocumented::NtSetInformationThread(ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength);
}

static NTSTATUS NTAPI HookNtClose(
    IN HANDLE Handle)
{
    ULONG pid=(ULONG)PsGetCurrentProcessId();
    NTSTATUS ret;
    if(HiderIsHidden(pid, HideNtClose))
    {
        /*
        //code by ahmadmansoor
        if(NT_SUCCESS(ObReferenceObjectByHandle(Handle,GENERIC_READ,0,UserMode,&XObject,NULL)))
        {
        	ObDereferenceObject(pObject);
            status = Undocumented::NtClose(Handle);
        }
        else
        {
        	status = STATUS_INVALID_HANDLE;
        }
        return status;
        */
        PVOID OldDebugPort=SetDebugPort(PsGetCurrentProcess(), 0);
        ret=Undocumented::NtClose(Handle);
        if(!NT_SUCCESS(ret))
            Log("[TITANHIDE] NtClose(0x%p) by %d\n", Handle, pid);
        SetDebugPort(PsGetCurrentProcess(), OldDebugPort);
    }
    else
        ret=Undocumented::NtClose(Handle);
    return ret;
}

static NTSTATUS NTAPI HookNtQuerySystemInformation(
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
    OUT PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    OUT PULONG ReturnLength OPTIONAL)
{
    NTSTATUS ret=Undocumented::NtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
    if(NT_SUCCESS(ret) && SystemInformation)
    {
        ULONG pid=(ULONG)PsGetCurrentProcessId();
        if(SystemInformationClass==SystemKernelDebuggerInformation)
        {
            if(HiderIsHidden(pid, HideSystemDebuggerInformation))
            {
                Log("[TITANHIDE] SystemKernelDebuggerInformation by %d\n", pid);
                typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION
                {
                    BOOLEAN DebuggerEnabled;
                    BOOLEAN DebuggerNotPresent;
                } SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION;
                SYSTEM_KERNEL_DEBUGGER_INFORMATION* DebuggerInfo=(SYSTEM_KERNEL_DEBUGGER_INFORMATION*)SystemInformation;
                DebuggerInfo->DebuggerEnabled=false;
                DebuggerInfo->DebuggerNotPresent=true;
            }
        }
    }
    return ret;
}

static NTSTATUS NTAPI HookNtQueryObject(
    IN HANDLE Handle OPTIONAL,
    IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
    OUT PVOID ObjectInformation OPTIONAL,
    IN ULONG ObjectInformationLength,
    OUT PULONG ReturnLength OPTIONAL)
{
    NTSTATUS ret=Undocumented::NtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
    if(NT_SUCCESS(ret) && ObjectInformation)
    {
        ULONG pid=(ULONG)PsGetCurrentProcessId();
        UNICODE_STRING DebugObject;
        RtlInitUnicodeString(&DebugObject, L"DebugObject");
        if(ObjectInformationClass==ObjectTypeInformation)
        {
            OBJECT_TYPE_INFORMATION* type=(OBJECT_TYPE_INFORMATION*)ObjectInformation;
            if(RtlEqualUnicodeString(&type->TypeName, &DebugObject, FALSE)) //DebugObject
            {
                if(HiderIsHidden(pid, HideDebugObject))
                {
                    Log("[TITANHIDE] DebugObject by %d\n", pid);
                    type->TotalNumberOfObjects=0;
                }
            }
        }
        else if(ObjectInformationClass==ObjectAllInformation)
        {
            OBJECT_ALL_INFORMATION* pObjectAllInfo=(OBJECT_ALL_INFORMATION*)ObjectInformation;
            unsigned char* pObjInfoLocation=(unsigned char*)pObjectAllInfo->ObjectTypeInformation;
            unsigned int TotalObjects=pObjectAllInfo->NumberOfObjects;
            for(unsigned int i=0; i<TotalObjects; i++)
            {
                OBJECT_TYPE_INFORMATION* pObjectTypeInfo=(OBJECT_TYPE_INFORMATION*)pObjInfoLocation;
                if(RtlEqualUnicodeString(&pObjectTypeInfo->TypeName, &DebugObject, FALSE)) //DebugObject
                {
                    if(HiderIsHidden(pid, HideDebugObject))
                    {
                        Log("[TITANHIDE] DebugObject by %d\n", pid);
                        pObjectTypeInfo->TotalNumberOfObjects=0;
                    }
                }
                pObjInfoLocation=(unsigned char*)pObjectTypeInfo->TypeName.Buffer;
                pObjInfoLocation+=pObjectTypeInfo->TypeName.MaximumLength;
                ULONG_PTR tmp=((ULONG_PTR)pObjInfoLocation)&-sizeof(void*);
                if((ULONG_PTR)tmp!=(ULONG_PTR)pObjInfoLocation)
                    tmp+=sizeof(void*);
                pObjInfoLocation=((unsigned char*)tmp);
            }
        }
    }
    return ret;
}

static NTSTATUS NTAPI HookNtQueryInformationProcess(
    IN HANDLE ProcessHandle,
    IN PROCESSINFOCLASS ProcessInformationClass,
    OUT PVOID ProcessInformation,
    IN ULONG ProcessInformationLength,
    OUT PULONG ReturnLength)
{
    SSDTunhook(hNtQueryInformationProcess);
    NTSTATUS ret=Undocumented::NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength);
    if(NT_SUCCESS(ret) && ProcessInformation)
    {
        ULONG pid=GetProcessIDFromProcessHandle(ProcessHandle);

        if(ProcessInformationClass==ProcessDebugFlags)
        {
            if(HiderIsHidden(pid, HideProcessDebugFlags))
            {
                Log("[TITANHIDE] ProcessDebugFlags by %d\n", pid);
                *(unsigned int*)ProcessInformation=TRUE;
            }
        }
        else if(ProcessInformationClass==ProcessDebugPort)
        {
            if(HiderIsHidden(pid, HideProcessDebugPort))
            {
                Log("[TITANHIDE] ProcessDebugPort by %d\n", pid);
                *(ULONG_PTR*)ProcessInformation=0;
            }
        }
        else if(ProcessInformationClass==ProcessDebugObjectHandle)
        {
            if(HiderIsHidden(pid, HideProcessDebugObjectHandle))
            {
                Log("[TITANHIDE] ProcessDebugObjectHandle by %d\n", pid);
                //Taken from: http://newgre.net/idastealth
                ret=STATUS_PORT_NOT_SET;
            }
        }
    }
    SSDThook(hNtQueryInformationProcess);
    return ret;
}

static NTSTATUS NTAPI HookNtSetContextThread(
    IN HANDLE ThreadHandle,
    IN PCONTEXT Context)
{
    ULONG pid=(ULONG)PsGetCurrentProcessId();
    bool IsHidden=HiderIsHidden(pid, HideNtSetContextThread);
    DWORD OriginalContextFlags;
    if(Context && IsHidden)
    {
        Log("[TITANHIDE] NtSetContextThread by %d\n", pid);
        OriginalContextFlags=Context->ContextFlags;
        Context->ContextFlags&=~CONTEXT_DEBUG_REGISTERS;
    }
    NTSTATUS ret=Undocumented::NtSetContextThread(ThreadHandle, Context);
    if(Context && IsHidden)
        Context->ContextFlags=OriginalContextFlags;
    return ret;
}

int HooksInit()
{
    int hook_count=0;
    hNtQueryInformationProcess=SSDThook(L"NtQueryInformationProcess", (void*)HookNtQueryInformationProcess);
    if(hNtQueryInformationProcess)
        hook_count++;
    hNtQueryObject=SSDThook(L"NtQueryObject", (void*)HookNtQueryObject);
    if(hNtQueryObject)
        hook_count++;
    hNtQuerySystemInformation=SSDThook(L"NtQuerySystemInformation", (void*)HookNtQuerySystemInformation);
    if(hNtQuerySystemInformation)
        hook_count++;
    hNtSetInformationThread=SSDThook(L"NtSetInformationThread", (void*)HookNtSetInformationThread);
    if(hNtSetInformationThread)
        hook_count++;
    hNtClose=SSDThook(L"NtClose", (void*)HookNtClose);
    if(hNtClose)
        hook_count++;
    hNtSetContextThread=SSDThook(L"NtSetContextThread", (void*)HookNtSetContextThread);
    if(hNtSetContextThread)
        hook_count++;
    return hook_count;
}

void HooksFree()
{
    SSDTunhook(hNtQueryInformationProcess, true);
    SSDTunhook(hNtQueryObject, true);
    SSDTunhook(hNtQuerySystemInformation, true);
    SSDTunhook(hNtSetInformationThread, true);
    SSDTunhook(hNtClose, true);
    SSDTunhook(hNtSetContextThread, true);
}
<commit_msg>full remove<commit_after>#include "hooks.h"
#include "undocumented.h"
#include "ssdt.h"
#include "hider.h"
#include "misc.h"
#include "pe.h"
#include "log.h"
#include "eprocess.h"

static HOOK hNtQueryInformationProcess=0;
static HOOK hNtQueryObject=0;
static HOOK hNtQuerySystemInformation=0;
static HOOK hNtClose=0;
static HOOK hNtSetInformationThread=0;
static HOOK hNtSetContextThread=0;

static NTSTATUS NTAPI HookNtSetInformationThread(
    IN HANDLE ThreadHandle,
    IN THREADINFOCLASS ThreadInformationClass,
    IN PVOID ThreadInformation,
    IN ULONG ThreadInformationLength)
{
    if(ThreadInformationClass==ThreadHideFromDebugger)
    {
        ULONG pid=(ULONG)PsGetCurrentProcessId();
        if(HiderIsHidden(pid, HideThreadHideFromDebugger))
        {
            Log("[TITANHIDE] ThreadHideFromDebugger by %d\n", pid);
            //Taken from: http://newgre.net/idastealth
            PKTHREAD Object;
            NTSTATUS status=ObReferenceObjectByHandle(ThreadHandle, 0, NULL, KernelMode, (PVOID*)&Object, NULL);
            if(NT_SUCCESS(status))
            {
                ObDereferenceObject(Object);
                return STATUS_SUCCESS;
            }
            else
                return status;
        }
    }
    return Undocumented::NtSetInformationThread(ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength);
}

static NTSTATUS NTAPI HookNtClose(
    IN HANDLE Handle)
{
    ULONG pid=(ULONG)PsGetCurrentProcessId();
    NTSTATUS ret;
    if(HiderIsHidden(pid, HideNtClose))
    {
        /*
        //code by ahmadmansoor
        if(NT_SUCCESS(ObReferenceObjectByHandle(Handle,GENERIC_READ,0,UserMode,&XObject,NULL)))
        {
        	ObDereferenceObject(pObject);
            status = Undocumented::NtClose(Handle);
        }
        else
        {
        	status = STATUS_INVALID_HANDLE;
        }
        return status;
        */
        PVOID OldDebugPort=SetDebugPort(PsGetCurrentProcess(), 0);
        ret=Undocumented::NtClose(Handle);
        if(!NT_SUCCESS(ret))
            Log("[TITANHIDE] NtClose(0x%p) by %d\n", Handle, pid);
        SetDebugPort(PsGetCurrentProcess(), OldDebugPort);
    }
    else
        ret=Undocumented::NtClose(Handle);
    return ret;
}

static NTSTATUS NTAPI HookNtQuerySystemInformation(
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
    OUT PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    OUT PULONG ReturnLength OPTIONAL)
{
    NTSTATUS ret=Undocumented::NtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
    if(NT_SUCCESS(ret) && SystemInformation)
    {
        ULONG pid=(ULONG)PsGetCurrentProcessId();
        if(SystemInformationClass==SystemKernelDebuggerInformation)
        {
            if(HiderIsHidden(pid, HideSystemDebuggerInformation))
            {
                Log("[TITANHIDE] SystemKernelDebuggerInformation by %d\n", pid);
                typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION
                {
                    BOOLEAN DebuggerEnabled;
                    BOOLEAN DebuggerNotPresent;
                } SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION;
                SYSTEM_KERNEL_DEBUGGER_INFORMATION* DebuggerInfo=(SYSTEM_KERNEL_DEBUGGER_INFORMATION*)SystemInformation;
                DebuggerInfo->DebuggerEnabled=false;
                DebuggerInfo->DebuggerNotPresent=true;
            }
        }
    }
    return ret;
}

static NTSTATUS NTAPI HookNtQueryObject(
    IN HANDLE Handle OPTIONAL,
    IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
    OUT PVOID ObjectInformation OPTIONAL,
    IN ULONG ObjectInformationLength,
    OUT PULONG ReturnLength OPTIONAL)
{
    NTSTATUS ret=Undocumented::NtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
    if(NT_SUCCESS(ret) && ObjectInformation)
    {
        ULONG pid=(ULONG)PsGetCurrentProcessId();
        UNICODE_STRING DebugObject;
        RtlInitUnicodeString(&DebugObject, L"DebugObject");
        if(ObjectInformationClass==ObjectTypeInformation)
        {
            OBJECT_TYPE_INFORMATION* type=(OBJECT_TYPE_INFORMATION*)ObjectInformation;
            if(RtlEqualUnicodeString(&type->TypeName, &DebugObject, FALSE)) //DebugObject
            {
                if(HiderIsHidden(pid, HideDebugObject))
                {
                    Log("[TITANHIDE] DebugObject by %d\n", pid);
                    type->TotalNumberOfObjects=0;
                }
            }
        }
        else if(ObjectInformationClass==ObjectAllInformation)
        {
            OBJECT_ALL_INFORMATION* pObjectAllInfo=(OBJECT_ALL_INFORMATION*)ObjectInformation;
            unsigned char* pObjInfoLocation=(unsigned char*)pObjectAllInfo->ObjectTypeInformation;
            unsigned int TotalObjects=pObjectAllInfo->NumberOfObjects;
            for(unsigned int i=0; i<TotalObjects; i++)
            {
                OBJECT_TYPE_INFORMATION* pObjectTypeInfo=(OBJECT_TYPE_INFORMATION*)pObjInfoLocation;
                if(RtlEqualUnicodeString(&pObjectTypeInfo->TypeName, &DebugObject, FALSE)) //DebugObject
                {
                    if(HiderIsHidden(pid, HideDebugObject))
                    {
                        Log("[TITANHIDE] DebugObject by %d\n", pid);
                        pObjectTypeInfo->TotalNumberOfObjects=0;
                    }
                }
                pObjInfoLocation=(unsigned char*)pObjectTypeInfo->TypeName.Buffer;
                pObjInfoLocation+=pObjectTypeInfo->TypeName.MaximumLength;
                ULONG_PTR tmp=((ULONG_PTR)pObjInfoLocation)&-sizeof(void*);
                if((ULONG_PTR)tmp!=(ULONG_PTR)pObjInfoLocation)
                    tmp+=sizeof(void*);
                pObjInfoLocation=((unsigned char*)tmp);
            }
        }
    }
    return ret;
}

static NTSTATUS NTAPI HookNtQueryInformationProcess(
    IN HANDLE ProcessHandle,
    IN PROCESSINFOCLASS ProcessInformationClass,
    OUT PVOID ProcessInformation,
    IN ULONG ProcessInformationLength,
    OUT PULONG ReturnLength)
{
    SSDTunhook(hNtQueryInformationProcess);
    NTSTATUS ret=Undocumented::NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength);
    if(NT_SUCCESS(ret) && ProcessInformation)
    {
        ULONG pid=GetProcessIDFromProcessHandle(ProcessHandle);

        if(ProcessInformationClass==ProcessDebugFlags)
        {
            if(HiderIsHidden(pid, HideProcessDebugFlags))
            {
                Log("[TITANHIDE] ProcessDebugFlags by %d\n", pid);
                *(unsigned int*)ProcessInformation=TRUE;
            }
        }
        else if(ProcessInformationClass==ProcessDebugPort)
        {
            if(HiderIsHidden(pid, HideProcessDebugPort))
            {
                Log("[TITANHIDE] ProcessDebugPort by %d\n", pid);
                *(ULONG_PTR*)ProcessInformation=0;
            }
        }
        else if(ProcessInformationClass==ProcessDebugObjectHandle)
        {
            if(HiderIsHidden(pid, HideProcessDebugObjectHandle))
            {
                Log("[TITANHIDE] ProcessDebugObjectHandle by %d\n", pid);
                //Taken from: http://newgre.net/idastealth
                ret=STATUS_PORT_NOT_SET;
            }
        }
    }
    SSDThook(hNtQueryInformationProcess);
    return ret;
}

static NTSTATUS NTAPI HookNtSetContextThread(
    IN HANDLE ThreadHandle,
    IN PCONTEXT Context)
{
    ULONG pid=(ULONG)PsGetCurrentProcessId();
    bool IsHidden=HiderIsHidden(pid, HideNtSetContextThread);
    DWORD OriginalContextFlags;
    if(Context && IsHidden)
    {
        Log("[TITANHIDE] NtSetContextThread by %d\n", pid);
        OriginalContextFlags=Context->ContextFlags;
        Context->ContextFlags&=~CONTEXT_DEBUG_REGISTERS;
    }
    NTSTATUS ret=Undocumented::NtSetContextThread(ThreadHandle, Context);
    if(Context && IsHidden)
        Context->ContextFlags=OriginalContextFlags;
    return ret;
}

int HooksInit()
{
    int hook_count=0;
    hNtQueryInformationProcess=SSDThook(L"NtQueryInformationProcess", (void*)HookNtQueryInformationProcess);
    if(hNtQueryInformationProcess)
        hook_count++;
    hNtQueryObject=SSDThook(L"NtQueryObject", (void*)HookNtQueryObject);
    if(hNtQueryObject)
        hook_count++;
    hNtQuerySystemInformation=SSDThook(L"NtQuerySystemInformation", (void*)HookNtQuerySystemInformation);
    if(hNtQuerySystemInformation)
        hook_count++;
    hNtSetInformationThread=SSDThook(L"NtSetInformationThread", (void*)HookNtSetInformationThread);
    if(hNtSetInformationThread)
        hook_count++;
    hNtClose=SSDThook(L"NtClose", (void*)HookNtClose);
    if(hNtClose)
        hook_count++;
    hNtSetContextThread=SSDThook(L"NtSetContextThread", (void*)HookNtSetContextThread);
    if(hNtSetContextThread)
        hook_count++;
    return hook_count;
}

void HooksFree()
{
    SSDTunhook(hNtQueryInformationProcess, true);
    SSDTunhook(hNtQueryObject, true);
    SSDTunhook(hNtQuerySystemInformation, true);
    SSDTunhook(hNtSetInformationThread, true);
    SSDTunhook(hNtClose, true);
    SSDTunhook(hNtSetContextThread, true);
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_
#define __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_

#include <threadhelp/threadhelpbase.hxx>
#include <macros/generic.hxx>
#include <macros/xinterface.hxx>
#include <macros/xtypeprovider.hxx>
#include <stdtypes.h>
#include <uielement/commandinfo.hxx>

#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XStatusListener.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/frame/XModuleManager.hpp>
#include <com/sun/star/frame/XUIControllerRegistration.hpp>
#include <com/sun/star/ui/XImageManager.hpp>
#include <com/sun/star/ui/XUIConfigurationManager.hpp>
#include <com/sun/star/frame/XSubToolbarController.hpp>
#include <com/sun/star/frame/XToolbarController.hpp>
#include <com/sun/star/ui/ItemStyle.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/ui/XAcceleratorConfiguration.hpp>

#include <rtl/ustring.hxx>
#include <cppuhelper/weak.hxx>
#include <cppuhelper/interfacecontainer.hxx>

#include <vcl/toolbox.hxx>
#include <vcl/accel.hxx>

namespace com
{
    namespace sun
    {
        namespace star
        {
            namespace frame
            {
                class XLayoutManager;
            }
        }
    }
}

namespace framework
{

class ToolBar;
class ToolBarManager : public ::com::sun::star::frame::XFrameActionListener         ,
                       public ::com::sun::star::frame::XStatusListener              ,
                       public ::com::sun::star::lang::XComponent                    ,
                       public ::com::sun::star::lang::XTypeProvider                 ,
                       public ::com::sun::star::ui::XUIConfigurationListener,
                       public ThreadHelpBase                                        ,
                       public ::cppu::OWeakObject
{
    public:
        ToolBarManager( const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& rxContext,
                        const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& rFrame,
                        const OUString& rResourceName,
                        ToolBar* pToolBar );
        virtual ~ToolBarManager();

        //  XInterface, XTypeProvider, XServiceInfo
        FWK_DECLARE_XINTERFACE
        FWK_DECLARE_XTYPEPROVIDER

        ToolBox* GetToolBar() const;

        // XFrameActionListener
        virtual void SAL_CALL frameAction( const com::sun::star::frame::FrameActionEvent& Action ) throw ( ::com::sun::star::uno::RuntimeException );

        // XStatusListener
        virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException );

        // XEventListener
        virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& Source ) throw ( ::com::sun::star::uno::RuntimeException );

        // XUIConfigurationListener
        virtual void SAL_CALL elementInserted( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementRemoved( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementReplaced( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);

        // XComponent
        void SAL_CALL dispose() throw ( ::com::sun::star::uno::RuntimeException );
        void SAL_CALL addEventListener( const com::sun::star::uno::Reference< XEventListener >& xListener ) throw( com::sun::star::uno::RuntimeException );
        void SAL_CALL removeEventListener( const com::sun::star::uno::Reference< XEventListener >& xListener ) throw( com::sun::star::uno::RuntimeException );

        void CheckAndUpdateImages();
        virtual void RefreshImages();
        void FillToolbar( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rToolBarData );
        void notifyRegisteredControllers( const OUString& aUIElementName, const OUString& aCommand );
        void Destroy();

        enum ExecuteCommand
        {
            EXEC_CMD_CLOSETOOLBAR,
            EXEC_CMD_DOCKTOOLBAR,
            EXEC_CMD_DOCKALLTOOLBARS,
            EXEC_CMD_NONE,
            EXEC_CMD_COUNT
        };

        struct ExecuteInfo
        {
            OUString   aToolbarResName;
            ExecuteCommand  nCmd;
            ::com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
            ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > xWindow;
        };
        struct ControllerParams
        {
            sal_Int16 nWidth;
        };
        typedef std::vector< ControllerParams > ControllerParamsVector;

    protected:
        DECL_LINK( Command, CommandEvent * );
        PopupMenu * GetToolBarCustomMenu(ToolBox* pToolBar);
        DECL_LINK(Click, void *);
        DECL_LINK(DropdownClick, void *);
        DECL_LINK(DoubleClick, void *);
        DECL_LINK(Select, void *);
        DECL_LINK(Activate, void *);
        DECL_LINK(Deactivate, void *);
        DECL_LINK( StateChanged, StateChangedType* );
        DECL_LINK( DataChanged, DataChangedEvent* );
        DECL_LINK( MiscOptionsChanged, void* );

        DECL_LINK( MenuButton, ToolBox * );
        DECL_LINK( MenuSelect, Menu * );
        DECL_LINK( MenuDeactivate, Menu * );
        DECL_LINK(AsyncUpdateControllersHdl, void *);
        DECL_STATIC_LINK( ToolBarManager, ExecuteHdl_Impl, ExecuteInfo* );

        virtual bool MenuItemAllowed( sal_uInt16 ) const;

        void RemoveControllers();
        OUString RetrieveLabelFromCommand( const OUString& aCmdURL );
        sal_Int32 RetrievePropertiesFromCommand( const OUString& aCmdURL );
        ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > GetPropsForCommand( const OUString& rCmdURL );
        void CreateControllers();
        void UpdateControllers();
        //for update controller via Support Visiable
        void UpdateController( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XToolbarController > xController);
        //end
        void AddFrameActionListener();
        void AddImageOrientationListener();
        void UpdateImageOrientation();
        void ImplClearPopupMenu( ToolBox *pToolBar );
        void RequestImages();
        sal_uInt16 ConvertStyleToToolboxItemBits( sal_Int32 nStyle );
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > GetModelFromFrame() const;
        sal_Bool IsPluginMode() const;
        Image QueryAddonsImage( const OUString& aCommandURL, bool bBigImages );
        long HandleClick(void ( SAL_CALL ::com::sun::star::frame::XToolbarController::*_pClick )(  ));
        void setToolBarImage(const Image& _aImage,const CommandToInfoMap::const_iterator& _pIter);
        void impl_elementChanged(bool _bRemove,const ::com::sun::star::ui::ConfigurationEvent& Event );

        static bool impl_RetrieveShortcutsFromConfiguration( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >& rAccelCfg, const OUString& rCommand, OUString& rShortCut );
        bool RetrieveShortcut( const OUString& rCommandURL, OUString& rShortCut );

    protected:
        typedef ::boost::unordered_map< sal_uInt16, ::com::sun::star::uno::Reference< com::sun::star::frame::XStatusListener > > ToolBarControllerMap;
        typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XSubToolbarController > > SubToolBarControllerVector;
        typedef BaseHash< SubToolBarControllerVector >                                                              SubToolBarToSubToolBarControllerMap;

        typedef ::boost::unordered_map< sal_uInt16, ::com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess > > MenuDescriptionMap;
        sal_Bool                                                                               m_bDisposed : 1,
                                                                                m_bSmallSymbols : 1,
                                                                                m_bModuleIdentified : 1,
                                                                                m_bAddedToTaskPaneList : 1,
                                                                                m_bVerticalTextEnabled : 1,
                                                                                m_bFrameActionRegistered : 1,
                                                                                m_bUpdateControllers : 1;
        sal_Bool                                                                               m_bImageOrientationRegistered : 1,
                                                                                m_bImageMirrored : 1;
        long                                                                                m_lImageRotation;
        ToolBar*                                                                               m_pToolBar;
        OUString                                                                          m_aModuleIdentifier;
        OUString                                                                          m_aResourceName;
        com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer >              m_xURLTransformer;
        com::sun::star::uno::Reference< com::sun::star::frame::XFrame >                        m_xFrame;
        com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >               m_xUICommandLabels;
        ToolBarControllerMap                                                                   m_aControllerMap;
        ::cppu::OMultiTypeInterfaceContainerHelper                                             m_aListenerContainer;   /// container for ALL Listener
        ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >             m_xContext;
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XUIControllerRegistration > m_xToolbarControllerRegistration;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XImageManager >                m_xModuleImageManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XImageManager >                m_xDocImageManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >                 m_xImageOrientationListener;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationManager >                m_xUICfgMgr;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationManager >                m_xDocUICfgMgr;

        CommandToInfoMap                                                                       m_aCommandMap;
        SubToolBarToSubToolBarControllerMap                                                    m_aSubToolBarControllerMap;
        Timer                                                                                m_aAsyncUpdateControllersTimer;
        sal_Int16                                                                              m_nSymbolsStyle;
        MenuDescriptionMap m_aMenuMap;
        sal_Bool                                                                               m_bAcceleratorCfg;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >    m_xDocAcceleratorManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >    m_xModuleAcceleratorManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >    m_xGlobalAcceleratorManager;
};

}

#endif // __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Include is better here.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_
#define __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_

#include <threadhelp/threadhelpbase.hxx>
#include <macros/generic.hxx>
#include <macros/xinterface.hxx>
#include <macros/xtypeprovider.hxx>
#include <stdtypes.h>
#include <uielement/commandinfo.hxx>

#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XStatusListener.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/frame/XModuleManager.hpp>
#include <com/sun/star/frame/XUIControllerRegistration.hpp>
#include <com/sun/star/ui/XImageManager.hpp>
#include <com/sun/star/ui/XUIConfigurationManager.hpp>
#include <com/sun/star/frame/XSubToolbarController.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/frame/XToolbarController.hpp>
#include <com/sun/star/ui/ItemStyle.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/ui/XAcceleratorConfiguration.hpp>

#include <rtl/ustring.hxx>
#include <cppuhelper/weak.hxx>
#include <cppuhelper/interfacecontainer.hxx>

#include <vcl/toolbox.hxx>
#include <vcl/accel.hxx>

namespace framework
{

class ToolBar;
class ToolBarManager : public ::com::sun::star::frame::XFrameActionListener         ,
                       public ::com::sun::star::frame::XStatusListener              ,
                       public ::com::sun::star::lang::XComponent                    ,
                       public ::com::sun::star::lang::XTypeProvider                 ,
                       public ::com::sun::star::ui::XUIConfigurationListener,
                       public ThreadHelpBase                                        ,
                       public ::cppu::OWeakObject
{
    public:
        ToolBarManager( const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& rxContext,
                        const com::sun::star::uno::Reference< com::sun::star::frame::XFrame >& rFrame,
                        const OUString& rResourceName,
                        ToolBar* pToolBar );
        virtual ~ToolBarManager();

        //  XInterface, XTypeProvider, XServiceInfo
        FWK_DECLARE_XINTERFACE
        FWK_DECLARE_XTYPEPROVIDER

        ToolBox* GetToolBar() const;

        // XFrameActionListener
        virtual void SAL_CALL frameAction( const com::sun::star::frame::FrameActionEvent& Action ) throw ( ::com::sun::star::uno::RuntimeException );

        // XStatusListener
        virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException );

        // XEventListener
        virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& Source ) throw ( ::com::sun::star::uno::RuntimeException );

        // XUIConfigurationListener
        virtual void SAL_CALL elementInserted( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementRemoved( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementReplaced( const ::com::sun::star::ui::ConfigurationEvent& Event ) throw (::com::sun::star::uno::RuntimeException);

        // XComponent
        void SAL_CALL dispose() throw ( ::com::sun::star::uno::RuntimeException );
        void SAL_CALL addEventListener( const com::sun::star::uno::Reference< XEventListener >& xListener ) throw( com::sun::star::uno::RuntimeException );
        void SAL_CALL removeEventListener( const com::sun::star::uno::Reference< XEventListener >& xListener ) throw( com::sun::star::uno::RuntimeException );

        void CheckAndUpdateImages();
        virtual void RefreshImages();
        void FillToolbar( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& rToolBarData );
        void notifyRegisteredControllers( const OUString& aUIElementName, const OUString& aCommand );
        void Destroy();

        enum ExecuteCommand
        {
            EXEC_CMD_CLOSETOOLBAR,
            EXEC_CMD_DOCKTOOLBAR,
            EXEC_CMD_DOCKALLTOOLBARS,
            EXEC_CMD_NONE,
            EXEC_CMD_COUNT
        };

        struct ExecuteInfo
        {
            OUString   aToolbarResName;
            ExecuteCommand  nCmd;
            ::com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
            ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > xWindow;
        };
        struct ControllerParams
        {
            sal_Int16 nWidth;
        };
        typedef std::vector< ControllerParams > ControllerParamsVector;

    protected:
        DECL_LINK( Command, CommandEvent * );
        PopupMenu * GetToolBarCustomMenu(ToolBox* pToolBar);
        DECL_LINK(Click, void *);
        DECL_LINK(DropdownClick, void *);
        DECL_LINK(DoubleClick, void *);
        DECL_LINK(Select, void *);
        DECL_LINK(Activate, void *);
        DECL_LINK(Deactivate, void *);
        DECL_LINK( StateChanged, StateChangedType* );
        DECL_LINK( DataChanged, DataChangedEvent* );
        DECL_LINK( MiscOptionsChanged, void* );

        DECL_LINK( MenuButton, ToolBox * );
        DECL_LINK( MenuSelect, Menu * );
        DECL_LINK( MenuDeactivate, Menu * );
        DECL_LINK(AsyncUpdateControllersHdl, void *);
        DECL_STATIC_LINK( ToolBarManager, ExecuteHdl_Impl, ExecuteInfo* );

        virtual bool MenuItemAllowed( sal_uInt16 ) const;

        void RemoveControllers();
        OUString RetrieveLabelFromCommand( const OUString& aCmdURL );
        sal_Int32 RetrievePropertiesFromCommand( const OUString& aCmdURL );
        ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > GetPropsForCommand( const OUString& rCmdURL );
        void CreateControllers();
        void UpdateControllers();
        //for update controller via Support Visiable
        void UpdateController( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XToolbarController > xController);
        //end
        void AddFrameActionListener();
        void AddImageOrientationListener();
        void UpdateImageOrientation();
        void ImplClearPopupMenu( ToolBox *pToolBar );
        void RequestImages();
        sal_uInt16 ConvertStyleToToolboxItemBits( sal_Int32 nStyle );
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > GetModelFromFrame() const;
        sal_Bool IsPluginMode() const;
        Image QueryAddonsImage( const OUString& aCommandURL, bool bBigImages );
        long HandleClick(void ( SAL_CALL ::com::sun::star::frame::XToolbarController::*_pClick )(  ));
        void setToolBarImage(const Image& _aImage,const CommandToInfoMap::const_iterator& _pIter);
        void impl_elementChanged(bool _bRemove,const ::com::sun::star::ui::ConfigurationEvent& Event );

        static bool impl_RetrieveShortcutsFromConfiguration( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >& rAccelCfg, const OUString& rCommand, OUString& rShortCut );
        bool RetrieveShortcut( const OUString& rCommandURL, OUString& rShortCut );

    protected:
        typedef ::boost::unordered_map< sal_uInt16, ::com::sun::star::uno::Reference< com::sun::star::frame::XStatusListener > > ToolBarControllerMap;
        typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XSubToolbarController > > SubToolBarControllerVector;
        typedef BaseHash< SubToolBarControllerVector >                                                              SubToolBarToSubToolBarControllerMap;

        typedef ::boost::unordered_map< sal_uInt16, ::com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess > > MenuDescriptionMap;
        sal_Bool                                                                               m_bDisposed : 1,
                                                                                m_bSmallSymbols : 1,
                                                                                m_bModuleIdentified : 1,
                                                                                m_bAddedToTaskPaneList : 1,
                                                                                m_bVerticalTextEnabled : 1,
                                                                                m_bFrameActionRegistered : 1,
                                                                                m_bUpdateControllers : 1;
        sal_Bool                                                                               m_bImageOrientationRegistered : 1,
                                                                                m_bImageMirrored : 1;
        long                                                                                m_lImageRotation;
        ToolBar*                                                                               m_pToolBar;
        OUString                                                                          m_aModuleIdentifier;
        OUString                                                                          m_aResourceName;
        com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer >              m_xURLTransformer;
        com::sun::star::uno::Reference< com::sun::star::frame::XFrame >                        m_xFrame;
        com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >               m_xUICommandLabels;
        ToolBarControllerMap                                                                   m_aControllerMap;
        ::cppu::OMultiTypeInterfaceContainerHelper                                             m_aListenerContainer;   /// container for ALL Listener
        ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >             m_xContext;
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XUIControllerRegistration > m_xToolbarControllerRegistration;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XImageManager >                m_xModuleImageManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XImageManager >                m_xDocImageManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >                 m_xImageOrientationListener;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationManager >                m_xUICfgMgr;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationManager >                m_xDocUICfgMgr;

        CommandToInfoMap                                                                       m_aCommandMap;
        SubToolBarToSubToolBarControllerMap                                                    m_aSubToolBarControllerMap;
        Timer                                                                                m_aAsyncUpdateControllersTimer;
        sal_Int16                                                                              m_nSymbolsStyle;
        MenuDescriptionMap m_aMenuMap;
        sal_Bool                                                                               m_bAcceleratorCfg;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >    m_xDocAcceleratorManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >    m_xModuleAcceleratorManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::ui::XAcceleratorConfiguration >    m_xGlobalAcceleratorManager;
};

}

#endif // __FRAMEWORK_UIELEMENT_TOOLBARMANAGER_HXX_

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/* Copyright 2014 Jonas Platte
 *
 * This file is part of Cyvasse Online.
 *
 * Cyvasse Online is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Cyvasse Online is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program.
 * If not, see <http://www.gnu.org/licenses/>.
 */

#include "job_handler.hpp"

#include <chrono>
#include <random>
#include <set>
#include <stdexcept>
#include <jsoncpp/json/value.h>
#include <jsoncpp/json/reader.h>
#include <jsoncpp/json/writer.h>
#include <tntdb/error.h>
#include <server_message.hpp>
#include <cyvdb/match.hpp>
#include <cyvdb/match_manager.hpp>
#include <cyvmath/match.hpp>
#include <cyvmath/player.hpp>
#include <cyvmath/rule_set_create.hpp>
#include "b64.hpp"
#include "cyvasse_server.hpp"
#include "client_data.hpp"
#include "match_data.hpp"

using namespace cyvmath;
using namespace std::chrono;

JobHandler::JobHandler(CyvasseServer& server)
	: m_server(server)
	, m_thread(std::bind(&JobHandler::processMessages, this))
{ }

JobHandler::~JobHandler()
{
	m_thread.join();
}

void JobHandler::processMessages()
{
	typedef CyvasseServer::Job Job;
	using namespace websocketpp::frame;

	auto& clientDataSets = m_server.m_clientDataSets;
	auto& matches = m_server.m_matches;
	auto& server = m_server.m_wsServer;

	Json::Reader reader;
	Json::FastWriter writer;

	while(m_server.m_running)
	{
		std::unique_lock<std::mutex> jobLock(m_server.m_jobMtx);

		while(m_server.m_running && m_server.m_jobQueue.empty())
			m_server.m_jobCond.wait(jobLock);

		if(!m_server.m_running)
			break;

		std::unique_ptr<Job> job = std::move(m_server.m_jobQueue.front());
		m_server.m_jobQueue.pop();

		jobLock.unlock();

		try
		{
			// Process job
			Json::Value msgData;
			if(!reader.parse(job->second->get_payload(), msgData, false))
			{
				// TODO: reply with error message
				return;
			}

			std::set<websocketpp::connection_hdl, std::owner_less<websocketpp::connection_hdl>> otherClients;

			std::shared_ptr<ClientData> clientData;

			std::unique_lock<std::mutex> matchDataLock(m_server.m_matchDataMtx, std::defer_lock); // don't lock yet
			std::unique_lock<std::mutex> clientDataLock(m_server.m_clientDataMtx);

			auto it1 = clientDataSets.find(job->first);
			if(it1 != clientDataSets.end())
			{
				clientData = it1->second;
				clientDataLock.unlock();

				for(auto it2 : clientData->getMatchData().getClientDataSets())
				{
					if(*it2 != *clientData)
						otherClients.insert(it2->getConnHdl());
				}
			}
			else clientDataLock.unlock();

			switch(StrToMessage(msgData["messageType"].asString()))
			{
				case Message::REQUEST:
				{
					auto& param = msgData["param"];

					Json::Value reply;
					reply["messageType"] = MessageToStr(Message::REPLY);
					// cast to int and back to not allow any non-numeral data
					reply["messageID"] = msgData["messageID"].asInt();

					auto setError = [&](const std::string& error) {
							reply["success"] = false;
							reply["error"] = error;
						};

					switch(StrToAction(msgData["action"].asString()))
					{
						case Action::CREATE_GAME:
						{
							if(clientData)
								setError("This connection is already in use for a running match");
							else
							{
								auto matchID  = newMatchID();
								auto playerID = newPlayerID();
								auto ruleSet  = StrToRuleSet(param["ruleSet"].asString());
								auto gameMode = StrToGameMode(param["gameMode"].asString());

								auto newMatchData = std::make_shared<MatchData>(matchID, ruleSet, createMatch(ruleSet));

								auto newClientData = std::make_shared<ClientData>(
									playerID,
									createPlayer(StrToPlayersColor(param["color"].asString()), *newMatchData->getMatch()),
									job->first,
									*newMatchData
								);

								newMatchData->getClientDataSets().insert(newClientData);

								clientDataLock.lock();
								auto tmp1 = clientDataSets.emplace(job->first, newClientData);
								clientDataLock.unlock();
								assert(tmp1.second);

								matchDataLock.lock();
								auto tmp2 = matches.emplace(matchID, newMatchData);
								matchDataLock.unlock();
								assert(tmp2.second);

								reply["success"] = true;
								reply["data"]["matchID"]  = matchID;
								reply["data"]["playerID"] = playerID;

								std::thread([matchID, ruleSet, gameMode]() {
									std::this_thread::sleep_for(milliseconds(50));
									cyvdb::MatchManager().addMatch(cyvdb::Match(matchID, ruleSet, (gameMode == GameMode::RANDOM)));
								}).detach();
							}
							break;
						}
						case Action::JOIN_GAME:
						{
							matchDataLock.lock();

							auto matchIt = matches.find(param["matchID"].asString());

							if(clientData)
								setError("This connection is already in use for a running match");
							else if(matchIt == matches.end())
								setError("Game not found");
							else
							{
								bool random = param["gameMode"] == "random";

								std::string matchID = random
									? cyvdb::MatchManager().getOldestRandomModeMatch(
											StrToRuleSet(param["ruleSet"].asString())
										).id
									: param["matchID"].asString();

								auto playerID = newPlayerID();

								auto matchData = matchIt->second;
								auto matchClients = matchData->getClientDataSets();

								if(matchClients.size() == 0)
									setError("You tried to join a game without an active player, this doesn't work yet");
								else if(matchClients.size() > 1)
									setError("This game already has two players");
								else
								{
									auto color = !(*matchClients.begin())->getPlayer()->getColor();

									auto newClientData = std::make_shared<ClientData>(
										playerID,
										createPlayer(color, *matchData->getMatch()),
										job->first,
										*matchData
									);

									matchData->getClientDataSets().insert(newClientData);

									clientDataLock.lock();
									auto tmp = clientDataSets.emplace(job->first, newClientData);
									clientDataLock.unlock();
									assert(tmp.second);

									reply["success"] = true;
									reply["data"]["color"]    = PlayersColorToStr(color);
									reply["data"]["playerID"] = playerID;

									if(random)
										reply["data"]["matchID"] = matchID;
									else
										reply["data"]["ruleSet"] = RuleSetToStr(matchData->getRuleSet());

									auto message = PlayersColorToStr(color) + " player joined.";
									message[0] -= ('a' - 'A'); // lowercase to uppercase

									Json::Value chatMsg;
									chatMsg["messageType"]      = "request";
									chatMsg["action"]           = "chat message";
									chatMsg["param"]["sender"]  = "Server";
									chatMsg["param"]["message"] = message;

									std::string json = writer.write(chatMsg);
									for(auto& clientIt : matchClients)
										server.send(clientIt->getConnHdl(), json, opcode::text);
								}
							}

							matchDataLock.unlock();

							break;
						}
						case Action::RESUME_GAME:
							// TODO
							break;
						case Action::CHAT_MSG:
						{
							std::string json = writer.write(msgData);
							for(auto hdl : otherClients)
								server.send(hdl, json, opcode::text);

							break;
						}
						default:
							setError("unrecognized action type");
					}

					server.send(job->first, writer.write(reply), opcode::text);

					break;
				}
				case Message::REPLY:
				{
					if(!msgData["success"].asBool())
					{
						msgData["error"] = msgData["error"].asString().empty() ?
							"The opponents client sent an error message without any detail" :
							"The opponents client sent the following error message: " + msgData["error"].asString();
					}

					std::string json = writer.write(msgData);
					for(auto hdl : otherClients)
						server.send(hdl, json, opcode::text);

					break;
				}
				case Message::GAME_UPDATE:
				{
					std::string json = writer.write(msgData);
					for(auto hdl : otherClients)
						server.send(hdl, json, opcode::text);

					break;
				}
				default: // TODO: reply with error message
					break;
			}
		}
		catch(std::error_code& e)
		{
			std::cerr << "Caught a std::error_code\n-----\n" << e << '\n' << e.message() << std::endl;
		}
		catch(std::exception& e)
		{
			std::cerr << "Caught a std::exception: " << e.what() << std::endl;
		}
		catch(...)
		{
			std::cerr << "Caught an unrecognized error (not derived from either std::exception or std::error_code)"
				<< std::endl;
		}
	}
}

std::string JobHandler::newMatchID()
{
	static std::ranlux24 int24Generator(system_clock::now().time_since_epoch().count());

	std::string res;
	std::unique_lock<std::mutex> matchDataLock(m_server.m_matchDataMtx);

	do
	{
		res = int24ToB64ID(int24Generator());
	}
	while(m_server.m_matches.find(res) != m_server.m_matches.end());

	matchDataLock.unlock();

	return res;
}

std::string JobHandler::newPlayerID()
{
	static std::ranlux48 int48Generator(system_clock::now().time_since_epoch().count());

	// TODO
	return int48ToB64ID(int48Generator());
}
<commit_msg>Changed how random game joining is specified by the client<commit_after>/* Copyright 2014 Jonas Platte
 *
 * This file is part of Cyvasse Online.
 *
 * Cyvasse Online is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Cyvasse Online is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program.
 * If not, see <http://www.gnu.org/licenses/>.
 */

#include "job_handler.hpp"

#include <chrono>
#include <random>
#include <set>
#include <stdexcept>
#include <jsoncpp/json/value.h>
#include <jsoncpp/json/reader.h>
#include <jsoncpp/json/writer.h>
#include <tntdb/error.h>
#include <server_message.hpp>
#include <cyvdb/match.hpp>
#include <cyvdb/match_manager.hpp>
#include <cyvmath/match.hpp>
#include <cyvmath/player.hpp>
#include <cyvmath/rule_set_create.hpp>
#include "b64.hpp"
#include "cyvasse_server.hpp"
#include "client_data.hpp"
#include "match_data.hpp"

using namespace cyvmath;
using namespace std::chrono;

JobHandler::JobHandler(CyvasseServer& server)
	: m_server(server)
	, m_thread(std::bind(&JobHandler::processMessages, this))
{ }

JobHandler::~JobHandler()
{
	m_thread.join();
}

void JobHandler::processMessages()
{
	typedef CyvasseServer::Job Job;
	using namespace websocketpp::frame;

	auto& clientDataSets = m_server.m_clientDataSets;
	auto& matches = m_server.m_matches;
	auto& server = m_server.m_wsServer;

	Json::Reader reader;
	Json::FastWriter writer;

	while(m_server.m_running)
	{
		std::unique_lock<std::mutex> jobLock(m_server.m_jobMtx);

		while(m_server.m_running && m_server.m_jobQueue.empty())
			m_server.m_jobCond.wait(jobLock);

		if(!m_server.m_running)
			break;

		std::unique_ptr<Job> job = std::move(m_server.m_jobQueue.front());
		m_server.m_jobQueue.pop();

		jobLock.unlock();

		try
		{
			// Process job
			Json::Value msgData;
			if(!reader.parse(job->second->get_payload(), msgData, false))
			{
				// TODO: reply with error message
				return;
			}

			std::set<websocketpp::connection_hdl, std::owner_less<websocketpp::connection_hdl>> otherClients;

			std::shared_ptr<ClientData> clientData;

			std::unique_lock<std::mutex> matchDataLock(m_server.m_matchDataMtx, std::defer_lock); // don't lock yet
			std::unique_lock<std::mutex> clientDataLock(m_server.m_clientDataMtx);

			auto it1 = clientDataSets.find(job->first);
			if(it1 != clientDataSets.end())
			{
				clientData = it1->second;
				clientDataLock.unlock();

				for(auto it2 : clientData->getMatchData().getClientDataSets())
					if(*it2 != *clientData)
						otherClients.insert(it2->getConnHdl());
			}
			else clientDataLock.unlock();

			switch(StrToMessage(msgData["messageType"].asString()))
			{
				case Message::REQUEST:
				{
					auto& param = msgData["param"];

					Json::Value reply;
					reply["messageType"] = MessageToStr(Message::REPLY);
					// cast to int and back to not allow any non-numeral data
					reply["messageID"] = msgData["messageID"].asInt();

					auto setError = [&](const std::string& error) {
							reply["success"] = false;
							reply["error"] = error;
						};

					switch(StrToAction(msgData["action"].asString()))
					{
						case Action::CREATE_GAME:
						{
							if(clientData)
								setError("This connection is already in use for a running match");
							else
							{
								auto matchID  = newMatchID();
								auto playerID = newPlayerID();
								auto ruleSet  = StrToRuleSet(param["ruleSet"].asString());
								auto gameMode = StrToGameMode(param["gameMode"].asString());

								auto newMatchData = std::make_shared<MatchData>(matchID, ruleSet, createMatch(ruleSet));

								auto newClientData = std::make_shared<ClientData>(
									playerID,
									createPlayer(StrToPlayersColor(param["color"].asString()), *newMatchData->getMatch()),
									job->first,
									*newMatchData
								);

								newMatchData->getClientDataSets().insert(newClientData);

								clientDataLock.lock();
								auto tmp1 = clientDataSets.emplace(job->first, newClientData);
								clientDataLock.unlock();
								assert(tmp1.second);

								matchDataLock.lock();
								auto tmp2 = matches.emplace(matchID, newMatchData);
								matchDataLock.unlock();
								assert(tmp2.second);

								reply["success"] = true;
								reply["data"]["matchID"]  = matchID;
								reply["data"]["playerID"] = playerID;

								std::thread([matchID, ruleSet, gameMode]() {
									std::this_thread::sleep_for(milliseconds(50));
									cyvdb::MatchManager().addMatch(cyvdb::Match(matchID, ruleSet, (gameMode == GameMode::RANDOM)));
								}).detach();
							}
							break;
						}
						case Action::JOIN_GAME:
						{
							matchDataLock.lock();

							auto matchIt = matches.find(param["matchID"].asString());

							if(clientData)
								setError("This connection is already in use for a running match");
							else if(matchIt == matches.end())
								setError("Game not found");
							else
							{
								bool random = param["random"].asBool();

								std::string matchID = random
									? cyvdb::MatchManager().getOldestRandomModeMatch(
											StrToRuleSet(param["ruleSet"].asString())
										).id
									: param["matchID"].asString();

								auto playerID = newPlayerID();

								auto matchData = matchIt->second;
								auto matchClients = matchData->getClientDataSets();

								if(matchClients.size() == 0)
									setError("You tried to join a game without an active player, this doesn't work yet");
								else if(matchClients.size() > 1)
									setError("This game already has two players");
								else
								{
									auto color = !(*matchClients.begin())->getPlayer()->getColor();

									auto newClientData = std::make_shared<ClientData>(
										playerID,
										createPlayer(color, *matchData->getMatch()),
										job->first,
										*matchData
									);

									matchData->getClientDataSets().insert(newClientData);

									clientDataLock.lock();
									auto tmp = clientDataSets.emplace(job->first, newClientData);
									clientDataLock.unlock();
									assert(tmp.second);

									reply["success"] = true;
									reply["data"]["color"]    = PlayersColorToStr(color);
									reply["data"]["playerID"] = playerID;

									if(random)
										reply["data"]["matchID"] = matchID;
									else
										reply["data"]["ruleSet"] = RuleSetToStr(matchData->getRuleSet());

									auto message = PlayersColorToStr(color) + " player joined.";
									message[0] -= ('a' - 'A'); // lowercase to uppercase

									Json::Value chatMsg;
									chatMsg["messageType"]      = "request";
									chatMsg["action"]           = "chat message";
									chatMsg["param"]["sender"]  = "Server";
									chatMsg["param"]["message"] = message;

									std::string json = writer.write(chatMsg);
									for(auto& clientIt : matchClients)
										server.send(clientIt->getConnHdl(), json, opcode::text);
								}
							}

							matchDataLock.unlock();

							break;
						}
						case Action::RESUME_GAME:
							// TODO
							break;
						case Action::CHAT_MSG:
						{
							std::string json = writer.write(msgData);
							for(auto hdl : otherClients)
								server.send(hdl, json, opcode::text);

							break;
						}
						default:
							setError("unrecognized action type");
					}

					server.send(job->first, writer.write(reply), opcode::text);

					break;
				}
				case Message::REPLY:
				{
					if(!msgData["success"].asBool())
					{
						msgData["error"] = msgData["error"].asString().empty() ?
							"The opponents client sent an error message without any detail" :
							"The opponents client sent the following error message: " + msgData["error"].asString();
					}

					std::string json = writer.write(msgData);
					for(auto hdl : otherClients)
						server.send(hdl, json, opcode::text);

					break;
				}
				case Message::GAME_UPDATE:
				{
					std::string json = writer.write(msgData);
					for(auto hdl : otherClients)
						server.send(hdl, json, opcode::text);

					break;
				}
				default: // TODO: reply with error message
					break;
			}
		}
		catch(std::error_code& e)
		{
			std::cerr << "Caught a std::error_code\n-----\n" << e << '\n' << e.message() << std::endl;
		}
		catch(std::exception& e)
		{
			std::cerr << "Caught a std::exception: " << e.what() << std::endl;
		}
		catch(...)
		{
			std::cerr << "Caught an unrecognized error (not derived from either std::exception or std::error_code)"
				<< std::endl;
		}
	}
}

std::string JobHandler::newMatchID()
{
	static std::ranlux24 int24Generator(system_clock::now().time_since_epoch().count());

	std::string res;
	std::unique_lock<std::mutex> matchDataLock(m_server.m_matchDataMtx);

	do
	{
		res = int24ToB64ID(int24Generator());
	}
	while(m_server.m_matches.find(res) != m_server.m_matches.end());

	matchDataLock.unlock();

	return res;
}

std::string JobHandler::newPlayerID()
{
	static std::ranlux48 int48Generator(system_clock::now().time_since_epoch().count());

	// TODO
	return int48ToB64ID(int48Generator());
}
<|endoftext|>