mirror of https://github.com/FreeRDP/FreeRDP
channels/smartcard: implement clean ListReadersW
This commit is contained in:
parent
73df99a432
commit
bbfd4fb361
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue