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.
 
 
 
 
 
 

495 lines
15 KiB

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