743 lines
17 KiB
C++
743 lines
17 KiB
C++
|
/*++
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
#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 -
|
|||
|
|
|||
|
Return Value:
|
|||
|
EP_S_CANT_PERFORM_OP - The Encoding for the floor [0 or 1] is incorrect.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
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);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
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 char PAPI * Tower,
|
|||
|
OUT char PAPI * UNALIGNED PAPI * Protseq,
|
|||
|
OUT char PAPI * UNALIGNED PAPI * Endpoint,
|
|||
|
OUT char PAPI * UNALIGNED PAPI * NetworkAddress
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
FLOOR_234 UNALIGNED *Floor = (PFLOOR_234) Tower;
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
|
|||
|
*Endpoint = new char[Floor->AddressByteCount];
|
|||
|
if (*Endpoint == NULL)
|
|||
|
{
|
|||
|
if (Protseq != NULL)
|
|||
|
{
|
|||
|
delete (*Protseq);
|
|||
|
}
|
|||
|
return(RPC_S_OUT_OF_MEMORY);
|
|||
|
}
|
|||
|
|
|||
|
RpcpMemoryCopy(*Endpoint, (char PAPI *)&Floor->Data[0],
|
|||
|
Floor->AddressByteCount);
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
GetProtseqAndEndpointFromFloor3(
|
|||
|
IN PFLOOR_234 Floor,
|
|||
|
OUT char PAPI * PAPI * Protseq,
|
|||
|
OUT char PAPI * PAPI * Endpoint,
|
|||
|
OUT char PAPI * PAPI * NWAddress
|
|||
|
)
|
|||
|
{
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function extracts the Protocol Sequence and Endpoint info
|
|||
|
from a "Lower Tower" representation
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Floor - Pointer to Floor2 structure.
|
|||
|
|
|||
|
Protseq - A pointer that will contain Protocol seq on return
|
|||
|
The memory will be allocated by this routins and caller
|
|||
|
will have to free this memory.
|
|||
|
|
|||
|
Endpoint- A pointer that will contain Endpoint on return
|
|||
|
The memory will be allocated by this routins and caller
|
|||
|
will have to free this memory.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK
|
|||
|
|
|||
|
RPC_S_OUT_OF_MEMORY - There is no memory to return Protseq or Endpoint str.
|
|||
|
|
|||
|
EP_S_CANT_PERFORM_OP - Lower Tower Encoding is incorrect.
|
|||
|
--*/
|
|||
|
|
|||
|
unsigned short Type = Floor->FloorId, ProtocolType;
|
|||
|
RPC_STATUS Status;
|
|||
|
|
|||
|
ProtocolType = Floor->FloorId;
|
|||
|
Floor = NEXTFLOOR(PFLOOR_234, Floor);
|
|||
|
|
|||
|
if (NWAddress != 0)
|
|||
|
{
|
|||
|
*NWAddress = 0;
|
|||
|
}
|
|||
|
|
|||
|
switch(ProtocolType)
|
|||
|
{
|
|||
|
|
|||
|
case LRPC:
|
|||
|
Status = LrpcTowerExplode((char *)Floor,
|
|||
|
Protseq, Endpoint, NWAddress);
|
|||
|
break;
|
|||
|
|
|||
|
case CONNECTIONFUL:
|
|||
|
case CONNECTIONLESS:
|
|||
|
|
|||
|
Status = OsfTowerExplode((char *) Floor,
|
|||
|
Protseq, Endpoint, NWAddress);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
Status = EP_S_CANT_PERFORM_OP;
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
#define BadMacByteCount 0x0100
|
|||
|
#define TCP_TOWER_ID 0x07
|
|||
|
|
|||
|
const unsigned short MinFloor0Or1LHS = 0x13;
|
|||
|
const unsigned short MinFloor0Or1RHS = 0x2;
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS
|
|||
|
TowerVerify(
|
|||
|
IN twr_p_t Tower
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function verifies a DCE tower representation of various binding
|
|||
|
information. This is to make sure that we don't choke while trying
|
|||
|
to decode the embeded information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Tower - Tower encoding.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
See Appendix L (Protocol Tower Encoding) of "X/Open DCE: Remote Procedure
|
|||
|
Call" specification for more information on the exact layout of the
|
|||
|
tower_octet_string and the tower floors.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RPC_S_OK - Tower is valid.
|
|||
|
|
|||
|
EP_S_CANT_PERFORM_OP - Error while parsing the Tower encoding
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
RPC_STATUS status;
|
|||
|
unsigned short i;
|
|||
|
unsigned short FloorCount = 0;
|
|||
|
unsigned short cLHSBytes = 0;
|
|||
|
unsigned short cRHSBytes = 0;
|
|||
|
byte *UpperBound, *LowerBound, *pAddress, *pTemp;
|
|||
|
int fBadMacClient = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Check for NULL pointer
|
|||
|
//
|
|||
|
if (NULL == Tower)
|
|||
|
{
|
|||
|
return (EP_S_CANT_PERFORM_OP);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Do the verification within an Try-Except block. Just in case...
|
|||
|
//
|
|||
|
__try
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// We trust MIDL to give us a valid Tower structure.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// 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;
|
|||
|
|
|||
|
//
|
|||
|
// Get the floor count.
|
|||
|
//
|
|||
|
FloorCount = *((unsigned short UNALIGNED *)&Tower->tower_octet_string);
|
|||
|
|
|||
|
|
|||
|
if ( FloorCount > MAX_FLOOR_COUNT
|
|||
|
|| FloorCount == 0)
|
|||
|
{
|
|||
|
#ifdef DEBUGRPC
|
|||
|
PrintToDebugger("RPC: TowerVerify(): Too many/few floors - %d",
|
|||
|
FloorCount);
|
|||
|
#endif // DEBUGRPC
|
|||
|
|
|||
|
status = EP_S_CANT_PERFORM_OP;
|
|||
|
goto endtry;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Loop through each Floor verifying it's integrity.
|
|||
|
//
|
|||
|
pAddress = LowerBound;
|
|||
|
|
|||
|
for (i = 0; i < FloorCount; i++)
|
|||
|
{
|
|||
|
//
|
|||
|
// Verify the LHS of the Tower floor.
|
|||
|
//
|
|||
|
cLHSBytes = *(unsigned short UNALIGNED *)pAddress;
|
|||
|
|
|||
|
if (i == 3
|
|||
|
&& cLHSBytes == BadMacByteCount
|
|||
|
&& *(((char *) pAddress)+2) == TCP_TOWER_ID)
|
|||
|
{
|
|||
|
fBadMacClient = 1;
|
|||
|
}
|
|||
|
|
|||
|
if (fBadMacClient)
|
|||
|
{
|
|||
|
cLHSBytes = RpcpByteSwapShort(cLHSBytes);
|
|||
|
}
|
|||
|
|
|||
|
pAddress += (2 + cLHSBytes); // size of cLHSBytes is 2 bytes
|
|||
|
if (pAddress >= UpperBound)
|
|||
|
{
|
|||
|
#ifdef DEBUGRPC
|
|||
|
PrintToDebugger("RPC: TowerVerify(): LHS of Tower floor %d "
|
|||
|
"greater than equal to Upper bound", i);
|
|||
|
#endif // DEBUGRPC
|
|||
|
status = EP_S_CANT_PERFORM_OP;
|
|||
|
goto endtry;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Verify the RHS of the Tower floor.
|
|||
|
//
|
|||
|
if (fBadMacClient)
|
|||
|
{
|
|||
|
cRHSBytes = RpcpByteSwapShort(*(unsigned short UNALIGNED *)pAddress);
|
|||
|
}
|
|||
|
else
|
|||
|
cRHSBytes = *(unsigned short UNALIGNED *)pAddress;
|
|||
|
|
|||
|
pAddress += (2 + cRHSBytes); // size of cRHSBytes is 2 bytes
|
|||
|
//
|
|||
|
// Note, for the last Floor, here, pAddress == UpperBound. So,
|
|||
|
// we do a '>' instead of '>='.
|
|||
|
//
|
|||
|
if (pAddress > UpperBound)
|
|||
|
{
|
|||
|
#ifdef DEBUGRPC
|
|||
|
PrintToDebugger("RPC: TowerVerify(): RHS of Tower floor %d "
|
|||
|
"greater than Upper bound", i);
|
|||
|
#endif // DEBUGRPC
|
|||
|
status = EP_S_CANT_PERFORM_OP;
|
|||
|
goto endtry;
|
|||
|
}
|
|||
|
|
|||
|
// if this is floor 0 or 1, verify that we have at least
|
|||
|
// an interface/transfer syntax id in there.
|
|||
|
if ((i == 0) || (i == 1))
|
|||
|
{
|
|||
|
if ((cLHSBytes < MinFloor0Or1LHS)
|
|||
|
|| (cRHSBytes < MinFloor0Or1RHS))
|
|||
|
{
|
|||
|
#ifdef DEBUGRPC
|
|||
|
PrintToDebugger("RPC: TowerVerify(): Floor 0or1 LHSBytes or RHSBytes less than minumum %d, %d "
|
|||
|
"greater than Upper bound", cLHSBytes, cRHSBytes);
|
|||
|
#endif // DEBUGRPC
|
|||
|
status = EP_S_CANT_PERFORM_OP;
|
|||
|
goto endtry;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} // for ()
|
|||
|
|
|||
|
//
|
|||
|
// Tower looks good, as far as we can tell
|
|||
|
//
|
|||
|
status = RPC_S_OK;
|
|||
|
|
|||
|
//
|
|||
|
// It's much better *not* to return from within the __try block.
|
|||
|
// (saves thousands of instructions)
|
|||
|
//
|
|||
|
endtry:
|
|||
|
|
|||
|
#if 1
|
|||
|
//
|
|||
|
// The compiler needs at least one statement between the label and the end of the block, I guess.
|
|||
|
// Luckily a null statement is sufficient.
|
|||
|
//
|
|||
|
;
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
__except( ( GetExceptionCode() == STATUS_ACCESS_VIOLATION )
|
|||
|
|| ( GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT ) )
|
|||
|
{
|
|||
|
|
|||
|
#ifdef DEBUGRPC
|
|||
|
PrintToDebugger("RPC: TowerVerify() generated an exception 0x%x",
|
|||
|
RpcExceptionCode());
|
|||
|
#endif // DEBUGRPC
|
|||
|
|
|||
|
status = EP_S_CANT_PERFORM_OP;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
TowerExplode(
|
|||
|
IN twr_p_t Tower,
|
|||
|
OUT RPC_IF_ID PAPI * Ifid, OPTIONAL
|
|||
|
OUT RPC_TRANSFER_SYNTAX PAPI * XferId, OPTIONAL
|
|||
|
OUT char PAPI * PAPI * Protseq, OPTIONAL
|
|||
|
OUT char PAPI * PAPI * Endpoint, OPTIONAL
|
|||
|
OUT char PAPI * PAPI * 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 Floor;
|
|||
|
PFLOOR_234 Floor234;
|
|||
|
unsigned short FloorCount;
|
|||
|
RPC_STATUS err = RPC_S_OK;
|
|||
|
|
|||
|
//
|
|||
|
// Validate the Tower before proceeding...
|
|||
|
//
|
|||
|
err = TowerVerify(Tower);
|
|||
|
if (err != RPC_S_OK)
|
|||
|
{
|
|||
|
return (err);
|
|||
|
}
|
|||
|
|
|||
|
FloorCount = *((unsigned short PAPI *)&Tower->tower_octet_string);
|
|||
|
|
|||
|
Floor = (PFLOOR_0OR1)
|
|||
|
((unsigned short PAPI *)&Tower->tower_octet_string + 1);
|
|||
|
|
|||
|
//Process Floor 0 Interface Spec.
|
|||
|
if (Ifid != NULL)
|
|||
|
{
|
|||
|
err = Floor0or1ToId(Floor, (PGENERIC_ID) Ifid);
|
|||
|
}
|
|||
|
|
|||
|
Floor = NEXTFLOOR(PFLOOR_0OR1, Floor);
|
|||
|
|
|||
|
|
|||
|
//Now we point to and process Floor 1 Transfer Syntax Spec.
|
|||
|
if ((!err) && (XferId != NULL))
|
|||
|
{
|
|||
|
err = Floor0or1ToId(Floor, (PGENERIC_ID) XferId);
|
|||
|
}
|
|||
|
|
|||
|
if (err)
|
|||
|
{
|
|||
|
return(err);
|
|||
|
}
|
|||
|
|
|||
|
Floor234 = (PFLOOR_234)NEXTFLOOR(PFLOOR_0OR1, Floor);
|
|||
|
|
|||
|
//Now Floor234 points to Floor 2. RpcProtocol [Connect-Datagram]
|
|||
|
|
|||
|
err = GetProtseqAndEndpointFromFloor3(Floor234, Protseq,Endpoint,NWAddress);
|
|||
|
|
|||
|
return(err);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
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 = 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()
|
|||
|
|