/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
WrpHelp
Abstract:
This file contains wrapper class implementations.
Author:
Environment:
Win32, C++ w/Exceptions, ATL, COM/OLE
Notes:
--*/
/////////////////////////////////////////////////////////////////////////////
//
// Includes
//
#include "stdafx.h"
#include "wrphelp.h"
#include "scarddef.h"
///////////////////////////////////////////////////////////////////////////
// Macros
//
#ifdef _DEBUG
#define TRACE_STR(name,sz) \
TRACE(_T("WrpHelp Classes::%s: %s\n"), name, sz)
#define TRACE_CODE(name,code) \
TRACE(_T("WrpHelp Classes::%s: error = 0x%x\n"), name, code)
#define TRACE_CATCH(name,code) TRACE_CODE(name,code)
#define TRACE_CATCH_UNKNOWN(name) TRACE_STR(name,_T("An unidentified exception has occurred!"))
#else
#define TRACE_STR(name,sz) ((void)0)
#define TRACE_CODE(name,code) ((void)0)
#define TRACE_CATCH(name,code) ((void)0)
#define TRACE_CATCH_UNKNOWN(name) ((void)0)
#endif // _DEBUG
///////////////////////////////////////////////////////////////////////////////
//
// Construction and Destruction
//
/*++
CCriticalSection::CCriticalSection
This method implements the constructor for CCriticalSection
Arguments:
None
Return Value:
None
Author:
--*/
CCriticalSection::CCriticalSection()
{
// locals
// Initialize the internal critical section object
try {
::InitializeCriticalSection(&m_CriticalSection);
}
catch (...){
TRACE_CATCH_UNKNOWN(_T("CCriticalSection"));
}
}
/*++
CCriticalSection::~CCriticalSection
This method implements the destructor for CCriticalSection
Arguments:
None
Return Value:
None
Author:
--*/
CCriticalSection::~CCriticalSection()
{
// locals
try {
::DeleteCriticalSection(&m_CriticalSection);
}
catch(...) {
TRACE_CATCH_UNKNOWN(_T("~CriticalSection"));
}
}
/////////////////////////////////////////////////////////////////////////////////////
//
// CCriticalSection
//
/*++
CCriticalSection::EnterCriticalSection
This routines puts the internal critical section
object into the non-signaled state
Arguments:
None
Return Value:
None
Author:
--*/
CCriticalSection::EnterCriticalSection()
{
// Locals
BOOL fResult = FALSE;
try {
::EnterCriticalSection(&m_CriticalSection);
// Ok...
fResult = TRUE;
}
catch (...) {
TRACE_CATCH_UNKNOWN(_T("EnterCriticalSection"));
}
return fResult;
}
/*++
CCriticalSection::ExitCriticalSection
This routines puts the internal critical section
object into the signaled state
Arguments:
None
Return Value:
None
Author:
Chris Dudley (cdudley) 2/6/1997
--*/
CCriticalSection::ExitCriticalSection()
{
// Locals
BOOL fResult = FALSE;
try {
::LeaveCriticalSection(&m_CriticalSection);
// Ok...
fResult = TRUE;
}
catch (...) {
TRACE_CATCH_UNKNOWN(_T("EnterCriticalSection"));
}
return fResult;
}
///////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
//
// CGrabData
//
/*++
CGrabData::GetExtraData
This routine calls the ISO7816-4 command GetResponse to get additional
data from the card and return it in the IByteBuffer (aka IStream)
Arguments:
ppDataOut - pointer to a pointer to an IByteBuffer. If this pointer is
NULL, the IStream will be created but MUST be release in caller's
code.
pwCmdStatus - (IN) The status word (SW1/SW2) returned from the initial smart card
command.
(OUT) the final status word.
pdwDataLength - (OUT) Total number of bytes written into the buffer.
Return Value:
A HRESULT value indicating the status of the requested action.
Return Meaning
====== =======
E_INVALIDARG An argument was invalid or unrecognizable.
E_OUTOFMEMORY No free memory in process address space
to create requested object.
E_UNEXPECTED One of the parameters was of an unexpected
type or value.
S_OK Command successful.
Author:
Notes:
This routine expects (*pwCmdStatus) to contain a 0x61xx response code where
xx is the number of bytes to be retrieved by the GetResponse.
--*/
HRESULT CGrabData::GetExtraData(LPBYTEBUFFER *ppDataOut,
WORD *pwCmdStatus,
LONG *plDataLength)
{
// Locals
HRESULT hresult = S_OK;
LONG lSize;
LPBYTEBUFFER pBuffer;
ULARGE_INTEGER liBytesToCopy,
liBytesRead,
liBytesWritten,
liLength;
try {
// clear length
(*plDataLength) = 0;
// Create buffers if needed...1 for GetResponse, another to copy into
if ( (*ppDataOut) == NULL) {
hresult = m_pISCardTypeConv->CreateByteBuffer((ULONG) 1,
ppDataOut);
if (FAILED(hresult))
throw (hresult);
};// if
hresult = m_pISCardTypeConv->CreateByteBuffer((ULONG) 1,
&pBuffer);
if (FAILED(hresult))
throw (hresult);
// Check status
m_wReplyStatus = (*pwCmdStatus);
while(HIBYTE(m_wReplyStatus) == SC_STATUS_MOREDATA){
lSize = LOBYTE( m_wReplyStatus );
// Build the command
hresult = m_pISCardISO7816->GetResponse((BYTE) 0,
(BYTE) 0,
lSize,
&m_pISCardCmd);
if (FAILED(hresult))
throw (hresult);
// Force correct class id for the vendor's card
hresult = m_pISCardCmd->put_ClassId(VENDOR_CLASS_ID);
if (FAILED(hresult))
throw (hresult);
// Do transaction
hresult = m_pISCard->LockSCard();
if (FAILED(hresult))
throw (hresult);
hresult = m_pISCard->Transaction(&m_pISCardCmd);
if (FAILED(hresult))
throw (hresult);
hresult = m_pISCard->UnlockSCard(LEAVE);
if (FAILED(hresult))
throw (hresult);
// Interpret response
hresult = m_pISCardCmd->get_ApduReplyLength(&m_lReplyLength);
if (FAILED(hresult))
throw (hresult);
hresult = m_pISCardCmd->get_ReplyStatus( &m_wReplyStatus );
if (FAILED(hresult))
throw (hresult);
if ( (m_wReplyStatus != SC_STATUS_SUCCESS) &&
(HIBYTE(m_wReplyStatus) != SC_STATUS_MOREDATA ))
throw ( (HRESULT) E_FAIL);
// Get reply data
hresult = m_pISCardCmd->get_ApduReply( &pBuffer );
if (FAILED(hresult))
throw (hresult);
// Copy it into given Internal IStream. First set new Length.
// Don't REALLY have to do this. The IStream Copy would take care of it...
(*plDataLength) += m_lReplyLength;
LISet32 (liLength, (*plDataLength));
hresult = (*ppDataOut)->SetSize((LONG) liLength.LowPart);
if (FAILED(hresult))
throw (hresult);
LISet32 (liBytesToCopy, m_lReplyLength );
hresult = (pBuffer)->CopyTo(ppDataOut,
(LONG) liBytesToCopy.LowPart,
(LONG*) &(liBytesRead.LowPart),
(LONG*) &(liBytesWritten.LowPart));
if (FAILED(hresult))
throw (hresult);
}; //while
}
catch (HRESULT hr) {
hresult = hr;
TRACE_CATCH(_T("GetResultData"),hr);
}
catch (...) {
hresult = (HRESULT) E_UNEXPECTED;
TRACE_CATCH_UNKNOWN(_T("GetResultData"));
}
// Release resources...Cleanup
if (pBuffer != NULL)
while (pBuffer->Release()>0);
(*pwCmdStatus) = m_wReplyStatus;
return hresult;
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//
// Various Useful routines
//
/*++
SspCreateByteArray:
This routine creates an array of bytes.
Arguments:
dwAllocSize - Size in bytes of the memory to be allocated for the array.
ppbyArray - Points to the created byte array to be returned.
pExceptInfo - Points to an OLE exception block which contains extended
information about any failure that might occur. Can be set to
NULL if the exception information is not desired.
Return Value:
A HRESULT value indicating the status of the requested action.
Return Meaning
====== =======
S_OK The byte array was created successfully.
S_FALSE Unknown error.
E_OUTOFMEMORY There is not enough memory in this process to
satisfy the request.
E_FAIL Unspecified error.
E_INVALIDARG One or more arguments are invalid.
E_HANDLE Invalid handle.
E_POINTER Invalid pointer.
E_UNEXPECTED Unexpected fault has occurred.
Author:
--*/
HRESULT
SspCreateByteArray(
IN DWORD dwAllocSize,
OUT LPBYTE *ppbyArray,
OUT OPTIONAL EXCEPINFO* pExceptInfo)
{
// Locals.
HRESULT hr = S_OK;
HGLOBAL hMem = NULL;
LPBYTE pObj = NULL;
DWORD dwErr = NO_ERROR;
try
{
// Initialize the parameters.
(*ppbyArray) = NULL;
// Is caller asking for a reasonable array size?
if (dwAllocSize <= 0)
throw ( (HRESULT) E_INVALIDARG);
// Allocate the memory for the array from the system.
hMem = ::GlobalAlloc(GHND, dwAllocSize);
if (hMem == NULL)
{
dwErr = ::GetLastError();
throw (HRESULT_FROM_WIN32(dwErr));
}
// Map the memory for use.
pObj = (LPBYTE) GlobalLock(hMem);
if (pObj == NULL)
{
dwErr = ::GetLastError();
throw (HRESULT_FROM_WIN32(dwErr));
}
ASSERT(pObj != NULL);
// Ok, pack for return.
(*ppbyArray) = pObj;
}
catch (HRESULT hrStatus)
{
hr = hrStatus;
TRACE_CATCH(_T("SspCreateByteArray"),hrStatus);
if (pObj!=NULL)
::GlobalUnlock(hMem);
if (hMem!=NULL)
::GlobalFree(hMem);
switch (hr)
{
case E_UNEXPECTED:
case E_POINTER:
case E_INVALIDARG:
::SetLastError( (DWORD) ERROR_INVALID_PARAMETER);
break;
case S_FALSE:
case E_FAIL:
::SetLastError((DWORD) ERROR_NOT_SUPPORTED);
break;
case E_ACCESSDENIED:
::SetLastError((DWORD)ERROR_ACCESS_DENIED);
break;
case E_HANDLE:
::SetLastError((DWORD) ERROR_INVALID_HANDLE);
break;
case E_OUTOFMEMORY:
::SetLastError((DWORD) ERROR_OUTOFMEMORY);
break;
default:
::SetLastError(dwErr);
break;
}
}
catch (...)
{
TRACE_CATCH_UNKNOWN(_T("SspCreateByteArray"));
if (pObj != NULL)
::GlobalUnlock(hMem);
if (hMem != NULL)
::GlobalFree(hMem);
::SetLastError( (DWORD) ERROR_INVALID_PARAMETER);
hr = (HRESULT) E_UNEXPECTED;
}
return (hr);
}
/*++
SspConvertDwordToByte:
This function will convert a DWORD to an array of BYTEs.
Arguments:
dwNum - DWORD number to be converted.
ppbyArray - Points to the byte array created to hold the converted
DWORD if successful; else, NULL!
pdwByteArraySize - Optional pointer to how big was the byte array
created to hold the DWORD is.
pExceptInfo - Points to an OLE exception block which contains extended
information about any failure that might occur. Can be set to
NULL if the exception information is not desired.
Return Value:
A HRESULT value indicating the status of the requested action.
Return Meaning
====== =======
S_OK Operation completed successfully.
S_FALSE Unknown error.
E_OUTOFMEMORY There is not enough memory in this process to
satisfy the request.
E_FAIL Unspecified error.
E_INVALIDARG One or more arguments are invalid.
E_POINTER Invalid pointer.
E_UNEXPECTED Unexpected event occurred in this function.
E_HANDLE Invalid handle.
E_ACCESSDENIED Access to resource is denied.
Author:
--*/
HRESULT
SspConvertDwordToByte(
IN DWORD dwNum,
OUT LPBYTE *ppbyArray,
OUT LPDWORD pdwByteArraySize,
OUT OPTIONAL EXCEPINFO* pExceptInfo)
{
// Locals.
LPBYTE pbyBuff = NULL;
HRESULT hr = S_OK;
DWORD dwSize = 0;
try
{
// Initialize...
if ((*ppbyArray))
(*ppbyArray) = NULL;
if (pdwByteArraySize)
(*pdwByteArraySize) = 0;
// Determine the appropriately sized byte array needed
// to hold DWORD.
if (dwNum <= 0xFF)
dwSize = 1;
else if (dwNum <= 0xFFFF)
dwSize = 2;
else if (dwNum <= 0xFFFFFF)
dwSize = 3;
else
throw ( (HRESULT) E_INVALIDARG);
// Create the byte array.
hr = SspCreateByteArray(dwSize,
&pbyBuff,
NULL);
if (FAILED(hr))
throw (hr);
if (pbyBuff == NULL)
throw ( (HRESULT) E_OUTOFMEMORY);
ASSERT(pbyBuff != NULL);
// Copy it!
::CopyMemory( (LPVOID) pbyBuff,
(CONST VOID*) &dwNum,
(DWORD) sizeof(DWORD) );
// Package for return.
*ppbyArray = pbyBuff;
if (pdwByteArraySize != NULL)
(*pdwByteArraySize) = dwSize;
}
catch (HRESULT hrStatus)
{
hr = hrStatus;
TRACE_CATCH(_T("SspConvertDwordToByte"),hrStatus);
switch (hr)
{
case E_UNEXPECTED:
case E_POINTER:
case E_INVALIDARG:
::SetLastError((DWORD) ERROR_INVALID_PARAMETER);
break;
case S_FALSE:
case E_FAIL:
::SetLastError((DWORD) ERROR_NOT_SUPPORTED);
break;
case E_ACCESSDENIED:
::SetLastError((DWORD) ERROR_ACCESS_DENIED);
break;
case E_HANDLE:
::SetLastError((DWORD) ERROR_INVALID_HANDLE);
break;
case E_OUTOFMEMORY:
::SetLastError((DWORD) ERROR_OUTOFMEMORY);
break;
}
}
catch (...)
{
TRACE_CATCH_UNKNOWN(_T("SspConvertDwordToByte"));
::SetLastError((DWORD) ERROR_INVALID_PARAMETER);
hr = (HRESULT) E_UNEXPECTED;
}
return (hr);
}
/*++
SspFreeByteArray:
This routine frees a byte array (aka a block of HGLOBAL memory).
Arguments:
pbyArray - Points to the byte array to be freed.
pExceptInfo - Points to an OLE exception block which contains extended
information about any failure that might occur. Can be set to
NULL if the exception information is not desired.
Return Value:
A HRESULT value indicating the status of the requested action.
Return Meaning
====== =======
S_OK The byte array was created freed.
S_FALSE Unknown error.
E_OUTOFMEMORY There is not enough memory in this process to
satisfy the request.
E_FAIL Unspecified error.
E_INVALIDARG One or more arguments are invalid.
E_UNEXPECTED Unexpected fault has occurred.
E_POINTER Invalid pointer.
E_HANDLE Invalid handle.
E_ACCESSDENIED Access to resource is denied.
Author:
--*/
HRESULT
SspFreeByteArray(
IN LPBYTE pbyArray,
OUT OPTIONAL EXCEPINFO* pExceptInfo)
{
// Locals.
DWORD dwErr = NO_ERROR;
HGLOBAL hMem = NULL;
HRESULT hr = S_OK;
try
{
// Is the parameter-list ok?
if (pbyArray == NULL)
throw ( (HRESULT) E_POINTER);
// Get access to the string's memory block.
hMem = ::GlobalHandle((LPCVOID) pbyArray);
if (hMem == NULL)
{
dwErr = ::GetLastError();
throw (HRESULT_FROM_WIN32(dwErr));
}
ASSERT(hMem != NULL);
// Decrement the memory block's reference count.
while (::GlobalUnlock(hMem));
dwErr = ::GetLastError();
if (dwErr != NO_ERROR)
throw (HRESULT_FROM_WIN32(dwErr));
// Free the memory!
hMem = ::GlobalFree(hMem);
if (hMem == NULL)
{
dwErr = ::GetLastError();
throw (HRESULT_FROM_WIN32(dwErr));
}
ASSERT(hMem == NULL);
}
catch (HRESULT hrStatus)
{
hr = hrStatus;
TRACE_CATCH(_T("SspFreeByteArray"),hrStatus);
switch (hr)
{
case E_UNEXPECTED:
case E_POINTER:
case E_INVALIDARG:
::SetLastError((DWORD) ERROR_INVALID_PARAMETER);
break;
case S_FALSE:
case E_FAIL:
::SetLastError((DWORD) ERROR_NOT_SUPPORTED);
break;
case E_ACCESSDENIED:
::SetLastError((DWORD) ERROR_ACCESS_DENIED);
break;
case E_HANDLE:
::SetLastError((DWORD) ERROR_INVALID_HANDLE);
break;
case E_OUTOFMEMORY:
::SetLastError((DWORD) ERROR_OUTOFMEMORY);
break;
default:
::SetLastError(dwErr);
break;
}
}
catch (...)
{
TRACE_CATCH_UNKNOWN(_T("SspFreeByteArray"));
::SetLastError((DWORD) ERROR_INVALID_PARAMETER);
hr = (HRESULT) E_UNEXPECTED;
}
return (hr);
}