channels/smartcard: implement clean ListReadersW

This commit is contained in:
Marc-André Moreau 2014-04-07 00:10:27 -04:00
parent 73df99a432
commit bbfd4fb361
4 changed files with 175 additions and 56 deletions

View File

@ -202,6 +202,32 @@ static UINT32 smartcard_output_return(IRP* irp, UINT32 status)
return status;
}
size_t smartcard_multi_string_length_a(const char* msz)
{
char* p = (char*) msz;
if (!p)
return 0;
while (p[0] || p[1])
p++;
return (p - msz);
}
size_t smartcard_multi_string_length_w(const WCHAR* msz)
{
WCHAR* p = (WCHAR*) msz;
if (!p)
return 0;
while (p[0] || p[1])
p++;
return (p - msz);
}
static UINT32 smartcard_EstablishContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT32 status;
@ -270,17 +296,14 @@ static UINT32 smartcard_IsValidContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
return status;
}
static UINT32 smartcard_ListReaders(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
static UINT32 smartcard_ListReadersA(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT32 status;
DWORD dwReaders;
SCARDCONTEXT hContext;
ListReaders_Call call;
char *readerList = NULL;
char* walker;
char* walkerEnd;
int elemLength, dataLength;
int pos, poslen1, poslen2;
ListReaders_Return ret;
LPSTR mszReaders = NULL;
DWORD cchReaders = 0;
status = smartcard_unpack_list_readers_call(smartcard, irp->input, &call);
@ -289,59 +312,64 @@ static UINT32 smartcard_ListReaders(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL
hContext = (ULONG_PTR) call.Context.pbContext;
dwReaders = SCARD_AUTOALLOCATE;
status = SCardListReadersA(hContext, (LPCSTR) call.mszGroups, (LPSTR) &readerList, &dwReaders);
cchReaders = SCARD_AUTOALLOCATE;
status = SCardListReadersA(hContext, (LPCSTR) call.mszGroups, (LPSTR) &mszReaders, &cchReaders);
if (status != SCARD_S_SUCCESS)
goto finish;
poslen1 = Stream_GetPosition(irp->output);
Stream_Seek_UINT32(irp->output);
ret.msz = (BYTE*) mszReaders;
ret.cBytes = smartcard_multi_string_length_a((char*) ret.msz) + 2;
Stream_Write_UINT32(irp->output, 0x01760650);
smartcard_pack_list_readers_return(smartcard, irp->output, &ret);
poslen2 = Stream_GetPosition(irp->output);
Stream_Seek_UINT32(irp->output);
walker = readerList;
walkerEnd = readerList + dwReaders;
dataLength = 0;
while (1)
{
elemLength = strlen(walker);
if (!elemLength)
break;
dataLength += smartcard_output_string(irp, walker, wide);
walker += elemLength + 1;
if (walker > walkerEnd)
{
status = SCARD_F_INTERNAL_ERROR;
goto finish;
}
}
dataLength += smartcard_output_string(irp, "\0", wide);
pos = Stream_GetPosition(irp->output);
Stream_SetPosition(irp->output, poslen1);
Stream_Write_UINT32(irp->output, dataLength);
Stream_SetPosition(irp->output, poslen2);
Stream_Write_UINT32(irp->output, dataLength);
Stream_SetPosition(irp->output, pos);
smartcard_output_repos(irp, dataLength);
smartcard_output_alignment(irp, 8);
finish:
if (readerList)
if (mszReaders)
{
SCardFreeMemory(hContext, readerList);
SCardFreeMemory(hContext, mszReaders);
}
if (call.mszGroups)
free(call.mszGroups);
return status;
}
static UINT32 smartcard_ListReadersW(SMARTCARD_DEVICE* smartcard, IRP* irp)
{
UINT32 status;
SCARDCONTEXT hContext;
ListReaders_Call call;
ListReaders_Return ret;
LPWSTR mszReaders = NULL;
DWORD cchReaders = 0;
status = smartcard_unpack_list_readers_call(smartcard, irp->input, &call);
if (status)
goto finish;
hContext = (ULONG_PTR) call.Context.pbContext;
cchReaders = SCARD_AUTOALLOCATE;
status = SCardListReadersW(hContext, (LPCWSTR) call.mszGroups, (LPWSTR) &mszReaders, &cchReaders);
if (status != SCARD_S_SUCCESS)
goto finish;
ret.msz = (BYTE*) mszReaders;
ret.cBytes = (smartcard_multi_string_length_w((WCHAR*) ret.msz) + 2) * 2;
smartcard_pack_list_readers_return(smartcard, irp->output, &ret);
smartcard_output_alignment(irp, 8);
finish:
if (mszReaders)
{
SCardFreeMemory(hContext, mszReaders);
}
if (call.mszGroups)
@ -1125,11 +1153,11 @@ void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
break;
case SCARD_IOCTL_LISTREADERSA:
result = smartcard_ListReaders(smartcard, irp, 0);
result = smartcard_ListReadersA(smartcard, irp);
break;
case SCARD_IOCTL_LISTREADERSW:
result = smartcard_ListReaders(smartcard, irp, 1);
result = smartcard_ListReadersW(smartcard, irp);
break;
case SCARD_IOCTL_INTRODUCEREADERGROUPA:

View File

@ -451,6 +451,17 @@ UINT32 smartcard_unpack_list_readers_call(SMARTCARD_DEVICE* smartcard, wStream*
return SCARD_S_SUCCESS;
}
UINT32 smartcard_pack_list_readers_return(SMARTCARD_DEVICE* smartcard, wStream* s, ListReaders_Return* ret)
{
Stream_Write_UINT32(s, ret->cBytes); /* cBytes (4 bytes) */
Stream_Write_UINT32(s, 0x00020008); /* mszNdrPtr (4 bytes) */
Stream_Write_UINT32(s, ret->cBytes); /* mszNdrLen (4 bytes) */
Stream_Write(s, ret->msz, ret->cBytes);
smartcard_pack_write_offset_align(smartcard, s, 4);
return SCARD_S_SUCCESS;
}
UINT32 smartcard_unpack_connect_common(SMARTCARD_DEVICE* smartcard, wStream* s, Connect_Common* common)
{
UINT32 status;

View File

@ -447,6 +447,7 @@ UINT32 smartcard_pack_establish_context_return(SMARTCARD_DEVICE* smartcard, wStr
UINT32 smartcard_unpack_context_call(SMARTCARD_DEVICE* smartcard, wStream* s, Context_Call* call);
UINT32 smartcard_unpack_list_readers_call(SMARTCARD_DEVICE* smartcard, wStream* s, ListReaders_Call* call);
UINT32 smartcard_pack_list_readers_return(SMARTCARD_DEVICE* smartcard, wStream* s, ListReaders_Return* ret);
UINT32 smartcard_unpack_connect_a_call(SMARTCARD_DEVICE* smartcard, wStream* s, ConnectA_Call* call);
UINT32 smartcard_unpack_connect_w_call(SMARTCARD_DEVICE* smartcard, wStream* s, ConnectW_Call* call);

View File

@ -24,6 +24,7 @@
#include <winpr/crt.h>
#include <winpr/library.h>
#include <winpr/smartcard.h>
#include <winpr/collections.h>
#include "smartcard_pcsc.h"
@ -47,6 +48,64 @@ LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode)
return errorCode;
}
size_t PCSC_MultiStringLengthA(const char* msz)
{
char* p = (char*) msz;
if (!p)
return 0;
while (p[0] || p[1])
p++;
return (p - msz);
}
size_t PCSC_MultiStringLengthW(const WCHAR* msz)
{
WCHAR* p = (WCHAR*) msz;
if (!p)
return 0;
while (p[0] || p[1])
p++;
return (p - msz);
}
static wListDictionary* g_MemoryBlocks = NULL;
void PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
{
if (!g_MemoryBlocks)
g_MemoryBlocks = ListDictionary_New(TRUE);
ListDictionary_Add(g_MemoryBlocks, pvMem, (void*) hContext);
}
void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
{
if (!g_MemoryBlocks)
return NULL;
return ListDictionary_Remove(g_MemoryBlocks, pvMem);
}
void* PCSC_SCardAllocMemory(SCARDCONTEXT hContext, size_t size)
{
void* pvMem;
pvMem = malloc(size);
if (!pvMem)
return NULL;
PCSC_AddMemoryBlock(hContext, pvMem);
return pvMem;
}
/**
* Standard Windows Smart Card API (PCSC)
*/
@ -145,7 +204,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
if (g_PCSC.pfnSCardListReaders)
{
UINT32 length;
LPSTR mszGroupsA = NULL;
LPSTR mszReadersA = NULL;
if (mszGroups)
ConvertFromUnicode(CP_UTF8, 0, mszGroups, -1, (char**) &mszGroupsA, 0, NULL, NULL);
@ -153,10 +214,20 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext,
if (!mszReaders)
pcchReaders = 0;
status = g_PCSC.pfnSCardListReaders(hContext, (LPSTR) mszGroupsA, (LPSTR) mszReaders, pcchReaders);
status = g_PCSC.pfnSCardListReaders(hContext, (LPSTR) mszGroupsA, (LPSTR) &mszReadersA, pcchReaders);
status = PCSC_MapErrorCodeToWinSCard(status);
/* TODO: unicode conversion */
if (mszReadersA)
{
length = (UINT32) PCSC_MultiStringLengthA(mszReadersA);
ConvertToUnicode(CP_UTF8, 0, mszReadersA, length + 2, (WCHAR**) mszReaders, 0);
PCSC_AddMemoryBlock(hContext, mszReaders);
if (g_PCSC.pfnSCardFreeMemory)
{
g_PCSC.pfnSCardFreeMemory(hContext, mszReadersA);
}
}
free(mszGroupsA);
}
@ -320,8 +391,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMe
if (g_PCSC.pfnSCardFreeMemory)
{
status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
status = PCSC_MapErrorCodeToWinSCard(status);
if (PCSC_RemoveMemoryBlock(hContext, (void*) pvMem))
{
free((void*) pvMem);
status = SCARD_S_SUCCESS;
}
else
{
status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
status = PCSC_MapErrorCodeToWinSCard(status);
}
}
return status;