You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
807 lines
20 KiB
807 lines
20 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
|
|
|
Module Name:
|
|
|
|
tower.c
|
|
|
|
Abstract:
|
|
|
|
This file contains encoding/decoding for the tower representation
|
|
of the binding information that DCE runtime uses.
|
|
|
|
TowerConstruct/TowerExplode will be called by the Runtime EpResolveBinding
|
|
on the client side, TowerExplode will be called by the Endpoint Mapper
|
|
and in addition the name service may call TowerExplode, TowerConstruct.
|
|
|
|
Author:
|
|
|
|
Bharat Shah (barats) 3-23-92
|
|
KamenM 05/02/2002 Major security and cleanup changes
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include <precomp.hxx>
|
|
#include <epmp.h>
|
|
#include <twrtypes.h>
|
|
#include <twrproto.h>
|
|
|
|
|
|
//
|
|
// TowerVerify() defines.
|
|
//
|
|
// Note: DECnet Protocol uses 6 Floors, all others 5.
|
|
//
|
|
#define MAX_FLOOR_COUNT 6
|
|
#define MIN_FLOOR_COUNT 3
|
|
|
|
#ifndef UNALIGNED
|
|
#error UNALIGNED not defined by sysinc.h or its includes and is needed.
|
|
#endif
|
|
|
|
#pragma pack(1)
|
|
|
|
|
|
/*
|
|
Some Lrpc specific stuff
|
|
*/
|
|
|
|
#define NP_TRANSPORTID_LRPC 0x10
|
|
#define NP_TOWERS_LRPC 0x04
|
|
|
|
// "ncalrpc" including the NULL terminator
|
|
const int LrpcProtocolSequenceLength = 8;
|
|
|
|
|
|
RPC_STATUS
|
|
Floor0or1ToId(
|
|
IN PFLOOR_0OR1 Floor,
|
|
OUT PGENERIC_ID Id
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function extracts Xfer Syntax or If info from a
|
|
a DCE tower Floor 0 or 1 encoding
|
|
|
|
Arguments:
|
|
|
|
Floor - A pointer to Floor0 or Floor 1 encoding
|
|
|
|
Id - on output, the transfer syntax or interface id
|
|
|
|
Return Value:
|
|
|
|
EP_S_CANT_PERFORM_OP - The Encoding for the floor [0 or 1] is incorrect.
|
|
|
|
N.B.
|
|
|
|
Caller must have verified that the whole floor is present (i.e. we can't walk
|
|
off the end of the buffer)
|
|
|
|
--*/
|
|
{
|
|
if (Floor->FloorId != UUID_ENCODING)
|
|
{
|
|
return (EP_S_CANT_PERFORM_OP);
|
|
}
|
|
|
|
RpcpMemoryCopy((char PAPI *)&Id->Uuid, (char PAPI *) &Floor->Uuid,
|
|
sizeof(UUID));
|
|
|
|
Id->MajorVersion = Floor->MajorVersion;
|
|
Id->MinorVersion = Floor->MinorVersion;
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
CopyIdToFloor(
|
|
OUT PFLOOR_0OR1 Floor,
|
|
IN PGENERIC_ID Id
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function constructs FLOOR 0 or 1 from the given IF-id or Transfer
|
|
Syntax Id.
|
|
|
|
Arguments:
|
|
|
|
Floor - Pointer to Floor 0 or 1 structure that will be constructed
|
|
|
|
Id - Pointer to If-id or Xfer Syntax Id.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
--*/
|
|
{
|
|
|
|
Floor->FloorId = UUID_ENCODING;
|
|
Floor->ProtocolIdByteCount = sizeof(Floor->Uuid) + sizeof(Floor->FloorId)
|
|
+ sizeof(Floor->MajorVersion);
|
|
Floor->AddressByteCount = sizeof(Floor->MinorVersion);
|
|
|
|
RpcpMemoryCopy((char PAPI *) &Floor->Uuid, (char PAPI *) &Id->Uuid,
|
|
sizeof(UUID));
|
|
|
|
Floor->MajorVersion = Id->MajorVersion;
|
|
Floor->MinorVersion = Id->MinorVersion;
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
BYTE *
|
|
VerifyFloorLHSAndRHS (
|
|
IN BYTE *FloorStart,
|
|
IN BYTE *UpperBound,
|
|
IN ULONG FloorNum
|
|
)
|
|
/*++
|
|
|
|
|
|
Routine Description:
|
|
|
|
Verifies that the left hand side (LHS) byte count and the
|
|
right hand side (RHS) byte count in the given floor are accurate
|
|
with respect to the floor start and size (i.e. jumping from the LHS
|
|
we go to the right hand side, and from there, to the end of the floor
|
|
without walking off the end).
|
|
|
|
Arguments:
|
|
|
|
FloorStart - the start of the current floor.
|
|
|
|
UpperBound - pointer to first invalid byte after the buffer.
|
|
|
|
FloorNum - the number of the floor. Used for debugging only
|
|
|
|
Return Value:
|
|
|
|
The position of the next floor, or NULL if the floor fails the check.
|
|
|
|
--*/
|
|
{
|
|
USHORT LHSBytes, RHSBytes;
|
|
|
|
if (FloorStart + 2 >= UpperBound)
|
|
return NULL;
|
|
|
|
LHSBytes = *(unsigned short UNALIGNED *)FloorStart;
|
|
if (FloorStart + (ULONG)LHSBytes + 4 >= UpperBound) // the LHSBytes counter itself is 2 bytes, and we
|
|
{ // must provide at least 2 bytes for the RHSBytes
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("RPC: TowerVerify(): LHS of Tower floor %d "
|
|
"greater than equal to FloorSize\n", FloorNum);
|
|
#endif // DEBUGRPC
|
|
return NULL;
|
|
}
|
|
|
|
FloorStart += LHSBytes + 2;
|
|
RHSBytes = *(unsigned short UNALIGNED *)FloorStart;
|
|
if (FloorStart + (ULONG)RHSBytes + 2 > UpperBound) // the RHSBytes counter itself is 2 bytes
|
|
{
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("RPC: TowerVerify(): RHS of Tower floor %d "
|
|
"greater than equal to FloorSize\n", FloorNum);
|
|
#endif // DEBUGRPC
|
|
return NULL;
|
|
}
|
|
|
|
return FloorStart + RHSBytes + 2;
|
|
}
|
|
|
|
RPC_STATUS
|
|
ExtractStringFromUntrustedPacket (
|
|
IN BYTE *UpperBound,
|
|
IN ULONG ClaimedStringLength,
|
|
IN char *StringStart,
|
|
OUT char **ExtractedString
|
|
)
|
|
/*++
|
|
|
|
|
|
Routine Description:
|
|
|
|
Extracts a string from untrusted packet. Verifies
|
|
string boundaries, reasonable length (at least one character
|
|
and no more than 1000), and null termination.
|
|
|
|
Arguments:
|
|
|
|
UpperBound - the first invalid byte after the end of the buffer.
|
|
|
|
ClaimedStringLength - the string length that the packet claims.
|
|
|
|
StringStart - the alleged start of the string - untrusted.
|
|
|
|
ExtractedString - the extracted string. Must be freed with delete. Undefined
|
|
on failure.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK, RPC_S_OUT_OF_MEMORY or EP_S_CANT_PERFORM_OP
|
|
|
|
--*/
|
|
{
|
|
char *NewString;
|
|
|
|
if ((ClaimedStringLength < 2) || (ClaimedStringLength > 1000))
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
if (StringStart + ClaimedStringLength > (char *)UpperBound)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
// the claimed string length includes the terminating NULL
|
|
if (StringStart[ClaimedStringLength - 1] != '\0')
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
NewString = new char [ClaimedStringLength];
|
|
if (NewString == NULL)
|
|
return RPC_S_OUT_OF_MEMORY;
|
|
|
|
RpcpMemoryCopy(NewString, StringStart, ClaimedStringLength);
|
|
*ExtractedString = NewString;
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
LrpcTowerConstruct(
|
|
IN char PAPI * Endpoint,
|
|
OUT unsigned short PAPI UNALIGNED * Floors,
|
|
OUT unsigned long PAPI UNALIGNED * ByteCount,
|
|
OUT unsigned char PAPI * UNALIGNED PAPI * Tower
|
|
)
|
|
{
|
|
unsigned long TowerSize;
|
|
FLOOR_234 UNALIGNED *Floor;
|
|
|
|
int EndpointLength;
|
|
|
|
*Floors = NP_TOWERS_LRPC;
|
|
if ((Endpoint == NULL) || (*Endpoint == '\0'))
|
|
{
|
|
EndpointLength = 0;
|
|
}
|
|
else
|
|
{
|
|
EndpointLength = RpcpStringLengthA(Endpoint) + 1;
|
|
}
|
|
|
|
if (EndpointLength == 0)
|
|
TowerSize = 2;
|
|
else
|
|
TowerSize = EndpointLength;
|
|
|
|
TowerSize += sizeof(FLOOR_234) - 2;
|
|
|
|
*ByteCount = TowerSize;
|
|
if ((*Tower = (unsigned char *)I_RpcAllocate(TowerSize)) == NULL)
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
Floor = (PFLOOR_234) *Tower;
|
|
|
|
Floor->ProtocolIdByteCount = 1;
|
|
Floor->FloorId = (unsigned char)(NP_TRANSPORTID_LRPC & 0xFF);
|
|
if (EndpointLength)
|
|
{
|
|
Floor->AddressByteCount = (unsigned short)EndpointLength;
|
|
RpcpMemoryCopy((char PAPI *)&Floor->Data[0], Endpoint,
|
|
EndpointLength);
|
|
}
|
|
else
|
|
{
|
|
Floor->AddressByteCount = 2;
|
|
Floor->Data[0] = 0;
|
|
}
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
LrpcTowerExplode(
|
|
IN PFLOOR_234 Floor34,
|
|
IN BYTE *UpperBound,
|
|
IN ULONG RemainingFloors,
|
|
OUT char ** Protseq, OPTIONAL
|
|
OUT char ** Endpoint, OPTIONAL
|
|
OUT char ** NetworkAddress OPTIONAL
|
|
)
|
|
{
|
|
BYTE *CurrentPosition;
|
|
BYTE *NextFloor;
|
|
RPC_STATUS RpcStatus;
|
|
ULONG EndpointLength;
|
|
|
|
// Initialize all our OUT pointers so we don't end up deleting uninitialized memory
|
|
if (Protseq)
|
|
*Protseq = NULL;
|
|
|
|
if (Endpoint)
|
|
*Endpoint = NULL;
|
|
|
|
|
|
// we expect only one floor more
|
|
if (RemainingFloors != 1)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
if (Protseq != NULL)
|
|
{
|
|
*Protseq = new char[LrpcProtocolSequenceLength];
|
|
if (*Protseq == NULL)
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
RpcpMemoryCopy(*Protseq, "ncalrpc", LrpcProtocolSequenceLength);
|
|
}
|
|
|
|
if (Endpoint == NULL)
|
|
{
|
|
return (RPC_S_OK);
|
|
}
|
|
|
|
CurrentPosition = (BYTE *)Floor34;
|
|
// an endpoint must be at least two chars long (null terminator included).
|
|
// Since FLOOR_234 has space for 2 chars, we need to subtract one
|
|
if (CurrentPosition + sizeof(FLOOR_234) >= UpperBound)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
NextFloor = VerifyFloorLHSAndRHS (CurrentPosition,
|
|
UpperBound,
|
|
3 // FloorNum
|
|
);
|
|
|
|
if (NextFloor == NULL)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto AbortAndExit;
|
|
}
|
|
|
|
EndpointLength = Floor34->AddressByteCount;
|
|
|
|
RpcStatus = ExtractStringFromUntrustedPacket (UpperBound,
|
|
EndpointLength,
|
|
(char *)&Floor34->Data[0],
|
|
Endpoint
|
|
);
|
|
|
|
if (RpcStatus == RPC_S_OK)
|
|
return(RPC_S_OK);
|
|
else
|
|
{
|
|
// fall through to cleanup call below
|
|
}
|
|
|
|
AbortAndExit:
|
|
if (Protseq && *Protseq)
|
|
delete [] *Protseq;
|
|
|
|
if (Endpoint && *Endpoint)
|
|
delete [] *Endpoint;
|
|
|
|
return RpcStatus;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
GetProtseqAndEndpointFromFloor3(
|
|
IN PFLOOR_234 Floor,
|
|
IN BYTE *UpperBound,
|
|
IN ULONG RemainingFloors,
|
|
OUT char **Protseq, OPTIONAL
|
|
OUT char **Endpoint, OPTIONAL
|
|
OUT char **NWAddress OPTIONAL
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function extracts the Protocol Sequence and Endpoint info
|
|
from a "Lower Tower" representation
|
|
|
|
Arguments:
|
|
|
|
Floor - Pointer to Floor2 structure.
|
|
|
|
UpperBound - the first invalid byte after the end of the buffer.
|
|
|
|
RemainingFloors - the number of floors remaining.
|
|
|
|
Protseq - A pointer that will contain Protocol seq on return
|
|
The memory will be allocated by this routine and caller
|
|
will have to free this memory using delete. Undefined on
|
|
failure.
|
|
|
|
Endpoint - A pointer that will contain Endpoint on return
|
|
The memory will be allocated by this routine and caller
|
|
will have to free this memory using delete. Undefined on
|
|
failure.
|
|
|
|
NWAddress - A pointer that will contain Endpoint on return
|
|
The memory will be allocated by this routine and caller
|
|
will have to free this memory using delete. Undefined on
|
|
failure.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
RPC_S_OUT_OF_MEMORY - There is no memory to return Protseq or Endpoint string
|
|
|
|
EP_S_CANT_PERFORM_OP - Lower Tower Encoding is incorrect.
|
|
|
|
--*/
|
|
|
|
USHORT ProtocolType;
|
|
RPC_STATUS Status;
|
|
BYTE *CurrentPosition;
|
|
PFLOOR_234 Floor34;
|
|
|
|
CurrentPosition = (BYTE *)Floor;
|
|
if (CurrentPosition + sizeof(FLOOR_234) >= UpperBound)
|
|
{
|
|
return EP_S_CANT_PERFORM_OP;
|
|
}
|
|
|
|
Floor34 = (PFLOOR_234)VerifyFloorLHSAndRHS(CurrentPosition,
|
|
UpperBound,
|
|
2 // FloorNum
|
|
);
|
|
|
|
if (Floor34 == NULL)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
ProtocolType = Floor->FloorId;
|
|
|
|
if (NWAddress != 0)
|
|
{
|
|
*NWAddress = 0;
|
|
}
|
|
|
|
switch(ProtocolType)
|
|
{
|
|
|
|
case CONN_LRPC:
|
|
Status = LrpcTowerExplode(Floor34, UpperBound, RemainingFloors - 1,
|
|
Protseq, Endpoint, NWAddress);
|
|
break;
|
|
|
|
case CONNECTIONFUL:
|
|
case CONNECTIONLESS:
|
|
|
|
Status = OsfTowerExplode((BYTE *)Floor34, UpperBound, RemainingFloors - 1,
|
|
Protseq, Endpoint, NWAddress);
|
|
break;
|
|
|
|
default:
|
|
Status = EP_S_CANT_PERFORM_OP;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
TowerExplode(
|
|
IN twr_p_t Tower,
|
|
OUT RPC_IF_ID *Ifid, OPTIONAL
|
|
OUT RPC_TRANSFER_SYNTAX *XferId, OPTIONAL
|
|
OUT char **Protseq, OPTIONAL
|
|
OUT char **Endpoint, OPTIONAL
|
|
OUT char **NWAddress OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
|
|
Routine Description:
|
|
|
|
This function converts a DCE tower representation of various binding
|
|
information to binding info that is suitable to MS runtime.
|
|
Specically it returns Ifid, Xferid, Protseq and Endpoint information
|
|
encoded in the tower.
|
|
|
|
Arguments:
|
|
|
|
Tower - Tower encoding.
|
|
|
|
Ifid - A pointer to Ifid
|
|
|
|
Xferid - A pointer to Xferid
|
|
|
|
Protseq - A pointer to pointer returning Protseq
|
|
|
|
Endpoint- A pointer to pointer returning Endpoint
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
EP_S_CANT_PERFORM_OP - Error while parsing the Tower encoding
|
|
|
|
RPC_S_OUT_OF_MEMORY - There is no memory to return Protseq and Endpoint
|
|
strings.
|
|
--*/
|
|
{
|
|
PFLOOR_0OR1 Floor00;
|
|
PFLOOR_0OR1 Floor01;
|
|
PFLOOR_234 Floor234;
|
|
unsigned short FloorCount;
|
|
RPC_STATUS RpcStatus;
|
|
BYTE *UpperBound, *LowerBound;
|
|
BYTE *CurrentPosition;
|
|
|
|
if (Tower == NULL)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
//
|
|
// LowerBound points to Floor1
|
|
// UpperBound points to the byte after the last Floor
|
|
//
|
|
LowerBound = Tower->tower_octet_string + 2; // FloorCount is 2 bytes
|
|
UpperBound = Tower->tower_octet_string + Tower->tower_length;
|
|
|
|
// make sure we at least have the floor count
|
|
if (UpperBound <= LowerBound)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
// go to the floor count
|
|
CurrentPosition = Tower->tower_octet_string;
|
|
// the tower octet string immediately follows the tower_length in the IDL
|
|
// so we know it is 4 bytes aligned. No need for unaligned here.
|
|
FloorCount = *((USHORT *)CurrentPosition);
|
|
|
|
if ( FloorCount > MAX_FLOOR_COUNT
|
|
|| FloorCount < MIN_FLOOR_COUNT)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("RPC: TowerVerify(): Too many/few floors - %d\n",
|
|
FloorCount);
|
|
#endif // DEBUGRPC
|
|
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
// skip the floor count and go to the first floor
|
|
CurrentPosition += 2; // floor count is 2 bytes
|
|
|
|
if (CurrentPosition + sizeof(FLOOR_0OR1) >= UpperBound)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
Floor01 = (PFLOOR_0OR1)VerifyFloorLHSAndRHS(CurrentPosition,
|
|
UpperBound,
|
|
0 // FloorNum
|
|
);
|
|
|
|
if (Floor01 == NULL)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
Floor00 = (PFLOOR_0OR1) CurrentPosition;
|
|
|
|
//Process Floor 0 Interface Spec.
|
|
if (Ifid != NULL)
|
|
{
|
|
RpcStatus = Floor0or1ToId(Floor00, (PGENERIC_ID) Ifid);
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
}
|
|
|
|
CurrentPosition = (BYTE *)Floor01;
|
|
if (CurrentPosition + sizeof(FLOOR_0OR1) >= UpperBound)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
Floor234 = (PFLOOR_234)VerifyFloorLHSAndRHS(CurrentPosition,
|
|
UpperBound,
|
|
1 // FloorNum
|
|
);
|
|
|
|
if (Floor234 == NULL)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
//Now we point to and process Floor 1 Transfer Syntax Spec.
|
|
if (XferId != NULL)
|
|
{
|
|
RpcStatus = Floor0or1ToId(Floor01, (PGENERIC_ID) XferId);
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
RpcStatus = EP_S_CANT_PERFORM_OP;
|
|
goto CleanupAndExit;
|
|
}
|
|
}
|
|
|
|
// Now Floor234 points to Floor 2. RpcProtocol [Connect-Datagram]
|
|
|
|
// we already did 2 floors - subtract them from the count of floors
|
|
RpcStatus = GetProtseqAndEndpointFromFloor3(Floor234, UpperBound, FloorCount - 2, Protseq, Endpoint, NWAddress);
|
|
|
|
// fall through with the status
|
|
|
|
CleanupAndExit:
|
|
#if DBG
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
DbgPrint("RPCRT4: %X: TowerExplode: Failed to decrypt tower: %X\n",
|
|
GetCurrentProcessId(), RpcStatus);
|
|
}
|
|
#endif // DBG
|
|
return RpcStatus;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
TowerConstruct(
|
|
IN RPC_IF_ID PAPI * Ifid,
|
|
IN RPC_TRANSFER_SYNTAX PAPI * Xferid,
|
|
IN char PAPI * RpcProtocolSequence,
|
|
IN char PAPI * Endpoint, OPTIONAL
|
|
IN char PAPI * NWAddress, OPTIONAL
|
|
OUT twr_t PAPI * PAPI * Tower
|
|
)
|
|
/*++
|
|
|
|
|
|
Routine Description:
|
|
|
|
This function constructs a DCE tower representation from
|
|
Protseq, Endpoint, XferId and IfId
|
|
|
|
Arguments:
|
|
|
|
Ifid - A pointer to Ifid
|
|
|
|
Xferid - A pointer to Xferid
|
|
|
|
Protseq - A pointer to Protseq
|
|
|
|
Endpoint- A pointer to Endpoint
|
|
|
|
Tower - The constructed tower returmed - The memory is allocated
|
|
by the routine and caller will have to free it.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
EP_S_CANT_PERFORM_OP - Error while parsing the Tower encoding
|
|
|
|
RPC_S_OUT_OF_MEMORY - There is no memory to return the constructed
|
|
Tower.
|
|
--*/
|
|
{
|
|
|
|
unsigned short Numfloors, PAPI *FloorCnt;
|
|
twr_t PAPI * Twr;
|
|
PFLOOR_0OR1 Floor;
|
|
PFLOOR_234 Floor234, Floor234_1;
|
|
RPC_STATUS Status;
|
|
unsigned long TowerLen, ByteCount;
|
|
char PAPI * UpperTower;
|
|
unsigned short ProtocolType;
|
|
|
|
|
|
if ( RpcpStringCompareA(RpcProtocolSequence, "ncalrpc") == 0 )
|
|
{
|
|
ProtocolType = CONN_LRPC;
|
|
Status = LrpcTowerConstruct(Endpoint, &Numfloors,
|
|
&ByteCount, (unsigned char **)&UpperTower);
|
|
}
|
|
else
|
|
|
|
{
|
|
|
|
if ( (RpcProtocolSequence[0] == 'n')
|
|
&& (RpcProtocolSequence[1] == 'c')
|
|
&& (RpcProtocolSequence[2] == 'a')
|
|
&& (RpcProtocolSequence[3] == 'c')
|
|
&& (RpcProtocolSequence[4] == 'n')
|
|
&& (RpcProtocolSequence[5] == '_'))
|
|
{
|
|
ProtocolType = CONNECTIONFUL;
|
|
}
|
|
else if ( (RpcProtocolSequence[0] == 'n')
|
|
&& (RpcProtocolSequence[1] == 'c')
|
|
&& (RpcProtocolSequence[2] == 'a')
|
|
&& (RpcProtocolSequence[3] == 'd')
|
|
&& (RpcProtocolSequence[4] == 'g')
|
|
&& (RpcProtocolSequence[5] == '_'))
|
|
{
|
|
ProtocolType = CONNECTIONLESS;
|
|
}
|
|
|
|
else
|
|
{
|
|
return(RPC_S_INVALID_RPC_PROTSEQ);
|
|
}
|
|
|
|
Status = OsfTowerConstruct(
|
|
RpcProtocolSequence,
|
|
Endpoint,
|
|
NWAddress,
|
|
&Numfloors,
|
|
&ByteCount,
|
|
(unsigned char **)&UpperTower
|
|
);
|
|
}
|
|
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
return (Status);
|
|
}
|
|
|
|
TowerLen = 2 + ByteCount;
|
|
TowerLen += 2 * sizeof(FLOOR_0OR1) + sizeof(FLOOR_2) ;
|
|
|
|
if ( (*Tower = Twr = (twr_t *)I_RpcAllocate((unsigned int)TowerLen+4)) == NULL)
|
|
{
|
|
I_RpcFree(UpperTower);
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
Twr->tower_length = TowerLen;
|
|
|
|
FloorCnt = (unsigned short PAPI *)&Twr->tower_octet_string;
|
|
*FloorCnt = Numfloors;
|
|
|
|
Floor = (PFLOOR_0OR1)(FloorCnt+1);
|
|
|
|
//Floor 0 - IfUuid and IfVersion
|
|
CopyIdToFloor(Floor, (PGENERIC_ID)Ifid);
|
|
Floor++;
|
|
|
|
//Floor 1 - XferUuid and XferVersion
|
|
CopyIdToFloor(Floor, (PGENERIC_ID)Xferid);
|
|
|
|
//Floor 2
|
|
//ProtocolId = CONNECTIONFUL/CONNECTIONLESS/LRPC and Address = 0(ushort)
|
|
Floor234 = (PFLOOR_234) (Floor + 1);
|
|
Floor234->ProtocolIdByteCount = 1;
|
|
Floor234->FloorId = (byte) ProtocolType;
|
|
Floor234->Data[0] = 0x0;
|
|
Floor234->Data[1] = 0x0;
|
|
Floor234->AddressByteCount = 2;
|
|
|
|
//Floor 3,4,5.. use the tower encoded by the Transports
|
|
Floor234_1 = NEXTFLOOR(PFLOOR_234, Floor234);
|
|
|
|
RpcpMemoryCopy((char PAPI *)Floor234_1, (char PAPI *)UpperTower,
|
|
(size_t)ByteCount);
|
|
I_RpcFree(UpperTower);
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
#pragma pack()
|
|
|