Leaked source code of windows server 2003
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.
 
 
 
 
 
 

646 lines
22 KiB

/*++
Copyright (c) 1989 - 1999 Microsoft Corporation
Module Name:
devfcb.c
Abstract:
This module implements all the passthru stuff from the wrapper. currently
there is only one such function:
statistics
--*/
#include "precomp.h"
#pragma hdrstop
#include "smbmrx.h"
//
// Forward declarations.
//
NTSTATUS
MRxSmbCreateConnection (
IN PRX_CONTEXT RxContext,
OUT PBOOLEAN PostToFsp
);
NTSTATUS
MRxSmbDeleteConnection (
IN PRX_CONTEXT RxContext,
OUT PBOOLEAN PostToFsp
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, MRxSmbGetStatistics)
#pragma alloc_text(PAGE, MRxSmbDevFcbXXXControlFile)
#endif
//
// The local trace mask for this part of the module
//
#define Dbg (DEBUG_TRACE_DEVFCB)
MRX_SMB_STATISTICS MRxSmbStatistics;
NTSTATUS
MRxSmbGetStatistics(
IN OUT PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine gathers the statistics from the mini redirector
Arguments:
RxContext - Describes the Fsctl and Context.
Return Value:
STATUS_SUCCESS -- the Startup sequence was successfully completed.
any other value indicates the appropriate error.
Notes:
--*/
{
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
PMRX_SMB_STATISTICS pStatistics;
ULONG BufferLength = LowIoContext->ParamsFor.FsCtl.OutputBufferLength;
PAGED_CODE();
pStatistics = (PMRX_SMB_STATISTICS)(LowIoContext->ParamsFor.FsCtl.pOutputBuffer);
if (BufferLength < sizeof(MRX_SMB_STATISTICS)) {
return STATUS_INVALID_PARAMETER;
}
RxContext->InformationToReturn = sizeof(MRX_SMB_STATISTICS);
MRxSmbStatistics.SmbsReceived.QuadPart++;
//some stuff we have to copy from the device object......
MRxSmbStatistics.PagingReadBytesRequested = MRxSmbDeviceObject->PagingReadBytesRequested;
MRxSmbStatistics.NonPagingReadBytesRequested = MRxSmbDeviceObject->NonPagingReadBytesRequested;
MRxSmbStatistics.CacheReadBytesRequested = MRxSmbDeviceObject->CacheReadBytesRequested;
MRxSmbStatistics.NetworkReadBytesRequested = MRxSmbDeviceObject->NetworkReadBytesRequested;
MRxSmbStatistics.PagingWriteBytesRequested = MRxSmbDeviceObject->PagingWriteBytesRequested;
MRxSmbStatistics.NonPagingWriteBytesRequested = MRxSmbDeviceObject->NonPagingWriteBytesRequested;
MRxSmbStatistics.CacheWriteBytesRequested = MRxSmbDeviceObject->CacheWriteBytesRequested;
MRxSmbStatistics.NetworkWriteBytesRequested = MRxSmbDeviceObject->NetworkWriteBytesRequested;
MRxSmbStatistics.ReadOperations = MRxSmbDeviceObject->ReadOperations;
MRxSmbStatistics.RandomReadOperations = MRxSmbDeviceObject->RandomReadOperations;
MRxSmbStatistics.WriteOperations = MRxSmbDeviceObject->WriteOperations;
MRxSmbStatistics.RandomWriteOperations = MRxSmbDeviceObject->RandomWriteOperations;
MRxSmbStatistics.LargeReadSmbs = MRxSmbStatistics.ReadSmbs - MRxSmbStatistics.SmallReadSmbs;
MRxSmbStatistics.LargeWriteSmbs = MRxSmbStatistics.WriteSmbs - MRxSmbStatistics.SmallWriteSmbs;
MRxSmbStatistics.CurrentCommands = SmbCeStartStopContext.ActiveExchanges;
*pStatistics = MRxSmbStatistics;
return STATUS_SUCCESS;
}
NTSTATUS
MRxSmbDevFcbXXXControlFile (
IN OUT PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine handles all the device FCB related FSCTL's in the mini rdr
Arguments:
RxContext - Describes the Fsctl and Context.
Return Value:
STATUS_SUCCESS -- the Startup sequence was successfully completed.
any other value indicates the appropriate error in the startup sequence.
--*/
{
NTSTATUS Status;
RxCaptureFobx;
UCHAR MajorFunctionCode = RxContext->MajorFunction;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
ULONG ControlCode = LowIoContext->ParamsFor.FsCtl.FsControlCode;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbDevFcb\n"));
switch (MajorFunctionCode) {
case IRP_MJ_FILE_SYSTEM_CONTROL:
{
switch (LowIoContext->ParamsFor.FsCtl.MinorFunction) {
case IRP_MN_USER_FS_REQUEST:
{
RxDbgTrace(-1, Dbg, ("RxCommonDevFCBFsCtl -> unimplemented fsctl\n"));
Status = STATUS_INVALID_DEVICE_REQUEST;
}
break;
default : //minor function != IRP_MN_USER_FS_REQUEST
Status = STATUS_INVALID_DEVICE_REQUEST;
} // end of switch
} // end of FSCTL case
break;
case IRP_MJ_DEVICE_CONTROL:
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
{
switch (ControlCode) {
case IOCTL_SMBMRX_ADDCONN:
DbgPrint("Processing Create Connection IOCTL\n");
Status = MRxSmbCreateConnection( RxContext, &RxContext->PostRequest );
break;
case IOCTL_SMBMRX_DELCONN:
DbgPrint("Processing Delete Connection IOCTL\n");
Status = MRxSmbDeleteConnection( RxContext, &RxContext->PostRequest );
break;
case IOCTL_SMBMRX_GETSTATE:
{
ULONG OutBufferLength = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
PBYTE OutBuffer = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
ULONG CurrentState = RDR_NULL_STATE;
if ( OutBufferLength >= sizeof(ULONG) )
{
// map the states to control app's equivalents
switch ( MRxSmbState )
{
case MRXSMB_STARTABLE:
case MRXSMB_STOPPED:
CurrentState = RDR_STOPPED;
break;
case MRXSMB_START_IN_PROGRESS:
CurrentState = RDR_STARTING;
break;
case MRXSMB_STARTED:
CurrentState = RDR_STARTED;
break;
}
*(ULONG *)OutBuffer = CurrentState;
RxContext->InformationToReturn = sizeof(ULONG);
Status = STATUS_SUCCESS;
}
else
{
Status = STATUS_INVALID_PARAMETER;
}
}
break;
case IOCTL_SMBMRX_START:
switch (MRxSmbState) {
case MRXSMB_STARTABLE:
// The correct sequence of start events issued by the workstation
// service would have avoided this. We can recover from this
// by actually invoking RxStartMiniRdr.
if (capFobx) {
Status = STATUS_INVALID_DEVICE_REQUEST;
goto FINALLY;
}
(MRXSMB_STATE)InterlockedCompareExchange(
(PLONG)&MRxSmbState,
MRXSMB_START_IN_PROGRESS,
MRXSMB_STARTABLE);
//lack of break is intentional
case MRXSMB_START_IN_PROGRESS:
{
Status = RxStartMinirdr(RxContext,&RxContext->PostRequest);
if (Status == STATUS_REDIRECTOR_STARTED) {
Status = STATUS_SUCCESS;
}
else if ( Status == STATUS_PENDING && RxContext->PostRequest == TRUE )
{
Status = STATUS_MORE_PROCESSING_REQUIRED;
}
}
break;
case MRXSMB_STARTED:
Status = STATUS_SUCCESS;
break;
default:
Status = STATUS_INVALID_PARAMETER;
break;
}
break;
case IOCTL_SMBMRX_STOP:
if (capFobx) {
Status = STATUS_INVALID_DEVICE_REQUEST;
goto FINALLY;
}
if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0) {
return STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
} else {
MRXSMB_STATE CurrentState;
CurrentState = (MRXSMB_STATE)
InterlockedCompareExchange(
(PLONG)&MRxSmbState,
MRXSMB_STARTABLE,
MRXSMB_STARTED);
Status = RxStopMinirdr(
RxContext,
&RxContext->PostRequest );
if ( Status == STATUS_PENDING && RxContext->PostRequest == TRUE )
{
Status = STATUS_MORE_PROCESSING_REQUIRED;
}
}
break;
default :
Status = STATUS_INVALID_DEVICE_REQUEST;
} // end of switch
} //end of IOCTL cases
break;
default:
ASSERT(!"unimplemented major function");
Status = STATUS_INVALID_DEVICE_REQUEST;
}
FINALLY:
RxDbgTrace(
-1,
Dbg,
("MRxSmbDevFcb st,info=%08lx,%08lx\n",
Status,
RxContext->InformationToReturn));
return(Status);
}
#if 0
// for ea testing
ULONG BuildCustomEAData( PVOID EaPtr )
{
PFILE_FULL_EA_INFORMATION thisEa = (PFILE_FULL_EA_INFORMATION) EaPtr;
PBYTE valuePtr;
// Set the user name EA
thisEa->Flags = 0;
thisEa->EaNameLength = sizeof("UserName");
RtlCopyMemory( thisEa->EaName, "UserName\0", thisEa->EaNameLength + 1 );
valuePtr = (PBYTE) thisEa->EaName + thisEa->EaNameLength + 1;
//thisEa->EaNameLength--; // don't include the null in the EaName length
thisEa->EaValueLength = sizeof(L"TestUser");
RtlCopyMemory( valuePtr, L"TestUser", thisEa->EaValueLength );
thisEa->NextEntryOffset = ((PBYTE) valuePtr + thisEa->EaValueLength ) -
(PBYTE) thisEa;
// Set the password EA
thisEa = (PFILE_FULL_EA_INFORMATION) ((PBYTE) thisEa + thisEa->NextEntryOffset);
thisEa->Flags = 0;
thisEa->EaNameLength = sizeof("Password");
RtlCopyMemory( thisEa->EaName, "Password\0", thisEa->EaNameLength + 1 );
valuePtr = (PBYTE) thisEa->EaName + thisEa->EaNameLength + 1;
//thisEa->EaNameLength--; // don't include the null in the EaName length
thisEa->EaValueLength = sizeof(WCHAR);
RtlCopyMemory( valuePtr, L"\0", thisEa->EaValueLength );
thisEa->NextEntryOffset = ((PBYTE) valuePtr + thisEa->EaValueLength ) -
(PBYTE) thisEa;
// Set the domain EA
thisEa = (PFILE_FULL_EA_INFORMATION) ((PBYTE) thisEa + thisEa->NextEntryOffset);
thisEa->Flags = 0;
thisEa->EaNameLength = sizeof("Domain");
RtlCopyMemory( thisEa->EaName, "Domain\0", thisEa->EaNameLength + 1 );
valuePtr = (PBYTE) thisEa->EaName + thisEa->EaNameLength + 1;
//thisEa->EaNameLength--; // don't include the null in the EaName length
thisEa->EaValueLength = sizeof(L"WORKGROUP");
RtlCopyMemory( valuePtr, L"WORKGROUP", thisEa->EaValueLength );
thisEa->NextEntryOffset = 0;
return ((PBYTE) valuePtr + thisEa->EaValueLength) - (PBYTE) EaPtr;
}
#endif
NTSTATUS
GetConnectionHandle(
IN PUNICODE_STRING ConnectionName,
PVOID EaBuffer,
ULONG EaLength,
PHANDLE Handle )
{
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING FileName;
InitializeObjectAttributes(
&ObjectAttributes,
ConnectionName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwCreateFile(
Handle,
SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
EaBuffer,
EaLength);
DbgPrint("ZwCreateFile returned %lx\n",Status);
if ( Status == STATUS_SUCCESS )
{
if ( *Handle != INVALID_HANDLE_VALUE ){
DbgPrint("ZwCreateFile returned success\n");
} else {
DbgPrint("ZwCreateFile failed\n");
}
}
return Status;
}
NTSTATUS
MRxSmbCreateConnection (
IN PRX_CONTEXT RxContext,
OUT PBOOLEAN PostToFsp
)
/*++
Routine Description:
Arguments:
IN PRX_CONTEXT RxContext - Describes the Fsctl and Context
Return Value:
RXSTATUS
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
ULONG InBufferLength = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
PBYTE InBuffer = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbCreateConnection - entry\n"));
if (!Wait) {
//just post right now!
*PostToFsp = TRUE;
return(STATUS_PENDING);
}
Status = STATUS_INVALID_PARAMETER;
try {
PSMBMRX_CONNECTINFO ConnectInfo;
UNICODE_STRING ConnectionName;
PBYTE EaBuffer;
ULONG EaLength;
ULONG Validator;
ULONG CompareLength;
HANDLE Handle;
if ( InBufferLength >= sizeof( PSMBMRX_CONNECTINFO ) )
{
ConnectInfo = (PSMBMRX_CONNECTINFO) InBuffer;
if (((ULONG)(FIELD_OFFSET(SMBMRX_CONNECTINFO, InfoArea)) + (USHORT)ConnectInfo->ConnectionNameOffset +
(USHORT)ConnectInfo->ConnectionNameLength <= InBufferLength) &&
((ULONG)(FIELD_OFFSET(SMBMRX_CONNECTINFO, InfoArea)) + (USHORT)ConnectInfo->EaDataOffset +
(USHORT)ConnectInfo->EaDataLength <= InBufferLength))
{
ConnectionName.Buffer = (PWCHAR) ((PBYTE) ConnectInfo->InfoArea +
ConnectInfo->ConnectionNameOffset);
ConnectionName.Length = (USHORT) ConnectInfo->ConnectionNameLength;
ConnectionName.MaximumLength = (USHORT) ConnectInfo->ConnectionNameLength;
EaLength = ConnectInfo->EaDataLength;
EaBuffer = ( EaLength > 0 ) ?
ConnectInfo->InfoArea + ConnectInfo->EaDataOffset : NULL;
// Validate the connection name. The name must start with our device name.
// We can't allow a create on some rogue pathname outside our device
CompareLength = sizeof(DD_SMBMRX_FS_DEVICE_NAME_U);
CompareLength -= ( CompareLength > 0 ) ? sizeof(WCHAR) : 0;
CompareLength = min( CompareLength, ConnectionName.Length );
Validator = (ULONG) RtlCompareMemory( ConnectionName.Buffer, DD_SMBMRX_FS_DEVICE_NAME_U,
CompareLength );
if ( Validator == CompareLength )
{
Status = GetConnectionHandle( &ConnectionName, EaBuffer, EaLength, &Handle );
if ( Status == STATUS_SUCCESS )
{
if ( Handle != INVALID_HANDLE_VALUE )
{
ZwClose( Handle );
}
else
{
Status = STATUS_BAD_NETWORK_NAME;
}
}
}
else
{
Status = STATUS_OBJECT_PATH_NOT_FOUND;
}
}
}
try_return(Status);
try_exit:NOTHING;
} finally {
RxDbgTrace(0, Dbg, ("MRxSmbCreateConnection - exit Status = %08lx\n", Status));
RxDbgTraceUnIndent(-1,Dbg);
}
return Status;
}
NTSTATUS
MRxSmbDeleteConnection (
IN PRX_CONTEXT RxContext,
OUT PBOOLEAN PostToFsp
)
/*++
Routine Description:
Arguments:
IN PRX_CONTEXT RxContext - Describes the Fsctl and Context
Return Value:
RXSTATUS
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
ULONG InBufferLength = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
PBYTE InBuffer = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
PV_NET_ROOT VNetRoot;
PFILE_OBJECT pFileObject;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbDeleteConnection - entry\n"));
if (!Wait) {
//just post right now!
*PostToFsp = TRUE;
return(STATUS_PENDING);
}
Status = STATUS_INVALID_PARAMETER;
try {
PSMBMRX_CONNECTINFO ConnectInfo;
UNICODE_STRING ConnectionName;
PBYTE EaBuffer;
ULONG EaLength;
ULONG Validator;
ULONG CompareLength;
HANDLE Handle;
if ( InBufferLength >= sizeof( PSMBMRX_CONNECTINFO ) )
{
ConnectInfo = (PSMBMRX_CONNECTINFO) InBuffer;
if (((ULONG)(FIELD_OFFSET(SMBMRX_CONNECTINFO, InfoArea)) + (USHORT)ConnectInfo->ConnectionNameOffset +
(USHORT)ConnectInfo->ConnectionNameLength <= InBufferLength) &&
((ULONG)(FIELD_OFFSET(SMBMRX_CONNECTINFO, InfoArea)) + (USHORT)ConnectInfo->EaDataOffset +
(USHORT)ConnectInfo->EaDataLength <= InBufferLength))
{
ConnectionName.Buffer = (PWCHAR) ((PBYTE) ConnectInfo->InfoArea +
ConnectInfo->ConnectionNameOffset);
ConnectionName.Length = (USHORT) ConnectInfo->ConnectionNameLength;
ConnectionName.MaximumLength = (USHORT) ConnectInfo->ConnectionNameLength;
EaLength = ConnectInfo->EaDataLength;
EaBuffer = ( EaLength > 0 ) ?
ConnectInfo->InfoArea + ConnectInfo->EaDataOffset : NULL;
// Validate the connection name. The name must start with our device name.
// We can't allow a create on some rogue pathname outside our device
CompareLength = sizeof(DD_SMBMRX_FS_DEVICE_NAME_U);
CompareLength -= ( CompareLength > 0 ) ? sizeof(WCHAR) : 0;
CompareLength = min( CompareLength, ConnectionName.Length );
Validator = (ULONG) RtlCompareMemory( ConnectionName.Buffer, DD_SMBMRX_FS_DEVICE_NAME_U,
CompareLength );
if ( Validator == CompareLength )
{
Status = GetConnectionHandle( &ConnectionName, EaBuffer, EaLength, &Handle );
if ( Status == STATUS_SUCCESS )
{
if ( Handle != INVALID_HANDLE_VALUE )
{
Status = ObReferenceObjectByHandle( Handle,
0L,
NULL,
KernelMode,
(PVOID *)&pFileObject,
NULL );
if ( NT_SUCCESS(Status) )
{
// VNetRoot exists as FOBx in the FsContext2
VNetRoot = (PV_NET_ROOT) pFileObject->FsContext2;
// make sure the node looks right
if (NodeType(VNetRoot) == RDBSS_NTC_V_NETROOT)
{
RxDbgTrace(-1, Dbg, ("MRxSmbDeleteConnection - Calling RxFinalizeConnection"));
Status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE);
}
else
{
Status = STATUS_BAD_NETWORK_NAME;
}
ObDereferenceObject(pFileObject);
}
ZwClose(Handle);
}
else
{
Status = STATUS_BAD_NETWORK_NAME;
}
}
}
else
{
Status =STATUS_OBJECT_PATH_NOT_FOUND;
}
}
}
try_return(Status);
try_exit:NOTHING;
} finally {
RxDbgTrace(0, Dbg, ("MRxSmbDeleteConnection - exit Status = %08lx\n", Status));
RxDbgTraceUnIndent(-1,Dbg);
}
return Status;
}