You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
326 lines
9.1 KiB
C++
326 lines
9.1 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
#include "ProjectDefines.h"
|
|
|
|
#if defined(CRY_ENABLE_RC_HELPER)
|
|
|
|
#include "SettingsManagerHelpers.h"
|
|
#include "EngineSettingsManager.h"
|
|
|
|
#include <codecvt>
|
|
#include <locale>
|
|
#include <string>
|
|
|
|
#include <AzCore/std/string/string_view.h>
|
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
|
|
|
#if defined(AZ_PLATFORM_WINDOWS)
|
|
#include <windows.h>
|
|
#include <shellapi.h> //ShellExecuteW()
|
|
#pragma comment(lib, "Shell32.lib")
|
|
#endif
|
|
#if AZ_TRAIT_OS_PLATFORM_APPLE
|
|
#include "AppleSpecific.h"
|
|
#endif
|
|
|
|
bool SettingsManagerHelpers::Utf16ContainsAsciiOnly(const wchar_t* wstr)
|
|
{
|
|
while (*wstr)
|
|
{
|
|
if (*wstr > 127 || *wstr < 0)
|
|
{
|
|
return false;
|
|
}
|
|
++wstr;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
void SettingsManagerHelpers::ConvertUtf16ToUtf8(const wchar_t* src, CCharBuffer dst)
|
|
{
|
|
if (dst.getSizeInElements() <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (src[0] == 0)
|
|
{
|
|
dst[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
const std::codecvt<wchar_t, char, std::mbstate_t>& utf8Utf16Facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(std::locale());
|
|
std::mbstate_t mb{};
|
|
const wchar_t* from_next;
|
|
char* to_next;
|
|
std::codecvt_base::result result = utf8Utf16Facet.out(mb, src, src + wcslen(src), from_next, dst.getPtr(), dst.getPtr() + dst.getSizeInElements(), to_next);
|
|
if (result != std::codecvt_base::ok)
|
|
{
|
|
dst[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
to_next = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SettingsManagerHelpers::ConvertUtf8ToUtf16(const char* src, CWCharBuffer dst)
|
|
{
|
|
if (dst.getSizeInElements() <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (src[0] == 0)
|
|
{
|
|
dst[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
const std::codecvt<wchar_t, char, std::mbstate_t>& utf8Utf16Facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(std::locale());
|
|
std::mbstate_t mb{};
|
|
const char* from_next;
|
|
wchar_t* to_next;
|
|
std::codecvt_base::result result = utf8Utf16Facet.in(mb, src, src + strlen(src), from_next, dst.getPtr(), dst.getPtr() + dst.getSizeInElements(), to_next);
|
|
if (result != std::codecvt_base::ok)
|
|
{
|
|
dst[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
to_next = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SettingsManagerHelpers::GetAsciiFilename(const wchar_t* wfilename, CCharBuffer buffer)
|
|
{
|
|
if (buffer.getSizeInElements() <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (wfilename[0] == 0)
|
|
{
|
|
buffer[0] = 0;
|
|
return;
|
|
}
|
|
|
|
if (Utf16ContainsAsciiOnly(wfilename))
|
|
{
|
|
ConvertUtf16ToUtf8(wfilename, buffer);
|
|
return;
|
|
}
|
|
|
|
#if defined(AZ_PLATFORM_WINDOWS)
|
|
// The path is non-ASCII unicode, so let's resort to short filenames (they are always ASCII-only, I hope)
|
|
wchar_t shortW[MAX_PATH];
|
|
const int bufferCharCount = sizeof(shortW) / sizeof(shortW[0]);
|
|
const int charCount = GetShortPathNameW(wfilename, shortW, bufferCharCount);
|
|
if (charCount <= 0 || charCount >= bufferCharCount)
|
|
{
|
|
buffer[0] = 0;
|
|
return;
|
|
}
|
|
|
|
shortW[charCount] = 0;
|
|
if (!Utf16ContainsAsciiOnly(shortW))
|
|
{
|
|
buffer[0] = 0;
|
|
return;
|
|
}
|
|
|
|
ConvertUtf16ToUtf8(shortW, buffer);
|
|
#else
|
|
buffer[0] = 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CSettingsManagerTools::CSettingsManagerTools(const wchar_t* szModuleName)
|
|
{
|
|
m_pSettingsManager = new CEngineSettingsManager(szModuleName);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CSettingsManagerTools::~CSettingsManagerTools()
|
|
{
|
|
delete m_pSettingsManager;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CSettingsManagerTools::GetInstalledBuildPathUtf16(const int index, SettingsManagerHelpers::CWCharBuffer name, SettingsManagerHelpers::CWCharBuffer path)
|
|
{
|
|
return m_pSettingsManager->GetInstalledBuildRootPathUtf16(index, name, path);
|
|
}
|
|
|
|
|
|
bool CSettingsManagerTools::GetInstalledBuildPathAscii(const int index, SettingsManagerHelpers::CCharBuffer name, SettingsManagerHelpers::CCharBuffer path)
|
|
{
|
|
wchar_t wName[MAX_PATH];
|
|
wchar_t wPath[MAX_PATH];
|
|
if (GetInstalledBuildPathUtf16(index, SettingsManagerHelpers::CWCharBuffer(wName, sizeof(wName)), SettingsManagerHelpers::CWCharBuffer(wPath, sizeof(wPath))))
|
|
{
|
|
SettingsManagerHelpers::GetAsciiFilename(wName, name);
|
|
SettingsManagerHelpers::GetAsciiFilename(wPath, path);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
static bool FileExists(const wchar_t* filename)
|
|
{
|
|
#if defined(AZ_PLATFORM_WINDOWS)
|
|
const DWORD dwAttrib = GetFileAttributesW(filename);
|
|
return dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
|
|
#else
|
|
char utf8Filename[MAX_PATH];
|
|
SettingsManagerHelpers::ConvertUtf16ToUtf8(filename, SettingsManagerHelpers::CCharBuffer(utf8Filename, sizeof(utf8Filename)));
|
|
struct stat buffer;
|
|
return (stat(utf8Filename, &buffer) == 0);
|
|
#endif
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CSettingsManagerTools::GetEditorExecutable(SettingsManagerHelpers::CWCharBuffer wbuffer)
|
|
{
|
|
if (wbuffer.getSizeInElements() <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
AZStd::string_view exePath;
|
|
AZ::ComponentApplicationBus::BroadcastResult(exePath, &AZ::ComponentApplicationRequests::GetExecutableFolder);
|
|
|
|
SettingsManagerHelpers::CFixedString<wchar_t, 1024> editorExe;
|
|
editorExe = wbuffer.getPtr();
|
|
editorExe.appendAscii(exePath.data(), exePath.size());
|
|
|
|
if (editorExe.length() <= 0)
|
|
{
|
|
wbuffer[0] = 0;
|
|
return;
|
|
}
|
|
|
|
bool bFound = false;
|
|
if (Is64bitWindows())
|
|
{
|
|
const size_t len = editorExe.length();
|
|
editorExe.appendAscii("/Editor.exe");
|
|
bFound = FileExists(editorExe.c_str());
|
|
if (!bFound)
|
|
{
|
|
editorExe.setLength(len);
|
|
}
|
|
}
|
|
|
|
const size_t sizeToCopy = (editorExe.length() + 1) * sizeof(wbuffer[0]);
|
|
if (!bFound || sizeToCopy > wbuffer.getSizeInBytes())
|
|
{
|
|
wbuffer[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
memcpy(wbuffer.getPtr(), editorExe.c_str(), sizeToCopy);
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CSettingsManagerTools::CallEditor(void** pEditorWindow, [[maybe_unused]] void* hParent, const char* pWindowName, const char* pFlag)
|
|
{
|
|
#if !defined(AZ_PLATFORM_WINDOWS)
|
|
AZ_Assert(false, "CSettingsManagerTools::CallEditor is not supported on this platform!");
|
|
return false;
|
|
#else
|
|
HWND window = ::FindWindowA(NULL, pWindowName);
|
|
if (window)
|
|
{
|
|
*pEditorWindow = window;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
*pEditorWindow = 0;
|
|
|
|
wchar_t buffer[512] = { L'\0' };
|
|
GetEditorExecutable(SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer)));
|
|
|
|
SettingsManagerHelpers::CFixedString<wchar_t, 256> wFlags;
|
|
SettingsManagerHelpers::ConvertUtf8ToUtf16(pFlag, wFlags.getBuffer());
|
|
wFlags.setLength(wcslen(wFlags.c_str()));
|
|
|
|
if (buffer[0] != '\0')
|
|
{
|
|
INT_PTR hIns = (INT_PTR)ShellExecuteW(NULL, L"open", buffer, wFlags.c_str(), NULL, SW_SHOWNORMAL);
|
|
if (hIns > 32)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
MessageBoxA(0, "Editor.exe was not found.\n\nPlease verify CryENGINE root path.", "Error", MB_ICONERROR | MB_OK);
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Modified version of
|
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684139(v=vs.85).aspx
|
|
bool CSettingsManagerTools::Is64bitWindows()
|
|
{
|
|
#if defined(_WIN64)
|
|
// 64-bit programs run only on 64-bit Windows
|
|
return true;
|
|
#elif !defined(AZ_PLATFORM_WINDOWS)
|
|
return false;
|
|
#else
|
|
// 32-bit programs run on both 32-bit and 64-bit Windows
|
|
static bool bWin64 = false;
|
|
static bool bOnce = true;
|
|
if (bOnce)
|
|
{
|
|
typedef BOOL (WINAPI * LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
|
|
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process");
|
|
if (fnIsWow64Process != NULL)
|
|
{
|
|
BOOL itIsWow64Process = FALSE;
|
|
if (fnIsWow64Process(GetCurrentProcess(), &itIsWow64Process))
|
|
{
|
|
bWin64 = (itIsWow64Process == TRUE);
|
|
}
|
|
}
|
|
bOnce = false;
|
|
}
|
|
return bWin64;
|
|
#endif
|
|
}
|
|
|
|
#endif // #if defined(CRY_ENABLE_RC_HELPER)
|
|
|
|
// eof
|