388 lines
7.9 KiB
C++
388 lines
7.9 KiB
C++
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ipm_io_c.hxx
|
|
|
|
Abstract:
|
|
|
|
This module contains classes for doing async io in the
|
|
worker process.
|
|
|
|
Author:
|
|
|
|
Michael Courage (MCourage) 22-Feb-1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.hxx"
|
|
#include "ipm.hxx"
|
|
#include "ipm_io_c.hxx"
|
|
|
|
|
|
/**
|
|
* IPMOverlappedCompletionRoutine()
|
|
* Callback function provided in ThreadPoolBindIoCompletionCallback.
|
|
* This function is called by NT thread pool.
|
|
*
|
|
* dwErrorCode Error Code
|
|
* dwNumberOfBytesTransfered Number of Bytes Transfered
|
|
* lpOverlapped Overlapped structure
|
|
*/
|
|
VOID
|
|
WINAPI
|
|
IPMOverlappedCompletionRoutine(
|
|
DWORD dwErrorCode,
|
|
DWORD dwNumberOfBytesTransfered,
|
|
LPOVERLAPPED lpOverlapped
|
|
)
|
|
{
|
|
IO_CONTEXT_C * pIoContext = NULL;
|
|
HRESULT hr = HRESULT_FROM_WIN32(dwErrorCode);
|
|
|
|
//
|
|
// get the context object
|
|
//
|
|
if (lpOverlapped != NULL)
|
|
{
|
|
pIoContext = CONTAINING_RECORD(lpOverlapped,
|
|
IO_CONTEXT_C,
|
|
m_Overlapped);
|
|
}
|
|
if ( pIoContext != NULL)
|
|
{
|
|
WpTrace(WPIPM, (
|
|
DBG_CONTEXT,
|
|
"\n IPMOverlappedCompletionRoutine(%d, %x, pIoContext %x) %s\n",
|
|
dwNumberOfBytesTransfered,
|
|
dwErrorCode,
|
|
pIoContext,
|
|
pIoContext->m_IoType == IPM_IO_WRITE ? "WRITE" : "READ"
|
|
));
|
|
|
|
//
|
|
// do the notification
|
|
//
|
|
switch (pIoContext->m_IoType) {
|
|
case IPM_IO_WRITE:
|
|
pIoContext->m_pContext->NotifyWriteCompletion(
|
|
pIoContext->m_pv,
|
|
dwNumberOfBytesTransfered,
|
|
hr
|
|
);
|
|
break;
|
|
|
|
case IPM_IO_READ:
|
|
pIoContext->m_pContext->NotifyReadCompletion(
|
|
pIoContext->m_pv,
|
|
dwNumberOfBytesTransfered,
|
|
hr
|
|
);
|
|
break;
|
|
|
|
default:
|
|
DBG_ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
delete pIoContext;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
* Creates an i/o handler
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hPipe - A handle to the named pipe to be handled
|
|
* ppPipeIoHandler - receives a pointer to the handler on success
|
|
*
|
|
* Return Value:
|
|
*
|
|
* HRESULT
|
|
*/
|
|
HRESULT
|
|
IO_FACTORY_C::CreatePipeIoHandler(
|
|
IN HANDLE hPipe,
|
|
OUT PIPE_IO_HANDLER ** ppPipeIoHandler
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IO_HANDLER_C * pHandler;
|
|
//
|
|
// create the object
|
|
//
|
|
|
|
pHandler = new IO_HANDLER_C(hPipe);
|
|
|
|
if (pHandler)
|
|
{
|
|
BOOL fBind;
|
|
//
|
|
// bind handle to completion port
|
|
//
|
|
|
|
fBind = ThreadPoolBindIoCompletionCallback(
|
|
pHandler->GetAsyncHandle(),
|
|
IPMOverlappedCompletionRoutine,
|
|
0 );
|
|
if (fBind) {
|
|
*ppPipeIoHandler = pHandler;
|
|
InterlockedIncrement(&m_cPipes);
|
|
|
|
pHandler->Reference();
|
|
|
|
WpTrace(WPIPM, (
|
|
DBG_CONTEXT,
|
|
"Created IO_HANDLER_C (%x) - m_cPipes = %d\n",
|
|
pHandler,
|
|
m_cPipes
|
|
));
|
|
}
|
|
else
|
|
{
|
|
// Error in XspBindIoCompletionCallback()
|
|
LONG rc = GetLastError();
|
|
delete pHandler;
|
|
pHandler = NULL;
|
|
|
|
|
|
WpTrace(WPIPM, (DBG_CONTEXT, "Create IO_HANDLER_C failed, %d\n", rc));
|
|
hr = HRESULT_FROM_WIN32(rc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Closes an i/o handler
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pPipeIoHandler - pointer to the handler to be closed
|
|
*
|
|
* Return Value:
|
|
*
|
|
* HRESULT
|
|
*/
|
|
HRESULT
|
|
IO_FACTORY_C::ClosePipeIoHandler(
|
|
IN PIPE_IO_HANDLER * pPipeIoHandler
|
|
)
|
|
{
|
|
IO_HANDLER_C * pIoHandler = (IO_HANDLER_C *) pPipeIoHandler;
|
|
LONG cPipes;
|
|
|
|
if (pIoHandler) {
|
|
cPipes = InterlockedDecrement(&m_cPipes);
|
|
|
|
WpTrace(WPIPM, (
|
|
DBG_CONTEXT,
|
|
"Closed IO_HANDLER_C (%x) - m_cPipes = %d\n",
|
|
pPipeIoHandler,
|
|
m_cPipes
|
|
));
|
|
|
|
DBG_ASSERT( cPipes >= 0 );
|
|
|
|
pIoHandler->Dereference();
|
|
|
|
return S_OK;
|
|
} else {
|
|
return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Disconnect()
|
|
* Routine Description:
|
|
*
|
|
* Disconnects the named pipe
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* HRESULT
|
|
*
|
|
*/
|
|
HRESULT
|
|
IO_HANDLER_C::Disconnect(
|
|
VOID
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CheckSignature();
|
|
|
|
if (!CloseHandle(GetHandle())) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*Routine Description:
|
|
*
|
|
* Writes data to the pipe
|
|
*
|
|
*Arguments:
|
|
*
|
|
* pContext - the context to be notified on completion
|
|
* pv - a parameter passed to the context
|
|
* pBuff - the data to send
|
|
* cbBuff - number of bytes in the data
|
|
*
|
|
*Return Value:
|
|
*
|
|
* HRESULT
|
|
*/
|
|
HRESULT
|
|
IO_HANDLER_C::Write(
|
|
IN IO_CONTEXT * pContext,
|
|
IN PVOID pv,
|
|
IN const BYTE * pBuff,
|
|
IN DWORD cbBuff
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IO_CONTEXT_C * pIoContext;
|
|
|
|
CheckSignature();
|
|
|
|
//
|
|
// create a context
|
|
//
|
|
pIoContext = new IO_CONTEXT_C;
|
|
if (pIoContext) {
|
|
pIoContext->m_pContext = pContext;
|
|
pIoContext->m_pv = pv;
|
|
pIoContext->m_IoType = IPM_IO_WRITE;
|
|
|
|
memset(&pIoContext->m_Overlapped, 0, sizeof(OVERLAPPED));
|
|
|
|
Reference();
|
|
//
|
|
// write to the pipe
|
|
//
|
|
hr = IpmWriteFile(
|
|
GetHandle(),
|
|
(PVOID) pBuff,
|
|
cbBuff,
|
|
&pIoContext->m_Overlapped
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
Dereference();
|
|
}
|
|
} else {
|
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
delete pIoContext;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*Routine Description:
|
|
*
|
|
* Reads data from the pipe
|
|
*
|
|
*Arguments:
|
|
*
|
|
* pContext - the context to be notified on completion
|
|
* pv - a parameter passed to the context
|
|
* pBuff - the buffer that receives the data
|
|
* cbBuff - size of the buffer
|
|
*
|
|
*Return Value:
|
|
*
|
|
* HRESULT
|
|
*/
|
|
HRESULT
|
|
IO_HANDLER_C::Read(
|
|
IN IO_CONTEXT * pContext,
|
|
IN PVOID pv,
|
|
IN BYTE * pBuff,
|
|
IN DWORD cbBuff
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IO_CONTEXT_C * pIoContext;
|
|
|
|
CheckSignature();
|
|
|
|
//
|
|
// create a context
|
|
//
|
|
pIoContext = new IO_CONTEXT_C;
|
|
if (pIoContext) {
|
|
pIoContext->m_pContext = pContext;
|
|
pIoContext->m_pv = pv;
|
|
pIoContext->m_IoType = IPM_IO_READ;
|
|
|
|
memset(&pIoContext->m_Overlapped, 0, sizeof(OVERLAPPED));
|
|
|
|
Reference();
|
|
//
|
|
// read from the pipe
|
|
//
|
|
hr = IpmReadFile(
|
|
GetHandle(),
|
|
pBuff,
|
|
cbBuff,
|
|
&pIoContext->m_Overlapped
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
Dereference();
|
|
}
|
|
} else {
|
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
delete pIoContext;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// end ipm_io_c.cxx
|
|
//
|
|
|