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.
 
 
 
 
 
 

391 lines
8.8 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
svccdevq.c
Abstract:
This module contains routines for supporting the character device
APIs in the server service, SrvNetCharDevQEnum, SrvNetCharDevQGetInfo,
SrvNetCharDevQPurge and SrvNetCharDevQSetInfo.
Author:
David Treadwell (davidtr) 31-Jan-1991
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, SrvNetCharDevQEnum )
#pragma alloc_text( PAGE, SrvNetCharDevQPurge )
#pragma alloc_text( PAGE, SrvNetCharDevQSetInfo )
#if SRV_COMM_DEVICES
#pragma alloc_text( PAGE, FillCharDevQInfoBuffer )
#pragma alloc_text( PAGE, FilterCharDevQs )
#pragma alloc_text( PAGE, SizeCharDevQs )
#endif
#endif
//
// Forward declarations.
//
VOID
FillCharDevQInfoBuffer (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Block,
IN OUT PVOID *FixedStructure,
IN LPTSTR *EndOfVariableData
);
BOOLEAN
FilterCharDevQs (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Block
);
ULONG
SizeCharDevQs (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Block
);
//
// Macros to determine the size a character device would take up at one of the
// levels of chardev information.
//
#define TOTAL_SIZE_OF_CHARDEVQ(level,share) \
( (level) == 0 ? sizeof(CHARDEVQ_INFO_0) + \
SrvLengthOfStringInApiBuffer(&(share)->ShareName) : \
sizeof(CHARDEVQ_INFO_1) + \
SrvLengthOfStringInApiBuffer(&(share)->ShareName) + \
SrvLengthOfStringInApiBuffer( \
&(share)->Type.CommDevice->DosPathName) )
#define FIXED_SIZE_OF_CHARDEVQ(level) \
( (level) == 0 ? sizeof(CHARDEVQ_INFO_0) : \
sizeof(CHARDEVQ_INFO_1) )
NTSTATUS
SrvNetCharDevQEnum (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Buffer,
IN ULONG BufferLength
)
/*++
Routine Description:
This routine processes the NetCharDevQEnum API in the server.
Arguments:
Srp - a pointer to the server request packet that contains all
the information necessary to satisfy the request. This includes:
INPUT:
Level - level of information to return, 0, or 1.
Name1 - a username; the number of requests ahead of a specified
user is written to cq1_numahead in lm2.x; since NT doesn't
support queueing or pooling of comm devices, we only use
the existence of a username to know to set the field to
CHARDEVQ_NO_REQUESTS.
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 the buffer for results.
BufferLength - the length of this buffer.
Return Value:
NTSTATUS - result of operation to return to the server service.
--*/
{
PAGED_CODE( );
#if SRV_COMM_DEVICES
return SrvShareEnumApiHandler(
Srp,
Buffer,
BufferLength,
FilterCharDevQs,
SizeCharDevQs,
FillCharDevQInfoBuffer
);
#else
Srp->Parameters.Get.EntriesRead = 0;
Srp->Parameters.Get.TotalEntries = 0;
Srp->Parameters.Get.TotalBytesNeeded = 0;
Srp->ErrorCode = NO_ERROR;
return STATUS_SUCCESS;
#endif
} // SrvNetCharDevQEnum
NTSTATUS
SrvNetCharDevQPurge (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Buffer,
IN ULONG BufferLength
)
{
PAGED_CODE( );
Srp, Buffer, BufferLength;
return STATUS_NOT_IMPLEMENTED;
} // SrvNetCharDevQPurge
NTSTATUS
SrvNetCharDevQSetInfo (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Buffer,
IN ULONG BufferLength
)
{
PAGED_CODE( );
Srp, Buffer, BufferLength;
return STATUS_NOT_IMPLEMENTED;
} // SrvNetCharDevQSetInfo
#if SRV_COMM_DEVICES
VOID
FillCharDevQInfoBuffer (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Block,
IN OUT PVOID *FixedStructure,
IN LPTSTR *EndOfVariableData
)
/*++
Routine Description:
This routine puts a single fixed file structure and associated
variable data, into a buffer. Fixed data goes at the beginning of
the buffer, variable data at the end.
*** This routine assumes that ALL the data, both fixed and variable,
will fit.
Arguments:
Srp - a pointer to the SRP for the operation. Only the Level
field is used.
Block - the comm share 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.
--*/
{
PCHARDEVQ_INFO_1 cq1 = *FixedStructure;
PSHARE share = Block;
PAGED_CODE( );
//
// Update FixedStructure to point to the next structure location.
//
*FixedStructure = (PCHAR)*FixedStructure +
FIXED_SIZE_OF_CHARDEVQ( Srp->Level );
ASSERT( (ULONG)*EndOfVariableData >= (ULONG)*FixedStructure );
//
// Case on the level to fill in the fixed structure appropriately.
// We fill in actual pointers in the output structure. This is
// possible because we are in the server FSD, hence the server
// service's process and address space.
//
// *** Using the switch statement in this fashion relies on the fact
// that the first fields on the different chardev structures are
// identical (with the exception of level 10, which is handled
// separately).
//
switch( Srp->Level ) {
case 1:
//
// Fill in level-1 fields of char dev Q structure.
//
// !!! we could store the priority in the share block and
// return it here, even though it has no impact on the way
// things operate. Does this make sense? Would it be
// confusing?
cq1->cq1_priority = 0;
SrvCopyUnicodeStringToBuffer(
&share->Type.CommDevice->DosPathName,
*FixedStructure,
EndOfVariableData,
&cq1->cq1_devs
);
cq1->cq1_numusers = 0;
if ( Srp->Name1.Buffer == NULL ) {
cq1->cq1_numahead = 0;
} else {
cq1->cq1_numahead = (ULONG)CHARDEVQ_NO_REQUESTS;
}
// *** lack of break is intentional!
case 0:
//
// Set up the share name in the output buffer.
//
SrvCopyUnicodeStringToBuffer(
&share->ShareName,
*FixedStructure,
EndOfVariableData,
&cq1->cq1_dev
);
break;
default:
//
// This should never happen. The server service should have
// checked for an invalid level.
//
INTERNAL_ERROR(
ERROR_LEVEL_UNEXPECTED,
"FillCharDevInfoBuffer: invalid level number: %ld",
Srp->Level,
NULL
);
SrvLogInvalidSmb( NULL );
}
return;
} // FillCharDevQInfoBuffer
BOOLEAN
FilterCharDevQs (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Block
)
/*++
Routine Description:
This routine is intended to be called by SrvEnumApiHandler to check
whether a particular share is a comm queue.
Arguments:
Srp - a pointer to the SRP for the operation.
Block - a pointer to the share to check.
Return Value:
TRUE if the block should be placed in the output buffer, FALSE
if it should be passed over.
--*/
{
PSHARE share = Block;
PAGED_CODE( );
return (BOOLEAN)( share->ShareType == ShareTypeComm );
} // FilterCharDevQs
ULONG
SizeCharDevQs (
IN PSERVER_REQUEST_PACKET Srp,
IN PVOID Block
)
/*++
Routine Description:
This routine returns the size the passed-in comm share would take
up in an API output buffer.
Arguments:
Srp - a pointer to the SRP for the operation. Only the level
parameter is used.
Block - a pointer to the comm device to size.
Return Value:
ULONG - The number of bytes the comm device would take up in the
output buffer.
--*/
{
PSHARE share = Block;
PAGED_CODE( );
return TOTAL_SIZE_OF_CHARDEVQ( Srp->Level, share );
} // SizeCharDevQs
#endif // SRV_COMM_DEVICES