commit
77b6a20223
1
.gitignore
vendored
1
.gitignore
vendored
@ -79,6 +79,7 @@ RelWithDebInfo
|
||||
*.resource.txt
|
||||
*.embed.manifest*
|
||||
*.intermediate.manifest*
|
||||
version.rc
|
||||
|
||||
# Binaries
|
||||
*.a
|
||||
|
@ -23,10 +23,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/smartcard.h>
|
||||
#include <winpr/environment.h>
|
||||
@ -385,7 +381,7 @@ void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
|
||||
WLog_ERR(TAG, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
|
||||
irp->MajorFunction, irp->MinorFunction);
|
||||
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
||||
|
||||
@ -521,8 +517,6 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
smartcard->name = name;
|
||||
}
|
||||
|
||||
smartcard->log = WLog_Get("com.freerdp.channel.smartcard.client");
|
||||
|
||||
smartcard->IrpQueue = MessageQueue_New(NULL);
|
||||
|
||||
smartcard->CompletedIrpQueue = Queue_New(TRUE, -1, -1);
|
||||
|
@ -108,8 +108,6 @@ struct _SMARTCARD_DEVICE
|
||||
{
|
||||
DEVICE device;
|
||||
|
||||
wLog* log;
|
||||
|
||||
char* name;
|
||||
char* path;
|
||||
|
||||
|
@ -23,9 +23,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
@ -1033,9 +1030,8 @@ static UINT32 smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
|
||||
|
||||
if (ret.ReturnCode)
|
||||
{
|
||||
WLog_Print(smartcard->log, WLOG_WARN,
|
||||
"SCardGetAttrib: %s (0x%08X) cbAttrLen: %d",
|
||||
SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->cbAttrLen);
|
||||
WLog_WARN(TAG, "SCardGetAttrib: %s (0x%08X) cbAttrLen: %d",
|
||||
SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->cbAttrLen);
|
||||
Stream_Zero(irp->output, 256);
|
||||
|
||||
free(ret.pbAttr);
|
||||
@ -1060,7 +1056,7 @@ static UINT32 smartcard_AccessStartedEvent_Decode(SMARTCARD_DEVICE* smartcard, S
|
||||
|
||||
if (Stream_GetRemainingLength(irp->input) < 4)
|
||||
{
|
||||
WLog_Print(smartcard->log, WLOG_WARN, "AccessStartedEvent is too short: %d",
|
||||
WLog_WARN(TAG, "AccessStartedEvent is too short: %d",
|
||||
(int) Stream_GetRemainingLength(irp->input));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
@ -1207,7 +1203,7 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
|
||||
|
||||
if (Stream_GetRemainingLength(irp->input) < 32)
|
||||
{
|
||||
WLog_Print(smartcard->log, WLOG_WARN, "Device Control Request is too short: %d",
|
||||
WLog_WARN(TAG, "Device Control Request is too short: %d",
|
||||
(int) Stream_GetRemainingLength(irp->input));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
@ -1220,18 +1216,14 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
|
||||
|
||||
if (Stream_Length(irp->input) != (Stream_GetPosition(irp->input) + inputBufferLength))
|
||||
{
|
||||
WLog_Print(smartcard->log, WLOG_WARN,
|
||||
"InputBufferLength mismatch: Actual: %d Expected: %d",
|
||||
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
|
||||
WLog_WARN(TAG, "InputBufferLength mismatch: Actual: %d Expected: %d",
|
||||
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
WLog_Print(smartcard->log, WLOG_DEBUG, "%s (0x%08X) FileId: %d CompletionId: %d",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId);
|
||||
#if 0
|
||||
WLog_DBG(TAG, "%s (0x%08X) FileId: %d CompletionId: %d",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId);
|
||||
#endif
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE),
|
||||
ioControlCode, irp->FileId, irp->CompletionId);
|
||||
|
||||
if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
|
||||
(ioControlCode != SCARD_IOCTL_RELEASESTARTEDEVENT))
|
||||
@ -1482,10 +1474,9 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
|
||||
{
|
||||
UINT32 difference;
|
||||
difference = (int)(Stream_Length(irp->input) - Stream_GetPosition(irp->input));
|
||||
WLog_Print(smartcard->log, WLOG_WARN,
|
||||
"IRP was not fully parsed %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
|
||||
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
|
||||
WLog_WARN(TAG, "IRP was not fully parsed %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
|
||||
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
|
||||
winpr_HexDump(TAG, WLOG_WARN, Stream_Pointer(irp->input), difference);
|
||||
}
|
||||
|
||||
@ -1493,10 +1484,9 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
|
||||
{
|
||||
UINT32 difference;
|
||||
difference = (int)(Stream_GetPosition(irp->input) - Stream_Length(irp->input));
|
||||
WLog_Print(smartcard->log, WLOG_WARN,
|
||||
"IRP was parsed beyond its end %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
|
||||
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
|
||||
WLog_WARN(TAG, "IRP was parsed beyond its end %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
|
||||
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
|
||||
}
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
@ -1756,10 +1746,9 @@ UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_
|
||||
if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
|
||||
(result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE))
|
||||
{
|
||||
WLog_Print(smartcard->log, WLOG_WARN,
|
||||
"IRP failure: %s (0x%08X), status: %s (0x%08X)",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
|
||||
SCardGetErrorString(result), result);
|
||||
WLog_WARN(TAG, "IRP failure: %s (0x%08X), status: %s (0x%08X)",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
|
||||
SCardGetErrorString(result), result);
|
||||
}
|
||||
|
||||
irp->IoStatus = 0;
|
||||
@ -1769,9 +1758,8 @@ UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_
|
||||
/* NTSTATUS error */
|
||||
irp->IoStatus = result;
|
||||
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
|
||||
WLog_Print(smartcard->log, WLOG_WARN,
|
||||
"IRP failure: %s (0x%08X), ntstatus: 0x%08X",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
|
||||
WLog_WARN(TAG, "IRP failure: %s (0x%08X), ntstatus: 0x%08X",
|
||||
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
|
||||
}
|
||||
|
||||
Stream_SealLength(irp->output);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -78,7 +78,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
||||
{ "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" },
|
||||
{ "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" },
|
||||
{ "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" },
|
||||
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, NULL, "Gateway usage method" },
|
||||
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, "gum", "Gateway usage method" },
|
||||
{ "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info string>", NULL, NULL, -1, NULL, "Load balance info" },
|
||||
{ "app", COMMAND_LINE_VALUE_REQUIRED, "<executable path> or <||alias>", NULL, NULL, -1, NULL, "Remote application program" },
|
||||
{ "app-name", COMMAND_LINE_VALUE_REQUIRED, "<app name>", NULL, NULL, -1, NULL, "Remote application name for user interface" },
|
||||
@ -1464,7 +1464,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
settings->GatewayEnabled = TRUE;
|
||||
settings->GatewayUseSameCredentials = TRUE;
|
||||
|
||||
freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DETECT);
|
||||
freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DIRECT);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "gu")
|
||||
{
|
||||
|
@ -44,29 +44,10 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
|
||||
sspi_GlobalInit();
|
||||
|
||||
ntlm->http = http;
|
||||
ntlm->Bindings = Bindings;
|
||||
|
||||
#ifdef WITH_NATIVE_SSPI
|
||||
{
|
||||
HMODULE hSSPI;
|
||||
INIT_SECURITY_INTERFACE InitSecurityInterface;
|
||||
PSecurityFunctionTable pSecurityInterface = NULL;
|
||||
|
||||
hSSPI = LoadLibrary(_T("secur32.dll"));
|
||||
|
||||
#ifdef UNICODE
|
||||
InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW");
|
||||
#else
|
||||
InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA");
|
||||
#endif
|
||||
ntlm->table = (*InitSecurityInterface)();
|
||||
}
|
||||
#else
|
||||
ntlm->table = InitSecurityInterface();
|
||||
#endif
|
||||
ntlm->table = InitSecurityInterfaceEx(SSPI_INTERFACE_WINPR);
|
||||
|
||||
sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password);
|
||||
|
||||
@ -74,18 +55,19 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", status);
|
||||
WLog_ERR(TAG, "QuerySecurityPackageInfo status: 0x%08X", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
|
||||
|
||||
status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME,
|
||||
SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration);
|
||||
SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL,
|
||||
&ntlm->credentials, &ntlm->expiration);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", status);
|
||||
WLog_ERR(TAG, "AcquireCredentialsHandle status: 0x%08X", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -121,45 +103,41 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
|
||||
|
||||
BOOL ntlm_client_make_spn(rdpNtlm* ntlm, LPCTSTR ServiceClass, char* hostname)
|
||||
{
|
||||
int length;
|
||||
DWORD status;
|
||||
DWORD SpnLength;
|
||||
LPTSTR hostnameX;
|
||||
|
||||
length = 0;
|
||||
DWORD SpnLength = 0;
|
||||
LPTSTR hostnameX = NULL;
|
||||
|
||||
#ifdef UNICODE
|
||||
length = strlen(hostname);
|
||||
hostnameX = (LPWSTR) malloc((length + 1)* sizeof(TCHAR));
|
||||
MultiByteToWideChar(CP_UTF8, 0, hostname, length, hostnameX, length);
|
||||
hostnameX[length] = 0;
|
||||
ConvertToUnicode(CP_UTF8, 0, hostname, -1, (LPWSTR*) &hostnameX, 0);
|
||||
#else
|
||||
hostnameX = hostname;
|
||||
hostnameX = _strdup(hostname);
|
||||
#endif
|
||||
|
||||
if (!hostnameX)
|
||||
return FALSE;
|
||||
|
||||
if (!ServiceClass)
|
||||
{
|
||||
ntlm->ServicePrincipalName = (LPTSTR) _tcsdup(hostnameX);
|
||||
|
||||
if (!ntlm->ServicePrincipalName)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SpnLength = 0;
|
||||
status = DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, NULL);
|
||||
|
||||
if (status != ERROR_BUFFER_OVERFLOW)
|
||||
if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, NULL) != ERROR_BUFFER_OVERFLOW)
|
||||
return FALSE;
|
||||
|
||||
ntlm->ServicePrincipalName = (LPTSTR) malloc(SpnLength * sizeof(TCHAR));
|
||||
|
||||
if (!ntlm->ServicePrincipalName)
|
||||
return FALSE;
|
||||
|
||||
status = DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName);
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
if (DsMakeSpn(ServiceClass, hostnameX, NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName) != ERROR_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
free(hostnameX);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -239,7 +217,7 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
|
||||
|
||||
if ((!ntlm) || (!ntlm->table))
|
||||
{
|
||||
WLog_ERR(TAG, "ntlm_authenticate: invalid ntlm context");
|
||||
WLog_ERR(TAG, "ntlm_authenticate: invalid ntlm context");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -253,12 +231,12 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
|
||||
|
||||
if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK))
|
||||
{
|
||||
if (ntlm->table->CompleteAuthToken != NULL)
|
||||
if (ntlm->table->CompleteAuthToken)
|
||||
ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc);
|
||||
|
||||
if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
|
||||
WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -271,6 +249,7 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
|
||||
if (ntlm->haveInputBuffer)
|
||||
{
|
||||
free(ntlm->inputBuffer[0].pvBuffer);
|
||||
ntlm->inputBuffer[0].pvBuffer = NULL;
|
||||
}
|
||||
|
||||
ntlm->haveInputBuffer = TRUE;
|
||||
@ -282,9 +261,16 @@ BOOL ntlm_authenticate(rdpNtlm* ntlm)
|
||||
void ntlm_client_uninit(rdpNtlm* ntlm)
|
||||
{
|
||||
free(ntlm->identity.User);
|
||||
ntlm->identity.User = NULL;
|
||||
|
||||
free(ntlm->identity.Domain);
|
||||
ntlm->identity.Domain = NULL;
|
||||
|
||||
free(ntlm->identity.Password);
|
||||
ntlm->identity.Password = NULL;
|
||||
|
||||
free(ntlm->ServicePrincipalName);
|
||||
ntlm->ServicePrincipalName = NULL;
|
||||
|
||||
if (ntlm->table)
|
||||
{
|
||||
|
@ -310,9 +310,9 @@ int rpc_recv_bind_ack_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
|
||||
int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
|
||||
{
|
||||
int status;
|
||||
BYTE* buffer;
|
||||
UINT32 offset;
|
||||
UINT32 length;
|
||||
RpcClientCall* clientCall;
|
||||
rpcconn_rpc_auth_3_hdr_t* auth_3_pdu;
|
||||
|
||||
@ -360,17 +360,17 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
|
||||
CopyMemory(&buffer[offset + 8], auth_3_pdu->auth_verifier.auth_value, auth_3_pdu->auth_length);
|
||||
offset += (8 + auth_3_pdu->auth_length);
|
||||
|
||||
length = auth_3_pdu->frag_length;
|
||||
status = (int) auth_3_pdu->frag_length;
|
||||
|
||||
clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0);
|
||||
ArrayList_Add(rpc->client->ClientCallList, clientCall);
|
||||
|
||||
if (rpc_send_enqueue_pdu(rpc, buffer, length) != 0)
|
||||
length = -1;
|
||||
if (rpc_send_enqueue_pdu(rpc, buffer, (UINT32) status) != 0)
|
||||
status = -1;
|
||||
|
||||
free(auth_3_pdu);
|
||||
|
||||
return length;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,7 +64,7 @@ RPC_PDU* rpc_client_receive_pool_take(rdpRpc* rpc)
|
||||
|
||||
if (!pdu)
|
||||
{
|
||||
pdu = (RPC_PDU*)malloc(sizeof(RPC_PDU));
|
||||
pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
|
||||
|
||||
if (!pdu)
|
||||
return NULL;
|
||||
@ -311,9 +311,10 @@ RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc, UINT32 CallId)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
RpcClientCall* clientCall;
|
||||
RpcClientCall* clientCall = NULL;
|
||||
|
||||
ArrayList_Lock(rpc->client->ClientCallList);
|
||||
clientCall = NULL;
|
||||
|
||||
count = ArrayList_Count(rpc->client->ClientCallList);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
@ -325,13 +326,15 @@ RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc, UINT32 CallId)
|
||||
}
|
||||
|
||||
ArrayList_Unlock(rpc->client->ClientCallList);
|
||||
|
||||
return clientCall;
|
||||
}
|
||||
|
||||
RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
|
||||
{
|
||||
RpcClientCall* clientCall;
|
||||
clientCall = (RpcClientCall*) malloc(sizeof(RpcClientCall));
|
||||
|
||||
clientCall = (RpcClientCall*) calloc(1, sizeof(RpcClientCall));
|
||||
|
||||
if (!clientCall)
|
||||
return NULL;
|
||||
@ -339,6 +342,7 @@ RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
|
||||
clientCall->CallId = CallId;
|
||||
clientCall->OpNum = OpNum;
|
||||
clientCall->State = RPC_CLIENT_CALL_STATE_SEND_PDUS;
|
||||
|
||||
return clientCall;
|
||||
}
|
||||
|
||||
@ -349,8 +353,9 @@ void rpc_client_call_free(RpcClientCall* clientCall)
|
||||
|
||||
int rpc_send_enqueue_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
{
|
||||
RPC_PDU* pdu;
|
||||
int status;
|
||||
RPC_PDU* pdu;
|
||||
|
||||
pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
|
||||
|
||||
if (!pdu)
|
||||
@ -385,6 +390,7 @@ out_free_stream:
|
||||
Stream_Free(pdu->s, TRUE);
|
||||
out_free:
|
||||
free(pdu);
|
||||
WLog_ERR(TAG, "rpc_send_enqueue_pdu failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -434,19 +440,20 @@ int rpc_send_dequeue_pdu(rdpRpc* rpc)
|
||||
RPC_PDU* rpc_recv_dequeue_pdu(rdpRpc* rpc)
|
||||
{
|
||||
RPC_PDU* pdu;
|
||||
DWORD waitStatus;
|
||||
DWORD dwMilliseconds;
|
||||
DWORD result;
|
||||
|
||||
dwMilliseconds = rpc->client->SynchronousReceive ? SYNCHRONOUS_TIMEOUT * 4 : 0;
|
||||
result = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
|
||||
|
||||
if (result == WAIT_TIMEOUT)
|
||||
waitStatus = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
|
||||
|
||||
if (waitStatus == WAIT_TIMEOUT)
|
||||
{
|
||||
WLog_ERR(TAG, "timed out waiting for receive event");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (result != WAIT_OBJECT_0)
|
||||
if (waitStatus != WAIT_OBJECT_0)
|
||||
return NULL;
|
||||
|
||||
pdu = (RPC_PDU*) Queue_Dequeue(rpc->client->ReceiveQueue);
|
||||
@ -456,52 +463,37 @@ RPC_PDU* rpc_recv_dequeue_pdu(rdpRpc* rpc)
|
||||
|
||||
RPC_PDU* rpc_recv_peek_pdu(rdpRpc* rpc)
|
||||
{
|
||||
DWORD waitStatus;
|
||||
DWORD dwMilliseconds;
|
||||
DWORD result;
|
||||
|
||||
dwMilliseconds = rpc->client->SynchronousReceive ? SYNCHRONOUS_TIMEOUT : 0;
|
||||
result = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
|
||||
|
||||
if (result != WAIT_OBJECT_0)
|
||||
waitStatus = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
|
||||
|
||||
if (waitStatus != WAIT_OBJECT_0)
|
||||
return NULL;
|
||||
|
||||
return (RPC_PDU*)Queue_Peek(rpc->client->ReceiveQueue);
|
||||
return (RPC_PDU*) Queue_Peek(rpc->client->ReceiveQueue);
|
||||
}
|
||||
|
||||
static void* rpc_client_thread(void* arg)
|
||||
{
|
||||
int fd;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
HANDLE events[3];
|
||||
HANDLE ReadEvent;
|
||||
HANDLE events[8];
|
||||
DWORD waitStatus;
|
||||
HANDLE ReadEvent = NULL;
|
||||
rdpRpc* rpc = (rdpRpc*) arg;
|
||||
|
||||
fd = BIO_get_fd(rpc->TlsOut->bio, NULL);
|
||||
ReadEvent = CreateFileDescriptorEvent(NULL, TRUE, FALSE, fd);
|
||||
BIO_get_event(rpc->TlsOut->bio, &ReadEvent);
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = rpc->client->StopEvent;
|
||||
events[nCount++] = Queue_Event(rpc->client->SendQueue);
|
||||
events[nCount++] = ReadEvent;
|
||||
|
||||
/* Do a first free run in case some bytes were set from the HTTP headers.
|
||||
* We also have to do it because most of the time the underlying socket has notified,
|
||||
* and the ssl layer has eaten all bytes, so we won't be notified any more even if the
|
||||
* bytes are buffered locally
|
||||
*/
|
||||
if (rpc_client_on_read_event(rpc) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "an error occurred when treating first packet");
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (rpc->transport->layer != TRANSPORT_LAYER_CLOSED)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, 100);
|
||||
|
||||
if (status == WAIT_TIMEOUT)
|
||||
continue;
|
||||
waitStatus = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(rpc->client->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
@ -521,8 +513,6 @@ static void* rpc_client_thread(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
CloseHandle(ReadEvent);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1413,6 +1413,9 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port)
|
||||
rpc->client->SynchronousSend = TRUE;
|
||||
rpc->client->SynchronousReceive = TRUE;
|
||||
|
||||
tsg->bio = BIO_new(BIO_s_tsg());
|
||||
tsg->bio->ptr = tsg;
|
||||
|
||||
WLog_INFO(TAG, "TS Gateway Connection Success");
|
||||
|
||||
return TRUE;
|
||||
@ -1602,9 +1605,121 @@ void tsg_free(rdpTsg* tsg)
|
||||
{
|
||||
if (tsg)
|
||||
{
|
||||
if (tsg->bio)
|
||||
{
|
||||
BIO_free(tsg->bio);
|
||||
tsg->bio = NULL;
|
||||
}
|
||||
|
||||
rpc_free(tsg->rpc);
|
||||
free(tsg->Hostname);
|
||||
free(tsg->MachineName);
|
||||
free(tsg);
|
||||
}
|
||||
}
|
||||
|
||||
long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
|
||||
{
|
||||
int status;
|
||||
rdpTsg* tsg = (rdpTsg*) bio->ptr;
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
status = tsg_write(tsg, (BYTE*) buf, num);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
}
|
||||
else if (status == 0)
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||
}
|
||||
|
||||
return status >= 0 ? status : -1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
int status;
|
||||
rdpTsg* tsg = (rdpTsg*) bio->ptr;
|
||||
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||
status = tsg_read(tsg, (BYTE*) buf, size);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
}
|
||||
else if (status == 0)
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||
}
|
||||
|
||||
return status > 0 ? status : -1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_puts(BIO* bio, const char* str)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
if (cmd == BIO_CTRL_FLUSH)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_new(BIO* bio)
|
||||
{
|
||||
bio->init = 1;
|
||||
bio->num = 0;
|
||||
bio->ptr = NULL;
|
||||
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_free(BIO* bio)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BIO_METHOD transport_bio_tsg_methods =
|
||||
{
|
||||
BIO_TYPE_TSG,
|
||||
"TSGateway",
|
||||
transport_bio_tsg_write,
|
||||
transport_bio_tsg_read,
|
||||
transport_bio_tsg_puts,
|
||||
transport_bio_tsg_gets,
|
||||
transport_bio_tsg_ctrl,
|
||||
transport_bio_tsg_new,
|
||||
transport_bio_tsg_free,
|
||||
NULL,
|
||||
};
|
||||
|
||||
BIO_METHOD* BIO_s_tsg(void)
|
||||
{
|
||||
return &transport_bio_tsg_methods;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ typedef enum _TSG_STATE TSG_STATE;
|
||||
|
||||
struct rdp_tsg
|
||||
{
|
||||
BIO* bio;
|
||||
rdpRpc* rpc;
|
||||
UINT16 Port;
|
||||
RPC_PDU* pdu;
|
||||
@ -317,4 +318,6 @@ BOOL tsg_set_blocking_mode(rdpTsg* tsg, BOOL blocking);
|
||||
rdpTsg* tsg_new(rdpTransport* transport);
|
||||
void tsg_free(rdpTsg* tsg);
|
||||
|
||||
BIO_METHOD* BIO_s_tsg(void);
|
||||
|
||||
#endif /* FREERDP_CORE_TSG_H */
|
||||
|
@ -149,7 +149,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
||||
if (status != 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WLog_ERR("bind() failed with error: %u", WSAGetLastError());
|
||||
WLog_ERR(TAG, "bind() failed with error: %d", (int) WSAGetLastError());
|
||||
WSACleanup();
|
||||
#else
|
||||
WLog_ERR(TAG, "bind");
|
||||
|
@ -394,7 +394,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
||||
settings->MultifragMaxRequestSize = 0xFFFF;
|
||||
|
||||
settings->GatewayUseSameCredentials = FALSE;
|
||||
settings->GatewayBypassLocal = TRUE;
|
||||
settings->GatewayBypassLocal = FALSE;
|
||||
|
||||
settings->FastPathInput = TRUE;
|
||||
settings->FastPathOutput = TRUE;
|
||||
|
@ -87,8 +87,30 @@
|
||||
|
||||
/* Simple Socket BIO */
|
||||
|
||||
static int transport_bio_simple_new(BIO* bio);
|
||||
static int transport_bio_simple_free(BIO* bio);
|
||||
struct _WINPR_BIO_SIMPLE_SOCKET
|
||||
{
|
||||
BOOL win32;
|
||||
SOCKET socket;
|
||||
HANDLE hEvent;
|
||||
};
|
||||
typedef struct _WINPR_BIO_SIMPLE_SOCKET WINPR_BIO_SIMPLE_SOCKET;
|
||||
|
||||
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown);
|
||||
static int transport_bio_simple_uninit(BIO* bio);
|
||||
|
||||
static void transport_bio_simple_check_reset_event(BIO* bio)
|
||||
{
|
||||
u_long nbytes = 0;
|
||||
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
|
||||
|
||||
if (!ptr->win32)
|
||||
return;
|
||||
|
||||
_ioctlsocket(ptr->socket, FIONREAD, &nbytes);
|
||||
|
||||
if (nbytes < 1)
|
||||
WSAResetEvent(ptr->hEvent);
|
||||
}
|
||||
|
||||
long transport_bio_simple_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
||||
{
|
||||
@ -99,13 +121,14 @@ static int transport_bio_simple_write(BIO* bio, const char* buf, int size)
|
||||
{
|
||||
int error;
|
||||
int status = 0;
|
||||
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
|
||||
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
|
||||
status = _send((SOCKET) bio->num, buf, size, 0);
|
||||
status = _send(ptr->socket, buf, size, 0);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
@ -129,15 +152,20 @@ static int transport_bio_simple_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
int error;
|
||||
int status = 0;
|
||||
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
|
||||
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||
|
||||
status = _recv((SOCKET) bio->num, buf, size, 0);
|
||||
status = _recv(ptr->socket, buf, size, 0);
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
transport_bio_simple_check_reset_event(bio);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
@ -157,6 +185,8 @@ static int transport_bio_simple_read(BIO* bio, char* buf, int size)
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
}
|
||||
|
||||
transport_bio_simple_check_reset_event(bio);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -173,17 +203,59 @@ static int transport_bio_simple_gets(BIO* bio, char* str, int size)
|
||||
static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
int status = -1;
|
||||
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
|
||||
|
||||
if (cmd == BIO_C_SET_SOCKET)
|
||||
{
|
||||
transport_bio_simple_uninit(bio);
|
||||
transport_bio_simple_init(bio, (SOCKET) arg2, (int) arg1);
|
||||
return 1;
|
||||
}
|
||||
else if (cmd == BIO_C_GET_SOCKET)
|
||||
{
|
||||
if (!bio->init || !arg2)
|
||||
return 0;
|
||||
|
||||
*((ULONG_PTR*) arg2) = (ULONG_PTR) ptr->socket;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (cmd == BIO_C_GET_EVENT)
|
||||
{
|
||||
if (!bio->init || !arg2)
|
||||
return 0;
|
||||
|
||||
*((ULONG_PTR*) arg2) = (ULONG_PTR) ptr->hEvent;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (cmd == BIO_C_SET_NONBLOCK)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int flags;
|
||||
|
||||
flags = fcntl((int) ptr->socket, F_GETFL);
|
||||
|
||||
if (flags == -1)
|
||||
return 0;
|
||||
|
||||
if (arg1)
|
||||
fcntl((int) ptr->socket, F_SETFL, flags | O_NONBLOCK);
|
||||
else
|
||||
fcntl((int) ptr->socket, F_SETFL, flags & ~(O_NONBLOCK));
|
||||
#else
|
||||
/* the internal socket is always non-blocking */
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case BIO_C_SET_FD:
|
||||
if (arg2)
|
||||
{
|
||||
transport_bio_simple_free(bio);
|
||||
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||
bio->num = *((int*) arg2);
|
||||
bio->shutdown = (int) arg1;
|
||||
bio->init = 1;
|
||||
transport_bio_simple_uninit(bio);
|
||||
transport_bio_simple_init(bio, (SOCKET) *((int*) arg2), (int) arg1);
|
||||
status = 1;
|
||||
}
|
||||
break;
|
||||
@ -192,8 +264,8 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
if (bio->init)
|
||||
{
|
||||
if (arg2)
|
||||
*((int*) arg2) = bio->num;
|
||||
status = bio->num;
|
||||
*((int*) arg2) = (int) ptr->socket;
|
||||
status = (int) ptr->socket;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -222,12 +294,81 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
return status;
|
||||
}
|
||||
|
||||
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
|
||||
{
|
||||
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
|
||||
|
||||
ptr->socket = socket;
|
||||
|
||||
bio->shutdown = shutdown;
|
||||
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||
bio->init = 1;
|
||||
|
||||
if (ptr->win32)
|
||||
{
|
||||
ptr->hEvent = WSACreateEvent(); /* creates a manual reset event */
|
||||
|
||||
if (!ptr->hEvent)
|
||||
return 0;
|
||||
|
||||
/* WSAEventSelect automatically sets the socket in non-blocking mode */
|
||||
WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_CLOSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr->hEvent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, (int) ptr->socket);
|
||||
|
||||
if (!ptr->hEvent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_simple_uninit(BIO* bio)
|
||||
{
|
||||
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
|
||||
|
||||
if (bio->shutdown)
|
||||
{
|
||||
if (bio->init)
|
||||
{
|
||||
closesocket(ptr->socket);
|
||||
ptr->socket = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr->hEvent)
|
||||
{
|
||||
CloseHandle(ptr->hEvent);
|
||||
ptr->hEvent = NULL;
|
||||
}
|
||||
|
||||
bio->init = 0;
|
||||
bio->flags = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_simple_new(BIO* bio)
|
||||
{
|
||||
WINPR_BIO_SIMPLE_SOCKET* ptr;
|
||||
|
||||
bio->init = 0;
|
||||
bio->num = 0;
|
||||
bio->ptr = NULL;
|
||||
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||
|
||||
ptr = (WINPR_BIO_SIMPLE_SOCKET*) calloc(1, sizeof(WINPR_BIO_SIMPLE_SOCKET));
|
||||
|
||||
if (!ptr)
|
||||
return 0;
|
||||
|
||||
bio->ptr = ptr;
|
||||
|
||||
#ifdef _WIN32
|
||||
ptr->win32 = TRUE;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -236,13 +377,12 @@ static int transport_bio_simple_free(BIO* bio)
|
||||
if (!bio)
|
||||
return 0;
|
||||
|
||||
if (bio->shutdown)
|
||||
{
|
||||
if (bio->init)
|
||||
closesocket((SOCKET) bio->num);
|
||||
transport_bio_simple_uninit(bio);
|
||||
|
||||
bio->init = 0;
|
||||
bio->flags = 0;
|
||||
if (bio->ptr)
|
||||
{
|
||||
free(bio->ptr);
|
||||
bio->ptr = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -931,7 +1071,7 @@ BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeou
|
||||
BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE);
|
||||
}
|
||||
|
||||
SetEventFileDescriptor(tcp->event, tcp->sockfd);
|
||||
BIO_get_event(tcp->socketBio, &tcp->event);
|
||||
|
||||
freerdp_tcp_get_ip_address(tcp);
|
||||
freerdp_tcp_get_mac_address(tcp);
|
||||
@ -994,49 +1134,7 @@ BOOL freerdp_tcp_disconnect(rdpTcp* tcp)
|
||||
|
||||
BOOL freerdp_tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int flags;
|
||||
flags = fcntl(tcp->sockfd, F_GETFL);
|
||||
|
||||
if (flags == -1)
|
||||
{
|
||||
WLog_ERR(TAG, "fcntl failed, %s.", strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (blocking == TRUE)
|
||||
fcntl(tcp->sockfd, F_SETFL, flags & ~(O_NONBLOCK));
|
||||
else
|
||||
fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||
#else
|
||||
/**
|
||||
* ioctlsocket function:
|
||||
* msdn.microsoft.com/en-ca/library/windows/desktop/ms738573/
|
||||
*
|
||||
* The WSAAsyncSelect and WSAEventSelect functions automatically set a socket to nonblocking mode.
|
||||
* If WSAAsyncSelect or WSAEventSelect has been issued on a socket, then any attempt to use
|
||||
* ioctlsocket to set the socket back to blocking mode will fail with WSAEINVAL.
|
||||
*
|
||||
* To set the socket back to blocking mode, an application must first disable WSAAsyncSelect
|
||||
* by calling WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect
|
||||
* by calling WSAEventSelect with the lNetworkEvents parameter equal to zero.
|
||||
*/
|
||||
|
||||
if (blocking == TRUE)
|
||||
{
|
||||
if (tcp->event)
|
||||
WSAEventSelect(tcp->sockfd, tcp->event, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tcp->event)
|
||||
tcp->event = WSACreateEvent();
|
||||
|
||||
WSAEventSelect(tcp->sockfd, tcp->event, FD_READ);
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
return BIO_set_nonblock(tcp->socketBio, blocking ? 0 : 1) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp)
|
||||
@ -1102,13 +1200,12 @@ BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp)
|
||||
int freerdp_tcp_attach(rdpTcp* tcp, int sockfd)
|
||||
{
|
||||
tcp->sockfd = sockfd;
|
||||
SetEventFileDescriptor(tcp->event, tcp->sockfd);
|
||||
|
||||
ringbuffer_commit_read_bytes(&tcp->xmitBuffer, ringbuffer_used(&tcp->xmitBuffer));
|
||||
|
||||
if (tcp->socketBio)
|
||||
{
|
||||
if (BIO_set_fd(tcp->socketBio, sockfd, 1) < 0)
|
||||
if (BIO_set_fd(tcp->socketBio, sockfd, BIO_CLOSE) < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
@ -1133,7 +1230,9 @@ int freerdp_tcp_attach(rdpTcp* tcp, int sockfd)
|
||||
tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio);
|
||||
}
|
||||
|
||||
return 0;
|
||||
BIO_get_event(tcp->socketBio, &tcp->event);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
HANDLE freerdp_tcp_get_event_handle(rdpTcp* tcp)
|
||||
@ -1235,19 +1334,8 @@ rdpTcp* freerdp_tcp_new(rdpSettings* settings)
|
||||
tcp->sockfd = -1;
|
||||
tcp->settings = settings;
|
||||
|
||||
if (0)
|
||||
goto out_ringbuffer; /* avoid unreferenced label warning on Windows */
|
||||
|
||||
#ifndef _WIN32
|
||||
tcp->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, tcp->sockfd);
|
||||
|
||||
if (!tcp->event || tcp->event == INVALID_HANDLE_VALUE)
|
||||
goto out_ringbuffer;
|
||||
#endif
|
||||
|
||||
return tcp;
|
||||
out_ringbuffer:
|
||||
ringbuffer_destroy(&tcp->xmitBuffer);
|
||||
|
||||
out_free:
|
||||
free(tcp);
|
||||
return NULL;
|
||||
@ -1259,6 +1347,18 @@ void freerdp_tcp_free(rdpTcp* tcp)
|
||||
return;
|
||||
|
||||
ringbuffer_destroy(&tcp->xmitBuffer);
|
||||
CloseHandle(tcp->event);
|
||||
|
||||
if (tcp->socketBio)
|
||||
{
|
||||
BIO_free(tcp->socketBio);
|
||||
tcp->socketBio = NULL;
|
||||
}
|
||||
|
||||
if (tcp->bufferedBio)
|
||||
{
|
||||
BIO_free(tcp->bufferedBio);
|
||||
tcp->bufferedBio = NULL;
|
||||
}
|
||||
|
||||
free(tcp);
|
||||
}
|
||||
|
@ -38,8 +38,19 @@
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#define BIO_TYPE_SIMPLE 66
|
||||
#define BIO_TYPE_BUFFERED 67
|
||||
#define BIO_TYPE_TSG 65
|
||||
#define BIO_TYPE_SIMPLE 66
|
||||
#define BIO_TYPE_BUFFERED 67
|
||||
|
||||
#define BIO_C_SET_SOCKET 1101
|
||||
#define BIO_C_GET_SOCKET 1102
|
||||
#define BIO_C_GET_EVENT 1103
|
||||
#define BIO_C_SET_NONBLOCK 1104
|
||||
|
||||
#define BIO_set_socket(b, s, c) BIO_ctrl(b, BIO_C_SET_SOCKET, c, s);
|
||||
#define BIO_get_socket(b, c) BIO_ctrl(b, BIO_C_GET_SOCKET, 0, (char*) c)
|
||||
#define BIO_get_event(b, c) BIO_ctrl(b, BIO_C_GET_EVENT, 0, (char*) c)
|
||||
#define BIO_set_nonblock(b, c) BIO_ctrl(b, BIO_C_SET_NONBLOCK, c, NULL)
|
||||
|
||||
typedef struct rdp_tcp rdpTcp;
|
||||
|
||||
|
@ -103,12 +103,6 @@ BOOL transport_disconnect(rdpTransport* transport)
|
||||
|
||||
transport_stop(transport);
|
||||
|
||||
if (transport->frontBio)
|
||||
{
|
||||
BIO_free_all(transport->frontBio);
|
||||
transport->frontBio = NULL;
|
||||
}
|
||||
|
||||
if (transport->TlsIn)
|
||||
tls_free(transport->TlsIn);
|
||||
|
||||
@ -145,114 +139,6 @@ BOOL transport_connect_rdp(rdpTransport* transport)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
|
||||
{
|
||||
int status;
|
||||
rdpTsg* tsg = (rdpTsg*) bio->ptr;
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
status = tsg_write(tsg, (BYTE*) buf, num);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
}
|
||||
else if (status == 0)
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||
}
|
||||
|
||||
return status >= 0 ? status : -1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
int status;
|
||||
rdpTsg* tsg = (rdpTsg*) bio->ptr;
|
||||
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||
status = tsg_read(tsg, (BYTE*) buf, size);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
}
|
||||
else if (status == 0)
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||
}
|
||||
|
||||
return status > 0 ? status : -1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_puts(BIO* bio, const char* str)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
if (cmd == BIO_CTRL_FLUSH)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_new(BIO* bio)
|
||||
{
|
||||
bio->init = 1;
|
||||
bio->num = 0;
|
||||
bio->ptr = NULL;
|
||||
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_free(BIO* bio)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BIO_TYPE_TSG 65
|
||||
|
||||
static BIO_METHOD transport_bio_tsg_methods =
|
||||
{
|
||||
BIO_TYPE_TSG,
|
||||
"TSGateway",
|
||||
transport_bio_tsg_write,
|
||||
transport_bio_tsg_read,
|
||||
transport_bio_tsg_puts,
|
||||
transport_bio_tsg_gets,
|
||||
transport_bio_tsg_ctrl,
|
||||
transport_bio_tsg_new,
|
||||
transport_bio_tsg_free,
|
||||
NULL,
|
||||
};
|
||||
|
||||
BIO_METHOD* BIO_s_tsg(void)
|
||||
{
|
||||
return &transport_bio_tsg_methods;
|
||||
}
|
||||
|
||||
BOOL transport_connect_tls(rdpTransport* transport)
|
||||
{
|
||||
rdpSettings* settings = transport->settings;
|
||||
@ -391,8 +277,10 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
|
||||
freerdp* instance;
|
||||
rdpContext* context;
|
||||
rdpSettings* settings = transport->settings;
|
||||
|
||||
instance = (freerdp*) transport->settings->instance;
|
||||
context = instance->context;
|
||||
|
||||
tsg = tsg_new(transport);
|
||||
|
||||
if (!tsg)
|
||||
@ -424,6 +312,7 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
|
||||
|
||||
transport->TlsIn->hostname = transport->TlsOut->hostname = settings->GatewayHostname;
|
||||
transport->TlsIn->port = transport->TlsOut->port = settings->GatewayPort;
|
||||
|
||||
transport->TlsIn->isGatewayTransport = TRUE;
|
||||
tls_status = tls_connect(transport->TlsIn, transport->TcpIn->bufferedBio);
|
||||
|
||||
@ -465,8 +354,8 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
|
||||
if (!tsg_connect(tsg, hostname, port))
|
||||
return FALSE;
|
||||
|
||||
transport->frontBio = BIO_new(BIO_s_tsg());
|
||||
transport->frontBio->ptr = tsg;
|
||||
transport->frontBio = tsg->bio;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -509,7 +398,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
|
||||
{
|
||||
transport->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
transport->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL);
|
||||
(LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -838,7 +727,7 @@ int transport_read_pdu(rdpTransport* transport, wStream* s)
|
||||
#endif
|
||||
|
||||
if (Stream_GetPosition(s) >= pduLength)
|
||||
WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
|
||||
WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
|
||||
|
||||
Stream_SealLength(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
@ -866,7 +755,7 @@ int transport_write(rdpTransport* transport, wStream* s)
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
|
||||
WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
@ -1138,20 +1027,23 @@ static void* transport_client_thread(void* arg)
|
||||
rdpTransport* transport = (rdpTransport*) arg;
|
||||
rdpContext* context = transport->context;
|
||||
freerdp* instance = context->instance;
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Starting transport thread");
|
||||
|
||||
WLog_DBG(TAG, "Starting transport thread");
|
||||
|
||||
nCount = 0;
|
||||
handles[nCount++] = transport->stopEvent;
|
||||
handles[nCount++] = transport->connectedEvent;
|
||||
|
||||
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread");
|
||||
WLog_DBG(TAG, "Terminating transport thread");
|
||||
ExitThread(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Asynchronous transport activated");
|
||||
WLog_DBG(TAG, "Asynchronous transport activated");
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -1177,7 +1069,7 @@ static void* transport_client_thread(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread");
|
||||
WLog_DBG(TAG, "Terminating transport thread");
|
||||
ExitThread(0);
|
||||
return NULL;
|
||||
}
|
||||
@ -1185,6 +1077,7 @@ static void* transport_client_thread(void* arg)
|
||||
rdpTransport* transport_new(rdpContext* context)
|
||||
{
|
||||
rdpTransport* transport;
|
||||
|
||||
transport = (rdpTransport*) calloc(1, sizeof(rdpTransport));
|
||||
|
||||
if (!transport)
|
||||
@ -1192,11 +1085,6 @@ rdpTransport* transport_new(rdpContext* context)
|
||||
|
||||
transport->context = context;
|
||||
transport->settings = context->settings;
|
||||
WLog_Init();
|
||||
transport->log = WLog_Get(TAG);
|
||||
|
||||
if (!transport->log)
|
||||
goto out_free;
|
||||
|
||||
transport->TcpIn = freerdp_tcp_new(context->settings);
|
||||
|
||||
|
@ -55,7 +55,7 @@ typedef int (*TransportRecv) (rdpTransport* transport, wStream* stream, void* ex
|
||||
struct rdp_transport
|
||||
{
|
||||
TRANSPORT_LAYER layer;
|
||||
BIO *frontBio;
|
||||
BIO* frontBio;
|
||||
rdpTsg* tsg;
|
||||
rdpTcp* TcpIn;
|
||||
rdpTcp* TcpOut;
|
||||
@ -82,7 +82,6 @@ struct rdp_transport
|
||||
BOOL GatewayEnabled;
|
||||
CRITICAL_SECTION ReadLock;
|
||||
CRITICAL_SECTION WriteLock;
|
||||
wLog* log;
|
||||
void* rdp;
|
||||
};
|
||||
|
||||
|
@ -74,9 +74,15 @@ PCSTR inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize);
|
||||
#include <netinet/tcp.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <winpr/io.h>
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/platform.h>
|
||||
|
||||
#define WSAEVENT HANDLE
|
||||
#define LPWSAEVENT LPHANDLE
|
||||
#define WSAOVERLAPPED OVERLAPPED
|
||||
typedef OVERLAPPED* LPWSAOVERLAPPED;
|
||||
|
||||
typedef UINT_PTR SOCKET;
|
||||
typedef struct sockaddr_storage SOCKADDR_STORAGE;
|
||||
|
||||
@ -87,6 +93,39 @@ typedef struct sockaddr_storage SOCKADDR_STORAGE;
|
||||
#define WSADESCRIPTION_LEN 256
|
||||
#define WSASYS_STATUS_LEN 128
|
||||
|
||||
#define FD_READ_BIT 0
|
||||
#define FD_READ (1 << FD_READ_BIT)
|
||||
|
||||
#define FD_WRITE_BIT 1
|
||||
#define FD_WRITE (1 << FD_WRITE_BIT)
|
||||
|
||||
#define FD_OOB_BIT 2
|
||||
#define FD_OOB (1 << FD_OOB_BIT)
|
||||
|
||||
#define FD_ACCEPT_BIT 3
|
||||
#define FD_ACCEPT (1 << FD_ACCEPT_BIT)
|
||||
|
||||
#define FD_CONNECT_BIT 4
|
||||
#define FD_CONNECT (1 << FD_CONNECT_BIT)
|
||||
|
||||
#define FD_CLOSE_BIT 5
|
||||
#define FD_CLOSE (1 << FD_CLOSE_BIT)
|
||||
|
||||
#define FD_QOS_BIT 6
|
||||
#define FD_QOS (1 << FD_QOS_BIT)
|
||||
|
||||
#define FD_GROUP_QOS_BIT 7
|
||||
#define FD_GROUP_QOS (1 << FD_GROUP_QOS_BIT)
|
||||
|
||||
#define FD_ROUTING_INTERFACE_CHANGE_BIT 8
|
||||
#define FD_ROUTING_INTERFACE_CHANGE (1 << FD_ROUTING_INTERFACE_CHANGE_BIT)
|
||||
|
||||
#define FD_ADDRESS_LIST_CHANGE_BIT 9
|
||||
#define FD_ADDRESS_LIST_CHANGE (1 << FD_ADDRESS_LIST_CHANGE_BIT)
|
||||
|
||||
#define FD_MAX_EVENTS 10
|
||||
#define FD_ALL_EVENTS ((1 << FD_MAX_EVENTS) - 1)
|
||||
|
||||
#define SD_RECEIVE 0
|
||||
#define SD_SEND 1
|
||||
#define SD_BOTH 2
|
||||
@ -126,6 +165,16 @@ WINPR_API int WSACleanup(void);
|
||||
WINPR_API void WSASetLastError(int iError);
|
||||
WINPR_API int WSAGetLastError(void);
|
||||
|
||||
WINPR_API HANDLE WSACreateEvent(void);
|
||||
WINPR_API BOOL WSASetEvent(HANDLE hEvent);
|
||||
WINPR_API BOOL WSAResetEvent(HANDLE hEvent);
|
||||
WINPR_API BOOL WSACloseEvent(HANDLE hEvent);
|
||||
|
||||
WINPR_API int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents);
|
||||
|
||||
WINPR_API DWORD WSAWaitForMultipleEvents(DWORD cEvents,
|
||||
const HANDLE* lphEvents, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable);
|
||||
|
||||
WINPR_API SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen);
|
||||
WINPR_API int _bind(SOCKET s, const struct sockaddr* addr, int namelen);
|
||||
WINPR_API int closesocket(SOCKET s);
|
||||
|
@ -28,7 +28,6 @@ endif()
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
smartcard.c
|
||||
smartcard.h
|
||||
smartcard_link.c
|
||||
smartcard_pcsc.c
|
||||
smartcard_pcsc.h
|
||||
smartcard_inspect.c
|
||||
|
@ -1,202 +0,0 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Smart Card API
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DISABLE_PCSC_WINPR
|
||||
|
||||
/**
|
||||
* PCSC-WinPR (optional for Mac OS X):
|
||||
*
|
||||
* PCSC-WinPR is a static build of libpcsclite with
|
||||
* minor modifications meant to avoid an ABI conflict.
|
||||
*
|
||||
* At this point, it is only a work in progress, as I was not
|
||||
* yet able to make it work properly. However, if we could make it
|
||||
* work, we might be able to build against a version of pcsc-lite
|
||||
* that doesn't have issues present in Apple's SmartCard Services.
|
||||
*
|
||||
* Patch pcsc-lite/src/PCSC/wintypes.h:
|
||||
* Change "unsigned long" to "unsigned int" for
|
||||
*
|
||||
* typedef unsigned int ULONG;
|
||||
* typedef unsigned int DWORD;
|
||||
*
|
||||
* This is important as ULONG and DWORD are supposed to be 32-bit,
|
||||
* but unsigned long on 64-bit OS X is 64-bit, not 32-bit.
|
||||
* More importantly, Apple's SmartCard Services uses unsigned int,
|
||||
* while vanilla pcsc-lite still uses unsigned long.
|
||||
*
|
||||
* Patch pcsc-lite/src/PCSC/pcsclite.h.in:
|
||||
*
|
||||
* Add the WinPR_PCSC_* definitions that follow "#define WinPR_PCSC"
|
||||
* in this source file at the beginning of the pcsclite.h.in.
|
||||
*
|
||||
* Change "unsigned long" to "unsigned int" in the definition
|
||||
* of the SCARD_IO_REQUEST structure:
|
||||
*
|
||||
* unsigned int dwProtocol;
|
||||
* unsigned int cbPciLength;
|
||||
*
|
||||
* Configure pcsc-lite with the following options (Mac OS X):
|
||||
*
|
||||
* ./configure --enable-static --prefix=/usr --program-suffix=winpr
|
||||
* --enable-usbdropdir=/usr/libexec/SmartCardServices/drivers
|
||||
* --enable-confdir=/etc --enable-ipcdir=/var/run
|
||||
*
|
||||
* Build pcsc-lite, and then copy libpcsclite.a to libpcsc-winpr.a:
|
||||
*
|
||||
* make
|
||||
* cp ./src/.libs/libpcsclite.a libpcsc-winpr.a
|
||||
*
|
||||
* Validate that libpcsc-winpr.a has a modified ABI:
|
||||
*
|
||||
* nm libpcsc-winpr.a | grep " T " | grep WinPR
|
||||
*
|
||||
* If the ABI has been successfully modified, you should
|
||||
* see pcsc-lite functions prefixed with "WinPR_PCSC_".
|
||||
*
|
||||
* You can keep this custom pcsc-lite build for later.
|
||||
* To install the library, copy it to /usr/lib or /usr/local/lib.
|
||||
*
|
||||
* The FreeRDP build system will then automatically pick it up
|
||||
* as long as it is present on the system. To ensure PCSC-WinPR
|
||||
* is properly detected at cmake generation time, look for the
|
||||
* following debug output:
|
||||
*
|
||||
* -- Found PCSC-WinPR: /usr/lib/libpcsc-winpr.a
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define WinPR_PCSC
|
||||
|
||||
#define SCardEstablishContext WinPR_PCSC_SCardEstablishContext
|
||||
#define SCardReleaseContext WinPR_PCSC_SCardReleaseContext
|
||||
#define SCardIsValidContext WinPR_PCSC_SCardIsValidContext
|
||||
#define SCardConnect WinPR_PCSC_SCardConnect
|
||||
#define SCardReconnect WinPR_PCSC_SCardReconnect
|
||||
#define SCardDisconnect WinPR_PCSC_SCardDisconnect
|
||||
#define SCardBeginTransaction WinPR_PCSC_SCardBeginTransaction
|
||||
#define SCardEndTransaction WinPR_PCSC_SCardEndTransaction
|
||||
#define SCardStatus WinPR_PCSC_SCardStatus
|
||||
#define SCardGetStatusChange WinPR_PCSC_SCardGetStatusChange
|
||||
#define SCardControl WinPR_PCSC_SCardControl
|
||||
#define SCardTransmit WinPR_PCSC_SCardTransmit
|
||||
#define SCardListReaderGroups WinPR_PCSC_SCardListReaderGroups
|
||||
#define SCardListReaders WinPR_PCSC_SCardListReaders
|
||||
#define SCardFreeMemory WinPR_PCSC_SCardFreeMemory
|
||||
#define SCardCancel WinPR_PCSC_SCardCancel
|
||||
#define SCardGetAttrib WinPR_PCSC_SCardGetAttrib
|
||||
#define SCardSetAttrib WinPR_PCSC_SCardSetAttrib
|
||||
|
||||
#define g_rgSCardT0Pci WinPR_PCSC_g_rgSCardT0Pci
|
||||
#define g_rgSCardT1Pci WinPR_PCSC_g_rgSCardT1Pci
|
||||
#define g_rgSCardRawPci WinPR_PCSC_g_rgSCardRawPci
|
||||
#endif
|
||||
|
||||
#ifdef WITH_WINPR_PCSC
|
||||
extern void* WinPR_PCSC_SCardEstablishContext();
|
||||
extern void* WinPR_PCSC_SCardReleaseContext();
|
||||
extern void* WinPR_PCSC_SCardIsValidContext();
|
||||
extern void* WinPR_PCSC_SCardConnect();
|
||||
extern void* WinPR_PCSC_SCardReconnect();
|
||||
extern void* WinPR_PCSC_SCardDisconnect();
|
||||
extern void* WinPR_PCSC_SCardBeginTransaction();
|
||||
extern void* WinPR_PCSC_SCardEndTransaction();
|
||||
extern void* WinPR_PCSC_SCardStatus();
|
||||
extern void* WinPR_PCSC_SCardGetStatusChange();
|
||||
extern void* WinPR_PCSC_SCardControl();
|
||||
extern void* WinPR_PCSC_SCardTransmit();
|
||||
extern void* WinPR_PCSC_SCardListReaderGroups();
|
||||
extern void* WinPR_PCSC_SCardListReaders();
|
||||
extern void* WinPR_PCSC_SCardFreeMemory();
|
||||
extern void* WinPR_PCSC_SCardCancel();
|
||||
extern void* WinPR_PCSC_SCardGetAttrib();
|
||||
extern void* WinPR_PCSC_SCardSetAttrib();
|
||||
#endif
|
||||
|
||||
struct _PCSCFunctionTable
|
||||
{
|
||||
void* pfnSCardEstablishContext;
|
||||
void* pfnSCardReleaseContext;
|
||||
void* pfnSCardIsValidContext;
|
||||
void* pfnSCardConnect;
|
||||
void* pfnSCardReconnect;
|
||||
void* pfnSCardDisconnect;
|
||||
void* pfnSCardBeginTransaction;
|
||||
void* pfnSCardEndTransaction;
|
||||
void* pfnSCardStatus;
|
||||
void* pfnSCardGetStatusChange;
|
||||
void* pfnSCardControl;
|
||||
void* pfnSCardTransmit;
|
||||
void* pfnSCardListReaderGroups;
|
||||
void* pfnSCardListReaders;
|
||||
void* pfnSCardFreeMemory;
|
||||
void* pfnSCardCancel;
|
||||
void* pfnSCardGetAttrib;
|
||||
void* pfnSCardSetAttrib;
|
||||
};
|
||||
typedef struct _PCSCFunctionTable PCSCFunctionTable;
|
||||
|
||||
PCSCFunctionTable g_PCSC_Link = { 0 };
|
||||
|
||||
int PCSC_InitializeSCardApi_Link(void)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
#ifdef DISABLE_PCSC_WINPR
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_WINPR_PCSC
|
||||
g_PCSC_Link.pfnSCardEstablishContext = (void*) WinPR_PCSC_SCardEstablishContext;
|
||||
g_PCSC_Link.pfnSCardReleaseContext = (void*) WinPR_PCSC_SCardReleaseContext;
|
||||
g_PCSC_Link.pfnSCardIsValidContext = (void*) WinPR_PCSC_SCardIsValidContext;
|
||||
g_PCSC_Link.pfnSCardConnect = (void*) WinPR_PCSC_SCardConnect;
|
||||
g_PCSC_Link.pfnSCardReconnect = (void*) WinPR_PCSC_SCardReconnect;
|
||||
g_PCSC_Link.pfnSCardDisconnect = (void*) WinPR_PCSC_SCardDisconnect;
|
||||
g_PCSC_Link.pfnSCardBeginTransaction = (void*) WinPR_PCSC_SCardBeginTransaction;
|
||||
g_PCSC_Link.pfnSCardEndTransaction = (void*) WinPR_PCSC_SCardEndTransaction;
|
||||
g_PCSC_Link.pfnSCardStatus = (void*) WinPR_PCSC_SCardStatus;
|
||||
g_PCSC_Link.pfnSCardGetStatusChange = (void*) WinPR_PCSC_SCardGetStatusChange;
|
||||
g_PCSC_Link.pfnSCardControl = (void*) WinPR_PCSC_SCardControl;
|
||||
g_PCSC_Link.pfnSCardTransmit = (void*) WinPR_PCSC_SCardTransmit;
|
||||
g_PCSC_Link.pfnSCardListReaderGroups = (void*) WinPR_PCSC_SCardListReaderGroups;
|
||||
g_PCSC_Link.pfnSCardListReaders = (void*) WinPR_PCSC_SCardListReaders;
|
||||
//g_PCSC_Link.pfnSCardFreeMemory = (void*) WinPR_PCSC_SCardFreeMemory;
|
||||
g_PCSC_Link.pfnSCardFreeMemory = (void*) NULL;
|
||||
g_PCSC_Link.pfnSCardCancel = (void*) WinPR_PCSC_SCardCancel;
|
||||
g_PCSC_Link.pfnSCardGetAttrib = (void*) WinPR_PCSC_SCardGetAttrib;
|
||||
g_PCSC_Link.pfnSCardSetAttrib = (void*) WinPR_PCSC_SCardSetAttrib;
|
||||
|
||||
status = 1;
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
@ -111,22 +111,24 @@
|
||||
|
||||
//#define DISABLE_PCSC_SCARD_AUTOALLOCATE
|
||||
|
||||
typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
|
||||
typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
|
||||
|
||||
struct _PCSC_SCARDCONTEXT
|
||||
{
|
||||
SCARDHANDLE owner;
|
||||
CRITICAL_SECTION lock;
|
||||
SCARDCONTEXT hContext;
|
||||
DWORD dwCardHandleCount;
|
||||
BOOL isTransactionLocked;
|
||||
};
|
||||
typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
|
||||
|
||||
struct _PCSC_SCARDHANDLE
|
||||
{
|
||||
CRITICAL_SECTION lock;
|
||||
BOOL shared;
|
||||
SCARDCONTEXT hSharedContext;
|
||||
SCARDCONTEXT hPrivateContext;
|
||||
};
|
||||
typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
|
||||
|
||||
struct _PCSC_READER
|
||||
{
|
||||
@ -143,6 +145,7 @@ static int g_StartedEventRefCount = 0;
|
||||
|
||||
static BOOL g_SCardAutoAllocate = FALSE;
|
||||
static BOOL g_PnP_Notification = TRUE;
|
||||
|
||||
#ifdef __MACOSX__
|
||||
static unsigned int OSXVersion = 0;
|
||||
#endif
|
||||
@ -425,6 +428,117 @@ SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
|
||||
return pCard->hPrivateContext;
|
||||
}
|
||||
|
||||
BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
PCSC_SCARDCONTEXT* pContext = NULL;
|
||||
|
||||
if (!hCard)
|
||||
{
|
||||
/* SCardConnect */
|
||||
|
||||
pContext = PCSC_GetCardContextData(hContext);
|
||||
|
||||
if (!pContext)
|
||||
return FALSE;
|
||||
|
||||
if (!pContext->owner)
|
||||
return TRUE;
|
||||
|
||||
/* wait for card ownership */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return FALSE;
|
||||
|
||||
shared = pCard->shared;
|
||||
hContext = pCard->hSharedContext;
|
||||
|
||||
pContext = PCSC_GetCardContextData(hContext);
|
||||
|
||||
if (!pContext)
|
||||
return FALSE;
|
||||
|
||||
if (!pContext->owner)
|
||||
{
|
||||
/* card is not owned */
|
||||
|
||||
if (!shared)
|
||||
pContext->owner = hCard;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (pContext->owner == hCard)
|
||||
{
|
||||
/* already card owner */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* wait for card ownership */
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard)
|
||||
{
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
PCSC_SCARDCONTEXT* pContext = NULL;
|
||||
|
||||
if (!hCard)
|
||||
{
|
||||
/* release current owner */
|
||||
|
||||
pContext = PCSC_GetCardContextData(hContext);
|
||||
|
||||
if (!pContext)
|
||||
return FALSE;
|
||||
|
||||
hCard = pContext->owner;
|
||||
|
||||
if (!hCard)
|
||||
return TRUE;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return FALSE;
|
||||
|
||||
/* release card ownership */
|
||||
|
||||
pContext->owner = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return FALSE;
|
||||
|
||||
hContext = pCard->hSharedContext;
|
||||
|
||||
pContext = PCSC_GetCardContextData(hContext);
|
||||
|
||||
if (!pContext)
|
||||
return FALSE;
|
||||
|
||||
if (pContext->owner == hCard)
|
||||
{
|
||||
/* release card ownership */
|
||||
|
||||
pContext->owner = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDCONTEXT hPrivateContext, SCARDHANDLE hCard)
|
||||
{
|
||||
PCSC_SCARDHANDLE* pCard;
|
||||
@ -444,13 +558,13 @@ PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDCONTE
|
||||
|
||||
pCard->hSharedContext = hSharedContext;
|
||||
pCard->hPrivateContext = hPrivateContext;
|
||||
InitializeCriticalSectionAndSpinCount(&(pCard->lock), 4000);
|
||||
pContext->dwCardHandleCount++;
|
||||
|
||||
if (!g_CardHandles)
|
||||
g_CardHandles = ListDictionary_New(TRUE);
|
||||
|
||||
ListDictionary_Add(g_CardHandles, (void*) hCard, (void*) pCard);
|
||||
|
||||
return pCard;
|
||||
}
|
||||
|
||||
@ -458,12 +572,12 @@ void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
|
||||
{
|
||||
PCSC_SCARDHANDLE* pCard;
|
||||
PCSC_SCARDCONTEXT* pContext;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return;
|
||||
|
||||
DeleteCriticalSection(&(pCard->lock));
|
||||
pContext = PCSC_GetCardContextData(pCard->hSharedContext);
|
||||
PCSC_SCardReleaseContext_Internal(pCard->hPrivateContext);
|
||||
free(pCard);
|
||||
@ -482,68 +596,6 @@ void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
|
||||
pContext->dwCardHandleCount--;
|
||||
}
|
||||
|
||||
BOOL PCSC_LockCardHandle(SCARDHANDLE hCard)
|
||||
{
|
||||
PCSC_SCARDHANDLE* pCard;
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
{
|
||||
WLog_ERR(TAG, "PCSC_LockCardHandle: invalid handle (%p)", (void*) hCard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&(pCard->lock));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL PCSC_UnlockCardHandle(SCARDHANDLE hCard)
|
||||
{
|
||||
PCSC_SCARDHANDLE* pCard;
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
{
|
||||
WLog_ERR(TAG, "PCSC_UnlockCardHandle: invalid handle (%p)", (void*) hCard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&(pCard->lock));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL PCSC_LockCardTransaction(SCARDHANDLE hCard)
|
||||
{
|
||||
PCSC_SCARDHANDLE* pCard;
|
||||
return TRUE; /* disable for now because it deadlocks */
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
{
|
||||
WLog_ERR(TAG, "PCSC_LockCardTransaction: invalid handle (%p)", (void*) hCard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&(pCard->lock));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL PCSC_UnlockCardTransaction(SCARDHANDLE hCard)
|
||||
{
|
||||
PCSC_SCARDHANDLE* pCard;
|
||||
return TRUE; /* disable for now because it deadlocks */
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
{
|
||||
WLog_ERR(TAG, "PCSC_UnlockCardTransaction: invalid handle (%p)", (void*) hCard);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&(pCard->lock));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char* PCSC_GetReaderNameFromAlias(char* nameWinSCard)
|
||||
{
|
||||
int index;
|
||||
@ -1605,8 +1657,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
|
||||
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
|
||||
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
|
||||
{
|
||||
BOOL shared;
|
||||
BOOL access;
|
||||
char* szReaderPCSC;
|
||||
LONG status = SCARD_S_SUCCESS;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
SCARDCONTEXT hPrivateContext = 0;
|
||||
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
|
||||
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
|
||||
@ -1615,6 +1670,10 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
|
||||
if (!g_PCSC.pfnSCardConnect)
|
||||
return SCARD_E_NO_SERVICE;
|
||||
|
||||
shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE;
|
||||
|
||||
access = PCSC_WaitForCardAccess(hContext, 0, shared);
|
||||
|
||||
status = PCSC_SCardEstablishContext_Internal(SCARD_SCOPE_SYSTEM, NULL, NULL, &hPrivateContext);
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
@ -1642,8 +1701,11 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
|
||||
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
{
|
||||
PCSC_ConnectCardHandle(hContext, hPrivateContext, *phCard);
|
||||
pCard = PCSC_ConnectCardHandle(hContext, hPrivateContext, *phCard);
|
||||
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
|
||||
|
||||
pCard->shared = shared;
|
||||
PCSC_WaitForCardAccess(hContext, pCard->hSharedContext, shared);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1697,6 +1759,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext,
|
||||
WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard,
|
||||
DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
|
||||
{
|
||||
BOOL shared;
|
||||
BOOL access;
|
||||
LONG status = SCARD_S_SUCCESS;
|
||||
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
|
||||
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
|
||||
@ -1706,11 +1770,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard,
|
||||
if (!g_PCSC.pfnSCardReconnect)
|
||||
return SCARD_E_NO_SERVICE;
|
||||
|
||||
shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE;
|
||||
|
||||
access = PCSC_WaitForCardAccess(0, hCard, shared);
|
||||
|
||||
pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
|
||||
status = (LONG) g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode,
|
||||
pcsc_dwPreferredProtocols, pcsc_dwInitialization, &pcsc_dwActiveProtocol);
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1730,6 +1799,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposit
|
||||
PCSC_DisconnectCardHandle(hCard);
|
||||
}
|
||||
|
||||
PCSC_ReleaseCardAccess(0, hCard);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1785,6 +1856,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisp
|
||||
if (!pContext)
|
||||
return SCARD_E_INVALID_HANDLE;
|
||||
|
||||
PCSC_ReleaseCardAccess(0, hCard);
|
||||
|
||||
if (!pContext->isTransactionLocked)
|
||||
return SCARD_S_SUCCESS; /* disable nested transactions */
|
||||
|
||||
@ -1795,21 +1868,23 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisp
|
||||
}
|
||||
|
||||
pContext->isTransactionLocked = FALSE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
WINSCARDAPI LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
|
||||
{
|
||||
return 0;
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
|
||||
LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
|
||||
LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
|
||||
{
|
||||
PCSC_DWORD cchReaderLen;
|
||||
SCARDCONTEXT hContext = 0;
|
||||
LPSTR mszReaderNames = NULL;
|
||||
LONG status = SCARD_S_SUCCESS;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
PCSC_DWORD pcsc_dwState = 0;
|
||||
PCSC_DWORD pcsc_dwProtocol = 0;
|
||||
PCSC_DWORD pcsc_cbAtrLen = (PCSC_DWORD) *pcbAtrLen;
|
||||
@ -1817,6 +1892,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
|
||||
if (!g_PCSC.pfnSCardStatus)
|
||||
return SCARD_E_NO_SERVICE;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return SCARD_E_INVALID_VALUE;
|
||||
|
||||
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
|
||||
|
||||
hContext = PCSC_GetCardContextFromHandle(hCard);
|
||||
|
||||
if (!hContext)
|
||||
@ -1824,7 +1906,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
|
||||
|
||||
cchReaderLen = SCARD_AUTOALLOCATE;
|
||||
status = (LONG) g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
|
||||
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
|
||||
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
|
||||
if (mszReaderNames)
|
||||
@ -1833,6 +1915,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
|
||||
*pdwState = (DWORD) pcsc_dwState;
|
||||
*pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol);
|
||||
*pcbAtrLen = (DWORD) pcsc_cbAtrLen;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1847,6 +1930,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
|
||||
LPBYTE* pPbAtr = (LPBYTE*) pbAtr;
|
||||
LPSTR* pMszReaderNames = (LPSTR*) mszReaderNames;
|
||||
LONG status = SCARD_S_SUCCESS;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
PCSC_DWORD pcsc_cchReaderLen = 0;
|
||||
PCSC_DWORD pcsc_dwState = 0;
|
||||
PCSC_DWORD pcsc_dwProtocol = 0;
|
||||
@ -1855,6 +1939,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
|
||||
if (!g_PCSC.pfnSCardStatus)
|
||||
return SCARD_E_NO_SERVICE;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return SCARD_E_INVALID_VALUE;
|
||||
|
||||
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
|
||||
|
||||
hContext = PCSC_GetCardContextFromHandle(hCard);
|
||||
|
||||
if (!hContext || !pcchReaderLen || !pdwState || !pdwProtocol || !pcbAtrLen)
|
||||
@ -1879,9 +1970,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
|
||||
pcsc_cbAtrLen = 0;
|
||||
|
||||
status = (LONG) g_PCSC.pfnSCardStatus(hCard,
|
||||
(pcchReaderLenAlloc) ? NULL : mszReaderNames, &pcsc_cchReaderLen,
|
||||
&pcsc_dwState, &pcsc_dwProtocol,
|
||||
(pcbAtrLenAlloc) ? NULL : pbAtr, &pcsc_cbAtrLen);
|
||||
(pcchReaderLenAlloc) ? NULL : mszReaderNames, &pcsc_cchReaderLen,
|
||||
&pcsc_dwState, &pcsc_dwProtocol,
|
||||
(pcbAtrLenAlloc) ? NULL : pbAtr, &pcsc_cbAtrLen);
|
||||
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
{
|
||||
@ -1909,9 +2000,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
|
||||
}
|
||||
|
||||
status = (LONG) g_PCSC.pfnSCardStatus(hCard,
|
||||
*pMszReaderNames, &pcsc_cchReaderLen,
|
||||
&pcsc_dwState, &pcsc_dwProtocol,
|
||||
pbAtr, &pcsc_cbAtrLen);
|
||||
*pMszReaderNames, &pcsc_cchReaderLen,
|
||||
&pcsc_dwState, &pcsc_dwProtocol,
|
||||
pbAtr, &pcsc_cbAtrLen);
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
@ -1940,7 +2031,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard,
|
||||
else
|
||||
{
|
||||
status = (LONG) g_PCSC.pfnSCardStatus(hCard, mszReaderNames, &pcsc_cchReaderLen,
|
||||
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
|
||||
&pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
|
||||
}
|
||||
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
@ -2003,6 +2094,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
|
||||
LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
|
||||
{
|
||||
LONG status = SCARD_S_SUCCESS;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
PCSC_DWORD cbExtraBytes = 0;
|
||||
BYTE* pbExtraBytes = NULL;
|
||||
BYTE* pcsc_pbExtraBytes = NULL;
|
||||
@ -2014,6 +2106,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
|
||||
if (!g_PCSC.pfnSCardTransmit)
|
||||
return SCARD_E_NO_SERVICE;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return SCARD_E_INVALID_VALUE;
|
||||
|
||||
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
|
||||
|
||||
if (!pcbRecvLength)
|
||||
return SCARD_E_INVALID_PARAMETER;
|
||||
|
||||
@ -2094,7 +2193,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
|
||||
|
||||
WINSCARDAPI LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount)
|
||||
{
|
||||
return 0;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return SCARD_E_INVALID_VALUE;
|
||||
|
||||
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
|
||||
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
||||
WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
|
||||
@ -2107,6 +2215,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
|
||||
DWORD IoCtlDeviceType = 0;
|
||||
BOOL getFeatureRequest = FALSE;
|
||||
LONG status = SCARD_S_SUCCESS;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
PCSC_DWORD pcsc_dwControlCode = 0;
|
||||
PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD) cbInBufferSize;
|
||||
PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD) cbOutBufferSize;
|
||||
@ -2115,6 +2224,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
|
||||
if (!g_PCSC.pfnSCardControl)
|
||||
return SCARD_E_NO_SERVICE;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return SCARD_E_INVALID_VALUE;
|
||||
|
||||
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
|
||||
|
||||
/**
|
||||
* PCSCv2 Part 10:
|
||||
* http://www.pcscworkgroup.com/specifications/files/pcsc10_v2.02.09.pdf
|
||||
@ -2173,12 +2289,20 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dw
|
||||
BOOL pcbAttrLenAlloc = FALSE;
|
||||
LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
|
||||
LONG status = SCARD_S_SUCCESS;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
|
||||
PCSC_DWORD pcsc_cbAttrLen = 0;
|
||||
|
||||
if (!g_PCSC.pfnSCardGetAttrib)
|
||||
return SCARD_E_NO_SERVICE;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return SCARD_E_INVALID_VALUE;
|
||||
|
||||
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
|
||||
|
||||
hContext = PCSC_GetCardContextFromHandle(hCard);
|
||||
|
||||
if (!hContext)
|
||||
@ -2516,14 +2640,23 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L
|
||||
WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
|
||||
{
|
||||
LONG status = SCARD_S_SUCCESS;
|
||||
PCSC_SCARDHANDLE* pCard = NULL;
|
||||
PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
|
||||
PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD) cbAttrLen;
|
||||
|
||||
if (!g_PCSC.pfnSCardSetAttrib)
|
||||
return SCARD_E_NO_SERVICE;
|
||||
|
||||
pCard = PCSC_GetCardHandleData(hCard);
|
||||
|
||||
if (!pCard)
|
||||
return SCARD_E_INVALID_VALUE;
|
||||
|
||||
PCSC_WaitForCardAccess(0, hCard, pCard->shared);
|
||||
|
||||
status = (LONG) g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -2806,48 +2939,37 @@ PSCardApiFunctionTable PCSC_GetSCardApiFunctionTable(void)
|
||||
return &PCSC_SCardApiFunctionTable;
|
||||
}
|
||||
|
||||
extern PCSCFunctionTable g_PCSC_Link;
|
||||
extern int PCSC_InitializeSCardApi_Link(void);
|
||||
|
||||
int PCSC_InitializeSCardApi(void)
|
||||
{
|
||||
/* Disable pcsc-lite's (poor) blocking so we can handle it ourselves */
|
||||
SetEnvironmentVariableA("PCSCLITE_NO_BLOCKING", "1");
|
||||
#ifndef DISABLE_PCSC_LINK
|
||||
DWORD nSize;
|
||||
char* env = NULL;
|
||||
|
||||
if (PCSC_InitializeSCardApi_Link() >= 0)
|
||||
nSize = GetEnvironmentVariableA("WINPR_WINSCARD_LOCK_TRANSACTIONS", NULL, 0);
|
||||
|
||||
if (nSize)
|
||||
{
|
||||
g_PCSC.pfnSCardEstablishContext = g_PCSC_Link.pfnSCardEstablishContext;
|
||||
g_PCSC.pfnSCardReleaseContext = g_PCSC_Link.pfnSCardReleaseContext;
|
||||
g_PCSC.pfnSCardIsValidContext = g_PCSC_Link.pfnSCardIsValidContext;
|
||||
g_PCSC.pfnSCardConnect = g_PCSC_Link.pfnSCardConnect;
|
||||
g_PCSC.pfnSCardReconnect = g_PCSC_Link.pfnSCardReconnect;
|
||||
g_PCSC.pfnSCardDisconnect = g_PCSC_Link.pfnSCardDisconnect;
|
||||
g_PCSC.pfnSCardBeginTransaction = g_PCSC_Link.pfnSCardBeginTransaction;
|
||||
g_PCSC.pfnSCardEndTransaction = g_PCSC_Link.pfnSCardEndTransaction;
|
||||
g_PCSC.pfnSCardStatus = g_PCSC_Link.pfnSCardStatus;
|
||||
g_PCSC.pfnSCardGetStatusChange = g_PCSC_Link.pfnSCardGetStatusChange;
|
||||
g_PCSC.pfnSCardControl = g_PCSC_Link.pfnSCardControl;
|
||||
g_PCSC.pfnSCardTransmit = g_PCSC_Link.pfnSCardTransmit;
|
||||
g_PCSC.pfnSCardListReaderGroups = g_PCSC_Link.pfnSCardListReaderGroups;
|
||||
g_PCSC.pfnSCardListReaders = g_PCSC_Link.pfnSCardListReaders;
|
||||
g_PCSC.pfnSCardFreeMemory = g_PCSC_Link.pfnSCardFreeMemory;
|
||||
g_PCSC.pfnSCardCancel = g_PCSC_Link.pfnSCardCancel;
|
||||
g_PCSC.pfnSCardGetAttrib = g_PCSC_Link.pfnSCardGetAttrib;
|
||||
g_PCSC.pfnSCardSetAttrib = g_PCSC_Link.pfnSCardSetAttrib;
|
||||
return 1;
|
||||
env = (LPSTR) malloc(nSize);
|
||||
nSize = GetEnvironmentVariableA("WINPR_WINSCARD_LOCK_TRANSACTIONS", env, nSize);
|
||||
|
||||
if (strcmp(env, "1") == 0)
|
||||
g_LockTransactions = TRUE;
|
||||
else if (strcmp(env, "0") == 0)
|
||||
g_LockTransactions = FALSE;
|
||||
|
||||
free(env);
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Disable pcsc-lite's (poor) blocking so we can handle it ourselves */
|
||||
SetEnvironmentVariableA("PCSCLITE_NO_BLOCKING", "1");
|
||||
|
||||
#ifdef __MACOSX__
|
||||
g_PCSCModule = LoadLibraryA("/System/Library/Frameworks/PCSC.framework/PCSC");
|
||||
OSXVersion = determineMacOSXVersion();
|
||||
OSXVersion = determineMacOSXVersion();
|
||||
#else
|
||||
g_PCSCModule = LoadLibraryA("libpcsclite.so.1");
|
||||
|
||||
if (!g_PCSCModule)
|
||||
g_PCSCModule = LoadLibraryA("libpcsclite.so");
|
||||
|
||||
#endif
|
||||
|
||||
if (!g_PCSCModule)
|
||||
@ -2863,6 +2985,7 @@ int PCSC_InitializeSCardApi(void)
|
||||
g_PCSC.pfnSCardEndTransaction = (void*) GetProcAddress(g_PCSCModule, "SCardEndTransaction");
|
||||
g_PCSC.pfnSCardStatus = (void*) GetProcAddress(g_PCSCModule, "SCardStatus");
|
||||
g_PCSC.pfnSCardGetStatusChange = (void*) GetProcAddress(g_PCSCModule, "SCardGetStatusChange");
|
||||
|
||||
#ifdef __MACOSX__
|
||||
if (OSXVersion >= 0x10050600)
|
||||
g_PCSC.pfnSCardControl = (void*) GetProcAddress(g_PCSCModule, "SCardControl132");
|
||||
@ -2871,12 +2994,14 @@ int PCSC_InitializeSCardApi(void)
|
||||
#else
|
||||
g_PCSC.pfnSCardControl = (void*) GetProcAddress(g_PCSCModule, "SCardControl");
|
||||
#endif
|
||||
|
||||
g_PCSC.pfnSCardTransmit = (void*) GetProcAddress(g_PCSCModule, "SCardTransmit");
|
||||
g_PCSC.pfnSCardListReaderGroups = (void*) GetProcAddress(g_PCSCModule, "SCardListReaderGroups");
|
||||
g_PCSC.pfnSCardListReaders = (void*) GetProcAddress(g_PCSCModule, "SCardListReaders");
|
||||
g_PCSC.pfnSCardCancel = (void*) GetProcAddress(g_PCSCModule, "SCardCancel");
|
||||
g_PCSC.pfnSCardGetAttrib = (void*) GetProcAddress(g_PCSCModule, "SCardGetAttrib");
|
||||
g_PCSC.pfnSCardSetAttrib = (void*) GetProcAddress(g_PCSCModule, "SCardSetAttrib");
|
||||
|
||||
g_PCSC.pfnSCardFreeMemory = NULL;
|
||||
#ifndef __APPLE__
|
||||
g_PCSC.pfnSCardFreeMemory = (void*) GetProcAddress(g_PCSCModule, "SCardFreeMemory");
|
||||
@ -2889,9 +3014,11 @@ int PCSC_InitializeSCardApi(void)
|
||||
g_PCSC.pfnSCardFreeMemory = NULL;
|
||||
g_SCardAutoAllocate = FALSE;
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
g_PnP_Notification = FALSE;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -740,9 +740,7 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAl
|
||||
|
||||
DWORD WaitForMultipleObjectsEx(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable)
|
||||
{
|
||||
WLog_ERR(TAG, "[ERROR] %s: Function not implemented.");
|
||||
assert(0);
|
||||
return 0;
|
||||
return WaitForMultipleObjects(nCount, lpHandles, bWaitAll, dwMilliseconds);
|
||||
}
|
||||
|
||||
DWORD SignalObjectAndWait(HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
|
||||
|
@ -36,8 +36,10 @@
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <io.h>
|
||||
#include <Windows.h>
|
||||
#include <Dbghelp.h>
|
||||
#define write _write
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
@ -421,16 +423,18 @@ void winpr_backtrace_symbols_fd(void *buffer, int fd)
|
||||
assert(data);
|
||||
backtrace_symbols_fd(data->buffer, data->used, fd);
|
||||
#elif defined(_WIN32) || defined(_WIN64) || defined(ANDROID)
|
||||
{
|
||||
size_t used;
|
||||
char **lines = winpr_backtrace_symbols(buffer, &used);
|
||||
{
|
||||
DWORD i;
|
||||
size_t used;
|
||||
char** lines;
|
||||
|
||||
lines = winpr_backtrace_symbols(buffer, &used);
|
||||
|
||||
if (lines)
|
||||
{
|
||||
DWORD i;
|
||||
for (i=0; i<used; i++)
|
||||
write(fd, lines[i], strlen(lines[i]));
|
||||
}
|
||||
if (lines)
|
||||
{
|
||||
for (i = 0; i < used; i++)
|
||||
write(fd, lines[i], strlen(lines[i]));
|
||||
}
|
||||
}
|
||||
#else
|
||||
LOGF(support_msg);
|
||||
|
@ -65,7 +65,6 @@ void winpr_HexDump(const char* tag, int level, const BYTE* data, int length)
|
||||
pos += trio_snprintf(&buffer[pos], blen - pos, "%c",
|
||||
(p[i] >= 0x20 && p[i] < 0x7F) ? p[i] : '.');
|
||||
|
||||
pos += trio_snprintf(&buffer[pos], blen - pos, "\n");
|
||||
WLog_LVL(tag, level, "%s", buffer);
|
||||
offset += line;
|
||||
p += line;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include <winpr/winsock.h>
|
||||
|
||||
@ -596,6 +597,43 @@ int WSAGetLastError(void)
|
||||
return iError;
|
||||
}
|
||||
|
||||
HANDLE WSACreateEvent(void)
|
||||
{
|
||||
return CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
}
|
||||
|
||||
BOOL WSASetEvent(HANDLE hEvent)
|
||||
{
|
||||
return SetEvent(hEvent);
|
||||
}
|
||||
|
||||
BOOL WSAResetEvent(HANDLE hEvent)
|
||||
{
|
||||
return ResetEvent(hEvent);
|
||||
}
|
||||
|
||||
BOOL WSACloseEvent(HANDLE hEvent)
|
||||
{
|
||||
BOOL status;
|
||||
|
||||
status = CloseHandle(hEvent);
|
||||
|
||||
if (!status)
|
||||
SetLastError(6);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WSAWaitForMultipleEvents(DWORD cEvents, const HANDLE* lphEvents, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable)
|
||||
{
|
||||
return WaitForMultipleObjectsEx(cEvents, lphEvents, fWaitAll, dwTimeout, fAlertable);
|
||||
}
|
||||
|
||||
SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen)
|
||||
{
|
||||
int status;
|
||||
|
Loading…
Reference in New Issue
Block a user