windows-nt/Source/XPSP1/NT/base/fs/srv/smbnotfy.c

306 lines
6.6 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
smbnotfy.c
Abstract:
This module contains routine for processing the following SMBs:
NT Notify Change.
Author:
Manny Weiser (mannyw) 29-Oct-1991
Revision History:
--*/
#include "precomp.h"
#include "smbnotfy.tmh"
#pragma hdrstop
//
// Forward declarations
//
VOID SRVFASTCALL
RestartNtNotifyChange (
PWORK_CONTEXT WorkContext
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, SrvSmbNtNotifyChange )
#pragma alloc_text( PAGE, RestartNtNotifyChange )
#pragma alloc_text( PAGE, SrvSmbFindNotify )
#pragma alloc_text( PAGE, SrvSmbFindNotifyClose )
#endif
SMB_TRANS_STATUS
SrvSmbNtNotifyChange (
IN OUT PWORK_CONTEXT WorkContext
)
/*++
Routine Description:
Processes an NT notify change SMB. This request arrives in an
NT Transaction SMB.
Arguments:
WorkContext - Supplies the address of a Work Context Block
describing the current request. See smbtypes.h for a more
complete description of the valid fields.
Return Value:
BOOLEAN - Indicates whether an error occurred. See smbtypes.h for a
more complete description.
--*/
{
PREQ_NOTIFY_CHANGE request;
NTSTATUS status;
PTRANSACTION transaction;
PRFCB rfcb;
USHORT fid;
PAGED_CODE( );
transaction = WorkContext->Parameters.Transaction;
request = (PREQ_NOTIFY_CHANGE)transaction->InSetup;
if( transaction->SetupCount * sizeof( USHORT ) < sizeof( REQ_NOTIFY_CHANGE ) ) {
SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
return SmbTransStatusErrorWithoutData;
}
fid = SmbGetUshort( &request->Fid );
//
// Verify the FID. If verified, the RFCB block is referenced
// and its addresses is stored in the WorkContext block, and the
// RFCB address is returned.
//
rfcb = SrvVerifyFid(
WorkContext,
fid,
TRUE,
NULL, // don't serialize with raw write
&status
);
if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
//
// Invalid file ID or write behind error. Reject the request.
//
IF_DEBUG(ERRORS) {
KdPrint((
"SrvSmbNtIoctl: Status %X on FID: 0x%lx\n",
status,
fid
));
}
SrvSetSmbError( WorkContext, status );
return SmbTransStatusErrorWithoutData;
}
CHECK_FUNCTION_ACCESS(
rfcb->GrantedAccess,
IRP_MJ_DIRECTORY_CONTROL,
IRP_MN_NOTIFY_CHANGE_DIRECTORY,
0,
&status
);
if ( !NT_SUCCESS( status ) ) {
SrvStatistics.GrantedAccessErrors++;
SrvSetSmbError( WorkContext, status );
return SmbTransStatusErrorWithoutData;
}
//
// Set the Restart Routine addresses in the work context block.
//
WorkContext->FsdRestartRoutine = SrvQueueWorkToFspAtDpcLevel;
WorkContext->FspRestartRoutine = RestartNtNotifyChange;
//
// Build the IRP to start a the I/O control.
// Pass this request to the filesystem.
//
SrvBuildNotifyChangeRequest(
WorkContext->Irp,
rfcb->Lfcb->FileObject,
WorkContext,
SmbGetUlong( &request->CompletionFilter ),
transaction->OutParameters,
transaction->MaxParameterCount,
request->WatchTree
);
#if DBG_STUCK
//
// Since change notify can take an arbitrary amount of time, do
// not include it in the "stuck detection & printout" code in the
// scavenger
//
WorkContext->IsNotStuck = TRUE;
#endif
(VOID)IoCallDriver(
IoGetRelatedDeviceObject( rfcb->Lfcb->FileObject ),
WorkContext->Irp
);
//
// The call was successfully started, return InProgress to the caller
//
return SmbTransStatusInProgress;
}
VOID SRVFASTCALL
RestartNtNotifyChange (
PWORK_CONTEXT WorkContext
)
/*++
Routine Description:
Completes processing of an NT Notify Change SMB.
Arguments:
WorkContext - Work context block for the operation.
Return Value:
None.
--*/
{
NTSTATUS status;
PTRANSACTION transaction;
PIRP irp;
ULONG length;
PAGED_CODE( );
//
// If we built an MDL for this IRP, free it now.
//
irp = WorkContext->Irp;
if ( irp->MdlAddress != NULL ) {
MmUnlockPages( irp->MdlAddress );
IoFreeMdl( irp->MdlAddress );
irp->MdlAddress = NULL;
}
status = irp->IoStatus.Status;
if ( !NT_SUCCESS( status ) ) {
SrvSetSmbError( WorkContext, status );
SrvCompleteExecuteTransaction(
WorkContext,
SmbTransStatusErrorWithoutData
);
return;
}
//
// The Notify change request has completed successfully. Send the
// response.
//
length = (ULONG)irp->IoStatus.Information;
transaction = WorkContext->Parameters.Transaction;
if ( irp->UserBuffer != NULL ) {
//
// The file system wanted "neither" I/O for this request. This
// means that the file system will have allocated a system
// buffer for the returned data. Normally this would be copied
// back to our user buffer during I/O completion, but we
// short-circuit I/O completion before the copy happens. So we
// have to copy the data ourselves.
//
if ( irp->AssociatedIrp.SystemBuffer != NULL ) {
ASSERT( irp->UserBuffer == transaction->OutParameters );
RtlCopyMemory( irp->UserBuffer, irp->AssociatedIrp.SystemBuffer, length );
}
}
transaction->SetupCount = 0;
transaction->ParameterCount = length;
transaction->DataCount = 0;
//
// !!! Mask a base notify bug, remove when the bug is fixed.
//
if ( status == STATUS_NOTIFY_CLEANUP ) {
transaction->ParameterCount = 0;
}
SrvCompleteExecuteTransaction( WorkContext, SmbTransStatusSuccess );
return;
} // RestartNtNotifyChange
//
// Since OS/2 chose not to expose the DosFindNotifyFirst/Next/Close APIs,
// OS/2 LAN Man does not officially support these SMBs. This is true,
// even though the Find Notify SMB is documented as a LAN Man 2.0 SMB
// there is code in both the LM2.0 server and redir to support it.
//
// Therefore the NT server will also not support these SMBs.
//
SMB_TRANS_STATUS
SrvSmbFindNotify (
IN OUT PWORK_CONTEXT WorkContext
)
{
PAGED_CODE( );
return SrvTransactionNotImplemented( WorkContext );
}
SMB_PROCESSOR_RETURN_TYPE
SrvSmbFindNotifyClose (
SMB_PROCESSOR_PARAMETERS
)
{
PAGED_CODE( );
return SrvSmbNotImplemented( SMB_PROCESSOR_ARGUMENTS );
}