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.
1747 lines
41 KiB
1747 lines
41 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dgudpc.cxx
|
|
|
|
Abstract:
|
|
|
|
This is the UDP datagram client dll.
|
|
|
|
Author:
|
|
|
|
Dave Steckler (davidst) 15-Mar-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include <sysinc.h>
|
|
|
|
#define FD_SETSIZE 1
|
|
|
|
#include <rpc.h>
|
|
#include <rpcdcep.h>
|
|
|
|
#ifdef NTENV
|
|
#include <winsock2.h>
|
|
#else
|
|
#include <winsock.h>
|
|
#endif
|
|
|
|
#ifdef NTENV
|
|
#include <tdi.h>
|
|
#include <afd.h>
|
|
#endif
|
|
|
|
#include <wsipx.h>
|
|
#include <wsnwlink.h>
|
|
#include "nsphack.h"
|
|
|
|
#include <rpctran.h>
|
|
#include <rpcerrp.h>
|
|
#include <stdlib.h>
|
|
#include "common.h"
|
|
|
|
|
|
#define ENDPOINT_LEN 6
|
|
|
|
#ifdef IPX
|
|
#define NETADDR_LEN 22
|
|
#define MAX_HOSTNAME_LEN 22
|
|
|
|
#define ADDRESS_FAMILY AF_IPX
|
|
#define PROTOCOL NSPROTO_IPX
|
|
|
|
#else
|
|
#define ADDRESS_FAMILY AF_INET
|
|
#define PROTOCOL 0
|
|
|
|
#define MAX_HOSTNAME_LEN 32
|
|
|
|
|
|
//
|
|
// Host name won't be bigger than 15, i.e.,
|
|
// nnn.nnn.nnn.nnn
|
|
//
|
|
#define NETADDR_LEN 15
|
|
#endif
|
|
|
|
/*
|
|
These are Transport Specific ENDPOINTS and ADDRESS
|
|
Runtime has allocated a chuck of memory and as far as runtime is
|
|
concerned this is opaque data that transport uses in transport
|
|
specific way!
|
|
*/
|
|
|
|
typedef struct {
|
|
int Socket;
|
|
#ifdef NTENV
|
|
union
|
|
{
|
|
HANDLE hIoEvent;
|
|
fd_set Set;
|
|
};
|
|
#else
|
|
fd_set Set;
|
|
#endif
|
|
} DG_UDP_ENDPOINT;
|
|
|
|
typedef DG_UDP_ENDPOINT * PDG_UDP_ENDPOINT;
|
|
|
|
typedef struct {
|
|
#ifdef IPX
|
|
SOCKADDR_IPX ServerAddress;
|
|
#else
|
|
SOCKADDR_IN ServerAddress;
|
|
#endif
|
|
BOOL ServerLookupFailed;
|
|
} DG_UDP_ADDRESS;
|
|
|
|
typedef DG_UDP_ADDRESS * PDG_UDP_ADDRESS;
|
|
|
|
#define DG_UDP_TRANSPORT_VERSION 1
|
|
|
|
|
|
#ifdef IPX
|
|
#define ADDRESS_TYPE SOCKADDR_IPX
|
|
|
|
#define InitLocalAddress(Address, Socket) \
|
|
{ \
|
|
Address.sa_family = ADDRESS_FAMILY; \
|
|
Address.sa_socket = htons(Socket); \
|
|
memset(&Address.sa_netnum, 0, 10); \
|
|
}
|
|
#else
|
|
#define ADDRESS_TYPE SOCKADDR_IN
|
|
|
|
#define InitLocalAddress(Address, Socket) \
|
|
{ \
|
|
Address.sin_family = ADDRESS_FAMILY; \
|
|
Address.sin_addr.s_addr = INADDR_ANY; \
|
|
Address.sin_port = htons((unsigned short) Socket); \
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef NTENV
|
|
|
|
#ifdef IPX
|
|
|
|
#define RAW_ADDRESS_SIZE sizeof(TA_IPX_ADDRESS)
|
|
|
|
#define RAW_ADDRESS_TYPE TA_IPX_ADDRESS
|
|
|
|
#define InitRawAddress(RawAddress, SockAddr) \
|
|
RawAddress.TAAddressCount = 1; \
|
|
RawAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IPX; \
|
|
RawAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IPX; \
|
|
memcpy(&RawAddress.Address[0].Address[0].NetworkAddress, \
|
|
SockAddr->sa_netnum, 4); \
|
|
memcpy(&RawAddress.Address[0].Address[0].NodeAddress, \
|
|
SockAddr->sa_nodenum, 6); \
|
|
RawAddress.Address[0].Address[0].Socket = SockAddr->sa_socket;
|
|
|
|
#else
|
|
|
|
#define RAW_ADDRESS_SIZE sizeof(TA_IP_ADDRESS)
|
|
|
|
#define RAW_ADDRESS_TYPE TA_IP_ADDRESS
|
|
|
|
#define InitRawAddress(RawAddress, SockAddr) \
|
|
RawAddress.TAAddressCount = 1; \
|
|
RawAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; \
|
|
RawAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP; \
|
|
RawAddress.Address[0].Address[0].sin_port = SockAddr->sin_port; \
|
|
RawAddress.Address[0].Address[0].in_addr = SockAddr->sin_addr.s_addr; \
|
|
memset(RawAddress.Address[0].Address[0].sin_zero, 0, 8);
|
|
|
|
#endif // IPX
|
|
#endif // NTENV
|
|
|
|
#pragma pack(1)
|
|
|
|
#ifdef IPX
|
|
#define TRANSPORTID 0x0e
|
|
#define TRANSPORTHOSTID 0x0d
|
|
#define TOWERFLOORS 5
|
|
/*Endpoint = 2 bytes, HostId = 10 bytes*/
|
|
#define TOWEREPSIZE 10
|
|
#define TOWERSIZE (TOWEREPSIZE+2)
|
|
#define PROTSEQ "ncadg_ipx"
|
|
#define ENDPOINT_MAPPER_EP "34280"
|
|
#define MAX_ENDPOINT_SIZE 8
|
|
#else
|
|
#define TRANSPORTID 0x08
|
|
#define TRANSPORTHOSTID 0x09
|
|
#define TOWERFLOORS 5
|
|
/*Endpoint = 2 bytes, HostId = 4 bytes*/
|
|
#define TOWEREPSIZE 4
|
|
#define TOWERSIZE (TOWEREPSIZE+2)
|
|
#define PROTSEQ "ncadg_ip_udp"
|
|
#define ENDPOINT_MAPPER_EP "135"
|
|
#define MAX_ENDPOINT_SIZE 6
|
|
#endif
|
|
|
|
|
|
typedef struct _FLOOR_234 {
|
|
unsigned short ProtocolIdByteCount;
|
|
unsigned char FloorId;
|
|
unsigned short AddressByteCount;
|
|
unsigned char Data[2];
|
|
} FLOOR_234;
|
|
typedef FLOOR_234 PAPI UNALIGNED * 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))
|
|
|
|
|
|
|
|
#define ByteSwapLong(Value) \
|
|
Value = ( (((unsigned long) (Value) & 0xFF000000) >> 24) \
|
|
| (((unsigned long) (Value) & 0x00FF0000) >> 8) \
|
|
| (((unsigned long) (Value) & 0x0000FF00) << 8) \
|
|
| (((unsigned long) (Value) & 0x000000FF) << 24))
|
|
|
|
#define ByteSwapShort(Value) \
|
|
Value = ( (((unsigned short) (Value) & 0x00FF) << 8) \
|
|
| (((unsigned short) (Value) & 0xFF00) >> 8))
|
|
|
|
|
|
/*
|
|
End of Tower Stuff!
|
|
*/
|
|
|
|
#pragma pack()
|
|
|
|
enum IP_INTERFACE_TYPE
|
|
{
|
|
IT_UNKNOWN,
|
|
IT_TDI,
|
|
IT_WINSOCK
|
|
};
|
|
|
|
#ifdef IPX
|
|
|
|
#define AssignLocalEndpoint IPX_AssignLocalEndpoint
|
|
#define FreeLocalEndpoint IPX_FreeLocalEndpoint
|
|
#define RegisterServerAddress IPX_RegisterServerAddress
|
|
#define DeregisterServerAddress IPX_DeregisterServerAddress
|
|
#define ClientTowerConstruct IPX_ClientTowerConstruct
|
|
#define ClientTowerExplode IPX_ClientTowerExplode
|
|
#define QueryClientEndpoint IPX_QueryClientEndpoint
|
|
#define TransportLoad IPX_TransportLoad
|
|
#define TransInfo IPX_TransInfo
|
|
|
|
#define SendPacketViaTdi IPX_SendPacketViaTdi
|
|
#define SendPacketViaWinsock IPX_SendPacketViaWinsock
|
|
#define ReceivePacketViaTdi IPX_ReceivePacketViaTdi
|
|
#define ReceivePacketViaWinsock IPX_ReceivePacketViaWinsock
|
|
|
|
#ifdef NTENV
|
|
|
|
extern DWORD
|
|
GetIpInterfaceType(
|
|
);
|
|
|
|
extern enum IP_INTERFACE_TYPE IpInterfaceType;
|
|
|
|
#endif // NTENV
|
|
|
|
#else
|
|
|
|
#define AssignLocalEndpoint UDP_AssignLocalEndpoint
|
|
#define FreeLocalEndpoint UDP_FreeLocalEndpoint
|
|
#define RegisterServerAddress UDP_RegisterServerAddress
|
|
#define DeregisterServerAddress UDP_DeregisterServerAddress
|
|
#define ClientTowerConstruct UDP_ClientTowerConstruct
|
|
#define ClientTowerExplode UDP_ClientTowerExplode
|
|
#define QueryClientEndpoint UDP_QueryClientEndpoint
|
|
#define TransportLoad UDP_TransportLoad
|
|
#define TransInfo UDP_TransInfo
|
|
|
|
#define SendPacketViaTdi UDP_SendPacketViaTdi
|
|
#define SendPacketViaWinsock UDP_SendPacketViaWinsock
|
|
#define ReceivePacketViaTdi UDP_ReceivePacketViaTdi
|
|
#define ReceivePacketViaWinsock UDP_ReceivePacketViaWinsock
|
|
|
|
#ifdef NTENV
|
|
|
|
enum IP_INTERFACE_TYPE IpInterfaceType = IT_UNKNOWN;
|
|
|
|
#endif // NTENV
|
|
|
|
#endif // IPX..else
|
|
|
|
|
|
RPC_STATUS
|
|
AssignLocalEndpoint(
|
|
IN void * Endpoint
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Ask transport for a new endpoint.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
BOOL SetSocketOptions;
|
|
int PacketType;
|
|
ADDRESS_TYPE LocalAddress;
|
|
|
|
//
|
|
// Create a socket.
|
|
//
|
|
|
|
PDG_UDP_ENDPOINT TransportEndpoint = (PDG_UDP_ENDPOINT) Endpoint;
|
|
|
|
TransportEndpoint->Socket = socket(ADDRESS_FAMILY, SOCK_DGRAM, PROTOCOL);
|
|
if (TransportEndpoint->Socket == INVALID_SOCKET)
|
|
{
|
|
return (MapStatusCode(WSAGetLastError(), RPC_S_CALL_FAILED_DNE) );
|
|
}
|
|
|
|
// Bind the socket to a local port
|
|
|
|
InitLocalAddress(LocalAddress, 0);
|
|
|
|
if ( bind(TransportEndpoint->Socket,
|
|
(SOCKADDR *)&LocalAddress,
|
|
sizeof(ADDRESS_TYPE)) == SOCKET_ERROR )
|
|
{
|
|
ASSERT(0);
|
|
closesocket(TransportEndpoint->Socket);
|
|
return(RPC_S_OUT_OF_RESOURCES);
|
|
}
|
|
|
|
#ifdef IPX
|
|
// Use packet type 4.
|
|
PacketType = 4;
|
|
if (setsockopt(
|
|
TransportEndpoint->Socket,
|
|
NSPROTO_IPX,
|
|
IPX_PTYPE,
|
|
(char *) &PacketType,
|
|
sizeof(PacketType)) != 0)
|
|
{
|
|
closesocket(TransportEndpoint->Socket);
|
|
return(RPC_S_CALL_FAILED_DNE);
|
|
}
|
|
#endif
|
|
|
|
//Enable broadcasts by default .. on this socket
|
|
//We may change this later - to do broadcasts by demand
|
|
|
|
SetSocketOptions = TRUE;
|
|
if (setsockopt(
|
|
TransportEndpoint->Socket,
|
|
SOL_SOCKET,
|
|
SO_BROADCAST,
|
|
(char *)&SetSocketOptions,
|
|
sizeof(SetSocketOptions)) != 0)
|
|
{
|
|
closesocket(TransportEndpoint->Socket);
|
|
return(RPC_S_CALL_FAILED_DNE);
|
|
}
|
|
|
|
#ifdef NTENV
|
|
if (IpInterfaceType == IT_WINSOCK)
|
|
{
|
|
SetSocketOptions = 1000L; //1 sec
|
|
if (setsockopt(
|
|
TransportEndpoint->Socket,
|
|
SOL_SOCKET,
|
|
SO_RCVTIMEO,
|
|
(char *)&SetSocketOptions,
|
|
sizeof(SetSocketOptions)) != 0)
|
|
{
|
|
closesocket(TransportEndpoint->Socket);
|
|
return(RPC_S_CALL_FAILED_DNE);
|
|
}
|
|
|
|
FD_ZERO(&(TransportEndpoint->Set));
|
|
FD_SET(TransportEndpoint->Socket, &(TransportEndpoint->Set));
|
|
}
|
|
else
|
|
{
|
|
TransportEndpoint->hIoEvent = CreateEventW(0, TRUE, FALSE, 0);
|
|
if (0 == TransportEndpoint->hIoEvent)
|
|
{
|
|
closesocket(TransportEndpoint->Socket);
|
|
return(RPC_S_OUT_OF_RESOURCES);
|
|
}
|
|
}
|
|
#else
|
|
SetSocketOptions = 1000L; //1 sec
|
|
if (setsockopt(
|
|
TransportEndpoint->Socket,
|
|
SOL_SOCKET,
|
|
SO_RCVTIMEO,
|
|
(char *)&SetSocketOptions,
|
|
sizeof(SetSocketOptions)) != 0)
|
|
{
|
|
closesocket(TransportEndpoint->Socket);
|
|
return(RPC_S_CALL_FAILED_DNE);
|
|
}
|
|
|
|
FD_ZERO(&(TransportEndpoint->Set));
|
|
FD_SET(TransportEndpoint->Socket, &(TransportEndpoint->Set));
|
|
#endif
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
FreeLocalEndpoint(
|
|
IN void * Endpoint
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Frees an endpoint
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
--*/
|
|
|
|
{
|
|
//We wont free the memory as the runtime will do that
|
|
//We just do the transport related stuff
|
|
|
|
PDG_UDP_ENDPOINT TransportEndpoint = (PDG_UDP_ENDPOINT)Endpoint;
|
|
|
|
closesocket(TransportEndpoint->Socket);
|
|
|
|
#ifdef NTENV
|
|
if (IT_TDI == IpInterfaceType)
|
|
{
|
|
CloseHandle(TransportEndpoint->hIoEvent);
|
|
}
|
|
#endif
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
ReceivePacketViaWinsock(
|
|
IN void * TransportEndpoint,
|
|
IN void * Buffer,
|
|
IN unsigned long * BufferLength,
|
|
IN unsigned long Timeout,
|
|
IN void * SenderAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a packet from the network.
|
|
|
|
Arguments:
|
|
|
|
pPack - Packet to receive into.
|
|
Timeout - Timeout in seconds.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
RPC_P_TIMEOUT
|
|
<return from WaitForSingleObject or MapStatusCode>
|
|
|
|
--*/
|
|
|
|
{
|
|
PDG_UDP_ENDPOINT Endpoint = (PDG_UDP_ENDPOINT)TransportEndpoint;
|
|
|
|
int SockStatus;
|
|
int BytesReceived;
|
|
struct timeval TimeoutVal;
|
|
int DummyLen = sizeof(struct sockaddr);
|
|
//
|
|
// Receive something on our socket.
|
|
//
|
|
|
|
//
|
|
// By default the socket we have setup will wait
|
|
// for 1 sec [default timeout] for a packet.
|
|
// If timeout is greater than 1 sec we need to force a select
|
|
// In the common case we just go and do a recvfrom and avoid the
|
|
// hit of doing a select followed by a recv
|
|
|
|
if (Timeout > 1)
|
|
{
|
|
|
|
TimeoutVal.tv_sec = Timeout;
|
|
TimeoutVal.tv_usec = 0;
|
|
|
|
//
|
|
// Wait for our socket to be receivable.
|
|
//
|
|
|
|
SockStatus = select(
|
|
1,
|
|
&(Endpoint->Set),
|
|
0,
|
|
0,
|
|
&TimeoutVal
|
|
);
|
|
|
|
if (SockStatus == 0)
|
|
{
|
|
FD_SET(Endpoint->Socket, &(Endpoint->Set));
|
|
return RPC_P_TIMEOUT;
|
|
}
|
|
#if DBG
|
|
if (SockStatus < 0)
|
|
{
|
|
PrintToDebugger("select returned %d \n", SockStatus);
|
|
}
|
|
#endif
|
|
ASSERT(FD_ISSET(Endpoint->Socket, &(Endpoint->Set)));
|
|
}
|
|
|
|
BytesReceived = recvfrom(
|
|
Endpoint->Socket,
|
|
(char *)Buffer,
|
|
*BufferLength,
|
|
0,
|
|
SenderAddress,
|
|
&DummyLen
|
|
);
|
|
|
|
//
|
|
// Did we get something?
|
|
//
|
|
|
|
if ((BytesReceived == SOCKET_ERROR) || (BytesReceived == 0))
|
|
{
|
|
return MapStatusCode(WSAGetLastError(), RPC_P_RECEIVE_FAILED);
|
|
}
|
|
|
|
*BufferLength = BytesReceived;
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
|
|
#ifdef NTENV
|
|
|
|
RPC_STATUS
|
|
ReceivePacketViaTdi(
|
|
IN void * TransportEndpoint,
|
|
IN void * Buffer,
|
|
IN unsigned long * BufferLength,
|
|
IN unsigned long Timeout,
|
|
IN void * SenderAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Receives a packet from the network.
|
|
|
|
Arguments:
|
|
|
|
pPack - Packet to receive into.
|
|
Timeout - Timeout in seconds.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
RPC_P_TIMEOUT
|
|
<return from WaitForSingleObject or MapStatusCode>
|
|
|
|
--*/
|
|
|
|
{
|
|
PDG_UDP_ENDPOINT Endpoint = (PDG_UDP_ENDPOINT)TransportEndpoint;
|
|
|
|
//
|
|
// Receive something on our socket.
|
|
//
|
|
|
|
DWORD cAddr;
|
|
IO_STATUS_BLOCK ioStatus;
|
|
AFD_RECV_DATAGRAM_INFO recvInfo;
|
|
DWORD status;
|
|
NTSTATUS NtStatus;
|
|
WSABUF buffer;
|
|
HANDLE hIoEvent;
|
|
|
|
buffer.len = *BufferLength;
|
|
buffer.buf = Buffer;
|
|
|
|
cAddr = sizeof(ADDRESS_TYPE);
|
|
|
|
recvInfo.TdiFlags = TDI_RECEIVE_NORMAL;
|
|
recvInfo.AfdFlags = 0;
|
|
recvInfo.BufferArray = &buffer;
|
|
recvInfo.BufferCount = 1;
|
|
recvInfo.Address = SenderAddress;
|
|
recvInfo.AddressLength = &cAddr;
|
|
|
|
ioStatus.Status = 0;
|
|
ioStatus.Information = 0;
|
|
|
|
NtStatus = NtDeviceIoControlFile((HANDLE)Endpoint->Socket,
|
|
Endpoint->hIoEvent,
|
|
0,
|
|
0,
|
|
&ioStatus,
|
|
IOCTL_AFD_RECEIVE_DATAGRAM,
|
|
&recvInfo,
|
|
sizeof(recvInfo),
|
|
NULL,
|
|
0);
|
|
|
|
if (NtStatus == STATUS_PENDING)
|
|
{
|
|
status = WaitForSingleObject(Endpoint->hIoEvent,
|
|
Timeout * 1000);
|
|
|
|
if (status != STATUS_WAIT_0)
|
|
{
|
|
IO_STATUS_BLOCK ioStatus2;
|
|
ASSERT(status == STATUS_TIMEOUT);
|
|
|
|
// Cancel the IO
|
|
|
|
ioStatus2.Status = STATUS_PENDING;
|
|
|
|
NtStatus = NtCancelIoFile((HANDLE)Endpoint->Socket,
|
|
&ioStatus2);
|
|
|
|
ASSERT(NtStatus != STATUS_PENDING);
|
|
ASSERT(NT_SUCCESS(NtStatus));
|
|
ASSERT(NT_SUCCESS(ioStatus2.Status));
|
|
|
|
return(RPC_P_TIMEOUT);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
if ( NtStatus == STATUS_BUFFER_OVERFLOW
|
|
|| NtStatus == STATUS_RECEIVE_PARTIAL )
|
|
{
|
|
ASSERT(ioStatus.Information == *BufferLength);
|
|
return(RPC_P_OVERSIZE_PACKET);
|
|
}
|
|
|
|
#if DBG
|
|
DbgPrint("RPC DG: Receive failed %p\n", NtStatus);
|
|
ASSERT(0);
|
|
#endif
|
|
return(RPC_S_OUT_OF_RESOURCES);
|
|
}
|
|
|
|
#if DBG
|
|
if (NtStatus != 0)
|
|
{
|
|
DbgPrint("RPC DG: Receive submitted and returned %p\n", NtStatus);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ( ioStatus.Status == STATUS_BUFFER_OVERFLOW
|
|
|| ioStatus.Status == STATUS_RECEIVE_PARTIAL )
|
|
{
|
|
ASSERT(ioStatus.Information == *BufferLength);
|
|
return(RPC_P_OVERSIZE_PACKET);
|
|
}
|
|
|
|
if (ioStatus.Status != 0)
|
|
{
|
|
#if DBG
|
|
DbgPrint("RPC DG: Recieve completed with 0x%p\n", ioStatus.Status);
|
|
ASSERT(0);
|
|
#endif
|
|
return(RPC_P_RECEIVE_FAILED);
|
|
}
|
|
|
|
ASSERT( ioStatus.Information != 0
|
|
&& ioStatus.Information <= *BufferLength);
|
|
|
|
ASSERT(cAddr <= sizeof(ADDRESS_TYPE));
|
|
|
|
*BufferLength = ioStatus.Information;
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef IPX
|
|
RPC_CHAR MaxEndpoint[] = { '6', '5', '5', '3', '5', '\0' };
|
|
#else
|
|
extern RPC_CHAR MaxEndpoint[] ;
|
|
#endif
|
|
|
|
#ifdef IPX
|
|
|
|
RPC_STATUS
|
|
RegisterServerAddress(
|
|
IN void * pClientCall,
|
|
IN RPC_CHAR * pServer,
|
|
IN RPC_CHAR * pEndpoint,
|
|
OUT void PAPI * PAPI * ppTransAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Registers a new call with the transport. This informs the transport that
|
|
data is about to be sent and received on this address to and from
|
|
the server/endpoint. This routine returns a 'transport address' through
|
|
which the sending and receiving will be accomplished.
|
|
|
|
This routine serves mainly as a psuedo-constructor for a
|
|
DG_UDP_CLIENT_TRANSPORT object, where all the real work occurs.
|
|
|
|
Arguments:
|
|
|
|
pClientCall - A pointer to the protocol's DG_CCALL object for this call.
|
|
This is defined as a 'void *' instead of a PDG_CCALL because we don't
|
|
want to have to include (and link in) all the stuff associated
|
|
with DG_CCALL (including DCE_BINDING, BINDING_HANDLE, MESSAGE_OBJECT,
|
|
etc.)
|
|
|
|
pServer - Name of the server we are talking with.
|
|
|
|
pEndpoint - Endpoint on that server.
|
|
|
|
ppTransAddress - Where to place a pointer to a new transport address
|
|
which the protocol will use to identify the socket
|
|
we are using.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
RPC_S_OUT_OF_MEMORY
|
|
<return from construction of DG_UDP_CLIENT_TRANS_ADDRESS>
|
|
|
|
--*/
|
|
|
|
{
|
|
int Endpoint;
|
|
int EndpointLength;
|
|
int i;
|
|
int length;
|
|
SOCKET dummy;
|
|
SOCKADDR_IPX dummy_address;
|
|
PDG_UDP_ADDRESS pdgAddress = (PDG_UDP_ADDRESS) *ppTransAddress ;
|
|
RPC_STATUS status;
|
|
#ifdef NTENV
|
|
UNICODE_STRING UServer;
|
|
UNICODE_STRING UEndpoint;
|
|
ANSI_STRING AServer;
|
|
ANSI_STRING AEndpoint;
|
|
NTSTATUS NtStatus;
|
|
#endif // NTENV
|
|
|
|
|
|
if (*ppTransAddress == NULL)
|
|
{
|
|
return RPC_S_OUT_OF_MEMORY;
|
|
}
|
|
|
|
pdgAddress->ServerLookupFailed = TRUE;
|
|
|
|
//
|
|
// convert the endpoint to a number.
|
|
//
|
|
|
|
EndpointLength = RpcpStringLength(pEndpoint);
|
|
|
|
if (EndpointLength > 5 ||
|
|
(EndpointLength == 5 && RpcpStringCompare(pEndpoint, MaxEndpoint) > 0))
|
|
{
|
|
return RPC_S_INVALID_ENDPOINT_FORMAT;
|
|
}
|
|
|
|
for (i=0, Endpoint=0 ; i< EndpointLength ; i++)
|
|
{
|
|
if ( ((char)pEndpoint[i] >= '0') && ((char)pEndpoint[i] <= '9'))
|
|
{
|
|
Endpoint *= 10;
|
|
Endpoint += (char)pEndpoint[i]-'0';
|
|
}
|
|
else
|
|
{
|
|
return RPC_S_INVALID_ENDPOINT_FORMAT;
|
|
}
|
|
}
|
|
|
|
// Get a socket in case my_get_address_by_name needs to look up the local
|
|
// address.
|
|
memset( &dummy_address, 0, sizeof(dummy_address) );
|
|
dummy_address.sa_family = ADDRESS_FAMILY;
|
|
dummy = socket( ADDRESS_FAMILY, SOCK_DGRAM, PROTOCOL );
|
|
if (dummy == INVALID_SOCKET)
|
|
return RPC_S_OK;
|
|
length = sizeof ( pdgAddress->ServerAddress );
|
|
if (bind( dummy, (struct sockaddr *) &dummy_address, length ) != 0)
|
|
{
|
|
closesocket(dummy);
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
// Find the address.
|
|
#ifdef NTENV
|
|
|
|
RtlInitUnicodeString(&UServer,pServer);
|
|
RtlInitUnicodeString(&UEndpoint,pEndpoint);
|
|
AServer.Buffer = NULL;
|
|
AEndpoint.Buffer = NULL;
|
|
NtStatus = RtlUnicodeStringToAnsiString(&AServer,&UServer,TRUE);
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
NtStatus = RtlUnicodeStringToAnsiString(&AEndpoint,&UEndpoint,TRUE);
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
unsigned CacheTime;
|
|
status = spx_get_host_by_name( dummy,
|
|
&pdgAddress->ServerAddress,
|
|
AServer.Buffer,
|
|
PROTOCOL,
|
|
RPC_C_BINDING_DEFAULT_TIMEOUT,
|
|
&CacheTime
|
|
);
|
|
if (status == RPC_S_OK)
|
|
pdgAddress->ServerLookupFailed = FALSE;
|
|
}
|
|
}
|
|
|
|
RtlFreeAnsiString(&AServer);
|
|
RtlFreeAnsiString(&AEndpoint);
|
|
|
|
#else // !NTENV
|
|
|
|
{
|
|
unsigned CacheTime;
|
|
status = spx_get_host_by_name( dummy,
|
|
&pdgAddress->ServerAddress,
|
|
pServer,
|
|
PROTOCOL,
|
|
RPC_C_BINDING_DEFAULT_TIMEOUT,
|
|
&CacheTime
|
|
);
|
|
if (status == RPC_S_OK)
|
|
pdgAddress->ServerLookupFailed = FALSE;
|
|
}
|
|
|
|
#endif // NTENV
|
|
closesocket( dummy );
|
|
pdgAddress->ServerAddress.sa_family = ADDRESS_FAMILY;
|
|
pdgAddress->ServerAddress.sa_socket = htons((unsigned short) Endpoint);
|
|
return RPC_S_OK;
|
|
}
|
|
#else
|
|
|
|
|
|
RPC_STATUS
|
|
RegisterServerAddress(
|
|
IN void * pClientCall,
|
|
IN RPC_CHAR * pServer,
|
|
IN RPC_CHAR * pEndpoint,
|
|
OUT void PAPI * PAPI * ppTransAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Registers a new call with the transport. This informs the transport that
|
|
data is about to be sent and received on this address to and from
|
|
the server/endpoint. This routine returns a 'transport address' through
|
|
which the sending and receiving will be accomplished.
|
|
|
|
This routine serves mainly as a psuedo-constructor for a
|
|
DG_UDP_CLIENT_TRANSPORT object, where all the real work occurs.
|
|
|
|
Arguments:
|
|
|
|
pClientCall - A pointer to the protocol's DG_CCALL object for this call.
|
|
This is defined as a 'void *' instead of a PDG_CCALL because we don't
|
|
want to have to include (and link in) all the stuff associated
|
|
with DG_CCALL (including DCE_BINDING, BINDING_HANDLE, MESSAGE_OBJECT,
|
|
etc.)
|
|
|
|
pServer - Name of the server we are talking with.
|
|
|
|
pEndpoint - Endpoint on that server.
|
|
|
|
ppTransAddress - Where to place a pointer to a new transport address
|
|
which the protocol will use to identify the socket
|
|
we are using.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
RPC_S_OUT_OF_MEMORY
|
|
<return from construction of DG_UDP_CLIENT_TRANS_ADDRESS>
|
|
|
|
--*/
|
|
|
|
{
|
|
RPC_STATUS Status;
|
|
int EndpointLength;
|
|
int ServerLength;
|
|
int i;
|
|
char * pCharServerName;
|
|
struct hostent *pHostEntry;
|
|
int Endpoint;
|
|
PDG_UDP_ADDRESS pdgAddress = (PDG_UDP_ADDRESS) *ppTransAddress ;
|
|
unsigned long HostAddr;
|
|
|
|
if (*ppTransAddress == NULL)
|
|
{
|
|
return RPC_S_OUT_OF_MEMORY;
|
|
}
|
|
|
|
pdgAddress->ServerLookupFailed = FALSE;
|
|
|
|
//
|
|
// convert the endpoint to a number.
|
|
//
|
|
EndpointLength = RpcpStringLength(pEndpoint);
|
|
|
|
if (EndpointLength > 5 ||
|
|
(EndpointLength == 5 && RpcpStringCompare(pEndpoint, MaxEndpoint) > 0))
|
|
{
|
|
return RPC_S_INVALID_ENDPOINT_FORMAT;
|
|
}
|
|
|
|
for (i=0, Endpoint=0 ; i< EndpointLength ; i++)
|
|
{
|
|
if ( ((char)pEndpoint[i] >= '0') && ((char)pEndpoint[i] <= '9'))
|
|
{
|
|
Endpoint *= 10;
|
|
Endpoint += (char)pEndpoint[i]-'0';
|
|
}
|
|
else
|
|
{
|
|
return RPC_S_INVALID_ENDPOINT_FORMAT;
|
|
}
|
|
}
|
|
|
|
if (Endpoint > 65535)
|
|
{
|
|
return (RPC_S_INVALID_ENDPOINT_FORMAT);
|
|
}
|
|
//
|
|
// Put our server name in a character array (instead of wchar)
|
|
//
|
|
|
|
if ((pServer == NULL) || (*pServer == '\0'))
|
|
{
|
|
HostAddr = LOOPBACK;
|
|
}
|
|
else
|
|
{
|
|
ServerLength = RpcpStringLength((char *)pServer);
|
|
if ( (pCharServerName = (char *) I_RpcAllocate(ServerLength+1)) == 0 )
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
|
|
for (i=0 ; i<ServerLength+1 ; i++)
|
|
{
|
|
pCharServerName[i] = (char)pServer[i];
|
|
}
|
|
|
|
HostAddr = inet_addr(pCharServerName);
|
|
if (HostAddr == -1)
|
|
{
|
|
pHostEntry = gethostbyname(pCharServerName);
|
|
if (pHostEntry == 0)
|
|
{
|
|
pdgAddress->ServerLookupFailed = TRUE;
|
|
}
|
|
else
|
|
{
|
|
HostAddr = *(unsigned long *)pHostEntry->h_addr;
|
|
}
|
|
}
|
|
|
|
I_RpcFree(pCharServerName);
|
|
}
|
|
|
|
pdgAddress->ServerAddress.sin_family = ADDRESS_FAMILY;
|
|
pdgAddress->ServerAddress.sin_port = htons((unsigned short) Endpoint);
|
|
|
|
if (pdgAddress->ServerLookupFailed == FALSE)
|
|
{
|
|
|
|
RpcpMemoryCopy((char *) &(pdgAddress->ServerAddress.sin_addr.s_addr),
|
|
(char *) &HostAddr,
|
|
sizeof(unsigned long));
|
|
}
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
RPC_STATUS
|
|
DeregisterServerAddress(
|
|
IN void * pTransAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine serves as a psuedo-destructor for a DG_UDP_CLIENT_TRANSPORT
|
|
object. It frees up a socket.
|
|
|
|
Arguments:
|
|
|
|
pTransAddress - Address to deregister.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
|
|
--*/
|
|
|
|
{
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
|
|
RPC_STATUS
|
|
SendPacketViaWinsock(
|
|
IN void * TransportEndpoint,
|
|
IN void * Buffer,
|
|
IN unsigned long BufferLength,
|
|
IN BOOL Broadcast,
|
|
IN void * TransportAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends a packet on the network through the transport address associated
|
|
with the passed packet.
|
|
|
|
Arguments:
|
|
|
|
pPack - Packet to send.
|
|
Broadcast - Whether to broadcast or not.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
<return value from MapStatusCode>
|
|
|
|
--*/
|
|
|
|
{
|
|
PDG_UDP_ADDRESS pTransAddress = (PDG_UDP_ADDRESS)TransportAddress;
|
|
int SockStatus;
|
|
SOCKET Socket = ((PDG_UDP_ENDPOINT)TransportEndpoint)->Socket;
|
|
|
|
//
|
|
// Send the data on the net.
|
|
//
|
|
|
|
if ((Broadcast == FALSE) && (pTransAddress->ServerLookupFailed == TRUE))
|
|
{
|
|
return(RPC_S_SERVER_UNAVAILABLE);
|
|
}
|
|
|
|
if (Broadcast)
|
|
{
|
|
#ifdef IPX
|
|
SOCKADDR_IPX ServerAddress;
|
|
int i;
|
|
RpcpMemoryCopy( (char *) &ServerAddress,
|
|
(char *) &pTransAddress->ServerAddress,
|
|
sizeof( ServerAddress ) );
|
|
for (i = 0; i < 6; i++)
|
|
ServerAddress.sa_nodenum[i] = (char) 0xff;
|
|
#else
|
|
struct sockaddr_in ServerAddress;
|
|
|
|
ServerAddress.sin_family = ADDRESS_FAMILY;
|
|
ServerAddress.sin_port = pTransAddress->ServerAddress.sin_port;
|
|
*((long *) &ServerAddress.sin_addr.s_addr) = INADDR_BROADCAST;
|
|
#endif
|
|
|
|
SockStatus = sendto(
|
|
Socket,
|
|
(char *)Buffer,
|
|
BufferLength,
|
|
0,
|
|
(struct sockaddr *)&ServerAddress,
|
|
sizeof(ServerAddress)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
SockStatus = sendto(
|
|
Socket,
|
|
(char *)Buffer,
|
|
BufferLength,
|
|
0,
|
|
(struct sockaddr *)&(pTransAddress->ServerAddress),
|
|
sizeof(pTransAddress->ServerAddress)
|
|
);
|
|
}
|
|
|
|
if (SockStatus == (int) BufferLength)
|
|
{
|
|
return RPC_S_OK;
|
|
}
|
|
else
|
|
{
|
|
return MapStatusCode(WSAGetLastError(), RPC_P_SEND_FAILED);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
#ifdef NTENV
|
|
|
|
RPC_STATUS
|
|
SendPacketViaTdi(
|
|
IN void * TransportEndpoint,
|
|
IN void * Buffer,
|
|
IN unsigned long BufferLength,
|
|
IN BOOL Broadcast,
|
|
IN void * TransportAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends a packet on the network through the transport address associated
|
|
with the passed packet.
|
|
|
|
Arguments:
|
|
|
|
pPack - Packet to send.
|
|
Broadcast - Whether to broadcast or not.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK
|
|
RPC_P_SEND_FAILED
|
|
|
|
--*/
|
|
|
|
{
|
|
PDG_UDP_ADDRESS pTransAddress = (PDG_UDP_ADDRESS)TransportAddress;
|
|
SOCKET Socket = ((PDG_UDP_ENDPOINT)TransportEndpoint)->Socket;
|
|
HANDLE IoEvent = ((PDG_UDP_ENDPOINT)TransportEndpoint)->hIoEvent;
|
|
//
|
|
// Send the data on the net.
|
|
//
|
|
|
|
ADDRESS_TYPE *pSockAddr = &pTransAddress->ServerAddress;
|
|
RAW_ADDRESS_TYPE rawAddress;
|
|
IO_STATUS_BLOCK ioStatus;
|
|
AFD_SEND_DATAGRAM_INFO sendInfo;
|
|
WSABUF buffer;
|
|
DWORD status;
|
|
NTSTATUS NtStatus;
|
|
|
|
if ((Broadcast == FALSE) && (pTransAddress->ServerLookupFailed == TRUE))
|
|
{
|
|
return(RPC_S_SERVER_UNAVAILABLE);
|
|
}
|
|
|
|
buffer.len = BufferLength;
|
|
buffer.buf = Buffer;
|
|
|
|
InitRawAddress(rawAddress, pSockAddr);
|
|
|
|
if (Broadcast)
|
|
{
|
|
#ifdef IPX
|
|
memset(&rawAddress.Address[0].Address[0].NodeAddress, 0xFF, 6);
|
|
#else
|
|
rawAddress.Address[0].Address[0].in_addr = INADDR_BROADCAST;
|
|
#endif
|
|
}
|
|
|
|
sendInfo.AfdFlags = 0;
|
|
sendInfo.BufferArray = &buffer;
|
|
sendInfo.BufferCount = 1;
|
|
sendInfo.TdiRequest.SendDatagramInformation = &sendInfo.TdiConnInfo;
|
|
sendInfo.TdiConnInfo.UserDataLength = 0;
|
|
sendInfo.TdiConnInfo.UserData = 0;
|
|
sendInfo.TdiConnInfo.OptionsLength = 0;
|
|
sendInfo.TdiConnInfo.Options = 0;
|
|
sendInfo.TdiConnInfo.RemoteAddressLength = RAW_ADDRESS_SIZE;
|
|
sendInfo.TdiConnInfo.RemoteAddress = &rawAddress;
|
|
|
|
ioStatus.Status = STATUS_PENDING;
|
|
ioStatus.Information = 0;
|
|
|
|
NtStatus = NtDeviceIoControlFile((HANDLE)Socket,
|
|
IoEvent,
|
|
0,
|
|
0,
|
|
&ioStatus,
|
|
IOCTL_AFD_SEND_DATAGRAM,
|
|
&sendInfo,
|
|
sizeof(sendInfo),
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
if (NtStatus == STATUS_PENDING)
|
|
{
|
|
status = WaitForSingleObject(IoEvent,
|
|
INFINITE);
|
|
|
|
// If you hit then you will probably want to add
|
|
// a call to NtCancelIoFile.
|
|
|
|
ASSERT(status == STATUS_WAIT_0);
|
|
}
|
|
else
|
|
{
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
#if DBG
|
|
DbgPrint("RPC DG: Send failed %p\n", NtStatus);
|
|
ASSERT(0);
|
|
#endif
|
|
return(RPC_P_SEND_FAILED);
|
|
}
|
|
}
|
|
|
|
if (ioStatus.Information != BufferLength)
|
|
{
|
|
#if DBG
|
|
DbgPrint("RPC DG: Send wait failed %p\n", ioStatus.Status);
|
|
ASSERT(0);
|
|
#endif
|
|
return(RPC_P_SEND_FAILED);
|
|
}
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
#endif
|
|
|
|
#pragma pack(1)
|
|
RPC_STATUS RPC_ENTRY
|
|
ClientTowerConstruct(
|
|
IN char PAPI * Endpoint,
|
|
IN char PAPI * NetworkAddress,
|
|
OUT UNALIGNED unsigned short PAPI * Floors,
|
|
OUT UNALIGNED unsigned long PAPI * ByteCount,
|
|
OUT unsigned char PAPI * UNALIGNED PAPI * Tower,
|
|
IN char PAPI * Protseq
|
|
)
|
|
{
|
|
unsigned long TowerSize;
|
|
unsigned short portnum;
|
|
UNALIGNED PFLOOR_234 Floor;
|
|
#ifdef IPX
|
|
SOCKADDR_IPX netaddr;
|
|
#else
|
|
unsigned long hostval;
|
|
#endif
|
|
|
|
/* Compute the memory size of the tower. */
|
|
*Floors = TOWERFLOORS;
|
|
TowerSize = TOWERSIZE;
|
|
TowerSize += 2*sizeof(FLOOR_234) - 4;
|
|
|
|
/* Allocate memory for the tower. */
|
|
*ByteCount = TowerSize;
|
|
if ((*Tower = (unsigned char PAPI*)I_RpcAllocate(TowerSize)) == NULL)
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
/* Put the endpoint address and transport protocol id in the first floor. */
|
|
Floor = (PFLOOR_234) *Tower;
|
|
Floor->ProtocolIdByteCount = 1;
|
|
Floor->FloorId = (unsigned char)(TRANSPORTID & 0xFF);
|
|
Floor->AddressByteCount = 2;
|
|
if (Endpoint == NULL || *Endpoint == '\0')
|
|
{
|
|
Endpoint = ENDPOINT_MAPPER_EP;
|
|
}
|
|
portnum = (unsigned short) htons ( (unsigned short) atoi (Endpoint));
|
|
memcpy((char PAPI *)&Floor->Data[0], &portnum, sizeof(portnum));
|
|
|
|
/* Put the network address and the transport host protocol id in the
|
|
second floor. */
|
|
Floor = NEXTFLOOR(PFLOOR_234, Floor);
|
|
Floor->ProtocolIdByteCount = 1;
|
|
Floor->FloorId = (unsigned char)(TRANSPORTHOSTID & 0xFF);
|
|
Floor->AddressByteCount = TOWEREPSIZE;
|
|
|
|
Floor->Data[0] = '\0';
|
|
Floor->Data[1] = '\0';
|
|
|
|
if ((NetworkAddress) && (*NetworkAddress))
|
|
{
|
|
#ifdef IPX
|
|
memset(&Floor->Data[0], 0, sizeof(netaddr.sa_netnum));
|
|
memset(&Floor->Data[4], 0, sizeof(netaddr.sa_nodenum));
|
|
#else
|
|
hostval = inet_addr((char *) NetworkAddress);
|
|
memcpy((char PAPI *)&Floor->Data[0], &hostval, sizeof(hostval));
|
|
#endif
|
|
}
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
ClientTowerExplode(
|
|
IN unsigned char PAPI * Tower,
|
|
OUT char PAPI * UNALIGNED PAPI * Protseq,
|
|
OUT char PAPI * UNALIGNED PAPI * Endpoint,
|
|
OUT char PAPI * UNALIGNED PAPI * NetworkAddress
|
|
)
|
|
{
|
|
UNALIGNED PFLOOR_234 Floor = (PFLOOR_234) Tower;
|
|
RPC_STATUS Status = RPC_S_OK;
|
|
unsigned short portnum;
|
|
UNALIGNED unsigned short *Port;
|
|
|
|
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(6); //Ports are all <64K [5 decimal dig +1]
|
|
if (*Endpoint == NULL)
|
|
{
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
if (Protseq != NULL)
|
|
{
|
|
I_RpcFree(*Protseq);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if defined(MIPS) || defined(_ALPHA_)
|
|
memcpy(&portnum, (char PAPI *)&Floor->Data[0], sizeof(portnum));
|
|
#else
|
|
Port = (unsigned short *)&Floor->Data[0];
|
|
portnum = *Port;
|
|
#endif
|
|
_itoa(ByteSwapShort(portnum), *Endpoint, 10);
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
|
|
#pragma pack()
|
|
|
|
|
|
#ifdef IPX
|
|
|
|
|
|
RPC_STATUS
|
|
QueryClientEndpoint(
|
|
IN void * pOriginalEndpoint,
|
|
OUT RPC_CHAR * pClientEndpoint
|
|
)
|
|
{
|
|
SOCKADDR_IPX * pSockAddr = (SOCKADDR_IPX *) pOriginalEndpoint;
|
|
unsigned NativeSocket = ntohs(pSockAddr->sa_socket);
|
|
char AnsiBuffer[6];
|
|
|
|
char * pAnsi = AnsiBuffer;
|
|
RPC_CHAR * pUni = pClientEndpoint;
|
|
|
|
//
|
|
// Convert endpoint to an ASCII string, and thence to Unicode.
|
|
//
|
|
_ultoa(NativeSocket, AnsiBuffer, 10);
|
|
|
|
do
|
|
{
|
|
*pUni++ = *pAnsi;
|
|
}
|
|
while ( *pAnsi++ );
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
#else
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
QueryClientEndpoint
|
|
(
|
|
IN void * pOriginalEndpoint,
|
|
OUT RPC_CHAR * pClientEndpoint
|
|
)
|
|
{
|
|
struct sockaddr_in * pSockAddr = (struct sockaddr_in *) pOriginalEndpoint;
|
|
unsigned NativeSocket = ntohs(pSockAddr->sin_port);
|
|
char AnsiBuffer[6];
|
|
|
|
char * pAnsi = AnsiBuffer;
|
|
RPC_CHAR * pUni = pClientEndpoint;
|
|
|
|
//
|
|
// Convert endpoint to an ASCII string, and thence to Unicode.
|
|
//
|
|
_ultoa(NativeSocket, AnsiBuffer, 10);
|
|
|
|
do
|
|
{
|
|
*pUni++ = *pAnsi;
|
|
}
|
|
while ( *pAnsi++ );
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
#endif
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
SetBufferLength(
|
|
IN void PAPI * Endpoint,
|
|
IN unsigned Length
|
|
);
|
|
|
|
#ifdef IPX
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
SetBufferLength(
|
|
IN void PAPI * Endpoint,
|
|
IN unsigned Length
|
|
)
|
|
{
|
|
DG_UDP_ENDPOINT * pInfo = (DG_UDP_ENDPOINT *) Endpoint;
|
|
int SockStatus;
|
|
|
|
SockStatus = setsockopt(pInfo->Socket,
|
|
SOL_SOCKET,
|
|
SO_RCVBUF,
|
|
(char *) &Length,
|
|
sizeof(Length)
|
|
);
|
|
|
|
if (SockStatus == SOCKET_ERROR)
|
|
{
|
|
return RPC_S_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return RPC_S_OK;
|
|
}
|
|
|
|
#endif // IPX
|
|
|
|
|
|
#ifdef IPX
|
|
DG_RPC_CLIENT_TRANSPORT_INFO IPX_TransInfo =
|
|
{
|
|
RPC_TRANSPORT_INTERFACE_VERSION,
|
|
TRANSPORTID,
|
|
|
|
(TRANS_CLIENT_TOWERCONSTRUCT) ClientTowerConstruct,
|
|
(TRANS_CLIENT_TOWEREXPLODE) ClientTowerExplode,
|
|
|
|
sizeof(DG_UDP_ADDRESS),
|
|
sizeof(DG_UDP_ENDPOINT),
|
|
MAX_ENDPOINT_SIZE,
|
|
0,
|
|
|
|
0,
|
|
#ifdef NTENV
|
|
0,
|
|
0,
|
|
#else
|
|
ReceivePacketViaWinsock,
|
|
SendPacketViaWinsock,
|
|
#endif
|
|
RegisterServerAddress,
|
|
DeregisterServerAddress,
|
|
AssignLocalEndpoint,
|
|
FreeLocalEndpoint,
|
|
QueryClientEndpoint,
|
|
SetBufferLength,
|
|
0, // inq buffer length
|
|
|
|
0,
|
|
0,
|
|
|
|
1024, // baseline PDU size
|
|
1464, // preferred PDU size
|
|
1464, // max PDU size
|
|
|
|
1464, // max packet size
|
|
|
|
0 // default buffer length
|
|
};
|
|
|
|
|
|
|
|
extern BOOL SpxCacheInitialized;
|
|
|
|
RPC_CLIENT_TRANSPORT_INFO PAPI *
|
|
IpxTransportLoad(
|
|
)
|
|
{
|
|
SOCKET Socket;
|
|
int ReceiveBufferSize;
|
|
int SizeofReceiveBufferSize;
|
|
|
|
Socket = socket(ADDRESS_FAMILY, SOCK_DGRAM, PROTOCOL);
|
|
if (Socket == INVALID_SOCKET)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
SizeofReceiveBufferSize = sizeof(int);
|
|
if (getsockopt(Socket, SOL_SOCKET, SO_RCVBUF, (char *) &ReceiveBufferSize, &SizeofReceiveBufferSize))
|
|
{
|
|
closesocket(Socket);
|
|
return 0;
|
|
}
|
|
|
|
IPX_TransInfo.DefaultBufferLength = ReceiveBufferSize;
|
|
|
|
closesocket(Socket);
|
|
|
|
if (FALSE == SpxCacheInitialized)
|
|
{
|
|
RPC_STATUS Status = InitializeSpxCache();
|
|
if (Status)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
SpxCacheInitialized = TRUE;
|
|
}
|
|
|
|
#ifdef NTENV
|
|
|
|
GetIpInterfaceType();
|
|
|
|
if (IT_WINSOCK == IpInterfaceType)
|
|
{
|
|
IPX_TransInfo.Send = SendPacketViaWinsock;
|
|
IPX_TransInfo.ReceivePacket = ReceivePacketViaWinsock;
|
|
}
|
|
else
|
|
{
|
|
IPX_TransInfo.Send = SendPacketViaTdi;
|
|
IPX_TransInfo.ReceivePacket = ReceivePacketViaTdi;
|
|
}
|
|
|
|
#endif
|
|
|
|
return ((RPC_CLIENT_TRANSPORT_INFO PAPI *) &IPX_TransInfo) ;
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
#ifdef NTENV
|
|
|
|
DWORD
|
|
GetIpInterfaceType(
|
|
)
|
|
{
|
|
HKEY Key;
|
|
DWORD Status, Status2;
|
|
|
|
DWORD ValueType;
|
|
BOOL ValueData;
|
|
unsigned ValueLength = sizeof(ValueData);
|
|
|
|
if (IpInterfaceType != IT_UNKNOWN)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
IpInterfaceType = IT_TDI;
|
|
|
|
// open local registry
|
|
Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
"Software\\Microsoft\\Rpc",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&Key
|
|
);
|
|
if (Status)
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
// get value
|
|
Status = RegQueryValueEx( Key,
|
|
"UseWinsockForIP",
|
|
0,
|
|
&ValueType,
|
|
(LPBYTE) &ValueData,
|
|
&ValueLength
|
|
);
|
|
|
|
Status2 = RegCloseKey(Key);
|
|
ASSERT( Status2 == ERROR_SUCCESS );
|
|
|
|
if (Status)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
|
|
if (Status != ERROR_NOT_ENOUGH_MEMORY &&
|
|
Status != ERROR_CANTREAD)
|
|
{
|
|
DbgPrint("RPC UDP: error %lu from RegQueryValueEx\n", Status);
|
|
}
|
|
|
|
#endif
|
|
return Status;
|
|
}
|
|
|
|
if (ValueType != REG_DWORD)
|
|
{
|
|
//
|
|
// The user incorrectly created the entry.
|
|
//
|
|
return ERROR_CANTREAD;
|
|
}
|
|
|
|
if (ValueData)
|
|
{
|
|
IpInterfaceType = IT_WINSOCK;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
#endif // NTENV
|
|
|
|
DG_RPC_CLIENT_TRANSPORT_INFO UDP_TransInfo =
|
|
{
|
|
RPC_TRANSPORT_INTERFACE_VERSION,
|
|
TRANSPORTID,
|
|
|
|
(TRANS_CLIENT_TOWERCONSTRUCT) ClientTowerConstruct,
|
|
(TRANS_CLIENT_TOWEREXPLODE) ClientTowerExplode,
|
|
|
|
sizeof(DG_UDP_ADDRESS),
|
|
sizeof(DG_UDP_ENDPOINT),
|
|
MAX_ENDPOINT_SIZE,
|
|
0,
|
|
|
|
0,
|
|
#ifdef NTENV
|
|
0,
|
|
0,
|
|
#else
|
|
ReceivePacketViaWinsock,
|
|
SendPacketViaWinsock,
|
|
#endif
|
|
RegisterServerAddress,
|
|
DeregisterServerAddress,
|
|
AssignLocalEndpoint,
|
|
FreeLocalEndpoint,
|
|
QueryClientEndpoint,
|
|
SetBufferLength,
|
|
0, // inq buffer length
|
|
|
|
0,
|
|
0,
|
|
|
|
1024, // baseline PDU size
|
|
4096, // preferred PDU size
|
|
65528, // max PDU size
|
|
|
|
1472, // max packet size
|
|
|
|
0 // default buffer length
|
|
};
|
|
|
|
|
|
RPC_CLIENT_TRANSPORT_INFO PAPI *
|
|
UdpTransportLoad(
|
|
)
|
|
{
|
|
SOCKET Socket;
|
|
int ReceiveBufferSize;
|
|
int SizeofReceiveBufferSize;
|
|
|
|
Socket = socket(ADDRESS_FAMILY, SOCK_DGRAM, 0);
|
|
if (Socket == INVALID_SOCKET)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
SizeofReceiveBufferSize = sizeof(int);
|
|
if (getsockopt(Socket, SOL_SOCKET, SO_RCVBUF, (char *) &ReceiveBufferSize, &SizeofReceiveBufferSize))
|
|
{
|
|
closesocket(Socket);
|
|
return 0;
|
|
}
|
|
|
|
UDP_TransInfo.DefaultBufferLength = ReceiveBufferSize;
|
|
|
|
closesocket(Socket);
|
|
|
|
#ifdef NTENV
|
|
|
|
GetIpInterfaceType();
|
|
|
|
if (IT_WINSOCK == IpInterfaceType)
|
|
{
|
|
UDP_TransInfo.Send = SendPacketViaWinsock;
|
|
UDP_TransInfo.ReceivePacket = ReceivePacketViaWinsock;
|
|
}
|
|
else
|
|
{
|
|
UDP_TransInfo.Send = SendPacketViaTdi;
|
|
UDP_TransInfo.ReceivePacket = ReceivePacketViaTdi;
|
|
}
|
|
|
|
#endif
|
|
|
|
return ((RPC_CLIENT_TRANSPORT_INFO PAPI *) &UDP_TransInfo) ;
|
|
}
|
|
|
|
#endif
|
|
|
|
|