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.
1133 lines
37 KiB
1133 lines
37 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
srvcall.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the routines for handling the creation/manipulation
|
|
of server entries in the connection engine database.
|
|
|
|
Author:
|
|
|
|
Balan Sethu Raman [SethuR]
|
|
|
|
Rohan Kumar [RohanK] 04-April-1999
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "webdav.h"
|
|
|
|
//
|
|
// Mentioned below are the prototypes of functions tht are used only within
|
|
// this module (file). These functions should not be exposed outside.
|
|
//
|
|
|
|
VOID
|
|
MRxDAVSrvCallWrapper(
|
|
PVOID Context
|
|
);
|
|
|
|
NTSTATUS
|
|
MRxDAVCreateSrvCallContinuation(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
|
|
);
|
|
|
|
NTSTATUS
|
|
MRxDAVFormatUserModeSrvCallCreateRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
|
|
ULONG WorkItemLength,
|
|
PULONG_PTR ReturnedLength
|
|
);
|
|
|
|
BOOL
|
|
MRxDAVPrecompleteUserModeSrvCallCreateRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
|
|
ULONG WorkItemLength,
|
|
BOOL OperationCancelled
|
|
);
|
|
|
|
NTSTATUS
|
|
MRxDAVFinalizeSrvCallContinuation(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
|
|
);
|
|
|
|
NTSTATUS
|
|
MRxDAVFormatUserModeSrvCallFinalizeRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
|
|
ULONG WorkItemLength,
|
|
PULONG_PTR ReturnedLength
|
|
);
|
|
|
|
BOOL
|
|
MRxDAVPrecompleteUserModeSrvCallFinalizeRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
|
|
ULONG WorkItemLength,
|
|
BOOL OperationCancelled
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, MRxDAVCreateSrvCall)
|
|
#pragma alloc_text(PAGE, MRxDAVSrvCallWrapper)
|
|
#pragma alloc_text(PAGE, MRxDAVCreateSrvCallContinuation)
|
|
#pragma alloc_text(PAGE, MRxDAVFormatUserModeSrvCallCreateRequest)
|
|
#pragma alloc_text(PAGE, MRxDAVPrecompleteUserModeSrvCallCreateRequest)
|
|
#pragma alloc_text(PAGE, MRxDAVFinalizeSrvCall)
|
|
#pragma alloc_text(PAGE, MRxDAVFinalizeSrvCallContinuation)
|
|
#pragma alloc_text(PAGE, MRxDAVFormatUserModeSrvCallFinalizeRequest)
|
|
#pragma alloc_text(PAGE, MRxDAVPrecompleteUserModeSrvCallFinalizeRequest)
|
|
#pragma alloc_text(PAGE, MRxDAVSrvCallWinnerNotify)
|
|
#endif
|
|
|
|
//
|
|
// Implementation of functions begins here.
|
|
//
|
|
|
|
NTSTATUS
|
|
MRxDAVCreateSrvCall(
|
|
PMRX_SRV_CALL SrvCall,
|
|
PMRX_SRVCALL_CALLBACK_CONTEXT CallbackContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles the creation of SrvCalls.
|
|
|
|
Arguments:
|
|
|
|
SrvCall -
|
|
|
|
CallBackContext - the call back context in RDBSS for continuation.
|
|
|
|
Return Value:
|
|
|
|
RXSTATUS - The return status for the operation
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = CallbackContext;
|
|
PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = NULL;
|
|
PRX_CONTEXT RxContext = NULL;
|
|
|
|
PAGED_CODE();
|
|
|
|
#if 1
|
|
|
|
SrvCalldownStructure = (PMRX_SRVCALLDOWN_STRUCTURE)(CallbackContext->SrvCalldownStructure);
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVCreateSrvCall!!!!\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVCreateSrvCall: SrvCall: %08lx, CallbackContext: "
|
|
"%08lx.\n", PsGetCurrentThreadId(), SrvCall, CallbackContext));
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: MRxDAVCreateSrvCall: SrvCallName: %wZ\n",
|
|
PsGetCurrentThreadId(), SrvCall->pSrvCallName));
|
|
|
|
//
|
|
// Perform the following checks.
|
|
//
|
|
ASSERT(NodeType(SrvCall) == RDBSS_NTC_SRVCALL);
|
|
ASSERT(SrvCall);
|
|
ASSERT(SrvCall->pSrvCallName);
|
|
ASSERT(SrvCall->pSrvCallName->Buffer);
|
|
ASSERT(SCCBC->RxDeviceObject);
|
|
|
|
//
|
|
// Before delaying the final close, RDBSS looks at the number of closes that
|
|
// have been delayed and compares it against this value.
|
|
//
|
|
SrvCall->MaximumNumberOfCloseDelayedFiles = 150;
|
|
|
|
//
|
|
// Allocate memory for the context pointer in the SrvCall structure. This is
|
|
// for the Mini-Redirs use.
|
|
//
|
|
ASSERT(SrvCall->Context == NULL);
|
|
SrvCall->Context = RxAllocatePoolWithTag(NonPagedPool,
|
|
sizeof(WEBDAV_SRV_CALL),
|
|
DAV_SRVCALL_POOLTAG);
|
|
if (SrvCall->Context == NULL) {
|
|
//
|
|
// There was an error in dispatching the MRxDAVSrvCallWrapper method to
|
|
// a worker thread. Complete the request and return STATUS_PENDING.
|
|
//
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: MRxDAVCreateSrvCall/RxAllocatePoolWithTag.\n",
|
|
PsGetCurrentThreadId()));
|
|
SCCBC->Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
SrvCalldownStructure->CallBack(SCCBC);
|
|
NtStatus = STATUS_PENDING;
|
|
return NtStatus;
|
|
}
|
|
|
|
RtlZeroMemory(SrvCall->Context, sizeof(WEBDAV_SRV_CALL));
|
|
|
|
//
|
|
// Check to see if the DAV server mentioned in the SrvCall exists. To do
|
|
// this, we need to go to the usermode and call GetHostByName on the name
|
|
// mentioned in the SrvCall strucutre.
|
|
//
|
|
RxContext = SrvCalldownStructure->RxContext;
|
|
|
|
//
|
|
// We need to pass the server name to the user mode to check whether such a
|
|
// server actually exists. RxContext has 4 pointers that the mini-redirs
|
|
// can use. Here we use MRxContext[1]. We store a reference to the SCCBC
|
|
// strucutre which contains the name of the server. MRxContext[0] is used to
|
|
// store a reference to the AsynEngineContext and this is done when the
|
|
// context gets created in the function UMRxCreateAsyncEngineContext. The
|
|
// pointer to SCCBC is also used while calling the callback function to
|
|
// complete the creation of the SrvCall.
|
|
//
|
|
RxContext->MRxContext[1] = SCCBC;
|
|
|
|
//
|
|
// Dispatch the request to a system thread.
|
|
//
|
|
NtStatus = RxDispatchToWorkerThread((PRDBSS_DEVICE_OBJECT)MRxDAVDeviceObject,
|
|
DelayedWorkQueue,
|
|
MRxDAVSrvCallWrapper,
|
|
RxContext);
|
|
if (NtStatus == STATUS_SUCCESS) {
|
|
//
|
|
// Map the return value since the wrapper expects STATUS_PENDING.
|
|
//
|
|
NtStatus = STATUS_PENDING;
|
|
} else {
|
|
//
|
|
// There was an error in dispatching the MRxDAVSrvCallWrapper method to
|
|
// a worker thread. Complete the request and return STATUS_PENDING.
|
|
//
|
|
SCCBC->Status = NtStatus;
|
|
SrvCalldownStructure->CallBack(SCCBC);
|
|
NtStatus = STATUS_PENDING;
|
|
}
|
|
|
|
#else
|
|
|
|
SCCBC->Status = STATUS_SUCCESS;
|
|
SrvCalldownStructure->CallBack(SCCBC);
|
|
NtStatus = STATUS_PENDING;
|
|
|
|
#endif
|
|
|
|
return(NtStatus);
|
|
}
|
|
|
|
|
|
VOID
|
|
MRxDAVSrvCallWrapper(
|
|
PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the worker thread. Its a routine that wraps the
|
|
call to MRxDAVOuterWrapper.
|
|
|
|
Arguments:
|
|
|
|
RxContext - The RDBSS context.
|
|
|
|
Return Value:
|
|
|
|
RXSTATUS - The return status for the operation
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PRX_CONTEXT RxContext = (PRX_CONTEXT)Context;
|
|
PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = NULL;
|
|
PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = NULL;
|
|
PMRX_SRV_CALL SrvCall = NULL;
|
|
PWEBDAV_SRV_CALL DavSrvCall = NULL;
|
|
|
|
PAGED_CODE();
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVSrvCallWrapper!!!!\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVSrvCallWrapper: RxContext: %08lx.\n",
|
|
PsGetCurrentThreadId(), RxContext));
|
|
|
|
NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
|
|
SIZEOF_DAV_SPECIFIC_CONTEXT,
|
|
MRxDAVFormatTheDAVContext,
|
|
DAV_MINIRDR_ENTRY_FROM_CREATESRVCALL,
|
|
MRxDAVCreateSrvCallContinuation,
|
|
"MRxDAVCreateSrvCall");
|
|
|
|
//
|
|
// If we failed to queue the request to be sent to the usermode, then we
|
|
// need to do some cleanup. If NtStatus is STATUS_CANCELLED then we would
|
|
// have already done the cleanup in the MRxDAVHandleCreateSrvCallCancellation
|
|
// funtcion. Hence we don't need to do it now.
|
|
//
|
|
if (NtStatus != STATUS_SUCCESS && NtStatus != STATUS_PENDING && NtStatus != STATUS_CANCELLED) {
|
|
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVSrvCallWrapper/UMRxAsyncEngOuterWrapper: "
|
|
"NtStatus = %08lx\n", PsGetCurrentThreadId(), NtStatus));
|
|
|
|
//
|
|
// The SrvCall pointer is stored in the SCCBC structure which is
|
|
// stored in the MRxContext[1] pointer of the RxContext structure.
|
|
// This is done in the MRxDAVCreateSrvCall function.
|
|
//
|
|
ASSERT(RxContext->MRxContext[1] != NULL);
|
|
SCCBC = (PMRX_SRVCALL_CALLBACK_CONTEXT)RxContext->MRxContext[1];
|
|
|
|
SrvCalldownStructure = SCCBC->SrvCalldownStructure;
|
|
ASSERT(SrvCalldownStructure != NULL);
|
|
|
|
SrvCall = SrvCalldownStructure->SrvCall;
|
|
ASSERT(SrvCall != NULL);
|
|
|
|
DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
|
|
ASSERT(DavSrvCall != NULL);
|
|
|
|
//
|
|
// Free the memory that was allocatted for the SecurityClientContext in
|
|
// the function MRxDAVFormatTheDAVContext. Before Freeing the memory, we
|
|
// need to delete the SecurityClientContext.
|
|
//
|
|
if (DavSrvCall->SCAlreadyInitialized) {
|
|
ASSERT(RxContext->MRxContext[2] != NULL);
|
|
SeDeleteClientSecurity((PSECURITY_CLIENT_CONTEXT)RxContext->MRxContext[2]);
|
|
RxFreePool(RxContext->MRxContext[2]);
|
|
RxContext->MRxContext[2] = NULL;
|
|
DavSrvCall->SCAlreadyInitialized = FALSE;
|
|
}
|
|
|
|
SCCBC->Status = NtStatus;
|
|
SrvCalldownStructure->CallBack(SCCBC);
|
|
|
|
}
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Leaving MRxDAVSrvCallWrapper with NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MRxDAVCreateSrvCallContinuation(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks to see if the server for which a SrvCall is being
|
|
created exists or not.
|
|
|
|
Arguments:
|
|
|
|
AsyncEngineContext - The Reflectors context.
|
|
|
|
RxContext - The RDBSS context.
|
|
|
|
Return Value:
|
|
|
|
RXSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVCreateSrvCallContinuation!!!!\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVCreateSrvCallContinuation: "
|
|
"AsyncEngineContext: %08lx, RxContext: %08lx\n",
|
|
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
|
|
|
|
//
|
|
// We are executing in the context of a worker thread. No point in holding
|
|
// onto this thread. Set the Async flag irrespective of the nature of the
|
|
// request. By nature we mean sync or async. Also since CreateSrvCall has
|
|
// its own Callback, we do not need to call RxLowIoCompletion when the
|
|
// AsyncEngineContext is getting finalized.
|
|
//
|
|
SetFlag(AsyncEngineContext->Flags, UMRX_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
|
|
AsyncEngineContext->ShouldCallLowIoCompletion = FALSE;
|
|
|
|
//
|
|
// Try usermode.
|
|
//
|
|
NtStatus = UMRxSubmitAsyncEngUserModeRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENTS,
|
|
MRxDAVFormatUserModeSrvCallCreateRequest,
|
|
MRxDAVPrecompleteUserModeSrvCallCreateRequest
|
|
);
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Leaving MRxDAVCreateSrvCallContinuation with NtStatus ="
|
|
" %08lx.\n", PsGetCurrentThreadId(), NtStatus));
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MRxDAVFormatUserModeSrvCallCreateRequest(
|
|
IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
|
|
IN ULONG WorkItemLength,
|
|
OUT PULONG_PTR ReturnedLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine formats the SrvCall create request being sent to the user mode
|
|
for processing.
|
|
|
|
Arguments:
|
|
|
|
RxContext - The RDBSS context.
|
|
|
|
AsyncEngineContext - The reflctor's context.
|
|
|
|
WorkItem - The work item buffer.
|
|
|
|
WorkItemLength - The length of the work item buffer.
|
|
|
|
ReturnedLength -
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
|
|
PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = NULL;
|
|
PMRX_SRV_CALL SrvCall = NULL;
|
|
PWCHAR ServerName = NULL;
|
|
DWORD ServerNameLenInBytes = 0;
|
|
PBYTE SecondaryBuff = NULL;
|
|
PDAV_USERMODE_CREATE_SRVCALL_REQUEST SrvCallCreateReq = NULL;
|
|
PSECURITY_CLIENT_CONTEXT SecurityClientContext = NULL;
|
|
PSECURITY_SUBJECT_CONTEXT SecSubCtx = NULL;
|
|
PNT_CREATE_PARAMETERS NtCP = &(RxContext->Create.NtCreateParameters);
|
|
PACCESS_TOKEN AccessToken = NULL;
|
|
|
|
PAGED_CODE();
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVFormatUserModeSrvCallCreateRequest!!!!\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVFormatUserModeSrvCallCreateRequest: "
|
|
"AsyncEngineContext: %08lx, RxContext: %08lx.\n",
|
|
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
|
|
|
|
SrvCallCreateReq = &(DavWorkItem->CreateSrvCallRequest);
|
|
|
|
//
|
|
// Get the SecuritySubjectContext.
|
|
//
|
|
ASSERT(NtCP->SecurityContext->AccessState != NULL);
|
|
SecSubCtx = &(NtCP->SecurityContext->AccessState->SubjectSecurityContext);
|
|
|
|
//
|
|
// Get the AccessToken.
|
|
//
|
|
AccessToken = SeQuerySubjectContextToken(SecSubCtx);
|
|
|
|
//
|
|
// Get the LogonID for this user/session.
|
|
//
|
|
if (!SeTokenIsRestricted(AccessToken)) {
|
|
NtStatus = SeQueryAuthenticationIdToken(AccessToken,
|
|
&(SrvCallCreateReq->LogonID));
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVFormatUserModeCreateSrvCallRequest/"
|
|
"SeQueryAuthenticationIdToken. NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
goto EXIT_THE_FUNCTION;
|
|
}
|
|
} else {
|
|
NtStatus = STATUS_ACCESS_DENIED;
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVFormatUserModeCreateSrvCallRequest/"
|
|
"SeTokenIsRestricted. NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
goto EXIT_THE_FUNCTION;
|
|
}
|
|
|
|
//
|
|
// Impersonate the client who initiated the request. If we fail to
|
|
// impersonate, tough luck. The SecurityClientContext is stored in
|
|
// RxContext->MRxContext[2]. This was done in MRxDAVFormatTheDAVContext.
|
|
//
|
|
ASSERT(RxContext->MRxContext[2] != NULL);
|
|
SecurityClientContext = (PSECURITY_CLIENT_CONTEXT)RxContext->MRxContext[2];
|
|
if (SecurityClientContext != NULL) {
|
|
NtStatus = UMRxImpersonateClient(SecurityClientContext, WorkItemHeader);
|
|
if (!NT_SUCCESS(NtStatus)) {
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVFormatUserModeCreateSrvCallRequest/"
|
|
"UMRxImpersonateClient. NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
goto EXIT_THE_FUNCTION;
|
|
}
|
|
} else {
|
|
NtStatus = STATUS_INVALID_PARAMETER;
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVFormatUserModeCreateSrvCallRequest: "
|
|
"SecurityClientContext is NULL.\n",
|
|
PsGetCurrentThreadId()));
|
|
goto EXIT_THE_FUNCTION;
|
|
}
|
|
|
|
DavWorkItem->WorkItemType = UserModeCreateSrvCall;
|
|
|
|
SCCBC = (PMRX_SRVCALL_CALLBACK_CONTEXT)RxContext->MRxContext[1];
|
|
SrvCall = SCCBC->SrvCalldownStructure->SrvCall;
|
|
|
|
//
|
|
// Set the name of the server to be verified. We need to allocate memory
|
|
// for the UserModeInfoBuff before filling in the ServerName in it.
|
|
//
|
|
ASSERT(SrvCall->pSrvCallName);
|
|
ServerName = &(SrvCall->pSrvCallName->Buffer[1]);
|
|
ServerNameLenInBytes = (1 + wcslen(ServerName)) * sizeof(WCHAR);
|
|
SecondaryBuff = UMRxAllocateSecondaryBuffer(AsyncEngineContext,
|
|
ServerNameLenInBytes);
|
|
if (SecondaryBuff == NULL) {
|
|
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("ld: MRxDAVFormatUserModeSrvCallCreateRequest/"
|
|
"UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
goto EXIT_THE_FUNCTION;
|
|
}
|
|
|
|
SrvCallCreateReq->ServerName = (PWCHAR)SecondaryBuff;
|
|
wcscpy(SrvCallCreateReq->ServerName, ServerName);
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("ld: MRxDAVFormatUserModeSrvCallCreateRequest: ServerName = %ws\n",
|
|
PsGetCurrentThreadId(), SrvCallCreateReq->ServerName));
|
|
|
|
if (RxContext->Create.UserName.Length) {
|
|
RtlCopyMemory(DavWorkItem->UserName,RxContext->Create.UserName.Buffer,RxContext->Create.UserName.Length);
|
|
}
|
|
|
|
if (RxContext->Create.Password.Length) {
|
|
RtlCopyMemory(DavWorkItem->Password,RxContext->Create.Password.Buffer,RxContext->Create.Password.Length);
|
|
}
|
|
|
|
EXIT_THE_FUNCTION:
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Leaving MRxDAVFormatUserModeSrvCallCreateRequest with "
|
|
"NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
BOOL
|
|
MRxDAVPrecompleteUserModeSrvCallCreateRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
|
|
ULONG WorkItemLength,
|
|
BOOL OperationCancelled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The precompletion routine for the create SrvCall request.
|
|
|
|
Arguments:
|
|
|
|
RxContext - The RDBSS context.
|
|
|
|
AsyncEngineContext - The reflctor's context.
|
|
|
|
WorkItem - The work item buffer.
|
|
|
|
WorkItemLength - The length of the work item buffer.
|
|
|
|
OperationCancelled - TRUE if this operation was cancelled by the user.
|
|
|
|
Return Value:
|
|
|
|
FALSE - UMRxAsyncEngineCalldownIrpCompletion is NOT called by the function
|
|
UMRxCompleteUserModeRequest after we return.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PDAV_USERMODE_WORKITEM WorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
|
|
PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = NULL;
|
|
PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = NULL;
|
|
PMRX_SRV_CALL SrvCall = NULL;
|
|
PDAV_USERMODE_CREATE_SRVCALL_REQUEST SrvCallCreateReq = NULL;
|
|
PDAV_USERMODE_CREATE_SRVCALL_RESPONSE CreateSrvCallResponse = NULL;
|
|
BOOL didFinalize = FALSE;
|
|
PWEBDAV_SRV_CALL DavSrvCall = NULL;
|
|
BOOL AsyncOperation = FALSE;
|
|
|
|
PAGED_CODE();
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVPrecompleteUserModeSrvCallCreateRequest!!!!\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVPrecompleteUserModeSrvCallCreateRequest: "
|
|
"AsyncEngineContext: %08lx, RxContext: %08lx.\n",
|
|
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
|
|
|
|
AsyncOperation = FlagOn(AsyncEngineContext->Flags, UMRX_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
|
|
ASSERT(AsyncOperation == TRUE);
|
|
|
|
//
|
|
// We do the following only if the Operation has not been cancelled. If it
|
|
// has been then this would have been done by the timer thread.
|
|
//
|
|
if (!OperationCancelled) {
|
|
|
|
SCCBC = (PMRX_SRVCALL_CALLBACK_CONTEXT)RxContext->MRxContext[1];
|
|
ASSERT(SCCBC != NULL);
|
|
SrvCalldownStructure = SCCBC->SrvCalldownStructure;
|
|
ASSERT(SrvCalldownStructure != NULL);
|
|
SrvCall = SrvCalldownStructure->SrvCall;
|
|
ASSERT(SrvCall != NULL);
|
|
|
|
//
|
|
// We allocated memory for it, so it better not be NULL.
|
|
//
|
|
DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
|
|
ASSERT(DavSrvCall != NULL);
|
|
|
|
//
|
|
// Free the memory that was allocatted for the SecurityClientContext in the
|
|
// function MRxDAVFormatTheDAVContext. Before Freeing the memory, we need
|
|
// to delete the SecurityClientContext.
|
|
//
|
|
ASSERT(DavSrvCall->SCAlreadyInitialized == TRUE);
|
|
ASSERT(RxContext->MRxContext[2] != NULL);
|
|
SeDeleteClientSecurity((PSECURITY_CLIENT_CONTEXT)RxContext->MRxContext[2]);
|
|
RxFreePool(RxContext->MRxContext[2]);
|
|
RxContext->MRxContext[2] = NULL;
|
|
DavSrvCall->SCAlreadyInitialized = FALSE;
|
|
|
|
} else {
|
|
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: MRxDAVPrecompleteUserModeSrvCallCreateRequest: Operation Cancelled. "
|
|
"AsyncEngineContext = %08lx, RxContext = %08lx.\n",
|
|
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
|
|
|
|
}
|
|
|
|
SrvCallCreateReq = &(WorkItem->CreateSrvCallRequest);
|
|
CreateSrvCallResponse = &(WorkItem->CreateSrvCallResponse);
|
|
|
|
//
|
|
// We need to free up the heap we allocated in the format routine.
|
|
//
|
|
if (SrvCallCreateReq->ServerName != NULL) {
|
|
|
|
if (AsyncEngineContext->Status != STATUS_SUCCESS) {
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVPrecompleteUserModeSrvCallCreateRequest."
|
|
" Server \"%ws\" is not a DAV server.\n",
|
|
PsGetCurrentThreadId(), SrvCallCreateReq->ServerName));
|
|
}
|
|
|
|
NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
|
|
(PBYTE)SrvCallCreateReq->ServerName);
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVPrecompleteUserModeSrvCallCreateRequest/"
|
|
"UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
}
|
|
|
|
}
|
|
|
|
if (!OperationCancelled) {
|
|
|
|
//
|
|
// Get this servers unique ID.
|
|
//
|
|
DavSrvCall->ServerID = CreateSrvCallResponse->ServerID;
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: MRxDAVPrecompleteUserModeSrvCallCreateRequest: "
|
|
"ServerID = %ld assigned to this server entry.\n",
|
|
PsGetCurrentThreadId(), DavSrvCall->ServerID));
|
|
|
|
//
|
|
// Set the status in the callback structure.
|
|
//
|
|
SCCBC->Status = AsyncEngineContext->Status;
|
|
|
|
}
|
|
|
|
//
|
|
// We call the first finalize here since we return STATUS_PENDING back to
|
|
// the continuation routine in the create srvcall case. So the reference
|
|
// that was made at the time of creation of the AsyncEngineContext is not
|
|
// removed in the wrapper routine. The second finalize is because, we do not
|
|
// call UMRxAsyncEngineCalldownIrpCompletion.
|
|
//
|
|
didFinalize = UMRxFinalizeAsyncEngineContext( &(AsyncEngineContext) );
|
|
didFinalize = UMRxFinalizeAsyncEngineContext( &(AsyncEngineContext) );
|
|
|
|
if (!OperationCancelled) {
|
|
//
|
|
// Call the callback function supplied by RDBSS.
|
|
//
|
|
SrvCalldownStructure->CallBack(SCCBC);
|
|
}
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Leaving MRxDAVPrecompleteUserModeSrvCallCreateRequest.\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MRxDAVFinalizeSrvCall(
|
|
PMRX_SRV_CALL pSrvCall,
|
|
BOOLEAN Force
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine destroys a given server call instance.
|
|
|
|
Arguments:
|
|
|
|
pSrvCall - The server call instance to be disconnected.
|
|
|
|
Force - TRUE if a disconnection is to be enforced immediately.
|
|
|
|
Return Value:
|
|
|
|
RXSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PRX_CONTEXT RxContext = NULL;
|
|
PRDBSS_DEVICE_OBJECT RxDeviceObject = pSrvCall->RxDeviceObject;
|
|
PWEBDAV_SRV_CALL DavSrvCall;
|
|
|
|
PAGED_CODE();
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVFinalizeSrvCall.\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVFinalizeSrvCall: SrvCall: %08lx, Force: %d.\n",
|
|
PsGetCurrentThreadId(), pSrvCall, Force));
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: MRxDAVFinalizeSrvCall: SrvCallName: %wZ\n",
|
|
PsGetCurrentThreadId(), pSrvCall->pSrvCallName));
|
|
|
|
//
|
|
// We allocated memory for pSrvCall->Context, so it better not be NULL.
|
|
//
|
|
ASSERT(pSrvCall != NULL);
|
|
|
|
//
|
|
// If the MiniRedir didn't get a chance to allocate a SrvCall, then we
|
|
// should return right away.
|
|
//
|
|
if (pSrvCall->Context == NULL) {
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: MRxDAVFinalizeSrvCall. pSrvCall->Context == NULL\n",
|
|
PsGetCurrentThreadId()));
|
|
return NtStatus;
|
|
}
|
|
|
|
ASSERT(pSrvCall->Context != NULL);
|
|
|
|
//
|
|
// If we did not create any server entry for this server in the user mode,
|
|
// then we do not need to go to the user mode at all. This fact is
|
|
// indicated by the ServerID field in the WEBDAV_SRV_CALL strucutre. If the
|
|
// ID value is zero, that implies that the server entry was not created.
|
|
//
|
|
DavSrvCall = (PWEBDAV_SRV_CALL)pSrvCall->Context;
|
|
if (DavSrvCall->ServerID == 0) {
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: No server entry was created in the user mode.\n",
|
|
PsGetCurrentThreadId()));
|
|
goto EXIT_THE_FUNCTION;
|
|
}
|
|
|
|
//
|
|
// Unfortunately, we do not have an RxContext here and hence have to create
|
|
// one. An RxContext is required for a request to be reflected up.
|
|
//
|
|
RxContext = RxCreateRxContext(NULL, RxDeviceObject, 0);
|
|
if (RxContext == NULL) {
|
|
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: MRxDAVFinalizeSrvCall/RxCreateRxContext: "
|
|
"NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
|
|
goto EXIT_THE_FUNCTION;
|
|
}
|
|
|
|
//
|
|
// We need to send the SrvCall to the format routine and use the
|
|
// MRxContext[1] pointer of the RxContext structure to store it.
|
|
//
|
|
RxContext->MRxContext[1] = (PVOID)pSrvCall;
|
|
|
|
NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
|
|
SIZEOF_DAV_SPECIFIC_CONTEXT,
|
|
MRxDAVFormatTheDAVContext,
|
|
DAV_MINIRDR_ENTRY_FROM_FINALIZESRVCALL,
|
|
MRxDAVFinalizeSrvCallContinuation,
|
|
"MRxDAVFinalizeSrvCall");
|
|
if (NtStatus != ERROR_SUCCESS) {
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: MRxDAVFinalizeSrvCall/UMRxAsyncEngOuterWrapper: "
|
|
"NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
|
|
}
|
|
|
|
EXIT_THE_FUNCTION:
|
|
|
|
if (RxContext) {
|
|
RxDereferenceAndDeleteRxContext(RxContext);
|
|
}
|
|
|
|
//
|
|
// Free up the memory allocated for the context pointer.
|
|
//
|
|
RxFreePool(pSrvCall->Context);
|
|
pSrvCall->Context = NULL;
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Leaving MRxDAVFinalizeSrvCall with NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MRxDAVFinalizeSrvCallContinuation(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the continuation routine which finalizes a SrvCall.
|
|
|
|
Arguments:
|
|
|
|
AsyncEngineContext - The Reflectors context.
|
|
|
|
RxContext - The RDBSS context.
|
|
|
|
Return Value:
|
|
|
|
RXSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVFinalizeSrvCallContinuation!!!!\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVFinalizeSrvCallContinuation: "
|
|
"AsyncEngineContext: %08lx, RxContext: %08lx\n",
|
|
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
|
|
|
|
//
|
|
// Try usermode.
|
|
//
|
|
NtStatus = UMRxSubmitAsyncEngUserModeRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENTS,
|
|
MRxDAVFormatUserModeSrvCallFinalizeRequest,
|
|
MRxDAVPrecompleteUserModeSrvCallFinalizeRequest
|
|
);
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Leaving MRxDAVFinalizeSrvCallContinuation with NtStatus"
|
|
" = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MRxDAVFormatUserModeSrvCallFinalizeRequest(
|
|
IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
|
|
IN ULONG WorkItemLength,
|
|
OUT PULONG_PTR ReturnedLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine formats the SrvCall finalize request being sent to the user
|
|
mode for processing.
|
|
|
|
Arguments:
|
|
|
|
RxContext - The RDBSS context.
|
|
|
|
AsyncEngineContext - The reflctor's context.
|
|
|
|
WorkItem - The work item buffer.
|
|
|
|
WorkItemLength - The length of the work item buffer.
|
|
|
|
ReturnedLength -
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
|
|
PMRX_SRV_CALL SrvCall = NULL;
|
|
PWEBDAV_SRV_CALL DavSrvCall = NULL;
|
|
PDAV_USERMODE_FINALIZE_SRVCALL_REQUEST FinSrvCallReq = NULL;
|
|
PWCHAR ServerName = NULL;
|
|
ULONG ServerNameLengthInBytes = 0;
|
|
PBYTE SecondaryBuff = NULL;
|
|
|
|
PAGED_CODE();
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVFormatUserModeSrvCallFinalizeRequest.\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVFormatUserModeSrvCallFinalizeRequest: "
|
|
"AsyncEngineContext: %08lx, RxContext: %08lx.\n",
|
|
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
|
|
|
|
//
|
|
// SrvCall was set to MRxContext[0] in MRxDAVFinalizeSrvCall. We need it to
|
|
// get the ServerID.
|
|
//
|
|
SrvCall = (PMRX_SRV_CALL)RxContext->MRxContext[1];
|
|
DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
|
|
ASSERT(DavSrvCall != NULL);
|
|
|
|
DavWorkItem->WorkItemType = UserModeFinalizeSrvCall;
|
|
|
|
FinSrvCallReq = &(DavWorkItem->FinalizeSrvCallRequest);
|
|
|
|
//
|
|
// Set the ServerID.
|
|
//
|
|
FinSrvCallReq->ServerID = DavSrvCall->ServerID;
|
|
|
|
//
|
|
// Set the Server name.
|
|
//
|
|
ServerName = &(SrvCall->pSrvCallName->Buffer[1]);
|
|
ServerNameLengthInBytes = (1 + wcslen(ServerName)) * sizeof(WCHAR);
|
|
SecondaryBuff = UMRxAllocateSecondaryBuffer(AsyncEngineContext,
|
|
ServerNameLengthInBytes);
|
|
if (SecondaryBuff == NULL) {
|
|
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("ld: MRxDAVFormatUserModeSrvCallFinalizeRequest/"
|
|
"UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
goto EXIT_THE_FUNCTION;
|
|
}
|
|
|
|
FinSrvCallReq->ServerName = (PWCHAR)SecondaryBuff;
|
|
|
|
wcscpy(FinSrvCallReq->ServerName, ServerName);
|
|
|
|
EXIT_THE_FUNCTION:
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Leaving MRxDAVFormatUserModeSrvCallFinalizeRequest "
|
|
"with NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
|
|
BOOL
|
|
MRxDAVPrecompleteUserModeSrvCallFinalizeRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
|
|
ULONG WorkItemLength,
|
|
BOOL OperationCancelled
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The precompletion routine for the finalize SrvCall request.
|
|
|
|
Arguments:
|
|
|
|
RxContext - The RDBSS context.
|
|
|
|
AsyncEngineContext - The reflctor's context.
|
|
|
|
WorkItem - The work item buffer.
|
|
|
|
WorkItemLength - The length of the work item buffer.
|
|
|
|
OperationCancelled - TRUE if this operation was cancelled by the user.
|
|
|
|
Return Value:
|
|
|
|
TRUE - UMRxAsyncEngineCalldownIrpCompletion is called by the function
|
|
UMRxCompleteUserModeRequest after we return.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PDAV_USERMODE_WORKITEM WorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
|
|
PDAV_USERMODE_FINALIZE_SRVCALL_REQUEST FinSrvCallReq;
|
|
|
|
PAGED_CODE();
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Entering MRxDAVPrecompleteUserModeSrvCallFinalizeRequest\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
DavDbgTrace(DAV_TRACE_CONTEXT,
|
|
("%ld: MRxDAVPrecompleteUserModeSrvCallFinalizeRequest: "
|
|
"AsyncEngineContext: %08lx, RxContext: %08lx.\n",
|
|
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
|
|
|
|
FinSrvCallReq = &(WorkItem->FinalizeSrvCallRequest);
|
|
|
|
if (OperationCancelled) {
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: MRxDAVPrecompleteUserModeSrvCallFinalizeRequest: Operation Cancelled. "
|
|
"AsyncEngineContext = %08lx, RxContext = %08lx.\n",
|
|
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
|
|
}
|
|
|
|
//
|
|
// We need to free up the heap we allocated in the format routine.
|
|
//
|
|
if (FinSrvCallReq->ServerName != NULL) {
|
|
|
|
NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
|
|
(PBYTE)FinSrvCallReq->ServerName);
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVPrecompleteUserModeSrvCallFinalizeRequest/"
|
|
"UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
|
|
PsGetCurrentThreadId(), NtStatus));
|
|
}
|
|
|
|
}
|
|
|
|
if (AsyncEngineContext->Status != STATUS_SUCCESS) {
|
|
DavDbgTrace(DAV_TRACE_ERROR,
|
|
("%ld: ERROR: MRxDAVPrecompleteUserModeSrvCallFinalizeRequest. "
|
|
"Finalize SrvCall Failed!!!\n",
|
|
PsGetCurrentThreadId()));
|
|
}
|
|
|
|
DavDbgTrace(DAV_TRACE_DETAIL,
|
|
("%ld: Leaving MRxDAVPrecompleteUserModeSrvCallFinalizeRequest\n",
|
|
PsGetCurrentThreadId()));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
MRxDAVSrvCallWinnerNotify(
|
|
IN PMRX_SRV_CALL pSrvCall,
|
|
IN BOOLEAN ThisMinirdrIsTheWinner,
|
|
IN OUT PVOID pSrvCallContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine finalizes the mini rdr context associated with an RDBSS Server call instance
|
|
|
|
Arguments:
|
|
|
|
pSrvCall - the Server Call
|
|
|
|
ThisMinirdrIsTheWinner - TRUE if this mini rdr is the choosen one.
|
|
|
|
pSrvCallContext - the server call context created by the mini redirector.
|
|
|
|
Return Value:
|
|
|
|
RXSTATUS - The return status for the operation
|
|
|
|
Notes:
|
|
|
|
The two phase construction protocol for Server calls is required because of parallel
|
|
initiation of a number of mini redirectors. The RDBSS finalizes the particular mini
|
|
redirector to be used in communicating with a given server based on quality of
|
|
service criterion.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|