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.
 
 
 
 
 
 

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.