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.
 
 
 
 
 
 

2341 lines
60 KiB

#include <windows.h>
#include "basecsp.h"
#include "cardmod.h"
#include "debug.h"
//
// Debugging Macros
//
#define LOG_BEGIN_FUNCTION(x) \
{ DebugLog((DEB_TRACE_CACHE, "%s: Entering\n", #x)); }
#define LOG_END_FUNCTION(x, y) \
{ DebugLog((DEB_TRACE_CACHE, "%s: Leaving, status: 0x%x\n", #x, y)); }
//
// Type: CARD_CACHED_DATA_TYPE
//
// These values are used as keys for the card data cache,
// to distinguish the various types of cached data.
//
typedef enum
{
Cached_CardCapabilities = 1,
Cached_ContainerInfo,
Cached_GeneralFile,
Cached_FileEnumeration,
Cached_ContainerEnumeration,
Cached_KeySizes,
Cached_FreeSpace,
Cached_CardmodFile,
Cached_Pin
} CARD_CACHED_DATA_TYPE;
//
// Type: CARD_CACHE_FRESHNESS_LOCATION
//
// These values distinguish the broad classes of card data.
//
typedef DWORD CARD_CACHE_FRESHNESS_LOCATION;
#define CacheLocation_Pins 1
#define CacheLocation_Containers 2
#define CacheLocation_Files 4
//
// Type: CARD_CACHE_ITEM_INFO
//
// This struct is used as the actual item to be added to the
// cache for each data item cached. The data itself is expected to follow
// this header in memory, so that the blob can be managed by a single pointer.
//
typedef struct _CARD_CACHE_ITEM_INFO
{
CARD_CACHE_FILE_FORMAT CacheFreshness;
DWORD cbCachedItem;
} CARD_CACHE_ITEM_INFO, *PCARD_CACHE_ITEM_INFO;
//
// Used for the CARD_CACHE_QUERY_INFO dwQuerySource member
//
#define CARD_CACHE_QUERY_SOURCE_CSP 0
#define CARD_CACHE_QUERY_SOURCE_CARDMOD 1
//
// Type: CARD_CACHE_QUERY_INFO
//
// This is the parameter list for the
// I_CspQueryCardCacheForItem function, below.
//
typedef struct _CARD_CACHE_QUERY_INFO
{
// Input parameters
PCARD_STATE pCardState;
CARD_CACHE_FRESHNESS_LOCATION CacheLocation;
BOOL fIsPerishable;
DWORD cCacheKeys;
DATA_BLOB *mpdbCacheKeys;
DWORD dwQuerySource;
// Output parameters
CARD_CACHE_FILE_FORMAT CacheFreshness;
BOOL fCheckedFreshness;
PCARD_CACHE_ITEM_INFO pItem;
BOOL fFoundStaleItem;
} CARD_CACHE_QUERY_INFO, *PCARD_CACHE_QUERY_INFO;
//
// Function: CountCharsInMultiSz
//
DWORD CountCharsInMultiSz(
IN LPWSTR mwszStrings)
{
DWORD cch = 0;
while (L'\0' != mwszStrings[cch])
cch += wcslen(mwszStrings + cch) + 1;
return cch + 1;
}
//
// Function: MyCacheAddItem
//
// Purpose: Provide the caching functionality of SCardCacheAddItem, until that
// function is available via winscard.dll
//
DWORD WINAPI MyCacheAddItem(
IN PCARD_CACHE_QUERY_INFO pInfo,
IN DATA_BLOB *pdbItem)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB dbLocalItem;
CACHEHANDLE hCache = 0;
memset(&dbLocalItem, 0, sizeof(dbLocalItem));
if (CARD_CACHE_QUERY_SOURCE_CSP == pInfo->dwQuerySource &&
NULL != pInfo->pCardState->pfnCacheAdd)
{
dwSts = pInfo->pCardState->pfnCacheAdd(
pInfo->mpdbCacheKeys,
pInfo->cCacheKeys,
pdbItem);
}
else
{
switch (pInfo->dwQuerySource)
{
case CARD_CACHE_QUERY_SOURCE_CSP:
hCache = pInfo->pCardState->hCache;
break;
case CARD_CACHE_QUERY_SOURCE_CARDMOD:
hCache = pInfo->pCardState->hCacheCardModuleData;
break;
default:
dwSts = ERROR_INTERNAL_ERROR;
goto Ret;
}
//
// Since we expect that the winscard cache will make a copy of our
// data buffer, we need to do that here to expose the same
// behavior.
//
dbLocalItem.cbData = pdbItem->cbData;
dbLocalItem.pbData = CspAllocH(pdbItem->cbData);
LOG_CHECK_ALLOC(dbLocalItem.pbData);
memcpy(
dbLocalItem.pbData,
pdbItem->pbData,
dbLocalItem.cbData);
dwSts = CacheAddItem(
hCache,
pInfo->mpdbCacheKeys,
pInfo->cCacheKeys,
&dbLocalItem);
}
Ret:
return dwSts;
}
//
// Function: MyCacheLookupItem
//
// Provide: Provide the caching functionality of SCardCacheLookupItem, until
// that function is available via winscard.dll.
//
// Assumes that the caller will free the buffer pInfo->dbItem.pbData
//
DWORD WINAPI MyCacheLookupItem(
IN PCARD_CACHE_QUERY_INFO pInfo,
IN OUT PDATA_BLOB pdbItem)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB dbLocalItem;
CACHEHANDLE hCache = 0;
SCARD_CACHE_LOOKUP_ITEM_INFO ScardCacheLookup;
memset(&dbLocalItem, 0, sizeof(dbLocalItem));
memset(&ScardCacheLookup, 0, sizeof(ScardCacheLookup));
if (pInfo->pCardState->pfnCacheLookup)
{
ScardCacheLookup.cCacheKey = pInfo->cCacheKeys;
ScardCacheLookup.dwVersion =
SCARD_CACHE_LOOKUP_ITEM_INFO_CURRENT_VERSION;
ScardCacheLookup.pfnAlloc = CspAllocH;
ScardCacheLookup.mpdbCacheKey = pInfo->mpdbCacheKeys;
dwSts = pInfo->pCardState->pfnCacheLookup(&ScardCacheLookup);
if (ERROR_SUCCESS != dwSts)
goto Ret;
pdbItem->cbData = ScardCacheLookup.dbItem.cbData;
pdbItem->pbData = ScardCacheLookup.dbItem.pbData;
}
else
{
switch (pInfo->dwQuerySource)
{
case CARD_CACHE_QUERY_SOURCE_CSP:
hCache = pInfo->pCardState->hCache;
break;
case CARD_CACHE_QUERY_SOURCE_CARDMOD:
hCache = pInfo->pCardState->hCacheCardModuleData;
break;
default:
dwSts = ERROR_INTERNAL_ERROR;
goto Ret;
}
dwSts = CacheGetItem(
hCache,
pInfo->mpdbCacheKeys,
pInfo->cCacheKeys,
&dbLocalItem);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Expect that the winscard cache will make a copy of the cached data
// buffer before returning it to us. So, we need to make our own copy
// of the buffer in this code path.
//
pdbItem->cbData = dbLocalItem.cbData;
pdbItem->pbData = CspAllocH(dbLocalItem.cbData);
LOG_CHECK_ALLOC(pdbItem->pbData);
memcpy(
pdbItem->pbData,
dbLocalItem.pbData,
pdbItem->cbData);
}
Ret:
return dwSts;
}
//
// Function: MyCacheDeleteItem
//
DWORD WINAPI MyCacheDeleteItem(
IN PCARD_CACHE_QUERY_INFO pInfo)
{
DWORD dwSts = ERROR_SUCCESS;
CACHEHANDLE hCache = 0;
//
// We're only concerned about deleting cached items if we're doing local
// caching. Otherwise, we assume that the global cache is doing its own
// management of stale items.
//
if (NULL == pInfo->pCardState->pfnCacheAdd ||
CARD_CACHE_QUERY_SOURCE_CARDMOD == pInfo->dwQuerySource)
{
switch (pInfo->dwQuerySource)
{
case CARD_CACHE_QUERY_SOURCE_CSP:
hCache = pInfo->pCardState->hCache;
break;
case CARD_CACHE_QUERY_SOURCE_CARDMOD:
hCache = pInfo->pCardState->hCacheCardModuleData;
break;
default:
dwSts = ERROR_INTERNAL_ERROR;
goto Ret;
}
dwSts = CacheDeleteItem(
hCache,
pInfo->mpdbCacheKeys,
pInfo->cCacheKeys);
}
Ret:
return dwSts;
}
//
// Function: I_CspReadCardCacheFile
//
DWORD I_CspReadCardCacheFile(
IN PCARD_STATE pCardState,
OUT PCARD_CACHE_FILE_FORMAT pCacheFile)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB dbCacheFile;
if (FALSE == pCardState->fCacheFileValid)
{
memset(&dbCacheFile, 0, sizeof(dbCacheFile));
dwSts = pCardState->pCardData->pfnCardReadFile(
pCardState->pCardData,
wszCACHE_FILE_FULL_PATH,
0,
&dbCacheFile.pbData,
&dbCacheFile.cbData);
if (ERROR_SUCCESS != dwSts)
goto Ret;
if (sizeof(CARD_CACHE_FILE_FORMAT) != dbCacheFile.cbData)
{
dwSts = ERROR_BAD_LENGTH;
goto Ret;
}
memcpy(
&pCardState->CacheFile,
dbCacheFile.pbData,
sizeof(CARD_CACHE_FILE_FORMAT));
pCardState->fCacheFileValid = TRUE;
CspFreeH(dbCacheFile.pbData);
}
memcpy(
pCacheFile,
&pCardState->CacheFile,
sizeof(CARD_CACHE_FILE_FORMAT));
Ret:
return dwSts;
}
//
// Function: I_CspWriteCardCacheFile
//
DWORD I_CspWriteCardCacheFile(
IN PCARD_STATE pCardState,
IN PCARD_CACHE_FILE_FORMAT pCacheFile)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB dbCacheFile;
memset(&dbCacheFile, 0, sizeof(dbCacheFile));
dbCacheFile.pbData = (PBYTE) pCacheFile;
dbCacheFile.cbData = sizeof(CARD_CACHE_FILE_FORMAT);
dwSts = pCardState->pCardData->pfnCardWriteFile(
pCardState->pCardData,
wszCACHE_FILE_FULL_PATH,
0,
dbCacheFile.pbData,
dbCacheFile.cbData);
if (ERROR_SUCCESS != dwSts)
goto Ret;
// Also update the cached copy of the cache file in the CARD_STATE.
memcpy(
&pCardState->CacheFile,
pCacheFile,
sizeof(CARD_CACHE_FILE_FORMAT));
pCardState->fCacheFileValid = TRUE;
Ret:
return dwSts;
}
//
// Function: I_CspIncrementCacheFreshness
//
// Purpose: Indicates that an item in the specified cache location is
// being updated. As a result, the corresponding counter in
// the cache file will be incremented.
//
DWORD I_CspIncrementCacheFreshness(
IN PCARD_STATE pCardState,
IN CARD_CACHE_FRESHNESS_LOCATION CacheLocation,
OUT PCARD_CACHE_FILE_FORMAT pNewFreshness)
{
DWORD dwSts = ERROR_SUCCESS;
memset(pNewFreshness, 0, sizeof(CARD_CACHE_FILE_FORMAT));
dwSts = I_CspReadCardCacheFile(
pCardState, pNewFreshness);
if (ERROR_SUCCESS != dwSts)
goto Ret;
if (CacheLocation_Pins & CacheLocation)
++pNewFreshness->bPinsFreshness;
if (CacheLocation_Containers & CacheLocation)
++pNewFreshness->wContainersFreshness;
if (CacheLocation_Files & CacheLocation)
++pNewFreshness->wFilesFreshness;
dwSts = I_CspWriteCardCacheFile(
pCardState, pNewFreshness);
Ret:
return dwSts;
}
//
// Function: I_CspAddCardCacheItem
//
// Purpose: Abstract the process of caching some card data that has been
// confirmed to not exist cached (or was removed for being
// stale.
// Copy the provided card data, wrap it in a CARD_CACHE_ITEM_INFO
// structure and then cache it.
//
// Assume: The card state critical section must be held by caller.
// I_CspQueryCardCacheForItem should be called before this function,
// without releasing the crit sec between the two calls.
//
DWORD I_CspAddCardCacheItem(
IN PCARD_CACHE_QUERY_INFO pInfo,
IN PCARD_CACHE_ITEM_INFO pItem)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB dbItem;
DsysAssert(NULL == pInfo->pItem);
memset(&dbItem, 0, sizeof(dbItem));
if (pInfo->fIsPerishable)
{
if (pInfo->fCheckedFreshness)
{
memcpy(
&pItem->CacheFreshness,
&pInfo->CacheFreshness,
sizeof(pInfo->CacheFreshness));
}
else
{
// This item can stale, and we haven't already queried for the
// current cache counter for this location, so do it now.
dwSts = I_CspReadCardCacheFile(
pInfo->pCardState,
&pItem->CacheFreshness);
if (ERROR_SUCCESS != dwSts)
goto Ret;
}
}
dbItem.pbData = (PBYTE) pItem;
dbItem.cbData = sizeof(CARD_CACHE_ITEM_INFO) + pItem->cbCachedItem;
dwSts = MyCacheAddItem(pInfo, &dbItem);
Ret:
return dwSts;
}
//
// Function: I_CspQueryCardCacheForItem
//
// Purpose: Abstract some of the processing that needs to be done for cache
// lookups of card data. If the item is found
// cached, check if it's perishable, and if so, if it's still valid.
// If it's valid, done.
// If the data is not valid, free it's resources and delete its
// entry from the cache.
//
// Assume: The CARD_STATE critical section is assumed to be held by the caller.
// Also, that the item returned by cache lookups is of type
// CARD_CACHE_ITEM_INFO.
//
DWORD I_CspQueryCardCacheForItem(
PCARD_CACHE_QUERY_INFO pInfo)
{
DWORD dwSts = ERROR_SUCCESS;
PCARD_CACHE_ITEM_INFO pCacheItem = NULL;
BOOL fItemIsFresh = TRUE;
DATA_BLOB dbLocalItem;
LOG_BEGIN_FUNCTION(I_CspQueryCardCacheForItem);
memset(&dbLocalItem, 0, sizeof(dbLocalItem));
pInfo->pItem = NULL;
dwSts = MyCacheLookupItem(pInfo, &dbLocalItem);
switch (dwSts)
{
case ERROR_SUCCESS:
// Item was found cached
pCacheItem = (PCARD_CACHE_ITEM_INFO) dbLocalItem.pbData;
if (TRUE == pInfo->fIsPerishable)
{
// Is the cached data stale?
if (FALSE == pInfo->fCheckedFreshness)
{
// We haven't already read the card cache file for this
// query, so do it now.
dwSts = I_CspReadCardCacheFile(
pInfo->pCardState,
&pInfo->CacheFreshness);
if (ERROR_SUCCESS != dwSts)
goto Ret;
pInfo->fCheckedFreshness = TRUE;
}
//
// Mask out and check each cache counter location, since some
// cached data types may be dependent on multiple cache
// locations to stay fresh.
//
if (CacheLocation_Pins & pInfo->CacheLocation)
{
if ( pCacheItem->CacheFreshness.bPinsFreshness <
pInfo->CacheFreshness.bPinsFreshness)
fItemIsFresh = FALSE;
}
if (CacheLocation_Containers & pInfo->CacheLocation)
{
if ( pCacheItem->CacheFreshness.wContainersFreshness <
pInfo->CacheFreshness.wContainersFreshness)
fItemIsFresh = FALSE;
}
if (CacheLocation_Files & pInfo->CacheLocation)
{
if ( pCacheItem->CacheFreshness.wFilesFreshness <
pInfo->CacheFreshness.wFilesFreshness)
fItemIsFresh = FALSE;
}
if (FALSE == fItemIsFresh)
{
// Cached data is not fresh. Delete it from the cache.
pInfo->fFoundStaleItem = TRUE;
dwSts = MyCacheDeleteItem(pInfo);
if (ERROR_SUCCESS != dwSts)
goto Ret;
// Set error to indicate no cached item is being
// returned.
dwSts = ERROR_NOT_FOUND;
goto Ret;
}
}
// Item is either not perishable, or still fresh.
pInfo->pItem = pCacheItem;
pCacheItem = NULL;
break;
case ERROR_NOT_FOUND:
// No cached data was found
// Don't do anything else at this point, just report the
// status to the caller.
break;
default:
// some sort of unexpected error occurred
goto Ret;
}
Ret:
if (pCacheItem)
CspFreeH(pCacheItem);
LOG_END_FUNCTION(I_CspQueryCardCacheForItem, dwSts);
return dwSts;
}
//
// Initializes the CARD_CACHE_QUERY_INFO structure for a cache lookup
// being performed on behalf of the card module.
//
void I_CspCacheInitializeQueryForCardmod(
IN PVOID pvCacheContext,
IN LPWSTR wszFileName,
IN OUT PCARD_CACHE_QUERY_INFO pInfo,
IN OUT PDATA_BLOB mpdbCacheKeys,
IN DWORD cCacheKeys)
{
CARD_CACHED_DATA_TYPE cachedType = Cached_CardmodFile;
DsysAssert(3 == cCacheKeys);
// Setup the cache keys for this item
mpdbCacheKeys[0].cbData = sizeof(cachedType);
mpdbCacheKeys[0].pbData = (PBYTE) &cachedType;
mpdbCacheKeys[1].cbData =
wcslen(
((PCARD_STATE) pvCacheContext)->wszSerialNumber) * sizeof(WCHAR);
mpdbCacheKeys[1].pbData =
(PBYTE) ((PCARD_STATE) pvCacheContext)->wszSerialNumber;
mpdbCacheKeys[2].cbData = wcslen(wszFileName) * sizeof(wszFileName[0]);
mpdbCacheKeys[2].pbData = (PBYTE) wszFileName;
//
// Since the card module will use this function to cache files that
// aren't "owned" by the Base CSP, and since cardmod files probably
// don't map to our CacheLocation's very well, assume that any change
// to any part of the card should cause this cached data to be staled.
//
pInfo->CacheLocation =
CacheLocation_Pins | CacheLocation_Files | CacheLocation_Containers;
pInfo->cCacheKeys = cCacheKeys;
pInfo->dwQuerySource = CARD_CACHE_QUERY_SOURCE_CARDMOD;
pInfo->fIsPerishable = TRUE;
pInfo->mpdbCacheKeys = mpdbCacheKeys;
pInfo->pCardState = (PCARD_STATE) pvCacheContext;
}
//
// Cache "Add item" function exposed to the card module.
//
DWORD WINAPI CspCacheAddFileProc(
IN PVOID pvCacheContext,
IN LPWSTR wszTag,
IN DWORD dwFlags,
IN PBYTE pbData,
IN DWORD cbData)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKeys[3];
PCARD_CACHE_ITEM_INFO pItem = NULL;
CARD_CACHE_QUERY_INFO CacheQueryInfo;
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
if (0 == cbData || NULL == pbData)
goto Ret;
// Copy the data to be cached into a buffer w/ space for a cache
// header.
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO) + cbData);
LOG_CHECK_ALLOC(pItem);
memcpy(
((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
pbData,
cbData);
pItem->cbCachedItem = cbData;
I_CspCacheInitializeQueryForCardmod(
pvCacheContext,
wszTag,
&CacheQueryInfo,
rgdbKeys,
sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
dwSts = I_CspAddCardCacheItem(&CacheQueryInfo, pItem);
Ret:
if (pItem)
CspFreeH(pItem);
return dwSts;
}
//
// Cache "Lookup item" function exposed to the card module.
//
DWORD WINAPI CspCacheLookupFileProc(
IN PVOID pvCacheContext,
IN LPWSTR wszTag,
IN DWORD dwFlags,
IN PBYTE *ppbData,
IN PDWORD pcbData)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKeys[3];
CARD_CACHE_QUERY_INFO CacheQueryInfo;
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
*ppbData = NULL;
*pcbData = 0;
I_CspCacheInitializeQueryForCardmod(
pvCacheContext,
wszTag,
&CacheQueryInfo,
rgdbKeys,
sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
dwSts = I_CspQueryCardCacheForItem(&CacheQueryInfo);
// Will return ERROR_NOT_FOUND if no matching cached item was found.
if (ERROR_SUCCESS != dwSts)
goto Ret;
*pcbData = CacheQueryInfo.pItem->cbCachedItem;
*ppbData = (PBYTE) CspAllocH(*pcbData);
LOG_CHECK_ALLOC(*ppbData);
memcpy(
*ppbData,
((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
*pcbData);
Ret:
return dwSts;
}
//
// Cache "Delete item" function exposed to the card module.
//
DWORD WINAPI CspCacheDeleteFileProc(
IN PVOID pvCacheContext,
IN LPWSTR wszTag,
IN DWORD dwFlags)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKeys[3];
CARD_CACHE_QUERY_INFO CacheQueryInfo;
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
I_CspCacheInitializeQueryForCardmod(
pvCacheContext,
wszTag,
&CacheQueryInfo,
rgdbKeys,
sizeof(rgdbKeys) / sizeof(rgdbKeys[0]));
dwSts = MyCacheDeleteItem(&CacheQueryInfo);
return dwSts;
}
//
// Initializes caching for the CSP and for the caching helper routines
// provided to the card module.
//
DWORD InitializeCspCaching(
IN OUT PCARD_STATE pCardState)
{
DWORD dwSts = ERROR_SUCCESS;
CACHE_INITIALIZE_INFO CacheInitializeInfo;
memset(&CacheInitializeInfo, 0, sizeof(CacheInitializeInfo));
//
// Initialize caching for the CSP
//
// Data cached by the CSP should be cached system-wide if possible.
CacheInitializeInfo.dwType = CACHE_TYPE_SERVICE;
//
// Initialize our data caching routines. First, see if winscard.dll
// provides caching routines. If it does, use them. Otherwise,
// use our own local cache.
//
pCardState->hWinscard = LoadLibrary(L"winscard.dll");
if (NULL == pCardState->hWinscard)
{
dwSts = GetLastError();
goto Ret;
}
pCardState->pfnCacheLookup = (PFN_SCARD_CACHE_LOOKUP_ITEM) GetProcAddress(
pCardState->hWinscard,
"SCardCacheLookupItem");
if (NULL == pCardState->pfnCacheLookup)
{
// Since this export is missing from winscard, use local caching.
dwSts = CacheInitializeCache(
&pCardState->hCache,
&CacheInitializeInfo);
if (ERROR_SUCCESS != dwSts)
goto Ret;
}
else
{
pCardState->pfnCacheAdd = (PFN_SCARD_CACHE_ADD_ITEM) GetProcAddress(
pCardState->hWinscard,
"SCardCacheAddItem");
if (NULL == pCardState->pfnCacheAdd)
{
dwSts = GetLastError();
goto Ret;
}
}
//
// Initialize caching for the card module
//
// Assume that file data cached by the card module should only be
// maintained per-process, not system-wide.
CacheInitializeInfo.dwType = CACHE_TYPE_IN_PROC;
dwSts = CacheInitializeCache(
&pCardState->hCacheCardModuleData,
&CacheInitializeInfo);
if (ERROR_SUCCESS != dwSts)
goto Ret;
// When the card module calls back to use our caching routines,
// we need a pointer to the CARD_STATE.
pCardState->pCardData->pvCacheContext = pCardState;
pCardState->pCardData->pfnCspCacheAddFile = CspCacheAddFileProc;
pCardState->pCardData->pfnCspCacheDeleteFile = CspCacheDeleteFileProc;
pCardState->pCardData->pfnCspCacheLookupFile = CspCacheLookupFileProc;
Ret:
return dwSts;
}
//
// Function: InitializeCardState
//
DWORD InitializeCardState(
IN OUT PCARD_STATE pCardState)
{
DWORD dwSts = ERROR_SUCCESS;
dwSts = CspInitializeCriticalSection(
&pCardState->cs);
if (ERROR_SUCCESS != dwSts)
goto Ret;
else
pCardState->fInitializedCS = TRUE;
Ret:
if (ERROR_SUCCESS != dwSts)
DeleteCardState(pCardState);
return dwSts;
}
//
// Takes an array of DATA_BLOB structures, enumerated from a cache.
// Frees all "pbData" pointers in the array.
//
void FreeCacheItems(
PDATA_BLOB pdbItems,
DWORD cItems)
{
PCARD_CACHE_ITEM_INFO pItemInfo = NULL;
PCONTAINER_INFO pContainerInfo = NULL;
while (0 != cItems--)
CspFreeH(pdbItems[cItems].pbData);
}
//
// Function: InitializeCardData
//
DWORD InitializeCardData(PCARD_DATA pCardData)
{
DWORD dwSts = ERROR_SUCCESS;
CACHE_INITIALIZE_INFO CacheInitializeInfo;
memset(&CacheInitializeInfo, 0, sizeof(CacheInitializeInfo));
pCardData->dwVersion = CARD_DATA_CURRENT_VERSION;
pCardData->pfnCspAlloc = CspAllocH;
pCardData->pfnCspReAlloc = CspReAllocH;
pCardData->pfnCspFree = CspFreeH;
return dwSts;
}
//
// Function: CleanupCardData
//
void CleanupCardData(PCARD_DATA pCardData)
{
if (pCardData->pfnCardDeleteContext)
pCardData->pfnCardDeleteContext(pCardData);
if (pCardData->pbAtr)
{
CspFreeH(pCardData->pbAtr);
pCardData->pbAtr = NULL;
}
if (pCardData->pwszCardName)
{
CspFreeH(pCardData->pwszCardName);
pCardData->pwszCardName = NULL;
}
if (pCardData->hScard)
{
SCardDisconnect(pCardData->hScard, SCARD_LEAVE_CARD);
pCardData->hScard = 0;
}
if (pCardData->hSCardCtx)
{
SCardReleaseContext(pCardData->hSCardCtx);
pCardData->hSCardCtx = 0;
}
}
//
// Enumerates and frees all items in the cache, then deletes the cache.
//
void DeleteCacheAndAllItems(CACHEHANDLE hCache)
{
PDATA_BLOB pdbCacheItems = NULL;
DWORD cCacheItems = 0;
if (ERROR_SUCCESS == CacheEnumItems(
hCache, &pdbCacheItems, &cCacheItems))
{
FreeCacheItems(pdbCacheItems, cCacheItems);
CacheFreeEnumItems(pdbCacheItems);
}
CacheDeleteCache(hCache);
}
//
// Function: DeleteCardState
//
void DeleteCardState(PCARD_STATE pCardState)
{
DWORD dwSts = ERROR_SUCCESS;
if (pCardState->fInitializedCS)
CspDeleteCriticalSection(
&pCardState->cs);
if (pCardState->hCache)
{
// Need to free all of our cached data before
// deleting the cache handle.
DeleteCacheAndAllItems(pCardState->hCache);
pCardState->hCache = 0;
}
if (pCardState->hCacheCardModuleData)
{
// Need to free the card module cached data.
DeleteCacheAndAllItems(pCardState->hCacheCardModuleData);
pCardState->hCacheCardModuleData = 0;
}
if (pCardState->hWinscard)
{
FreeLibrary(pCardState->hWinscard);
pCardState->hWinscard = NULL;
pCardState->pfnCacheAdd = NULL;
pCardState->pfnCacheLookup = NULL;
}
if (pCardState->pCardData)
{
CleanupCardData(pCardState->pCardData);
CspFreeH(pCardState->pCardData);
}
if (pCardState->hCardModule)
FreeLibrary(pCardState->hCardModule);
}
//
// Function: CspQueryCapabilities
//
DWORD
WINAPI
CspQueryCapabilities(
IN PCARD_STATE pCardState,
IN OUT PCARD_CAPABILITIES pCardCapabilities)
{
DWORD dwSts = ERROR_SUCCESS;
CARD_CACHE_QUERY_INFO CacheQueryInfo;
DATA_BLOB rgdbKeys[2];
PCARD_CACHE_ITEM_INFO pItem = NULL;
CARD_CACHED_DATA_TYPE cachedType = Cached_CardCapabilities;
memset(rgdbKeys, 0, sizeof(rgdbKeys));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
rgdbKeys[0].pbData = (PBYTE) &cachedType;
rgdbKeys[0].cbData = sizeof(cachedType);
rgdbKeys[1].pbData = (PBYTE) pCardState->wszSerialNumber;
rgdbKeys[1].cbData =
sizeof(WCHAR) * wcslen(pCardState->wszSerialNumber);
// Card Capabilities data item is Non-Perishable
CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
CacheQueryInfo.mpdbCacheKeys = rgdbKeys;
CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem(
&CacheQueryInfo);
switch (dwSts)
{
case ERROR_NOT_FOUND:
// This data has not yet been cached. We'll have to
// query the data from the card module.
dwSts = pCardState->pCardData->pfnCardQueryCapabilities(
pCardState->pCardData,
pCardCapabilities);
if (ERROR_SUCCESS != dwSts)
goto Ret;
// Now add this data to the cache before returning.
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_CAPABILITIES));
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = sizeof(CARD_CAPABILITIES);
memcpy(
((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
pCardCapabilities,
sizeof(CARD_CAPABILITIES));
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
break;
case ERROR_SUCCESS:
//
// The data was found in the cache.
//
DsysAssert(
sizeof(CARD_CAPABILITIES) == CacheQueryInfo.pItem->cbCachedItem);
memcpy(
pCardCapabilities,
((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
sizeof(CARD_CAPABILITIES));
break;
default:
// Unexpected error
break;
}
Ret:
if (CacheQueryInfo.pItem)
CspFreeH(CacheQueryInfo.pItem);
if (pItem)
CspFreeH(pItem);
return dwSts;
}
//
// Function: CspDeleteContainer
//
DWORD
WINAPI
CspDeleteContainer(
IN PCARD_STATE pCardState,
IN BYTE bContainerIndex,
IN DWORD dwReserved)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKeys[3];
CARD_CACHED_DATA_TYPE cachedType = Cached_ContainerInfo;
CARD_CACHE_FILE_FORMAT CacheFile;
CARD_CACHE_QUERY_INFO QueryInfo;
memset(&QueryInfo, 0, sizeof(QueryInfo));
memset(rgdbKeys, 0, sizeof(rgdbKeys));
//
// First, update the cache file.
//
dwSts = I_CspIncrementCacheFreshness(
pCardState,
CacheLocation_Containers,
&CacheFile);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Do the container deletion in the card module
//
dwSts = pCardState->pCardData->pfnCardDeleteContainer(
pCardState->pCardData,
bContainerIndex,
dwReserved);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Finally, delete any cached Container Information for the
// specified container.
//
// First part of key is data type
rgdbKeys[0].cbData = sizeof(cachedType);
rgdbKeys[0].pbData = (PBYTE) &cachedType;
// Second part of key is container name
rgdbKeys[1].cbData = sizeof(bContainerIndex);
rgdbKeys[1].pbData = &bContainerIndex;
rgdbKeys[2].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
QueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
QueryInfo.mpdbCacheKeys = rgdbKeys;
QueryInfo.pCardState = pCardState;
MyCacheDeleteItem(&QueryInfo);
Ret:
return dwSts;
}
//
// Function: CspCreateContainer
//
DWORD
WINAPI
CspCreateContainer(
IN PCARD_STATE pCardState,
IN BYTE bContainerIndex,
IN DWORD dwFlags,
IN DWORD dwKeySpec,
IN DWORD dwKeySize,
IN PBYTE pbKeyData)
{
DWORD dwSts = ERROR_SUCCESS;
CARD_CACHE_FILE_FORMAT CacheFreshness;
memset(&CacheFreshness, 0, sizeof(CacheFreshness));
//
// Update the cache file
//
dwSts = I_CspIncrementCacheFreshness(
pCardState,
CacheLocation_Containers,
&CacheFreshness);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Create the container on (and/or add the keyset to) the card
//
dwSts = pCardState->pCardData->pfnCardCreateContainer(
pCardState->pCardData,
bContainerIndex,
dwFlags,
dwKeySpec,
dwKeySize,
pbKeyData);
Ret:
return dwSts;
}
//
// Function: CspGetContainerInfo
//
// Purpose: Query for key information for the specified container.
//
// Note, the public key buffers returned in the PCONTAINER_INFO
// struct must be freed by the caller.
//
DWORD
WINAPI
CspGetContainerInfo(
IN PCARD_STATE pCardState,
IN BYTE bContainerIndex,
IN DWORD dwFlags,
IN OUT PCONTAINER_INFO pContainerInfo)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKey[3];
CARD_CACHED_DATA_TYPE cachedType = Cached_ContainerInfo;
CARD_CACHE_QUERY_INFO CacheQueryInfo;
PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKey, 0, sizeof(rgdbKey));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// first part of cache key is item type
rgdbKey[0].cbData = sizeof(cachedType);
rgdbKey[0].pbData = (PBYTE) &cachedType;
// second part of cache key is container name
rgdbKey[1].cbData = sizeof(bContainerIndex);
rgdbKey[1].pbData = &bContainerIndex;
rgdbKey[2].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
rgdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
CacheQueryInfo.CacheLocation = CacheLocation_Containers;
CacheQueryInfo.fIsPerishable = TRUE;
CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]);
CacheQueryInfo.mpdbCacheKeys = rgdbKey;
CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem(
&CacheQueryInfo);
switch (dwSts)
{
case ERROR_SUCCESS:
// Item was successfully found cached.
//
// This data length includes the size of the public keys, so we can
// only check a minimum size for the cached data.
//
DsysAssert(sizeof(CONTAINER_INFO) <= CacheQueryInfo.pItem->cbCachedItem);
memcpy(
pContainerInfo,
((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
sizeof(CONTAINER_INFO));
//
// Now we can check the exact length of the cached blob for sanity.
//
DsysAssert(
sizeof(CONTAINER_INFO) +
pContainerInfo->cbKeyExPublicKey +
pContainerInfo->cbSigPublicKey ==
CacheQueryInfo.pItem->cbCachedItem);
//
// If the Signature and Key Exchange public keys exist, copy them out
// of the "flat" cache structure.
//
if (pContainerInfo->cbKeyExPublicKey)
{
pContainerInfo->pbKeyExPublicKey = CspAllocH(
pContainerInfo->cbKeyExPublicKey);
LOG_CHECK_ALLOC(pContainerInfo->pbKeyExPublicKey);
memcpy(
pContainerInfo->pbKeyExPublicKey,
((PBYTE) CacheQueryInfo.pItem) +
sizeof(CARD_CACHE_ITEM_INFO) +
sizeof(CONTAINER_INFO),
pContainerInfo->cbKeyExPublicKey);
}
if (pContainerInfo->cbSigPublicKey)
{
pContainerInfo->pbSigPublicKey = CspAllocH(
pContainerInfo->cbSigPublicKey);
LOG_CHECK_ALLOC(pContainerInfo->pbSigPublicKey);
memcpy(
pContainerInfo->pbSigPublicKey,
((PBYTE) CacheQueryInfo.pItem) +
sizeof(CARD_CACHE_ITEM_INFO) +
sizeof(CONTAINER_INFO),
pContainerInfo->cbSigPublicKey);
}
break;
case ERROR_NOT_FOUND:
// No matching item was found cached, or the found item
// was stale. Have to read it from the card.
//
// Send the request to the card module
//
dwSts = pCardState->pCardData->pfnCardGetContainerInfo(
pCardState->pCardData,
bContainerIndex,
dwFlags,
pContainerInfo);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Cache the returned container information
//
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO) +
sizeof(CONTAINER_INFO) +
pContainerInfo->cbKeyExPublicKey +
pContainerInfo->cbSigPublicKey);
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem =
sizeof(CONTAINER_INFO) +
pContainerInfo->cbKeyExPublicKey +
pContainerInfo->cbSigPublicKey;
memcpy(
((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
pContainerInfo,
sizeof(CONTAINER_INFO));
if (pContainerInfo->pbKeyExPublicKey)
{
memcpy(
((PBYTE) pItem) +
sizeof(CARD_CACHE_ITEM_INFO) +
sizeof(CONTAINER_INFO),
pContainerInfo->pbKeyExPublicKey,
pContainerInfo->cbKeyExPublicKey);
}
if (pContainerInfo->pbSigPublicKey)
{
memcpy(
((PBYTE) pItem) +
sizeof(CARD_CACHE_ITEM_INFO) +
sizeof(CONTAINER_INFO) +
pContainerInfo->cbKeyExPublicKey,
pContainerInfo->pbSigPublicKey,
pContainerInfo->cbSigPublicKey);
}
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
break;
default:
// An unexpected error occurred.
goto Ret;
}
Ret:
if (pItem)
CspFreeH(pItem);
if (CacheQueryInfo.pItem)
CspFreeH(CacheQueryInfo.pItem);
if (ERROR_SUCCESS != dwSts)
{
if (pContainerInfo->pbKeyExPublicKey)
{
CspFreeH(pContainerInfo->pbKeyExPublicKey);
pContainerInfo->pbKeyExPublicKey = NULL;
}
if (pContainerInfo->pbSigPublicKey)
{
CspFreeH(pContainerInfo->pbSigPublicKey);
pContainerInfo->pbSigPublicKey = NULL;
}
}
return dwSts;
}
//
// Initializes the cache lookup keys and CARD_CACHE_QUERY_INFO structure
// pin-related cache operations.
//
void I_BuildPinCacheQueryInfo(
IN PCARD_STATE pCardState,
IN LPWSTR pwszUserId,
IN PDATA_BLOB pdbKey,
IN CARD_CACHED_DATA_TYPE *pType,
IN OUT PCARD_CACHE_QUERY_INFO pInfo)
{
// first part of cache key is item type
pdbKey[0].cbData = sizeof(CARD_CACHED_DATA_TYPE);
pdbKey[0].pbData = (PBYTE) pType;
// second part of cache key is user name
pdbKey[1].cbData =
wcslen(pwszUserId) * sizeof(WCHAR);
pdbKey[1].pbData = (PBYTE) pwszUserId;
pdbKey[2].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
pdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
pInfo->CacheLocation = CacheLocation_Pins;
pInfo->fIsPerishable = TRUE;
pInfo->mpdbCacheKeys = pdbKey;
pInfo->cCacheKeys = 3;
pInfo->pCardState = pCardState;
}
//
// Removes cached pin information for the specified user from the general data
// cache and the PinCache.
//
void
WINAPI
CspRemoveCachedPin(
IN PCARD_STATE pCardState,
IN LPWSTR pwszUserId)
{
DATA_BLOB rgdbKey[3];
CARD_CACHE_QUERY_INFO CacheQueryInfo;
PCARD_CACHE_ITEM_INFO pItem = NULL;
CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
memset(rgdbKey, 0, sizeof(rgdbKey));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
I_BuildPinCacheQueryInfo(
pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
MyCacheDeleteItem(&CacheQueryInfo);
PinCacheFlush(&pCardState->hPinCache);
}
//
// Record the change of the pin (or challenge) for the specified user in
// the data cache, and increment the pin cache counter on the card.
//
DWORD
WINAPI
CspChangeAuthenticator(
IN PCARD_STATE pCardState,
IN LPWSTR pwszUserId,
IN PBYTE pbCurrentAuthenticator,
IN DWORD cbCurrentAuthenticator,
IN PBYTE pbNewAuthenticator,
IN DWORD cbNewAuthenticator,
IN DWORD cRetryCount,
OUT OPTIONAL PDWORD pcAttemptsRemaining)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKey[3];
CARD_CACHE_QUERY_INFO CacheQueryInfo;
PCARD_CACHE_ITEM_INFO pItem = NULL;
CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
memset(rgdbKey, 0, sizeof(rgdbKey));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
//
// Do the requestion operation
//
dwSts = pCardState->pCardData->pfnCardChangeAuthenticator(
pCardState->pCardData,
pwszUserId,
pbCurrentAuthenticator,
cbCurrentAuthenticator,
pbNewAuthenticator,
cbNewAuthenticator,
cRetryCount,
pcAttemptsRemaining);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Update the Pins freshness counter of the card cache file. We do
// this after the pin change because we need to wait for the card to be
// authenticated.
//
dwSts = I_CspIncrementCacheFreshness(
pCardState,
CacheLocation_Pins,
&CacheQueryInfo.CacheFreshness);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Delete any existing entry for this user-pin in the cache
//
I_BuildPinCacheQueryInfo(
pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
MyCacheDeleteItem(&CacheQueryInfo);
//
// Cache the updated pin info
//
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO));
LOG_CHECK_ALLOC(pItem);
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
Ret:
if (pItem)
CspFreeH(pItem);
return dwSts;
}
//
// -- Expect that CspSubmitPin is only called from within a PinCache verify-pin
// callback. This is because the pbPin is expected to have come directly
// from the pin cache, and therefore may be stale.
//
// -- Expect that the user pin in the pin cache is tightly coupled to the
// cache stamp information cached in the general data cache for the user.
// That is, the cached pin must have been the correct pin when the pin-location
// cache stamp on the card had the stamp value that is stored in the general
// cache.
//
// This allows us to avoid presenting a pin to the card that we already know is
// wrong. This could happen, for example, if the pin has been changed via a
// separate process.
//
DWORD
WINAPI
CspSubmitPin(
IN PCARD_STATE pCardState,
IN LPWSTR pwszUserId,
IN PBYTE pbPin,
IN DWORD cbPin,
OUT OPTIONAL PDWORD pcAttemptsRemaining)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKey[3];
CARD_CACHE_QUERY_INFO CacheQueryInfo;
PCARD_CACHE_ITEM_INFO pItem = NULL;
CARD_CACHED_DATA_TYPE cachedType = Cached_Pin;
memset(rgdbKey, 0, sizeof(rgdbKey));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
I_BuildPinCacheQueryInfo(
pCardState, pwszUserId, rgdbKey, &cachedType, &CacheQueryInfo);
dwSts = I_CspQueryCardCacheForItem(
&CacheQueryInfo);
switch (dwSts)
{
case ERROR_SUCCESS:
// The user's cached pin appears to be synchronized with the pin
// cache counter on the card. Do the submit.
break;
case ERROR_NOT_FOUND:
if (TRUE == CacheQueryInfo.fFoundStaleItem)
{
//
// The user's cached pin is out of synch with the pin cache counter.
// Don't do the submit, but return a sensible error code.
//
dwSts = SCARD_W_WRONG_CHV;
goto Ret;
}
// There is no cached pin information for this user yet. Add it now.
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO));
LOG_CHECK_ALLOC(pItem);
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
if (ERROR_SUCCESS != dwSts)
goto Ret;
// Now continue and submit the pin
break;
default:
// Unexpected error occurred
goto Ret;
}
dwSts = pCardState->pCardData->pfnCardSubmitPin(
pCardState->pCardData,
pwszUserId,
pbPin,
cbPin,
pcAttemptsRemaining);
Ret:
if (pItem)
CspFreeH(pItem);
if (CacheQueryInfo.pItem)
CspFreeH(CacheQueryInfo.pItem);
return dwSts;
}
//
// Function: CspCreateFile
//
DWORD
WINAPI
CspCreateFile(
IN PCARD_STATE pCardState,
IN LPWSTR pwszFileName,
IN CARD_FILE_ACCESS_CONDITION AccessCondition)
{
DWORD dwSts = ERROR_SUCCESS;
CARD_CACHE_FILE_FORMAT CacheFreshness;
memset(&CacheFreshness, 0, sizeof(CacheFreshness));
//
// Update the Files freshness counter of the card cache file
//
dwSts = I_CspIncrementCacheFreshness(
pCardState,
CacheLocation_Files,
&CacheFreshness);
if (ERROR_SUCCESS != dwSts)
goto Ret;
dwSts = pCardState->pCardData->pfnCardCreateFile(
pCardState->pCardData,
pwszFileName,
AccessCondition);
Ret:
return dwSts;
}
//
// Function: CspReadFile
//
DWORD
WINAPI
CspReadFile(
IN PCARD_STATE pCardState,
IN LPWSTR pwszFileName,
IN DWORD dwFlags,
OUT PBYTE *ppbData,
OUT PDWORD pcbData)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKey[3];
CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile;
CARD_CACHE_QUERY_INFO CacheQueryInfo;
PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKey, 0, sizeof(rgdbKey));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// first part of cache key is item type
rgdbKey[0].cbData = sizeof(cachedType);
rgdbKey[0].pbData = (PBYTE) &cachedType;
// second part of cache key is file name
rgdbKey[1].cbData =
wcslen(pwszFileName) * sizeof(WCHAR);
rgdbKey[1].pbData = (PBYTE) pwszFileName;
rgdbKey[2].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
rgdbKey[2].pbData = (PBYTE) pCardState->wszSerialNumber;
CacheQueryInfo.CacheLocation = CacheLocation_Files;
CacheQueryInfo.fIsPerishable = TRUE;
CacheQueryInfo.mpdbCacheKeys = rgdbKey;
CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]);
CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem(
&CacheQueryInfo);
switch (dwSts)
{
case ERROR_SUCCESS:
// This file was found cached and up to date.
*pcbData = CacheQueryInfo.pItem->cbCachedItem;
*ppbData = CspAllocH(*pcbData);
LOG_CHECK_ALLOC(*ppbData);
memcpy(
*ppbData,
((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
*pcbData);
break;
case ERROR_NOT_FOUND:
// An up-to-date cached version of the file was not found
dwSts = pCardState->pCardData->pfnCardReadFile(
pCardState->pCardData,
pwszFileName,
dwFlags,
ppbData,
pcbData);
if (ERROR_SUCCESS != dwSts)
goto Ret;
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO) + *pcbData);
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = *pcbData;
memcpy(
((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
*ppbData,
*pcbData);
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
break;
default:
// Unexpected error occurred
break;
}
Ret:
if (pItem)
CspFreeH(pItem);
if (CacheQueryInfo.pItem)
CspFreeH(CacheQueryInfo.pItem);
if (ERROR_SUCCESS != dwSts)
{
if (*ppbData)
{
CspFreeH(*ppbData);
*ppbData = NULL;
}
}
return dwSts;
}
//
// Function: CspWriteFile
//
DWORD
WINAPI
CspWriteFile(
IN PCARD_STATE pCardState,
IN LPWSTR pwszFileName,
IN DWORD dwFlags,
IN PBYTE pbData,
IN DWORD cbData)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKeys[3];
CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile;
CARD_CACHE_QUERY_INFO CacheQueryInfo;
PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKeys, 0, sizeof(rgdbKeys));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
//
// Update the Files freshness counter of the card cache file
//
dwSts = I_CspIncrementCacheFreshness(
pCardState,
CacheLocation_Files,
&CacheQueryInfo.CacheFreshness);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Delete any existing entry for this file in the cache
//
// First cache lookup key is data type
rgdbKeys[0].cbData = sizeof(cachedType);
rgdbKeys[0].pbData = (PBYTE) &cachedType;
// Second cache lookup key is filename
rgdbKeys[1].cbData = wcslen(pwszFileName) * sizeof(WCHAR);
rgdbKeys[1].pbData = (PBYTE) pwszFileName;
rgdbKeys[2].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
CacheQueryInfo.fCheckedFreshness = TRUE;
CacheQueryInfo.fIsPerishable = TRUE;
CacheQueryInfo.mpdbCacheKeys = rgdbKeys;
CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
CacheQueryInfo.CacheLocation = CacheLocation_Files;
CacheQueryInfo.pCardState = pCardState;
//
// Since we know that any currently cached data for this file is
// obsolete, make an attempt to delete it from the cache.
//
MyCacheDeleteItem(&CacheQueryInfo);
//
// Perform the Write File operation
//
dwSts = pCardState->pCardData->pfnCardWriteFile(
pCardState->pCardData,
pwszFileName,
dwFlags,
pbData,
cbData);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Cache the updated file contents
//
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO) + cbData);
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = cbData;
memcpy(
((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
pbData,
cbData);
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
Ret:
if (pItem)
CspFreeH(pItem);
return dwSts;
}
//
// Function: CspDeleteFile
//
DWORD
WINAPI
CspDeleteFile(
IN PCARD_STATE pCardState,
IN DWORD dwReserved,
IN LPWSTR pwszFileName)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKeys[3];
CARD_CACHED_DATA_TYPE cachedType = Cached_GeneralFile;
CARD_CACHE_FILE_FORMAT CacheFile;
CARD_CACHE_QUERY_INFO QueryInfo;
memset(rgdbKeys, 0, sizeof(rgdbKeys));
memset(&QueryInfo, 0, sizeof(QueryInfo));
//
// Update the Files freshness counter of the card cache file
//
dwSts = I_CspIncrementCacheFreshness(
pCardState,
CacheLocation_Files,
&CacheFile);
if (ERROR_SUCCESS != dwSts)
goto Ret;
//
// Delete any existing entry for this file in the cache
//
// First cache lookup key is data type
rgdbKeys[0].cbData = sizeof(cachedType);
rgdbKeys[0].pbData = (PBYTE) &cachedType;
// Second cache lookup key is filename
rgdbKeys[1].cbData = wcslen(pwszFileName) * sizeof(WCHAR);
rgdbKeys[1].pbData = (PBYTE) pwszFileName;
rgdbKeys[2].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
QueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
QueryInfo.mpdbCacheKeys = rgdbKeys;
QueryInfo.pCardState = pCardState;
MyCacheDeleteItem(&QueryInfo);
//
// Do the CardDeleteFile operation
//
dwSts = pCardState->pCardData->pfnCardDeleteFile(
pCardState->pCardData,
dwReserved,
pwszFileName);
Ret:
return dwSts;
}
//
// Function: CspEnumFiles
//
DWORD
WINAPI
CspEnumFiles(
IN PCARD_STATE pCardState,
IN DWORD dwFlags,
IN OUT LPWSTR *pmwszFileNames)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKey[2];
CARD_CACHED_DATA_TYPE cachedType = Cached_FileEnumeration;
CARD_CACHE_QUERY_INFO CacheQueryInfo;
DWORD cbFileNames = 0;
PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKey, 0, sizeof(rgdbKey));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// cache key is item type
rgdbKey[0].cbData = sizeof(cachedType);
rgdbKey[0].pbData = (PBYTE) &cachedType;
rgdbKey[1].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
rgdbKey[1].pbData = (PBYTE) pCardState->wszSerialNumber;
CacheQueryInfo.CacheLocation = CacheLocation_Files;
CacheQueryInfo.fIsPerishable = TRUE;
CacheQueryInfo.mpdbCacheKeys = rgdbKey;
CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]);
CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem(
&CacheQueryInfo);
switch (dwSts)
{
case ERROR_SUCCESS:
// The list of files was found cached and up to date.
*pmwszFileNames = (LPWSTR) CspAllocH(
CacheQueryInfo.pItem->cbCachedItem);
memcpy(
(PBYTE) *pmwszFileNames,
((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
CacheQueryInfo.pItem->cbCachedItem);
break;
case ERROR_NOT_FOUND:
// An up-to-date cached version of the file was not found
dwSts = pCardState->pCardData->pfnCardEnumFiles(
pCardState->pCardData,
dwFlags,
pmwszFileNames);
if (ERROR_SUCCESS != dwSts)
goto Ret;
cbFileNames =
sizeof(WCHAR) * CountCharsInMultiSz(*pmwszFileNames);
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO) + cbFileNames);
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = cbFileNames;
memcpy(
((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
(PBYTE) *pmwszFileNames,
cbFileNames);
// Cache the new data
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
break;
default:
// Unexpected error occurred
break;
}
Ret:
if (pItem)
CspFreeH(pItem);
if (CacheQueryInfo.pItem)
CspFreeH(CacheQueryInfo.pItem);
if (ERROR_SUCCESS != dwSts)
{
if (*pmwszFileNames)
{
CspFreeH(*pmwszFileNames);
*pmwszFileNames = NULL;
}
}
return dwSts;
}
//
// Function: CspQueryFreeSpace
//
DWORD
WINAPI
CspQueryFreeSpace(
IN PCARD_STATE pCardState,
IN DWORD dwFlags,
OUT PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)
{
DWORD dwSts = ERROR_SUCCESS;
DATA_BLOB rgdbKey[2];
CARD_CACHED_DATA_TYPE cachedType = Cached_FreeSpace;
CARD_CACHE_QUERY_INFO CacheQueryInfo;
PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKey, 0, sizeof(rgdbKey));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// cache key is item type
rgdbKey[0].cbData = sizeof(cachedType);
rgdbKey[0].pbData = (PBYTE) &cachedType;
rgdbKey[1].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
rgdbKey[1].pbData = (PBYTE) pCardState->wszSerialNumber;
// Card Free Space information is dependent on both the Files
// and the Containers cache counters.
CacheQueryInfo.CacheLocation =
CacheLocation_Files | CacheLocation_Containers;
CacheQueryInfo.fIsPerishable = TRUE;
CacheQueryInfo.mpdbCacheKeys = rgdbKey;
CacheQueryInfo.cCacheKeys = sizeof(rgdbKey) / sizeof(rgdbKey[0]);
CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem(
&CacheQueryInfo);
switch (dwSts)
{
case ERROR_SUCCESS:
// Free Space info was found cached and up to date
DsysAssert(
sizeof(CARD_FREE_SPACE_INFO) ==
CacheQueryInfo.pItem->cbCachedItem);
memcpy(
pCardFreeSpaceInfo,
((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
sizeof(CARD_FREE_SPACE_INFO));
break;
case ERROR_NOT_FOUND:
// Up to date Free Space info was not found
dwSts = pCardState->pCardData->pfnCardQueryFreeSpace(
pCardState->pCardData,
dwFlags,
pCardFreeSpaceInfo);
if (ERROR_SUCCESS != dwSts)
goto Ret;
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_FREE_SPACE_INFO));
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = sizeof(CARD_FREE_SPACE_INFO);
memcpy(
((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
(PBYTE) pCardFreeSpaceInfo,
sizeof(CARD_FREE_SPACE_INFO));
// Cache the new data
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
break;
default:
// Unexpected error occurred
goto Ret;
}
Ret:
if (pItem)
CspFreeH(pItem);
if (CacheQueryInfo.pItem)
CspFreeH(CacheQueryInfo.pItem);
return dwSts;
}
//
// Function: CspPrivateKeyDecrypt
//
DWORD
WINAPI
CspPrivateKeyDecrypt(
IN PCARD_STATE pCardState,
IN PCARD_PRIVATE_KEY_DECRYPT_INFO pInfo)
{
return pCardState->pCardData->pfnCardPrivateKeyDecrypt(
pCardState->pCardData,
pInfo);
}
//
// Function: CspQueryKeySizes
//
DWORD
WINAPI
CspQueryKeySizes(
IN PCARD_STATE pCardState,
IN DWORD dwKeySpec,
IN DWORD dwReserved,
OUT PCARD_KEY_SIZES pKeySizes)
{
DWORD dwSts = ERROR_SUCCESS;
CARD_CACHE_QUERY_INFO CacheQueryInfo;
DATA_BLOB rgdbKeys[3];
CARD_CACHED_DATA_TYPE cachedType = Cached_KeySizes;
PCARD_CACHE_ITEM_INFO pItem = NULL;
memset(rgdbKeys, 0, sizeof(rgdbKeys));
memset(&CacheQueryInfo, 0, sizeof(CacheQueryInfo));
// First part of cache key is item type
rgdbKeys[0].pbData = (PBYTE) &cachedType;
rgdbKeys[0].cbData = sizeof(cachedType);
// Second part of cache key is public-key type
rgdbKeys[1].pbData = (PBYTE) &dwKeySpec;
rgdbKeys[1].cbData = sizeof(dwKeySpec);
rgdbKeys[2].pbData = (PBYTE) pCardState->wszSerialNumber;
rgdbKeys[2].cbData =
wcslen(pCardState->wszSerialNumber) * sizeof(WCHAR);
// Key Sizes data item is Non-Perishable
CacheQueryInfo.cCacheKeys = sizeof(rgdbKeys) / sizeof(rgdbKeys[0]);
CacheQueryInfo.mpdbCacheKeys = rgdbKeys;
CacheQueryInfo.pCardState = pCardState;
dwSts = I_CspQueryCardCacheForItem(
&CacheQueryInfo);
switch (dwSts)
{
case ERROR_NOT_FOUND:
// This data has not yet been cached. We'll have to
// query the data from the card module.
dwSts = pCardState->pCardData->pfnCardQueryKeySizes(
pCardState->pCardData,
dwKeySpec,
dwReserved,
pKeySizes);
if (ERROR_SUCCESS != dwSts)
goto Ret;
// Now add this data to the cache
pItem = (PCARD_CACHE_ITEM_INFO) CspAllocH(
sizeof(CARD_CACHE_ITEM_INFO) + sizeof(CARD_KEY_SIZES));
LOG_CHECK_ALLOC(pItem);
pItem->cbCachedItem = sizeof(CARD_KEY_SIZES);
memcpy(
((PBYTE) pItem) + sizeof(CARD_CACHE_ITEM_INFO),
(PBYTE) pKeySizes,
sizeof(CARD_KEY_SIZES));
dwSts = I_CspAddCardCacheItem(
&CacheQueryInfo,
pItem);
break;
case ERROR_SUCCESS:
//
// The data was found in the cache.
//
DsysAssert(
sizeof(CARD_KEY_SIZES) == CacheQueryInfo.pItem->cbCachedItem);
memcpy(
pKeySizes,
((PBYTE) CacheQueryInfo.pItem) + sizeof(CARD_CACHE_ITEM_INFO),
sizeof(CARD_KEY_SIZES));
break;
default:
// Unexpected error
break;
}
Ret:
if (pItem)
CspFreeH(pItem);
if (CacheQueryInfo.pItem)
CspFreeH(CacheQueryInfo.pItem);
return dwSts;
}