14827 lines
563 KiB
Diff
14827 lines
563 KiB
Diff
From 9088b82c20844abf72d51368a3b14d3e95128937 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Wed, 6 May 2026 16:32:49 +0200
|
|
Subject: [PATCH 01/31] [channels,rdpdr] fix capability type check
|
|
|
|
caps was accumulated using CAP_*_TYPE enum values (sequential: 1-5)
|
|
but compared against context->supported which uses RDPDR_DTYP_*
|
|
bitmask values. Map CAP_*_TYPE to the corresponding RDPDR_DTYP_*
|
|
bitmask before accumulating into caps.
|
|
|
|
Also moved the supported-check and deactivation out of the
|
|
per-capability loop to avoid prematurely clearing context->supported
|
|
bits before all capabilities were accumulated.
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 41 ++++++++++++++++++++----------
|
|
1 file changed, 27 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 62e5b90448a3..1de60b6688df 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -904,6 +904,24 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
return error;
|
|
}
|
|
|
|
+static UINT16 rdpdr_cap_type_to_dtyp(UINT16 capabilityType)
|
|
+{
|
|
+ switch (capabilityType)
|
|
+ {
|
|
+ case CAP_PRINTER_TYPE:
|
|
+ return RDPDR_DTYP_PRINT;
|
|
+ case CAP_PORT_TYPE:
|
|
+ return RDPDR_DTYP_SERIAL | RDPDR_DTYP_PARALLEL;
|
|
+ case CAP_DRIVE_TYPE:
|
|
+ return RDPDR_DTYP_FILESYSTEM;
|
|
+ case CAP_SMARTCARD_TYPE:
|
|
+ return RDPDR_DTYP_SMARTCARD;
|
|
+ case CAP_GENERAL_TYPE:
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
/**
|
|
* Function description
|
|
*
|
|
@@ -943,7 +961,6 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
if (status != CHANNEL_RC_OK)
|
|
return status;
|
|
|
|
- caps |= capabilityHeader.CapabilityType;
|
|
switch (capabilityHeader.CapabilityType)
|
|
{
|
|
case CAP_GENERAL_TYPE:
|
|
@@ -1007,21 +1024,14 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
- for (UINT16 x = 0; x < 16; x++)
|
|
+ const UINT16 client_dtyp = rdpdr_cap_type_to_dtyp(capabilityHeader.CapabilityType);
|
|
+ if ((client_dtyp != 0) && ((client_dtyp & context->supported) == 0))
|
|
{
|
|
- const UINT16 mask = (UINT16)(1u << x);
|
|
- if (((caps & mask) != 0) && ((context->supported & mask) == 0))
|
|
- {
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
- "client sent capability %s we did not announce!",
|
|
- freerdp_rdpdr_dtyp_string(mask));
|
|
- }
|
|
-
|
|
- /* we assume the server supports the capability. so only deactivate what the client did
|
|
- * not respond with */
|
|
- if ((caps & mask) == 0)
|
|
- context->supported &= ~mask;
|
|
+ WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ "client sent capability %s we did not announce!",
|
|
+ rdpdr_cap_type_string(capabilityHeader.CapabilityType));
|
|
}
|
|
+ caps |= client_dtyp;
|
|
|
|
const size_t end = Stream_GetPosition(s);
|
|
const size_t diff = end - start;
|
|
@@ -1035,6 +1045,9 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
}
|
|
}
|
|
|
|
+ /* Only deactivate what the client did not respond with */
|
|
+ context->supported &= caps;
|
|
+
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
|
|
From 0e5bcdbb78657828098b290579da03c080e40333 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Wed, 6 May 2026 19:02:19 +0200
|
|
Subject: [PATCH 02/31] [channels,smartcard] fix DeviceDataLength in
|
|
DEVICE_ANNOUNCE
|
|
|
|
Per MS-RDPEFS 2.2.1.3, the DeviceDataLength field in the
|
|
DEVICE_ANNOUNCE message for smartcard devices must be 0.
|
|
Remove the "SCARD" device data that was incorrectly sent,
|
|
which caused the server to reject the announcement.
|
|
---
|
|
channels/smartcard/client/smartcard_main.c | 11 -----------
|
|
1 file changed, 11 deletions(-)
|
|
|
|
diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c
|
|
index d186ddfa7ad8..bf08b8c08c7e 100644
|
|
--- a/channels/smartcard/client/smartcard_main.c
|
|
+++ b/channels/smartcard/client/smartcard_main.c
|
|
@@ -632,7 +632,6 @@ static void smartcard_free_irp(void* obj)
|
|
*/
|
|
FREERDP_ENTRY_POINT(UINT VCAPITYPE DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints))
|
|
{
|
|
- size_t length = 0;
|
|
UINT error = CHANNEL_RC_NO_MEMORY;
|
|
|
|
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*)calloc(1, sizeof(SMARTCARD_DEVICE));
|
|
@@ -649,16 +648,6 @@ FREERDP_ENTRY_POINT(UINT VCAPITYPE DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POIN
|
|
smartcard->device.Init = smartcard_init;
|
|
smartcard->device.Free = smartcard_free;
|
|
smartcard->rdpcontext = pEntryPoints->rdpcontext;
|
|
- length = strlen(smartcard->device.name);
|
|
- smartcard->device.data = Stream_New(nullptr, length + 1);
|
|
-
|
|
- if (!smartcard->device.data)
|
|
- {
|
|
- WLog_ERR(TAG, "Stream_New failed!");
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- Stream_Write(smartcard->device.data, "SCARD", 6);
|
|
smartcard->IrpQueue = MessageQueue_New(nullptr);
|
|
|
|
if (!smartcard->IrpQueue)
|
|
|
|
From 8a9b9d3b0e30f1e5454fb377bd5400c75175ae2e Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Thu, 7 May 2026 19:05:10 +0200
|
|
Subject: [PATCH 03/31] [utils,smartcard] use
|
|
RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH constant
|
|
|
|
Replace hardcoded 32 with the named constant for the device control
|
|
request header length check.
|
|
---
|
|
libfreerdp/utils/smartcard_operations.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/libfreerdp/utils/smartcard_operations.c b/libfreerdp/utils/smartcard_operations.c
|
|
index b7a754831b30..dfbdfeacb08c 100644
|
|
--- a/libfreerdp/utils/smartcard_operations.c
|
|
+++ b/libfreerdp/utils/smartcard_operations.c
|
|
@@ -547,7 +547,7 @@ LONG smartcard_irp_device_control_decode(wStream* s, UINT32 CompletionId, UINT32
|
|
|
|
/* Device Control Request */
|
|
|
|
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 32))
|
|
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH))
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
const UINT32 outputBufferLength = Stream_Get_UINT32(s); /* OutputBufferLength (4 bytes) */
|
|
|
|
From be8358d457f18dd9b6ace7abd9a04f5338676a05 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Thu, 7 May 2026 19:08:06 +0200
|
|
Subject: [PATCH 04/31] [utils,smartcard] rename decode to decode_request
|
|
|
|
smartcard_irp_device_control_decode only decodes device control request
|
|
types (DR_CONTROL_REQ), not response types. Rename to decode_request to
|
|
make this explicit and allow a symmetric decode_response counterpart.
|
|
---
|
|
channels/smartcard/client/smartcard_main.c | 4 +-
|
|
include/freerdp/utils/smartcard_operations.h | 31 ++++
|
|
libfreerdp/utils/smartcard_operations.c | 184 ++++++++++---------
|
|
server/proxy/channels/pf_channel_smartcard.c | 2 +-
|
|
4 files changed, 130 insertions(+), 91 deletions(-)
|
|
|
|
diff --git a/channels/smartcard/client/smartcard_main.c b/channels/smartcard/client/smartcard_main.c
|
|
index bf08b8c08c7e..0093a1955d8a 100644
|
|
--- a/channels/smartcard/client/smartcard_main.c
|
|
+++ b/channels/smartcard/client/smartcard_main.c
|
|
@@ -378,8 +378,8 @@ static UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL* h
|
|
element->irp = irp;
|
|
element->operation.completionID = irp->CompletionId;
|
|
|
|
- status = smartcard_irp_device_control_decode(irp->input, irp->CompletionId, irp->FileId,
|
|
- &element->operation);
|
|
+ status = smartcard_irp_device_control_decode_request(irp->input, irp->CompletionId,
|
|
+ irp->FileId, &element->operation);
|
|
|
|
if (status != SCARD_S_SUCCESS)
|
|
{
|
|
diff --git a/include/freerdp/utils/smartcard_operations.h b/include/freerdp/utils/smartcard_operations.h
|
|
index 90c71baf7dee..41a5fd6b043a 100644
|
|
--- a/include/freerdp/utils/smartcard_operations.h
|
|
+++ b/include/freerdp/utils/smartcard_operations.h
|
|
@@ -86,11 +86,42 @@ extern "C"
|
|
UINT32 outputBufferLength; /** @since version 3.13.0 */
|
|
} SMARTCARD_OPERATION;
|
|
|
|
+ /** @brief Alias for \ref smartcard_irp_device_control_decode_request.
|
|
+ *
|
|
+ * Kept for backward compatibility; new code should use the _request variant.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_irp_device_control_decode(wStream* s, UINT32 CompletionId,
|
|
UINT32 FileId,
|
|
SMARTCARD_OPERATION* operation);
|
|
|
|
+ /** @brief Decode a smartcard IOCTL request received from the client.
|
|
+ *
|
|
+ * Parses the Device Control Request fields (OutputBufferLength, InputBufferLength,
|
|
+ * IoControlCode, Padding), then unpacks the Common Type Header, Private Type Header,
|
|
+ * and the IOCTL-specific call payload into \p operation->call.
|
|
+ *
|
|
+ * @param s Stream positioned at OutputBufferLength, after the DeviceIoRequest header.
|
|
+ * @param CompletionId The CompletionId from the DeviceIoRequest header.
|
|
+ * @param FileId The FileId from the DeviceIoRequest header.
|
|
+ * @param operation [out] The decoded ioControlCode, call union, and context handles.
|
|
+ * @return \b SCARD_S_SUCCESS on success, a smartcard error code on failure.
|
|
+ *
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_irp_device_control_decode_request(wStream* s, UINT32 CompletionId,
|
|
+ UINT32 FileId,
|
|
+ SMARTCARD_OPERATION* operation);
|
|
+
|
|
+ /** @brief Free resources held by a SMARTCARD_OPERATION.
|
|
+ *
|
|
+ * Releases any memory allocated inside the call and ret unions (e.g., reader name
|
|
+ * strings, reader state arrays, receive buffers).
|
|
+ *
|
|
+ * @param op The operation to clean up. May be NULL (no-op).
|
|
+ * @param allocated If TRUE, also frees the SMARTCARD_OPERATION struct itself.
|
|
+ */
|
|
FREERDP_API void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated);
|
|
|
|
#ifdef __cplusplus
|
|
diff --git a/libfreerdp/utils/smartcard_operations.c b/libfreerdp/utils/smartcard_operations.c
|
|
index dfbdfeacb08c..a56e4e23c3f0 100644
|
|
--- a/libfreerdp/utils/smartcard_operations.c
|
|
+++ b/libfreerdp/utils/smartcard_operations.c
|
|
@@ -55,7 +55,7 @@ static LONG smartcard_call_to_operation_handle(SMARTCARD_OPERATION* operation)
|
|
return SCARD_S_SUCCESS;
|
|
}
|
|
|
|
-static LONG smartcard_EstablishContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_EstablishContext_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -71,7 +71,7 @@ static LONG smartcard_EstablishContext_Decode(wStream* s, SMARTCARD_OPERATION* o
|
|
return SCARD_S_SUCCESS;
|
|
}
|
|
|
|
-static LONG smartcard_ReleaseContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ReleaseContext_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -85,7 +85,7 @@ static LONG smartcard_ReleaseContext_Decode(wStream* s, SMARTCARD_OPERATION* ope
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_IsValidContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_IsValidContext_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -97,7 +97,7 @@ static LONG smartcard_IsValidContext_Decode(wStream* s, SMARTCARD_OPERATION* ope
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ListReaderGroupsA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ListReaderGroupsA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -109,7 +109,7 @@ static LONG smartcard_ListReaderGroupsA_Decode(wStream* s, SMARTCARD_OPERATION*
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ListReaderGroupsW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ListReaderGroupsW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -121,7 +121,7 @@ static LONG smartcard_ListReaderGroupsW_Decode(wStream* s, SMARTCARD_OPERATION*
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ListReadersA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ListReadersA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -133,7 +133,7 @@ static LONG smartcard_ListReadersA_Decode(wStream* s, SMARTCARD_OPERATION* opera
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ListReadersW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ListReadersW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -145,7 +145,8 @@ static LONG smartcard_ListReadersW_Decode(wStream* s, SMARTCARD_OPERATION* opera
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_context_and_two_strings_a_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ContextAndTwoStringA_decode_request(wStream* s,
|
|
+ SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -158,7 +159,8 @@ static LONG smartcard_context_and_two_strings_a_Decode(wStream* s, SMARTCARD_OPE
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_context_and_two_strings_w_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ContextAndTwoStringW_decode_request(wStream* s,
|
|
+ SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -171,7 +173,7 @@ static LONG smartcard_context_and_two_strings_w_Decode(wStream* s, SMARTCARD_OPE
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_context_and_string_a_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ContextAndStringA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -183,7 +185,7 @@ static LONG smartcard_context_and_string_a_Decode(wStream* s, SMARTCARD_OPERATIO
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_context_and_string_w_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ContextAndStringW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -195,7 +197,7 @@ static LONG smartcard_context_and_string_w_Decode(wStream* s, SMARTCARD_OPERATIO
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_LocateCardsA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_LocateCardsA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -207,7 +209,7 @@ static LONG smartcard_LocateCardsA_Decode(wStream* s, SMARTCARD_OPERATION* opera
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_LocateCardsW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_LocateCardsW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -219,7 +221,7 @@ static LONG smartcard_LocateCardsW_Decode(wStream* s, SMARTCARD_OPERATION* opera
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_GetStatusChangeA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_GetStatusChangeA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
WINPR_ASSERT(s);
|
|
WINPR_ASSERT(operation);
|
|
@@ -227,7 +229,7 @@ static LONG smartcard_GetStatusChangeA_Decode(wStream* s, SMARTCARD_OPERATION* o
|
|
return smartcard_unpack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
|
|
}
|
|
|
|
-static LONG smartcard_GetStatusChangeW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_GetStatusChangeW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
WINPR_ASSERT(s);
|
|
WINPR_ASSERT(operation);
|
|
@@ -235,7 +237,7 @@ static LONG smartcard_GetStatusChangeW_Decode(wStream* s, SMARTCARD_OPERATION* o
|
|
return smartcard_unpack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
|
|
}
|
|
|
|
-static LONG smartcard_Cancel_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_Cancel_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -247,7 +249,7 @@ static LONG smartcard_Cancel_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ConnectA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ConnectA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -259,7 +261,7 @@ static LONG smartcard_ConnectA_Decode(wStream* s, SMARTCARD_OPERATION* operation
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ConnectW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ConnectW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -271,7 +273,7 @@ static LONG smartcard_ConnectW_Decode(wStream* s, SMARTCARD_OPERATION* operation
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_Reconnect_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_Reconnect_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -283,7 +285,7 @@ static LONG smartcard_Reconnect_Decode(wStream* s, SMARTCARD_OPERATION* operatio
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_Disconnect_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_Disconnect_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -296,7 +298,7 @@ static LONG smartcard_Disconnect_Decode(wStream* s, SMARTCARD_OPERATION* operati
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_BeginTransaction_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_BeginTransaction_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -309,7 +311,7 @@ static LONG smartcard_BeginTransaction_Decode(wStream* s, SMARTCARD_OPERATION* o
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_EndTransaction_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_EndTransaction_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -322,7 +324,7 @@ static LONG smartcard_EndTransaction_Decode(wStream* s, SMARTCARD_OPERATION* ope
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_State_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_State_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -334,7 +336,7 @@ static LONG smartcard_State_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_StatusA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_StatusA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -346,7 +348,7 @@ static LONG smartcard_StatusA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_StatusW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_StatusW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -358,7 +360,7 @@ static LONG smartcard_StatusW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_Transmit_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_Transmit_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -370,7 +372,7 @@ static LONG smartcard_Transmit_Decode(wStream* s, SMARTCARD_OPERATION* operation
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_Control_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_Control_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -382,7 +384,7 @@ static LONG smartcard_Control_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_GetAttrib_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_GetAttrib_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -394,7 +396,7 @@ static LONG smartcard_GetAttrib_Decode(wStream* s, SMARTCARD_OPERATION* operatio
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_SetAttrib_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_SetAttrib_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -406,7 +408,7 @@ static LONG smartcard_SetAttrib_Decode(wStream* s, SMARTCARD_OPERATION* operatio
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_AccessStartedEvent_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_AccessStartedEvent_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
WINPR_ASSERT(s);
|
|
WINPR_ASSERT(operation);
|
|
@@ -419,7 +421,7 @@ static LONG smartcard_AccessStartedEvent_Decode(wStream* s, SMARTCARD_OPERATION*
|
|
return SCARD_S_SUCCESS;
|
|
}
|
|
|
|
-static LONG smartcard_LocateCardsByATRA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_LocateCardsByATRA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -431,7 +433,7 @@ static LONG smartcard_LocateCardsByATRA_Decode(wStream* s, SMARTCARD_OPERATION*
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_LocateCardsByATRW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_LocateCardsByATRW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -443,7 +445,7 @@ static LONG smartcard_LocateCardsByATRW_Decode(wStream* s, SMARTCARD_OPERATION*
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ReadCacheA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ReadCacheA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -455,7 +457,7 @@ static LONG smartcard_ReadCacheA_Decode(wStream* s, SMARTCARD_OPERATION* operati
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ReadCacheW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ReadCacheW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -467,7 +469,7 @@ static LONG smartcard_ReadCacheW_Decode(wStream* s, SMARTCARD_OPERATION* operati
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_WriteCacheA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_WriteCacheA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -479,7 +481,7 @@ static LONG smartcard_WriteCacheA_Decode(wStream* s, SMARTCARD_OPERATION* operat
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_WriteCacheW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_WriteCacheW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -491,7 +493,7 @@ static LONG smartcard_WriteCacheW_Decode(wStream* s, SMARTCARD_OPERATION* operat
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_GetTransmitCount_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_GetTransmitCount_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -503,7 +505,7 @@ static LONG smartcard_GetTransmitCount_Decode(wStream* s, SMARTCARD_OPERATION* o
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_ReleaseStartedEvent_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_ReleaseStartedEvent_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
WINPR_UNUSED(s);
|
|
WINPR_UNUSED(operation);
|
|
@@ -512,7 +514,7 @@ static LONG smartcard_ReleaseStartedEvent_Decode(wStream* s, SMARTCARD_OPERATION
|
|
return SCARD_E_UNSUPPORTED_FEATURE;
|
|
}
|
|
|
|
-static LONG smartcard_GetReaderIcon_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_GetReaderIcon_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -524,7 +526,7 @@ static LONG smartcard_GetReaderIcon_Decode(wStream* s, SMARTCARD_OPERATION* oper
|
|
return status;
|
|
}
|
|
|
|
-static LONG smartcard_GetDeviceTypeId_Decode(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+static LONG smartcard_GetDeviceTypeId_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
|
|
@@ -538,6 +540,12 @@ static LONG smartcard_GetDeviceTypeId_Decode(wStream* s, SMARTCARD_OPERATION* op
|
|
|
|
LONG smartcard_irp_device_control_decode(wStream* s, UINT32 CompletionId, UINT32 FileId,
|
|
SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ return smartcard_irp_device_control_decode_request(s, CompletionId, FileId, operation);
|
|
+}
|
|
+
|
|
+LONG smartcard_irp_device_control_decode_request(wStream* s, UINT32 CompletionId, UINT32 FileId,
|
|
+ SMARTCARD_OPERATION* operation)
|
|
{
|
|
LONG status = 0;
|
|
UINT32 offset = 0;
|
|
@@ -584,195 +592,195 @@ LONG smartcard_irp_device_control_decode(wStream* s, UINT32 CompletionId, UINT32
|
|
switch (ioControlCode)
|
|
{
|
|
case SCARD_IOCTL_ESTABLISHCONTEXT:
|
|
- status = smartcard_EstablishContext_Decode(s, operation);
|
|
+ status = smartcard_EstablishContext_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_RELEASECONTEXT:
|
|
- status = smartcard_ReleaseContext_Decode(s, operation);
|
|
+ status = smartcard_ReleaseContext_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ISVALIDCONTEXT:
|
|
- status = smartcard_IsValidContext_Decode(s, operation);
|
|
+ status = smartcard_IsValidContext_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LISTREADERGROUPSA:
|
|
- status = smartcard_ListReaderGroupsA_Decode(s, operation);
|
|
+ status = smartcard_ListReaderGroupsA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LISTREADERGROUPSW:
|
|
- status = smartcard_ListReaderGroupsW_Decode(s, operation);
|
|
+ status = smartcard_ListReaderGroupsW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LISTREADERSA:
|
|
- status = smartcard_ListReadersA_Decode(s, operation);
|
|
+ status = smartcard_ListReadersA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LISTREADERSW:
|
|
- status = smartcard_ListReadersW_Decode(s, operation);
|
|
+ status = smartcard_ListReadersW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPA:
|
|
- status = smartcard_context_and_string_a_Decode(s, operation);
|
|
+ status = smartcard_ContextAndStringA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPW:
|
|
- status = smartcard_context_and_string_w_Decode(s, operation);
|
|
+ status = smartcard_ContextAndStringW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPA:
|
|
- status = smartcard_context_and_string_a_Decode(s, operation);
|
|
+ status = smartcard_ContextAndStringA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPW:
|
|
- status = smartcard_context_and_string_w_Decode(s, operation);
|
|
+ status = smartcard_ContextAndStringW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERA:
|
|
- status = smartcard_context_and_two_strings_a_Decode(s, operation);
|
|
+ status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERW:
|
|
- status = smartcard_context_and_two_strings_w_Decode(s, operation);
|
|
+ status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERA:
|
|
- status = smartcard_context_and_string_a_Decode(s, operation);
|
|
+ status = smartcard_ContextAndStringA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_FORGETREADERW:
|
|
- status = smartcard_context_and_string_w_Decode(s, operation);
|
|
+ status = smartcard_ContextAndStringW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPA:
|
|
- status = smartcard_context_and_two_strings_a_Decode(s, operation);
|
|
+ status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPW:
|
|
- status = smartcard_context_and_two_strings_w_Decode(s, operation);
|
|
+ status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
|
|
- status = smartcard_context_and_two_strings_a_Decode(s, operation);
|
|
+ status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
|
|
- status = smartcard_context_and_two_strings_w_Decode(s, operation);
|
|
+ status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LOCATECARDSA:
|
|
- status = smartcard_LocateCardsA_Decode(s, operation);
|
|
+ status = smartcard_LocateCardsA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LOCATECARDSW:
|
|
- status = smartcard_LocateCardsW_Decode(s, operation);
|
|
+ status = smartcard_LocateCardsW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETSTATUSCHANGEA:
|
|
- status = smartcard_GetStatusChangeA_Decode(s, operation);
|
|
+ status = smartcard_GetStatusChangeA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETSTATUSCHANGEW:
|
|
- status = smartcard_GetStatusChangeW_Decode(s, operation);
|
|
+ status = smartcard_GetStatusChangeW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_CANCEL:
|
|
- status = smartcard_Cancel_Decode(s, operation);
|
|
+ status = smartcard_Cancel_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_CONNECTA:
|
|
- status = smartcard_ConnectA_Decode(s, operation);
|
|
+ status = smartcard_ConnectA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_CONNECTW:
|
|
- status = smartcard_ConnectW_Decode(s, operation);
|
|
+ status = smartcard_ConnectW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_RECONNECT:
|
|
- status = smartcard_Reconnect_Decode(s, operation);
|
|
+ status = smartcard_Reconnect_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_DISCONNECT:
|
|
- status = smartcard_Disconnect_Decode(s, operation);
|
|
+ status = smartcard_Disconnect_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_BEGINTRANSACTION:
|
|
- status = smartcard_BeginTransaction_Decode(s, operation);
|
|
+ status = smartcard_BeginTransaction_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ENDTRANSACTION:
|
|
- status = smartcard_EndTransaction_Decode(s, operation);
|
|
+ status = smartcard_EndTransaction_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_STATE:
|
|
- status = smartcard_State_Decode(s, operation);
|
|
+ status = smartcard_State_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_STATUSA:
|
|
- status = smartcard_StatusA_Decode(s, operation);
|
|
+ status = smartcard_StatusA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_STATUSW:
|
|
- status = smartcard_StatusW_Decode(s, operation);
|
|
+ status = smartcard_StatusW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_TRANSMIT:
|
|
- status = smartcard_Transmit_Decode(s, operation);
|
|
+ status = smartcard_Transmit_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_CONTROL:
|
|
- status = smartcard_Control_Decode(s, operation);
|
|
+ status = smartcard_Control_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETATTRIB:
|
|
- status = smartcard_GetAttrib_Decode(s, operation);
|
|
+ status = smartcard_GetAttrib_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_SETATTRIB:
|
|
- status = smartcard_SetAttrib_Decode(s, operation);
|
|
+ status = smartcard_SetAttrib_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_ACCESSSTARTEDEVENT:
|
|
- status = smartcard_AccessStartedEvent_Decode(s, operation);
|
|
+ status = smartcard_AccessStartedEvent_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LOCATECARDSBYATRA:
|
|
- status = smartcard_LocateCardsByATRA_Decode(s, operation);
|
|
+ status = smartcard_LocateCardsByATRA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_LOCATECARDSBYATRW:
|
|
- status = smartcard_LocateCardsByATRW_Decode(s, operation);
|
|
+ status = smartcard_LocateCardsByATRW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_READCACHEA:
|
|
- status = smartcard_ReadCacheA_Decode(s, operation);
|
|
+ status = smartcard_ReadCacheA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_READCACHEW:
|
|
- status = smartcard_ReadCacheW_Decode(s, operation);
|
|
+ status = smartcard_ReadCacheW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_WRITECACHEA:
|
|
- status = smartcard_WriteCacheA_Decode(s, operation);
|
|
+ status = smartcard_WriteCacheA_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_WRITECACHEW:
|
|
- status = smartcard_WriteCacheW_Decode(s, operation);
|
|
+ status = smartcard_WriteCacheW_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETTRANSMITCOUNT:
|
|
- status = smartcard_GetTransmitCount_Decode(s, operation);
|
|
+ status = smartcard_GetTransmitCount_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_RELEASETARTEDEVENT:
|
|
- status = smartcard_ReleaseStartedEvent_Decode(s, operation);
|
|
+ status = smartcard_ReleaseStartedEvent_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETREADERICON:
|
|
- status = smartcard_GetReaderIcon_Decode(s, operation);
|
|
+ status = smartcard_GetReaderIcon_decode_request(s, operation);
|
|
break;
|
|
|
|
case SCARD_IOCTL_GETDEVICETYPEID:
|
|
- status = smartcard_GetDeviceTypeId_Decode(s, operation);
|
|
+ status = smartcard_GetDeviceTypeId_decode_request(s, operation);
|
|
break;
|
|
|
|
default:
|
|
diff --git a/server/proxy/channels/pf_channel_smartcard.c b/server/proxy/channels/pf_channel_smartcard.c
|
|
index 3bd9360bb0c7..a69dc55b9250 100644
|
|
--- a/server/proxy/channels/pf_channel_smartcard.c
|
|
+++ b/server/proxy/channels/pf_channel_smartcard.c
|
|
@@ -214,7 +214,7 @@ BOOL pf_channel_smartcard_client_handle(wLog* log, pClientContext* pc, wStream*
|
|
return FALSE;
|
|
}
|
|
|
|
- status = smartcard_irp_device_control_decode(s, CompletionId, FileId, &e.op);
|
|
+ status = smartcard_irp_device_control_decode_request(s, CompletionId, FileId, &e.op);
|
|
if (status != 0)
|
|
goto fail;
|
|
|
|
|
|
From 6efff92ae960647bd48afb1c0e913610a1768f81 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Thu, 14 May 2026 13:02:38 +0200
|
|
Subject: [PATCH 05/31] [utils,smartcard] remove extra line breaks in
|
|
smartcard_operation_free
|
|
|
|
In the switch some entries had line breaks and others didn't.
|
|
This ensures there's a consistent style.
|
|
---
|
|
libfreerdp/utils/smartcard_operations.c | 9 ---------
|
|
1 file changed, 9 deletions(-)
|
|
|
|
diff --git a/libfreerdp/utils/smartcard_operations.c b/libfreerdp/utils/smartcard_operations.c
|
|
index a56e4e23c3f0..61c5761a41f6 100644
|
|
--- a/libfreerdp/utils/smartcard_operations.c
|
|
+++ b/libfreerdp/utils/smartcard_operations.c
|
|
@@ -871,7 +871,6 @@ void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
|
|
case SCARD_IOCTL_GETATTRIB:
|
|
case SCARD_IOCTL_GETTRANSMITCOUNT:
|
|
break;
|
|
-
|
|
case SCARD_IOCTL_LOCATECARDSA:
|
|
{
|
|
LocateCardsA_Call* call = &op->call.locateCardsA;
|
|
@@ -888,7 +887,6 @@ void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
|
|
free_reader_states_w(call->rgReaderStates, call->cReaders);
|
|
}
|
|
break;
|
|
-
|
|
case SCARD_IOCTL_LOCATECARDSBYATRA:
|
|
{
|
|
LocateCardsByATRA_Call* call = &op->call.locateCardsByATRA;
|
|
@@ -910,7 +908,6 @@ void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
|
|
free(call->sz);
|
|
}
|
|
break;
|
|
-
|
|
case SCARD_IOCTL_FORGETREADERW:
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPW:
|
|
case SCARD_IOCTL_FORGETREADERGROUPW:
|
|
@@ -919,29 +916,24 @@ void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
|
|
free(call->sz);
|
|
}
|
|
break;
|
|
-
|
|
case SCARD_IOCTL_INTRODUCEREADERA:
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
|
|
case SCARD_IOCTL_ADDREADERTOGROUPA:
|
|
-
|
|
{
|
|
ContextAndTwoStringA_Call* call = &op->call.contextAndTwoStringA;
|
|
free(call->sz1);
|
|
free(call->sz2);
|
|
}
|
|
break;
|
|
-
|
|
case SCARD_IOCTL_INTRODUCEREADERW:
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
|
|
case SCARD_IOCTL_ADDREADERTOGROUPW:
|
|
-
|
|
{
|
|
ContextAndTwoStringW_Call* call = &op->call.contextAndTwoStringW;
|
|
free(call->sz1);
|
|
free(call->sz2);
|
|
}
|
|
break;
|
|
-
|
|
case SCARD_IOCTL_LISTREADERSA:
|
|
case SCARD_IOCTL_LISTREADERSW:
|
|
{
|
|
@@ -955,7 +947,6 @@ void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
|
|
free_reader_states_a(call->rgReaderStates, call->cReaders);
|
|
}
|
|
break;
|
|
-
|
|
case SCARD_IOCTL_GETSTATUSCHANGEW:
|
|
{
|
|
GetStatusChangeW_Call* call = &op->call.getStatusChangeW;
|
|
|
|
From ed6f3bc1306313f94acc694d60686f2278a3fdb5 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Wed, 13 May 2026 12:34:46 +0200
|
|
Subject: [PATCH 06/31] [utils,smartcard] document smartcard_pack.h public API
|
|
|
|
Add comments to all public functions describing parameters, return
|
|
values and stream positioning, preparing for additional unpack methods.
|
|
|
|
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
---
|
|
include/freerdp/utils/smartcard_pack.h | 315 ++++++++++++++++++++++++-
|
|
1 file changed, 313 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/include/freerdp/utils/smartcard_pack.h b/include/freerdp/utils/smartcard_pack.h
|
|
index 4dc31b4a1a64..96cae2387abb 100644
|
|
--- a/include/freerdp/utils/smartcard_pack.h
|
|
+++ b/include/freerdp/utils/smartcard_pack.h
|
|
@@ -39,197 +39,508 @@ extern "C"
|
|
{
|
|
#endif
|
|
|
|
+ /** @brief Write adding bytes to align to \p alignment.
|
|
+ * @param s Stream to write padding into.
|
|
+ * @param size Number of data bytes written so far.
|
|
+ * @param alignment Required alignment boundary.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_write_size_align(wStream* s, size_t size, UINT32 alignment);
|
|
|
|
+ /** @brief Read and skip padding bytes to align to \p alignment.
|
|
+ * @param s Stream to read padding from.
|
|
+ * @param size Number of data bytes read so far.
|
|
+ * @param alignment Required alignment boundary.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_read_size_align(wStream* s, size_t size, UINT32 alignment);
|
|
|
|
+ /** @brief Convert a REDIR_SCARDCONTEXT to a native SCARDCONTEXT.
|
|
+ * @param context The redirected context to convert.
|
|
+ * @return The native SCARDCONTEXT value.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API SCARDCONTEXT smartcard_scard_context_native_from_redir(REDIR_SCARDCONTEXT* context);
|
|
+
|
|
+ /** @brief Convert a native SCARDCONTEXT to a REDIR_SCARDCONTEXT.
|
|
+ * @param context [out] The redirected context to populate.
|
|
+ * @param hContext The native SCARDCONTEXT value.
|
|
+ */
|
|
FREERDP_API void smartcard_scard_context_native_to_redir(REDIR_SCARDCONTEXT* context,
|
|
SCARDCONTEXT hContext);
|
|
|
|
+ /** @brief Convert a REDIR_SCARDHANDLE to a native SCARDHANDLE.
|
|
+ * @param handle The redirected handle to convert.
|
|
+ * @return The native SCARDHANDLE value.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API SCARDHANDLE smartcard_scard_handle_native_from_redir(REDIR_SCARDHANDLE* handle);
|
|
+
|
|
+ /** @brief Convert a native SCARDHANDLE to a REDIR_SCARDHANDLE.
|
|
+ * @param handle [out] The redirected handle to populate.
|
|
+ * @param hCard The native SCARDHANDLE value.
|
|
+ */
|
|
FREERDP_API void smartcard_scard_handle_native_to_redir(REDIR_SCARDHANDLE* handle,
|
|
SCARDHANDLE hCard);
|
|
|
|
+ /** @brief Unpack the Common Type Header [MS-RPCE] from a stream.
|
|
+ * @param s Stream to read from.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_common_type_header(wStream* s);
|
|
+
|
|
+ /** @brief Pack the Common Type Header [MS-RPCE] into a stream.
|
|
+ * @param s Stream to write into.
|
|
+ */
|
|
FREERDP_API void smartcard_pack_common_type_header(wStream* s);
|
|
|
|
+ /** @brief Unpack the Private Type Header [MS-RPCE] from a stream.
|
|
+ * @param s Stream to read from.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_private_type_header(wStream* s);
|
|
+
|
|
+ /** @brief Pack the Private Type Header [MS-RPCE] into a stream.
|
|
+ * @param s Stream to write into.
|
|
+ * @param objectBufferLength Length of the payload following this header.
|
|
+ */
|
|
FREERDP_API void smartcard_pack_private_type_header(wStream* s, UINT32 objectBufferLength);
|
|
|
|
+ /** @brief Unpack an EstablishContext_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded EstablishContext_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_establish_context_call(wStream* s,
|
|
EstablishContext_Call* call);
|
|
|
|
+ /** @brief Pack an EstablishContext_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The EstablishContext_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_establish_context_return(wStream* s,
|
|
const EstablishContext_Return* ret);
|
|
|
|
+ /** @brief Unpack a Context_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded Context_Call.
|
|
+ * @param name Operation name used for trace logging.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_context_call(wStream* s, Context_Call* call,
|
|
const char* name);
|
|
|
|
+ /** @brief Log a Long_Return for tracing purposes.
|
|
+ * @param ret The Long_Return to trace.
|
|
+ * @param name Operation name used for the log message.
|
|
+ */
|
|
FREERDP_API void smartcard_trace_long_return(const Long_Return* ret, const char* name);
|
|
|
|
+ /** @brief Unpack a ListReaderGroups_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ListReaderGroups_Call.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_list_reader_groups_call(wStream* s,
|
|
ListReaderGroups_Call* call,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Pack a ListReaderGroups_Return into a stream.
|
|
+ * @param s Stream positioned after the the Common/Private Type Headers and the
|
|
+ * ReturnCode.
|
|
+ * @param ret The ListReaderGroups_Return to encode.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_list_reader_groups_return(wStream* s,
|
|
const ListReaderGroups_Return* ret,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Unpack a ListReaders_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ListReaders_Call.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Pack a ListReaders_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the
|
|
+ * ReturnCode.
|
|
+ * @param ret The ListReaders_Return to encode.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_list_readers_return(wStream* s, const ListReaders_Return* ret,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Unpack a ContextAndTwoStringA_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ContextAndTwoStringA_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG
|
|
smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call);
|
|
|
|
+ /** @brief Unpack a ContextAndTwoStringW_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ContextAndTwoStringW_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG
|
|
smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call);
|
|
|
|
+ /** @brief Unpack a ContextAndStringA_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ContextAndStringA_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_context_and_string_a_call(wStream* s,
|
|
ContextAndStringA_Call* call);
|
|
|
|
+ /** @brief Unpack a ContextAndStringW_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ContextAndStringW_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_context_and_string_w_call(wStream* s,
|
|
ContextAndStringW_Call* call);
|
|
|
|
+ /** @brief Unpack a LocateCardsA_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded LocateCardsA_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call);
|
|
|
|
+ /** @brief Pack a LocateCards_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The LocateCards_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret);
|
|
|
|
+ /** @brief Unpack a LocateCardsW_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded LocateCardsW_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call);
|
|
|
|
+ /** @brief Pack a LocateCardsW return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The LocateCards_Return containing the return data to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
- FREERDP_API LONG smartcard_pack_locate_cards_w_return(wStream* s, const LocateCardsW_Call* ret);
|
|
+ FREERDP_API LONG smartcard_pack_locate_cards_w_return(wStream* s,
|
|
+ const LocateCards_Return* ret);
|
|
|
|
+ /** @brief Unpack a ConnectA_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ConnectA_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_connect_a_call(wStream* s, ConnectA_Call* call);
|
|
|
|
+ /** @brief Unpack a ConnectW_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ConnectW_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_connect_w_call(wStream* s, ConnectW_Call* call);
|
|
|
|
+ /** @brief Pack a Connect_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The Connect_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret);
|
|
|
|
+ /** @brief Unpack a Reconnect_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded Reconnect_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call);
|
|
|
|
+ /** @brief Pack a Reconnect_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The Reconnect_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret);
|
|
|
|
+ /** @brief Unpack a HCardAndDisposition_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded HCardAndDisposition_Call.
|
|
+ * @param name Operation name used for trace logging.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_hcard_and_disposition_call(wStream* s,
|
|
HCardAndDisposition_Call* call,
|
|
const char* name);
|
|
|
|
+ /** @brief Unpack a GetStatusChangeA_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded GetStatusChangeA_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_get_status_change_a_call(wStream* s,
|
|
GetStatusChangeA_Call* call);
|
|
|
|
+ /** @brief Unpack a GetStatusChangeW_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded GetStatusChangeW_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_get_status_change_w_call(wStream* s,
|
|
GetStatusChangeW_Call* call);
|
|
|
|
+ /** @brief Pack a GetStatusChange_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the
|
|
+ * ReturnCode.
|
|
+ * @param ret The GetStatusChange_Return to encode.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_get_status_change_return(wStream* s,
|
|
const GetStatusChange_Return* ret,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Unpack a State_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded State_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_state_call(wStream* s, State_Call* call);
|
|
+
|
|
+ /** @brief Pack a State_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The State_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_state_return(wStream* s, const State_Return* ret);
|
|
|
|
+ /** @brief Unpack a Status_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded Status_Call.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode);
|
|
|
|
+ /** @brief Pack a Status_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the
|
|
+ * ReturnCode.
|
|
+ * @param ret The Status_Return to encode.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Unpack a GetAttrib_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded GetAttrib_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call);
|
|
|
|
+ /** @brief Pack a GetAttrib_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the
|
|
+ * ReturnCode.
|
|
+ * @param ret The GetAttrib_Return to encode.
|
|
+ * @param dwAttrId The attribute ID from the original request.
|
|
+ * @param cbAttrCallLen The cbAttrLen from the original request.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret,
|
|
DWORD dwAttrId, DWORD cbAttrCallLen);
|
|
|
|
+ /** @brief Unpack a SetAttrib_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded SetAttrib_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call);
|
|
|
|
+ /** @brief Unpack a Control_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded Control_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_control_call(wStream* s, Control_Call* call);
|
|
|
|
+ /** @brief Pack a Control_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The Control_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret);
|
|
|
|
+ /** @brief Unpack a Transmit_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded Transmit_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call);
|
|
|
|
+ /** @brief Pack a Transmit_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The Transmit_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret);
|
|
|
|
+ /** @brief Unpack a LocateCardsByATRA_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded LocateCardsByATRA_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s,
|
|
LocateCardsByATRA_Call* call);
|
|
|
|
+ /** @brief Unpack a LocateCardsByATRW_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded LocateCardsByATRW_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s,
|
|
LocateCardsByATRW_Call* call);
|
|
|
|
+ /** @brief Unpack a ReadCacheA_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ReadCacheA_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call);
|
|
|
|
+ /** @brief Unpack a ReadCacheW_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded ReadCacheW_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call);
|
|
|
|
+ /** @brief Pack a ReadCache_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The ReadCache_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret);
|
|
|
|
+ /** @brief Unpack a WriteCacheA_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded WriteCacheA_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call);
|
|
|
|
+ /** @brief Unpack a WriteCacheW_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded WriteCacheW_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call);
|
|
|
|
+ /** @brief Unpack a GetTransmitCount_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded GetTransmitCount_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_get_transmit_count_call(wStream* s,
|
|
GetTransmitCount_Call* call);
|
|
+
|
|
+ /** @brief Pack a GetTransmitCount_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The GetTransmitCount_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_get_transmit_count_return(wStream* s,
|
|
- const GetTransmitCount_Return* call);
|
|
+ const GetTransmitCount_Return* ret);
|
|
|
|
+ /** @brief Unpack a GetReaderIcon_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded GetReaderIcon_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call);
|
|
+
|
|
+ /** @brief Pack a GetReaderIcon_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The GetReaderIcon_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_get_reader_icon_return(wStream* s,
|
|
const GetReaderIcon_Return* ret);
|
|
|
|
+ /** @brief Unpack a GetDeviceTypeId_Call from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call [out] The decoded GetDeviceTypeId_Call.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_get_device_type_id_call(wStream* s,
|
|
GetDeviceTypeId_Call* call);
|
|
|
|
+ /** @brief Pack a GetDeviceTypeId_Return into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret The GetDeviceTypeId_Return to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ */
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_device_type_id_return(wStream* s,
|
|
const GetDeviceTypeId_Return* ret);
|
|
|
|
From 4374e3045325e5587ca18e35dca1e6fb14aa7382 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Fri, 12 Jun 2026 21:29:42 +0200
|
|
Subject: [PATCH 07/31] [utils,smartcard] fix NDR write alignment to use byte
|
|
count instead of element count
|
|
|
|
---
|
|
libfreerdp/utils/smartcard_pack.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/libfreerdp/utils/smartcard_pack.c b/libfreerdp/utils/smartcard_pack.c
|
|
index 83d1fbd4a384..b978e2fb8209 100644
|
|
--- a/libfreerdp/utils/smartcard_pack.c
|
|
+++ b/libfreerdp/utils/smartcard_pack.c
|
|
@@ -286,7 +286,7 @@ static LONG smartcard_ndr_write(wStream* s, const BYTE* data, UINT32 size, UINT3
|
|
Stream_Write(s, data, dataLen);
|
|
else
|
|
Stream_Zero(s, dataLen);
|
|
- return smartcard_pack_write_size_align(s, len, 4);
|
|
+ return smartcard_pack_write_size_align(s, dataLen, 4);
|
|
}
|
|
|
|
static LONG smartcard_ndr_write_state(wStream* s, const ReaderState_Return* data, UINT32 size,
|
|
|
|
From 24ff58507f09ca7d1c5ca806500433254d94b232 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Wed, 13 May 2026 12:34:46 +0200
|
|
Subject: [PATCH 08/31] [utils,smartcard] add pack and unpack helpers for
|
|
MS-RDPESC messages
|
|
|
|
Add pack_call and unpack_return functions for smartcard IOCTL messages
|
|
defined in the Smart Card Virtual Channel Extension (MS-RDPESC).
|
|
These messages are wrapped in device control requests and responses.
|
|
|
|
Co-authored-by: David Fort <contact@hardening-consulting.com>
|
|
---
|
|
include/freerdp/utils/smartcard_pack.h | 249 +++++++
|
|
libfreerdp/utils/smartcard_pack.c | 961 ++++++++++++++++++++++++-
|
|
2 files changed, 1206 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/include/freerdp/utils/smartcard_pack.h b/include/freerdp/utils/smartcard_pack.h
|
|
index 96cae2387abb..040db784be39 100644
|
|
--- a/include/freerdp/utils/smartcard_pack.h
|
|
+++ b/include/freerdp/utils/smartcard_pack.h
|
|
@@ -119,6 +119,16 @@ extern "C"
|
|
FREERDP_API LONG smartcard_unpack_establish_context_call(wStream* s,
|
|
EstablishContext_Call* call);
|
|
|
|
+ /** @brief Pack an EstablishContext_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The EstablishContext_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_establish_context_call(wStream* s,
|
|
+ const EstablishContext_Call* call);
|
|
+
|
|
/** @brief Pack an EstablishContext_Return into a stream.
|
|
* @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
* @param ret The EstablishContext_Return to encode.
|
|
@@ -128,6 +138,16 @@ extern "C"
|
|
FREERDP_API LONG smartcard_pack_establish_context_return(wStream* s,
|
|
const EstablishContext_Return* ret);
|
|
|
|
+ /** @brief Unpack an EstablishContext_Return from a stream.
|
|
+ * @param s Stream positioned after the the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded EstablishContext_Return.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_establish_context_return(wStream* s,
|
|
+ EstablishContext_Return* ret);
|
|
+
|
|
/** @brief Unpack a Context_Call from a stream.
|
|
* @param s Stream positioned after the Common/Private Type Headers.
|
|
* @param call [out] The decoded Context_Call.
|
|
@@ -155,6 +175,18 @@ extern "C"
|
|
ListReaderGroups_Call* call,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Pack a ListReaderGroups_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The ListReaderGroups_Call to encode.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_list_reader_groups_call(wStream* s,
|
|
+ const ListReaderGroups_Call* call,
|
|
+ BOOL unicode);
|
|
+
|
|
/** @brief Pack a ListReaderGroups_Return into a stream.
|
|
* @param s Stream positioned after the the Common/Private Type Headers and the
|
|
* ReturnCode.
|
|
@@ -167,6 +199,18 @@ extern "C"
|
|
const ListReaderGroups_Return* ret,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Unpack a ListReaderGroups_Return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded ListReaderGroups_Return.
|
|
+ * @param unicode TRUE for the W variant, FALSE for the A variant.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_list_reader_groups_return(wStream* s,
|
|
+ ListReaderGroups_Return* ret,
|
|
+ BOOL unicode);
|
|
+
|
|
/** @brief Unpack a ListReaders_Call from a stream.
|
|
* @param s Stream positioned after the Common/Private Type Headers.
|
|
* @param call [out] The decoded ListReaders_Call.
|
|
@@ -281,6 +325,33 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret);
|
|
|
|
+ /** @brief Unpack a Connect_Return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded Connect_Return.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_connect_return(wStream* s, Connect_Return* ret);
|
|
+
|
|
+ /** @brief Pack a Control_Call into a stream.
|
|
+ * @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param call The Control_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_control_call(wStream* s, const Control_Call* call);
|
|
+
|
|
+ /** @brief Unpack a Control_return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param ret [out] the decoded Control_Return.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_control_return(wStream* s, Control_Return* ret);
|
|
+
|
|
/** @brief Unpack a Reconnect_Call from a stream.
|
|
* @param s Stream positioned after the Common/Private Type Headers.
|
|
* @param call [out] The decoded Reconnect_Call.
|
|
@@ -289,6 +360,15 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call);
|
|
|
|
+ /** @brief Pack a Reconnect_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The Reconnect_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_reconnect_call(wStream* s, const Reconnect_Call* call);
|
|
+
|
|
/** @brief Pack a Reconnect_Return into a stream.
|
|
* @param s Stream to write into after the Common/Private Type Headers and the ReturnCode.
|
|
* @param ret The Reconnect_Return to encode.
|
|
@@ -297,6 +377,15 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret);
|
|
|
|
+ /** @brief Unpack a Reconnect_Return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded Reconnect_Return.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_reconnect_return(wStream* s, Reconnect_Return* ret);
|
|
+
|
|
/** @brief Unpack a HCardAndDisposition_Call from a stream.
|
|
* @param s Stream positioned after the Common/Private Type Headers.
|
|
* @param call [out] The decoded HCardAndDisposition_Call.
|
|
@@ -363,6 +452,16 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode);
|
|
|
|
+ /** @brief Pack a Status_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The Status_Call to encode.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_status_call(wStream* s, const Status_Call* call, BOOL unicode);
|
|
+
|
|
/** @brief Pack a Status_Return into a stream.
|
|
* @param s Stream to write into after the Common/Private Type Headers and the
|
|
* ReturnCode.
|
|
@@ -374,6 +473,16 @@ extern "C"
|
|
FREERDP_API LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret,
|
|
BOOL unicode);
|
|
|
|
+ /** @brief Unpack a Status_Return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded Status_Return.
|
|
+ * @param unicode TRUE for the W variant, FALSE for the A variant.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_status_return(wStream* s, Status_Return* ret, BOOL unicode);
|
|
+
|
|
/** @brief Unpack a GetAttrib_Call from a stream.
|
|
* @param s Stream positioned after the Common/Private Type Headers.
|
|
* @param call [out] The decoded GetAttrib_Call.
|
|
@@ -382,6 +491,15 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call);
|
|
|
|
+ /** @brief Pack a GetAttrib_Call to a stream.
|
|
+ * @param s wStream to write to.
|
|
+ * @param call The GetAttrib_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_get_attrib_call(wStream* s, const GetAttrib_Call* call);
|
|
+
|
|
/** @brief Pack a GetAttrib_Return into a stream.
|
|
* @param s Stream to write into after the Common/Private Type Headers and the
|
|
* ReturnCode.
|
|
@@ -394,6 +512,15 @@ extern "C"
|
|
FREERDP_API LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret,
|
|
DWORD dwAttrId, DWORD cbAttrCallLen);
|
|
|
|
+ /** @brief Unpack a GetAttrib_Return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded GetAttrib_Return.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_get_attrib_return(wStream* s, GetAttrib_Return* ret);
|
|
+
|
|
/** @brief Unpack a SetAttrib_Call from a stream.
|
|
* @param s Stream positioned after the Common/Private Type Headers.
|
|
* @param call [out] The decoded SetAttrib_Call.
|
|
@@ -402,6 +529,15 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call);
|
|
|
|
+ /** @brief Pack a SetAttrib_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The SetAttrib_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_set_attrib_call(wStream* s, const SetAttrib_Call* call);
|
|
+
|
|
/** @brief Unpack a Control_Call from a stream.
|
|
* @param s Stream positioned after the Common/Private Type Headers.
|
|
* @param call [out] The decoded Control_Call.
|
|
@@ -434,6 +570,15 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret);
|
|
|
|
+ /** @brief Unpack a Transmit_Return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded Transmit_Return.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_transmit_return(wStream* s, Transmit_Return* ret);
|
|
+
|
|
/** @brief Unpack a LocateCardsByATRA_Call from a stream.
|
|
* @param s Stream positioned after the Common/Private Type Headers.
|
|
* @param call [out] The decoded LocateCardsByATRA_Call.
|
|
@@ -545,6 +690,110 @@ extern "C"
|
|
FREERDP_API LONG smartcard_pack_device_type_id_return(wStream* s,
|
|
const GetDeviceTypeId_Return* ret);
|
|
|
|
+ /** @brief Pack a Context_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The Context_Call to encode.
|
|
+ * @param name Operation name used for trace logging.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_context_call(wStream* s, const Context_Call* call,
|
|
+ const char* name);
|
|
+
|
|
+ /** @brief Pack a ListReaders_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The ListReaders_Call to encode.
|
|
+ * @param unicode TRUE for wide-char (W) variant, FALSE for ANSI (A).
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_list_readers_call(wStream* s, const ListReaders_Call* call,
|
|
+ BOOL unicode);
|
|
+
|
|
+ /** @brief Pack a GetStatusChangeA_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The GetStatusChangeA_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_get_status_change_a_call(wStream* s,
|
|
+ const GetStatusChangeA_Call* call);
|
|
+
|
|
+ /** @brief Pack a GetStatusChangeW_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The GetStatusChangeW_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_get_status_change_w_call(wStream* s,
|
|
+ const GetStatusChangeW_Call* call);
|
|
+
|
|
+ /** @brief Pack a ConnectA_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The ConnectA_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_connect_a_call(wStream* s, const ConnectA_Call* call);
|
|
+
|
|
+ /** @brief Pack a ConnectW_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The ConnectW_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_connect_w_call(wStream* s, const ConnectW_Call* call);
|
|
+
|
|
+ /** @brief Pack a HCardAndDisposition_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The HCardAndDisposition_Call to encode.
|
|
+ * @param name Operation name used for trace logging.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_hcard_and_disposition_call(wStream* s,
|
|
+ const HCardAndDisposition_Call* call,
|
|
+ const char* name);
|
|
+
|
|
+ /** @brief Pack a Transmit_Call into a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers.
|
|
+ * @param call The Transmit_Call to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_pack_transmit_call(wStream* s, const Transmit_Call* call);
|
|
+
|
|
+ /** @brief Unpack a ListReaders_Return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded ListReaders_Return.
|
|
+ * @param unicode TRUE for the W variant, FALSE for the A variant.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_list_readers_return(wStream* s, ListReaders_Return* ret,
|
|
+ BOOL unicode);
|
|
+
|
|
+ /** @brief Unpack a GetStatusChange_Return from a stream.
|
|
+ * @param s Stream positioned after the Common/Private Type Headers and the ReturnCode.
|
|
+ * @param ret [out] The decoded GetStatusChange_Return.
|
|
+ * @param unicode TRUE for the W variant, FALSE for the A variant.
|
|
+ * @return \b SCARD_S_SUCCESS on success, an error code on failure.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_unpack_get_status_change_return(wStream* s,
|
|
+ GetStatusChange_Return* ret,
|
|
+ BOOL unicode);
|
|
+
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
diff --git a/libfreerdp/utils/smartcard_pack.c b/libfreerdp/utils/smartcard_pack.c
|
|
index b978e2fb8209..5aa54590f4fc 100644
|
|
--- a/libfreerdp/utils/smartcard_pack.c
|
|
+++ b/libfreerdp/utils/smartcard_pack.c
|
|
@@ -303,6 +303,18 @@ static LONG smartcard_ndr_write_state(wStream* s, const ReaderState_Return* data
|
|
return smartcard_ndr_write(s, cnv.data, size, sizeof(ReaderState_Return), type);
|
|
}
|
|
|
|
+static LONG smartcard_ndr_read_state(wLog* log, wStream* s, ReaderState_Return** data, size_t min,
|
|
+ ndr_ptr_t type)
|
|
+{
|
|
+ union
|
|
+ {
|
|
+ ReaderState_Return** ppc;
|
|
+ BYTE** ppv;
|
|
+ } u;
|
|
+ u.ppc = data;
|
|
+ return smartcard_ndr_read(log, s, u.ppv, min, sizeof(ReaderState_Return), type);
|
|
+}
|
|
+
|
|
static LONG smartcard_ndr_read_atrmask(wLog* log, wStream* s, LocateCards_ATRMask** data,
|
|
size_t min, ndr_ptr_t type)
|
|
{
|
|
@@ -382,6 +394,28 @@ static LONG smartcard_ndr_read_w(wLog* log, wStream* s, WCHAR** data, ndr_ptr_t
|
|
return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(WCHAR), type);
|
|
}
|
|
|
|
+static LONG smartcard_ndr_write_w(wStream* s, const WCHAR* data, UINT32 size, ndr_ptr_t type)
|
|
+{
|
|
+ union
|
|
+ {
|
|
+ const WCHAR* wz;
|
|
+ const BYTE* bp;
|
|
+ } cnv;
|
|
+ cnv.wz = data;
|
|
+ return smartcard_ndr_write(s, cnv.bp, size, sizeof(WCHAR), type);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ndr_write_a(wStream* s, const CHAR* data, UINT32 size, ndr_ptr_t type)
|
|
+{
|
|
+ union
|
|
+ {
|
|
+ const CHAR* sz;
|
|
+ const BYTE* bp;
|
|
+ } cnv;
|
|
+ cnv.sz = data;
|
|
+ return smartcard_ndr_write(s, cnv.bp, size, sizeof(CHAR), type);
|
|
+}
|
|
+
|
|
static LONG smartcard_ndr_read_u(wLog* log, wStream* s, UUID** data)
|
|
{
|
|
union
|
|
@@ -546,7 +580,7 @@ static void smartcard_dump_array(wLog* log, DWORD level, WINPR_FORMAT_ARG const
|
|
va_start(ap, len);
|
|
winpr_vasprintf(&fprefix, &flen, prefix, ap);
|
|
va_end(ap);
|
|
- WLog_Print(log, level, "%s%s%s", prefix, buffer, postfix);
|
|
+ WLog_Print(log, level, "%s%s%s", fprefix, buffer, postfix);
|
|
free(buffer);
|
|
free(fprefix);
|
|
}
|
|
@@ -554,7 +588,7 @@ static void smartcard_dump_array(wLog* log, DWORD level, WINPR_FORMAT_ARG const
|
|
static void smartcard_log_redir_handle(wLog* log, const REDIR_SCARDHANDLE* pHandle)
|
|
{
|
|
WINPR_ASSERT(pHandle);
|
|
- smartcard_dump_array(log, g_LogLevel, " hContext: ", "", pHandle->pbHandle, pHandle->cbHandle);
|
|
+ smartcard_dump_array(log, g_LogLevel, "handle: ", "", pHandle->pbHandle, pHandle->cbHandle);
|
|
}
|
|
|
|
static void smartcard_log_context(wLog* log, const REDIR_SCARDCONTEXT* phContext)
|
|
@@ -2041,6 +2075,21 @@ LONG smartcard_unpack_establish_context_call(wStream* s, EstablishContext_Call*
|
|
return SCARD_S_SUCCESS;
|
|
}
|
|
|
|
+LONG smartcard_pack_establish_context_call(wStream* s, const EstablishContext_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+
|
|
+ smartcard_trace_establish_context_call(log, call);
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 4))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->dwScope);
|
|
+
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_Return* ret)
|
|
{
|
|
WINPR_ASSERT(ret);
|
|
@@ -2059,6 +2108,26 @@ LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_
|
|
return smartcard_pack_redir_scard_context_ref(log, s, &(ret->hContext));
|
|
}
|
|
|
|
+LONG smartcard_unpack_establish_context_return(wStream* s, EstablishContext_Return* ret)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 pbContextNdrPtr = 0;
|
|
+
|
|
+ LONG status =
|
|
+ smartcard_unpack_redir_scard_context(log, s, &(ret->hContext), &index, &pbContextNdrPtr);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &(ret->hContext));
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ smartcard_trace_establish_context_return(log, ret);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
LONG smartcard_unpack_context_call(wStream* s, Context_Call* call, const char* name)
|
|
{
|
|
UINT32 index = 0;
|
|
@@ -2110,6 +2179,28 @@ LONG smartcard_unpack_list_reader_groups_call(wStream* s, ListReaderGroups_Call*
|
|
return SCARD_S_SUCCESS;
|
|
}
|
|
|
|
+LONG smartcard_pack_list_reader_groups_call(wStream* s, const ListReaderGroups_Call* call,
|
|
+ BOOL unicode)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_list_reader_groups_call(log, call, unicode);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 8))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_INT32(s, call->fmszGroupsIsNULL);
|
|
+ Stream_Write_UINT32(s, call->cchGroups);
|
|
+
|
|
+ return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+}
|
|
+
|
|
LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups_Return* ret,
|
|
BOOL unicode)
|
|
{
|
|
@@ -2138,6 +2229,33 @@ LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups
|
|
return ret->ReturnCode;
|
|
}
|
|
|
|
+LONG smartcard_unpack_list_reader_groups_return(wStream* s, ListReaderGroups_Return* ret,
|
|
+ BOOL unicode)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 mszNdrPtr = 0;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->cBytes);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ if (mszNdrPtr)
|
|
+ {
|
|
+ LONG status = smartcard_ndr_read(log, s, &ret->msz, ret->cBytes, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ smartcard_trace_list_reader_groups_return(log, ret, unicode);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call, BOOL unicode)
|
|
{
|
|
UINT32 index = 0;
|
|
@@ -2368,6 +2486,36 @@ LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call)
|
|
return status;
|
|
}
|
|
|
|
+LONG smartcard_pack_reconnect_call(wStream* s, const Reconnect_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_reconnect_call(log, call);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 12))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->dwShareMode);
|
|
+ Stream_Write_UINT32(s, call->dwPreferredProtocols);
|
|
+ Stream_Write_UINT32(s, call->dwInitialization);
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
|
|
+}
|
|
+
|
|
LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
|
|
{
|
|
WINPR_ASSERT(ret);
|
|
@@ -2380,6 +2528,20 @@ LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
|
|
return ret->ReturnCode;
|
|
}
|
|
|
|
+LONG smartcard_unpack_reconnect_return(wStream* s, Reconnect_Return* ret)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->dwActiveProtocol);
|
|
+
|
|
+ smartcard_trace_reconnect_return(log, ret);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
LONG smartcard_unpack_hcard_and_disposition_call(wStream* s, HCardAndDisposition_Call* call,
|
|
const char* name)
|
|
{
|
|
@@ -2816,6 +2978,36 @@ LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
|
|
return status;
|
|
}
|
|
|
|
+LONG smartcard_pack_status_call(wStream* s, const Status_Call* call, BOOL unicode)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_status_call(log, call, unicode);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 12))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_INT32(s, call->fmszReaderNamesIsNULL);
|
|
+ Stream_Write_UINT32(s, call->cchReaderLen);
|
|
+ Stream_Write_UINT32(s, call->cbAtrLen);
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
|
|
+}
|
|
+
|
|
LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
|
|
{
|
|
WINPR_ASSERT(ret);
|
|
@@ -2851,6 +3043,41 @@ LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL uni
|
|
return ret->ReturnCode;
|
|
}
|
|
|
|
+LONG smartcard_unpack_status_return(wStream* s, Status_Return* ret, BOOL unicode)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 mszNdrPtr = 0;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->cBytes);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 44))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->dwState);
|
|
+ Stream_Read_UINT32(s, ret->dwProtocol);
|
|
+ Stream_Read(s, ret->pbAtr, sizeof(ret->pbAtr));
|
|
+ Stream_Read_UINT32(s, ret->cbAtrLen);
|
|
+
|
|
+ if (mszNdrPtr)
|
|
+ {
|
|
+ LONG status =
|
|
+ smartcard_ndr_read(log, s, &ret->mszReaderNames, ret->cBytes, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ smartcard_trace_status_return(log, ret, unicode);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
|
|
{
|
|
WINPR_ASSERT(call);
|
|
@@ -2944,8 +3171,8 @@ LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
- Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */
|
|
- Stream_Read_UINT32(s, call->cbInBufferSize); /* cbInBufferSize (4 bytes) */
|
|
+ Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */
|
|
+ Stream_Read_UINT32(s, call->cbInBufferSize); /* cbInBufferSize (4 bytes) */
|
|
if (!smartcard_ndr_pointer_read(log, s, &index,
|
|
&pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
|
|
return ERROR_INVALID_DATA;
|
|
@@ -3557,6 +3784,46 @@ LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
|
|
return SCARD_S_SUCCESS;
|
|
}
|
|
|
|
+LONG smartcard_pack_set_attrib_call(wStream* s, const SetAttrib_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_set_attrib_call(log, call);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 8))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->dwAttrId);
|
|
+ Stream_Write_UINT32(s, call->cbAttrLen);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, call->cbAttrLen))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_ndr_write(s, call->pbAttr, call->cbAttrLen, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
|
|
{
|
|
UINT32 rgReaderStatesNdrPtr = 0;
|
|
@@ -4037,3 +4304,689 @@ LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
|
|
return status;
|
|
return ret->ReturnCode;
|
|
}
|
|
+
|
|
+LONG smartcard_pack_context_call(wStream* s, const Context_Call* call, const char* name)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_context_call(log, call, name);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_list_readers_call(wStream* s, const ListReaders_Call* call, BOOL unicode)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_list_readers_call(log, call, unicode);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 4))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->cBytes);
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, call->cBytes))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 8))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_INT32(s, call->fmszReadersIsNULL);
|
|
+ Stream_Write_UINT32(s, call->cchReaders);
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (call->cBytes > 0)
|
|
+ {
|
|
+ status = smartcard_ndr_write(s, call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+static LONG smartcard_pack_reader_state_a(wStream* s, const LPSCARD_READERSTATEA rgReaderStates,
|
|
+ UINT32 cReaders, UINT32* ptrIndex)
|
|
+{
|
|
+ WINPR_ASSERT(rgReaderStates || (cReaders == 0));
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 4))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, cReaders);
|
|
+
|
|
+ for (UINT32 i = 0; i < cReaders; i++)
|
|
+ {
|
|
+ const SCARD_READERSTATEA* state = &rgReaderStates[i];
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 52))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ const DWORD nameLen = state->szReader ? (DWORD)(strlen(state->szReader) + 1) : 0;
|
|
+ if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, state->dwCurrentState);
|
|
+ Stream_Write_UINT32(s, state->dwEventState);
|
|
+ Stream_Write_UINT32(s, state->cbAtr);
|
|
+ Stream_Write(s, state->rgbAtr, 36);
|
|
+ }
|
|
+
|
|
+ for (UINT32 i = 0; i < cReaders; i++)
|
|
+ {
|
|
+ const SCARD_READERSTATEA* state = &rgReaderStates[i];
|
|
+
|
|
+ if (state->szReader)
|
|
+ {
|
|
+ const UINT32 nameLen = (UINT32)(strlen(state->szReader) + 1);
|
|
+ LONG status = smartcard_ndr_write_a(s, state->szReader, nameLen, NDR_PTR_FULL);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+static LONG smartcard_pack_reader_state_w(wStream* s, const LPSCARD_READERSTATEW rgReaderStates,
|
|
+ UINT32 cReaders, UINT32* ptrIndex)
|
|
+{
|
|
+ WINPR_ASSERT(rgReaderStates || (cReaders == 0));
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 4))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, cReaders);
|
|
+
|
|
+ for (UINT32 i = 0; i < cReaders; i++)
|
|
+ {
|
|
+ const SCARD_READERSTATEW* state = &rgReaderStates[i];
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 52))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ const DWORD nameLen = state->szReader ? (DWORD)(_wcslen(state->szReader) + 1) : 0;
|
|
+ if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, state->dwCurrentState);
|
|
+ Stream_Write_UINT32(s, state->dwEventState);
|
|
+ Stream_Write_UINT32(s, state->cbAtr);
|
|
+ Stream_Write(s, state->rgbAtr, 36);
|
|
+ }
|
|
+
|
|
+ for (UINT32 i = 0; i < cReaders; i++)
|
|
+ {
|
|
+ const SCARD_READERSTATEW* state = &rgReaderStates[i];
|
|
+
|
|
+ if (state->szReader)
|
|
+ {
|
|
+ const UINT32 nameLen = (UINT32)(_wcslen(state->szReader) + 1);
|
|
+ LONG status = smartcard_ndr_write_w(s, state->szReader, nameLen, NDR_PTR_FULL);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_get_status_change_a_call(wStream* s, const GetStatusChangeA_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_get_status_change_a_call(log, call);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 8))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->dwTimeOut);
|
|
+ Stream_Write_UINT32(s, call->cReaders);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (call->cReaders > 0)
|
|
+ {
|
|
+ status = smartcard_pack_reader_state_a(s, call->rgReaderStates, call->cReaders, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_get_status_change_w_call(wStream* s, const GetStatusChangeW_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_get_status_change_w_call(log, call);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 8))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->dwTimeOut);
|
|
+ Stream_Write_UINT32(s, call->cReaders);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (call->cReaders > 0)
|
|
+ {
|
|
+ status = smartcard_pack_reader_state_w(s, call->rgReaderStates, call->cReaders, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_connect_a_call(wStream* s, const ConnectA_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_connect_a_call(log, call);
|
|
+
|
|
+ const DWORD readerLen = call->szReader ? (DWORD)(strlen(call->szReader) + 1) : 0;
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, readerLen))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ LONG status =
|
|
+ smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 8))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->Common.dwShareMode);
|
|
+ Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
|
|
+
|
|
+ if (call->szReader)
|
|
+ {
|
|
+ status = smartcard_ndr_write_a(s, call->szReader, readerLen, NDR_PTR_FULL);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_connect_w_call(wStream* s, const ConnectW_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_connect_w_call(log, call);
|
|
+
|
|
+ const DWORD readerLen = call->szReader ? (DWORD)(_wcslen(call->szReader) + 1) : 0;
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, readerLen))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ LONG status =
|
|
+ smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 8))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->Common.dwShareMode);
|
|
+ Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
|
|
+
|
|
+ if (call->szReader)
|
|
+ {
|
|
+ status = smartcard_ndr_write_w(s, call->szReader, readerLen, NDR_PTR_FULL);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_control_call(wStream* s, const Control_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_control_call(log, call);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 8))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->dwControlCode);
|
|
+ Stream_Write_UINT32(s, call->cbInBufferSize);
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, call->cbInBufferSize))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_INT32(s, call->fpvOutBufferIsNULL);
|
|
+ Stream_Write_UINT32(s, call->cbOutBufferSize);
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (call->cbInBufferSize)
|
|
+ {
|
|
+ status = smartcard_ndr_write(s, call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_hcard_and_disposition_call(wStream* s, const HCardAndDisposition_Call* call,
|
|
+ const char* name)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_hcard_and_disposition_call(log, call, name);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 4))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->dwDisposition);
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_transmit_call(wStream* s, const Transmit_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_transmit_call(log, call);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ UINT32 cbExtraBytes = 0;
|
|
+ const BYTE* pbExtraBytes = NULL;
|
|
+ if (call->pioSendPci)
|
|
+ {
|
|
+ cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
|
|
+ if (cbExtraBytes > 0)
|
|
+ pbExtraBytes = &((const BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
|
|
+ }
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 32))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->pioSendPci ? call->pioSendPci->dwProtocol : 0);
|
|
+ Stream_Write_UINT32(s, cbExtraBytes);
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->cbSendLength);
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, call->cbSendLength))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ const UINT32 recvPciLen = call->pioRecvPci ? (UINT32)call->pioRecvPci->cbPciLength : 0;
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, recvPciLen))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_INT32(s, call->fpbRecvBufferIsNULL);
|
|
+ Stream_Write_UINT32(s, call->cbRecvLength);
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (cbExtraBytes > 0)
|
|
+ {
|
|
+ status = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ if (call->cbSendLength > 0)
|
|
+ {
|
|
+ status = smartcard_ndr_write(s, call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ if (call->pioRecvPci && recvPciLen > 0)
|
|
+ {
|
|
+ UINT32 cbRecvExtra = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
|
|
+ const BYTE* pbRecvExtra = &((const BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 12))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->pioRecvPci->dwProtocol);
|
|
+ Stream_Write_UINT32(s, cbRecvExtra);
|
|
+ if (!smartcard_ndr_pointer_write(s, &index, cbRecvExtra))
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ if (cbRecvExtra > 0)
|
|
+ {
|
|
+ status = smartcard_ndr_write(s, pbRecvExtra, cbRecvExtra, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_pack_get_attrib_call(wStream* s, const GetAttrib_Call* call)
|
|
+{
|
|
+ WINPR_ASSERT(call);
|
|
+ wLog* log = scard_log();
|
|
+ DWORD index = 0;
|
|
+
|
|
+ smartcard_trace_get_attrib_call(log, call);
|
|
+
|
|
+ LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_EnsureRemainingCapacity(s, 12))
|
|
+ return STATUS_NO_MEMORY;
|
|
+
|
|
+ Stream_Write_UINT32(s, call->dwAttrId);
|
|
+ Stream_Write_INT32(s, call->fpbAttrIsNULL);
|
|
+ Stream_Write_UINT32(s, call->cbAttrLen);
|
|
+
|
|
+ status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
|
|
+}
|
|
+
|
|
+LONG smartcard_unpack_list_readers_return(wStream* s, ListReaders_Return* ret, BOOL unicode)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 mszNdrPtr = 0;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->cBytes);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ if (mszNdrPtr)
|
|
+ {
|
|
+ LONG status = smartcard_ndr_read(log, s, &ret->msz, ret->cBytes, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ smartcard_trace_list_readers_return(log, ret, unicode);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_unpack_get_status_change_return(wStream* s, GetStatusChange_Return* ret,
|
|
+ BOOL unicode)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 ndrPtr = 0;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->cReaders);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ if (ndrPtr && ret->cReaders > 0)
|
|
+ {
|
|
+ LONG status =
|
|
+ smartcard_ndr_read_state(log, s, &ret->rgReaderStates, ret->cReaders, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+ else
|
|
+ ret->rgReaderStates = NULL;
|
|
+
|
|
+ smartcard_trace_get_status_change_return(log, ret, unicode);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_unpack_connect_return(wStream* s, Connect_Return* ret)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 pbContextNdrPtr = 0;
|
|
+
|
|
+ LONG status =
|
|
+ smartcard_unpack_redir_scard_context(log, s, &ret->hContext, &index, &pbContextNdrPtr);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_unpack_redir_scard_handle(log, s, &ret->hCard, &index);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->dwActiveProtocol);
|
|
+
|
|
+ status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &ret->hContext);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_unpack_redir_scard_handle_ref(log, s, &ret->hCard);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ smartcard_trace_connect_return(log, ret);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_unpack_control_return(wStream* s, Control_Return* ret)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 pvOutBufferNdrPtr = 0;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->cbOutBufferSize);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &pvOutBufferNdrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ if (pvOutBufferNdrPtr && ret->cbOutBufferSize)
|
|
+ {
|
|
+ LONG status =
|
|
+ smartcard_ndr_read(log, s, &ret->pvOutBuffer, ret->cbOutBufferSize, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+ smartcard_trace_control_return(log, ret);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_unpack_transmit_return(wStream* s, Transmit_Return* ret)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 recvPciNdrPtr = 0;
|
|
+ UINT32 recvBufferNdrPtr = 0;
|
|
+
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &recvPciNdrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ Stream_Read_UINT32(s, ret->cbRecvLength);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &recvBufferNdrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ if (recvPciNdrPtr)
|
|
+ {
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ UINT32 dwProtocol = 0;
|
|
+ UINT32 cbExtraBytes = 0;
|
|
+ Stream_Read_UINT32(s, dwProtocol);
|
|
+ Stream_Read_UINT32(s, cbExtraBytes);
|
|
+
|
|
+ UINT32 pbExtraBytesNdrPtr = 0;
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &pbExtraBytesNdrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ if (pbExtraBytesNdrPtr)
|
|
+ {
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ UINT32 length = 0;
|
|
+ Stream_Read_UINT32(s, length);
|
|
+ if (length != cbExtraBytes)
|
|
+ {
|
|
+ WLog_Print(log, WLOG_WARN,
|
|
+ "Transmit_Return unexpected length: Actual: %" PRIu32
|
|
+ ", Expected: %" PRIu32 " (pioRecvPci.cbExtraBytes)",
|
|
+ length, cbExtraBytes);
|
|
+ return STATUS_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, cbExtraBytes))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
|
|
+ if (!ret->pioRecvPci)
|
|
+ return SCARD_E_NO_MEMORY;
|
|
+
|
|
+ ret->pioRecvPci->dwProtocol = dwProtocol;
|
|
+ ret->pioRecvPci->cbPciLength = (DWORD)(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
|
|
+
|
|
+ BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
|
|
+ Stream_Read(s, pbExtraBytes, length);
|
|
+ if (smartcard_unpack_read_size_align(s, cbExtraBytes, 4) < 0)
|
|
+ return STATUS_INVALID_PARAMETER;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (recvBufferNdrPtr && ret->cbRecvLength > 0)
|
|
+ {
|
|
+ LONG status =
|
|
+ smartcard_ndr_read(log, s, &ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ smartcard_trace_transmit_return(log, ret);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_unpack_get_attrib_return(wStream* s, GetAttrib_Return* ret)
|
|
+{
|
|
+ WINPR_ASSERT(ret);
|
|
+ wLog* log = scard_log();
|
|
+ UINT32 index = 0;
|
|
+ UINT32 pbAttrPtr = 0;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
|
|
+ return STATUS_BUFFER_TOO_SMALL;
|
|
+
|
|
+ ret->cbAttrLen = Stream_Get_UINT32(s);
|
|
+
|
|
+ if (!smartcard_ndr_pointer_read(log, s, &index, &pbAttrPtr))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
+ LONG status = smartcard_ndr_read(log, s, &ret->pbAttr, ret->cbAttrLen, 1, NDR_PTR_SIMPLE);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ smartcard_trace_get_attrib_return(log, ret, 0);
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
|
|
From c3cbf5dc622e1f00a3176694829c1e151135b75a Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Fri, 8 May 2026 10:44:30 +0200
|
|
Subject: [PATCH 09/31] [utils,smartcard] add decode_response for server-side
|
|
IOCTL parsing
|
|
|
|
Add smartcard_irp_device_control_decode_response as the symmetric
|
|
counterpart to decode_request. It decodes DR_CONTROL_RSP: reads
|
|
OutputBufferLength, CommonTypeHeader, PrivateTypeHeader, then dispatches
|
|
to per-IOCTL decode functions.
|
|
|
|
Add a ret union to SMARTCARD_OPERATION for decoded response data, and a
|
|
returnCode field since all smartcard IOCTL responses share a common
|
|
ReturnCode as their first field before the per-operation return data.
|
|
|
|
There are some responses that aren't supported for decoding yet.
|
|
---
|
|
include/freerdp/utils/smartcard_operations.h | 46 +++
|
|
libfreerdp/utils/smartcard_operations.c | 382 ++++++++++++++++++-
|
|
2 files changed, 427 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/include/freerdp/utils/smartcard_operations.h b/include/freerdp/utils/smartcard_operations.h
|
|
index 41a5fd6b043a..a090b64fdfad 100644
|
|
--- a/include/freerdp/utils/smartcard_operations.h
|
|
+++ b/include/freerdp/utils/smartcard_operations.h
|
|
@@ -84,6 +84,19 @@ extern "C"
|
|
SCARDHANDLE hCard;
|
|
const char* ioControlCodeName;
|
|
UINT32 outputBufferLength; /** @since version 3.13.0 */
|
|
+ union
|
|
+ {
|
|
+ EstablishContext_Return establishContext;
|
|
+ ListReaders_Return listReaders;
|
|
+ GetStatusChange_Return getStatusChange;
|
|
+ Connect_Return connect;
|
|
+ Control_Return control;
|
|
+ Transmit_Return transmit;
|
|
+ GetAttrib_Return getAttrib;
|
|
+ Reconnect_Return reconnect;
|
|
+ Status_Return status;
|
|
+ } ret; /** @since version 3.28.0 */
|
|
+ LONG returnCode; /** @since version 3.28.0 */
|
|
} SMARTCARD_OPERATION;
|
|
|
|
/** @brief Alias for \ref smartcard_irp_device_control_decode_request.
|
|
@@ -114,6 +127,39 @@ extern "C"
|
|
UINT32 FileId,
|
|
SMARTCARD_OPERATION* operation);
|
|
|
|
+ /** @brief Decode a smartcard IOCTL response received from the client.
|
|
+ *
|
|
+ * Parses the OutputBufferLength, Common Type Header, Private Type Header, and the
|
|
+ * ReturnCode, then unpacks the IOCTL-specific return payload into \p operation->ret.
|
|
+ *
|
|
+ * @param s Stream positioned at OutputBufferLength, after the DeviceIoReply
|
|
+ * header.
|
|
+ * @param ioControlCode The SCARD_IOCTL_* code identifying the response type.
|
|
+ * @param operation [out] The decoded returnCode and ret union.
|
|
+ * @return \b SCARD_S_SUCCESS on success, a smartcard error code on failure.
|
|
+ *
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG smartcard_irp_device_control_decode_response(wStream* s, UINT32 ioControlCode,
|
|
+ SMARTCARD_OPERATION* operation);
|
|
+
|
|
+ /** @brief Encode a smartcard IOCTL request to send to the client.
|
|
+ *
|
|
+ * Writes the Common Type Header, Private Type Header, and the IOCTL-specific
|
|
+ * call payload from \p operation->call into the stream. The ioControlCode field
|
|
+ * in \p operation selects which pack_call function is dispatched.
|
|
+ *
|
|
+ * @param s Stream to write into, positioned where the type headers should start.
|
|
+ * @param operation with the populated call union and ioControlCode to encode.
|
|
+ * @return \b SCARD_S_SUCCESS on success, a smartcard error code on failure.
|
|
+ *
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API LONG
|
|
+ smartcard_irp_device_control_encode_request(wStream* s, const SMARTCARD_OPERATION* operation);
|
|
+
|
|
/** @brief Free resources held by a SMARTCARD_OPERATION.
|
|
*
|
|
* Releases any memory allocated inside the call and ret unions (e.g., reader name
|
|
diff --git a/libfreerdp/utils/smartcard_operations.c b/libfreerdp/utils/smartcard_operations.c
|
|
index 61c5761a41f6..906923fc7ecc 100644
|
|
--- a/libfreerdp/utils/smartcard_operations.c
|
|
+++ b/libfreerdp/utils/smartcard_operations.c
|
|
@@ -561,7 +561,7 @@ LONG smartcard_irp_device_control_decode_request(wStream* s, UINT32 CompletionId
|
|
const UINT32 outputBufferLength = Stream_Get_UINT32(s); /* OutputBufferLength (4 bytes) */
|
|
const UINT32 inputBufferLength = Stream_Get_UINT32(s); /* InputBufferLength (4 bytes) */
|
|
const UINT32 ioControlCode = Stream_Get_UINT32(s); /* IoControlCode (4 bytes) */
|
|
- Stream_Seek(s, 20); /* Padding (20 bytes) */
|
|
+ Stream_Seek(s, 20); /* Padding (20 bytes) */
|
|
operation->ioControlCode = ioControlCode;
|
|
operation->ioControlCodeName = scard_get_ioctl_string(ioControlCode, FALSE);
|
|
operation->outputBufferLength = outputBufferLength;
|
|
@@ -825,6 +825,347 @@ LONG smartcard_irp_device_control_decode_request(wStream* s, UINT32 CompletionId
|
|
return status;
|
|
}
|
|
|
|
+static LONG smartcard_EstablishContext_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_establish_context_return(s, &operation->ret.establishContext);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ReleaseContext_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_UNUSED(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ const Long_Return ret = { .ReturnCode = operation->returnCode };
|
|
+ smartcard_trace_long_return(&ret, "ReleaseContext");
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+static LONG smartcard_IsValidContext_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_UNUSED(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ const Long_Return ret = { .ReturnCode = operation->returnCode };
|
|
+ smartcard_trace_long_return(&ret, "IsValidContext");
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+static LONG smartcard_ListReaderGroupsA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_list_reader_groups_return(s, &operation->ret.listReaders, FALSE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ListReaderGroupsW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_list_reader_groups_return(s, &operation->ret.listReaders, TRUE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ListReadersA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_list_readers_return(s, &operation->ret.listReaders, FALSE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ListReadersW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_list_readers_return(s, &operation->ret.listReaders, TRUE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_GetStatusChangeA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_get_status_change_return(s, &operation->ret.getStatusChange, FALSE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_GetStatusChangeW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_get_status_change_return(s, &operation->ret.getStatusChange, TRUE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Cancel_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_UNUSED(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ const Long_Return ret = { .ReturnCode = operation->returnCode };
|
|
+ smartcard_trace_long_return(&ret, "Cancel");
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+static LONG smartcard_ConnectA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_connect_return(s, &operation->ret.connect);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ConnectW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_connect_return(s, &operation->ret.connect);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Reconnect_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_reconnect_return(s, &operation->ret.reconnect);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Disconnect_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_UNUSED(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ const Long_Return ret = { .ReturnCode = operation->returnCode };
|
|
+ smartcard_trace_long_return(&ret, "Disconnect");
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+static LONG smartcard_BeginTransaction_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_UNUSED(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ const Long_Return ret = { .ReturnCode = operation->returnCode };
|
|
+ smartcard_trace_long_return(&ret, "BeginTransaction");
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+static LONG smartcard_EndTransaction_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_UNUSED(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ const Long_Return ret = { .ReturnCode = operation->returnCode };
|
|
+ smartcard_trace_long_return(&ret, "EndTransaction");
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+static LONG smartcard_StatusA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_status_return(s, &operation->ret.status, FALSE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_StatusW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_status_return(s, &operation->ret.status, TRUE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Transmit_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_transmit_return(s, &operation->ret.transmit);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Control_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_control_return(s, &operation->ret.control);
|
|
+}
|
|
+
|
|
+static LONG smartcard_GetAttrib_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_unpack_get_attrib_return(s, &operation->ret.getAttrib);
|
|
+}
|
|
+
|
|
+static LONG smartcard_SetAttrib_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_UNUSED(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ const Long_Return ret = { .ReturnCode = operation->returnCode };
|
|
+ smartcard_trace_long_return(&ret, "SetAttrib");
|
|
+ return SCARD_S_SUCCESS;
|
|
+}
|
|
+
|
|
+LONG smartcard_irp_device_control_decode_response(wStream* s, UINT32 ioControlCode,
|
|
+ SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ LONG status = SCARD_S_SUCCESS;
|
|
+
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH))
|
|
+ return SCARD_F_INTERNAL_ERROR;
|
|
+
|
|
+ const size_t startPosition = Stream_GetPosition(s);
|
|
+
|
|
+ const UINT32 outputBufferLength = Stream_Get_UINT32(s);
|
|
+ operation->ioControlCode = ioControlCode;
|
|
+ operation->ioControlCodeName = scard_get_ioctl_string(ioControlCode, FALSE);
|
|
+ operation->outputBufferLength = outputBufferLength;
|
|
+
|
|
+ if (outputBufferLength == 0)
|
|
+ return SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, outputBufferLength))
|
|
+ return SCARD_F_INTERNAL_ERROR;
|
|
+
|
|
+ status = smartcard_unpack_common_type_header(s);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ status = smartcard_unpack_private_type_header(s);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
|
|
+ return SCARD_F_INTERNAL_ERROR;
|
|
+
|
|
+ Stream_Read_INT32(s, operation->returnCode);
|
|
+
|
|
+ if (operation->returnCode != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ WLog_WARN(TAG, "%s failed with ReturnCode %s [0x%08" PRIX32 "]",
|
|
+ scard_get_ioctl_string(ioControlCode, TRUE),
|
|
+ SCardGetErrorString(operation->returnCode), (UINT32)operation->returnCode);
|
|
+ return SCARD_S_SUCCESS;
|
|
+ }
|
|
+
|
|
+ switch (ioControlCode)
|
|
+ {
|
|
+ case SCARD_IOCTL_ESTABLISHCONTEXT:
|
|
+ status = smartcard_EstablishContext_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_RELEASECONTEXT:
|
|
+ status = smartcard_ReleaseContext_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_ISVALIDCONTEXT:
|
|
+ status = smartcard_IsValidContext_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_LISTREADERGROUPSA:
|
|
+ status = smartcard_ListReaderGroupsA_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_LISTREADERGROUPSW:
|
|
+ status = smartcard_ListReaderGroupsW_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_LISTREADERSA:
|
|
+ status = smartcard_ListReadersA_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_LISTREADERSW:
|
|
+ status = smartcard_ListReadersW_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEA:
|
|
+ status = smartcard_GetStatusChangeA_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEW:
|
|
+ status = smartcard_GetStatusChangeW_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_CANCEL:
|
|
+ status = smartcard_Cancel_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_CONNECTA:
|
|
+ status = smartcard_ConnectA_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_CONNECTW:
|
|
+ status = smartcard_ConnectW_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_RECONNECT:
|
|
+ status = smartcard_Reconnect_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_DISCONNECT:
|
|
+ status = smartcard_Disconnect_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_BEGINTRANSACTION:
|
|
+ status = smartcard_BeginTransaction_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_ENDTRANSACTION:
|
|
+ status = smartcard_EndTransaction_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_STATUSA:
|
|
+ status = smartcard_StatusA_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_STATUSW:
|
|
+ status = smartcard_StatusW_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_TRANSMIT:
|
|
+ status = smartcard_Transmit_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_CONTROL:
|
|
+ status = smartcard_Control_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_GETATTRIB:
|
|
+ status = smartcard_GetAttrib_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_SETATTRIB:
|
|
+ status = smartcard_SetAttrib_decode_response(s, operation);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ WLog_WARN(TAG, "unsupported response for %s (0x%08" PRIX32 ")",
|
|
+ scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ const size_t offset = startPosition + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH;
|
|
+ if (smartcard_unpack_read_size_align(s, Stream_GetPosition(s) - offset, 8) < 0)
|
|
+ return STATUS_INVALID_PARAMETER;
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
static void free_reader_states_a(LPSCARD_READERSTATEA rgReaderStates, UINT32 cReaders)
|
|
{
|
|
for (UINT32 x = 0; x < cReaders; x++)
|
|
@@ -851,6 +1192,8 @@ void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
|
|
{
|
|
if (!op)
|
|
return;
|
|
+
|
|
+ /* Free resources in the call union */
|
|
switch (op->ioControlCode)
|
|
{
|
|
case SCARD_IOCTL_CANCEL:
|
|
@@ -1028,6 +1371,43 @@ void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
|
|
break;
|
|
}
|
|
|
|
+ /* Free resources in the ret union */
|
|
+ switch (op->ioControlCode)
|
|
+ {
|
|
+ case SCARD_IOCTL_LISTREADERSA:
|
|
+ case SCARD_IOCTL_LISTREADERSW:
|
|
+ case SCARD_IOCTL_LISTREADERGROUPSA:
|
|
+ case SCARD_IOCTL_LISTREADERGROUPSW:
|
|
+ {
|
|
+ ListReaders_Return* ret = &op->ret.listReaders;
|
|
+ free(ret->msz);
|
|
+ }
|
|
+ break;
|
|
+ case SCARD_IOCTL_STATUSA:
|
|
+ case SCARD_IOCTL_STATUSW:
|
|
+ {
|
|
+ Status_Return* ret = &op->ret.status;
|
|
+ free(ret->mszReaderNames);
|
|
+ }
|
|
+ break;
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEA:
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEW:
|
|
+ {
|
|
+ GetStatusChange_Return* ret = &op->ret.getStatusChange;
|
|
+ free(ret->rgReaderStates);
|
|
+ }
|
|
+ break;
|
|
+ case SCARD_IOCTL_TRANSMIT:
|
|
+ {
|
|
+ Transmit_Return* ret = &op->ret.transmit;
|
|
+ free(ret->pbRecvBuffer);
|
|
+ free(ret->pioRecvPci);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
{
|
|
SMARTCARD_OPERATION empty = WINPR_C_ARRAY_INIT;
|
|
*op = empty;
|
|
|
|
From 4c83cecd3bb108e0643020c2b2a21514d316b976 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Thu, 14 May 2026 16:44:31 +0200
|
|
Subject: [PATCH 10/31] [utils,smartcard] add encode_request for server-side
|
|
IOCTL encoding
|
|
|
|
Add smartcard_irp_device_control_encode_request as the symmetric
|
|
counterpart to decode_request. It encodes DR_CONTROL_REQ: writes
|
|
CommonTypeHeader, PrivateTypeHeader, then dispatches to per-IOCTL
|
|
encode functions.
|
|
|
|
There are some requests that aren't supported for encoding yet.
|
|
|
|
Co-authored-by: David Fort <contact@hardening-consulting.com>
|
|
---
|
|
libfreerdp/utils/smartcard_operations.c | 329 ++++++++++++++++++++++++
|
|
1 file changed, 329 insertions(+)
|
|
|
|
diff --git a/libfreerdp/utils/smartcard_operations.c b/libfreerdp/utils/smartcard_operations.c
|
|
index 906923fc7ecc..a38e0d102487 100644
|
|
--- a/libfreerdp/utils/smartcard_operations.c
|
|
+++ b/libfreerdp/utils/smartcard_operations.c
|
|
@@ -1166,6 +1166,335 @@ LONG smartcard_irp_device_control_decode_response(wStream* s, UINT32 ioControlCo
|
|
return status;
|
|
}
|
|
|
|
+static LONG smartcard_EstablishContext_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_establish_context_call(s, &operation->call.establishContext);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ReleaseContext_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_context_call(s, &operation->call.context, "ReleaseContext");
|
|
+}
|
|
+
|
|
+static LONG smartcard_IsValidContext_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_context_call(s, &operation->call.context, "IsValidContext");
|
|
+}
|
|
+
|
|
+static LONG smartcard_ListReaderGroupsA_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_list_reader_groups_call(s, &operation->call.listReaderGroups, FALSE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ListReaderGroupsW_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_list_reader_groups_call(s, &operation->call.listReaderGroups, TRUE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ListReadersA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_list_readers_call(s, &operation->call.listReaders, FALSE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ListReadersW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_list_readers_call(s, &operation->call.listReaders, TRUE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_GetStatusChangeA_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
|
|
+}
|
|
+
|
|
+static LONG smartcard_GetStatusChangeW_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Cancel_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_context_call(s, &operation->call.context, "Cancel");
|
|
+}
|
|
+
|
|
+static LONG smartcard_ConnectA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_connect_a_call(s, &operation->call.connectA);
|
|
+}
|
|
+
|
|
+static LONG smartcard_ConnectW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_connect_w_call(s, &operation->call.connectW);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Reconnect_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_reconnect_call(s, &operation->call.reconnect);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Disconnect_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
|
|
+ "Disconnect");
|
|
+}
|
|
+
|
|
+static LONG smartcard_BeginTransaction_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
|
|
+ "BeginTransaction");
|
|
+}
|
|
+
|
|
+static LONG smartcard_EndTransaction_encode_request(wStream* s,
|
|
+ const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
|
|
+ "EndTransaction");
|
|
+}
|
|
+
|
|
+static LONG smartcard_StatusA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_status_call(s, &operation->call.status, FALSE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_StatusW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_status_call(s, &operation->call.status, TRUE);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Transmit_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_transmit_call(s, &operation->call.transmit);
|
|
+}
|
|
+
|
|
+static LONG smartcard_Control_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_control_call(s, &operation->call.control);
|
|
+}
|
|
+
|
|
+static LONG smartcard_GetAttrib_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_get_attrib_call(s, &operation->call.getAttrib);
|
|
+}
|
|
+
|
|
+static LONG smartcard_SetAttrib_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ return smartcard_pack_set_attrib_call(s, &operation->call.setAttrib);
|
|
+}
|
|
+
|
|
+LONG smartcard_irp_device_control_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
|
|
+{
|
|
+ LONG status = SCARD_S_SUCCESS;
|
|
+
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(operation);
|
|
+
|
|
+ const UINT32 ioControlCode = operation->ioControlCode;
|
|
+
|
|
+ const size_t headerPos = Stream_GetPosition(s);
|
|
+ Stream_Zero(s, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
|
|
+ Stream_Zero(s, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */
|
|
+
|
|
+ switch (ioControlCode)
|
|
+ {
|
|
+ case SCARD_IOCTL_ESTABLISHCONTEXT:
|
|
+ status = smartcard_EstablishContext_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_RELEASECONTEXT:
|
|
+ status = smartcard_ReleaseContext_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_ISVALIDCONTEXT:
|
|
+ status = smartcard_IsValidContext_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_LISTREADERGROUPSA:
|
|
+ status = smartcard_ListReaderGroupsA_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_LISTREADERGROUPSW:
|
|
+ status = smartcard_ListReaderGroupsW_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_LISTREADERSA:
|
|
+ status = smartcard_ListReadersA_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_LISTREADERSW:
|
|
+ status = smartcard_ListReadersW_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEA:
|
|
+ status = smartcard_GetStatusChangeA_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEW:
|
|
+ status = smartcard_GetStatusChangeW_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_CANCEL:
|
|
+ status = smartcard_Cancel_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_CONNECTA:
|
|
+ status = smartcard_ConnectA_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_CONNECTW:
|
|
+ status = smartcard_ConnectW_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_RECONNECT:
|
|
+ status = smartcard_Reconnect_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_DISCONNECT:
|
|
+ status = smartcard_Disconnect_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_BEGINTRANSACTION:
|
|
+ status = smartcard_BeginTransaction_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_ENDTRANSACTION:
|
|
+ status = smartcard_EndTransaction_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_STATUSA:
|
|
+ status = smartcard_StatusA_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_STATUSW:
|
|
+ status = smartcard_StatusW_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_TRANSMIT:
|
|
+ status = smartcard_Transmit_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_CONTROL:
|
|
+ status = smartcard_Control_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_GETATTRIB:
|
|
+ status = smartcard_GetAttrib_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ case SCARD_IOCTL_SETATTRIB:
|
|
+ status = smartcard_SetAttrib_encode_request(s, operation);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ WLog_WARN(TAG, "unsupported request for %s (0x%08" PRIX32 ")",
|
|
+ scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
|
|
+ return SCARD_E_UNSUPPORTED_FEATURE;
|
|
+ }
|
|
+
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
|
|
+ (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
|
|
+ {
|
|
+ const LONG rc = smartcard_pack_write_size_align(s, Stream_GetPosition(s), 8);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
+ return rc;
|
|
+ }
|
|
+
|
|
+ const size_t dataEndPos = Stream_GetPosition(s);
|
|
+ const size_t payloadSize = dataEndPos - headerPos;
|
|
+ const size_t objectBufferLength =
|
|
+ payloadSize - SMARTCARD_COMMON_TYPE_HEADER_LENGTH - SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH;
|
|
+
|
|
+ status = smartcard_pack_write_size_align(s, payloadSize, 8);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ return status;
|
|
+
|
|
+ const size_t endPos = Stream_GetPosition(s);
|
|
+ if (!Stream_SetPosition(s, headerPos))
|
|
+ return SCARD_E_BAD_SEEK;
|
|
+ smartcard_pack_common_type_header(s);
|
|
+ smartcard_pack_private_type_header(s, (UINT32)objectBufferLength);
|
|
+ if (!Stream_SetPosition(s, endPos))
|
|
+ return SCARD_E_BAD_SEEK;
|
|
+ Stream_SealLength(s);
|
|
+
|
|
+ return status;
|
|
+}
|
|
+
|
|
static void free_reader_states_a(LPSCARD_READERSTATEA rgReaderStates, UINT32 cReaders)
|
|
{
|
|
for (UINT32 x = 0; x < cReaders; x++)
|
|
|
|
From 41fa3da3f479ea6967c6e37f8935f8e4d143b61d Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Tue, 23 Jun 2026 19:10:08 +0200
|
|
Subject: [PATCH 11/31] [channels,rdpdr] cache context->priv in local variable
|
|
|
|
Common subexpression elimination: extract RdpdrServerPrivate* priv
|
|
to avoid repeated context->priv pointer dereferences.
|
|
|
|
Co-Authored-By: David Fort <contact@hardening-consulting.com>
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 759 +++++++++++++++++------------
|
|
1 file changed, 438 insertions(+), 321 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 1de60b6688df..5f37a3c7a3d0 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -250,8 +250,10 @@ static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context, RDPDR_IRP* irp
|
|
{
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
const uintptr_t key = irp->CompletionId + 1ull;
|
|
- return ListDictionary_Add(context->priv->IrpList, (void*)key, irp);
|
|
+ return ListDictionary_Add(priv->IrpList, (void*)key, irp);
|
|
}
|
|
|
|
static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 completionId)
|
|
@@ -260,8 +262,9 @@ static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 c
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
const uintptr_t key = completionId + 1ull;
|
|
- irp = (RDPDR_IRP*)ListDictionary_Take(context->priv->IrpList, (void*)key);
|
|
+ irp = (RDPDR_IRP*)ListDictionary_Take(priv->IrpList, (void*)key);
|
|
return irp;
|
|
}
|
|
|
|
@@ -274,6 +277,7 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(s);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
Stream_SealLength(s);
|
|
const size_t length = Stream_Length(s);
|
|
WINPR_ASSERT(length <= UINT32_MAX);
|
|
@@ -285,14 +289,14 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
|
|
Stream_Read_UINT16(s, header.Component);
|
|
Stream_Read_UINT16(s, header.PacketId);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"sending message {Component %s[%04" PRIx16 "], PacketId %s[%04" PRIx16 "]",
|
|
rdpdr_component_string(header.Component), header.Component,
|
|
rdpdr_packetid_string(header.PacketId), header.PacketId);
|
|
}
|
|
- winpr_HexLogDump(context->priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
|
|
- status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s, char),
|
|
- (ULONG)length, &written);
|
|
+ winpr_HexLogDump(priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
|
|
+ status = WTSVirtualChannelWrite(priv->ChannelHandle, Stream_BufferAs(s, char), (ULONG)length,
|
|
+ &written);
|
|
Stream_Free(s, TRUE);
|
|
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -318,19 +322,20 @@ static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
|
|
if (error != CHANNEL_RC_OK)
|
|
return error;
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 8);
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
|
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
|
- Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */
|
|
- Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */
|
|
- Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */
|
|
+ Stream_Write_UINT16(s, priv->VersionMajor); /* VersionMajor (2 bytes) */
|
|
+ Stream_Write_UINT16(s, priv->VersionMinor); /* VersionMinor (2 bytes) */
|
|
+ Stream_Write_UINT32(s, priv->ClientId); /* ClientId (4 bytes) */
|
|
return rdpdr_seal_send_free_request(context, s);
|
|
}
|
|
|
|
@@ -349,19 +354,21 @@ static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
WINPR_UNUSED(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT16(s, VersionMajor); /* VersionMajor (2 bytes) */
|
|
Stream_Read_UINT16(s, VersionMinor); /* VersionMinor (2 bytes) */
|
|
Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"Client Announce Response: VersionMajor: 0x%08" PRIX16 " VersionMinor: 0x%04" PRIX16
|
|
" ClientId: 0x%08" PRIX32 "",
|
|
VersionMajor, VersionMinor, ClientId);
|
|
- context->priv->ClientId = ClientId;
|
|
+ priv->ClientId = ClientId;
|
|
|
|
return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveAnnounceResponse, context, VersionMajor,
|
|
VersionMinor, ClientId);
|
|
@@ -385,7 +392,9 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
|
WINPR_ASSERT(header);
|
|
WINPR_UNUSED(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 12))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */
|
|
@@ -396,7 +405,7 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
|
UnicodeFlag = UnicodeFlag & 0x00000001;
|
|
|
|
if (CodePage != 0)
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.2.4 Client Name Request (DR_CORE_CLIENT_NAME_REQ)::CodePage "
|
|
"must be 0, but is 0x%08" PRIx32,
|
|
CodePage);
|
|
@@ -410,8 +419,8 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
|
{
|
|
if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
- "invalid unicode computer name length: %" PRIu32 "", ComputerNameLen);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "invalid unicode computer name length: %" PRIu32 "",
|
|
+ ComputerNameLen);
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
@@ -419,56 +428,55 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
|
{
|
|
if (ComputerNameLen > 256 || ComputerNameLen < 1)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
- "invalid ascii computer name length: %" PRIu32 "", ComputerNameLen);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "invalid ascii computer name length: %" PRIu32 "",
|
|
+ ComputerNameLen);
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, ComputerNameLen))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, ComputerNameLen))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
/* ComputerName must be null terminated, check if it really is */
|
|
const char* computerName = Stream_ConstPointer(s);
|
|
if (computerName[ComputerNameLen - 1] || (UnicodeFlag && computerName[ComputerNameLen - 2]))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "computer name must be null terminated");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "computer name must be null terminated");
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
- if (context->priv->ClientComputerName)
|
|
+ if (priv->ClientComputerName)
|
|
{
|
|
- free(context->priv->ClientComputerName);
|
|
- context->priv->ClientComputerName = nullptr;
|
|
+ free(priv->ClientComputerName);
|
|
+ priv->ClientComputerName = nullptr;
|
|
}
|
|
|
|
if (UnicodeFlag)
|
|
{
|
|
- context->priv->ClientComputerName =
|
|
+ priv->ClientComputerName =
|
|
Stream_Read_UTF16_String_As_UTF8(s, ComputerNameLen / sizeof(WCHAR), nullptr);
|
|
- if (!context->priv->ClientComputerName)
|
|
+ if (!priv->ClientComputerName)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "failed to convert client computer name");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "failed to convert client computer name");
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const char* name = Stream_ConstPointer(s);
|
|
- context->priv->ClientComputerName = _strdup(name);
|
|
+ priv->ClientComputerName = _strdup(name);
|
|
Stream_Seek(s, ComputerNameLen);
|
|
|
|
- if (!context->priv->ClientComputerName)
|
|
+ if (!priv->ClientComputerName)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "failed to duplicate client computer name");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "failed to duplicate client computer name");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
}
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "ClientComputerName: %s",
|
|
- context->priv->ClientComputerName);
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "ClientComputerName: %s", priv->ClientComputerName);
|
|
return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveClientNameRequest, context, ComputerNameLen,
|
|
- context->priv->ClientComputerName);
|
|
+ priv->ClientComputerName);
|
|
}
|
|
|
|
static UINT rdpdr_server_write_capability_set_header_cb(RdpdrServerContext* context, wStream* s,
|
|
@@ -476,7 +484,9 @@ static UINT rdpdr_server_write_capability_set_header_cb(RdpdrServerContext* cont
|
|
{
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- UINT error = rdpdr_write_capset_header(context->priv->log, s, header);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ UINT error = rdpdr_write_capset_header(priv->log, s, header);
|
|
if (error != CHANNEL_RC_OK)
|
|
return error;
|
|
|
|
@@ -495,7 +505,9 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const UINT32 OsType = Stream_Get_UINT32(s); /* osType (4 bytes), ignored on receipt */
|
|
@@ -513,7 +525,7 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
|
|
|
|
{
|
|
char buffer[1024] = WINPR_C_ARRAY_INIT;
|
|
- WLog_Print(context->priv->log, WLOG_TRACE,
|
|
+ WLog_Print(priv->log, WLOG_TRACE,
|
|
"OsType=%" PRIu32 ", OsVersion=%" PRIu32 ", VersionMajor=%" PRIu32
|
|
", VersionMinor=%" PRIu32 ", IoCode1=%s, IoCode2=%" PRIu32
|
|
", ExtendedPdu=%" PRIu32 ", ExtraFlags1=%" PRIu32 ", ExtraFlags2=%" PRIu32,
|
|
@@ -524,7 +536,7 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
|
|
|
|
if (VersionMajor != RDPDR_MAJOR_RDP_VERSION)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "unsupported RDPDR version %" PRIu16 ".%" PRIu16,
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "unsupported RDPDR version %" PRIu16 ".%" PRIu16,
|
|
VersionMajor, VersionMinor);
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
@@ -538,21 +550,20 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
|
|
case RDPDR_MINOR_RDP_VERSION_5_0:
|
|
break;
|
|
default:
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
- "unsupported RDPDR minor version %" PRIu16 ".%" PRIu16, VersionMajor,
|
|
- VersionMinor);
|
|
+ WLog_Print(priv->log, WLOG_WARN, "unsupported RDPDR minor version %" PRIu16 ".%" PRIu16,
|
|
+ VersionMajor, VersionMinor);
|
|
break;
|
|
}
|
|
|
|
UINT32 SpecialTypeDeviceCap = 0;
|
|
if (header->Version == GENERAL_CAPABILITY_VERSION_02)
|
|
{
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
SpecialTypeDeviceCap = Stream_Get_UINT32(s); /* SpecialTypeDeviceCap (4 bytes) */
|
|
}
|
|
- context->priv->SpecialDeviceTypeCap = SpecialTypeDeviceCap;
|
|
+ priv->SpecialDeviceTypeCap = SpecialTypeDeviceCap;
|
|
|
|
const UINT32 mask =
|
|
RDPDR_IRP_MJ_CREATE | RDPDR_IRP_MJ_CLEANUP | RDPDR_IRP_MJ_CLOSE | RDPDR_IRP_MJ_READ |
|
|
@@ -564,15 +575,15 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
|
|
if ((IoCode1 & mask) == 0)
|
|
{
|
|
char buffer[1024] = WINPR_C_ARRAY_INIT;
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Missing IRP mask values %s",
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Missing IRP mask values %s",
|
|
rdpdr_irp_mask2str(IoCode1 & mask, buffer, sizeof(buffer)));
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
- context->priv->IoCode1 = IoCode1;
|
|
+ priv->IoCode1 = IoCode1;
|
|
|
|
if (IoCode2 != 0)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) ioCode2 is "
|
|
"reserved for future use, expected value 0 got %" PRIu32,
|
|
IoCode2);
|
|
@@ -580,17 +591,17 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
|
|
|
|
if ((ExtendedPdu & RDPDR_CLIENT_DISPLAY_NAME_PDU) == 0)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) extendedPDU "
|
|
"should always set RDPDR_CLIENT_DISPLAY_NAME_PDU[0x00000002]");
|
|
}
|
|
|
|
- context->priv->ExtendedPDU = ExtendedPdu;
|
|
- context->priv->UserLoggedOnPdu = (ExtendedPdu & RDPDR_USER_LOGGEDON_PDU) != 0;
|
|
+ priv->ExtendedPDU = ExtendedPdu;
|
|
+ priv->UserLoggedOnPdu = (ExtendedPdu & RDPDR_USER_LOGGEDON_PDU) != 0;
|
|
|
|
if (ExtraFlags2 != 0)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) ExtraFlags2 is "
|
|
"reserved for future use, expected value 0 got %" PRIu32,
|
|
ExtraFlags2);
|
|
@@ -637,14 +648,15 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* contex
|
|
extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU; /* always set */
|
|
extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS; /* optional */
|
|
|
|
- if (context->priv->UserLoggedOnPdu)
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ if (priv->UserLoggedOnPdu)
|
|
extendedPdu |= RDPDR_USER_LOGGEDON_PDU; /* optional */
|
|
|
|
extraFlags1 = 0;
|
|
extraFlags1 |= ENABLE_ASYNCIO; /* optional */
|
|
SpecialTypeDeviceCap = 0;
|
|
|
|
- UINT error = rdpdr_write_capset_header(context->priv->log, s, &header);
|
|
+ UINT error = rdpdr_write_capset_header(priv->log, s, &header);
|
|
if (error != CHANNEL_RC_OK)
|
|
return error;
|
|
|
|
@@ -652,8 +664,8 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* contex
|
|
const size_t start = Stream_GetPosition(s);
|
|
Stream_Write_UINT32(s, 0); /* osType (4 bytes), ignored on receipt */
|
|
Stream_Write_UINT32(s, 0); /* osVersion (4 bytes), unused and must be set to zero */
|
|
- Stream_Write_UINT16(s, context->priv->VersionMajor); /* protocolMajorVersion (2 bytes) */
|
|
- Stream_Write_UINT16(s, context->priv->VersionMinor); /* protocolMinorVersion (2 bytes) */
|
|
+ Stream_Write_UINT16(s, priv->VersionMajor); /* protocolMajorVersion (2 bytes) */
|
|
+ Stream_Write_UINT16(s, priv->VersionMinor); /* protocolMinorVersion (2 bytes) */
|
|
Stream_Write_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */
|
|
Stream_Write_UINT32(s, 0); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */
|
|
Stream_Write_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */
|
|
@@ -832,11 +844,12 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
|
|
numCapabilities++;
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 512);
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
@@ -847,7 +860,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
|
|
if ((error = rdpdr_server_write_general_capability_set(context, s)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_write_general_capability_set failed with error %" PRIu32 "!",
|
|
error);
|
|
goto out;
|
|
@@ -857,7 +870,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
{
|
|
if ((error = rdpdr_server_write_drive_capability_set(context, s)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_write_drive_capability_set failed with error %" PRIu32 "!",
|
|
error);
|
|
goto out;
|
|
@@ -869,7 +882,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
{
|
|
if ((error = rdpdr_server_write_port_capability_set(context, s)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_write_port_capability_set failed with error %" PRIu32 "!",
|
|
error);
|
|
goto out;
|
|
@@ -880,7 +893,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
{
|
|
if ((error = rdpdr_server_write_printer_capability_set(context, s)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_write_printer_capability_set failed with error %" PRIu32 "!",
|
|
error);
|
|
goto out;
|
|
@@ -891,7 +904,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
{
|
|
if ((error = rdpdr_server_write_smartcard_capability_set(context, s)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_write_printer_capability_set failed with error %" PRIu32 "!",
|
|
error);
|
|
goto out;
|
|
@@ -936,9 +949,11 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
WINPR_UNUSED(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
|
|
@@ -950,9 +965,9 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
RDPDR_CAPABILITY_HEADER capabilityHeader = WINPR_C_ARRAY_INIT;
|
|
const size_t start = Stream_GetPosition(s);
|
|
|
|
- if ((status = rdpdr_read_capset_header(context->priv->log, s, &capabilityHeader)))
|
|
+ if ((status = rdpdr_read_capset_header(priv->log, s, &capabilityHeader)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!", status);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!", status);
|
|
return status;
|
|
}
|
|
|
|
@@ -967,8 +982,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
if ((status =
|
|
rdpdr_server_read_general_capability_set(context, s, &capabilityHeader)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!",
|
|
- status);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!", status);
|
|
return status;
|
|
}
|
|
|
|
@@ -978,8 +992,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
if ((status =
|
|
rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!",
|
|
- status);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!", status);
|
|
return status;
|
|
}
|
|
|
|
@@ -988,8 +1001,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
case CAP_PORT_TYPE:
|
|
if ((status = rdpdr_server_read_port_capability_set(context, s, &capabilityHeader)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!",
|
|
- status);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!", status);
|
|
return status;
|
|
}
|
|
|
|
@@ -999,8 +1011,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
if ((status =
|
|
rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!",
|
|
- status);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!", status);
|
|
return status;
|
|
}
|
|
|
|
@@ -1010,15 +1021,14 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
if ((status =
|
|
rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!",
|
|
- status);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!", status);
|
|
return status;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "Unknown capabilityType %" PRIu16 "",
|
|
+ WLog_Print(priv->log, WLOG_WARN, "Unknown capabilityType %" PRIu16 "",
|
|
capabilityHeader.CapabilityType);
|
|
Stream_Seek(s, capabilityHeader.CapabilityLength);
|
|
return ERROR_INVALID_DATA;
|
|
@@ -1027,8 +1037,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
const UINT16 client_dtyp = rdpdr_cap_type_to_dtyp(capabilityHeader.CapabilityType);
|
|
if ((client_dtyp != 0) && ((client_dtyp & context->supported) == 0))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
- "client sent capability %s we did not announce!",
|
|
+ WLog_Print(priv->log, WLOG_WARN, "client sent capability %s we did not announce!",
|
|
rdpdr_cap_type_string(capabilityHeader.CapabilityType));
|
|
}
|
|
caps |= client_dtyp;
|
|
@@ -1037,7 +1046,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
const size_t diff = end - start;
|
|
if (diff != capabilityHeader.CapabilityLength + RDPDR_CAPABILITY_HEADER_LENGTH)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"{capability %s[0x%04" PRIx16 "]} processed %" PRIuz
|
|
" bytes, but expected to be %" PRIu16,
|
|
rdpdr_cap_type_string(capabilityHeader.CapabilityType),
|
|
@@ -1066,19 +1075,21 @@ static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
|
|
|
|
header.Component = RDPDR_CTYP_CORE;
|
|
header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 8);
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
|
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
|
- Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */
|
|
- Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */
|
|
- Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */
|
|
+ Stream_Write_UINT16(s, priv->VersionMajor); /* VersionMajor (2 bytes) */
|
|
+ Stream_Write_UINT16(s, priv->VersionMinor); /* VersionMinor (2 bytes) */
|
|
+ Stream_Write_UINT32(s, priv->ClientId); /* ClientId (4 bytes) */
|
|
return rdpdr_seal_send_free_request(context, s);
|
|
}
|
|
|
|
@@ -1096,20 +1107,22 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
WINPR_UNUSED(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "DeviceCount: %" PRIu32 "", DeviceCount);
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "DeviceCount: %" PRIu32 "", DeviceCount);
|
|
|
|
for (UINT32 i = 0; i < DeviceCount; i++)
|
|
{
|
|
UINT error = 0;
|
|
RdpdrDevice device = WINPR_C_ARRAY_INIT;
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, device.DeviceType); /* DeviceType (4 bytes) */
|
|
@@ -1118,7 +1131,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
Stream_Read_UINT32(s, device.DeviceDataLength); /* DeviceDataLength (4 bytes) */
|
|
device.DeviceData = Stream_Pointer(s);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, device.DeviceDataLength))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, device.DeviceDataLength))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
if (!rdpdr_add_device(context->priv, &device))
|
|
@@ -1143,7 +1156,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
case RDPDR_DTYP_SERIAL:
|
|
if (device.DeviceDataLength != 0)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[rdpdr] RDPDR_DTYP_SERIAL::DeviceDataLength != 0 [%" PRIu32 "]",
|
|
device.DeviceDataLength);
|
|
error = ERROR_INVALID_DATA;
|
|
@@ -1156,7 +1169,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
case RDPDR_DTYP_PARALLEL:
|
|
if (device.DeviceDataLength != 0)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[rdpdr] RDPDR_DTYP_PARALLEL::DeviceDataLength != 0 [%" PRIu32 "]",
|
|
device.DeviceDataLength);
|
|
error = ERROR_INVALID_DATA;
|
|
@@ -1169,7 +1182,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
case RDPDR_DTYP_SMARTCARD:
|
|
if (device.DeviceDataLength != 0)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[rdpdr] RDPDR_DTYP_SMARTCARD::DeviceDataLength != 0 [%" PRIu32 "]",
|
|
device.DeviceDataLength);
|
|
error = ERROR_INVALID_DATA;
|
|
@@ -1180,7 +1193,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
break;
|
|
|
|
default:
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.2.9 Client Device List Announce Request "
|
|
"(DR_CORE_DEVICELIST_ANNOUNCE_REQ) unknown device type %04" PRIx16
|
|
" at position %" PRIu32,
|
|
@@ -1212,26 +1225,27 @@ static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext*
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
WINPR_UNUSED(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "DeviceCount: %" PRIu32 "", DeviceCount);
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "DeviceCount: %" PRIu32 "", DeviceCount);
|
|
|
|
for (UINT32 i = 0; i < DeviceCount; i++)
|
|
{
|
|
UINT error = 0;
|
|
const RdpdrDevice* device = nullptr;
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
|
|
device = rdpdr_get_device_by_id(context->priv, DeviceId);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "Device %" PRIu32 " Id: 0x%08" PRIX32 "", i,
|
|
- DeviceId);
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "Device %" PRIu32 " Id: 0x%08" PRIX32 "", i, DeviceId);
|
|
DeviceType = 0;
|
|
if (device)
|
|
DeviceType = device->DeviceType;
|
|
@@ -1301,7 +1315,9 @@ static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
|
|
UINT32 PathLength = 0;
|
|
|
|
WINPR_ASSERT(context);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, DesiredAccess);
|
|
@@ -1312,13 +1328,13 @@ static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
|
|
Stream_Read_UINT32(s, CreateOptions);
|
|
Stream_Read_UINT32(s, PathLength);
|
|
|
|
- path = rdpdr_read_ustring(context->priv->log, s, PathLength);
|
|
+ path = rdpdr_read_ustring(priv->log, s, PathLength);
|
|
if (!path && (PathLength > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4.1 Device Create Request (DR_CREATE_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1331,14 +1347,16 @@ static UINT rdpdr_server_receive_io_close_request(RdpdrServerContext* context, w
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Seek(s, 32); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4.2 Device Close Request (DR_CLOSE_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1353,19 +1371,21 @@ static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context, wS
|
|
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Read_UINT64(s, Offset);
|
|
Stream_Seek(s, 20); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "Got Offset [0x%016" PRIx64 "], Length %" PRIu32,
|
|
- Offset, Length);
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "Got Offset [0x%016" PRIx64 "], Length %" PRIu32, Offset,
|
|
+ Length);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4.3 Device Read Request (DR_READ_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1381,24 +1401,26 @@ static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context, w
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Read_UINT64(s, Offset);
|
|
Stream_Seek(s, 20); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "Got Offset [0x%016" PRIx64 "], Length %" PRIu32,
|
|
- Offset, Length);
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "Got Offset [0x%016" PRIx64 "], Length %" PRIu32, Offset,
|
|
+ Length);
|
|
|
|
const BYTE* data = Stream_ConstPointer(s);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
|
|
return ERROR_INVALID_DATA;
|
|
Stream_Seek(s, Length);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4.4 Device Write Request (DR_WRITE_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO: parse %p", (const void*)data);
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO: parse %p", (const void*)data);
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1415,7 +1437,9 @@ static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* c
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, OutputBufferLength);
|
|
@@ -1424,14 +1448,13 @@ static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* c
|
|
Stream_Seek(s, 20); /* Padding */
|
|
|
|
const BYTE* InputBuffer = Stream_ConstPointer(s);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, InputBufferLength))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, InputBufferLength))
|
|
return ERROR_INVALID_DATA;
|
|
Stream_Seek(s, InputBufferLength);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4.5 Device Control Request (DR_CONTROL_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
- "TODO: parse %p [%" PRIu32 "], OutputBufferLength=%" PRIu32,
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO: parse %p [%" PRIu32 "], OutputBufferLength=%" PRIu32,
|
|
(const void*)InputBuffer, InputBufferLength, OutputBufferLength);
|
|
|
|
return CHANNEL_RC_OK;
|
|
@@ -1445,26 +1468,28 @@ static UINT rdpdr_server_receive_io_query_volume_information_request(
|
|
UINT32 Length = 0;
|
|
|
|
WINPR_ASSERT(context);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"Got FSInformationClass %s [0x%08" PRIx32 "], Length %" PRIu32,
|
|
FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
|
|
|
|
const BYTE* QueryVolumeBuffer = Stream_ConstPointer(s);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
|
|
return ERROR_INVALID_DATA;
|
|
Stream_Seek(s, Length);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.3.3.6 Server Drive Query Volume Information Request "
|
|
"(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO: parse %p", (const void*)QueryVolumeBuffer);
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO: parse %p", (const void*)QueryVolumeBuffer);
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1479,26 +1504,28 @@ static UINT rdpdr_server_receive_io_set_volume_information_request(
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"Got FSInformationClass %s [0x%08" PRIx32 "], Length %" PRIu32,
|
|
FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
|
|
|
|
const BYTE* SetVolumeBuffer = Stream_ConstPointer(s);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
|
|
return ERROR_INVALID_DATA;
|
|
Stream_Seek(s, Length);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.3.3.7 Server Drive Set Volume Information Request "
|
|
"(DR_DRIVE_SET_VOLUME_INFORMATION_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO: parse %p", (const void*)SetVolumeBuffer);
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO: parse %p", (const void*)SetVolumeBuffer);
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1515,26 +1542,28 @@ static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"Got FSInformationClass %s [0x%08" PRIx32 "], Length %" PRIu32,
|
|
FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
|
|
|
|
const BYTE* QueryBuffer = Stream_ConstPointer(s);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
|
|
return ERROR_INVALID_DATA;
|
|
Stream_Seek(s, Length);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.3.3.8 Server Drive Query Information Request "
|
|
"(DR_DRIVE_QUERY_INFORMATION_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO: parse %p", (const void*)QueryBuffer);
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO: parse %p", (const void*)QueryBuffer);
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1550,26 +1579,28 @@ static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext*
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"Got FSInformationClass %s [0x%08" PRIx32 "], Length %" PRIu32,
|
|
FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
|
|
|
|
const BYTE* SetBuffer = Stream_ConstPointer(s);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
|
|
return ERROR_INVALID_DATA;
|
|
Stream_Seek(s, Length);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.3.3.9 Server Drive Set Information Request "
|
|
"(DR_DRIVE_SET_INFORMATION_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO: parse %p", (const void*)SetBuffer);
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO: parse %p", (const void*)SetBuffer);
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1586,7 +1617,9 @@ static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext*
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
@@ -1594,22 +1627,22 @@ static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext*
|
|
Stream_Read_UINT32(s, PathLength);
|
|
Stream_Seek(s, 23); /* Padding */
|
|
|
|
- const WCHAR* wPath = rdpdr_read_ustring(context->priv->log, s, PathLength);
|
|
+ const WCHAR* wPath = rdpdr_read_ustring(priv->log, s, PathLength);
|
|
if (!wPath && (PathLength > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
char* Path = ConvertWCharNToUtf8Alloc(wPath, PathLength / sizeof(WCHAR), nullptr);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"Got FSInformationClass %s [0x%08" PRIx32 "], InitialQuery [%" PRIu8
|
|
"] Path[%" PRIu32 "] %s",
|
|
FSInformationClass2Tag(FsInformationClass), FsInformationClass, InitialQuery,
|
|
PathLength, Path);
|
|
free(Path);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.3.3.10 Server Drive Query Directory Request "
|
|
"(DR_DRIVE_QUERY_DIRECTORY_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1626,17 +1659,19 @@ static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext*
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT8(s, WatchTree);
|
|
Stream_Read_UINT32(s, CompletionFilter);
|
|
Stream_Seek(s, 27); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.3.3.11 Server Drive NotifyChange Directory Request "
|
|
"(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1649,6 +1684,7 @@ static UINT rdpdr_server_receive_io_directory_control_request(RdpdrServerContext
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
switch (MinorFunction)
|
|
{
|
|
case IRP_MN_QUERY_DIRECTORY:
|
|
@@ -1658,7 +1694,7 @@ static UINT rdpdr_server_receive_io_directory_control_request(RdpdrServerContext
|
|
return rdpdr_server_receive_io_change_directory_request(context, s, DeviceId, FileId,
|
|
CompletionId);
|
|
default:
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) "
|
|
"MajorFunction=%s, MinorFunction=%08" PRIx32 " is not supported",
|
|
rdpdr_irp_string(IRP_MJ_DIRECTORY_CONTROL), MinorFunction);
|
|
@@ -1674,7 +1710,9 @@ static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* con
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const uint32_t Operation = Stream_Get_UINT32(s);
|
|
@@ -1682,7 +1720,7 @@ static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* con
|
|
const uint32_t NumLocks = Stream_Get_UINT32(s);
|
|
Stream_Seek(s, 20); /* Padding */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"IRP_MJ_LOCK_CONTROL, Operation=%s, Lock=0x%08" PRIx32 ", NumLocks=%" PRIu32,
|
|
DR_DRIVE_LOCK_REQ2str(Operation), Lock, NumLocks);
|
|
|
|
@@ -1693,22 +1731,22 @@ static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* con
|
|
UINT64 Length = 0;
|
|
UINT64 Offset = 0;
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 16))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 16))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT64(s, Length);
|
|
Stream_Read_UINT64(s, Offset);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
- "Locking at Offset=0x%08" PRIx64 " [Length %" PRIu64 "]", Offset, Length);
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "Locking at Offset=0x%08" PRIx64 " [Length %" PRIu64 "]",
|
|
+ Offset, Length);
|
|
}
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.3.3.12 Server Drive Lock Control Request (DR_DRIVE_LOCK_REQ) "
|
|
"[Lock=0x%08" PRIx32 "]"
|
|
"not implemented",
|
|
Lock);
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1726,7 +1764,9 @@ static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, DeviceId);
|
|
@@ -1735,7 +1775,7 @@ static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
|
|
Stream_Read_UINT32(s, MajorFunction);
|
|
Stream_Read_UINT32(s, MinorFunction);
|
|
if ((MinorFunction != 0) && (MajorFunction != IRP_MJ_DIRECTORY_CONTROL))
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) MajorFunction=%s, "
|
|
"MinorFunction=0x%08" PRIx32 " != 0",
|
|
rdpdr_irp_string(MajorFunction), MinorFunction);
|
|
@@ -1777,9 +1817,9 @@ static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
|
|
|
|
default:
|
|
WLog_Print(
|
|
- context->priv->log, WLOG_WARN,
|
|
+ priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"got DeviceId=0x%08" PRIx32 ", FileId=0x%08" PRIx32
|
|
", CompletionId=0x%08" PRIx32 ", MajorFunction=0x%08" PRIx32
|
|
", MinorFunction=0x%08" PRIx32,
|
|
@@ -1806,22 +1846,24 @@ static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* contex
|
|
WINPR_ASSERT(s);
|
|
WINPR_ASSERT(header);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
WINPR_UNUSED(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 12))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, deviceId);
|
|
Stream_Read_UINT32(s, completionId);
|
|
Stream_Read_UINT32(s, ioStatus);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"deviceId=%" PRIu32 ", completionId=0x%" PRIx32 ", ioStatus=0x%" PRIx32 "", deviceId,
|
|
completionId, ioStatus);
|
|
irp = rdpdr_server_dequeue_irp(context, completionId);
|
|
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "IRP not found for completionId=0x%" PRIx32 "",
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "IRP not found for completionId=0x%" PRIx32 "",
|
|
completionId);
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -1850,11 +1892,13 @@ static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
|
|
|
|
header.Component = RDPDR_CTYP_CORE;
|
|
header.PacketId = PAKID_CORE_USER_LOGGEDON;
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
s = Stream_New(nullptr, RDPDR_HEADER_LENGTH);
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
@@ -1877,7 +1921,9 @@ static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* conte
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 24))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 24))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read(s, PortDosName, 8);
|
|
@@ -1886,23 +1932,23 @@ static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* conte
|
|
Stream_Read_UINT32(s, PrinterNameLen);
|
|
Stream_Read_UINT32(s, CachedFieldsLen);
|
|
|
|
- PnPName = rdpdr_read_ustring(context->priv->log, s, PnPNameLen);
|
|
+ PnPName = rdpdr_read_ustring(priv->log, s, PnPNameLen);
|
|
if (!PnPName && (PnPNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
- DriverName = rdpdr_read_ustring(context->priv->log, s, DriverNameLen);
|
|
+ DriverName = rdpdr_read_ustring(priv->log, s, DriverNameLen);
|
|
if (!DriverName && (DriverNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
- PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
|
|
+ PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
if (!PrinterName && (PrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, CachedFieldsLen))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, CachedFieldsLen))
|
|
return ERROR_INVALID_DATA;
|
|
Stream_Seek(s, CachedFieldsLen);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEPC] 2.2.2.3 Add Printer Cachedata (DR_PRN_ADD_CACHEDATA) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
@@ -1914,25 +1960,27 @@ static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* co
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, PrinterNameLen);
|
|
Stream_Read_UINT32(s, CachedFieldsLen);
|
|
|
|
- PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
|
|
+ PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
if (!PrinterName && (PrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const BYTE* config = Stream_ConstPointer(s);
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, CachedFieldsLen))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, CachedFieldsLen))
|
|
return ERROR_INVALID_DATA;
|
|
Stream_Seek(s, CachedFieldsLen);
|
|
|
|
WLog_Print(
|
|
- context->priv->log, WLOG_WARN,
|
|
+ priv->log, WLOG_WARN,
|
|
"[MS-RDPEPC] 2.2.2.4 Update Printer Cachedata (DR_PRN_UPDATE_CACHEDATA) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO: parse %p", (const void*)config);
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO: parse %p", (const void*)config);
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
@@ -1944,19 +1992,21 @@ static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* co
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, PrinterNameLen);
|
|
|
|
- PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
|
|
+ PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
if (!PrinterName && (PrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
WLog_Print(
|
|
- context->priv->log, WLOG_WARN,
|
|
+ priv->log, WLOG_WARN,
|
|
"[MS-RDPEPC] 2.2.2.5 Delete Printer Cachedata (DR_PRN_DELETE_CACHEDATA) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
@@ -1970,23 +2020,25 @@ static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext*
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, OldPrinterNameLen);
|
|
Stream_Read_UINT32(s, NewPrinterNameLen);
|
|
|
|
- OldPrinterName = rdpdr_read_ustring(context->priv->log, s, OldPrinterNameLen);
|
|
+ OldPrinterName = rdpdr_read_ustring(priv->log, s, OldPrinterNameLen);
|
|
if (!OldPrinterName && (OldPrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
- NewPrinterName = rdpdr_read_ustring(context->priv->log, s, NewPrinterNameLen);
|
|
+ NewPrinterName = rdpdr_read_ustring(priv->log, s, NewPrinterNameLen);
|
|
if (!NewPrinterName && (NewPrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
WLog_Print(
|
|
- context->priv->log, WLOG_WARN,
|
|
+ priv->log, WLOG_WARN,
|
|
"[MS-RDPEPC] 2.2.2.6 Rename Printer Cachedata (DR_PRN_RENAME_CACHEDATA) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "TODO");
|
|
+ WLog_Print(priv->log, WLOG_WARN, "TODO");
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
@@ -2000,7 +2052,8 @@ rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context, wStream
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, EventId);
|
|
@@ -2015,7 +2068,7 @@ rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context, wStream
|
|
case RDPDR_RENAME_PRINTER_EVENT:
|
|
return rdpdr_server_receive_prn_cache_rename_cachedata(context, s);
|
|
default:
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEPC] PAKID_PRN_CACHE_DATA unknown EventId=0x%08" PRIx32, EventId);
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
@@ -2031,17 +2084,19 @@ static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* conte
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, PrinterId);
|
|
Stream_Read_UINT32(s, Flags);
|
|
|
|
WLog_Print(
|
|
- context->priv->log, WLOG_WARN,
|
|
+ priv->log, WLOG_WARN,
|
|
"[MS-RDPEPC] 2.2.2.2 Server Printer Set XPS Mode (DR_PRN_USING_XPS) not implemented");
|
|
- WLog_Print(context->priv->log, WLOG_WARN, "PrinterId=0x%08" PRIx32 ", Flags=0x%08" PRIx32,
|
|
- PrinterId, Flags);
|
|
+ WLog_Print(priv->log, WLOG_WARN, "PrinterId=0x%08" PRIx32 ", Flags=0x%08" PRIx32, PrinterId,
|
|
+ Flags);
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
@@ -2059,7 +2114,8 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
WINPR_ASSERT(s);
|
|
WINPR_ASSERT(header);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"receiving message {Component %s[%04" PRIx16 "], PacketId %s[%04" PRIx16 "]",
|
|
rdpdr_component_string(header->Component), header->Component,
|
|
rdpdr_packetid_string(header->PacketId), header->PacketId);
|
|
@@ -2069,7 +2125,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
switch (header->PacketId)
|
|
{
|
|
case PAKID_CORE_SERVER_ANNOUNCE:
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"[MS-RDPEFS] 2.2.2.2 Server Announce Request "
|
|
"(DR_CORE_SERVER_ANNOUNCE_REQ) must not be sent by a client!");
|
|
break;
|
|
@@ -2087,13 +2143,13 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
break;
|
|
|
|
case PAKID_CORE_USER_LOGGEDON:
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"[MS-RDPEFS] 2.2.2.5 Server User Logged On (DR_CORE_USER_LOGGEDON) "
|
|
"must not be sent by a client!");
|
|
break;
|
|
|
|
case PAKID_CORE_SERVER_CAPABILITY:
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"[MS-RDPEFS] 2.2.2.7 Server Core Capability Request "
|
|
"(DR_CORE_CAPABILITY_REQ) must not be sent by a client!");
|
|
break;
|
|
@@ -2102,7 +2158,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
error = rdpdr_server_receive_core_capability_response(context, s, header);
|
|
if (error == CHANNEL_RC_OK)
|
|
{
|
|
- if (context->priv->UserLoggedOnPdu)
|
|
+ if (priv->UserLoggedOnPdu)
|
|
error = rdpdr_server_send_user_logged_on(context);
|
|
}
|
|
|
|
@@ -2117,7 +2173,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
break;
|
|
|
|
case PAKID_CORE_DEVICE_REPLY:
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"[MS-RDPEFS] 2.2.2.1 Server Device Announce Response "
|
|
"(DR_CORE_DEVICE_ANNOUNCE_RSP) must not be sent by a client!");
|
|
break;
|
|
@@ -2131,7 +2187,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
break;
|
|
|
|
default:
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16 "], PacketId: %s",
|
|
rdpdr_component_string(header->Component), header->Component,
|
|
rdpdr_packetid_string(header->PacketId));
|
|
@@ -2151,7 +2207,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
break;
|
|
|
|
default:
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16 "], PacketId: %s",
|
|
rdpdr_component_string(header->Component), header->Component,
|
|
rdpdr_packetid_string(header->PacketId));
|
|
@@ -2160,7 +2216,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
}
|
|
else
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_WARN,
|
|
+ WLog_Print(priv->log, WLOG_WARN,
|
|
"Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16 "], PacketId: %s",
|
|
rdpdr_component_string(header->Component), header->Component,
|
|
rdpdr_packetid_string(header->PacketId));
|
|
@@ -2184,14 +2240,16 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
error = CHANNEL_RC_NO_MEMORY;
|
|
goto out;
|
|
}
|
|
|
|
- if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
|
|
+ if (WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
|
|
&BytesReturned) == TRUE)
|
|
{
|
|
if (BytesReturned == sizeof(HANDLE))
|
|
@@ -2202,11 +2260,11 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
|
|
nCount = 0;
|
|
events[nCount++] = ChannelEvent;
|
|
- events[nCount++] = context->priv->StopEvent;
|
|
+ events[nCount++] = priv->StopEvent;
|
|
|
|
if ((error = rdpdr_server_send_announce_request(context)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_send_announce_request failed with error %" PRIu32 "!", error);
|
|
goto out_stream;
|
|
}
|
|
@@ -2220,42 +2278,42 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
if (status == WAIT_FAILED)
|
|
{
|
|
error = GetLastError();
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"WaitForMultipleObjects failed with error %" PRIu32 "!", error);
|
|
goto out_stream;
|
|
}
|
|
|
|
- status = WaitForSingleObject(context->priv->StopEvent, 0);
|
|
+ status = WaitForSingleObject(priv->StopEvent, 0);
|
|
|
|
if (status == WAIT_FAILED)
|
|
{
|
|
error = GetLastError();
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
- "WaitForSingleObject failed with error %" PRIu32 "!", error);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!",
|
|
+ error);
|
|
goto out_stream;
|
|
}
|
|
|
|
if (status == WAIT_OBJECT_0)
|
|
break;
|
|
|
|
- if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, nullptr, 0, &BytesReturned))
|
|
+ if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, nullptr, 0, &BytesReturned))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "WTSVirtualChannelRead failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "WTSVirtualChannelRead failed!");
|
|
error = ERROR_INTERNAL_ERROR;
|
|
break;
|
|
}
|
|
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
|
|
error = ERROR_INTERNAL_ERROR;
|
|
break;
|
|
}
|
|
|
|
capacity = MIN(Stream_Capacity(s), UINT32_MAX);
|
|
- if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, Stream_BufferAs(s, char),
|
|
+ if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, Stream_BufferAs(s, char),
|
|
(ULONG)capacity, &BytesReturned))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "WTSVirtualChannelRead failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "WTSVirtualChannelRead failed!");
|
|
error = ERROR_INTERNAL_ERROR;
|
|
break;
|
|
}
|
|
@@ -2278,7 +2336,7 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
|
|
if ((error = rdpdr_server_receive_pdu(context, s, &header)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_receive_pdu failed with error %" PRIu32 "!", error);
|
|
goto out_stream;
|
|
}
|
|
@@ -2306,27 +2364,28 @@ static UINT rdpdr_server_start(RdpdrServerContext* context)
|
|
{
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- context->priv->ChannelHandle =
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ priv->ChannelHandle =
|
|
WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPDR_SVC_CHANNEL_NAME);
|
|
|
|
- if (!context->priv->ChannelHandle)
|
|
+ if (!priv->ChannelHandle)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "WTSVirtualChannelOpen failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "WTSVirtualChannelOpen failed!");
|
|
return CHANNEL_RC_BAD_CHANNEL;
|
|
}
|
|
|
|
- if (!(context->priv->StopEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
|
|
+ if (!(priv->StopEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "CreateEvent failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "CreateEvent failed!");
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
- if (!(context->priv->Thread =
|
|
- CreateThread(nullptr, 0, rdpdr_server_thread, (void*)context, 0, nullptr)))
|
|
+ if (!(priv->Thread = CreateThread(nullptr, 0, rdpdr_server_thread, (void*)context, 0, nullptr)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "CreateThread failed!");
|
|
- (void)CloseHandle(context->priv->StopEvent);
|
|
- context->priv->StopEvent = nullptr;
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "CreateThread failed!");
|
|
+ (void)CloseHandle(priv->StopEvent);
|
|
+ priv->StopEvent = nullptr;
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
@@ -2344,28 +2403,30 @@ static UINT rdpdr_server_stop(RdpdrServerContext* context)
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- if (context->priv->StopEvent)
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ if (priv->StopEvent)
|
|
{
|
|
- (void)SetEvent(context->priv->StopEvent);
|
|
+ (void)SetEvent(priv->StopEvent);
|
|
|
|
- if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
|
|
+ if (WaitForSingleObject(priv->Thread, INFINITE) == WAIT_FAILED)
|
|
{
|
|
error = GetLastError();
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
- "WaitForSingleObject failed with error %" PRIu32 "!", error);
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!",
|
|
+ error);
|
|
return error;
|
|
}
|
|
|
|
- (void)CloseHandle(context->priv->Thread);
|
|
- context->priv->Thread = nullptr;
|
|
- (void)CloseHandle(context->priv->StopEvent);
|
|
- context->priv->StopEvent = nullptr;
|
|
+ (void)CloseHandle(priv->Thread);
|
|
+ priv->Thread = nullptr;
|
|
+ (void)CloseHandle(priv->StopEvent);
|
|
+ priv->StopEvent = nullptr;
|
|
}
|
|
|
|
- if (context->priv->ChannelHandle)
|
|
+ if (priv->ChannelHandle)
|
|
{
|
|
- (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
|
|
- context->priv->ChannelHandle = nullptr;
|
|
+ (void)WTSVirtualChannelClose(priv->ChannelHandle);
|
|
+ priv->ChannelHandle = nullptr;
|
|
}
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
@@ -2441,7 +2502,9 @@ static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context,
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerSendDeviceCreateRequest: deviceId=%" PRIu32
|
|
", path=%s, desiredAccess=0x%" PRIx32 " createOptions=0x%" PRIx32
|
|
" createDisposition=0x%" PRIx32 "",
|
|
@@ -2452,7 +2515,7 @@ static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context,
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
@@ -2488,14 +2551,16 @@ static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context,
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerSendDeviceCloseRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32 "",
|
|
deviceId, fileId);
|
|
s = Stream_New(nullptr, 128);
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
@@ -2517,7 +2582,9 @@ static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, U
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerSendDeviceReadRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32
|
|
", length=%" PRIu32 ", offset=%" PRIu32 "",
|
|
deviceId, fileId, length, offset);
|
|
@@ -2525,7 +2592,7 @@ static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, U
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
@@ -2550,7 +2617,9 @@ static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context,
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerSendDeviceWriteRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32
|
|
", length=%" PRIu32 ", offset=%" PRIu32 "",
|
|
deviceId, fileId, length, offset);
|
|
@@ -2558,7 +2627,7 @@ static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context,
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
@@ -2585,7 +2654,9 @@ static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext*
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerSendDeviceQueryDirectoryRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32
|
|
", path=%s",
|
|
deviceId, fileId, path);
|
|
@@ -2595,7 +2666,7 @@ static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext*
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
@@ -2635,7 +2706,9 @@ static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* con
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerSendDeviceFileNameRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32
|
|
", path=%s",
|
|
deviceId, fileId, path);
|
|
@@ -2645,7 +2718,7 @@ static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* con
|
|
|
|
if (!s)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
@@ -2704,7 +2777,8 @@ static UINT rdpdr_server_drive_create_directory_callback2(RdpdrServerContext* co
|
|
WINPR_ASSERT(irp);
|
|
WINPR_UNUSED(s);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveCreateDirectoryCallback2: deviceId=%" PRIu32
|
|
", completionId=%" PRIu32 ", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -2728,7 +2802,9 @@ static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* co
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(s);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveCreateDirectoryCallback1: deviceId=%" PRIu32
|
|
", completionId=%" PRIu32 ", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -2742,23 +2818,23 @@ static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* co
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const uint32_t fileId = Stream_Get_UINT32(s); /* FileId (4 bytes) */
|
|
const uint8_t information = Stream_Get_UINT8(s); /* Information (1 byte) */
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
fileInformation2str(information));
|
|
|
|
/* Setup the IRP. */
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_create_directory_callback2;
|
|
irp->DeviceId = deviceId;
|
|
irp->FileId = fileId;
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -2780,15 +2856,17 @@ static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context, voi
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(callbackData);
|
|
WINPR_ASSERT(path);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_create_directory_callback1;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -2797,7 +2875,7 @@ static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context, voi
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -2826,7 +2904,8 @@ static UINT rdpdr_server_drive_delete_directory_callback2(RdpdrServerContext* co
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveDeleteDirectoryCallback2: deviceId=%" PRIu32
|
|
", completionId=%" PRIu32 ", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -2849,7 +2928,9 @@ static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* co
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveDeleteDirectoryCallback1: deviceId=%" PRIu32
|
|
", completionId=%" PRIu32 ", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -2863,23 +2944,23 @@ static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* co
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const uint32_t fileId = Stream_Get_UINT32(s); /* FileId (4 bytes) */
|
|
const uint8_t information = Stream_Get_UINT8(s); /* Information (1 byte) */
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
fileInformation2str(information));
|
|
|
|
/* Setup the IRP. */
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_delete_directory_callback2;
|
|
irp->DeviceId = deviceId;
|
|
irp->FileId = fileId;
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -2901,13 +2982,15 @@ static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context, voi
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_delete_directory_callback1;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -2916,7 +2999,7 @@ static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context, voi
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -2947,21 +3030,23 @@ static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* con
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveQueryDirectoryCallback2: deviceId=%" PRIu32
|
|
", completionId=%" PRIu32 ", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
|
|
if (length > 0)
|
|
{
|
|
- if ((error = rdpdr_server_read_file_directory_information(context->priv->log, s, &fdi)))
|
|
+ if ((error = rdpdr_server_read_file_directory_information(priv->log, s, &fdi)))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_read_file_directory_information failed with error %" PRIu32
|
|
"!",
|
|
error);
|
|
@@ -2970,7 +3055,7 @@ static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* con
|
|
}
|
|
else
|
|
{
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 1))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 1))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Seek(s, 1); /* Padding (1 byte) */
|
|
@@ -2982,12 +3067,12 @@ static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* con
|
|
context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
|
|
length > 0 ? &fdi : nullptr);
|
|
/* Setup the IRP. */
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_query_directory_callback2;
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3019,7 +3104,9 @@ static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* con
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveQueryDirectoryCallback1: deviceId=%" PRIu32
|
|
", completionId=%" PRIu32 ", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -3033,12 +3120,12 @@ static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* con
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const uint32_t fileId = Stream_Get_UINT32(s);
|
|
/* Setup the IRP. */
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_query_directory_callback2;
|
|
irp->DeviceId = deviceId;
|
|
irp->FileId = fileId;
|
|
@@ -3046,7 +3133,7 @@ static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* con
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3069,13 +3156,15 @@ static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context, void
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_query_directory_callback1;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -3084,7 +3173,7 @@ static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context, void
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3111,17 +3200,19 @@ static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context, w
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveOpenFileCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const uint32_t fileId = Stream_Get_UINT32(s); /* FileId (4 bytes) */
|
|
const uint8_t information = Stream_Get_UINT8(s); /* Information (1 byte) */
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
fileInformation2str(information));
|
|
|
|
/* Invoke the open file completion routine. */
|
|
@@ -3145,13 +3236,15 @@ static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context, void* call
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_open_file_callback;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -3160,7 +3253,7 @@ static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context, void* call
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3189,17 +3282,19 @@ static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, w
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveReadFileCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, length))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, length))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
if (length > 0)
|
|
@@ -3229,13 +3324,15 @@ static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context, void* call
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_read_file_callback;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -3243,7 +3340,7 @@ static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context, void* call
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3271,18 +3368,20 @@ static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveWriteFileCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
Stream_Seek(s, 1); /* Padding (1 byte) */
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, length))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, length))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
/* Invoke the write file completion routine. */
|
|
@@ -3306,13 +3405,15 @@ static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, void* cal
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_write_file_callback;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -3320,7 +3421,7 @@ static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, void* cal
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3349,13 +3450,15 @@ static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context,
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveCloseFileCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
|
|
// padding 5 bytes
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Seek(s, 5);
|
|
@@ -3380,13 +3483,15 @@ static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, void* cal
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_close_file_callback;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -3394,7 +3499,7 @@ static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, void* cal
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3422,7 +3527,8 @@ static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* context
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveDeleteFileCallback2: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -3445,7 +3551,9 @@ static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveDeleteFileCallback1: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -3459,23 +3567,23 @@ static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const uint32_t fileId = Stream_Get_UINT32(s); /* FileId (4 bytes) */
|
|
const uint8_t information = Stream_Get_UINT8(s); /* Information (1 byte) */
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
fileInformation2str(information));
|
|
/* Setup the IRP. */
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_delete_file_callback2;
|
|
irp->DeviceId = deviceId;
|
|
irp->FileId = fileId;
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3497,13 +3605,15 @@ static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context, void* ca
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_delete_file_callback1;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -3512,7 +3622,7 @@ static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context, void* ca
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3542,7 +3652,8 @@ static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* context
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveRenameFileCallback3: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -3564,12 +3675,14 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveRenameFileCallback2: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
@@ -3577,13 +3690,13 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context
|
|
/* Invoke the rename file completion routine. */
|
|
context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
|
|
/* Setup the IRP. */
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_rename_file_callback3;
|
|
irp->DeviceId = deviceId;
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3605,7 +3718,9 @@ static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG,
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerDriveRenameFileCallback1: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
", ioStatus=0x%" PRIx32 "",
|
|
deviceId, completionId, ioStatus);
|
|
@@ -3619,23 +3734,23 @@ static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
const uint32_t fileId = Stream_Get_UINT32(s); /* FileId (4 bytes) */
|
|
const uint8_t information = Stream_Get_UINT8(s); /* Information (1 byte) */
|
|
- WLog_Print(context->priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
+ WLog_Print(priv->log, WLOG_DEBUG, "fileId [0x%08" PRIx32 "], information %s", fileId,
|
|
fileInformation2str(information));
|
|
|
|
/* Setup the IRP. */
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_rename_file_callback2;
|
|
irp->DeviceId = deviceId;
|
|
irp->FileId = fileId;
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -3656,15 +3771,17 @@ static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context, void* ca
|
|
{
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
- irp->CompletionId = context->priv->NextCompletionId++;
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
irp->Callback = rdpdr_server_drive_rename_file_callback1;
|
|
irp->CallbackData = callbackData;
|
|
irp->DeviceId = deviceId;
|
|
@@ -3675,7 +3792,7 @@ static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context, void* ca
|
|
|
|
if (!rdpdr_server_enqueue_irp(context, irp))
|
|
{
|
|
- WLog_Print(context->priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
rdpdr_server_irp_free(irp);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
From 65d04a2f4eb13ae313c44c5443ab06b973376049 Mon Sep 17 00:00:00 2001
|
|
From: David Fort <contact@hardening-consulting.com>
|
|
Date: Tue, 23 Jun 2026 19:10:19 +0200
|
|
Subject: [PATCH 12/31] [channels,rdpdr] extract RDPDR_IRP_Callback typedef and
|
|
convert RDPDR_IRP to struct
|
|
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.h | 12 +++++++-----
|
|
1 file changed, 7 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.h b/channels/rdpdr/server/rdpdr_main.h
|
|
index dabbae24ad8b..b1d86b148ad7 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.h
|
|
+++ b/channels/rdpdr/server/rdpdr_main.h
|
|
@@ -31,7 +31,11 @@
|
|
#include <freerdp/settings.h>
|
|
#include <freerdp/server/rdpdr.h>
|
|
|
|
-typedef struct S_RDPDR_IRP
|
|
+typedef struct S_RDPDR_IRP RDPDR_IRP;
|
|
+typedef UINT (*RDPDR_IRP_Callback)(RdpdrServerContext* context, wStream* s, struct S_RDPDR_IRP* irp,
|
|
+ UINT32 deviceId, UINT32 completionId, UINT32 ioStatus);
|
|
+
|
|
+struct S_RDPDR_IRP
|
|
{
|
|
UINT32 CompletionId;
|
|
UINT32 DeviceId;
|
|
@@ -39,9 +43,7 @@ typedef struct S_RDPDR_IRP
|
|
char PathName[256];
|
|
char ExtraBuffer[256];
|
|
void* CallbackData;
|
|
- UINT(*Callback)
|
|
- (RdpdrServerContext* context, wStream* s, struct S_RDPDR_IRP* irp, UINT32 deviceId,
|
|
- UINT32 completionId, UINT32 ioStatus);
|
|
-} RDPDR_IRP;
|
|
+ RDPDR_IRP_Callback Callback;
|
|
+};
|
|
|
|
#endif /* FREERDP_CHANNEL_RDPDR_SERVER_MAIN_H */
|
|
|
|
From f29fc22218918fb8b2c8f9f8b04150db2bee7fee Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Tue, 23 Jun 2026 19:10:31 +0200
|
|
Subject: [PATCH 13/31] [channels,rdpdr] declare variables at point of first
|
|
use
|
|
|
|
Move variable declarations from function tops to just before
|
|
their first use.
|
|
|
|
Co-Authored-By: David Fort <contact@hardening-consulting.com>
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 378 ++++++++++++-----------------
|
|
1 file changed, 154 insertions(+), 224 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 5f37a3c7a3d0..488efca5bc46 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -191,9 +191,9 @@ static RdpdrDevice* rdpdr_get_device_by_id(RdpdrServerPrivate* priv, UINT32 Devi
|
|
|
|
static BOOL rdpdr_remove_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
|
|
{
|
|
- const RdpdrDevice* device = rdpdr_get_device_by_id(priv, DeviceId);
|
|
WINPR_ASSERT(priv);
|
|
|
|
+ const RdpdrDevice* device = rdpdr_get_device_by_id(priv, DeviceId);
|
|
if (!device)
|
|
{
|
|
WLog_Print(priv->log, WLOG_WARN, "[del] Device Id: 0x%08" PRIX32 ": no such device",
|
|
@@ -258,21 +258,17 @@ static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context, RDPDR_IRP* irp
|
|
|
|
static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 completionId)
|
|
{
|
|
- RDPDR_IRP* irp = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
const uintptr_t key = completionId + 1ull;
|
|
- irp = (RDPDR_IRP*)ListDictionary_Take(priv->IrpList, (void*)key);
|
|
+ RDPDR_IRP* irp = (RDPDR_IRP*)ListDictionary_Take(priv->IrpList, (void*)key);
|
|
return irp;
|
|
}
|
|
|
|
static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- BOOL status = 0;
|
|
- ULONG written = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(s);
|
|
@@ -295,8 +291,9 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
|
|
rdpdr_packetid_string(header.PacketId), header.PacketId);
|
|
}
|
|
winpr_HexLogDump(priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
|
|
- status = WTSVirtualChannelWrite(priv->ChannelHandle, Stream_BufferAs(s, char), (ULONG)length,
|
|
- &written);
|
|
+ ULONG written = 0;
|
|
+ BOOL status = WTSVirtualChannelWrite(priv->ChannelHandle, Stream_BufferAs(s, char),
|
|
+ (ULONG)length, &written);
|
|
Stream_Free(s, TRUE);
|
|
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
|
}
|
|
@@ -308,29 +305,25 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
|
|
*/
|
|
static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
|
|
{
|
|
- UINT error = 0;
|
|
- wStream* s = nullptr;
|
|
- RDPDR_HEADER header = WINPR_C_ARRAY_INIT;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- header.Component = RDPDR_CTYP_CORE;
|
|
- header.PacketId = PAKID_CORE_SERVER_ANNOUNCE;
|
|
-
|
|
- error = IFCALLRESULT(CHANNEL_RC_OK, context->SendServerAnnounce, context);
|
|
+ UINT error = IFCALLRESULT(CHANNEL_RC_OK, context->SendServerAnnounce, context);
|
|
if (error != CHANNEL_RC_OK)
|
|
return error;
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
- s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 8);
|
|
-
|
|
+ wStream* s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 8);
|
|
if (!s)
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
+ const RDPDR_HEADER header = {
|
|
+ .Component = RDPDR_CTYP_CORE,
|
|
+ .PacketId = PAKID_CORE_SERVER_ANNOUNCE,
|
|
+ };
|
|
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
|
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
|
Stream_Write_UINT16(s, priv->VersionMajor); /* VersionMajor (2 bytes) */
|
|
@@ -347,9 +340,6 @@ static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
|
|
static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context, wStream* s,
|
|
const RDPDR_HEADER* header)
|
|
{
|
|
- UINT32 ClientId = 0;
|
|
- UINT16 VersionMajor = 0;
|
|
- UINT16 VersionMinor = 0;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
@@ -361,6 +351,9 @@ static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT16 VersionMajor = 0;
|
|
+ UINT16 VersionMinor = 0;
|
|
+ UINT32 ClientId = 0;
|
|
Stream_Read_UINT16(s, VersionMajor); /* VersionMajor (2 bytes) */
|
|
Stream_Read_UINT16(s, VersionMinor); /* VersionMinor (2 bytes) */
|
|
Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */
|
|
@@ -382,10 +375,6 @@ static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
|
|
static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context, wStream* s,
|
|
const RDPDR_HEADER* header)
|
|
{
|
|
- UINT32 UnicodeFlag = 0;
|
|
- UINT32 CodePage = 0;
|
|
- UINT32 ComputerNameLen = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(s);
|
|
@@ -397,6 +386,9 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 UnicodeFlag = 0;
|
|
+ UINT32 CodePage = 0;
|
|
+ UINT32 ComputerNameLen = 0;
|
|
Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */
|
|
Stream_Read_UINT32(s, CodePage); /* CodePage (4 bytes), MUST be set to zero */
|
|
Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */
|
|
@@ -617,17 +609,13 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
|
|
*/
|
|
static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- UINT32 ioCode1 = 0;
|
|
- UINT32 extendedPdu = 0;
|
|
- UINT32 extraFlags1 = 0;
|
|
- UINT32 SpecialTypeDeviceCap = 0;
|
|
- const RDPDR_CAPABILITY_HEADER header = { CAP_GENERAL_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH + 36,
|
|
- GENERAL_CAPABILITY_VERSION_02 };
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- ioCode1 = 0;
|
|
+ const RDPDR_CAPABILITY_HEADER header = { CAP_GENERAL_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH + 36,
|
|
+ GENERAL_CAPABILITY_VERSION_02 };
|
|
+
|
|
+ UINT32 ioCode1 = 0;
|
|
ioCode1 |= RDPDR_IRP_MJ_CREATE; /* always set */
|
|
ioCode1 |= RDPDR_IRP_MJ_CLEANUP; /* always set */
|
|
ioCode1 |= RDPDR_IRP_MJ_CLOSE; /* always set */
|
|
@@ -644,7 +632,8 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* contex
|
|
ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL; /* always set */
|
|
ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY; /* optional */
|
|
ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY; /* optional */
|
|
- extendedPdu = 0;
|
|
+
|
|
+ UINT32 extendedPdu = 0;
|
|
extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU; /* always set */
|
|
extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS; /* optional */
|
|
|
|
@@ -652,9 +641,9 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* contex
|
|
if (priv->UserLoggedOnPdu)
|
|
extendedPdu |= RDPDR_USER_LOGGEDON_PDU; /* optional */
|
|
|
|
- extraFlags1 = 0;
|
|
+ UINT32 extraFlags1 = 0;
|
|
extraFlags1 |= ENABLE_ASYNCIO; /* optional */
|
|
- SpecialTypeDeviceCap = 0;
|
|
+ UINT32 SpecialTypeDeviceCap = 0;
|
|
|
|
UINT error = rdpdr_write_capset_header(priv->log, s, &header);
|
|
if (error != CHANNEL_RC_OK)
|
|
@@ -703,12 +692,13 @@ static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* context
|
|
*/
|
|
static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- const RDPDR_CAPABILITY_HEADER header = { CAP_PRINTER_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
|
|
- PRINT_CAPABILITY_VERSION_01 };
|
|
WINPR_UNUSED(context);
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ const RDPDR_CAPABILITY_HEADER header = { CAP_PRINTER_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
|
|
+ PRINT_CAPABILITY_VERSION_01 };
|
|
+
|
|
return rdpdr_server_write_capability_set_header_cb(context, s, &header);
|
|
}
|
|
|
|
@@ -736,12 +726,13 @@ static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context, w
|
|
*/
|
|
static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- const RDPDR_CAPABILITY_HEADER header = { CAP_PORT_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
|
|
- PORT_CAPABILITY_VERSION_01 };
|
|
WINPR_UNUSED(context);
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ const RDPDR_CAPABILITY_HEADER header = { CAP_PORT_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
|
|
+ PORT_CAPABILITY_VERSION_01 };
|
|
+
|
|
return rdpdr_server_write_capability_set_header_cb(context, s, &header);
|
|
}
|
|
|
|
@@ -769,13 +760,13 @@ static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context,
|
|
*/
|
|
static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- const RDPDR_CAPABILITY_HEADER header = { CAP_DRIVE_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
|
|
- DRIVE_CAPABILITY_VERSION_02 };
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_UNUSED(context);
|
|
|
|
+ const RDPDR_CAPABILITY_HEADER header = { CAP_DRIVE_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
|
|
+ DRIVE_CAPABILITY_VERSION_02 };
|
|
+
|
|
return rdpdr_server_write_capability_set_header_cb(context, s, &header);
|
|
}
|
|
|
|
@@ -803,13 +794,13 @@ static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* conte
|
|
*/
|
|
static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- const RDPDR_CAPABILITY_HEADER header = { CAP_SMARTCARD_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
|
|
- SMARTCARD_CAPABILITY_VERSION_01 };
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
-
|
|
WINPR_UNUSED(context);
|
|
|
|
+ const RDPDR_CAPABILITY_HEADER header = { CAP_SMARTCARD_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
|
|
+ SMARTCARD_CAPABILITY_VERSION_01 };
|
|
+
|
|
return rdpdr_server_write_capability_set_header_cb(context, s, &header);
|
|
}
|
|
|
|
@@ -820,17 +811,10 @@ static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* cont
|
|
*/
|
|
static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
|
|
{
|
|
- wStream* s = nullptr;
|
|
- RDPDR_HEADER header = WINPR_C_ARRAY_INIT;
|
|
- UINT16 numCapabilities = 0;
|
|
- UINT error = 0;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- header.Component = RDPDR_CTYP_CORE;
|
|
- header.PacketId = PAKID_CORE_SERVER_CAPABILITY;
|
|
- numCapabilities = 1;
|
|
-
|
|
+ UINT16 numCapabilities = 1;
|
|
if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
|
|
numCapabilities++;
|
|
|
|
@@ -845,19 +829,23 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
numCapabilities++;
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
- s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 512);
|
|
-
|
|
+ wStream* s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 512);
|
|
if (!s)
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
+ const RDPDR_HEADER header = {
|
|
+ .Component = RDPDR_CTYP_CORE,
|
|
+ .PacketId = PAKID_CORE_SERVER_CAPABILITY,
|
|
+ };
|
|
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
|
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
|
Stream_Write_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
|
|
Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */
|
|
|
|
+ UINT error = 0;
|
|
if ((error = rdpdr_server_write_general_capability_set(context, s)))
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR,
|
|
@@ -943,9 +931,6 @@ static UINT16 rdpdr_cap_type_to_dtyp(UINT16 capabilityType)
|
|
static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* context, wStream* s,
|
|
const RDPDR_HEADER* header)
|
|
{
|
|
- UINT status = 0;
|
|
- UINT16 numCapabilities = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -956,6 +941,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT16 numCapabilities = 0;
|
|
Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
|
|
Stream_Seek_UINT16(s); /* Padding (2 bytes) */
|
|
|
|
@@ -965,6 +951,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
RDPDR_CAPABILITY_HEADER capabilityHeader = WINPR_C_ARRAY_INIT;
|
|
const size_t start = Stream_GetPosition(s);
|
|
|
|
+ UINT status = 0;
|
|
if ((status = rdpdr_read_capset_header(priv->log, s, &capabilityHeader)))
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR, "failed with error %" PRIu32 "!", status);
|
|
@@ -1067,24 +1054,21 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
*/
|
|
static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
|
|
{
|
|
- wStream* s = nullptr;
|
|
- RDPDR_HEADER header = WINPR_C_ARRAY_INIT;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- header.Component = RDPDR_CTYP_CORE;
|
|
- header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
|
|
-
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
- s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 8);
|
|
-
|
|
+ wStream* s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 8);
|
|
if (!s)
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
+ const RDPDR_HEADER header = {
|
|
+ .Component = RDPDR_CTYP_CORE,
|
|
+ .PacketId = PAKID_CORE_CLIENTID_CONFIRM,
|
|
+ };
|
|
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
|
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
|
Stream_Write_UINT16(s, priv->VersionMajor); /* VersionMajor (2 bytes) */
|
|
@@ -1102,8 +1086,6 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
wStream* s,
|
|
const RDPDR_HEADER* header)
|
|
{
|
|
- UINT32 DeviceCount = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1114,17 +1096,16 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 DeviceCount = 0;
|
|
Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
|
|
WLog_Print(priv->log, WLOG_DEBUG, "DeviceCount: %" PRIu32 "", DeviceCount);
|
|
|
|
for (UINT32 i = 0; i < DeviceCount; i++)
|
|
{
|
|
- UINT error = 0;
|
|
- RdpdrDevice device = WINPR_C_ARRAY_INIT;
|
|
-
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ RdpdrDevice device = WINPR_C_ARRAY_INIT;
|
|
Stream_Read_UINT32(s, device.DeviceType); /* DeviceType (4 bytes) */
|
|
Stream_Read_UINT32(s, device.DeviceId); /* DeviceId (4 bytes) */
|
|
Stream_Read(s, device.PreferredDosName, 8); /* PreferredDosName (8 bytes) */
|
|
@@ -1137,7 +1118,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
if (!rdpdr_add_device(context->priv, &device))
|
|
return ERROR_INTERNAL_ERROR;
|
|
|
|
- error = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceAnnounce, context, &device);
|
|
+ UINT error = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceAnnounce, context, &device);
|
|
if (error != CHANNEL_RC_OK)
|
|
return error;
|
|
|
|
@@ -1219,9 +1200,6 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext* context, wStream* s,
|
|
const RDPDR_HEADER* header)
|
|
{
|
|
- UINT32 DeviceCount = 0;
|
|
- UINT32 DeviceType = 0;
|
|
- UINT32 DeviceId = 0;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1232,6 +1210,7 @@ static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 DeviceCount = 0;
|
|
Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
|
|
WLog_Print(priv->log, WLOG_DEBUG, "DeviceCount: %" PRIu32 "", DeviceCount);
|
|
|
|
@@ -1243,10 +1222,11 @@ static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 DeviceId = 0;
|
|
Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
|
|
device = rdpdr_get_device_by_id(context->priv, DeviceId);
|
|
WLog_Print(priv->log, WLOG_DEBUG, "Device %" PRIu32 " Id: 0x%08" PRIX32 "", i, DeviceId);
|
|
- DeviceType = 0;
|
|
+ UINT32 DeviceType = 0;
|
|
if (device)
|
|
DeviceType = device->DeviceType;
|
|
|
|
@@ -1305,7 +1285,12 @@ static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
|
|
WINPR_ATTR_UNUSED UINT32 FileId,
|
|
WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- const WCHAR* path = nullptr;
|
|
+ WINPR_ASSERT(context);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
+ return ERROR_INVALID_DATA;
|
|
+
|
|
UINT32 DesiredAccess = 0;
|
|
UINT32 AllocationSize = 0;
|
|
UINT32 FileAttributes = 0;
|
|
@@ -1313,13 +1298,6 @@ static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
|
|
UINT32 CreateDisposition = 0;
|
|
UINT32 CreateOptions = 0;
|
|
UINT32 PathLength = 0;
|
|
-
|
|
- WINPR_ASSERT(context);
|
|
-
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
- return ERROR_INVALID_DATA;
|
|
-
|
|
Stream_Read_UINT32(s, DesiredAccess);
|
|
Stream_Read_UINT32(s, AllocationSize);
|
|
Stream_Read_UINT32(s, FileAttributes);
|
|
@@ -1328,7 +1306,7 @@ static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
|
|
Stream_Read_UINT32(s, CreateOptions);
|
|
Stream_Read_UINT32(s, PathLength);
|
|
|
|
- path = rdpdr_read_ustring(priv->log, s, PathLength);
|
|
+ const WCHAR* path = rdpdr_read_ustring(priv->log, s, PathLength);
|
|
if (!path && (PathLength > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
@@ -1366,9 +1344,6 @@ static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context, wS
|
|
WINPR_ATTR_UNUSED UINT32 FileId,
|
|
WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- UINT32 Length = 0;
|
|
- UINT64 Offset = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1376,6 +1351,8 @@ static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context, wS
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 Length = 0;
|
|
+ UINT64 Offset = 0;
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Read_UINT64(s, Offset);
|
|
Stream_Seek(s, 20); /* Padding */
|
|
@@ -1395,9 +1372,6 @@ static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context, w
|
|
WINPR_ATTR_UNUSED UINT32 FileId,
|
|
WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- UINT32 Length = 0;
|
|
- UINT64 Offset = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1406,6 +1380,8 @@ static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context, w
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 Length = 0;
|
|
+ UINT64 Offset = 0;
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Read_UINT64(s, Offset);
|
|
Stream_Seek(s, 20); /* Padding */
|
|
@@ -1430,10 +1406,6 @@ static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* c
|
|
WINPR_ATTR_UNUSED UINT32 FileId,
|
|
WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- UINT32 OutputBufferLength = 0;
|
|
- UINT32 InputBufferLength = 0;
|
|
- UINT32 IoControlCode = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1442,6 +1414,9 @@ static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* c
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 OutputBufferLength = 0;
|
|
+ UINT32 InputBufferLength = 0;
|
|
+ UINT32 IoControlCode = 0;
|
|
Stream_Read_UINT32(s, OutputBufferLength);
|
|
Stream_Read_UINT32(s, InputBufferLength);
|
|
Stream_Read_UINT32(s, IoControlCode);
|
|
@@ -1464,15 +1439,14 @@ static UINT rdpdr_server_receive_io_query_volume_information_request(
|
|
RdpdrServerContext* context, wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
|
|
WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 Length = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 FsInformationClass = 0;
|
|
+ UINT32 Length = 0;
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
@@ -1498,9 +1472,6 @@ static UINT rdpdr_server_receive_io_set_volume_information_request(
|
|
RdpdrServerContext* context, wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
|
|
WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 Length = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1509,6 +1480,8 @@ static UINT rdpdr_server_receive_io_set_volume_information_request(
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 FsInformationClass = 0;
|
|
+ UINT32 Length = 0;
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
@@ -1536,9 +1509,6 @@ static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext
|
|
WINPR_ATTR_UNUSED UINT32 FileId,
|
|
WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 Length = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1547,6 +1517,8 @@ static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 FsInformationClass = 0;
|
|
+ UINT32 Length = 0;
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
@@ -1573,9 +1545,6 @@ static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext*
|
|
WINPR_ATTR_UNUSED UINT32 FileId,
|
|
WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 Length = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1584,6 +1553,8 @@ static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 FsInformationClass = 0;
|
|
+ UINT32 Length = 0;
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT32(s, Length);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
@@ -1610,10 +1581,6 @@ static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext*
|
|
WINPR_ATTR_UNUSED UINT32 FileId,
|
|
WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- BYTE InitialQuery = 0;
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 PathLength = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1622,6 +1589,9 @@ static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 FsInformationClass = 0;
|
|
+ BYTE InitialQuery = 0;
|
|
+ UINT32 PathLength = 0;
|
|
Stream_Read_UINT32(s, FsInformationClass);
|
|
Stream_Read_UINT8(s, InitialQuery);
|
|
Stream_Read_UINT32(s, PathLength);
|
|
@@ -1653,9 +1623,6 @@ static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext*
|
|
WINPR_ATTR_UNUSED UINT32 FileId,
|
|
WINPR_ATTR_UNUSED UINT32 CompletionId)
|
|
{
|
|
- BYTE WatchTree = 0;
|
|
- UINT32 CompletionFilter = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1664,6 +1631,8 @@ static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ BYTE WatchTree = 0;
|
|
+ UINT32 CompletionFilter = 0;
|
|
Stream_Read_UINT8(s, WatchTree);
|
|
Stream_Read_UINT32(s, CompletionFilter);
|
|
Stream_Seek(s, 27); /* Padding */
|
|
@@ -1754,12 +1723,6 @@ static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* con
|
|
static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context, wStream* s,
|
|
WINPR_ATTR_UNUSED const RDPDR_HEADER* header)
|
|
{
|
|
- UINT32 DeviceId = 0;
|
|
- UINT32 FileId = 0;
|
|
- UINT32 CompletionId = 0;
|
|
- UINT32 MajorFunction = 0;
|
|
- UINT32 MinorFunction = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
@@ -1769,6 +1732,11 @@ static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 DeviceId = 0;
|
|
+ UINT32 FileId = 0;
|
|
+ UINT32 CompletionId = 0;
|
|
+ UINT32 MajorFunction = 0;
|
|
+ UINT32 MinorFunction = 0;
|
|
Stream_Read_UINT32(s, DeviceId);
|
|
Stream_Read_UINT32(s, FileId);
|
|
Stream_Read_UINT32(s, CompletionId);
|
|
@@ -1836,11 +1804,6 @@ static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
|
|
static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* context, wStream* s,
|
|
const RDPDR_HEADER* header)
|
|
{
|
|
- UINT32 deviceId = 0;
|
|
- UINT32 completionId = 0;
|
|
- UINT32 ioStatus = 0;
|
|
- RDPDR_IRP* irp = nullptr;
|
|
- UINT error = CHANNEL_RC_OK;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(s);
|
|
@@ -1853,13 +1816,16 @@ static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* contex
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 deviceId = 0;
|
|
+ UINT32 completionId = 0;
|
|
+ UINT32 ioStatus = 0;
|
|
Stream_Read_UINT32(s, deviceId);
|
|
Stream_Read_UINT32(s, completionId);
|
|
Stream_Read_UINT32(s, ioStatus);
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
"deviceId=%" PRIu32 ", completionId=0x%" PRIx32 ", ioStatus=0x%" PRIx32 "", deviceId,
|
|
completionId, ioStatus);
|
|
- irp = rdpdr_server_dequeue_irp(context, completionId);
|
|
+ RDPDR_IRP* irp = rdpdr_server_dequeue_irp(context, completionId);
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -1869,6 +1835,7 @@ static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* contex
|
|
}
|
|
|
|
/* Invoke the callback. */
|
|
+ UINT error = CHANNEL_RC_OK;
|
|
if (irp->Callback)
|
|
{
|
|
error = (*irp->Callback)(context, s, irp, deviceId, completionId, ioStatus);
|
|
@@ -1884,24 +1851,21 @@ static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* contex
|
|
*/
|
|
static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
|
|
{
|
|
- wStream* s = nullptr;
|
|
- RDPDR_HEADER header = WINPR_C_ARRAY_INIT;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- header.Component = RDPDR_CTYP_CORE;
|
|
- header.PacketId = PAKID_CORE_USER_LOGGEDON;
|
|
-
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
- s = Stream_New(nullptr, RDPDR_HEADER_LENGTH);
|
|
-
|
|
+ wStream* s = Stream_New(nullptr, RDPDR_HEADER_LENGTH);
|
|
if (!s)
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
return CHANNEL_RC_NO_MEMORY;
|
|
}
|
|
|
|
+ const RDPDR_HEADER header = {
|
|
+ .Component = RDPDR_CTYP_CORE,
|
|
+ .PacketId = PAKID_CORE_USER_LOGGEDON,
|
|
+ };
|
|
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
|
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
|
return rdpdr_seal_send_free_request(context, s);
|
|
@@ -1909,15 +1873,6 @@ static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
|
|
|
|
static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- char PortDosName[9] = WINPR_C_ARRAY_INIT;
|
|
- UINT32 PnPNameLen = 0;
|
|
- UINT32 DriverNameLen = 0;
|
|
- UINT32 PrinterNameLen = 0;
|
|
- UINT32 CachedFieldsLen = 0;
|
|
- const WCHAR* PnPName = nullptr;
|
|
- const WCHAR* DriverName = nullptr;
|
|
- const WCHAR* PrinterName = nullptr;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1926,19 +1881,24 @@ static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* conte
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 24))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ char PortDosName[9] = WINPR_C_ARRAY_INIT;
|
|
+ UINT32 PnPNameLen = 0;
|
|
+ UINT32 DriverNameLen = 0;
|
|
+ UINT32 PrinterNameLen = 0;
|
|
+ UINT32 CachedFieldsLen = 0;
|
|
Stream_Read(s, PortDosName, 8);
|
|
Stream_Read_UINT32(s, PnPNameLen);
|
|
Stream_Read_UINT32(s, DriverNameLen);
|
|
Stream_Read_UINT32(s, PrinterNameLen);
|
|
Stream_Read_UINT32(s, CachedFieldsLen);
|
|
|
|
- PnPName = rdpdr_read_ustring(priv->log, s, PnPNameLen);
|
|
+ const WCHAR* PnPName = rdpdr_read_ustring(priv->log, s, PnPNameLen);
|
|
if (!PnPName && (PnPNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
- DriverName = rdpdr_read_ustring(priv->log, s, DriverNameLen);
|
|
+ const WCHAR* DriverName = rdpdr_read_ustring(priv->log, s, DriverNameLen);
|
|
if (!DriverName && (DriverNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
- PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
+ const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
if (!PrinterName && (PrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
@@ -1954,10 +1914,6 @@ static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* conte
|
|
|
|
static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- UINT32 PrinterNameLen = 0;
|
|
- UINT32 CachedFieldsLen = 0;
|
|
- const WCHAR* PrinterName = nullptr;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
@@ -1965,10 +1921,12 @@ static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* co
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 PrinterNameLen = 0;
|
|
+ UINT32 CachedFieldsLen = 0;
|
|
Stream_Read_UINT32(s, PrinterNameLen);
|
|
Stream_Read_UINT32(s, CachedFieldsLen);
|
|
|
|
- PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
+ const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
if (!PrinterName && (PrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
@@ -1986,9 +1944,6 @@ static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* co
|
|
|
|
static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- UINT32 PrinterNameLen = 0;
|
|
- const WCHAR* PrinterName = nullptr;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -1997,9 +1952,10 @@ static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* co
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 PrinterNameLen = 0;
|
|
Stream_Read_UINT32(s, PrinterNameLen);
|
|
|
|
- PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
+ const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
if (!PrinterName && (PrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
@@ -2012,11 +1968,6 @@ static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* co
|
|
|
|
static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext* context, wStream* s)
|
|
{
|
|
- UINT32 OldPrinterNameLen = 0;
|
|
- UINT32 NewPrinterNameLen = 0;
|
|
- const WCHAR* OldPrinterName = nullptr;
|
|
- const WCHAR* NewPrinterName = nullptr;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -2025,13 +1976,15 @@ static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 OldPrinterNameLen = 0;
|
|
+ UINT32 NewPrinterNameLen = 0;
|
|
Stream_Read_UINT32(s, OldPrinterNameLen);
|
|
Stream_Read_UINT32(s, NewPrinterNameLen);
|
|
|
|
- OldPrinterName = rdpdr_read_ustring(priv->log, s, OldPrinterNameLen);
|
|
+ const WCHAR* OldPrinterName = rdpdr_read_ustring(priv->log, s, OldPrinterNameLen);
|
|
if (!OldPrinterName && (OldPrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
- NewPrinterName = rdpdr_read_ustring(priv->log, s, NewPrinterNameLen);
|
|
+ const WCHAR* NewPrinterName = rdpdr_read_ustring(priv->log, s, NewPrinterNameLen);
|
|
if (!NewPrinterName && (NewPrinterNameLen > 0))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
@@ -2046,8 +1999,6 @@ static UINT
|
|
rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context, wStream* s,
|
|
WINPR_ATTR_UNUSED const RDPDR_HEADER* header)
|
|
{
|
|
- UINT32 EventId = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
@@ -2056,6 +2007,7 @@ rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context, wStream
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 EventId = 0;
|
|
Stream_Read_UINT32(s, EventId);
|
|
switch (EventId)
|
|
{
|
|
@@ -2077,9 +2029,6 @@ rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context, wStream
|
|
static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* context, wStream* s,
|
|
WINPR_ATTR_UNUSED const RDPDR_HEADER* header)
|
|
{
|
|
- UINT32 PrinterId = 0;
|
|
- UINT32 Flags = 0;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(header);
|
|
@@ -2089,6 +2038,8 @@ static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* conte
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 PrinterId = 0;
|
|
+ UINT32 Flags = 0;
|
|
Stream_Read_UINT32(s, PrinterId);
|
|
Stream_Read_UINT32(s, Flags);
|
|
|
|
@@ -2227,20 +2178,19 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
|
|
|
static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
{
|
|
- DWORD status = 0;
|
|
- DWORD nCount = 0;
|
|
- void* buffer = nullptr;
|
|
- HANDLE events[8] = WINPR_C_ARRAY_INIT;
|
|
- HANDLE ChannelEvent = nullptr;
|
|
- DWORD BytesReturned = 0;
|
|
- UINT error = 0;
|
|
RdpdrServerContext* context = (RdpdrServerContext*)arg;
|
|
- wStream* s = Stream_New(nullptr, 4096);
|
|
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ UINT error = 0;
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
+ DWORD nCount = 0;
|
|
+ void* buffer = nullptr;
|
|
+ HANDLE events[8] = WINPR_C_ARRAY_INIT;
|
|
+ HANDLE ChannelEvent = nullptr;
|
|
+ DWORD BytesReturned = 0;
|
|
+ wStream* s = Stream_New(nullptr, 4096);
|
|
|
|
if (!s)
|
|
{
|
|
@@ -2273,7 +2223,7 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
{
|
|
size_t capacity = 0;
|
|
BytesReturned = 0;
|
|
- status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
|
+ DWORD status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
|
|
|
if (status == WAIT_FAILED)
|
|
{
|
|
@@ -2399,19 +2349,17 @@ static UINT rdpdr_server_start(RdpdrServerContext* context)
|
|
*/
|
|
static UINT rdpdr_server_stop(RdpdrServerContext* context)
|
|
{
|
|
- UINT error = 0;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
-
|
|
if (priv->StopEvent)
|
|
{
|
|
(void)SetEvent(priv->StopEvent);
|
|
|
|
if (WaitForSingleObject(priv->Thread, INFINITE) == WAIT_FAILED)
|
|
{
|
|
- error = GetLastError();
|
|
+ UINT error = GetLastError();
|
|
WLog_Print(priv->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!",
|
|
error);
|
|
return error;
|
|
@@ -2452,7 +2400,6 @@ static void rdpdr_server_write_device_iorequest(wStream* s, UINT32 deviceId, UIN
|
|
static UINT rdpdr_server_read_file_directory_information(wLog* log, wStream* s,
|
|
FILE_DIRECTORY_INFORMATION* fdi)
|
|
{
|
|
- UINT32 fileNameLength = 0;
|
|
WINPR_ASSERT(fdi);
|
|
ZeroMemory(fdi, sizeof(FILE_DIRECTORY_INFORMATION));
|
|
|
|
@@ -2468,6 +2415,7 @@ static UINT rdpdr_server_read_file_directory_information(wLog* log, wStream* s,
|
|
Stream_Read_INT64(s, fdi->EndOfFile.QuadPart); /* EndOfFile (8 bytes) */
|
|
Stream_Read_INT64(s, fdi->AllocationSize.QuadPart); /* AllocationSize (8 bytes) */
|
|
Stream_Read_UINT32(s, fdi->FileAttributes); /* FileAttributes (4 bytes) */
|
|
+ UINT32 fileNameLength = 0;
|
|
Stream_Read_UINT32(s, fileNameLength); /* FileNameLength (4 bytes) */
|
|
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(log, s, fileNameLength))
|
|
@@ -2497,8 +2445,6 @@ static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context,
|
|
UINT32 desiredAccess, UINT32 createOptions,
|
|
UINT32 createDisposition)
|
|
{
|
|
- size_t pathLength = 0;
|
|
- wStream* s = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -2510,8 +2456,8 @@ static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context,
|
|
" createDisposition=0x%" PRIx32 "",
|
|
deviceId, path, desiredAccess, createOptions, createDisposition);
|
|
/* Compute the required Unicode size. */
|
|
- pathLength = (strlen(path) + 1U) * sizeof(WCHAR);
|
|
- s = Stream_New(nullptr, 256U + pathLength);
|
|
+ size_t pathLength = (strlen(path) + 1U) * sizeof(WCHAR);
|
|
+ wStream* s = Stream_New(nullptr, 256U + pathLength);
|
|
|
|
if (!s)
|
|
{
|
|
@@ -2547,7 +2493,6 @@ static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context,
|
|
static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context, UINT32 deviceId,
|
|
UINT32 fileId, UINT32 completionId)
|
|
{
|
|
- wStream* s = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -2556,7 +2501,7 @@ static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context,
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
"RdpdrServerSendDeviceCloseRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32 "",
|
|
deviceId, fileId);
|
|
- s = Stream_New(nullptr, 128);
|
|
+ wStream* s = Stream_New(nullptr, 128);
|
|
|
|
if (!s)
|
|
{
|
|
@@ -2578,7 +2523,6 @@ static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, U
|
|
UINT32 fileId, UINT32 completionId, UINT32 length,
|
|
UINT32 offset)
|
|
{
|
|
- wStream* s = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -2588,7 +2532,7 @@ static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, U
|
|
"RdpdrServerSendDeviceReadRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32
|
|
", length=%" PRIu32 ", offset=%" PRIu32 "",
|
|
deviceId, fileId, length, offset);
|
|
- s = Stream_New(nullptr, 128);
|
|
+ wStream* s = Stream_New(nullptr, 128);
|
|
|
|
if (!s)
|
|
{
|
|
@@ -2613,7 +2557,6 @@ static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context,
|
|
UINT32 fileId, UINT32 completionId,
|
|
const char* data, UINT32 length, UINT32 offset)
|
|
{
|
|
- wStream* s = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -2623,7 +2566,7 @@ static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context,
|
|
"RdpdrServerSendDeviceWriteRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32
|
|
", length=%" PRIu32 ", offset=%" PRIu32 "",
|
|
deviceId, fileId, length, offset);
|
|
- s = Stream_New(nullptr, 64 + length);
|
|
+ wStream* s = Stream_New(nullptr, 64 + length);
|
|
|
|
if (!s)
|
|
{
|
|
@@ -2649,8 +2592,6 @@ static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext*
|
|
UINT32 deviceId, UINT32 fileId,
|
|
UINT32 completionId, const char* path)
|
|
{
|
|
- size_t pathLength = 0;
|
|
- wStream* s = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -2661,8 +2602,8 @@ static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext*
|
|
", path=%s",
|
|
deviceId, fileId, path);
|
|
/* Compute the required Unicode size. */
|
|
- pathLength = path ? (strlen(path) + 1) * sizeof(WCHAR) : 0;
|
|
- s = Stream_New(nullptr, 64 + pathLength);
|
|
+ size_t pathLength = path ? (strlen(path) + 1) * sizeof(WCHAR) : 0;
|
|
+ wStream* s = Stream_New(nullptr, 64 + pathLength);
|
|
|
|
if (!s)
|
|
{
|
|
@@ -2701,8 +2642,6 @@ static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* con
|
|
UINT32 deviceId, UINT32 fileId,
|
|
UINT32 completionId, const char* path)
|
|
{
|
|
- size_t pathLength = 0;
|
|
- wStream* s = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
@@ -2713,8 +2652,8 @@ static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* con
|
|
", path=%s",
|
|
deviceId, fileId, path);
|
|
/* Compute the required Unicode size. */
|
|
- pathLength = path ? (strlen(path) + 1) * sizeof(WCHAR) : 0;
|
|
- s = Stream_New(nullptr, 64 + pathLength);
|
|
+ size_t pathLength = path ? (strlen(path) + 1) * sizeof(WCHAR) : 0;
|
|
+ wStream* s = Stream_New(nullptr, 64 + pathLength);
|
|
|
|
if (!s)
|
|
{
|
|
@@ -2851,14 +2790,13 @@ static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* co
|
|
static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context, void* callbackData,
|
|
UINT32 deviceId, const char* path)
|
|
{
|
|
- RDPDR_IRP* irp = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(callbackData);
|
|
WINPR_ASSERT(path);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
- irp = rdpdr_server_irp_new();
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -2977,12 +2915,11 @@ static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* co
|
|
static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context, void* callbackData,
|
|
UINT32 deviceId, const char* path)
|
|
{
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- WINPR_ASSERT(irp);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -3023,10 +2960,6 @@ static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* con
|
|
RDPDR_IRP* irp, UINT32 deviceId,
|
|
UINT32 completionId, UINT32 ioStatus)
|
|
{
|
|
- UINT error = 0;
|
|
- UINT32 length = 0;
|
|
- FILE_DIRECTORY_INFORMATION fdi = WINPR_C_ARRAY_INIT;
|
|
-
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
@@ -3040,11 +2973,14 @@ static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* con
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 length = 0;
|
|
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
|
|
+ FILE_DIRECTORY_INFORMATION fdi = WINPR_C_ARRAY_INIT;
|
|
if (length > 0)
|
|
{
|
|
- if ((error = rdpdr_server_read_file_directory_information(priv->log, s, &fdi)))
|
|
+ UINT error = rdpdr_server_read_file_directory_information(priv->log, s, &fdi);
|
|
+ if (error)
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_read_file_directory_information failed with error %" PRIu32
|
|
@@ -3151,12 +3087,11 @@ static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* con
|
|
static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context, void* callbackData,
|
|
UINT32 deviceId, const char* path)
|
|
{
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- WINPR_ASSERT(irp);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -3231,12 +3166,11 @@ static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context, void* call
|
|
UINT32 deviceId, const char* path, UINT32 desiredAccess,
|
|
UINT32 createDisposition)
|
|
{
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- WINPR_ASSERT(irp);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -3277,8 +3211,6 @@ static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, w
|
|
RDPDR_IRP* irp, UINT32 deviceId,
|
|
UINT32 completionId, UINT32 ioStatus)
|
|
{
|
|
- UINT32 length = 0;
|
|
- char* buffer = nullptr;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
@@ -3292,11 +3224,13 @@ static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, w
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 length = 0;
|
|
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, length))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ char* buffer = nullptr;
|
|
if (length > 0)
|
|
{
|
|
buffer = Stream_Pointer(s);
|
|
@@ -3319,12 +3253,11 @@ static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context, void* call
|
|
UINT32 deviceId, UINT32 fileId, UINT32 length,
|
|
UINT32 offset)
|
|
{
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- WINPR_ASSERT(irp);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -3364,7 +3297,6 @@ static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
|
|
RDPDR_IRP* irp, UINT32 deviceId,
|
|
UINT32 completionId, UINT32 ioStatus)
|
|
{
|
|
- UINT32 length = 0;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
@@ -3378,6 +3310,7 @@ static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 length = 0;
|
|
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
Stream_Seek(s, 1); /* Padding (1 byte) */
|
|
|
|
@@ -3400,12 +3333,11 @@ static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, void* cal
|
|
UINT32 deviceId, UINT32 fileId, const char* buffer,
|
|
UINT32 length, UINT32 offset)
|
|
{
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- WINPR_ASSERT(irp);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -3478,12 +3410,11 @@ static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context,
|
|
static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, void* callbackData,
|
|
UINT32 deviceId, UINT32 fileId)
|
|
{
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- WINPR_ASSERT(irp);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -3600,12 +3531,11 @@ static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context
|
|
static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context, void* callbackData,
|
|
UINT32 deviceId, const char* path)
|
|
{
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
- WINPR_ASSERT(irp);
|
|
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
|
|
if (!irp)
|
|
{
|
|
@@ -3671,7 +3601,6 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context
|
|
RDPDR_IRP* irp, UINT32 deviceId,
|
|
UINT32 completionId, UINT32 ioStatus)
|
|
{
|
|
- UINT32 length = 0;
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
WINPR_ASSERT(irp);
|
|
@@ -3685,6 +3614,7 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
+ UINT32 length = 0;
|
|
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
Stream_Seek(s, 1); /* Padding (1 byte) */
|
|
/* Invoke the rename file completion routine. */
|
|
|
|
From d67800b0d1c7ac10f574a56bcfb8d36e3f17bd3f Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Mon, 22 Jun 2026 21:36:20 +0200
|
|
Subject: [PATCH 14/31] [channels,rdpdr] migrate Stream API usage
|
|
|
|
- Stream_Read_UINT32/UINT16 to Stream_Get_UINT32/UINT16
|
|
- Stream_Free to Stream_Release
|
|
- Stream_Pointer to Stream_PointerAs
|
|
|
|
Co-Authored-By: David Fort <contact@hardening-consulting.com>
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 271 +++++++++++------------------
|
|
1 file changed, 104 insertions(+), 167 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 488efca5bc46..132f0746a17a 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -281,9 +281,10 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
|
|
|
|
if (length >= RDPDR_HEADER_LENGTH)
|
|
{
|
|
- RDPDR_HEADER header = WINPR_C_ARRAY_INIT;
|
|
- Stream_Read_UINT16(s, header.Component);
|
|
- Stream_Read_UINT16(s, header.PacketId);
|
|
+ const RDPDR_HEADER header = {
|
|
+ .Component = Stream_Get_UINT16(s),
|
|
+ .PacketId = Stream_Get_UINT16(s),
|
|
+ };
|
|
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
"sending message {Component %s[%04" PRIx16 "], PacketId %s[%04" PRIx16 "]",
|
|
@@ -294,7 +295,7 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
|
|
ULONG written = 0;
|
|
BOOL status = WTSVirtualChannelWrite(priv->ChannelHandle, Stream_BufferAs(s, char),
|
|
(ULONG)length, &written);
|
|
- Stream_Free(s, TRUE);
|
|
+ Stream_Release(s);
|
|
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
|
}
|
|
|
|
@@ -351,12 +352,9 @@ static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT16 VersionMajor = 0;
|
|
- UINT16 VersionMinor = 0;
|
|
- UINT32 ClientId = 0;
|
|
- Stream_Read_UINT16(s, VersionMajor); /* VersionMajor (2 bytes) */
|
|
- Stream_Read_UINT16(s, VersionMinor); /* VersionMinor (2 bytes) */
|
|
- Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */
|
|
+ const UINT16 VersionMajor = Stream_Get_UINT16(s); /* VersionMajor (2 bytes) */
|
|
+ const UINT16 VersionMinor = Stream_Get_UINT16(s); /* VersionMinor (2 bytes) */
|
|
+ const UINT32 ClientId = Stream_Get_UINT32(s); /* ClientId (4 bytes) */
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
"Client Announce Response: VersionMajor: 0x%08" PRIX16 " VersionMinor: 0x%04" PRIX16
|
|
" ClientId: 0x%08" PRIX32 "",
|
|
@@ -386,12 +384,9 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 UnicodeFlag = 0;
|
|
- UINT32 CodePage = 0;
|
|
- UINT32 ComputerNameLen = 0;
|
|
- Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */
|
|
- Stream_Read_UINT32(s, CodePage); /* CodePage (4 bytes), MUST be set to zero */
|
|
- Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */
|
|
+ UINT32 UnicodeFlag = Stream_Get_UINT32(s); /* UnicodeFlag (4 bytes) */
|
|
+ const UINT32 CodePage = Stream_Get_UINT32(s); /* CodePage (4 bytes) */
|
|
+ const UINT32 ComputerNameLen = Stream_Get_UINT32(s); /* ComputerNameLen (4 bytes) */
|
|
/* UnicodeFlag is either 0 or 1, the other 31 bits must be ignored.
|
|
*/
|
|
UnicodeFlag = UnicodeFlag & 0x00000001;
|
|
@@ -502,18 +497,19 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- const UINT32 OsType = Stream_Get_UINT32(s); /* osType (4 bytes), ignored on receipt */
|
|
- const UINT32 OsVersion =
|
|
- Stream_Get_UINT32(s); /* osVersion (4 bytes), unused and must be set to zero */
|
|
+ const UINT32 OsType = Stream_Get_UINT32(s); /* osType (4 bytes),
|
|
+ ignored on receipt */
|
|
+ const UINT32 OsVersion = Stream_Get_UINT32(s); /* osVersion (4 bytes),
|
|
+ unused and must be set to zero */
|
|
const UINT32 VersionMajor = Stream_Get_UINT16(s); /* protocolMajorVersion (2 bytes) */
|
|
const UINT32 VersionMinor = Stream_Get_UINT16(s); /* protocolMinorVersion (2 bytes) */
|
|
const UINT32 IoCode1 = Stream_Get_UINT32(s); /* ioCode1 (4 bytes) */
|
|
- const UINT32 IoCode2 =
|
|
- Stream_Get_UINT32(s); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */
|
|
+ const UINT32 IoCode2 = Stream_Get_UINT32(s); /* ioCode2 (4 bytes),
|
|
+ must be set to zero, reserved for future use */
|
|
const UINT32 ExtendedPdu = Stream_Get_UINT32(s); /* extendedPdu (4 bytes) */
|
|
const UINT32 ExtraFlags1 = Stream_Get_UINT32(s); /* extraFlags1 (4 bytes) */
|
|
- const UINT32 ExtraFlags2 = Stream_Get_UINT32(
|
|
- s); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */
|
|
+ const UINT32 ExtraFlags2 = Stream_Get_UINT32(s); /* extraFlags2 (4 bytes),
|
|
+ must be set to zero, reserved for future use */
|
|
|
|
{
|
|
char buffer[1024] = WINPR_C_ARRAY_INIT;
|
|
@@ -901,7 +897,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
|
|
|
return rdpdr_seal_send_free_request(context, s);
|
|
out:
|
|
- Stream_Free(s, TRUE);
|
|
+ Stream_Release(s);
|
|
return error;
|
|
}
|
|
|
|
@@ -941,9 +937,8 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT16 numCapabilities = 0;
|
|
- Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
|
|
- Stream_Seek_UINT16(s); /* Padding (2 bytes) */
|
|
+ const UINT16 numCapabilities = Stream_Get_UINT16(s); /* numCapabilities (2 bytes) */
|
|
+ Stream_Seek_UINT16(s); /* Padding (2 bytes) */
|
|
|
|
UINT16 caps = 0;
|
|
for (UINT16 i = 0; i < numCapabilities; i++)
|
|
@@ -1096,8 +1091,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 DeviceCount = 0;
|
|
- Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
|
|
+ const UINT32 DeviceCount = Stream_Get_UINT32(s); /* DeviceCount (4 bytes) */
|
|
WLog_Print(priv->log, WLOG_DEBUG, "DeviceCount: %" PRIu32 "", DeviceCount);
|
|
|
|
for (UINT32 i = 0; i < DeviceCount; i++)
|
|
@@ -1106,11 +1100,11 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
return ERROR_INVALID_DATA;
|
|
|
|
RdpdrDevice device = WINPR_C_ARRAY_INIT;
|
|
- Stream_Read_UINT32(s, device.DeviceType); /* DeviceType (4 bytes) */
|
|
- Stream_Read_UINT32(s, device.DeviceId); /* DeviceId (4 bytes) */
|
|
+ device.DeviceType = Stream_Get_UINT32(s); /* DeviceType (4 bytes) */
|
|
+ device.DeviceId = Stream_Get_UINT32(s); /* DeviceId (4 bytes) */
|
|
Stream_Read(s, device.PreferredDosName, 8); /* PreferredDosName (8 bytes) */
|
|
- Stream_Read_UINT32(s, device.DeviceDataLength); /* DeviceDataLength (4 bytes) */
|
|
- device.DeviceData = Stream_Pointer(s);
|
|
+ device.DeviceDataLength = Stream_Get_UINT32(s); /* DeviceDataLength (4 bytes) */
|
|
+ device.DeviceData = Stream_PointerAs(s, BYTE);
|
|
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, device.DeviceDataLength))
|
|
return ERROR_INVALID_DATA;
|
|
@@ -1210,8 +1204,7 @@ static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 DeviceCount = 0;
|
|
- Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
|
|
+ const UINT32 DeviceCount = Stream_Get_UINT32(s); /* DeviceCount (4 bytes) */
|
|
WLog_Print(priv->log, WLOG_DEBUG, "DeviceCount: %" PRIu32 "", DeviceCount);
|
|
|
|
for (UINT32 i = 0; i < DeviceCount; i++)
|
|
@@ -1222,8 +1215,7 @@ static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 DeviceId = 0;
|
|
- Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
|
|
+ const UINT32 DeviceId = Stream_Get_UINT32(s); /* DeviceId (4 bytes) */
|
|
device = rdpdr_get_device_by_id(context->priv, DeviceId);
|
|
WLog_Print(priv->log, WLOG_DEBUG, "Device %" PRIu32 " Id: 0x%08" PRIX32 "", i, DeviceId);
|
|
UINT32 DeviceType = 0;
|
|
@@ -1291,20 +1283,13 @@ static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 DesiredAccess = 0;
|
|
- UINT32 AllocationSize = 0;
|
|
- UINT32 FileAttributes = 0;
|
|
- UINT32 SharedAccess = 0;
|
|
- UINT32 CreateDisposition = 0;
|
|
- UINT32 CreateOptions = 0;
|
|
- UINT32 PathLength = 0;
|
|
- Stream_Read_UINT32(s, DesiredAccess);
|
|
- Stream_Read_UINT32(s, AllocationSize);
|
|
- Stream_Read_UINT32(s, FileAttributes);
|
|
- Stream_Read_UINT32(s, SharedAccess);
|
|
- Stream_Read_UINT32(s, CreateDisposition);
|
|
- Stream_Read_UINT32(s, CreateOptions);
|
|
- Stream_Read_UINT32(s, PathLength);
|
|
+ WINPR_ATTR_UNUSED const UINT32 DesiredAccess = Stream_Get_UINT32(s);
|
|
+ WINPR_ATTR_UNUSED const UINT32 AllocationSize = Stream_Get_UINT32(s);
|
|
+ WINPR_ATTR_UNUSED const UINT32 FileAttributes = Stream_Get_UINT32(s);
|
|
+ WINPR_ATTR_UNUSED const UINT32 SharedAccess = Stream_Get_UINT32(s);
|
|
+ WINPR_ATTR_UNUSED const UINT32 CreateDisposition = Stream_Get_UINT32(s);
|
|
+ WINPR_ATTR_UNUSED const UINT32 CreateOptions = Stream_Get_UINT32(s);
|
|
+ const UINT32 PathLength = Stream_Get_UINT32(s);
|
|
|
|
const WCHAR* path = rdpdr_read_ustring(priv->log, s, PathLength);
|
|
if (!path && (PathLength > 0))
|
|
@@ -1351,10 +1336,8 @@ static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context, wS
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 Length = 0;
|
|
- UINT64 Offset = 0;
|
|
- Stream_Read_UINT32(s, Length);
|
|
- Stream_Read_UINT64(s, Offset);
|
|
+ const UINT32 Length = Stream_Get_UINT32(s);
|
|
+ const UINT64 Offset = Stream_Get_UINT64(s);
|
|
Stream_Seek(s, 20); /* Padding */
|
|
|
|
WLog_Print(priv->log, WLOG_DEBUG, "Got Offset [0x%016" PRIx64 "], Length %" PRIu32, Offset,
|
|
@@ -1380,10 +1363,8 @@ static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context, w
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 Length = 0;
|
|
- UINT64 Offset = 0;
|
|
- Stream_Read_UINT32(s, Length);
|
|
- Stream_Read_UINT64(s, Offset);
|
|
+ const UINT32 Length = Stream_Get_UINT32(s);
|
|
+ const UINT64 Offset = Stream_Get_UINT64(s);
|
|
Stream_Seek(s, 20); /* Padding */
|
|
|
|
WLog_Print(priv->log, WLOG_DEBUG, "Got Offset [0x%016" PRIx64 "], Length %" PRIu32, Offset,
|
|
@@ -1414,12 +1395,9 @@ static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* c
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 OutputBufferLength = 0;
|
|
- UINT32 InputBufferLength = 0;
|
|
- UINT32 IoControlCode = 0;
|
|
- Stream_Read_UINT32(s, OutputBufferLength);
|
|
- Stream_Read_UINT32(s, InputBufferLength);
|
|
- Stream_Read_UINT32(s, IoControlCode);
|
|
+ WINPR_ATTR_UNUSED const UINT32 OutputBufferLength = Stream_Get_UINT32(s);
|
|
+ WINPR_ATTR_UNUSED const UINT32 InputBufferLength = Stream_Get_UINT32(s);
|
|
+ WINPR_ATTR_UNUSED const UINT32 IoControlCode = Stream_Get_UINT32(s);
|
|
Stream_Seek(s, 20); /* Padding */
|
|
|
|
const BYTE* InputBuffer = Stream_ConstPointer(s);
|
|
@@ -1445,10 +1423,8 @@ static UINT rdpdr_server_receive_io_query_volume_information_request(
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 Length = 0;
|
|
- Stream_Read_UINT32(s, FsInformationClass);
|
|
- Stream_Read_UINT32(s, Length);
|
|
+ const UINT32 FsInformationClass = Stream_Get_UINT32(s);
|
|
+ const UINT32 Length = Stream_Get_UINT32(s);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
@@ -1480,10 +1456,8 @@ static UINT rdpdr_server_receive_io_set_volume_information_request(
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 Length = 0;
|
|
- Stream_Read_UINT32(s, FsInformationClass);
|
|
- Stream_Read_UINT32(s, Length);
|
|
+ const UINT32 FsInformationClass = Stream_Get_UINT32(s);
|
|
+ const UINT32 Length = Stream_Get_UINT32(s);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
@@ -1517,10 +1491,8 @@ static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 Length = 0;
|
|
- Stream_Read_UINT32(s, FsInformationClass);
|
|
- Stream_Read_UINT32(s, Length);
|
|
+ const UINT32 FsInformationClass = Stream_Get_UINT32(s);
|
|
+ const UINT32 Length = Stream_Get_UINT32(s);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
@@ -1553,10 +1525,8 @@ static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 FsInformationClass = 0;
|
|
- UINT32 Length = 0;
|
|
- Stream_Read_UINT32(s, FsInformationClass);
|
|
- Stream_Read_UINT32(s, Length);
|
|
+ const UINT32 FsInformationClass = Stream_Get_UINT32(s);
|
|
+ const UINT32 Length = Stream_Get_UINT32(s);
|
|
Stream_Seek(s, 24); /* Padding */
|
|
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
@@ -1589,12 +1559,9 @@ static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 FsInformationClass = 0;
|
|
- BYTE InitialQuery = 0;
|
|
- UINT32 PathLength = 0;
|
|
- Stream_Read_UINT32(s, FsInformationClass);
|
|
- Stream_Read_UINT8(s, InitialQuery);
|
|
- Stream_Read_UINT32(s, PathLength);
|
|
+ const UINT32 FsInformationClass = Stream_Get_UINT32(s);
|
|
+ const BYTE InitialQuery = Stream_Get_UINT8(s);
|
|
+ const UINT32 PathLength = Stream_Get_UINT32(s);
|
|
Stream_Seek(s, 23); /* Padding */
|
|
|
|
const WCHAR* wPath = rdpdr_read_ustring(priv->log, s, PathLength);
|
|
@@ -1631,10 +1598,8 @@ static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- BYTE WatchTree = 0;
|
|
- UINT32 CompletionFilter = 0;
|
|
- Stream_Read_UINT8(s, WatchTree);
|
|
- Stream_Read_UINT32(s, CompletionFilter);
|
|
+ WINPR_ATTR_UNUSED const BYTE WatchTree = Stream_Get_UINT8(s);
|
|
+ WINPR_ATTR_UNUSED const UINT32 CompletionFilter = Stream_Get_UINT32(s);
|
|
Stream_Seek(s, 27); /* Padding */
|
|
|
|
WLog_Print(priv->log, WLOG_WARN,
|
|
@@ -1697,14 +1662,11 @@ static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* con
|
|
|
|
for (UINT32 x = 0; x < NumLocks; x++)
|
|
{
|
|
- UINT64 Length = 0;
|
|
- UINT64 Offset = 0;
|
|
-
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 16))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- Stream_Read_UINT64(s, Length);
|
|
- Stream_Read_UINT64(s, Offset);
|
|
+ const UINT64 Length = Stream_Get_UINT64(s);
|
|
+ const UINT64 Offset = Stream_Get_UINT64(s);
|
|
|
|
WLog_Print(priv->log, WLOG_DEBUG, "Locking at Offset=0x%08" PRIx64 " [Length %" PRIu64 "]",
|
|
Offset, Length);
|
|
@@ -1732,16 +1694,11 @@ static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 DeviceId = 0;
|
|
- UINT32 FileId = 0;
|
|
- UINT32 CompletionId = 0;
|
|
- UINT32 MajorFunction = 0;
|
|
- UINT32 MinorFunction = 0;
|
|
- Stream_Read_UINT32(s, DeviceId);
|
|
- Stream_Read_UINT32(s, FileId);
|
|
- Stream_Read_UINT32(s, CompletionId);
|
|
- Stream_Read_UINT32(s, MajorFunction);
|
|
- Stream_Read_UINT32(s, MinorFunction);
|
|
+ const UINT32 DeviceId = Stream_Get_UINT32(s);
|
|
+ const UINT32 FileId = Stream_Get_UINT32(s);
|
|
+ const UINT32 CompletionId = Stream_Get_UINT32(s);
|
|
+ const UINT32 MajorFunction = Stream_Get_UINT32(s);
|
|
+ const UINT32 MinorFunction = Stream_Get_UINT32(s);
|
|
if ((MinorFunction != 0) && (MajorFunction != IRP_MJ_DIRECTORY_CONTROL))
|
|
WLog_Print(priv->log, WLOG_WARN,
|
|
"[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) MajorFunction=%s, "
|
|
@@ -1816,12 +1773,9 @@ static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* contex
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 deviceId = 0;
|
|
- UINT32 completionId = 0;
|
|
- UINT32 ioStatus = 0;
|
|
- Stream_Read_UINT32(s, deviceId);
|
|
- Stream_Read_UINT32(s, completionId);
|
|
- Stream_Read_UINT32(s, ioStatus);
|
|
+ const UINT32 deviceId = Stream_Get_UINT32(s);
|
|
+ const UINT32 completionId = Stream_Get_UINT32(s);
|
|
+ const UINT32 ioStatus = Stream_Get_UINT32(s);
|
|
WLog_Print(priv->log, WLOG_DEBUG,
|
|
"deviceId=%" PRIu32 ", completionId=0x%" PRIx32 ", ioStatus=0x%" PRIx32 "", deviceId,
|
|
completionId, ioStatus);
|
|
@@ -1882,15 +1836,11 @@ static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* conte
|
|
return ERROR_INVALID_DATA;
|
|
|
|
char PortDosName[9] = WINPR_C_ARRAY_INIT;
|
|
- UINT32 PnPNameLen = 0;
|
|
- UINT32 DriverNameLen = 0;
|
|
- UINT32 PrinterNameLen = 0;
|
|
- UINT32 CachedFieldsLen = 0;
|
|
Stream_Read(s, PortDosName, 8);
|
|
- Stream_Read_UINT32(s, PnPNameLen);
|
|
- Stream_Read_UINT32(s, DriverNameLen);
|
|
- Stream_Read_UINT32(s, PrinterNameLen);
|
|
- Stream_Read_UINT32(s, CachedFieldsLen);
|
|
+ const UINT32 PnPNameLen = Stream_Get_UINT32(s);
|
|
+ const UINT32 DriverNameLen = Stream_Get_UINT32(s);
|
|
+ const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
|
|
+ const UINT32 CachedFieldsLen = Stream_Get_UINT32(s);
|
|
|
|
const WCHAR* PnPName = rdpdr_read_ustring(priv->log, s, PnPNameLen);
|
|
if (!PnPName && (PnPNameLen > 0))
|
|
@@ -1921,10 +1871,8 @@ static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* co
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 PrinterNameLen = 0;
|
|
- UINT32 CachedFieldsLen = 0;
|
|
- Stream_Read_UINT32(s, PrinterNameLen);
|
|
- Stream_Read_UINT32(s, CachedFieldsLen);
|
|
+ const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
|
|
+ const UINT32 CachedFieldsLen = Stream_Get_UINT32(s);
|
|
|
|
const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
if (!PrinterName && (PrinterNameLen > 0))
|
|
@@ -1952,8 +1900,7 @@ static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* co
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 PrinterNameLen = 0;
|
|
- Stream_Read_UINT32(s, PrinterNameLen);
|
|
+ const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
|
|
|
|
const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
|
|
if (!PrinterName && (PrinterNameLen > 0))
|
|
@@ -1976,10 +1923,8 @@ static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext*
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 OldPrinterNameLen = 0;
|
|
- UINT32 NewPrinterNameLen = 0;
|
|
- Stream_Read_UINT32(s, OldPrinterNameLen);
|
|
- Stream_Read_UINT32(s, NewPrinterNameLen);
|
|
+ const UINT32 OldPrinterNameLen = Stream_Get_UINT32(s);
|
|
+ const UINT32 NewPrinterNameLen = Stream_Get_UINT32(s);
|
|
|
|
const WCHAR* OldPrinterName = rdpdr_read_ustring(priv->log, s, OldPrinterNameLen);
|
|
if (!OldPrinterName && (OldPrinterNameLen > 0))
|
|
@@ -2007,8 +1952,7 @@ rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context, wStream
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 EventId = 0;
|
|
- Stream_Read_UINT32(s, EventId);
|
|
+ const UINT32 EventId = Stream_Get_UINT32(s);
|
|
switch (EventId)
|
|
{
|
|
case RDPDR_ADD_PRINTER_EVENT:
|
|
@@ -2038,10 +1982,8 @@ static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* conte
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 PrinterId = 0;
|
|
- UINT32 Flags = 0;
|
|
- Stream_Read_UINT32(s, PrinterId);
|
|
- Stream_Read_UINT32(s, Flags);
|
|
+ const UINT32 PrinterId = Stream_Get_UINT32(s);
|
|
+ const UINT32 Flags = Stream_Get_UINT32(s);
|
|
|
|
WLog_Print(
|
|
priv->log, WLOG_WARN,
|
|
@@ -2279,10 +2221,10 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
|
|
while (Stream_GetRemainingLength(s) >= RDPDR_HEADER_LENGTH)
|
|
{
|
|
- RDPDR_HEADER header = WINPR_C_ARRAY_INIT;
|
|
-
|
|
- Stream_Read_UINT16(s, header.Component); /* Component (2 bytes) */
|
|
- Stream_Read_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
|
+ const RDPDR_HEADER header = {
|
|
+ .Component = Stream_Get_UINT16(s), /* Component (2 bytes) */
|
|
+ .PacketId = Stream_Get_UINT16(s), /* PacketId (2 bytes) */
|
|
+ };
|
|
|
|
if ((error = rdpdr_server_receive_pdu(context, s, &header)))
|
|
{
|
|
@@ -2295,7 +2237,7 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
}
|
|
|
|
out_stream:
|
|
- Stream_Free(s, TRUE);
|
|
+ Stream_Release(s);
|
|
out:
|
|
|
|
if (error && context->rdpcontext)
|
|
@@ -2406,17 +2348,16 @@ static UINT rdpdr_server_read_file_directory_information(wLog* log, wStream* s,
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 64))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- Stream_Read_UINT32(s, fdi->NextEntryOffset); /* NextEntryOffset (4 bytes) */
|
|
- Stream_Read_UINT32(s, fdi->FileIndex); /* FileIndex (4 bytes) */
|
|
- Stream_Read_INT64(s, fdi->CreationTime.QuadPart); /* CreationTime (8 bytes) */
|
|
- Stream_Read_INT64(s, fdi->LastAccessTime.QuadPart); /* LastAccessTime (8 bytes) */
|
|
- Stream_Read_INT64(s, fdi->LastWriteTime.QuadPart); /* LastWriteTime (8 bytes) */
|
|
- Stream_Read_INT64(s, fdi->ChangeTime.QuadPart); /* ChangeTime (8 bytes) */
|
|
- Stream_Read_INT64(s, fdi->EndOfFile.QuadPart); /* EndOfFile (8 bytes) */
|
|
- Stream_Read_INT64(s, fdi->AllocationSize.QuadPart); /* AllocationSize (8 bytes) */
|
|
- Stream_Read_UINT32(s, fdi->FileAttributes); /* FileAttributes (4 bytes) */
|
|
- UINT32 fileNameLength = 0;
|
|
- Stream_Read_UINT32(s, fileNameLength); /* FileNameLength (4 bytes) */
|
|
+ fdi->NextEntryOffset = Stream_Get_UINT32(s); /* NextEntryOffset (4 bytes) */
|
|
+ fdi->FileIndex = Stream_Get_UINT32(s); /* FileIndex (4 bytes) */
|
|
+ fdi->CreationTime.QuadPart = Stream_Get_INT64(s); /* CreationTime (8 bytes) */
|
|
+ fdi->LastAccessTime.QuadPart = Stream_Get_INT64(s); /* LastAccessTime (8 bytes) */
|
|
+ fdi->LastWriteTime.QuadPart = Stream_Get_INT64(s); /* LastWriteTime (8 bytes) */
|
|
+ fdi->ChangeTime.QuadPart = Stream_Get_INT64(s); /* ChangeTime (8 bytes) */
|
|
+ fdi->EndOfFile.QuadPart = Stream_Get_INT64(s); /* EndOfFile (8 bytes) */
|
|
+ fdi->AllocationSize.QuadPart = Stream_Get_INT64(s); /* AllocationSize (8 bytes) */
|
|
+ fdi->FileAttributes = Stream_Get_UINT32(s); /* FileAttributes (4 bytes) */
|
|
+ const UINT32 fileNameLength = Stream_Get_UINT32(s); /* FileNameLength (4 bytes) */
|
|
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(log, s, fileNameLength))
|
|
return ERROR_INVALID_DATA;
|
|
@@ -2479,7 +2420,7 @@ static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context,
|
|
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
|
|
pathLength / sizeof(WCHAR), TRUE) < 0)
|
|
{
|
|
- Stream_Free(s, TRUE);
|
|
+ Stream_Release(s);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
return rdpdr_seal_send_free_request(context, s);
|
|
@@ -2625,7 +2566,7 @@ static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext*
|
|
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
|
|
pathLength / sizeof(WCHAR), TRUE) < 0)
|
|
{
|
|
- Stream_Free(s, TRUE);
|
|
+ Stream_Release(s);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
}
|
|
@@ -2678,7 +2619,7 @@ static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* con
|
|
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
|
|
pathLength / sizeof(WCHAR), TRUE) < 0)
|
|
{
|
|
- Stream_Free(s, TRUE);
|
|
+ Stream_Release(s);
|
|
return ERROR_INTERNAL_ERROR;
|
|
}
|
|
}
|
|
@@ -2973,8 +2914,7 @@ static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* con
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 length = 0;
|
|
- Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
+ const UINT32 length = Stream_Get_UINT32(s); /* Length (4 bytes) */
|
|
|
|
FILE_DIRECTORY_INFORMATION fdi = WINPR_C_ARRAY_INIT;
|
|
if (length > 0)
|
|
@@ -3224,16 +3164,14 @@ static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, w
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 length = 0;
|
|
- Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
-
|
|
+ const UINT32 length = Stream_Get_UINT32(s); /* Length (4 bytes) */
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, length))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
char* buffer = nullptr;
|
|
if (length > 0)
|
|
{
|
|
- buffer = Stream_Pointer(s);
|
|
+ buffer = Stream_PointerAs(s, char);
|
|
Stream_Seek(s, length);
|
|
}
|
|
|
|
@@ -3310,9 +3248,8 @@ static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 length = 0;
|
|
- Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
- Stream_Seek(s, 1); /* Padding (1 byte) */
|
|
+ const UINT32 length = Stream_Get_UINT32(s); /* Length (4 bytes) */
|
|
+ Stream_Seek(s, 1); /* Padding (1 byte) */
|
|
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, length))
|
|
return ERROR_INVALID_DATA;
|
|
@@ -3614,9 +3551,9 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context
|
|
if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
|
|
return ERROR_INVALID_DATA;
|
|
|
|
- UINT32 length = 0;
|
|
- Stream_Read_UINT32(s, length); /* Length (4 bytes) */
|
|
- Stream_Seek(s, 1); /* Padding (1 byte) */
|
|
+ WINPR_ATTR_UNUSED const UINT32 length = Stream_Get_UINT32(s); /* Length (4 bytes) */
|
|
+ Stream_Seek(s, 1); /* Padding (1 byte) */
|
|
+
|
|
/* Invoke the rename file completion routine. */
|
|
context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
|
|
/* Setup the IRP. */
|
|
|
|
From 1c81bb4568234088886378e73d465e3717687271 Mon Sep 17 00:00:00 2001
|
|
From: David Fort <contact@hardening-consulting.com>
|
|
Date: Tue, 23 Jun 2026 20:07:50 +0200
|
|
Subject: [PATCH 15/31] [channels] handle CHANNEL_OPTION_SHOW_PROTOCOL
|
|
server-side
|
|
|
|
With some static channels like rdpdr or clipdr there's no marking of packet
|
|
length so in theory you can't handle packets that you don't know (you don't know
|
|
how many bytes to skip) or that are badly encoded (WTSVirtualChannelRead linearizes
|
|
the traffic so you can't know which bytes are part of the current PDU and which
|
|
bytes are from the next one). To solve that this patch adds server-side the handling
|
|
of a CHANNEL_OPTION_SHOW_PROTOCOL with WTSVirtualChannelOpen, when you set that
|
|
option you get CHANNEL_PDU_HEADER before the packet payload, and so you can do the
|
|
reassembly of a PDU. This allows to skip a PDU when you don't know the type, and
|
|
go to the next one correctly if for instance the padding at the end of the PDU is
|
|
incorrect (think of some smartcard commands invalidly padded by FreeRDP).
|
|
|
|
The patch also provides a ChannelPduTracker component that can do the reassembly
|
|
for you.
|
|
|
|
Co-Authored-By: Joan Torres Lopez <joantolo@redhat.com>
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 131 +++++++++++++----------------
|
|
1 file changed, 57 insertions(+), 74 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 132f0746a17a..06cd7a025ee4 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -33,6 +33,7 @@
|
|
|
|
#include <freerdp/channels/log.h>
|
|
#include "rdpdr_main.h"
|
|
+#include <freerdp/utils/channel_pdu_tracker.h>
|
|
|
|
#define RDPDR_ADD_PRINTER_EVENT 0x00000001
|
|
#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002
|
|
@@ -2126,101 +2127,62 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
UINT error = 0;
|
|
+ wStream* s = nullptr;
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
- DWORD nCount = 0;
|
|
+ ChannelPduTracker* tracker = ChannelPduTracker_new(priv->ChannelHandle);
|
|
+ if (!tracker)
|
|
+ goto out;
|
|
+
|
|
void* buffer = nullptr;
|
|
- HANDLE events[8] = WINPR_C_ARRAY_INIT;
|
|
HANDLE ChannelEvent = nullptr;
|
|
DWORD BytesReturned = 0;
|
|
- wStream* s = Stream_New(nullptr, 4096);
|
|
-
|
|
- if (!s)
|
|
+ if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
|
|
+ &BytesReturned))
|
|
{
|
|
- WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
- error = CHANNEL_RC_NO_MEMORY;
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "error retrieving WTSVirtualEventHandle");
|
|
goto out;
|
|
}
|
|
|
|
- if (WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
|
|
- &BytesReturned) == TRUE)
|
|
+ if (BytesReturned != sizeof(HANDLE))
|
|
{
|
|
- if (BytesReturned == sizeof(HANDLE))
|
|
- ChannelEvent = *(HANDLE*)buffer;
|
|
-
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "invalid size for WTSVirtualEventHandle");
|
|
WTSFreeMemory(buffer);
|
|
+ goto out;
|
|
}
|
|
|
|
- nCount = 0;
|
|
- events[nCount++] = ChannelEvent;
|
|
- events[nCount++] = priv->StopEvent;
|
|
+ ChannelEvent = *(HANDLE*)buffer;
|
|
+ WTSFreeMemory(buffer);
|
|
|
|
if ((error = rdpdr_server_send_announce_request(context)))
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_send_announce_request failed with error %" PRIu32 "!", error);
|
|
- goto out_stream;
|
|
+ goto out;
|
|
}
|
|
|
|
+ HANDLE events[2] = { priv->StopEvent, ChannelEvent };
|
|
+
|
|
while (1)
|
|
{
|
|
- size_t capacity = 0;
|
|
- BytesReturned = 0;
|
|
- DWORD status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
|
-
|
|
- if (status == WAIT_FAILED)
|
|
- {
|
|
- error = GetLastError();
|
|
- WLog_Print(priv->log, WLOG_ERROR,
|
|
- "WaitForMultipleObjects failed with error %" PRIu32 "!", error);
|
|
- goto out_stream;
|
|
- }
|
|
-
|
|
- status = WaitForSingleObject(priv->StopEvent, 0);
|
|
-
|
|
- if (status == WAIT_FAILED)
|
|
- {
|
|
- error = GetLastError();
|
|
- WLog_Print(priv->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!",
|
|
- error);
|
|
- goto out_stream;
|
|
- }
|
|
-
|
|
- if (status == WAIT_OBJECT_0)
|
|
- break;
|
|
-
|
|
- if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, nullptr, 0, &BytesReturned))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "WTSVirtualChannelRead failed!");
|
|
- error = ERROR_INTERNAL_ERROR;
|
|
- break;
|
|
- }
|
|
- if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
|
|
- error = ERROR_INTERNAL_ERROR;
|
|
- break;
|
|
- }
|
|
-
|
|
- capacity = MIN(Stream_Capacity(s), UINT32_MAX);
|
|
- if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, Stream_BufferAs(s, char),
|
|
- (ULONG)capacity, &BytesReturned))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "WTSVirtualChannelRead failed!");
|
|
- error = ERROR_INTERNAL_ERROR;
|
|
- break;
|
|
- }
|
|
+ DWORD status = WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
|
|
|
- if (BytesReturned >= RDPDR_HEADER_LENGTH)
|
|
+ switch (status)
|
|
{
|
|
- Stream_ResetPosition(s);
|
|
- if (!Stream_SetLength(s, BytesReturned))
|
|
+ case WAIT_OBJECT_0:
|
|
+ /* StopEvent */
|
|
+ goto out;
|
|
+ case WAIT_OBJECT_0 + 1:
|
|
{
|
|
- error = ERROR_INTERNAL_ERROR;
|
|
- goto out_stream;
|
|
- }
|
|
+ s = ChannelPduTracker_poll(tracker);
|
|
+ if (!s)
|
|
+ break;
|
|
+
|
|
+ if (Stream_GetRemainingLength(s) < RDPDR_HEADER_LENGTH)
|
|
+ {
|
|
+ error = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
|
|
- while (Stream_GetRemainingLength(s) >= RDPDR_HEADER_LENGTH)
|
|
- {
|
|
const RDPDR_HEADER header = {
|
|
.Component = Stream_Get_UINT16(s), /* Component (2 bytes) */
|
|
.PacketId = Stream_Get_UINT16(s), /* PacketId (2 bytes) */
|
|
@@ -2230,15 +2192,26 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR,
|
|
"rdpdr_server_receive_pdu failed with error %" PRIu32 "!", error);
|
|
- goto out_stream;
|
|
+ goto out;
|
|
}
|
|
+ Stream_Release(s);
|
|
+ s = nullptr;
|
|
+ break;
|
|
}
|
|
+ case WAIT_FAILED:
|
|
+ default:
|
|
+ error = GetLastError();
|
|
+ WLog_Print(priv->log, WLOG_ERROR,
|
|
+ "WaitForMultipleObjects failed with error %" PRIu32 "!", error);
|
|
+ goto out;
|
|
}
|
|
}
|
|
|
|
-out_stream:
|
|
- Stream_Release(s);
|
|
out:
|
|
+ ChannelPduTracker_free(tracker);
|
|
+
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
|
|
if (error && context->rdpcontext)
|
|
setChannelError(context->rdpcontext, error, "rdpdr_server_thread reported an error");
|
|
@@ -2257,9 +2230,19 @@ static UINT rdpdr_server_start(RdpdrServerContext* context)
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
+ PULONG pSessionId = nullptr;
|
|
+ DWORD BytesReturned = 0;
|
|
+
|
|
+ if (!WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
|
|
+ (LPSTR*)&pSessionId, &BytesReturned))
|
|
+ return CHANNEL_RC_BAD_CHANNEL;
|
|
+
|
|
+ DWORD SessionId = (DWORD)*pSessionId;
|
|
+ WTSFreeMemory(pSessionId);
|
|
+
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
priv->ChannelHandle =
|
|
- WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPDR_SVC_CHANNEL_NAME);
|
|
+ WTSVirtualChannelOpenEx(SessionId, RDPDR_SVC_CHANNEL_NAME, CHANNEL_OPTION_SHOW_PROTOCOL);
|
|
|
|
if (!priv->ChannelHandle)
|
|
{
|
|
|
|
From 7af13f0b5d3b784e00348ebaa46284aa48c70d44 Mon Sep 17 00:00:00 2001
|
|
From: David Fort <contact@hardening-consulting.com>
|
|
Date: Mon, 22 Jun 2026 21:37:34 +0200
|
|
Subject: [PATCH 16/31] [channels,rdpdr] track smartcard device in device
|
|
announce
|
|
|
|
- add haveSmartcardDevice and smartcardDeviceId to RdpdrServerPrivate
|
|
- store smartcard device ID on device announce
|
|
- clear smartcard device state on device remove
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 22 ++++++++++++++--------
|
|
1 file changed, 14 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 06cd7a025ee4..e90c287c8a4e 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -64,6 +64,8 @@ struct s_rdpdr_server_private
|
|
UINT32 SpecialDeviceTypeCap;
|
|
UINT32 IoCode1;
|
|
UINT32 ExtendedPDU;
|
|
+ BOOL haveSmartcardDevice;
|
|
+ UINT32 smartcardDeviceId;
|
|
};
|
|
|
|
static const char* fileInformation2str(uint8_t val)
|
|
@@ -1156,16 +1158,13 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
break;
|
|
|
|
case RDPDR_DTYP_SMARTCARD:
|
|
- if (device.DeviceDataLength != 0)
|
|
+ if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
|
|
{
|
|
- WLog_Print(priv->log, WLOG_WARN,
|
|
- "[rdpdr] RDPDR_DTYP_SMARTCARD::DeviceDataLength != 0 [%" PRIu32 "]",
|
|
- device.DeviceDataLength);
|
|
- error = ERROR_INVALID_DATA;
|
|
- }
|
|
- else if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
|
|
+ priv->smartcardDeviceId = device.DeviceId;
|
|
+ priv->haveSmartcardDevice = TRUE;
|
|
error =
|
|
- IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardCreate, context, &device);
|
|
+ IFCALLRESULT(STATUS_SUCCESS, context->OnSmartcardCreate, context, &device);
|
|
+ }
|
|
break;
|
|
|
|
default:
|
|
@@ -1254,6 +1253,11 @@ static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext*
|
|
break;
|
|
|
|
case RDPDR_DTYP_SMARTCARD:
|
|
+ if (priv->haveSmartcardDevice)
|
|
+ {
|
|
+ priv->haveSmartcardDevice = FALSE;
|
|
+ priv->smartcardDeviceId = 0;
|
|
+ }
|
|
if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
|
|
error =
|
|
IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardDelete, context, DeviceId);
|
|
@@ -3678,6 +3682,8 @@ static RdpdrServerPrivate* rdpdr_server_private_new(void)
|
|
priv->ClientId = g_ClientId++;
|
|
priv->UserLoggedOnPdu = TRUE;
|
|
priv->NextCompletionId = 1;
|
|
+ priv->haveSmartcardDevice = FALSE;
|
|
+ priv->smartcardDeviceId = 0;
|
|
priv->IrpList = ListDictionary_New(TRUE);
|
|
|
|
if (!priv->IrpList)
|
|
|
|
From 5a61669cd5bd16643545ad46bb7c2edebe4004bb Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Tue, 23 Jun 2026 20:27:59 +0200
|
|
Subject: [PATCH 17/31] [channels,rdpdr] send DEVICE_REPLY in device announce
|
|
|
|
Send PAKID_CORE_DEVICE_REPLY for each announced device.
|
|
|
|
Co-Authored-By: David Fort <contact@hardening-consulting.com>
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 36 ++++++++++++++++++++++++++++--
|
|
1 file changed, 34 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index e90c287c8a4e..fd11ad86e37f 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -1075,6 +1075,36 @@ static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
|
|
return rdpdr_seal_send_free_request(context, s);
|
|
}
|
|
|
|
+/**
|
|
+ * Function description
|
|
+ *
|
|
+ * @return 0 on success, otherwise a Win32 error code
|
|
+ */
|
|
+static UINT rdpdr_server_send_device_reply(RdpdrServerContext* context, UINT32 deviceId,
|
|
+ UINT32 resultCode)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ wStream* s = Stream_New(nullptr, RDPDR_HEADER_LENGTH + 8);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ return CHANNEL_RC_NO_MEMORY;
|
|
+ }
|
|
+
|
|
+ const RDPDR_HEADER header = {
|
|
+ .Component = RDPDR_CTYP_CORE,
|
|
+ .PacketId = PAKID_CORE_DEVICE_REPLY,
|
|
+ };
|
|
+ Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
|
+ Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
|
+ Stream_Write_UINT32(s, deviceId); /* DeviceId (4 bytes) */
|
|
+ Stream_Write_UINT32(s, resultCode); /* ResultCode (4 bytes) */
|
|
+ return rdpdr_seal_send_free_request(context, s);
|
|
+}
|
|
+
|
|
/**
|
|
* Function description
|
|
*
|
|
@@ -1119,6 +1149,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
if (error != CHANNEL_RC_OK)
|
|
return error;
|
|
|
|
+ error = STATUS_NOT_SUPPORTED;
|
|
switch (device.DeviceType)
|
|
{
|
|
case RDPDR_DTYP_FILESYSTEM:
|
|
@@ -1177,10 +1208,11 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
break;
|
|
}
|
|
|
|
+ Stream_Seek(s, device.DeviceDataLength);
|
|
+
|
|
+ error = rdpdr_server_send_device_reply(context, device.DeviceId, error);
|
|
if (error != CHANNEL_RC_OK)
|
|
return error;
|
|
-
|
|
- Stream_Seek(s, device.DeviceDataLength);
|
|
}
|
|
|
|
return CHANNEL_RC_OK;
|
|
|
|
From c8becfea93ae68bde1dc235e2bbc46a18c443dd2 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Fri, 19 Jun 2026 12:19:03 +0200
|
|
Subject: [PATCH 18/31] [channels,rdpdr] fix IRP list leak on shutdown
|
|
|
|
Set fnObjectFree on IrpList so that pending IRPs are freed when the
|
|
dictionary is destroyed during shutdown.
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index fd11ad86e37f..5c2df122f1ad 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -3721,6 +3721,8 @@ static RdpdrServerPrivate* rdpdr_server_private_new(void)
|
|
if (!priv->IrpList)
|
|
goto fail;
|
|
|
|
+ ListDictionary_ValueObject(priv->IrpList)->fnObjectFree = (OBJECT_FREE_FN)rdpdr_server_irp_free;
|
|
+
|
|
priv->devicelist = HashTable_New(FALSE);
|
|
if (!priv->devicelist)
|
|
goto fail;
|
|
|
|
From 97612e10160c38f1d241025d0fe2af87196ae9f9 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Tue, 23 Jun 2026 21:30:37 +0200
|
|
Subject: [PATCH 19/31] [channels,rdpdr] add and use prepare_irp helper
|
|
|
|
- add prepare_irp to centralize IRP creation, enqueue, and device check
|
|
- replace inline IRP creation in all drive operations
|
|
- add prepare_smartcard_irp wrapper with smartcard device check and IoControlCode
|
|
- add IoControlCode field to RDPDR_IRP
|
|
|
|
Co-Authored-By: David Fort <contact@hardening-consulting.com>
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 310 +++++++++++------------------
|
|
channels/rdpdr/server/rdpdr_main.h | 1 +
|
|
2 files changed, 122 insertions(+), 189 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 5c2df122f1ad..af42beb7520f 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -2395,6 +2395,66 @@ static UINT rdpdr_server_read_file_directory_information(wLog* log, wStream* s,
|
|
return CHANNEL_RC_OK;
|
|
}
|
|
|
|
+static UINT prepare_irp(RdpdrServerContext* context, UINT32 deviceId, RDPDR_IRP_Callback callback,
|
|
+ void* callbackData, RDPDR_IRP** outIrp)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(callbackData);
|
|
+ WINPR_ASSERT(outIrp);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
+ if (!irp)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
+ return CHANNEL_RC_NO_MEMORY;
|
|
+ }
|
|
+
|
|
+ irp->CompletionId = priv->NextCompletionId++;
|
|
+ irp->Callback = callback;
|
|
+ irp->CallbackData = callbackData;
|
|
+ irp->DeviceId = deviceId;
|
|
+
|
|
+ if (!rdpdr_server_enqueue_irp(context, irp))
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return ERROR_INTERNAL_ERROR;
|
|
+ }
|
|
+
|
|
+ *outIrp = irp;
|
|
+ return CHANNEL_RC_OK;
|
|
+}
|
|
+
|
|
+static UINT prepare_smartcard_irp(RdpdrServerContext* context, UINT32 ioControlCode,
|
|
+ RDPDR_IRP_Callback callback, void* callbackData,
|
|
+ RDPDR_IRP** outIrp)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(callbackData);
|
|
+
|
|
+ const char* cmd = scard_get_ioctl_string(ioControlCode, FALSE);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ if (!priv->haveSmartcardDevice)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "%s - no smartcard device registered", cmd);
|
|
+ return ERROR_BAD_DEVICE;
|
|
+ }
|
|
+
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT error = prepare_irp(context, priv->smartcardDeviceId, callback, callbackData, &irp);
|
|
+ if (error != CHANNEL_RC_OK)
|
|
+ return error;
|
|
+
|
|
+ irp->IoControlCode = ioControlCode;
|
|
+ *outIrp = irp;
|
|
+ return CHANNEL_RC_OK;
|
|
+}
|
|
+
|
|
/**
|
|
* Function description
|
|
*
|
|
@@ -2755,32 +2815,18 @@ static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context, voi
|
|
WINPR_ASSERT(callbackData);
|
|
WINPR_ASSERT(path);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_create_directory_callback1,
|
|
+ callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
-
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_create_directory_callback1;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
strncpy(irp->PathName, path, sizeof(irp->PathName) - 1);
|
|
rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the file. */
|
|
return rdpdr_server_send_device_create_request(
|
|
- context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
|
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_CREATE);
|
|
}
|
|
|
|
@@ -2878,32 +2924,18 @@ static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context, voi
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
-
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_delete_directory_callback1,
|
|
+ callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_delete_directory_callback1;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
strncpy(irp->PathName, path, sizeof(irp->PathName) - 1);
|
|
rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the file. */
|
|
return rdpdr_server_send_device_create_request(
|
|
- context, deviceId, irp->CompletionId, irp->PathName, DELETE | SYNCHRONIZE,
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->PathName, DELETE | SYNCHRONIZE,
|
|
FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
|
|
}
|
|
|
|
@@ -3049,32 +3081,18 @@ static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context, void
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_query_directory_callback1,
|
|
+ callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
-
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_query_directory_callback1;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
strncpy(irp->PathName, path, sizeof(irp->PathName) - 1);
|
|
rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the directory. */
|
|
return rdpdr_server_send_device_create_request(
|
|
- context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
|
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
|
|
}
|
|
|
|
@@ -3128,31 +3146,17 @@ static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context, void* call
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
-
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret =
|
|
+ prepare_irp(context, deviceId, rdpdr_server_drive_open_file_callback, callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_open_file_callback;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
strncpy(irp->PathName, path, sizeof(irp->PathName) - 1);
|
|
rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the file. */
|
|
- return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId,
|
|
+ return rdpdr_server_send_device_create_request(context, irp->DeviceId, irp->CompletionId,
|
|
irp->PathName, desiredAccess | SYNCHRONIZE,
|
|
FILE_SYNCHRONOUS_IO_NONALERT, createDisposition);
|
|
}
|
|
@@ -3213,32 +3217,17 @@ static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context, void* call
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret =
|
|
+ prepare_irp(context, deviceId, rdpdr_server_drive_read_file_callback, callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
-
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_read_file_callback;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
irp->FileId = fileId;
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the directory. */
|
|
- // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): rdpdr_server_enqueue_irp owns irp
|
|
- return rdpdr_server_send_device_read_request(context, deviceId, fileId, irp->CompletionId,
|
|
- length, offset);
|
|
+ return rdpdr_server_send_device_read_request(context, irp->DeviceId, irp->FileId,
|
|
+ irp->CompletionId, length, offset);
|
|
}
|
|
|
|
/*************************************************
|
|
@@ -3292,32 +3281,17 @@ static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, void* cal
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret =
|
|
+ prepare_irp(context, deviceId, rdpdr_server_drive_write_file_callback, callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
-
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_write_file_callback;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
irp->FileId = fileId;
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the directory. */
|
|
- // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): rdpdr_server_enqueue_irp owns irp
|
|
- return rdpdr_server_send_device_write_request(context, deviceId, fileId, irp->CompletionId,
|
|
- buffer, length, offset);
|
|
+ return rdpdr_server_send_device_write_request(context, irp->DeviceId, irp->FileId,
|
|
+ irp->CompletionId, buffer, length, offset);
|
|
}
|
|
|
|
/*************************************************
|
|
@@ -3369,31 +3343,17 @@ static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, void* cal
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret =
|
|
+ prepare_irp(context, deviceId, rdpdr_server_drive_close_file_callback, callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
-
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_close_file_callback;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
irp->FileId = fileId;
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the directory. */
|
|
- // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): rdpdr_server_enqueue_irp owns irp
|
|
- return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
|
|
+ return rdpdr_server_send_device_close_request(context, irp->DeviceId, irp->FileId,
|
|
+ irp->CompletionId);
|
|
}
|
|
|
|
/*************************************************
|
|
@@ -3476,7 +3436,8 @@ static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context
|
|
}
|
|
|
|
/* Send a request to close the file */
|
|
- return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
|
|
+ return rdpdr_server_send_device_close_request(context, irp->DeviceId, irp->FileId,
|
|
+ irp->CompletionId);
|
|
}
|
|
|
|
/**
|
|
@@ -3490,32 +3451,18 @@ static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context, void* ca
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_delete_file_callback1,
|
|
+ callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
-
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_delete_file_callback1;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
strncpy(irp->PathName, path, sizeof(irp->PathName) - 1);
|
|
rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the file. */
|
|
return rdpdr_server_send_device_create_request(
|
|
- context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
|
|
FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
|
|
}
|
|
|
|
@@ -3588,7 +3535,7 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context
|
|
}
|
|
|
|
/* Send a request to close the file */
|
|
- return rdpdr_server_send_device_close_request(context, deviceId, irp->FileId,
|
|
+ return rdpdr_server_send_device_close_request(context, irp->DeviceId, irp->FileId,
|
|
irp->CompletionId);
|
|
}
|
|
|
|
@@ -3642,7 +3589,7 @@ static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context
|
|
}
|
|
|
|
/* Send a request to rename the file */
|
|
- return rdpdr_server_send_device_file_rename_request(context, deviceId, fileId,
|
|
+ return rdpdr_server_send_device_file_rename_request(context, irp->DeviceId, irp->FileId,
|
|
irp->CompletionId, irp->ExtraBuffer);
|
|
}
|
|
|
|
@@ -3658,34 +3605,19 @@ static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context, void* ca
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
|
|
- RdpdrServerPrivate* priv = context->priv;
|
|
- RDPDR_IRP* irp = rdpdr_server_irp_new();
|
|
-
|
|
- if (!irp)
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_irp_new failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
- }
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_rename_file_callback1,
|
|
+ callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
|
|
- irp->CompletionId = priv->NextCompletionId++;
|
|
- irp->Callback = rdpdr_server_drive_rename_file_callback1;
|
|
- irp->CallbackData = callbackData;
|
|
- irp->DeviceId = deviceId;
|
|
strncpy(irp->PathName, oldPath, sizeof(irp->PathName) - 1);
|
|
strncpy(irp->ExtraBuffer, newPath, sizeof(irp->ExtraBuffer) - 1);
|
|
rdpdr_server_convert_slashes(irp->PathName, sizeof(irp->PathName));
|
|
rdpdr_server_convert_slashes(irp->ExtraBuffer, sizeof(irp->ExtraBuffer));
|
|
|
|
- if (!rdpdr_server_enqueue_irp(context, irp))
|
|
- {
|
|
- WLog_Print(priv->log, WLOG_ERROR, "rdpdr_server_enqueue_irp failed!");
|
|
- rdpdr_server_irp_free(irp);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
- }
|
|
-
|
|
/* Send a request to open the file. */
|
|
- // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): rdpdr_server_enqueue_irp owns irp
|
|
- return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId,
|
|
+ return rdpdr_server_send_device_create_request(context, irp->DeviceId, irp->CompletionId,
|
|
irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
|
|
FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
|
|
}
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.h b/channels/rdpdr/server/rdpdr_main.h
|
|
index b1d86b148ad7..40327a81313b 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.h
|
|
+++ b/channels/rdpdr/server/rdpdr_main.h
|
|
@@ -40,6 +40,7 @@ struct S_RDPDR_IRP
|
|
UINT32 CompletionId;
|
|
UINT32 DeviceId;
|
|
UINT32 FileId;
|
|
+ UINT32 IoControlCode;
|
|
char PathName[256];
|
|
char ExtraBuffer[256];
|
|
void* CallbackData;
|
|
|
|
From 26c63ef8e8591b6fec802c2e04a024f04314f418 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Wed, 24 Jun 2026 18:19:58 +0200
|
|
Subject: [PATCH 20/31] [channels,rdpdr] normalize indentation in rdpdr.h
|
|
|
|
Indent all declarations inside extern "C" block one level.
|
|
---
|
|
include/freerdp/server/rdpdr.h | 359 +++++++++++++++++----------------
|
|
1 file changed, 185 insertions(+), 174 deletions(-)
|
|
|
|
diff --git a/include/freerdp/server/rdpdr.h b/include/freerdp/server/rdpdr.h
|
|
index f2c33a14ba97..411b33b6d6d7 100644
|
|
--- a/include/freerdp/server/rdpdr.h
|
|
+++ b/include/freerdp/server/rdpdr.h
|
|
@@ -49,186 +49,197 @@ extern "C"
|
|
} RDPDR_HEADER;
|
|
|
|
#ifndef __MINGW32__
|
|
-typedef struct
|
|
-{
|
|
- UINT32 NextEntryOffset;
|
|
- UINT32 FileIndex;
|
|
- LARGE_INTEGER CreationTime;
|
|
- LARGE_INTEGER LastAccessTime;
|
|
- LARGE_INTEGER LastWriteTime;
|
|
- LARGE_INTEGER ChangeTime;
|
|
- LARGE_INTEGER EndOfFile;
|
|
- LARGE_INTEGER AllocationSize;
|
|
- UINT32 FileAttributes;
|
|
+ typedef struct
|
|
+ {
|
|
+ UINT32 NextEntryOffset;
|
|
+ UINT32 FileIndex;
|
|
+ LARGE_INTEGER CreationTime;
|
|
+ LARGE_INTEGER LastAccessTime;
|
|
+ LARGE_INTEGER LastWriteTime;
|
|
+ LARGE_INTEGER ChangeTime;
|
|
+ LARGE_INTEGER EndOfFile;
|
|
+ LARGE_INTEGER AllocationSize;
|
|
+ UINT32 FileAttributes;
|
|
#if defined(WITH_WCHAR_FILE_DIRECTORY_INFORMATION)
|
|
- WCHAR FileName[512];
|
|
+ WCHAR FileName[512];
|
|
#else
|
|
- char FileName[512];
|
|
+ char FileName[512];
|
|
#endif
|
|
-} FILE_DIRECTORY_INFORMATION;
|
|
+ } FILE_DIRECTORY_INFORMATION;
|
|
#endif
|
|
|
|
-typedef UINT (*psRdpdrStart)(RdpdrServerContext* context);
|
|
-typedef UINT (*psRdpdrStop)(RdpdrServerContext* context);
|
|
-
|
|
-typedef UINT (*psRdpdrCapablityPDU)(RdpdrServerContext* context,
|
|
- const RDPDR_CAPABILITY_HEADER* header, size_t size,
|
|
- const BYTE* data);
|
|
-typedef UINT (*psRdpdrReceivePDU)(RdpdrServerContext* context, const RDPDR_HEADER* header,
|
|
- UINT error);
|
|
-typedef UINT (*psRdpdrReceiveAnnounceResponse)(RdpdrServerContext* context, UINT16 VersionMajor,
|
|
- UINT16 VersionMinor, UINT32 ClientId);
|
|
-typedef UINT (*psRdpdrSendServerAnnounce)(RdpdrServerContext* context);
|
|
-typedef UINT (*psRdpdrReceiveDeviceAnnounce)(RdpdrServerContext* context,
|
|
- const RdpdrDevice* device);
|
|
-typedef UINT (*psRdpdrReceiveDeviceRemove)(RdpdrServerContext* context, UINT32 deviceId,
|
|
- const RdpdrDevice* device);
|
|
-typedef UINT (*psRdpdrReceiveClientNameRequest)(RdpdrServerContext* context, size_t ComputerNameLen,
|
|
- const char* name);
|
|
-
|
|
-typedef UINT (*psRdpdrDriveCreateDirectory)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 deviceId, const char* path);
|
|
-typedef UINT (*psRdpdrDriveDeleteDirectory)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 deviceId, const char* path);
|
|
-typedef UINT (*psRdpdrDriveQueryDirectory)(RdpdrServerContext* context, void* callbackData,
|
|
+ typedef UINT (*psRdpdrStart)(RdpdrServerContext* context);
|
|
+ typedef UINT (*psRdpdrStop)(RdpdrServerContext* context);
|
|
+
|
|
+ typedef UINT (*psRdpdrCapablityPDU)(RdpdrServerContext* context,
|
|
+ const RDPDR_CAPABILITY_HEADER* header, size_t size,
|
|
+ const BYTE* data);
|
|
+ typedef UINT (*psRdpdrReceivePDU)(RdpdrServerContext* context, const RDPDR_HEADER* header,
|
|
+ UINT error);
|
|
+ typedef UINT (*psRdpdrReceiveAnnounceResponse)(RdpdrServerContext* context, UINT16 VersionMajor,
|
|
+ UINT16 VersionMinor, UINT32 ClientId);
|
|
+ typedef UINT (*psRdpdrSendServerAnnounce)(RdpdrServerContext* context);
|
|
+ typedef UINT (*psRdpdrReceiveDeviceAnnounce)(RdpdrServerContext* context,
|
|
+ const RdpdrDevice* device);
|
|
+ typedef UINT (*psRdpdrReceiveDeviceRemove)(RdpdrServerContext* context, UINT32 deviceId,
|
|
+ const RdpdrDevice* device);
|
|
+ typedef UINT (*psRdpdrReceiveClientNameRequest)(RdpdrServerContext* context,
|
|
+ size_t ComputerNameLen, const char* name);
|
|
+
|
|
+ typedef UINT (*psRdpdrDriveCreateDirectory)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 deviceId, const char* path);
|
|
+ typedef UINT (*psRdpdrDriveDeleteDirectory)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 deviceId, const char* path);
|
|
+ typedef UINT (*psRdpdrDriveQueryDirectory)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 deviceId, const char* path);
|
|
+ typedef UINT (*psRdpdrDriveOpenFile)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 deviceId, const char* path, UINT32 desiredAccess,
|
|
+ UINT32 createDisposition);
|
|
+ typedef UINT (*psRdpdrDriveReadFile)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 deviceId, UINT32 fileId, UINT32 length,
|
|
+ UINT32 offset);
|
|
+ typedef UINT (*psRdpdrDriveWriteFile)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 deviceId, UINT32 fileId, const char* buffer,
|
|
+ UINT32 length, UINT32 offset);
|
|
+ typedef UINT (*psRdpdrDriveCloseFile)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 deviceId, UINT32 fileId);
|
|
+ typedef UINT (*psRdpdrDriveDeleteFile)(RdpdrServerContext* context, void* callbackData,
|
|
UINT32 deviceId, const char* path);
|
|
-typedef UINT (*psRdpdrDriveOpenFile)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 deviceId, const char* path, UINT32 desiredAccess,
|
|
- UINT32 createDisposition);
|
|
-typedef UINT (*psRdpdrDriveReadFile)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 deviceId, UINT32 fileId, UINT32 length, UINT32 offset);
|
|
-typedef UINT (*psRdpdrDriveWriteFile)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 deviceId, UINT32 fileId, const char* buffer,
|
|
- UINT32 length, UINT32 offset);
|
|
-typedef UINT (*psRdpdrDriveCloseFile)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 deviceId, UINT32 fileId);
|
|
-typedef UINT (*psRdpdrDriveDeleteFile)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 deviceId, const char* path);
|
|
-typedef UINT (*psRdpdrDriveRenameFile)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 deviceId, const char* oldPath, const char* newPath);
|
|
-
|
|
-typedef void (*psRdpdrOnDriveCreateDirectoryComplete)(RdpdrServerContext* context,
|
|
- void* callbackData, UINT32 ioStatus);
|
|
-typedef void (*psRdpdrOnDriveDeleteDirectoryComplete)(RdpdrServerContext* context,
|
|
- void* callbackData, UINT32 ioStatus);
|
|
-typedef void (*psRdpdrOnDriveQueryDirectoryComplete)(RdpdrServerContext* context,
|
|
- void* callbackData, UINT32 ioStatus,
|
|
- FILE_DIRECTORY_INFORMATION* fdi);
|
|
-typedef void (*psRdpdrOnDriveOpenFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 ioStatus, UINT32 deviceId, UINT32 fileId);
|
|
-typedef void (*psRdpdrOnDriveReadFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 ioStatus, const char* buffer, UINT32 length);
|
|
-typedef void (*psRdpdrOnDriveWriteFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 ioStatus, UINT32 bytesWritten);
|
|
-typedef void (*psRdpdrOnDriveCloseFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 ioStatus);
|
|
-typedef void (*psRdpdrOnDriveDeleteFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 ioStatus);
|
|
-typedef void (*psRdpdrOnDriveRenameFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
- UINT32 ioStatus);
|
|
-
|
|
-typedef UINT (*psRdpdrOnDeviceCreate)(RdpdrServerContext* context, const RdpdrDevice* device);
|
|
-typedef UINT (*psRdpdrOnDeviceDelete)(RdpdrServerContext* context, UINT32 deviceId);
|
|
-
|
|
-struct s_rdpdr_server_context
|
|
-{
|
|
- HANDLE vcm;
|
|
-
|
|
- WINPR_ATTR_NODISCARD psRdpdrStart Start;
|
|
- psRdpdrStop Stop;
|
|
-
|
|
- RdpdrServerPrivate* priv;
|
|
-
|
|
- /* Server self-defined pointer. */
|
|
- void* data;
|
|
-
|
|
- /**< Server supported redirections.
|
|
- * initially used to determine which redirections are supported by the
|
|
- * server in the server capability, later on updated with what the client
|
|
- * actually wants to have supported.
|
|
- *
|
|
- * Use the \b RDPDR_DTYP_* defines as a mask to check.
|
|
- */
|
|
- UINT16 supported;
|
|
-
|
|
- /*** RDPDR message intercept callbacks */
|
|
- WINPR_ATTR_NODISCARD psRdpdrCapablityPDU
|
|
- ReceiveCaps; /**< Called for each received capability */
|
|
- WINPR_ATTR_NODISCARD psRdpdrCapablityPDU SendCaps; /**< Called for each capability to be sent */
|
|
- WINPR_ATTR_NODISCARD psRdpdrReceivePDU
|
|
- ReceivePDU; /**< Called after a RDPDR pdu was received and parsed */
|
|
- WINPR_ATTR_NODISCARD psRdpdrSendServerAnnounce
|
|
- SendServerAnnounce; /**< Called before the server sends the announce message */
|
|
- WINPR_ATTR_NODISCARD psRdpdrReceiveAnnounceResponse
|
|
- ReceiveAnnounceResponse; /**< Called after the client announce response is received */
|
|
- WINPR_ATTR_NODISCARD psRdpdrReceiveClientNameRequest
|
|
- ReceiveClientNameRequest; /**< Called after a client name request is received */
|
|
- WINPR_ATTR_NODISCARD psRdpdrReceiveDeviceAnnounce
|
|
- ReceiveDeviceAnnounce; /** < Called after a new device request was received but before the
|
|
- device is added */
|
|
- WINPR_ATTR_NODISCARD psRdpdrReceiveDeviceRemove
|
|
- ReceiveDeviceRemove; /**< Called after a new device request was
|
|
- received, but before it is removed */
|
|
-
|
|
- /*** Drive APIs called by the server. ***/
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveCreateDirectory DriveCreateDirectory;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveDeleteDirectory DriveDeleteDirectory;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveQueryDirectory DriveQueryDirectory;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveOpenFile DriveOpenFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveReadFile DriveReadFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveWriteFile DriveWriteFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveCloseFile DriveCloseFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveDeleteFile DriveDeleteFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveRenameFile DriveRenameFile;
|
|
-
|
|
- /*** Drive callbacks registered by the server. ***/
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate OnDriveCreate; /**< Called for devices of type \b
|
|
- RDPDR_DTYP_FILESYSTEM after \b ReceiveDeviceAnnounce */
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete OnDriveDelete; /**< Called for devices of type \b
|
|
- RDPDR_DTYP_FILESYSTEM after \b ReceiveDeviceRemove */
|
|
- psRdpdrOnDriveCreateDirectoryComplete OnDriveCreateDirectoryComplete;
|
|
- psRdpdrOnDriveDeleteDirectoryComplete OnDriveDeleteDirectoryComplete;
|
|
- psRdpdrOnDriveQueryDirectoryComplete OnDriveQueryDirectoryComplete;
|
|
- psRdpdrOnDriveOpenFileComplete OnDriveOpenFileComplete;
|
|
- psRdpdrOnDriveReadFileComplete OnDriveReadFileComplete;
|
|
- psRdpdrOnDriveWriteFileComplete OnDriveWriteFileComplete;
|
|
- psRdpdrOnDriveCloseFileComplete OnDriveCloseFileComplete;
|
|
- psRdpdrOnDriveDeleteFileComplete OnDriveDeleteFileComplete;
|
|
- psRdpdrOnDriveRenameFileComplete OnDriveRenameFileComplete;
|
|
-
|
|
- /*** Serial Port callbacks registered by the server. ***/
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate OnSerialPortCreate; /**< Called for devices of type
|
|
- \b RDPDR_DTYP_SERIAL after \b ReceiveDeviceAnnounce */
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete OnSerialPortDelete; /**< Called for devices of type
|
|
- \b RDPDR_DTYP_SERIAL after \b ReceiveDeviceRemove */
|
|
-
|
|
- /*** Parallel Port callbacks registered by the server. ***/
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate OnParallelPortCreate; /**< Called for devices of type
|
|
- \b RDPDR_DTYP_PARALLEL after \b ReceiveDeviceAnnounce */
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete OnParallelPortDelete; /**< Called for devices of type
|
|
- \b RDPDR_DTYP_PARALLEL after \b ReceiveDeviceRemove */
|
|
-
|
|
- /*** Printer callbacks registered by the server. ***/
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate OnPrinterCreate; /**< Called for devices of type
|
|
- RDPDR_DTYP_PRINT after \b ReceiveDeviceAnnounce */
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete OnPrinterDelete; /**< Called for devices of type
|
|
- RDPDR_DTYP_PRINT after \b ReceiveDeviceRemove */
|
|
-
|
|
- /*** Smartcard callbacks registered by the server. ***/
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate
|
|
- OnSmartcardCreate; /**< Called for devices of type RDPDR_DTYP_SMARTCARD
|
|
- after \b ReceiveDeviceAnnounce */
|
|
- WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete OnSmartcardDelete; /**< Called for devices of type
|
|
- RDPDR_DTYP_SMARTCARD after \b ReceiveDeviceRemove */
|
|
-
|
|
- rdpContext* rdpcontext;
|
|
-};
|
|
-
|
|
-FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context);
|
|
-
|
|
-WINPR_ATTR_MALLOC(rdpdr_server_context_free, 1)
|
|
-WINPR_ATTR_NODISCARD
|
|
-FREERDP_API RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm);
|
|
+ typedef UINT (*psRdpdrDriveRenameFile)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 deviceId, const char* oldPath,
|
|
+ const char* newPath);
|
|
+
|
|
+ typedef void (*psRdpdrOnDriveCreateDirectoryComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus);
|
|
+ typedef void (*psRdpdrOnDriveDeleteDirectoryComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus);
|
|
+ typedef void (*psRdpdrOnDriveQueryDirectoryComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ FILE_DIRECTORY_INFORMATION* fdi);
|
|
+ typedef void (*psRdpdrOnDriveOpenFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 ioStatus, UINT32 deviceId, UINT32 fileId);
|
|
+ typedef void (*psRdpdrOnDriveReadFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 ioStatus, const char* buffer,
|
|
+ UINT32 length);
|
|
+ typedef void (*psRdpdrOnDriveWriteFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 ioStatus, UINT32 bytesWritten);
|
|
+ typedef void (*psRdpdrOnDriveCloseFileComplete)(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 ioStatus);
|
|
+ typedef void (*psRdpdrOnDriveDeleteFileComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus);
|
|
+ typedef void (*psRdpdrOnDriveRenameFileComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus);
|
|
+
|
|
+ typedef UINT (*psRdpdrOnDeviceCreate)(RdpdrServerContext* context, const RdpdrDevice* device);
|
|
+ typedef UINT (*psRdpdrOnDeviceDelete)(RdpdrServerContext* context, UINT32 deviceId);
|
|
+
|
|
+ struct s_rdpdr_server_context
|
|
+ {
|
|
+ HANDLE vcm;
|
|
+
|
|
+ WINPR_ATTR_NODISCARD psRdpdrStart Start;
|
|
+ psRdpdrStop Stop;
|
|
+
|
|
+ RdpdrServerPrivate* priv;
|
|
+
|
|
+ /* Server self-defined pointer. */
|
|
+ void* data;
|
|
+
|
|
+ /**< Server supported redirections.
|
|
+ * initially used to determine which redirections are supported by the
|
|
+ * server in the server capability, later on updated with what the client
|
|
+ * actually wants to have supported.
|
|
+ *
|
|
+ * Use the \b RDPDR_DTYP_* defines as a mask to check.
|
|
+ */
|
|
+ UINT16 supported;
|
|
+
|
|
+ /*** RDPDR message intercept callbacks */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrCapablityPDU
|
|
+ ReceiveCaps; /**< Called for each received capability */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrCapablityPDU
|
|
+ SendCaps; /**< Called for each capability to be sent */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrReceivePDU
|
|
+ ReceivePDU; /**< Called after a RDPDR pdu was received and parsed */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSendServerAnnounce
|
|
+ SendServerAnnounce; /**< Called before the server sends the announce message */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrReceiveAnnounceResponse
|
|
+ ReceiveAnnounceResponse; /**< Called after the client announce response is received */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrReceiveClientNameRequest
|
|
+ ReceiveClientNameRequest; /**< Called after a client name request is received */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrReceiveDeviceAnnounce
|
|
+ ReceiveDeviceAnnounce; /** < Called after a new device request was received but before
|
|
+ the device is added */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrReceiveDeviceRemove
|
|
+ ReceiveDeviceRemove; /**< Called after a new device request was
|
|
+ received, but before it is removed */
|
|
+
|
|
+ /*** Drive APIs called by the server. ***/
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveCreateDirectory DriveCreateDirectory;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveDeleteDirectory DriveDeleteDirectory;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveQueryDirectory DriveQueryDirectory;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveOpenFile DriveOpenFile;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveReadFile DriveReadFile;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveWriteFile DriveWriteFile;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveCloseFile DriveCloseFile;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveDeleteFile DriveDeleteFile;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveRenameFile DriveRenameFile;
|
|
+
|
|
+ /*** Drive callbacks registered by the server. ***/
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate
|
|
+ OnDriveCreate; /**< Called for devices of type \b
|
|
+ RDPDR_DTYP_FILESYSTEM after \b ReceiveDeviceAnnounce */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete
|
|
+ OnDriveDelete; /**< Called for devices of type \b
|
|
+ RDPDR_DTYP_FILESYSTEM after \b ReceiveDeviceRemove */
|
|
+ psRdpdrOnDriveCreateDirectoryComplete OnDriveCreateDirectoryComplete;
|
|
+ psRdpdrOnDriveDeleteDirectoryComplete OnDriveDeleteDirectoryComplete;
|
|
+ psRdpdrOnDriveQueryDirectoryComplete OnDriveQueryDirectoryComplete;
|
|
+ psRdpdrOnDriveOpenFileComplete OnDriveOpenFileComplete;
|
|
+ psRdpdrOnDriveReadFileComplete OnDriveReadFileComplete;
|
|
+ psRdpdrOnDriveWriteFileComplete OnDriveWriteFileComplete;
|
|
+ psRdpdrOnDriveCloseFileComplete OnDriveCloseFileComplete;
|
|
+ psRdpdrOnDriveDeleteFileComplete OnDriveDeleteFileComplete;
|
|
+ psRdpdrOnDriveRenameFileComplete OnDriveRenameFileComplete;
|
|
+
|
|
+ /*** Serial Port callbacks registered by the server. ***/
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate
|
|
+ OnSerialPortCreate; /**< Called for devices of type
|
|
+ \b RDPDR_DTYP_SERIAL after \b ReceiveDeviceAnnounce */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete
|
|
+ OnSerialPortDelete; /**< Called for devices of type
|
|
+ \b RDPDR_DTYP_SERIAL after \b ReceiveDeviceRemove */
|
|
+
|
|
+ /*** Parallel Port callbacks registered by the server. ***/
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate
|
|
+ OnParallelPortCreate; /**< Called for devices of type
|
|
+ \b RDPDR_DTYP_PARALLEL after \b ReceiveDeviceAnnounce */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete
|
|
+ OnParallelPortDelete; /**< Called for devices of type
|
|
+ \b RDPDR_DTYP_PARALLEL after \b ReceiveDeviceRemove */
|
|
+
|
|
+ /*** Printer callbacks registered by the server. ***/
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate OnPrinterCreate; /**< Called for devices of type
|
|
+ RDPDR_DTYP_PRINT after \b ReceiveDeviceAnnounce */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete OnPrinterDelete; /**< Called for devices of type
|
|
+ RDPDR_DTYP_PRINT after \b ReceiveDeviceRemove */
|
|
+
|
|
+ /*** Smartcard callbacks registered by the server. ***/
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate
|
|
+ OnSmartcardCreate; /**< Called for devices of type RDPDR_DTYP_SMARTCARD
|
|
+ after \b ReceiveDeviceAnnounce */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete
|
|
+ OnSmartcardDelete; /**< Called for devices of type
|
|
+ RDPDR_DTYP_SMARTCARD after \b ReceiveDeviceRemove */
|
|
+
|
|
+ rdpContext* rdpcontext;
|
|
+ };
|
|
+
|
|
+ FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context);
|
|
+
|
|
+ WINPR_ATTR_MALLOC(rdpdr_server_context_free, 1)
|
|
+ WINPR_ATTR_NODISCARD
|
|
+ FREERDP_API RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
|
|
From 8064bf9ed77211dea30c1114b5286c5303e1af78 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Mon, 22 Jun 2026 13:58:54 +0200
|
|
Subject: [PATCH 21/31] [channels,rdpdr] add smartcard server operations
|
|
|
|
Add smartcard IOCTL operations to the RDPDR server. Each operation
|
|
sends an IRP_MJ_DEVICE_CONTROL request to the client and parses
|
|
the response via a completion callback.
|
|
|
|
Add rdpdr_server_send_device_control_request for sending
|
|
IRP_MJ_DEVICE_CONTROL requests, following the existing drive pattern.
|
|
|
|
Add request and completion function pointers to the public
|
|
RdpdrServerContext API for all smartcard operations.
|
|
|
|
Co-authored-by: David Fort <contact@hardening-consulting.com>
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 1979 ++++++++++++++++-
|
|
include/freerdp/server/rdpdr.h | 220 ++
|
|
libfreerdp/utils/test/CMakeLists.txt | 4 +-
|
|
.../utils/test/TestSmartcardOperations.c | 1445 ++++++++++++
|
|
4 files changed, 3614 insertions(+), 34 deletions(-)
|
|
create mode 100644 libfreerdp/utils/test/TestSmartcardOperations.c
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index af42beb7520f..7b9c1d33ff10 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -32,6 +32,8 @@
|
|
#include <winpr/stream.h>
|
|
|
|
#include <freerdp/channels/log.h>
|
|
+#include <freerdp/channels/scard.h>
|
|
+#include <freerdp/utils/smartcard_operations.h>
|
|
#include "rdpdr_main.h"
|
|
#include <freerdp/utils/channel_pdu_tracker.h>
|
|
|
|
@@ -43,6 +45,9 @@
|
|
#define RDPDR_HEADER_LENGTH 4
|
|
#define RDPDR_CAPABILITY_HEADER_LENGTH 8
|
|
|
|
+/* [MS-RDPESC] 3.2.5.1: the output buffer length SHOULD be set to 2048 */
|
|
+#define SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH 2048
|
|
+
|
|
struct s_rdpdr_server_private
|
|
{
|
|
HANDLE Thread;
|
|
@@ -2706,6 +2711,55 @@ static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* con
|
|
return rdpdr_seal_send_free_request(context, s);
|
|
}
|
|
|
|
+static UINT rdpdr_server_send_device_control_request(RdpdrServerContext* context, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioControlCode,
|
|
+ UINT32 outputBufferLength,
|
|
+ const void* inputBuffer,
|
|
+ size_t inputBufferLength)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(inputBuffer || (inputBufferLength == 0));
|
|
+
|
|
+ if (inputBufferLength > UINT32_MAX)
|
|
+ {
|
|
+ WLog_Print(context->priv->log, WLOG_ERROR,
|
|
+ "inputBufferLength %" PRIuz " exceeds UINT32_MAX", inputBufferLength);
|
|
+ return ERROR_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "RdpdrServerSendDeviceControlRequest: deviceId=%" PRIu32 ","
|
|
+ " ioControlCode=0x%" PRIx32 ", inputBufferLength=%" PRIuz,
|
|
+ deviceId, ioControlCode, inputBufferLength);
|
|
+
|
|
+ if (inputBufferLength > 0)
|
|
+ winpr_HexLogDump(priv->log, WLOG_DEBUG, inputBuffer, inputBufferLength);
|
|
+
|
|
+ wStream* s =
|
|
+ Stream_New(nullptr, RDPDR_HEADER_LENGTH + RDPDR_DEVICE_IO_REQUEST_LENGTH +
|
|
+ RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH + inputBufferLength);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ return CHANNEL_RC_NO_MEMORY;
|
|
+ }
|
|
+
|
|
+ UINT32 inputLength = WINPR_ASSERTING_INT_CAST(UINT32, inputBufferLength);
|
|
+ rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_DEVICE_CONTROL, 0);
|
|
+ Stream_Write_UINT32(s, outputBufferLength); /* OutputBufferLength (4 bytes) */
|
|
+ Stream_Write_UINT32(s, inputLength); /* InputBufferLength (4 bytes) */
|
|
+ Stream_Write_UINT32(s, ioControlCode); /* IoControlCode (4 bytes) */
|
|
+ Stream_Zero(s, 20); /* Padding (20 bytes) */
|
|
+
|
|
+ if (inputBufferLength > 0)
|
|
+ Stream_Write(s, inputBuffer, inputBufferLength);
|
|
+
|
|
+ return rdpdr_seal_send_free_request(context, s);
|
|
+}
|
|
+
|
|
static void rdpdr_server_convert_slashes(char* path, int size)
|
|
{
|
|
WINPR_ASSERT(path || (size <= 0));
|
|
@@ -3682,46 +3736,1905 @@ static RdpdrServerPrivate* rdpdr_server_private_new(void)
|
|
return nullptr;
|
|
}
|
|
|
|
-RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
|
|
+static UINT rdpdr_server_smartcard_establish_context_callback(RdpdrServerContext* context,
|
|
+ wStream* s, RDPDR_IRP* irp,
|
|
+ UINT32 deviceId, UINT32 completionId,
|
|
+ UINT32 ioStatus)
|
|
{
|
|
- RdpdrServerContext* context = (RdpdrServerContext*)calloc(1, sizeof(RdpdrServerContext));
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
|
|
- if (!context)
|
|
- goto fail;
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
|
|
- context->vcm = vcm;
|
|
- context->Start = rdpdr_server_start;
|
|
- context->Stop = rdpdr_server_stop;
|
|
- context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
|
|
- context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
|
|
- context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
|
|
- context->DriveOpenFile = rdpdr_server_drive_open_file;
|
|
- context->DriveReadFile = rdpdr_server_drive_read_file;
|
|
- context->DriveWriteFile = rdpdr_server_drive_write_file;
|
|
- context->DriveCloseFile = rdpdr_server_drive_close_file;
|
|
- context->DriveDeleteFile = rdpdr_server_drive_delete_file;
|
|
- context->DriveRenameFile = rdpdr_server_drive_rename_file;
|
|
- context->priv = rdpdr_server_private_new();
|
|
- if (!context->priv)
|
|
- goto fail;
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "RdpdrServerSmartcardEstablishContextCallback: deviceId=%" PRIu32
|
|
+ ", completionId=%" PRIu32 ", ioStatus=0x%" PRIx32 "",
|
|
+ deviceId, completionId, ioStatus);
|
|
|
|
- /* By default announce everything, the server application can deactivate that later on */
|
|
- context->supported = UINT16_MAX;
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardEstablishContextComplete)
|
|
+ context->OnSmartcardEstablishContextComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
|
|
- return context;
|
|
-fail:
|
|
- WINPR_PRAGMA_DIAG_PUSH
|
|
- WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
|
- rdpdr_server_context_free(context);
|
|
- WINPR_PRAGMA_DIAG_POP
|
|
- return nullptr;
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardEstablishContextComplete)
|
|
+ context->OnSmartcardEstablishContextComplete(context, irp->CallbackData, ioStatus,
|
|
+ op.returnCode, &op.ret.establishContext);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
}
|
|
|
|
-void rdpdr_server_context_free(RdpdrServerContext* context)
|
|
+static UINT rdpdr_server_smartcard_establish_context(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 dwScope,
|
|
+ UINT32* completionId)
|
|
{
|
|
- if (!context)
|
|
- return;
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(completionId);
|
|
|
|
- rdpdr_server_private_free(context->priv);
|
|
- free(context);
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ switch (dwScope)
|
|
+ {
|
|
+ case SCARD_SCOPE_USER:
|
|
+ case SCARD_SCOPE_TERMINAL:
|
|
+ case SCARD_SCOPE_SYSTEM:
|
|
+ break;
|
|
+ default:
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "invalid dwScope=0x%08" PRIx32, dwScope);
|
|
+ return ERROR_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ result = prepare_smartcard_irp(context, SCARD_IOCTL_ESTABLISHCONTEXT,
|
|
+ rdpdr_server_smartcard_establish_context_callback, callbackData,
|
|
+ &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_ESTABLISHCONTEXT,
|
|
+ .call.establishContext.dwScope = dwScope,
|
|
+ };
|
|
+
|
|
+ s = Stream_New(nullptr, 64);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* ReleaseContext */
|
|
+static UINT rdpdr_server_smartcard_release_context_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardReleaseContextCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardReleaseContextComplete)
|
|
+ context->OnSmartcardReleaseContextComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardReleaseContextComplete)
|
|
+ context->OnSmartcardReleaseContextComplete(context, irp->CallbackData, ioStatus,
|
|
+ op.returnCode);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_release_context(RdpdrServerContext* context, void* callbackData,
|
|
+ const REDIR_SCARDCONTEXT* hContext,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(hContext);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result =
|
|
+ prepare_smartcard_irp(context, SCARD_IOCTL_RELEASECONTEXT,
|
|
+ rdpdr_server_smartcard_release_context_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_RELEASECONTEXT,
|
|
+ .call.context.handles.hContext = *hContext,
|
|
+ };
|
|
+
|
|
+ s = Stream_New(nullptr, 64);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* IsValidContext */
|
|
+static UINT rdpdr_server_smartcard_is_valid_context_callback(RdpdrServerContext* context,
|
|
+ wStream* s, RDPDR_IRP* irp,
|
|
+ UINT32 deviceId, UINT32 completionId,
|
|
+ UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardIsValidContextCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardIsValidContextComplete)
|
|
+ context->OnSmartcardIsValidContextComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardIsValidContextComplete)
|
|
+ context->OnSmartcardIsValidContextComplete(context, irp->CallbackData, ioStatus,
|
|
+ op.returnCode);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_is_valid_context(RdpdrServerContext* context, void* callbackData,
|
|
+ const REDIR_SCARDCONTEXT* hContext,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(hContext);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result =
|
|
+ prepare_smartcard_irp(context, SCARD_IOCTL_ISVALIDCONTEXT,
|
|
+ rdpdr_server_smartcard_is_valid_context_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_ISVALIDCONTEXT,
|
|
+ .call.context.handles.hContext = *hContext,
|
|
+ };
|
|
+
|
|
+ s = Stream_New(nullptr, 64);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* ListReaderGroups */
|
|
+static UINT rdpdr_server_smartcard_list_reader_groups_callback(RdpdrServerContext* context,
|
|
+ wStream* s, RDPDR_IRP* irp,
|
|
+ UINT32 deviceId, UINT32 completionId,
|
|
+ UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardListReaderGroupsCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardListReaderGroupsComplete)
|
|
+ context->OnSmartcardListReaderGroupsComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardListReaderGroupsComplete)
|
|
+ context->OnSmartcardListReaderGroupsComplete(context, irp->CallbackData, ioStatus,
|
|
+ op.returnCode, &op.ret.listReaders);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_list_reader_groups(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioControlCode,
|
|
+ const ListReaderGroups_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, ioControlCode,
|
|
+ rdpdr_server_smartcard_list_reader_groups_callback, callbackData,
|
|
+ &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = ioControlCode,
|
|
+ .call.listReaderGroups = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .fmszGroupsIsNULL = call->fmszGroupsIsNULL,
|
|
+ .cchGroups = call->cchGroups,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 32);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_list_reader_groupsA(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const ListReaderGroups_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_list_reader_groups(
|
|
+ context, callbackData, SCARD_IOCTL_LISTREADERGROUPSA, call, completionId);
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_list_reader_groupsW(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const ListReaderGroups_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_list_reader_groups(
|
|
+ context, callbackData, SCARD_IOCTL_LISTREADERGROUPSW, call, completionId);
|
|
+}
|
|
+
|
|
+/* ListReaders */
|
|
+static UINT rdpdr_server_smartcard_list_readers_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardListReadersCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardListReadersComplete)
|
|
+ context->OnSmartcardListReadersComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardListReadersComplete)
|
|
+ context->OnSmartcardListReadersComplete(context, irp->CallbackData, ioStatus, op.returnCode,
|
|
+ &op.ret.listReaders);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_list_readers(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 ioControlCode, const ListReaders_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(
|
|
+ context, ioControlCode, rdpdr_server_smartcard_list_readers_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = ioControlCode,
|
|
+ .call.listReaders = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .cBytes = call->cBytes,
|
|
+ .mszGroups = call->mszGroups,
|
|
+ .fmszReadersIsNULL = call->fmszReadersIsNULL,
|
|
+ .cchReaders = call->cchReaders,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 256);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_list_readersA(RdpdrServerContext* context, void* callbackData,
|
|
+ const ListReaders_Call* call, UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_list_readers(context, callbackData, SCARD_IOCTL_LISTREADERSA,
|
|
+ call, completionId);
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_list_readersW(RdpdrServerContext* context, void* callbackData,
|
|
+ const ListReaders_Call* call, UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_list_readers(context, callbackData, SCARD_IOCTL_LISTREADERSW,
|
|
+ call, completionId);
|
|
+}
|
|
+
|
|
+/* GetStatusChange */
|
|
+static UINT rdpdr_server_smartcard_get_status_change_callback(RdpdrServerContext* context,
|
|
+ wStream* s, RDPDR_IRP* irp,
|
|
+ UINT32 deviceId, UINT32 completionId,
|
|
+ UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardGetStatusChangeCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardGetStatusChangeComplete)
|
|
+ context->OnSmartcardGetStatusChangeComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardGetStatusChangeComplete)
|
|
+ context->OnSmartcardGetStatusChangeComplete(context, irp->CallbackData, ioStatus,
|
|
+ op.returnCode, &op.ret.getStatusChange);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_get_status_change(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioControlCode,
|
|
+ const void* call, DWORD cReaders,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, ioControlCode,
|
|
+ rdpdr_server_smartcard_get_status_change_callback, callbackData,
|
|
+ &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+ op.ioControlCode = ioControlCode;
|
|
+
|
|
+ switch (ioControlCode)
|
|
+ {
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEA:
|
|
+ op.call.getStatusChangeA = *(const GetStatusChangeA_Call*)call;
|
|
+ break;
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEW:
|
|
+ op.call.getStatusChangeW = *(const GetStatusChangeW_Call*)call;
|
|
+ break;
|
|
+ default:
|
|
+ WINPR_ASSERT(FALSE);
|
|
+ return ERROR_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ s = Stream_New(nullptr, 256 + cReaders * 256);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_get_status_changeA(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const GetStatusChangeA_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_get_status_change(
|
|
+ context, callbackData, SCARD_IOCTL_GETSTATUSCHANGEA, call, call->cReaders, completionId);
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_get_status_changeW(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const GetStatusChangeW_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_get_status_change(
|
|
+ context, callbackData, SCARD_IOCTL_GETSTATUSCHANGEW, call, call->cReaders, completionId);
|
|
+}
|
|
+
|
|
+/* Cancel */
|
|
+static UINT rdpdr_server_smartcard_cancel_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardCancelCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardCancelComplete)
|
|
+ context->OnSmartcardCancelComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardCancelComplete)
|
|
+ context->OnSmartcardCancelComplete(context, irp->CallbackData, ioStatus, op.returnCode);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_cancel(RdpdrServerContext* context, void* callbackData,
|
|
+ const REDIR_SCARDCONTEXT* hContext, UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(hContext);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, SCARD_IOCTL_CANCEL,
|
|
+ rdpdr_server_smartcard_cancel_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_CANCEL,
|
|
+ .call.context.handles.hContext = *hContext,
|
|
+ };
|
|
+
|
|
+ s = Stream_New(nullptr, 64);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* Connect */
|
|
+static UINT rdpdr_server_smartcard_connect_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardConnectCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardConnectComplete)
|
|
+ context->OnSmartcardConnectComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardConnectComplete)
|
|
+ context->OnSmartcardConnectComplete(context, irp->CallbackData, ioStatus, op.returnCode,
|
|
+ &op.ret.connect);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_connect(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 ioControlCode, const void* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, ioControlCode, rdpdr_server_smartcard_connect_callback,
|
|
+ callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+ op.ioControlCode = ioControlCode;
|
|
+
|
|
+ switch (ioControlCode)
|
|
+ {
|
|
+ case SCARD_IOCTL_CONNECTA:
|
|
+ op.call.connectA = *(const ConnectA_Call*)call;
|
|
+ break;
|
|
+ case SCARD_IOCTL_CONNECTW:
|
|
+ op.call.connectW = *(const ConnectW_Call*)call;
|
|
+ break;
|
|
+ default:
|
|
+ WINPR_ASSERT(FALSE);
|
|
+ return ERROR_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ s = Stream_New(nullptr, 512);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_connectA(RdpdrServerContext* context, void* callbackData,
|
|
+ const ConnectA_Call* call, UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_connect(context, callbackData, SCARD_IOCTL_CONNECTA, call,
|
|
+ completionId);
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_connectW(RdpdrServerContext* context, void* callbackData,
|
|
+ const ConnectW_Call* call, UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_connect(context, callbackData, SCARD_IOCTL_CONNECTW, call,
|
|
+ completionId);
|
|
+}
|
|
+
|
|
+/* Reconnect */
|
|
+static UINT rdpdr_server_smartcard_reconnect_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardReconnectCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardReconnectComplete)
|
|
+ context->OnSmartcardReconnectComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardReconnectComplete)
|
|
+ context->OnSmartcardReconnectComplete(context, irp->CallbackData, ioStatus, op.returnCode,
|
|
+ &op.ret.reconnect);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_reconnect(RdpdrServerContext* context, void* callbackData,
|
|
+ const Reconnect_Call* call, UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, SCARD_IOCTL_RECONNECT,
|
|
+ rdpdr_server_smartcard_reconnect_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_RECONNECT,
|
|
+ .call.reconnect = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwShareMode = call->dwShareMode,
|
|
+ .dwPreferredProtocols = call->dwPreferredProtocols,
|
|
+ .dwInitialization = call->dwInitialization,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 128);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* Disconnect */
|
|
+static UINT rdpdr_server_smartcard_disconnect_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardDisconnectCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardDisconnectComplete)
|
|
+ context->OnSmartcardDisconnectComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardDisconnectComplete)
|
|
+ context->OnSmartcardDisconnectComplete(context, irp->CallbackData, ioStatus, op.returnCode);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_disconnect(RdpdrServerContext* context, void* callbackData,
|
|
+ const HCardAndDisposition_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, SCARD_IOCTL_DISCONNECT,
|
|
+ rdpdr_server_smartcard_disconnect_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_DISCONNECT,
|
|
+ .call.hCardAndDisposition = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwDisposition = call->dwDisposition,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 128);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* BeginTransaction */
|
|
+static UINT rdpdr_server_smartcard_begin_transaction_callback(RdpdrServerContext* context,
|
|
+ wStream* s, RDPDR_IRP* irp,
|
|
+ UINT32 deviceId, UINT32 completionId,
|
|
+ UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardBeginTransactionCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardBeginTransactionComplete)
|
|
+ context->OnSmartcardBeginTransactionComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardBeginTransactionComplete)
|
|
+ context->OnSmartcardBeginTransactionComplete(context, irp->CallbackData, ioStatus,
|
|
+ op.returnCode);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_begin_transaction(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const HCardAndDisposition_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, SCARD_IOCTL_BEGINTRANSACTION,
|
|
+ rdpdr_server_smartcard_begin_transaction_callback, callbackData,
|
|
+ &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_BEGINTRANSACTION,
|
|
+ .call.hCardAndDisposition = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwDisposition = SCARD_LEAVE_CARD,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 128);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* EndTransaction */
|
|
+static UINT rdpdr_server_smartcard_end_transaction_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardEndTransactionCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardEndTransactionComplete)
|
|
+ context->OnSmartcardEndTransactionComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardEndTransactionComplete)
|
|
+ context->OnSmartcardEndTransactionComplete(context, irp->CallbackData, ioStatus,
|
|
+ op.returnCode);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_end_transaction(RdpdrServerContext* context, void* callbackData,
|
|
+ const HCardAndDisposition_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result =
|
|
+ prepare_smartcard_irp(context, SCARD_IOCTL_ENDTRANSACTION,
|
|
+ rdpdr_server_smartcard_end_transaction_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_ENDTRANSACTION,
|
|
+ .call.hCardAndDisposition = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwDisposition = call->dwDisposition,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 128);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* Status */
|
|
+static UINT rdpdr_server_smartcard_status_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardStatusCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardStatusComplete)
|
|
+ context->OnSmartcardStatusComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardStatusComplete)
|
|
+ context->OnSmartcardStatusComplete(context, irp->CallbackData, ioStatus, op.returnCode,
|
|
+ &op.ret.status);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_status(RdpdrServerContext* context, void* callbackData,
|
|
+ UINT32 ioControlCode, const Status_Call* call,
|
|
+ UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, ioControlCode, rdpdr_server_smartcard_status_callback,
|
|
+ callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = ioControlCode,
|
|
+ .call.status = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .fmszReaderNamesIsNULL = call->fmszReaderNamesIsNULL,
|
|
+ .cchReaderLen = call->cchReaderLen,
|
|
+ .cbAtrLen = call->cbAtrLen,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 128);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_statusA(RdpdrServerContext* context, void* callbackData,
|
|
+ const Status_Call* call, UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_status(context, callbackData, SCARD_IOCTL_STATUSA, call,
|
|
+ completionId);
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_statusW(RdpdrServerContext* context, void* callbackData,
|
|
+ const Status_Call* call, UINT32* completionId)
|
|
+{
|
|
+ return rdpdr_server_smartcard_status(context, callbackData, SCARD_IOCTL_STATUSW, call,
|
|
+ completionId);
|
|
+}
|
|
+
|
|
+/* Transmit */
|
|
+static UINT rdpdr_server_smartcard_transmit_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardTransmitCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardTransmitComplete)
|
|
+ context->OnSmartcardTransmitComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardTransmitComplete)
|
|
+ context->OnSmartcardTransmitComplete(context, irp->CallbackData, ioStatus, op.returnCode,
|
|
+ &op.ret.transmit);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_transmit(RdpdrServerContext* context, void* callbackData,
|
|
+ const Transmit_Call* call, UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, SCARD_IOCTL_TRANSMIT,
|
|
+ rdpdr_server_smartcard_transmit_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_TRANSMIT,
|
|
+ .call.transmit = *call
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 512 + call->cbSendLength);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* Control */
|
|
+static UINT rdpdr_server_smartcard_control_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardControlCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardControlComplete)
|
|
+ context->OnSmartcardControlComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardControlComplete)
|
|
+ context->OnSmartcardControlComplete(context, irp->CallbackData, ioStatus, op.returnCode,
|
|
+ &op.ret.control);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_control(RdpdrServerContext* context, void* callbackData,
|
|
+ const Control_Call* call, UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, SCARD_IOCTL_CONTROL,
|
|
+ rdpdr_server_smartcard_control_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_CONTROL,
|
|
+ .call.control = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwControlCode = call->dwControlCode,
|
|
+ .cbInBufferSize = call->cbInBufferSize,
|
|
+ .pvInBuffer = call->pvInBuffer,
|
|
+ .fpvOutBufferIsNULL = call->fpvOutBufferIsNULL,
|
|
+ .cbOutBufferSize = call->cbOutBufferSize,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 512 + call->cbOutBufferSize);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/* getAttrib */
|
|
+static UINT rdpdr_server_smartcard_get_attrib_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardGetAttribCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardGetAttribComplete)
|
|
+ context->OnSmartcardGetAttribComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR, nullptr);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardGetAttribComplete)
|
|
+ context->OnSmartcardGetAttribComplete(context, irp->CallbackData, ioStatus, op.returnCode,
|
|
+ &op.ret.getAttrib);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+UINT rdpdr_server_smartcard_get_attrib(RdpdrServerContext* context, void* callbackData,
|
|
+ const GetAttrib_Call* call, UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ UINT ret =
|
|
+ prepare_smartcard_irp(context, SCARD_IOCTL_GETATTRIB,
|
|
+ rdpdr_server_smartcard_get_attrib_callback, callbackData, &irp);
|
|
+ if (ret != CHANNEL_RC_OK)
|
|
+ return ret;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_GETATTRIB,
|
|
+ .call.getAttrib = *call
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ wStream* s = Stream_New(nullptr, 64);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ return CHANNEL_RC_NO_MEMORY;
|
|
+ }
|
|
+
|
|
+ LONG status = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ Stream_Release(s);
|
|
+ return ERROR_INTERNAL_ERROR;
|
|
+ }
|
|
+
|
|
+ const UINT error = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+ Stream_Release(s);
|
|
+ return error;
|
|
+}
|
|
+
|
|
+/* SetAttrib */
|
|
+static UINT rdpdr_server_smartcard_set_attrib_callback(RdpdrServerContext* context, wStream* s,
|
|
+ RDPDR_IRP* irp, UINT32 deviceId,
|
|
+ UINT32 completionId, UINT32 ioStatus)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(s);
|
|
+ WINPR_ASSERT(irp);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ SMARTCARD_OPERATION op = WINPR_C_ARRAY_INIT;
|
|
+
|
|
+ WLog_Print(priv->log, WLOG_DEBUG,
|
|
+ "SmartcardSetAttribCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32
|
|
+ ", ioStatus=0x%" PRIx32,
|
|
+ deviceId, completionId, ioStatus);
|
|
+
|
|
+ if (ioStatus != STATUS_SUCCESS)
|
|
+ {
|
|
+ if (context->OnSmartcardSetAttribComplete)
|
|
+ context->OnSmartcardSetAttribComplete(context, irp->CallbackData, ioStatus,
|
|
+ SCARD_F_INTERNAL_ERROR);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INVALID_DATA;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (context->OnSmartcardSetAttribComplete)
|
|
+ context->OnSmartcardSetAttribComplete(context, irp->CallbackData, ioStatus, op.returnCode);
|
|
+
|
|
+out:
|
|
+ smartcard_operation_free(&op, FALSE);
|
|
+ rdpdr_server_irp_free(irp);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+static UINT rdpdr_server_smartcard_set_attrib(RdpdrServerContext* context, void* callbackData,
|
|
+ const SetAttrib_Call* call, UINT32* completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(context->priv);
|
|
+ WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(completionId);
|
|
+
|
|
+ UINT result = CHANNEL_RC_OK;
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ RDPDR_IRP* irp = nullptr;
|
|
+ wStream* s = nullptr;
|
|
+
|
|
+ result = prepare_smartcard_irp(context, SCARD_IOCTL_SETATTRIB,
|
|
+ rdpdr_server_smartcard_set_attrib_callback, callbackData, &irp);
|
|
+ if (result != CHANNEL_RC_OK)
|
|
+ return result;
|
|
+
|
|
+ *completionId = irp->CompletionId;
|
|
+
|
|
+ /* clang-format off */
|
|
+ const SMARTCARD_OPERATION op = {
|
|
+ .ioControlCode = SCARD_IOCTL_SETATTRIB,
|
|
+ .call.setAttrib = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwAttrId = call->dwAttrId,
|
|
+ .cbAttrLen = call->cbAttrLen,
|
|
+ .pbAttr = call->pbAttr,
|
|
+ }
|
|
+ };
|
|
+ /* clang-format on */
|
|
+
|
|
+ s = Stream_New(nullptr, 64 + call->cbAttrLen);
|
|
+ if (!s)
|
|
+ {
|
|
+ WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
+ result = CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (result != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ result = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ result = rdpdr_server_send_device_control_request(
|
|
+ context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
+ SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
+
|
|
+out:
|
|
+ if (result != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
+ return result;
|
|
+}
|
|
+
|
|
+RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
|
|
+{
|
|
+ RdpdrServerContext* context = (RdpdrServerContext*)calloc(1, sizeof(RdpdrServerContext));
|
|
+
|
|
+ if (!context)
|
|
+ goto fail;
|
|
+
|
|
+ context->vcm = vcm;
|
|
+ context->Start = rdpdr_server_start;
|
|
+ context->Stop = rdpdr_server_stop;
|
|
+ context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
|
|
+ context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
|
|
+ context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
|
|
+ context->DriveOpenFile = rdpdr_server_drive_open_file;
|
|
+ context->DriveReadFile = rdpdr_server_drive_read_file;
|
|
+ context->DriveWriteFile = rdpdr_server_drive_write_file;
|
|
+ context->DriveCloseFile = rdpdr_server_drive_close_file;
|
|
+ context->DriveDeleteFile = rdpdr_server_drive_delete_file;
|
|
+ context->DriveRenameFile = rdpdr_server_drive_rename_file;
|
|
+ context->SmartcardEstablishContext = rdpdr_server_smartcard_establish_context;
|
|
+ context->SmartcardReleaseContext = rdpdr_server_smartcard_release_context;
|
|
+ context->SmartcardIsValidContext = rdpdr_server_smartcard_is_valid_context;
|
|
+ context->SmartcardListReaderGroupsA = rdpdr_server_smartcard_list_reader_groupsA;
|
|
+ context->SmartcardListReaderGroupsW = rdpdr_server_smartcard_list_reader_groupsW;
|
|
+ context->SmartcardListReadersA = rdpdr_server_smartcard_list_readersA;
|
|
+ context->SmartcardListReadersW = rdpdr_server_smartcard_list_readersW;
|
|
+ context->SmartcardGetStatusChangeA = rdpdr_server_smartcard_get_status_changeA;
|
|
+ context->SmartcardGetStatusChangeW = rdpdr_server_smartcard_get_status_changeW;
|
|
+ context->SmartcardCancel = rdpdr_server_smartcard_cancel;
|
|
+ context->SmartcardConnectA = rdpdr_server_smartcard_connectA;
|
|
+ context->SmartcardConnectW = rdpdr_server_smartcard_connectW;
|
|
+ context->SmartcardReconnect = rdpdr_server_smartcard_reconnect;
|
|
+ context->SmartcardDisconnect = rdpdr_server_smartcard_disconnect;
|
|
+ context->SmartcardBeginTransaction = rdpdr_server_smartcard_begin_transaction;
|
|
+ context->SmartcardEndTransaction = rdpdr_server_smartcard_end_transaction;
|
|
+ context->SmartcardStatusA = rdpdr_server_smartcard_statusA;
|
|
+ context->SmartcardStatusW = rdpdr_server_smartcard_statusW;
|
|
+ context->SmartcardTransmit = rdpdr_server_smartcard_transmit;
|
|
+ context->SmartcardControl = rdpdr_server_smartcard_control;
|
|
+ context->SmartcardGetAttrib = rdpdr_server_smartcard_get_attrib;
|
|
+ context->SmartcardSetAttrib = rdpdr_server_smartcard_set_attrib;
|
|
+ context->priv = rdpdr_server_private_new();
|
|
+ if (!context->priv)
|
|
+ goto fail;
|
|
+
|
|
+ /* By default announce everything, the server application can deactivate that later on */
|
|
+ context->supported = UINT16_MAX;
|
|
+
|
|
+ return context;
|
|
+fail:
|
|
+ WINPR_PRAGMA_DIAG_PUSH
|
|
+ WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
|
+ rdpdr_server_context_free(context);
|
|
+ WINPR_PRAGMA_DIAG_POP
|
|
+ return nullptr;
|
|
+}
|
|
+
|
|
+void rdpdr_server_context_free(RdpdrServerContext* context)
|
|
+{
|
|
+ if (!context)
|
|
+ return;
|
|
+
|
|
+ rdpdr_server_private_free(context->priv);
|
|
+ free(context);
|
|
+}
|
|
+
|
|
+void rdpdr_server_discard_request(RdpdrServerContext* context, UINT32 completionId)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+
|
|
+ RdpdrServerPrivate* priv = context->priv;
|
|
+ const uintptr_t key = completionId + 1ull;
|
|
+ ListDictionary_Remove(priv->IrpList, (void*)key);
|
|
}
|
|
diff --git a/include/freerdp/server/rdpdr.h b/include/freerdp/server/rdpdr.h
|
|
index 411b33b6d6d7..a44a7e1cef87 100644
|
|
--- a/include/freerdp/server/rdpdr.h
|
|
+++ b/include/freerdp/server/rdpdr.h
|
|
@@ -28,6 +28,7 @@
|
|
#include <freerdp/types.h>
|
|
#include <freerdp/channels/wtsvc.h>
|
|
#include <freerdp/channels/rdpdr.h>
|
|
+#include <freerdp/channels/scard.h>
|
|
#include <freerdp/utils/rdpdr_utils.h>
|
|
|
|
#ifdef __cplusplus
|
|
@@ -133,6 +134,117 @@ extern "C"
|
|
typedef UINT (*psRdpdrOnDeviceCreate)(RdpdrServerContext* context, const RdpdrDevice* device);
|
|
typedef UINT (*psRdpdrOnDeviceDelete)(RdpdrServerContext* context, UINT32 deviceId);
|
|
|
|
+ typedef UINT (*psRdpdrSmartcardEstablishContext)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 dwScope,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardReleaseContext)(RdpdrServerContext* context, void* callbackData,
|
|
+ const REDIR_SCARDCONTEXT* hContext,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardIsValidContext)(RdpdrServerContext* context, void* callbackData,
|
|
+ const REDIR_SCARDCONTEXT* hContext,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardListReaderGroups)(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const ListReaderGroups_Call* call,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardListReaders)(RdpdrServerContext* context, void* callbackData,
|
|
+ const ListReaders_Call* call, UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardGetStatusChangeA)(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const GetStatusChangeA_Call* call,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardGetStatusChangeW)(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const GetStatusChangeW_Call* call,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardCancel)(RdpdrServerContext* context, void* callbackData,
|
|
+ const REDIR_SCARDCONTEXT* hContext,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardConnectA)(RdpdrServerContext* context, void* callbackData,
|
|
+ const ConnectA_Call* call, UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardConnectW)(RdpdrServerContext* context, void* callbackData,
|
|
+ const ConnectW_Call* call, UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardReconnect)(RdpdrServerContext* context, void* callbackData,
|
|
+ const Reconnect_Call* call, UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardDisconnect)(RdpdrServerContext* context, void* callbackData,
|
|
+ const HCardAndDisposition_Call* call,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardBeginTransaction)(RdpdrServerContext* context,
|
|
+ void* callbackData,
|
|
+ const HCardAndDisposition_Call* call,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardEndTransaction)(RdpdrServerContext* context, void* callbackData,
|
|
+ const HCardAndDisposition_Call* call,
|
|
+ UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardStatus)(RdpdrServerContext* context, void* callbackData,
|
|
+ const Status_Call* call, UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardTransmit)(RdpdrServerContext* context, void* callbackData,
|
|
+ const Transmit_Call* call, UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardControl)(RdpdrServerContext* context, void* callbackData,
|
|
+ const Control_Call* call, UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardGetAttrib)(RdpdrServerContext* context, void* callbackData,
|
|
+ const GetAttrib_Call* call, UINT32* completionId);
|
|
+ typedef UINT (*psRdpdrSmartcardSetAttrib)(RdpdrServerContext* context, void* callbackData,
|
|
+ const SetAttrib_Call* call, UINT32* completionId);
|
|
+
|
|
+ typedef void (*psRdpdrOnSmartcardEstablishContextComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode,
|
|
+ const EstablishContext_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardReleaseContextComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode);
|
|
+ typedef void (*psRdpdrOnSmartcardIsValidContextComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode);
|
|
+ typedef void (*psRdpdrOnSmartcardListReaderGroupsComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode,
|
|
+ const ListReaderGroups_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardListReadersComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode,
|
|
+ const ListReaders_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardGetStatusChangeComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode,
|
|
+ const GetStatusChange_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardCancelComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode);
|
|
+ typedef void (*psRdpdrOnSmartcardConnectComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode, const Connect_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardReconnectComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode,
|
|
+ const Reconnect_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardDisconnectComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode);
|
|
+ typedef void (*psRdpdrOnSmartcardBeginTransactionComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode);
|
|
+ typedef void (*psRdpdrOnSmartcardEndTransactionComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode);
|
|
+ typedef void (*psRdpdrOnSmartcardStatusComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode, const Status_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardTransmitComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode, const Transmit_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardControlComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode, const Control_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardGetAttribComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode,
|
|
+ const GetAttrib_Return* ret);
|
|
+ typedef void (*psRdpdrOnSmartcardSetAttribComplete)(RdpdrServerContext* context,
|
|
+ void* callbackData, UINT32 ioStatus,
|
|
+ LONG returnCode);
|
|
+
|
|
struct s_rdpdr_server_context
|
|
{
|
|
HANDLE vcm;
|
|
@@ -233,6 +345,107 @@ extern "C"
|
|
RDPDR_DTYP_SMARTCARD after \b ReceiveDeviceRemove */
|
|
|
|
rdpContext* rdpcontext;
|
|
+
|
|
+ /*** New Smartcard APIs called by the server. ***/
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardEstablishContext
|
|
+ SmartcardEstablishContext; /**< Send SCardEstablishContext to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardReleaseContext
|
|
+ SmartcardReleaseContext; /**< Send SCardReleaseContext to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardIsValidContext
|
|
+ SmartcardIsValidContext; /**< Send SCardIsValidContext to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardListReaderGroups
|
|
+ SmartcardListReaderGroupsA; /**< Send SCardListReaderGroupsA to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardListReaderGroups
|
|
+ SmartcardListReaderGroupsW; /**< Send SCardListReaderGroupsW to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardListReaders
|
|
+ SmartcardListReadersA; /**< Send SCardListReadersA to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardListReaders
|
|
+ SmartcardListReadersW; /**< Send SCardListReadersW to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardGetStatusChangeA
|
|
+ SmartcardGetStatusChangeA; /**< Send SCardGetStatusChangeA to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardGetStatusChangeW
|
|
+ SmartcardGetStatusChangeW; /**< Send SCardGetStatusChangeW to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardCancel
|
|
+ SmartcardCancel; /**< Send SCardCancel to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardConnectA
|
|
+ SmartcardConnectA; /**< Send SCardConnectA to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardConnectW
|
|
+ SmartcardConnectW; /**< Send SCardConnectW to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardReconnect
|
|
+ SmartcardReconnect; /**< Send SCardReconnect to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardDisconnect
|
|
+ SmartcardDisconnect; /**< Send SCardDisconnect to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardBeginTransaction
|
|
+ SmartcardBeginTransaction; /**< Send SCardBeginTransaction to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardEndTransaction
|
|
+ SmartcardEndTransaction; /**< Send SCardEndTransaction to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardStatus
|
|
+ SmartcardStatusA; /**< Send SCardStatusA to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardStatus
|
|
+ SmartcardStatusW; /**< Send SCardStatusW to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardTransmit
|
|
+ SmartcardTransmit; /**< Send SCardTransmit to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardControl
|
|
+ SmartcardControl; /**< Send SCardControl to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardGetAttrib
|
|
+ SmartcardGetAttrib; /**< Send SCardGetAttrib to the client. */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrSmartcardSetAttrib
|
|
+ SmartcardSetAttrib; /**< Send SCardSetAttrib to the client. */
|
|
+
|
|
+ /*** New Smartcard callbacks registered by the server. ***/
|
|
+ /* clang-format off */
|
|
+ psRdpdrOnSmartcardEstablishContextComplete
|
|
+ OnSmartcardEstablishContextComplete; /**< Completion callback for
|
|
+ SmartcardEstablishContext. */
|
|
+ psRdpdrOnSmartcardReleaseContextComplete
|
|
+ OnSmartcardReleaseContextComplete; /**< Completion callback for
|
|
+ SmartcardReleaseContext. */
|
|
+ psRdpdrOnSmartcardIsValidContextComplete
|
|
+ OnSmartcardIsValidContextComplete; /**< Completion callback for
|
|
+ SmartcardIsValidContext. */
|
|
+ psRdpdrOnSmartcardListReaderGroupsComplete
|
|
+ OnSmartcardListReaderGroupsComplete; /**< Completion callback for
|
|
+ SmartcardListReaderGroups. */
|
|
+ psRdpdrOnSmartcardListReadersComplete
|
|
+ OnSmartcardListReadersComplete; /**< Completion callback for
|
|
+ SmartcardListReaders. */
|
|
+ psRdpdrOnSmartcardGetStatusChangeComplete
|
|
+ OnSmartcardGetStatusChangeComplete; /**< Completion callback for
|
|
+ SmartcardGetStatusChange. */
|
|
+ psRdpdrOnSmartcardCancelComplete
|
|
+ OnSmartcardCancelComplete; /**< Completion callback for
|
|
+ SmartcardCancel. */
|
|
+ psRdpdrOnSmartcardConnectComplete
|
|
+ OnSmartcardConnectComplete; /**< Completion callback for
|
|
+ SmartcardConnect. */
|
|
+ psRdpdrOnSmartcardReconnectComplete
|
|
+ OnSmartcardReconnectComplete; /**< Completion callback for
|
|
+ SmartcardReconnect. */
|
|
+ psRdpdrOnSmartcardDisconnectComplete
|
|
+ OnSmartcardDisconnectComplete; /**< Completion callback for
|
|
+ SmartcardDisconnect. */
|
|
+ psRdpdrOnSmartcardBeginTransactionComplete
|
|
+ OnSmartcardBeginTransactionComplete; /**< Completion callback for
|
|
+ SmartcardBeginTransaction. */
|
|
+ psRdpdrOnSmartcardEndTransactionComplete
|
|
+ OnSmartcardEndTransactionComplete; /**< Completion callback for
|
|
+ SmartcardEndTransaction. */
|
|
+ psRdpdrOnSmartcardStatusComplete
|
|
+ OnSmartcardStatusComplete; /**< Completion callback for
|
|
+ SmartcardStatus. */
|
|
+ psRdpdrOnSmartcardTransmitComplete
|
|
+ OnSmartcardTransmitComplete; /**< Completion callback for
|
|
+ SmartcardTransmit. */
|
|
+ psRdpdrOnSmartcardControlComplete
|
|
+ OnSmartcardControlComplete; /**< Completion callback for
|
|
+ SmartcardControl. */
|
|
+ psRdpdrOnSmartcardGetAttribComplete
|
|
+ OnSmartcardGetAttribComplete; /**< Completion callback for
|
|
+ SmartcardGetAttrib. */
|
|
+ psRdpdrOnSmartcardSetAttribComplete
|
|
+ OnSmartcardSetAttribComplete; /**< Completion callback for
|
|
+ SmartcardSetAttrib. */
|
|
+ /* clang-format on */
|
|
};
|
|
|
|
FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context);
|
|
@@ -241,6 +454,13 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD
|
|
FREERDP_API RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm);
|
|
|
|
+ /**
|
|
+ * @brief Remove and free a pending IRP request from the context.
|
|
+ * @param context The RDPDR server context.
|
|
+ * @param completionId The completion ID of the IRP to discard.
|
|
+ * @since version 3.28
|
|
+ */
|
|
+ FREERDP_API void rdpdr_server_discard_request(RdpdrServerContext* context, UINT32 completionId);
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
diff --git a/libfreerdp/utils/test/CMakeLists.txt b/libfreerdp/utils/test/CMakeLists.txt
|
|
index 0c2bf8491d7f..eedd7b2599f6 100644
|
|
--- a/libfreerdp/utils/test/CMakeLists.txt
|
|
+++ b/libfreerdp/utils/test/CMakeLists.txt
|
|
@@ -5,7 +5,9 @@ disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
|
|
|
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
|
|
|
-set(${MODULE_PREFIX}_TESTS TestRingBuffer.c TestPodArrays.c TestEncodedTypes.c TestSmartcardPack.c)
|
|
+set(${MODULE_PREFIX}_TESTS TestRingBuffer.c TestPodArrays.c TestEncodedTypes.c TestSmartcardPack.c
|
|
+ TestSmartcardOperations.c
|
|
+)
|
|
|
|
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
|
|
|
diff --git a/libfreerdp/utils/test/TestSmartcardOperations.c b/libfreerdp/utils/test/TestSmartcardOperations.c
|
|
new file mode 100644
|
|
index 000000000000..4c885b13359c
|
|
--- /dev/null
|
|
+++ b/libfreerdp/utils/test/TestSmartcardOperations.c
|
|
@@ -0,0 +1,1445 @@
|
|
+/**
|
|
+ * FreeRDP: A Remote Desktop Protocol Implementation
|
|
+ *
|
|
+ * Copyright 2026 Joan Torres Lopez <joantolo@redhat.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.
|
|
+ */
|
|
+
|
|
+#include <stdio.h>
|
|
+
|
|
+#include <winpr/crt.h>
|
|
+#include <winpr/stream.h>
|
|
+#include <winpr/smartcard.h>
|
|
+
|
|
+#include <freerdp/channels/rdpdr.h>
|
|
+#include <freerdp/channels/scard.h>
|
|
+#include <freerdp/utils/rdpdr_utils.h>
|
|
+#include <freerdp/utils/smartcard_operations.h>
|
|
+#include <freerdp/utils/smartcard_pack.h>
|
|
+
|
|
+static inline void fill_redir_context(REDIR_SCARDCONTEXT* ctx, SCARDCONTEXT val)
|
|
+{
|
|
+ smartcard_scard_context_native_to_redir(ctx, val);
|
|
+}
|
|
+
|
|
+static inline void fill_redir_handle(REDIR_SCARDHANDLE* handle, SCARDHANDLE val)
|
|
+{
|
|
+ smartcard_scard_handle_native_to_redir(handle, val);
|
|
+}
|
|
+
|
|
+static wStream* build_device_control_request(UINT32 ioControlCode, const void* inputBuffer,
|
|
+ size_t inputBufferLength)
|
|
+{
|
|
+ const char* name = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ const size_t totalLength = RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH + inputBufferLength;
|
|
+
|
|
+ wStream* s = Stream_New(NULL, totalLength);
|
|
+ if (!s)
|
|
+ {
|
|
+ (void)fprintf(stderr, "build_device_control_request(%s): Stream_New(%" PRIuz ") failed\n",
|
|
+ name, totalLength);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ UINT32 inputLength = WINPR_ASSERTING_INT_CAST(UINT32, inputBufferLength);
|
|
+ Stream_Write_UINT32(s, 2048); /* OutputBufferLength */
|
|
+ Stream_Write_UINT32(s, inputLength); /* InputBufferLength */
|
|
+ Stream_Write_UINT32(s, ioControlCode); /* IoControlCode */
|
|
+ Stream_Zero(s, 20); /* Padding */
|
|
+
|
|
+ if (inputBufferLength > 0)
|
|
+ Stream_Write(s, inputBuffer, inputBufferLength);
|
|
+
|
|
+ Stream_SealLength(s);
|
|
+ if (!Stream_SetPosition(s, 0))
|
|
+ {
|
|
+ (void)fprintf(stderr, "build_device_control_request(%s): Stream_SetPosition failed\n",
|
|
+ name);
|
|
+ Stream_Release(s);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return s;
|
|
+}
|
|
+
|
|
+static BOOL test_request_roundtrip(const SMARTCARD_OPERATION* opIn, SMARTCARD_OPERATION* opOut)
|
|
+{
|
|
+ const UINT32 ioControlCode = opIn->ioControlCode;
|
|
+ const char* name = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+
|
|
+ wStream* sEnc = Stream_New(NULL, 4096);
|
|
+ if (!sEnc)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: Stream_New for encode failed\n", name);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ LONG status = smartcard_irp_device_control_encode_request(sEnc, opIn);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: encode_request failed with 0x%08" PRIX32 "\n", name,
|
|
+ (UINT32)status);
|
|
+ Stream_Release(sEnc);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ wStream* sDec =
|
|
+ build_device_control_request(ioControlCode, Stream_Buffer(sEnc), Stream_Length(sEnc));
|
|
+ Stream_Release(sEnc);
|
|
+ if (!sDec)
|
|
+ return FALSE;
|
|
+
|
|
+ *opOut = (SMARTCARD_OPERATION)WINPR_C_ARRAY_INIT;
|
|
+ status = smartcard_irp_device_control_decode_request(sDec, 1, 0, opOut);
|
|
+ Stream_Release(sDec);
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: decode_request failed with 0x%08" PRIX32 "\n", name,
|
|
+ (UINT32)status);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ if (opOut->ioControlCode != ioControlCode)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: ioControlCode mismatch: 0x%08" PRIX32 " != 0x%08" PRIX32 "\n",
|
|
+ name, opOut->ioControlCode, ioControlCode);
|
|
+ smartcard_operation_free(opOut, FALSE);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static inline BOOL check_field(const char* name, const char* field, UINT32 a, UINT32 b)
|
|
+{
|
|
+ if (a != b)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: %s mismatch: 0x%" PRIX32 " != 0x%" PRIX32 "\n", name, field, a,
|
|
+ b);
|
|
+ return FALSE;
|
|
+ }
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static inline BOOL check_bytes(const char* name, const char* field, const void* a, const void* b,
|
|
+ size_t len)
|
|
+{
|
|
+ if (!a || !b || memcmp(a, b, len) != 0)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: %s mismatch (%" PRIuz " bytes)\n", name, field, len);
|
|
+ return FALSE;
|
|
+ }
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static inline BOOL check_redir_context(const char* name, const REDIR_SCARDCONTEXT* a,
|
|
+ const REDIR_SCARDCONTEXT* b)
|
|
+{
|
|
+ return check_field(name, "hContext.cbContext", a->cbContext, b->cbContext) &&
|
|
+ check_bytes(name, "hContext.pbContext", a->pbContext, b->pbContext, a->cbContext);
|
|
+}
|
|
+
|
|
+static inline BOOL check_redir_handle(const char* name, const REDIR_SCARDHANDLE* a,
|
|
+ const REDIR_SCARDHANDLE* b)
|
|
+{
|
|
+ return check_field(name, "hCard.cbHandle", a->cbHandle, b->cbHandle) &&
|
|
+ check_bytes(name, "hCard.pbHandle", a->pbHandle, b->pbHandle, a->cbHandle);
|
|
+}
|
|
+
|
|
+static BOOL test_establish_context_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_ESTABLISHCONTEXT;
|
|
+ opIn.call.establishContext.dwScope = SCARD_SCOPE_SYSTEM;
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("EstablishContext", "dwScope", opIn.call.establishContext.dwScope,
|
|
+ opOut.call.establishContext.dwScope))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_release_context_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_RELEASECONTEXT;
|
|
+ fill_redir_context(&opIn.call.context.handles.hContext, 0x1234);
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("ReleaseContext", &opIn.call.context.handles.hContext,
|
|
+ &opOut.call.context.handles.hContext))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_is_valid_context_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_ISVALIDCONTEXT;
|
|
+ fill_redir_context(&opIn.call.context.handles.hContext, 0x5678);
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("IsValidContext", &opIn.call.context.handles.hContext,
|
|
+ &opOut.call.context.handles.hContext))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_list_reader_groups_encode_decode_request_impl(UINT32 ioControlCode)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ fill_redir_context(&opIn.call.listReaderGroups.handles.hContext, 0x1234);
|
|
+ opIn.call.listReaderGroups.fmszGroupsIsNULL = 0;
|
|
+ opIn.call.listReaderGroups.cchGroups = SCARD_AUTOALLOCATE;
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context(n, &opIn.call.listReaderGroups.handles.hContext,
|
|
+ &opOut.call.listReaderGroups.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_field(n, "fmszGroupsIsNULL", opIn.call.listReaderGroups.fmszGroupsIsNULL,
|
|
+ opOut.call.listReaderGroups.fmszGroupsIsNULL))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cchGroups", opIn.call.listReaderGroups.cchGroups,
|
|
+ opOut.call.listReaderGroups.cchGroups))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_list_reader_groups_a_encode_decode_request(void)
|
|
+{
|
|
+ return test_list_reader_groups_encode_decode_request_impl(SCARD_IOCTL_LISTREADERGROUPSA);
|
|
+}
|
|
+
|
|
+static BOOL test_list_reader_groups_w_encode_decode_request(void)
|
|
+{
|
|
+ return test_list_reader_groups_encode_decode_request_impl(SCARD_IOCTL_LISTREADERGROUPSW);
|
|
+}
|
|
+
|
|
+static BOOL test_list_readers_encode_decode_request_impl(UINT32 ioControlCode)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ fill_redir_context(&opIn.call.listReaders.handles.hContext, 0x1234);
|
|
+ opIn.call.listReaders.fmszReadersIsNULL = 0;
|
|
+ opIn.call.listReaders.cchReaders = SCARD_AUTOALLOCATE;
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context(n, &opIn.call.listReaders.handles.hContext,
|
|
+ &opOut.call.listReaders.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cchReaders", opIn.call.listReaders.cchReaders,
|
|
+ opOut.call.listReaders.cchReaders))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_list_readers_a_encode_decode_request(void)
|
|
+{
|
|
+ return test_list_readers_encode_decode_request_impl(SCARD_IOCTL_LISTREADERSA);
|
|
+}
|
|
+
|
|
+static BOOL test_list_readers_w_encode_decode_request(void)
|
|
+{
|
|
+ return test_list_readers_encode_decode_request_impl(SCARD_IOCTL_LISTREADERSW);
|
|
+}
|
|
+
|
|
+static BOOL test_cancel_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_CANCEL;
|
|
+ fill_redir_context(&opIn.call.context.handles.hContext, 0xABCD);
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("Cancel", &opIn.call.context.handles.hContext,
|
|
+ &opOut.call.context.handles.hContext))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_connect_a_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_CONNECTA;
|
|
+ fill_redir_context(&opIn.call.connectA.Common.handles.hContext, 0x1234);
|
|
+ opIn.call.connectA.Common.dwShareMode = SCARD_SHARE_SHARED;
|
|
+ opIn.call.connectA.Common.dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
|
|
+ opIn.call.connectA.szReader = _strdup("TestReader");
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("ConnectA", &opIn.call.connectA.Common.handles.hContext,
|
|
+ &opOut.call.connectA.Common.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_field("ConnectA", "dwShareMode", opIn.call.connectA.Common.dwShareMode,
|
|
+ opOut.call.connectA.Common.dwShareMode))
|
|
+ goto out;
|
|
+ if (!check_field("ConnectA", "dwPreferredProtocols",
|
|
+ opIn.call.connectA.Common.dwPreferredProtocols,
|
|
+ opOut.call.connectA.Common.dwPreferredProtocols))
|
|
+ goto out;
|
|
+ if (!check_bytes("ConnectA", "szReader", opIn.call.connectA.szReader,
|
|
+ opOut.call.connectA.szReader, strlen(opIn.call.connectA.szReader) + 1))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_connect_w_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_CONNECTW;
|
|
+ fill_redir_context(&opIn.call.connectW.Common.handles.hContext, 0x1234);
|
|
+ opIn.call.connectW.Common.dwShareMode = SCARD_SHARE_SHARED;
|
|
+ opIn.call.connectW.Common.dwPreferredProtocols = SCARD_PROTOCOL_T0;
|
|
+ opIn.call.connectW.szReader = ConvertUtf8ToWCharAlloc("TestReader", NULL);
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("ConnectW", &opIn.call.connectW.Common.handles.hContext,
|
|
+ &opOut.call.connectW.Common.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_field("ConnectW", "dwShareMode", opIn.call.connectW.Common.dwShareMode,
|
|
+ opOut.call.connectW.Common.dwShareMode))
|
|
+ goto out;
|
|
+ if (!check_bytes("ConnectW", "szReader", opIn.call.connectW.szReader,
|
|
+ opOut.call.connectW.szReader,
|
|
+ (_wcslen(opIn.call.connectW.szReader) + 1) * sizeof(WCHAR)))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_reconnect_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = "Reconnect";
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_RECONNECT;
|
|
+ fill_redir_context(&opIn.call.reconnect.handles.hContext, 0x1234);
|
|
+ fill_redir_handle(&opIn.call.reconnect.handles.hCard, 0x5678);
|
|
+ opIn.call.reconnect.dwShareMode = SCARD_SHARE_EXCLUSIVE;
|
|
+ opIn.call.reconnect.dwPreferredProtocols = SCARD_PROTOCOL_T1;
|
|
+ opIn.call.reconnect.dwInitialization = SCARD_LEAVE_CARD;
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context(n, &opIn.call.reconnect.handles.hContext,
|
|
+ &opOut.call.reconnect.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_redir_handle(n, &opIn.call.reconnect.handles.hCard,
|
|
+ &opOut.call.reconnect.handles.hCard))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwShareMode", opIn.call.reconnect.dwShareMode,
|
|
+ opOut.call.reconnect.dwShareMode))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwPreferredProtocols", opIn.call.reconnect.dwPreferredProtocols,
|
|
+ opOut.call.reconnect.dwPreferredProtocols))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwInitialization", opIn.call.reconnect.dwInitialization,
|
|
+ opOut.call.reconnect.dwInitialization))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_hcard_and_disposition_encode_decode_request_impl(UINT32 ioControlCode,
|
|
+ DWORD dwDisposition)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ fill_redir_context(&opIn.call.hCardAndDisposition.handles.hContext, 0x1234);
|
|
+ fill_redir_handle(&opIn.call.hCardAndDisposition.handles.hCard, 0x5678);
|
|
+ opIn.call.hCardAndDisposition.dwDisposition = dwDisposition;
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context(n, &opIn.call.hCardAndDisposition.handles.hContext,
|
|
+ &opOut.call.hCardAndDisposition.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_redir_handle(n, &opIn.call.hCardAndDisposition.handles.hCard,
|
|
+ &opOut.call.hCardAndDisposition.handles.hCard))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwDisposition", opIn.call.hCardAndDisposition.dwDisposition,
|
|
+ opOut.call.hCardAndDisposition.dwDisposition))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_disconnect_encode_decode_request(void)
|
|
+{
|
|
+ return test_hcard_and_disposition_encode_decode_request_impl(SCARD_IOCTL_DISCONNECT,
|
|
+ SCARD_LEAVE_CARD);
|
|
+}
|
|
+
|
|
+static BOOL test_begin_transaction_encode_decode_request(void)
|
|
+{
|
|
+ return test_hcard_and_disposition_encode_decode_request_impl(SCARD_IOCTL_BEGINTRANSACTION,
|
|
+ SCARD_LEAVE_CARD);
|
|
+}
|
|
+
|
|
+static BOOL test_end_transaction_encode_decode_request(void)
|
|
+{
|
|
+ return test_hcard_and_disposition_encode_decode_request_impl(SCARD_IOCTL_ENDTRANSACTION,
|
|
+ SCARD_RESET_CARD);
|
|
+}
|
|
+
|
|
+static BOOL test_status_encode_decode_request_impl(UINT32 ioControlCode)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ fill_redir_context(&opIn.call.status.handles.hContext, 0x1234);
|
|
+ fill_redir_handle(&opIn.call.status.handles.hCard, 0x5678);
|
|
+ opIn.call.status.fmszReaderNamesIsNULL = 0;
|
|
+ opIn.call.status.cchReaderLen = SCARD_AUTOALLOCATE;
|
|
+ opIn.call.status.cbAtrLen = 36;
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context(n, &opIn.call.status.handles.hContext,
|
|
+ &opOut.call.status.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_redir_handle(n, &opIn.call.status.handles.hCard, &opOut.call.status.handles.hCard))
|
|
+ goto out;
|
|
+ if (!check_field(n, "fmszReaderNamesIsNULL", opIn.call.status.fmszReaderNamesIsNULL,
|
|
+ opOut.call.status.fmszReaderNamesIsNULL))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cchReaderLen", opIn.call.status.cchReaderLen,
|
|
+ opOut.call.status.cchReaderLen))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cbAtrLen", opIn.call.status.cbAtrLen, opOut.call.status.cbAtrLen))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_status_a_encode_decode_request(void)
|
|
+{
|
|
+ return test_status_encode_decode_request_impl(SCARD_IOCTL_STATUSA);
|
|
+}
|
|
+
|
|
+static BOOL test_status_w_encode_decode_request(void)
|
|
+{
|
|
+ return test_status_encode_decode_request_impl(SCARD_IOCTL_STATUSW);
|
|
+}
|
|
+
|
|
+static BOOL test_transmit_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ BYTE sendBuf[] = { 0x00, 0xA4, 0x04, 0x00, 0x07 };
|
|
+ SCARD_IO_REQUEST pioSendPci = { .dwProtocol = SCARD_PROTOCOL_T0, .cbPciLength = 8 };
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_TRANSMIT;
|
|
+ fill_redir_context(&opIn.call.transmit.handles.hContext, 0x1234);
|
|
+ fill_redir_handle(&opIn.call.transmit.handles.hCard, 0x5678);
|
|
+ opIn.call.transmit.pioSendPci = &pioSendPci;
|
|
+ opIn.call.transmit.cbSendLength = sizeof(sendBuf);
|
|
+ opIn.call.transmit.pbSendBuffer = sendBuf;
|
|
+ opIn.call.transmit.fpbRecvBufferIsNULL = 0;
|
|
+ opIn.call.transmit.cbRecvLength = 256;
|
|
+
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("Transmit", &opIn.call.transmit.handles.hContext,
|
|
+ &opOut.call.transmit.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_redir_handle("Transmit", &opIn.call.transmit.handles.hCard,
|
|
+ &opOut.call.transmit.handles.hCard))
|
|
+ goto out;
|
|
+ if (!check_field("Transmit", "cbSendLength", opIn.call.transmit.cbSendLength,
|
|
+ opOut.call.transmit.cbSendLength))
|
|
+ goto out;
|
|
+ if (!check_bytes("Transmit", "pbSendBuffer", opIn.call.transmit.pbSendBuffer,
|
|
+ opOut.call.transmit.pbSendBuffer, opIn.call.transmit.cbSendLength))
|
|
+ goto out;
|
|
+ if (!check_field("Transmit", "fpbRecvBufferIsNULL",
|
|
+ (UINT32)opIn.call.transmit.fpbRecvBufferIsNULL,
|
|
+ (UINT32)opOut.call.transmit.fpbRecvBufferIsNULL))
|
|
+ goto out;
|
|
+ if (!check_field("Transmit", "cbRecvLength", opIn.call.transmit.cbRecvLength,
|
|
+ opOut.call.transmit.cbRecvLength))
|
|
+ goto out;
|
|
+ if (!check_field("Transmit", "pioSendPci.dwProtocol", opIn.call.transmit.pioSendPci->dwProtocol,
|
|
+ opOut.call.transmit.pioSendPci->dwProtocol))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.call.transmit.pioSendPci = NULL;
|
|
+ opIn.call.transmit.pbSendBuffer = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_control_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ BYTE inBuf[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_CONTROL;
|
|
+ fill_redir_context(&opIn.call.control.handles.hContext, 0x1234);
|
|
+ fill_redir_handle(&opIn.call.control.handles.hCard, 0x5678);
|
|
+ opIn.call.control.dwControlCode = 0x42000001;
|
|
+ opIn.call.control.cbInBufferSize = sizeof(inBuf);
|
|
+ opIn.call.control.pvInBuffer = inBuf;
|
|
+ opIn.call.control.fpvOutBufferIsNULL = 0;
|
|
+ opIn.call.control.cbOutBufferSize = 256;
|
|
+
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("Control", &opIn.call.control.handles.hContext,
|
|
+ &opOut.call.control.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_redir_handle("Control", &opIn.call.control.handles.hCard,
|
|
+ &opOut.call.control.handles.hCard))
|
|
+ goto out;
|
|
+ if (!check_field("Control", "dwControlCode", opIn.call.control.dwControlCode,
|
|
+ opOut.call.control.dwControlCode))
|
|
+ goto out;
|
|
+ if (!check_field("Control", "cbInBufferSize", opIn.call.control.cbInBufferSize,
|
|
+ opOut.call.control.cbInBufferSize))
|
|
+ goto out;
|
|
+ if (!check_bytes("Control", "pvInBuffer", opIn.call.control.pvInBuffer,
|
|
+ opOut.call.control.pvInBuffer, opIn.call.control.cbInBufferSize))
|
|
+ goto out;
|
|
+ if (!check_field("Control", "cbOutBufferSize", opIn.call.control.cbOutBufferSize,
|
|
+ opOut.call.control.cbOutBufferSize))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.call.control.pvInBuffer = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_get_attrib_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_GETATTRIB;
|
|
+ fill_redir_context(&opIn.call.getAttrib.handles.hContext, 0x1234);
|
|
+ fill_redir_handle(&opIn.call.getAttrib.handles.hCard, 0x5678);
|
|
+ opIn.call.getAttrib.dwAttrId = SCARD_ATTR_ATR_STRING;
|
|
+ opIn.call.getAttrib.fpbAttrIsNULL = 0;
|
|
+ opIn.call.getAttrib.cbAttrLen = 36;
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("GetAttrib", &opIn.call.getAttrib.handles.hContext,
|
|
+ &opOut.call.getAttrib.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_redir_handle("GetAttrib", &opIn.call.getAttrib.handles.hCard,
|
|
+ &opOut.call.getAttrib.handles.hCard))
|
|
+ goto out;
|
|
+ if (!check_field("GetAttrib", "dwAttrId", opIn.call.getAttrib.dwAttrId,
|
|
+ opOut.call.getAttrib.dwAttrId))
|
|
+ goto out;
|
|
+ if (!check_field("GetAttrib", "cbAttrLen", opIn.call.getAttrib.cbAttrLen,
|
|
+ opOut.call.getAttrib.cbAttrLen))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_set_attrib_encode_decode_request(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ BYTE attrBuf[] = { 0x3B, 0x00 };
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_SETATTRIB;
|
|
+ fill_redir_context(&opIn.call.setAttrib.handles.hContext, 0x1234);
|
|
+ fill_redir_handle(&opIn.call.setAttrib.handles.hCard, 0x5678);
|
|
+ opIn.call.setAttrib.dwAttrId = SCARD_ATTR_ATR_STRING;
|
|
+ opIn.call.setAttrib.cbAttrLen = sizeof(attrBuf);
|
|
+ opIn.call.setAttrib.pbAttr = attrBuf;
|
|
+
|
|
+ if (!test_request_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("SetAttrib", &opIn.call.setAttrib.handles.hContext,
|
|
+ &opOut.call.setAttrib.handles.hContext))
|
|
+ goto out;
|
|
+ if (!check_redir_handle("SetAttrib", &opIn.call.setAttrib.handles.hCard,
|
|
+ &opOut.call.setAttrib.handles.hCard))
|
|
+ goto out;
|
|
+ if (!check_field("SetAttrib", "dwAttrId", opIn.call.setAttrib.dwAttrId,
|
|
+ opOut.call.setAttrib.dwAttrId))
|
|
+ goto out;
|
|
+ if (!check_field("SetAttrib", "cbAttrLen", opIn.call.setAttrib.cbAttrLen,
|
|
+ opOut.call.setAttrib.cbAttrLen))
|
|
+ goto out;
|
|
+ if (!check_bytes("SetAttrib", "pbAttr", opIn.call.setAttrib.pbAttr, opOut.call.setAttrib.pbAttr,
|
|
+ opIn.call.setAttrib.cbAttrLen))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.call.setAttrib.pbAttr = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_encode_decode_requests(void)
|
|
+{
|
|
+ BOOL success = TRUE;
|
|
+
|
|
+ if (!test_establish_context_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_release_context_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_is_valid_context_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_list_reader_groups_a_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_list_reader_groups_w_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_list_readers_a_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_list_readers_w_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_cancel_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_connect_a_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_connect_w_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_reconnect_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_disconnect_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_begin_transaction_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_end_transaction_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_status_a_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_status_w_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_transmit_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_control_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_get_attrib_encode_decode_request())
|
|
+ success = FALSE;
|
|
+ if (!test_set_attrib_encode_decode_request())
|
|
+ success = FALSE;
|
|
+
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static LONG encode_response_payload(wStream* s, UINT32 ioControlCode,
|
|
+ const SMARTCARD_OPERATION* opIn)
|
|
+{
|
|
+ switch (ioControlCode)
|
|
+ {
|
|
+ case SCARD_IOCTL_ESTABLISHCONTEXT:
|
|
+ return smartcard_pack_establish_context_return(s, &opIn->ret.establishContext);
|
|
+ case SCARD_IOCTL_RECONNECT:
|
|
+ return smartcard_pack_reconnect_return(s, &opIn->ret.reconnect);
|
|
+ case SCARD_IOCTL_CONNECTA:
|
|
+ case SCARD_IOCTL_CONNECTW:
|
|
+ return smartcard_pack_connect_return(s, &opIn->ret.connect);
|
|
+ case SCARD_IOCTL_CONTROL:
|
|
+ return smartcard_pack_control_return(s, &opIn->ret.control);
|
|
+ case SCARD_IOCTL_TRANSMIT:
|
|
+ return smartcard_pack_transmit_return(s, &opIn->ret.transmit);
|
|
+ case SCARD_IOCTL_GETATTRIB:
|
|
+ return smartcard_pack_get_attrib_return(s, &opIn->ret.getAttrib, 0,
|
|
+ opIn->ret.getAttrib.cbAttrLen);
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEA:
|
|
+ return smartcard_pack_get_status_change_return(s, &opIn->ret.getStatusChange, FALSE);
|
|
+ case SCARD_IOCTL_GETSTATUSCHANGEW:
|
|
+ return smartcard_pack_get_status_change_return(s, &opIn->ret.getStatusChange, TRUE);
|
|
+ case SCARD_IOCTL_LISTREADERGROUPSA:
|
|
+ return smartcard_pack_list_reader_groups_return(s, &opIn->ret.listReaders, FALSE);
|
|
+ case SCARD_IOCTL_LISTREADERGROUPSW:
|
|
+ return smartcard_pack_list_reader_groups_return(s, &opIn->ret.listReaders, TRUE);
|
|
+ case SCARD_IOCTL_LISTREADERSA:
|
|
+ return smartcard_pack_list_readers_return(s, &opIn->ret.listReaders, FALSE);
|
|
+ case SCARD_IOCTL_LISTREADERSW:
|
|
+ return smartcard_pack_list_readers_return(s, &opIn->ret.listReaders, TRUE);
|
|
+ case SCARD_IOCTL_STATUSA:
|
|
+ return smartcard_pack_status_return(s, &opIn->ret.status, FALSE);
|
|
+ case SCARD_IOCTL_STATUSW:
|
|
+ return smartcard_pack_status_return(s, &opIn->ret.status, TRUE);
|
|
+ case SCARD_IOCTL_RELEASECONTEXT:
|
|
+ case SCARD_IOCTL_ISVALIDCONTEXT:
|
|
+ case SCARD_IOCTL_CANCEL:
|
|
+ case SCARD_IOCTL_DISCONNECT:
|
|
+ case SCARD_IOCTL_BEGINTRANSACTION:
|
|
+ case SCARD_IOCTL_ENDTRANSACTION:
|
|
+ case SCARD_IOCTL_SETATTRIB:
|
|
+ return SCARD_S_SUCCESS;
|
|
+ default:
|
|
+ return SCARD_F_INTERNAL_ERROR;
|
|
+ }
|
|
+}
|
|
+
|
|
+static wStream* build_device_control_response(UINT32 ioControlCode, const SMARTCARD_OPERATION* opIn)
|
|
+{
|
|
+ const char* name = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+
|
|
+ wStream* payload = Stream_New(NULL, 4096);
|
|
+ if (!payload)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: Stream_New for payload failed\n", name);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ LONG rc = encode_response_payload(payload, ioControlCode, opIn);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: encode_response_payload failed with 0x%08" PRIX32 "\n", name,
|
|
+ (UINT32)rc);
|
|
+ Stream_Release(payload);
|
|
+ return NULL;
|
|
+ }
|
|
+ Stream_SealLength(payload);
|
|
+
|
|
+ wStream* s = Stream_New(NULL, 256 + Stream_Length(payload));
|
|
+ if (!s)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: Stream_New for response failed\n", name);
|
|
+ Stream_Release(payload);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ Stream_Seek(s, 4); /* Placeholder for outputBufferLength */
|
|
+ const size_t headerPos = Stream_GetPosition(s);
|
|
+ Stream_Seek(s, SMARTCARD_COMMON_TYPE_HEADER_LENGTH +
|
|
+ SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* Placeholder for headers */
|
|
+ Stream_Write_INT32(s, opIn->returnCode);
|
|
+ Stream_Write(s, Stream_Buffer(payload), Stream_Length(payload));
|
|
+ Stream_Release(payload);
|
|
+
|
|
+ const size_t payloadSize = Stream_GetPosition(s) - headerPos;
|
|
+ const size_t objectBufferLength =
|
|
+ payloadSize - SMARTCARD_COMMON_TYPE_HEADER_LENGTH - SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH;
|
|
+
|
|
+ WINPR_UNUSED(smartcard_pack_write_size_align(s, payloadSize, 8));
|
|
+
|
|
+ const size_t endPos = Stream_GetPosition(s);
|
|
+ const size_t outputBufferLength = endPos - headerPos;
|
|
+
|
|
+ Stream_SetPosition(s, 0);
|
|
+ UINT32 outputLength = WINPR_ASSERTING_INT_CAST(UINT32, outputBufferLength);
|
|
+ UINT32 objectLength = WINPR_ASSERTING_INT_CAST(UINT32, objectBufferLength);
|
|
+ Stream_Write_UINT32(s, outputLength);
|
|
+ smartcard_pack_common_type_header(s);
|
|
+ smartcard_pack_private_type_header(s, objectLength);
|
|
+
|
|
+ Stream_SetPosition(s, endPos);
|
|
+ Stream_SealLength(s);
|
|
+ if (!Stream_SetPosition(s, 0))
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: Stream_SetPosition failed\n", name);
|
|
+ Stream_Release(s);
|
|
+ return NULL;
|
|
+ }
|
|
+ return s;
|
|
+}
|
|
+
|
|
+static BOOL test_response_roundtrip(const SMARTCARD_OPERATION* opIn, SMARTCARD_OPERATION* opOut)
|
|
+{
|
|
+ const UINT32 ioControlCode = opIn->ioControlCode;
|
|
+ const char* name = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+
|
|
+ wStream* s = build_device_control_response(ioControlCode, opIn);
|
|
+ if (!s)
|
|
+ return FALSE;
|
|
+
|
|
+ *opOut = (SMARTCARD_OPERATION)WINPR_C_ARRAY_INIT;
|
|
+ LONG status = smartcard_irp_device_control_decode_response(s, ioControlCode, opOut);
|
|
+ Stream_Release(s);
|
|
+
|
|
+ if (status != SCARD_S_SUCCESS)
|
|
+ {
|
|
+ (void)fprintf(stderr, "%s: decode_response failed with 0x%08" PRIX32 "\n", name,
|
|
+ (UINT32)status);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static BOOL test_establish_context_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_ESTABLISHCONTEXT;
|
|
+ fill_redir_context(&opIn.ret.establishContext.hContext, 0xABCD);
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_redir_context("EstablishContext", &opIn.ret.establishContext.hContext,
|
|
+ &opOut.ret.establishContext.hContext))
|
|
+ goto out;
|
|
+ if (!check_field("EstablishContext", "returnCode", (UINT32)opIn.returnCode,
|
|
+ (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_release_context_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_RELEASECONTEXT;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("ReleaseContext", "returnCode", (UINT32)opIn.returnCode,
|
|
+ (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_is_valid_context_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_ISVALIDCONTEXT;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("IsValidContext", "returnCode", (UINT32)opIn.returnCode,
|
|
+ (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_list_reader_groups_decode_response_impl(UINT32 ioControlCode)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ BYTE groups[] = { 'G', 'r', 'p', '\0', '\0' };
|
|
+ opIn.ret.listReaders.cBytes = sizeof(groups);
|
|
+ opIn.ret.listReaders.msz = groups;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field(n, "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cBytes", opIn.ret.listReaders.cBytes, opOut.ret.listReaders.cBytes))
|
|
+ goto out;
|
|
+ if (!check_bytes(n, "msz", opIn.ret.listReaders.msz, opOut.ret.listReaders.msz,
|
|
+ opIn.ret.listReaders.cBytes))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.ret.listReaders.msz = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_list_reader_groups_a_decode_response(void)
|
|
+{
|
|
+ return test_list_reader_groups_decode_response_impl(SCARD_IOCTL_LISTREADERGROUPSA);
|
|
+}
|
|
+
|
|
+static BOOL test_list_reader_groups_w_decode_response(void)
|
|
+{
|
|
+ return test_list_reader_groups_decode_response_impl(SCARD_IOCTL_LISTREADERGROUPSW);
|
|
+}
|
|
+
|
|
+static BOOL test_list_readers_decode_response_impl(UINT32 ioControlCode)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ BYTE readers[] = { 'R', 'd', 'r', '\0', '\0' };
|
|
+ opIn.ret.listReaders.cBytes = sizeof(readers);
|
|
+ opIn.ret.listReaders.msz = readers;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field(n, "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cBytes", opIn.ret.listReaders.cBytes, opOut.ret.listReaders.cBytes))
|
|
+ goto out;
|
|
+ if (!check_bytes(n, "msz", opIn.ret.listReaders.msz, opOut.ret.listReaders.msz,
|
|
+ opIn.ret.listReaders.cBytes))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.ret.listReaders.msz = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_list_readers_a_decode_response(void)
|
|
+{
|
|
+ return test_list_readers_decode_response_impl(SCARD_IOCTL_LISTREADERSA);
|
|
+}
|
|
+
|
|
+static BOOL test_list_readers_w_decode_response(void)
|
|
+{
|
|
+ return test_list_readers_decode_response_impl(SCARD_IOCTL_LISTREADERSW);
|
|
+}
|
|
+
|
|
+static BOOL test_get_status_change_decode_response_impl(UINT32 ioControlCode)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ ReaderState_Return state = WINPR_C_ARRAY_INIT;
|
|
+ state.dwCurrentState = SCARD_STATE_PRESENT;
|
|
+ state.dwEventState = SCARD_STATE_CHANGED;
|
|
+ state.cbAtr = 2;
|
|
+ state.rgbAtr[0] = 0x3B;
|
|
+ state.rgbAtr[1] = 0x00;
|
|
+ opIn.ret.getStatusChange.cReaders = 1;
|
|
+ opIn.ret.getStatusChange.rgReaderStates = &state;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field(n, "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cReaders", opIn.ret.getStatusChange.cReaders,
|
|
+ opOut.ret.getStatusChange.cReaders))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwCurrentState", state.dwCurrentState,
|
|
+ opOut.ret.getStatusChange.rgReaderStates[0].dwCurrentState))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwEventState", state.dwEventState,
|
|
+ opOut.ret.getStatusChange.rgReaderStates[0].dwEventState))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cbAtr", state.cbAtr, opOut.ret.getStatusChange.rgReaderStates[0].cbAtr))
|
|
+ goto out;
|
|
+ if (!check_bytes(n, "rgbAtr", state.rgbAtr, opOut.ret.getStatusChange.rgReaderStates[0].rgbAtr,
|
|
+ sizeof(state.rgbAtr)))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.ret.getStatusChange.rgReaderStates = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_get_status_change_a_decode_response(void)
|
|
+{
|
|
+ return test_get_status_change_decode_response_impl(SCARD_IOCTL_GETSTATUSCHANGEA);
|
|
+}
|
|
+
|
|
+static BOOL test_get_status_change_w_decode_response(void)
|
|
+{
|
|
+ return test_get_status_change_decode_response_impl(SCARD_IOCTL_GETSTATUSCHANGEW);
|
|
+}
|
|
+
|
|
+static BOOL test_cancel_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_CANCEL;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("Cancel", "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_connect_decode_response_impl(UINT32 ioControlCode)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ fill_redir_context(&opIn.ret.connect.hContext, 0x1234);
|
|
+ fill_redir_handle(&opIn.ret.connect.hCard, 0x5678);
|
|
+ opIn.ret.connect.dwActiveProtocol = SCARD_PROTOCOL_T0;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field(n, "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_redir_context(n, &opIn.ret.connect.hContext, &opOut.ret.connect.hContext))
|
|
+ goto out;
|
|
+ if (!check_redir_handle(n, &opIn.ret.connect.hCard, &opOut.ret.connect.hCard))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwActiveProtocol", opIn.ret.connect.dwActiveProtocol,
|
|
+ opOut.ret.connect.dwActiveProtocol))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_connect_a_decode_response(void)
|
|
+{
|
|
+ return test_connect_decode_response_impl(SCARD_IOCTL_CONNECTA);
|
|
+}
|
|
+
|
|
+static BOOL test_connect_w_decode_response(void)
|
|
+{
|
|
+ return test_connect_decode_response_impl(SCARD_IOCTL_CONNECTW);
|
|
+}
|
|
+
|
|
+static BOOL test_reconnect_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_RECONNECT;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ opIn.ret.reconnect.dwActiveProtocol = SCARD_PROTOCOL_T1;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("Reconnect", "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_field("Reconnect", "dwActiveProtocol", opIn.ret.reconnect.dwActiveProtocol,
|
|
+ opOut.ret.reconnect.dwActiveProtocol))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_disconnect_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_DISCONNECT;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("Disconnect", "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_begin_transaction_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_BEGINTRANSACTION;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("BeginTransaction", "returnCode", (UINT32)opIn.returnCode,
|
|
+ (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_end_transaction_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_ENDTRANSACTION;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("EndTransaction", "returnCode", (UINT32)opIn.returnCode,
|
|
+ (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_status_decode_response_impl(UINT32 ioControlCode)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ const char* n = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = ioControlCode;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ BYTE readerName[] = { 'R', 'd', 'r', '\0' };
|
|
+ opIn.ret.status.cBytes = sizeof(readerName);
|
|
+ opIn.ret.status.mszReaderNames = readerName;
|
|
+ opIn.ret.status.dwState = SCARD_SPECIFIC;
|
|
+ opIn.ret.status.dwProtocol = SCARD_PROTOCOL_T1;
|
|
+ memset(opIn.ret.status.pbAtr, 0x3B, sizeof(opIn.ret.status.pbAtr));
|
|
+ opIn.ret.status.cbAtrLen = 2;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field(n, "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwState", opIn.ret.status.dwState, opOut.ret.status.dwState))
|
|
+ goto out;
|
|
+ if (!check_field(n, "dwProtocol", opIn.ret.status.dwProtocol, opOut.ret.status.dwProtocol))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cbAtrLen", opIn.ret.status.cbAtrLen, opOut.ret.status.cbAtrLen))
|
|
+ goto out;
|
|
+ if (!check_bytes(n, "pbAtr", opIn.ret.status.pbAtr, opOut.ret.status.pbAtr,
|
|
+ sizeof(opIn.ret.status.pbAtr)))
|
|
+ goto out;
|
|
+ if (!check_field(n, "cBytes", opIn.ret.status.cBytes, opOut.ret.status.cBytes))
|
|
+ goto out;
|
|
+ if (!check_bytes(n, "mszReaderNames", opIn.ret.status.mszReaderNames,
|
|
+ opOut.ret.status.mszReaderNames, opIn.ret.status.cBytes))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.ret.status.mszReaderNames = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_status_a_decode_response(void)
|
|
+{
|
|
+ return test_status_decode_response_impl(SCARD_IOCTL_STATUSA);
|
|
+}
|
|
+
|
|
+static BOOL test_status_w_decode_response(void)
|
|
+{
|
|
+ return test_status_decode_response_impl(SCARD_IOCTL_STATUSW);
|
|
+}
|
|
+
|
|
+static BOOL test_transmit_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_TRANSMIT;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ BYTE recvBuf[] = { 0x90, 0x00 };
|
|
+ opIn.ret.transmit.cbRecvLength = sizeof(recvBuf);
|
|
+ opIn.ret.transmit.pbRecvBuffer = recvBuf;
|
|
+ opIn.ret.transmit.pioRecvPci = NULL;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("Transmit", "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_field("Transmit", "cbRecvLength", opIn.ret.transmit.cbRecvLength,
|
|
+ opOut.ret.transmit.cbRecvLength))
|
|
+ goto out;
|
|
+ if (!check_bytes("Transmit", "pbRecvBuffer", opIn.ret.transmit.pbRecvBuffer,
|
|
+ opOut.ret.transmit.pbRecvBuffer, opIn.ret.transmit.cbRecvLength))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.ret.transmit.pbRecvBuffer = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_control_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_CONTROL;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ BYTE outBuf[] = { 0xAA, 0xBB, 0xCC };
|
|
+ opIn.ret.control.cbOutBufferSize = sizeof(outBuf);
|
|
+ opIn.ret.control.pvOutBuffer = outBuf;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("Control", "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_field("Control", "cbOutBufferSize", opIn.ret.control.cbOutBufferSize,
|
|
+ opOut.ret.control.cbOutBufferSize))
|
|
+ goto out;
|
|
+ if (!check_bytes("Control", "pvOutBuffer", opIn.ret.control.pvOutBuffer,
|
|
+ opOut.ret.control.pvOutBuffer, opIn.ret.control.cbOutBufferSize))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.ret.control.pvOutBuffer = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_get_attrib_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_GETATTRIB;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+ BYTE attr[] = { 0x3B, 0x90, 0x00 };
|
|
+ opIn.ret.getAttrib.cbAttrLen = sizeof(attr);
|
|
+ opIn.ret.getAttrib.pbAttr = attr;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("GetAttrib", "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+ if (!check_field("GetAttrib", "cbAttrLen", opIn.ret.getAttrib.cbAttrLen,
|
|
+ opOut.ret.getAttrib.cbAttrLen))
|
|
+ goto out;
|
|
+ if (!check_bytes("GetAttrib", "pbAttr", opIn.ret.getAttrib.pbAttr, opOut.ret.getAttrib.pbAttr,
|
|
+ opIn.ret.getAttrib.cbAttrLen))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ opIn.ret.getAttrib.pbAttr = NULL;
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_set_attrib_decode_response(void)
|
|
+{
|
|
+ BOOL success = FALSE;
|
|
+ SMARTCARD_OPERATION opOut = WINPR_C_ARRAY_INIT;
|
|
+ SMARTCARD_OPERATION opIn = WINPR_C_ARRAY_INIT;
|
|
+ opIn.ioControlCode = SCARD_IOCTL_SETATTRIB;
|
|
+ opIn.returnCode = SCARD_S_SUCCESS;
|
|
+
|
|
+ if (!test_response_roundtrip(&opIn, &opOut))
|
|
+ goto out;
|
|
+ if (!check_field("SetAttrib", "returnCode", (UINT32)opIn.returnCode, (UINT32)opOut.returnCode))
|
|
+ goto out;
|
|
+
|
|
+ success = TRUE;
|
|
+out:
|
|
+ smartcard_operation_free(&opIn, FALSE);
|
|
+ smartcard_operation_free(&opOut, FALSE);
|
|
+ return success;
|
|
+}
|
|
+
|
|
+static BOOL test_decode_responses(void)
|
|
+{
|
|
+ BOOL success = TRUE;
|
|
+
|
|
+ if (!test_establish_context_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_release_context_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_is_valid_context_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_list_reader_groups_a_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_list_reader_groups_w_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_list_readers_a_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_list_readers_w_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_get_status_change_a_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_get_status_change_w_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_cancel_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_connect_a_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_connect_w_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_reconnect_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_disconnect_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_begin_transaction_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_end_transaction_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_status_a_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_status_w_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_transmit_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_control_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_get_attrib_decode_response())
|
|
+ success = FALSE;
|
|
+ if (!test_set_attrib_decode_response())
|
|
+ success = FALSE;
|
|
+
|
|
+ return success;
|
|
+}
|
|
+
|
|
+int TestSmartcardOperations(int argc, char* argv[])
|
|
+{
|
|
+ WINPR_UNUSED(argc);
|
|
+ WINPR_UNUSED(argv);
|
|
+
|
|
+ if (!test_encode_decode_requests())
|
|
+ return -1;
|
|
+
|
|
+ if (!test_decode_responses())
|
|
+ return -1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
From 13dd1b439790515be4f6df013b4fb4fc4cbbae69 Mon Sep 17 00:00:00 2001
|
|
From: Joan Torres Lopez <joantolo@redhat.com>
|
|
Date: Sat, 27 Jun 2026 01:28:31 +0200
|
|
Subject: [PATCH 22/31] [channels,rdpdr] add doxygen documentation to rdpdr.h
|
|
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.h | 17 +++---
|
|
include/freerdp/server/rdpdr.h | 97 ++++++++++++++++++------------
|
|
2 files changed, 68 insertions(+), 46 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.h b/channels/rdpdr/server/rdpdr_main.h
|
|
index 40327a81313b..bbcb09aea173 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.h
|
|
+++ b/channels/rdpdr/server/rdpdr_main.h
|
|
@@ -35,16 +35,17 @@ typedef struct S_RDPDR_IRP RDPDR_IRP;
|
|
typedef UINT (*RDPDR_IRP_Callback)(RdpdrServerContext* context, wStream* s, struct S_RDPDR_IRP* irp,
|
|
UINT32 deviceId, UINT32 completionId, UINT32 ioStatus);
|
|
|
|
+/** IRP request structure */
|
|
struct S_RDPDR_IRP
|
|
{
|
|
- UINT32 CompletionId;
|
|
- UINT32 DeviceId;
|
|
- UINT32 FileId;
|
|
- UINT32 IoControlCode;
|
|
- char PathName[256];
|
|
- char ExtraBuffer[256];
|
|
- void* CallbackData;
|
|
- RDPDR_IRP_Callback Callback;
|
|
+ UINT32 CompletionId; /**< IRP completion identifier */
|
|
+ UINT32 DeviceId; /**< Target device identifier */
|
|
+ UINT32 FileId; /**< File handle identifier */
|
|
+ UINT32 IoControlCode; /**< I/O control code */
|
|
+ char PathName[256]; /**< File path name */
|
|
+ char ExtraBuffer[256]; /**< Data buffer */
|
|
+ void* CallbackData; /**< User callback data */
|
|
+ RDPDR_IRP_Callback Callback; /**< Completion callback function */
|
|
};
|
|
|
|
#endif /* FREERDP_CHANNEL_RDPDR_SERVER_MAIN_H */
|
|
diff --git a/include/freerdp/server/rdpdr.h b/include/freerdp/server/rdpdr.h
|
|
index a44a7e1cef87..9fb1515e1a4e 100644
|
|
--- a/include/freerdp/server/rdpdr.h
|
|
+++ b/include/freerdp/server/rdpdr.h
|
|
@@ -43,28 +43,30 @@ extern "C"
|
|
typedef struct s_rdpdr_server_context RdpdrServerContext;
|
|
typedef struct s_rdpdr_server_private RdpdrServerPrivate;
|
|
|
|
+ /** RDPDR protocol header */
|
|
typedef struct
|
|
{
|
|
- UINT16 Component;
|
|
- UINT16 PacketId;
|
|
+ UINT16 Component; /**< Component identifier */
|
|
+ UINT16 PacketId; /**< Packet identifier */
|
|
} RDPDR_HEADER;
|
|
|
|
#ifndef __MINGW32__
|
|
+ /** File directory information structure */
|
|
typedef struct
|
|
{
|
|
- UINT32 NextEntryOffset;
|
|
- UINT32 FileIndex;
|
|
- LARGE_INTEGER CreationTime;
|
|
- LARGE_INTEGER LastAccessTime;
|
|
- LARGE_INTEGER LastWriteTime;
|
|
- LARGE_INTEGER ChangeTime;
|
|
- LARGE_INTEGER EndOfFile;
|
|
- LARGE_INTEGER AllocationSize;
|
|
- UINT32 FileAttributes;
|
|
+ UINT32 NextEntryOffset; /**< Offset to next entry */
|
|
+ UINT32 FileIndex; /**< File index */
|
|
+ LARGE_INTEGER CreationTime; /**< File creation time */
|
|
+ LARGE_INTEGER LastAccessTime; /**< Last access time */
|
|
+ LARGE_INTEGER LastWriteTime; /**< Last write time */
|
|
+ LARGE_INTEGER ChangeTime; /**< Last change time */
|
|
+ LARGE_INTEGER EndOfFile; /**< End of file position */
|
|
+ LARGE_INTEGER AllocationSize; /**< Allocated size */
|
|
+ UINT32 FileAttributes; /**< File attributes */
|
|
#if defined(WITH_WCHAR_FILE_DIRECTORY_INFORMATION)
|
|
- WCHAR FileName[512];
|
|
+ WCHAR FileName[512]; /**< File name (wide char) */
|
|
#else
|
|
- char FileName[512];
|
|
+ char FileName[512]; /**< File name */
|
|
#endif
|
|
} FILE_DIRECTORY_INFORMATION;
|
|
#endif
|
|
@@ -247,12 +249,12 @@ extern "C"
|
|
|
|
struct s_rdpdr_server_context
|
|
{
|
|
- HANDLE vcm;
|
|
+ HANDLE vcm; /**< Virtual channel manager handle */
|
|
|
|
- WINPR_ATTR_NODISCARD psRdpdrStart Start;
|
|
- psRdpdrStop Stop;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrStart Start; /**< Start the RDPDR server */
|
|
+ psRdpdrStop Stop; /**< Stop the RDPDR server */
|
|
|
|
- RdpdrServerPrivate* priv;
|
|
+ RdpdrServerPrivate* priv; /**< Private server context data */
|
|
|
|
/* Server self-defined pointer. */
|
|
void* data;
|
|
@@ -280,22 +282,24 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD psRdpdrReceiveClientNameRequest
|
|
ReceiveClientNameRequest; /**< Called after a client name request is received */
|
|
WINPR_ATTR_NODISCARD psRdpdrReceiveDeviceAnnounce
|
|
- ReceiveDeviceAnnounce; /** < Called after a new device request was received but before
|
|
+ ReceiveDeviceAnnounce; /**< Called after a new device request was received but before
|
|
the device is added */
|
|
WINPR_ATTR_NODISCARD psRdpdrReceiveDeviceRemove
|
|
ReceiveDeviceRemove; /**< Called after a new device request was
|
|
received, but before it is removed */
|
|
|
|
/*** Drive APIs called by the server. ***/
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveCreateDirectory DriveCreateDirectory;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveDeleteDirectory DriveDeleteDirectory;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveQueryDirectory DriveQueryDirectory;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveOpenFile DriveOpenFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveReadFile DriveReadFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveWriteFile DriveWriteFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveCloseFile DriveCloseFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveDeleteFile DriveDeleteFile;
|
|
- WINPR_ATTR_NODISCARD psRdpdrDriveRenameFile DriveRenameFile;
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveCreateDirectory
|
|
+ DriveCreateDirectory; /**< Create directory */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveDeleteDirectory
|
|
+ DriveDeleteDirectory; /**< Delete directory */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveQueryDirectory DriveQueryDirectory; /**< Query directory */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveOpenFile DriveOpenFile; /**< Open file */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveReadFile DriveReadFile; /**< Read file */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveWriteFile DriveWriteFile; /**< Write file */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveCloseFile DriveCloseFile; /**< Close file */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveDeleteFile DriveDeleteFile; /**< Delete file */
|
|
+ WINPR_ATTR_NODISCARD psRdpdrDriveRenameFile DriveRenameFile; /**< Rename file */
|
|
|
|
/*** Drive callbacks registered by the server. ***/
|
|
WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate
|
|
@@ -304,15 +308,24 @@ extern "C"
|
|
WINPR_ATTR_NODISCARD psRdpdrOnDeviceDelete
|
|
OnDriveDelete; /**< Called for devices of type \b
|
|
RDPDR_DTYP_FILESYSTEM after \b ReceiveDeviceRemove */
|
|
- psRdpdrOnDriveCreateDirectoryComplete OnDriveCreateDirectoryComplete;
|
|
- psRdpdrOnDriveDeleteDirectoryComplete OnDriveDeleteDirectoryComplete;
|
|
- psRdpdrOnDriveQueryDirectoryComplete OnDriveQueryDirectoryComplete;
|
|
- psRdpdrOnDriveOpenFileComplete OnDriveOpenFileComplete;
|
|
- psRdpdrOnDriveReadFileComplete OnDriveReadFileComplete;
|
|
- psRdpdrOnDriveWriteFileComplete OnDriveWriteFileComplete;
|
|
- psRdpdrOnDriveCloseFileComplete OnDriveCloseFileComplete;
|
|
- psRdpdrOnDriveDeleteFileComplete OnDriveDeleteFileComplete;
|
|
- psRdpdrOnDriveRenameFileComplete OnDriveRenameFileComplete;
|
|
+ psRdpdrOnDriveCreateDirectoryComplete
|
|
+ OnDriveCreateDirectoryComplete; /**< DriveCreateDirectory completion callback */
|
|
+ psRdpdrOnDriveDeleteDirectoryComplete
|
|
+ OnDriveDeleteDirectoryComplete; /**< DriveDeleteDirectory completion callback */
|
|
+ psRdpdrOnDriveQueryDirectoryComplete
|
|
+ OnDriveQueryDirectoryComplete; /**< DriveQueryDirectory completion callback */
|
|
+ psRdpdrOnDriveOpenFileComplete
|
|
+ OnDriveOpenFileComplete; /**< DriveOpenFile completion callback */
|
|
+ psRdpdrOnDriveReadFileComplete
|
|
+ OnDriveReadFileComplete; /**< DriveReadFile completion callback */
|
|
+ psRdpdrOnDriveWriteFileComplete
|
|
+ OnDriveWriteFileComplete; /**< DriveWriteFile completion callback */
|
|
+ psRdpdrOnDriveCloseFileComplete
|
|
+ OnDriveCloseFileComplete; /**< DriveCloseFile completion callback */
|
|
+ psRdpdrOnDriveDeleteFileComplete
|
|
+ OnDriveDeleteFileComplete; /**< DriveDeleteFile completion callback */
|
|
+ psRdpdrOnDriveRenameFileComplete
|
|
+ OnDriveRenameFileComplete; /**< DriveRenameFile completion callback */
|
|
|
|
/*** Serial Port callbacks registered by the server. ***/
|
|
WINPR_ATTR_NODISCARD psRdpdrOnDeviceCreate
|
|
@@ -344,7 +357,7 @@ extern "C"
|
|
OnSmartcardDelete; /**< Called for devices of type
|
|
RDPDR_DTYP_SMARTCARD after \b ReceiveDeviceRemove */
|
|
|
|
- rdpContext* rdpcontext;
|
|
+ rdpContext* rdpcontext; /**< RDP context */
|
|
|
|
/*** New Smartcard APIs called by the server. ***/
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardEstablishContext
|
|
@@ -448,10 +461,18 @@ extern "C"
|
|
/* clang-format on */
|
|
};
|
|
|
|
+ /**
|
|
+ * @brief Free an RDPDR server context.
|
|
+ * @param context The RDPDR server context to free.
|
|
+ */
|
|
FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context);
|
|
|
|
+ /**
|
|
+ * @brief Create a new RDPDR server context.
|
|
+ * @param vcm Virtual channel manager handle.
|
|
+ * @return Newly allocated RDPDR server context, or NULL on failure.
|
|
+ */
|
|
WINPR_ATTR_MALLOC(rdpdr_server_context_free, 1)
|
|
- WINPR_ATTR_NODISCARD
|
|
FREERDP_API RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm);
|
|
|
|
/**
|
|
|
|
From 3f911fca8307754edfbc60c3b0994f1cabd52432 Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Mon, 29 Jun 2026 19:20:46 +0200
|
|
Subject: [PATCH 23/31] [channels,rdpdr] fix compile warnings
|
|
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 150 +++++++++++++++--------------
|
|
1 file changed, 79 insertions(+), 71 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 7b9c1d33ff10..f5565dcdeb2c 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -254,6 +254,11 @@ static void rdpdr_server_irp_free(RDPDR_IRP* irp)
|
|
free(irp);
|
|
}
|
|
|
|
+static void rdpdr_server_list_free(void* ptr)
|
|
+{
|
|
+ RDPDR_IRP* irp = ptr;
|
|
+ rdpdr_server_irp_free(irp);
|
|
+}
|
|
static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context, RDPDR_IRP* irp)
|
|
{
|
|
WINPR_ASSERT(context);
|
|
@@ -1154,7 +1159,7 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
|
if (error != CHANNEL_RC_OK)
|
|
return error;
|
|
|
|
- error = STATUS_NOT_SUPPORTED;
|
|
+ error = ERROR_NOT_SUPPORTED;
|
|
switch (device.DeviceType)
|
|
{
|
|
case RDPDR_DTYP_FILESYSTEM:
|
|
@@ -2214,7 +2219,10 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
|
goto out;
|
|
case WAIT_OBJECT_0 + 1:
|
|
{
|
|
- s = ChannelPduTracker_poll(tracker);
|
|
+ BOOL ok = FALSE;
|
|
+ s = ChannelPduTracker_poll(tracker, &ok);
|
|
+ if (!s && ok)
|
|
+ continue;
|
|
if (!s)
|
|
break;
|
|
|
|
@@ -3707,7 +3715,7 @@ static RdpdrServerPrivate* rdpdr_server_private_new(void)
|
|
if (!priv->IrpList)
|
|
goto fail;
|
|
|
|
- ListDictionary_ValueObject(priv->IrpList)->fnObjectFree = (OBJECT_FREE_FN)rdpdr_server_irp_free;
|
|
+ ListDictionary_ValueObject(priv->IrpList)->fnObjectFree = rdpdr_server_list_free;
|
|
|
|
priv->devicelist = HashTable_New(FALSE);
|
|
if (!priv->devicelist)
|
|
@@ -3763,8 +3771,8 @@ static UINT rdpdr_server_smartcard_establish_context_callback(RdpdrServerContext
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -3825,8 +3833,8 @@ static UINT rdpdr_server_smartcard_establish_context(RdpdrServerContext* context
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -3871,8 +3879,8 @@ static UINT rdpdr_server_smartcard_release_context_callback(RdpdrServerContext*
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -3923,8 +3931,8 @@ static UINT rdpdr_server_smartcard_release_context(RdpdrServerContext* context,
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -3970,8 +3978,8 @@ static UINT rdpdr_server_smartcard_is_valid_context_callback(RdpdrServerContext*
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4022,8 +4030,8 @@ static UINT rdpdr_server_smartcard_is_valid_context(RdpdrServerContext* context,
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4069,8 +4077,8 @@ static UINT rdpdr_server_smartcard_list_reader_groups_callback(RdpdrServerContex
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4128,8 +4136,8 @@ static UINT rdpdr_server_smartcard_list_reader_groups(RdpdrServerContext* contex
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4192,8 +4200,8 @@ static UINT rdpdr_server_smartcard_list_readers_callback(RdpdrServerContext* con
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4251,8 +4259,8 @@ static UINT rdpdr_server_smartcard_list_readers(RdpdrServerContext* context, voi
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4312,8 +4320,8 @@ static UINT rdpdr_server_smartcard_get_status_change_callback(RdpdrServerContext
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4376,8 +4384,8 @@ static UINT rdpdr_server_smartcard_get_status_change(RdpdrServerContext* context
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4440,8 +4448,8 @@ static UINT rdpdr_server_smartcard_cancel_callback(RdpdrServerContext* context,
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4489,8 +4497,8 @@ static UINT rdpdr_server_smartcard_cancel(RdpdrServerContext* context, void* cal
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4535,8 +4543,8 @@ static UINT rdpdr_server_smartcard_connect_callback(RdpdrServerContext* context,
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4597,8 +4605,8 @@ static UINT rdpdr_server_smartcard_connect(RdpdrServerContext* context, void* ca
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4657,8 +4665,8 @@ static UINT rdpdr_server_smartcard_reconnect_callback(RdpdrServerContext* contex
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4715,8 +4723,8 @@ static UINT rdpdr_server_smartcard_reconnect(RdpdrServerContext* context, void*
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4761,8 +4769,8 @@ static UINT rdpdr_server_smartcard_disconnect_callback(RdpdrServerContext* conte
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4817,8 +4825,8 @@ static UINT rdpdr_server_smartcard_disconnect(RdpdrServerContext* context, void*
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4864,8 +4872,8 @@ static UINT rdpdr_server_smartcard_begin_transaction_callback(RdpdrServerContext
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -4923,8 +4931,8 @@ static UINT rdpdr_server_smartcard_begin_transaction(RdpdrServerContext* context
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -4969,8 +4977,8 @@ static UINT rdpdr_server_smartcard_end_transaction_callback(RdpdrServerContext*
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -5027,8 +5035,8 @@ static UINT rdpdr_server_smartcard_end_transaction(RdpdrServerContext* context,
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -5073,8 +5081,8 @@ static UINT rdpdr_server_smartcard_status_callback(RdpdrServerContext* context,
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -5132,8 +5140,8 @@ static UINT rdpdr_server_smartcard_status(RdpdrServerContext* context, void* cal
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -5192,8 +5200,8 @@ static UINT rdpdr_server_smartcard_transmit_callback(RdpdrServerContext* context
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -5244,8 +5252,8 @@ static UINT rdpdr_server_smartcard_transmit(RdpdrServerContext* context, void* c
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -5290,8 +5298,8 @@ static UINT rdpdr_server_smartcard_control_callback(RdpdrServerContext* context,
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -5350,8 +5358,8 @@ static UINT rdpdr_server_smartcard_control(RdpdrServerContext* context, void* ca
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
@@ -5396,8 +5404,8 @@ static UINT rdpdr_server_smartcard_get_attrib_callback(RdpdrServerContext* conte
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -5413,8 +5421,8 @@ static UINT rdpdr_server_smartcard_get_attrib_callback(RdpdrServerContext* conte
|
|
return result;
|
|
}
|
|
|
|
-UINT rdpdr_server_smartcard_get_attrib(RdpdrServerContext* context, void* callbackData,
|
|
- const GetAttrib_Call* call, UINT32* completionId)
|
|
+static UINT rdpdr_server_smartcard_get_attrib(RdpdrServerContext* context, void* callbackData,
|
|
+ const GetAttrib_Call* call, UINT32* completionId)
|
|
{
|
|
WINPR_ASSERT(context);
|
|
WINPR_ASSERT(context->priv);
|
|
@@ -5488,8 +5496,8 @@ static UINT rdpdr_server_smartcard_set_attrib_callback(RdpdrServerContext* conte
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INVALID_DATA;
|
|
goto out;
|
|
@@ -5545,8 +5553,8 @@ static UINT rdpdr_server_smartcard_set_attrib(RdpdrServerContext* context, void*
|
|
goto out;
|
|
}
|
|
|
|
- result = smartcard_irp_device_control_encode_request(s, &op);
|
|
- if (result != SCARD_S_SUCCESS)
|
|
+ const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
|
|
+ if (rc != SCARD_S_SUCCESS)
|
|
{
|
|
result = ERROR_INTERNAL_ERROR;
|
|
goto out;
|
|
|
|
From 0cf276e1716ba1febd60761f0ab54b02b610e143 Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Tue, 30 Jun 2026 08:49:08 +0200
|
|
Subject: [PATCH 24/31] [utils,smartcard] add missing entries in
|
|
smartcard_operation_free
|
|
|
|
---
|
|
libfreerdp/utils/smartcard_operations.c | 12 ++++++++++++
|
|
1 file changed, 12 insertions(+)
|
|
|
|
diff --git a/libfreerdp/utils/smartcard_operations.c b/libfreerdp/utils/smartcard_operations.c
|
|
index a38e0d102487..a92f7222dd7b 100644
|
|
--- a/libfreerdp/utils/smartcard_operations.c
|
|
+++ b/libfreerdp/utils/smartcard_operations.c
|
|
@@ -1733,6 +1733,18 @@ void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
|
|
free(ret->pioRecvPci);
|
|
}
|
|
break;
|
|
+ case SCARD_IOCTL_CONTROL:
|
|
+ {
|
|
+ Control_Return* call = &op->ret.control;
|
|
+ free(call->pvOutBuffer);
|
|
+ }
|
|
+ break;
|
|
+ case SCARD_IOCTL_GETATTRIB:
|
|
+ {
|
|
+ GetAttrib_Return* ret = &op->ret.getAttrib;
|
|
+ free(ret->pbAttr);
|
|
+ }
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
From 5793486ae671b43d5b99fc23dfb82a121b7eb9e6 Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Tue, 30 Jun 2026 09:04:21 +0200
|
|
Subject: [PATCH 25/31] [server,rdpdr] update doxygen
|
|
|
|
---
|
|
include/freerdp/server/rdpdr.h | 207 ++++++++++++++++++++++-----------
|
|
1 file changed, 140 insertions(+), 67 deletions(-)
|
|
|
|
diff --git a/include/freerdp/server/rdpdr.h b/include/freerdp/server/rdpdr.h
|
|
index 9fb1515e1a4e..a9b38a0dd9ba 100644
|
|
--- a/include/freerdp/server/rdpdr.h
|
|
+++ b/include/freerdp/server/rdpdr.h
|
|
@@ -359,106 +359,179 @@ extern "C"
|
|
|
|
rdpContext* rdpcontext; /**< RDP context */
|
|
|
|
- /*** New Smartcard APIs called by the server. ***/
|
|
+ /*** New Smartcard APIs called by the server.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardEstablishContext
|
|
- SmartcardEstablishContext; /**< Send SCardEstablishContext to the client. */
|
|
+ SmartcardEstablishContext; /**< Send SCardEstablishContext to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardReleaseContext
|
|
- SmartcardReleaseContext; /**< Send SCardReleaseContext to the client. */
|
|
+ SmartcardReleaseContext; /**< Send SCardReleaseContext to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardIsValidContext
|
|
- SmartcardIsValidContext; /**< Send SCardIsValidContext to the client. */
|
|
+ SmartcardIsValidContext; /**< Send SCardIsValidContext to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardListReaderGroups
|
|
- SmartcardListReaderGroupsA; /**< Send SCardListReaderGroupsA to the client. */
|
|
+ SmartcardListReaderGroupsA; /**< Send SCardListReaderGroupsA to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardListReaderGroups
|
|
- SmartcardListReaderGroupsW; /**< Send SCardListReaderGroupsW to the client. */
|
|
+ SmartcardListReaderGroupsW; /**< Send SCardListReaderGroupsW to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardListReaders
|
|
- SmartcardListReadersA; /**< Send SCardListReadersA to the client. */
|
|
+ SmartcardListReadersA; /**< Send SCardListReadersA to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardListReaders
|
|
- SmartcardListReadersW; /**< Send SCardListReadersW to the client. */
|
|
+ SmartcardListReadersW; /**< Send SCardListReadersW to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardGetStatusChangeA
|
|
- SmartcardGetStatusChangeA; /**< Send SCardGetStatusChangeA to the client. */
|
|
+ SmartcardGetStatusChangeA; /**< Send SCardGetStatusChangeA to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardGetStatusChangeW
|
|
- SmartcardGetStatusChangeW; /**< Send SCardGetStatusChangeW to the client. */
|
|
+ SmartcardGetStatusChangeW; /**< Send SCardGetStatusChangeW to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardCancel
|
|
- SmartcardCancel; /**< Send SCardCancel to the client. */
|
|
+ SmartcardCancel; /**< Send SCardCancel to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardConnectA
|
|
- SmartcardConnectA; /**< Send SCardConnectA to the client. */
|
|
+ SmartcardConnectA; /**< Send SCardConnectA to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardConnectW
|
|
- SmartcardConnectW; /**< Send SCardConnectW to the client. */
|
|
+ SmartcardConnectW; /**< Send SCardConnectW to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardReconnect
|
|
- SmartcardReconnect; /**< Send SCardReconnect to the client. */
|
|
+ SmartcardReconnect; /**< Send SCardReconnect to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardDisconnect
|
|
- SmartcardDisconnect; /**< Send SCardDisconnect to the client. */
|
|
+ SmartcardDisconnect; /**< Send SCardDisconnect to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardBeginTransaction
|
|
- SmartcardBeginTransaction; /**< Send SCardBeginTransaction to the client. */
|
|
+ SmartcardBeginTransaction; /**< Send SCardBeginTransaction to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardEndTransaction
|
|
- SmartcardEndTransaction; /**< Send SCardEndTransaction to the client. */
|
|
+ SmartcardEndTransaction; /**< Send SCardEndTransaction to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardStatus
|
|
- SmartcardStatusA; /**< Send SCardStatusA to the client. */
|
|
+ SmartcardStatusA; /**< Send SCardStatusA to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardStatus
|
|
- SmartcardStatusW; /**< Send SCardStatusW to the client. */
|
|
+ SmartcardStatusW; /**< Send SCardStatusW to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardTransmit
|
|
- SmartcardTransmit; /**< Send SCardTransmit to the client. */
|
|
+ SmartcardTransmit; /**< Send SCardTransmit to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardControl
|
|
- SmartcardControl; /**< Send SCardControl to the client. */
|
|
+ SmartcardControl; /**< Send SCardControl to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardGetAttrib
|
|
- SmartcardGetAttrib; /**< Send SCardGetAttrib to the client. */
|
|
+ SmartcardGetAttrib; /**< Send SCardGetAttrib to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
WINPR_ATTR_NODISCARD psRdpdrSmartcardSetAttrib
|
|
- SmartcardSetAttrib; /**< Send SCardSetAttrib to the client. */
|
|
+ SmartcardSetAttrib; /**< Send SCardSetAttrib to the client.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
|
|
/*** New Smartcard callbacks registered by the server. ***/
|
|
- /* clang-format off */
|
|
psRdpdrOnSmartcardEstablishContextComplete
|
|
- OnSmartcardEstablishContextComplete; /**< Completion callback for
|
|
- SmartcardEstablishContext. */
|
|
+ OnSmartcardEstablishContextComplete; /**<
|
|
+ * Completion callback for
|
|
+ * SmartcardEstablishContext.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
psRdpdrOnSmartcardReleaseContextComplete
|
|
- OnSmartcardReleaseContextComplete; /**< Completion callback for
|
|
- SmartcardReleaseContext. */
|
|
+ OnSmartcardReleaseContextComplete; /**< Completion
|
|
+ * callback for SmartcardReleaseContext.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
psRdpdrOnSmartcardIsValidContextComplete
|
|
- OnSmartcardIsValidContextComplete; /**< Completion callback for
|
|
- SmartcardIsValidContext. */
|
|
+ OnSmartcardIsValidContextComplete; /**< Completion
|
|
+ * callback for SmartcardIsValidContext.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
psRdpdrOnSmartcardListReaderGroupsComplete
|
|
- OnSmartcardListReaderGroupsComplete; /**< Completion callback for
|
|
- SmartcardListReaderGroups. */
|
|
+ OnSmartcardListReaderGroupsComplete; /**<
|
|
+ * Completion callback for
|
|
+ * SmartcardListReaderGroups.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
psRdpdrOnSmartcardListReadersComplete
|
|
- OnSmartcardListReadersComplete; /**< Completion callback for
|
|
- SmartcardListReaders. */
|
|
+ OnSmartcardListReadersComplete; /**< Completion
|
|
+ * callback for SmartcardListReaders.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
psRdpdrOnSmartcardGetStatusChangeComplete
|
|
- OnSmartcardGetStatusChangeComplete; /**< Completion callback for
|
|
- SmartcardGetStatusChange. */
|
|
- psRdpdrOnSmartcardCancelComplete
|
|
- OnSmartcardCancelComplete; /**< Completion callback for
|
|
- SmartcardCancel. */
|
|
- psRdpdrOnSmartcardConnectComplete
|
|
- OnSmartcardConnectComplete; /**< Completion callback for
|
|
- SmartcardConnect. */
|
|
- psRdpdrOnSmartcardReconnectComplete
|
|
- OnSmartcardReconnectComplete; /**< Completion callback for
|
|
- SmartcardReconnect. */
|
|
+ OnSmartcardGetStatusChangeComplete; /**<
|
|
+ * Completion callback for SmartcardGetStatusChange.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ psRdpdrOnSmartcardCancelComplete OnSmartcardCancelComplete; /**< Completion callback for
|
|
+ * SmartcardCancel.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ psRdpdrOnSmartcardConnectComplete OnSmartcardConnectComplete; /**< Completion callback for
|
|
+ * SmartcardConnect.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ psRdpdrOnSmartcardReconnectComplete OnSmartcardReconnectComplete; /**< Completion callback
|
|
+ * for SmartcardReconnect.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
psRdpdrOnSmartcardDisconnectComplete
|
|
- OnSmartcardDisconnectComplete; /**< Completion callback for
|
|
- SmartcardDisconnect. */
|
|
+ OnSmartcardDisconnectComplete; /**< Completion callback
|
|
+ * for SmartcardDisconnect.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
psRdpdrOnSmartcardBeginTransactionComplete
|
|
- OnSmartcardBeginTransactionComplete; /**< Completion callback for
|
|
- SmartcardBeginTransaction. */
|
|
+ OnSmartcardBeginTransactionComplete; /**<
|
|
+ * Completion callback for
|
|
+ * SmartcardBeginTransaction.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
psRdpdrOnSmartcardEndTransactionComplete
|
|
- OnSmartcardEndTransactionComplete; /**< Completion callback for
|
|
- SmartcardEndTransaction. */
|
|
- psRdpdrOnSmartcardStatusComplete
|
|
- OnSmartcardStatusComplete; /**< Completion callback for
|
|
- SmartcardStatus. */
|
|
- psRdpdrOnSmartcardTransmitComplete
|
|
- OnSmartcardTransmitComplete; /**< Completion callback for
|
|
- SmartcardTransmit. */
|
|
- psRdpdrOnSmartcardControlComplete
|
|
- OnSmartcardControlComplete; /**< Completion callback for
|
|
- SmartcardControl. */
|
|
- psRdpdrOnSmartcardGetAttribComplete
|
|
- OnSmartcardGetAttribComplete; /**< Completion callback for
|
|
- SmartcardGetAttrib. */
|
|
- psRdpdrOnSmartcardSetAttribComplete
|
|
- OnSmartcardSetAttribComplete; /**< Completion callback for
|
|
- SmartcardSetAttrib. */
|
|
- /* clang-format on */
|
|
+ OnSmartcardEndTransactionComplete; /**< Completion
|
|
+ * callback for SmartcardEndTransaction.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ psRdpdrOnSmartcardStatusComplete OnSmartcardStatusComplete; /**< Completion callback for
|
|
+ * SmartcardStatus.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ psRdpdrOnSmartcardTransmitComplete OnSmartcardTransmitComplete; /**< Completion callback for
|
|
+ * SmartcardTransmit.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ psRdpdrOnSmartcardControlComplete OnSmartcardControlComplete; /**< Completion callback for
|
|
+ * SmartcardControl.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ psRdpdrOnSmartcardGetAttribComplete OnSmartcardGetAttribComplete; /**< Completion callback
|
|
+ * for SmartcardGetAttrib.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
+ psRdpdrOnSmartcardSetAttribComplete OnSmartcardSetAttribComplete; /**< Completion callback
|
|
+ * for SmartcardSetAttrib.
|
|
+ * @since version 3.28.0
|
|
+ */
|
|
};
|
|
|
|
/**
|
|
|
|
From 8cb4b9ca8e80c3a8d50a9f5ef9ef3248bccc37fc Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Tue, 30 Jun 2026 09:06:32 +0200
|
|
Subject: [PATCH 26/31] [utils,test] replace NULL with nullptr
|
|
|
|
---
|
|
libfreerdp/utils/smartcard_pack.c | 4 +-
|
|
.../utils/test/TestSmartcardOperations.c | 42 +++++++++----------
|
|
2 files changed, 23 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/libfreerdp/utils/smartcard_pack.c b/libfreerdp/utils/smartcard_pack.c
|
|
index 5aa54590f4fc..a10974f75bfb 100644
|
|
--- a/libfreerdp/utils/smartcard_pack.c
|
|
+++ b/libfreerdp/utils/smartcard_pack.c
|
|
@@ -4672,7 +4672,7 @@ LONG smartcard_pack_transmit_call(wStream* s, const Transmit_Call* call)
|
|
return status;
|
|
|
|
UINT32 cbExtraBytes = 0;
|
|
- const BYTE* pbExtraBytes = NULL;
|
|
+ const BYTE* pbExtraBytes = nullptr;
|
|
if (call->pioSendPci)
|
|
{
|
|
cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
|
|
@@ -4825,7 +4825,7 @@ LONG smartcard_unpack_get_status_change_return(wStream* s, GetStatusChange_Retur
|
|
return status;
|
|
}
|
|
else
|
|
- ret->rgReaderStates = NULL;
|
|
+ ret->rgReaderStates = nullptr;
|
|
|
|
smartcard_trace_get_status_change_return(log, ret, unicode);
|
|
return SCARD_S_SUCCESS;
|
|
diff --git a/libfreerdp/utils/test/TestSmartcardOperations.c b/libfreerdp/utils/test/TestSmartcardOperations.c
|
|
index 4c885b13359c..590d9cc6fb93 100644
|
|
--- a/libfreerdp/utils/test/TestSmartcardOperations.c
|
|
+++ b/libfreerdp/utils/test/TestSmartcardOperations.c
|
|
@@ -44,12 +44,12 @@ static wStream* build_device_control_request(UINT32 ioControlCode, const void* i
|
|
const char* name = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
const size_t totalLength = RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH + inputBufferLength;
|
|
|
|
- wStream* s = Stream_New(NULL, totalLength);
|
|
+ wStream* s = Stream_New(nullptr, totalLength);
|
|
if (!s)
|
|
{
|
|
(void)fprintf(stderr, "build_device_control_request(%s): Stream_New(%" PRIuz ") failed\n",
|
|
name, totalLength);
|
|
- return NULL;
|
|
+ return nullptr;
|
|
}
|
|
|
|
UINT32 inputLength = WINPR_ASSERTING_INT_CAST(UINT32, inputBufferLength);
|
|
@@ -67,7 +67,7 @@ static wStream* build_device_control_request(UINT32 ioControlCode, const void* i
|
|
(void)fprintf(stderr, "build_device_control_request(%s): Stream_SetPosition failed\n",
|
|
name);
|
|
Stream_Release(s);
|
|
- return NULL;
|
|
+ return nullptr;
|
|
}
|
|
|
|
return s;
|
|
@@ -78,7 +78,7 @@ static BOOL test_request_roundtrip(const SMARTCARD_OPERATION* opIn, SMARTCARD_OP
|
|
const UINT32 ioControlCode = opIn->ioControlCode;
|
|
const char* name = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
|
|
- wStream* sEnc = Stream_New(NULL, 4096);
|
|
+ wStream* sEnc = Stream_New(nullptr, 4096);
|
|
if (!sEnc)
|
|
{
|
|
(void)fprintf(stderr, "%s: Stream_New for encode failed\n", name);
|
|
@@ -361,7 +361,7 @@ static BOOL test_connect_w_encode_decode_request(void)
|
|
fill_redir_context(&opIn.call.connectW.Common.handles.hContext, 0x1234);
|
|
opIn.call.connectW.Common.dwShareMode = SCARD_SHARE_SHARED;
|
|
opIn.call.connectW.Common.dwPreferredProtocols = SCARD_PROTOCOL_T0;
|
|
- opIn.call.connectW.szReader = ConvertUtf8ToWCharAlloc("TestReader", NULL);
|
|
+ opIn.call.connectW.szReader = ConvertUtf8ToWCharAlloc("TestReader", nullptr);
|
|
|
|
if (!test_request_roundtrip(&opIn, &opOut))
|
|
goto out;
|
|
@@ -559,8 +559,8 @@ static BOOL test_transmit_encode_decode_request(void)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.call.transmit.pioSendPci = NULL;
|
|
- opIn.call.transmit.pbSendBuffer = NULL;
|
|
+ opIn.call.transmit.pioSendPci = nullptr;
|
|
+ opIn.call.transmit.pbSendBuffer = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -604,7 +604,7 @@ static BOOL test_control_encode_decode_request(void)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.call.control.pvInBuffer = NULL;
|
|
+ opIn.call.control.pvInBuffer = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -677,7 +677,7 @@ static BOOL test_set_attrib_encode_decode_request(void)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.call.setAttrib.pbAttr = NULL;
|
|
+ opIn.call.setAttrib.pbAttr = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -787,7 +787,7 @@ static wStream* build_device_control_response(UINT32 ioControlCode, const SMARTC
|
|
if (!payload)
|
|
{
|
|
(void)fprintf(stderr, "%s: Stream_New for payload failed\n", name);
|
|
- return NULL;
|
|
+ return nullptr;
|
|
}
|
|
|
|
LONG rc = encode_response_payload(payload, ioControlCode, opIn);
|
|
@@ -796,7 +796,7 @@ static wStream* build_device_control_response(UINT32 ioControlCode, const SMARTC
|
|
(void)fprintf(stderr, "%s: encode_response_payload failed with 0x%08" PRIX32 "\n", name,
|
|
(UINT32)rc);
|
|
Stream_Release(payload);
|
|
- return NULL;
|
|
+ return nullptr;
|
|
}
|
|
Stream_SealLength(payload);
|
|
|
|
@@ -805,7 +805,7 @@ static wStream* build_device_control_response(UINT32 ioControlCode, const SMARTC
|
|
{
|
|
(void)fprintf(stderr, "%s: Stream_New for response failed\n", name);
|
|
Stream_Release(payload);
|
|
- return NULL;
|
|
+ return nullptr;
|
|
}
|
|
|
|
Stream_Seek(s, 4); /* Placeholder for outputBufferLength */
|
|
@@ -838,7 +838,7 @@ static wStream* build_device_control_response(UINT32 ioControlCode, const SMARTC
|
|
{
|
|
(void)fprintf(stderr, "%s: Stream_SetPosition failed\n", name);
|
|
Stream_Release(s);
|
|
- return NULL;
|
|
+ return nullptr;
|
|
}
|
|
return s;
|
|
}
|
|
@@ -957,7 +957,7 @@ static BOOL test_list_reader_groups_decode_response_impl(UINT32 ioControlCode)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.ret.listReaders.msz = NULL;
|
|
+ opIn.ret.listReaders.msz = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -997,7 +997,7 @@ static BOOL test_list_readers_decode_response_impl(UINT32 ioControlCode)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.ret.listReaders.msz = NULL;
|
|
+ opIn.ret.listReaders.msz = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -1051,7 +1051,7 @@ static BOOL test_get_status_change_decode_response_impl(UINT32 ioControlCode)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.ret.getStatusChange.rgReaderStates = NULL;
|
|
+ opIn.ret.getStatusChange.rgReaderStates = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -1251,7 +1251,7 @@ static BOOL test_status_decode_response_impl(UINT32 ioControlCode)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.ret.status.mszReaderNames = NULL;
|
|
+ opIn.ret.status.mszReaderNames = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -1277,7 +1277,7 @@ static BOOL test_transmit_decode_response(void)
|
|
BYTE recvBuf[] = { 0x90, 0x00 };
|
|
opIn.ret.transmit.cbRecvLength = sizeof(recvBuf);
|
|
opIn.ret.transmit.pbRecvBuffer = recvBuf;
|
|
- opIn.ret.transmit.pioRecvPci = NULL;
|
|
+ opIn.ret.transmit.pioRecvPci = nullptr;
|
|
|
|
if (!test_response_roundtrip(&opIn, &opOut))
|
|
goto out;
|
|
@@ -1292,7 +1292,7 @@ static BOOL test_transmit_decode_response(void)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.ret.transmit.pbRecvBuffer = NULL;
|
|
+ opIn.ret.transmit.pbRecvBuffer = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -1322,7 +1322,7 @@ static BOOL test_control_decode_response(void)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.ret.control.pvOutBuffer = NULL;
|
|
+ opIn.ret.control.pvOutBuffer = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
@@ -1352,7 +1352,7 @@ static BOOL test_get_attrib_decode_response(void)
|
|
|
|
success = TRUE;
|
|
out:
|
|
- opIn.ret.getAttrib.pbAttr = NULL;
|
|
+ opIn.ret.getAttrib.pbAttr = nullptr;
|
|
smartcard_operation_free(&opIn, FALSE);
|
|
smartcard_operation_free(&opOut, FALSE);
|
|
return success;
|
|
|
|
From 5562dec703fc1873ee23e272691872087aeb3158 Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Tue, 30 Jun 2026 09:08:01 +0200
|
|
Subject: [PATCH 27/31] [utils,smartcard] make declaration parameters
|
|
consistent
|
|
|
|
---
|
|
libfreerdp/utils/smartcard_pack.c | 10 +++++-----
|
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/libfreerdp/utils/smartcard_pack.c b/libfreerdp/utils/smartcard_pack.c
|
|
index a10974f75bfb..a035fcab94d7 100644
|
|
--- a/libfreerdp/utils/smartcard_pack.c
|
|
+++ b/libfreerdp/utils/smartcard_pack.c
|
|
@@ -4256,12 +4256,12 @@ LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Retur
|
|
return ret->ReturnCode;
|
|
}
|
|
|
|
-LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* call)
|
|
+LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* ret)
|
|
{
|
|
- WINPR_ASSERT(call);
|
|
+ WINPR_ASSERT(ret);
|
|
wLog* log = scard_log();
|
|
|
|
- smartcard_trace_get_transmit_count_return(log, call);
|
|
+ smartcard_trace_get_transmit_count_return(log, ret);
|
|
|
|
if (!Stream_EnsureRemainingCapacity(s, 4))
|
|
{
|
|
@@ -4269,9 +4269,9 @@ LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
}
|
|
|
|
- Stream_Write_UINT32(s, call->cTransmitCount); /* cBytes (4 cbDataLen) */
|
|
+ Stream_Write_UINT32(s, ret->cTransmitCount); /* cBytes (4 cbDataLen) */
|
|
|
|
- return call->ReturnCode;
|
|
+ return ret->ReturnCode;
|
|
}
|
|
|
|
LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
|
|
|
|
From c974edcac03ae90b82e6b177cf0875ff10b97a81 Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Tue, 30 Jun 2026 09:10:28 +0200
|
|
Subject: [PATCH 28/31] [channel,rdpdr] remove manual code formatting
|
|
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 184 +++++++++++------------------
|
|
1 file changed, 70 insertions(+), 114 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index f5565dcdeb2c..f04acffdaafd 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -4117,16 +4117,12 @@ static UINT rdpdr_server_smartcard_list_reader_groups(RdpdrServerContext* contex
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = ioControlCode,
|
|
- .call.listReaderGroups = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .fmszGroupsIsNULL = call->fmszGroupsIsNULL,
|
|
- .cchGroups = call->cchGroups,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = ioControlCode,
|
|
+ .call.listReaderGroups = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .fmszGroupsIsNULL = call->fmszGroupsIsNULL,
|
|
+ .cchGroups = call->cchGroups,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 32);
|
|
if (!s)
|
|
@@ -4238,18 +4234,14 @@ static UINT rdpdr_server_smartcard_list_readers(RdpdrServerContext* context, voi
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = ioControlCode,
|
|
- .call.listReaders = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .cBytes = call->cBytes,
|
|
- .mszGroups = call->mszGroups,
|
|
- .fmszReadersIsNULL = call->fmszReadersIsNULL,
|
|
- .cchReaders = call->cchReaders,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = ioControlCode,
|
|
+ .call.listReaders = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .cBytes = call->cBytes,
|
|
+ .mszGroups = call->mszGroups,
|
|
+ .fmszReadersIsNULL = call->fmszReadersIsNULL,
|
|
+ .cchReaders = call->cchReaders,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 256);
|
|
if (!s)
|
|
@@ -4702,18 +4694,14 @@ static UINT rdpdr_server_smartcard_reconnect(RdpdrServerContext* context, void*
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = SCARD_IOCTL_RECONNECT,
|
|
- .call.reconnect = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .handles.hCard = call->handles.hCard,
|
|
- .dwShareMode = call->dwShareMode,
|
|
- .dwPreferredProtocols = call->dwPreferredProtocols,
|
|
- .dwInitialization = call->dwInitialization,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_RECONNECT,
|
|
+ .call.reconnect = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwShareMode = call->dwShareMode,
|
|
+ .dwPreferredProtocols = call->dwPreferredProtocols,
|
|
+ .dwInitialization = call->dwInitialization,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 128);
|
|
if (!s)
|
|
@@ -4806,16 +4794,12 @@ static UINT rdpdr_server_smartcard_disconnect(RdpdrServerContext* context, void*
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = SCARD_IOCTL_DISCONNECT,
|
|
- .call.hCardAndDisposition = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .handles.hCard = call->handles.hCard,
|
|
- .dwDisposition = call->dwDisposition,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_DISCONNECT,
|
|
+ .call.hCardAndDisposition = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwDisposition = call->dwDisposition,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 128);
|
|
if (!s)
|
|
@@ -4912,16 +4896,12 @@ static UINT rdpdr_server_smartcard_begin_transaction(RdpdrServerContext* context
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = SCARD_IOCTL_BEGINTRANSACTION,
|
|
- .call.hCardAndDisposition = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .handles.hCard = call->handles.hCard,
|
|
- .dwDisposition = SCARD_LEAVE_CARD,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_BEGINTRANSACTION,
|
|
+ .call.hCardAndDisposition = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwDisposition = SCARD_LEAVE_CARD,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 128);
|
|
if (!s)
|
|
@@ -5016,16 +4996,12 @@ static UINT rdpdr_server_smartcard_end_transaction(RdpdrServerContext* context,
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = SCARD_IOCTL_ENDTRANSACTION,
|
|
- .call.hCardAndDisposition = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .handles.hCard = call->handles.hCard,
|
|
- .dwDisposition = call->dwDisposition,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_ENDTRANSACTION,
|
|
+ .call.hCardAndDisposition = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwDisposition = call->dwDisposition,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 128);
|
|
if (!s)
|
|
@@ -5119,18 +5095,14 @@ static UINT rdpdr_server_smartcard_status(RdpdrServerContext* context, void* cal
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = ioControlCode,
|
|
- .call.status = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .handles.hCard = call->handles.hCard,
|
|
- .fmszReaderNamesIsNULL = call->fmszReaderNamesIsNULL,
|
|
- .cchReaderLen = call->cchReaderLen,
|
|
- .cbAtrLen = call->cbAtrLen,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = ioControlCode,
|
|
+ .call.status = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .fmszReaderNamesIsNULL = call->fmszReaderNamesIsNULL,
|
|
+ .cchReaderLen = call->cchReaderLen,
|
|
+ .cbAtrLen = call->cbAtrLen,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 128);
|
|
if (!s)
|
|
@@ -5237,12 +5209,8 @@ static UINT rdpdr_server_smartcard_transmit(RdpdrServerContext* context, void* c
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = SCARD_IOCTL_TRANSMIT,
|
|
- .call.transmit = *call
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_TRANSMIT,
|
|
+ .call.transmit = *call };
|
|
|
|
s = Stream_New(nullptr, 512 + call->cbSendLength);
|
|
if (!s)
|
|
@@ -5335,20 +5303,16 @@ static UINT rdpdr_server_smartcard_control(RdpdrServerContext* context, void* ca
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = SCARD_IOCTL_CONTROL,
|
|
- .call.control = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .handles.hCard = call->handles.hCard,
|
|
- .dwControlCode = call->dwControlCode,
|
|
- .cbInBufferSize = call->cbInBufferSize,
|
|
- .pvInBuffer = call->pvInBuffer,
|
|
- .fpvOutBufferIsNULL = call->fpvOutBufferIsNULL,
|
|
- .cbOutBufferSize = call->cbOutBufferSize,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_CONTROL,
|
|
+ .call.control = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwControlCode = call->dwControlCode,
|
|
+ .cbInBufferSize = call->cbInBufferSize,
|
|
+ .pvInBuffer = call->pvInBuffer,
|
|
+ .fpvOutBufferIsNULL = call->fpvOutBufferIsNULL,
|
|
+ .cbOutBufferSize = call->cbOutBufferSize,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 512 + call->cbOutBufferSize);
|
|
if (!s)
|
|
@@ -5440,12 +5404,8 @@ static UINT rdpdr_server_smartcard_get_attrib(RdpdrServerContext* context, void*
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = SCARD_IOCTL_GETATTRIB,
|
|
- .call.getAttrib = *call
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_GETATTRIB,
|
|
+ .call.getAttrib = *call };
|
|
|
|
wStream* s = Stream_New(nullptr, 64);
|
|
if (!s)
|
|
@@ -5532,18 +5492,14 @@ static UINT rdpdr_server_smartcard_set_attrib(RdpdrServerContext* context, void*
|
|
|
|
*completionId = irp->CompletionId;
|
|
|
|
- /* clang-format off */
|
|
- const SMARTCARD_OPERATION op = {
|
|
- .ioControlCode = SCARD_IOCTL_SETATTRIB,
|
|
- .call.setAttrib = {
|
|
- .handles.hContext = call->handles.hContext,
|
|
- .handles.hCard = call->handles.hCard,
|
|
- .dwAttrId = call->dwAttrId,
|
|
- .cbAttrLen = call->cbAttrLen,
|
|
- .pbAttr = call->pbAttr,
|
|
- }
|
|
- };
|
|
- /* clang-format on */
|
|
+ const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_SETATTRIB,
|
|
+ .call.setAttrib = {
|
|
+ .handles.hContext = call->handles.hContext,
|
|
+ .handles.hCard = call->handles.hCard,
|
|
+ .dwAttrId = call->dwAttrId,
|
|
+ .cbAttrLen = call->cbAttrLen,
|
|
+ .pbAttr = call->pbAttr,
|
|
+ } };
|
|
|
|
s = Stream_New(nullptr, 64 + call->cbAttrLen);
|
|
if (!s)
|
|
|
|
From 05fd708bec929581bea630a9d2cb877bdbadb86a Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Tue, 30 Jun 2026 09:19:58 +0200
|
|
Subject: [PATCH 29/31] [channels,rdpdr] silence false clang-analyzer warning
|
|
|
|
rdpdr_server_discard_request does free up IRP so the
|
|
clang-analyzer-unix.Malloc is a false positive and misleading.
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 35 ++++++++++++++++++++++++++++--
|
|
1 file changed, 33 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index f04acffdaafd..7588e15d1fc1 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -3845,8 +3845,10 @@ static UINT rdpdr_server_smartcard_establish_context(RdpdrServerContext* context
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -3943,8 +3945,10 @@ static UINT rdpdr_server_smartcard_release_context(RdpdrServerContext* context,
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4042,8 +4046,10 @@ static UINT rdpdr_server_smartcard_is_valid_context(RdpdrServerContext* context,
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4144,8 +4150,10 @@ static UINT rdpdr_server_smartcard_list_reader_groups(RdpdrServerContext* contex
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4263,8 +4271,10 @@ static UINT rdpdr_server_smartcard_list_readers(RdpdrServerContext* context, voi
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4388,8 +4398,10 @@ static UINT rdpdr_server_smartcard_get_status_change(RdpdrServerContext* context
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4501,8 +4513,10 @@ static UINT rdpdr_server_smartcard_cancel(RdpdrServerContext* context, void* cal
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4609,8 +4623,10 @@ static UINT rdpdr_server_smartcard_connect(RdpdrServerContext* context, void* ca
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4723,8 +4739,10 @@ static UINT rdpdr_server_smartcard_reconnect(RdpdrServerContext* context, void*
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4821,8 +4839,10 @@ static UINT rdpdr_server_smartcard_disconnect(RdpdrServerContext* context, void*
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -4923,8 +4943,10 @@ static UINT rdpdr_server_smartcard_begin_transaction(RdpdrServerContext* context
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -5023,8 +5045,10 @@ static UINT rdpdr_server_smartcard_end_transaction(RdpdrServerContext* context,
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -5124,8 +5148,10 @@ static UINT rdpdr_server_smartcard_status(RdpdrServerContext* context, void* cal
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -5232,8 +5258,10 @@ static UINT rdpdr_server_smartcard_transmit(RdpdrServerContext* context, void* c
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -5334,8 +5362,10 @@ static UINT rdpdr_server_smartcard_control(RdpdrServerContext* context, void* ca
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
@@ -5483,7 +5513,6 @@ static UINT rdpdr_server_smartcard_set_attrib(RdpdrServerContext* context, void*
|
|
UINT result = CHANNEL_RC_OK;
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
RDPDR_IRP* irp = nullptr;
|
|
- wStream* s = nullptr;
|
|
|
|
result = prepare_smartcard_irp(context, SCARD_IOCTL_SETATTRIB,
|
|
rdpdr_server_smartcard_set_attrib_callback, callbackData, &irp);
|
|
@@ -5501,7 +5530,7 @@ static UINT rdpdr_server_smartcard_set_attrib(RdpdrServerContext* context, void*
|
|
.pbAttr = call->pbAttr,
|
|
} };
|
|
|
|
- s = Stream_New(nullptr, 64 + call->cbAttrLen);
|
|
+ wStream* s = Stream_New(nullptr, 64 + call->cbAttrLen);
|
|
if (!s)
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
@@ -5521,8 +5550,10 @@ static UINT rdpdr_server_smartcard_set_attrib(RdpdrServerContext* context, void*
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (result != CHANNEL_RC_OK && irp)
|
|
rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
if (s)
|
|
Stream_Release(s);
|
|
return result;
|
|
|
|
From e8704c1e11605d902ba077c187fab768e250c04b Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Tue, 30 Jun 2026 09:34:30 +0200
|
|
Subject: [PATCH 30/31] [channels,rdpdr] fix clang-analyzer-unix.Malloc
|
|
|
|
* Fix false positives with annotations
|
|
* Fix actual leaks
|
|
---
|
|
channels/rdpdr/server/rdpdr_main.c | 23 +++++++++++++++++------
|
|
1 file changed, 17 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
|
|
index 7588e15d1fc1..ae230dc1a3d5 100644
|
|
--- a/channels/rdpdr/server/rdpdr_main.c
|
|
+++ b/channels/rdpdr/server/rdpdr_main.c
|
|
@@ -3352,8 +3352,10 @@ static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, void* cal
|
|
irp->FileId = fileId;
|
|
|
|
/* Send a request to open the directory. */
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
return rdpdr_server_send_device_write_request(context, irp->DeviceId, irp->FileId,
|
|
irp->CompletionId, buffer, length, offset);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
}
|
|
|
|
/*************************************************
|
|
@@ -3414,8 +3416,10 @@ static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, void* cal
|
|
irp->FileId = fileId;
|
|
|
|
/* Send a request to open the directory. */
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
return rdpdr_server_send_device_close_request(context, irp->DeviceId, irp->FileId,
|
|
irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
}
|
|
|
|
/*************************************************
|
|
@@ -5426,7 +5430,7 @@ static UINT rdpdr_server_smartcard_get_attrib(RdpdrServerContext* context, void*
|
|
RdpdrServerPrivate* priv = context->priv;
|
|
|
|
RDPDR_IRP* irp = nullptr;
|
|
- UINT ret =
|
|
+ const UINT ret =
|
|
prepare_smartcard_irp(context, SCARD_IOCTL_GETATTRIB,
|
|
rdpdr_server_smartcard_get_attrib_callback, callbackData, &irp);
|
|
if (ret != CHANNEL_RC_OK)
|
|
@@ -5437,25 +5441,32 @@ static UINT rdpdr_server_smartcard_get_attrib(RdpdrServerContext* context, void*
|
|
const SMARTCARD_OPERATION op = { .ioControlCode = SCARD_IOCTL_GETATTRIB,
|
|
.call.getAttrib = *call };
|
|
|
|
+ UINT error = CHANNEL_RC_NO_MEMORY;
|
|
wStream* s = Stream_New(nullptr, 64);
|
|
if (!s)
|
|
{
|
|
WLog_Print(priv->log, WLOG_ERROR, "Stream_New failed!");
|
|
- return CHANNEL_RC_NO_MEMORY;
|
|
+ goto out;
|
|
}
|
|
|
|
LONG status = smartcard_irp_device_control_encode_request(s, &op);
|
|
if (status != SCARD_S_SUCCESS)
|
|
{
|
|
- Stream_Release(s);
|
|
- return ERROR_INTERNAL_ERROR;
|
|
+ error = ERROR_INTERNAL_ERROR;
|
|
+ goto out;
|
|
}
|
|
|
|
- const UINT error = rdpdr_server_send_device_control_request(
|
|
+ error = rdpdr_server_send_device_control_request(
|
|
context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
|
|
SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
|
|
|
|
- Stream_Release(s);
|
|
+out:
|
|
+ // NOLINTBEGIN(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
+ if (error != CHANNEL_RC_OK && irp)
|
|
+ rdpdr_server_discard_request(context, irp->CompletionId);
|
|
+ // NOLINTEND(clang-analyzer-unix.Malloc): IRP is removed from context and freed there
|
|
+ if (s)
|
|
+ Stream_Release(s);
|
|
return error;
|
|
}
|
|
|
|
|
|
From 07bee6f35bc236cbe99e9240aa4c8ac2d923b68a Mon Sep 17 00:00:00 2001
|
|
From: Armin Novak <armin.novak@thincast.com>
|
|
Date: Tue, 30 Jun 2026 09:35:36 +0200
|
|
Subject: [PATCH 31/31] [utils,test] replace NULL with nullptr
|
|
|
|
---
|
|
libfreerdp/utils/test/TestSmartcardOperations.c | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/libfreerdp/utils/test/TestSmartcardOperations.c b/libfreerdp/utils/test/TestSmartcardOperations.c
|
|
index 590d9cc6fb93..19969df9794e 100644
|
|
--- a/libfreerdp/utils/test/TestSmartcardOperations.c
|
|
+++ b/libfreerdp/utils/test/TestSmartcardOperations.c
|
|
@@ -783,7 +783,7 @@ static wStream* build_device_control_response(UINT32 ioControlCode, const SMARTC
|
|
{
|
|
const char* name = scard_get_ioctl_string(ioControlCode, TRUE);
|
|
|
|
- wStream* payload = Stream_New(NULL, 4096);
|
|
+ wStream* payload = Stream_New(nullptr, 4096);
|
|
if (!payload)
|
|
{
|
|
(void)fprintf(stderr, "%s: Stream_New for payload failed\n", name);
|
|
@@ -800,7 +800,7 @@ static wStream* build_device_control_response(UINT32 ioControlCode, const SMARTC
|
|
}
|
|
Stream_SealLength(payload);
|
|
|
|
- wStream* s = Stream_New(NULL, 256 + Stream_Length(payload));
|
|
+ wStream* s = Stream_New(nullptr, 256 + Stream_Length(payload));
|
|
if (!s)
|
|
{
|
|
(void)fprintf(stderr, "%s: Stream_New for response failed\n", name);
|