Files
hyblocker--OpenVR-SpaceCali…/OpenVR-SpaceCalibrator/IPCClient.cpp
T
2021-11-07 23:37:33 -05:00

94 lines
2.4 KiB
C++

#include "stdafx.h"
#include "IPCClient.h"
#include <string>
static std::string LastErrorString(DWORD lastError)
{
LPSTR buffer = nullptr;
size_t size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buffer, 0, NULL
);
std::string message(buffer, size);
LocalFree(buffer);
return message;
}
IPCClient::~IPCClient()
{
if (pipe && pipe != INVALID_HANDLE_VALUE)
CloseHandle(pipe);
}
void IPCClient::Connect()
{
LPTSTR pipeName = TEXT(OPENVR_SPACECALIBRATOR_PIPE_NAME);
WaitNamedPipe(pipeName, 1000);
pipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (pipe == INVALID_HANDLE_VALUE)
{
throw std::runtime_error("Space Calibrator driver unavailable. Make sure SteamVR is running, and the Space Calibrator addon is enabled in SteamVR settings.");
}
DWORD mode = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(pipe, &mode, 0, 0))
{
throw std::runtime_error("Couldn't set pipe mode. Error: " + LastErrorString(GetLastError()));
}
auto response = SendBlocking(protocol::Request(protocol::RequestHandshake));
if (response.type != protocol::ResponseHandshake || response.protocol.version != protocol::Version)
{
throw std::runtime_error(
"Incorrect driver version installed, try reinstalling OpenVR-SpaceCalibrator. (Client: " +
std::to_string(protocol::Version) +
", Driver: " +
std::to_string(response.protocol.version) +
")"
);
}
}
protocol::Response IPCClient::SendBlocking(const protocol::Request &request)
{
Send(request);
return Receive();
}
void IPCClient::Send(const protocol::Request &request)
{
DWORD bytesWritten;
BOOL success = WriteFile(pipe, &request, sizeof request, &bytesWritten, 0);
if (!success)
{
throw std::runtime_error("Error writing IPC request. Error: " + LastErrorString(GetLastError()));
}
}
protocol::Response IPCClient::Receive()
{
protocol::Response response(protocol::ResponseInvalid);
DWORD bytesRead;
BOOL success = ReadFile(pipe, &response, sizeof response, &bytesRead, 0);
if (!success)
{
DWORD lastError = GetLastError();
if (lastError != ERROR_MORE_DATA)
{
throw std::runtime_error("Error reading IPC response. Error: " + LastErrorString(lastError));
}
}
if (bytesRead != sizeof response)
{
throw std::runtime_error("Invalid IPC response with size " + std::to_string(bytesRead));
}
return response;
}