windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dvoice/dxvtlib/fdtipc.cpp
2020-09-26 16:20:57 +08:00

1352 lines
29 KiB
C++

/*==========================================================================;
*
* 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
***************************************************************************/
#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 szPriorityCommandLine[_MAX_PATH+1];
DNEnterCriticalSection(&m_csLock);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
_tcsncpy( szPriorityCommandLine, gc_szPriorityCommand, _MAX_PATH );
szPriorityCommandLine[_MAX_PATH] = 0;
if (!CreateProcess(
NULL,
(LPTSTR) szPriorityCommandLine,
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 szFullDuplexCommandLine[_MAX_PATH+1];
DPF_ENTER();
DNEnterCriticalSection(&m_csLock);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
_tcsncpy( szFullDuplexCommandLine, gc_szFullDuplexCommand, _MAX_PATH );
szFullDuplexCommandLine[_MAX_PATH] = 0;
if (!CreateProcess(
NULL,
(LPTSTR) szFullDuplexCommandLine,
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 "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;
}