|
|
/*++
Copyright (c) 1989 - 1999 Microsoft Corporation
Module Name:
devfcb.c
Abstract:
This module implements the mechanism for deleting an established connection
--*/
#include "precomp.h"
#pragma hdrstop
#include "fsctlbuf.h"
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_DEVFCB)
#define FIXED_CONNECT_NAME L"\\;0:\\nulsvr\\share"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, NulMRxDevFcbXXXControlFile)
#endif
NTSTATUS NulMRxDevFcbXXXControlFile ( 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:
a valid NTSTATUS code.
Notes:
--*/ { NTSTATUS Status; RxCaptureFobx; UCHAR MajorFunctionCode = RxContext->MajorFunction; NulMRxGetDeviceExtension(RxContext,pDeviceExtension); PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext; ULONG ControlCode = 0;
DbgPrint("NulMRxDevFcb\n");
switch (MajorFunctionCode) { case IRP_MJ_FILE_SYSTEM_CONTROL: { switch (LowIoContext->ParamsFor.FsCtl.MinorFunction) { case IRP_MN_USER_FS_REQUEST: switch (ControlCode) { default: Status = STATUS_INVALID_DEVICE_REQUEST; } break; default : //minor function != IRP_MN_USER_FS_REQUEST
Status = STATUS_INVALID_DEVICE_REQUEST; } } // FSCTL case
break;
case IRP_MJ_DEVICE_CONTROL: {
ControlCode = LowIoContext->ParamsFor.IoCtl.IoControlCode;
switch (ControlCode) {
case IOCTL_NULMRX_ADDCONN: { Status = NulMRxCreateConnection( RxContext, &RxContext->PostRequest ); } break;
case IOCTL_NULMRX_DELCONN: Status = NulMRxDeleteConnection( RxContext, &RxContext->PostRequest ); break;
case IOCTL_NULMRX_GETLIST: { ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength; PVOID pbOut = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
if ( cbOut >= 26 ) { BOOLEAN GotMutex;
GotMutex = ExTryToAcquireFastMutex( &pDeviceExtension->LCMutex ); RtlCopyMemory( pbOut, pDeviceExtension->LocalConnections, 26 ); if ( GotMutex ) { ExReleaseFastMutex( &pDeviceExtension->LCMutex ); } RxContext->InformationToReturn = 26; } else { RxContext->InformationToReturn = 0; }
Status = STATUS_SUCCESS; } break;
case IOCTL_NULMRX_GETCONN: { UNICODE_STRING LookupName; UNICODE_STRING RemainingName; LOCK_HOLDING_STATE LockHoldingState; PVOID Container; ULONG ReturnedSize = 0;
ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength; PWCHAR ConnectName = LowIoContext->ParamsFor.IoCtl.pInputBuffer; ULONG RemoteNameLen = LowIoContext->ParamsFor.IoCtl.OutputBufferLength; PULONG RemoteName = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
PRX_PREFIX_TABLE pRxNetNameTable = RxContext->RxDeviceObject->pRxNetNameTable;
// insert the local connection name
if ( ConnectNameLen > sizeof( WCHAR ) ) { PWCHAR pLookupName = ExAllocatePool( PagedPool, sizeof(FIXED_CONNECT_NAME) );
RtlCopyMemory( pLookupName, FIXED_CONNECT_NAME, sizeof( FIXED_CONNECT_NAME ) ); pLookupName[2] = ConnectName[0]; LookupName.Buffer = pLookupName; LookupName.Length = sizeof(FIXED_CONNECT_NAME); LookupName.MaximumLength = sizeof(FIXED_CONNECT_NAME); if ( LookupName.Buffer ) { LockHoldingState = LHS_SharedLockHeld;
RxAcquirePrefixTableLockShared(pRxNetNameTable, TRUE); Container = RxPrefixTableLookupName(pRxNetNameTable, &LookupName, &RemainingName, NULL); if (Container) { switch (NodeType(Container)) { case RDBSS_NTC_V_NETROOT: { PMRX_NET_ROOT pNetRoot = ((PV_NET_ROOT)Container)->pNetRoot; RtlCopyMemory( RemoteName, pNetRoot->pNetRootName->Buffer, pNetRoot->pNetRootName->Length ); ReturnedSize = pNetRoot->pNetRootName->Length; RxDereferenceVNetRoot((PV_NET_ROOT)Container, LockHoldingState); } break; case RDBSS_NTC_NETROOT: { PNET_ROOT pNetRoot = (PNET_ROOT) Container; RtlCopyMemory( RemoteName, pNetRoot->pNetRootName->Buffer, pNetRoot->pNetRootName->Length ); ReturnedSize = pNetRoot->pNetRootName->Length; RxDereferenceNetRoot((PNET_ROOT)Container, LockHoldingState); } break;
case RDBSS_NTC_SRVCALL: RxDereferenceSrvCall((PSRV_CALL)Container, LockHoldingState); ReturnedSize = 0; break; default: RxDereference((PVOID)Container,LockHoldingState); ReturnedSize = 0; break; } }
RxReleasePrefixTableLock(pRxNetNameTable); ExFreePool( LookupName.Buffer ); } } if ( ReturnedSize ) { Status = STATUS_SUCCESS; } else { Status = STATUS_BAD_NETWORK_NAME; } RxContext->InformationToReturn = ReturnedSize; } break;
default : Status = STATUS_INVALID_DEVICE_REQUEST; } } break;
case IRP_MJ_INTERNAL_DEVICE_CONTROL: { switch (ControlCode) { default : Status = STATUS_INVALID_DEVICE_REQUEST; } } break;
default: ASSERT(!"unimplemented major function"); Status = STATUS_INVALID_DEVICE_REQUEST; }
DbgPrint("NulMRxDevFcb st,info=%08lx,%08lx\n", Status,RxContext->InformationToReturn); return(Status); }
HANDLE GetConnectionHandle( IN PUNICODE_STRING ConnectionName ) {
NTSTATUS Status; HANDLE Handle; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING FileName;
// Connection name should get checked to be certain our device is in the path
InitializeObjectAttributes( &ObjectAttributes, ConnectionName, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwCreateFile( &Handle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, // Allocation size
FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT, NULL, // Ptr to EA Buffer
0); // Length of EA buffer
DbgPrint("ZwCreateFile returned %lx\n",Status);
if ( (STATUS_SUCCESS == Status) && (INVALID_HANDLE_VALUE != Handle) ) { DbgPrint("ZwCreateFile returned success\n"); } else Handle = INVALID_HANDLE_VALUE;
return Handle; }
NTSTATUS DoCreateConnection( IN PRX_CONTEXT RxContext, ULONG CreateDisposition ) {
NTSTATUS Status = STATUS_SUCCESS; HANDLE Handle; PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext; ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength; PWCHAR ConnectName = LowIoContext->ParamsFor.IoCtl.pInputBuffer; UNICODE_STRING FileName; NulMRxGetDeviceExtension(RxContext,pDeviceExtension);
// The sample code passes in only the filename in the Ioctl data buffer.
// An actual implementation could pass in stuff like EAs, security
// credentials, etc
RxDbgTrace(0, Dbg,("DoCreateConnection"));
FileName.Buffer = ConnectName; FileName.Length = (USHORT) ConnectNameLen; FileName.MaximumLength = (USHORT) ConnectNameLen;
Handle = GetConnectionHandle(&FileName);
if ( INVALID_HANDLE_VALUE != Handle ) { PWCHAR pwcLC; ULONG i;
DbgPrint("GetConnectionHandle returned success\n"); ZwClose(Handle);
for ( i = 0, pwcLC = (PWCHAR) ConnectName; i < ConnectNameLen && *pwcLC!= L':'; i+=sizeof(WCHAR), pwcLC++ );
if ( i >= sizeof(WCHAR) && i < ConnectNameLen ) { pwcLC--; if ( *pwcLC >= L'A' && *pwcLC <= L'Z' ) { ExAcquireFastMutex( &pDeviceExtension->LCMutex ); pDeviceExtension->LocalConnections[*pwcLC - L'A'] = TRUE; ExReleaseFastMutex( &pDeviceExtension->LCMutex ); } } } else { DbgPrint("GetConnectionHandle returned failure\n"); Status = STATUS_BAD_NETWORK_NAME; }
return(Status); }
NTSTATUS NulMRxCreateConnection ( IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp ) /*++
Routine Description:
Arguments:
IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
Return Value:
RXSTATUS
--*/ { NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT); BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
PAGED_CODE();
DbgPrint("NulMrxCreateConnection called\n"); RxDbgTrace(+1, Dbg, ("NulMRxCreateConnection \n"));
if (!Wait) { //just post right now!
*PostToFsp = TRUE; return STATUS_PENDING; }
Status = DoCreateConnection(RxContext, (ULONG)FILE_OPEN_IF);
return Status; }
NTSTATUS DoDeleteConnection( PUNICODE_STRING FileName ) { HANDLE Handle; NTSTATUS Status = STATUS_INVALID_HANDLE; PFILE_OBJECT pFileObject; PNET_ROOT NetRoot; PV_NET_ROOT VNetRoot; PFOBX Fobx;
Handle = GetConnectionHandle(FileName);
if ( INVALID_HANDLE_VALUE != Handle ) { DbgPrint("GetConnectionHandle returned success\n");
Status = ObReferenceObjectByHandle( Handle, 0L, NULL, KernelMode, (PVOID *)&pFileObject, NULL);
DbgPrint("ObReferenceObjectByHandle worked ok\n"); if ( NT_SUCCESS(Status) ) {
// Got the FileObject. Now get an Fobx
Fobx = pFileObject->FsContext2; if (NodeType(Fobx)==RDBSS_NTC_V_NETROOT) { VNetRoot = (PV_NET_ROOT)(Fobx); NetRoot = (PNET_ROOT)VNetRoot->NetRoot; DbgPrint("Calling RxFinalizeConnection\n"); Status = RxFinalizeConnection(NetRoot,VNetRoot,TRUE); } else { ASSERT(FALSE); Status = STATUS_INVALID_DEVICE_REQUEST; }
ObDereferenceObject(pFileObject); }
ZwClose(Handle); }
return Status; }
NTSTATUS NulMRxDeleteConnection ( IN PRX_CONTEXT RxContext, OUT PBOOLEAN PostToFsp ) /*++
Routine Description:
This routine deletes a single vnetroot.
Arguments:
IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
Return Value:
RXSTATUS
--*/ { NTSTATUS Status; UNICODE_STRING FileName; BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT); PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext; PWCHAR ConnectName = LowIoContext->ParamsFor.IoCtl.pInputBuffer; ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength; NulMRxGetDeviceExtension(RxContext,pDeviceExtension);
PAGED_CODE();
//RxDbgTrace(+1, Dbg, ("NulMRxDeleteConnection Fobx %08lx\n", capFobx));
if (!Wait) { //just post right now!
*PostToFsp = TRUE; return(STATUS_PENDING); }
FileName.Buffer = ConnectName; FileName.Length = (USHORT) ConnectNameLen; FileName.MaximumLength = (USHORT) ConnectNameLen;
Status = DoDeleteConnection(&FileName);
if ( NT_SUCCESS(Status) ) { PWCHAR pwcLC; ULONG i;
for ( i = 0, pwcLC = ConnectName; i < ConnectNameLen && *pwcLC!= L':'; i+=sizeof(WCHAR), pwcLC++ ); if ( i >= sizeof(WCHAR) && i < ConnectNameLen ) { pwcLC--; if ( *pwcLC >= L'A' && *pwcLC <= L'Z' ) { ExAcquireFastMutex( &pDeviceExtension->LCMutex ); pDeviceExtension->LocalConnections[*pwcLC - L'A'] = FALSE; ExReleaseFastMutex( &pDeviceExtension->LCMutex ); } } }
return Status;
}
|