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.
838 lines
21 KiB
838 lines
21 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
|
|
Module Name:
|
|
|
|
Tower.cxx
|
|
|
|
Abstract:
|
|
|
|
Common code from building and exploding towers. Each
|
|
protocol supported by the transport interface needs
|
|
a section in this file.
|
|
|
|
Author:
|
|
|
|
Mario Goertzel [MarioGo]
|
|
|
|
Revision History:
|
|
|
|
MarioGo 11/11/1996 Bits 'n pieces
|
|
KamenM 05/02/2002 Major security and cleanup changes
|
|
|
|
--*/
|
|
|
|
#include <precomp.hxx>
|
|
#include <epmp.h>
|
|
#include <twrtypes.h>
|
|
#include <twrproto.h>
|
|
|
|
// Transport protocols defined in cotrans.hxx and dgtrans.hxx
|
|
|
|
RPC_STATUS
|
|
RPC_ENTRY
|
|
COMMON_TowerConstruct(
|
|
IN PCHAR Protseq,
|
|
IN PCHAR NetworkAddress,
|
|
IN PCHAR Endpoint,
|
|
OUT PUSHORT Floors,
|
|
OUT PULONG ByteCount,
|
|
OUT PUCHAR *Tower
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructs a OSF tower for the protocol, network address and endpoint.
|
|
|
|
Arguments:
|
|
|
|
Protseq - The protocol for the tower.
|
|
NetworkAddress - The network address to be encoded in the tower.
|
|
Endpoint - The endpoint to be encoded in the tower.
|
|
Floors - The number of twoer floors it encoded into the tower.
|
|
ByteCount - The size of the "upper-transport-specific" tower that
|
|
is encoded by this call.
|
|
Tower - The encoded "upper tower" that is encoded by this call.
|
|
This caller is responsible for freeing this memory.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
RPC_S_OUT_OF_MEMORY
|
|
RPC_S_OUT_OF_RESOURCES
|
|
RPC_S_INVALID_RPC_PROTSEQ
|
|
|
|
--*/
|
|
{
|
|
PFLOOR_234 Floor;
|
|
ADDRINFO *AddrInfo;
|
|
ADDRINFO Hint;
|
|
|
|
INT index = MapProtseq(Protseq);
|
|
|
|
if (index == 0)
|
|
{
|
|
return(RPC_S_INVALID_RPC_PROTSEQ);
|
|
}
|
|
|
|
RPC_TRANSPORT_INTERFACE pInfo = TransportTable[index].pInfo;
|
|
|
|
ASSERT(pInfo);
|
|
|
|
if (Endpoint == NULL || *Endpoint == '\0')
|
|
{
|
|
Endpoint = pInfo->WellKnownEndpoint;
|
|
}
|
|
|
|
// Currently all protocols have 5 floors. If a new protocol
|
|
// is added with < 5 floors watch out in tower explode.
|
|
|
|
*Floors = 5;
|
|
|
|
// Figure out the size of the tower
|
|
|
|
size_t addr_size;
|
|
size_t ept_size;
|
|
size_t size;
|
|
|
|
// Figure out the endpoint size
|
|
switch (index)
|
|
{
|
|
// Protocols which use port numbers (ushorts) as endpoints
|
|
case TCP:
|
|
#ifdef SPX_ON
|
|
case SPX:
|
|
#endif
|
|
case HTTP:
|
|
case UDP:
|
|
#ifdef IPX_ON
|
|
case IPX:
|
|
#endif
|
|
ept_size = 2;
|
|
break;
|
|
|
|
// Protocols which use strings as endpoints
|
|
case NMP:
|
|
#ifdef NETBIOS_ON
|
|
case NBF:
|
|
case NBT:
|
|
case NBI:
|
|
#endif
|
|
|
|
#ifdef NCADG_MQ_ON
|
|
case MSMQ:
|
|
#endif
|
|
|
|
#ifdef APPLETALK_ON
|
|
case DSP:
|
|
#endif
|
|
{
|
|
ASSERT(Endpoint && *Endpoint);
|
|
ept_size = strlen(Endpoint) + 1;
|
|
break;
|
|
}
|
|
|
|
#if DBG
|
|
default:
|
|
ASSERT(0);
|
|
return(RPC_S_INTERNAL_ERROR);
|
|
#endif
|
|
}
|
|
|
|
// Figure out the address size
|
|
switch(index)
|
|
{
|
|
// Protocols which use 4 bytes longs as the address size
|
|
case TCP:
|
|
case UDP:
|
|
case HTTP:
|
|
{
|
|
addr_size = 4;
|
|
break;
|
|
}
|
|
#ifndef SPX_IPX_OFF
|
|
// Protocols which use 10 byte (32+48 bit) address size
|
|
#ifdef SPX_ON
|
|
case SPX:
|
|
#endif
|
|
#ifdef IPX_ON
|
|
case IPX:
|
|
#endif
|
|
{
|
|
addr_size = 10;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
// Protocols which use the string as the address
|
|
case NMP:
|
|
|
|
#ifdef NETBIOS_ON
|
|
case NBF:
|
|
case NBT:
|
|
case NBI:
|
|
#endif
|
|
|
|
#ifdef NCADG_MQ_ON
|
|
case MSMQ:
|
|
#endif
|
|
|
|
#ifdef APPLETALK_ON
|
|
case DSP:
|
|
#endif
|
|
{
|
|
if ((NetworkAddress == NULL) || (*NetworkAddress== '\0'))
|
|
{
|
|
addr_size = 2;
|
|
}
|
|
else
|
|
{
|
|
addr_size = strlen(NetworkAddress) + 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
#if DBG
|
|
default:
|
|
ASSERT(0);
|
|
return(RPC_S_INTERNAL_ERROR);
|
|
#endif
|
|
}
|
|
|
|
|
|
// Compute total size.
|
|
// Note: FLOOR_234 already contains 2 bytes of data.
|
|
|
|
size = addr_size + ept_size + 2*(sizeof(FLOOR_234) - 2);
|
|
|
|
// Allocate tower
|
|
*Tower = new UCHAR[size];
|
|
if (!*Tower)
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
*ByteCount = size;
|
|
|
|
// Now fill-in the endpoint part of the tower
|
|
|
|
Floor = (PFLOOR_234)*Tower;
|
|
Floor->ProtocolIdByteCount = 1;
|
|
Floor->FloorId = (UCHAR)pInfo->TransId;
|
|
|
|
switch(index)
|
|
{
|
|
// Protocols which use big endian ushorts
|
|
case TCP:
|
|
case HTTP:
|
|
#ifdef SPX_ON
|
|
case SPX:
|
|
#endif
|
|
case UDP:
|
|
#ifdef IPX_ON
|
|
case IPX:
|
|
#endif
|
|
{
|
|
Floor->AddressByteCount = 2;
|
|
USHORT port = (USHORT) atoi(Endpoint);
|
|
port = htons(port);
|
|
memcpy((char PAPI *)&Floor->Data[0], &port, 2);
|
|
break;
|
|
}
|
|
|
|
// Protocols which use ansi strings
|
|
case NMP:
|
|
|
|
#ifdef NETBIOS_ON
|
|
case NBT:
|
|
case NBF:
|
|
case NBI:
|
|
#endif
|
|
|
|
#ifdef NCADG_MQ_ON
|
|
case MSMQ:
|
|
#endif
|
|
|
|
#ifdef APPLETALK_ON
|
|
case DSP:
|
|
#endif
|
|
{
|
|
Floor->AddressByteCount = (unsigned short) ept_size;
|
|
memcpy(&Floor->Data[0], Endpoint, ept_size);
|
|
break;
|
|
}
|
|
|
|
#if DBG
|
|
default:
|
|
ASSERT(0);
|
|
#endif
|
|
}
|
|
|
|
// Move to the next tower and fill-in the address part of the tower
|
|
|
|
Floor = NEXTFLOOR(PFLOOR_234, Floor);
|
|
Floor->ProtocolIdByteCount = 1;
|
|
Floor->FloorId = (unsigned char) pInfo->TransAddrId;
|
|
|
|
switch (index)
|
|
{
|
|
// IP protocols use 4 byte big endian IP addreses
|
|
case TCP:
|
|
case HTTP:
|
|
case UDP:
|
|
{
|
|
int err;
|
|
|
|
RpcpMemorySet(&Hint, 0, sizeof(Hint));
|
|
Hint.ai_flags = AI_NUMERICHOST;
|
|
|
|
err = getaddrinfo(NetworkAddress,
|
|
NULL,
|
|
&Hint,
|
|
&AddrInfo);
|
|
|
|
if (err)
|
|
{
|
|
// if it's not a dot address, keep it zero
|
|
RpcpMemorySet(&Floor->Data[0], 0, 4);
|
|
}
|
|
else
|
|
{
|
|
RpcpMemoryCopy(&Floor->Data[0], &(((SOCKADDR_IN *)AddrInfo->ai_addr)->sin_addr.s_addr), 4);
|
|
freeaddrinfo(AddrInfo);
|
|
}
|
|
|
|
Floor->AddressByteCount = 4;
|
|
break;
|
|
}
|
|
|
|
#ifndef SPX_IPX_OFF
|
|
// IPX protocols use little endian net (32 bit) + node (48 bit) addresses
|
|
#ifdef SPX_ON
|
|
case SPX:
|
|
#endif
|
|
#ifdef IPX_ON
|
|
case IPX:
|
|
#endif
|
|
{
|
|
Floor->AddressByteCount = 10;
|
|
memset(&Floor->Data[0], 0, 10); // Zero is fine..
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
// Protocols which use string names.
|
|
case NMP:
|
|
|
|
#ifdef NETBIOS_ON
|
|
case NBF:
|
|
case NBT:
|
|
case NBI:
|
|
#endif
|
|
|
|
#ifdef NCADG_MQ_ON
|
|
case MSMQ:
|
|
#endif
|
|
|
|
#ifdef APPLETALK_ON
|
|
case DSP:
|
|
#endif
|
|
{
|
|
if ((NetworkAddress) && (*NetworkAddress))
|
|
{
|
|
Floor->AddressByteCount = (unsigned short) addr_size;
|
|
memcpy(&Floor->Data[0], NetworkAddress, addr_size);
|
|
}
|
|
else
|
|
{
|
|
Floor->AddressByteCount = 2;
|
|
Floor->Data[0] = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
#if DBG
|
|
default:
|
|
ASSERT(0);
|
|
#endif
|
|
}
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
const INT HTTP_OLD_ADDRESS_ID = 0x20;
|
|
|
|
RPC_STATUS
|
|
FixupFloorForMac(
|
|
IN BYTE *Floor,
|
|
IN BYTE *UpperBound
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Mac clients have their LHS and RHS byte counts in big endian format.
|
|
This routine fixes the bug counts.
|
|
|
|
Arguments:
|
|
|
|
Floor - The floor to fix
|
|
UpperBound - The first invalid byte after the end of the buffer.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
EP_S_CANT_PERFORM_OP - The floor provided is invalid.
|
|
|
|
Note:
|
|
|
|
The function expects the LHSBytes value to be present.
|
|
The caller should have verified that we can read this floor:
|
|
&Floor->Data[0] < UpperBound
|
|
|
|
--*/
|
|
{
|
|
USHORT LHSBytes, RHSBytes;
|
|
BYTE *RHSBytesPosition;
|
|
|
|
// The caller must verify that we are given a full floor.
|
|
|
|
// PFLOOR_234 is defined as unaligned - no need to worry about alignment
|
|
LHSBytes = ((PFLOOR_234)Floor)->ProtocolIdByteCount;
|
|
|
|
// Swap the LHSBytes,
|
|
LHSBytes = RpcpByteSwapShort(LHSBytes);
|
|
((PFLOOR_234)Floor)->ProtocolIdByteCount = LHSBytes;
|
|
|
|
// find the RHSBytes and swap them too
|
|
RHSBytesPosition = Floor + 2 + LHSBytes;
|
|
|
|
// Make sure we can read the field.
|
|
if (RHSBytesPosition + 2 >= UpperBound)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
RHSBytes = *(USHORT UNALIGNED *)RHSBytesPosition;
|
|
RHSBytes = RpcpByteSwapShort(RHSBytes);
|
|
*(USHORT UNALIGNED *)RHSBytesPosition = RHSBytes;
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
#define BadMacByteCount 0x0100
|
|
|
|
RPC_STATUS
|
|
COMMON_TowerExplode(
|
|
IN BYTE *Tower,
|
|
IN BYTE *UpperBound,
|
|
IN ULONG RemainingFloors,
|
|
OUT PCHAR *Protseq,
|
|
OUT PCHAR *NetworkAddress,
|
|
OUT PCHAR *Endpoint
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Decodes an OSF transport "upper tower" for the runtime.
|
|
|
|
Arguments:
|
|
|
|
Tower - The encoded "upper tower" to decode
|
|
UpperBound - the first invalid byte after the end of the buffer.
|
|
RemainingFloors - the number of floors remaining
|
|
Protseq - The protseq encoded in the Tower
|
|
Does not need to be freed by the caller.
|
|
NetworkAddress - The network address encoded in the Tower
|
|
Must be freed by the caller.
|
|
Endpoint - The endpoint encoded in the Tower.
|
|
Must be freed by the caller.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
EP_S_CANT_PERFORM_OP - The tower provided is invalid.
|
|
|
|
RPC_S_INVALID_RPC_PROTSEQ
|
|
|
|
RPC_S_OUT_OF_MEMORY
|
|
|
|
--*/
|
|
{
|
|
PFLOOR_234 Floor = (PFLOOR_234)Tower;
|
|
BYTE *FloorAfterThat;
|
|
RPC_STATUS Status = RPC_S_OK;
|
|
INT Index;
|
|
BOOL NextFloorVerified;
|
|
ULONG EndpointLength;
|
|
char *NewEndpoint;
|
|
ULONG NetworkAddressLength;
|
|
char *NewNetworkAddress;
|
|
USHORT LHSBytes, RHSBytes;
|
|
unsigned short TransportId;
|
|
BOOL fBadMacClient = FALSE;
|
|
|
|
if (RemainingFloors == 0)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
// Verify that we can access the floor data.
|
|
if (&Floor->Data[0] >= UpperBound)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
PFLOOR_234 NextFloor = NEXTFLOOR(PFLOOR_234, Tower);
|
|
|
|
// The pointer to the tower is actually a pointer to the 3rd floor.
|
|
|
|
TransportId = Floor->FloorId;
|
|
|
|
// Mac clients have their LHS and RHS byte counts in big endian format.
|
|
// Detect such clients, and byte swap them.
|
|
|
|
// PFLOOR_234 is defined as unaligned - no need to worry about alignment
|
|
LHSBytes = Floor->ProtocolIdByteCount;
|
|
if ((LHSBytes == BadMacByteCount) && (TransportId == TCP_TOWER_ID))
|
|
{
|
|
fBadMacClient = TRUE;
|
|
|
|
if (FixupFloorForMac((BYTE*)Floor,
|
|
UpperBound
|
|
) != RPC_S_OK)
|
|
{
|
|
return EP_S_CANT_PERFORM_OP;
|
|
}
|
|
}
|
|
|
|
NextFloor = (PFLOOR_234)VerifyFloorLHSAndRHS (Tower,
|
|
UpperBound,
|
|
3 // FloorNum
|
|
);
|
|
|
|
if (NextFloor == NULL)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
// Find the protocol based first on the ID from this floor,
|
|
// and then the next floor. We only dereference the next
|
|
// floor if we match the ID on this floor.
|
|
|
|
NextFloorVerified = FALSE;
|
|
for (unsigned i = 1; i < cTransportTable; i++)
|
|
{
|
|
if (TransportTable[i].ProtocolTowerId == Floor->FloorId)
|
|
{
|
|
if (NextFloorVerified == FALSE)
|
|
{
|
|
if (RemainingFloors == 1)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
if ((BYTE *)NextFloor + sizeof(FLOOR_234) - 2 >= UpperBound)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
// Don't forget to byteswap NextFloor if it came from a Mac client.
|
|
if (fBadMacClient)
|
|
{
|
|
if (FixupFloorForMac((BYTE *)NextFloor,
|
|
UpperBound
|
|
) != RPC_S_OK)
|
|
{
|
|
return EP_S_CANT_PERFORM_OP;
|
|
}
|
|
}
|
|
|
|
FloorAfterThat = VerifyFloorLHSAndRHS ((BYTE *)NextFloor,
|
|
UpperBound,
|
|
4 // FloorNum
|
|
);
|
|
|
|
if (FloorAfterThat == NULL)
|
|
return EP_S_CANT_PERFORM_OP;
|
|
|
|
NextFloorVerified = TRUE;
|
|
}
|
|
|
|
if (TransportTable[i].AddressTowerId == NextFloor->FloorId)
|
|
break;
|
|
|
|
//
|
|
// The & 0x0F is needed because the legacy server code incorrectly
|
|
// cleared the high nibble before sending the address tower id
|
|
//
|
|
if ((TransportTable[i].AddressTowerId & 0x0F) == NextFloor->FloorId )
|
|
break;
|
|
|
|
// N.B. Old (Win9x/NT4) clients would send a AddressTowerId of 0x20
|
|
// (HTTP_OLD_ADDRESS_ID). We need to match this as well.
|
|
if ((Floor->FloorId == HTTP_TOWER_ID)
|
|
&& (NextFloor->FloorId == HTTP_OLD_ADDRESS_ID))
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (i == cTransportTable)
|
|
{
|
|
return(RPC_S_INVALID_RPC_PROTSEQ);
|
|
}
|
|
|
|
// the only way to break early of the loop passed through the second floor
|
|
// verification code
|
|
ASSERT(NextFloorVerified);
|
|
|
|
Index = i;
|
|
|
|
RPC_TRANSPORT_INTERFACE pInfo = TransportTable[Index].pInfo;
|
|
|
|
if (pInfo == NULL){
|
|
ASSERT(pInfo);
|
|
return EP_S_CANT_PERFORM_OP;
|
|
}
|
|
|
|
//
|
|
// Figure out the protseq
|
|
//
|
|
|
|
if (ARGUMENT_PRESENT(Protseq))
|
|
{
|
|
size_t len = RpcpStringLength(pInfo->ProtocolSequence);
|
|
*Protseq = new char[len + 1];
|
|
if (*Protseq)
|
|
{
|
|
RPC_CHAR *MySrc = (RPC_CHAR *) pInfo->ProtocolSequence;
|
|
char *MyDest = *Protseq;
|
|
|
|
while (*MyDest++ = (char) *MySrc++);
|
|
}
|
|
else
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Figure out the endpoint
|
|
//
|
|
|
|
if (ARGUMENT_PRESENT(Endpoint))
|
|
{
|
|
switch(Index)
|
|
{
|
|
// Protocols which use strings as the endpoint format.
|
|
case NMP:
|
|
|
|
#ifdef NETBIOS_ON
|
|
case NBT:
|
|
case NBI:
|
|
case NBF:
|
|
#endif
|
|
|
|
#ifdef NCADG_MQ_ON
|
|
case MSMQ:
|
|
#endif
|
|
|
|
#ifdef APPLETALK_ON
|
|
case DSP:
|
|
#endif
|
|
{
|
|
EndpointLength = Floor->AddressByteCount;
|
|
Status = ExtractStringFromUntrustedPacket (UpperBound,
|
|
EndpointLength,
|
|
(char *)&Floor->Data[0],
|
|
Endpoint
|
|
);
|
|
}
|
|
break;
|
|
|
|
// Protocols which use ushort's as the endpoint format.
|
|
case TCP:
|
|
#ifdef SPX_ON
|
|
case SPX:
|
|
#endif
|
|
case HTTP:
|
|
case UDP:
|
|
#ifdef IPX_ON
|
|
case IPX:
|
|
#endif
|
|
{
|
|
if (Tower + sizeof(FLOOR_234) >= UpperBound)
|
|
{
|
|
Status = EP_S_CANT_PERFORM_OP;
|
|
break;
|
|
}
|
|
|
|
USHORT PortNum = *(USHORT UNALIGNED *)(&Floor->Data[0]);
|
|
|
|
PortNum = RpcpByteSwapShort(PortNum); // Towers are big endian.
|
|
|
|
*Endpoint = new CHAR[6]; // 65535'\0'
|
|
if (*Endpoint)
|
|
{
|
|
RpcpItoa(PortNum, *Endpoint, 10);
|
|
Status = RPC_S_OK;
|
|
}
|
|
else
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
CORRUPTION_ASSERT(0);
|
|
Status = RPC_S_INVALID_RPC_PROTSEQ;
|
|
}
|
|
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
if (ARGUMENT_PRESENT(Protseq))
|
|
{
|
|
delete *Protseq;
|
|
*Protseq = 0;
|
|
}
|
|
return(Status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now the hard part, figure out the network address.
|
|
//
|
|
|
|
if (ARGUMENT_PRESENT(NetworkAddress))
|
|
{
|
|
Floor = NextFloor;
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
|
|
switch(Index)
|
|
{
|
|
// Protocols which use strings as their network address
|
|
case NMP:
|
|
|
|
#ifdef NETBIOS_ON
|
|
case NBF:
|
|
case NBT:
|
|
case NBI:
|
|
#endif
|
|
|
|
#ifdef NCADG_MQ_ON
|
|
case MSMQ:
|
|
#endif
|
|
|
|
#ifdef APPLETALK_ON
|
|
case DSP:
|
|
#endif
|
|
Status = ExtractStringFromUntrustedPacket (UpperBound,
|
|
Floor->AddressByteCount,
|
|
(char *)&Floor->Data[0],
|
|
NetworkAddress
|
|
);
|
|
break;
|
|
|
|
// Protocols using IP addresses
|
|
case TCP:
|
|
case HTTP:
|
|
case UDP:
|
|
{
|
|
|
|
if (Floor->AddressByteCount != 4)
|
|
{
|
|
Status = RPC_S_INVALID_RPC_PROTSEQ;
|
|
break;
|
|
}
|
|
|
|
// make sure we have all four bytes. The check
|
|
// above does not ensure that
|
|
if (&Floor->Data[3] >= UpperBound)
|
|
{
|
|
Status = RPC_S_INVALID_RPC_PROTSEQ;
|
|
break;
|
|
}
|
|
|
|
struct in_addr in;
|
|
in.S_un.S_un_b.s_b1 = Floor->Data[0];
|
|
in.S_un.S_un_b.s_b2 = Floor->Data[1];
|
|
in.S_un.S_un_b.s_b3 = Floor->Data[2];
|
|
in.S_un.S_un_b.s_b4 = Floor->Data[3];
|
|
|
|
PCHAR t = inet_ntoa(in);
|
|
if (t)
|
|
{
|
|
*NetworkAddress = new CHAR[16+1];
|
|
if (*NetworkAddress)
|
|
{
|
|
strcpy(*NetworkAddress, t);
|
|
Status = RPC_S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
Status = RPC_S_INVALID_RPC_PROTSEQ;
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
#ifndef SPX_IPX_OFF
|
|
// Protocols using IPX 80 bit addresses
|
|
#ifdef SPX_ON
|
|
case SPX:
|
|
#endif
|
|
#ifdef IPX_ON
|
|
case IPX:
|
|
#endif
|
|
{
|
|
if (Floor->AddressByteCount != 10)
|
|
{
|
|
Status = RPC_S_INVALID_RPC_PROTSEQ;
|
|
break;
|
|
}
|
|
|
|
if (&Floor->Data[9] >= UpperBound)
|
|
{
|
|
Status = RPC_S_INVALID_RPC_PROTSEQ;
|
|
break;
|
|
}
|
|
|
|
// Format: ~NNNNNNNNAAAAAAAAAAAA'\0'
|
|
// Network number (32bits) and IEEE 802 address (48bits)
|
|
|
|
*NetworkAddress = new CHAR[1 + 8 + 12 + 1];
|
|
if (*NetworkAddress)
|
|
{
|
|
PCHAR p = *NetworkAddress;
|
|
PCHAR pInput = (PCHAR) &Floor->Data[0];
|
|
*p++ = '~';
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
CHAR c = *pInput ++;
|
|
*p++ = (char) HexDigits[(c >> 4) & 0xF];
|
|
*p++ = (char) HexDigits[ c & 0xF];
|
|
}
|
|
*p = '\0';
|
|
Status = RPC_S_OK;
|
|
}
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
if (ARGUMENT_PRESENT(Endpoint))
|
|
{
|
|
delete *Endpoint;
|
|
*Endpoint = 0;
|
|
}
|
|
if (ARGUMENT_PRESENT(Protseq))
|
|
{
|
|
delete *Protseq;
|
|
*Protseq = 0;
|
|
}
|
|
return(Status);
|
|
}
|
|
}
|
|
|
|
ASSERT(Status == RPC_S_OK);
|
|
return(Status);
|
|
}
|
|
|