discord-rpc/src/connection_win.cpp

97 lines
2.4 KiB
C++
Raw Normal View History

#include "connection.h"
#define WIN32_LEAN_AND_MEAN
#define NOMCX
#define NOSERVICE
#define NOIME
#include <windows.h>
2017-07-20 22:58:23 +01:00
int GetProcessId()
{
return ::GetCurrentProcessId();
}
2017-07-17 17:28:54 +01:00
struct BaseConnectionWin : public BaseConnection {
HANDLE pipe{INVALID_HANDLE_VALUE};
};
2017-07-17 17:28:54 +01:00
static BaseConnectionWin Connection;
2017-07-17 17:28:54 +01:00
/*static*/ BaseConnection* BaseConnection::Create()
{
2017-07-17 17:28:54 +01:00
return &Connection;
}
2017-07-17 17:28:54 +01:00
/*static*/ void BaseConnection::Destroy(BaseConnection*& c)
{
2017-07-17 17:28:54 +01:00
auto self = reinterpret_cast<BaseConnectionWin*>(c);
self->Close();
c = nullptr;
}
2017-07-17 17:28:54 +01:00
bool BaseConnection::Open()
{
2017-07-28 00:02:47 +01:00
wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"};
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
pipeName[pipeDigit] = L'0';
2017-07-17 17:28:54 +01:00
auto self = reinterpret_cast<BaseConnectionWin*>(this);
for (;;) {
2017-07-25 17:27:48 +01:00
self->pipe = ::CreateFileW(
2017-07-28 00:02:47 +01:00
pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
if (self->pipe != INVALID_HANDLE_VALUE) {
self->isOpen = true;
2017-07-17 17:28:54 +01:00
return true;
}
2017-07-28 00:02:47 +01:00
auto lastError = GetLastError();
if (lastError == ERROR_FILE_NOT_FOUND) {
if (pipeName[pipeDigit] < L'9') {
pipeName[pipeDigit]++;
continue;
}
}
2017-07-28 00:02:47 +01:00
else if (lastError == ERROR_PIPE_BUSY) {
if (!WaitNamedPipeW(pipeName, 10000)) {
return false;
}
continue;
}
2017-07-28 00:02:47 +01:00
return false;
}
}
2017-07-17 17:28:54 +01:00
bool BaseConnection::Close()
{
2017-07-17 17:28:54 +01:00
auto self = reinterpret_cast<BaseConnectionWin*>(this);
::CloseHandle(self->pipe);
self->pipe = INVALID_HANDLE_VALUE;
self->isOpen = false;
2017-07-17 17:28:54 +01:00
return true;
}
2017-07-17 17:28:54 +01:00
bool BaseConnection::Write(const void* data, size_t length)
{
2017-07-17 17:28:54 +01:00
auto self = reinterpret_cast<BaseConnectionWin*>(this);
return ::WriteFile(self->pipe, data, length, nullptr, nullptr) == TRUE;
}
2017-07-17 17:28:54 +01:00
bool BaseConnection::Read(void* data, size_t length)
{
2017-07-17 17:28:54 +01:00
auto self = reinterpret_cast<BaseConnectionWin*>(this);
DWORD bytesAvailable = 0;
if (::PeekNamedPipe(self->pipe, nullptr, 0, nullptr, &bytesAvailable, nullptr)) {
if (bytesAvailable >= length) {
if (::ReadFile(self->pipe, data, length, nullptr, nullptr) == TRUE) {
return true;
}
else {
Close();
}
2017-07-17 17:28:54 +01:00
}
}
else {
Close();
}
2017-07-17 17:28:54 +01:00
return false;
}