2025-11-28 00:35:46 +09:00

680 lines
19 KiB
C++

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
Copyright (C) 1998 - 2000. Microsoft Corporation. All rights reserved.
Module: SCQuery.cpp
Abstract: Main program of SCQuery for Smart Card SDK sample. See
ReadMe.txt for more detail information about this sample.
Environment: Win32 console, C++ w/SEH, UNICODE ready.
------------------------------------------------------------------------------*/
////////////////////
//
// INCLUDE
//
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
#include <winscard.h>
#include "SCCommon.h"
///////////////
//
// Prototype
//
LONG ListReaders (IN SCARDCONTEXT hContext, IN LPCTSTR lpmszReaderGroups);
LONG ListCards (IN SCARDCONTEXT hContext, IN LPCBYTE lpszATR);
LONG ListGroups (IN SCARDCONTEXT hContext);
LONG QueryCards (IN SCARDCONTEXT hContext, IN LPCTSTR lpmszReaderGroups);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : _tmain
Synopsis : Entry point of SCQuery.
Parameter: Standard ANSI C command line parameters.
Return : SCARD_S_SUCCESS or error code
------------------------------------------------------------------------------*/
extern "C" int __cdecl _tmain (int argc, _TCHAR * argv[])
{
LONG lResult;
SCARDCONTEXT hContext = NULL;
__try
{
//
// Establish context with the resource manager.
//
lResult = SCardEstablishContext(SCARD_SCOPE_USER,
NULL,
NULL,
&hContext);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
//
// List readers
//
lResult = ListReaders(hContext, NULL);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
//
// List cards
//
lResult = ListCards(hContext, NULL);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
//
// List groups
//
lResult = ListGroups(hContext);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
//
// Query cards
//
lResult = QueryCards(hContext, NULL);
}
__finally
{
//
// Don't forget to release the context handle if established.
//
if (hContext != NULL)
{
LONG lReturn = SCardReleaseContext(hContext);
//
// If successful so far, then capture the SCardReleaseContext()
// return code; otherwise, don't bother
//
if (lResult == SCARD_S_SUCCESS)
{
lResult = lReturn;
}
}
}
//
// Inform user if an error had occurred.
//
if (lResult != SCARD_S_SUCCESS)
{
_tprintf(_T("\nError [0x%lx]: Program terminated abnormally.\n"),
lResult);
}
return((int) lResult);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : ListReaders
Synopsis : Print out a formatted list of registered Smart Card readers
associated with the specified reader groups to STDOUT.
Parameter: - IN SCARDCONTEXT hContext
Resource manager context returned by SCardEstablishContext(), or
NULL if the query is not directed towards a specific context.
- IN LPCTSTR lpmszReaderGroups
Pointer to multi-string reader group names, or NULL to specify all
readers known to the system.
Return : SCARD_S_SUCCESS or error code
------------------------------------------------------------------------------*/
LONG ListReaders (IN SCARDCONTEXT hContext,
IN LPCTSTR lpmszReaderGroups)
{
LONG lResult;
LPTSTR lpmszReaderNames;
__try
{
//
// Get the list of registered readers associated with the specified
// group(s).
// Note: The buffer is automatically allocated and must be freed
// by SCFree().
//
lResult = SCListReaders(hContext,
lpmszReaderGroups,
(LPTSTR *) &lpmszReaderNames);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
DWORD dwNumReaders = 0;
LPTSTR lpszReaderName = lpmszReaderNames;
_tprintf(_T("\n"));
_tprintf(_T("Registered Reader(s)\n"));
_tprintf(_T("====================\n"));
//
// Walk through the list of readers and print out some information.
// Note: The list of readers are in a multi-string structure.
//
while (*lpszReaderName != _T('\0'))
{
_tprintf(_T("%02d: %s\n"), ++dwNumReaders, lpszReaderName);
lpszReaderName += lstrlen(lpszReaderName) + 1;
}
//
// Inform the user if no reader was found.
//
if (dwNumReaders == 0)
{
_tprintf(_T("No registered reader was found for the specified "
_T("reader group(s) [%s].\n")), lpmszReaderGroups);
}
}
__finally
{
//
// Don't forget to release memory, if allocated.
//
if (lpmszReaderNames != NULL)
{
LONG lReturn = SCFree((LPVOID) lpmszReaderNames);
//
// If successful so far, then capture the return code
// from SCFree(); otherwise, don't bother.
//
if (lResult == SCARD_S_SUCCESS)
{
lResult = lReturn;
}
}
}
return lResult;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : ListCards
Synopsis : Print out a formatted list of registered Smart Cards associated with
the specified ATR string to STDOUT.
Parameter: - IN SCARDCONTEXT hContext
Resource manager context returned by SCardEstablishContext(), or
NULL if the query is not directed towards a specific context.
- IN LPCBYTE lpszATR
ATR string of the card to list, or NULL to return all cards known
to the system.
Return : SCARD_S_SUCCESS or error code
------------------------------------------------------------------------------*/
LONG ListCards (IN SCARDCONTEXT hContext,
IN LPCBYTE lpszATR)
{
LONG lResult;
LPTSTR lpmszCardNames;
__try
{
//
// Get the list of registered cards associated with the specified ATR.
// Note: The buffer is automatically allocated and must be freed
// by SCFree().
//
lResult = SCListCards(hContext,
lpszATR,
&lpmszCardNames);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
DWORD dwNumCards = 0;
LPTSTR lpszCardName = lpmszCardNames;
_tprintf(_T("\n"));
_tprintf(_T("Registered Card(s)\n"));
_tprintf(_T("==================\n"));
//
// Walk through the list of cards and print out some information.
// Note: The list of cards are in a multi-string structure.
//
while (*lpszCardName != _T('\0'))
{
_tprintf(_T("%02d: %s\n"), ++dwNumCards, lpszCardName);
lpszCardName += lstrlen(lpszCardName) + 1;
}
//
// Inform the user if no card was found.
//
if (dwNumCards == 0)
{
_tprintf(_T("No registered Smart Card was found for the "
_T("specified ATR [%s].\n")), lpszATR);
}
}
__finally
{
//
// Don't forget to release memory, if allocated.
//
if (lpmszCardNames != NULL)
{
LONG lReturn = SCFree((LPVOID) lpmszCardNames);
//
// If successful so far, then capture the return code
// from SCFree(); otherwise, don't bother.
//
if (lResult == SCARD_S_SUCCESS)
{
lResult = lReturn;
}
}
}
return lResult;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : ListGroups
Synopsis : Print out a formatted list of registered reader groups to STDOUT.
Parameter: - IN SCARDCONTEXT hContext
Resource manager context returned by SCardEstablishContext(), or
NULL if the query is not directed towards a specific context.
Return : SCARD_S_SUCCESS or error code
------------------------------------------------------------------------------*/
LONG ListGroups (IN SCARDCONTEXT hContext)
{
LONG lResult;
LPTSTR lpmszGroupNames;
__try
{
//
// Get the list of registered reader groups.
// Note: The buffer is automatically allocated and must be freed
// by SCFree().
//
lResult = SCListGroups(hContext,
(LPTSTR *) &lpmszGroupNames);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
DWORD dwNumGroups = 0;
LPTSTR lpszGroupName = lpmszGroupNames;
_tprintf(_T("\n"));
_tprintf(_T("Registered Group(s)\n"));
_tprintf(_T("===================\n"));
//
// Walk through the list of groups and print out some information.
// Note: The list of cards are in a multi-string structure.
//
while (*lpszGroupName != TEXT('\0'))
{
_tprintf(_T("%02d: %s\n"), ++dwNumGroups, lpszGroupName);
lpszGroupName += lstrlen(lpszGroupName) + 1;
}
//
// Inform the user if no group was found.
//
if (dwNumGroups == 0)
{
_tprintf(_T("No registered reader group was found.\n"));
}
}
__finally
{
//
// Don't forget to release memory, if allocated.
//
if (lpmszGroupNames != NULL)
{
LONG lReturn = SCFree((LPVOID) lpmszGroupNames);
//
// If successful so far, then capture the return code
// from SCFree(); otherwise, don't bother.
//
if (lResult == SCARD_S_SUCCESS)
{
lResult = lReturn;
}
}
}
return lResult;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function : QueryCards
Synopsis : Print out a formatted list of card found in the specified reader
group to STDOUT.
Parameter: - IN SCARDCONTEXT hContext
Resource manager context returned by SCardEstablishContext(), or
NULL if the query is not directed towards a specific context.
- IN LPCTSTR lpmszReaderGroups
Pointer to multi-string reader group names, or NULL to specify all
readers known to the system.
Return : SCARD_S_SUCCESS or error code
------------------------------------------------------------------------------*/
LONG QueryCards (IN SCARDCONTEXT hContext,
IN LPCTSTR lpmszReaderGroups)
{
LONG lResult = SCARD_S_SUCCESS;
LPTSTR lpmszReaderNames = NULL;
__try
{
//
// Get the list of registered readers associated with the specified
// group(s).
// Note: The buffer is automatically allocated and must be freed
// by SCFree().
//
lResult = SCListReaders(hContext,
lpmszReaderGroups,
(LPTSTR *) &lpmszReaderNames);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
_tprintf(_T("\n"));
_tprintf(_T("Card in reader\n"));
_tprintf(_T("==============\n"));
//
// Note that MAXIMUM_SMARTCARD_READERS (10) only refers to maximum # of
// non-PnP readers. The resource manager is capable of handling any number
// of PnP readers, in addition to the 10 non-PnP readers (your physical
// system is the limiting factor). Make appropriate changes as necessary
// to accomodate more readers.
//
DWORD dwNumReaders = 0;
LPTSTR lpszReaderName = lpmszReaderNames;
SCARD_READERSTATE rsReaders[MAXIMUM_SMARTCARD_READERS];
ZeroMemory((LPVOID)rsReaders, sizeof(rsReaders));
//
// Prepare state array
//
while ((*lpszReaderName != _T('\0')) &&
(dwNumReaders < MAXIMUM_SMARTCARD_READERS))
{
rsReaders[dwNumReaders].szReader = (LPCTSTR)lpszReaderName;
rsReaders[dwNumReaders].dwCurrentState = SCARD_STATE_UNAWARE;
dwNumReaders++;
lpszReaderName += lstrlen(lpszReaderName) + 1;
}
if (dwNumReaders == 0)
{
_tprintf(_T("No registered reader was found for the specified "
_T("reader group(s) [%s].\n")), lpmszReaderGroups);
__leave;
}
//
// Now check state of each reader
//
lResult = SCardGetStatusChange(hContext,
INFINITE,
rsReaders,
dwNumReaders);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
for (DWORD dwIndex = 0; dwIndex < dwNumReaders; dwIndex++)
{
//
// Print out reader name
//
_tprintf(_T("%02d: %s\n"), dwIndex + 1, rsReaders[dwIndex].szReader);
//
// If a card is present in this reader, print ATR and
// any extra data from the Select File command.
//
if (!(rsReaders[dwIndex].dwEventState & SCARD_STATE_PRESENT))
{
_tprintf(_T(" No Smart Card found in this reader.\n"));
continue;
}
SCARDHANDLE hCard = NULL;
LPBYTE lpbResponse = NULL;
__try
{
DWORD dwActiveProtocol;
//
// Connect to the card
//
lResult = SCardConnect(hContext,
rsReaders[dwIndex].szReader,
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
&hCard,
&dwActiveProtocol);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
DWORD dwReaderLen = 0;
DWORD dwState;
DWORD dwProtocol;
BYTE atr[MAXIMUM_ATTR_STRING_LENGTH];
DWORD dwAtrLen;
//
// Get status of card
//
lResult = SCardStatus(hCard,
NULL,
&dwReaderLen,
&dwState,
&dwProtocol,
atr,
&dwAtrLen);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
//
// Print out ATR bytes of card
//
_tprintf(_T(" ATR = "), dwIndex + 1);
for (DWORD i = 0; i < dwAtrLen; i++)
{
_tprintf(_T("%02x "), (DWORD) atr[i]);
}
_tprintf(_T("\n"));
BYTE filename[2] = {0x3f, 0x00};
DWORD dwExtraBytes;
//
// Select Master File (0x3f00)
//
lResult = SCSelectFile(hCard,
filename,
&dwExtraBytes);
if (lResult != SCARD_S_SUCCESS)
{
__leave;
}
//
// Any extra data?
//
if (dwExtraBytes)
{
//
// Yes, so retrieve it
//
lResult = SCGetResponse(hCard, dwExtraBytes, &lpbResponse);
if (lResult == SCARD_S_SUCCESS)
{
//
// Print out MF file control information
//
_tprintf(_T(" FCI = "), dwIndex + 1);
for (DWORD i = 0; i < dwExtraBytes; i++)
{
_tprintf(_T("%02x "), (DWORD) lpbResponse[i]);
}
_tprintf(_T("\n"));
}
}
_tprintf(_T("\n"));
}
__finally
{
LONG lReturn;
//
// Don't forget to release the memory block if it had been
// allocated by SCGetResponse().
//
if (lpbResponse != NULL)
{
lReturn = SCFree((LPVOID) lpbResponse);
//
// If successful so far, then capture the return code
// from SCFree(); otherwise, don't bother.
//
if (lResult == SCARD_S_SUCCESS)
{
lResult = lReturn;
}
}
//
// Don't forget to disconnect the card.
//
if (hCard != NULL)
{
lReturn = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
//
// If successful so far, then capture the SCardDisconnect()
// return code; otherwise, don't bother.
//
if (lResult == SCARD_S_SUCCESS)
{
lResult = lReturn;
}
}
}
}
}
__finally
{
LONG lReturn;
//
// Don't forget to release memory, if allocated.
//
if (lpmszReaderNames != NULL)
{
lReturn = SCFree((LPVOID) lpmszReaderNames);
//
// If successful so far, then capture the return code
// from SCFree(); otherwise, don't bother.
//
if (lResult == SCARD_S_SUCCESS)
{
lResult = lReturn;
}
}
}
return lResult;
}