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.
244 lines
8.4 KiB
244 lines
8.4 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
getreq.c
|
|
|
|
Abstract:
|
|
|
|
This code handles getting requests and sending responses to the kernel for
|
|
the user mode reflector library. This implements UMReflectorGetRequest
|
|
and UMReflectorSendResponse.
|
|
|
|
Author:
|
|
|
|
Andy Herron (andyhe) 19-Apr-1999
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
ULONG
|
|
UMReflectorGetRequest (
|
|
PUMRX_USERMODE_WORKER_INSTANCE WorkerHandle,
|
|
PUMRX_USERMODE_WORKITEM_HEADER ResponseWorkItem,
|
|
PUMRX_USERMODE_WORKITEM_HEADER ReceiveWorkItem,
|
|
BOOL revertAlreadyDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sends down an IOCTL to get a request and in some cases
|
|
send a response.
|
|
|
|
Arguments:
|
|
|
|
Handle - The reflector's handle.
|
|
|
|
ResponseWorkItem - Response to an earlier request.
|
|
|
|
ReceiveWorkItem - Buffer to receive another request.
|
|
|
|
revertAlreadyDone - If this is TRUE, it means that the thread that is
|
|
executing this function has been reverted back to its
|
|
original state. When the request is picked up from the
|
|
kernel, in some cases the thread impersonates the client
|
|
that issued the request. If we revert back in the
|
|
usermode for some reason, then we don't need to revert
|
|
back in the kernel.
|
|
|
|
Return Value:
|
|
|
|
The return value is a Win32 error code. STATUS_SUCCESS is returned on
|
|
success.
|
|
|
|
--*/
|
|
{
|
|
PUMRX_USERMODE_WORKITEM_ADDON workItem = NULL;
|
|
PUMRX_USERMODE_WORKITEM_ADDON previousWorkItem = NULL;
|
|
BOOL SuccessfulOperation;
|
|
ULONG NumberOfBytesTransferred;
|
|
ULONG rc;
|
|
|
|
if (WorkerHandle == NULL || ReceiveWorkItem == NULL) {
|
|
RlDavDbgPrint(("%ld: ERROR: UMReflectorGetRequest. Invalid Parameter.\n",
|
|
GetCurrentThreadId()));
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// We get back to our item by subtracting off of the item passed to us.
|
|
// this is safe because we fully control allocation.
|
|
//
|
|
workItem = (PUMRX_USERMODE_WORKITEM_ADDON) (PCHAR)((PCHAR)ReceiveWorkItem -
|
|
FIELD_OFFSET(UMRX_USERMODE_WORKITEM_ADDON, Header));
|
|
|
|
ASSERT(workItem->WorkItemState == WorkItemStateNotYetSentToKernel);
|
|
workItem->WorkItemState = WorkItemStateInKernel;
|
|
|
|
if (ResponseWorkItem != NULL) {
|
|
//
|
|
// If we have a response to send, then we don't have to go check the
|
|
// free pending list. Just do it now.
|
|
//
|
|
previousWorkItem = (PUMRX_USERMODE_WORKITEM_ADDON)
|
|
(PCHAR)((PCHAR)ResponseWorkItem -
|
|
FIELD_OFFSET(UMRX_USERMODE_WORKITEM_ADDON, Header));
|
|
|
|
ASSERT(previousWorkItem->WorkItemState != WorkItemStateFree);
|
|
ASSERT(previousWorkItem->WorkItemState != WorkItemStateAvailable);
|
|
|
|
previousWorkItem->WorkItemState = WorkItemStateResponseNotYetToKernel;
|
|
|
|
if (WorkerHandle->IsImpersonating) {
|
|
ASSERT( (ResponseWorkItem->Flags & UMRX_WORKITEM_IMPERSONATING) );
|
|
WorkerHandle->IsImpersonating = FALSE;
|
|
//
|
|
// If we have already reverted back to the threads original context,
|
|
// then we clear this flag as we don't need to revert back in the
|
|
// kernel.
|
|
//
|
|
if (revertAlreadyDone) {
|
|
ResponseWorkItem->Flags &= ~UMRX_WORKITEM_IMPERSONATING;
|
|
}
|
|
}
|
|
|
|
SuccessfulOperation = DeviceIoControl(WorkerHandle->ReflectorHandle,
|
|
IOCTL_UMRX_RESPONSE_AND_REQUEST,
|
|
ResponseWorkItem,
|
|
ResponseWorkItem->WorkItemLength,
|
|
ReceiveWorkItem,
|
|
ReceiveWorkItem->WorkItemLength,
|
|
&NumberOfBytesTransferred,
|
|
NULL);
|
|
|
|
previousWorkItem->WorkItemState = WorkItemStateResponseFromKernel;
|
|
} else {
|
|
//
|
|
// If this thread was impersonating a client when it came up, store that
|
|
// info in the workitem that is being sent down to get the request. In the
|
|
// kernel, the reflector will look at this flag and revert back. After
|
|
// setting the flag, we set the IsImpersonating value to FALSE.
|
|
//
|
|
if (WorkerHandle->IsImpersonating) {
|
|
|
|
//
|
|
// If we have already reverted back to the threads original context,
|
|
// then we do not set this flag as we don't need to revert back in
|
|
// the kernel.
|
|
//
|
|
if (!revertAlreadyDone) {
|
|
ReceiveWorkItem->Flags |= UMRX_WORKITEM_IMPERSONATING;
|
|
}
|
|
WorkerHandle->IsImpersonating = FALSE;
|
|
}
|
|
SuccessfulOperation = DeviceIoControl(WorkerHandle->ReflectorHandle,
|
|
IOCTL_UMRX_GET_REQUEST,
|
|
NULL,
|
|
0,
|
|
ReceiveWorkItem,
|
|
ReceiveWorkItem->WorkItemLength,
|
|
&NumberOfBytesTransferred,
|
|
NULL);
|
|
}
|
|
|
|
if (!SuccessfulOperation) {
|
|
rc = GetLastError();
|
|
RlDavDbgPrint(("%ld: ERROR: UMReflectorGetRequest/DeviceIoControl: Error Val = "
|
|
"%08lx.\n", GetCurrentThreadId(), rc));
|
|
workItem->WorkItemState = WorkItemStateNotYetSentToKernel;
|
|
} else {
|
|
rc = STATUS_SUCCESS;
|
|
workItem->WorkItemState = WorkItemStateReceivedFromKernel;
|
|
//
|
|
// If the thread is Impersonating a client, store that info. This is
|
|
// needed to tell the kernel to revert the thread back when it goes to
|
|
// collect another request.
|
|
//
|
|
if( (ReceiveWorkItem->Flags & UMRX_WORKITEM_IMPERSONATING) ) {
|
|
WorkerHandle->IsImpersonating = TRUE;
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
ULONG
|
|
UMReflectorSendResponse (
|
|
PUMRX_USERMODE_WORKER_INSTANCE WorkerHandle,
|
|
PUMRX_USERMODE_WORKITEM_HEADER ResponseWorkItem
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sends down an IOCTL to get send a response for an asynchronous
|
|
request.
|
|
|
|
Arguments:
|
|
|
|
Handle - The reflector's handle.
|
|
|
|
ResponseWorkItem - Response to an earlier request.
|
|
|
|
Return Value:
|
|
|
|
The return value is a Win32 error code. STATUS_SUCCESS is returned on
|
|
success.
|
|
|
|
--*/
|
|
{
|
|
PUMRX_USERMODE_WORKITEM_ADDON workItem = NULL;
|
|
BOOL SuccessfulOperation;
|
|
ULONG NumberOfBytesTransferred;
|
|
ULONG rc;
|
|
|
|
if (WorkerHandle == NULL || ResponseWorkItem == NULL) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// We get back to our item by subtracting off of the item passed to us.
|
|
// This is safe because we fully control allocation.
|
|
//
|
|
workItem = (PUMRX_USERMODE_WORKITEM_ADDON)(PCHAR)((PCHAR)ResponseWorkItem -
|
|
FIELD_OFFSET(UMRX_USERMODE_WORKITEM_ADDON, Header));
|
|
|
|
ASSERT(workItem->WorkItemState == WorkItemStateReceivedFromKernel);
|
|
workItem->WorkItemState = WorkItemStateResponseNotYetToKernel;
|
|
|
|
if( (ResponseWorkItem->Flags & UMRX_WORKITEM_IMPERSONATING) ) {
|
|
ResponseWorkItem->Flags &= ~UMRX_WORKITEM_IMPERSONATING;
|
|
}
|
|
|
|
SuccessfulOperation = DeviceIoControl(WorkerHandle->ReflectorHandle,
|
|
IOCTL_UMRX_RESPONSE,
|
|
ResponseWorkItem,
|
|
ResponseWorkItem->WorkItemLength,
|
|
NULL,
|
|
0,
|
|
&NumberOfBytesTransferred,
|
|
NULL);
|
|
if (!SuccessfulOperation) {
|
|
rc = GetLastError();
|
|
} else {
|
|
rc = ERROR_SUCCESS;
|
|
}
|
|
|
|
workItem->WorkItemState = WorkItemStateResponseFromKernel;
|
|
|
|
return rc;
|
|
}
|
|
|
|
// getreq.c eof.
|
|
|