You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
7.4 KiB
321 lines
7.4 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
|
|
Module Name:
|
|
|
|
ComChanl
|
|
|
|
Abstract:
|
|
|
|
This module implements the CComChannel Communications Class
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 10/30/1996
|
|
|
|
Environment:
|
|
|
|
Win32, C++ w/ Exceptions
|
|
|
|
Notes:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
#define __SUBROUTINE__
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#include <WinSCard.h>
|
|
#include <CalMsgs.h>
|
|
#include <CalCom.h>
|
|
|
|
|
|
//
|
|
//==============================================================================
|
|
//
|
|
// CComChannel
|
|
//
|
|
|
|
/*++
|
|
|
|
CComChannel:
|
|
|
|
This is the standard constructor and destructor for the Comm Channel
|
|
class. They just call the clean and clear functions, respectively.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Throws:
|
|
|
|
None
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 10/30/1996
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ DBGT("CComChannel::CComChannel")
|
|
|
|
CComChannel::CComChannel(
|
|
HANDLE hPipe)
|
|
: m_hPipe(DBGT("CComChannel connection pipe")),
|
|
m_hProc(DBGT("CComChannel process handle")),
|
|
m_hOvrWait(DBGT("CComChannel overlapped I/O event"))
|
|
{
|
|
m_hPipe = hPipe;
|
|
ZeroMemory(&m_ovrlp, sizeof(m_ovrlp));
|
|
m_ovrlp.hEvent = m_hOvrWait = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
if (!m_hOvrWait.IsValid())
|
|
{
|
|
DWORD dwErr = m_hOvrWait.GetLastError();
|
|
CalaisWarning(
|
|
__SUBROUTINE__,
|
|
DBGT("Comm Responder failed to create overlapped event: %1"),
|
|
dwErr);
|
|
throw dwErr;
|
|
}
|
|
}
|
|
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ DBGT("CComChannel::~CComChannel")
|
|
CComChannel::~CComChannel()
|
|
{
|
|
if (m_hPipe.IsValid())
|
|
m_hPipe.Close();
|
|
if (m_hProc.IsValid())
|
|
m_hProc.Close();
|
|
if (m_hOvrWait.IsValid())
|
|
m_hOvrWait.Close();
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Send:
|
|
|
|
Send data over the communications channel.
|
|
|
|
Arguments:
|
|
|
|
pvData supplies the data to be written.
|
|
cbLen supplies the length of the data, in bytes.
|
|
|
|
Return Value:
|
|
|
|
A DWORD status code.
|
|
|
|
Throws:
|
|
|
|
None.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 11/4/1996
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ DBGT("CComChannel::Send")
|
|
|
|
DWORD
|
|
CComChannel::Send(
|
|
LPCVOID pvData,
|
|
DWORD cbLen)
|
|
{
|
|
BOOL fSts;
|
|
DWORD dwLen, dwOffset = 0;
|
|
DWORD dwSts = SCARD_S_SUCCESS;
|
|
|
|
while (0 < cbLen)
|
|
{
|
|
fSts = WriteFile(
|
|
m_hPipe,
|
|
&((LPBYTE)pvData)[dwOffset],
|
|
cbLen,
|
|
&dwLen,
|
|
&m_ovrlp);
|
|
if (!fSts)
|
|
{
|
|
BOOL fErrorProcessed;
|
|
dwSts = GetLastError();
|
|
|
|
do
|
|
{
|
|
fErrorProcessed = TRUE;
|
|
switch (dwSts)
|
|
{
|
|
//
|
|
// Postpone processing
|
|
case ERROR_IO_PENDING:
|
|
fErrorProcessed = FALSE;
|
|
WaitForever(
|
|
m_ovrlp.hEvent,
|
|
REASONABLE_TIME,
|
|
DBGT("Comm Channel response write"),
|
|
(DWORD)0);
|
|
fSts = GetOverlappedResult(
|
|
m_hPipe,
|
|
&m_ovrlp,
|
|
&dwLen,
|
|
TRUE);
|
|
dwSts = fSts ? ERROR_SUCCESS : GetLastError();
|
|
break;
|
|
|
|
//
|
|
// Success after a wait event.
|
|
case ERROR_SUCCESS:
|
|
break;
|
|
|
|
//
|
|
// The pipe may have been closed, for instance, the context
|
|
// may have been marked invalid as a result of a session
|
|
// change.
|
|
case ERROR_BROKEN_PIPE:
|
|
case ERROR_INVALID_HANDLE:
|
|
throw (DWORD)ERROR_BROKEN_PIPE;
|
|
break;
|
|
|
|
//
|
|
// Some other error.
|
|
default:
|
|
CalaisWarning(
|
|
__SUBROUTINE__,
|
|
DBGT("Comm Channel could not write to pipe: %1"),
|
|
dwSts);
|
|
goto ErrorExit;
|
|
}
|
|
} while (!fErrorProcessed);
|
|
}
|
|
cbLen -= dwLen;
|
|
}
|
|
|
|
ErrorExit:
|
|
return dwSts;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Receive:
|
|
|
|
This method receives a given number of bytes from the communications
|
|
channel.
|
|
|
|
Arguments:
|
|
|
|
pvData receives the incoming bytes.
|
|
cbLen supplies the length of the data expected.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
Throws:
|
|
|
|
Transmission errors as a DWORD.
|
|
|
|
Author:
|
|
|
|
Doug Barlow (dbarlow) 11/4/1996
|
|
|
|
--*/
|
|
#undef __SUBROUTINE__
|
|
#define __SUBROUTINE__ DBGT("CComChannel::Receive")
|
|
|
|
void
|
|
CComChannel::Receive(
|
|
LPVOID pvData,
|
|
DWORD cbLen)
|
|
{
|
|
BOOL fSts;
|
|
DWORD dwLen, dwOffset = 0;
|
|
|
|
while (0 < cbLen)
|
|
{
|
|
fSts = ReadFile(
|
|
m_hPipe,
|
|
&((LPBYTE)pvData)[dwOffset],
|
|
cbLen,
|
|
&dwLen,
|
|
&m_ovrlp);
|
|
if (!fSts)
|
|
{
|
|
BOOL fErrorProcessed;
|
|
DWORD dwSts = GetLastError();
|
|
DWORD dwWait;
|
|
|
|
do
|
|
{
|
|
fErrorProcessed = TRUE;
|
|
switch (dwSts)
|
|
{
|
|
//
|
|
// Postpone processing
|
|
case ERROR_IO_PENDING:
|
|
dwWait = WaitForAnyObject(
|
|
INFINITE,
|
|
m_ovrlp.hEvent,
|
|
g_hCalaisShutdown, // Make sure this is last
|
|
NULL);
|
|
switch (dwWait)
|
|
{
|
|
case 1:
|
|
fErrorProcessed = FALSE;
|
|
fSts = GetOverlappedResult(
|
|
m_hPipe,
|
|
&m_ovrlp,
|
|
&dwLen,
|
|
TRUE);
|
|
dwSts = fSts ? ERROR_SUCCESS : GetLastError();
|
|
break;
|
|
case 2:
|
|
throw (DWORD)SCARD_P_SHUTDOWN;
|
|
break;
|
|
default:
|
|
CalaisWarning(
|
|
__SUBROUTINE__,
|
|
DBGT("Wait for comm pipe receive returned invalid value"));
|
|
throw (DWORD)SCARD_F_INTERNAL_ERROR;
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Success after a wait event.
|
|
case ERROR_SUCCESS:
|
|
break;
|
|
|
|
//
|
|
// The client exited.
|
|
case ERROR_BROKEN_PIPE:
|
|
case ERROR_INVALID_HANDLE:
|
|
throw (DWORD)ERROR_BROKEN_PIPE;
|
|
break;
|
|
|
|
//
|
|
// Some other error.
|
|
default:
|
|
CalaisWarning(
|
|
__SUBROUTINE__,
|
|
DBGT("Comm Channel could not read from pipe: %1"),
|
|
dwSts);
|
|
throw dwSts;
|
|
}
|
|
} while (!fErrorProcessed);
|
|
}
|
|
|
|
ASSERT(dwLen <= cbLen);
|
|
cbLen -= dwLen;
|
|
dwOffset += dwLen;
|
|
}
|
|
}
|
|
|