Compare commits

...

4 Commits

Author SHA1 Message Date
Mr_Goldberg 0595490c00
Support old steam http interfaces. 2021-05-10 09:46:42 -04:00
Nemirtingas 76c9e7a9ee Fix game crash.
WHen overlay is shown, you have at least 1 friend connected and you resize the game window smaller to the friend list position, it crashes because ImGui::ListBoxHeader returns false when its clipped and ImGui::ListBoxFooter shouldn't be called.
2021-05-09 10:11:35 +02:00
Mr_Goldberg ff6c3e994b
UNICODE support in the steamclient loader. 2021-04-29 18:53:13 -04:00
Mr_Goldberg 51702b898e
UTF8 paths are now properly handled on windows. 2021-04-25 12:44:41 -04:00
12 changed files with 448 additions and 164 deletions

View File

@ -28,14 +28,14 @@ randombytes(char * const buf, const size_t size)
std::string get_env_variable(std::string name) std::string get_env_variable(std::string name)
{ {
char env_variable[1024]; wchar_t env_variable[1024];
DWORD ret = GetEnvironmentVariableA(name.c_str(), env_variable, sizeof(env_variable)); DWORD ret = GetEnvironmentVariableW(utf8_decode(name).c_str(), env_variable, _countof(env_variable));
if (ret <= 0) { if (ret <= 0) {
return std::string(); return std::string();
} }
env_variable[ret] = 0; env_variable[ret] = 0;
return std::string(env_variable); return utf8_encode(env_variable);
} }
#else #else
@ -194,9 +194,9 @@ std::string get_full_lib_path()
{ {
std::string program_path; std::string program_path;
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
char DllPath[MAX_PATH] = {0}; wchar_t DllPath[2048] = {0};
GetModuleFileName((HINSTANCE)&__ImageBase, DllPath, _countof(DllPath)); GetModuleFileNameW((HINSTANCE)&__ImageBase, DllPath, _countof(DllPath));
program_path = DllPath; program_path = utf8_encode(DllPath);
#else #else
program_path = get_lib_path(); program_path = get_lib_path();
#endif #endif
@ -240,15 +240,18 @@ std::string canonical_path(std::string path)
{ {
std::string output; std::string output;
#if defined(STEAM_WIN32) #if defined(STEAM_WIN32)
char *buffer = _fullpath(NULL, path.c_str(), 0); wchar_t *buffer = _wfullpath(NULL, utf8_decode(path).c_str(), 0);
if (buffer) {
output = utf8_encode(buffer);
free(buffer);
}
#else #else
char *buffer = canonicalize_file_name(path.c_str()); char *buffer = canonicalize_file_name(path.c_str());
#endif
if (buffer) { if (buffer) {
output = buffer; output = buffer;
free(buffer); free(buffer);
} }
#endif
return output; return output;
} }
@ -633,7 +636,7 @@ static void load_dll()
PRINT_DEBUG("Crack file %s\n", path.c_str()); PRINT_DEBUG("Crack file %s\n", path.c_str());
if (file_exists(path)) { if (file_exists(path)) {
redirect_crackdll(); redirect_crackdll();
crack_dll_handle = LoadLibraryA(path.c_str()); crack_dll_handle = LoadLibraryW(utf8_decode(path).c_str());
unredirect_crackdll(); unredirect_crackdll();
PRINT_DEBUG("Loaded crack file\n"); PRINT_DEBUG("Loaded crack file\n");
} }
@ -657,7 +660,7 @@ static void load_dlls()
if (full_path[length - 4] != '.') continue; if (full_path[length - 4] != '.') continue;
PRINT_DEBUG("Trying to load %s\n", full_path.c_str()); PRINT_DEBUG("Trying to load %s\n", full_path.c_str());
if (LoadLibraryA(full_path.c_str())) { if (LoadLibraryW(utf8_decode(full_path).c_str())) {
PRINT_DEBUG("LOADED %s\n", full_path.c_str()); PRINT_DEBUG("LOADED %s\n", full_path.c_str());
} }
} }

View File

