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.
 
 
 
 
 
 

327 lines
9.8 KiB

/*++
Copyright (c) 1989-1993 Microsoft Corporation
Module Name:
shadow.c
Abstract:
This module contains the code that implements the fast loopback routines
Author:
Ahmed Mohamed (ahmedm) 15-Dec-2001
Environment:
Kernel mode
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include <srvfsctl.h>
#define SERVER_DEVICE_NAME_W L"\\Device\\LanmanServer"
#define MrxLog(x) // DbgPrint x
typedef struct {
MRXSHADOW_SRV_OPEN;
//
// State obtained from srv
//
SRV_RESPONSE_HANDLE_DUP UnderlyingHandle;
SRV_RESUME_KEY Key;
}MRXSMBSHADOW_SRV_OPEN, *PMRXSMBSHADOW_SRV_OPEN;
NTSTATUS
MRxSmbCloseShadowSrvOpen(PRX_CONTEXT RxContext)
{
PMRXSMBSHADOW_SRV_OPEN MrxSmbShadowSrvOpen;
NTSTATUS status;
// if we can find an active queue then add this item to it, otherwise call
// underlying device to satisfy IO
MrxSmbShadowSrvOpen = (PMRXSMBSHADOW_SRV_OPEN) RxContext->pRelevantSrvOpen->ShadowContext;
if (MrxSmbShadowSrvOpen != NULL) {
ObDereferenceObject(MrxSmbShadowSrvOpen->UnderlyingFileObject);
ZwClose(MrxSmbShadowSrvOpen->UnderlyingHandle.hFile);
ExFreePool(MrxSmbShadowSrvOpen);
RxContext->pRelevantSrvOpen->ShadowContext = NULL;
}
return STATUS_SUCCESS;
}
PSRV_REQUEST_RESUME_KEY
MRxSmbQueryResumeKey(PRX_CONTEXT RxContext)
{
PRX_CONTEXT LocalRxContext = NULL;
PSRV_REQUEST_RESUME_KEY key = NULL;
NTSTATUS status = STATUS_NO_MEMORY;
PIRP irp;
IO_STATUS_BLOCK ios;
irp = RxContext->CurrentIrp;
if (irp != NULL) {
key = ExAllocatePool( NonPagedPool,
sizeof(*key) + SRV_LWIO_CONTEXT_SIZE);
}
if (key != NULL) {
LocalRxContext = RxCreateRxContext(NULL,
RxContext->RxDeviceObject,
RX_CONTEXT_FLAG_WAIT);
}
if (LocalRxContext != NULL) {
PLOWIO_CONTEXT LowIoContext = &LocalRxContext->LowIoContext;
LocalRxContext->pFcb = RxContext->pFcb;
LocalRxContext->pFobx = RxContext->pFobx;
LocalRxContext->pRelevantSrvOpen = RxContext->pRelevantSrvOpen;
LocalRxContext->CurrentIrp = irp;
LocalRxContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
LowIoContext->Operation = LOWIO_OP_FSCTL;
LowIoContext->ParamsFor.FsCtl.FsControlCode =
FSCTL_SRV_REQUEST_RESUME_KEY;
LowIoContext->ParamsFor.FsCtl.MinorFunction =
IRP_MN_USER_FS_REQUEST;
LowIoContext->ParamsFor.FsCtl.InputBufferLength = 0;
LowIoContext->ParamsFor.FsCtl.pInputBuffer = NULL;
LowIoContext->ParamsFor.FsCtl.OutputBufferLength =
(sizeof(*key) + SRV_LWIO_CONTEXT_SIZE);
LowIoContext->ParamsFor.FsCtl.pOutputBuffer = (PVOID) key;
SetFlag(LocalRxContext->Flags,
RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED);
LocalRxContext->InformationToReturn = 0;
LowIoContext->CompletionRoutine = NULL;
SetFlag(LowIoContext->Flags, LOWIO_CONTEXT_FLAG_SYNCCALL);
status = RxContext->RxDeviceObject->Dispatch->MRxLowIOSubmit[LowIoContext->Operation](LocalRxContext);
if (status == STATUS_PENDING) {
RxWaitSync(LocalRxContext);
status = LocalRxContext->StoredStatus;
}
LocalRxContext->CurrentIrp = NULL;
if (status == STATUS_SUCCESS) {
MrxLog(("Key is %I64x %I64x pid %I64d\n",
key->Key.ResumeKey, key->Key.Timestamp,
key->Key.Pid));
}
}
if (LocalRxContext) {
RxDereferenceAndDeleteRxContext(LocalRxContext);
}
if (status != STATUS_SUCCESS && key != NULL) {
ExFreePool(key);
key = NULL;
}
return key;
}
NTSTATUS
MrxSmbGetSrvHandle(PRX_CONTEXT RxContext)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING cwspath;
NTSTATUS status;
HANDLE FileHandle;
PMRXSMBSHADOW_SRV_OPEN SrvOpen;
SRV_REQUEST_HANDLE_DUP request;
SrvOpen = (PMRXSMBSHADOW_SRV_OPEN) RxContext->MRxContext[0];
RtlInitUnicodeString(&cwspath, SERVER_DEVICE_NAME_W);
InitializeObjectAttributes(
&ObjectAttributes,
&cwspath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
0,
NULL // !!! Security
);
status = ZwOpenFile(&FileHandle,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(status)) {
MrxLog(("Unable to open srv %x\n", status));
return status;
}
request.Key = SrvOpen->Key;
request.Options = RxContext->CurrentIrpSp->Parameters.Create.Options;
request.Options &= ~FILE_SYNCHRONOUS_IO_ALERT;
request.Options &= ~FILE_SYNCHRONOUS_IO_NONALERT;
request.Options &= ~FILE_COMPLETE_IF_OPLOCKED;
status = ZwFsControlFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
FSCTL_SRV_REQUEST_HANDLE_DUP,
(PVOID) &request,
sizeof(request),
(PVOID) &SrvOpen->UnderlyingHandle,
sizeof(SrvOpen->UnderlyingHandle));
if (status == STATUS_PENDING) {
ZwWaitForSingleObject(FileHandle, FALSE, NULL);
status = IoStatusBlock.Status;
}
ZwClose(FileHandle);
if (status == STATUS_SUCCESS) {
// set lock key
SrvOpen->LockKey = SrvOpen->UnderlyingHandle.LockKey;
// set file object
status = ObReferenceObjectByHandle(SrvOpen->UnderlyingHandle.hFile,
0L,
NULL,
KernelMode,
(PVOID *) &SrvOpen->UnderlyingFileObject,
NULL );
if (NT_SUCCESS(status)) {
PFAST_IO_DISPATCH fastIoDispatch;
SrvOpen->UnderlyingDeviceObject =
IoGetRelatedDeviceObject(SrvOpen->UnderlyingFileObject );
fastIoDispatch = SrvOpen->UnderlyingDeviceObject->DriverObject->FastIoDispatch;
if ( fastIoDispatch != NULL ) {
SrvOpen->FastIoRead = fastIoDispatch->FastIoRead;
SrvOpen->FastIoWrite = fastIoDispatch->FastIoWrite;
}
}
}
RxContext->MRxContext[0] = (PVOID) ((ULONG_PTR)status);
RxSignalSynchronousWaiter(RxContext);
return STATUS_SUCCESS;
}
NTSTATUS
MRxSmbCreateShadowSrvOpen(PRX_CONTEXT RxContext)
{
PFCB Fcb = (PFCB) RxContext->pFcb;
PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
ACCESS_MASK Access;
NTSTATUS status = STATUS_NO_MEMORY;
Access = RxContext->Create.NtCreateParameters.DesiredAccess;
if ( !(Access & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
(Access & DELETE) ) {
// Only do READ's and WRITE's.
// Don't activate on open-for-delete because of problems with RENAME
return STATUS_NOT_SUPPORTED;
}
if (SrvOpen->ShadowContext != NULL ||
!ExIsResourceAcquiredExclusiveLite(Fcb->Header.Resource)) {
return STATUS_NOT_SUPPORTED;
}
MrxLog(("MrxLoop create access %x file '%wZ'\n", Access,
&Fcb->PrivateAlreadyPrefixedName));
if (TRUE) {
PSRV_REQUEST_RESUME_KEY SrvKey = NULL;
PMRXSMBSHADOW_SRV_OPEN MrxSmbShadowSrvOpen;
MrxSmbShadowSrvOpen = ExAllocatePool( NonPagedPool, sizeof(*MrxSmbShadowSrvOpen));
if (MrxSmbShadowSrvOpen == NULL) {
return status;
}
RtlZeroMemory(MrxSmbShadowSrvOpen, sizeof(*MrxSmbShadowSrvOpen));
SrvKey = MRxSmbQueryResumeKey(RxContext);
if (SrvKey == NULL) {
ExFreePool(MrxSmbShadowSrvOpen);
return status;
}
MrxSmbShadowSrvOpen->Key = SrvKey->Key;
SrvOpen->ShadowContext = (PMRXSHADOW_SRV_OPEN) MrxSmbShadowSrvOpen;
KeInitializeEvent(&RxContext->SyncEvent,
NotificationEvent,
FALSE );
// issue fsctl to get handle from srv
RxContext->MRxContext[0] = (PVOID) MrxSmbShadowSrvOpen;
// post to a worker thread
status = RxPostToWorkerThread(RxContext->RxDeviceObject,
CriticalWorkQueue,
&RxContext->WorkQueueItem,
MrxSmbGetSrvHandle,
RxContext);
if (status == STATUS_SUCCESS) {
RxWaitSync(RxContext);
status = (NTSTATUS) ((ULONG_PTR)RxContext->MRxContext[0]);
}
if (status == STATUS_SUCCESS) {
if (!FlagOn(Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED)) {
SetFlag(Fcb->FcbState, FCB_STATE_FILE_IS_SHADOWED);
SetFlag(Fcb->FcbState, FCB_STATE_DISABLE_LOCAL_BUFFERING);
RxChangeBufferingState(
(PSRV_OPEN)SrvOpen,
NULL,
FALSE);
}
} else {
SrvOpen->ShadowContext = NULL;
ExFreePool(MrxSmbShadowSrvOpen);
}
ExFreePool(SrvKey);
}
return status;
}