mirror of https://github.com/lianthony/NT4.0
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.
494 lines
10 KiB
494 lines
10 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
common.c
|
|
|
|
Abstract:
|
|
|
|
|
|
Revision History:
|
|
Mazhar Mohammed Consolidated winsock transports
|
|
|
|
Comments:
|
|
|
|
This file contains common code for RPC transport dlls using Winsock.
|
|
|
|
--*/
|
|
|
|
#include "sysinc.h"
|
|
#include <winsock.h>
|
|
#include <stdlib.h>
|
|
#include "rpc.h"
|
|
#include "rpcdcep.h"
|
|
#include "rpctran.h"
|
|
#include "rpcerrp.h"
|
|
#include "common.h"
|
|
#include "reg.h"
|
|
|
|
#define ADDRESS_FAMILY AF_NS
|
|
#define ENDPOINT_LEN 5
|
|
|
|
|
|
/* for registry lookup */
|
|
PROTOCOL_MAP ProtoToLana[MAX_LANA] = { 0};
|
|
|
|
/* number of Network cards */
|
|
int NumCards;
|
|
|
|
|
|
|
|
|
|
unsigned char chtob( unsigned char c1, unsigned char c2 )
|
|
/* Convert two hex digits (stored as ascii) into one byte. */
|
|
|
|
{
|
|
unsigned char out;
|
|
|
|
if (c1 >= '0' && c1 <= '9')
|
|
out = (c1 - '0') << 4;
|
|
else
|
|
{
|
|
if (c1 >= 'a' && c1 <= 'f')
|
|
out = (c1 - 'a' + 10) << 4;
|
|
else if (c1 >= 'A' && c1 <= 'F')
|
|
out = (c1 - 'A' + 10) << 4;
|
|
else
|
|
out = 0;
|
|
}
|
|
|
|
if (c2 >= '0' && c2 <= '9')
|
|
out |= c2 -'0';
|
|
else
|
|
{
|
|
if (c2 >= 'a' && c2 <= 'f')
|
|
out |= c2 - 'a' + 10;
|
|
else if (c2 >= 'A' && c2 <= 'F')
|
|
out |= c2 - 'A' + 10;
|
|
else
|
|
out = 0;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
|
|
int tcp_get_host_by_name(
|
|
SOCKET socket,
|
|
void *netaddr,
|
|
char *host)
|
|
|
|
{
|
|
UNALIGNED struct sockaddr_in *server = netaddr;
|
|
UNALIGNED struct hostent *phostentry;
|
|
unsigned long host_addr;
|
|
|
|
if (*host == '\0')
|
|
{
|
|
// An empty hostname means to RPC to the local machine
|
|
host_addr = LOOPBACK;
|
|
}
|
|
else
|
|
{
|
|
// Assume a numeric address
|
|
host_addr = inet_addr(host);
|
|
if (host_addr == -1)
|
|
{
|
|
// Try a friendly name
|
|
|
|
phostentry = gethostbyname(host);
|
|
|
|
if (phostentry == (struct hostent *)NULL)
|
|
{
|
|
return (RPC_S_SERVER_UNAVAILABLE);
|
|
}
|
|
else
|
|
{
|
|
host_addr = *(unsigned long *)phostentry->h_addr;
|
|
}
|
|
}
|
|
}
|
|
|
|
memcpy((char *) &server->sin_addr,
|
|
(unsigned char *) &host_addr,
|
|
sizeof(unsigned long));
|
|
return 0;
|
|
}
|
|
|
|
RPC_STATUS
|
|
MapStatusCode(
|
|
int SocketError,
|
|
RPC_STATUS Default
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Maps a winsock return value into a RPC_STATUS. Right now, any winsock
|
|
error is an internal error.
|
|
|
|
Arguments:
|
|
|
|
ErrorCode - Input error code.
|
|
|
|
Return Value:
|
|
|
|
mapped status code
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_STATUS Status;
|
|
|
|
switch (SocketError)
|
|
{
|
|
case 0:
|
|
{
|
|
Status = RPC_S_OK;
|
|
break;
|
|
}
|
|
|
|
case WSAETIMEDOUT:
|
|
{
|
|
Status = RPC_P_TIMEOUT;
|
|
break;
|
|
}
|
|
|
|
case WSAENOBUFS:
|
|
{
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
break;
|
|
}
|
|
|
|
case WSAEMSGSIZE:
|
|
{
|
|
Status = RPC_P_OVERSIZE_PACKET;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
#ifdef DEBUGRPC
|
|
PrintToDebugger("RPC DG: Winsock error %d\n", SocketError);
|
|
#endif
|
|
Status = Default;
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
// we need to have a common transport load module (no protocol specific ifdefs in here)
|
|
|
|
BOOL SpxCacheInitialized = FALSE;
|
|
|
|
RPC_CLIENT_TRANSPORT_INFO PAPI * RPC_ENTRY TransportLoad (
|
|
IN RPC_CHAR PAPI * RpcProtocolSequence
|
|
)
|
|
|
|
// Loadable transport initialization function
|
|
|
|
{
|
|
WSADATA WsaData;
|
|
SOCKET Socket;
|
|
static int initialized = 0 ;
|
|
int Status ;
|
|
|
|
UNUSED (RpcProtocolSequence);
|
|
|
|
if(!initialized)
|
|
{
|
|
RpcTryExcept
|
|
{
|
|
Status = WSAStartup( 0x0101, &WsaData ) ;
|
|
}
|
|
RpcExcept( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Status = ERROR_OUTOFMEMORY ;
|
|
}
|
|
RpcEndExcept
|
|
|
|
if ( Status != NO_ERROR )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef NTENV
|
|
InitialNtRegistry();
|
|
#endif
|
|
initialized = 1 ;
|
|
}
|
|
|
|
// check if the string is in UNICODE
|
|
if (RpcpStringCompare(RpcProtocolSequence, RPC_CONST_STRING("ncacn_spx")) == 0)
|
|
{
|
|
//For SPX we do this to avoid a bizzare deadlock
|
|
Socket = socket(ADDRESS_FAMILY, SOCK_STREAM, NSPROTO_SPXII);
|
|
if (Socket == INVALID_SOCKET)
|
|
{
|
|
return (NULL);
|
|
}
|
|
closesocket(Socket);
|
|
|
|
if (FALSE == SpxCacheInitialized)
|
|
{
|
|
RPC_STATUS Status = InitializeSpxCache();
|
|
if (Status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
SpxCacheInitialized = TRUE;
|
|
}
|
|
|
|
return (&SPX_TransInfo) ;
|
|
}
|
|
|
|
if (RpcpStringCompare(RpcProtocolSequence, RPC_CONST_STRING("ncacn_ip_tcp")) == 0)
|
|
{
|
|
return (&TCP_TransInfo) ;
|
|
}
|
|
|
|
#ifdef NTENV
|
|
if (RpcpStringCompare(RpcProtocolSequence, RPC_CONST_STRING("ncacn_at_dsp")) == 0)
|
|
{
|
|
return(&ADSP_TransInfo) ;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
if (RpcpStringCompare(RpcProtocolSequence, RPC_CONST_STRING("ncacn_np")) == 0)
|
|
{
|
|
return (&NP_TransInfo) ;
|
|
}
|
|
#endif
|
|
|
|
#if defined(NTENV) || defined(WIN96)
|
|
if (RpcpStringCompare(RpcProtocolSequence, RPC_CONST_STRING("ncadg_ipx")) == 0)
|
|
{
|
|
return IpxTransportLoad();
|
|
}
|
|
|
|
if (RpcpStringCompare(RpcProtocolSequence, RPC_CONST_STRING("ncadg_ip_udp")) == 0)
|
|
{
|
|
return UdpTransportLoad();
|
|
}
|
|
|
|
#ifndef WIN96
|
|
if (RpcpStringNCompare(RpcProtocolSequence, RPC_CONST_STRING("ncacn_nb"), 8) == 0)
|
|
{
|
|
return ((RPC_CLIENT_TRANSPORT_INFO PAPI *) &NB_TransInfo) ;
|
|
}
|
|
#endif // !WIN96
|
|
|
|
#endif // NTENV || WIN96
|
|
|
|
ASSERT(0) ;
|
|
|
|
return NULL ;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
InitialNtRegistry(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This information is automatically generated by NT setup and the Networks
|
|
Control Panel applet. Because it can change dynamically, we load it
|
|
all at once to achieve consistent data.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
ReturnValue:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
HKEY RegHandle;
|
|
LONG status;
|
|
int i;
|
|
char protseq[64];
|
|
DWORD protseq_len;
|
|
DWORD lana;
|
|
DWORD lana_len;
|
|
DWORD data_type;
|
|
char * LanaString ;
|
|
int LanaNum;
|
|
|
|
|
|
|
|
|
|
// Return immediately if the table is already initialized.
|
|
if (ProtocolTable[0].ProtoSeq)
|
|
{
|
|
return;
|
|
}
|
|
|
|
NumCards = 0;
|
|
|
|
// Open the registry key for RPC NetBIOS information
|
|
status = RegOpenKeyExA(RPC_REG_ROOT,
|
|
REG_NETBIOS,
|
|
0,
|
|
KEY_READ,
|
|
&RegHandle);
|
|
|
|
ASSERT(!status);
|
|
|
|
if (status)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
for (i = 0; !status && i < MAX_LANA; i++)
|
|
{
|
|
protseq_len = sizeof(protseq);
|
|
lana_len = sizeof(lana);
|
|
|
|
status = RegEnumValueA(RegHandle,
|
|
i,
|
|
protseq,
|
|
&protseq_len,
|
|
NULL,
|
|
&data_type,
|
|
(LPBYTE) &lana,
|
|
&lana_len);
|
|
|
|
if (!status && data_type == REG_DWORD && lana <= MAX_LANA)
|
|
{
|
|
ProtocolTable[i].ProtoSeq = I_RpcAllocate(protseq_len + 1);
|
|
|
|
ASSERT(ProtocolTable[i].ProtoSeq);
|
|
|
|
if (! ProtocolTable[i].ProtoSeq)
|
|
{
|
|
status = RPC_S_OUT_OF_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
strcpy(ProtocolTable[i].ProtoSeq, protseq);
|
|
ProtocolTable[i].Lana = (unsigned char) lana;
|
|
|
|
LanaString = protseq + strlen(protseq) -1;
|
|
LanaNum = atoi(LanaString);
|
|
|
|
#ifdef TONY
|
|
PrintToDebugger("RPCLTSCM: the current lana examinging is %d \n"
|
|
, LanaNum);
|
|
#endif
|
|
/* find out how many cards we have */
|
|
if(NumCards < LanaNum)
|
|
{
|
|
NumCards = LanaNum;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(status == ERROR_NO_MORE_ITEMS);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(RegHandle);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
MapProtocol(
|
|
IN RPC_CHAR *ProtoSeq,
|
|
IN int DriverNumber,
|
|
OUT PPROTOCOL_MAP *ProtocolEntry
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function maps a protocol string into a protocol map entry.
|
|
|
|
Arguments:
|
|
|
|
ProtoSeq - the protocol sequence that we want to map
|
|
|
|
DriverNumber - the logical driver number for the protocol.
|
|
|
|
ProtocolEntry - pointer to place to return the results.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK, RPC_S_OUT_OF_RESOURCES, RPC_S_INVALID_ENDPOINT_FORMAT
|
|
|
|
The output pointer is set to the corresponding entry when found.
|
|
|
|
--*/
|
|
{
|
|
long status;
|
|
char Protocol[40];
|
|
char LanaString[10];
|
|
long BufferLength = sizeof(LanaString);
|
|
int i;
|
|
|
|
// Copy the possible unicode protocol string to ascii.
|
|
|
|
for (i = 0; (Protocol[i] = (char) ProtoSeq[i]) && i < sizeof(Protocol);
|
|
i++) ;
|
|
|
|
// Add the logical driver number to the protocol string. This
|
|
// allows multiple drivers (net cards) to be attached to the same
|
|
// logical protocol.
|
|
|
|
Protocol[i] = (char) ('0' + DriverNumber);
|
|
Protocol[i+1] = 0;
|
|
|
|
// First look in the proto sequences that we have already mapped.
|
|
|
|
for (i = 0; ProtocolTable[i].ProtoSeq && i < MAX_LANA; i++)
|
|
{
|
|
// If found, set the output pointer.
|
|
|
|
if (strcmp(ProtocolTable[i].ProtoSeq, Protocol) == 0)
|
|
{
|
|
*ProtocolEntry = &ProtocolTable[i];
|
|
return(RPC_S_OK);
|
|
}
|
|
}
|
|
|
|
return(RPC_S_PROTSEQ_NOT_FOUND);
|
|
|
|
}
|
|
|
|
|