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.
 
 
 
 
 
 

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);
}