|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
mssndrcv.c
Abstract:
This module implements all functions related to transmitting and recieving SMB's for mailslot related operations.
Revision History:
Balan Sethu Raman [SethuR] 6-June-1995
Notes:
--*/
#include "precomp.h"
#pragma hdrstop
#include "hostannc.h"
#include "mssndrcv.h"
// Forward references of functions ....
//
NTSTATUS MsUninitialize(PVOID pTransport);
NTSTATUS MsInitializeExchange( PSMBCE_SERVER_TRANSPORT pTransport, PSMB_EXCHANGE pExchange);
NTSTATUS MsTranceive( PSMBCE_SERVER_TRANSPORT pTransport, PSMBCEDB_SERVER_ENTRY pServerEntry, PSMB_EXCHANGE pExchange, ULONG SendOptions, PMDL pSmbMdl, ULONG SendLength, PVOID pSendCompletionContext);
NTSTATUS MsReceive( PSMBCE_SERVER_TRANSPORT pTransport, PSMBCEDB_SERVER_ENTRY pServerEntry, PSMB_EXCHANGE pExchange);
NTSTATUS MsSend( PSMBCE_SERVER_TRANSPORT pTransport, PSMBCEDB_SERVER_ENTRY pServerEntry, ULONG SendOptions, PMDL pSmbMdl, ULONG SendLength, PVOID pSendCompletionContext);
NTSTATUS MsSendDatagram( PSMBCE_SERVER_TRANSPORT pTransport, PSMBCEDB_SERVER_ENTRY pServerEntry, ULONG SendOptions, PMDL pSmbMdl, ULONG SendLength, PVOID pSendCompletionContext);
NTSTATUS MsInitializeExchange( PSMBCE_SERVER_TRANSPORT pTransport, PSMB_EXCHANGE pExchange);
NTSTATUS MsUninitializeExchange( PSMBCE_SERVER_TRANSPORT pTransport, PSMB_EXCHANGE pExchange);
VOID MsTimerEventHandler( PVOID pTransport);
NTSTATUS MsInitiateDisconnect( PSMBCE_SERVER_TRANSPORT pServerTransport);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, MsInstantiateServerTransport)
#pragma alloc_text(PAGE, MsTranceive)
#pragma alloc_text(PAGE, MsReceive)
#pragma alloc_text(PAGE, MsSend)
#pragma alloc_text(PAGE, MsSendDatagram)
#pragma alloc_text(PAGE, MsInitializeExchange)
#pragma alloc_text(PAGE, MsUninitializeExchange)
#pragma alloc_text(PAGE, MsTimerEventHandler)
#pragma alloc_text(PAGE, MsInitiateDisconnect)
#endif
RXDT_DefineCategory(MSSNDRCV); #define Dbg (DEBUG_TRACE_MSSNDRCV)
extern TRANSPORT_DISPATCH_VECTOR MRxSmbMailSlotTransportDispatch;
#define SMBDATAGRAM_LOCAL_ENDPOINT_NAME "*SMBDATAGRAM "
NTSTATUS MsInstantiateServerTransport( IN OUT PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext) /*++
Routine Description:
This routine initializes the MAILSLOT transport information corresponding to a server
It allocates the transport address. It constructs two address strutures for the server name: a NETBIOS_EX type address and a NETBIOS type address. The latter only has up to the first 16 characters of the name, while a NETBIOS_EX may have more.
Arguments:
pContext - the transport construction context
Return Value:
STATUS_SUCCESS - the server transport construction has been finalized.
Other Status codes correspond to error situations.
Notes:
The remote address can be either deduced from the information in the Rx Context or a NETBIOS address needs to be built from the server name. This transport address is used subsequently to establish the connection.
// The last character of the name depends upon the path name passed in.
// There are currently four possible alternatives ....
//
// \\*\mailslot\...... => the primary domain is used for broadcasts
// (This mapping is handled by the RDBSS)
//
// \\Uniquename\mailslot\.... => maps to either a computer name or a group
// name for mailslot writes.
//
// \\DomainName*\mailslot\.... => maps to a netbios address of the form
// domainname ...1c for broadcasts.
//
// \\DomainName**\mailslot\.... => maps to a netbios address of the form
// domainname....1b for broadcasts.
//
// Initialize the NETBIOS address according to these formats.
Nbt.SendDatagram only looks at the first address. It is smart enough to treat a NETBIOS_EX address like a NETBIOS address when the length < NETBIOS_NAME_LEN. So if the name is short enough, I fill in byte 15 of the name for the NETBIOS_EX case as well.
--*/ { NTSTATUS Status; PSMBCEDB_SERVER_ENTRY pServerEntry; PSMBCE_SERVER_MAILSLOT_TRANSPORT pMsTransport; UNICODE_STRING ServerName; OEM_STRING OemServerName; ULONG ServerNameLength; PTRANSPORT_ADDRESS pTA; PTA_ADDRESS taa; PTDI_ADDRESS_NETBIOS na;
PAGED_CODE();
RxDbgTrace(0, Dbg, ("MsInitialize : Mailslot Transport Initialization\n"));
ASSERT(pContext->State == SmbCeServerMailSlotTransportConstructionBegin);
pServerEntry = pContext->pServerEntry;
pMsTransport = (PSMBCE_SERVER_MAILSLOT_TRANSPORT) RxAllocatePoolWithTag( NonPagedPool, sizeof(SMBCE_SERVER_MAILSLOT_TRANSPORT), MRXSMB_MAILSLOT_POOLTAG);
if (pMsTransport != NULL) { RtlZeroMemory(pMsTransport,sizeof(SMBCE_SERVER_MAILSLOT_TRANSPORT));
ServerName.Buffer = pServerEntry->Name.Buffer + 1; ServerName.Length = pServerEntry->Name.Length - sizeof(WCHAR); ServerName.MaximumLength = pServerEntry->Name.MaximumLength - sizeof(WCHAR); ServerNameLength = RtlUnicodeStringToOemSize(&ServerName) - 1;
pMsTransport->TransportAddressLength = FIELD_OFFSET(TRANSPORT_ADDRESS,Address) + (FIELD_OFFSET(TA_ADDRESS,Address)) + TDI_ADDRESS_LENGTH_NETBIOS + 4 * sizeof(ULONG); // if the server name length is NETBIOS_NAME_LEN,
// RtlUpcaseUnicodeStringToOemString could overrun the buffer.
if (ServerNameLength > NETBIOS_NAME_LEN) { pMsTransport->TransportAddressLength += ServerNameLength; }
pMsTransport->pTransportAddress = (PTRANSPORT_ADDRESS)RxAllocatePoolWithTag( NonPagedPool, pMsTransport->TransportAddressLength, MRXSMB_MAILSLOT_POOLTAG);
if (pMsTransport->pTransportAddress != NULL) { pTA = pMsTransport->pTransportAddress;
pTA->TAAddressCount = 1;
// *****************************************
// FIRST ADDRESS: TDI_ADDRESS_TYPE_NETBIOS
// *****************************************
taa = pTA->Address; taa->AddressLength = (USHORT) TDI_ADDRESS_LENGTH_NETBIOS;
if (ServerNameLength > NETBIOS_NAME_LEN) { taa->AddressLength += (USHORT)(ServerNameLength - NETBIOS_NAME_LEN); }
taa->AddressType = TDI_ADDRESS_TYPE_NETBIOS;
na = (PTDI_ADDRESS_NETBIOS) taa->Address; na->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE;
OemServerName.MaximumLength = (USHORT) (ServerNameLength + 1); // in case null term
OemServerName.Buffer = na->NetbiosName; Status = RtlUpcaseUnicodeStringToOemString(&OemServerName, &ServerName, FALSE); if (Status == STATUS_SUCCESS) {
// Blank-pad the server name buffer if necessary to 16 characters
if (OemServerName.Length <= NETBIOS_NAME_LEN) { RtlCopyMemory(&OemServerName.Buffer[OemServerName.Length], " ", NETBIOS_NAME_LEN - OemServerName.Length); }
// Set type pneultimate byte in netbios name
if (OemServerName.Buffer[OemServerName.Length - 1] == '*') { if (OemServerName.Length <= NETBIOS_NAME_LEN || (OemServerName.Length == NETBIOS_NAME_LEN + 1 && OemServerName.Buffer[OemServerName.Length - 2] == '*')) { if ((OemServerName.Length >= 2) && (OemServerName.Buffer[OemServerName.Length - 2] == '*')) { if (OemServerName.Length <= NETBIOS_NAME_LEN) { OemServerName.Buffer[OemServerName.Length - 1] = ' '; OemServerName.Buffer[OemServerName.Length - 2] = ' '; } else { taa->AddressLength = (USHORT)TDI_ADDRESS_LENGTH_NETBIOS; } OemServerName.Buffer[NETBIOS_NAME_LEN - 1] = PRIMARY_CONTROLLER_SIGNATURE; } else { OemServerName.Buffer[OemServerName.Length - 1] = ' '; OemServerName.Buffer[NETBIOS_NAME_LEN - 1] = DOMAIN_CONTROLLER_SIGNATURE; } } else { Status = STATUS_BAD_NETWORK_PATH; } } else { OemServerName.Buffer[NETBIOS_NAME_LEN - 1] = WORKSTATION_SIGNATURE; } } } else { Status = STATUS_INSUFFICIENT_RESOURCES; RxDbgTrace(0, Dbg, ("MsInitialize : Memory Allocation failed\n")); }
if (Status == STATUS_SUCCESS) { pMsTransport->pTransport = NULL; pMsTransport->State = SMBCEDB_ACTIVE; pMsTransport->pDispatchVector = &MRxSmbMailSlotTransportDispatch; } else { RxDbgTrace(0, Dbg, ("MsInitialize : Mailsslot transport initialization Failed %lx\n", Status)); MsUninitialize(pMsTransport); pMsTransport = NULL; } } else { RxDbgTrace(0, Dbg, ("MsInitialize : Memory Allocation failed\n")); Status = STATUS_INSUFFICIENT_RESOURCES; }
if (Status == STATUS_SUCCESS) { pContext->pMailSlotTransport = (PSMBCE_SERVER_TRANSPORT)pMsTransport; } else { pContext->pMailSlotTransport = NULL; }
pContext->State = SmbCeServerMailSlotTransportConstructionEnd; pContext->Status = Status;
return Status; }
NTSTATUS MsUninitialize( PSMBCE_SERVER_TRANSPORT pTransport) /*++
Routine Description:
This routine uninitializes the transport instance
Arguments:
pVcTransport - the VC transport instance
Return Value:
STATUS_SUCCESS - the server transport construction has been uninitialzied.
Other Status codes correspond to error situations.
Notes:
--*/ { NTSTATUS Status = STATUS_SUCCESS; PKEVENT pRundownEvent = pTransport->pRundownEvent; PSMBCE_SERVER_MAILSLOT_TRANSPORT pMsTransport = (PSMBCE_SERVER_MAILSLOT_TRANSPORT)pTransport;
PAGED_CODE();
if (pMsTransport->pTransportAddress != NULL) { RxFreePool(pMsTransport->pTransportAddress); }
RxFreePool(pMsTransport);
if (pRundownEvent != NULL) { KeSetEvent(pRundownEvent, 0, FALSE ); } return Status; }
NTSTATUS MsInitiateDisconnect( PSMBCE_SERVER_TRANSPORT pTransport) /*++
Routine Description:
This routine uninitializes the transport instance
Arguments:
pTransport - the mailslot transport instance
Return Value:
STATUS_SUCCESS - the server transport construction has been uninitialzied.
Other Status codes correspond to error situations.
--*/ { PAGED_CODE();
return STATUS_SUCCESS; }
NTSTATUS MsTranceive( PSMBCE_SERVER_TRANSPORT pTransport, PSMBCEDB_SERVER_ENTRY pServerEntry, PSMB_EXCHANGE pExchange, ULONG SendOptions, PMDL pSmbMdl, ULONG SendLength, PVOID pSendCompletionContext) /*++
Routine Description:
This routine transmits/receives a SMB for a give exchange
Arguments:
pTransport - the transport instance
pServerEntry - the server entry
pExchange - the exchange instance issuing this SMB.
SendOptions - options for send
pSmbMdl - the SMB that needs to be sent.
SendLength - length of data to be transmitted
Return Value:
STATUS_SUCCESS - the server call construction has been finalized.
STATUS_PENDING - the open involves network traffic and the exchange has been queued for notification ( pServerPointer is set to NULL)
Other Status codes correspond to error situations.
--*/ { PAGED_CODE();
return RX_MAP_STATUS(NOT_SUPPORTED); }
NTSTATUS MsReceive( PSMBCE_SERVER_TRANSPORT pTransport, PSMBCEDB_SERVER_ENTRY pServerEntry, PSMB_EXCHANGE pExchange) /*++
Routine Description:
This routine transmits/receives a SMB for a give exchange
Arguments:
pTransport - the transport instance
pServerEntry - the server entry
pExchange - the exchange instance issuing this SMB.
Return Value:
STATUS_PENDING - the request has been queued
Other Status codes correspond to error situations.
--*/ { PAGED_CODE();
ASSERT(FALSE); return RX_MAP_STATUS(NOT_SUPPORTED); }
NTSTATUS MsSend( PSMBCE_SERVER_TRANSPORT pTransport, PSMBCEDB_SERVER_ENTRY pServerEntry, ULONG SendOptions, PMDL pSmbMdl, ULONG SendLength, PVOID pSendCompletionContext) /*++
Routine Description:
This routine opens/creates a server entry in the connection engine database
Arguments:
pTransport - the transport instance
pServer - the recepient server
pVc - the Vc on which the SMB is sent( if it is NULL SMBCE picks one)
SendOptions - options for send
pSmbMdl - the SMB that needs to be sent.
SendLength - length of data to be sent
Return Value:
STATUS_SUCCESS - the server call construction has been finalized.
STATUS_PENDING - the open involves network traffic and the exchange has been queued for notification ( pServerPointer is set to NULL)
Other Status codes correspond to error situations.
--*/ { NTSTATUS Status = STATUS_CONNECTION_DISCONNECTED; NTSTATUS FinalStatus = STATUS_CONNECTION_DISCONNECTED; PSMBCE_SERVER_MAILSLOT_TRANSPORT pMsTransport; PSMBCE_TRANSPORT pDatagramTransport; BOOLEAN fAtleastOneSendWasSuccessful = FALSE; PSMBCE_TRANSPORT_ARRAY pTransportArray;
RXCE_CONNECTION_INFORMATION RxCeConnectionInformation;
PAGED_CODE();
pMsTransport = (PSMBCE_SERVER_MAILSLOT_TRANSPORT)pTransport;
RxCeConnectionInformation.RemoteAddress = pMsTransport->pTransportAddress; RxCeConnectionInformation.RemoteAddressLength = pMsTransport->TransportAddressLength;
RxCeConnectionInformation.UserDataLength = 0; RxCeConnectionInformation.UserData = NULL;
RxCeConnectionInformation.OptionsLength = 0; RxCeConnectionInformation.Options = NULL;
pTransportArray = SmbCeReferenceTransportArray();
if (pTransportArray == NULL) { RxDbgTrace(0, Dbg, ("MsSend : Transport not available.\n")); return STATUS_NETWORK_UNREACHABLE; }
if (pTransportArray != NULL) { ULONG i;
for(i=0;i<pTransportArray->Count;i++) { pDatagramTransport = pTransportArray->SmbCeTransports[i];
if (pDatagramTransport->Active && (pDatagramTransport->RxCeTransport.pProviderInfo->MaxDatagramSize > 0)) { Status = RxCeSendDatagram( &pDatagramTransport->RxCeAddress, &RxCeConnectionInformation, SendOptions, pSmbMdl, SendLength, NULL);
if (!NT_SUCCESS(Status)) { RxDbgTrace(0, Dbg, ("MsSend: RxCeSendDatagram on transport (%lx) returned %lx\n",pTransport,Status)); FinalStatus = Status; } else { fAtleastOneSendWasSuccessful = TRUE; } } } }
SmbCeDereferenceTransportArray(pTransportArray);
if (fAtleastOneSendWasSuccessful) { SmbCeSendCompleteInd(pServerEntry,pSendCompletionContext,RX_MAP_STATUS(SUCCESS)); Status = RX_MAP_STATUS(SUCCESS); } else { Status = FinalStatus; }
return Status; }
NTSTATUS MsSendDatagram( PSMBCE_SERVER_TRANSPORT pTransport, PSMBCEDB_SERVER_ENTRY pServerEntry, ULONG SendOptions, PMDL pSmbMdl, ULONG SendLength, PVOID pSendCompletionContext) /*++
Routine Description:
This routine opens/creates a server entry in the connection engine database
Arguments:
pTransport - the transport instance
pServer - the recepient server
SendOptions - options for send
pSmbMdl - the SMB that needs to be sent.
SendLength - length of data to be sent
Return Value:
STATUS_SUCCESS - the server call construction has been finalized.
STATUS_PENDING - the open involves network traffic and the exchange has been queued for notification ( pServerPointer is set to NULL)
Other Status codes correspond to error situations.
--*/ { PAGED_CODE();
ASSERT(FALSE); return STATUS_NOT_IMPLEMENTED; }
NTSTATUS MsInitializeExchange( PSMBCE_SERVER_TRANSPORT pTransport, PSMB_EXCHANGE pExchange) /*++
Routine Description:
This routine initializes the transport information pertinent to a exchange
Arguments:
pTransport - the transport structure
pExchange - the exchange instance
Return Value:
STATUS_SUCCESS -
Other Status codes correspond to error situations.
--*/ { return STATUS_SUCCESS; }
NTSTATUS MsUninitializeExchange( PSMBCE_SERVER_TRANSPORT pTransport, PSMB_EXCHANGE pExchange) /*++
Routine Description:
This routine uninitializes the transport information pertinent to a exchange
Arguments:
pTransport - the transport structure
pExchange - the exchange instance
Return Value:
STATUS_SUCCESS -
Other Status codes correspond to error situations.
--*/ { PAGED_CODE();
return STATUS_SUCCESS; }
VOID MsTimerEventHandler( PVOID pTransport) /*++
Routine Description:
This routine handles the periodic strobes to determine if the connection is still alive
Arguments:
pTransport - the recepient server
Notes:
This routine is not implemented for mail slot related transports
--*/ { PAGED_CODE(); }
TRANSPORT_DISPATCH_VECTOR MRxSmbMailSlotTransportDispatch = { MsSend, MsSendDatagram, MsTranceive, MsReceive, MsTimerEventHandler, MsInitializeExchange, MsUninitializeExchange, MsUninitialize, MsInitiateDisconnect };
|