593 lines
11 KiB
C
593 lines
11 KiB
C
|
#include "std.h"
|
||
|
|
||
|
|
||
|
|
||
|
// {6249D949-5263-4d6a-883C-78EFAF85D5E3}
|
||
|
static const GUID g_lhcHandleGUID =
|
||
|
{
|
||
|
// This guid will be used to identify LCHHANDLE structures to
|
||
|
// help prevent accessing invalid items
|
||
|
0x6249d949, 0x5263, 0x4d6a,
|
||
|
{
|
||
|
0x88, 0x3c, 0x78, 0xef, 0xaf, 0x85, 0xd5, 0xe3
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// {40A71300-B2C7-4d4f-808F-52643110B329}
|
||
|
static const GUID g_lhcLibraryGUID =
|
||
|
{
|
||
|
// This guid will be used to identify LIBRARY_NODE structures to
|
||
|
// help prevent accessing invalid items
|
||
|
0x40a71300, 0xb2c7, 0x4d4f,
|
||
|
{
|
||
|
0x80, 0x8f, 0x52, 0x64, 0x31, 0x10, 0xb3, 0x29
|
||
|
}
|
||
|
};
|
||
|
|
||
|
PLIBRARY_NODE g_pLibraryList = NULL;
|
||
|
PLHCSTRUCT g_pObjectList = NULL;
|
||
|
CRITICAL_SECTION g_csTableControl;
|
||
|
|
||
|
|
||
|
BOOL lhcpIsValidHandle(PLHCSTRUCT pObject);
|
||
|
PLIBRARY_NODE lhcpNewLibraryNode();
|
||
|
void lhcpFreeLibraryNode(PLIBRARY_NODE pNode);
|
||
|
PLHCSTRUCT lhcpNewObjectHandle();
|
||
|
void lhcpFreeObjectHandle(PLHCSTRUCT pNode);
|
||
|
BOOL lhcpIsValidHandle(PLHCSTRUCT pObject);
|
||
|
PWSTR lhcpGetExeDirectory();
|
||
|
PLHCSTRUCT lhcpCreateHandle(
|
||
|
PLIBRARY_DESCRIPTOR pLibrary,
|
||
|
PLHCOBJECT_DESCRIPTOR pObject);
|
||
|
void lhcpDestroyHandle(PLHCSTRUCT pNode);
|
||
|
|
||
|
|
||
|
BOOL lhcpIsValidHandle(PLHCSTRUCT pObject)
|
||
|
{
|
||
|
BOOL bResult;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
bResult = IsEqualGUID(
|
||
|
&g_lhcHandleGUID,
|
||
|
&pObject->m_Secret);
|
||
|
}
|
||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
SetLastError(
|
||
|
ERROR_INVALID_HANDLE);
|
||
|
bResult = FALSE;
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
Done:
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
PLIBRARY_NODE lhcpNewLibraryNode()
|
||
|
{
|
||
|
//
|
||
|
// Create the new node, zero out the memory and copy in the secret
|
||
|
//
|
||
|
PLIBRARY_NODE pNode = malloc(
|
||
|
sizeof(LIBRARY_NODE));
|
||
|
|
||
|
if (pNode!=NULL)
|
||
|
{
|
||
|
ZeroMemory(
|
||
|
pNode,
|
||
|
sizeof(LIBRARY_NODE));
|
||
|
CopyMemory(
|
||
|
&pNode->m_Secret,
|
||
|
&g_lhcLibraryGUID,
|
||
|
sizeof(GUID));
|
||
|
}
|
||
|
|
||
|
return pNode;
|
||
|
}
|
||
|
|
||
|
|
||
|
void lhcpFreeLibraryNode(PLIBRARY_NODE pNode)
|
||
|
{
|
||
|
ZeroMemory(
|
||
|
pNode,
|
||
|
sizeof(LIBRARY_NODE));
|
||
|
free(
|
||
|
pNode);
|
||
|
}
|
||
|
|
||
|
|
||
|
PLHCSTRUCT lhcpNewObjectHandle()
|
||
|
{
|
||
|
//
|
||
|
// Create the new node, zero out the memory and copy in the secret
|
||
|
//
|
||
|
|
||
|
PLHCSTRUCT pNode = malloc(
|
||
|
sizeof(LHCSTRUCT));
|
||
|
|
||
|
if (pNode!=NULL)
|
||
|
{
|
||
|
ZeroMemory(
|
||
|
pNode,
|
||
|
sizeof(LHCSTRUCT));
|
||
|
CopyMemory(
|
||
|
&pNode->m_Secret,
|
||
|
&g_lhcHandleGUID,
|
||
|
sizeof(GUID));
|
||
|
}
|
||
|
|
||
|
return pNode;
|
||
|
}
|
||
|
|
||
|
|
||
|
void lhcpFreeObjectHandle(PLHCSTRUCT pNode)
|
||
|
{
|
||
|
ZeroMemory(
|
||
|
pNode,
|
||
|
sizeof(LHCSTRUCT));
|
||
|
free(
|
||
|
pNode);
|
||
|
}
|
||
|
|
||
|
|
||
|
PWSTR lhcpGetExeDirectory()
|
||
|
{
|
||
|
DWORD dwSize = 64;
|
||
|
PWSTR pszBuffer = NULL;
|
||
|
PWSTR pszReturn;
|
||
|
DWORD dwResult;
|
||
|
BOOL bResult;
|
||
|
PWSTR pszLastBackslash;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
pszBuffer = malloc(
|
||
|
dwSize * sizeof(WCHAR));
|
||
|
|
||
|
if (NULL==pszBuffer)
|
||
|
{
|
||
|
SetLastError(
|
||
|
ERROR_NOT_ENOUGH_MEMORY);
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
dwResult = GetModuleFileNameW(
|
||
|
NULL,
|
||
|
pszBuffer,
|
||
|
dwSize);
|
||
|
|
||
|
if (0==dwResult)
|
||
|
{
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
if (dwSize==dwResult) // INSUFFICIENT_BUFFER
|
||
|
{
|
||
|
dwSize *= 2; // Double the buffer length
|
||
|
free(
|
||
|
pszBuffer);
|
||
|
pszBuffer = NULL;
|
||
|
dwResult = 0;
|
||
|
}
|
||
|
} while (0==dwResult && dwSize<=65536);
|
||
|
|
||
|
if (dwSize>65536)
|
||
|
{
|
||
|
SetLastError(
|
||
|
ERROR_INSUFFICIENT_BUFFER);
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
pszLastBackslash = wcsrchr(
|
||
|
pszBuffer,
|
||
|
L'\\');
|
||
|
|
||
|
if (NULL==pszLastBackslash)
|
||
|
{
|
||
|
SetLastError(
|
||
|
ERROR_GEN_FAILURE);
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
pszLastBackslash++;
|
||
|
*pszLastBackslash = L'\0';
|
||
|
|
||
|
pszReturn = malloc(
|
||
|
(wcslen(pszBuffer)+MAX_PATH+1)*sizeof(WCHAR));
|
||
|
|
||
|
if (NULL==pszReturn)
|
||
|
{
|
||
|
SetLastError(
|
||
|
ERROR_NOT_ENOUGH_MEMORY);
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
wcscpy(
|
||
|
pszReturn,
|
||
|
pszBuffer);
|
||
|
|
||
|
free(
|
||
|
pszBuffer);
|
||
|
|
||
|
return pszReturn;
|
||
|
|
||
|
Error:
|
||
|
if (pszBuffer!=NULL)
|
||
|
{
|
||
|
free(
|
||
|
pszBuffer);
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
PLHCSTRUCT lhcpCreateHandle(
|
||
|
PLIBRARY_DESCRIPTOR pLibrary,
|
||
|
PLHCOBJECT_DESCRIPTOR pObject)
|
||
|
{
|
||
|
PLHCSTRUCT pNode = lhcpNewObjectHandle();
|
||
|
|
||
|
if (pNode!=NULL)
|
||
|
{
|
||
|
EnterCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
pNode->m_pObject = pObject;
|
||
|
pNode->m_pLibrary = pLibrary;
|
||
|
pNode->m_pNext = g_pObjectList;
|
||
|
pNode->m_ppThis = &g_pObjectList;
|
||
|
|
||
|
if (pNode->m_pNext!=NULL)
|
||
|
{
|
||
|
pNode->m_pNext->m_ppThis = &pNode->m_pNext;
|
||
|
}
|
||
|
|
||
|
g_pObjectList = pNode;
|
||
|
|
||
|
LeaveCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetLastError(
|
||
|
ERROR_NOT_ENOUGH_MEMORY);
|
||
|
}
|
||
|
|
||
|
return pNode;
|
||
|
}
|
||
|
|
||
|
|
||
|
void lhcpDestroyHandle(PLHCSTRUCT pNode)
|
||
|
{
|
||
|
EnterCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
// Remove this node from the list of handles.
|
||
|
|
||
|
*(pNode->m_ppThis) = pNode->m_pNext;
|
||
|
if (pNode->m_pNext!=NULL)
|
||
|
{
|
||
|
pNode->m_pNext->m_ppThis = pNode->m_ppThis;
|
||
|
}
|
||
|
|
||
|
lhcpFreeObjectHandle(
|
||
|
pNode); // Invalidates the structure and frees the memory
|
||
|
|
||
|
LeaveCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL lhcInitialize()
|
||
|
{
|
||
|
PWSTR pszPath = NULL;
|
||
|
PWSTR pszFileName;
|
||
|
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||
|
WIN32_FIND_DATA FindData;
|
||
|
BOOL bResult;
|
||
|
PLIBRARY_DESCRIPTOR pLibrary = NULL;
|
||
|
PLIBRARY_NODE pNode = NULL;
|
||
|
WCHAR pszLibraryName[64];
|
||
|
|
||
|
InitializeCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
pszPath = lhcpGetExeDirectory();
|
||
|
|
||
|
if (NULL==pszPath)
|
||
|
{
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
pszFileName = pszPath + wcslen(pszPath);
|
||
|
|
||
|
wcscat(
|
||
|
pszFileName,
|
||
|
L"*.lhc");
|
||
|
|
||
|
hFind = FindFirstFileW(
|
||
|
pszPath,
|
||
|
&FindData);
|
||
|
|
||
|
bResult = (hFind!=INVALID_HANDLE_VALUE);
|
||
|
|
||
|
if (!bResult)
|
||
|
{
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
while (bResult)
|
||
|
{
|
||
|
wcscpy(
|
||
|
pszFileName,
|
||
|
FindData.cFileName);
|
||
|
|
||
|
pLibrary = lhclLoadLibrary(
|
||
|
pszPath);
|
||
|
|
||
|
if (pLibrary==NULL)
|
||
|
{
|
||
|
wprintf(
|
||
|
L"Unable to load (%u).\n",
|
||
|
pszFileName,
|
||
|
GetLastError());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lhclGetLibraryName(
|
||
|
pLibrary,
|
||
|
pszLibraryName,
|
||
|
64);
|
||
|
|
||
|
wprintf(
|
||
|
L"Loaded %s library.\n",
|
||
|
pszLibraryName);
|
||
|
|
||
|
pNode = lhcpNewLibraryNode();
|
||
|
|
||
|
if (NULL==pNode)
|
||
|
{
|
||
|
SetLastError(
|
||
|
ERROR_NOT_ENOUGH_MEMORY);
|
||
|
goto Error;
|
||
|
// Out of memory is fatal
|
||
|
}
|
||
|
|
||
|
pNode->m_pLibrary = pLibrary;
|
||
|
pNode->m_pNext = g_pLibraryList;
|
||
|
g_pLibraryList = pNode;
|
||
|
pNode = NULL;
|
||
|
pLibrary = NULL;
|
||
|
}
|
||
|
|
||
|
bResult = FindNextFileW(
|
||
|
hFind,
|
||
|
&FindData);
|
||
|
}
|
||
|
|
||
|
FindClose(hFind);
|
||
|
|
||
|
free(pszPath);
|
||
|
|
||
|
return g_pLibraryList!=NULL;
|
||
|
|
||
|
Error:
|
||
|
if (pLibrary!=NULL)
|
||
|
{
|
||
|
lhclFreeLibrary(pLibrary);
|
||
|
}
|
||
|
if (pszPath!=NULL)
|
||
|
{
|
||
|
free(pszPath);
|
||
|
}
|
||
|
if (pNode!=NULL)
|
||
|
{
|
||
|
free(pszPath);
|
||
|
}
|
||
|
if (hFind!=INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
FindClose(hFind);
|
||
|
}
|
||
|
// We need to unload the libraries that successfully loaded.
|
||
|
lhcFinalize();
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void lhcFinalize()
|
||
|
{
|
||
|
PLIBRARY_NODE pNode;
|
||
|
WCHAR pszLibraryName[64];
|
||
|
|
||
|
while (g_pObjectList!=NULL)
|
||
|
{
|
||
|
lhcClose(
|
||
|
g_pObjectList);
|
||
|
}
|
||
|
|
||
|
while (g_pLibraryList!=NULL)
|
||
|
{
|
||
|
pNode = g_pLibraryList;
|
||
|
g_pLibraryList = g_pLibraryList->m_pNext;
|
||
|
|
||
|
lhclGetLibraryName(
|
||
|
pNode->m_pLibrary,
|
||
|
pszLibraryName,
|
||
|
64);
|
||
|
|
||
|
lhclFreeLibrary(
|
||
|
pNode->m_pLibrary);
|
||
|
|
||
|
wprintf(
|
||
|
L"Unloaded %s library.\n",
|
||
|
pszLibraryName);
|
||
|
|
||
|
lhcpFreeLibraryNode(
|
||
|
pNode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
LHCHANDLE lhcOpen(PCWSTR pcszPortSpec)
|
||
|
{
|
||
|
PLIBRARY_NODE pLibraryNode = g_pLibraryList;
|
||
|
PLHCOBJECT_DESCRIPTOR pObject = NULL;
|
||
|
PLHCSTRUCT hObject;
|
||
|
|
||
|
while (pLibraryNode!=NULL && pObject==NULL)
|
||
|
{
|
||
|
// Try libraries one at a time until one opens successfully
|
||
|
pObject = lhclOpen(
|
||
|
pLibraryNode->m_pLibrary,
|
||
|
pcszPortSpec);
|
||
|
|
||
|
if (!pObject)
|
||
|
{
|
||
|
pLibraryNode = pLibraryNode->m_pNext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!pObject)
|
||
|
{
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
hObject = lhcpCreateHandle(
|
||
|
pLibraryNode->m_pLibrary,
|
||
|
pObject);
|
||
|
|
||
|
if (hObject==NULL)
|
||
|
{
|
||
|
SetLastError(
|
||
|
ERROR_NOT_ENOUGH_MEMORY);
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
return hObject;
|
||
|
|
||
|
Error:
|
||
|
if (pObject!=NULL)
|
||
|
{
|
||
|
lhclClose(
|
||
|
pLibraryNode->m_pLibrary,
|
||
|
pObject);
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL lhcRead(
|
||
|
LHCHANDLE hObject,
|
||
|
PVOID pBuffer,
|
||
|
DWORD dwBufferSize,
|
||
|
PDWORD pdwBytesRead)
|
||
|
{
|
||
|
PLIBRARY_DESCRIPTOR pLibrary;
|
||
|
PLHCOBJECT_DESCRIPTOR pObject;
|
||
|
|
||
|
if (!lhcpIsValidHandle(hObject))
|
||
|
{
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
EnterCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
// Ensure consistent information
|
||
|
pLibrary = ((PLHCSTRUCT)hObject)->m_pLibrary;
|
||
|
pObject = ((PLHCSTRUCT)hObject)->m_pObject;
|
||
|
|
||
|
LeaveCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
return lhclRead(
|
||
|
pLibrary,
|
||
|
pObject,
|
||
|
pBuffer,
|
||
|
dwBufferSize,
|
||
|
pdwBytesRead);
|
||
|
|
||
|
Error:
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL lhcWrite(
|
||
|
LHCHANDLE hObject,
|
||
|
PVOID pBuffer,
|
||
|
DWORD dwBufferSize)
|
||
|
{
|
||
|
PLIBRARY_DESCRIPTOR pLibrary;
|
||
|
PLHCOBJECT_DESCRIPTOR pObject;
|
||
|
|
||
|
if (!lhcpIsValidHandle(hObject))
|
||
|
{
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
// Ensure consistent information by using the critical section
|
||
|
EnterCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
// Ensure consistent information
|
||
|
pLibrary = ((PLHCSTRUCT)hObject)->m_pLibrary;
|
||
|
pObject = ((PLHCSTRUCT)hObject)->m_pObject;
|
||
|
|
||
|
LeaveCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
return lhclWrite(
|
||
|
pLibrary,
|
||
|
pObject,
|
||
|
pBuffer,
|
||
|
dwBufferSize);
|
||
|
|
||
|
Error:
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL lhcClose(
|
||
|
LHCHANDLE hObject)
|
||
|
{
|
||
|
PLIBRARY_DESCRIPTOR pLibrary;
|
||
|
PLHCOBJECT_DESCRIPTOR pObject;
|
||
|
|
||
|
if (!lhcpIsValidHandle(hObject))
|
||
|
{
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
// Ensure consistent information by using the critical section
|
||
|
|
||
|
EnterCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
// Ensure consistent information
|
||
|
pLibrary = ((PLHCSTRUCT)hObject)->m_pLibrary;
|
||
|
pObject = ((PLHCSTRUCT)hObject)->m_pObject;
|
||
|
|
||
|
lhcpDestroyHandle(
|
||
|
hObject);
|
||
|
|
||
|
LeaveCriticalSection(
|
||
|
&g_csTableControl);
|
||
|
|
||
|
return lhclClose(
|
||
|
pLibrary,
|
||
|
pObject);
|
||
|
|
||
|
Error:
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|