#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; }