306 lines
6.6 KiB
C
306 lines
6.6 KiB
C
|
/*++
|
|||
|
|
|||
|
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 );
|
|||
|
}
|
|||
|
|