|
|
/*==========================================================================;
* * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved. * * File: fdtipc.cpp * Content: Implements the IPC calls for the full duplex test * History: * Date By Reason * ============ * 08/26/99 pnewson created * 04/19/2000 pnewson Error handling cleanup * 06/28/2000 rodtoll Prefix Bug #38022 * 03/01/2002 simonpow Bug #550054. Fixed CreateProcess calls to specifiy * both app name and command line ***************************************************************************/
#include "dxvtlibpch.h"
#undef DPF_SUBCOMP
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
// static helper functions for this file
HRESULT DoReceive( SFDTestCommand* pfdtc, HANDLE hEvent, HANDLE hReplyEvent, LPVOID lpvShMemPtr); HRESULT DoReply(HRESULT hr, HANDLE hReplyEvent, LPVOID lpvShMemPtr);
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::CSupervisorIPC"
CSupervisorIPC::CSupervisorIPC() : m_fInitComplete(FALSE) , m_hFullDuplexEvent(NULL) , m_hFullDuplexMutex(NULL) , m_hFullDuplexReplyEvent(NULL) , m_hFullDuplexShMemHandle(NULL) , m_hPriorityEvent(NULL) , m_hPriorityMutex(NULL) , m_hPriorityReplyEvent(NULL) , m_hPriorityShMemHandle(NULL) , m_lpvFullDuplexShMemPtr(NULL) , m_lpvPriorityShMemPtr(NULL) { ZeroMemory(&m_piFullDuplex, sizeof(PROCESS_INFORMATION)); ZeroMemory(&m_piPriority, sizeof(PROCESS_INFORMATION)); return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::Init"
HRESULT CSupervisorIPC::Init() { LONG lRet; HRESULT hr;
DPF_ENTER();
if (!DNInitializeCriticalSection(&m_csLock)) { return DVERR_OUTOFMEMORY; }
DNEnterCriticalSection(&m_csLock);
if (m_fInitComplete != FALSE) { hr = DVERR_GENERIC; goto error_cleanup; }
// create the event objects - make sure they don't already
// exist!
m_hPriorityEvent = CreateEvent(NULL, FALSE, FALSE, gc_szPriorityEventName); lRet = GetLastError(); if (m_hPriorityEvent == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } if (lRet == ERROR_ALREADY_EXISTS) { hr = DVERR_GENERIC; goto error_cleanup; }
m_hFullDuplexEvent = CreateEvent(NULL, FALSE, FALSE, gc_szFullDuplexEventName); lRet = GetLastError(); if (m_hFullDuplexEvent == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } if (lRet == ERROR_ALREADY_EXISTS) { hr = DVERR_GENERIC; goto error_cleanup; }
m_hPriorityReplyEvent = CreateEvent(NULL, FALSE, FALSE, gc_szPriorityReplyEventName); lRet = GetLastError(); if (m_hPriorityReplyEvent == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } if (lRet == ERROR_ALREADY_EXISTS) { hr = DVERR_GENERIC; goto error_cleanup; }
m_hFullDuplexReplyEvent = CreateEvent(NULL, FALSE, FALSE, gc_szFullDuplexReplyEventName); lRet = GetLastError(); if (m_hFullDuplexReplyEvent == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } if (lRet == ERROR_ALREADY_EXISTS) { hr = DVERR_GENERIC; goto error_cleanup; }
// create the shared memory blocks
m_hPriorityShMemHandle = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, gc_dwPriorityShMemSize, gc_szPriorityShMemName); lRet = GetLastError(); if (m_hPriorityShMemHandle == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } if (lRet == ERROR_ALREADY_EXISTS) { hr = DVERR_GENERIC; goto error_cleanup; } m_lpvPriorityShMemPtr = MapViewOfFile( m_hPriorityShMemHandle, FILE_MAP_WRITE, 0, 0, gc_dwPriorityShMemSize); if (m_lpvPriorityShMemPtr == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } m_hFullDuplexShMemHandle = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, gc_dwFullDuplexShMemSize, gc_szFullDuplexShMemName); lRet = GetLastError(); if (m_hFullDuplexShMemHandle == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } if (lRet == ERROR_ALREADY_EXISTS) { hr = DVERR_GENERIC; goto error_cleanup; } m_lpvFullDuplexShMemPtr = MapViewOfFile( m_hFullDuplexShMemHandle, FILE_MAP_WRITE, 0, 0, gc_dwFullDuplexShMemSize); if (m_lpvFullDuplexShMemPtr == NULL) { hr = DVERR_GENERIC; goto error_cleanup; }
// create the send mutexes
m_hPriorityMutex = CreateMutex(NULL, FALSE, gc_szPrioritySendMutex); lRet = GetLastError(); if (m_hPriorityMutex == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } if (lRet == ERROR_ALREADY_EXISTS) { hr = DVERR_GENERIC; goto error_cleanup; }
m_hFullDuplexMutex = CreateMutex(NULL, FALSE, gc_szFullDuplexSendMutex); lRet = GetLastError(); if (m_hFullDuplexMutex == NULL) { hr = DVERR_GENERIC; goto error_cleanup; } if (lRet == ERROR_ALREADY_EXISTS) { hr = DVERR_GENERIC; goto error_cleanup; } m_fInitComplete = TRUE; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return S_OK;
error_cleanup: if (m_hFullDuplexMutex != NULL) { CloseHandle(m_hFullDuplexMutex); m_hFullDuplexMutex = NULL; }
if (m_hPriorityMutex != NULL) { CloseHandle(m_hPriorityMutex); m_hPriorityMutex = NULL; }
if (m_lpvFullDuplexShMemPtr != NULL) { UnmapViewOfFile(m_lpvFullDuplexShMemPtr); m_lpvFullDuplexShMemPtr = NULL; }
if (m_hFullDuplexShMemHandle != NULL) { CloseHandle(m_hFullDuplexShMemHandle); m_hFullDuplexShMemHandle = NULL; }
if (m_lpvPriorityShMemPtr != NULL) { UnmapViewOfFile(m_lpvPriorityShMemPtr); m_lpvPriorityShMemPtr = NULL; }
if (m_hPriorityShMemHandle != NULL) { CloseHandle(m_hPriorityShMemHandle); m_hPriorityShMemHandle = NULL; }
if (m_hFullDuplexReplyEvent != NULL) { CloseHandle(m_hFullDuplexReplyEvent); m_hFullDuplexReplyEvent = NULL; }
if (m_hPriorityReplyEvent != NULL) { CloseHandle(m_hPriorityReplyEvent); m_hPriorityReplyEvent = NULL; }
if (m_hFullDuplexEvent != NULL) { CloseHandle(m_hFullDuplexEvent); m_hFullDuplexEvent = NULL; }
if (m_hPriorityEvent != NULL) { CloseHandle(m_hPriorityEvent); m_hPriorityEvent = NULL; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::Deinit"
HRESULT CSupervisorIPC::Deinit() { LONG lRet; HRESULT hr = DV_OK;
DPF_ENTER();
DNEnterCriticalSection(&m_csLock);
if (m_fInitComplete != TRUE) { hr = DVERR_NOTINITIALIZED; } m_fInitComplete = FALSE;
if (m_hFullDuplexMutex != NULL) { CloseHandle(m_hFullDuplexMutex); m_hFullDuplexMutex = NULL; }
if (m_hPriorityMutex != NULL) { CloseHandle(m_hPriorityMutex); m_hPriorityMutex = NULL; }
if (m_lpvFullDuplexShMemPtr != NULL) { UnmapViewOfFile(m_lpvFullDuplexShMemPtr); m_lpvFullDuplexShMemPtr = NULL; }
if (m_hFullDuplexShMemHandle != NULL) { CloseHandle(m_hFullDuplexShMemHandle); m_hFullDuplexShMemHandle = NULL; }
if (m_lpvPriorityShMemPtr != NULL) { UnmapViewOfFile(m_lpvPriorityShMemPtr); m_lpvPriorityShMemPtr = NULL; }
if (m_hPriorityShMemHandle != NULL) { CloseHandle(m_hPriorityShMemHandle); m_hPriorityShMemHandle = NULL; }
if (m_hFullDuplexReplyEvent != NULL) { CloseHandle(m_hFullDuplexReplyEvent); m_hFullDuplexReplyEvent = NULL; }
if (m_hPriorityReplyEvent != NULL) { CloseHandle(m_hPriorityReplyEvent); m_hPriorityReplyEvent = NULL; }
if (m_hFullDuplexEvent != NULL) { CloseHandle(m_hFullDuplexEvent); m_hFullDuplexEvent = NULL; }
if (m_hPriorityEvent != NULL) { CloseHandle(m_hPriorityEvent); m_hPriorityEvent = NULL; }
DNLeaveCriticalSection(&m_csLock);
DNDeleteCriticalSection(&m_csLock);
DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::SendToPriority"
HRESULT CSupervisorIPC::SendToPriority(const SFDTestCommand *pfdtc) { HRESULT hr;
DPF_ENTER();
DNEnterCriticalSection(&m_csLock);
hr = DoSend( pfdtc, m_piPriority.hProcess, m_hPriorityEvent, m_hPriorityReplyEvent, m_lpvPriorityShMemPtr, m_hPriorityMutex);
DNLeaveCriticalSection(&m_csLock);
DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::SendToFullDuplex"
HRESULT CSupervisorIPC::SendToFullDuplex(const SFDTestCommand *pfdtc) { HRESULT hr;
DPF_ENTER();
DNEnterCriticalSection(&m_csLock);
hr = DoSend( pfdtc, m_piFullDuplex.hProcess, m_hFullDuplexEvent, m_hFullDuplexReplyEvent, m_lpvFullDuplexShMemPtr, m_hFullDuplexMutex);
DNLeaveCriticalSection(&m_csLock);
DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::DoSend"
HRESULT CSupervisorIPC::DoSend( const SFDTestCommand* pfdtc, HANDLE hProcess, HANDLE hEvent, HANDLE hReplyEvent, LPVOID lpvShMemPtr, HANDLE hMutex) { DWORD dwRet; LONG lRet; HRESULT hr; HANDLE hWaitArray[2]; BOOL fHaveMutex = FALSE;
DPF_ENTER();
// grab the mutex
dwRet = WaitForSingleObject(hMutex, gc_dwSendMutexTimeout); if (dwRet != WAIT_OBJECT_0) { if (dwRet == WAIT_TIMEOUT) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Timed out waiting for send mutex"); hr = DVERR_TIMEOUT; goto error_cleanup; } lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Error waiting for send mutex, code: %i", lRet); hr = DVERR_WIN32; goto error_cleanup; } fHaveMutex = TRUE;
// copy the command into shared memory
CopyMemory(lpvShMemPtr, pfdtc, pfdtc->dwSize);
// signal the event
if (!SetEvent(hEvent)) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to set event, code: %i", lRet); hr = DVERR_WIN32; goto error_cleanup; }
// Wait for the reply event - note that we only expect the
// supervisor process to call this function, and therefore
// we don't check for directsound events occuring during this
// time.
// Also, wait on the process handle, if the process we are sending
// to exits, we'll want to continue right away, not wait for a timeout.
hWaitArray[0] = hReplyEvent; hWaitArray[1] = hProcess; dwRet = WaitForMultipleObjects(2, hWaitArray, FALSE, gc_dwCommandReplyTimeout); switch(dwRet) { case WAIT_OBJECT_0: // The other process replied, move along.
break;
case WAIT_OBJECT_0+1: // The other process exited!
DPFX(DPFPREP, DVF_ERRORLEVEL, "Process exited while waiting for reply"); hr = DVERR_TIMEOUT; goto error_cleanup;
case WAIT_TIMEOUT: // The other process did not reply in a reasonable amount of time.
DPFX(DPFPREP, DVF_ERRORLEVEL, "Timed out waiting for reply to command"); hr = DVERR_TIMEOUT; goto error_cleanup;
default: // No idea what happened here...
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error waiting for reply event, code: %i", dwRet); hr = DVERR_GENERIC; goto error_cleanup; } // get the reply code (an HRESULT) from shared memory
hr = *(HRESULT*)lpvShMemPtr;
// release the mutex
if (!ReleaseMutex(hMutex)) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Error releasing mutex, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
DPF_EXIT(); return hr;
error_cleanup: if (hMutex != NULL) { ReleaseMutex(hMutex); } DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::StartPriorityProcess"
HRESULT CSupervisorIPC::StartPriorityProcess() { STARTUPINFO si; DPF_ENTER();
TCHAR szCmdLine[128]; TCHAR szAppName[_MAX_PATH+1]; DNEnterCriticalSection(&m_csLock); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
BuildLaunchAppName(szAppName);
_tcsncpy( szCmdLine, gc_szPriorityCommand, 127 ); szCmdLine[127] = 0;
if (!CreateProcess( szAppName, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &m_piPriority)) { m_piPriority.hProcess = NULL; m_piPriority.hThread = NULL; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DVERR_WIN32; }
// don't need the thread handle
if (!CloseHandle(m_piPriority.hThread)) { m_piPriority.hThread = NULL; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DVERR_WIN32; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return S_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::WaitOnChildren"
HRESULT CSupervisorIPC::WaitOnChildren() { HANDLE rghChildren[2]; DWORD dwRet; LONG lRet; HRESULT hr = DV_OK; BOOL fRet;
DPF_ENTER(); DNEnterCriticalSection(&m_csLock); rghChildren[0] = m_piPriority.hProcess; rghChildren[1] = m_piFullDuplex.hProcess; DNLeaveCriticalSection(&m_csLock); dwRet = WaitForMultipleObjects(2, rghChildren, TRUE, gc_dwChildWaitTimeout); if (dwRet == WAIT_TIMEOUT) { DPFX(DPFPREP, DVF_ERRORLEVEL, "WaitForMultipleObjects timed out waiting on child process handles"); DPF_EXIT(); return DVERR_CHILDPROCESSFAILED; } else if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_OBJECT_0 + 1) { // This is the expected behavior. The processes shut down
// gracefully. Close and NULL out our handles to them.
// Note that just because the process shut down gracefully,
// that does not mean that it did not have an error. The
// process returns an HRESULT for it's exit code. Check it.
// Note that this code assumes HRESULTS are DWORDS. Hopefully
// this won't break in Win64!
DNEnterCriticalSection(&m_csLock); fRet = GetExitCodeProcess(m_piPriority.hProcess, (LPDWORD)&hr); if (!fRet || FAILED(hr)) { lRet = GetLastError(); CloseHandle(m_piPriority.hProcess); CloseHandle(m_piFullDuplex.hProcess); m_piPriority.hProcess = NULL; m_piFullDuplex.hProcess = NULL; DNLeaveCriticalSection(&m_csLock); if (!fRet && SUCCEEDED(hr)) { DPFX(DPFPREP, DVF_ERRORLEVEL, "GetExitCodeProcess failed, lRet: %i", lRet); DPF_EXIT(); return DVERR_GENERIC; } DPFX(DPFPREP, DVF_ERRORLEVEL, "Priority Process exited with error code, hr: %i", hr); DPF_EXIT(); return hr; } if (!CloseHandle(m_piPriority.hProcess)) { lRet = GetLastError(); CloseHandle(m_piFullDuplex.hProcess); m_piPriority.hProcess = NULL; m_piFullDuplex.hProcess = NULL; DNLeaveCriticalSection(&m_csLock); DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed, lRet: %i", lRet); DPF_EXIT(); return DVERR_GENERIC; } fRet = GetExitCodeProcess(m_piFullDuplex.hProcess, (LPDWORD)&hr); if (!fRet || FAILED(hr)) { lRet = GetLastError(); CloseHandle(m_piFullDuplex.hProcess); m_piPriority.hProcess = NULL; m_piFullDuplex.hProcess = NULL; DNLeaveCriticalSection(&m_csLock); if (!fRet && SUCCEEDED(hr)) { DPFX(DPFPREP, DVF_ERRORLEVEL, "GetExitCodeProcess failed, lRet: %i", lRet); DPF_EXIT(); return DVERR_GENERIC; } DPFX(DPFPREP, DVF_ERRORLEVEL, "FullDuplex Process exited with error code, hr: %i", hr); DPF_EXIT(); return hr; } if (!CloseHandle(m_piFullDuplex.hProcess)) { lRet = GetLastError(); m_piPriority.hProcess = NULL; m_piFullDuplex.hProcess = NULL; DNLeaveCriticalSection(&m_csLock); DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed, lRet: %i", lRet); DPF_EXIT(); return DVERR_GENERIC; } m_piPriority.hProcess = NULL; m_piFullDuplex.hProcess = NULL; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK; } else { // Not sure what happened...
DPF_EXIT(); return DVERR_GENERIC; } }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::TerminateChildProcesses"
HRESULT CSupervisorIPC::TerminateChildProcesses() { LONG lRet; HRESULT hr = DV_OK;
DPF_ENTER(); // The child processes did not exit gracefully. So now
// we get to kill them off rudely. Note that this
// function may be called at any time, including when
// there are no child processes running.
DNEnterCriticalSection(&m_csLock); if (m_piPriority.hProcess != NULL) { if (!TerminateProcess(m_piPriority.hProcess, 0)) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "TerminateProcess failed on priority process, code: %i", lRet); if (!CloseHandle(m_piPriority.hProcess)) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed on priority process handle, code: %i", lRet); } m_piPriority.hProcess = NULL; hr = DVERR_GENERIC; } if (!CloseHandle(m_piPriority.hProcess)) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed on priority process handle, code: %i", lRet); hr = DVERR_GENERIC; } m_piPriority.hProcess = NULL; } if (m_piFullDuplex.hProcess != NULL) { if (!TerminateProcess(m_piFullDuplex.hProcess, 0)) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "TerminateProcess failed on full duplex process, code: %i", lRet); hr = DVERR_GENERIC; } if (!CloseHandle(m_piFullDuplex.hProcess)) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed on full duplex process handle, code: %i", lRet); hr = DVERR_GENERIC; } m_piFullDuplex.hProcess = NULL; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::StartFullDuplexProcess"
HRESULT CSupervisorIPC::StartFullDuplexProcess() { STARTUPINFO si; TCHAR szCmdLine[128]; TCHAR szAppName[MAX_PATH+1];
DPF_ENTER();
DNEnterCriticalSection(&m_csLock); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
BuildLaunchAppName(szAppName); _tcsncpy( szCmdLine, gc_szFullDuplexCommand, 127 );
if (!CreateProcess( szAppName, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &m_piFullDuplex)) { m_piFullDuplex.hProcess = NULL; m_piFullDuplex.hThread = NULL; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DVERR_WIN32; }
// don't need the thread handle
if (!CloseHandle(m_piFullDuplex.hThread)) { m_piFullDuplex.hThread = NULL; DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DVERR_WIN32; }
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return S_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::WaitForStartupSignals"
HRESULT CSupervisorIPC::WaitForStartupSignals() { HANDLE rghEvents[2]; DWORD dwRet; HRESULT hr; LONG lRet; // wait to be signaled by both child processes, indicating that
// they are ready to go.
DNEnterCriticalSection(&m_csLock); rghEvents[0] = m_hPriorityReplyEvent; rghEvents[1] = m_hFullDuplexReplyEvent; DNLeaveCriticalSection(&m_csLock); dwRet = WaitForMultipleObjects(2, rghEvents, TRUE, gc_dwChildStartupTimeout); if (dwRet != WAIT_OBJECT_0 && dwRet != WAIT_OBJECT_0 + 1) { if (dwRet == WAIT_TIMEOUT) { DPFX(DPFPREP, DVF_ERRORLEVEL, "Timeout waiting for child processes to startup"); return DVERR_TIMEOUT; } else { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Error waiting for signals from child processes, code: %i", lRet); return DVERR_WIN32; } } return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CSupervisorIPC::BuildAppName"
void CSupervisorIPC::BuildLaunchAppName(TCHAR * wszFullPath) { GetSystemDirectory(wszFullPath, MAX_PATH); DWORD dwAppNameFullPathLen=_tcslen(wszFullPath); if (wszFullPath[dwAppNameFullPathLen-1]!='\\') wszFullPath[dwAppNameFullPathLen++]='\\'; wszFullPath[dwAppNameFullPathLen++]=0; _tcsncat(wszFullPath, gc_szLaunchAppName, MAX_PATH-dwAppNameFullPathLen); }
#undef DPF_MODNAME
#define DPF_MODNAME "CPriorityIPC::CPriorityIPC"
CPriorityIPC::CPriorityIPC() : m_fInitComplete(FALSE) , m_hPriorityEvent(NULL) , m_hPriorityMutex(NULL) , m_hPriorityReplyEvent(NULL) , m_hPriorityShMemHandle(NULL) , m_lpvPriorityShMemPtr(NULL) { return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CPriorityIPC::Init"
HRESULT CPriorityIPC::Init() { LONG lRet; HRESULT hr;
DPF_ENTER();
if (!DNInitializeCriticalSection(&m_csLock)) { return DVERR_OUTOFMEMORY; }
DNEnterCriticalSection(&m_csLock);
if (m_fInitComplete == TRUE) { DPFX(DPFPREP, DVF_ERRORLEVEL, "CPriorityIPC::Init - already initialized"); hr = DVERR_INITIALIZED; goto error_cleanup; } m_hPriorityEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, gc_szPriorityEventName); if (m_hPriorityEvent == NULL) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open Priority event, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_hPriorityReplyEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, gc_szPriorityReplyEventName); if (m_hPriorityReplyEvent == NULL) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open Priority Reply event, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_hPriorityShMemHandle = OpenFileMapping(FILE_MAP_WRITE, FALSE, gc_szPriorityShMemName); if (m_hPriorityShMemHandle == NULL) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open Priority FileMapping object, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_lpvPriorityShMemPtr = MapViewOfFile( m_hPriorityShMemHandle, FILE_MAP_WRITE, 0, 0, gc_dwPriorityShMemSize); if (m_lpvPriorityShMemPtr == NULL) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to Map view of Priority FileMapping object, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_fInitComplete = TRUE;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return S_OK;
error_cleanup: if (m_lpvPriorityShMemPtr != NULL) { UnmapViewOfFile(m_lpvPriorityShMemPtr); m_lpvPriorityShMemPtr = NULL; } if (m_hPriorityShMemHandle != NULL) { CloseHandle(m_hPriorityShMemHandle); m_hPriorityShMemHandle = NULL; }
if (m_hPriorityReplyEvent != NULL) { CloseHandle(m_hPriorityReplyEvent); m_hPriorityReplyEvent = NULL; }
if (m_hPriorityEvent != NULL) { CloseHandle(m_hPriorityEvent); m_hPriorityEvent = NULL; } DNLeaveCriticalSection(&m_csLock);
DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CPriorityIPC::Deinit"
HRESULT CPriorityIPC::Deinit() { LONG lRet; HRESULT hr = DV_OK;
DPF_ENTER();
DNEnterCriticalSection(&m_csLock);
if (m_fInitComplete != TRUE) { DPFX(DPFPREP, DVF_ERRORLEVEL, "CPriorityIPC::Deinit called on uninitialized object"); hr = DVERR_NOTINITIALIZED; } m_fInitComplete = FALSE;
if (m_lpvPriorityShMemPtr != NULL) { UnmapViewOfFile(m_lpvPriorityShMemPtr); m_lpvPriorityShMemPtr = NULL; } if (m_hPriorityShMemHandle != NULL) { CloseHandle(m_hPriorityShMemHandle); m_hPriorityShMemHandle = NULL; }
if (m_hPriorityReplyEvent != NULL) { CloseHandle(m_hPriorityReplyEvent); m_hPriorityReplyEvent = NULL; }
if (m_hPriorityEvent != NULL) { CloseHandle(m_hPriorityEvent); m_hPriorityEvent = NULL; }
DNLeaveCriticalSection(&m_csLock);
DNDeleteCriticalSection(&m_csLock);
DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CPriorityIPC::SignalParentReady"
HRESULT CPriorityIPC::SignalParentReady() { BOOL fRet; LONG lRet; DPF_ENTER();
DNEnterCriticalSection(&m_csLock); fRet = SetEvent(m_hPriorityReplyEvent); if (!fRet) { lRet = GetLastError(); DPFX(DPFPREP, 0, "Error Setting Priority Reply Event, code: %i", lRet); DPF_EXIT(); return DVERR_WIN32; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CPriorityIPC::Receive"
HRESULT CPriorityIPC::Receive(SFDTestCommand* pfdtc) { HRESULT hr; DPF_ENTER(); DNEnterCriticalSection(&m_csLock);
hr = DoReceive(pfdtc, m_hPriorityEvent, m_hPriorityReplyEvent, m_lpvPriorityShMemPtr);
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CPriorityIPC::Reply"
HRESULT CPriorityIPC::Reply(HRESULT hr) { DPF_ENTER(); DNEnterCriticalSection(&m_csLock);
hr = DoReply(hr, m_hPriorityReplyEvent, m_lpvPriorityShMemPtr);
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CFullDuplexIPC::CFullDuplexIPC"
CFullDuplexIPC::CFullDuplexIPC() : m_fInitComplete(FALSE) , m_hFullDuplexEvent(NULL) , m_hFullDuplexMutex(NULL) , m_hFullDuplexReplyEvent(NULL) , m_hFullDuplexShMemHandle(NULL) , m_lpvFullDuplexShMemPtr(NULL) { return; }
#undef DPF_MODNAME
#define DPF_MODNAME "CFullDuplexIPC::Init"
HRESULT CFullDuplexIPC::Init() { LONG lRet; HRESULT hr;
DPF_ENTER();
if (!DNInitializeCriticalSection(&m_csLock)) { return DVERR_OUTOFMEMORY; }
DNEnterCriticalSection(&m_csLock);
if (m_fInitComplete != FALSE) { DPFX(DPFPREP, DVF_ERRORLEVEL, "CFullDuplexIPC::Init - already initialized"); hr = DVERR_INITIALIZED; goto error_cleanup; } m_hFullDuplexEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, gc_szFullDuplexEventName); if (m_hFullDuplexEvent == NULL) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open FullDuplex event, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_hFullDuplexReplyEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, gc_szFullDuplexReplyEventName); if (m_hFullDuplexReplyEvent == NULL) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open FullDuplex Reply event, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_hFullDuplexShMemHandle = OpenFileMapping(FILE_MAP_WRITE, FALSE, gc_szFullDuplexShMemName); if (m_hFullDuplexShMemHandle == NULL) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open FullDuplex FileMapping object, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_lpvFullDuplexShMemPtr = MapViewOfFile( m_hFullDuplexShMemHandle, FILE_MAP_WRITE, 0, 0, gc_dwFullDuplexShMemSize); if (m_lpvFullDuplexShMemPtr == NULL) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to Map view of FullDuplex FileMapping object, code: %i", lRet); hr = DVERR_GENERIC; goto error_cleanup; }
m_fInitComplete = TRUE;
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return S_OK;
error_cleanup: if (m_lpvFullDuplexShMemPtr != NULL) { UnmapViewOfFile(m_lpvFullDuplexShMemPtr); m_lpvFullDuplexShMemPtr = NULL; }
if (m_hFullDuplexShMemHandle != NULL) { CloseHandle(m_hFullDuplexShMemHandle); m_hFullDuplexShMemHandle = NULL; }
if (m_hFullDuplexReplyEvent != NULL) { CloseHandle(m_hFullDuplexReplyEvent); m_hFullDuplexReplyEvent = NULL; }
if (m_hFullDuplexEvent != NULL) { CloseHandle(m_hFullDuplexEvent); m_hFullDuplexEvent = NULL; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CFullDuplexIPC::Deinit"
HRESULT CFullDuplexIPC::Deinit() { LONG lRet; HRESULT hr = DV_OK;
DPF_ENTER();
DNEnterCriticalSection(&m_csLock);
if (m_fInitComplete != TRUE) { DPFX(DPFPREP, DVF_ERRORLEVEL, "CFullDuplexIPC::Deinit called on uninitialized object"); hr = DVERR_NOTINITIALIZED; } m_fInitComplete = FALSE;
if (m_lpvFullDuplexShMemPtr != NULL) { UnmapViewOfFile(m_lpvFullDuplexShMemPtr); m_lpvFullDuplexShMemPtr = NULL; }
if (m_hFullDuplexShMemHandle != NULL) { CloseHandle(m_hFullDuplexShMemHandle); m_hFullDuplexShMemHandle = NULL; }
if (m_hFullDuplexReplyEvent != NULL) { CloseHandle(m_hFullDuplexReplyEvent); m_hFullDuplexReplyEvent = NULL; }
if (m_hFullDuplexEvent != NULL) { CloseHandle(m_hFullDuplexEvent); m_hFullDuplexEvent = NULL; } DNLeaveCriticalSection(&m_csLock);
DNDeleteCriticalSection(&m_csLock);
DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CFullDuplexIPC::SignalParentReady"
HRESULT CFullDuplexIPC::SignalParentReady() { BOOL fRet; LONG lRet; DPF_ENTER();
DNEnterCriticalSection(&m_csLock); fRet = SetEvent(m_hFullDuplexReplyEvent); if (!fRet) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Error Setting FullDuplex Event, code: %i", lRet); DPF_EXIT(); return DVERR_WIN32; } DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return DV_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "CFullDuplexIPC::Receive"
HRESULT CFullDuplexIPC::Receive(SFDTestCommand* pfdtc) { HRESULT hr; DPF_ENTER(); DNEnterCriticalSection(&m_csLock);
hr = DoReceive(pfdtc, m_hFullDuplexEvent, m_hFullDuplexReplyEvent, m_lpvFullDuplexShMemPtr);
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "CFullDuplexIPC::Reply"
HRESULT CFullDuplexIPC::Reply(HRESULT hrReply) { HRESULT hr; DPF_ENTER(); DNEnterCriticalSection(&m_csLock);
hr = DoReply(hrReply, m_hFullDuplexReplyEvent, m_lpvFullDuplexShMemPtr);
DNLeaveCriticalSection(&m_csLock); DPF_EXIT(); return hr; }
#undef DPF_MODNAME
#define DPF_MODNAME "DoReceive"
HRESULT DoReceive( SFDTestCommand* pfdtc, HANDLE hEvent, HANDLE hReplyEvent, LPVOID lpvShMemPtr) { DWORD dwRet; LONG lRet;
DPF_ENTER();
dwRet = WaitForSingleObject(hEvent, gc_dwCommandReceiveTimeout); switch (dwRet) { case WAIT_OBJECT_0: // this is the expected signal, continue
break; case WAIT_FAILED: lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Error waiting for event, code: %i", lRet); DPF_EXIT(); return DVERR_WIN32;
case WAIT_TIMEOUT: DPFX(DPFPREP, DVF_ERRORLEVEL, "Timed out waiting to receive command"); DPF_EXIT(); return DVERR_TIMEOUT;
default: DPFX(DPFPREP, DVF_ERRORLEVEL, "Unknown error waiting for event"); DPF_EXIT(); return DVERR_UNKNOWN; } // Copy the command from shared memory to the caller's
// buffer. Ensure the caller's buffer is large enough
if (pfdtc->dwSize < ((SFDTestCommand*)lpvShMemPtr)->dwSize) { // reply to both the sender and receiver that the
// buffer was not large enough! We already have an
// error, so ingore the return code from the reply
// call
DoReply(DVERR_BUFFERTOOSMALL, hReplyEvent, lpvShMemPtr); DPF_EXIT(); return DVERR_BUFFERTOOSMALL; }
CopyMemory(pfdtc, lpvShMemPtr, ((SFDTestCommand*)lpvShMemPtr)->dwSize);
// Let the caller know how much was copied
pfdtc->dwSize = ((SFDTestCommand*)lpvShMemPtr)->dwSize;
// all done.
DPF_EXIT(); return S_OK; }
#undef DPF_MODNAME
#define DPF_MODNAME "DoReply"
HRESULT DoReply(HRESULT hr, HANDLE hReplyEvent, LPVOID lpvShMemPtr) { LONG lRet;
DPF_ENTER();
// Copy the return code to shared memory
*((HRESULT*)lpvShMemPtr) = hr;
// Signal that we have replied
if (!SetEvent(hReplyEvent)) { lRet = GetLastError(); DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to set event, code: %i", lRet); DPF_EXIT(); return DVERR_WIN32; } DPF_EXIT(); return S_OK; }
|