Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

608 lines
14 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
clntat.c
Abstract:
This is the client side loadable transport module for ADSP
Author:
Mario Goertzel (MarioGo) 02-Feb-1994 Cloned from TCP/IP & SPX module
Revision History:
25-Oct-1994 (MarioGo)
Updated to use ADSP messages
13-Nov-1994 (MarioGo)
Changed to use pretty names for endpoints
--*/
#include "sysinc.h"
#include <winsock.h>
#include <atalkwsh.h>
#include <stdlib.h>
#include "rpc.h"
#include "rpcdcep.h"
#include "rpctran.h"
#include "rpcerrp.h"
typedef struct
{
SOCKET Socket;
} CONNECTION, *PCONNECTION;
#define MAXIMUM_SEND 4096
#define NETADDR_LEN (MAX_COMPUTERNAME_LENGTH + 1)
#define HOSTNAME_LEN (MAX_COMPUTERNAME_LENGTH)
#define ADDRESS_FAMILY AF_APPLETALK
#define PROTOCOL ATPROTO_ADSP
#define SOCKET_TYPE SOCKET_STREAM
#define MAX_HOSTNAME_LEN 32
#define OBJECTTYPE_PREFIX "DceDspRpc "
#define DEFAULTZONE "*"
#define DLL_NAME "rpcltc7.dll"
#define ENDPOINT_MAPPER_EP "Endpoint Mapper"
#pragma pack(1)
#define TOWERFLOORS 5
#define PROTSEQ "ncacn_at_dsp"
#define TRANSPORTID 0x16
#define TRANSPORTHOSTID 0x18
typedef struct _FLOOR_234 {
unsigned short ProtocolIdByteCount;
unsigned char FloorId;
unsigned short AddressByteCount;
unsigned char Data[2];
} FLOOR_234, PAPI * PFLOOR_234;
#define NEXTFLOOR(t,x) (t)((unsigned char PAPI *)x +((t)x)->ProtocolIdByteCount\
+ ((t)x)->AddressByteCount\
+ sizeof(((t)x)->ProtocolIdByteCount)\
+ sizeof(((t)x)->AddressByteCount))
#pragma pack()
#if DBG
int
string_to_netaddr(
SOCKET socket,
void *netaddr,
char *host,
char *endpoint
)
{
int Length;
int BufferSize;
UCHAR ComputerName[33];
UCHAR *Zone;
UCHAR Endpoint[33];
UCHAR Buffer[sizeof(WSH_LOOKUP_NAME) + 2*sizeof(WSH_NBP_TUPLE)];
PWSH_LOOKUP_NAME pNameToLookup;
PWSH_NBP_TUPLE pTuple;
PSOCKADDR_AT pServerAddr;
RPC_STATUS Status;
// The names registered are of the format:
// Object: ComputerName (for Appletalk workstations)
// Type : DceDspRpc <Endpoint>
// Zone : * or 'ZoneName' part of ComputerName@ZoneName
if (*host == '@')
return(RPC_S_SERVER_UNAVAILABLE);
if (*host == '\0' )
{
extern RPC_STATUS GetAppleTalkName( char *);
Status = GetAppleTalkName(ComputerName);
if (Status != RPC_S_OK)
return(Status);
Zone = "*";
}
else
{
Zone = strchr(host, '@');
if (0 != Zone)
{
*Zone = '\0'; // Terminate the host name
Zone++;
}
if ( 0 == Zone
|| '\0' == *Zone)
{
Zone = "*";
}
strcpy(ComputerName, host);
}
strcpy(Endpoint, OBJECTTYPE_PREFIX);
strcat(Endpoint, endpoint);
// The PWSH_LOOKUP_NAME structure takes a "nice" name and
// returns an array of matching names (both "nice" and "x.y.z" format)
pNameToLookup = (PWSH_LOOKUP_NAME)Buffer;
Length = strlen(ComputerName);
pNameToLookup->LookupTuple.NbpName.ObjectNameLen = Length;
memcpy(pNameToLookup->LookupTuple.NbpName.ObjectName,
ComputerName,
Length);
Length = strlen(Endpoint);
pNameToLookup->LookupTuple.NbpName.TypeNameLen = Length;
memcpy(pNameToLookup->LookupTuple.NbpName.TypeName,
Endpoint,
Length);
Length = strlen(Zone);
pNameToLookup->LookupTuple.NbpName.ZoneNameLen = Length;
memcpy(pNameToLookup->LookupTuple.NbpName.ZoneName,
Zone,
Length);
BufferSize = sizeof(Buffer);
// Use getsockopt to find the address, really!?!
if (getsockopt(socket,
SOL_APPLETALK,
SO_LOOKUP_NAME,
(void *)pNameToLookup,
&BufferSize
) < 0 )
{
#ifdef DEBUGRPC
DbgPrint("Rpc on ADSP: LookupName Failed: %d \n",
WSAGetLastError());
#endif
ASSERT(WSAGetLastError() != WSAENOBUFS); // BUGBUG
return(RPC_S_SERVER_UNAVAILABLE);
}
Length = pNameToLookup->NoTuples; // Number of matching names.
pTuple = (PWSH_NBP_TUPLE)(Buffer + sizeof(WSH_LOOKUP_NAME));
while(Length)
{
BufferSize = sizeof(WSH_NBP_TUPLE);
// Confirm that the actual server still exists and has
// this name registered.
if (getsockopt(socket,
SOL_APPLETALK,
SO_CONFIRM_NAME,
(void *)pTuple,
&BufferSize
) < 0 )
{
PrintToDebugger( "%s: getsockopt failed on confirm - %d\n",
DLL_NAME, WSAGetLastError() );
return (RPC_S_SERVER_UNAVAILABLE);
}
else
{
// Found it.
pServerAddr = netaddr;
pServerAddr->sat_family = PF_APPLETALK;
pServerAddr->sat_net = pTuple->Address.Network;
pServerAddr->sat_node = pTuple->Address.Node;
pServerAddr->sat_socket = pTuple->Address.Socket;
return (RPC_S_OK);
}
// Next name, if any.
Length--;
pTuple++;
}
// No more names, server must not exist.
return(RPC_S_SERVER_UNAVAILABLE);
}
void
unicode_to_ascii ( RPC_CHAR * in, unsigned char * out )
{
unsigned char *ascii_ptr;
RPC_CHAR *unicode_ptr;
ascii_ptr = out;
unicode_ptr = in;
*ascii_ptr = (unsigned char) *unicode_ptr ;
while (1)
{
if (*ascii_ptr == 0) return;
ascii_ptr++;
unicode_ptr++;
*ascii_ptr = (unsigned char) *unicode_ptr;
}
}
#endif
RPC_STATUS RPC_ENTRY
ClientOpen (
IN PCONNECTION pConn,
IN RPC_CHAR * NetworkAddress,
IN RPC_CHAR * Endpoint,
IN RPC_CHAR * NetworkOptions,
IN RPC_CHAR * TransportAddress,
IN RPC_CHAR * RpcProtocolSequence,
IN unsigned int Timeout
)
// Open a client connection
{
#if DBG
SOCKADDR_AT server;
SOCKADDR_AT client;
unsigned char host[67]; // Server@Zone
unsigned char endpoint[33];
int status;
int length;
UNUSED(NetworkOptions);
UNUSED(TransportAddress);
UNUSED(RpcProtocolSequence);
UNUSED(Timeout);
if (wcslen(NetworkAddress) > 67)
return(RPC_S_SERVER_UNAVAILABLE);
if (wcslen(Endpoint) > 33)
return(RPC_S_INVALID_ENDPOINT_FORMAT);
unicode_to_ascii(NetworkAddress, host);
unicode_to_ascii(Endpoint, endpoint);
memset((char *)&server, 0, sizeof (server));
memset((char *)&client, 0, sizeof (client));
//
// Get a socket
//
if ((pConn->Socket = socket(ADDRESS_FAMILY, SOCK_RDM, PROTOCOL)) ==
INVALID_SOCKET)
return (RPC_S_SERVER_UNAVAILABLE);
client.sat_family = ADDRESS_FAMILY;
if ( bind(pConn->Socket,
(struct sockaddr *) &client,
sizeof (client) ) )
{
closesocket(pConn->Socket);
return(RPC_S_SERVER_UNAVAILABLE);
}
//
// Convert the network address.
//
status = string_to_netaddr(pConn->Socket, &server, host, endpoint );
if (status != 0)
{
closesocket(pConn->Socket);
return status;
}
//
// Try to connect...
//
if ( connect(pConn->Socket,
(struct sockaddr *) &server,
sizeof (server)) < 0 )
{
PrintToDebugger("%s: ClientOpen failed calling connect - %d\n",
DLL_NAME, WSAGetLastError() );
closesocket(pConn->Socket);
return (RPC_S_SERVER_UNAVAILABLE);
}
return (RPC_S_OK);
#else
return (RPC_S_CANNOT_SUPPORT) ;
#endif
}
RPC_STATUS RPC_ENTRY
ClientClose (
IN PCONNECTION pConn
)
// Close a client connection
{
#if DBG
closesocket(pConn->Socket);
return (RPC_S_OK);
#else
return (RPC_S_CANNOT_SUPPORT) ;
#endif
}
RPC_STATUS RPC_ENTRY
ClientSend (
IN PCONNECTION pConn,
IN void PAPI * Buffer,
IN unsigned int BufferLength
)
// Write a message to a connection. This operation is retried in case
// the server is "busy".
{
#if DBG
int bytes;
//
// Send a message on the socket
//
bytes = send(pConn->Socket, (char *) Buffer, (int) BufferLength,
0 /* SEND_BITS */);
if (bytes != (int) BufferLength)
{
#ifdef DEBUGRPC
PrintToDebugger("rpcltc7: Send fail: %d \n",
WSAGetLastError());
#endif
ClientClose ( pConn );
return(RPC_P_SEND_FAILED);
}
return(RPC_S_OK);
#else
return (RPC_S_CANNOT_SUPPORT) ;
#endif
}
RPC_TRANS_STATUS RPC_ENTRY
ClientRecv (
IN PCONNECTION pConn,
IN OUT void PAPI * PAPI * Buffer,
IN OUT unsigned int PAPI * BufferLength
)
// Read a message from a connection.
{
#if DBG
RPC_STATUS RpcStatus;
int bytes;
int totalBytes = 0;
int retry = 1;
int flags ;
if (*Buffer == 0)
{
*BufferLength = 512; // Min cached buffer size
RpcStatus = I_RpcTransClientReallocBuffer(pConn,
Buffer,
0,
*BufferLength);
if (RpcStatus != RPC_S_OK)
{
return(RPC_S_OUT_OF_MEMORY);
}
}
for(;;)
{
flags = 0 ;
bytes = WSARecvEx ( pConn->Socket, (char *)*Buffer + totalBytes,
*BufferLength - totalBytes, &flags);
if (bytes <= 0)
{
return(RPC_P_RECEIVE_FAILED);
}
if (flags & MSG_PARTIAL)
{
totalBytes += bytes;
*BufferLength = I_RpcTransClientMaxFrag(pConn);
RpcStatus = I_RpcTransClientReallocBuffer(pConn,
Buffer,
totalBytes,
*BufferLength);
if (RpcStatus != RPC_S_OK)
{
return(RPC_S_OUT_OF_MEMORY);
}
}
else
{
totalBytes += bytes;
*BufferLength = totalBytes;
return(RPC_S_OK);
}
} // for
ASSERT(0);
#else
return (RPC_S_CANNOT_SUPPORT) ;
#endif
}
#pragma pack(1)
RPC_STATUS RPC_ENTRY
ClientTowerConstruct(
IN char PAPI * Endpoint,
IN char PAPI * NetworkAddress,
OUT UNALIGNED short PAPI * Floors,
OUT UNALIGNED unsigned long PAPI * ByteCount,
OUT unsigned char PAPI * PAPI * Tower,
IN char PAPI * Protseq
)
{
unsigned long TowerSize;
UNALIGNED PFLOOR_234 Floor;
*Floors = TOWERFLOORS;
TowerSize = ((Endpoint == NULL) || (*Endpoint == '\0')) ?
2 : strlen(Endpoint) + 1;
TowerSize += ((NetworkAddress== NULL) || (*NetworkAddress== '\0')) ?
2 : strlen(NetworkAddress) + 1;
TowerSize += 2*sizeof(FLOOR_234) - 4;
if ((*Tower = (unsigned char PAPI*)I_RpcAllocate(*ByteCount = TowerSize))
== NULL)
{
return (RPC_S_OUT_OF_MEMORY);
}
Floor = (PFLOOR_234) *Tower;
Floor->ProtocolIdByteCount = 1;
Floor->FloorId = (unsigned char)(TRANSPORTID & 0xFF);
if ((Endpoint) && (*Endpoint))
{
memcpy((char PAPI *)&Floor->Data[0], Endpoint,
(Floor->AddressByteCount = strlen(Endpoint)+1));
}
else
{
Floor->AddressByteCount = 2;
Floor->Data[0] = 0;
}
//Onto the next floor
Floor = NEXTFLOOR(PFLOOR_234, Floor);
Floor->ProtocolIdByteCount = 1;
Floor->FloorId = (unsigned char)(TRANSPORTHOSTID & 0x0F);
if ((NetworkAddress) && (*NetworkAddress))
{
memcpy((char PAPI *)&Floor->Data[0], NetworkAddress,
(Floor->AddressByteCount = strlen(NetworkAddress) + 1));
}
else
{
Floor->AddressByteCount = 2;
Floor->Data[0] = 0;
}
return(RPC_S_OK);
}
RPC_STATUS RPC_ENTRY
ClientTowerExplode(
IN unsigned char PAPI * Tower,
OUT char PAPI * PAPI * Protseq,
OUT char PAPI * PAPI * Endpoint,
OUT char PAPI * PAPI * NetworkAddress
)
{
#if DBG
UNALIGNED PFLOOR_234 Floor = (PFLOOR_234) Tower;
RPC_STATUS Status = RPC_S_OK;
if (Protseq != NULL)
{
*Protseq = I_RpcAllocate(strlen(PROTSEQ) + 1);
if (*Protseq == NULL)
{
Status = RPC_S_OUT_OF_MEMORY;
}
else
{
memcpy(*Protseq, PROTSEQ, strlen(PROTSEQ) + 1);
}
}
if ((Endpoint == NULL) || (Status != RPC_S_OK))
{
return (Status);
}
*Endpoint = I_RpcAllocate(Floor->AddressByteCount);
if (*Endpoint == NULL)
{
Status = RPC_S_OUT_OF_MEMORY;
if (Protseq != NULL)
I_RpcFree(*Protseq);
}
else
{
memcpy(*Endpoint, (char PAPI *)&Floor->Data[0], Floor->AddressByteCount);
}
return(Status);
#else
return (RPC_S_CANNOT_SUPPORT) ;
#endif
}
#pragma pack()
RPC_CLIENT_TRANSPORT_INFO TransInfo = {
RPC_TRANSPORT_INTERFACE_VERSION,
MAXIMUM_SEND,
sizeof (CONNECTION),
ClientOpen,
ClientClose,
ClientSend,
ClientRecv,
NULL,
ClientTowerConstruct,
ClientTowerExplode,
TRANSPORTID,
0
};
RPC_CLIENT_TRANSPORT_INFO PAPI * RPC_ENTRY TransportLoad (
IN RPC_CHAR PAPI * RpcProtocolSequence
)
// Loadable transport initialization function
{
#if DBG
WSADATA WsaData;
UNUSED (RpcProtocolSequence);
if ( WSAStartup( 0x0101, &WsaData ) != NO_ERROR ) {
return NULL;
}
#endif
return(&TransInfo);
}