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.
744 lines
18 KiB
744 lines
18 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,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
RxDevFcbQueryDeviceInfo (
|
|
IN PRX_CONTEXT RxContext,
|
|
IN PFOBX Fobx,
|
|
OUT PBOOLEAN PostToFsp,
|
|
PFILE_FS_DEVICE_INFORMATION UsersBuffer,
|
|
ULONG BufferSize,
|
|
PULONG ReturnedLength
|
|
);
|
|
|
|
|
|
#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)
|
|
#pragma alloc_text(PAGE, RxCommonDevFCBIoCtl)
|
|
#pragma alloc_text(PAGE, RxCommonDevFCBQueryVolInfo)
|
|
#pragma alloc_text(PAGE, RxDevFcbQueryDeviceInfo)
|
|
#endif
|
|
|
|
NTSTATUS
|
|
RxXXXControlFileCallthru (
|
|
IN PRX_CONTEXT RxContext,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
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
|
|
|
|
Irp - the current irp
|
|
|
|
Return Value:
|
|
|
|
RXSTATUS - The FSD status for the request include the PostRequest field....
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (RxContext->RxDeviceObject->Dispatch == NULL) {
|
|
|
|
//
|
|
// don't try again on lowio
|
|
//
|
|
|
|
RxContext->pFobx = NULL;
|
|
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
Status = RxLowIoPopulateFsctlInfo( RxContext, Irp );
|
|
|
|
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) {
|
|
|
|
Irp->IoStatus.Information = RxContext->InformationToReturn;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
RxCommonDevFCBClose (
|
|
IN PRX_CONTEXT RxContext,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
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;
|
|
|
|
PFILE_OBJECT FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
|
|
PFOBX Fobx;
|
|
PFCB Fcb;
|
|
NODE_TYPE_CODE TypeOfOpen;
|
|
PRX_PREFIX_TABLE RxNetNameTable = RxContext->RxDeviceObject->pRxNetNameTable;
|
|
|
|
PAGED_CODE();
|
|
|
|
TypeOfOpen = RxDecodeFileObject( FileObject, &Fcb, &Fobx );
|
|
|
|
RxDbgTrace( 0, Dbg, ("RxCommonDevFCBClose\n", 0) );
|
|
RxLog(( "DevFcbClose %lx %lx\n",RxContext, FileObject ));
|
|
RxWmiLog( LOG,
|
|
RxCommonDevFCBClose,
|
|
LOGPTR( RxContext )
|
|
LOGPTR( FileObject ) );
|
|
|
|
if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB) {
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
//
|
|
// deal with the device fcb
|
|
//
|
|
|
|
if (!Fobx) {
|
|
Fcb->OpenCount -= 1;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// otherwise, it's a connection-type file. you have to get the lock; then case-out
|
|
//
|
|
|
|
RxAcquirePrefixTableLockExclusive( RxNetNameTable, TRUE );
|
|
|
|
try {
|
|
|
|
switch (NodeType( Fobx )) {
|
|
|
|
case RDBSS_NTC_V_NETROOT:
|
|
{
|
|
PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
|
|
|
|
VNetRoot->NumberOfOpens -= 1;
|
|
RxDereferenceVNetRoot( VNetRoot, LHS_ExclusiveLockHeld );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
} finally {
|
|
RxReleasePrefixTableLock( RxNetNameTable );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
RxCommonDevFCBCleanup (
|
|
IN PRX_CONTEXT RxContext,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
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;
|
|
|
|
PFILE_OBJECT FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
|
|
PFOBX Fobx;
|
|
PFCB Fcb;
|
|
NODE_TYPE_CODE TypeOfOpen;
|
|
|
|
|
|
PAGED_CODE();
|
|
|
|
TypeOfOpen = RxDecodeFileObject( FileObject, &Fcb, &Fobx );
|
|
|
|
RxDbgTrace( 0, Dbg, ("RxCommonFCBCleanup\n", 0) );
|
|
RxLog(( "DevFcbCleanup %lx\n", RxContext, FileObject ));
|
|
RxWmiLog( LOG,
|
|
RxCommonDevFCBCleanup,
|
|
LOGPTR( RxContext )
|
|
LOGPTR( FileObject ) );
|
|
|
|
if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB) {
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
//
|
|
// deal with the device fcb
|
|
//
|
|
|
|
if (!Fobx) {
|
|
|
|
Fcb->UncleanCount -= 1;
|
|
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 {
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
switch (NodeType( Fobx )) {
|
|
|
|
case RDBSS_NTC_V_NETROOT:
|
|
|
|
//
|
|
// nothing to do
|
|
//
|
|
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
} finally {
|
|
RxReleasePrefixTableLock( RxContext->RxDeviceObject->pRxNetNameTable );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// | *********************|
|
|
// | | F S C T L ||
|
|
// | *********************|
|
|
//
|
|
|
|
|
|
NTSTATUS
|
|
RxCommonDevFCBFsCtl (
|
|
IN PRX_CONTEXT RxContext,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
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;
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
PFOBX Fobx;
|
|
PFCB Fcb;
|
|
NODE_TYPE_CODE TypeOfOpen;
|
|
ULONG FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
|
|
|
|
PAGED_CODE();
|
|
|
|
TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx );
|
|
|
|
RxDbgTrace( +1, Dbg, ("RxCommonDevFCBFsCtl IrpC = %08lx\n", RxContext) );
|
|
RxDbgTrace( 0, Dbg, ("MinorFunction = %08lx, ControlCode = %08lx \n",
|
|
IrpSp->MinorFunction, FsControlCode) );
|
|
RxLog(( "DevFcbFsCtl %lx %lx %lx\n", RxContext, IrpSp->MinorFunction, FsControlCode ));
|
|
RxWmiLog( LOG,
|
|
RxCommonDevFCBFsCtl,
|
|
LOGPTR( RxContext )
|
|
LOGUCHAR( IrpSp->MinorFunction )
|
|
LOGULONG( FsControlCode ) );
|
|
|
|
if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB ) {
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
//
|
|
// 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 (IrpSp->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( Irp->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, Irp );
|
|
if ((Status == STATUS_INVALID_DEVICE_REQUEST) && (Fobx != NULL)) {
|
|
|
|
RxDbgTrace( 0, Dbg, ("RxCommonDevFCBFsCtl -> Invoking Lowio for FSCTL\n") );
|
|
Status = RxLowIoFsCtlShell( RxContext, Irp, Fcb, Fobx );
|
|
}
|
|
}
|
|
break;
|
|
|
|
default :
|
|
RxDbgTrace( 0, Dbg, ("RxFsdDevFCBFsCTL nonuser request!!\n", 0) );
|
|
Status = RxXXXControlFileCallthru( RxContext, Irp );
|
|
}
|
|
|
|
|
|
if (RxContext->PostRequest) {
|
|
Status = RxFsdPostRequestWithResume( RxContext, RxCommonDevFCBFsCtl );
|
|
}
|
|
|
|
RxDbgTrace(-1, Dbg, ("RxCommonDevFCBFsCtl -> %08lx\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// | *********************|
|
|
// | | I O C T L ||
|
|
// | *********************|
|
|
//
|
|
|
|
|
|
|
|
NTSTATUS
|
|
RxCommonDevFCBIoCtl (
|
|
IN PRX_CONTEXT RxContext,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
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;
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
PFCB Fcb;
|
|
PFOBX Fobx;
|
|
NODE_TYPE_CODE TypeOfOpen;
|
|
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
PAGED_CODE();
|
|
|
|
TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx );
|
|
|
|
RxDbgTrace( +1, Dbg, ("RxCommonDevFCBIoCtl IrpC-%08lx\n", RxContext) );
|
|
RxDbgTrace( 0, Dbg, ("ControlCode = %08lx\n", IoControlCode) );
|
|
|
|
if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB ) {
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
if (Fobx == NULL) {
|
|
|
|
switch (IoControlCode) {
|
|
|
|
case IOCTL_REDIR_QUERY_PATH:
|
|
//
|
|
// This particular IOCTL should only come to us from the MUP and
|
|
// hence the requestor mode of the IRP should always be KernelMode.
|
|
// If its not we return STATUS_INVALID_DEVICE_REQUEST.
|
|
//
|
|
if (Irp->RequestorMode != KernelMode) {
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
} else {
|
|
Status = RxPrefixClaim( RxContext );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Status = RxXXXControlFileCallthru( RxContext, Irp );
|
|
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));
|
|
|
|
//
|
|
// Use SeQuerySubjectContextToken to get the proper token in case of impersonation
|
|
//
|
|
|
|
SeQueryAuthenticationIdToken( SeQuerySubjectContextToken( SubjectSecurityContext ), &LogonId );
|
|
RxDbgTrace( -1, Dbg, (" ->UserUidHigh/Low = %08lx %08lx\n", LogonId.HighPart, LogonId.LowPart) );
|
|
|
|
return LogonId;
|
|
}
|
|
|
|
//
|
|
// | *********************|
|
|
// | | V O L I N F O ||
|
|
// | *********************|
|
|
//
|
|
|
|
NTSTATUS
|
|
RxCommonDevFCBQueryVolInfo (
|
|
IN PRX_CONTEXT RxContext,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
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:
|
|
|
|
NTSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
FS_INFORMATION_CLASS InformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
|
|
PFCB Fcb;
|
|
PFOBX Fobx;
|
|
NODE_TYPE_CODE TypeOfOpen;
|
|
|
|
PVOID UsersBuffer = Irp->AssociatedIrp.SystemBuffer;
|
|
ULONG BufferSize = IrpSp->Parameters.QueryVolume.Length;
|
|
ULONG ReturnedLength;
|
|
BOOLEAN PostToFsp = FALSE;
|
|
|
|
PAGED_CODE();
|
|
|
|
TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx );
|
|
|
|
if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB ) {
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
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, Fobx, &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) {
|
|
Irp->IoStatus.Information = ReturnedLength;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
RxDevFcbQueryDeviceInfo (
|
|
IN PRX_CONTEXT RxContext,
|
|
IN PFOBX Fobx,
|
|
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:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
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 (!Fobx) {
|
|
|
|
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( Fobx )) {
|
|
|
|
case RDBSS_NTC_V_NETROOT:
|
|
{
|
|
PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
|
|
PNET_ROOT NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
|
|
|
|
if (NetRoot->Type == NET_ROOT_PIPE) {
|
|
NetRoot->DeviceType = FILE_DEVICE_NAMED_PIPE;
|
|
}
|
|
|
|
UsersBuffer->DeviceType = NetRoot->DeviceType;
|
|
}
|
|
break;
|
|
default:
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
} finally {
|
|
RxReleasePrefixTableLock( RxContext->RxDeviceObject->pRxNetNameTable );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|