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

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. getreq.c
  5. Abstract:
  6. This code handles getting requests and sending responses to the kernel for
  7. the user mode reflector library. This implements UMReflectorGetRequest
  8. and UMReflectorSendResponse.
  9. Author:
  10. Andy Herron (andyhe) 19-Apr-1999
  11. Environment:
  12. User Mode - Win32
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. ULONG
  18. UMReflectorGetRequest (
  19. PUMRX_USERMODE_WORKER_INSTANCE WorkerHandle,
  20. PUMRX_USERMODE_WORKITEM_HEADER ResponseWorkItem,
  21. PUMRX_USERMODE_WORKITEM_HEADER ReceiveWorkItem,
  22. BOOL revertAlreadyDone
  23. )
  24. /*++
  25. Routine Description:
  26. This routine sends down an IOCTL to get a request and in some cases
  27. send a response.
  28. Arguments:
  29. Handle - The reflector's handle.
  30. ResponseWorkItem - Response to an earlier request.
  31. ReceiveWorkItem - Buffer to receive another request.
  32. revertAlreadyDone - If this is TRUE, it means that the thread that is
  33. executing this function has been reverted back to its
  34. original state. When the request is picked up from the
  35. kernel, in some cases the thread impersonates the client
  36. that issued the request. If we revert back in the
  37. usermode for some reason, then we don't need to revert
  38. back in the kernel.
  39. Return Value:
  40. The return value is a Win32 error code. STATUS_SUCCESS is returned on
  41. success.
  42. --*/
  43. {
  44. PUMRX_USERMODE_WORKITEM_ADDON workItem = NULL;
  45. PUMRX_USERMODE_WORKITEM_ADDON previousWorkItem = NULL;
  46. BOOL SuccessfulOperation;
  47. ULONG NumberOfBytesTransferred;
  48. ULONG rc;
  49. if (WorkerHandle == NULL || ReceiveWorkItem == NULL) {
  50. RlDavDbgPrint(("%ld: ERROR: UMReflectorGetRequest. Invalid Parameter.\n",
  51. GetCurrentThreadId()));
  52. return ERROR_INVALID_PARAMETER;
  53. }
  54. //
  55. // We get back to our item by subtracting off of the item passed to us.
  56. // this is safe because we fully control allocation.
  57. //
  58. workItem = (PUMRX_USERMODE_WORKITEM_ADDON) (PCHAR)((PCHAR)ReceiveWorkItem -
  59. FIELD_OFFSET(UMRX_USERMODE_WORKITEM_ADDON, Header));
  60. ASSERT(workItem->WorkItemState == WorkItemStateNotYetSentToKernel);
  61. workItem->WorkItemState = WorkItemStateInKernel;
  62. if (ResponseWorkItem != NULL) {
  63. //
  64. // If we have a response to send, then we don't have to go check the
  65. // free pending list. Just do it now.
  66. //
  67. previousWorkItem = (PUMRX_USERMODE_WORKITEM_ADDON)
  68. (PCHAR)((PCHAR)ResponseWorkItem -
  69. FIELD_OFFSET(UMRX_USERMODE_WORKITEM_ADDON, Header));
  70. ASSERT(previousWorkItem->WorkItemState != WorkItemStateFree);
  71. ASSERT(previousWorkItem->WorkItemState != WorkItemStateAvailable);
  72. previousWorkItem->WorkItemState = WorkItemStateResponseNotYetToKernel;
  73. if (WorkerHandle->IsImpersonating) {
  74. ASSERT( (ResponseWorkItem->Flags & UMRX_WORKITEM_IMPERSONATING) );
  75. WorkerHandle->IsImpersonating = FALSE;
  76. //
  77. // If we have already reverted back to the threads original context,
  78. // then we clear this flag as we don't need to revert back in the
  79. // kernel.
  80. //
  81. if (revertAlreadyDone) {
  82. ResponseWorkItem->Flags &= ~UMRX_WORKITEM_IMPERSONATING;
  83. }
  84. }
  85. SuccessfulOperation = DeviceIoControl(WorkerHandle->ReflectorHandle,
  86. IOCTL_UMRX_RESPONSE_AND_REQUEST,
  87. ResponseWorkItem,
  88. ResponseWorkItem->WorkItemLength,
  89. ReceiveWorkItem,
  90. ReceiveWorkItem->WorkItemLength,
  91. &NumberOfBytesTransferred,
  92. NULL);
  93. previousWorkItem->WorkItemState = WorkItemStateResponseFromKernel;
  94. } else {
  95. //
  96. // If this thread was impersonating a client when it came up, store that
  97. // info in the workitem that is being sent down to get the request. In the
  98. // kernel, the reflector will look at this flag and revert back. After
  99. // setting the flag, we set the IsImpersonating value to FALSE.
  100. //
  101. if (WorkerHandle->IsImpersonating) {
  102. //
  103. // If we have already reverted back to the threads original context,
  104. // then we do not set this flag as we don't need to revert back in
  105. // the kernel.
  106. //
  107. if (!revertAlreadyDone) {
  108. ReceiveWorkItem->Flags |= UMRX_WORKITEM_IMPERSONATING;
  109. }
  110. WorkerHandle->IsImpersonating = FALSE;
  111. }
  112. SuccessfulOperation = DeviceIoControl(WorkerHandle->ReflectorHandle,
  113. IOCTL_UMRX_GET_REQUEST,
  114. NULL,
  115. 0,
  116. ReceiveWorkItem,
  117. ReceiveWorkItem->WorkItemLength,
  118. &NumberOfBytesTransferred,
  119. NULL);
  120. }
  121. if (!SuccessfulOperation) {
  122. rc = GetLastError();
  123. RlDavDbgPrint(("%ld: ERROR: UMReflectorGetRequest/DeviceIoControl: Error Val = "
  124. "%08lx.\n", GetCurrentThreadId(), rc));
  125. workItem->WorkItemState = WorkItemStateNotYetSentToKernel;
  126. } else {
  127. rc = STATUS_SUCCESS;
  128. workItem->WorkItemState = WorkItemStateReceivedFromKernel;
  129. //
  130. // If the thread is Impersonating a client, store that info. This is
  131. // needed to tell the kernel to revert the thread back when it goes to
  132. // collect another request.
  133. //
  134. if( (ReceiveWorkItem->Flags & UMRX_WORKITEM_IMPERSONATING) ) {
  135. WorkerHandle->IsImpersonating = TRUE;
  136. }
  137. }
  138. return rc;
  139. }
  140. ULONG
  141. UMReflectorSendResponse (
  142. PUMRX_USERMODE_WORKER_INSTANCE WorkerHandle,
  143. PUMRX_USERMODE_WORKITEM_HEADER ResponseWorkItem
  144. )
  145. /*++
  146. Routine Description:
  147. This routine sends down an IOCTL to get send a response for an asynchronous
  148. request.
  149. Arguments:
  150. Handle - The reflector's handle.
  151. ResponseWorkItem - Response to an earlier request.
  152. Return Value:
  153. The return value is a Win32 error code. STATUS_SUCCESS is returned on
  154. success.
  155. --*/
  156. {
  157. PUMRX_USERMODE_WORKITEM_ADDON workItem = NULL;
  158. BOOL SuccessfulOperation;
  159. ULONG NumberOfBytesTransferred;
  160. ULONG rc;
  161. if (WorkerHandle == NULL || ResponseWorkItem == NULL) {
  162. return ERROR_INVALID_PARAMETER;
  163. }
  164. //
  165. // We get back to our item by subtracting off of the item passed to us.
  166. // This is safe because we fully control allocation.
  167. //
  168. workItem = (PUMRX_USERMODE_WORKITEM_ADDON)(PCHAR)((PCHAR)ResponseWorkItem -
  169. FIELD_OFFSET(UMRX_USERMODE_WORKITEM_ADDON, Header));
  170. ASSERT(workItem->WorkItemState == WorkItemStateReceivedFromKernel);
  171. workItem->WorkItemState = WorkItemStateResponseNotYetToKernel;
  172. if( (ResponseWorkItem->Flags & UMRX_WORKITEM_IMPERSONATING) ) {
  173. ResponseWorkItem->Flags &= ~UMRX_WORKITEM_IMPERSONATING;
  174. }
  175. SuccessfulOperation = DeviceIoControl(WorkerHandle->ReflectorHandle,
  176. IOCTL_UMRX_RESPONSE,
  177. ResponseWorkItem,
  178. ResponseWorkItem->WorkItemLength,
  179. NULL,
  180. 0,
  181. &NumberOfBytesTransferred,
  182. NULL);
  183. if (!SuccessfulOperation) {
  184. rc = GetLastError();
  185. } else {
  186. rc = ERROR_SUCCESS;
  187. }
  188. workItem->WorkItemState = WorkItemStateResponseFromKernel;
  189. return rc;
  190. }
  191. // getreq.c eof.