📄 ea.c
字号:
/*++
Copyright (c) 1989 - 1999 Microsoft Corporation
Module Name:
ea.c
Abstract:
This module implements the mini redirector call down routines pertaining to query/set ea/security.
--*/
#include "precomp.h"
#pragma hdrstop
//
// Forward declarations.
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, MRxSmbQueryEaInformation)
#pragma alloc_text(PAGE, MRxSmbSetEaInformation)
#pragma alloc_text(PAGE, MRxSmbQuerySecurityInformation)
#pragma alloc_text(PAGE, MRxSmbSetSecurityInformation)
#pragma alloc_text(PAGE, MRxSmbLoadEaList)
#pragma alloc_text(PAGE, MRxSmbNtGeaListToOs2)
#pragma alloc_text(PAGE, MRxSmbNtGetEaToOs2)
#pragma alloc_text(PAGE, MRxSmbQueryEasFromServer)
#pragma alloc_text(PAGE, MRxSmbNtFullEaSizeToOs2)
#pragma alloc_text(PAGE, MRxSmbNtFullListToOs2)
#pragma alloc_text(PAGE, MRxSmbNtFullEaToOs2)
#pragma alloc_text(PAGE, MRxSmbSetEaList)
#endif
////
//// The Bug check file id for this module
////
//
//#define BugCheckFileId (RDBSS_BUG_CHECK_LOCAL_CREATE)
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_EA)
//this is the largest EAs that could ever be returned!
//this is used to simulate the nt resumable queryEA using the downlevel call
//sigh!
#define EA_QUERY_SIZE 0x0000ffff
//for QueryEA
NTSTATUS
MRxSmbLoadEaList(
IN PRX_CONTEXT RxContext,
IN PUCHAR UserEaList,
IN ULONG UserEaListLength,
OUT PFEALIST *ServerEaList
);
NTSTATUS
MRxSmbQueryEasFromServer(
IN PRX_CONTEXT RxContext,
IN PFEALIST ServerEaList,
IN PVOID Buffer,
IN OUT PULONG BufferLengthRemaining,
IN BOOLEAN ReturnSingleEntry,
IN BOOLEAN UserEaListSupplied
);
//for SetEA
NTSTATUS
MRxSmbSetEaList(
// IN PICB Icb,
// IN PIRP Irp,
IN PRX_CONTEXT RxContext,
IN PFEALIST ServerEaList
);
VOID MRxSmbExtraEaRoutine(LONG i){
RxDbgTrace( 0, Dbg, ("MRxSmbExtraEaRoutine i=%08lx\n", i ));
}
NTSTATUS
MRxSmbQueryEaInformation (
IN OUT PRX_CONTEXT RxContext
)
{
NTSTATUS Status;
RxCaptureFcb;
RxCaptureFobx;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PVOID Buffer = RxContext->Info.Buffer;
PLONG pLengthRemaining = &RxContext->Info.LengthRemaining;
PUCHAR UserEaList = RxContext->QueryEa.UserEaList;
ULONG UserEaListLength = RxContext->QueryEa.UserEaListLength;
ULONG UserEaIndex = RxContext->QueryEa.UserEaIndex;
BOOLEAN RestartScan = RxContext->QueryEa.RestartScan;
BOOLEAN ReturnSingleEntry = RxContext->QueryEa.ReturnSingleEntry;
BOOLEAN IndexSpecified = RxContext->QueryEa.IndexSpecified;
PFEALIST ServerEaList = NULL;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbQueryEaInformation\n"));
pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
//get rid of nonEA guys right now
if (!FlagOn(pServerEntry->Server.DialectFlags,DF_SUPPORTEA)) {
RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
return((STATUS_NOT_SUPPORTED));
}
Status = MRxSmbDeferredCreate(RxContext);
if (Status!=STATUS_SUCCESS) {
goto FINALLY;
}
Status = MRxSmbLoadEaList( RxContext, UserEaList, UserEaListLength, &ServerEaList );
if (( !NT_SUCCESS( Status ) )||
( ServerEaList == NULL )) {
goto FINALLY;
}
if (IndexSpecified) {
capFobx->OffsetOfNextEaToReturn = UserEaIndex;
Status = MRxSmbQueryEasFromServer(
RxContext,
ServerEaList,
Buffer,
pLengthRemaining,
ReturnSingleEntry,
(BOOLEAN)(UserEaList != NULL) );
//
// if there are no Ea's on the file, and the user supplied an EA
// index, we want to map the error to STATUS_NONEXISTANT_EA_ENTRY.
//
if ( Status == STATUS_NO_EAS_ON_FILE ) {
Status = STATUS_NONEXISTENT_EA_ENTRY;
}
} else {
if ( ( RestartScan == TRUE ) || (UserEaList != NULL) ){
//
// Ea Indices start at 1, not 0....
//
capFobx->OffsetOfNextEaToReturn = 1;
}
Status = MRxSmbQueryEasFromServer( //it is offensive to have two identical calls but oh, well.....
RxContext,
ServerEaList,
Buffer,
pLengthRemaining,
ReturnSingleEntry,
(BOOLEAN)(UserEaList != NULL) );
}
FINALLY:
if ( ServerEaList != NULL) {
RxFreePool(ServerEaList);
}
RxDbgTrace(-1, Dbg, ("MRxSmbQueryEaInformation st=%08lx\n",Status));
return Status;
}
NTSTATUS
MRxSmbSetEaInformation (
IN OUT struct _RX_CONTEXT * RxContext
)
{
NTSTATUS Status;
RxCaptureFcb; RxCaptureFobx;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PVOID Buffer = RxContext->Info.Buffer;
ULONG Length = RxContext->Info.Length;
PFEALIST ServerEaList = NULL;
ULONG Size;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbSetEaInformation\n"));
pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
//get rid of nonEA guys right now
if (!FlagOn(pServerEntry->Server.DialectFlags,DF_SUPPORTEA)) {
RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
return((STATUS_NOT_SUPPORTED));
}
Status = MRxSmbDeferredCreate(RxContext);
if (Status!=STATUS_SUCCESS) {
goto FINALLY;
}
//
// Convert Nt format FEALIST to OS/2 format
//
Size = MRxSmbNtFullEaSizeToOs2 ( Buffer );
if ( Size > 0x0000ffff ) {
Status = STATUS_EA_TOO_LARGE;
goto FINALLY;
}
ServerEaList = RxAllocatePool ( PagedPool, EA_QUERY_SIZE );
if ( ServerEaList == NULL ) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto FINALLY;
}
MRxSmbNtFullListToOs2 ( Buffer, ServerEaList );
//
// Set EAs on the file/directory; if the error is EA_ERROR then SetEaList
// sets iostatus.information to the offset of the offender
//
Status = MRxSmbSetEaList( RxContext, ServerEaList);
FINALLY:
if ( ServerEaList != NULL) {
RxFreePool(ServerEaList);
}
RxDbgTrace(-1, Dbg, ("MRxSmbSetEaInformation st=%08lx\n",Status));
return Status;
}
NTSTATUS
MRxSmbQuerySecurityInformation (
IN OUT PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine implements the NtQuerySecurityFile api.
Arguments:
Return Value:
Status - Result of the operation.
--*/
{
RxCaptureFcb;
RxCaptureFobx;
PVOID Buffer = RxContext->Info.Buffer;
PLONG pLengthRemaining = &RxContext->Info.LengthRemaining;
PMRX_SMB_SRV_OPEN smbSrvOpen;
PSMBCEDB_SERVER_ENTRY pServerEntry;
NTSTATUS Status;
REQ_QUERY_SECURITY_DESCRIPTOR QuerySecurityRequest;
RESP_QUERY_SECURITY_DESCRIPTOR QuerySecurityResponse;
PBYTE pInputParamBuffer = NULL;
PBYTE pOutputParamBuffer = NULL;
PBYTE pInputDataBuffer = NULL;
PBYTE pOutputDataBuffer = NULL;
ULONG InputParamBufferLength = 0;
ULONG OutputParamBufferLength = 0;
ULONG InputDataBufferLength = 0;
ULONG OutputDataBufferLength = 0;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbQuerySecurityInformation...\n"));
// Turn away this call from those servers which do not support the NT SMBs
pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
RxDbgTrace(-1, Dbg, ("QuerySecurityDescriptor not supported!\n"));
return((STATUS_NOT_SUPPORTED));
}
Status = MRxSmbDeferredCreate(RxContext);
if (Status!=STATUS_SUCCESS) {
goto FINALLY;
}
Status = STATUS_MORE_PROCESSING_REQUIRED;
smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
ASSERT (!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN));
if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
//BOOLEAN printflag;
TransactionOptions.NtTransactFunction = NT_TRANSACT_QUERY_SECURITY_DESC;
//TransactionOptions.Flags |= SMB_XACT_FLAGS_COPY_ON_ERROR;
QuerySecurityRequest.Fid = smbSrvOpen->Fid;
QuerySecurityRequest.Reserved = 0;
QuerySecurityRequest.SecurityInformation = RxContext->QuerySecurity.SecurityInformation;
QuerySecurityResponse.LengthNeeded = 0xbaadbaad;
//printflag = RxDbgTraceDisableGlobally();//this is debug code anyway!
//RxDbgTraceEnableGlobally(FALSE);
Status = SmbCeTransact(
RxContext, // the RXContext for the transaction
&TransactionOptions, // transaction options
NULL, // the setup buffer
0, // input setup buffer length
NULL, // output setup buffer
0, // output setup buffer length
&QuerySecurityRequest, // Input Param Buffer
sizeof(QuerySecurityRequest), // Input param buffer length
&QuerySecurityResponse, // Output param buffer
sizeof(QuerySecurityResponse),// output param buffer length
NULL, // Input data buffer
0, // Input data buffer length
Buffer, // output data buffer
*pLengthRemaining, // output data buffer length
&ResumptionContext // the resumption context
);
//DbgPrint("QSR.len=%x\n", QuerySecurityResponse.LengthNeeded);
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_TOO_SMALL)) {
ULONG ReturnedDataCount = ResumptionContext.DataBytesReceived;
RxContext->InformationToReturn = QuerySecurityResponse.LengthNeeded;
RxDbgTrace(0, Dbg, ("MRxSmbQuerySecurityInformation...ReturnedDataCount=%08lx\n",ReturnedDataCount));
ASSERT(ResumptionContext.ParameterBytesReceived == sizeof(RESP_QUERY_SECURITY_DESCRIPTOR));
if (((LONG)(QuerySecurityResponse.LengthNeeded)) > *pLengthRemaining) {
Status = STATUS_BUFFER_OVERFLOW;
}
}
//RxDbgTraceEnableGlobally(printflag);
}
FINALLY:
RxDbgTrace(-1, Dbg, ("MRxSmbQuerySecurityInformation...exit, st=%08lx,info=%08lx\n",
Status, RxContext->InformationToReturn));
return Status;
}
NTSTATUS
MRxSmbSetSecurityInformation (
IN OUT struct _RX_CONTEXT * RxContext
)
{
RxCaptureFcb;
RxCaptureFobx;
PMRX_SMB_SRV_OPEN smbSrvOpen;
PSMBCEDB_SERVER_ENTRY pServerEntry;
NTSTATUS Status;
REQ_SET_SECURITY_DESCRIPTOR SetSecurityRequest;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbSetSecurityInformation...\n"));
pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
RxDbgTrace(-1, Dbg, ("Set Security Descriptor not supported!\n"));
return((STATUS_NOT_SUPPORTED));
}
Status = MRxSmbDeferredCreate(RxContext);
if (Status!=STATUS_SUCCESS) {
goto FINALLY;
}
Status = STATUS_MORE_PROCESSING_REQUIRED;
smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
ULONG SdLength = RtlLengthSecurityDescriptor(RxContext->SetSecurity.SecurityDescriptor);
TransactionOptions.NtTransactFunction = NT_TRANSACT_SET_SECURITY_DESC;
SetSecurityRequest.Fid = smbSrvOpen->Fid;
SetSecurityRequest.Reserved = 0;
SetSecurityRequest.SecurityInformation = RxContext->SetSecurity.SecurityInformation;
Status = SmbCeTransact(
RxContext, // the RXContext for the transaction
&TransactionOptions, // transaction options
NULL, // the input setup buffer
0, // input setup buffer length
NULL, // the output setup buffer
0, // output setup buffer length
&SetSecurityRequest, // Input Param Buffer
sizeof(SetSecurityRequest), // Input param buffer length
NULL, // Output param buffer
0, // output param buffer length
RxContext->SetSecurity.SecurityDescriptor, // Input data buffer
SdLength, // Input data buffer length
NULL, // output data buffer
0, // output data buffer length
&ResumptionContext // the resumption context
);
//the old rdr doesn't return any info...................
//RxContext->InformationToReturn = SetSecurityResponse.LengthNeeded;
if ( NT_SUCCESS(Status) ) {
ULONG ReturnedDataCount = ResumptionContext.DataBytesReceived;
RxDbgTrace(0, Dbg, ("MRxSmbSetSecurityInformation...ReturnedDataCount=%08lx\n",ReturnedDataCount));
ASSERT(ResumptionContext.ParameterBytesReceived == 0);
ASSERT(ResumptionContext.SetupBytesReceived == 0);
ASSERT(ResumptionContext.DataBytesReceived == 0);
}
}
FINALLY:
RxDbgTrace(-1, Dbg, ("MRxSmbSetSecurityInformation...exit, st=%08lx,info=%08lx\n",
Status, RxContext->InformationToReturn));
return Status;
}
NTSTATUS
MRxSmbLoadEaList(
IN PRX_CONTEXT RxContext,
IN PUCHAR UserEaList,
IN ULONG UserEaListLength,
OUT PFEALIST *ServerEaList
)
/*++
Routine Description:
This routine implements the NtQueryEaFile api.
It returns the following information:
Arguments:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -