|
|
/*++
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; }
|