From 25d2533eaabc26447d43b2916d899d1caa8ea2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 17 Nov 2012 03:45:15 -0500 Subject: [PATCH] libwinpr-rpc: added UUID functions --- libfreerdp/core/http.c | 54 ++++++++-------- libfreerdp/core/rpc.c | 75 ++++++++++++---------- libfreerdp/core/rpc.h | 5 ++ libfreerdp/core/rts.c | 1 + libfreerdp/core/tsg.c | 5 -- winpr/include/winpr/rpc.h | 23 +++++++ winpr/libwinpr/rpc/rpc.c | 131 ++++++++++++++++++++++++++++++++++---- 7 files changed, 215 insertions(+), 79 deletions(-) diff --git a/libfreerdp/core/http.c b/libfreerdp/core/http.c index 1e7a1a6e8..9ac9e5272 100644 --- a/libfreerdp/core/http.c +++ b/libfreerdp/core/http.c @@ -406,39 +406,39 @@ HttpResponse* http_response_recv(rdpTls* tls) while (TRUE) { - while (nbytes < 5) - { - status = tls_read(tls, p, length - nbytes); + while (nbytes < 5) + { + status = tls_read(tls, p, length - nbytes); - if (status > 0) - { - nbytes += status; - p = (BYTE*) &buffer[nbytes]; - } - else if (status == 0) - { - continue; - } - else - { - http_response_free(http_response); - return NULL; - } - } + if (status > 0) + { + nbytes += status; + p = (BYTE*) &buffer[nbytes]; + } + else if (status == 0) + { + continue; + } + else + { + http_response_free(http_response); + return NULL; + } + } header_end = strstr((char*) buffer, "\r\n\r\n"); - if (header_end) - { - header_end += 2; - } - else - { - printf("http_response_recv: invalid response:\n"); - winpr_HexDump(buffer, status); + if (header_end) + { + header_end += 2; + } + else + { + printf("http_response_recv: invalid response:\n"); + winpr_HexDump(buffer, status); http_response_free(http_response); return NULL; - } + } if (header_end != NULL) { diff --git a/libfreerdp/core/rpc.c b/libfreerdp/core/rpc.c index 1eabf71e7..dde71cc2a 100644 --- a/libfreerdp/core/rpc.c +++ b/libfreerdp/core/rpc.c @@ -433,39 +433,6 @@ void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header) header->common.packed_drep[3] = rpc->packed_drep[3]; } -int rpc_out_read(rdpRpc* rpc, BYTE* data, int length) -{ - int status; - - status = tls_read(rpc->TlsOut, data, length); - - return status; -} - -int rpc_out_write(rdpRpc* rpc, BYTE* data, int length) -{ - int status; - - status = tls_write_all(rpc->TlsOut, data, length); - - return status; -} - -int rpc_in_write(rdpRpc* rpc, BYTE* data, int length) -{ - int status; - - status = tls_write_all(rpc->TlsIn, data, length); - - if (status > 0) - { - rpc->VirtualConnection->DefaultInChannel->BytesSent += status; - rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow -= status; - } - - return status; -} - UINT32 rpc_offset_align(UINT32* offset, UINT32 alignment) { UINT32 pad; @@ -731,6 +698,46 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l return TRUE; } +int rpc_out_read(rdpRpc* rpc, BYTE* data, int length) +{ + int status; + + status = tls_read(rpc->TlsOut, data, length); + + return status; +} + +int rpc_out_write(rdpRpc* rpc, BYTE* data, int length) +{ + int status; + + status = tls_write_all(rpc->TlsOut, data, length); + + return status; +} + +int rpc_in_write(rdpRpc* rpc, BYTE* data, int length) +{ + int status; + + status = tls_write_all(rpc->TlsIn, data, length); + + if (status > 0) + { + /* + * This protocol specifies that only RPC PDUs are subject to the flow control abstract + * data model. RTS PDUs and the HTTP request and response headers are not subject to flow control. + * Implementations of this protocol MUST NOT include them when computing any of the variables + * specified by this abstract data model. + */ + + rpc->VirtualConnection->DefaultInChannel->BytesSent += status; + rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow -= status; + } + + return status; +} + int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header) { int status; @@ -810,7 +817,7 @@ int rpc_recv_pdu(rdpRpc* rpc) if (!(header->common.pfc_flags & PFC_LAST_FRAG)) { - DEBUG_RPC("Fragmented PDU"); + printf("Fragmented PDU\n"); } if (header->common.ptype == PTYPE_RTS) /* RTS PDU */ diff --git a/libfreerdp/core/rpc.h b/libfreerdp/core/rpc.h index 050d496f3..66cfb8b5e 100644 --- a/libfreerdp/core/rpc.h +++ b/libfreerdp/core/rpc.h @@ -630,6 +630,11 @@ typedef struct rpc_virtual_connection RpcVirtualConnection; /* Virtual Connection Cookie Table */ +#define RPC_UUID_FORMAT_STRING "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define RPC_UUID_FORMAT_ARGUMENTS(_rpc_uuid) \ + _rpc_uuid[0], _rpc_uuid[1], _rpc_uuid[2], _rpc_uuid[3], _rpc_uuid[4], _rpc_uuid[5], _rpc_uuid[6], _rpc_uuid[7], \ + _rpc_uuid[8], _rpc_uuid[9], _rpc_uuid[10], _rpc_uuid[11], _rpc_uuid[12], _rpc_uuid[13], _rpc_uuid[14], _rpc_uuid[15] + struct rpc_virtual_connection_cookie_entry { BYTE Cookie[16]; diff --git a/libfreerdp/core/rts.c b/libfreerdp/core/rts.c index 581a7695a..5e745cef4 100644 --- a/libfreerdp/core/rts.c +++ b/libfreerdp/core/rts.c @@ -900,6 +900,7 @@ int rts_recv_flow_control_ack_with_destination_pdu(rdpRpc* rpc, BYTE* buffer, UI printf("Destination: %d BytesReceived: %d AvailableWindow: %d\n", Destination, BytesReceived, AvailableWindow); + printf("ChannelCookie: " RPC_UUID_FORMAT_STRING "\n", RPC_UUID_FORMAT_ARGUMENTS(ChannelCookie)); return 0; } diff --git a/libfreerdp/core/tsg.c b/libfreerdp/core/tsg.c index e0ea73b90..5d08ea91a 100644 --- a/libfreerdp/core/tsg.c +++ b/libfreerdp/core/tsg.c @@ -1146,11 +1146,6 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) return -1; } -#ifdef WITH_DEBUG_TSG - printf("RPC Stub (offset: %d length: %d):\n", tsg->StubOffset, tsg->StubLength); - freerdp_hexdump(&rpc->buffer[tsg->StubOffset], tsg->StubLength); -#endif - if (header->alloc_hint == 4) { DEBUG_TSG("Ignoring TsProxySetupReceivePipe Response"); diff --git a/winpr/include/winpr/rpc.h b/winpr/include/winpr/rpc.h index ca455d759..13acc075f 100644 --- a/winpr/include/winpr/rpc.h +++ b/winpr/include/winpr/rpc.h @@ -44,6 +44,29 @@ typedef PCONTEXT_HANDLE PCHANNEL_CONTEXT_HANDLE_SERIALIZE; #include #include #include +#include + +#define RPC_S_OK ERROR_SUCCESS +#define RPC_S_INVALID_ARG ERROR_INVALID_PARAMETER +#define RPC_S_OUT_OF_MEMORY ERROR_OUTOFMEMORY +#define RPC_S_OUT_OF_THREADS ERROR_MAX_THRDS_REACHED +#define RPC_S_INVALID_LEVEL ERROR_INVALID_PARAMETER +#define RPC_S_BUFFER_TOO_SMALL ERROR_INSUFFICIENT_BUFFER +#define RPC_S_INVALID_SECURITY_DESC ERROR_INVALID_SECURITY_DESCR +#define RPC_S_ACCESS_DENIED ERROR_ACCESS_DENIED +#define RPC_S_SERVER_OUT_OF_MEMORY ERROR_NOT_ENOUGH_SERVER_MEMORY +#define RPC_S_ASYNC_CALL_PENDING ERROR_IO_PENDING +#define RPC_S_UNKNOWN_PRINCIPAL ERROR_NONE_MAPPED +#define RPC_S_TIMEOUT ERROR_TIMEOUT + +#define RPC_X_NO_MEMORY RPC_S_OUT_OF_MEMORY +#define RPC_X_INVALID_BOUND RPC_S_INVALID_BOUND +#define RPC_X_INVALID_TAG RPC_S_INVALID_TAG +#define RPC_X_ENUM_VALUE_TOO_LARGE RPC_X_ENUM_VALUE_OUT_OF_RANGE +#define RPC_X_SS_CONTEXT_MISMATCH ERROR_INVALID_HANDLE +#define RPC_X_INVALID_BUFFER ERROR_INVALID_USER_BUFFER +#define RPC_X_PIPE_APP_MEMORY ERROR_OUTOFMEMORY +#define RPC_X_INVALID_PIPE_OPERATION RPC_X_WRONG_PIPE_ORDER #define RPC_VAR_ENTRY __cdecl diff --git a/winpr/libwinpr/rpc/rpc.c b/winpr/libwinpr/rpc/rpc.c index a7f1e9a5e..07dcd3ed8 100644 --- a/winpr/libwinpr/rpc/rpc.c +++ b/winpr/libwinpr/rpc/rpc.c @@ -23,10 +23,13 @@ #include +#include #include #ifndef _WIN32 +#include + RPC_STATUS RpcBindingCopy(RPC_BINDING_HANDLE SourceBinding, RPC_BINDING_HANDLE* DestinationBinding) { return 0; @@ -123,12 +126,14 @@ RPC_STATUS RpcStringBindingParseW(RPC_WSTR StringBinding, RPC_WSTR* ObjUuid, RPC RPC_STATUS RpcStringFreeA(RPC_CSTR* String) { - return 0; + free(String); + return RPC_S_OK; } RPC_STATUS RpcStringFreeW(RPC_WSTR* String) { - return 0; + free(String); + return RPC_S_OK; } RPC_STATUS RpcIfInqId(RPC_IF_HANDLE RpcIfHandle, RPC_IF_ID* RpcIfId) @@ -540,30 +545,105 @@ RPC_STATUS RpcCancelThreadEx(void* Thread, long Timeout) return 0; } +/** + * UUID Functions + */ + +static UUID UUID_NIL = +{ + 0x00000000, 0x0000, 0x0000, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; RPC_STATUS UuidCreate(UUID* Uuid) { - return 0; + RAND_pseudo_bytes((void*) Uuid, 16); + return RPC_S_OK; } RPC_STATUS UuidCreateSequential(UUID* Uuid) { - return 0; + RAND_pseudo_bytes((void*) Uuid, 16); + return RPC_S_OK; } RPC_STATUS UuidToStringA(UUID* Uuid, RPC_CSTR* StringUuid) +{ + *StringUuid = (RPC_CSTR) malloc(36 + 1); + + if (!(*StringUuid)) + return RPC_S_OUT_OF_MEMORY; + + if (!Uuid) + Uuid = &UUID_NIL; + + /** + * Format is 32 hex digits partitioned in 5 groups: + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + */ + + sprintf_s((char*) *StringUuid, 36 + 1, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + Uuid->Data1, Uuid->Data2, Uuid->Data3, + Uuid->Data4[0], Uuid->Data4[1], + Uuid->Data4[2], Uuid->Data4[3], Uuid->Data4[4], + Uuid->Data4[5], Uuid->Data4[6], Uuid->Data4[7]); + + return RPC_S_OK; +} + +RPC_STATUS UuidToStringW(UUID* Uuid, RPC_WSTR* StringUuid) { return 0; } RPC_STATUS UuidFromStringA(RPC_CSTR StringUuid, UUID* Uuid) { - return 0; -} + int index; + BYTE bin[36]; -RPC_STATUS UuidToStringW(UUID* Uuid, RPC_WSTR* StringUuid) -{ - return 0; + if (!StringUuid) + return UuidCreateNil(Uuid); + + if (strlen((char*) StringUuid) != 36) + return RPC_S_INVALID_STRING_UUID; + + if ((StringUuid[8] != '-') || (StringUuid[13] != '-') || + (StringUuid[18] != '-') || (StringUuid[23] != '-')) + { + return RPC_S_INVALID_STRING_UUID; + } + + for (index = 0; index < 36; index++) + { + if ((index == 8) || (index == 13) || (index == 18) || (index == 23)) + continue; + + if ((StringUuid[index] >= '0') && (StringUuid[index] <= '9')) + bin[index] = StringUuid[index] - '0'; + else if ((StringUuid[index] >= 'a') && (StringUuid[index] <= 'f')) + bin[index] = StringUuid[index] - 'a' + 10; + else if ((StringUuid[index] >= 'A') && (StringUuid[index] <= 'F')) + bin[index] = StringUuid[index] - 'A' + 10; + else + return RPC_S_INVALID_STRING_UUID; + } + + Uuid->Data1 = ((bin[0] << 28) | (bin[1] << 24) | (bin[2] << 20) | (bin[3] << 16) | + (bin[4] << 12) | (bin[5] << 8) | (bin[6] << 4) | bin[7]); + + Uuid->Data2 = ((bin[9] << 12) | (bin[10] << 8) | (bin[11] << 4) | bin[12]); + Uuid->Data3 = ((bin[14] << 12) | (bin[15] << 8) | (bin[16] << 4) | bin[17]); + + Uuid->Data4[0] = ((bin[19] << 4) | bin[20]); + Uuid->Data4[1] = ((bin[21] << 4) | bin[22]); + Uuid->Data4[2] = ((bin[24] << 4) | bin[25]); + Uuid->Data4[3] = ((bin[26] << 4) | bin[27]); + Uuid->Data4[4] = ((bin[28] << 4) | bin[29]); + Uuid->Data4[5] = ((bin[30] << 4) | bin[31]); + Uuid->Data4[6] = ((bin[32] << 4) | bin[33]); + Uuid->Data4[7] = ((bin[34] << 4) | bin[35]); + + return RPC_S_OK; } RPC_STATUS UuidFromStringW(RPC_WSTR StringUuid, UUID* Uuid) @@ -573,17 +653,43 @@ RPC_STATUS UuidFromStringW(RPC_WSTR StringUuid, UUID* Uuid) signed int UuidCompare(UUID* Uuid1, UUID* Uuid2, RPC_STATUS* Status) { + int index; + + *Status = RPC_S_OK; + + if (!Uuid1) + Uuid1 = &UUID_NIL; + + if (!Uuid2) + Uuid2 = &UUID_NIL; + + if (Uuid1->Data1 != Uuid2->Data1) + return (Uuid1->Data1 < Uuid2->Data1) ? -1 : 1; + + if (Uuid1->Data2 != Uuid2->Data2) + return (Uuid1->Data2 < Uuid2->Data2) ? -1 : 1; + + if (Uuid1->Data3 != Uuid2->Data3) + return (Uuid1->Data3 < Uuid2->Data3) ? -1 : 1; + + for (index = 0; index < 8; index++) + { + if (Uuid1->Data4[index] != Uuid2->Data4[index]) + return (Uuid1->Data4[index] < Uuid2->Data4[index]) ? -1 : 1; + } + return 0; } RPC_STATUS UuidCreateNil(UUID* NilUuid) { - return 0; + CopyMemory((void*) NilUuid, (void*) &UUID_NIL, 16); + return RPC_S_OK; } int UuidEqual(UUID* Uuid1, UUID* Uuid2, RPC_STATUS* Status) { - return 0; + return ((UuidCompare(Uuid1, Uuid2, Status) == 0) ? TRUE : FALSE); } unsigned short UuidHash(UUID* Uuid, RPC_STATUS* Status) @@ -593,10 +699,9 @@ unsigned short UuidHash(UUID* Uuid, RPC_STATUS* Status) int UuidIsNil(UUID* Uuid, RPC_STATUS* Status) { - return 0; + return UuidEqual(Uuid, &UUID_NIL, Status); } - RPC_STATUS RpcEpRegisterNoReplaceA(RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector, UUID_VECTOR* UuidVector, RPC_CSTR Annotation) { return 0;