Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

661 lines
16 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
NtDevFcb.c
Abstract:
This module implements the FSD level Close, CleanUp, and FsCtl and IoCtl routines for RxDevice
files. Also, the createroutine is not here; rather, it is called from CommonCreate and
not called directly by the dispatch driver.
Each of the pieces listed (close, cleanup, fsctl, ioctl) has its own little section of the
file......complete with its own forward-prototypes and alloc pragmas
Author:
Joe Linn [JoeLinn] 3-aug-1994
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include <ntddnfs2.h>
#include <ntddmup.h>
#include "fsctlbuf.h"
#include "prefix.h"
#include "rxce.h"
//
// The local trace mask for this part of the module
//
#define Dbg (DEBUG_TRACE_DEVFCB)
NTSTATUS
RxXXXControlFileCallthru(
IN PRX_CONTEXT RxContext
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RxCommonDevFCBFsCtl)
#pragma alloc_text(PAGE, RxXXXControlFileCallthru)
#pragma alloc_text(PAGE, RxCommonDevFCBClose)
#pragma alloc_text(PAGE, RxCommonDevFCBCleanup)
#pragma alloc_text(PAGE, RxGetUid)
#endif
NTSTATUS
RxXXXControlFileCallthru(
IN PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine calls down to the minirdr to implement ioctl and fsctl controls that
the wrapper doesn't understand. note that if there is no dispatch defined (i.e. for the
wrapper's own device object) then we also set Rxcontext->Fobx to NULL so that the caller
won't try to go thru lowio to get to the minirdr.
Arguments:
RxContext - the context of the request
Return Value:
RXSTATUS - The FSD status for the request include the PostRequest field....
--*/
{
NTSTATUS Status;
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
RxCaptureRequestPacket;
PAGED_CODE();
if (RxContext->RxDeviceObject->Dispatch == NULL) {
RxContext->pFobx = NULL; //don't try again on lowio
return(STATUS_INVALID_DEVICE_REQUEST);
}
Status = RxLowIoPopulateFsctlInfo (RxContext);
if (Status != STATUS_SUCCESS) {
return Status;
}
if ((LowIoContext->ParamsFor.FsCtl.InputBufferLength > 0) &&
(LowIoContext->ParamsFor.FsCtl.pInputBuffer == NULL)) {
return STATUS_INVALID_PARAMETER;
}
if ((LowIoContext->ParamsFor.FsCtl.OutputBufferLength > 0) &&
(LowIoContext->ParamsFor.FsCtl.pOutputBuffer == NULL)) {
return STATUS_INVALID_PARAMETER;
}
Status = (RxContext->RxDeviceObject->Dispatch->MRxDevFcbXXXControlFile)(RxContext);
if (Status!=STATUS_PENDING) {
capReqPacket->IoStatus.Information = RxContext->InformationToReturn;
}
return(Status);
}
NTSTATUS
RxCommonDevFCBClose ( RXCOMMON_SIGNATURE )
/*++
Routine Description:
This routine implements the FSD Close for a Device FCB.
Arguments:
RxDeviceObject - Supplies the volume device object where the
file exists
Irp - Supplies the Irp being processed
Return Value:
RXSTATUS - The FSD status for the IRP
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
RxCaptureRequestPacket;
RxCaptureFcb;
RxCaptureFobx;
RxCaptureParamBlock;
RxCaptureFileObject;
PRX_PREFIX_TABLE pRxNetNameTable
= RxContext->RxDeviceObject->pRxNetNameTable;
PAGED_CODE();
RxDbgTrace(0, Dbg, ("RxCommonDevFCBClose\n", 0));
RxLog(("DevFcbClose %lx %lx\n",RxContext,capFileObject));
RxWmiLog(LOG,
RxCommonDevFCBClose,
LOGPTR(RxContext)
LOGPTR(capFileObject));
ASSERT (NodeType(capFcb) == RDBSS_NTC_DEVICE_FCB);
// deal with the device fcb
if (!capFobx) {
capFcb->OpenCount--;
return STATUS_SUCCESS;
}
//otherwise, it's a connection-type file. you have to get the lock; then case-out
RxAcquirePrefixTableLockExclusive(pRxNetNameTable, TRUE);
try {
switch (NodeType(capFobx)) {
case RDBSS_NTC_V_NETROOT:
{
PV_NET_ROOT VNetRoot = (PV_NET_ROOT)capFobx;
VNetRoot->NumberOfOpens--;
RxDereferenceVNetRoot(VNetRoot,LHS_ExclusiveLockHeld);
}
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
}
try_return(NOTHING); //eliminate warning
try_exit: NOTHING;
} finally {
RxReleasePrefixTableLock( pRxNetNameTable );
}
return Status;
}
NTSTATUS
RxCommonDevFCBCleanup ( RXCOMMON_SIGNATURE )
/*++
Routine Description:
This routine implements the FSD part of closing down a handle to a
device FCB.
Arguments:
RxDeviceObject - Supplies the volume device object where the
file being Cleanup exists
Irp - Supplies the Irp being processed
Return Value:
RXSTATUS - The FSD status for the IRP
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
RxCaptureRequestPacket;
RxCaptureFcb;
RxCaptureFobx;
RxCaptureParamBlock;
RxCaptureFileObject;
PAGED_CODE();
RxDbgTrace(0, Dbg, ("RxCommonFCBCleanup\n", 0));
RxLog(("DevFcbCleanup %lx\n",RxContext,capFileObject));
RxWmiLog(LOG,
RxCommonDevFCBCleanup,
LOGPTR(RxContext)
LOGPTR(capFileObject));
ASSERT (NodeType(capFcb) == RDBSS_NTC_DEVICE_FCB);
// deal with the device fcb
if (!capFobx) {
capFcb->UncleanCount--;
// RxCompleteContextAndReturn( RxStatus(SUCCESS) );
return STATUS_SUCCESS;
}
//otherwise, it's a connection-type file. you have to get the lock; then case-out
RxAcquirePrefixTableLockShared(RxContext->RxDeviceObject->pRxNetNameTable, TRUE);
try {
switch (NodeType(capFobx)) {
Status = STATUS_SUCCESS;
case RDBSS_NTC_V_NETROOT:
//nothing to do
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
}
try_return(NOTHING); //eliminate warning
try_exit: NOTHING;
} finally {
RxReleasePrefixTableLock( RxContext->RxDeviceObject->pRxNetNameTable );
}
// RxCompleteContextAndReturn( Status );
return Status;
}
// | *********************|
// | | F S C T L ||
// | *********************|
//
NTSTATUS
RxCommonDevFCBFsCtl ( RXCOMMON_SIGNATURE )
/*++
Routine Description:
This is the common routine for doing FileSystem control operations called
by both the fsd and fsp threads
Arguments:
RxContext - Supplies the Irp to process and stateinfo about where we are
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
RxCaptureRequestPacket;
RxCaptureFobx;
RxCaptureParamBlock;
ULONG FsControlCode = capPARAMS->Parameters.FileSystemControl.FsControlCode;
PAGED_CODE();
RxDbgTrace (+1, Dbg, ("RxCommonDevFCBFsCtl IrpC = %08lx\n", RxContext));
RxDbgTrace( 0, Dbg, ("MinorFunction = %08lx, ControlCode = %08lx \n",
capPARAMS->MinorFunction, FsControlCode));
RxLog(("DevFcbFsCtl %lx %lx %lx\n",RxContext,capPARAMS->MinorFunction,FsControlCode));
RxWmiLog(LOG,
RxCommonDevFCBFsCtl,
LOGPTR(RxContext)
LOGUCHAR(capPARAMS->MinorFunction)
LOGULONG(FsControlCode));
//
// We know this is a file system control so we'll case on the
// minor function, and call a internal worker routine to complete
// the irp.
//
switch (capPARAMS->MinorFunction) {
case IRP_MN_USER_FS_REQUEST:
switch (FsControlCode) {
#ifdef RDBSSLOG
case FSCTL_LMR_DEBUG_TRACE:
//
// This FSCTL is being disabled since no one uses this anymore. If
// it needs to be reactivated for some reason, the appropriate
// checks have to be added to make sure that the IRP->UserBuffer is
// a valid address. The try/except call below won't protect against
// a random kernel address being passed.
//
return STATUS_INVALID_DEVICE_REQUEST;
// the 2nd buffer points to the string
//
// We need to try/except this call to protect against random buffers
// being passed in from UserMode.
//
try {
RxDebugControlCommand(capReqPacket->UserBuffer);
} except (EXCEPTION_EXECUTE_HANDLER) {
return STATUS_INVALID_USER_BUFFER;
}
Status = STATUS_SUCCESS;
break;
#endif //RDBSSLOG
default:
RxDbgTrace(0, Dbg, ("RxFsdDevFCBFsCTL unknown user request\n"));
Status = RxXXXControlFileCallthru(RxContext);
if ( (Status == STATUS_INVALID_DEVICE_REQUEST) && (RxContext->pFobx!=NULL) ) {
RxDbgTrace(0, Dbg, ("RxCommonDevFCBFsCtl -> Invoking Lowio for FSCTL\n"));
Status = RxLowIoFsCtlShell(RxContext);
}
}
break;
default :
RxDbgTrace(0, Dbg, ("RxFsdDevFCBFsCTL nonuser request!!\n", 0));
Status = RxXXXControlFileCallthru(RxContext);
}
if (RxContext->PostRequest) {
Status = RxFsdPostRequestWithResume(RxContext,RxCommonDevFCBFsCtl);
}
RxDbgTrace(-1, Dbg, ("RxCommonDevFCBFsCtl -> %08lx\n", Status));
return Status;
}
// | *********************|
// | | I O C T L ||
// | *********************|
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RxCommonDevFCBIoCtl)
#endif
NTSTATUS
RxCommonDevFCBIoCtl ( RXCOMMON_SIGNATURE )
/*++
Routine Description:
This is the common routine for doing FileSystem control operations called
by both the fsd and fsp threads
Arguments:
RxContext - Supplies the Irp to process and stateinfo about where we are
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
RxCaptureRequestPacket; RxCaptureFobx;
RxCaptureParamBlock;
ULONG IoControlCode = capPARAMS->Parameters.DeviceIoControl.IoControlCode;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("RxCommonDevFCBIoCtl IrpC-%08lx\n", RxContext));
RxDbgTrace( 0, Dbg, ("ControlCode = %08lx\n", IoControlCode));
if (capFobx == NULL) {
switch (IoControlCode) {
case IOCTL_REDIR_QUERY_PATH:
Status = RxPrefixClaim(RxContext);
break;
default:
{
Status = RxXXXControlFileCallthru(RxContext);
if ((Status != STATUS_PENDING) && RxContext->PostRequest) {
Status = RxFsdPostRequestWithResume(RxContext,RxCommonDevFCBIoCtl);
}
}
break;
}
} else {
Status = STATUS_INVALID_HANDLE;
}
RxDbgTrace(-1, Dbg, ("RxCommonDevFCBIoCtl -> %08lx\n", Status));
return Status;
}
//
// Utility Routine
//
LUID
RxGetUid(
IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
)
/*++
Routine Description:
This routine gets the effective UID to be used for this create.
Arguments:
SubjectSecurityContext - Supplies the information from IrpSp.
Return Value:
None
--*/
{
LUID LogonId;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("RxGetUid ... \n", 0));
// Is the thread currently impersonating someone else?
if (SubjectSecurityContext->ClientToken != NULL) {
//
// If its impersonating someone that is logged in locally then use
// the local id.
//
SeQueryAuthenticationIdToken(SubjectSecurityContext->ClientToken, &LogonId);
} else {
//
// Use the processes LogonId
//
SeQueryAuthenticationIdToken(SubjectSecurityContext->PrimaryToken, &LogonId);
}
RxDbgTrace(-1, Dbg, (" ->UserUidHigh/Low = %08lx %08lx\n", LogonId.HighPart, LogonId.LowPart));
return LogonId;
}
// | *********************|
// | | V O L I N F O ||
// | *********************|
NTSTATUS
RxDevFcbQueryDeviceInfo (
IN PRX_CONTEXT RxContext,
OUT PBOOLEAN PostToFsp,
PFILE_FS_DEVICE_INFORMATION UsersBuffer,
ULONG BufferSize,
PULONG ReturnedLength
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RxCommonDevFCBQueryVolInfo)
#pragma alloc_text(PAGE, RxDevFcbQueryDeviceInfo)
#endif
NTSTATUS
RxCommonDevFCBQueryVolInfo ( RXCOMMON_SIGNATURE )
/*++
Routine Description:
This is the common routine for doing FileSystem control operations called
by both the fsd and fsp threads
Arguments:
RxContext - Supplies the Irp to process and stateinfo about where we are
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
BOOLEAN PostToFsp = FALSE;
RxCaptureRequestPacket;
RxCaptureParamBlock;
FS_INFORMATION_CLASS InformationClass = capPARAMS->Parameters.QueryVolume.FsInformationClass;
PVOID UsersBuffer = capReqPacket->AssociatedIrp.SystemBuffer;
ULONG BufferSize = capPARAMS->Parameters.QueryVolume.Length;
ULONG ReturnedLength;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("RxCommonDevFCBQueryVolInfo IrpC-%08lx\n", RxContext));
RxDbgTrace( 0, Dbg, ("ControlCode = %08lx\n", InformationClass));
RxLog(("DevFcbQVolInfo %lx %lx\n",RxContext,InformationClass));
RxWmiLog(LOG,
RxCommonDevFCBQueryVolInfo,
LOGPTR(RxContext)
LOGULONG(InformationClass));
switch (InformationClass) {
case FileFsDeviceInformation:
Status = RxDevFcbQueryDeviceInfo (RxContext, &PostToFsp, UsersBuffer, BufferSize, &ReturnedLength);
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
};
RxDbgTrace(-1, Dbg, ("RxCommonDevFCBQueryVolInfo -> %08lx\n", Status));
if ( PostToFsp ) return RxFsdPostRequestWithResume(RxContext,RxCommonDevFCBQueryVolInfo);
if (Status==STATUS_SUCCESS) {
capReqPacket->IoStatus.Information = ReturnedLength;
}
// RxCompleteContextAndReturn( Status );
return Status;
}
NTSTATUS
RxDevFcbQueryDeviceInfo (
IN PRX_CONTEXT RxContext,
OUT PBOOLEAN PostToFsp,
PFILE_FS_DEVICE_INFORMATION UsersBuffer,
ULONG BufferSize,
PULONG ReturnedLength
)
/*++
Routine Description:
This routine shuts down up the RDBSS filesystem...i.e. we connect to the MUP. We can only shut down
if there's no netroots and if there's only one deviceFCB handle.
Arguments:
IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
Return Value:
RXSTATUS
--*/
{
NTSTATUS Status;
RxCaptureFobx;
BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
PAGED_CODE();
RxDbgTrace(0, Dbg, ("RxDevFcbQueryDeviceInfo -> %08lx\n", 0));
if (BufferSize < sizeof(FILE_FS_DEVICE_INFORMATION)) {
return STATUS_BUFFER_OVERFLOW;
};
UsersBuffer->Characteristics = FILE_REMOTE_DEVICE;
*ReturnedLength = sizeof(FILE_FS_DEVICE_INFORMATION);
// deal with the device fcb
if (!capFobx) {
UsersBuffer->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
return(STATUS_SUCCESS);
}
//otherwise, it's a connection-type file. you have to get the lock; then case-out
if (!RxAcquirePrefixTableLockShared(RxContext->RxDeviceObject->pRxNetNameTable, Wait)) {
*PostToFsp = TRUE;
return STATUS_PENDING;
}
try {
Status = STATUS_SUCCESS;
switch (NodeType(capFobx)) {
case RDBSS_NTC_V_NETROOT: {
PV_NET_ROOT VNetRoot = (PV_NET_ROOT)capFobx;
PNET_ROOT NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
if (NetRoot->Type==NET_ROOT_PIPE) {
NetRoot->DeviceType = RxDeviceType(NAMED_PIPE);
}
UsersBuffer->DeviceType = NetRoot->DeviceType;
}
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
}
try_return(NOTHING); //eliminate warning
try_exit: NOTHING;
} finally {
RxReleasePrefixTableLock( RxContext->RxDeviceObject->pRxNetNameTable );
}
return Status;
}