Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1485 lines
49 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
netroot.c
Abstract:
This module implements the routines for creating net roots for the WebDav
miniredir.
Author:
Rohan Kumar [RohanK] 24-April-1999
Revision History:
--*/
#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.
//
NTSTATUS
MRxDAVCreateVNetRootContinuation(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
);
NTSTATUS
MRxDAVFormatUserModeVNetRootCreateRequest(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
ULONG WorkItemLength,
PULONG_PTR ReturnedLength
);
BOOL
MRxDAVPrecompleteUserModeVNetRootCreateRequest(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
ULONG WorkItemLength,
BOOL OperationCancelled
);
NTSTATUS
MRxDAVFinalizeVNetRootContinuation(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
);
NTSTATUS
MRxDAVFormatUserModeVNetRootFinalizeRequest(
IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
IN ULONG WorkItemLength,
OUT PULONG_PTR ReturnedLength
);
BOOL
MRxDAVPrecompleteUserModeVNetRootFinalizeRequest(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
ULONG WorkItemLength,
BOOL OperationCancelled
);
NTSTATUS
MRxDAVDereferenceNetRootContext(
IN PWEBDAV_NET_ROOT DavNetRoot
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, MRxDAVUpdateNetRootState)
#pragma alloc_text(PAGE, MRxDAVCreateVNetRoot)
#pragma alloc_text(PAGE, MRxDAVCreateVNetRootContinuation)
#pragma alloc_text(PAGE, MRxDAVFormatUserModeVNetRootCreateRequest)
#pragma alloc_text(PAGE, MRxDAVPrecompleteUserModeVNetRootCreateRequest)
#pragma alloc_text(PAGE, MRxDAVFinalizeNetRoot)
#pragma alloc_text(PAGE, MRxDAVExtractNetRootName)
#pragma alloc_text(PAGE, MRxDAVFinalizeVNetRoot)
#pragma alloc_text(PAGE, MRxDAVFinalizeVNetRootContinuation)
#pragma alloc_text(PAGE, MRxDAVFormatUserModeVNetRootFinalizeRequest)
#pragma alloc_text(PAGE, MRxDAVPrecompleteUserModeVNetRootFinalizeRequest)
#pragma alloc_text(PAGE, MRxDAVDereferenceNetRootContext)
#endif
//
// Implementation of functions begins here.
//
NTSTATUS
MRxDAVUpdateNetRootState(
IN OUT PMRX_NET_ROOT pNetRoot
)
/*++
Routine Description:
This routine update the mini redirector state associated with a net root.
Arguments:
pNetRoot - the net root instance.
Return Value:
RXSTATUS - The return status for the operation
Notes:
--*/
{
PAGED_CODE();
if (pNetRoot->Context == NULL) {
pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
} else {
pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
}
return STATUS_SUCCESS;
}
NTSTATUS
MRxDAVCreateVNetRoot(
IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext
)
/*++
Routine Description:
This routine patches the RDBSS created net root instance with the
information required by the mini redirector.
Arguments:
pCreateNetRootContext - the net root context for calling back
Return Value:
RXSTATUS - The return status for the operation
Notes:
--*/
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PRX_CONTEXT RxContext = NULL;
PMRX_V_NET_ROOT pVNetRoot = NULL;
PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
PWEBDAV_DEVICE_OBJECT DavDeviceObject = NULL;
PUMRX_DEVICE_OBJECT UMRxDeviceObject = NULL;
PMRX_SRV_CALL pSrvCall = NULL;
PMRX_NET_ROOT pNetRoot = NULL;
BOOLEAN SynchronousIo = FALSE;
NTSTATUS ExNtStatus = STATUS_SUCCESS;
HANDLE ExDeviceHandle = INVALID_HANDLE_VALUE;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ExDeviceName;
IO_STATUS_BLOCK IoStatusBlock;
PKEY_VALUE_PARTIAL_INFORMATION DavKeyValuePartialInfo = NULL;
PIO_STACK_LOCATION IrpSp = NULL;
PFILE_OBJECT DavFileObject = NULL;
PWCHAR NewFileName = NULL;
ULONG NewFileNameLength = 0;
PAGED_CODE();
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Entering MRxDAVCreateVNetRoot\n", PsGetCurrentThreadId()));
DavDbgTrace(DAV_TRACE_CONTEXT,
("%ld: MRxDAVCreateVNetRoot: pVNetRoot = %08lx\n",
PsGetCurrentThreadId(), pVNetRoot));
RxContext = pCreateNetRootContext->RxContext;
pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;
DavDeviceObject = (PWEBDAV_DEVICE_OBJECT)(RxContext->RxDeviceObject);
UMRxDeviceObject = (PUMRX_DEVICE_OBJECT)&(DavDeviceObject->UMRefDeviceObject);
pNetRoot = pVNetRoot->pNetRoot;
pSrvCall = pNetRoot->pSrvCall;
DavVNetRoot = MRxDAVGetVNetRootExtension(pVNetRoot);
ASSERT(DavVNetRoot != NULL);
ASSERT(NodeType(pNetRoot) == RDBSS_NTC_NETROOT);
ASSERT(NodeType(pSrvCall) == RDBSS_NTC_SRVCALL);
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVCreateVNetRoot: NetRootName = %wZ\n",
PsGetCurrentThreadId(), pVNetRoot->pNetRoot->pNetRootName));
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVCreateVNetRoot: VNetRoot = %08lx\n",
PsGetCurrentThreadId(), pVNetRoot));
//
// Copy the LogonID in the MiniRedir's portion of the V_NET_ROOT.
//
DavVNetRoot->LogonID.LowPart = pVNetRoot->LogonId.LowPart;
DavVNetRoot->LogonID.HighPart = pVNetRoot->LogonId.HighPart;
DavVNetRoot->LogonIDSet = TRUE;
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVCreateVNetRoot: LogonID.LowPart = %08lx\n",
PsGetCurrentThreadId(), DavVNetRoot->LogonID.LowPart));
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVCreateVNetRoot: LogonID.HighPart = %08lx\n",
PsGetCurrentThreadId(), DavVNetRoot->LogonID.HighPart));
//
// There are cases when we fail, we want the error which SMB returned to be
// returned to the user. This is becuase SMB could have returned a more
// specific error like logon failure or something on the share where as we
// return share not found. To enable this we return STATUS_BAD_NETWORK_PATH
// when the creation of netroot fails instead of STATUS_BAD_NETWORK_NAME
// because MUP will overwrite SMBs error with our error if we return
// STATUS_BAD_NETWORK_NAME. STATUS_BAD_NETWORK_NAME is a specif error which
// implies that the share does not exist where as STATUS_BAD_NETWORK_PATH is
// a more general error.
//
//
// If the share name is a net root or a pipe, we reject it since SMB
// Mini-Redir is the only one that handles it.
//
if ( pNetRoot->Type == NET_ROOT_PIPE || pNetRoot->Type == NET_ROOT_MAILSLOT ) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVCreateVNetRoot: Invalid NetRootType\n",
PsGetCurrentThreadId()));
//
// We set the following flag in the DavVNetRoot structure to TRUE. This
// is because when the finalize comes, we don't need to go to the
// usermode.
//
DavVNetRoot->createVNetRootUnSuccessful = TRUE;
pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_PATH;
// pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_NAME;
pCreateNetRootContext->NetRootStatus = STATUS_BAD_NETWORK_PATH;
// pCreateNetRootContext->NetRootStatus = STATUS_BAD_NETWORK_NAME;
goto EXIT_THE_FUNCTION;
}
SynchronousIo = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVCreateVNetRoot: SynchronousIo = %d\n",
PsGetCurrentThreadId(), SynchronousIo));
//
// We need to pass the server and share names to the user mode to check
// whether they actually exist. RxContext has 4 pointers that the mini-redirs
// can use. Here we use MRxContext[1]. We store a reference to the pVNetRoot
// strucutre. MRxContext[0] is used to store a reference to the
// AsynEngineContext and this is done when the context gets created in the
// function UMRxCreateAsyncEngineContext.
//
RxContext->MRxContext[1] = pVNetRoot;
//
// We now need to go to the user mode and find out if this WebDav share
// exists on the server.
//
NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
SIZEOF_DAV_SPECIFIC_CONTEXT,
MRxDAVFormatTheDAVContext,
DAV_MINIRDR_ENTRY_FROM_CREATEVNETROOT,
MRxDAVCreateVNetRootContinuation,
"MRxDAVCreateVNetRoot");
if (NtStatus != STATUS_SUCCESS) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVCreateVNetRoot/UMRxAsyncEngOuterWrapper: "
"NtStatus = %08lx\n", PsGetCurrentThreadId(), NtStatus));
if (NtStatus == STATUS_ACCESS_DENIED ||
NtStatus == STATUS_LOGON_FAILURE ||
NtStatus == STATUS_NETWORK_CREDENTIAL_CONFLICT) {
pCreateNetRootContext->VirtualNetRootStatus = NtStatus;
} else {
pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_PATH;
}
//
// Don't set the NetRootStatus here since it is a global data structure
// shared among different VNetRoots (TS users). Failure on one VNetRoot
// should not affects the NetRoot.
//
goto EXIT_THE_FUNCTION;
}
//
// If we succeeded and the share is not a TAHOE share, nor an Office Web
// Server share, then we claim the share name. Otherwise we fail since the
// users intends to use the TAHOE specific features in Rosebud, or Office
// specific features in Shell.
//
if ( !DavVNetRoot->isTahoeShare && !DavVNetRoot->isOfficeShare ) {
pNetRoot->DeviceType = RxDeviceType(DISK);
pNetRoot->Type = NET_ROOT_DISK;
pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
} else {
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVCreateVNetRoot/UMRxAsyncEngOuterWrapper: "
"TAHOE or OFFICE Share\n", PsGetCurrentThreadId()));
pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_PATH;
// pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_NAME;
pCreateNetRootContext->NetRootStatus = STATUS_BAD_NETWORK_PATH;
// pCreateNetRootContext->NetRootStatus = STATUS_BAD_NETWORK_NAME;
}
if (pNetRoot->Context == NULL) {
pNetRoot->Context = RxAllocatePoolWithTag(PagedPool,
sizeof(WEBDAV_NET_ROOT),
DAV_NETROOT_POOLTAG);
if (pNetRoot->Context == NULL) {
pCreateNetRootContext->VirtualNetRootStatus = STATUS_INSUFFICIENT_RESOURCES;
pCreateNetRootContext->NetRootStatus = STATUS_INSUFFICIENT_RESOURCES;
} else {
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)pNetRoot->Context;
//
// Refcount of 2, one is taken away at VNetRoot finalization, another one is taken
// away at NetRoot finalization.
//
DavNetRoot->RefCount = 2;
DavNetRoot->pRdbssNetRoot = pNetRoot;
RxNameCacheInitialize(&DavNetRoot->NameCacheCtlGFABasic,
sizeof(FILE_BASIC_INFORMATION),
NameCacheMaxEntries);
RxNameCacheInitialize(&DavNetRoot->NameCacheCtlGFAStandard,
sizeof(FILE_STANDARD_INFORMATION),
NameCacheMaxEntries);
RxNameCacheInitialize(&DavNetRoot->NameCacheCtlFNF,
0,
NameCacheMaxEntries);
pVNetRoot->Context2 = DavNetRoot;
DavDbgTrace(DAV_TRACE_DAVNETROOT,
("MRxDav allocates DavNetRoot %x %x %x 2\n",DavNetRoot,pNetRoot,pVNetRoot));
}
} else {
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)pNetRoot->Context;
pVNetRoot->Context2 = DavNetRoot;
InterlockedIncrement(&DavNetRoot->RefCount);
DavDbgTrace(DAV_TRACE_DAVNETROOT,
("MRxDAVCreateVNetRoot ref DavNetRoot %x %x %x %d\n",DavNetRoot,pNetRoot,pVNetRoot,DavNetRoot->RefCount));
}
//
// We return from here since the code below was written for accomodating the
// exchange DAV Redir which was suppose to ship with Office 2000. Since that
// project (LocalStore which included the Exchange Redir) has been canned,
// (as of Dec 8th, 2000) we don't need to execute the code below any more.
// We will keep it around though, just in case.
//
goto EXIT_THE_FUNCTION;
//
// The Exchange Redir has been installed on the system. Now we need to find
// out if its loaded. This is an exchange share. If the exchange Redir is
// not installed, we claim the name.
//
DavKeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)DavExchangeDeviceName;
RtlInitUnicodeString( &(ExDeviceName), (PWCHAR)DavKeyValuePartialInfo->Data );
InitializeObjectAttributes(&(ObjectAttributes),
&(ExDeviceName),
OBJ_CASE_INSENSITIVE,
0,
NULL);
ExNtStatus = NtOpenFile(&(ExDeviceHandle),
0,
&(ObjectAttributes),
&(IoStatusBlock),
0,
0);
if (ExNtStatus != STATUS_SUCCESS) {
//
// This is an exchange share but the Exchange Redir is not installed.
// We will handle this.
//
ExDeviceHandle = INVALID_HANDLE_VALUE;
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVCreateVNetRoot. Exchange BUT No Redir\n",
PsGetCurrentThreadId()));
pNetRoot->DeviceType = RxDeviceType(DISK);
pNetRoot->Type = NET_ROOT_DISK;
pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
goto EXIT_THE_FUNCTION;
}
IrpSp = IoGetCurrentIrpStackLocation(RxContext->CurrentIrp);
DavFileObject = IrpSp->FileObject;
//
// The NewFileNameLength is = ExchangeDeviceNameLength + PathName. The
// DavKeyValuePartialInfo->DataLength contains an extra 2 bytes for the
// \0 char.
//
NewFileNameLength = ( DavKeyValuePartialInfo->DataLength +
DavFileObject->FileName.Length );
//
// If the first char is not a \, then we need to add another sizeof(WCHAR).
//
if (DavFileObject->FileName.Buffer[0] != L'\\') {
NewFileNameLength += sizeof(WCHAR);
}
//
// Allocate memory for the NewFileName.
//
NewFileName = ExAllocatePoolWithTag(PagedPool, NewFileNameLength, DAV_EXCHANGE_POOLTAG);
if (NewFileName == NULL) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVCreateVNetRoot/ExAllocatePoolWithTag\n",
PsGetCurrentThreadId()));
pCreateNetRootContext->VirtualNetRootStatus = STATUS_INSUFFICIENT_RESOURCES;
pCreateNetRootContext->NetRootStatus = STATUS_INSUFFICIENT_RESOURCES;
goto EXIT_THE_FUNCTION;
}
RtlZeroMemory(NewFileName, NewFileNameLength);
//
// Copy the new device name.
//
RtlCopyMemory(NewFileName,
DavKeyValuePartialInfo->Data,
DavKeyValuePartialInfo->DataLength);
//
// If the first char is not a \, then we need to copy it before we copy the
// rest of the name.
//
if (DavFileObject->FileName.Buffer[0] != L'\\') {
//
// Copy the \ next.
//
RtlCopyMemory( ( NewFileName + DavKeyValuePartialInfo->DataLength ),
L"\\",
sizeof(WCHAR) );
//
// Finally copy the PathName that was sent with this IRP.
//
RtlCopyMemory( ( NewFileName + DavKeyValuePartialInfo->DataLength + sizeof(WCHAR) ),
DavFileObject->FileName.Buffer,
DavFileObject->FileName.Length );
} else {
//
// Finally copy the PathName that was sent with this IRP.
//
RtlCopyMemory( ( NewFileName + DavKeyValuePartialInfo->DataLength ),
DavFileObject->FileName.Buffer,
DavFileObject->FileName.Length );
}
//
// Free the memory allocated in the FileObject's original filename buffer.
//
ExFreePool(DavFileObject->FileName.Buffer);
//
// Set the NewFileName in the FileObject.
//
DavFileObject->FileName.Buffer = NewFileName;
DavFileObject->FileName.Length = (USHORT)NewFileNameLength;
DavFileObject->FileName.MaximumLength = (USHORT)NewFileNameLength;
//
// Finally, set the status to STATUS_REPARSE so that the I/O manager will
// call into the Exchange Redir.
//
pCreateNetRootContext->VirtualNetRootStatus = STATUS_REPARSE;
pCreateNetRootContext->NetRootStatus = STATUS_REPARSE;
EXIT_THE_FUNCTION:
//
// Callback the RDBSS for resumption.
//
pCreateNetRootContext->Callback(pCreateNetRootContext);
//
// If we opened a handle to the exchange redir, we need to close it now.
//
if (ExDeviceHandle != INVALID_HANDLE_VALUE) {
NtClose(ExDeviceHandle);
}
//
// Map the error code to STATUS_PENDING since this triggers the
// synchronization mechanism in the RDBSS.
//
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Leaving MRxDAVCreateVNetRoot\n", PsGetCurrentThreadId()));
return STATUS_PENDING;
}
NTSTATUS
MRxDAVCreateVNetRootContinuation(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
)
/*++
Routine Description:
This routine checks to see if the share for which a VNetRoot 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 MRxDAVCreateVNetRootContinuation\n",
PsGetCurrentThreadId()));
DavDbgTrace(DAV_TRACE_CONTEXT,
("%ld: MRxDAVCreateVNetRootContinuation: "
"AsyncEngineContext: %08lx, RxContext: %08lx\n",
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
//
// Try usermode.
//
NtStatus = UMRxSubmitAsyncEngUserModeRequest(
UMRX_ASYNCENGINE_ARGUMENTS,
MRxDAVFormatUserModeVNetRootCreateRequest,
MRxDAVPrecompleteUserModeVNetRootCreateRequest
);
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Leaving MRxDAVCreateVNetRootContinuation with NtStatus ="
" %08lx.\n", PsGetCurrentThreadId(), NtStatus));
return NtStatus;
}
NTSTATUS
MRxDAVFormatUserModeVNetRootCreateRequest(
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 VNetRoot 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 WorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
PMRX_SRV_CALL SrvCall = NULL;
PWEBDAV_SRV_CALL DavSrvCall = NULL;
PMRX_NET_ROOT NetRoot = NULL;
PMRX_V_NET_ROOT VNetRoot = NULL;
PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
PSECURITY_CLIENT_CONTEXT SecurityClientContext = NULL;
PDAV_USERMODE_CREATE_V_NET_ROOT_REQUEST CreateVNetRootRequest = NULL;
PWCHAR ServerName = NULL, ShareName = NULL;
PWCHAR NetRootName = NULL, JustTheNetRootName = NULL;
ULONG ServerNameLengthInBytes = 0, NetRootNameLengthInBytes = 0;
PAGED_CODE();
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Entering MRxDAVFormatUserModeVNetRootCreateRequest!!!!\n",
PsGetCurrentThreadId()));
DavDbgTrace(DAV_TRACE_CONTEXT,
("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: AsyncEngineContext"
" = %08lx, RxContext = %08lx.\n", PsGetCurrentThreadId(),
AsyncEngineContext, RxContext));
CreateVNetRootRequest = &(WorkItem->CreateVNetRootRequest);
//
// We need to set the work item type.
//
WorkItem->WorkItemType = UserModeCreateVNetRoot;
//
// The VNetRoot pointer is stored in the MRxContext[1] pointer of the
// RxContext structure. This is done in the MRxDAVCreateVNetRoot function.
//
VNetRoot = (PMRX_V_NET_ROOT)RxContext->MRxContext[1];
ASSERT(VNetRoot != NULL);
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: "
"VNetRoot = %08lx\n", PsGetCurrentThreadId(), VNetRoot));
DavVNetRoot = MRxDAVGetVNetRootExtension(VNetRoot);
ASSERT(DavVNetRoot != NULL);
NetRoot = VNetRoot->pNetRoot;
ASSERT(NetRoot != NULL);
SrvCall = NetRoot->pSrvCall;
ASSERT(SrvCall != NULL);
DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
ASSERT(DavSrvCall != NULL);
SecurityClientContext = &(DavVNetRoot->SecurityClientContext);
//
// Copy the LogonID in the CreateRequest buffer. The LogonId is in the
// MiniRedir's portion of the V_NET_ROOT.
//
CreateVNetRootRequest->LogonID.LowPart = DavVNetRoot->LogonID.LowPart;
CreateVNetRootRequest->LogonID.HighPart = DavVNetRoot->LogonID.HighPart;
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: LogonID.LowPart = %08lx\n",
PsGetCurrentThreadId(), DavVNetRoot->LogonID.LowPart));
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: LogonID.HighPart = %08lx\n",
PsGetCurrentThreadId(), DavVNetRoot->LogonID.HighPart));
//
// Copy the ServerName.
//
ServerNameLengthInBytes = ( SrvCall->pSrvCallName->Length + sizeof(WCHAR) );
ServerName = (PWCHAR) UMRxAllocateSecondaryBuffer(AsyncEngineContext,
ServerNameLengthInBytes);
if (ServerName == NULL) {
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVFormatUserModeVNetRootCreateRequest/"
"UMRxAllocateSecondaryBuffer. NtStatus = %08lx.\n",
PsGetCurrentThreadId(), NtStatus));
goto EXIT_THE_FUNCTION;
}
RtlCopyBytes(ServerName,
SrvCall->pSrvCallName->Buffer,
SrvCall->pSrvCallName->Length);
ServerName[( ( (ServerNameLengthInBytes) / sizeof(WCHAR) ) - 1 )] = L'\0';
CreateVNetRootRequest->ServerName = ServerName;
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: ServerName: "
"%ws\n", PsGetCurrentThreadId(), ServerName));
//
// Copy the ServerID.
//
CreateVNetRootRequest->ServerID = DavSrvCall->ServerID;
//
// The NetRootName (pNetRootName) includes the ServerName. Hence to get the
// NetRootNameLengthInBytes, we do the following.
//
NetRootNameLengthInBytes = (NetRoot->pNetRootName->Length - SrvCall->pSrvCallName->Length);
//
// For '\0' at the end.
//
NetRootNameLengthInBytes += sizeof(WCHAR);
NetRootName = &(NetRoot->pNetRootName->Buffer[1]);
JustTheNetRootName = wcschr(NetRootName, L'\\');
//
// Copy the NetRoot (Share) name.
//
ShareName = (PWCHAR) UMRxAllocateSecondaryBuffer(AsyncEngineContext,
NetRootNameLengthInBytes);
if (ShareName == NULL) {
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVFormatUserModeVNetRootCreateRequest/"
"UMRxAllocateSecondaryBuffer. NtStatus = %08lx.\n",
PsGetCurrentThreadId(), NtStatus));
goto EXIT_THE_FUNCTION;
}
RtlCopyBytes(ShareName,
JustTheNetRootName,
(NetRoot->pNetRootName->Length - SrvCall->pSrvCallName->Length));
ShareName[( ( (NetRootNameLengthInBytes) / sizeof(WCHAR) ) - 1 )] = L'\0';
CreateVNetRootRequest->ShareName = ShareName;
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: ShareName: "
"%ws\n", PsGetCurrentThreadId(), ShareName));
//
// Impersonate the client who initiated the request. If we fail to
// impersonate, tough luck.
//
if (SecurityClientContext != NULL) {
NtStatus = UMRxImpersonateClient(SecurityClientContext, WorkItemHeader);
if (!NT_SUCCESS(NtStatus)) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVFormatUserModeVNetRootCreateRequest/"
"UMRxImpersonateClient. NtStatus = %08lx.\n",
PsGetCurrentThreadId(), NtStatus));
goto EXIT_THE_FUNCTION;
}
} else {
NtStatus = STATUS_INVALID_PARAMETER;
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVFormatUserModeVNetRootCreateRequest: "
"SecurityClientContext is NULL.\n",
PsGetCurrentThreadId()));
goto EXIT_THE_FUNCTION;
}
ASSERT(WorkItem->UserName[0] == L'\0' && WorkItem->Password[0] == L'\0');
if (VNetRoot->pUserName && VNetRoot->pUserName->Length) {
RtlCopyMemory(WorkItem->UserName,VNetRoot->pUserName->Buffer,VNetRoot->pUserName->Length);
}
if (VNetRoot->pPassword && VNetRoot->pPassword->Length) {
RtlCopyMemory(WorkItem->Password,VNetRoot->pPassword->Buffer,VNetRoot->pPassword->Length);
}
EXIT_THE_FUNCTION:
DavDbgTrace(DAV_TRACE_ENTRYEXIT,
("%ld: Leaving MRxDAVFormatUserModeVNetRootCreateRequest with "
"NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
return NtStatus;
}
BOOL
MRxDAVPrecompleteUserModeVNetRootCreateRequest(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
ULONG WorkItemLength,
BOOL OperationCancelled
)
/*++
Routine Description:
The precompletion routine for the CreateVNetRoot 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_CREATE_V_NET_ROOT_REQUEST CreateVNetRootRequest = NULL;
PDAV_USERMODE_CREATE_V_NET_ROOT_RESPONSE CreateVNetRootResponse = NULL;
PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
PMRX_V_NET_ROOT VNetRoot = NULL;
PAGED_CODE();
CreateVNetRootRequest = &(DavWorkItem->CreateVNetRootRequest);
CreateVNetRootResponse = &(DavWorkItem->CreateVNetRootResponse);
if (!OperationCancelled) {
//
// The VNetRoot pointer is stored in the MRxContext[1] pointer of the
// RxContext structure. This is done in the MRxDAVCreateVNetRoot
// function.
//
VNetRoot = (PMRX_V_NET_ROOT)RxContext->MRxContext[1];
DavVNetRoot = MRxDAVGetVNetRootExtension(VNetRoot);
ASSERT(DavVNetRoot != NULL);
} else {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: MRxDAVPrecompleteUserModeVNetRootCreateRequest: Operation Cancelled. "
"AsyncEngineContext = %08lx, RxContext = %08lx.\n",
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
}
//
// We need to free up the heaps, we allocated in the format routine.
//
if (CreateVNetRootRequest->ServerName != NULL) {
NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
(PBYTE)CreateVNetRootRequest->ServerName);
if (NtStatus != STATUS_SUCCESS) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootCreateRequest/"
"UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
PsGetCurrentThreadId(), NtStatus));
goto EXIT_THE_FUNCTION;
}
}
if (CreateVNetRootRequest->ShareName != NULL) {
NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
(PBYTE)CreateVNetRootRequest->ShareName);
if (NtStatus != STATUS_SUCCESS) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootCreateRequest/"
"UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
PsGetCurrentThreadId(), NtStatus));
goto EXIT_THE_FUNCTION;
}
}
if (!OperationCancelled) {
NtStatus = AsyncEngineContext->Status;
if (NtStatus != STATUS_SUCCESS) {
//
// If the CreateVNetRoot failed in the usermode, we set the following
// in the DavVNetRoot structure to TRUE. This is because when the
// finalize comes, we don't need to go to the usermode.
//
DavVNetRoot->createVNetRootUnSuccessful = TRUE;
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootCreateRequest:"
" NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
} else {
//
// We would have figured out in the usermode if this share is a TAHOE
// share or an Office Web Server share and whether this share allows
// PROPPATCH or not, and resporst available space or not
//
DavVNetRoot->isOfficeShare = CreateVNetRootResponse->isOfficeShare;
DavVNetRoot->isTahoeShare = CreateVNetRootResponse->isTahoeShare;
DavVNetRoot->fAllowsProppatch = CreateVNetRootResponse->fAllowsProppatch;
DavVNetRoot->fReportsAvailableSpace = CreateVNetRootResponse->fReportsAvailableSpace;
}
}
EXIT_THE_FUNCTION:
return(TRUE);
}
NTSTATUS
MRxDAVDereferenceNetRootContext(
IN PWEBDAV_NET_ROOT DavNetRoot
)
/*++
Routine Description:
This routine dereferences the Webdav NetRoot instance and free it if the refcount reaches 0.
Arguments:
DavNetRoot - The Webdav NetRoot.
Return Value:
STATUS_SUCCESS
--*/
{
PAGED_CODE();
if (DavNetRoot != NULL) {
ULONG RefCount;
RefCount = InterlockedDecrement(&DavNetRoot->RefCount);
DavDbgTrace(DAV_TRACE_DAVNETROOT,
("MRxDAVDereferenceNetRootContext %x %d\n",DavNetRoot,RefCount));
if (RefCount == 0) {
//
// Free storage associated with all entries in the name caches.
//
RxNameCacheFinalize(&DavNetRoot->NameCacheCtlGFABasic);
RxNameCacheFinalize(&DavNetRoot->NameCacheCtlGFAStandard);
RxNameCacheFinalize(&DavNetRoot->NameCacheCtlFNF);
//
// Reset the Context so that no further reference can be made to this DavNetRoot
//
ASSERT(DavNetRoot->pRdbssNetRoot->Context == DavNetRoot);
DavNetRoot->pRdbssNetRoot->Context = NULL;
RxFreePool(DavNetRoot);
DavDbgTrace(DAV_TRACE_DAVNETROOT,
("MRxDav frees DavNetRoot %x\n",DavNetRoot));
}
}
return STATUS_SUCCESS;
}
NTSTATUS
MRxDAVFinalizeNetRoot(
IN PMRX_NET_ROOT pNetRoot,
IN PBOOLEAN ForceDisconnect
)
/*++
Routine Description:
Arguments:
pVirtualNetRoot - The Virtual NetRoot.
ForceDisconnect - Disconnect is forced.
Return Value:
RXSTATUS - The return status for the operation
--*/
{
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)pNetRoot->Context;
PAGED_CODE();
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Entering UMRxFinalizeNetRoot!!!!\n",
PsGetCurrentThreadId()));
DavDbgTrace(DAV_TRACE_CONTEXT,
("%ld: UMRxFinalizeNetRoot: pNetRoot = %08lx.\n",
PsGetCurrentThreadId(), pNetRoot));
DavDbgTrace(DAV_TRACE_DAVNETROOT,
("MRxDAVFinalizeNetRoot deref DavNetRoot %x %x\n",pNetRoot->Context,pNetRoot));
MRxDAVDereferenceNetRootContext((PWEBDAV_NET_ROOT)pNetRoot->Context);
return STATUS_SUCCESS;
}
VOID
MRxDAVExtractNetRootName(
IN PUNICODE_STRING FilePathName,
IN PMRX_SRV_CALL SrvCall,
OUT PUNICODE_STRING NetRootName,
OUT PUNICODE_STRING RestOfName OPTIONAL
)
/*++
Routine Description:
This routine parses the input name into srv, netroot, and the
rest.
Arguments:
FilePathName - The filename that came in.
SrvCall - The SrvCall strucutre created by RDBSS.
NetRootName - Pointer to the netroot name.
RestOfName - Pointer to the Rest of the name.
Return Value:
none.
--*/
{
UNICODE_STRING xRestOfName;
ULONG length = FilePathName->Length;
PWCH w = FilePathName->Buffer;
PWCH wlimit = (PWCH)(((PCHAR)w) + length);
PWCH wlow;
PAGED_CODE();
//
// The netroot name starts after the SrvCall name.
//
w += (SrvCall->pSrvCallName->Length/sizeof(WCHAR));
NetRootName->Buffer = wlow = w;
//
// Calculate the length of the NetRoot name.
//
for ( ; ; ) {
if (w >= wlimit) break;
if ( (*w == OBJ_NAME_PATH_SEPARATOR) && (w != wlow) ){
#if ZZZ_MODE
if (*(w - 1) == L'z') {
w++;
continue;
}
#endif // if ZZZ_MODE
break;
}
w++;
}
NetRootName->Length = NetRootName->MaximumLength = (USHORT)((PCHAR)w - (PCHAR)wlow);
if (!RestOfName) {
RestOfName = &xRestOfName;
}
RestOfName->Buffer = w;
RestOfName->Length = RestOfName->MaximumLength = (USHORT)((PCHAR)wlimit - (PCHAR)w);
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVExtractNetRootName: FilePath = %wZ\n",
PsGetCurrentThreadId(), FilePathName));
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVExtractNetRootName: Srv = %wZ, Root = %wZ, "
"Rest = %wZ\n", PsGetCurrentThreadId(),
SrvCall->pSrvCallName, NetRootName, RestOfName));
return;
}
NTSTATUS
MRxDAVFinalizeVNetRoot(
IN PMRX_V_NET_ROOT pVNetRoot,
IN PBOOLEAN ForceDisconnect
)
/*++
Routine Description:
Arguments:
pVNetRoot - The virtual net root which has to be finalized.
ForceDisconnect - Disconnect is forced.
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PRX_CONTEXT RxContext = NULL;
PMRX_SRV_CALL SrvCall = NULL;
PRDBSS_DEVICE_OBJECT RxDeviceObject = NULL;
PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
PAGED_CODE();
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Entering UMRxFinalizeVNetRoot!!!!\n",
PsGetCurrentThreadId()));
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: UMRxFinalizeVNetRoot: NetRootName = %wZ\n",
PsGetCurrentThreadId(), pVNetRoot->pNetRoot->pNetRootName));
SrvCall = pVNetRoot->pNetRoot->pSrvCall;
RxDeviceObject = SrvCall->RxDeviceObject;
DavVNetRoot = MRxDAVGetVNetRootExtension(pVNetRoot);
ASSERT(DavVNetRoot != NULL);
//
// If we created the SecurityClientContext, we need to delete it now. We
// don't need this when we go up to the usermode to finalize the VNetRoot
// since we don't impersonate the client when doing this.
//
if (DavVNetRoot->SCAlreadyInitialized) {
SeDeleteClientSecurity(&(DavVNetRoot->SecurityClientContext));
}
DavDbgTrace(DAV_TRACE_DAVNETROOT,
("MRxDAVFinalizeVNetRoot deref DavNetRoot %x %x %x\n",pVNetRoot->Context2,pVNetRoot->pNetRoot,pVNetRoot));
MRxDAVDereferenceNetRootContext((PWEBDAV_NET_ROOT)pVNetRoot->Context2);
pVNetRoot->Context2 = NULL;
//
// We need to make sure that the creation of this VNetRoot was successful.
// If it was not, then we don't go to the usermode to finalize the
// PerUserEntry. Also, if the MiniRedir never got called during the
// creation of VNetRoot (possible in some failure case) then we should not
// go to the user mode. If the MiniRedir never gets called LogonIDSet will
// be FALSE. If the MiniRedir gets called this will be TRUE for sure.
//
if (DavVNetRoot->createVNetRootUnSuccessful || !DavVNetRoot->LogonIDSet) {
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: UMRxFinalizeVNetRoot. createVNetRootUnSuccessful\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: MRxDAVFinalizeVNetRoot/RxCreateRxContext: "
"NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
goto EXIT_THE_FUNCTION;
}
//
// We need to send the VNetRoot to the format routine and use the
// MRxContext[1] pointer of the RxContext structure to store it.
//
RxContext->MRxContext[1] = (PVOID)pVNetRoot;
NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
SIZEOF_DAV_SPECIFIC_CONTEXT,
MRxDAVFormatTheDAVContext,
DAV_MINIRDR_ENTRY_FROM_FINALIZEVNETROOT,
MRxDAVFinalizeVNetRootContinuation,
"MRxDAVFinalizeVNetRoot");
if (NtStatus != ERROR_SUCCESS) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: MRxDAVFinalizeVNetRoot/UMRxAsyncEngOuterWrapper: "
"NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
}
EXIT_THE_FUNCTION:
if (RxContext) {
RxDereferenceAndDeleteRxContext(RxContext);
}
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Leaving MRxDAVFinalizeVNetRoot with NtStatus = %08lx.\n",
PsGetCurrentThreadId(), NtStatus));
return NtStatus;
}
NTSTATUS
MRxDAVFinalizeVNetRootContinuation(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
)
/*++
ORoutine Description:
This is the continuation routine which finalizes a VNetRoot.
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 MRxDAVFinalizeVNetRootContinuation!!!!\n",
PsGetCurrentThreadId()));
DavDbgTrace(DAV_TRACE_CONTEXT,
("%ld: MRxDAVFinalizeVNetRootContinuation: "
"AsyncEngineContext: %08lx, RxContext: %08lx\n",
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
//
// Try usermode.
//
NtStatus = UMRxSubmitAsyncEngUserModeRequest(
UMRX_ASYNCENGINE_ARGUMENTS,
MRxDAVFormatUserModeVNetRootFinalizeRequest,
MRxDAVPrecompleteUserModeVNetRootFinalizeRequest
);
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Leaving MRxDAVFinalizeVNetRootContinuation with NtStatus"
" = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
return NtStatus;
}
NTSTATUS
MRxDAVFormatUserModeVNetRootFinalizeRequest(
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 VNetRoot 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;
PMRX_V_NET_ROOT VNetRoot = NULL;
PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
PWCHAR ServerName = NULL;
ULONG ServerNameLengthInBytes = 0;
PBYTE SecondaryBuff = NULL;
PDAV_USERMODE_FINALIZE_V_NET_ROOT_REQUEST DavFinalizeVNetRootRequest = NULL;
PAGED_CODE();
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Entering MRxDAVFormatUserModeVNetRootFinalizeRequest\n",
PsGetCurrentThreadId()));
DavDbgTrace(DAV_TRACE_CONTEXT,
("%ld: MRxDAVFormatUserModeVNetRootFinalizeRequest: "
"AsyncEngineContext: %08lx, RxContext: %08lx.\n",
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
VNetRoot = (PMRX_V_NET_ROOT)RxContext->MRxContext[1];
ASSERT(VNetRoot != NULL);
DavVNetRoot = MRxDAVGetVNetRootExtension(VNetRoot);
ASSERT(DavVNetRoot != NULL);
SrvCall = VNetRoot->pNetRoot->pSrvCall;
ASSERT(SrvCall != NULL);
DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
ASSERT(DavSrvCall != NULL);
DavWorkItem->WorkItemType = UserModeFinalizeVNetRoot;
DavFinalizeVNetRootRequest = &(DavWorkItem->FinalizeVNetRootRequest);
//
// Set the ServerID.
//
DavFinalizeVNetRootRequest->ServerID = DavSrvCall->ServerID;
//
// Set the LogonID.
//
DavFinalizeVNetRootRequest->LogonID.LowPart = DavVNetRoot->LogonID.LowPart;
DavFinalizeVNetRootRequest->LogonID.HighPart = DavVNetRoot->LogonID.HighPart;
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: MRxDAVFormatUserModeVNetRootFinalizeRequest: "
"LogonID.LowPart = %d, LogonID.HighPart = %d\n",
PsGetCurrentThreadId(),
DavVNetRoot->LogonID.LowPart, DavVNetRoot->LogonID.HighPart));
//
// 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: MRxDAVFormatUserModeVNetRootFinalizeRequest/"
"UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
PsGetCurrentThreadId(), NtStatus));
goto EXIT_THE_FUNCTION;
}
DavFinalizeVNetRootRequest->ServerName = (PWCHAR)SecondaryBuff;
wcscpy(DavFinalizeVNetRootRequest->ServerName, ServerName);
EXIT_THE_FUNCTION:
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Leaving MRxDAVFormatUserModeVNetRootFinalizeRequest "
"with NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
return NtStatus;
}
BOOL
MRxDAVPrecompleteUserModeVNetRootFinalizeRequest(
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
ULONG WorkItemLength,
BOOL OperationCancelled
)
/*++
Routine Description:
The precompletion routine for the finalize VNetRoot 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_V_NET_ROOT_REQUEST DavFinalizeVNetRootRequest = NULL;
PAGED_CODE();
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Entering MRxDAVPrecompleteUserModeVNetRootFinalizeRequest\n",
PsGetCurrentThreadId()));
DavDbgTrace(DAV_TRACE_CONTEXT,
("%ld: MRxDAVPrecompleteUserModeVNetRootFinalizeRequest: "
"AsyncEngineContext: %08lx, RxContext: %08lx.\n",
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
//
// A FinalizeVNetRoot request can never by Async.
//
ASSERT(AsyncEngineContext->AsyncOperation == FALSE);
//
// If this operation was cancelled, then we don't need to do anything
// special in the FinalizeVNetRoot case.
//
if (OperationCancelled) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: MRxDAVPrecompleteUserModeVNetRootFinalizeRequest: Operation Cancelled. "
"AsyncEngineContext = %08lx, RxContext = %08lx.\n",
PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
}
DavFinalizeVNetRootRequest = &(WorkItem->FinalizeVNetRootRequest);
//
// We need to free up the heap we allocated in the format routine.
//
if (DavFinalizeVNetRootRequest->ServerName != NULL) {
NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
(PBYTE)DavFinalizeVNetRootRequest->ServerName);
if (NtStatus != STATUS_SUCCESS) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootFinalizeRequestt/"
"UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
PsGetCurrentThreadId(), NtStatus));
}
}
if (AsyncEngineContext->Status != STATUS_SUCCESS) {
DavDbgTrace(DAV_TRACE_ERROR,
("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootFinalizeRequest. "
"Finalize VNetRoot Failed!!!\n",
PsGetCurrentThreadId()));
}
DavDbgTrace(DAV_TRACE_DETAIL,
("%ld: Leaving MRxDAVPrecompleteUserModeVNetRootFinalizeRequest\n",
PsGetCurrentThreadId()));
return TRUE;
}