@ -84,6 +84,27 @@
#endif #endif
#endif #endif
#include <string>
// Convert a wide Unicode string to an UTF8 string
inline std::string utf8_encode(const std::wstring &wstr)
{
if( wstr.empty() ) return std::string();
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo( size_needed, 0 );
WideCharToMultiByte (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
}
// Convert an UTF8 string to a wide Unicode String
inline std::wstring utf8_decode(const std::string &str)
{
if( str.empty() ) return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo( size_needed, 0 );
MultiByteToWideChar (CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
#elif defined(__LINUX__) #elif defined(__LINUX__)
#include <arpa/inet.h> #include <arpa/inet.h>
@ -112,6 +133,8 @@
#define PRINT_DEBUG(...) {FILE *t = fopen("STEAM_LOG.txt", "a"); fprintf(t, __VA_ARGS__); fclose(t);} #define PRINT_DEBUG(...) {FILE *t = fopen("STEAM_LOG.txt", "a"); fprintf(t, __VA_ARGS__); fclose(t);}
#endif #endif
#define PATH_SEPARATOR "/" #define PATH_SEPARATOR "/"
#define utf8_decode(a) a
#endif #endif
//#define PRINT_DEBUG(...) fprintf(stdout, __VA_ARGS__) //#define PRINT_DEBUG(...) fprintf(stdout, __VA_ARGS__)
#ifdef EMU_RELEASE_BUILD #ifdef EMU_RELEASE_BUILD

View File

@ -49,7 +49,7 @@ static void load_old_interface_versions()
static bool loaded = false; static bool loaded = false;
if (loaded) return; if (loaded) return;
std::string interfaces_path = Local_Storage::get_program_path() + "steam_interfaces.txt"; std::string interfaces_path = Local_Storage::get_program_path() + "steam_interfaces.txt";
std::ifstream input( interfaces_path ); std::ifstream input( utf8_decode(interfaces_path) );
PRINT_DEBUG("load from: %s\n", interfaces_path.c_str()); PRINT_DEBUG("load from: %s\n", interfaces_path.c_str());
for( std::string line; getline( input, line ); ) for( std::string line; getline( input, line ); )

View File

@ -21,6 +21,9 @@
#define STB_IMAGE_STATIC #define STB_IMAGE_STATIC
#define STBI_ONLY_PNG #define STBI_ONLY_PNG
#define STBI_ONLY_JPEG #define STBI_ONLY_JPEG
#if defined(__WINDOWS__)
#define STBI_WINDOWS_UTF8
#endif
#include "../stb/stb_image.h" #include "../stb/stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION
@ -166,49 +169,93 @@ bool Local_Storage::save_screenshot(std::string const& image_path, uint8_t* img_
#else #else
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
static BOOL DirectoryExists(LPCSTR szPath) static BOOL DirectoryExists(LPCWSTR szPath)
{ {
DWORD dwAttrib = GetFileAttributesA(szPath); DWORD dwAttrib = GetFileAttributesW(szPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
} }
static void createDirectoryRecursively(std::string path) static void createDirectoryRecursively(std::wstring path)
{ {
unsigned long long pos = 0; unsigned long long pos = 0;
do do
{ {
pos = path.find_first_of("\\/", pos + 1); pos = path.find_first_of(L"\\/", pos + 1);
CreateDirectoryA(path.substr(0, pos).c_str(), NULL); CreateDirectoryW(path.substr(0, pos).c_str(), NULL);
} while (pos != std::string::npos); } while (pos != std::string::npos);
} }
static void create_directory(std::string strPath) static void create_directory(std::string in_path)
{ {
std::wstring strPath = utf8_decode(in_path);
if (DirectoryExists(strPath.c_str()) == FALSE) if (DirectoryExists(strPath.c_str()) == FALSE)
createDirectoryRecursively(strPath); createDirectoryRecursively(strPath);
} }
static std::vector<struct File_Data> get_filenames(std::string strPath) static std::vector<struct File_Data> get_filenames(std::string in_path)
{ {
std::vector<struct File_Data> output; std::vector<struct File_Data> output;
strPath = strPath.append("\\*"); in_path = in_path.append("\\*");
WIN32_FIND_DATAA ffd; WIN32_FIND_DATAW ffd;
HANDLE hFind = INVALID_HANDLE_VALUE; HANDLE hFind = INVALID_HANDLE_VALUE;
std::wstring strPath = utf8_decode(in_path);
// Start iterating over the files in the path directory. // Start iterating over the files in the path directory.
hFind = ::FindFirstFileA (strPath.c_str(), &ffd); hFind = ::FindFirstFileW (strPath.c_str(), &ffd);
if (hFind != INVALID_HANDLE_VALUE) if (hFind != INVALID_HANDLE_VALUE)
{ {
do // Managed to locate and create an handle to that folder. do // Managed to locate and create an handle to that folder.
{ {
if (strcmp(".", ffd.cFileName) == 0) continue; if (wcscmp(L".", ffd.cFileName) == 0) continue;
if (strcmp("..", ffd.cFileName) == 0) continue; if (wcscmp(L"..", ffd.cFileName) == 0) continue;
struct File_Data f_data; struct File_Data f_data;
f_data.name = ffd.cFileName; f_data.name = utf8_encode(ffd.cFileName);
output.push_back(f_data); output.push_back(f_data);
} while (::FindNextFileA(hFind, &ffd) == TRUE); } while (::FindNextFileW(hFind, &ffd) == TRUE);
::FindClose(hFind);
} else {
//printf("Failed to find path: %s", strPath.c_str());
}
return output;
}
static std::vector<struct File_Data> get_filenames_recursive_w(std::wstring base_path)
{
if (base_path.back() == *L"\\")
base_path.pop_back();
std::vector<struct File_Data> output;
std::wstring strPath = base_path;
strPath = strPath.append(L"\\*");
WIN32_FIND_DATAW ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
// Start iterating over the files in the path directory.
hFind = ::FindFirstFileW (strPath.c_str(), &ffd);
if (hFind != INVALID_HANDLE_VALUE)
{
do // Managed to locate and create an handle to that folder.
{
if (wcscmp(L".", ffd.cFileName) == 0) continue;
if (wcscmp(L"..", ffd.cFileName) == 0) continue;
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// Construct new path from our base path
std::wstring dir_name = ffd.cFileName;
std::wstring path = base_path;
path += L"\\";
path += dir_name;
std::vector<struct File_Data> lower = get_filenames_recursive_w(path);
std::transform(lower.begin(), lower.end(), std::back_inserter(output), [&dir_name](File_Data f) {f.name = utf8_encode(dir_name) + "\\" + f.name; return f;});
} else {
File_Data f;
f.name = utf8_encode(ffd.cFileName);
output.push_back(f);
}
} while (::FindNextFileW(hFind, &ffd) == TRUE);
::FindClose(hFind); ::FindClose(hFind);
} else { } else {
//printf("Failed to find path: %s", strPath.c_str()); //printf("Failed to find path: %s", strPath.c_str());
@ -219,44 +266,7 @@ static std::vector<struct File_Data> get_filenames(std::string strPath)
static std::vector<struct File_Data> get_filenames_recursive(std::string base_path) static std::vector<struct File_Data> get_filenames_recursive(std::string base_path)
{ {
if (base_path.back() == *PATH_SEPARATOR) return get_filenames_recursive_w(utf8_decode(base_path));
base_path.pop_back();
std::vector<struct File_Data> output;
std::string strPath = base_path;
strPath = strPath.append("\\*");
WIN32_FIND_DATAA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
// Start iterating over the files in the path directory.
hFind = ::FindFirstFileA (strPath.c_str(), &ffd);
if (hFind != INVALID_HANDLE_VALUE)
{
do // Managed to locate and create an handle to that folder.
{
if (strcmp(".", ffd.cFileName) == 0) continue;
if (strcmp("..", ffd.cFileName) == 0) continue;
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// Construct new path from our base path
std::string dir_name = ffd.cFileName;
std::string path = base_path;
path += PATH_SEPARATOR;
path += dir_name;
std::vector<struct File_Data> lower = get_filenames_recursive(path);
std::transform(lower.begin(), lower.end(), std::back_inserter(output), [&dir_name](File_Data f) {f.name = dir_name + "\\" + f.name; return f;});
} else {
File_Data f;
f.name = ffd.cFileName;
output.push_back(f);
}
} while (::FindNextFileA(hFind, &ffd) == TRUE);
::FindClose(hFind);
} else {
//printf("Failed to find path: %s", strPath.c_str());
}
return output;
} }
#else #else
@ -403,12 +413,12 @@ std::string Local_Storage::get_user_appdata_path()
{ {
std::string user_appdata_path = "SAVE"; std::string user_appdata_path = "SAVE";
#if defined(STEAM_WIN32) #if defined(STEAM_WIN32)
CHAR szPath[MAX_PATH] = {}; WCHAR szPath[MAX_PATH] = {};
HRESULT hr = SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, szPath); HRESULT hr = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, szPath);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
user_appdata_path = szPath; user_appdata_path = utf8_encode(szPath);
} }
#else #else
@ -504,7 +514,7 @@ int Local_Storage::store_file_data(std::string folder, std::string file, char *d
create_directory(folder + file_folder); create_directory(folder + file_folder);
std::ofstream myfile; std::ofstream myfile;
myfile.open(folder + file, std::ios::binary | std::ios::out); myfile.open(utf8_decode(folder + file), std::ios::binary | std::ios::out);
if (!myfile.is_open()) return -1; if (!myfile.is_open()) return -1;
myfile.write(data, length); myfile.write(data, length);
int position = myfile.tellp(); int position = myfile.tellp();
@ -553,7 +563,7 @@ int Local_Storage::store_data_settings(std::string file, char *data, unsigned in
int Local_Storage::get_file_data(std::string full_path, char *data, unsigned int max_length, unsigned int offset) int Local_Storage::get_file_data(std::string full_path, char *data, unsigned int max_length, unsigned int offset)
{ {
std::ifstream myfile; std::ifstream myfile;
myfile.open(full_path, std::ios::binary | std::ios::in); myfile.open(utf8_decode(full_path), std::ios::binary | std::ios::in);
if (!myfile.is_open()) return -1; if (!myfile.is_open()) return -1;
myfile.seekg (offset, std::ios::beg); myfile.seekg (offset, std::ios::beg);
@ -597,15 +607,19 @@ bool Local_Storage::file_exists(std::string folder, std::string file)
} }
std::string full_path = save_directory + appid + folder + file; std::string full_path = save_directory + appid + folder + file;
struct stat buffer;
if (stat(full_path.c_str(), &buffer) != 0)
return false;
#if defined(STEAM_WIN32) #if defined(STEAM_WIN32)
struct _stat buffer;
if (_wstat(utf8_decode(full_path).c_str(), &buffer) != 0)
return false;
if ( buffer.st_mode & _S_IFDIR) if ( buffer.st_mode & _S_IFDIR)
return false; return false;
#else #else
struct stat buffer;
if (stat(full_path.c_str(), &buffer) != 0)
return false;
if (S_ISDIR(buffer.st_mode)) if (S_ISDIR(buffer.st_mode))
return false; return false;
#endif #endif
@ -621,8 +635,14 @@ unsigned int Local_Storage::file_size(std::string folder, std::string file)
} }
std::string full_path = save_directory + appid + folder + file; std::string full_path = save_directory + appid + folder + file;
#if defined(STEAM_WIN32)
struct _stat buffer = {};
if (_wstat(utf8_decode(full_path).c_str(), &buffer) != 0) return 0;
#else
struct stat buffer = {}; struct stat buffer = {};
if (stat (full_path.c_str(), &buffer) != 0) return 0; if (stat (full_path.c_str(), &buffer) != 0) return 0;
#endif
return buffer.st_size; return buffer.st_size;
} }
@ -634,7 +654,11 @@ bool Local_Storage::file_delete(std::string folder, std::string file)
} }
std::string full_path = save_directory + appid + folder + file; std::string full_path = save_directory + appid + folder + file;
#if defined(STEAM_WIN32)
return _wremove(utf8_decode(full_path).c_str()) == 0;
#else
return remove(full_path.c_str()) == 0; return remove(full_path.c_str()) == 0;
#endif
} }
uint64_t Local_Storage::file_timestamp(std::string folder, std::string file) uint64_t Local_Storage::file_timestamp(std::string folder, std::string file)
@ -645,8 +669,14 @@ uint64_t Local_Storage::file_timestamp(std::string folder, std::string file)
} }
std::string full_path = save_directory + appid + folder + file; std::string full_path = save_directory + appid + folder + file;
#if defined(STEAM_WIN32)
struct _stat buffer = {};
if (_wstat(utf8_decode(full_path).c_str(), &buffer) != 0) return 0;
#else
struct stat buffer = {}; struct stat buffer = {};
if (stat (full_path.c_str(), &buffer) != 0) return 0; if (stat (full_path.c_str(), &buffer) != 0) return 0;
#endif
return buffer.st_mtime; return buffer.st_mtime;
} }
@ -695,7 +725,7 @@ bool Local_Storage::update_save_filenames(std::string folder)
bool Local_Storage::load_json(std::string full_path, nlohmann::json& json) bool Local_Storage::load_json(std::string full_path, nlohmann::json& json)
{ {
std::ifstream inventory_file(full_path); std::ifstream inventory_file(utf8_decode(full_path));
// If there is a file and we opened it // If there is a file and we opened it
if (inventory_file) if (inventory_file)
{ {
@ -745,7 +775,7 @@ bool Local_Storage::write_json_file(std::string folder, std::string const&file,
create_directory(inv_path); create_directory(inv_path);
std::ofstream inventory_file(full_path, std::ios::trunc | std::ios::out); std::ofstream inventory_file(utf8_decode(full_path), std::ios::trunc | std::ios::out);
if (inventory_file) if (inventory_file)
{ {
inventory_file << std::setw(2) << json; inventory_file << std::setw(2) << json;
@ -760,11 +790,8 @@ bool Local_Storage::write_json_file(std::string folder, std::string const&file,
std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path) std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path)
{ {
std::vector<image_pixel_t> res; std::vector<image_pixel_t> res;
FILE* hFile = fopen(image_path.c_str(), "r");
if (hFile != nullptr)
{
int width, height; int width, height;
image_pixel_t* img = (image_pixel_t*)stbi_load_from_file(hFile, &width, &height, nullptr, 4); image_pixel_t* img = (image_pixel_t*)stbi_load(image_path.c_str(), &width, &height, nullptr, 4);
if (img != nullptr) if (img != nullptr)
{ {
res.resize(width*height); res.resize(width*height);
@ -772,8 +799,6 @@ std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_pa
stbi_image_free(img); stbi_image_free(img);
} }
fclose(hFile);
}
return res; return res;
} }

View File

@ -31,7 +31,7 @@ static void consume_bom(std::ifstream &input)
static void load_custom_broadcasts(std::string broadcasts_filepath, std::set<uint32> &custom_broadcasts) static void load_custom_broadcasts(std::string broadcasts_filepath, std::set<uint32> &custom_broadcasts)
{ {
PRINT_DEBUG("Broadcasts file path: %s\n", broadcasts_filepath.c_str()); PRINT_DEBUG("Broadcasts file path: %s\n", broadcasts_filepath.c_str());
std::ifstream broadcasts_file(broadcasts_filepath); std::ifstream broadcasts_file(utf8_decode(broadcasts_filepath));
consume_bom(broadcasts_file); consume_bom(broadcasts_file);
if (broadcasts_file.is_open()) { if (broadcasts_file.is_open()) {
std::string line; std::string line;
@ -69,7 +69,7 @@ static void load_gamecontroller_settings(Settings *settings)
std::transform(action_set_name.begin(), action_set_name.end(), action_set_name.begin(),[](unsigned char c){ return std::toupper(c); }); std::transform(action_set_name.begin(), action_set_name.end(), action_set_name.begin(),[](unsigned char c){ return std::toupper(c); });
std::string controller_config_path = path + PATH_SEPARATOR + p; std::string controller_config_path = path + PATH_SEPARATOR + p;
std::ifstream input( controller_config_path ); std::ifstream input( utf8_decode(controller_config_path) );
if (input.is_open()) { if (input.is_open()) {
consume_bom(input); consume_bom(input);
std::map<std::string, std::pair<std::set<std::string>, std::string>> button_pairs; std::map<std::string, std::pair<std::set<std::string>, std::string>> button_pairs;
@ -307,7 +307,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
{ {
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt"; std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt";
std::ifstream input( dlc_config_path ); std::ifstream input( utf8_decode(dlc_config_path) );
if (input.is_open()) { if (input.is_open()) {
consume_bom(input); consume_bom(input);
settings_client->unlockAllDLC(false); settings_client->unlockAllDLC(false);
@ -349,7 +349,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
{ {
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "app_paths.txt"; std::string dlc_config_path = Local_Storage::get_game_settings_path() + "app_paths.txt";
std::ifstream input( dlc_config_path ); std::ifstream input( utf8_decode(dlc_config_path) );
if (input.is_open()) { if (input.is_open()) {
consume_bom(input); consume_bom(input);
@ -384,7 +384,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
{ {
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "leaderboards.txt"; std::string dlc_config_path = Local_Storage::get_game_settings_path() + "leaderboards.txt";
std::ifstream input( dlc_config_path ); std::ifstream input( utf8_decode(dlc_config_path) );
if (input.is_open()) { if (input.is_open()) {
consume_bom(input); consume_bom(input);
settings_client->setCreateUnknownLeaderboards(false); settings_client->setCreateUnknownLeaderboards(false);
@ -426,7 +426,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
{ {
std::string stats_config_path = Local_Storage::get_game_settings_path() + "stats.txt"; std::string stats_config_path = Local_Storage::get_game_settings_path() + "stats.txt";
std::ifstream input( stats_config_path ); std::ifstream input( utf8_decode(stats_config_path) );
if (input.is_open()) { if (input.is_open()) {
consume_bom(input); consume_bom(input);
for( std::string line; getline( input, line ); ) { for( std::string line; getline( input, line ); ) {
@ -491,7 +491,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
{ {
std::string depots_config_path = Local_Storage::get_game_settings_path() + "depots.txt"; std::string depots_config_path = Local_Storage::get_game_settings_path() + "depots.txt";
std::ifstream input( depots_config_path ); std::ifstream input( utf8_decode(depots_config_path) );
if (input.is_open()) { if (input.is_open()) {
consume_bom(input); consume_bom(input);
for( std::string line; getline( input, line ); ) { for( std::string line; getline( input, line ); ) {
@ -513,7 +513,7 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
{ {
std::string depots_config_path = Local_Storage::get_game_settings_path() + "subscribed_groups.txt"; std::string depots_config_path = Local_Storage::get_game_settings_path() + "subscribed_groups.txt";
std::ifstream input( depots_config_path ); std::ifstream input( utf8_decode(depots_config_path) );
if (input.is_open()) { if (input.is_open()) {
consume_bom(input); consume_bom(input);
for( std::string line; getline( input, line ); ) { for( std::string line; getline( input, line ); ) {

View File

@ -812,11 +812,25 @@ ISteamHTTP *Steam_Client::GetISteamHTTP( HSteamUser hSteamuser, HSteamPipe hStea
{ {
PRINT_DEBUG("GetISteamHTTP %s\n", pchVersion); PRINT_DEBUG("GetISteamHTTP %s\n", pchVersion);
if (!steam_pipes.count(hSteamPipe) || !hSteamuser) return NULL; if (!steam_pipes.count(hSteamPipe) || !hSteamuser) return NULL;
Steam_HTTP *steam_http_temp;
if (steam_pipes[hSteamPipe] == Steam_Pipe::SERVER) { if (steam_pipes[hSteamPipe] == Steam_Pipe::SERVER) {
return steam_gameserver_http; steam_http_temp = steam_gameserver_http;
} else {
steam_http_temp = steam_http;
} }
return steam_http; if (strcmp(pchVersion, "STEAMHTTP_INTERFACE_VERSION001") == 0) {
return (ISteamHTTP *)(void *)(ISteamHTTP001 *)steam_http_temp;
} else if (strcmp(pchVersion, "STEAMHTTP_INTERFACE_VERSION002") == 0) {
return (ISteamHTTP *)(void *)(ISteamHTTP002 *)steam_http_temp;
} else if (strcmp(pchVersion, STEAMHTTP_INTERFACE_VERSION) == 0) {
return (ISteamHTTP *)(void *)(ISteamHTTP *)steam_http_temp;
} else {
return (ISteamHTTP *)(void *)(ISteamHTTP *)steam_http_temp;
}
return steam_http_temp;
} }
// Deprecated - the ISteamUnifiedMessages interface is no longer intended for public consumption. // Deprecated - the ISteamUnifiedMessages interface is no longer intended for public consumption.

View File

@ -25,7 +25,10 @@ struct Steam_Http_Request {
std::string response; std::string response;
}; };
class Steam_HTTP : public ISteamHTTP class Steam_HTTP :
public ISteamHTTP001,
public ISteamHTTP002,
public ISteamHTTP
{ {
class Settings *settings; class Settings *settings;
class Networking *network; class Networking *network;

View File

@ -657,7 +657,8 @@ void Steam_Overlay::OverlayProc()
std::lock_guard<std::recursive_mutex> lock(overlay_mutex); std::lock_guard<std::recursive_mutex> lock(overlay_mutex);
if (!friends.empty()) if (!friends.empty())
{ {
ImGui::ListBoxHeader("##label", friends.size()); if (ImGui::ListBoxHeader("##label", friends.size()))
{
std::for_each(friends.begin(), friends.end(), [this](std::pair<Friend const, friend_window_state> &i) std::for_each(friends.begin(), friends.end(), [this](std::pair<Friend const, friend_window_state> &i)
{ {
ImGui::PushID(i.second.id-base_friend_window_id+base_friend_item_id); ImGui::PushID(i.second.id-base_friend_window_id+base_friend_item_id);
@ -675,6 +676,7 @@ void Steam_Overlay::OverlayProc()
ImGui::ListBoxFooter(); ImGui::ListBoxFooter();
} }
} }
}
ImGui::End(); ImGui::End();
ImGui::PopFont(); ImGui::PopFont();

View File

@ -0,0 +1,85 @@
#ifndef ISTEAMHTTP001_H
#define ISTEAMHTTP001_H
#ifdef STEAM_WIN32
#pragma once
#endif
class ISteamHTTP001
{
public:
// Initializes a new HTTP request, returning a handle to use in further operations on it. Requires
// the method (GET or POST) and the absolute URL for the request. Only http requests (ie, not https) are
// currently supported, so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/
// or such.
virtual HTTPRequestHandle CreateHTTPRequest( EHTTPMethod eHTTPRequestMethod, const char *pchAbsoluteURL ) = 0;
// Set a context value for the request, which will be returned in the HTTPRequestCompleted_t callback after
// sending the request. This is just so the caller can easily keep track of which callbacks go with which request data.
virtual bool SetHTTPRequestContextValue( HTTPRequestHandle hRequest, uint64 ulContextValue ) = 0;
// Set a timeout in seconds for the HTTP request, must be called prior to sending the request. Default
// timeout is 60 seconds if you don't call this. Returns false if the handle is invalid, or the request
// has already been sent.
virtual bool SetHTTPRequestNetworkActivityTimeout( HTTPRequestHandle hRequest, uint32 unTimeoutSeconds ) = 0;
// Set a request header value for the request, must be called prior to sending the request. Will
// return false if the handle is invalid or the request is already sent.
virtual bool SetHTTPRequestHeaderValue( HTTPRequestHandle hRequest, const char *pchHeaderName, const char *pchHeaderValue ) = 0;
// Set a GET or POST parameter value on the request, which is set will depend on the EHTTPMethod specified
// when creating the request. Must be called prior to sending the request. Will return false if the
// handle is invalid or the request is already sent.
virtual bool SetHTTPRequestGetOrPostParameter( HTTPRequestHandle hRequest, const char *pchParamName, const char *pchParamValue ) = 0;
// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on
// asyncronous response via callback.
//
// Note: If the user is in offline mode in Steam, then this will add a only-if-cached cache-control
// header and only do a local cache lookup rather than sending any actual remote request.
virtual bool SendHTTPRequest( HTTPRequestHandle hRequest, SteamAPICall_t *pCallHandle ) = 0;
// Defers a request you have sent, the actual HTTP client code may have many requests queued, and this will move
// the specified request to the tail of the queue. Returns false on invalid handle, or if the request is not yet sent.
virtual bool DeferHTTPRequest( HTTPRequestHandle hRequest ) = 0;
// Prioritizes a request you have sent, the actual HTTP client code may have many requests queued, and this will move
// the specified request to the head of the queue. Returns false on invalid handle, or if the request is not yet sent.
virtual bool PrioritizeHTTPRequest( HTTPRequestHandle hRequest ) = 0;
// Checks if a response header is present in a HTTP response given a handle from HTTPRequestCompleted_t, also
// returns the size of the header value if present so the caller and allocate a correctly sized buffer for
// GetHTTPResponseHeaderValue.
virtual bool GetHTTPResponseHeaderSize( HTTPRequestHandle hRequest, const char *pchHeaderName, uint32 *unResponseHeaderSize ) = 0;
// Gets header values from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
// header is not present or if your buffer is too small to contain it's value. You should first call
// BGetHTTPResponseHeaderSize to check for the presence of the header and to find out the size buffer needed.
virtual bool GetHTTPResponseHeaderValue( HTTPRequestHandle hRequest, const char *pchHeaderName, uint8 *pHeaderValueBuffer, uint32 unBufferSize ) = 0;
// Gets the size of the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
// handle is invalid.
virtual bool GetHTTPResponseBodySize( HTTPRequestHandle hRequest, uint32 *unBodySize ) = 0;
// Gets the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
// handle is invalid or if the provided buffer is not the correct size. Use BGetHTTPResponseBodySize first to find out
// the correct buffer size to use.
virtual bool GetHTTPResponseBodyData( HTTPRequestHandle hRequest, uint8 *pBodyDataBuffer, uint32 unBufferSize ) = 0;
// Releases an HTTP response handle, should always be called to free resources after receiving a HTTPRequestCompleted_t
// callback and finishing using the response.
virtual bool ReleaseHTTPRequest( HTTPRequestHandle hRequest ) = 0;
// Gets progress on downloading the body for the request. This will be zero unless a response header has already been
// received which included a content-length field. For responses that contain no content-length it will report
// zero for the duration of the request as the size is unknown until the connection closes.
virtual bool GetHTTPDownloadProgressPct( HTTPRequestHandle hRequest, float *pflPercentOut ) = 0;
// Sets the body for an HTTP Post request. Will fail and return false on a GET request, and will fail if POST params
// have already been set for the request. Setting this raw body makes it the only contents for the post, the pchContentType
// parameter will set the content-type header for the request so the server may know how to interpret the body.
virtual bool SetHTTPRequestRawPostBody( HTTPRequestHandle hRequest, const char *pchContentType, uint8 *pubBody, uint32 unBodyLen ) = 0;
};
#endif // ISTEAMHTTP001_H

View File

@ -0,0 +1,124 @@
#ifndef ISTEAMHTTP002_H
#define ISTEAMHTTP002_H
#ifdef STEAM_WIN32
#pragma once
#endif
class ISteamHTTP002
{
public:
// Initializes a new HTTP request, returning a handle to use in further operations on it. Requires
// the method (GET or POST) and the absolute URL for the request. Both http and https are supported,
// so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/
// or such.
virtual HTTPRequestHandle CreateHTTPRequest( EHTTPMethod eHTTPRequestMethod, const char *pchAbsoluteURL ) = 0;
// Set a context value for the request, which will be returned in the HTTPRequestCompleted_t callback after
// sending the request. This is just so the caller can easily keep track of which callbacks go with which request data.
virtual bool SetHTTPRequestContextValue( HTTPRequestHandle hRequest, uint64 ulContextValue ) = 0;
// Set a timeout in seconds for the HTTP request, must be called prior to sending the request. Default
// timeout is 60 seconds if you don't call this. Returns false if the handle is invalid, or the request
// has already been sent.
virtual bool SetHTTPRequestNetworkActivityTimeout( HTTPRequestHandle hRequest, uint32 unTimeoutSeconds ) = 0;
// Set a request header value for the request, must be called prior to sending the request. Will
// return false if the handle is invalid or the request is already sent.
virtual bool SetHTTPRequestHeaderValue( HTTPRequestHandle hRequest, const char *pchHeaderName, const char *pchHeaderValue ) = 0;
// Set a GET or POST parameter value on the request, which is set will depend on the EHTTPMethod specified
// when creating the request. Must be called prior to sending the request. Will return false if the
// handle is invalid or the request is already sent.
virtual bool SetHTTPRequestGetOrPostParameter( HTTPRequestHandle hRequest, const char *pchParamName, const char *pchParamValue ) = 0;
// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on
// asynchronous response via callback.
//
// Note: If the user is in offline mode in Steam, then this will add a only-if-cached cache-control
// header and only do a local cache lookup rather than sending any actual remote request.
virtual bool SendHTTPRequest( HTTPRequestHandle hRequest, SteamAPICall_t *pCallHandle ) = 0;
// Sends the HTTP request, will return false on a bad handle, otherwise use SteamCallHandle to wait on
// asynchronous response via callback for completion, and listen for HTTPRequestHeadersReceived_t and
// HTTPRequestDataReceived_t callbacks while streaming.
virtual bool SendHTTPRequestAndStreamResponse( HTTPRequestHandle hRequest, SteamAPICall_t *pCallHandle ) = 0;
// Defers a request you have sent, the actual HTTP client code may have many requests queued, and this will move
// the specified request to the tail of the queue. Returns false on invalid handle, or if the request is not yet sent.
virtual bool DeferHTTPRequest( HTTPRequestHandle hRequest ) = 0;
// Prioritizes a request you have sent, the actual HTTP client code may have many requests queued, and this will move
// the specified request to the head of the queue. Returns false on invalid handle, or if the request is not yet sent.
virtual bool PrioritizeHTTPRequest( HTTPRequestHandle hRequest ) = 0;
// Checks if a response header is present in a HTTP response given a handle from HTTPRequestCompleted_t, also
// returns the size of the header value if present so the caller and allocate a correctly sized buffer for
// GetHTTPResponseHeaderValue.
virtual bool GetHTTPResponseHeaderSize( HTTPRequestHandle hRequest, const char *pchHeaderName, uint32 *unResponseHeaderSize ) = 0;
// Gets header values from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
// header is not present or if your buffer is too small to contain it's value. You should first call
// BGetHTTPResponseHeaderSize to check for the presence of the header and to find out the size buffer needed.
virtual bool GetHTTPResponseHeaderValue( HTTPRequestHandle hRequest, const char *pchHeaderName, uint8 *pHeaderValueBuffer, uint32 unBufferSize ) = 0;
// Gets the size of the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
// handle is invalid.
virtual bool GetHTTPResponseBodySize( HTTPRequestHandle hRequest, uint32 *unBodySize ) = 0;
// Gets the body data from a HTTP response given a handle from HTTPRequestCompleted_t, will return false if the
// handle is invalid or is to a streaming response, or if the provided buffer is not the correct size. Use BGetHTTPResponseBodySize first to find out
// the correct buffer size to use.
virtual bool GetHTTPResponseBodyData( HTTPRequestHandle hRequest, uint8 *pBodyDataBuffer, uint32 unBufferSize ) = 0;
// Gets the body data from a streaming HTTP response given a handle from HTTPRequestDataReceived_t. Will return false if the
// handle is invalid or is to a non-streaming response (meaning it wasn't sent with SendHTTPRequestAndStreamResponse), or if the buffer size and offset
// do not match the size and offset sent in HTTPRequestDataReceived_t.
virtual bool GetHTTPStreamingResponseBodyData( HTTPRequestHandle hRequest, uint32 cOffset, uint8 *pBodyDataBuffer, uint32 unBufferSize ) = 0;
// Releases an HTTP response handle, should always be called to free resources after receiving a HTTPRequestCompleted_t
// callback and finishing using the response.
virtual bool ReleaseHTTPRequest( HTTPRequestHandle hRequest ) = 0;
// Gets progress on downloading the body for the request. This will be zero unless a response header has already been
// received which included a content-length field. For responses that contain no content-length it will report
// zero for the duration of the request as the size is unknown until the connection closes.
virtual bool GetHTTPDownloadProgressPct( HTTPRequestHandle hRequest, float *pflPercentOut ) = 0;
// Sets the body for an HTTP Post request. Will fail and return false on a GET request, and will fail if POST params
// have already been set for the request. Setting this raw body makes it the only contents for the post, the pchContentType
// parameter will set the content-type header for the request so the server may know how to interpret the body.
virtual bool SetHTTPRequestRawPostBody( HTTPRequestHandle hRequest, const char *pchContentType, uint8 *pubBody, uint32 unBodyLen ) = 0;
// Creates a cookie container handle which you must later free with ReleaseCookieContainer(). If bAllowResponsesToModify=true
// than any response to your requests using this cookie container may add new cookies which may be transmitted with
// future requests. If bAllowResponsesToModify=false than only cookies you explicitly set will be sent. This API is just for
// during process lifetime, after steam restarts no cookies are persisted and you have no way to access the cookie container across
// repeat executions of your process.
virtual HTTPCookieContainerHandle CreateCookieContainer( bool bAllowResponsesToModify ) = 0;
// Release a cookie container you are finished using, freeing it's memory
virtual bool ReleaseCookieContainer( HTTPCookieContainerHandle hCookieContainer ) = 0;
// Adds a cookie to the specified cookie container that will be used with future requests.
virtual bool SetCookie( HTTPCookieContainerHandle hCookieContainer, const char *pchHost, const char *pchUrl, const char *pchCookie ) = 0;
// Set the cookie container to use for a HTTP request
virtual bool SetHTTPRequestCookieContainer( HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer ) = 0;
// Set the extra user agent info for a request, this doesn't clobber the normal user agent, it just adds the extra info on the end
virtual bool SetHTTPRequestUserAgentInfo( HTTPRequestHandle hRequest, const char *pchUserAgentInfo ) = 0;
// Set that https request should require verified SSL certificate via machines certificate trust store
virtual bool SetHTTPRequestRequiresVerifiedCertificate( HTTPRequestHandle hRequest, bool bRequireVerifiedCertificate ) = 0;
// Set an absolute timeout on the HTTP request, this is just a total time timeout different than the network activity timeout
// which can bump everytime we get more data
virtual bool SetHTTPRequestAbsoluteTimeoutMS( HTTPRequestHandle hRequest, uint32 unMilliseconds ) = 0;
// Check if the reason the request failed was because we timed it out (rather than some harder failure)
virtual bool GetHTTPRequestWasTimedOut( HTTPRequestHandle hRequest, bool *pbWasTimedOut ) = 0;
};
#endif // ISTEAMHTTP002_H

View File

@ -128,6 +128,8 @@
#include "isteammusic.h" #include "isteammusic.h"
#include "isteammusicremote.h" #include "isteammusicremote.h"
#include "isteamhttp.h" #include "isteamhttp.h"
#include "isteamhttp001.h"
#include "isteamhttp002.h"
#include "isteamcontroller.h" #include "isteamcontroller.h"
#include "isteamcontroller001.h" #include "isteamcontroller001.h"
#include "isteamcontroller003.h" #include "isteamcontroller003.h"

View File

@ -10,13 +10,13 @@
#include <tchar.h> #include <tchar.h>
#include <stdio.h> #include <stdio.h>
bool IsNotRelativePathOrRemoveFileName(CHAR* output, bool Remove) bool IsNotRelativePathOrRemoveFileName(WCHAR* output, bool Remove)
{ {
int LG = lstrlenA(output); int LG = lstrlenW(output);
for (int i = LG; i > 0; i--) { for (int i = LG; i > 0; i--) {
if (output[i] == '\\') { if (output[i] == '\\') {
if(Remove) if(Remove)
RtlFillMemory(&output[i], LG - i, NULL); RtlFillMemory(&output[i], (LG - i) * sizeof(WCHAR), NULL);
return true; return true;
} }
} }
@ -25,81 +25,84 @@ bool IsNotRelativePathOrRemoveFileName(CHAR* output, bool Remove)
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{ {
CHAR CurrentDirectory[MAX_PATH] = { 0 }; WCHAR CurrentDirectory[MAX_PATH] = { 0 };
CHAR Client64Path[MAX_PATH] = { 0 }; WCHAR Client64Path[MAX_PATH] = { 0 };
CHAR ClientPath[MAX_PATH] = { 0 }; WCHAR ClientPath[MAX_PATH] = { 0 };
CHAR ExeFile[MAX_PATH] = { 0 }; WCHAR ExeFile[MAX_PATH] = { 0 };
CHAR ExeRunDir[MAX_PATH] = { 0 }; WCHAR ExeRunDir[MAX_PATH] = { 0 };
CHAR ExeCommandLine[4096] = { 0 }; WCHAR ExeCommandLine[4096] = { 0 };
CHAR AppId[128] = { 0 }; WCHAR AppId[128] = { 0 };
STARTUPINFOA info = { sizeof(info) }; STARTUPINFOW info = { sizeof(info) };
PROCESS_INFORMATION processInfo; PROCESS_INFORMATION processInfo;
int Length = GetModuleFileNameA(GetModuleHandleA(NULL), CurrentDirectory, sizeof(CurrentDirectory)) + 1; int Length = GetModuleFileNameW(GetModuleHandleW(NULL), CurrentDirectory, sizeof(CurrentDirectory)) + 1;
for (int i = Length; i > 0; i--) { for (int i = Length; i > 0; i--) {
if (CurrentDirectory[i] == '\\') { if (CurrentDirectory[i] == '\\') {
lstrcpyA(&CurrentDirectory[i + 1], "ColdClientLoader.ini"); lstrcpyW(&CurrentDirectory[i + 1], L"ColdClientLoader.ini");
break; break;
} }
} }
if (GetFileAttributesA(CurrentDirectory) == INVALID_FILE_ATTRIBUTES) { if (GetFileAttributesW(CurrentDirectory) == INVALID_FILE_ATTRIBUTES) {
MessageBoxA(NULL, "Couldn't find the configuration file(ColdClientLoader.ini).", "ColdClientLoader", MB_ICONERROR); MessageBoxA(NULL, "Couldn't find the configuration file(ColdClientLoader.ini).", "ColdClientLoader", MB_ICONERROR);
return 0; return 0;
} }
GetPrivateProfileStringA("SteamClient", "SteamClient64Dll", "", Client64Path, MAX_PATH, CurrentDirectory); GetPrivateProfileStringW(L"SteamClient", L"SteamClient64Dll", L"", Client64Path, MAX_PATH, CurrentDirectory);
GetPrivateProfileStringA("SteamClient", "SteamClientDll", "", ClientPath, MAX_PATH, CurrentDirectory); GetPrivateProfileStringW(L"SteamClient", L"SteamClientDll", L"", ClientPath, MAX_PATH, CurrentDirectory);
GetPrivateProfileStringA("SteamClient", "Exe", NULL, ExeFile, MAX_PATH, CurrentDirectory); GetPrivateProfileStringW(L"SteamClient", L"Exe", NULL, ExeFile, MAX_PATH, CurrentDirectory);
GetPrivateProfileStringA("SteamClient", "ExeRunDir", NULL, ExeRunDir, MAX_PATH, CurrentDirectory); GetPrivateProfileStringW(L"SteamClient", L"ExeRunDir", NULL, ExeRunDir, MAX_PATH, CurrentDirectory);
GetPrivateProfileStringA("SteamClient", "ExeCommandLine", NULL, ExeCommandLine, 4096, CurrentDirectory); GetPrivateProfileStringW(L"SteamClient", L"ExeCommandLine", NULL, ExeCommandLine, 4096, CurrentDirectory);
GetPrivateProfileStringA("SteamClient", "AppId", NULL, AppId, sizeof(AppId), CurrentDirectory); GetPrivateProfileStringW(L"SteamClient", L"AppId", NULL, AppId, sizeof(AppId), CurrentDirectory);
if (AppId[0]) { if (AppId[0]) {
SetEnvironmentVariableA("SteamAppId", AppId); SetEnvironmentVariableW(L"SteamAppId", AppId);
SetEnvironmentVariableA("SteamGameId", AppId); SetEnvironmentVariableW(L"SteamGameId", AppId);
} else {
MessageBoxA(NULL, "You forgot to set the AppId.", "ColdClientLoader", MB_ICONERROR);
return 0;
} }
CHAR TMP[MAX_PATH] = {}; WCHAR TMP[MAX_PATH] = {};
if (!IsNotRelativePathOrRemoveFileName(Client64Path, false)) { if (!IsNotRelativePathOrRemoveFileName(Client64Path, false)) {
lstrcpyA(TMP, Client64Path); lstrcpyW(TMP, Client64Path);
ZeroMemory(Client64Path, sizeof(Client64Path)); ZeroMemory(Client64Path, sizeof(Client64Path));
GetFullPathNameA(TMP, MAX_PATH, Client64Path, NULL); GetFullPathNameW(TMP, MAX_PATH, Client64Path, NULL);
} }
if (!IsNotRelativePathOrRemoveFileName(ClientPath, false)) { if (!IsNotRelativePathOrRemoveFileName(ClientPath, false)) {
lstrcpyA(TMP, ClientPath); lstrcpyW(TMP, ClientPath);
ZeroMemory(ClientPath, sizeof(ClientPath)); ZeroMemory(ClientPath, sizeof(ClientPath));
GetFullPathNameA(TMP, MAX_PATH, ClientPath, NULL); GetFullPathNameW(TMP, MAX_PATH, ClientPath, NULL);
} }
if (!IsNotRelativePathOrRemoveFileName(ExeFile, false)) { if (!IsNotRelativePathOrRemoveFileName(ExeFile, false)) {
lstrcpyA(TMP, ExeFile); lstrcpyW(TMP, ExeFile);
ZeroMemory(ExeFile, sizeof(ExeFile)); ZeroMemory(ExeFile, sizeof(ExeFile));
GetFullPathNameA(TMP, MAX_PATH, ExeFile, NULL); GetFullPathNameW(TMP, MAX_PATH, ExeFile, NULL);
} }
if (!IsNotRelativePathOrRemoveFileName(ExeRunDir, false)) { if (!IsNotRelativePathOrRemoveFileName(ExeRunDir, false)) {
lstrcpyA(TMP, ExeRunDir); lstrcpyW(TMP, ExeRunDir);
ZeroMemory(ExeRunDir, sizeof(ExeRunDir)); ZeroMemory(ExeRunDir, sizeof(ExeRunDir));
GetFullPathNameA(TMP, MAX_PATH, ExeRunDir, NULL); GetFullPathNameW(TMP, MAX_PATH, ExeRunDir, NULL);
} }
if (GetFileAttributesA(Client64Path) == INVALID_FILE_ATTRIBUTES) { if (GetFileAttributesW(Client64Path) == INVALID_FILE_ATTRIBUTES) {
MessageBoxA(NULL, "Couldn't find the requested SteamClient64Dll.", "ColdClientLoader", MB_ICONERROR); MessageBoxA(NULL, "Couldn't find the requested SteamClient64Dll.", "ColdClientLoader", MB_ICONERROR);
return 0; return 0;
} }
if (GetFileAttributesA(ClientPath) == INVALID_FILE_ATTRIBUTES) { if (GetFileAttributesW(ClientPath) == INVALID_FILE_ATTRIBUTES) {
MessageBoxA(NULL, "Couldn't find the requested SteamClientDll.", "ColdClientLoader", MB_ICONERROR); MessageBoxA(NULL, "Couldn't find the requested SteamClientDll.", "ColdClientLoader", MB_ICONERROR);
return 0; return 0;
} }
if (GetFileAttributesA(ExeFile) == INVALID_FILE_ATTRIBUTES) { if (GetFileAttributesW(ExeFile) == INVALID_FILE_ATTRIBUTES) {
MessageBoxA(NULL, "Couldn't find the requested Exe file.", "ColdClientLoader", MB_ICONERROR); MessageBoxA(NULL, "Couldn't find the requested Exe file.", "ColdClientLoader", MB_ICONERROR);
return 0; return 0;
} }
CHAR CommandLine[8192]; WCHAR CommandLine[8192];
snprintf(CommandLine, sizeof(CommandLine), "\"%s\" %s", ExeFile, ExeCommandLine); _snwprintf(CommandLine, _countof(CommandLine), L"\"%ls\" %ls", ExeFile, ExeCommandLine);
if (!ExeFile[0] || !CreateProcessA(ExeFile, CommandLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ExeRunDir, &info, &processInfo)) if (!ExeFile[0] || !CreateProcessW(ExeFile, CommandLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ExeRunDir, &info, &processInfo))
{ {
MessageBoxA(NULL, "Unable to load the requested EXE file.", "ColdClientLoader", MB_ICONERROR); MessageBoxA(NULL, "Unable to load the requested EXE file.", "ColdClientLoader", MB_ICONERROR);
return 0; return 0;
@ -111,18 +114,18 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
bool orig_steam = false; bool orig_steam = false;
DWORD keyType = REG_SZ; DWORD keyType = REG_SZ;
CHAR OrgSteamCDir[MAX_PATH] = { 0 }; WCHAR OrgSteamCDir[MAX_PATH] = { 0 };
CHAR OrgSteamCDir64[MAX_PATH] = { 0 }; WCHAR OrgSteamCDir64[MAX_PATH] = { 0 };
DWORD Size1 = MAX_PATH; DWORD Size1 = MAX_PATH;
DWORD Size2 = MAX_PATH; DWORD Size2 = MAX_PATH;
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS) if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
{ {
orig_steam = true; orig_steam = true;
// Get original values to restore later. // Get original values to restore later.
RegQueryValueExA(Registrykey, "SteamClientDll", 0, &keyType, (LPBYTE)& OrgSteamCDir, &Size1); RegQueryValueExW(Registrykey, L"SteamClientDll", 0, &keyType, (LPBYTE)& OrgSteamCDir, &Size1);
RegQueryValueExA(Registrykey, "SteamClientDll64", 0, &keyType, (LPBYTE)& OrgSteamCDir64, &Size2); RegQueryValueExW(Registrykey, L"SteamClientDll64", 0, &keyType, (LPBYTE)& OrgSteamCDir64, &Size2);
} else { } else {
if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, 0, REG_OPTION_NON_VOLATILE, if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, 0, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &Registrykey, NULL) != ERROR_SUCCESS) KEY_ALL_ACCESS, NULL, &Registrykey, NULL) != ERROR_SUCCESS)
{ {
MessageBoxA(NULL, "Unable to patch Steam process informations on the Windows registry.", "ColdClientLoader", MB_ICONERROR); MessageBoxA(NULL, "Unable to patch Steam process informations on the Windows registry.", "ColdClientLoader", MB_ICONERROR);
@ -137,17 +140,17 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
{ {
// Before saving to the registry check again if the path was valid and if the file exist // Before saving to the registry check again if the path was valid and if the file exist
if (GetFileAttributesA(ClientPath) != INVALID_FILE_ATTRIBUTES) { if (GetFileAttributesW(ClientPath) != INVALID_FILE_ATTRIBUTES) {
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)lstrlenA(ClientPath) + 1); RegSetValueExW(Registrykey, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)(lstrlenW(ClientPath) * sizeof(WCHAR)) + 1);
} }
else { else {
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0); RegSetValueExW(Registrykey, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0);
} }
if (GetFileAttributesA(Client64Path) != INVALID_FILE_ATTRIBUTES) { if (GetFileAttributesW(Client64Path) != INVALID_FILE_ATTRIBUTES) {
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)lstrlenA(Client64Path) + 1); RegSetValueExW(Registrykey, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)(lstrlenW(Client64Path) * sizeof(WCHAR)) + 1);
} }
else { else {
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0); RegSetValueExW(Registrykey, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0);
} }
} }
RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1); RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1);
@ -161,11 +164,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
CloseHandle(processInfo.hThread); CloseHandle(processInfo.hThread);
if (orig_steam) { if (orig_steam) {
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS) if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
{ {
// Restore the values. // Restore the values.
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)OrgSteamCDir, (DWORD)lstrlenA(OrgSteamCDir) + 1); RegSetValueExW(Registrykey, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)OrgSteamCDir, Size1);
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)OrgSteamCDir64, (DWORD)lstrlenA(OrgSteamCDir64) + 1); RegSetValueExW(Registrykey, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)OrgSteamCDir64, Size2);
// Close the HKEY Handle. // Close the HKEY Handle.
RegCloseKey(Registrykey); RegCloseKey(Registrykey);