#include "stdafx.h" #include "LwIPCExchg.hpp" #define EVENT_CMD_SENT _T("{BC6F0A88-0DFC-42c5-AFCA-60635652D8B0}") #define EVENT_CMD_RECV _T("{6E611ED1-4D3A-48ab-8E30-B7D7F2EFDB3D}") HANDLE gLockData = NULL; HANDLE ghCmdDispatched = NULL; HANDLE ghCmdResponse = NULL; /* ************************************************************* * Global variables IPC *************************************************************/ HANDLE g_hMapFileObjEx = NULL; BOOL g_bRunIPC = FALSE; BT_USER_EX *g_pstBtUserEx = NULL; // Use the new format for event transfer CRITICAL_SECTION g_criticalSectionEx; // To protect BT_USER_EX enum _StartContext StartContext = IPC_SERVER; /**************************************************************************** * Name :StartIPCEx * Created : * Returns :None * * Desc :Initializes and runs interprocess communications to the * BT DLL API for BNEP data exchange. * Notes : * ****************************************************************************/ BOOL StartIPCEx() { TRACE(_T("LwIPCExchg <== StartIPCEx()\n")); if ( g_hMapFileObjEx == NULL ) { ACQUIRELOCK if ( GetLastError() == ERROR_ALREADY_EXISTS ) { TRACE(_T("Global lock object already existing\n")); AfxMessageBox(_T("Server already running!")); RELEASELOCK return FALSE; } if ( gLockData == NULL ) return FALSE; // the handle of 0xFFFFFFFF means that the file mapping will be created in the // system pagefile. g_hMapFileObjEx = CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE | SEC_COMMIT, 0, sizeof(struct _BT_USER_EX), GLOBAL_MAPPED_FILE_GUID); if(g_hMapFileObjEx == NULL) { TRACE(_T("Failed to create file mapping object\n")); g_bRunIPC = FALSE; goto DONE; } // Create the mapping in the process' address space g_pstBtUserEx = (BT_USER_EX*) MapViewOfFile(g_hMapFileObjEx, FILE_MAP_ALL_ACCESS, 0, 0, 0); if(g_pstBtUserEx == NULL) { TRACE(_T("FATAL ERROR: MapViewOfFile() failed\n")); CloseHandle( g_hMapFileObjEx ); g_hMapFileObjEx = NULL; g_bRunIPC = FALSE; goto DONE; } ghCmdDispatched = CreateEvent( NULL, FALSE, FALSE, EVENT_CMD_SENT ); ASSERT( ghCmdDispatched != NULL ); ghCmdResponse = CreateEvent( NULL, FALSE, FALSE, EVENT_CMD_RECV ); ASSERT( ghCmdResponse != NULL ); InitializeCriticalSection( &g_criticalSectionEx ); TRACE(_T("LwIPCExchg ==> StartIPCEx() returns TRUE\n")); gMySharedArray = &g_pstBtUserEx->myData; StartContext = IPC_SERVER; g_pstBtUserEx->bServRunning = TRUE; g_bRunIPC = TRUE; } else { TRACE(_T("Only one IPC server instance can run at a time\n")); return FALSE; } DONE: RELEASELOCK return g_bRunIPC; } /**************************************************************************** * Name :OpenIPCEx * Created : * Returns :None * * Desc :Opens and runs interprocess communications to the * BT DLL API for BNEP data exchange. * Notes : * ****************************************************************************/ BOOL OpenIPCEx() { TRACE(_T("LwIPCExchg <== OpenIPCEx()\n")); if ( g_hMapFileObjEx == NULL ) { // Create the global lock object ACQUIRELOCK if ( GetLastError() == ERROR_ALREADY_EXISTS ) { TRACE(_T("Global lock object already existing. Okay to proceed for clients\n")); } else { RELEASELOCK return FALSE; } // Open the file mapping handle g_hMapFileObjEx = OpenFileMapping( FILE_MAP_ALL_ACCESS, TRUE, GLOBAL_MAPPED_FILE_GUID ); if(g_hMapFileObjEx == NULL) { TRACE(_T("Failed to create file mapping object. Error = %u\n"), GetLastError()); g_bRunIPC = FALSE; goto DONE; } // Create the mapping in the process' address space g_pstBtUserEx = (BT_USER_EX*) MapViewOfFile(g_hMapFileObjEx, FILE_MAP_ALL_ACCESS, 0, 0, 0); if ( g_pstBtUserEx == NULL ) { TRACE(_T("FATAL ERROR: MapViewOfFile() failed\n")); CloseHandle( g_hMapFileObjEx ); g_hMapFileObjEx = NULL; g_bRunIPC = FALSE; goto DONE; } ghCmdDispatched = CreateEvent( NULL, FALSE, FALSE, EVENT_CMD_SENT ); ASSERT( ghCmdDispatched != NULL ); ghCmdResponse = CreateEvent( NULL, FALSE, FALSE, EVENT_CMD_RECV ); ASSERT( ghCmdResponse != NULL ); InitializeCriticalSection( &g_criticalSectionEx ); TRACE(_T("LwIPCExchg ==> OpenIPCEx() returns TRUE\n")); gMySharedArray = &g_pstBtUserEx->myData; StartContext = IPC_CLIENT; g_bRunIPC = TRUE; } DONE: RELEASELOCK return g_bRunIPC; } /**************************************************************************** * Name :RunIPCEx * Created : * Returns :None * * Desc :Closes interprocess communications for BNEP data exchange. * Notes : * ****************************************************************************/ VOID CloseIPCEx() { if (g_bRunIPC) { ISUNLOCK ACQUIRELOCK if ( ghCmdDispatched ) { CloseHandle( ghCmdDispatched ); ghCmdDispatched = NULL; } EnterCriticalSection( &g_criticalSectionEx ); if (g_hMapFileObjEx) { if (g_pstBtUserEx) { // Set server is going down status from server's start context if ( StartContext == IPC_SERVER ) g_pstBtUserEx->bServRunning = FALSE; if (!UnmapViewOfFile(g_pstBtUserEx)) { TRACE(_T("ERROR: Failed to unmap Extended IPC\n")); } // Dereference the map address g_pstBtUserEx = NULL; } CloseHandle( g_hMapFileObjEx ); g_hMapFileObjEx = NULL; g_bRunIPC = FALSE; TRACE(_T("Shut down IPC\n")); } LeaveCriticalSection( &g_criticalSectionEx ); DeleteCriticalSection( &g_criticalSectionEx ); RELEASELOCK } } /**************************************************************************** * Name :IsExIPCRunning * Created : * Returns :True, if BNEP IPC is running and valid * * Desc :Closes interprocess communications for BNEP data exchange. * Notes : * ****************************************************************************/ BOOL IsExIPCRunning() { if (g_bRunIPC) if ( g_hMapFileObjEx && (g_hMapFileObjEx != INVALID_HANDLE_VALUE)) return TRUE; return FALSE; } /**************************************************************************** * Name :IsServerRunning * Created : * Returns :True, if IPC server is running * * Desc : * Notes : * ****************************************************************************/ BOOL IsServerRunning() { BOOL bServRunning = FALSE; if ( StartContext == IPC_CLIENT ) { if ( g_pstBtUserEx ) bServRunning = g_pstBtUserEx->bServRunning; return bServRunning; } return (IsExIPCRunning()); } /**************************************************************************** * Name :CommitMemoryEx * Created : * Returns :Boolean value to indicate success/ failure of the call. * * Desc :Makes permanent changes to the extended shared memory. * Notes : * ****************************************************************************/ BOOL CommitMemoryEx( BT_USER_EX* pMapAddr ) { DWORD dwElapsed = 0L; DWORD dwLastTick = 0L; BOOL bRetCode = FALSE; const UINT ACK_TIMEOUT = 1400; // Check if the global map memory is created or not // Wait until the creation of the shared memory mapping ISUNLOCK if (pMapAddr && g_bRunIPC) { TRACE(_T("CommitMemoryEx <== Received data commit\n")); // Set event occured bit pMapAddr->masterEventBit = 0x01; if (g_pstBtUserEx) { // Write to global memory now EnterCriticalSection( &g_criticalSectionEx ); CopyMemory( (void*)g_pstBtUserEx, (const void*)pMapAddr, sizeof(BT_USER_EX)); //Set this the last when all data have been copied g_pstBtUserEx->masterEventBit = pMapAddr->masterEventBit; LeaveCriticalSection( &g_criticalSectionEx ); PulseEvent( ghCmdDispatched ); //Signal all waiting threads TRACE(_T("Global shared memory updated\n")); WaitForSingleObject( ghCmdResponse, ACK_TIMEOUT ); TRACE(_T("Memory update ACK by the other process\n")); bRetCode = TRUE; } } // Release anyway RELEASELOCK return bRetCode; }