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.

1133 lines
37 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. srvcall.c
  5. Abstract:
  6. This module implements the routines for handling the creation/manipulation
  7. of server entries in the connection engine database.
  8. Author:
  9. Balan Sethu Raman [SethuR]
  10. Rohan Kumar [RohanK] 04-April-1999
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "webdav.h"
  15. //
  16. // Mentioned below are the prototypes of functions tht are used only within
  17. // this module (file). These functions should not be exposed outside.
  18. //
  19. VOID
  20. MRxDAVSrvCallWrapper(
  21. PVOID Context
  22. );
  23. NTSTATUS
  24. MRxDAVCreateSrvCallContinuation(
  25. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  26. );
  27. NTSTATUS
  28. MRxDAVFormatUserModeSrvCallCreateRequest(
  29. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  30. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  31. ULONG WorkItemLength,
  32. PULONG_PTR ReturnedLength
  33. );
  34. BOOL
  35. MRxDAVPrecompleteUserModeSrvCallCreateRequest(
  36. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  37. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  38. ULONG WorkItemLength,
  39. BOOL OperationCancelled
  40. );
  41. NTSTATUS
  42. MRxDAVFinalizeSrvCallContinuation(
  43. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  44. );
  45. NTSTATUS
  46. MRxDAVFormatUserModeSrvCallFinalizeRequest(
  47. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  48. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  49. ULONG WorkItemLength,
  50. PULONG_PTR ReturnedLength
  51. );
  52. BOOL
  53. MRxDAVPrecompleteUserModeSrvCallFinalizeRequest(
  54. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  55. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  56. ULONG WorkItemLength,
  57. BOOL OperationCancelled
  58. );
  59. #ifdef ALLOC_PRAGMA
  60. #pragma alloc_text(PAGE, MRxDAVCreateSrvCall)
  61. #pragma alloc_text(PAGE, MRxDAVSrvCallWrapper)
  62. #pragma alloc_text(PAGE, MRxDAVCreateSrvCallContinuation)
  63. #pragma alloc_text(PAGE, MRxDAVFormatUserModeSrvCallCreateRequest)
  64. #pragma alloc_text(PAGE, MRxDAVPrecompleteUserModeSrvCallCreateRequest)
  65. #pragma alloc_text(PAGE, MRxDAVFinalizeSrvCall)
  66. #pragma alloc_text(PAGE, MRxDAVFinalizeSrvCallContinuation)
  67. #pragma alloc_text(PAGE, MRxDAVFormatUserModeSrvCallFinalizeRequest)
  68. #pragma alloc_text(PAGE, MRxDAVPrecompleteUserModeSrvCallFinalizeRequest)
  69. #pragma alloc_text(PAGE, MRxDAVSrvCallWinnerNotify)
  70. #endif
  71. //
  72. // Implementation of functions begins here.
  73. //
  74. NTSTATUS
  75. MRxDAVCreateSrvCall(
  76. PMRX_SRV_CALL SrvCall,
  77. PMRX_SRVCALL_CALLBACK_CONTEXT CallbackContext
  78. )
  79. /*++
  80. Routine Description:
  81. This routine handles the creation of SrvCalls.
  82. Arguments:
  83. SrvCall -
  84. CallBackContext - the call back context in RDBSS for continuation.
  85. Return Value:
  86. RXSTATUS - The return status for the operation
  87. Notes:
  88. --*/
  89. {
  90. NTSTATUS NtStatus = STATUS_SUCCESS;
  91. PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = CallbackContext;
  92. PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = NULL;
  93. PRX_CONTEXT RxContext = NULL;
  94. PAGED_CODE();
  95. #if 1
  96. SrvCalldownStructure = (PMRX_SRVCALLDOWN_STRUCTURE)(CallbackContext->SrvCalldownStructure);
  97. DavDbgTrace(DAV_TRACE_DETAIL,
  98. ("%ld: Entering MRxDAVCreateSrvCall!!!!\n",
  99. PsGetCurrentThreadId()));
  100. DavDbgTrace(DAV_TRACE_CONTEXT,
  101. ("%ld: MRxDAVCreateSrvCall: SrvCall: %08lx, CallbackContext: "
  102. "%08lx.\n", PsGetCurrentThreadId(), SrvCall, CallbackContext));
  103. DavDbgTrace(DAV_TRACE_DETAIL,
  104. ("%ld: MRxDAVCreateSrvCall: SrvCallName: %wZ\n",
  105. PsGetCurrentThreadId(), SrvCall->pSrvCallName));
  106. //
  107. // Perform the following checks.
  108. //
  109. ASSERT(NodeType(SrvCall) == RDBSS_NTC_SRVCALL);
  110. ASSERT(SrvCall);
  111. ASSERT(SrvCall->pSrvCallName);
  112. ASSERT(SrvCall->pSrvCallName->Buffer);
  113. ASSERT(SCCBC->RxDeviceObject);
  114. //
  115. // Before delaying the final close, RDBSS looks at the number of closes that
  116. // have been delayed and compares it against this value.
  117. //
  118. SrvCall->MaximumNumberOfCloseDelayedFiles = 150;
  119. //
  120. // Allocate memory for the context pointer in the SrvCall structure. This is
  121. // for the Mini-Redirs use.
  122. //
  123. ASSERT(SrvCall->Context == NULL);
  124. SrvCall->Context = RxAllocatePoolWithTag(NonPagedPool,
  125. sizeof(WEBDAV_SRV_CALL),
  126. DAV_SRVCALL_POOLTAG);
  127. if (SrvCall->Context == NULL) {
  128. //
  129. // There was an error in dispatching the MRxDAVSrvCallWrapper method to
  130. // a worker thread. Complete the request and return STATUS_PENDING.
  131. //
  132. DavDbgTrace(DAV_TRACE_ERROR,
  133. ("%ld: MRxDAVCreateSrvCall/RxAllocatePoolWithTag.\n",
  134. PsGetCurrentThreadId()));
  135. SCCBC->Status = STATUS_INSUFFICIENT_RESOURCES;
  136. SrvCalldownStructure->CallBack(SCCBC);
  137. NtStatus = STATUS_PENDING;
  138. return NtStatus;
  139. }
  140. RtlZeroMemory(SrvCall->Context, sizeof(WEBDAV_SRV_CALL));
  141. //
  142. // Check to see if the DAV server mentioned in the SrvCall exists. To do
  143. // this, we need to go to the usermode and call GetHostByName on the name
  144. // mentioned in the SrvCall strucutre.
  145. //
  146. RxContext = SrvCalldownStructure->RxContext;
  147. //
  148. // We need to pass the server name to the user mode to check whether such a
  149. // server actually exists. RxContext has 4 pointers that the mini-redirs
  150. // can use. Here we use MRxContext[1]. We store a reference to the SCCBC
  151. // strucutre which contains the name of the server. MRxContext[0] is used to
  152. // store a reference to the AsynEngineContext and this is done when the
  153. // context gets created in the function UMRxCreateAsyncEngineContext. The
  154. // pointer to SCCBC is also used while calling the callback function to
  155. // complete the creation of the SrvCall.
  156. //
  157. RxContext->MRxContext[1] = SCCBC;
  158. //
  159. // Dispatch the request to a system thread.
  160. //
  161. NtStatus = RxDispatchToWorkerThread((PRDBSS_DEVICE_OBJECT)MRxDAVDeviceObject,
  162. DelayedWorkQueue,
  163. MRxDAVSrvCallWrapper,
  164. RxContext);
  165. if (NtStatus == STATUS_SUCCESS) {
  166. //
  167. // Map the return value since the wrapper expects STATUS_PENDING.
  168. //
  169. NtStatus = STATUS_PENDING;
  170. } else {
  171. //
  172. // There was an error in dispatching the MRxDAVSrvCallWrapper method to
  173. // a worker thread. Complete the request and return STATUS_PENDING.
  174. //
  175. SCCBC->Status = NtStatus;
  176. SrvCalldownStructure->CallBack(SCCBC);
  177. NtStatus = STATUS_PENDING;
  178. }
  179. #else
  180. SCCBC->Status = STATUS_SUCCESS;
  181. SrvCalldownStructure->CallBack(SCCBC);
  182. NtStatus = STATUS_PENDING;
  183. #endif
  184. return(NtStatus);
  185. }
  186. VOID
  187. MRxDAVSrvCallWrapper(
  188. PVOID Context
  189. )
  190. /*++
  191. Routine Description:
  192. This routine is called by the worker thread. Its a routine that wraps the
  193. call to MRxDAVOuterWrapper.
  194. Arguments:
  195. RxContext - The RDBSS context.
  196. Return Value:
  197. RXSTATUS - The return status for the operation
  198. Notes:
  199. --*/
  200. {
  201. NTSTATUS NtStatus = STATUS_SUCCESS;
  202. PRX_CONTEXT RxContext = (PRX_CONTEXT)Context;
  203. PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = NULL;
  204. PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = NULL;
  205. PMRX_SRV_CALL SrvCall = NULL;
  206. PWEBDAV_SRV_CALL DavSrvCall = NULL;
  207. PAGED_CODE();
  208. DavDbgTrace(DAV_TRACE_DETAIL,
  209. ("%ld: Entering MRxDAVSrvCallWrapper!!!!\n",
  210. PsGetCurrentThreadId()));
  211. DavDbgTrace(DAV_TRACE_CONTEXT,
  212. ("%ld: MRxDAVSrvCallWrapper: RxContext: %08lx.\n",
  213. PsGetCurrentThreadId(), RxContext));
  214. NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
  215. SIZEOF_DAV_SPECIFIC_CONTEXT,
  216. MRxDAVFormatTheDAVContext,
  217. DAV_MINIRDR_ENTRY_FROM_CREATESRVCALL,
  218. MRxDAVCreateSrvCallContinuation,
  219. "MRxDAVCreateSrvCall");
  220. //
  221. // If we failed to queue the request to be sent to the usermode, then we
  222. // need to do some cleanup. If NtStatus is STATUS_CANCELLED then we would
  223. // have already done the cleanup in the MRxDAVHandleCreateSrvCallCancellation
  224. // funtcion. Hence we don't need to do it now.
  225. //
  226. if (NtStatus != STATUS_SUCCESS && NtStatus != STATUS_PENDING && NtStatus != STATUS_CANCELLED) {
  227. DavDbgTrace(DAV_TRACE_ERROR,
  228. ("%ld: ERROR: MRxDAVSrvCallWrapper/UMRxAsyncEngOuterWrapper: "
  229. "NtStatus = %08lx\n", PsGetCurrentThreadId(), NtStatus));
  230. //
  231. // The SrvCall pointer is stored in the SCCBC structure which is
  232. // stored in the MRxContext[1] pointer of the RxContext structure.
  233. // This is done in the MRxDAVCreateSrvCall function.
  234. //
  235. ASSERT(RxContext->MRxContext[1] != NULL);
  236. SCCBC = (PMRX_SRVCALL_CALLBACK_CONTEXT)RxContext->MRxContext[1];
  237. SrvCalldownStructure = SCCBC->SrvCalldownStructure;
  238. ASSERT(SrvCalldownStructure != NULL);
  239. SrvCall = SrvCalldownStructure->SrvCall;
  240. ASSERT(SrvCall != NULL);
  241. DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
  242. ASSERT(DavSrvCall != NULL);
  243. //
  244. // Free the memory that was allocatted for the SecurityClientContext in
  245. // the function MRxDAVFormatTheDAVContext. Before Freeing the memory, we
  246. // need to delete the SecurityClientContext.
  247. //
  248. if (DavSrvCall->SCAlreadyInitialized) {
  249. ASSERT(RxContext->MRxContext[2] != NULL);
  250. SeDeleteClientSecurity((PSECURITY_CLIENT_CONTEXT)RxContext->MRxContext[2]);
  251. RxFreePool(RxContext->MRxContext[2]);
  252. RxContext->MRxContext[2] = NULL;
  253. DavSrvCall->SCAlreadyInitialized = FALSE;
  254. }
  255. SCCBC->Status = NtStatus;
  256. SrvCalldownStructure->CallBack(SCCBC);
  257. }
  258. DavDbgTrace(DAV_TRACE_DETAIL,
  259. ("%ld: Leaving MRxDAVSrvCallWrapper with NtStatus = %08lx.\n",
  260. PsGetCurrentThreadId(), NtStatus));
  261. return;
  262. }
  263. NTSTATUS
  264. MRxDAVCreateSrvCallContinuation(
  265. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  266. )
  267. /*++
  268. Routine Description:
  269. This routine checks to see if the server for which a SrvCall is being
  270. created exists or not.
  271. Arguments:
  272. AsyncEngineContext - The Reflectors context.
  273. RxContext - The RDBSS context.
  274. Return Value:
  275. RXSTATUS - The return status for the operation
  276. --*/
  277. {
  278. NTSTATUS NtStatus = STATUS_SUCCESS;
  279. PAGED_CODE();
  280. DavDbgTrace(DAV_TRACE_DETAIL,
  281. ("%ld: Entering MRxDAVCreateSrvCallContinuation!!!!\n",
  282. PsGetCurrentThreadId()));
  283. DavDbgTrace(DAV_TRACE_CONTEXT,
  284. ("%ld: MRxDAVCreateSrvCallContinuation: "
  285. "AsyncEngineContext: %08lx, RxContext: %08lx\n",
  286. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  287. //
  288. // We are executing in the context of a worker thread. No point in holding
  289. // onto this thread. Set the Async flag irrespective of the nature of the
  290. // request. By nature we mean sync or async. Also since CreateSrvCall has
  291. // its own Callback, we do not need to call RxLowIoCompletion when the
  292. // AsyncEngineContext is getting finalized.
  293. //
  294. SetFlag(AsyncEngineContext->Flags, UMRX_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
  295. AsyncEngineContext->ShouldCallLowIoCompletion = FALSE;
  296. //
  297. // Try usermode.
  298. //
  299. NtStatus = UMRxSubmitAsyncEngUserModeRequest(
  300. UMRX_ASYNCENGINE_ARGUMENTS,
  301. MRxDAVFormatUserModeSrvCallCreateRequest,
  302. MRxDAVPrecompleteUserModeSrvCallCreateRequest
  303. );
  304. DavDbgTrace(DAV_TRACE_DETAIL,
  305. ("%ld: Leaving MRxDAVCreateSrvCallContinuation with NtStatus ="
  306. " %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  307. return NtStatus;
  308. }
  309. NTSTATUS
  310. MRxDAVFormatUserModeSrvCallCreateRequest(
  311. IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  312. IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  313. IN ULONG WorkItemLength,
  314. OUT PULONG_PTR ReturnedLength
  315. )
  316. /*++
  317. Routine Description:
  318. This routine formats the SrvCall create request being sent to the user mode
  319. for processing.
  320. Arguments:
  321. RxContext - The RDBSS context.
  322. AsyncEngineContext - The reflctor's context.
  323. WorkItem - The work item buffer.
  324. WorkItemLength - The length of the work item buffer.
  325. ReturnedLength -
  326. Return Value:
  327. STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES.
  328. --*/
  329. {
  330. NTSTATUS NtStatus = STATUS_SUCCESS;
  331. PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  332. PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = NULL;
  333. PMRX_SRV_CALL SrvCall = NULL;
  334. PWCHAR ServerName = NULL;
  335. DWORD ServerNameLenInBytes = 0;
  336. PBYTE SecondaryBuff = NULL;
  337. PDAV_USERMODE_CREATE_SRVCALL_REQUEST SrvCallCreateReq = NULL;
  338. PSECURITY_CLIENT_CONTEXT SecurityClientContext = NULL;
  339. PSECURITY_SUBJECT_CONTEXT SecSubCtx = NULL;
  340. PNT_CREATE_PARAMETERS NtCP = &(RxContext->Create.NtCreateParameters);
  341. PACCESS_TOKEN AccessToken = NULL;
  342. PAGED_CODE();
  343. DavDbgTrace(DAV_TRACE_DETAIL,
  344. ("%ld: Entering MRxDAVFormatUserModeSrvCallCreateRequest!!!!\n",
  345. PsGetCurrentThreadId()));
  346. DavDbgTrace(DAV_TRACE_CONTEXT,
  347. ("%ld: MRxDAVFormatUserModeSrvCallCreateRequest: "
  348. "AsyncEngineContext: %08lx, RxContext: %08lx.\n",
  349. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  350. SrvCallCreateReq = &(DavWorkItem->CreateSrvCallRequest);
  351. //
  352. // Get the SecuritySubjectContext.
  353. //
  354. ASSERT(NtCP->SecurityContext->AccessState != NULL);
  355. SecSubCtx = &(NtCP->SecurityContext->AccessState->SubjectSecurityContext);
  356. //
  357. // Get the AccessToken.
  358. //
  359. AccessToken = SeQuerySubjectContextToken(SecSubCtx);
  360. //
  361. // Get the LogonID for this user/session.
  362. //
  363. if (!SeTokenIsRestricted(AccessToken)) {
  364. NtStatus = SeQueryAuthenticationIdToken(AccessToken,
  365. &(SrvCallCreateReq->LogonID));
  366. if (NtStatus != STATUS_SUCCESS) {
  367. DavDbgTrace(DAV_TRACE_ERROR,
  368. ("%ld: ERROR: MRxDAVFormatUserModeCreateSrvCallRequest/"
  369. "SeQueryAuthenticationIdToken. NtStatus = %08lx.\n",
  370. PsGetCurrentThreadId(), NtStatus));
  371. goto EXIT_THE_FUNCTION;
  372. }
  373. } else {
  374. NtStatus = STATUS_ACCESS_DENIED;
  375. DavDbgTrace(DAV_TRACE_ERROR,
  376. ("%ld: ERROR: MRxDAVFormatUserModeCreateSrvCallRequest/"
  377. "SeTokenIsRestricted. NtStatus = %08lx.\n",
  378. PsGetCurrentThreadId(), NtStatus));
  379. goto EXIT_THE_FUNCTION;
  380. }
  381. //
  382. // Impersonate the client who initiated the request. If we fail to
  383. // impersonate, tough luck. The SecurityClientContext is stored in
  384. // RxContext->MRxContext[2]. This was done in MRxDAVFormatTheDAVContext.
  385. //
  386. ASSERT(RxContext->MRxContext[2] != NULL);
  387. SecurityClientContext = (PSECURITY_CLIENT_CONTEXT)RxContext->MRxContext[2];
  388. if (SecurityClientContext != NULL) {
  389. NtStatus = UMRxImpersonateClient(SecurityClientContext, WorkItemHeader);
  390. if (!NT_SUCCESS(NtStatus)) {
  391. DavDbgTrace(DAV_TRACE_ERROR,
  392. ("%ld: ERROR: MRxDAVFormatUserModeCreateSrvCallRequest/"
  393. "UMRxImpersonateClient. NtStatus = %08lx.\n",
  394. PsGetCurrentThreadId(), NtStatus));
  395. goto EXIT_THE_FUNCTION;
  396. }
  397. } else {
  398. NtStatus = STATUS_INVALID_PARAMETER;
  399. DavDbgTrace(DAV_TRACE_ERROR,
  400. ("%ld: ERROR: MRxDAVFormatUserModeCreateSrvCallRequest: "
  401. "SecurityClientContext is NULL.\n",
  402. PsGetCurrentThreadId()));
  403. goto EXIT_THE_FUNCTION;
  404. }
  405. DavWorkItem->WorkItemType = UserModeCreateSrvCall;
  406. SCCBC = (PMRX_SRVCALL_CALLBACK_CONTEXT)RxContext->MRxContext[1];
  407. SrvCall = SCCBC->SrvCalldownStructure->SrvCall;
  408. //
  409. // Set the name of the server to be verified. We need to allocate memory
  410. // for the UserModeInfoBuff before filling in the ServerName in it.
  411. //
  412. ASSERT(SrvCall->pSrvCallName);
  413. ServerName = &(SrvCall->pSrvCallName->Buffer[1]);
  414. ServerNameLenInBytes = (1 + wcslen(ServerName)) * sizeof(WCHAR);
  415. SecondaryBuff = UMRxAllocateSecondaryBuffer(AsyncEngineContext,
  416. ServerNameLenInBytes);
  417. if (SecondaryBuff == NULL) {
  418. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  419. DavDbgTrace(DAV_TRACE_ERROR,
  420. ("ld: MRxDAVFormatUserModeSrvCallCreateRequest/"
  421. "UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
  422. PsGetCurrentThreadId(), NtStatus));
  423. goto EXIT_THE_FUNCTION;
  424. }
  425. SrvCallCreateReq->ServerName = (PWCHAR)SecondaryBuff;
  426. wcscpy(SrvCallCreateReq->ServerName, ServerName);
  427. DavDbgTrace(DAV_TRACE_DETAIL,
  428. ("ld: MRxDAVFormatUserModeSrvCallCreateRequest: ServerName = %ws\n",
  429. PsGetCurrentThreadId(), SrvCallCreateReq->ServerName));
  430. if (RxContext->Create.UserName.Length) {
  431. RtlCopyMemory(DavWorkItem->UserName,RxContext->Create.UserName.Buffer,RxContext->Create.UserName.Length);
  432. }
  433. if (RxContext->Create.Password.Length) {
  434. RtlCopyMemory(DavWorkItem->Password,RxContext->Create.Password.Buffer,RxContext->Create.Password.Length);
  435. }
  436. EXIT_THE_FUNCTION:
  437. DavDbgTrace(DAV_TRACE_DETAIL,
  438. ("%ld: Leaving MRxDAVFormatUserModeSrvCallCreateRequest with "
  439. "NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  440. return NtStatus;
  441. }
  442. BOOL
  443. MRxDAVPrecompleteUserModeSrvCallCreateRequest(
  444. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  445. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  446. ULONG WorkItemLength,
  447. BOOL OperationCancelled
  448. )
  449. /*++
  450. Routine Description:
  451. The precompletion routine for the create SrvCall request.
  452. Arguments:
  453. RxContext - The RDBSS context.
  454. AsyncEngineContext - The reflctor's context.
  455. WorkItem - The work item buffer.
  456. WorkItemLength - The length of the work item buffer.
  457. OperationCancelled - TRUE if this operation was cancelled by the user.
  458. Return Value:
  459. FALSE - UMRxAsyncEngineCalldownIrpCompletion is NOT called by the function
  460. UMRxCompleteUserModeRequest after we return.
  461. --*/
  462. {
  463. NTSTATUS NtStatus = STATUS_SUCCESS;
  464. PDAV_USERMODE_WORKITEM WorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  465. PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = NULL;
  466. PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure = NULL;
  467. PMRX_SRV_CALL SrvCall = NULL;
  468. PDAV_USERMODE_CREATE_SRVCALL_REQUEST SrvCallCreateReq = NULL;
  469. PDAV_USERMODE_CREATE_SRVCALL_RESPONSE CreateSrvCallResponse = NULL;
  470. BOOL didFinalize = FALSE;
  471. PWEBDAV_SRV_CALL DavSrvCall = NULL;
  472. BOOL AsyncOperation = FALSE;
  473. PAGED_CODE();
  474. DavDbgTrace(DAV_TRACE_DETAIL,
  475. ("%ld: Entering MRxDAVPrecompleteUserModeSrvCallCreateRequest!!!!\n",
  476. PsGetCurrentThreadId()));
  477. DavDbgTrace(DAV_TRACE_CONTEXT,
  478. ("%ld: MRxDAVPrecompleteUserModeSrvCallCreateRequest: "
  479. "AsyncEngineContext: %08lx, RxContext: %08lx.\n",
  480. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  481. AsyncOperation = FlagOn(AsyncEngineContext->Flags, UMRX_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
  482. ASSERT(AsyncOperation == TRUE);
  483. //
  484. // We do the following only if the Operation has not been cancelled. If it
  485. // has been then this would have been done by the timer thread.
  486. //
  487. if (!OperationCancelled) {
  488. SCCBC = (PMRX_SRVCALL_CALLBACK_CONTEXT)RxContext->MRxContext[1];
  489. ASSERT(SCCBC != NULL);
  490. SrvCalldownStructure = SCCBC->SrvCalldownStructure;
  491. ASSERT(SrvCalldownStructure != NULL);
  492. SrvCall = SrvCalldownStructure->SrvCall;
  493. ASSERT(SrvCall != NULL);
  494. //
  495. // We allocated memory for it, so it better not be NULL.
  496. //
  497. DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
  498. ASSERT(DavSrvCall != NULL);
  499. //
  500. // Free the memory that was allocatted for the SecurityClientContext in the
  501. // function MRxDAVFormatTheDAVContext. Before Freeing the memory, we need
  502. // to delete the SecurityClientContext.
  503. //
  504. ASSERT(DavSrvCall->SCAlreadyInitialized == TRUE);
  505. ASSERT(RxContext->MRxContext[2] != NULL);
  506. SeDeleteClientSecurity((PSECURITY_CLIENT_CONTEXT)RxContext->MRxContext[2]);
  507. RxFreePool(RxContext->MRxContext[2]);
  508. RxContext->MRxContext[2] = NULL;
  509. DavSrvCall->SCAlreadyInitialized = FALSE;
  510. } else {
  511. DavDbgTrace(DAV_TRACE_ERROR,
  512. ("%ld: MRxDAVPrecompleteUserModeSrvCallCreateRequest: Operation Cancelled. "
  513. "AsyncEngineContext = %08lx, RxContext = %08lx.\n",
  514. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  515. }
  516. SrvCallCreateReq = &(WorkItem->CreateSrvCallRequest);
  517. CreateSrvCallResponse = &(WorkItem->CreateSrvCallResponse);
  518. //
  519. // We need to free up the heap we allocated in the format routine.
  520. //
  521. if (SrvCallCreateReq->ServerName != NULL) {
  522. if (AsyncEngineContext->Status != STATUS_SUCCESS) {
  523. DavDbgTrace(DAV_TRACE_ERROR,
  524. ("%ld: ERROR: MRxDAVPrecompleteUserModeSrvCallCreateRequest."
  525. " Server \"%ws\" is not a DAV server.\n",
  526. PsGetCurrentThreadId(), SrvCallCreateReq->ServerName));
  527. }
  528. NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
  529. (PBYTE)SrvCallCreateReq->ServerName);
  530. if (NtStatus != STATUS_SUCCESS) {
  531. DavDbgTrace(DAV_TRACE_ERROR,
  532. ("%ld: ERROR: MRxDAVPrecompleteUserModeSrvCallCreateRequest/"
  533. "UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
  534. PsGetCurrentThreadId(), NtStatus));
  535. }
  536. }
  537. if (!OperationCancelled) {
  538. //
  539. // Get this servers unique ID.
  540. //
  541. DavSrvCall->ServerID = CreateSrvCallResponse->ServerID;
  542. DavDbgTrace(DAV_TRACE_DETAIL,
  543. ("%ld: MRxDAVPrecompleteUserModeSrvCallCreateRequest: "
  544. "ServerID = %ld assigned to this server entry.\n",
  545. PsGetCurrentThreadId(), DavSrvCall->ServerID));
  546. //
  547. // Set the status in the callback structure.
  548. //
  549. SCCBC->Status = AsyncEngineContext->Status;
  550. }
  551. //
  552. // We call the first finalize here since we return STATUS_PENDING back to
  553. // the continuation routine in the create srvcall case. So the reference
  554. // that was made at the time of creation of the AsyncEngineContext is not
  555. // removed in the wrapper routine. The second finalize is because, we do not
  556. // call UMRxAsyncEngineCalldownIrpCompletion.
  557. //
  558. didFinalize = UMRxFinalizeAsyncEngineContext( &(AsyncEngineContext) );
  559. didFinalize = UMRxFinalizeAsyncEngineContext( &(AsyncEngineContext) );
  560. if (!OperationCancelled) {
  561. //
  562. // Call the callback function supplied by RDBSS.
  563. //
  564. SrvCalldownStructure->CallBack(SCCBC);
  565. }
  566. DavDbgTrace(DAV_TRACE_DETAIL,
  567. ("%ld: Leaving MRxDAVPrecompleteUserModeSrvCallCreateRequest.\n",
  568. PsGetCurrentThreadId()));
  569. return FALSE;
  570. }
  571. NTSTATUS
  572. MRxDAVFinalizeSrvCall(
  573. PMRX_SRV_CALL pSrvCall,
  574. BOOLEAN Force
  575. )
  576. /*++
  577. Routine Description:
  578. This routine destroys a given server call instance.
  579. Arguments:
  580. pSrvCall - The server call instance to be disconnected.
  581. Force - TRUE if a disconnection is to be enforced immediately.
  582. Return Value:
  583. RXSTATUS - The return status for the operation
  584. --*/
  585. {
  586. NTSTATUS NtStatus = STATUS_SUCCESS;
  587. PRX_CONTEXT RxContext = NULL;
  588. PRDBSS_DEVICE_OBJECT RxDeviceObject = pSrvCall->RxDeviceObject;
  589. PWEBDAV_SRV_CALL DavSrvCall;
  590. PAGED_CODE();
  591. DavDbgTrace(DAV_TRACE_DETAIL,
  592. ("%ld: Entering MRxDAVFinalizeSrvCall.\n",
  593. PsGetCurrentThreadId()));
  594. DavDbgTrace(DAV_TRACE_CONTEXT,
  595. ("%ld: MRxDAVFinalizeSrvCall: SrvCall: %08lx, Force: %d.\n",
  596. PsGetCurrentThreadId(), pSrvCall, Force));
  597. DavDbgTrace(DAV_TRACE_DETAIL,
  598. ("%ld: MRxDAVFinalizeSrvCall: SrvCallName: %wZ\n",
  599. PsGetCurrentThreadId(), pSrvCall->pSrvCallName));
  600. //
  601. // We allocated memory for pSrvCall->Context, so it better not be NULL.
  602. //
  603. ASSERT(pSrvCall != NULL);
  604. //
  605. // If the MiniRedir didn't get a chance to allocate a SrvCall, then we
  606. // should return right away.
  607. //
  608. if (pSrvCall->Context == NULL) {
  609. DavDbgTrace(DAV_TRACE_DETAIL,
  610. ("%ld: MRxDAVFinalizeSrvCall. pSrvCall->Context == NULL\n",
  611. PsGetCurrentThreadId()));
  612. return NtStatus;
  613. }
  614. ASSERT(pSrvCall->Context != NULL);
  615. //
  616. // If we did not create any server entry for this server in the user mode,
  617. // then we do not need to go to the user mode at all. This fact is
  618. // indicated by the ServerID field in the WEBDAV_SRV_CALL strucutre. If the
  619. // ID value is zero, that implies that the server entry was not created.
  620. //
  621. DavSrvCall = (PWEBDAV_SRV_CALL)pSrvCall->Context;
  622. if (DavSrvCall->ServerID == 0) {
  623. DavDbgTrace(DAV_TRACE_DETAIL,
  624. ("%ld: No server entry was created in the user mode.\n",
  625. PsGetCurrentThreadId()));
  626. goto EXIT_THE_FUNCTION;
  627. }
  628. //
  629. // Unfortunately, we do not have an RxContext here and hence have to create
  630. // one. An RxContext is required for a request to be reflected up.
  631. //
  632. RxContext = RxCreateRxContext(NULL, RxDeviceObject, 0);
  633. if (RxContext == NULL) {
  634. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  635. DavDbgTrace(DAV_TRACE_ERROR,
  636. ("%ld: MRxDAVFinalizeSrvCall/RxCreateRxContext: "
  637. "NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  638. goto EXIT_THE_FUNCTION;
  639. }
  640. //
  641. // We need to send the SrvCall to the format routine and use the
  642. // MRxContext[1] pointer of the RxContext structure to store it.
  643. //
  644. RxContext->MRxContext[1] = (PVOID)pSrvCall;
  645. NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
  646. SIZEOF_DAV_SPECIFIC_CONTEXT,
  647. MRxDAVFormatTheDAVContext,
  648. DAV_MINIRDR_ENTRY_FROM_FINALIZESRVCALL,
  649. MRxDAVFinalizeSrvCallContinuation,
  650. "MRxDAVFinalizeSrvCall");
  651. if (NtStatus != ERROR_SUCCESS) {
  652. DavDbgTrace(DAV_TRACE_ERROR,
  653. ("%ld: MRxDAVFinalizeSrvCall/UMRxAsyncEngOuterWrapper: "
  654. "NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  655. }
  656. EXIT_THE_FUNCTION:
  657. if (RxContext) {
  658. RxDereferenceAndDeleteRxContext(RxContext);
  659. }
  660. //
  661. // Free up the memory allocated for the context pointer.
  662. //
  663. RxFreePool(pSrvCall->Context);
  664. pSrvCall->Context = NULL;
  665. DavDbgTrace(DAV_TRACE_DETAIL,
  666. ("%ld: Leaving MRxDAVFinalizeSrvCall with NtStatus = %08lx.\n",
  667. PsGetCurrentThreadId(), NtStatus));
  668. return NtStatus;
  669. }
  670. NTSTATUS
  671. MRxDAVFinalizeSrvCallContinuation(
  672. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  673. )
  674. /*++
  675. Routine Description:
  676. This is the continuation routine which finalizes a SrvCall.
  677. Arguments:
  678. AsyncEngineContext - The Reflectors context.
  679. RxContext - The RDBSS context.
  680. Return Value:
  681. RXSTATUS - The return status for the operation
  682. --*/
  683. {
  684. NTSTATUS NtStatus = STATUS_SUCCESS;
  685. PAGED_CODE();
  686. DavDbgTrace(DAV_TRACE_DETAIL,
  687. ("%ld: Entering MRxDAVFinalizeSrvCallContinuation!!!!\n",
  688. PsGetCurrentThreadId()));
  689. DavDbgTrace(DAV_TRACE_CONTEXT,
  690. ("%ld: MRxDAVFinalizeSrvCallContinuation: "
  691. "AsyncEngineContext: %08lx, RxContext: %08lx\n",
  692. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  693. //
  694. // Try usermode.
  695. //
  696. NtStatus = UMRxSubmitAsyncEngUserModeRequest(
  697. UMRX_ASYNCENGINE_ARGUMENTS,
  698. MRxDAVFormatUserModeSrvCallFinalizeRequest,
  699. MRxDAVPrecompleteUserModeSrvCallFinalizeRequest
  700. );
  701. DavDbgTrace(DAV_TRACE_DETAIL,
  702. ("%ld: Leaving MRxDAVFinalizeSrvCallContinuation with NtStatus"
  703. " = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  704. return NtStatus;
  705. }
  706. NTSTATUS
  707. MRxDAVFormatUserModeSrvCallFinalizeRequest(
  708. IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  709. IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  710. IN ULONG WorkItemLength,
  711. OUT PULONG_PTR ReturnedLength
  712. )
  713. /*++
  714. Routine Description:
  715. This routine formats the SrvCall finalize request being sent to the user
  716. mode for processing.
  717. Arguments:
  718. RxContext - The RDBSS context.
  719. AsyncEngineContext - The reflctor's context.
  720. WorkItem - The work item buffer.
  721. WorkItemLength - The length of the work item buffer.
  722. ReturnedLength -
  723. Return Value:
  724. STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES.
  725. --*/
  726. {
  727. NTSTATUS NtStatus = STATUS_SUCCESS;
  728. PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  729. PMRX_SRV_CALL SrvCall = NULL;
  730. PWEBDAV_SRV_CALL DavSrvCall = NULL;
  731. PDAV_USERMODE_FINALIZE_SRVCALL_REQUEST FinSrvCallReq = NULL;
  732. PWCHAR ServerName = NULL;
  733. ULONG ServerNameLengthInBytes = 0;
  734. PBYTE SecondaryBuff = NULL;
  735. PAGED_CODE();
  736. DavDbgTrace(DAV_TRACE_DETAIL,
  737. ("%ld: Entering MRxDAVFormatUserModeSrvCallFinalizeRequest.\n",
  738. PsGetCurrentThreadId()));
  739. DavDbgTrace(DAV_TRACE_CONTEXT,
  740. ("%ld: MRxDAVFormatUserModeSrvCallFinalizeRequest: "
  741. "AsyncEngineContext: %08lx, RxContext: %08lx.\n",
  742. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  743. //
  744. // SrvCall was set to MRxContext[0] in MRxDAVFinalizeSrvCall. We need it to
  745. // get the ServerID.
  746. //
  747. SrvCall = (PMRX_SRV_CALL)RxContext->MRxContext[1];
  748. DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
  749. ASSERT(DavSrvCall != NULL);
  750. DavWorkItem->WorkItemType = UserModeFinalizeSrvCall;
  751. FinSrvCallReq = &(DavWorkItem->FinalizeSrvCallRequest);
  752. //
  753. // Set the ServerID.
  754. //
  755. FinSrvCallReq->ServerID = DavSrvCall->ServerID;
  756. //
  757. // Set the Server name.
  758. //
  759. ServerName = &(SrvCall->pSrvCallName->Buffer[1]);
  760. ServerNameLengthInBytes = (1 + wcslen(ServerName)) * sizeof(WCHAR);
  761. SecondaryBuff = UMRxAllocateSecondaryBuffer(AsyncEngineContext,
  762. ServerNameLengthInBytes);
  763. if (SecondaryBuff == NULL) {
  764. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  765. DavDbgTrace(DAV_TRACE_ERROR,
  766. ("ld: MRxDAVFormatUserModeSrvCallFinalizeRequest/"
  767. "UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
  768. PsGetCurrentThreadId(), NtStatus));
  769. goto EXIT_THE_FUNCTION;
  770. }
  771. FinSrvCallReq->ServerName = (PWCHAR)SecondaryBuff;
  772. wcscpy(FinSrvCallReq->ServerName, ServerName);
  773. EXIT_THE_FUNCTION:
  774. DavDbgTrace(DAV_TRACE_DETAIL,
  775. ("%ld: Leaving MRxDAVFormatUserModeSrvCallFinalizeRequest "
  776. "with NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  777. return NtStatus;
  778. }
  779. BOOL
  780. MRxDAVPrecompleteUserModeSrvCallFinalizeRequest(
  781. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  782. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  783. ULONG WorkItemLength,
  784. BOOL OperationCancelled
  785. )
  786. /*++
  787. Routine Description:
  788. The precompletion routine for the finalize SrvCall request.
  789. Arguments:
  790. RxContext - The RDBSS context.
  791. AsyncEngineContext - The reflctor's context.
  792. WorkItem - The work item buffer.
  793. WorkItemLength - The length of the work item buffer.
  794. OperationCancelled - TRUE if this operation was cancelled by the user.
  795. Return Value:
  796. TRUE - UMRxAsyncEngineCalldownIrpCompletion is called by the function
  797. UMRxCompleteUserModeRequest after we return.
  798. --*/
  799. {
  800. NTSTATUS NtStatus = STATUS_SUCCESS;
  801. PDAV_USERMODE_WORKITEM WorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  802. PDAV_USERMODE_FINALIZE_SRVCALL_REQUEST FinSrvCallReq;
  803. PAGED_CODE();
  804. DavDbgTrace(DAV_TRACE_DETAIL,
  805. ("%ld: Entering MRxDAVPrecompleteUserModeSrvCallFinalizeRequest\n",
  806. PsGetCurrentThreadId()));
  807. DavDbgTrace(DAV_TRACE_CONTEXT,
  808. ("%ld: MRxDAVPrecompleteUserModeSrvCallFinalizeRequest: "
  809. "AsyncEngineContext: %08lx, RxContext: %08lx.\n",
  810. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  811. FinSrvCallReq = &(WorkItem->FinalizeSrvCallRequest);
  812. if (OperationCancelled) {
  813. DavDbgTrace(DAV_TRACE_ERROR,
  814. ("%ld: MRxDAVPrecompleteUserModeSrvCallFinalizeRequest: Operation Cancelled. "
  815. "AsyncEngineContext = %08lx, RxContext = %08lx.\n",
  816. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  817. }
  818. //
  819. // We need to free up the heap we allocated in the format routine.
  820. //
  821. if (FinSrvCallReq->ServerName != NULL) {
  822. NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
  823. (PBYTE)FinSrvCallReq->ServerName);
  824. if (NtStatus != STATUS_SUCCESS) {
  825. DavDbgTrace(DAV_TRACE_ERROR,
  826. ("%ld: ERROR: MRxDAVPrecompleteUserModeSrvCallFinalizeRequest/"
  827. "UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
  828. PsGetCurrentThreadId(), NtStatus));
  829. }
  830. }
  831. if (AsyncEngineContext->Status != STATUS_SUCCESS) {
  832. DavDbgTrace(DAV_TRACE_ERROR,
  833. ("%ld: ERROR: MRxDAVPrecompleteUserModeSrvCallFinalizeRequest. "
  834. "Finalize SrvCall Failed!!!\n",
  835. PsGetCurrentThreadId()));
  836. }
  837. DavDbgTrace(DAV_TRACE_DETAIL,
  838. ("%ld: Leaving MRxDAVPrecompleteUserModeSrvCallFinalizeRequest\n",
  839. PsGetCurrentThreadId()));
  840. return TRUE;
  841. }
  842. NTSTATUS
  843. MRxDAVSrvCallWinnerNotify(
  844. IN PMRX_SRV_CALL pSrvCall,
  845. IN BOOLEAN ThisMinirdrIsTheWinner,
  846. IN OUT PVOID pSrvCallContext
  847. )
  848. /*++
  849. Routine Description:
  850. This routine finalizes the mini rdr context associated with an RDBSS Server call instance
  851. Arguments:
  852. pSrvCall - the Server Call
  853. ThisMinirdrIsTheWinner - TRUE if this mini rdr is the choosen one.
  854. pSrvCallContext - the server call context created by the mini redirector.
  855. Return Value:
  856. RXSTATUS - The return status for the operation
  857. Notes:
  858. The two phase construction protocol for Server calls is required because of parallel
  859. initiation of a number of mini redirectors. The RDBSS finalizes the particular mini
  860. redirector to be used in communicating with a given server based on quality of
  861. service criterion.
  862. --*/
  863. {
  864. NTSTATUS Status = STATUS_SUCCESS;
  865. PAGED_CODE();
  866. return STATUS_SUCCESS;
  867. }