Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1975 lines
58 KiB

/*++
Copyright (C) Microsoft Corporation, 1999 - 1999
Module Name:
ISO7816
Abstract:
The ISCardISO7816 interface provides methods for implementing ISO 7816-4
functionality. With the exception of ISCardISO7816::SetDefaultClassId,
these methods create an APDU command that is encapsulated in a ISCardCmd
object.
The ISO 7816-4 specification defines standard commands available on smart
cards. The specification also defines how a smart card Application
Protocol Data Unit (APDU) command should be constructed and sent to the
smart card for execution. This interface automates the building process.
The following example shows a typical use of the ISCardISO7816 interface.
In this case, the ISCardISO7816 interface is used to build an APDU command.
To submit a transaction to a specific card
1) Create an ISCardISO7816 and ISCardCmd interface. The ISCardCmd
interface is used to encapsulate the APDU.
2) Call the appropriate method of the ISCardISO7816 interface, passing the
required parameters and the ISCardCmd interface pointer.
3) The ISO 7816-4 APDU command will be built and encapsulated in the
ISCardCmd interface.
4) Release the ISCardISO7816 and ISCardCmd interfaces.
Note
In the method reference pages, if a bit sequence in a table is not defined,
assume that bit sequence is reserved for future use or proprietary to a
specific vendor).
Author:
Doug Barlow (dbarlow) 6/24/1999
Notes:
?Notes?
--*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include "stdafx.h"
#include "ISO7816.h"
/////////////////////////////////////////////////////////////////////////////
// CSCardISO7816
/*++
CSCardISO7816::AppendRecord:
The AppendRecord method constructs an APDU command that either appends a
record to the end of a linear-structured elementary file (EF) or writes
record number 1 in an cyclic-structured elementary file.
Arguments:
byRefCtrl [in, defaultvalue(NULL_BYTE)] Identifies the elementary file to
be appended:
Meaning 8 7 6 5 4 3 2 1
Current EF 0 0 0 0 0 0 0 0
Short EF ID x x x x x 0 0 0
Reserved x x x x x x x x
pData [in] Pointer to the data to be appended to the file:
Tn (1 byte)
Ln (1 or 3 bytes)
data (Ln bytes)
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
read.
If another elementary file is selected at the time of issuing this command,
it may be processed without identification of the currently selected file.
Elementary files without a record structure cannot be read. The
encapsulated command aborts if applied to an elementary file without a
record structure.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::AppendRecord")
STDMETHODIMP
CSCardISO7816::AppendRecord(
/* [in] */ BYTE byRefCtrl,
/* [in] */ LPBYTEBUFFER pData,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xe2, // INS
0, // P1
byRefCtrl, // P2
pData,
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::EraseBinary:
The EraseBinary method constructs an APDU command that sequentially sets
part of the content of an elementary file to its logical erased state,
starting from a given offset.
Arguments:
byP1, byP2 [in] RFU position.
If… Then…
b8=1 in P1 b7 and b6 of P1 are set to 0 (RFU bits), b5 to b1 of P1 are
a short EF identifier and P2 is the offset of the first
byte to be erased (in data units) from the beginning of the
file.
b8=0 in P1 then P1 || P2 is the offset of the first byte to be erased
(in data units) from the beginning of the file.
If the data field is present, it codes the offset of the first data
unit not to be erased. This offset shall be higher than the one coded
in P1-P2. When the data field is empty, the command erases up to the
end of the file.
pData [in, defaultvalue(NULL)] Pointer to the data that specifies the erase
range; may be NULL.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
being processed.
When the command contains a valid short elementary identifier, it sets the
file as current elementary file.
Elementary files without a transparent structure cannot be erased. The
encapsulated command aborts if applied to an elementary file without a
transparent structure.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::EraseBinary")
STDMETHODIMP
CSCardISO7816::EraseBinary(
/* [in] */ BYTE byP1,
/* [in] */ BYTE byP2,
/* [in] */ LPBYTEBUFFER pData,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0x0e, // INS
byP1, // P1
byP2, // P2
pData,
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::ExternalAuthenticate:
The ExternalAuthenticate method constructs an APDU command that
conditionally updates security status, verifying the identity of the
computer when the smart card does not trust it.
The command uses the result (yes or no) of the computation by the card
(based on a challenge previously issued by the card — for example, by the
INS_GET_CHALLENGE command), a key (possibly secret) stored in the card, and
authentication data transmitted by the interface device.
Arguments:
byAlgorithmRef [in, defaultvalue(NULL_BYTE)] Reference of the algorithm in
the card. If this value is zero, this indicates that no information is
given. The reference of the algorithm is known either before issuing
the command or is provided in the data field.
bySecretRef [in, defaultvalue(NULL_BYTE)] Reference of the secret:
Meaning 8 7 6 5 4 3 2 1
No Info 0 0 0 0 0 0 0 0
Global ref 0 - - - - - - -
Specific ref 1 - - - - - - -
RFU - x x - - - - -
Secret - - - x x x x x
No Info = No information is given. The reference of the secret is known
either before issuing the command or is provided in the data field.
Global ref = Global reference data (an MF specific key).
Specific ref = Specific reference data (a DF specific key).
RFU = 00 (other values are RFU).
Secret = Number of the secret.
pChallenge [in, defaultvalue(NULL)] Pointer to the authentication-related
data; may be NULL.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
For the encapsulated command to be successful, the last challenge obtained
from the card must be valid.
Unsuccessful comparisons may be recorded in the card (for example, to limit
the number of further attempts of the use of the reference data).
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::ExternalAuthenticate")
STDMETHODIMP
CSCardISO7816::ExternalAuthenticate(
/* [in] */ BYTE byAlgorithmRef,
/* [in] */ BYTE bySecretRef,
/* [in] */ LPBYTEBUFFER pChallenge,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0x82, // INS
byAlgorithmRef, // P1
bySecretRef, // P2
pChallenge, // data
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::GetChallenge:
The GetChallenge method constructs an APDU command that issue a challenge
(for example, a random number) for use in a security-related procedure.
Arguments:
lBytesExpected [in, defaultvalue(0)] Maximum length of the expected response.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd object
is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The challenge is valid at least for the next command.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::GetChallenge")
STDMETHODIMP
CSCardISO7816::GetChallenge(
/* [in] */ LONG lBytesExpected,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0x84, // INS
0x00, // P1
0x00, // P2
NULL,
&lBytesExpected);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::GetData:
The GetData method constructs an APDU command that retrieves either a
single primitive data object or a set of data objects (contained in a
constructed data object), depending on the type of file selected.
Arguments:
byP1, byP2 [in] Parameters:
Value Meaning
0000 - 003F RFU
0040 - 00FF BER-TLV tag (1 byte) in P2
0100 - 01FF Application data (proprietary coding)
0200 - 02FF SIMPLE-TLV tag in P2
0300 - 03FF RFU
0400 - 04FF BER-TLV tag (2 bytes) in P1-P2
lBytesToGet [in, defaultvalue(0)] Number of bytes expected in the response.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
being read. Security conditions are dependent on the policy of the card,
and may be manipulated through ExternalAuthenticate, InternalAuthenticate,
ISCardAuth, etc.
To select a file, call SelectFile.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::GetData")
STDMETHODIMP
CSCardISO7816::GetData(
/* [in] */ BYTE byP1,
/* [in] */ BYTE byP2,
/* [in] */ LONG lBytesToGet,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xca, // INS
byP1, // P1
byP2, // P2
NULL,
&lBytesToGet);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::GetResponse:
The GetResponse method constructs an APDU command that transmits APDU
commands (or part of an APDU command) which otherwise could not be
transmitted by the available protocols.
Arguments:
byP1, byP2 [in, defaultvalue(0)] Per the ISO 7816-4, P1 and P2 should be 0
(RFU).
lDataLength [in, defaultvalue(0)] Length of data transmitted.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::GetResponse")
STDMETHODIMP
CSCardISO7816::GetResponse(
/* [in] */ BYTE byP1,
/* [in] */ BYTE byP2,
/* [in] */ LONG lDataLength,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xc0, // INS
0x00, // P1
0x00, // P2
NULL,
&lDataLength);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::InternalAuthenticate:
The InternalAuthenticate method constructs an APDU command that initiates
the computation of the authentication data by the card using the challenge
data sent from the interface device and a relevant secret (for example, a
key) stored in the card.
When the relevant secret is attached to the MF, the command may be used to
authenticate the card as a whole.
When the relevant secret is attached to another DF, the command may be used
to authenticate that DF.
Arguments:
byAlgorithmRef [in, defaultvalue(NULL_BYTE)] Reference of the algorithm in
the card. If this value is zero, this indicates that no information is
given. The reference of the algorithm is known either before issuing
the command or is provided in the data field.
bySecretRef [in, defaultvalue(NULL_BYTE)] Reference of the secret:
Meaning 8 7 6 5 4 3 2 1
No Info 0 0 0 0 0 0 0 0
Global ref 0 - - - - - - -
Specific ref 1 - - - - - - -
RFU - x x - - - - -
Secret - - - x x x x x
No Info = No information is given.
Global ref = Global reference data (an MF specific key).
Specific ref = Specific reference data (a DF specific key).
RFU = 00 (other values are RFU).
Secret = Number of the secret.
pChallenge [in] Pointer to the authentication-related data (for example,
challenge).
lReplyBytes [in, defaultvalue(0)] Maximum number of bytes expected in
response.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The successful execution of the command may be subject to successful
completion of prior commands (for example, VERIFY or SELECT FILE) or
selections (for example, the relevant secret).
If a key and an algorithm are currently selected when issuing the command,
then the command may implicitly use the key and the algorithm.
The number of times the command is issued may be recorded in the card to
limit the number of further attempts of using the relevant secret or the
algorithm.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::InternalAuthenticate")
STDMETHODIMP
CSCardISO7816::InternalAuthenticate(
/* [in] */ BYTE byAlgorithmRef,
/* [in] */ BYTE bySecretRef,
/* [in] */ LPBYTEBUFFER pChallenge,
/* [in] */ LONG lReplyBytes,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0x88, // INS
byAlgorithmRef, // P1
bySecretRef, // P2
pChallenge,
&lReplyBytes);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::ManageChannel:
The ManageChannel method constructs an APDU command that opens and closes
logical channels.
The open function opens a new logical channel other than the basic one.
Options are provided for the card to assign a logical channel number, or
for the logical channel number to be supplied to the card.
The close function explicitly closes a logical channel other than the basic
one. After the successful closing, the logical channel shall be available
for re-use.
Arguments:
byChannelState [in, defaultvalue(ISO_CLOSE_LOGICAL_CHANNEL)] Bit b8 of P1
is used to indicate the open function or the close function; if b8 is 0
then MANAGE CHANNEL shall open a logical channel and if b8 is 1 then
MANAGE CHANNEL shall close a logical channel:
P1 = '00' to open
P1 = '80' to close
Other values are RFU
byChannel [in, defaultvalue(ISO_LOGICAL_CHANNEL_0)] For the open function
(P1 = '00'), the bits b1 and b2 of P2 are used to code the logical
channel number in the same manner as in the class byte, the other bits
of P2 are RFU. When b1 and b2 of P2 are NULL, then the card will
assign a logical channel number that will be returned in bits b1 and
b2 of the data field.
When b1 and/or b2 of P2 are not NULL, they code a logical channel
number other than the basic one; then the card will open the externally
assigned logical channel number.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
When the open function is successfully performed from the basic logical
channel, the MF shall be implicitly selected as the current DF and the
security status of the new logical channel should be the same as the basic
logical channel after ATR. The security status of the new logical channel
should be separate from that of any other logical channel.
When the open function is successfully performed from a logical channel,
which is not the basic one, the current DF of the logical channel that
issued the command will be selected as the current DF. In addition, the
security status for the new logical channel should be the same as the
security status of the logical channel from which the open function was
performed.
After a successful close function, the security status related to this
logical channel is lost.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::ManageChannel")
STDMETHODIMP
CSCardISO7816::ManageChannel(
/* [in] */ BYTE byChannelState,
/* [in] */ BYTE byChannel,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
LONG lLe = 1;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0x70, // INS
byChannelState, // P1
byChannel, // P2
NULL,
0 == (byChannelState | byChannel)
? &lLe
: NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::PutData:
The PutData method constructs an APDU command that stores a single
primitive data object or the set of data objects contained in a constructed
data object, depending on the file selected.
How the objects are stored (writing once and/or updating and/or appending)
depends on the definition or the nature of the data objects.
Arguments:
byP1, byP2 [in] Coding of P1-P2:
Value Meaning
0000 - 003F RFU
0040 - 00FF BER-TLV tag (1 byte) in P2
0100 - 01FF Application data (proprietary coding)
0200 - 02FF SIMPLE-TLV tag in P2
0300 - 03FF RFU
0400 - 04FF BER-TLV tag (2 bytes) in P1-P2
pData [in] Pointer to a byte buffer that contains the parameters and data to be
written.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The command can be performed only if the security status satisfies the
security conditions defined by the application within the context for the
function.
Store Application Data
When the value of P1-P2 lies in the range from 0100 to 01FF, the value
of P1-P2 shall be an identifier reserved for card internal tests and
for proprietary services meaningful within a given application context.
Store Data Objects
When the value P1-P2 lies in the range from 0040 to 00FF, the value of
P2 shall be a BER-TLV tag on a single byte. The value of 00FF is
reserved for indicating that the data field carries BER-TLV data
objects.
When the value of P1-P2 lies in the range 0200 to 02FF, the value of P2
shall be a SIMPLE-TLV tag. The value 0200 is RFU. The value 02FF is
reserved for indicating that the data field carries SIMPLE-TLV data
objects.
When the value of P1-P2 lies in the range from 4000 to FFFF, the value
of P1-P2 shall be a BER-TLV tag on two bytes. The values 4000 to FFFF
are RFU.
When a primitive data object is provided, the data field of the command
message shall contain the value of the corresponding primitive data
object.
When a constructed data object is provided, the data field of the
command message shall contain the value of the constructed data object
(that is, data objects including their tag, length, and value).
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::PutData")
STDMETHODIMP
CSCardISO7816::PutData(
/* [in] */ BYTE byP1,
/* [in] */ BYTE byP2,
/* [in] */ LPBYTEBUFFER pData,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xda, // INS
byP1, // P1
byP2, // P2
pData,
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::ReadBinary:
The ReadBinary method constructs an APDU command that acquires a response
message that gives that part of the contents of a transparent-structured
elementary file.
Arguments:
byP1, byP2 [in] The P1-P2 field, offset to the first byte to be read from
the beginning of the file.
If b8=1 in P1, then b7 and b6 of P1 are set to 0 (RFU bits), b5 to b1
of P1 are a short EF identifier and P2 is the offset of the first byte
to be read in data units from the beginning of the file.
If b8=0 in P1, then P1||P2 is the offset of the first byte to be read
in data units from the beginning of the file.
lBytesToRead [in, defaultvalue(0)] Number of bytes to read from the
transparent EF. If the Le field contains only zeroes, then within the
limit of 256 for short length or 65536 for extended length, all the bytes
until the end of the file should be read.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
being processed.
When the command contains a valid short elementary identifier, it sets the
file as current elementary file.
Elementary files without a transparent structure cannot be erased. The
encapsulated command aborts if applied to an elementary file without a
transparent structure.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::ReadBinary")
STDMETHODIMP
CSCardISO7816::ReadBinary(
/* [in] */ BYTE byP1,
/* [in] */ BYTE byP2,
/* [in] */ LONG lBytesToRead,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xb0, // INS
byP1, // P1
byP2, // P2
NULL,
&lBytesToRead);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::ReadRecord:
The ReadRecord method constructs an APDU command that reads either the
contents of the specified record(s) or the beginning part of one record of
an elementary file.
Arguments:
byRecordId [in, defaultvalue(NULL_BYTE)] Record number or ID of the first
record to be read (00 indicates the current record).
byRefCtrl [in] Coding of the reference control:
Meaning 8 7 6 5 4 3 2 1
Current EF 0 0 0 0 0 - - -
Short EF ID x x x x x - - -
RFU 1 1 1 1 1 - - -
Record - - - - - 1 x x
Read Record - - - - - 1 0 0
Up to Last - - - - - 1 0 1
Up to P1 - - - - - 1 1 0
RFU - - - - - 1 1 1
Record ID - - - - - 0 x x
First Occur - - - - - 0 0 0
Last Occur - - - - - 0 0 1
Next Occur - - - - - 0 1 0
Previous - - - - - 0 1 1
Secret - - - x x x x x
Current EF = Currently selected EF.
Short EF ID = Short EF identifier.
Record # = Usage of record number in P1.
Read Record = Read record P1.
Up to Last = Read all records from P1 up to the last.
Up to P1 = Read all records from the last up to P1.
Record ID = Usage of record ID in P1.
First Occur = Read first occurrence.
Last Occur = Read last occurrence.
Next Occur = Read next occurrence.
Previous = Read previous occurrence.
lBytesToRead [in, defaultvalue(0)] Number of bytes to read from the
transparent EF. If the Le field contains only zeroes, then depending
on b3b2b1 of P2 and within the limit of 256 for short length or 65536
for extended length, the command should read completely either the
single requested record or the requested sequence of records.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
being read.
If another elementary file is currently selected at the time of issuing
this command, it may be processed without identification of the currently
selected file.
When the command contains a valid short elementary identifier, it sets the
file as current elementary file.
Elementary files without a record structure cannot be read. The
encapsulated command aborts if applied to an elementary file without a
record structure.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::ReadRecord")
STDMETHODIMP
CSCardISO7816::ReadRecord(
/* [in] */ BYTE byRecordId,
/* [in] */ BYTE byRefCtrl,
/* [in] */ LONG lBytesToRead,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xb2, // INS
byRecordId, // P1
byRefCtrl, // P2
NULL,
&lBytesToRead);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::SelectFile:
The SelectFile method constructs an APDU command that sets a current
elementary file within a logical channel. Subsequent commands may
implicitly refer to the current file through the logical channel.
Selecting a directory (DF) within the card filestore — which may be the
root (MF) of the filestore — makes it the current DF. After such a
selection, an implicit current elementary file may be referred to through
that logical channel.
Selecting an elementary file sets the selected file and its parent as
current files.
After the answer to reset, the MF is implicitly selected through the basic
logical channel, unless specified differently in the historical bytes or in
the initial data string.
Arguments:
byP1, byP2 [in] Selection control.
P1 (upper byte in word):
Meaning 8 7 6 5 4 3 2 1
Select File ID 0 0 0 0 0 0 x x
EF, DF, or MF 0 0 0 0 0 0 0 0
child DF 0 0 0 0 0 0 0 1
EF under DF 0 0 0 0 0 0 1 0
parent DF of current DF 0 0 0 0 0 0 1 1
Select by DF Name 0 0 0 0 0 1 x x
DFname 0 0 0 0 0 1 0 0
RFU 0 0 0 0 0 1 0 1
RFU 0 0 0 0 0 1 1 0
RFU 0 0 0 0 0 1 1 1
Select by path 0 0 0 0 1 0 x x
from MF 0 0 0 0 1 0 0 0
current DF 0 0 0 0 1 0 0 1
RFU 0 0 0 0 1 0 1 0
RFU 0 0 0 0 1 0 1 1
When P1=00, the card knows either because of a specific coding of
the file ID or because of the context of execution of the command
if the file to select is the MF, a DF, or an EF.
When P1-P2=0000, if a file ID is provided, then it shall be unique
in the following environments:
the immediate children of the current DF
the parent DF
the immediate children of the parent DF
If P1-P2=0000 and if the data field is empty or equal to 3F00, then
select the MF.
When P1=04, the data field is a DF name, possibly right truncated.
When supported, successive such commands with the same data field
shall select DFs whose names match with the data field (that is,
start with the command data field). If the card accepts the
command with an empty data field, then all or a subset of the DFs
can be successively selected.
P2 (lower byte of word):
Meaning 8 7 6 5 4 3 2 1
First occur 0 0 0 0 - - 0 0
Last occur 0 0 0 0 - - 0 1
Next occur 0 0 0 0 - - 1 0
Previous occur 0 0 0 0 - - 1 1
File Control 0 0 0 0 x x - -
Return FCI 0 0 0 0 0 0 - -
Return FCP 0 0 0 0 0 1 - -
Return FMD 0 0 0 0 1 0 - -
pData [in, defaultvalue(NULL)] Data for operation if needed; else, NULL.
Types of data that are passed in this parameter include:
file ID
path from the MF
path from the current DF
DF name
lBytesToRead [in, defaultvalue(0)] Empty (that is, 0) or maximum length of
data expected in response.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
Unless otherwise specified, the correct execution of the encapsulated
command modifies the security status according to the following rules:
* When the current elementary file is changed, or when there is no
current elementary file, the security status specific to a former
current elementary file is lost.
* When the current filestore directory (DF) is descendant of, or
identical to the former current DF, the security status specific to the
former current DF is lost. The security status common to all common
ancestors of the previous and new current DF is maintained.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::SelectFile")
STDMETHODIMP
CSCardISO7816::SelectFile(
/* [in] */ BYTE byP1,
/* [in] */ BYTE byP2,
/* [in] */ LPBYTEBUFFER pData,
/* [in] */ LONG lBytesToRead,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xa4, // INS
byP1, // P1
byP2, // P2
pData,
0 == lBytesToRead ? NULL : &lBytesToRead);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::SetDefaultClassId:
The SetDefaultClassId method assigns a standard class identifier byte that
will be used in all operations when constructing an ISO 7816-4 command
APDU. By default, the standard class identifier byte is 0x00.
Arguments:
byClass [in] Class ID byte.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::SetDefaultClassId")
STDMETHODIMP
CSCardISO7816::SetDefaultClassId(
/* [in] */ BYTE byClass)
{
m_bCla = byClass;
return S_OK;
}
/*++
CSCardISO7816::UpdateBinary:
The UpdateBinary method constructs an APDU command that updates the bits
present in an elementary file with the bits given in the APDU command.
Arguments:
byP1, byP2 [in] Offset to the write (update) location into the binary from
the start of the binary.
If b8=1 in P1, then b7 and b6 of P1 are set to 0 (RFU bits), b5 to b1
of P1 are a short EF identifier and P2 is the offset of the first byte
to be updated in data units from the beginning of the file.
If b8=0 in P1, then P1 || P2 is the offset of the first byte to be
updated in data units from the beginning of the file.
pData [in] Pointer to the string of data units to be updated.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
being processed.
When the command contains a valid short elementary identifier, it sets the
file as current elementary file.
Elementary files without a transparent structure cannot be erased. The
encapsulated command aborts if applied to an elementary file without a
transparent structure.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::UpdateBinary")
STDMETHODIMP
CSCardISO7816::UpdateBinary(
/* [in] */ BYTE byP1,
/* [in] */ BYTE byP2,
/* [in] */ LPBYTEBUFFER pData,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xd6, // INS
byP1, // P1
byP2, // P2
pData,
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::UpdateRecord:
The UpdateRecord method constructs an APDU command that updates a specific
record with the bits given in the APDU command.
Note When using current record addressing, the command sets the record
pointer on the successfully updated record.
Arguments:
byRecordId [in, defaultvalue(NULL_BYTE)] P1 value:
P1 = 00 designates the current record
P1 != '00' is the number of the specified record
byRefCtrl [in, defaultvalue(NULL_BYTE)] Coding of the reference control P2:
Meaning 8 7 6 5 4 3 2 1
Current EF 0 0 0 0 0 - - -
Short EF ID x x x x x - - -
First Record - - - - - 0 0 0
Last Record - - - - - 0 0 1
Next Record - - - - - 0 1 0
Previous Record - - - - - 0 1 1
Record # in P1 - - - - - 1 0 0
pData [in] Pointer to the record to be updated.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
being processed.
When the command contains a valid short elementary identifier, it sets the
file as current elementary file. If another elementary file is currently
selected at the time of issuing this command, this command may be processed
without identification of the currently selected file.
If the constructed command applies to a linear-fixed or cyclic-structured
elementary file, it will abort if the record length is different from the
length of the existing record.
If the command applies to a linear-variable structured elementary file, it
may be carried out when the record length is different from the length of
the existing record.
The "previous" option of the command (P2=xxxxx011), applied to a cyclic
file, has the same behavior as a command constructed by AppendRecord.
Elementary files without a record structure cannot be read. The
constructed command aborts if applied to an elementary file without record
structure.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::UpdateRecord")
STDMETHODIMP
CSCardISO7816::UpdateRecord(
/* [in] */ BYTE byRecordId,
/* [in] */ BYTE byRefCtrl,
/* [in] */ LPBYTEBUFFER pData,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xdc, // INS
byRecordId, // P1
byRefCtrl, // P2
pData,
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::Verify:
The Verify method constructs an APDU command that initiates the comparison
(in the card) of the verification data sent from the interface device with
the reference data stored in the card (for example, password).
Arguments:
byRefCtrl [in, defaultvalue(NULL_BYTE)] Quantifier of the reference data;
coding of the reference control P2:
Meaning 8 7 6 5 4 3 2 1
No Info 0 0 0 0 0 0 0 0
Global Ref 0 - - - - - - -
Specific Ref 1 - - - - - - -
RFU - x x - - - - -
Ref Data # - - - x x x x x
An example of Global Ref would be a password.
An example of Specific Ref is DF specific password.
P2=00 is reserved to indicate that no particular qualifier is used in
those cards where the verify command references the secret data
unambiguously.
The reference data number may be for example a password number or a
short EF identifier.
When the body is empty, the command may be used either to retrieve the
number 'X' of further allowed retries (SW1-SW2=63CX) or to check
whether the verification is not required (SW1-SW2=9000).
pData [in, defaultvalue(NULL)] Pointer to the verification data, or can be
NULL.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd object
is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The security status may be modified as a result of a comparison.
Unsuccessful comparisons may be recorded in the card (for example, to limit
the number of further attempts of the use of the reference data).
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::Verify")
STDMETHODIMP
CSCardISO7816::Verify(
/* [in] */ BYTE byRefCtrl,
/* [in] */ LPBYTEBUFFER pData,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0x20, // INS
0x00, // P1
byRefCtrl, // P2
pData,
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::WriteBinary:
The WriteBinary method constructs an APDU command that writes binary values
into an elementary file.
Depending upon the file attributes, the command performs one of the
following operations:
* The logical OR of the bits already present in the card with the bits
given in the command APDU (logical erased state of the bits of the file
is 0).
* The logical AND of the bits already present in the card with the bits
given in the command APDU (logical erased state of the bits of the file
is 1).
* The one-time write in the card of the bits given in the command APDU.
When no indication is given in the data coding byte, the logical OR
behavior applies.
Arguments:
byP1, byP2 [in] Offset to the write location from the beginning of the
binary file (EF).
If b8=1 in P1, then b7 and b6 of P1 are set to 0 (RFU bits), b5 to b1
of P1 are a short EF identifier and P2 is the offset of the first byte
to be written in data units from the beginning of the file.
If b8=0 in P1, then P1||P2 is the offset of the first byte to be
written in data units from the beginning of the file.
pData [in] Pointer to the string of data units to be written.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
being processed.
When the command contains a valid short elementary identifier, it sets the
file as current elementary file.
Once a write binary operation has been applied to a data unit of a one-time
write EF, any further write operation referring to this data unit will be
aborted if the content of the data unit or the logical erased state
indicator (if any) attached to this data unit is different from the logical
erased state.
Elementary files without a transparent structure cannot be written to. The
encapsulated command aborts if applied to an elementary file without a
transparent structure.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::WriteBinary")
STDMETHODIMP
CSCardISO7816::WriteBinary(
/* [in] */ BYTE byP1,
/* [in] */ BYTE byP2,
/* [in] */ LPBYTEBUFFER pData,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xd0, // INS
byP1, // P1
byP2, // P2
pData,
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}
/*++
CSCardISO7816::WriteRecord:
The WriteRecord method constructs an APDU command that initiates one of the
following operations:
* The write once of a record.
* The logical OR of the data bytes of a record already present in the
card with the data bytes of the record given in the command APDU.
* The logical AND of the data bytes of a record already present in the
card with the data bytes of the record given in the command APDU.
When no indication is given in the data coding byte, the logical OR behavior applies.
Note: When using current record addressing, the command sets the record
pointer on the successfully updated record.
Arguments:
byRecordId [in, defaultvalue(NULL_BYTE)] Record identification. This is the
P1 value:
P1 = '00' designates the current record.
P1 != '00' is the number of the specified record.
byRefCtrl [in, defaultvalue(NULL_BYTE)] Coding of the reference control P2:
Meaning 8 7 6 5 4 3 2 1
Current EF 0 0 0 0 0 - - -
Short EF ID x x x x x - - -
First Record - - - - - 0 0 0
Last Record - - - - - 0 0 1
Next Record - - - - - 0 1 0
Previous Record - - - - - 0 1 1
Record # in P1 - - - - - 1 0 0
pData [in] Pointer to the record to be written.
ppCmd [in, out] On input, a pointer to an ISCardCmd interface object or
NULL. On return, it is filled with the APDU command constructed by
this operation. If ppCmd was set to NULL, a smart card ISCardCmd
object is internally created and returned via the ppCmd pointer.
Return Value:
The return value is an HRESULT. A value of S_OK indicates the call was
successful.
Remarks:
The encapsulated command can only be performed if the security status of
the smart card satisfies the security attributes of the elementary file
being processed.
When the command contains a valid short elementary identifier, it sets the
file as current elementary file. If another elementary file is currently
selected at the time of issuing this command, this command may be processed
without identification of the currently selected file.
If the encapsulated command applies to a linear-fixed or cyclic-structured
elementary file, it will abort if the record length is different from the
length of the existing record. If it applies to a linear-variable
structured elementary file, it may be carried out when the record length is
different from the length of the existing record.
If P2=xxxxx011 and the elementary file is cyclic file, this command has the
same behavior a command constructed using AppendRecord.
Elementary files without a record structure cannot be written to. The
constructed command aborts if applied to an elementary file without a
record structure.
Author:
Doug Barlow (dbarlow) 6/24/1999
--*/
#undef __SUBROUTINE__
#define __SUBROUTINE__ TEXT("CSCardISO7816::WriteRecord")
STDMETHODIMP
CSCardISO7816::WriteRecord(
/* [in] */ BYTE byRecordId,
/* [in] */ BYTE byRefCtrl,
/* [in] */ LPBYTEBUFFER pData,
/* [out][in] */ LPSCARDCMD __RPC_FAR *ppCmd)
{
HRESULT hReturn;
try
{
HRESULT hr;
if (NULL == *ppCmd)
{
*ppCmd = NewSCardCmd();
if (NULL == *ppCmd)
throw (HRESULT)E_OUTOFMEMORY;
}
hr = (*ppCmd)->BuildCmd(
m_bCla, // CLA
0xd2, // INS
byRecordId, // P1
byRefCtrl, // P2
pData,
NULL);
hReturn = hr;
}
catch (HRESULT hError)
{
hReturn = hError;
}
catch (...)
{
hReturn = E_INVALIDARG;
}
return hReturn;
}