- 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
608 lines
16 KiB
C++
608 lines
16 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
|
|
|
|
#define SHARED_SEM_NULL NULL
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//CShared
|
|
class CShared
|
|
{
|
|
struct sShared
|
|
{
|
|
HANDLE hMemory;
|
|
HANDLE hMutex;
|
|
tXCHAR *pName;
|
|
};
|
|
|
|
enum eType
|
|
{
|
|
ETYPE_MUTEX = 0,
|
|
ETYPE_FILE ,
|
|
ETYPE_MAX
|
|
};
|
|
|
|
public:
|
|
typedef sShared *hShared;
|
|
typedef HANDLE hSem;
|
|
|
|
enum eLock
|
|
{
|
|
E_OK,
|
|
E_TIMEOUT,
|
|
E_ERROR,
|
|
E_NOT_EXISTS
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//CShared::Create
|
|
static tBOOL Create(CShared::hShared *o_pHandle,
|
|
const tXCHAR *i_pName,
|
|
const tUINT8 *i_pData,
|
|
tUINT16 i_wSize
|
|
)
|
|
{
|
|
sShared *l_pShared = NULL;
|
|
tBOOL l_bReturn = TRUE;
|
|
DWORD l_dwLen = 0;
|
|
wchar_t *l_pName = NULL;
|
|
BOOL l_bRelease = FALSE;
|
|
tUINT8 *l_pBuffer = NULL;
|
|
|
|
|
|
if ( (NULL == i_pName)
|
|
|| (NULL == i_pData)
|
|
|| (0 >= i_wSize)
|
|
|| (NULL == o_pHandle)
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_pShared = new sShared;
|
|
if (NULL == l_pShared)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
memset(l_pShared, 0, sizeof(sShared));
|
|
|
|
l_dwLen = (DWORD)wcslen(i_pName) + 128;
|
|
l_pName = (wchar_t*)malloc(sizeof(wchar_t) * l_dwLen);
|
|
l_pShared->pName = PStrDub(i_pName);
|
|
|
|
if ( (NULL == l_pName)
|
|
|| (NULL == l_pShared->pName)
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//create mutex and own it
|
|
Create_Name(l_pName, l_dwLen, ETYPE_MUTEX, i_pName);
|
|
|
|
l_pShared->hMutex = CreateMutexW(NULL, TRUE, l_pName);
|
|
if ( (NULL == l_pShared->hMutex)
|
|
|| (ERROR_ALREADY_EXISTS == GetLastError())
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_bRelease = TRUE;
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//create shared memory object
|
|
Create_Name(l_pName, l_dwLen, ETYPE_FILE, i_pName);
|
|
|
|
l_pShared->hMemory = CreateFileMappingW(INVALID_HANDLE_VALUE, // use paging file
|
|
NULL, // default security
|
|
PAGE_READWRITE, // read/write access
|
|
0, // maximum object size (high-order tUINT32)
|
|
i_wSize, // maximum object size (low-order tUINT32)
|
|
l_pName // name of mapping object
|
|
);
|
|
|
|
if ( (NULL == l_pShared->hMemory)
|
|
|| (ERROR_ALREADY_EXISTS == GetLastError())
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_pBuffer = (tUINT8*)MapViewOfFile(l_pShared->hMemory,
|
|
FILE_MAP_ALL_ACCESS,
|
|
0,
|
|
0,
|
|
i_wSize
|
|
);
|
|
|
|
if (NULL == l_pBuffer)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
*o_pHandle = (CShared::hShared)l_pShared;
|
|
|
|
__try
|
|
{
|
|
memcpy(l_pBuffer, i_pData, i_wSize);
|
|
}
|
|
|
|
__except ( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR
|
|
? EXCEPTION_EXECUTE_HANDLER
|
|
: EXCEPTION_CONTINUE_SEARCH
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_lblExit:
|
|
if (l_pName)
|
|
{
|
|
free(l_pName);
|
|
l_pName = NULL;
|
|
}
|
|
|
|
if (l_pBuffer)
|
|
{
|
|
UnmapViewOfFile(l_pBuffer);
|
|
l_pBuffer = NULL;
|
|
}
|
|
|
|
if (l_bRelease)
|
|
{
|
|
ReleaseMutex(l_pShared->hMutex);
|
|
}
|
|
|
|
if (FALSE == l_bReturn)
|
|
{
|
|
Close((hShared)l_pShared);
|
|
l_pShared = NULL;
|
|
|
|
if (o_pHandle)
|
|
{
|
|
*o_pHandle = NULL;
|
|
}
|
|
}
|
|
|
|
return l_bReturn;
|
|
}//Shared_Create
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Read
|
|
static tBOOL Read(const tXCHAR *i_pName,
|
|
tUINT8 *o_pData,
|
|
tUINT16 i_wSize
|
|
)
|
|
{
|
|
HANDLE l_hMemory = NULL;
|
|
tBOOL l_bReturn = TRUE;
|
|
DWORD l_dwLen = 0;
|
|
wchar_t *l_pName = NULL;
|
|
tUINT8 *l_pBuffer = NULL;
|
|
|
|
if ( (NULL == i_pName)
|
|
|| (NULL == o_pData)
|
|
|| (0 >= i_wSize)
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_dwLen = (DWORD)wcslen(i_pName) + 128;
|
|
l_pName = (wchar_t*)malloc(sizeof(wchar_t) * l_dwLen);
|
|
|
|
if (NULL == l_pName)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//open shared memory object
|
|
Create_Name(l_pName, l_dwLen, ETYPE_FILE, i_pName);
|
|
|
|
l_hMemory = OpenFileMappingW(FILE_MAP_ALL_ACCESS, // read/write access
|
|
FALSE, // do not inherit the name
|
|
l_pName // name of mapping object
|
|
);
|
|
|
|
if (NULL == l_hMemory)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_pBuffer = (tUINT8*)MapViewOfFile(l_hMemory,
|
|
FILE_MAP_READ,
|
|
0,
|
|
0,
|
|
i_wSize
|
|
);
|
|
|
|
if (NULL == l_pBuffer)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
__try
|
|
{
|
|
memcpy(o_pData, l_pBuffer, i_wSize);
|
|
}
|
|
|
|
__except ( (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR)
|
|
? EXCEPTION_EXECUTE_HANDLER
|
|
: EXCEPTION_CONTINUE_SEARCH
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_lblExit:
|
|
if (l_pName)
|
|
{
|
|
free(l_pName);
|
|
l_pName = NULL;
|
|
}
|
|
|
|
if (l_pBuffer)
|
|
{
|
|
UnmapViewOfFile(l_pBuffer);
|
|
l_pBuffer = NULL;
|
|
}
|
|
|
|
if (l_hMemory)
|
|
{
|
|
CloseHandle(l_hMemory);
|
|
l_hMemory = NULL;
|
|
}
|
|
|
|
return l_bReturn;
|
|
}//Read
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Write
|
|
static tBOOL Write(const tXCHAR *i_pName,
|
|
const tUINT8 *i_pData,
|
|
tUINT16 i_wSize
|
|
)
|
|
{
|
|
HANDLE l_hMemory = NULL;
|
|
tBOOL l_bReturn = TRUE;
|
|
DWORD l_dwLen = 0;
|
|
wchar_t *l_pName = NULL;
|
|
tUINT8 *l_pBuffer = NULL;
|
|
|
|
if ( (NULL == i_pName)
|
|
|| (NULL == i_pData)
|
|
|| (0 >= i_wSize)
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_dwLen = (DWORD)wcslen(i_pName) + 128;
|
|
l_pName = (wchar_t*)malloc(sizeof(wchar_t) * l_dwLen);
|
|
|
|
if (NULL == l_pName)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//open shared memory object
|
|
Create_Name(l_pName, l_dwLen, ETYPE_FILE, i_pName);
|
|
|
|
l_hMemory = OpenFileMappingW(FILE_MAP_ALL_ACCESS, // read/write access
|
|
FALSE, // do not inherit the name
|
|
l_pName // name of mapping object
|
|
);
|
|
|
|
if (NULL == l_hMemory)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_pBuffer = (tUINT8*)MapViewOfFile(l_hMemory,
|
|
FILE_MAP_WRITE,
|
|
0,
|
|
0,
|
|
i_wSize
|
|
);
|
|
|
|
if (NULL == l_pBuffer)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
__try
|
|
{
|
|
memcpy(l_pBuffer, i_pData, i_wSize);
|
|
}
|
|
|
|
__except ( (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR)
|
|
? EXCEPTION_EXECUTE_HANDLER
|
|
: EXCEPTION_CONTINUE_SEARCH
|
|
)
|
|
{
|
|
l_bReturn = FALSE;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_lblExit:
|
|
if (l_pName)
|
|
{
|
|
free(l_pName);
|
|
l_pName = NULL;
|
|
}
|
|
|
|
if (l_pBuffer)
|
|
{
|
|
UnmapViewOfFile(l_pBuffer);
|
|
l_pBuffer = NULL;
|
|
}
|
|
|
|
if (l_hMemory)
|
|
{
|
|
CloseHandle(l_hMemory);
|
|
l_hMemory = NULL;
|
|
}
|
|
|
|
return l_bReturn;
|
|
}//Write
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Lock
|
|
static eLock Lock(const tXCHAR *i_pName, CShared::hSem &o_rSem, tUINT32 i_dwTimeout_ms)
|
|
{
|
|
HANDLE l_hMutex = NULL;
|
|
eLock l_eReturn = CShared::E_OK;
|
|
DWORD l_dwLen = 0;
|
|
wchar_t *l_pName = NULL;
|
|
|
|
o_rSem = SHARED_SEM_NULL;
|
|
|
|
if (NULL == i_pName)
|
|
{
|
|
l_eReturn = CShared::E_ERROR;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_dwLen = (DWORD)wcslen(i_pName) + 128;
|
|
l_pName = (wchar_t*)malloc(sizeof(wchar_t) * l_dwLen);
|
|
|
|
if (NULL == l_pName)
|
|
{
|
|
l_eReturn = CShared::E_ERROR;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//open mutex and own it
|
|
Create_Name(l_pName, l_dwLen, ETYPE_MUTEX, i_pName);
|
|
|
|
l_hMutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, l_pName);
|
|
if (NULL == l_hMutex)
|
|
{
|
|
l_eReturn = CShared::E_NOT_EXISTS;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
if (WAIT_OBJECT_0 != WaitForSingleObject(l_hMutex, i_dwTimeout_ms))
|
|
{
|
|
l_eReturn = CShared::E_TIMEOUT;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
l_lblExit:
|
|
if (l_pName)
|
|
{
|
|
free(l_pName);
|
|
l_pName = NULL;
|
|
}
|
|
|
|
if (SHARED_SEM_NULL != l_hMutex)
|
|
{
|
|
if (CShared::E_OK == l_eReturn)
|
|
{
|
|
o_rSem = l_hMutex;
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(l_hMutex);
|
|
l_hMutex = SHARED_SEM_NULL;
|
|
}
|
|
}
|
|
|
|
return l_eReturn;
|
|
}//Lock
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//UnLock
|
|
static eLock UnLock(CShared::hSem &io_rSem)
|
|
{
|
|
HANDLE l_hMutex = NULL;
|
|
eLock l_eReturn = CShared::E_ERROR;
|
|
|
|
if (SHARED_SEM_NULL == io_rSem)
|
|
{
|
|
l_eReturn = CShared::E_NOT_EXISTS;
|
|
goto l_lblExit;
|
|
}
|
|
|
|
ReleaseMutex(io_rSem);
|
|
|
|
l_lblExit:
|
|
if (io_rSem)
|
|
{
|
|
CloseHandle(io_rSem);
|
|
io_rSem = SHARED_SEM_NULL;
|
|
}
|
|
|
|
return l_eReturn;
|
|
}//UnLock
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//GetSemName
|
|
static const tXCHAR* GetName(hShared i_pShared)
|
|
{
|
|
if (NULL == i_pShared)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return i_pShared->pName;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Close
|
|
static tBOOL Close(hShared i_hShared)
|
|
{
|
|
if (NULL == i_hShared)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//if (i_hShared->hMutex)
|
|
//{
|
|
// WaitForSingleObject(i_hShared->hMutex, 3000);
|
|
//}
|
|
|
|
if (i_hShared->hMemory)
|
|
{
|
|
CloseHandle(i_hShared->hMemory);
|
|
i_hShared->hMemory = NULL;
|
|
}
|
|
|
|
if (i_hShared->hMutex)
|
|
{
|
|
CloseHandle(i_hShared->hMutex);
|
|
i_hShared->hMutex = NULL;
|
|
}
|
|
|
|
if (i_hShared->pName)
|
|
{
|
|
PStrFreeDub(i_hShared->pName);
|
|
i_hShared->pName = NULL;
|
|
}
|
|
|
|
delete i_hShared;
|
|
|
|
return TRUE;
|
|
}//Shared_Close
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//UnLink - linux required it due to fact that life time of shared object is
|
|
//almost infinit, and cleanup should be done manually
|
|
static tBOOL UnLink(const tXCHAR *i_pName)
|
|
{
|
|
UNUSED_ARG(i_pName);
|
|
return TRUE;
|
|
}//UnLink
|
|
|
|
|
|
private:
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//Create_Name
|
|
static tBOOL Create_Name(tXCHAR *o_pName,
|
|
size_t i_szName,
|
|
eType i_eType,
|
|
const tXCHAR *i_pPostfix
|
|
)
|
|
{
|
|
if ( (NULL == o_pName)
|
|
|| (16 >= i_szName)
|
|
|| (ETYPE_MAX <= i_eType)
|
|
|| (NULL == i_pPostfix)
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
FILETIME l_tProcess_Time = {0};
|
|
FILETIME l_tStub_01 = {0};
|
|
FILETIME l_tStub_02 = {0};
|
|
FILETIME l_tStub_03 = {0};
|
|
|
|
GetProcessTimes(GetCurrentProcess(),
|
|
&l_tProcess_Time,
|
|
&l_tStub_01,
|
|
&l_tStub_02,
|
|
&l_tStub_03
|
|
);
|
|
|
|
if (ETYPE_MUTEX == i_eType)
|
|
{
|
|
swprintf_s(o_pName,
|
|
i_szName,
|
|
L"Local\\m%d%d%d%s",
|
|
GetCurrentProcessId(),
|
|
l_tProcess_Time.dwHighDateTime,
|
|
l_tProcess_Time.dwLowDateTime,
|
|
i_pPostfix
|
|
);
|
|
}
|
|
else if (ETYPE_FILE == i_eType)
|
|
{
|
|
swprintf_s(o_pName,
|
|
i_szName,
|
|
L"Local\\f%d%d%d%s",
|
|
GetCurrentProcessId(),
|
|
l_tProcess_Time.dwHighDateTime,
|
|
l_tProcess_Time.dwLowDateTime,
|
|
i_pPostfix
|
|
);
|
|
}
|
|
|
|
return TRUE;
|
|
}//Create_Name
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|