|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
svcxport.c
Abstract:
This module contains routines for supporting the transport APIs in the server service, NetServerTransportAdd, NetServerTransportDel, and NetServerTransportEnum.
Author:
David Treadwell (davidtr) 6-Mar-1991
Revision History:
--*/
#include "precomp.h"
#include "svcxport.tmh"
#pragma hdrstop
//
// Forward declarations.
//
VOID FillTransportInfoBuffer ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Block, IN OUT PVOID *FixedStructure, IN LPWSTR *EndOfVariableData );
BOOLEAN FilterTransports ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Block );
ULONG SizeTransports ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Block );
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, SrvNetServerTransportAdd )
#pragma alloc_text( PAGE, SrvNetServerTransportDel )
#pragma alloc_text( PAGE, SrvNetServerTransportEnum )
#pragma alloc_text( PAGE, FillTransportInfoBuffer )
#pragma alloc_text( PAGE, FilterTransports )
#pragma alloc_text( PAGE, SizeTransports )
#endif
NTSTATUS SrvNetServerTransportAdd ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Buffer, IN ULONG BufferLength )
/*++
Routine Description:
This routine processes the NetServerTransportAdd API in the server FSP. Because it opens an object (the transport device object) it must be done in the server FSP, not the FSD.
Arguments:
Srp - a pointer to the server request packet that contains all the information necessary to satisfy the request. This includes:
INPUT:
None.
OUTPUT:
None.
Buffer - a pointer to a TRANSPORT_INFO_0 structure for the new transport. All pointers should have been changed to offsets within the buffer.
BufferLength - total length of this buffer.
Return Value:
NTSTATUS - result of operation to return to the server service.
--*/
{ NTSTATUS status; PSERVER_TRANSPORT_INFO_3 svti3; UNICODE_STRING transportName; UNICODE_STRING domainName; ANSI_STRING transportAddress; UNICODE_STRING netName;
PAGED_CODE( );
//
// Convert the offsets in the transport data structure to pointers.
// Also make sure that all the pointers are within the specified
// buffer.
//
svti3 = Buffer;
OFFSET_TO_POINTER( svti3->svti3_transportname, svti3 ); OFFSET_TO_POINTER( svti3->svti3_transportaddress, svti3 ); OFFSET_TO_POINTER( svti3->svti3_domain, svti3 );
if ( !POINTER_IS_VALID( svti3->svti3_transportname, svti3, BufferLength ) || !POINTER_IS_VALID( svti3->svti3_transportaddress, svti3, BufferLength ) || !POINTER_IS_VALID( svti3->svti3_domain, svti3, BufferLength ) ) {
IF_DEBUG( ERRORS ) { KdPrint(( "SrvNetServerTransportAdd: Bad pointers\n" )); }
return STATUS_ACCESS_VIOLATION; }
if( svti3->svti3_passwordlength > sizeof( svti3->svti3_password ) ) {
IF_DEBUG( ERRORS ) { KdPrint(( "SrvNetServerTransportAdd: svti3_passwordlength %d\n", svti3->svti3_passwordlength )); }
return STATUS_INVALID_PARAMETER; }
//
// Set up the transport name, server name, domain name, and net name.
//
RtlInitUnicodeString( &transportName, (PWCH)svti3->svti3_transportname );
netName.Buffer = NULL; netName.Length = 0; netName.MaximumLength = 0;
RtlInitUnicodeString( &domainName, (PWCH)svti3->svti3_domain );
transportAddress.Buffer = svti3->svti3_transportaddress; transportAddress.Length = (USHORT)svti3->svti3_transportaddresslength; transportAddress.MaximumLength = (USHORT)svti3->svti3_transportaddresslength;
//
// Attempt to add the new transport to the server.
//
IF_DEBUG( PNP ) { KdPrint(( "SRV: SrvNetServerTransportAdd: %wZ\n", &transportName )); }
status = SrvAddServedNet( &netName, &transportName, &transportAddress, &domainName, Srp->Flags & SRP_XADD_FLAGS, svti3->svti3_passwordlength, svti3->svti3_password );
IF_DEBUG( PNP ) { KdPrint(( "SRV: SrvNetServerTransportAdd: %wZ, status %X\n", &transportName, status )); }
return status;
} // SrvNetServerTransportAdd
NTSTATUS SrvNetServerTransportDel ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Buffer, IN ULONG BufferLength )
/*++
Routine Description:
This routine processes the NetServerTransportEnum API in the server FSD.
Arguments:
Srp - a pointer to the server request packet that contains all the information necessary to satisfy the request. This includes:
Buffer - a pointer to a TRANSPORT_INFO_0 structure for the transport. All pointers should have been changed to offsets within the buffer.
BufferLength - total length of this buffer.
Return Value:
NTSTATUS - result of operation to return to the server service.
--*/
{ NTSTATUS status; PSERVER_TRANSPORT_INFO_3 svti3; UNICODE_STRING transportName; ANSI_STRING transportAddress;
PAGED_CODE( );
Srp;
//
// Convert the offsets in the transport data structure to pointers.
// Also make sure that all the pointers are within the specified
// buffer.
//
svti3 = Buffer;
OFFSET_TO_POINTER( svti3->svti3_transportname, svti3 );
if ( !POINTER_IS_VALID( svti3->svti3_transportname, svti3, BufferLength ) ) { IF_DEBUG( ERRORS ) { KdPrint(("SrvNetServerTransportDel: STATUS_ACCESS_VIOLATION at %u\n", __LINE__ )); } return STATUS_ACCESS_VIOLATION; }
RtlInitUnicodeString( &transportName, (PWCH)svti3->svti3_transportname );
transportAddress.Length = (USHORT)svti3->svti3_transportaddresslength; transportAddress.MaximumLength = (USHORT)svti3->svti3_transportaddresslength;
if( transportAddress.Length != 0 ) {
OFFSET_TO_POINTER( svti3->svti3_transportaddress, svti3 );
if( !POINTER_IS_VALID( svti3->svti3_transportaddress, svti3, BufferLength ) ) { IF_DEBUG( ERRORS ) { KdPrint(("SrvNetServerTransportDel: STATUS_ACCESS_VIOLATION at %u\n", __LINE__ )); } return STATUS_ACCESS_VIOLATION; }
transportAddress.Buffer = svti3->svti3_transportaddress; }
//
// Attempt to delete the transport endpoint from the server.
//
status = SrvDeleteServedNet( &transportName, &transportAddress );
IF_DEBUG( ERRORS ) { if( !NT_SUCCESS( status ) ) { KdPrint(( "SrvNetServerTransportDel: SrvDeleteServedNet status %X\n", status )); } }
return status;
} // SrvNetServerTransportDel
NTSTATUS SrvNetServerTransportEnum ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Buffer, IN ULONG BufferLength )
/*++
Routine Description:
This routine processes the NetServerTransportEnum API in the server FSD.
Arguments:
Srp - a pointer to the server request packet that contains all the information necessary to satisfy the request. This includes:
INPUT:
None.
OUTPUT:
Parameters.Get.EntriesRead - the number of entries that fit in the output buffer.
Parameters.Get.TotalEntries - the total number of entries that would be returned with a large enough buffer.
Parameters.Get.TotalBytesNeeded - the buffer size that would be required to hold all the entries.
Buffer - a pointer to a TRANSPORT_INFO_0 structure for the new transport. All pointers should have been changed to offsets within the buffer.
BufferLength - total length of this buffer.
Return Value:
NTSTATUS - result of operation to return to the server service.
--*/
{ PAGED_CODE( );
return SrvEnumApiHandler( Srp, Buffer, BufferLength, &SrvEndpointList, FilterTransports, SizeTransports, FillTransportInfoBuffer );
} // SrvNetServerTransportEnum
VOID FillTransportInfoBuffer ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Block, IN OUT PVOID *FixedStructure, IN LPWSTR *EndOfVariableData )
/*++
Routine Description:
This routine puts a single fixed transport structure and, if it fits, associated variable data, into a buffer. Fixed data goes at the beginning of the buffer, variable data at the end.
Arguments:
Endpoint - the endpoint from which to get information.
FixedStructure - where the in the buffer to place the fixed structure. This pointer is updated to point to the next available position for a fixed structure.
EndOfVariableData - the last position on the buffer that variable data for this structure can occupy. The actual variable data is written before this position as long as it won't overwrite fixed structures. It is would overwrite fixed structures, it is not written.
Return Value:
None.
--*/
{ PENDPOINT endpoint = Block; PSERVER_TRANSPORT_INFO_1 svti1 = *FixedStructure; ULONG TransportAddressLength;
PAGED_CODE( );
//
// Update FixedStructure to point to the next structure location.
//
*FixedStructure = (PCHAR)*FixedStructure + (Srp->Level ? sizeof( SERVER_TRANSPORT_INFO_1 ) : sizeof( SERVER_TRANSPORT_INFO_0 ));
ASSERT( (ULONG_PTR)*EndOfVariableData >= (ULONG_PTR)*FixedStructure );
//
// The number of VCs on the endpoint is equal to the total number
// of connections on the endpoint less the free connections.
//
ACQUIRE_LOCK_SHARED( &SrvEndpointLock );
svti1->svti1_numberofvcs = endpoint->TotalConnectionCount - endpoint->FreeConnectionCount;
RELEASE_LOCK( &SrvEndpointLock );
//
// Copy over the transport name.
//
SrvCopyUnicodeStringToBuffer( &endpoint->TransportName, *FixedStructure, EndOfVariableData, &svti1->svti1_transportname );
//
// Copy over the network name.
//
SrvCopyUnicodeStringToBuffer( &endpoint->NetworkAddress, *FixedStructure, EndOfVariableData, &svti1->svti1_networkaddress );
//
// Copy over the domain name
//
if( Srp->Level > 0 ) {
SrvCopyUnicodeStringToBuffer( &endpoint->DomainName, *FixedStructure, EndOfVariableData, &svti1->svti1_domain );
}
//
// Copy over the transport address. We have to manually check here
// whether it will fit in the output buffer.
//
//
// Don't copy the trailing blanks of the transport address.
//
for ( TransportAddressLength = endpoint->TransportAddress.Length; TransportAddressLength > 0 && endpoint->TransportAddress.Buffer[TransportAddressLength-1] == ' ' ; TransportAddressLength-- ) ;
*EndOfVariableData = (LPWSTR)( (PCHAR)*EndOfVariableData - TransportAddressLength );
//
// Ensure we remain byte aligned, so knock off the low bit if necessary. Remember, we
// are filling backwards from the end of the buffer so we want to round the address down
//
*EndOfVariableData = (LPWSTR)( (ULONG_PTR)*EndOfVariableData & ~1 );
if ( (ULONG_PTR)*EndOfVariableData > (ULONG_PTR)*FixedStructure ) {
//
// The address will fit. Copy it over to the output buffer.
//
RtlCopyMemory( *EndOfVariableData, endpoint->TransportAddress.Buffer, TransportAddressLength );
svti1->svti1_transportaddress = (LPBYTE)*EndOfVariableData; svti1->svti1_transportaddresslength = TransportAddressLength;
} else {
svti1->svti1_transportaddress = NULL; svti1->svti1_transportaddresslength = 0; }
return;
} // FillTransportInfoBuffer
BOOLEAN FilterTransports ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Block )
/*++
Routine Description:
This routine just returns TRUE since we always want to place information about all transports in the output buffer for a NetServerTransportEnum.
Arguments:
Srp - not used.
Block - not used.
Return Value:
TRUE.
--*/
{ PENDPOINT endpoint = Block;
PAGED_CODE( );
Srp, Block;
//
// We filter out AlternateEndpoint since they are endpoints we've
// created ourselves.
//
if (endpoint->AlternateAddressFormat) {
return FALSE; }
//
// We always return information about all transports.
//
return TRUE;
} // FilterFiles
ULONG SizeTransports ( IN PSERVER_REQUEST_PACKET Srp, IN PVOID Block )
/*++
Routine Description:
This routine returns the size the passed-in endpoint would take up in an API output buffer.
Arguments:
Srp - not used.
Block - a pointer to the endpoint to size.
Return Value:
ULONG - The number of bytes the endpoint would take up in the output buffer.
--*/
{ PENDPOINT endpoint = Block; ULONG size;
PAGED_CODE( );
size = Srp->Level ? sizeof( SERVER_TRANSPORT_INFO_1 ) : sizeof( SERVER_TRANSPORT_INFO_0 );
size += SrvLengthOfStringInApiBuffer(&(endpoint)->TransportName); size += (endpoint)->TransportAddress.Length + sizeof(TCHAR); size += SrvLengthOfStringInApiBuffer(&(endpoint)->NetworkAddress);
if( Srp->Level ) { size += SrvLengthOfStringInApiBuffer( &(endpoint)->DomainName ); }
return size;
} // SizeTransports
|