/*++ Copyright (c) 1989 Microsoft Corporation Module Name: Ea.c Abstract: This module implements the EA, security and quota routines for Rx called by the dispatch driver. Author: Joe Linn [JoeLi] 1-Jan-95 Revision History: --*/ #include "precomp.h" #pragma hdrstop // // The local debug trace level // #define Dbg (DEBUG_TRACE_EA) #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, RxCommonQueryEa) #pragma alloc_text(PAGE, RxCommonSetEa) #pragma alloc_text(PAGE, RxCommonQuerySecurity) #pragma alloc_text(PAGE, RxCommonSetSecurity) #endif typedef NTSTATUS (NTAPI *PRX_MISC_OP_ROUTINE) ( IN PRX_CONTEXT RxContext, IN PIRP Irp, IN PFCB Fcb ); NTSTATUS RxpCommonMiscOp ( IN PRX_CONTEXT RxContext, IN PIRP Irp, IN PFCB Fcb, IN PRX_MISC_OP_ROUTINE MiscOpRoutine ) /*++ Routine Description: Main stub that all the common routines below use - this does the common work such as acquiring the fcb, parameter validation and posting if necc. Arguments: RxContext - the rxcontext Fcb - the fcb being used MiscOpRoutine - The callback that does the real work Return Value: Notes: --*/ { NTSTATUS Status; NODE_TYPE_CODE TypeOfOpen = NodeType( Fcb ); if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) && (TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) { RxDbgTrace( -1, Dbg, ("RxpCommonMiscOp -> %08lx\n", STATUS_INVALID_PARAMETER) ); return STATUS_INVALID_PARAMETER; } if (!FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT )) { RxDbgTrace( 0, Dbg, ("RxpCommonMiscOp: Set Ea must be waitable....posting\n", 0) ); Status = RxFsdPostRequest( RxContext ); RxDbgTrace(-1, Dbg, ("RxpCommonMiscOp -> %08lx\n", Status )); return Status; } Status = RxAcquireExclusiveFcb( RxContext, Fcb ); if (Status != STATUS_SUCCESS) { RxDbgTrace( -1, Dbg, ("RxpCommonMiscOp -> Error Acquiring Fcb %08lx\n", Status) ); return Status; } try { Status = (*MiscOpRoutine)( RxContext, Irp, Fcb ); } finally { DebugUnwind( *MiscOpRoutine ); RxReleaseFcb( RxContext, Fcb ); RxDbgTrace( -1, Dbg, ("RxpCommonMiscOp -> %08lx\n", Status )); } return Status; } NTSTATUS RxpCommonQuerySecurity ( IN PRX_CONTEXT RxContext, IN PIRP Irp, IN PFCB Fcb ) /*++ Routine Description: Callback that implements the query security call Arguments: RxContext - Irp - Fcb - Return Value: Note: --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PUCHAR Buffer; ULONG UserBufferLength; UserBufferLength = IrpSp->Parameters.QuerySecurity.Length; RxContext->QuerySecurity.SecurityInformation = IrpSp->Parameters.QuerySecurity.SecurityInformation; RxLockUserBuffer( RxContext, Irp, IoModifyAccess, UserBufferLength ); // // Lock before map so that map will get userbuffer instead of assoc buffer // Buffer = RxMapUserBuffer( RxContext, Irp ); RxDbgTrace( 0, Dbg, ("RxCommonQuerySecurity -> Buffer = %08lx\n", Buffer) ); if ((Buffer != NULL) || (UserBufferLength == 0)) { RxContext->Info.Buffer = Buffer; RxContext->Info.LengthRemaining = UserBufferLength; MINIRDR_CALL( Status, RxContext, Fcb->MRxDispatch, MRxQuerySdInfo, (RxContext) ); Irp->IoStatus.Information = RxContext->InformationToReturn; } else { Irp->IoStatus.Information = 0; Status = STATUS_INSUFFICIENT_RESOURCES; } return Status; } NTSTATUS RxCommonQuerySecurity ( IN PRX_CONTEXT RxContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for querying File ea called by both the fsd and fsp threads. Arguments: Irp - Supplies the Irp being processed Return Value: RXSTATUS - The return status for the operation STATUS_NO_MORE_EAS(warning): If the index of the last Ea + 1 == EaIndex. STATUS_NONEXISTENT_EA_ENTRY(error): EaIndex > index of last Ea + 1. STATUS_EAS_NOT_SUPPORTED(error): Attempt to do an operation to a server that did not negotiate "KNOWS_EAS". STATUS_BUFFER_OVERFLOW(warning): User did not supply an EaList, at least one but not all Eas fit in the buffer. STATUS_BUFFER_TOO_SMALL(error): Could not fit a single Ea in the buffer. User supplied an EaList and not all Eas fit in the buffer. STATUS_NO_EAS_ON_FILE(error): There were no eas on the file. STATUS_SUCCESS: All Eas fit in the buffer. If STATUS_BUFFER_TOO_SMALL is returned then IoStatus.Information is set to 0. Note: This code assumes that this is a buffered I/O operation. If it is ever implemented as a non buffered operation, then we have to put code to map in the users buffer here. --*/ { NTSTATUS Status; PFCB Fcb; PFOBX Fobx; NODE_TYPE_CODE TypeOfOpen; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PAGED_CODE(); RxDbgTrace(+1, Dbg, ("RxCommonQuerySecurity...\n", 0)); RxDbgTrace( 0, Dbg, (" Wait = %08lx\n", FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT ))); RxDbgTrace( 0, Dbg, (" Irp = %08lx\n", Irp )); RxDbgTrace( 0, Dbg, (" ->UserBuffer = %08lx\n", Irp->UserBuffer )); RxDbgTrace( 0, Dbg, (" ->Length = %08lx\n", IrpSp->Parameters.QuerySecurity.Length )); RxDbgTrace( 0, Dbg, (" ->SecurityInfo = %08lx\n", IrpSp->Parameters.QuerySecurity.SecurityInformation )); TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx ); if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) && (TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) { RxDbgTrace( -1, Dbg, ("RxpCommonQuerySecurity -> %08lx\n", STATUS_INVALID_PARAMETER) ); return STATUS_INVALID_PARAMETER; } Status = RxpCommonMiscOp( RxContext, Irp, Fcb, RxpCommonQuerySecurity ); RxDbgTrace(-1, Dbg, ("RxCommonQuerySecurity -> %08lx\n", Status)); return Status; } NTSTATUS RxpCommonSetSecurity ( IN PRX_CONTEXT RxContext, IN PIRP Irp, IN PFCB Fcb ) /*++ Routine Description: Callback that implements the set security call Arguments: RxContext - Irp - Fcb - Return Value: Note: --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); RxContext->SetSecurity.SecurityInformation = IrpSp->Parameters.SetSecurity.SecurityInformation; RxContext->SetSecurity.SecurityDescriptor = IrpSp->Parameters.SetSecurity.SecurityDescriptor; RxDbgTrace(0, Dbg, ("RxCommonSetSecurity -> Descr/Info = %08lx/%08lx\n", RxContext->SetSecurity.SecurityDescriptor, RxContext->SetSecurity.SecurityInformation )); MINIRDR_CALL( Status, RxContext, Fcb->MRxDispatch, MRxSetSdInfo, (RxContext) ); return Status; } NTSTATUS RxCommonSetSecurity ( IN PRX_CONTEXT RxContext, IN PIRP Irp ) /*++ Routine Description: This routine implements the common Set Ea File Api called by the the Fsd and Fsp threads Arguments: Irp - Supplies the Irp to process Return Value: RXSTATUS - The appropriate status for the Irp --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PFCB Fcb; PFOBX Fobx; NODE_TYPE_CODE TypeOfOpen; PAGED_CODE(); TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx ); if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) && (TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) { RxDbgTrace( -1, Dbg, ("RxpCommonSetSecurity -> %08lx\n", STATUS_INVALID_PARAMETER) ); return STATUS_INVALID_PARAMETER; } RxDbgTrace(+1, Dbg, ("RxCommonSetSecurity...\n", 0)); RxDbgTrace( 0, Dbg, (" Wait = %08lx\n", FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT ))); RxDbgTrace( 0, Dbg, (" Irp = %08lx\n", RxContext->CurrentIrp )); Status = RxpCommonMiscOp( RxContext, RxContext->CurrentIrp, Fcb, RxpCommonSetSecurity ); RxDbgTrace(-1, Dbg, ("RxCommonSetSecurity -> %08lx\n", Status)); return Status; } NTSTATUS RxpCommonQueryEa ( IN PRX_CONTEXT RxContext, IN PIRP Irp, IN PFCB Fcb ) /*++ Routine Description: Callback that implements the query ea call Arguments: RxContext - Irp - Fcb - Return Value: Note: --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PUCHAR Buffer; ULONG UserBufferLength; UserBufferLength = IrpSp->Parameters.QueryEa.Length; RxContext->QueryEa.UserEaList = IrpSp->Parameters.QueryEa.EaList; RxContext->QueryEa.UserEaListLength = IrpSp->Parameters.QueryEa.EaListLength; RxContext->QueryEa.UserEaIndex = IrpSp->Parameters.QueryEa.EaIndex; RxContext->QueryEa.RestartScan = BooleanFlagOn(IrpSp->Flags, SL_RESTART_SCAN); RxContext->QueryEa.ReturnSingleEntry = BooleanFlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY); RxContext->QueryEa.IndexSpecified = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED); RxLockUserBuffer( RxContext, Irp, IoModifyAccess, UserBufferLength ); // // lock before map so that map will get userbuffer instead of assoc buffer // Buffer = RxMapUserBuffer( RxContext, Irp ); if ((Buffer != NULL) || (UserBufferLength == 0)) { RxDbgTrace( 0, Dbg, ("RxCommonQueryEa -> Buffer = %08lx\n", Buffer )); RxContext->Info.Buffer = Buffer; RxContext->Info.LengthRemaining = UserBufferLength; MINIRDR_CALL( Status, RxContext, Fcb->MRxDispatch, MRxQueryEaInfo, (RxContext) ); // // In addition to manipulating the LengthRemaining and filling the buffer, // the minirdr also updates the fileindex (Fobx->OffsetOfNextEaToReturn) // Irp->IoStatus.Information = IrpSp->Parameters.QueryEa.Length - RxContext->Info.LengthRemaining; } else { Irp->IoStatus.Information = 0; Status = STATUS_INSUFFICIENT_RESOURCES; } return Status; } NTSTATUS RxCommonQueryEa ( IN PRX_CONTEXT RxContext, IN PIRP Irp ) /*++ Routine Description: This is the common routine for querying File ea called by both the fsd and fsp threads. Arguments: Irp - Supplies the Irp being processed Return Value: RXSTATUS - The return status for the operation STATUS_NO_MORE_EAS(warning): If the index of the last Ea + 1 == EaIndex. STATUS_NONEXISTENT_EA_ENTRY(error): EaIndex > index of last Ea + 1. STATUS_EAS_NOT_SUPPORTED(error): Attempt to do an operation to a server that did not negotiate "KNOWS_EAS". STATUS_BUFFER_OVERFLOW(warning): User did not supply an EaList, at least one but not all Eas fit in the buffer. STATUS_BUFFER_TOO_SMALL(error): Could not fit a single Ea in the buffer. User supplied an EaList and not all Eas fit in the buffer. STATUS_NO_EAS_ON_FILE(error): There were no eas on the file. STATUS_SUCCESS: All Eas fit in the buffer. If STATUS_BUFFER_TOO_SMALL is returned then IoStatus.Information is set to 0. Note: This code assumes that this is a buffered I/O operation. If it is ever implemented as a non buffered operation, then we have to put code to map in the users buffer here. --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PFCB Fcb; PFOBX Fobx; NODE_TYPE_CODE TypeOfOpen; PAGED_CODE(); RxDbgTrace( +1, Dbg, ("RxCommonQueryEa...\n", 0 )); RxDbgTrace( 0, Dbg, (" Wait = %08lx\n", FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT ))); RxDbgTrace( 0, Dbg, (" Irp = %08lx\n", Irp )); RxDbgTrace( 0, Dbg, (" ->SystemBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer )); RxDbgTrace( 0, Dbg, (" ->UserBuffer = %08lx\n", Irp->UserBuffer )); RxDbgTrace( 0, Dbg, (" ->Length = %08lx\n", IrpSp->Parameters.QueryEa.Length )); RxDbgTrace( 0, Dbg, (" ->EaList = %08lx\n", IrpSp->Parameters.QueryEa.EaList )); RxDbgTrace( 0, Dbg, (" ->EaListLength = %08lx\n", IrpSp->Parameters.QueryEa.EaListLength )); RxDbgTrace( 0, Dbg, (" ->EaIndex = %08lx\n", IrpSp->Parameters.QueryEa.EaIndex )); RxDbgTrace( 0, Dbg, (" ->RestartScan = %08lx\n", FlagOn( IrpSp->Flags, SL_RESTART_SCAN ))); RxDbgTrace( 0, Dbg, (" ->ReturnSingleEntry = %08lx\n", FlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY ))); RxDbgTrace( 0, Dbg, (" ->IndexSpecified = %08lx\n", FlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED ))); TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx ); Status = RxpCommonMiscOp( RxContext, Irp, Fcb, RxpCommonQueryEa ); RxDbgTrace(-1, Dbg, ("RxCommonQueryEa -> %08lx\n", Status)); return Status; } NTSTATUS RxpCommonSetEa ( IN PRX_CONTEXT RxContext, IN PIRP Irp, IN PFCB Fcb ) /*++ Routine Description: Callback that implements the set ea call Arguments: RxContext - Irp - Fcb - Return Value: Note: --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PFILE_OBJECT FileObject = IrpSp->FileObject; PUCHAR Buffer; ULONG UserBufferLength; // // Reference our input parameters to make things easier // UserBufferLength = IrpSp->Parameters.SetEa.Length; SetFlag( FileObject->Flags, FO_FILE_MODIFIED ); RxLockUserBuffer( RxContext, Irp, IoModifyAccess, UserBufferLength ); // // unless we lock first, rxmap actually gets the systembuffer! // Buffer = RxMapUserBuffer( RxContext, Irp ); if ((Buffer != NULL) || (UserBufferLength == 0)) { ULONG ErrorOffset; RxDbgTrace( 0, Dbg, ("RxCommonSetEa -> Buffer = %08lx\n", Buffer )); // // Check the validity of the buffer with the new eas. // Status = IoCheckEaBufferValidity( (PFILE_FULL_EA_INFORMATION)Buffer, UserBufferLength, &ErrorOffset ); if (!NT_SUCCESS( Status )) { Irp->IoStatus.Information = ErrorOffset; return Status; } } else { Irp->IoStatus.Information = 0; return STATUS_INSUFFICIENT_RESOURCES; } Irp->IoStatus.Information = 0; RxContext->Info.Buffer = Buffer; RxContext->Info.Length = UserBufferLength; MINIRDR_CALL( Status, RxContext, Fcb->MRxDispatch, MRxSetEaInfo, (RxContext) ); return Status; } NTSTATUS RxCommonSetEa ( IN PRX_CONTEXT RxContext, IN PIRP Irp ) /*++ Routine Description: This routine implements the common Set Ea File Api called by the the Fsd and Fsp threads Arguments: Irp - Supplies the Irp to process Return Value: RXSTATUS - The appropriate status for the Irp --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PFCB Fcb; PFOBX Fobx; NODE_TYPE_CODE TypeOfOpen; PAGED_CODE(); RxDbgTrace( +1, Dbg, ("RxCommonSetEa...\n", 0) ); RxDbgTrace( 0, Dbg, (" Wait = %08lx\n", FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT ))); RxDbgTrace( 0, Dbg, (" Irp = %08lx\n", Irp )); RxDbgTrace( 0, Dbg, (" ->SystemBuffer = %08lx\n", Irp->UserBuffer )); RxDbgTrace( 0, Dbg, (" ->Length = %08lx\n", IrpSp->Parameters.SetEa.Length )); TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx ); if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) && (TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) { RxDbgTrace( -1, Dbg, ("RxpCommonSetSecurity -> %08lx\n", STATUS_INVALID_PARAMETER) ); return STATUS_INVALID_PARAMETER; } Status = RxpCommonMiscOp( RxContext, Irp, Fcb, RxpCommonSetEa ); RxDbgTrace(-1, Dbg, ("RxCommonSetEa -> %08lx\n", Status)); return Status; } NTSTATUS RxpCommonQueryQuotaInformation ( IN PRX_CONTEXT RxContext, IN PIRP Irp, IN PFCB Fcb ) /*++ Routine Description: Callback that implements the query quota call Arguments: RxContext - Irp - Fcb - Return Value: Note: --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PUCHAR Buffer; ULONG UserBufferLength; UserBufferLength = IrpSp->Parameters.QueryQuota.Length; RxContext->QueryQuota.SidList = IrpSp->Parameters.QueryQuota.SidList; RxContext->QueryQuota.SidListLength = IrpSp->Parameters.QueryQuota.SidListLength; RxContext->QueryQuota.StartSid = IrpSp->Parameters.QueryQuota.StartSid; RxContext->QueryQuota.Length = IrpSp->Parameters.QueryQuota.Length; RxContext->QueryQuota.RestartScan = BooleanFlagOn( IrpSp->Flags, SL_RESTART_SCAN ); RxContext->QueryQuota.ReturnSingleEntry = BooleanFlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY ); RxContext->QueryQuota.IndexSpecified = BooleanFlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED ); RxLockUserBuffer( RxContext, Irp, IoModifyAccess, UserBufferLength ); // // lock before map so that map will get userbuffer instead of assoc buffer // Buffer = RxMapUserBuffer( RxContext, Irp ); if ((Buffer != NULL) || (UserBufferLength == 0)) { RxDbgTrace( 0, Dbg, ("RxCommonQueryQuota -> Buffer = %08lx\n", Buffer) ); RxContext->Info.Buffer = Buffer; RxContext->Info.LengthRemaining = UserBufferLength; MINIRDR_CALL( Status, RxContext, Fcb->MRxDispatch, MRxQueryQuotaInfo, (RxContext) ); Irp->IoStatus.Information = RxContext->Info.LengthRemaining; } else { Irp->IoStatus.Information = 0; Status = STATUS_INSUFFICIENT_RESOURCES; } return Status; } NTSTATUS RxCommonQueryQuotaInformation ( IN PRX_CONTEXT RxContext, IN PIRP Irp ) /*++ Routine Description: Main entry point for IRP_MJ_QUERY_QUOTA_INFORMATION Arguments: RxContext - Return Value: Note: --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PFCB Fcb; PFOBX Fobx; NODE_TYPE_CODE TypeOfOpen; PAGED_CODE(); RxDbgTrace( +1, Dbg, ("RxCommonQueryQueryQuotaInformation...\n", 0) ); RxDbgTrace( 0, Dbg, (" Wait = %08lx\n", FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT ))); RxDbgTrace( 0, Dbg, (" Irp = %08lx\n", Irp )); RxDbgTrace( 0, Dbg, (" ->SystemBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer )); RxDbgTrace( 0, Dbg, (" ->UserBuffer = %08lx\n", Irp->UserBuffer )); RxDbgTrace( 0, Dbg, (" ->Length = %08lx\n", IrpSp->Parameters.QueryQuota.Length )); RxDbgTrace( 0, Dbg, (" ->StartSid = %08lx\n", IrpSp->Parameters.QueryQuota.StartSid )); RxDbgTrace( 0, Dbg, (" ->SidList = %08lx\n", IrpSp->Parameters.QueryQuota.SidList )); RxDbgTrace( 0, Dbg, (" ->SidListLength = %08lx\n", IrpSp->Parameters.QueryQuota.SidListLength )); RxDbgTrace( 0, Dbg, (" ->RestartScan = %08lx\n", FlagOn( IrpSp->Flags, SL_RESTART_SCAN ))); RxDbgTrace( 0, Dbg, (" ->ReturnSingleEntry = %08lx\n", FlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY ))); RxDbgTrace( 0, Dbg, (" ->IndexSpecified = %08lx\n", FlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED ))); TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx ); if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) && (TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) { RxDbgTrace( -1, Dbg, ("RxpCommonQueryQuotaInformation -> %08lx\n", STATUS_INVALID_PARAMETER) ); return STATUS_INVALID_PARAMETER; } Status = RxpCommonMiscOp( RxContext, Irp, Fcb, RxpCommonQueryQuotaInformation ); return Status; } NTSTATUS RxpCommonSetQuotaInformation ( IN PRX_CONTEXT RxContext, IN PIRP Irp, IN PFCB Fcb ) /*++ Routine Description: Callback that implements the set quota call Arguments: RxContext - Irp - Fcb - Return Value: Note: --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PUCHAR Buffer; ULONG UserBufferLength; PAGED_CODE(); UserBufferLength = IrpSp->Parameters.SetQuota.Length; RxLockUserBuffer( RxContext, Irp, IoModifyAccess, UserBufferLength ); // // lock before map so that map will get userbuffer instead of assoc buffer // Buffer = RxMapUserBuffer( RxContext, Irp ); if ((Buffer != NULL) || (UserBufferLength == 0)) { RxDbgTrace(0, Dbg, ("RxCommonQueryQuota -> Buffer = %08lx\n", Buffer)); RxContext->Info.Buffer = Buffer; RxContext->Info.LengthRemaining = UserBufferLength; MINIRDR_CALL( Status, RxContext, Fcb->MRxDispatch, MRxSetQuotaInfo, (RxContext) ); } else { Status = STATUS_INSUFFICIENT_RESOURCES; } return Status; } NTSTATUS RxCommonSetQuotaInformation ( IN PRX_CONTEXT RxContext, IN PIRP Irp ) /*++ Routine Description: Main entry point for IRP_MJ_SET_QUOTA_INFORMATION Arguments: RxContext - Return Value: Note: --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PFCB Fcb; PFOBX Fobx; NODE_TYPE_CODE TypeOfOpen; PAGED_CODE(); RxDbgTrace( +1, Dbg, ("RxCommonSetQuotaInformation...\n", 0) ); RxDbgTrace( 0, Dbg, (" Wait = %08lx\n", FlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT ))); RxDbgTrace( 0, Dbg, (" Irp = %08lx\n", Irp )); TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx ); if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) && (TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) { RxDbgTrace( -1, Dbg, ("RxpCommonSetQuotaInformation -> %08lx\n", STATUS_INVALID_PARAMETER) ); return STATUS_INVALID_PARAMETER; } Status = RxpCommonMiscOp( RxContext, Irp, Fcb, RxpCommonSetQuotaInformation ); return Status; }