检查 Steam 是否 运行 并且用户已登录
Check if Steam is running and user is logged in
简而言之,我想检查 Steam 是否 运行 以及用户是否已登录。我只能找到关于网络的文档 -api 这将是错误的开始点我想想。
我什至不需要代码示例,我只需要提示正确的方向和从哪里开始。我听说 Steam 本身有一个 OpenID 实现,但我不知道它是否是正确的起点。
感谢任何帮助!
我假设您正在将此用于游戏,如果我是正确的,您需要来自 Valve 的 Steamworks SDK。获得官方 SDK 的唯一方法是在 Steam 上通过绿灯流程。但是,您可以使用 https://steamworks.github.io/ 。希望对你有帮助。
我知道这是一个比较老的问题,但我自己在寻找答案时偶然发现了它。我找到了一种方法,虽然它是在 C++ 中,但是它可以完美地转换为 C#。
伪代码
string SteamExePath = RegistryKey("HKEY_CURRENT_USER\SOFTWARE\Valve\Steam\SteamExe");
while RegistryKey("HKEY_CURRENT_USER\SOFTWARE\Valve\Steam\ActiveProcess\ActiveUser") == 0
{
RegisterForRegistryChange("HKEY_CURRENT_USER\SOFTWARE\Valve\Steam\ActiveProcess");
StartProcess(SteamExePath);
WaitForRegistryChange();
}
C++代码
Util.h
#pragma once
#include <memory>
#include <string>
#include "Shared.h"
#define EXCEPTION(message, ...) throw std::runtime_error(Shared::stringFormat(Shared::stringFormat("%s: %s", __FUNCTION__, message), __VA_ARGS__));
#define EXCEPTION_LAST_ERROR(message, ...) throw std::runtime_error(Shared::stringFormat(Shared::stringFormat("%s: %s\nSystem error code: %u", __FUNCTION__, message, GetLastError()), __VA_ARGS__));
#define EXCEPTION_LAST_ERROR2(message, lastError, ...) throw std::runtime_error(Shared::stringFormat(Shared::stringFormat("%s: %s\nSystem error code: %u", __FUNCTION__, message, lastError), __VA_ARGS__));
namespace Shared
{
template<typename ... Args>
std::string stringFormat(const std::string &format, Args ...args)
{
size_t size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
std::unique_ptr<char[]> buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1);
}
template<typename ... Args>
std::wstring stringFormat(const std::wstring &format, Args ...args)
{
size_t size = std::swprintf(nullptr, 0, format.c_str(), args...) + 1;
std::unique_ptr<wchar_t[]> buf(new wchar_t[size]);
std::swprintf(buf.get(), size, format.c_str(), args...);
return std::wstring(buf.get(), buf.get() + size - 1);
}
void getExecutionPath(std::wstring &path);
}
Process.h
#pragma once
#include <Windows.h>
#include <string>
namespace Shared
{
class Process
{
public:
Process(
const std::wstring &path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &&path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &&path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &&path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &&path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(Process &&other);
~Process();
void create();
void terminate(UINT exitCode);
bool awaitTermination(DWORD milliseconds, DWORD &exitCode);
void resume();
inline bool awaitTermination(DWORD milliseconds)
{
DWORD exitCode;
return awaitTermination(milliseconds, exitCode);
}
inline bool isCreated() const
{
return this->created;
}
inline const std::wstring &getPath() const
{
return this->path;
}
inline const std::wstring &getArguments() const
{
return this->arguments;
}
inline const LPSECURITY_ATTRIBUTES getProcessAttributes() const
{
return this->processAttributes;
}
inline const LPSECURITY_ATTRIBUTES getThreadAttributes() const
{
return this->threadAttributes;
}
inline bool getInheritHandles() const
{
return this->inheritHandles;
}
inline DWORD getCreationFlags() const
{
return this->creationFlags;
}
inline const LPVOID getEnvironment() const
{
return this->environment;
}
inline const std::wstring &getCurrentDirectory() const
{
return this->currentDirectory;
}
inline const STARTUPINFOEXW &getStartupInfo() const
{
return this->startupInfo;
}
inline const PROCESS_INFORMATION &getProcessInformation() const
{
return this->processInformation;
}
inline DWORD getProcessId() const
{
return this->processInformation.dwProcessId;
}
inline DWORD getThreadId() const
{
return this->processInformation.dwThreadId;
}
inline HANDLE getProcessHandle() const
{
return this->processInformation.hProcess;
}
inline HANDLE getThreadHandle() const
{
return this->processInformation.hThread;
}
private:
Process(const Process &other) = delete;
Process &operator=(const Process &other) = delete;
Process &operator=(const Process &&other) = delete;
void init(LPSECURITY_ATTRIBUTES processAttributes, LPSECURITY_ATTRIBUTES threadAttributes);
void cleanup();
bool created;
std::wstring path;
std::wstring arguments;
LPSECURITY_ATTRIBUTES processAttributes;
LPSECURITY_ATTRIBUTES threadAttributes;
bool inheritHandles;
DWORD creationFlags;
LPVOID environment;
std::wstring currentDirectory;
STARTUPINFOEXW startupInfo;
PROCESS_INFORMATION processInformation;
};
}
Process.cpp
#include "stdafx.h"
#include "Process.h"
#include "Util.h"
namespace Shared
{
Process::Process(
const std::wstring &path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(path),
arguments(arguments),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(currentDirectory),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &&path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(std::forward<const std::wstring>(path)),
arguments(std::forward<const std::wstring>(arguments)),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(std::forward<const std::wstring>(currentDirectory)),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &&path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(std::forward<const std::wstring>(path)),
arguments(arguments),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(currentDirectory),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(path),
arguments(std::forward<const std::wstring>(arguments)),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(currentDirectory),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(path),
arguments(arguments),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(std::forward<const std::wstring>(currentDirectory)),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &&path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(std::forward<const std::wstring>(path)),
arguments(std::forward<const std::wstring>(arguments)),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(currentDirectory),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(path),
arguments(std::forward<const std::wstring>(arguments)),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(std::forward<const std::wstring>(currentDirectory)),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &&path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(std::forward<const std::wstring>(path)),
arguments(arguments),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(std::forward<const std::wstring>(currentDirectory)),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(Process &&other) :
created(other.created),
path(other.path),
arguments(other.arguments),
processAttributes(other.processAttributes),
threadAttributes(other.threadAttributes),
inheritHandles(other.inheritHandles),
creationFlags(other.creationFlags),
environment(other.environment),
currentDirectory(other.currentDirectory),
startupInfo(other.startupInfo),
processInformation(other.processInformation)
{
other.processAttributes = NULL;
other.threadAttributes = NULL;
other.processInformation.hProcess = NULL;
other.processInformation.hThread = NULL;
}
Process::~Process()
{
if (this->processAttributes != NULL)
{
delete this->processAttributes->lpSecurityDescriptor;
}
if (this->threadAttributes != NULL)
{
delete this->threadAttributes->lpSecurityDescriptor;
}
delete this->processAttributes;
delete this->threadAttributes;
if (this->startupInfo.lpAttributeList != NULL)
{
DeleteProcThreadAttributeList(this->startupInfo.lpAttributeList);
}
if (this->created)
{
CloseHandle(this->processInformation.hProcess);
CloseHandle(this->processInformation.hThread);
}
}
void Process::create()
{
if (this->created)
{
EXCEPTION("Already created");
}
wchar_t *arguments = NULL;
if (!this->arguments.empty())
{
std::size_t argumentsLength = this->arguments.length() + 1;
arguments = new wchar_t[argumentsLength];
ZeroMemory(arguments, argumentsLength * sizeof(wchar_t));
wcscpy_s(arguments, argumentsLength, this->arguments.c_str());
}
if (CreateProcessW(this->path.empty() ? NULL : this->path.c_str(), arguments, this->processAttributes, this->threadAttributes, this->inheritHandles, this->creationFlags, this->environment, this->currentDirectory.empty() ? NULL : this->currentDirectory.c_str(), reinterpret_cast<LPSTARTUPINFOW>(&this->startupInfo), &this->processInformation) == FALSE)
{
delete[] arguments;
EXCEPTION_LAST_ERROR("Failed CreateProcessW");
}
delete[] arguments;
this->created = true;
}
void Process::terminate(UINT exitCode)
{
if (!this->created)
{
return;
}
if (TerminateProcess(this->processInformation.hProcess, exitCode) == FALSE)
{
EXCEPTION_LAST_ERROR("Failed TerminateProcess");
}
cleanup();
}
bool Process::awaitTermination(DWORD milliseconds, DWORD &exitCode)
{
if (!this->created)
{
EXCEPTION("Process not created");
}
DWORD waitResult = WaitForSingleObject(this->processInformation.hProcess, milliseconds);
if (waitResult == WAIT_TIMEOUT)
{
return false;
}
else if (waitResult == WAIT_OBJECT_0)
{
DWORD eCode;
if (GetExitCodeProcess(this->processInformation.hProcess, &eCode) == FALSE)
{
EXCEPTION_LAST_ERROR("Failed GetExitCodeProcess");
}
cleanup();
exitCode = eCode;
return true;
}
else
{
EXCEPTION("Failed WaitForSingleObject\nWait result: %u", waitResult);
}
}
void Process::resume()
{
if (!this->created)
{
EXCEPTION("Process not created");
}
if (ResumeThread(this->processInformation.hThread) == -1)
{
EXCEPTION_LAST_ERROR("Failed ResumeThread");
}
}
void Process::init(LPSECURITY_ATTRIBUTES processAttributes, LPSECURITY_ATTRIBUTES threadAttributes)
{
if (processAttributes != NULL)
{
PSECURITY_DESCRIPTOR securityDescriptor = NULL;
if (processAttributes->lpSecurityDescriptor != NULL)
{
securityDescriptor = new SECURITY_DESCRIPTOR();
memcpy(securityDescriptor, processAttributes->lpSecurityDescriptor, sizeof(SECURITY_DESCRIPTOR));
}
this->processAttributes = new SECURITY_ATTRIBUTES();
memcpy(this->processAttributes, processAttributes, sizeof(SECURITY_ATTRIBUTES));
this->processAttributes->lpSecurityDescriptor = securityDescriptor;
}
if (threadAttributes != NULL)
{
PSECURITY_DESCRIPTOR securityDescriptor = NULL;
if (threadAttributes->lpSecurityDescriptor != NULL)
{
securityDescriptor = new SECURITY_DESCRIPTOR();
memcpy(securityDescriptor, threadAttributes->lpSecurityDescriptor, sizeof(SECURITY_DESCRIPTOR));
}
this->threadAttributes = new SECURITY_ATTRIBUTES();
memcpy(this->threadAttributes, threadAttributes, sizeof(SECURITY_ATTRIBUTES));
this->threadAttributes->lpSecurityDescriptor = securityDescriptor;
}
this->creationFlags |= EXTENDED_STARTUPINFO_PRESENT;
ZeroMemory(&this->processInformation, sizeof(PROCESS_INFORMATION));
}
void Process::cleanup()
{
if (CloseHandle(this->processInformation.hProcess) == FALSE || CloseHandle(this->processInformation.hThread) == FALSE)
{
EXCEPTION_LAST_ERROR("Failed CloseHandle");
}
ZeroMemory(&this->processInformation, sizeof(PROCESS_INFORMATION));
this->created = false;
}
}
RegistryKey.h
#pragma once
#include <Windows.h>
#include <string>
namespace Shared
{
class RegistryKey
{
public:
RegistryKey(HKEY key, const std::wstring &subKey, DWORD options, REGSAM samDesired);
RegistryKey(HKEY key, const std::wstring &&subKey, DWORD options, REGSAM samDesired);
RegistryKey(RegistryKey &&other);
RegistryKey &operator=(RegistryKey &&other);
~RegistryKey();
std::wstring getRegSZ(const std::wstring &subKey, const std::wstring &valueName) const;
DWORD getRegDword(const std::wstring &valueName) const;
void regNotifyChangeKeyValue(bool watchSubTree, DWORD notifyFilter, HANDLE eventHandle, bool asynchronous) const;
inline HKEY getKey() const
{
return this->key;
}
inline const std::wstring &getSubKey() const
{
return this->subKey;
}
inline DWORD getOptions() const
{
return this->options;
}
inline REGSAM getSamDesired() const
{
return this->samDesired;
}
private:
RegistryKey(const RegistryKey &other) = delete;
RegistryKey &operator=(const RegistryKey &other) = delete;
void init();
void close();
HKEY keyHandle;
HKEY key;
std::wstring subKey;
DWORD options;
REGSAM samDesired;
};
}
RegistryKey.cpp
#include "stdafx.h"
#include "RegistryKey.h"
#include "Util.h"
namespace Shared
{
RegistryKey::RegistryKey(HKEY key, const std::wstring &subKey, DWORD options, REGSAM samDesired) :
keyHandle(NULL),
key(key),
subKey(subKey),
options(options),
samDesired(samDesired)
{
init();
}
RegistryKey::RegistryKey(HKEY key, const std::wstring &&subKey, DWORD options, REGSAM samDesired) :
keyHandle(NULL),
key(key),
subKey(std::forward<const std::wstring>(subKey)),
options(options),
samDesired(samDesired)
{
init();
}
RegistryKey::RegistryKey(RegistryKey &&other) :
keyHandle(other.keyHandle),
key(other.key),
subKey(other.subKey),
options(other.options),
samDesired(other.samDesired)
{
other.keyHandle = NULL;
}
RegistryKey &RegistryKey::operator=(RegistryKey &&other)
{
close();
this->keyHandle = other.keyHandle;
this->key = other.key;
this->subKey = other.subKey;
this->options = other.options;
this->samDesired = other.samDesired;
other.keyHandle = NULL;
return (*this);
}
RegistryKey::~RegistryKey()
{
try
{
close();
}
catch (std::runtime_error)
{
}
}
std::wstring RegistryKey::getRegSZ(const std::wstring &subKey, const std::wstring &valueName) const
{
if ((this->samDesired & KEY_QUERY_VALUE) != KEY_QUERY_VALUE)
{
EXCEPTION("This registry key handle does not have KEY_QUERY_VALUE rights");
}
std::size_t bufferSize = MAX_PATH;
wchar_t *buffer = new wchar_t[bufferSize];
DWORD bufferByteSize = static_cast<DWORD>(bufferSize * sizeof(wchar_t));
LSTATUS registryGetValueStatus = RegGetValueW(this->keyHandle, subKey.empty() ? NULL : subKey.c_str(), valueName.empty() ? NULL : valueName.c_str(), RRF_RT_REG_SZ, NULL, reinterpret_cast<LPBYTE>(buffer), &bufferByteSize);
while (registryGetValueStatus != ERROR_SUCCESS)
{
delete[] buffer;
if (registryGetValueStatus == ERROR_MORE_DATA)
{
bufferSize *= 2;
buffer = new wchar_t[bufferSize];
bufferByteSize = static_cast<DWORD>(bufferSize * sizeof(wchar_t));
registryGetValueStatus = RegGetValueW(this->keyHandle, subKey.empty() ? NULL : subKey.c_str(), valueName.empty() ? NULL : valueName.c_str(), RRF_RT_REG_SZ, NULL, reinterpret_cast<LPBYTE>(buffer), &bufferByteSize);
}
else
{
EXCEPTION("Failed RegGetValueW\nLSTATUS: %d", registryGetValueStatus);
}
}
std::wstring arkInstallPath(buffer);
delete[] buffer;
return arkInstallPath;
}
DWORD RegistryKey::getRegDword(const std::wstring &valueName) const
{
if ((this->samDesired & KEY_QUERY_VALUE) != KEY_QUERY_VALUE)
{
EXCEPTION("This registry key handle does not have KEY_QUERY_VALUE rights");
}
DWORD result;
DWORD dataSize = sizeof(DWORD);
LSTATUS status = RegQueryValueExW(this->keyHandle, valueName.empty() ? NULL : valueName.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&result), &dataSize);
if (status != ERROR_SUCCESS)
{
EXCEPTION("Failed RegQueryValueExW\nLSTATUS: %d", status);
}
return result;
}
void RegistryKey::regNotifyChangeKeyValue(bool watchSubTree, DWORD notifyFilter, HANDLE eventHandle, bool asynchronous) const
{
if ((this->samDesired & KEY_NOTIFY) != KEY_NOTIFY)
{
EXCEPTION("This registry key handle does not have KEY_NOTIFY rights");
}
LSTATUS result = RegNotifyChangeKeyValue(this->keyHandle, watchSubTree ? TRUE : FALSE, notifyFilter, eventHandle, asynchronous ? TRUE : FALSE);
if (result != ERROR_SUCCESS)
{
EXCEPTION("Failed RegNotifyChangeKeyValue\nLSTATUS: %d", result);
}
}
void RegistryKey::init()
{
LSTATUS registryOpenStatus = RegOpenKeyExW(this->key, this->subKey.empty() ? NULL : this->subKey.c_str(), this->options, this->samDesired, &this->keyHandle);
if (registryOpenStatus != ERROR_SUCCESS)
{
EXCEPTION("Failed RegOpenKeyExW\nLSTATUS: %d", registryOpenStatus);
}
}
void RegistryKey::close()
{
if (this->keyHandle == NULL)
{
return;
}
LSTATUS registryCloseStatus = RegCloseKey(this->keyHandle);
if (registryCloseStatus != ERROR_SUCCESS)
{
EXCEPTION("Failed RegCloseKey\nSystem error code: %d", registryCloseStatus);
}
this->keyHandle = NULL;
}
}
SteamClient.h
#pragma once
#include <Windows.h>
namespace BattleyeInjector
{
class SteamClient final
{
public:
SteamClient();
void start();
void startAndAwaitLogin(int maxTryCount);
private:
DWORD getActiveUserId();
};
}
SteamClient.cpp
#include "stdafx.h"
#include "SteamClient.h"
#include <string>
#include <RegistryKey.h>
#include <Process.h>
#include <Util.h>
namespace BattleyeInjector
{
static const HKEY STEAM_KEY = HKEY_CURRENT_USER;
static const std::wstring STEAM_INSTALL_PATH_SUB_KEY = L"SOFTWARE\Valve\Steam";
static const std::wstring STEAM_INSTALL_PATH_KEY_NAME = L"SteamExe";
static const std::wstring STEAM_ACTIVE_PROCESS_SUB_KEY = L"SOFTWARE\Valve\Steam\ActiveProcess";
static const std::wstring STEAM_ACTIVE_USER_KEY_NAME = L"ActiveUser";
SteamClient::SteamClient()
{
}
void SteamClient::start()
{
Shared::RegistryKey registryKey(STEAM_KEY, STEAM_INSTALL_PATH_SUB_KEY, 0, KEY_READ);
const std::wstring steamInstallPath = registryKey.getRegSZ(L"", STEAM_INSTALL_PATH_KEY_NAME);
STARTUPINFOEXW startupInfo;
ZeroMemory(&startupInfo, sizeof(STARTUPINFOEXW));
startupInfo.StartupInfo.cb = sizeof(STARTUPINFOEXW);
Shared::Process steamProcess(steamInstallPath, L"", NULL, NULL, false, 0, NULL, L"", startupInfo);
steamProcess.create();
}
void SteamClient::startAndAwaitLogin(int maxTryCount)
{
if (maxTryCount <= 0)
{
EXCEPTION("maxTryCount is invalid");
}
if (getActiveUserId() != 0)
{
return;
}
HANDLE eventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
if (eventHandle == NULL)
{
EXCEPTION_LAST_ERROR("Failed CreateEventW");
}
try
{
Shared::RegistryKey registryKey(STEAM_KEY, STEAM_ACTIVE_PROCESS_SUB_KEY, 0, KEY_READ);
for (int x = 0; x < maxTryCount; x++)
{
registryKey.regNotifyChangeKeyValue(false, REG_NOTIFY_CHANGE_LAST_SET, eventHandle, true);
start();
DWORD waitResult = WaitForSingleObject(eventHandle, INFINITE);
if (waitResult != WAIT_OBJECT_0)
{
EXCEPTION("Failed WaitForSingleObject\nWaitResult: %u", waitResult);
}
if (getActiveUserId() != 0)
{
return;
}
if (ResetEvent(eventHandle) == FALSE)
{
EXCEPTION_LAST_ERROR("Failed ResetEvent");
}
}
EXCEPTION("Failed await login to steam");
}
catch (...)
{
CloseHandle(eventHandle);
throw;
}
}
DWORD SteamClient::getActiveUserId()
{
Shared::RegistryKey registryKey(STEAM_KEY, STEAM_ACTIVE_PROCESS_SUB_KEY, 0, KEY_READ);
return registryKey.getRegDword(STEAM_ACTIVE_USER_KEY_NAME);
}
}
简而言之,我想检查 Steam 是否 运行 以及用户是否已登录。我只能找到关于网络的文档 -api 这将是错误的开始点我想想。
我什至不需要代码示例,我只需要提示正确的方向和从哪里开始。我听说 Steam 本身有一个 OpenID 实现,但我不知道它是否是正确的起点。
感谢任何帮助!
我假设您正在将此用于游戏,如果我是正确的,您需要来自 Valve 的 Steamworks SDK。获得官方 SDK 的唯一方法是在 Steam 上通过绿灯流程。但是,您可以使用 https://steamworks.github.io/ 。希望对你有帮助。
我知道这是一个比较老的问题,但我自己在寻找答案时偶然发现了它。我找到了一种方法,虽然它是在 C++ 中,但是它可以完美地转换为 C#。
伪代码
string SteamExePath = RegistryKey("HKEY_CURRENT_USER\SOFTWARE\Valve\Steam\SteamExe");
while RegistryKey("HKEY_CURRENT_USER\SOFTWARE\Valve\Steam\ActiveProcess\ActiveUser") == 0
{
RegisterForRegistryChange("HKEY_CURRENT_USER\SOFTWARE\Valve\Steam\ActiveProcess");
StartProcess(SteamExePath);
WaitForRegistryChange();
}
C++代码
Util.h
#pragma once
#include <memory>
#include <string>
#include "Shared.h"
#define EXCEPTION(message, ...) throw std::runtime_error(Shared::stringFormat(Shared::stringFormat("%s: %s", __FUNCTION__, message), __VA_ARGS__));
#define EXCEPTION_LAST_ERROR(message, ...) throw std::runtime_error(Shared::stringFormat(Shared::stringFormat("%s: %s\nSystem error code: %u", __FUNCTION__, message, GetLastError()), __VA_ARGS__));
#define EXCEPTION_LAST_ERROR2(message, lastError, ...) throw std::runtime_error(Shared::stringFormat(Shared::stringFormat("%s: %s\nSystem error code: %u", __FUNCTION__, message, lastError), __VA_ARGS__));
namespace Shared
{
template<typename ... Args>
std::string stringFormat(const std::string &format, Args ...args)
{
size_t size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
std::unique_ptr<char[]> buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1);
}
template<typename ... Args>
std::wstring stringFormat(const std::wstring &format, Args ...args)
{
size_t size = std::swprintf(nullptr, 0, format.c_str(), args...) + 1;
std::unique_ptr<wchar_t[]> buf(new wchar_t[size]);
std::swprintf(buf.get(), size, format.c_str(), args...);
return std::wstring(buf.get(), buf.get() + size - 1);
}
void getExecutionPath(std::wstring &path);
}
Process.h
#pragma once
#include <Windows.h>
#include <string>
namespace Shared
{
class Process
{
public:
Process(
const std::wstring &path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &&path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &&path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &&path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(
const std::wstring &&path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo);
Process(Process &&other);
~Process();
void create();
void terminate(UINT exitCode);
bool awaitTermination(DWORD milliseconds, DWORD &exitCode);
void resume();
inline bool awaitTermination(DWORD milliseconds)
{
DWORD exitCode;
return awaitTermination(milliseconds, exitCode);
}
inline bool isCreated() const
{
return this->created;
}
inline const std::wstring &getPath() const
{
return this->path;
}
inline const std::wstring &getArguments() const
{
return this->arguments;
}
inline const LPSECURITY_ATTRIBUTES getProcessAttributes() const
{
return this->processAttributes;
}
inline const LPSECURITY_ATTRIBUTES getThreadAttributes() const
{
return this->threadAttributes;
}
inline bool getInheritHandles() const
{
return this->inheritHandles;
}
inline DWORD getCreationFlags() const
{
return this->creationFlags;
}
inline const LPVOID getEnvironment() const
{
return this->environment;
}
inline const std::wstring &getCurrentDirectory() const
{
return this->currentDirectory;
}
inline const STARTUPINFOEXW &getStartupInfo() const
{
return this->startupInfo;
}
inline const PROCESS_INFORMATION &getProcessInformation() const
{
return this->processInformation;
}
inline DWORD getProcessId() const
{
return this->processInformation.dwProcessId;
}
inline DWORD getThreadId() const
{
return this->processInformation.dwThreadId;
}
inline HANDLE getProcessHandle() const
{
return this->processInformation.hProcess;
}
inline HANDLE getThreadHandle() const
{
return this->processInformation.hThread;
}
private:
Process(const Process &other) = delete;
Process &operator=(const Process &other) = delete;
Process &operator=(const Process &&other) = delete;
void init(LPSECURITY_ATTRIBUTES processAttributes, LPSECURITY_ATTRIBUTES threadAttributes);
void cleanup();
bool created;
std::wstring path;
std::wstring arguments;
LPSECURITY_ATTRIBUTES processAttributes;
LPSECURITY_ATTRIBUTES threadAttributes;
bool inheritHandles;
DWORD creationFlags;
LPVOID environment;
std::wstring currentDirectory;
STARTUPINFOEXW startupInfo;
PROCESS_INFORMATION processInformation;
};
}
Process.cpp
#include "stdafx.h"
#include "Process.h"
#include "Util.h"
namespace Shared
{
Process::Process(
const std::wstring &path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(path),
arguments(arguments),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(currentDirectory),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &&path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(std::forward<const std::wstring>(path)),
arguments(std::forward<const std::wstring>(arguments)),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(std::forward<const std::wstring>(currentDirectory)),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &&path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(std::forward<const std::wstring>(path)),
arguments(arguments),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(currentDirectory),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(path),
arguments(std::forward<const std::wstring>(arguments)),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(currentDirectory),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(path),
arguments(arguments),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(std::forward<const std::wstring>(currentDirectory)),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &&path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring ¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(std::forward<const std::wstring>(path)),
arguments(std::forward<const std::wstring>(arguments)),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(currentDirectory),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &path,
const std::wstring &&arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(path),
arguments(std::forward<const std::wstring>(arguments)),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(std::forward<const std::wstring>(currentDirectory)),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(
const std::wstring &&path,
const std::wstring &arguments,
LPSECURITY_ATTRIBUTES processAttributes,
LPSECURITY_ATTRIBUTES threadAttributes,
bool inheritHandles,
DWORD creationFlags,
LPVOID environment,
const std::wstring &¤tDirectory,
const STARTUPINFOEXW &startupInfo) :
created(false),
path(std::forward<const std::wstring>(path)),
arguments(arguments),
processAttributes(NULL),
threadAttributes(NULL),
inheritHandles(inheritHandles),
creationFlags(creationFlags),
environment(environment),
currentDirectory(std::forward<const std::wstring>(currentDirectory)),
startupInfo(startupInfo),
processInformation()
{
init(processAttributes, threadAttributes);
}
Process::Process(Process &&other) :
created(other.created),
path(other.path),
arguments(other.arguments),
processAttributes(other.processAttributes),
threadAttributes(other.threadAttributes),
inheritHandles(other.inheritHandles),
creationFlags(other.creationFlags),
environment(other.environment),
currentDirectory(other.currentDirectory),
startupInfo(other.startupInfo),
processInformation(other.processInformation)
{
other.processAttributes = NULL;
other.threadAttributes = NULL;
other.processInformation.hProcess = NULL;
other.processInformation.hThread = NULL;
}
Process::~Process()
{
if (this->processAttributes != NULL)
{
delete this->processAttributes->lpSecurityDescriptor;
}
if (this->threadAttributes != NULL)
{
delete this->threadAttributes->lpSecurityDescriptor;
}
delete this->processAttributes;
delete this->threadAttributes;
if (this->startupInfo.lpAttributeList != NULL)
{
DeleteProcThreadAttributeList(this->startupInfo.lpAttributeList);
}
if (this->created)
{
CloseHandle(this->processInformation.hProcess);
CloseHandle(this->processInformation.hThread);
}
}
void Process::create()
{
if (this->created)
{
EXCEPTION("Already created");
}
wchar_t *arguments = NULL;
if (!this->arguments.empty())
{
std::size_t argumentsLength = this->arguments.length() + 1;
arguments = new wchar_t[argumentsLength];
ZeroMemory(arguments, argumentsLength * sizeof(wchar_t));
wcscpy_s(arguments, argumentsLength, this->arguments.c_str());
}
if (CreateProcessW(this->path.empty() ? NULL : this->path.c_str(), arguments, this->processAttributes, this->threadAttributes, this->inheritHandles, this->creationFlags, this->environment, this->currentDirectory.empty() ? NULL : this->currentDirectory.c_str(), reinterpret_cast<LPSTARTUPINFOW>(&this->startupInfo), &this->processInformation) == FALSE)
{
delete[] arguments;
EXCEPTION_LAST_ERROR("Failed CreateProcessW");
}
delete[] arguments;
this->created = true;
}
void Process::terminate(UINT exitCode)
{
if (!this->created)
{
return;
}
if (TerminateProcess(this->processInformation.hProcess, exitCode) == FALSE)
{
EXCEPTION_LAST_ERROR("Failed TerminateProcess");
}
cleanup();
}
bool Process::awaitTermination(DWORD milliseconds, DWORD &exitCode)
{
if (!this->created)
{
EXCEPTION("Process not created");
}
DWORD waitResult = WaitForSingleObject(this->processInformation.hProcess, milliseconds);
if (waitResult == WAIT_TIMEOUT)
{
return false;
}
else if (waitResult == WAIT_OBJECT_0)
{
DWORD eCode;
if (GetExitCodeProcess(this->processInformation.hProcess, &eCode) == FALSE)
{
EXCEPTION_LAST_ERROR("Failed GetExitCodeProcess");
}
cleanup();
exitCode = eCode;
return true;
}
else
{
EXCEPTION("Failed WaitForSingleObject\nWait result: %u", waitResult);
}
}
void Process::resume()
{
if (!this->created)
{
EXCEPTION("Process not created");
}
if (ResumeThread(this->processInformation.hThread) == -1)
{
EXCEPTION_LAST_ERROR("Failed ResumeThread");
}
}
void Process::init(LPSECURITY_ATTRIBUTES processAttributes, LPSECURITY_ATTRIBUTES threadAttributes)
{
if (processAttributes != NULL)
{
PSECURITY_DESCRIPTOR securityDescriptor = NULL;
if (processAttributes->lpSecurityDescriptor != NULL)
{
securityDescriptor = new SECURITY_DESCRIPTOR();
memcpy(securityDescriptor, processAttributes->lpSecurityDescriptor, sizeof(SECURITY_DESCRIPTOR));
}
this->processAttributes = new SECURITY_ATTRIBUTES();
memcpy(this->processAttributes, processAttributes, sizeof(SECURITY_ATTRIBUTES));
this->processAttributes->lpSecurityDescriptor = securityDescriptor;
}
if (threadAttributes != NULL)
{
PSECURITY_DESCRIPTOR securityDescriptor = NULL;
if (threadAttributes->lpSecurityDescriptor != NULL)
{
securityDescriptor = new SECURITY_DESCRIPTOR();
memcpy(securityDescriptor, threadAttributes->lpSecurityDescriptor, sizeof(SECURITY_DESCRIPTOR));
}
this->threadAttributes = new SECURITY_ATTRIBUTES();
memcpy(this->threadAttributes, threadAttributes, sizeof(SECURITY_ATTRIBUTES));
this->threadAttributes->lpSecurityDescriptor = securityDescriptor;
}
this->creationFlags |= EXTENDED_STARTUPINFO_PRESENT;
ZeroMemory(&this->processInformation, sizeof(PROCESS_INFORMATION));
}
void Process::cleanup()
{
if (CloseHandle(this->processInformation.hProcess) == FALSE || CloseHandle(this->processInformation.hThread) == FALSE)
{
EXCEPTION_LAST_ERROR("Failed CloseHandle");
}
ZeroMemory(&this->processInformation, sizeof(PROCESS_INFORMATION));
this->created = false;
}
}
RegistryKey.h
#pragma once
#include <Windows.h>
#include <string>
namespace Shared
{
class RegistryKey
{
public:
RegistryKey(HKEY key, const std::wstring &subKey, DWORD options, REGSAM samDesired);
RegistryKey(HKEY key, const std::wstring &&subKey, DWORD options, REGSAM samDesired);
RegistryKey(RegistryKey &&other);
RegistryKey &operator=(RegistryKey &&other);
~RegistryKey();
std::wstring getRegSZ(const std::wstring &subKey, const std::wstring &valueName) const;
DWORD getRegDword(const std::wstring &valueName) const;
void regNotifyChangeKeyValue(bool watchSubTree, DWORD notifyFilter, HANDLE eventHandle, bool asynchronous) const;
inline HKEY getKey() const
{
return this->key;
}
inline const std::wstring &getSubKey() const
{
return this->subKey;
}
inline DWORD getOptions() const
{
return this->options;
}
inline REGSAM getSamDesired() const
{
return this->samDesired;
}
private:
RegistryKey(const RegistryKey &other) = delete;
RegistryKey &operator=(const RegistryKey &other) = delete;
void init();
void close();
HKEY keyHandle;
HKEY key;
std::wstring subKey;
DWORD options;
REGSAM samDesired;
};
}
RegistryKey.cpp
#include "stdafx.h"
#include "RegistryKey.h"
#include "Util.h"
namespace Shared
{
RegistryKey::RegistryKey(HKEY key, const std::wstring &subKey, DWORD options, REGSAM samDesired) :
keyHandle(NULL),
key(key),
subKey(subKey),
options(options),
samDesired(samDesired)
{
init();
}
RegistryKey::RegistryKey(HKEY key, const std::wstring &&subKey, DWORD options, REGSAM samDesired) :
keyHandle(NULL),
key(key),
subKey(std::forward<const std::wstring>(subKey)),
options(options),
samDesired(samDesired)
{
init();
}
RegistryKey::RegistryKey(RegistryKey &&other) :
keyHandle(other.keyHandle),
key(other.key),
subKey(other.subKey),
options(other.options),
samDesired(other.samDesired)
{
other.keyHandle = NULL;
}
RegistryKey &RegistryKey::operator=(RegistryKey &&other)
{
close();
this->keyHandle = other.keyHandle;
this->key = other.key;
this->subKey = other.subKey;
this->options = other.options;
this->samDesired = other.samDesired;
other.keyHandle = NULL;
return (*this);
}
RegistryKey::~RegistryKey()
{
try
{
close();
}
catch (std::runtime_error)
{
}
}
std::wstring RegistryKey::getRegSZ(const std::wstring &subKey, const std::wstring &valueName) const
{
if ((this->samDesired & KEY_QUERY_VALUE) != KEY_QUERY_VALUE)
{
EXCEPTION("This registry key handle does not have KEY_QUERY_VALUE rights");
}
std::size_t bufferSize = MAX_PATH;
wchar_t *buffer = new wchar_t[bufferSize];
DWORD bufferByteSize = static_cast<DWORD>(bufferSize * sizeof(wchar_t));
LSTATUS registryGetValueStatus = RegGetValueW(this->keyHandle, subKey.empty() ? NULL : subKey.c_str(), valueName.empty() ? NULL : valueName.c_str(), RRF_RT_REG_SZ, NULL, reinterpret_cast<LPBYTE>(buffer), &bufferByteSize);
while (registryGetValueStatus != ERROR_SUCCESS)
{
delete[] buffer;
if (registryGetValueStatus == ERROR_MORE_DATA)
{
bufferSize *= 2;
buffer = new wchar_t[bufferSize];
bufferByteSize = static_cast<DWORD>(bufferSize * sizeof(wchar_t));
registryGetValueStatus = RegGetValueW(this->keyHandle, subKey.empty() ? NULL : subKey.c_str(), valueName.empty() ? NULL : valueName.c_str(), RRF_RT_REG_SZ, NULL, reinterpret_cast<LPBYTE>(buffer), &bufferByteSize);
}
else
{
EXCEPTION("Failed RegGetValueW\nLSTATUS: %d", registryGetValueStatus);
}
}
std::wstring arkInstallPath(buffer);
delete[] buffer;
return arkInstallPath;
}
DWORD RegistryKey::getRegDword(const std::wstring &valueName) const
{
if ((this->samDesired & KEY_QUERY_VALUE) != KEY_QUERY_VALUE)
{
EXCEPTION("This registry key handle does not have KEY_QUERY_VALUE rights");
}
DWORD result;
DWORD dataSize = sizeof(DWORD);
LSTATUS status = RegQueryValueExW(this->keyHandle, valueName.empty() ? NULL : valueName.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&result), &dataSize);
if (status != ERROR_SUCCESS)
{
EXCEPTION("Failed RegQueryValueExW\nLSTATUS: %d", status);
}
return result;
}
void RegistryKey::regNotifyChangeKeyValue(bool watchSubTree, DWORD notifyFilter, HANDLE eventHandle, bool asynchronous) const
{
if ((this->samDesired & KEY_NOTIFY) != KEY_NOTIFY)
{
EXCEPTION("This registry key handle does not have KEY_NOTIFY rights");
}
LSTATUS result = RegNotifyChangeKeyValue(this->keyHandle, watchSubTree ? TRUE : FALSE, notifyFilter, eventHandle, asynchronous ? TRUE : FALSE);
if (result != ERROR_SUCCESS)
{
EXCEPTION("Failed RegNotifyChangeKeyValue\nLSTATUS: %d", result);
}
}
void RegistryKey::init()
{
LSTATUS registryOpenStatus = RegOpenKeyExW(this->key, this->subKey.empty() ? NULL : this->subKey.c_str(), this->options, this->samDesired, &this->keyHandle);
if (registryOpenStatus != ERROR_SUCCESS)
{
EXCEPTION("Failed RegOpenKeyExW\nLSTATUS: %d", registryOpenStatus);
}
}
void RegistryKey::close()
{
if (this->keyHandle == NULL)
{
return;
}
LSTATUS registryCloseStatus = RegCloseKey(this->keyHandle);
if (registryCloseStatus != ERROR_SUCCESS)
{
EXCEPTION("Failed RegCloseKey\nSystem error code: %d", registryCloseStatus);
}
this->keyHandle = NULL;
}
}
SteamClient.h
#pragma once
#include <Windows.h>
namespace BattleyeInjector
{
class SteamClient final
{
public:
SteamClient();
void start();
void startAndAwaitLogin(int maxTryCount);
private:
DWORD getActiveUserId();
};
}
SteamClient.cpp
#include "stdafx.h"
#include "SteamClient.h"
#include <string>
#include <RegistryKey.h>
#include <Process.h>
#include <Util.h>
namespace BattleyeInjector
{
static const HKEY STEAM_KEY = HKEY_CURRENT_USER;
static const std::wstring STEAM_INSTALL_PATH_SUB_KEY = L"SOFTWARE\Valve\Steam";
static const std::wstring STEAM_INSTALL_PATH_KEY_NAME = L"SteamExe";
static const std::wstring STEAM_ACTIVE_PROCESS_SUB_KEY = L"SOFTWARE\Valve\Steam\ActiveProcess";
static const std::wstring STEAM_ACTIVE_USER_KEY_NAME = L"ActiveUser";
SteamClient::SteamClient()
{
}
void SteamClient::start()
{
Shared::RegistryKey registryKey(STEAM_KEY, STEAM_INSTALL_PATH_SUB_KEY, 0, KEY_READ);
const std::wstring steamInstallPath = registryKey.getRegSZ(L"", STEAM_INSTALL_PATH_KEY_NAME);
STARTUPINFOEXW startupInfo;
ZeroMemory(&startupInfo, sizeof(STARTUPINFOEXW));
startupInfo.StartupInfo.cb = sizeof(STARTUPINFOEXW);
Shared::Process steamProcess(steamInstallPath, L"", NULL, NULL, false, 0, NULL, L"", startupInfo);
steamProcess.create();
}
void SteamClient::startAndAwaitLogin(int maxTryCount)
{
if (maxTryCount <= 0)
{
EXCEPTION("maxTryCount is invalid");
}
if (getActiveUserId() != 0)
{
return;
}
HANDLE eventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
if (eventHandle == NULL)
{
EXCEPTION_LAST_ERROR("Failed CreateEventW");
}
try
{
Shared::RegistryKey registryKey(STEAM_KEY, STEAM_ACTIVE_PROCESS_SUB_KEY, 0, KEY_READ);
for (int x = 0; x < maxTryCount; x++)
{
registryKey.regNotifyChangeKeyValue(false, REG_NOTIFY_CHANGE_LAST_SET, eventHandle, true);
start();
DWORD waitResult = WaitForSingleObject(eventHandle, INFINITE);
if (waitResult != WAIT_OBJECT_0)
{
EXCEPTION("Failed WaitForSingleObject\nWaitResult: %u", waitResult);
}
if (getActiveUserId() != 0)
{
return;
}
if (ResetEvent(eventHandle) == FALSE)
{
EXCEPTION_LAST_ERROR("Failed ResetEvent");
}
}
EXCEPTION("Failed await login to steam");
}
catch (...)
{
CloseHandle(eventHandle);
throw;
}
}
DWORD SteamClient::getActiveUserId()
{
Shared::RegistryKey registryKey(STEAM_KEY, STEAM_ACTIVE_PROCESS_SUB_KEY, 0, KEY_READ);
return registryKey.getRegDword(STEAM_ACTIVE_USER_KEY_NAME);
}
}