Commit e15e60b9 authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

rpcrt4: Implement TowerConstruct and TowerExplode.

Add some tests for these undocumented functions.
parent 37364b83
......@@ -36,6 +36,7 @@
#include "wine/debug.h"
#include "rpc_binding.h"
#include "epm_towers.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
......@@ -245,3 +246,131 @@ RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE
/* otherwise we fully bind the handle & return RPC_S_OK */
return RPCRT4_ResolveBinding(Binding, reply.as_string);
}
typedef unsigned int unsigned32;
typedef struct twr_t
{
unsigned32 tower_length;
/* [size_is] */ byte tower_octet_string[ 1 ];
} twr_t;
RPC_STATUS WINAPI TowerExplode(
const twr_t *tower, RPC_SYNTAX_IDENTIFIER *object, RPC_SYNTAX_IDENTIFIER *syntax,
char **protseq, char **endpoint, char **address)
{
size_t tower_size;
RPC_STATUS status;
const unsigned char *p;
u_int16 floor_count;
const twr_uuid_floor_t *object_floor;
const twr_uuid_floor_t *syntax_floor;
*protseq = NULL;
*endpoint = NULL;
*address = NULL;
tower_size = tower->tower_length;
if (tower_size < sizeof(u_int16))
return EPT_S_NOT_REGISTERED;
p = &tower->tower_octet_string[0];
floor_count = *(const u_int16 *)p;
p += sizeof(u_int16);
tower_size -= sizeof(u_int16);
TRACE("floor_count: %d\n", floor_count);
/* FIXME: should we do something with the floor count? at the moment we don't */
if (tower_size < sizeof(*object_floor) + sizeof(*syntax_floor))
return EPT_S_NOT_REGISTERED;
object_floor = (const twr_uuid_floor_t *)p;
p += sizeof(*object_floor);
tower_size -= sizeof(*object_floor);
syntax_floor = (const twr_uuid_floor_t *)p;
p += sizeof(*syntax_floor);
tower_size -= sizeof(*syntax_floor);
if ((object_floor->count_lhs != sizeof(object_floor->protid) +
sizeof(object_floor->uuid) + sizeof(object_floor->major_version)) ||
(object_floor->protid != EPM_PROTOCOL_UUID) ||
(object_floor->count_rhs != sizeof(object_floor->minor_version)))
return EPT_S_NOT_REGISTERED;
if ((syntax_floor->count_lhs != sizeof(syntax_floor->protid) +
sizeof(syntax_floor->uuid) + sizeof(syntax_floor->major_version)) ||
(syntax_floor->protid != EPM_PROTOCOL_UUID) ||
(syntax_floor->count_rhs != sizeof(syntax_floor->minor_version)))
return EPT_S_NOT_REGISTERED;
status = RpcTransport_ParseTopOfTower(p, tower_size, protseq, address, endpoint);
if (status == RPC_S_OK)
{
syntax->SyntaxGUID = syntax_floor->uuid;
syntax->SyntaxVersion.MajorVersion = syntax_floor->major_version;
syntax->SyntaxVersion.MinorVersion = syntax_floor->minor_version;
object->SyntaxGUID = object_floor->uuid;
object->SyntaxVersion.MajorVersion = object_floor->major_version;
object->SyntaxVersion.MinorVersion = object_floor->minor_version;
}
return status;
}
RPC_STATUS WINAPI TowerConstruct(
const RPC_SYNTAX_IDENTIFIER *object, const RPC_SYNTAX_IDENTIFIER *syntax,
const char *protseq, const char *endpoint, const char *address,
twr_t **tower)
{
size_t tower_size;
RPC_STATUS status;
unsigned char *p;
twr_uuid_floor_t *object_floor;
twr_uuid_floor_t *syntax_floor;
*tower = NULL;
status = RpcTransport_GetTopOfTower(NULL, &tower_size, protseq, address, endpoint);
if (status != RPC_S_OK)
return status;
tower_size += sizeof(u_int16) + sizeof(*object_floor) + sizeof(*syntax_floor);
*tower = I_RpcAllocate(FIELD_OFFSET(twr_t, tower_octet_string[tower_size]));
if (!*tower)
return RPC_S_OUT_OF_RESOURCES;
(*tower)->tower_length = tower_size;
p = &(*tower)->tower_octet_string[0];
*(u_int16 *)p = 5; /* number of floors */
p += sizeof(u_int16);
object_floor = (twr_uuid_floor_t *)p;
p += sizeof(*object_floor);
syntax_floor = (twr_uuid_floor_t *)p;
p += sizeof(*syntax_floor);
object_floor->count_lhs = sizeof(object_floor->protid) + sizeof(object_floor->uuid) +
sizeof(object_floor->major_version);
object_floor->protid = EPM_PROTOCOL_UUID;
object_floor->count_rhs = sizeof(object_floor->minor_version);
object_floor->uuid = object->SyntaxGUID;
object_floor->major_version = object->SyntaxVersion.MajorVersion;
object_floor->minor_version = object->SyntaxVersion.MinorVersion;
syntax_floor->count_lhs = sizeof(syntax_floor->protid) + sizeof(syntax_floor->uuid) +
sizeof(syntax_floor->major_version);
syntax_floor->protid = EPM_PROTOCOL_UUID;
syntax_floor->count_rhs = sizeof(syntax_floor->minor_version);
syntax_floor->uuid = syntax->SyntaxGUID;
syntax_floor->major_version = syntax->SyntaxVersion.MajorVersion;
syntax_floor->minor_version = syntax->SyntaxVersion.MinorVersion;
status = RpcTransport_GetTopOfTower(p, &tower_size, protseq, address, endpoint);
if (status != RPC_S_OK)
{
I_RpcFree(*tower);
*tower = NULL;
return status;
}
return RPC_S_OK;
}
......@@ -527,8 +527,8 @@
@ stub SimpleTypeBufferSize # wxp
@ stub SimpleTypeMemorySize # wxp
@ stub StartServiceIfNecessary # win9x
@ stub TowerConstruct
@ stub TowerExplode
@ stdcall TowerConstruct(ptr ptr ptr ptr ptr ptr)
@ stdcall TowerExplode(ptr ptr ptr ptr ptr ptr)
@ stdcall UuidCompare(ptr ptr ptr)
@ stdcall UuidCreate(ptr)
@ stdcall UuidCreateNil(ptr)
......
......@@ -19,6 +19,7 @@
*/
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include <windef.h>
......@@ -29,6 +30,16 @@
#include "rpc.h"
#include "rpcdce.h"
typedef unsigned int unsigned32;
typedef struct twr_t
{
unsigned32 tower_length;
/* [size_is] */ byte tower_octet_string[ 1 ];
} twr_t;
RPC_STATUS WINAPI TowerExplode(const twr_t *tower, RPC_SYNTAX_IDENTIFIER *object, RPC_SYNTAX_IDENTIFIER *syntax, char **protseq, char **endpoint, char **address);
RPC_STATUS WINAPI TowerConstruct(const RPC_SYNTAX_IDENTIFIER *object, const RPC_SYNTAX_IDENTIFIER *syntax, const char *protseq, const char *endpoint, const char *address, twr_t **tower);
static UUID Uuid_Table[10] = {
{ 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, /* 0 (null) */
{ 0xdeadbeef, 0xdead, 0xbeef, {0x10, 0x21, 0x35, 0x56, 0x89, 0xa0, 0xf4, 0x8a} }, /* 1 */
......@@ -175,6 +186,88 @@ static void test_rpc_ncacn_ip_tcp(void)
ok(status == RPC_S_OK, "return wrong\n");
}
/* this is what's generated with MS/RPC - it includes an extra 2
* bytes in the protocol floor */
static const unsigned char tower_data_tcp_ip1[] =
{
0x05,0x00,0x13,0x00,0x0d,0x00,0xdb,0xf1,
0xa4,0x47,0xca,0x67,0x10,0xb3,0x1f,0x00,
0xdd,0x01,0x06,0x62,0xda,0x00,0x00,0x02,
0x00,0x00,0x00,0x13,0x00,0x0d,0x04,0x5d,
0x88,0x8a,0xeb,0x1c,0xc9,0x11,0x9f,0xe8,
0x08,0x00,0x2b,0x10,0x48,0x60,0x02,0x00,
0x02,0x00,0x00,0x00,0x01,0x00,0x0b,0x02,
0x00,0x00,0x00,0x01,0x00,0x07,0x02,0x00,
0x00,0x87,0x01,0x00,0x09,0x04,0x00,0x0a,
0x00,0x00,0x01,
};
/* this is the optimal data that i think should be generated */
static const unsigned char tower_data_tcp_ip2[] =
{
0x05,0x00,0x13,0x00,0x0d,0x00,0xdb,0xf1,
0xa4,0x47,0xca,0x67,0x10,0xb3,0x1f,0x00,
0xdd,0x01,0x06,0x62,0xda,0x00,0x00,0x02,
0x00,0x00,0x00,0x13,0x00,0x0d,0x04,0x5d,
0x88,0x8a,0xeb,0x1c,0xc9,0x11,0x9f,0xe8,
0x08,0x00,0x2b,0x10,0x48,0x60,0x02,0x00,
0x02,0x00,0x00,0x00,0x01,0x00,0x0b,0x00,
0x00,0x01,0x00,0x07,0x02,0x00,0x00,0x87,
0x01,0x00,0x09,0x04,0x00,0x0a,0x00,0x00,
0x01,
};
static void test_towers(void)
{
RPC_STATUS ret;
twr_t *tower;
static const RPC_SYNTAX_IDENTIFIER mapi_if_id = { { 0xa4f1db00, 0xca47, 0x1067, { 0xb3, 0x1f, 0x00, 0xdd, 0x01, 0x06, 0x62, 0xda } }, { 0, 0 } };
static const RPC_SYNTAX_IDENTIFIER ndr_syntax = { { 0x8a885d04, 0x1ceb, 0x11c9, { 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60 } }, { 2, 0 } };
RPC_SYNTAX_IDENTIFIER object, syntax;
char *protseq, *endpoint, *address;
BOOL same;
ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_ip_tcp", "135", "10.0.0.1", &tower);
ok(ret == RPC_S_OK, "TowerConstruct failed with error %ld\n", ret);
/* first check we have the right amount of data */
ok(tower->tower_length == sizeof(tower_data_tcp_ip1) ||
tower->tower_length == sizeof(tower_data_tcp_ip2),
"Size of tower differs (expected %d or %d, actual %d)\n",
sizeof(tower_data_tcp_ip1), sizeof(tower_data_tcp_ip2), tower->tower_length);
/* then do a byte-by-byte comparison */
same = ((tower->tower_length == sizeof(tower_data_tcp_ip1)) &&
!memcmp(&tower->tower_octet_string, tower_data_tcp_ip1, sizeof(tower_data_tcp_ip1))) ||
((tower->tower_length == sizeof(tower_data_tcp_ip2)) &&
!memcmp(&tower->tower_octet_string, tower_data_tcp_ip2, sizeof(tower_data_tcp_ip2)));
ok(same, "Tower data differs\n");
if (!same)
{
unsigned32 i;
for (i = 0; i < tower->tower_length; i++)
{
if (i % 8 == 0) printf(" ");
printf("0x%02x,", tower->tower_octet_string[i]);
if (i % 8 == 7) printf("\n");
}
printf("\n");
}
ret = TowerExplode(tower, &object, &syntax, &protseq, &endpoint, &address);
ok(ret == RPC_S_OK, "TowerExplode failed with error %ld\n", ret);
ok(!memcmp(&object, &mapi_if_id, sizeof(mapi_if_id)), "object id didn't match\n");
ok(!memcmp(&syntax, &ndr_syntax, sizeof(syntax)), "syntax id didn't match\n");
ok(!strcmp(protseq, "ncacn_ip_tcp"), "protseq was \"%s\" instead of \"ncacn_ip_tcp\"\n", protseq);
ok(!strcmp(endpoint, "135"), "endpoint was \"%s\" instead of \"135\"\n", endpoint);
ok(!strcmp(address, "10.0.0.1"), "address was \"%s\" instead of \"10.0.0.1\"\n", address);
I_RpcFree(protseq);
I_RpcFree(endpoint);
I_RpcFree(address);
I_RpcFree(tower);
}
START_TEST( rpc )
{
trace ( " ** Uuid Conversion and Comparison Tests **\n" );
......@@ -182,4 +275,5 @@ START_TEST( rpc )
trace ( " ** DceErrorInqText **\n");
TestDceErrorInqText();
test_rpc_ncacn_ip_tcp();
test_towers();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment