- Naming style migrated to camel-case - P7lib logger sources added - Vcpkg manifest, CMake presets and build moved to root - SDL2, Vulkan and RmlUi dependencies added - Logger LOG macro added - Logger configuration - SDL2 window configuration - Vulkan configuration - RmlUi configuration - SDL event loop
619 lines
19 KiB
C++
619 lines
19 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// /
|
|
// 2012-2020 (c) Baical /
|
|
// /
|
|
// This library is free software; you can redistribute it and/or /
|
|
// modify it under the terms of the GNU Lesser General Public /
|
|
// License as published by the Free Software Foundation; either /
|
|
// version 3.0 of the License, or (at your option) any later version. /
|
|
// /
|
|
// This library is distributed in the hope that it will be useful, /
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
|
|
// Lesser General Public License for more details. /
|
|
// /
|
|
// You should have received a copy of the GNU Lesser General Public /
|
|
// License along with this library. /
|
|
// /
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#pragma once
|
|
|
|
#pragma warning(disable : 4091)
|
|
|
|
#include "Shlobj.h"
|
|
|
|
class CFSYS
|
|
{
|
|
public:
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Directory_Exists
|
|
static BOOL Directory_Exists(const wchar_t * i_pPath)
|
|
{
|
|
DWORD l_dwFile_Attr = 0;
|
|
BOOL l_bRes = FALSE;
|
|
|
|
if (NULL == i_pPath)
|
|
{
|
|
return l_bRes;
|
|
}
|
|
|
|
l_dwFile_Attr = GetFileAttributesW(i_pPath);
|
|
//check if that directory is exist ...
|
|
if ((FILE_ATTRIBUTE_DIRECTORY & l_dwFile_Attr) &&
|
|
( ((DWORD)-1) != l_dwFile_Attr)
|
|
)
|
|
{
|
|
l_bRes = TRUE;
|
|
}
|
|
|
|
return l_bRes;
|
|
}//Directory_Exists
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Directory_Create
|
|
static BOOL Directory_Create(const wchar_t *i_pDirectory)
|
|
{
|
|
if (NULL == i_pDirectory)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
wchar_t *l_pDirectory = _wcsdup(i_pDirectory);
|
|
tBOOL l_bReturn = FALSE;
|
|
|
|
if (NULL == l_pDirectory)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
size_t l_szLength = wcslen(l_pDirectory);
|
|
|
|
for (size_t l_dwI = 3; /*wcslen(L"C:\\")*/ l_dwI < l_szLength; l_dwI++)
|
|
{
|
|
if ( (L'\\' == l_pDirectory[l_dwI])
|
|
|| (L'/' == l_pDirectory[l_dwI])
|
|
)
|
|
{
|
|
l_pDirectory[l_dwI] = 0;
|
|
if (FALSE == Directory_Exists(l_pDirectory))
|
|
{
|
|
CreateDirectoryW(l_pDirectory, NULL);
|
|
}
|
|
|
|
l_pDirectory[l_dwI] = L'\\';
|
|
}
|
|
}
|
|
|
|
CreateDirectoryW(l_pDirectory, NULL);
|
|
l_bReturn = Directory_Exists(l_pDirectory);
|
|
|
|
free(l_pDirectory);
|
|
l_pDirectory = NULL;
|
|
|
|
return l_bReturn;
|
|
}//Directory_Create
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Directory_Delete
|
|
static BOOL Directory_Delete(const wchar_t *i_pDirectory)
|
|
{
|
|
if (NULL == i_pDirectory)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return RemoveDirectoryW(i_pDirectory);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//File_Exists
|
|
static BOOL File_Exists(const wchar_t * i_pFileName)
|
|
{
|
|
HANDLE l_hFind_Handle = NULL;
|
|
WIN32_FIND_DATAW l_tFind_Data;
|
|
BOOL l_bRes = FALSE;
|
|
|
|
if (NULL == i_pFileName)
|
|
{
|
|
return l_bRes;
|
|
}
|
|
|
|
memset(&l_tFind_Data, 0, sizeof(WIN32_FIND_DATAW));
|
|
|
|
l_hFind_Handle = FindFirstFileW(i_pFileName, &l_tFind_Data);
|
|
if (INVALID_HANDLE_VALUE != l_hFind_Handle)
|
|
{
|
|
l_bRes = (0 == (l_tFind_Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
|
|
FindClose(l_hFind_Handle);
|
|
l_hFind_Handle = NULL;
|
|
}
|
|
|
|
return l_bRes;
|
|
}//File_Exists
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// Enumerate_Files
|
|
static void Enumerate_Files(CBList<CWString*> *io_pFilesList,
|
|
CWString *i_pDirectory,
|
|
const wchar_t *i_pMask, //for example L"*.dll"
|
|
DWORD i_dwDepth = 0xFFFFFF
|
|
)
|
|
{
|
|
WIN32_FIND_DATAW l_sFind_Info = {0};
|
|
HANDLE l_hFind = INVALID_HANDLE_VALUE;
|
|
DWORD l_dwLength = i_pDirectory->Length();
|
|
CWString l_cSearch_Path;
|
|
|
|
|
|
//**************************************************************************
|
|
// Enumerate all files in current directory
|
|
l_cSearch_Path.Set(i_pDirectory->Get());
|
|
l_cSearch_Path.Append(2, L"\\", i_pMask);
|
|
|
|
l_hFind = FindFirstFileW(l_cSearch_Path.Get(), &l_sFind_Info);
|
|
|
|
while(INVALID_HANDLE_VALUE != l_hFind)
|
|
{
|
|
if (0 == (l_sFind_Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
CWString *l_pFile = new CWString();
|
|
if (l_pFile)
|
|
{
|
|
l_pFile->Set(i_pDirectory->Get());
|
|
l_pFile->Append(2, L"\\", l_sFind_Info.cFileName);
|
|
io_pFilesList->Add_After(io_pFilesList->Get_Last(), l_pFile);
|
|
}
|
|
}
|
|
|
|
if (! FindNextFileW(l_hFind, &l_sFind_Info))
|
|
{
|
|
FindClose(l_hFind);
|
|
l_hFind = INVALID_HANDLE_VALUE;
|
|
}
|
|
} //while(INVALID_HANDLE_VALUE != hFind)
|
|
|
|
|
|
//**************************************************************************
|
|
// Enumerate all sub directories in current directory ....
|
|
if (i_dwDepth)
|
|
{
|
|
l_cSearch_Path.Set(i_pDirectory->Get());
|
|
l_cSearch_Path.Append(1, L"\\*");
|
|
|
|
l_hFind = FindFirstFileW(l_cSearch_Path.Get(), &l_sFind_Info);
|
|
|
|
while(INVALID_HANDLE_VALUE != l_hFind)
|
|
{
|
|
if ( (0 != (l_sFind_Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
&& (0 != wcscmp(l_sFind_Info.cFileName, L"."))
|
|
&& (0 != wcscmp(l_sFind_Info.cFileName, L".."))
|
|
)
|
|
{
|
|
i_pDirectory->Append(2, L"\\", l_sFind_Info.cFileName);
|
|
Enumerate_Files(io_pFilesList, i_pDirectory, i_pMask, i_dwDepth - 1);
|
|
i_pDirectory->Trim(l_dwLength);
|
|
}
|
|
|
|
if (! FindNextFileW(l_hFind, &l_sFind_Info))
|
|
{
|
|
FindClose(l_hFind);
|
|
l_hFind = INVALID_HANDLE_VALUE;
|
|
}
|
|
} //while(INVALID_HANDLE_VALUE != hFind)
|
|
}
|
|
}// Enumerate_Files
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// Enumerate_Dirs
|
|
static void Enumerate_Dirs(CBList<CWString*> *io_pFilesList, const tXCHAR *i_pRoot)
|
|
{
|
|
WIN32_FIND_DATAW l_sFind_Info = {0};
|
|
HANDLE l_hFind = INVALID_HANDLE_VALUE;
|
|
|
|
if (!io_pFilesList)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( (i_pRoot)
|
|
&& (*i_pRoot)
|
|
)
|
|
{
|
|
CWString l_cSearch_Path;
|
|
|
|
|
|
//**************************************************************************
|
|
// Enumerate all files in current directory
|
|
l_cSearch_Path.Set(i_pRoot);
|
|
l_cSearch_Path.Append(1, L"\\*");
|
|
|
|
l_hFind = FindFirstFileW(l_cSearch_Path.Get(), &l_sFind_Info);
|
|
|
|
while(INVALID_HANDLE_VALUE != l_hFind)
|
|
{
|
|
if ( (0 != (l_sFind_Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
&& (0 != wcscmp(l_sFind_Info.cFileName, L"."))
|
|
&& (0 != wcscmp(l_sFind_Info.cFileName, L".."))
|
|
)
|
|
{
|
|
CWString *l_pFile = new CWString();
|
|
if (l_pFile)
|
|
{
|
|
l_pFile->Set(i_pRoot);
|
|
l_pFile->Append(2, L"\\", l_sFind_Info.cFileName);
|
|
io_pFilesList->Add_After(io_pFilesList->Get_Last(), l_pFile);
|
|
}
|
|
}
|
|
|
|
if (! FindNextFileW(l_hFind, &l_sFind_Info))
|
|
{
|
|
FindClose(l_hFind);
|
|
l_hFind = INVALID_HANDLE_VALUE;
|
|
}
|
|
} //while(INVALID_HANDLE_VALUE != hFind)
|
|
}
|
|
else
|
|
{
|
|
DWORD l_dwDrives = GetLogicalDrives();
|
|
DWORD l_dwBit = 0;
|
|
tXCHAR l_pDrive[4];
|
|
|
|
l_pDrive[0] = TM('A');
|
|
l_pDrive[1] = TM(':');
|
|
l_pDrive[2] = TM('\\');
|
|
l_pDrive[3] = 0;
|
|
|
|
while (l_dwDrives)
|
|
{
|
|
if (l_dwDrives & 1)
|
|
{
|
|
l_pDrive[0] = (tXCHAR)(l_dwBit + TM('A'));
|
|
|
|
UINT l_uiType = GetDriveTypeW(l_pDrive);
|
|
if ( (DRIVE_UNKNOWN != l_uiType)
|
|
&& (DRIVE_NO_ROOT_DIR != l_uiType)
|
|
)
|
|
{
|
|
CWString *l_pFile = new CWString();
|
|
if (l_pFile)
|
|
{
|
|
l_pFile->Set(l_pDrive);
|
|
io_pFilesList->Add_After(io_pFilesList->Get_Last(), l_pFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
l_dwDrives = l_dwDrives >> 1;
|
|
l_dwBit ++;
|
|
}
|
|
}
|
|
}// Enumerate_Dirs
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Get_Version
|
|
static UINT64 Get_Version(const wchar_t *i_pFile)
|
|
{
|
|
DWORD l_dwUnknown = 0;
|
|
DWORD l_dwFileInfoSize = 0;
|
|
UINT64 l_qwReturn = 0;
|
|
CWString l_cPath;
|
|
|
|
if (!i_pFile)
|
|
{
|
|
l_cPath.Realloc(4096);
|
|
if (GetModuleFileNameW(GetModuleHandleW(NULL),
|
|
l_cPath.Get(),
|
|
l_cPath.Max_Length()
|
|
)
|
|
)
|
|
{
|
|
i_pFile = l_cPath.Get();
|
|
}
|
|
else
|
|
{
|
|
return 0ull;
|
|
}
|
|
}
|
|
|
|
l_dwFileInfoSize = GetFileVersionInfoSizeW(i_pFile, &l_dwUnknown);
|
|
|
|
if (l_dwFileInfoSize)
|
|
{
|
|
BYTE * l_pFileInfo = new BYTE[l_dwFileInfoSize];
|
|
if (l_pFileInfo)
|
|
{
|
|
memset(l_pFileInfo, 0, l_dwFileInfoSize);
|
|
|
|
if (GetFileVersionInfoW(i_pFile, 0, l_dwFileInfoSize, l_pFileInfo) )
|
|
{
|
|
VS_FIXEDFILEINFO * l_tVersion = NULL;
|
|
UINT l_dwSize = 0;
|
|
if (VerQueryValueW(l_pFileInfo, L"\\", (LPVOID *)&l_tVersion, &l_dwSize))
|
|
{
|
|
l_qwReturn = (((UINT64)l_tVersion->dwProductVersionMS) << 32) +
|
|
l_tVersion->dwProductVersionLS;
|
|
}
|
|
}
|
|
|
|
if (l_pFileInfo)
|
|
{
|
|
delete [ ] l_pFileInfo;
|
|
l_pFileInfo = NULL;
|
|
}
|
|
} //if (l_pFileInfo)
|
|
} //if (l_dwFileInfoSize)
|
|
|
|
return l_qwReturn;
|
|
}//Get_Version
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Get_TextResource
|
|
static tBOOL Get_TextResource(const tXCHAR *i_pFile,
|
|
const tXCHAR *i_pName,
|
|
tXCHAR *o_pBuffer,
|
|
size_t i_szBuffer
|
|
)
|
|
{
|
|
tBOOL l_bReturn = FALSE;
|
|
tUINT32 l_dwUnknown = 0;
|
|
DWORD l_dwFileInfoSize = 0;
|
|
tUINT32 *l_pCodePage = NULL;
|
|
tUINT8 *l_pFileInfo = NULL;
|
|
tUINT32 l_dwSize = 0;
|
|
wchar_t *l_pValue = NULL;
|
|
const size_t l_szName = 256;
|
|
wchar_t l_pName[l_szName];
|
|
|
|
CWString l_cPath;
|
|
|
|
if ( (!i_pName)
|
|
|| (!o_pBuffer)
|
|
|| (32 > i_szBuffer)
|
|
|| ((l_szName / 2) < wcslen(i_pName))
|
|
)
|
|
{
|
|
goto l_lblExit;
|
|
}
|
|
|
|
if (!i_pFile)
|
|
{
|
|
l_cPath.Realloc(4096);
|
|
if (GetModuleFileNameW(GetModuleHandleW(NULL),
|
|
l_cPath.Get(),
|
|
l_cPath.Max_Length()
|
|
)
|
|
)
|
|
{
|
|
i_pFile = l_cPath.Get();
|
|
}
|
|
else
|
|
{
|
|
goto l_lblExit;
|
|
}
|
|
}
|
|
|
|
l_dwFileInfoSize = GetFileVersionInfoSizeW(i_pFile, (LPDWORD)&l_dwUnknown);
|
|
|
|
if (!l_dwFileInfoSize)
|
|
{
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_pFileInfo = (tUINT8*)malloc(l_dwFileInfoSize);
|
|
|
|
if (!l_pFileInfo)
|
|
{
|
|
goto l_lblExit;
|
|
}
|
|
|
|
memset(l_pFileInfo, 0, l_dwFileInfoSize);
|
|
|
|
if (!GetFileVersionInfoW(i_pFile, 0, l_dwFileInfoSize, l_pFileInfo) )
|
|
{
|
|
goto l_lblExit;
|
|
}
|
|
|
|
if (!VerQueryValueW(l_pFileInfo, L"\\VarFileInfo\\Translation", (LPVOID*) &l_pCodePage, &l_dwSize))
|
|
{
|
|
goto l_lblExit;
|
|
}
|
|
|
|
swprintf_s(l_pName, l_szName,
|
|
L"\\StringFileInfo\\%08x\\%s",
|
|
(tUINT32)((*l_pCodePage) << 16 | (*l_pCodePage) >> 16),
|
|
i_pName
|
|
);
|
|
|
|
if (!VerQueryValueW(l_pFileInfo, l_pName, (LPVOID *)&l_pValue, &l_dwSize))
|
|
{
|
|
goto l_lblExit;
|
|
}
|
|
|
|
|
|
wcsncpy_s(o_pBuffer, i_szBuffer, l_pValue, (l_dwSize > i_szBuffer) ? i_szBuffer : l_dwSize);
|
|
o_pBuffer[i_szBuffer-1] = 0;
|
|
l_bReturn = TRUE;
|
|
|
|
l_lblExit:
|
|
if (l_pFileInfo)
|
|
{
|
|
free(l_pFileInfo);
|
|
l_pFileInfo = NULL;
|
|
}
|
|
return l_bReturn;
|
|
}//Get_TextResource
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Get_Process_Directory
|
|
static BOOL Get_Process_Directory(CWString *o_pDirectory)
|
|
{
|
|
BOOL l_bReturn = FALSE;
|
|
DWORD l_dwLength = 4096;
|
|
|
|
if ( (NULL == o_pDirectory)
|
|
|| (FALSE == o_pDirectory->Realloc(l_dwLength))
|
|
)
|
|
{
|
|
return l_bReturn;
|
|
}
|
|
|
|
if (0 != GetModuleFileNameW(GetModuleHandleW(NULL),
|
|
o_pDirectory->Get(),
|
|
o_pDirectory->Max_Length())
|
|
)
|
|
{
|
|
wchar_t *l_pExe_Name = NULL;
|
|
|
|
if ( (l_pExe_Name = wcsrchr(o_pDirectory->Get(), L'\\'))
|
|
|| (l_pExe_Name = wcsrchr(o_pDirectory->Get(), L'/'))
|
|
)
|
|
{
|
|
o_pDirectory->Trim((DWORD)(l_pExe_Name - o_pDirectory->Get()));
|
|
l_bReturn = TRUE;
|
|
}
|
|
}
|
|
|
|
return l_bReturn;
|
|
}//Get_Process_Directory
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Get_Process_Path
|
|
static BOOL Get_Process_Path(CWString *o_pPath)
|
|
{
|
|
BOOL l_bReturn = FALSE;
|
|
DWORD l_dwLength = 4096;
|
|
|
|
if ( (NULL == o_pPath)
|
|
|| (FALSE == o_pPath->Realloc(l_dwLength))
|
|
)
|
|
{
|
|
return l_bReturn;
|
|
}
|
|
|
|
if (0 != GetModuleFileNameW(GetModuleHandleW(NULL),
|
|
o_pPath->Get(),
|
|
o_pPath->Max_Length())
|
|
)
|
|
{
|
|
l_bReturn = TRUE;
|
|
}
|
|
|
|
return l_bReturn;
|
|
}//Get_Process_Path
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Get_File_Size
|
|
static tUINT64 Get_File_Size(const wchar_t *i_pFile)
|
|
{
|
|
WIN32_FILE_ATTRIBUTE_DATA l_sFAD = {0};
|
|
LARGE_INTEGER l_sSize = {0};
|
|
|
|
if (!GetFileAttributesExW(i_pFile, GetFileExInfoStandard, &l_sFAD))
|
|
{
|
|
return 0; // error condition, could call GetLastError to find out more
|
|
}
|
|
|
|
l_sSize.HighPart = l_sFAD.nFileSizeHigh;
|
|
l_sSize.LowPart = l_sFAD.nFileSizeLow;
|
|
return l_sSize.QuadPart;
|
|
}//Get_File_Size
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Delete_File
|
|
static BOOL Delete_File(const wchar_t *i_pFile_Name)
|
|
{
|
|
if (NULL == i_pFile_Name)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD l_dwFAttr = GetFileAttributesW(i_pFile_Name);
|
|
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_ARCHIVE);
|
|
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_READONLY);
|
|
l_dwFAttr = l_dwFAttr & (~FILE_ATTRIBUTE_SYSTEM);
|
|
SetFileAttributesW(i_pFile_Name, l_dwFAttr);
|
|
return DeleteFileW(i_pFile_Name);
|
|
}//Delete_File
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//GetUserDirectory
|
|
static tBOOL GetUserDirectory(CWString *o_pPath)
|
|
{
|
|
if ( (NULL == o_pPath)
|
|
|| (FALSE == o_pPath->Realloc(4096))
|
|
)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if ( S_OK != SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, o_pPath->Get()))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//GetUserDirectory
|
|
static tBOOL GetDirectoryParent(CWString &i_rChild, CWString &o_rParent)
|
|
{
|
|
o_rParent.Set(i_rChild.Get());
|
|
size_t l_szDir = o_rParent.Length();
|
|
tXCHAR *l_pDir = o_rParent.Get();
|
|
|
|
//cut trailing '/' or '\'
|
|
while ( (l_szDir)
|
|
&& ( (TM('\\') == l_pDir[l_szDir - 1])
|
|
|| (TM('/') == l_pDir[l_szDir - 1])
|
|
)
|
|
)
|
|
{
|
|
l_pDir[--l_szDir] = 0;
|
|
}
|
|
|
|
tXCHAR *l_pTemp = wcsrchr(l_pDir, TM('\\'));
|
|
if (!l_pTemp)
|
|
{
|
|
l_pTemp = wcsrchr(l_pDir, TM('/'));
|
|
}
|
|
|
|
if (!l_pTemp)
|
|
{
|
|
o_rParent.Set(TM(""));
|
|
return TRUE;
|
|
}
|
|
|
|
*l_pTemp = 0;
|
|
l_pTemp--;
|
|
//removing duplicates of '\' '/'
|
|
while ( (TM('\\') == *l_pTemp)
|
|
|| (TM('/') == *l_pTemp)
|
|
)
|
|
{
|
|
*l_pTemp = 0;
|
|
l_pTemp--;
|
|
|
|
if (l_pDir > l_pTemp)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
};
|
|
|
|
|