mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-06 13:47:48 +00:00
GEEKING
This commit is contained in:
@@ -0,0 +1,581 @@
|
||||
#include "StdAfx.h"
|
||||
#include "SharedHelpers.h"
|
||||
#include "format_string.h"
|
||||
#include "atlutil.h"
|
||||
#include <strstream>
|
||||
#include <vector>
|
||||
#include <shlguid.h>
|
||||
#include <shobjidl.h>
|
||||
#include "FileSystem.h"
|
||||
|
||||
void throwHRESULT(HRESULT hr, const char* message)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
throw std::runtime_error(format_string("%s: %S", message, (LPCTSTR)AtlGetErrorDescription(hr)));
|
||||
}
|
||||
|
||||
void throwHRESULT(HRESULT hr, const std::string& message)
|
||||
{
|
||||
throwHRESULT(hr, message.c_str());
|
||||
}
|
||||
|
||||
void throwLastError(BOOL result, const std::string& message)
|
||||
{
|
||||
if (!result)
|
||||
throwHRESULT(HRESULT_FROM_WIN32(GetLastError()), message.c_str());
|
||||
}
|
||||
|
||||
CString GetLastErrorDescription()
|
||||
{
|
||||
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
CString s = AtlGetErrorDescription(hr);
|
||||
if (s.Find(_T("HRESULT"))!=0)
|
||||
{
|
||||
CString str;
|
||||
str.Format(_T(" (HRESULT 0x%8.8x)"), hr);
|
||||
s += str;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string QueryStringValue(CRegKey& key, const TCHAR* name)
|
||||
{
|
||||
TCHAR value[64];
|
||||
ULONG length = 64;
|
||||
if (ERROR_SUCCESS == key.QueryStringValue(name, value, &length))
|
||||
return convert_w2s(value);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
CRegKey CreateKey(HKEY parent, const TCHAR* name, const TCHAR* defaultValue, bool is64bits)
|
||||
{
|
||||
//log << "CreateKey " << name << '\n'; log.flush();
|
||||
CRegKey key;
|
||||
REGSAM regSam = KEY_READ | KEY_WRITE;
|
||||
if (is64bits)
|
||||
regSam |= KEY_WOW64_64KEY;
|
||||
|
||||
throwHRESULT(key.Create(parent, name, REG_NONE, REG_OPTION_NON_VOLATILE, regSam), format_string("Failed to create key %S", name));
|
||||
if (defaultValue)
|
||||
{
|
||||
//log << format_string("set '%s' default value to '%s'\n", name, defaultValue); log.flush();
|
||||
throwHRESULT(key.SetStringValue(NULL, defaultValue), format_string("Failed to set default value for key %S to %S", name, defaultValue));
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
void DeleteKey(simple_logger<wchar_t> &logger, HKEY parent, const TCHAR* name)
|
||||
{
|
||||
if (!name)
|
||||
{
|
||||
throw std::runtime_error("Attempt to delete a null key");
|
||||
}
|
||||
|
||||
if (std::wstring(name).empty())
|
||||
{
|
||||
throw std::runtime_error("Attempt to delete an empty key");
|
||||
}
|
||||
|
||||
if (FAILED(::SHDeleteKey(parent, name)))
|
||||
{
|
||||
LLOG_ENTRY2(logger, "Failed to delete key %S %S", name, (LPCTSTR)GetLastErrorDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteSubKey(simple_logger<wchar_t> &logger, HKEY parent, const TCHAR* child, const TCHAR* key)
|
||||
{
|
||||
std::wstring s = key;
|
||||
if (s.empty())
|
||||
{
|
||||
throw std::runtime_error("DeleteSubkey empty");
|
||||
}
|
||||
|
||||
CRegKey k;
|
||||
if (!FAILED(k.Open(parent, child)))
|
||||
{
|
||||
LLOG_ENTRY2(logger, "Delete %S\\%S", child, key);
|
||||
DeleteKey(logger, k, key);
|
||||
}
|
||||
}
|
||||
|
||||
std::string exceptionToString(const _com_error& e, int stage)
|
||||
{
|
||||
CString desc = CString(e.Description().GetBSTR());
|
||||
CString errorMessage = CString(e.ErrorMessage());
|
||||
CString source = CString(e.Source().GetBSTR());
|
||||
std::ostrstream message;
|
||||
message << "_com_error stage=" << stage << " error=" << e.Error()
|
||||
<< " message='" << errorMessage.GetString() << "' desc='" << desc.GetString() << "'"
|
||||
<< " source='" << source.GetString() << "'";
|
||||
return message.str();
|
||||
}
|
||||
|
||||
std::string exceptionToString(const std::exception& e)
|
||||
{
|
||||
return e.what();
|
||||
}
|
||||
|
||||
void copyFile(simple_logger<wchar_t> &logger, const TCHAR* srcFile, const TCHAR* dstFile)
|
||||
{
|
||||
LOG_ENTRY2("Bootstrapper::copyFile src = %S, dst = %S", srcFile, dstFile);
|
||||
//log << "copyFile(\"" << srcFile << "\", \"" << dstFile << "\")\n"; log.flush();
|
||||
std::ifstream src(srcFile, std::ios::binary);
|
||||
std::ofstream dst(dstFile, std::ios::binary);
|
||||
|
||||
if(src.fail()){
|
||||
throw std::exception(format_string("Error opening srcFile='%S' for copy",srcFile).c_str());
|
||||
}
|
||||
if(dst.fail()){
|
||||
throw std::exception(format_string("Error opening dstFile='%S' for copy",dstFile).c_str());
|
||||
}
|
||||
|
||||
|
||||
src.seekg(0, std::ifstream::end);
|
||||
if((src.rdstate() & (std::ifstream::failbit | std::ifstream::badbit)) != 0){
|
||||
throw std::exception(format_string("Error with seekg to end on srcFile='%S' during copy",srcFile).c_str());
|
||||
}
|
||||
|
||||
|
||||
size_t size = src.tellg();
|
||||
if(size == -1){
|
||||
throw std::exception(format_string("Error with tellg on srcFile='%S' during copy",srcFile).c_str());
|
||||
}
|
||||
|
||||
src.seekg(0);
|
||||
if((src.rdstate() & (std::ifstream::failbit | std::ifstream::badbit)) != 0){
|
||||
throw std::exception(format_string("Error with seekg to beginning on srcFile='%S' during copy",srcFile).c_str());
|
||||
}
|
||||
|
||||
|
||||
//log << "new char [" << size << "]\n"; log.flush();
|
||||
// allocate memory for file content
|
||||
std::vector<char> buffer(size);
|
||||
|
||||
//log << "src.read\n"; log.flush();
|
||||
// read content of infile
|
||||
src.read(&buffer[0], size);
|
||||
|
||||
if(src.fail()){
|
||||
throw std::exception(format_string("Error reading srcFile='%S' during copy",srcFile).c_str());
|
||||
}
|
||||
|
||||
//log << "dst.write\n"; log.flush();
|
||||
// write to outfile
|
||||
dst.write(&buffer[0], size);
|
||||
|
||||
if(dst.fail()){
|
||||
throw std::exception(format_string("Error writing dstFile='%S' during copy",dstFile).c_str());
|
||||
}
|
||||
|
||||
src.close();
|
||||
if(src.fail()){
|
||||
throw std::exception(format_string("Error closing srcFile='%S' during copy",srcFile).c_str());
|
||||
}
|
||||
|
||||
dst.close();
|
||||
if(dst.fail()){
|
||||
throw std::exception(format_string("Error closing dstFile='%S' during copy",dstFile).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static std::wstring buildVersionKey(const TCHAR* componentCode)
|
||||
{
|
||||
return std::wstring(_T("cur")) + componentCode + std::wstring(_T("Ver"));
|
||||
}
|
||||
|
||||
static std::wstring buildUrlKey(const TCHAR* componentCode)
|
||||
{
|
||||
return std::wstring(_T("cur")) + componentCode + std::wstring(_T("Url"));
|
||||
}
|
||||
|
||||
void deleteCurVersionKeys(simple_logger<wchar_t> &logger, bool isPerUser, const TCHAR *component)
|
||||
{
|
||||
CRegKey key;
|
||||
LOG_ENTRY("deleteCurVersionKeys");
|
||||
if(!FAILED(key.Open(isPerUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, _T("Software\\watrbx Corporation\\watrbx"), KEY_WRITE)))
|
||||
{
|
||||
LOG_ENTRY("deleteCurVersionKeys - key Opened");
|
||||
key.DeleteValue(buildVersionKey(component).c_str());
|
||||
key.DeleteValue(buildUrlKey(component).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void setCurrentVersion(simple_logger<wchar_t> &logger, bool isPerUser, const TCHAR* componentCode, const TCHAR* version, const TCHAR* baseUrl)
|
||||
{
|
||||
CRegKey key;
|
||||
LOG_ENTRY3("setCurrentVersion - opening write registry key component=%S, version=%S, url=%S", componentCode, version, baseUrl);
|
||||
if (ERROR_SUCCESS == key.Create(isPerUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, _T("Software\\watrbx Corporation\\watrbx")))
|
||||
{
|
||||
std::wstring vKey = buildVersionKey(componentCode);
|
||||
std::wstring uKey = buildUrlKey(componentCode);
|
||||
|
||||
LOG_ENTRY3("Writing current version to registry for %S, version = %S, key = %S", componentCode, version, vKey.c_str());
|
||||
LONG result = key.SetStringValue(vKey.c_str(), version);
|
||||
LOG_ENTRY1("Succcess = %d", result == ERROR_SUCCESS);
|
||||
|
||||
LOG_ENTRY3("Writing current url to registry for %S, url = %S, key = %S", componentCode, baseUrl, uKey.c_str());
|
||||
result = key.SetStringValue(uKey.c_str(), baseUrl);
|
||||
LOG_ENTRY1("Succcess = %d", result == ERROR_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
void getCurrentVersion(simple_logger<wchar_t> &logger, bool isPerUser, const TCHAR* componentCode, TCHAR* version, int vBufSize, TCHAR* baseUrl, int uBaseSize)
|
||||
{
|
||||
CRegKey key;
|
||||
LOG_ENTRY1("getCurrentVersion - opening read registry key component=%S", componentCode);
|
||||
version[0] = 0;
|
||||
baseUrl[0] = 0;
|
||||
if (ERROR_SUCCESS == key.Open(isPerUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, _T("Software\\watrbx Corporation\\watrbx"), KEY_READ))
|
||||
{
|
||||
std::wstring vKey = buildVersionKey(componentCode);
|
||||
std::wstring uKey = buildUrlKey(componentCode);
|
||||
|
||||
LOG_ENTRY2("Reading current version from registry for %S, key = %S", componentCode, vKey.c_str());
|
||||
ULONG size = vBufSize;
|
||||
LONG result = key.QueryStringValue(vKey.c_str(), version, &size);
|
||||
LOG_ENTRY2("Success = %d, version = %S", result == ERROR_SUCCESS, version);
|
||||
|
||||
LOG_ENTRY2("Reading current url from registry for %S, key = %S", componentCode, uKey.c_str());
|
||||
size = uBaseSize;
|
||||
result = key.QueryStringValue(uKey.c_str(), baseUrl, &size );
|
||||
LOG_ENTRY2("Success = %d, url = %S", result == ERROR_SUCCESS, baseUrl);
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring getPlayerInstallKey()
|
||||
{
|
||||
return std::wstring(_T("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{373B1718-8CC5-4567-8EE2-9033AD08A680}"));
|
||||
}
|
||||
|
||||
std::wstring getStudioInstallKey()
|
||||
{
|
||||
return std::wstring(_T("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{B805FF17-92FE-4757-8142-F0A2850DFE03}"));
|
||||
}
|
||||
|
||||
std::wstring getQTStudioInstallKey()
|
||||
{
|
||||
return std::wstring(_T("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{2922D6F1-2865-4EFA-97A9-94EEAB3AFA14}"));
|
||||
}
|
||||
|
||||
std::wstring getPlayerCode()
|
||||
{
|
||||
return std::wstring(_T("Player"));
|
||||
}
|
||||
|
||||
std::wstring getStudioCode()
|
||||
{
|
||||
return std::wstring(_T("Studio"));
|
||||
}
|
||||
|
||||
std::wstring getQTStudioCode()
|
||||
{
|
||||
return std::wstring(_T("QTStudio"));
|
||||
}
|
||||
|
||||
void appendEnvironmentToProtocolScheme(std::wstring& scheme, const std::string baseUrl)
|
||||
{
|
||||
std::vector<std::string> baseHostUrlParts = splitOn(baseUrl, '.');
|
||||
if (baseHostUrlParts[1] != "watrbx")
|
||||
{
|
||||
scheme += convert_s2w("-" + baseHostUrlParts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring getPlayerProtocolScheme(const std::string& baseUrl)
|
||||
{
|
||||
std::wstring scheme = _T("watrbx-player");
|
||||
|
||||
appendEnvironmentToProtocolScheme(scheme, baseUrl);
|
||||
|
||||
return scheme;
|
||||
}
|
||||
|
||||
std::wstring getQTStudioProtocolScheme(const std::string& baseUrl)
|
||||
{
|
||||
std::wstring scheme = _T("watrbx-studio");
|
||||
|
||||
appendEnvironmentToProtocolScheme(scheme, baseUrl);
|
||||
|
||||
return scheme;
|
||||
}
|
||||
|
||||
std::wstring getStudioRegistrySubPath()
|
||||
{
|
||||
return _T("StudiowatrbxReg");
|
||||
}
|
||||
|
||||
std::wstring getStudioRegistryPath()
|
||||
{
|
||||
return _T("SOFTWARE\\") + getStudioRegistrySubPath();
|
||||
}
|
||||
|
||||
std::wstring getQTStudioRegistrySubPath()
|
||||
{
|
||||
return _T("StudioQTwatrbxReg");
|
||||
}
|
||||
|
||||
std::wstring getQTStudioRegistryPath()
|
||||
{
|
||||
return _T("SOFTWARE\\") + getQTStudioRegistrySubPath();
|
||||
}
|
||||
|
||||
static void createShortcut(const TCHAR *linkFileName, const TCHAR *exePath, const TCHAR *args)
|
||||
{
|
||||
CComPtr<IShellLink> psl;
|
||||
throwHRESULT(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl), "CLSID_ShellLink failed");
|
||||
|
||||
// Set the path to the shortcut target
|
||||
throwHRESULT(psl->SetPath(exePath), "psl->SetPath failed");
|
||||
|
||||
if (args)
|
||||
{
|
||||
throwHRESULT(psl->SetArguments(args), "psl->SetArguments failed");
|
||||
}
|
||||
|
||||
::DeleteFile(linkFileName);
|
||||
|
||||
// Query IShellLink for the IPersistFile interface for saving
|
||||
//the shortcut in persistent storage.
|
||||
CComPtr<IPersistFile> ppf;
|
||||
throwHRESULT(psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf)), "IID_IPersistFile failed");
|
||||
|
||||
// Save the link by calling IPersistFile::Save.
|
||||
throwHRESULT(ppf->Save(linkFileName, TRUE), "IPersistFile Save failed");
|
||||
}
|
||||
|
||||
void createRobloxShortcut(simple_logger<wchar_t> &logger, bool isPerUser, const TCHAR *linkFileName, const TCHAR *exePath, const TCHAR *args, bool desktop, bool forceCreate)
|
||||
{
|
||||
std::wstring shortcutsDirectory;
|
||||
if (!desktop)
|
||||
{
|
||||
shortcutsDirectory = FileSystem::getSpecialFolder(isPerUser ? FileSystem::RobloxUserPrograms : FileSystem::RobloxCommonPrograms, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
shortcutsDirectory = FileSystem::getSpecialFolder(FileSystem::Desktop, false, NULL, NULL);
|
||||
}
|
||||
|
||||
if (shortcutsDirectory.empty())
|
||||
{
|
||||
throw std::runtime_error("Failed to create Shortcuts folder");
|
||||
}
|
||||
|
||||
CString szFullLinkName;
|
||||
szFullLinkName.Format(_T("%s%s.lnk"), shortcutsDirectory.c_str(), linkFileName);
|
||||
|
||||
BOOL exists = FileSystem::IsFileExists(szFullLinkName);
|
||||
LOG_ENTRY2("shortcut status: '%S', exists = %d", (LPCTSTR)szFullLinkName, exists);
|
||||
|
||||
// if !exists mean that it is first install or user deleted shortcut, we want to update desktop shortcut only if it was there before us
|
||||
// or on first install
|
||||
if (forceCreate || exists)
|
||||
{
|
||||
LOG_ENTRY1("Creating shortcut: %S", (LPCTSTR)szFullLinkName);
|
||||
createShortcut(szFullLinkName, exePath, args);
|
||||
}
|
||||
}
|
||||
|
||||
// isPerUser: whether to install per user or global for machine (unused now?)
|
||||
// folder: where the shortcut files are located
|
||||
// exeName: name of executable to which shortcut points
|
||||
// exeFolderPath: path to exeName
|
||||
// baseFolderPath: path to unversioned programs
|
||||
void updateExistingRobloxShortcuts(
|
||||
simple_logger<wchar_t>& logger,
|
||||
bool isPerUser,
|
||||
const TCHAR* folder,
|
||||
const TCHAR* exeName,
|
||||
const TCHAR* exeFolderPath,
|
||||
const TCHAR* baseFolderPath )
|
||||
{
|
||||
LOG_ENTRY1("Searching for link files in : %S folder", folder);
|
||||
|
||||
std::wstring searchPattern(folder);
|
||||
searchPattern += _T("*.lnk");
|
||||
|
||||
WIN32_FIND_DATA findFileData;
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
handle = FindFirstFile(searchPattern.c_str(), &findFileData);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return; // unable to find this directory
|
||||
|
||||
std::wstring newLink = std::wstring(exeFolderPath) + std::wstring(exeName);
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
// skip folders
|
||||
if (findFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
|
||||
continue;
|
||||
|
||||
CComPtr<IShellLink> psl;
|
||||
throwHRESULT(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl), "CLSID_ShellLink failed");
|
||||
|
||||
CComPtr<IPersistFile> ppf;
|
||||
throwHRESULT(psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf)), "IID_IPersistFile failed");
|
||||
|
||||
std::wstring fullName(folder);
|
||||
fullName += findFileData.cFileName;
|
||||
|
||||
// Save the link by calling IPersistFile::Load.
|
||||
throwHRESULT(ppf->Load(fullName.c_str(), STGM_READWRITE), "IPersistFile Load failed");
|
||||
LOG_ENTRY1("Link found: %S", fullName.c_str());
|
||||
|
||||
TCHAR foundFilePath[MAX_PATH];
|
||||
throwHRESULT(psl->GetPath(foundFilePath, MAX_PATH, NULL, SLGP_RAWPATH), "psl->GetPath failed");
|
||||
|
||||
if (StrStr(foundFilePath, exeName))
|
||||
{
|
||||
// the executable we're looking for
|
||||
throwHRESULT(psl->SetPath(newLink.c_str()), "psl->SetPath failed");
|
||||
LOG_ENTRY2("Updating link: %S with path: %S", fullName.c_str(), newLink.c_str());
|
||||
throwHRESULT(ppf->Save(fullName.c_str(), TRUE), "IPersistFile Save failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
// even if we don't match, we might have to do some magic with old shortcuts that pointed to the player when
|
||||
// they wanted to launch studio (approx 04/2012 we only had one executable for player/studio)
|
||||
|
||||
bool isMFCStudio = (StrCmp(exeName, _T(STUDIOBOOTSTAPPERNAME)) == 0); // true if we're updating for MFC studio
|
||||
LOG_ENTRY1("updateExistingRobloxShortcuts isStudio = %d", isMFCStudio);
|
||||
|
||||
if (StrStr(foundFilePath, _T("Roblox.exe")))
|
||||
{
|
||||
// this shortcut points to the player
|
||||
TCHAR args[MAX_PATH];
|
||||
// detect if this shortcut is really a studio shortcut by looking at its arguments
|
||||
throwHRESULT(psl->GetArguments(args, MAX_PATH), "updateExistingRobloxShortcuts - GetArgument Failed");
|
||||
bool isIdeLink = (StrStr(args, _T("ide")) != 0);
|
||||
if (isIdeLink && isMFCStudio)
|
||||
{
|
||||
throwHRESULT(psl->SetPath(newLink.c_str()), "psl->SetPath failed");
|
||||
LOG_ENTRY2("Old studio link - updating link: %S with path: %S", fullName.c_str(), newLink.c_str());
|
||||
throwHRESULT(ppf->Save(fullName.c_str(), TRUE), "IPersistFile Save failed");
|
||||
}
|
||||
else if (!isIdeLink)
|
||||
{
|
||||
throwHRESULT(psl->SetPath(newLink.c_str()), "psl->SetPath failed");
|
||||
LOG_ENTRY2("Old player link - updating link: %S with path: %S", fullName.c_str(), newLink.c_str());
|
||||
throwHRESULT(ppf->Save(fullName.c_str(), TRUE), "IPersistFile Save failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// shortcut does not point to the player
|
||||
// rewrite studio shortcuts to point to the base folder instead of the versioned folder
|
||||
// in case the user pointed it directly to the exe instead of the bootstrapper
|
||||
std::vector<std::wstring> sbss;
|
||||
sbss.push_back(_T(STUDIOBOOTSTAPPERNAME));
|
||||
sbss.push_back(_T(STUDIOBOOTSTAPPERNAMEBETA));
|
||||
for (size_t i = 0;i < sbss.size();i ++)
|
||||
{
|
||||
if (StrStr(foundFilePath, sbss[i].c_str()))
|
||||
{
|
||||
LOG_ENTRY1("Studio bootstrapper found name = %S", sbss[i].c_str());
|
||||
std::wstring studioLink = std::wstring(baseFolderPath) + _T(STUDIOBOOTSTAPPERNAMEBETA); // All studios point to QT launcher
|
||||
throwHRESULT(psl->SetPath(studioLink.c_str()), "psl->SetPath failed");
|
||||
LOG_ENTRY2("Old studio link - updating link: %S with path: %S", fullName.c_str(), studioLink.c_str());
|
||||
throwHRESULT(ppf->Save(fullName.c_str(), TRUE), "IPersistFile Save failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (FindNextFile(handle, &findFileData));
|
||||
|
||||
FindClose(handle);
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
FindClose(handle);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring getDektopShortcutPath(simple_logger<wchar_t> &logger, const TCHAR *shortcutName)
|
||||
{
|
||||
std::wstring shortcutsDirectory = FileSystem::getSpecialFolder(FileSystem::Desktop, false, NULL, NULL);
|
||||
LOG_ENTRY1("hasDesktopShortcut - checking folder = %S", shortcutsDirectory.c_str());
|
||||
if (!shortcutsDirectory.empty())
|
||||
{
|
||||
CString szLinkName;
|
||||
szLinkName.Format(_T("%s%s.lnk"), shortcutsDirectory.c_str(), shortcutName);
|
||||
return std::wstring(szLinkName);
|
||||
}
|
||||
|
||||
return std::wstring(_T(""));
|
||||
}
|
||||
|
||||
bool hasDesktopShortcut(simple_logger<wchar_t> &logger, const TCHAR *shortcutName)
|
||||
{
|
||||
LOG_ENTRY1("hasDesktopShortcut - %S", shortcutName);
|
||||
std::wstring shortcut = getDektopShortcutPath(logger, shortcutName);
|
||||
LOG_ENTRY1("hasDesktopShortcut - is empty path = %S", shortcut.c_str());
|
||||
if (!shortcut.empty())
|
||||
{
|
||||
LOG_ENTRY1("hasDesktopShortcut - checking file = %S", shortcut.c_str());
|
||||
return FileSystem::IsFileExists(shortcut.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring getRobloxProgramsFolder(simple_logger<wchar_t> &logger, bool isPerUser)
|
||||
{
|
||||
return FileSystem::getSpecialFolder(isPerUser ? FileSystem::RobloxUserPrograms : FileSystem::RobloxCommonPrograms, false);
|
||||
}
|
||||
|
||||
bool hasProgramShortcut(simple_logger<wchar_t> &logger, bool isPerUser, const TCHAR *shortcutName)
|
||||
{
|
||||
LOG_ENTRY1("hasProgramShortcut - %S", shortcutName);
|
||||
|
||||
std::wstring shortcutsDirectory = getRobloxProgramsFolder(logger, isPerUser);
|
||||
if (!shortcutsDirectory.empty())
|
||||
{
|
||||
CString szLinkName;
|
||||
szLinkName.Format(_T("%s%s.lnk"), shortcutsDirectory.c_str(), shortcutName);
|
||||
|
||||
return FileSystem::IsFileExists(szLinkName);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool deleteDesktopShortcut(simple_logger<wchar_t> &logger, const TCHAR *shortcutName)
|
||||
{
|
||||
LOG_ENTRY1("deleteDesktopShortcut - %S", shortcutName);
|
||||
std::wstring shortcutsDirectory = FileSystem::getSpecialFolder(FileSystem::Desktop, false, NULL, NULL);
|
||||
if (!shortcutsDirectory.empty())
|
||||
{
|
||||
CString szLinkName;
|
||||
szLinkName.Format(_T("%s%s.lnk"), shortcutsDirectory.c_str(), shortcutName);
|
||||
|
||||
BOOL exists = FileSystem::IsFileExists(szLinkName);
|
||||
if (exists)
|
||||
{
|
||||
LOG_ENTRY1("deleteDesktopShortcut - %S", (LPCTSTR)szLinkName);
|
||||
return ::DeleteFile(szLinkName) == TRUE;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void deleteProgramsShortcut(simple_logger<wchar_t> &logger, bool isPerUser, const TCHAR *shortcutName)
|
||||
{
|
||||
LOG_ENTRY1("deleteProgramsShortcut - %S", shortcutName);
|
||||
|
||||
std::wstring shortcutsDirectory = FileSystem::getSpecialFolder(isPerUser ? FileSystem::RobloxUserPrograms : FileSystem::RobloxCommonPrograms, false);
|
||||
if (!shortcutsDirectory.empty())
|
||||
{
|
||||
CString szLinkName;
|
||||
szLinkName.Format(_T("%s%s.lnk"), shortcutsDirectory.c_str(), shortcutName);
|
||||
|
||||
BOOL exists = FileSystem::IsFileExists(szLinkName);
|
||||
if (exists)
|
||||
{
|
||||
LOG_ENTRY1("deleteProgramsShortcut - %S", (LPCTSTR)szLinkName);
|
||||
::DeleteFile(szLinkName);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user