📄 scardtpl.cpp
字号:
//******************************************************************************
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//******************************************************************************
/*++
Module Name:
Scardtpl.cpp
Abstract:
implementation of class and supported classes that include tests for tuple APIs
--*/
// PCMCIA tests of:
// CardGetFirstTuple
// CardGetNextTuple
// CardGetTupleData
// CardGetParsedTuple
#include "TestMain.h"
#include "common.h"
#include "scardtpl.h"
#include "tpltest.h"
//------------------------------ Utility functions --------------------------
// This test for modem vs. memory card is derived
static PCARD_TUPLE_PARMS newCopy (PCARD_TUPLE_PARMS p){
PCARD_TUPLE_PARMS q = new CARD_TUPLE_PARMS ;
if (!q)
return 0 ;
memcpy (q, p, sizeof (CARD_TUPLE_PARMS)) ;
return q ;
}
// Warning, this requires sizeOfP >= sizeof(CARD_DATA_PARMS)
static PCARD_DATA_PARMS newCopy (PCARD_DATA_PARMS p, UINT32 sizeOfP){
PUCHAR q = new UCHAR [sizeOfP] ;
if (!q )
return 0 ;
if(sizeOfP < sizeof(CARD_DATA_PARMS)) {
delete[] q;
return 0;
}
memset (q, 0, sizeOfP) ;
memcpy (q, p, sizeof(CARD_DATA_PARMS)) ;
return (PCARD_DATA_PARMS) q ;
}
// Warning, this is dangerous because p->uTupleLink may not be initialized.
static PCARD_DATA_PARMS newDataParmsFromTupleParms (PCARD_TUPLE_PARMS p){
UINT16 size = p->uTupleLink + sizeof (CARD_DATA_PARMS) ;
if (!size)
return 0 ;
PCARD_DATA_PARMS q = (PCARD_DATA_PARMS) new UCHAR [size] ;
if (!q)
return 0 ;
memset (q, 0, size) ;
memcpy (q, p, sizeof (CARD_TUPLE_PARMS)) ;
q->uBufLen = p->uTupleLink ;
q->uDataLen = 0 ;
q->uTupleOffset = 0 ; // This was a BIG gotcha.
return q ;
}
//------------------------------ SCardTuple ---------------------------------
#define TUPLE_LINK_ZONE 0x001F // All of the following bits
#define TUPLE_FLAG_COMMON 0x0001 // Tuples are in common memory
#define TUPLE_FLAG_LINK_TO_A 0x0002 // Link to attribute memory
#define TUPLE_FLAG_LINK_TO_C 0x0004 // Link to common memory
#define TUPLE_FLAG_NO_LINK 0x0008 // Do not take a link at CISTPL_END
#define TUPLE_FLAG_IMPLIED_LINK 0x0010 // If attribute first byte is 0xFF.
SCardTuple::SCardTuple (UINT8 cisTplCode, UINT8 length, PCARD_DATA_PARMS pParms){
uTupleCode = cisTplCode ;
uTupleLink = length ;
fFlags = pParms->fFlags ;
uCISOffset = pParms->uCISOffset ;
uLinkOffset = 0 ;
pTupleData = NULL ;
parsedBuf = 0 ;
parsedSize = 0 ;
nParsedItems = 0 ;
link = 0 ;
// Try to verify that we have a whole tuple, and set the tuple data.
if (!pParms->uDataLen || (pParms->uDataLen != uTupleLink)){
pTupleData = NULL ;
uTupleLink = 0 ;
}
else{
pTupleData = new UCHAR [uTupleLink] ;
if (pTupleData)
memcpy (pTupleData, (PUCHAR)pParms + sizeof (CARD_DATA_PARMS), uTupleLink) ;
}
CARD_SOCKET_HANDLE hSocket = pParms->hSocket ;
switch (uTupleCode){
case CISTPL_LONGLINK_A:
case CISTPL_LONGLINK_C:
if (pTupleData && (uTupleLink >= 4))
uLinkOffset = * (UINT32*) pTupleData ;
else uLinkOffset = 0 ; // This never happens.
break ;
case CISTPL_CONFIG:
nParsedItems = 0 ; // GLITCH
CardGetParsedTuple(hSocket, uTupleCode, 0, &nParsedItems);
parsedSize = nParsedItems * sizeof (PARSED_CONFIG) ;
if (parsedSize){
parsedBuf = new UCHAR [parsedSize] ;
if (parsedBuf){
memset(parsedBuf, 0, sizeof(UCHAR)*parsedSize);
CardGetParsedTuple(hSocket, uTupleCode, parsedBuf, &nParsedItems);
}
else parsedSize = 0 ;
}
else
nParsedItems = 0 ; // GLITCH
break ;
case CISTPL_CFTABLE_ENTRY:
nParsedItems = 0 ; // GLITCH
CardGetParsedTuple(hSocket, uTupleCode, 0, &nParsedItems);
parsedSize = nParsedItems * sizeof (PARSED_PCMCFTABLE) ;
if (parsedSize){
parsedBuf = new UCHAR [parsedSize] ;
if (parsedBuf){
memset(parsedBuf, 0, sizeof(UCHAR)*parsedSize);
CardGetParsedTuple(hSocket, uTupleCode, parsedBuf, &nParsedItems);
}
else
parsedSize = 0 ;
}
else
nParsedItems = 0 ;
break ;
}
}
SCardTuple::~SCardTuple () {delete pTupleData ; delete[] parsedBuf ;}
int SCardTuple::idMatches (UINT16 flags, UINT32 offset){
if (offset != uCISOffset)
return 0 ;
if ((TUPLE_FLAG_COMMON & fFlags) != (TUPLE_FLAG_COMMON & flags))
return 0 ;
return 1 ;
}
int SCardTuple::idMatches (PCARD_TUPLE_PARMS p) {return idMatches (p->fFlags, p->uCISOffset) ;}
int SCardTuple::idMatches (PCARD_DATA_PARMS p) {return idMatches (p->fFlags, p->uCISOffset) ;}
int SCardTuple::idPreceeds (UINT16 flags, UINT32 offset){
// Yes if I am in Attr and it is in Common.
if (!(TUPLE_FLAG_COMMON & fFlags) && (TUPLE_FLAG_COMMON & flags))
return 1 ;
// No if I am in Common and it is in Attr.
if ( (TUPLE_FLAG_COMMON & fFlags) && !(TUPLE_FLAG_COMMON & flags))
return 0 ;
// We are in the same space, so check the offsets.
return uCISOffset < offset ;
}
int SCardTuple::idPreceeds (PCARD_TUPLE_PARMS p) {return idPreceeds (p->fFlags, p->uCISOffset) ;}
int SCardTuple::idPreceeds (PCARD_DATA_PARMS p) {return idPreceeds (p->fFlags, p->uCISOffset) ;}
VOID SCardTuple::dump () {dumpTuple (uTupleCode, uTupleLink, fFlags, uCISOffset, nParsedItems) ;}
//------------------------------ SCard --------------------------------------
SCard::SCard (HCard *pHCard, UINT8 cSoc, UINT8 cFunc)
: head(0), current(0), uLinkOffset(0), fFlags(0)
{
PCARD_TUPLE_PARMS pTuple = new CARD_TUPLE_PARMS ;
if(pTuple == NULL){
g_pKato->Log(LOG_DETAIL,TEXT("-->SCard::SCard<-- FAIL -- out of memory\r\n"));
return;
}
// Set up to get the primary chain of tuples.
(pTuple->hSocket).uSocket = cSoc ;
(pTuple->hSocket).uFunction = cFunc ;
pTuple->fAttributes = 0xFF ;
pTuple->uDesiredTuple = 0xFF ;
// Now get started
STATUS status = pHCard->CardGetFirstTuple (pTuple) ;
// Add the primary tuple chain, others are added as found.
while (status == CERR_SUCCESS){
addTuple (pTuple, pHCard) ;
status = pHCard->CardGetNextTuple (pTuple) ;
}
delete pTuple ;
}
SCard::~SCard (){
for (current = head ; current ; current = head){
head = current->link ;
delete current ;
}
}
// For the goofy rules.
int isLink (UINT8 code){
switch (code){
case CISTPL_LONGLINK_CB:
case CISTPL_LONG_LINK_MFC:
case CISTPL_LONGLINK_A:
case CISTPL_LONGLINK_C:
case CISTPL_LINKTARGET:
case CISTPL_NO_LINK:
case CISTPL_END:
case CISTPL_NULL:
return 1 ;
default:
return 0 ;
}
}
int SCard::isFound (PCARD_TUPLE_PARMS p){
if (!current)
return 0 ;
// If link tuples are Ok, we can settle this quickly.
if (p->fAttributes & 1){
if (p->uDesiredTuple == current->uTupleCode)
return 1 ; // Really found.
if (p->uDesiredTuple == CISTPL_END)
return 1 ; // Anything will do.
if (isLink(current->uTupleCode))
return 1 ; // Nutty guess.
return 0 ;
}
// So, we must not accept link tuples (unless p->uDesiredTuple is a link?).
// This reject list is from the Developer's Guide.
// Note: we take p->uDesiredTuple to override p->fAttributes
// if they contradict each other. There is no documentation
// on this point.
switch (current->uTupleCode){
case CISTPL_LONGLINK_CB:
return p->uDesiredTuple == CISTPL_LONGLINK_CB ;
case CISTPL_LONG_LINK_MFC:
return p->uDesiredTuple == CISTPL_LONG_LINK_MFC ;
case CISTPL_LONGLINK_A:
return p->uDesiredTuple == CISTPL_LONGLINK_A ;
case CISTPL_LONGLINK_C:
return p->uDesiredTuple == CISTPL_LONGLINK_C ;
case CISTPL_LINKTARGET:
return p->uDesiredTuple == CISTPL_LINKTARGET ;
case CISTPL_NO_LINK:
return p->uDesiredTuple == CISTPL_NO_LINK ;
default:
break ;
}
// We ran out of special rules, and current is not a link tuple.
if (p->uDesiredTuple == current->uTupleCode)
return 1 ;
if (p->uDesiredTuple == CISTPL_END)
return 1 ;
return 0 ;
}
int SCard::followALink (PCARD_TUPLE_PARMS p){
SCardTuple *pTpl = current ;
UINT32 uLinkOffset = p->uLinkOffset ;
UINT16 fFlags = p->fFlags ;
// Set attr/common bit in fFlags for the link target.
if (fFlags & TUPLE_FLAG_LINK_TO_A)
fFlags = 0 ;
else if (fFlags & TUPLE_FLAG_LINK_TO_C)
fFlags = TUPLE_FLAG_COMMON ;
if (!goToId(fFlags,uLinkOffset)){
current = pTpl ;
return 0 ;
}
if (current->uTupleCode != CISTPL_LINKTARGET){
current = pTpl ;
return 0 ;
}
return followTheChain () ;
}
int SCard::followTheChain (){
if (current && current->link){
current = current->link ;
return 1 ;
}
return 0 ;
}
static int shouldFollowLink (UINT16 flags){
if (flags & TUPLE_FLAG_NO_LINK)
return 0 ;
if (flags & TUPLE_FLAG_LINK_TO_A)
return 1 ;
if (flags & TUPLE_FLAG_LINK_TO_C)
return 1 ;
if (flags & TUPLE_FLAG_IMPLIED_LINK)
return 1 ;
return 0 ;
}
int SCard::scanOneStep (PCARD_TUPLE_PARMS p){
if (!current)
return 0 ;
SCardTuple *pStart = current ;
if (p->uTupleCode == CISTPL_END){
if (shouldFollowLink(p->fFlags))
followALink (p) ;
else
followTheChain () ;
}
else
followTheChain () ;
if (pStart == current)
return 0 ;
// Wa are now parked on a new tuple.
p->uTupleCode = current->uTupleCode ;
p->uTupleLink = current->uTupleLink ;
p->uCISOffset = current->uCISOffset ;
// Now we must set fFlags and uLinkOffset
switch (current->uTupleCode){
case CISTPL_LONGLINK_CB:
p->fFlags = TUPLE_FLAG_LINK_TO_C ;
p->uLinkOffset = current->uLinkOffset ;
break ;
case CISTPL_LONG_LINK_MFC:
p->fFlags = TUPLE_FLAG_LINK_TO_C ;
p->uLinkOffset = current->uLinkOffset ;
break ;
case CISTPL_LONGLINK_A:
p->fFlags = TUPLE_FLAG_LINK_TO_A ;
p->uLinkOffset = current->uLinkOffset ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -