310 lines
6.3 KiB
C++
310 lines
6.3 KiB
C++
// Inproc.cpp
|
|
|
|
#include "precomp.h"
|
|
#include "Inproc.h"
|
|
#include "NCDefs.h"
|
|
#include "DUtils.h"
|
|
#include "Connection.h"
|
|
|
|
CInprocClient::CInprocClient() :
|
|
m_pSrvBuffer(NULL),
|
|
m_hthreadReady(NULL),
|
|
m_heventProviderReady(NULL),
|
|
m_heventDone(NULL),
|
|
m_bDone(FALSE),
|
|
m_hProv(NULL)
|
|
{
|
|
}
|
|
|
|
CInprocClient::~CInprocClient()
|
|
{
|
|
Deinit();
|
|
}
|
|
|
|
CInprocClient::IsReady()
|
|
{
|
|
return m_pSrvBuffer != NULL;
|
|
}
|
|
|
|
BOOL CInprocClient::SendData(LPBYTE pBuffer, DWORD dwSize)
|
|
{
|
|
BOOL bWritten;
|
|
|
|
#ifdef NO_SEND
|
|
bWriten = TRUE;
|
|
#else
|
|
if (m_pSrvBuffer != NULL)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr =
|
|
m_pSrvBuffer->PostBuffer(
|
|
pBuffer,
|
|
dwSize);
|
|
|
|
if (SUCCEEDED(hr))
|
|
bWritten = TRUE;
|
|
else
|
|
{
|
|
bWritten = FALSE;
|
|
|
|
TRACE("Failed to send buffer to server.");
|
|
|
|
DeinitBuffer();
|
|
|
|
// Start watching for our provider to be ready, and get the server
|
|
// buffer.
|
|
if(!StartReadyThreadProc())
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
bWritten = FALSE;
|
|
#endif
|
|
|
|
return bWritten;
|
|
}
|
|
|
|
void CInprocClient::Deinit()
|
|
{
|
|
if (m_hthreadReady)
|
|
{
|
|
m_bDone = TRUE;
|
|
|
|
SetEvent(m_heventDone);
|
|
WaitForSingleObject(m_hthreadReady, INFINITE);
|
|
CloseHandle(m_hthreadReady);
|
|
|
|
m_hthreadReady = NULL;
|
|
}
|
|
|
|
DeinitBuffer();
|
|
|
|
if (m_heventDone)
|
|
{
|
|
CloseHandle(m_heventDone);
|
|
m_heventDone = NULL;
|
|
}
|
|
|
|
Release();
|
|
}
|
|
|
|
// There's nothing to send in the inproc case.
|
|
void CInprocClient::SendMsgReply(NC_SRVMSG_REPLY *pReply)
|
|
{
|
|
}
|
|
|
|
// Init function.
|
|
BOOL CInprocClient::Init(LPCWSTR szBaseNamespace, LPCWSTR szBaseProvider)
|
|
{
|
|
WCHAR szReadyEventName[256];
|
|
|
|
// Get the ready event.
|
|
swprintf(
|
|
szReadyEventName,
|
|
OBJNAME_EVENT_READY L"%s%s",
|
|
szBaseNamespace,
|
|
szBaseProvider);
|
|
|
|
m_heventProviderReady =
|
|
CreateEventW(
|
|
NULL,
|
|
TRUE,
|
|
FALSE,
|
|
szReadyEventName);
|
|
if(m_heventProviderReady == NULL)
|
|
return FALSE;
|
|
|
|
|
|
// Construct the pipe name.
|
|
swprintf(
|
|
m_szPipeName,
|
|
L"\\\\.\\pipe\\" OBJNAME_NAMED_PIPE L"%s%s",
|
|
szBaseNamespace,
|
|
szBaseProvider);
|
|
|
|
m_heventDone =
|
|
CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
if(m_heventDone == NULL)
|
|
return FALSE;
|
|
|
|
// Before we start the thread see if our provider is ready right off
|
|
// the bat.
|
|
if (WaitForSingleObject(m_heventProviderReady, 1) != WAIT_OBJECT_0 ||
|
|
!GetBuffer())
|
|
{
|
|
if(!StartReadyThreadProc())
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CInprocClient::SignalProviderDisabled()
|
|
{
|
|
if (m_pSrvBuffer != NULL)
|
|
{
|
|
m_pConnection->IndicateProvDisabled();
|
|
|
|
DeinitBuffer();
|
|
|
|
if(!StartReadyThreadProc())
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CInprocClient::StartReadyThreadProc()
|
|
{
|
|
DWORD dwID;
|
|
|
|
if (m_hthreadReady)
|
|
CloseHandle(m_hthreadReady);
|
|
|
|
m_hthreadReady =
|
|
CreateThread(
|
|
NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE) ProviderReadyThreadProc,
|
|
this,
|
|
0,
|
|
&dwID);
|
|
if(m_hthreadReady == NULL)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CInprocClient::DeinitBuffer()
|
|
{
|
|
CInCritSec cs(&m_cs);
|
|
|
|
// Close the pipe.
|
|
if (m_pSrvBuffer != NULL)
|
|
{
|
|
m_pSrvBuffer->Release();
|
|
m_pSrvBuffer = NULL;
|
|
}
|
|
|
|
if (m_hProv != NULL)
|
|
{
|
|
FreeLibrary(m_hProv);
|
|
|
|
m_hProv = NULL;
|
|
}
|
|
}
|
|
|
|
// We don't need to add anything else to the buffer.
|
|
BOOL CInprocClient::InitCallback()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
#define NC_PROV_NAME L"NCProv.dll"
|
|
|
|
typedef BOOL (WINAPI *FPINPROC_CONNECT)(LPCWSTR, IPostBuffer*, IPostBuffer**);
|
|
|
|
BOOL CInprocClient::GetBuffer()
|
|
{
|
|
TRACE("Attempting to get server buffer...");
|
|
|
|
CInCritSec cs(&m_cs);
|
|
|
|
SetLastError(0);
|
|
|
|
#define MAX_RETRIES 10
|
|
|
|
if (m_pSrvBuffer == NULL)
|
|
{
|
|
// Get the server's buffer.
|
|
HANDLE hProv = GetModuleHandleW(NC_PROV_NAME);
|
|
|
|
// Make sure the 'real' event provider has been loaded.
|
|
if (hProv != NULL)
|
|
{
|
|
// Increase the ref count on the library so it doesn't ever get
|
|
// pulled out from under us.
|
|
m_hProv = LoadLibraryW(NC_PROV_NAME);
|
|
|
|
if (m_hProv != NULL)
|
|
{
|
|
FPINPROC_CONNECT fpInprocConnect;
|
|
|
|
fpInprocConnect =
|
|
(FPINPROC_CONNECT) GetProcAddress(m_hProv, "InprocConnect");
|
|
|
|
if (fpInprocConnect)
|
|
{
|
|
BOOL bRet;
|
|
|
|
bRet =
|
|
fpInprocConnect(
|
|
m_szPipeName,
|
|
this,
|
|
&m_pSrvBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_pSrvBuffer != NULL)
|
|
{
|
|
TRACE("Got the server buffer, calling IncEnabledCount.");
|
|
|
|
if(!m_pConnection->IndicateProvEnabled())
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
TRACE("Failed to get server buffer.");
|
|
|
|
DeinitBuffer();
|
|
}
|
|
}
|
|
else
|
|
TRACE("Already have a valid server buffer.");
|
|
|
|
return m_pSrvBuffer != NULL;
|
|
}
|
|
|
|
DWORD WINAPI CInprocClient::ProviderReadyThreadProc(CInprocClient *pThis)
|
|
{
|
|
HANDLE hwaitReady[2] = { pThis->m_heventDone, pThis->m_heventProviderReady };
|
|
|
|
TRACE("(Inproc) Waiting for provider ready event.");
|
|
|
|
while (WaitForMultipleObjects(2, hwaitReady, FALSE, INFINITE) == 1 &&
|
|
!pThis->GetBuffer())
|
|
{
|
|
Sleep(100);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// IPostBuffer
|
|
ULONG CInprocClient::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_iRef);
|
|
}
|
|
|
|
ULONG CInprocClient::Release()
|
|
{
|
|
LONG lRet = InterlockedDecrement(&m_iRef);
|
|
|
|
if (!lRet)
|
|
delete this;
|
|
|
|
return lRet;
|
|
}
|
|
|
|
HRESULT CInprocClient::PostBuffer(LPBYTE pData, DWORD dwSize)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = m_pConnection->ProcessMessage(pData, dwSize);
|
|
|
|
return hr;
|
|
}
|
|
|