/*==========================================================================; * * 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; }