Building an ISO7816-4 ADPU Command

To add functionality to a service provider, you need to know how an ISO7816-4 ADPU is built within the base service provider DLLs. The following procedure gives a brief overview of the build process.

Note The code segments included here are not necessarily complete; refer to the example applications and DLLs for more information.

    To Build an ISO7816-4 APDU Command
  1. Create an instance of ISCardCmd and ISCardISO7816 interface/objects.

    // Create an ISCardCmd object
    // Note: To use CoCreateInstance on Windows 95, make sure no Distributed COM 
    // flags are included in the API call or during build. Do not define flags
    // _WIN32_DCOM or _WIN32_WINNT >= 0x0400.
            hresult = CoCreateInstance(    CLSID_CSCardCmd,
                            NULL,
                            CLSCTX_ALL,
                            IID_ISCardCmd,
                            (LPVOID*) &g_pISCardCmd);
        //Create an ISCardISO7816 object
        hresult = CoCreateInstance(    CLSID_CSCardISO7816,
                            NULL,
                            CLSCTX_ALL,
                            IID_ISCardISO7816,
                            (LPVOID*) &g_pISCardISO7816);
     

    The ISCardCmd object contains two IByteBuffer buffers. One buffer contains the actual APDU command string (plus any data to send with the command). The other contains any reply information returned by the card after command execution.

  2. Using these objects, we can now create a valid ISO7816-4 command as follows:
    // Do challenge
            hresult = g_pISCardISO7816->GetChallenge(    dwLengthOfChallenge,
                                    &g_pISCardCmd);
     

    Here is the code used in the GetChallenge method:

    STDMETHODIMP CSCardISO7816::GetChallenge(    IN DWORD dwBytesExpected /*= 0*/,
                                    IN OUT LPSCARDCMD *ppCmd)
    {
        // Locals.
        HRESULT hr = S_OK;
        
        try
        {
            // Is the ISCardCmd object ok?
            hr = IsSCardCmdValid(ppCmd);
            if (FAILED(hr))
                throw (hr);
    
                    // Do it!
            hr = (*ppCmd)->BuildCmd(    m_byClassId,
                                    (BYTE) INS_GET_CHALLENGE),
                                    (BYTE) INS_NULL),// P1 = 0x00
                                    (BYTE) INS_NULL),// P2 = 0x00
                            NULL,
                                    &dwBytesExpected);
            if (FAILED(hr))
                throw (hr);        
        }
     

    The ISCardISO7816::GetChallenge method simply uses the ISCardCmd::BuildCmd to build the requested APDU. This is done by writing the appropriate information into the ISCardCmd APDU buffer in the hr = (*ppCmd)->BuildCmd line above.

  3. Using the built ISCardCmd object, do a transaction with the card, interpret the results, and continue.

Expanding beyond ISO7816-4

The recommended way to expand the service provider build-execute process described above is to create a new COM object. This COM object should support a new interface that allows creation of non-ISO7816-4 commands and should aggregate the ISCardISO7816 interface.