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.

1485 lines
49 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. netroot.c
  5. Abstract:
  6. This module implements the routines for creating net roots for the WebDav
  7. miniredir.
  8. Author:
  9. Rohan Kumar [RohanK] 24-April-1999
  10. Revision History:
  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. NTSTATUS
  20. MRxDAVCreateVNetRootContinuation(
  21. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  22. );
  23. NTSTATUS
  24. MRxDAVFormatUserModeVNetRootCreateRequest(
  25. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  26. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  27. ULONG WorkItemLength,
  28. PULONG_PTR ReturnedLength
  29. );
  30. BOOL
  31. MRxDAVPrecompleteUserModeVNetRootCreateRequest(
  32. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  33. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  34. ULONG WorkItemLength,
  35. BOOL OperationCancelled
  36. );
  37. NTSTATUS
  38. MRxDAVFinalizeVNetRootContinuation(
  39. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  40. );
  41. NTSTATUS
  42. MRxDAVFormatUserModeVNetRootFinalizeRequest(
  43. IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  44. IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  45. IN ULONG WorkItemLength,
  46. OUT PULONG_PTR ReturnedLength
  47. );
  48. BOOL
  49. MRxDAVPrecompleteUserModeVNetRootFinalizeRequest(
  50. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  51. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  52. ULONG WorkItemLength,
  53. BOOL OperationCancelled
  54. );
  55. NTSTATUS
  56. MRxDAVDereferenceNetRootContext(
  57. IN PWEBDAV_NET_ROOT DavNetRoot
  58. );
  59. #ifdef ALLOC_PRAGMA
  60. #pragma alloc_text(PAGE, MRxDAVUpdateNetRootState)
  61. #pragma alloc_text(PAGE, MRxDAVCreateVNetRoot)
  62. #pragma alloc_text(PAGE, MRxDAVCreateVNetRootContinuation)
  63. #pragma alloc_text(PAGE, MRxDAVFormatUserModeVNetRootCreateRequest)
  64. #pragma alloc_text(PAGE, MRxDAVPrecompleteUserModeVNetRootCreateRequest)
  65. #pragma alloc_text(PAGE, MRxDAVFinalizeNetRoot)
  66. #pragma alloc_text(PAGE, MRxDAVExtractNetRootName)
  67. #pragma alloc_text(PAGE, MRxDAVFinalizeVNetRoot)
  68. #pragma alloc_text(PAGE, MRxDAVFinalizeVNetRootContinuation)
  69. #pragma alloc_text(PAGE, MRxDAVFormatUserModeVNetRootFinalizeRequest)
  70. #pragma alloc_text(PAGE, MRxDAVPrecompleteUserModeVNetRootFinalizeRequest)
  71. #pragma alloc_text(PAGE, MRxDAVDereferenceNetRootContext)
  72. #endif
  73. //
  74. // Implementation of functions begins here.
  75. //
  76. NTSTATUS
  77. MRxDAVUpdateNetRootState(
  78. IN OUT PMRX_NET_ROOT pNetRoot
  79. )
  80. /*++
  81. Routine Description:
  82. This routine update the mini redirector state associated with a net root.
  83. Arguments:
  84. pNetRoot - the net root instance.
  85. Return Value:
  86. RXSTATUS - The return status for the operation
  87. Notes:
  88. --*/
  89. {
  90. PAGED_CODE();
  91. if (pNetRoot->Context == NULL) {
  92. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
  93. } else {
  94. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
  95. }
  96. return STATUS_SUCCESS;
  97. }
  98. NTSTATUS
  99. MRxDAVCreateVNetRoot(
  100. IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext
  101. )
  102. /*++
  103. Routine Description:
  104. This routine patches the RDBSS created net root instance with the
  105. information required by the mini redirector.
  106. Arguments:
  107. pCreateNetRootContext - the net root context for calling back
  108. Return Value:
  109. RXSTATUS - The return status for the operation
  110. Notes:
  111. --*/
  112. {
  113. NTSTATUS NtStatus = STATUS_SUCCESS;
  114. PRX_CONTEXT RxContext = NULL;
  115. PMRX_V_NET_ROOT pVNetRoot = NULL;
  116. PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
  117. PWEBDAV_DEVICE_OBJECT DavDeviceObject = NULL;
  118. PUMRX_DEVICE_OBJECT UMRxDeviceObject = NULL;
  119. PMRX_SRV_CALL pSrvCall = NULL;
  120. PMRX_NET_ROOT pNetRoot = NULL;
  121. BOOLEAN SynchronousIo = FALSE;
  122. NTSTATUS ExNtStatus = STATUS_SUCCESS;
  123. HANDLE ExDeviceHandle = INVALID_HANDLE_VALUE;
  124. OBJECT_ATTRIBUTES ObjectAttributes;
  125. UNICODE_STRING ExDeviceName;
  126. IO_STATUS_BLOCK IoStatusBlock;
  127. PKEY_VALUE_PARTIAL_INFORMATION DavKeyValuePartialInfo = NULL;
  128. PIO_STACK_LOCATION IrpSp = NULL;
  129. PFILE_OBJECT DavFileObject = NULL;
  130. PWCHAR NewFileName = NULL;
  131. ULONG NewFileNameLength = 0;
  132. PAGED_CODE();
  133. DavDbgTrace(DAV_TRACE_DETAIL,
  134. ("%ld: Entering MRxDAVCreateVNetRoot\n", PsGetCurrentThreadId()));
  135. DavDbgTrace(DAV_TRACE_CONTEXT,
  136. ("%ld: MRxDAVCreateVNetRoot: pVNetRoot = %08lx\n",
  137. PsGetCurrentThreadId(), pVNetRoot));
  138. RxContext = pCreateNetRootContext->RxContext;
  139. pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;
  140. DavDeviceObject = (PWEBDAV_DEVICE_OBJECT)(RxContext->RxDeviceObject);
  141. UMRxDeviceObject = (PUMRX_DEVICE_OBJECT)&(DavDeviceObject->UMRefDeviceObject);
  142. pNetRoot = pVNetRoot->pNetRoot;
  143. pSrvCall = pNetRoot->pSrvCall;
  144. DavVNetRoot = MRxDAVGetVNetRootExtension(pVNetRoot);
  145. ASSERT(DavVNetRoot != NULL);
  146. ASSERT(NodeType(pNetRoot) == RDBSS_NTC_NETROOT);
  147. ASSERT(NodeType(pSrvCall) == RDBSS_NTC_SRVCALL);
  148. DavDbgTrace(DAV_TRACE_DETAIL,
  149. ("%ld: MRxDAVCreateVNetRoot: NetRootName = %wZ\n",
  150. PsGetCurrentThreadId(), pVNetRoot->pNetRoot->pNetRootName));
  151. DavDbgTrace(DAV_TRACE_DETAIL,
  152. ("%ld: MRxDAVCreateVNetRoot: VNetRoot = %08lx\n",
  153. PsGetCurrentThreadId(), pVNetRoot));
  154. //
  155. // Copy the LogonID in the MiniRedir's portion of the V_NET_ROOT.
  156. //
  157. DavVNetRoot->LogonID.LowPart = pVNetRoot->LogonId.LowPart;
  158. DavVNetRoot->LogonID.HighPart = pVNetRoot->LogonId.HighPart;
  159. DavVNetRoot->LogonIDSet = TRUE;
  160. DavDbgTrace(DAV_TRACE_DETAIL,
  161. ("%ld: MRxDAVCreateVNetRoot: LogonID.LowPart = %08lx\n",
  162. PsGetCurrentThreadId(), DavVNetRoot->LogonID.LowPart));
  163. DavDbgTrace(DAV_TRACE_DETAIL,
  164. ("%ld: MRxDAVCreateVNetRoot: LogonID.HighPart = %08lx\n",
  165. PsGetCurrentThreadId(), DavVNetRoot->LogonID.HighPart));
  166. //
  167. // There are cases when we fail, we want the error which SMB returned to be
  168. // returned to the user. This is becuase SMB could have returned a more
  169. // specific error like logon failure or something on the share where as we
  170. // return share not found. To enable this we return STATUS_BAD_NETWORK_PATH
  171. // when the creation of netroot fails instead of STATUS_BAD_NETWORK_NAME
  172. // because MUP will overwrite SMBs error with our error if we return
  173. // STATUS_BAD_NETWORK_NAME. STATUS_BAD_NETWORK_NAME is a specif error which
  174. // implies that the share does not exist where as STATUS_BAD_NETWORK_PATH is
  175. // a more general error.
  176. //
  177. //
  178. // If the share name is a net root or a pipe, we reject it since SMB
  179. // Mini-Redir is the only one that handles it.
  180. //
  181. if ( pNetRoot->Type == NET_ROOT_PIPE || pNetRoot->Type == NET_ROOT_MAILSLOT ) {
  182. DavDbgTrace(DAV_TRACE_ERROR,
  183. ("%ld: ERROR: MRxDAVCreateVNetRoot: Invalid NetRootType\n",
  184. PsGetCurrentThreadId()));
  185. //
  186. // We set the following flag in the DavVNetRoot structure to TRUE. This
  187. // is because when the finalize comes, we don't need to go to the
  188. // usermode.
  189. //
  190. DavVNetRoot->createVNetRootUnSuccessful = TRUE;
  191. pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_PATH;
  192. // pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_NAME;
  193. pCreateNetRootContext->NetRootStatus = STATUS_BAD_NETWORK_PATH;
  194. // pCreateNetRootContext->NetRootStatus = STATUS_BAD_NETWORK_NAME;
  195. goto EXIT_THE_FUNCTION;
  196. }
  197. SynchronousIo = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
  198. DavDbgTrace(DAV_TRACE_DETAIL,
  199. ("%ld: MRxDAVCreateVNetRoot: SynchronousIo = %d\n",
  200. PsGetCurrentThreadId(), SynchronousIo));
  201. //
  202. // We need to pass the server and share names to the user mode to check
  203. // whether they actually exist. RxContext has 4 pointers that the mini-redirs
  204. // can use. Here we use MRxContext[1]. We store a reference to the pVNetRoot
  205. // strucutre. MRxContext[0] is used to store a reference to the
  206. // AsynEngineContext and this is done when the context gets created in the
  207. // function UMRxCreateAsyncEngineContext.
  208. //
  209. RxContext->MRxContext[1] = pVNetRoot;
  210. //
  211. // We now need to go to the user mode and find out if this WebDav share
  212. // exists on the server.
  213. //
  214. NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
  215. SIZEOF_DAV_SPECIFIC_CONTEXT,
  216. MRxDAVFormatTheDAVContext,
  217. DAV_MINIRDR_ENTRY_FROM_CREATEVNETROOT,
  218. MRxDAVCreateVNetRootContinuation,
  219. "MRxDAVCreateVNetRoot");
  220. if (NtStatus != STATUS_SUCCESS) {
  221. DavDbgTrace(DAV_TRACE_ERROR,
  222. ("%ld: ERROR: MRxDAVCreateVNetRoot/UMRxAsyncEngOuterWrapper: "
  223. "NtStatus = %08lx\n", PsGetCurrentThreadId(), NtStatus));
  224. if (NtStatus == STATUS_ACCESS_DENIED ||
  225. NtStatus == STATUS_LOGON_FAILURE ||
  226. NtStatus == STATUS_NETWORK_CREDENTIAL_CONFLICT) {
  227. pCreateNetRootContext->VirtualNetRootStatus = NtStatus;
  228. } else {
  229. pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_PATH;
  230. }
  231. //
  232. // Don't set the NetRootStatus here since it is a global data structure
  233. // shared among different VNetRoots (TS users). Failure on one VNetRoot
  234. // should not affects the NetRoot.
  235. //
  236. goto EXIT_THE_FUNCTION;
  237. }
  238. //
  239. // If we succeeded and the share is not a TAHOE share, nor an Office Web
  240. // Server share, then we claim the share name. Otherwise we fail since the
  241. // users intends to use the TAHOE specific features in Rosebud, or Office
  242. // specific features in Shell.
  243. //
  244. if ( !DavVNetRoot->isTahoeShare && !DavVNetRoot->isOfficeShare ) {
  245. pNetRoot->DeviceType = RxDeviceType(DISK);
  246. pNetRoot->Type = NET_ROOT_DISK;
  247. pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
  248. pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
  249. } else {
  250. DavDbgTrace(DAV_TRACE_DETAIL,
  251. ("%ld: MRxDAVCreateVNetRoot/UMRxAsyncEngOuterWrapper: "
  252. "TAHOE or OFFICE Share\n", PsGetCurrentThreadId()));
  253. pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_PATH;
  254. // pCreateNetRootContext->VirtualNetRootStatus = STATUS_BAD_NETWORK_NAME;
  255. pCreateNetRootContext->NetRootStatus = STATUS_BAD_NETWORK_PATH;
  256. // pCreateNetRootContext->NetRootStatus = STATUS_BAD_NETWORK_NAME;
  257. }
  258. if (pNetRoot->Context == NULL) {
  259. pNetRoot->Context = RxAllocatePoolWithTag(PagedPool,
  260. sizeof(WEBDAV_NET_ROOT),
  261. DAV_NETROOT_POOLTAG);
  262. if (pNetRoot->Context == NULL) {
  263. pCreateNetRootContext->VirtualNetRootStatus = STATUS_INSUFFICIENT_RESOURCES;
  264. pCreateNetRootContext->NetRootStatus = STATUS_INSUFFICIENT_RESOURCES;
  265. } else {
  266. PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)pNetRoot->Context;
  267. //
  268. // Refcount of 2, one is taken away at VNetRoot finalization, another one is taken
  269. // away at NetRoot finalization.
  270. //
  271. DavNetRoot->RefCount = 2;
  272. DavNetRoot->pRdbssNetRoot = pNetRoot;
  273. RxNameCacheInitialize(&DavNetRoot->NameCacheCtlGFABasic,
  274. sizeof(FILE_BASIC_INFORMATION),
  275. NameCacheMaxEntries);
  276. RxNameCacheInitialize(&DavNetRoot->NameCacheCtlGFAStandard,
  277. sizeof(FILE_STANDARD_INFORMATION),
  278. NameCacheMaxEntries);
  279. RxNameCacheInitialize(&DavNetRoot->NameCacheCtlFNF,
  280. 0,
  281. NameCacheMaxEntries);
  282. pVNetRoot->Context2 = DavNetRoot;
  283. DavDbgTrace(DAV_TRACE_DAVNETROOT,
  284. ("MRxDav allocates DavNetRoot %x %x %x 2\n",DavNetRoot,pNetRoot,pVNetRoot));
  285. }
  286. } else {
  287. PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)pNetRoot->Context;
  288. pVNetRoot->Context2 = DavNetRoot;
  289. InterlockedIncrement(&DavNetRoot->RefCount);
  290. DavDbgTrace(DAV_TRACE_DAVNETROOT,
  291. ("MRxDAVCreateVNetRoot ref DavNetRoot %x %x %x %d\n",DavNetRoot,pNetRoot,pVNetRoot,DavNetRoot->RefCount));
  292. }
  293. //
  294. // We return from here since the code below was written for accomodating the
  295. // exchange DAV Redir which was suppose to ship with Office 2000. Since that
  296. // project (LocalStore which included the Exchange Redir) has been canned,
  297. // (as of Dec 8th, 2000) we don't need to execute the code below any more.
  298. // We will keep it around though, just in case.
  299. //
  300. goto EXIT_THE_FUNCTION;
  301. //
  302. // The Exchange Redir has been installed on the system. Now we need to find
  303. // out if its loaded. This is an exchange share. If the exchange Redir is
  304. // not installed, we claim the name.
  305. //
  306. DavKeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)DavExchangeDeviceName;
  307. RtlInitUnicodeString( &(ExDeviceName), (PWCHAR)DavKeyValuePartialInfo->Data );
  308. InitializeObjectAttributes(&(ObjectAttributes),
  309. &(ExDeviceName),
  310. OBJ_CASE_INSENSITIVE,
  311. 0,
  312. NULL);
  313. ExNtStatus = NtOpenFile(&(ExDeviceHandle),
  314. 0,
  315. &(ObjectAttributes),
  316. &(IoStatusBlock),
  317. 0,
  318. 0);
  319. if (ExNtStatus != STATUS_SUCCESS) {
  320. //
  321. // This is an exchange share but the Exchange Redir is not installed.
  322. // We will handle this.
  323. //
  324. ExDeviceHandle = INVALID_HANDLE_VALUE;
  325. DavDbgTrace(DAV_TRACE_DETAIL,
  326. ("%ld: MRxDAVCreateVNetRoot. Exchange BUT No Redir\n",
  327. PsGetCurrentThreadId()));
  328. pNetRoot->DeviceType = RxDeviceType(DISK);
  329. pNetRoot->Type = NET_ROOT_DISK;
  330. pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
  331. pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
  332. goto EXIT_THE_FUNCTION;
  333. }
  334. IrpSp = IoGetCurrentIrpStackLocation(RxContext->CurrentIrp);
  335. DavFileObject = IrpSp->FileObject;
  336. //
  337. // The NewFileNameLength is = ExchangeDeviceNameLength + PathName. The
  338. // DavKeyValuePartialInfo->DataLength contains an extra 2 bytes for the
  339. // \0 char.
  340. //
  341. NewFileNameLength = ( DavKeyValuePartialInfo->DataLength +
  342. DavFileObject->FileName.Length );
  343. //
  344. // If the first char is not a \, then we need to add another sizeof(WCHAR).
  345. //
  346. if (DavFileObject->FileName.Buffer[0] != L'\\') {
  347. NewFileNameLength += sizeof(WCHAR);
  348. }
  349. //
  350. // Allocate memory for the NewFileName.
  351. //
  352. NewFileName = ExAllocatePoolWithTag(PagedPool, NewFileNameLength, DAV_EXCHANGE_POOLTAG);
  353. if (NewFileName == NULL) {
  354. DavDbgTrace(DAV_TRACE_ERROR,
  355. ("%ld: ERROR: MRxDAVCreateVNetRoot/ExAllocatePoolWithTag\n",
  356. PsGetCurrentThreadId()));
  357. pCreateNetRootContext->VirtualNetRootStatus = STATUS_INSUFFICIENT_RESOURCES;
  358. pCreateNetRootContext->NetRootStatus = STATUS_INSUFFICIENT_RESOURCES;
  359. goto EXIT_THE_FUNCTION;
  360. }
  361. RtlZeroMemory(NewFileName, NewFileNameLength);
  362. //
  363. // Copy the new device name.
  364. //
  365. RtlCopyMemory(NewFileName,
  366. DavKeyValuePartialInfo->Data,
  367. DavKeyValuePartialInfo->DataLength);
  368. //
  369. // If the first char is not a \, then we need to copy it before we copy the
  370. // rest of the name.
  371. //
  372. if (DavFileObject->FileName.Buffer[0] != L'\\') {
  373. //
  374. // Copy the \ next.
  375. //
  376. RtlCopyMemory( ( NewFileName + DavKeyValuePartialInfo->DataLength ),
  377. L"\\",
  378. sizeof(WCHAR) );
  379. //
  380. // Finally copy the PathName that was sent with this IRP.
  381. //
  382. RtlCopyMemory( ( NewFileName + DavKeyValuePartialInfo->DataLength + sizeof(WCHAR) ),
  383. DavFileObject->FileName.Buffer,
  384. DavFileObject->FileName.Length );
  385. } else {
  386. //
  387. // Finally copy the PathName that was sent with this IRP.
  388. //
  389. RtlCopyMemory( ( NewFileName + DavKeyValuePartialInfo->DataLength ),
  390. DavFileObject->FileName.Buffer,
  391. DavFileObject->FileName.Length );
  392. }
  393. //
  394. // Free the memory allocated in the FileObject's original filename buffer.
  395. //
  396. ExFreePool(DavFileObject->FileName.Buffer);
  397. //
  398. // Set the NewFileName in the FileObject.
  399. //
  400. DavFileObject->FileName.Buffer = NewFileName;
  401. DavFileObject->FileName.Length = (USHORT)NewFileNameLength;
  402. DavFileObject->FileName.MaximumLength = (USHORT)NewFileNameLength;
  403. //
  404. // Finally, set the status to STATUS_REPARSE so that the I/O manager will
  405. // call into the Exchange Redir.
  406. //
  407. pCreateNetRootContext->VirtualNetRootStatus = STATUS_REPARSE;
  408. pCreateNetRootContext->NetRootStatus = STATUS_REPARSE;
  409. EXIT_THE_FUNCTION:
  410. //
  411. // Callback the RDBSS for resumption.
  412. //
  413. pCreateNetRootContext->Callback(pCreateNetRootContext);
  414. //
  415. // If we opened a handle to the exchange redir, we need to close it now.
  416. //
  417. if (ExDeviceHandle != INVALID_HANDLE_VALUE) {
  418. NtClose(ExDeviceHandle);
  419. }
  420. //
  421. // Map the error code to STATUS_PENDING since this triggers the
  422. // synchronization mechanism in the RDBSS.
  423. //
  424. DavDbgTrace(DAV_TRACE_DETAIL,
  425. ("%ld: Leaving MRxDAVCreateVNetRoot\n", PsGetCurrentThreadId()));
  426. return STATUS_PENDING;
  427. }
  428. NTSTATUS
  429. MRxDAVCreateVNetRootContinuation(
  430. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  431. )
  432. /*++
  433. Routine Description:
  434. This routine checks to see if the share for which a VNetRoot is being
  435. created exists or not.
  436. Arguments:
  437. AsyncEngineContext - The Reflectors context.
  438. RxContext - The RDBSS context.
  439. Return Value:
  440. RXSTATUS - The return status for the operation.
  441. --*/
  442. {
  443. NTSTATUS NtStatus = STATUS_SUCCESS;
  444. PAGED_CODE();
  445. DavDbgTrace(DAV_TRACE_DETAIL,
  446. ("%ld: Entering MRxDAVCreateVNetRootContinuation\n",
  447. PsGetCurrentThreadId()));
  448. DavDbgTrace(DAV_TRACE_CONTEXT,
  449. ("%ld: MRxDAVCreateVNetRootContinuation: "
  450. "AsyncEngineContext: %08lx, RxContext: %08lx\n",
  451. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  452. //
  453. // Try usermode.
  454. //
  455. NtStatus = UMRxSubmitAsyncEngUserModeRequest(
  456. UMRX_ASYNCENGINE_ARGUMENTS,
  457. MRxDAVFormatUserModeVNetRootCreateRequest,
  458. MRxDAVPrecompleteUserModeVNetRootCreateRequest
  459. );
  460. DavDbgTrace(DAV_TRACE_DETAIL,
  461. ("%ld: Leaving MRxDAVCreateVNetRootContinuation with NtStatus ="
  462. " %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  463. return NtStatus;
  464. }
  465. NTSTATUS
  466. MRxDAVFormatUserModeVNetRootCreateRequest(
  467. IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  468. IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  469. IN ULONG WorkItemLength,
  470. OUT PULONG_PTR ReturnedLength
  471. )
  472. /*++
  473. Routine Description:
  474. This routine formats the VNetRoot create request being sent to the user mode
  475. for processing.
  476. Arguments:
  477. RxContext - The RDBSS context.
  478. AsyncEngineContext - The reflctor's context.
  479. WorkItem - The work item buffer.
  480. WorkItemLength - The length of the work item buffer.
  481. ReturnedLength -
  482. Return Value:
  483. STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES.
  484. --*/
  485. {
  486. NTSTATUS NtStatus = STATUS_SUCCESS;
  487. PDAV_USERMODE_WORKITEM WorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  488. PMRX_SRV_CALL SrvCall = NULL;
  489. PWEBDAV_SRV_CALL DavSrvCall = NULL;
  490. PMRX_NET_ROOT NetRoot = NULL;
  491. PMRX_V_NET_ROOT VNetRoot = NULL;
  492. PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
  493. PSECURITY_CLIENT_CONTEXT SecurityClientContext = NULL;
  494. PDAV_USERMODE_CREATE_V_NET_ROOT_REQUEST CreateVNetRootRequest = NULL;
  495. PWCHAR ServerName = NULL, ShareName = NULL;
  496. PWCHAR NetRootName = NULL, JustTheNetRootName = NULL;
  497. ULONG ServerNameLengthInBytes = 0, NetRootNameLengthInBytes = 0;
  498. PAGED_CODE();
  499. DavDbgTrace(DAV_TRACE_DETAIL,
  500. ("%ld: Entering MRxDAVFormatUserModeVNetRootCreateRequest!!!!\n",
  501. PsGetCurrentThreadId()));
  502. DavDbgTrace(DAV_TRACE_CONTEXT,
  503. ("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: AsyncEngineContext"
  504. " = %08lx, RxContext = %08lx.\n", PsGetCurrentThreadId(),
  505. AsyncEngineContext, RxContext));
  506. CreateVNetRootRequest = &(WorkItem->CreateVNetRootRequest);
  507. //
  508. // We need to set the work item type.
  509. //
  510. WorkItem->WorkItemType = UserModeCreateVNetRoot;
  511. //
  512. // The VNetRoot pointer is stored in the MRxContext[1] pointer of the
  513. // RxContext structure. This is done in the MRxDAVCreateVNetRoot function.
  514. //
  515. VNetRoot = (PMRX_V_NET_ROOT)RxContext->MRxContext[1];
  516. ASSERT(VNetRoot != NULL);
  517. DavDbgTrace(DAV_TRACE_DETAIL,
  518. ("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: "
  519. "VNetRoot = %08lx\n", PsGetCurrentThreadId(), VNetRoot));
  520. DavVNetRoot = MRxDAVGetVNetRootExtension(VNetRoot);
  521. ASSERT(DavVNetRoot != NULL);
  522. NetRoot = VNetRoot->pNetRoot;
  523. ASSERT(NetRoot != NULL);
  524. SrvCall = NetRoot->pSrvCall;
  525. ASSERT(SrvCall != NULL);
  526. DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
  527. ASSERT(DavSrvCall != NULL);
  528. SecurityClientContext = &(DavVNetRoot->SecurityClientContext);
  529. //
  530. // Copy the LogonID in the CreateRequest buffer. The LogonId is in the
  531. // MiniRedir's portion of the V_NET_ROOT.
  532. //
  533. CreateVNetRootRequest->LogonID.LowPart = DavVNetRoot->LogonID.LowPart;
  534. CreateVNetRootRequest->LogonID.HighPart = DavVNetRoot->LogonID.HighPart;
  535. DavDbgTrace(DAV_TRACE_DETAIL,
  536. ("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: LogonID.LowPart = %08lx\n",
  537. PsGetCurrentThreadId(), DavVNetRoot->LogonID.LowPart));
  538. DavDbgTrace(DAV_TRACE_DETAIL,
  539. ("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: LogonID.HighPart = %08lx\n",
  540. PsGetCurrentThreadId(), DavVNetRoot->LogonID.HighPart));
  541. //
  542. // Copy the ServerName.
  543. //
  544. ServerNameLengthInBytes = ( SrvCall->pSrvCallName->Length + sizeof(WCHAR) );
  545. ServerName = (PWCHAR) UMRxAllocateSecondaryBuffer(AsyncEngineContext,
  546. ServerNameLengthInBytes);
  547. if (ServerName == NULL) {
  548. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  549. DavDbgTrace(DAV_TRACE_ERROR,
  550. ("%ld: ERROR: MRxDAVFormatUserModeVNetRootCreateRequest/"
  551. "UMRxAllocateSecondaryBuffer. NtStatus = %08lx.\n",
  552. PsGetCurrentThreadId(), NtStatus));
  553. goto EXIT_THE_FUNCTION;
  554. }
  555. RtlCopyBytes(ServerName,
  556. SrvCall->pSrvCallName->Buffer,
  557. SrvCall->pSrvCallName->Length);
  558. ServerName[( ( (ServerNameLengthInBytes) / sizeof(WCHAR) ) - 1 )] = L'\0';
  559. CreateVNetRootRequest->ServerName = ServerName;
  560. DavDbgTrace(DAV_TRACE_DETAIL,
  561. ("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: ServerName: "
  562. "%ws\n", PsGetCurrentThreadId(), ServerName));
  563. //
  564. // Copy the ServerID.
  565. //
  566. CreateVNetRootRequest->ServerID = DavSrvCall->ServerID;
  567. //
  568. // The NetRootName (pNetRootName) includes the ServerName. Hence to get the
  569. // NetRootNameLengthInBytes, we do the following.
  570. //
  571. NetRootNameLengthInBytes = (NetRoot->pNetRootName->Length - SrvCall->pSrvCallName->Length);
  572. //
  573. // For '\0' at the end.
  574. //
  575. NetRootNameLengthInBytes += sizeof(WCHAR);
  576. NetRootName = &(NetRoot->pNetRootName->Buffer[1]);
  577. JustTheNetRootName = wcschr(NetRootName, L'\\');
  578. //
  579. // Copy the NetRoot (Share) name.
  580. //
  581. ShareName = (PWCHAR) UMRxAllocateSecondaryBuffer(AsyncEngineContext,
  582. NetRootNameLengthInBytes);
  583. if (ShareName == NULL) {
  584. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  585. DavDbgTrace(DAV_TRACE_ERROR,
  586. ("%ld: ERROR: MRxDAVFormatUserModeVNetRootCreateRequest/"
  587. "UMRxAllocateSecondaryBuffer. NtStatus = %08lx.\n",
  588. PsGetCurrentThreadId(), NtStatus));
  589. goto EXIT_THE_FUNCTION;
  590. }
  591. RtlCopyBytes(ShareName,
  592. JustTheNetRootName,
  593. (NetRoot->pNetRootName->Length - SrvCall->pSrvCallName->Length));
  594. ShareName[( ( (NetRootNameLengthInBytes) / sizeof(WCHAR) ) - 1 )] = L'\0';
  595. CreateVNetRootRequest->ShareName = ShareName;
  596. DavDbgTrace(DAV_TRACE_DETAIL,
  597. ("%ld: MRxDAVFormatUserModeVNetRootCreateRequest: ShareName: "
  598. "%ws\n", PsGetCurrentThreadId(), ShareName));
  599. //
  600. // Impersonate the client who initiated the request. If we fail to
  601. // impersonate, tough luck.
  602. //
  603. if (SecurityClientContext != NULL) {
  604. NtStatus = UMRxImpersonateClient(SecurityClientContext, WorkItemHeader);
  605. if (!NT_SUCCESS(NtStatus)) {
  606. DavDbgTrace(DAV_TRACE_ERROR,
  607. ("%ld: ERROR: MRxDAVFormatUserModeVNetRootCreateRequest/"
  608. "UMRxImpersonateClient. NtStatus = %08lx.\n",
  609. PsGetCurrentThreadId(), NtStatus));
  610. goto EXIT_THE_FUNCTION;
  611. }
  612. } else {
  613. NtStatus = STATUS_INVALID_PARAMETER;
  614. DavDbgTrace(DAV_TRACE_ERROR,
  615. ("%ld: ERROR: MRxDAVFormatUserModeVNetRootCreateRequest: "
  616. "SecurityClientContext is NULL.\n",
  617. PsGetCurrentThreadId()));
  618. goto EXIT_THE_FUNCTION;
  619. }
  620. ASSERT(WorkItem->UserName[0] == L'\0' && WorkItem->Password[0] == L'\0');
  621. if (VNetRoot->pUserName && VNetRoot->pUserName->Length) {
  622. RtlCopyMemory(WorkItem->UserName,VNetRoot->pUserName->Buffer,VNetRoot->pUserName->Length);
  623. }
  624. if (VNetRoot->pPassword && VNetRoot->pPassword->Length) {
  625. RtlCopyMemory(WorkItem->Password,VNetRoot->pPassword->Buffer,VNetRoot->pPassword->Length);
  626. }
  627. EXIT_THE_FUNCTION:
  628. DavDbgTrace(DAV_TRACE_ENTRYEXIT,
  629. ("%ld: Leaving MRxDAVFormatUserModeVNetRootCreateRequest with "
  630. "NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  631. return NtStatus;
  632. }
  633. BOOL
  634. MRxDAVPrecompleteUserModeVNetRootCreateRequest(
  635. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  636. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  637. ULONG WorkItemLength,
  638. BOOL OperationCancelled
  639. )
  640. /*++
  641. Routine Description:
  642. The precompletion routine for the CreateVNetRoot request.
  643. Arguments:
  644. RxContext - The RDBSS context.
  645. AsyncEngineContext - The reflctor's context.
  646. WorkItem - The work item buffer.
  647. WorkItemLength - The length of the work item buffer.
  648. OperationCancelled - TRUE if this operation was cancelled by the user.
  649. Return Value:
  650. TRUE - UMRxAsyncEngineCalldownIrpCompletion is called by the function
  651. UMRxCompleteUserModeRequest after we return.
  652. --*/
  653. {
  654. NTSTATUS NtStatus = STATUS_SUCCESS;
  655. PDAV_USERMODE_CREATE_V_NET_ROOT_REQUEST CreateVNetRootRequest = NULL;
  656. PDAV_USERMODE_CREATE_V_NET_ROOT_RESPONSE CreateVNetRootResponse = NULL;
  657. PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  658. PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
  659. PMRX_V_NET_ROOT VNetRoot = NULL;
  660. PAGED_CODE();
  661. CreateVNetRootRequest = &(DavWorkItem->CreateVNetRootRequest);
  662. CreateVNetRootResponse = &(DavWorkItem->CreateVNetRootResponse);
  663. if (!OperationCancelled) {
  664. //
  665. // The VNetRoot pointer is stored in the MRxContext[1] pointer of the
  666. // RxContext structure. This is done in the MRxDAVCreateVNetRoot
  667. // function.
  668. //
  669. VNetRoot = (PMRX_V_NET_ROOT)RxContext->MRxContext[1];
  670. DavVNetRoot = MRxDAVGetVNetRootExtension(VNetRoot);
  671. ASSERT(DavVNetRoot != NULL);
  672. } else {
  673. DavDbgTrace(DAV_TRACE_ERROR,
  674. ("%ld: MRxDAVPrecompleteUserModeVNetRootCreateRequest: Operation Cancelled. "
  675. "AsyncEngineContext = %08lx, RxContext = %08lx.\n",
  676. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  677. }
  678. //
  679. // We need to free up the heaps, we allocated in the format routine.
  680. //
  681. if (CreateVNetRootRequest->ServerName != NULL) {
  682. NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
  683. (PBYTE)CreateVNetRootRequest->ServerName);
  684. if (NtStatus != STATUS_SUCCESS) {
  685. DavDbgTrace(DAV_TRACE_ERROR,
  686. ("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootCreateRequest/"
  687. "UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
  688. PsGetCurrentThreadId(), NtStatus));
  689. goto EXIT_THE_FUNCTION;
  690. }
  691. }
  692. if (CreateVNetRootRequest->ShareName != NULL) {
  693. NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
  694. (PBYTE)CreateVNetRootRequest->ShareName);
  695. if (NtStatus != STATUS_SUCCESS) {
  696. DavDbgTrace(DAV_TRACE_ERROR,
  697. ("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootCreateRequest/"
  698. "UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
  699. PsGetCurrentThreadId(), NtStatus));
  700. goto EXIT_THE_FUNCTION;
  701. }
  702. }
  703. if (!OperationCancelled) {
  704. NtStatus = AsyncEngineContext->Status;
  705. if (NtStatus != STATUS_SUCCESS) {
  706. //
  707. // If the CreateVNetRoot failed in the usermode, we set the following
  708. // in the DavVNetRoot structure to TRUE. This is because when the
  709. // finalize comes, we don't need to go to the usermode.
  710. //
  711. DavVNetRoot->createVNetRootUnSuccessful = TRUE;
  712. DavDbgTrace(DAV_TRACE_ERROR,
  713. ("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootCreateRequest:"
  714. " NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  715. } else {
  716. //
  717. // We would have figured out in the usermode if this share is a TAHOE
  718. // share or an Office Web Server share and whether this share allows
  719. // PROPPATCH or not, and resporst available space or not
  720. //
  721. DavVNetRoot->isOfficeShare = CreateVNetRootResponse->isOfficeShare;
  722. DavVNetRoot->isTahoeShare = CreateVNetRootResponse->isTahoeShare;
  723. DavVNetRoot->fAllowsProppatch = CreateVNetRootResponse->fAllowsProppatch;
  724. DavVNetRoot->fReportsAvailableSpace = CreateVNetRootResponse->fReportsAvailableSpace;
  725. }
  726. }
  727. EXIT_THE_FUNCTION:
  728. return(TRUE);
  729. }
  730. NTSTATUS
  731. MRxDAVDereferenceNetRootContext(
  732. IN PWEBDAV_NET_ROOT DavNetRoot
  733. )
  734. /*++
  735. Routine Description:
  736. This routine dereferences the Webdav NetRoot instance and free it if the refcount reaches 0.
  737. Arguments:
  738. DavNetRoot - The Webdav NetRoot.
  739. Return Value:
  740. STATUS_SUCCESS
  741. --*/
  742. {
  743. PAGED_CODE();
  744. if (DavNetRoot != NULL) {
  745. ULONG RefCount;
  746. RefCount = InterlockedDecrement(&DavNetRoot->RefCount);
  747. DavDbgTrace(DAV_TRACE_DAVNETROOT,
  748. ("MRxDAVDereferenceNetRootContext %x %d\n",DavNetRoot,RefCount));
  749. if (RefCount == 0) {
  750. //
  751. // Free storage associated with all entries in the name caches.
  752. //
  753. RxNameCacheFinalize(&DavNetRoot->NameCacheCtlGFABasic);
  754. RxNameCacheFinalize(&DavNetRoot->NameCacheCtlGFAStandard);
  755. RxNameCacheFinalize(&DavNetRoot->NameCacheCtlFNF);
  756. //
  757. // Reset the Context so that no further reference can be made to this DavNetRoot
  758. //
  759. ASSERT(DavNetRoot->pRdbssNetRoot->Context == DavNetRoot);
  760. DavNetRoot->pRdbssNetRoot->Context = NULL;
  761. RxFreePool(DavNetRoot);
  762. DavDbgTrace(DAV_TRACE_DAVNETROOT,
  763. ("MRxDav frees DavNetRoot %x\n",DavNetRoot));
  764. }
  765. }
  766. return STATUS_SUCCESS;
  767. }
  768. NTSTATUS
  769. MRxDAVFinalizeNetRoot(
  770. IN PMRX_NET_ROOT pNetRoot,
  771. IN PBOOLEAN ForceDisconnect
  772. )
  773. /*++
  774. Routine Description:
  775. Arguments:
  776. pVirtualNetRoot - The Virtual NetRoot.
  777. ForceDisconnect - Disconnect is forced.
  778. Return Value:
  779. RXSTATUS - The return status for the operation
  780. --*/
  781. {
  782. PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)pNetRoot->Context;
  783. PAGED_CODE();
  784. DavDbgTrace(DAV_TRACE_DETAIL,
  785. ("%ld: Entering UMRxFinalizeNetRoot!!!!\n",
  786. PsGetCurrentThreadId()));
  787. DavDbgTrace(DAV_TRACE_CONTEXT,
  788. ("%ld: UMRxFinalizeNetRoot: pNetRoot = %08lx.\n",
  789. PsGetCurrentThreadId(), pNetRoot));
  790. DavDbgTrace(DAV_TRACE_DAVNETROOT,
  791. ("MRxDAVFinalizeNetRoot deref DavNetRoot %x %x\n",pNetRoot->Context,pNetRoot));
  792. MRxDAVDereferenceNetRootContext((PWEBDAV_NET_ROOT)pNetRoot->Context);
  793. return STATUS_SUCCESS;
  794. }
  795. VOID
  796. MRxDAVExtractNetRootName(
  797. IN PUNICODE_STRING FilePathName,
  798. IN PMRX_SRV_CALL SrvCall,
  799. OUT PUNICODE_STRING NetRootName,
  800. OUT PUNICODE_STRING RestOfName OPTIONAL
  801. )
  802. /*++
  803. Routine Description:
  804. This routine parses the input name into srv, netroot, and the
  805. rest.
  806. Arguments:
  807. FilePathName - The filename that came in.
  808. SrvCall - The SrvCall strucutre created by RDBSS.
  809. NetRootName - Pointer to the netroot name.
  810. RestOfName - Pointer to the Rest of the name.
  811. Return Value:
  812. none.
  813. --*/
  814. {
  815. UNICODE_STRING xRestOfName;
  816. ULONG length = FilePathName->Length;
  817. PWCH w = FilePathName->Buffer;
  818. PWCH wlimit = (PWCH)(((PCHAR)w) + length);
  819. PWCH wlow;
  820. PAGED_CODE();
  821. //
  822. // The netroot name starts after the SrvCall name.
  823. //
  824. w += (SrvCall->pSrvCallName->Length/sizeof(WCHAR));
  825. NetRootName->Buffer = wlow = w;
  826. //
  827. // Calculate the length of the NetRoot name.
  828. //
  829. for ( ; ; ) {
  830. if (w >= wlimit) break;
  831. if ( (*w == OBJ_NAME_PATH_SEPARATOR) && (w != wlow) ){
  832. #if ZZZ_MODE
  833. if (*(w - 1) == L'z') {
  834. w++;
  835. continue;
  836. }
  837. #endif // if ZZZ_MODE
  838. break;
  839. }
  840. w++;
  841. }
  842. NetRootName->Length = NetRootName->MaximumLength = (USHORT)((PCHAR)w - (PCHAR)wlow);
  843. if (!RestOfName) {
  844. RestOfName = &xRestOfName;
  845. }
  846. RestOfName->Buffer = w;
  847. RestOfName->Length = RestOfName->MaximumLength = (USHORT)((PCHAR)wlimit - (PCHAR)w);
  848. DavDbgTrace(DAV_TRACE_DETAIL,
  849. ("%ld: MRxDAVExtractNetRootName: FilePath = %wZ\n",
  850. PsGetCurrentThreadId(), FilePathName));
  851. DavDbgTrace(DAV_TRACE_DETAIL,
  852. ("%ld: MRxDAVExtractNetRootName: Srv = %wZ, Root = %wZ, "
  853. "Rest = %wZ\n", PsGetCurrentThreadId(),
  854. SrvCall->pSrvCallName, NetRootName, RestOfName));
  855. return;
  856. }
  857. NTSTATUS
  858. MRxDAVFinalizeVNetRoot(
  859. IN PMRX_V_NET_ROOT pVNetRoot,
  860. IN PBOOLEAN ForceDisconnect
  861. )
  862. /*++
  863. Routine Description:
  864. Arguments:
  865. pVNetRoot - The virtual net root which has to be finalized.
  866. ForceDisconnect - Disconnect is forced.
  867. Return Value:
  868. RXSTATUS - The return status for the operation
  869. --*/
  870. {
  871. NTSTATUS NtStatus = STATUS_SUCCESS;
  872. PRX_CONTEXT RxContext = NULL;
  873. PMRX_SRV_CALL SrvCall = NULL;
  874. PRDBSS_DEVICE_OBJECT RxDeviceObject = NULL;
  875. PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
  876. PAGED_CODE();
  877. DavDbgTrace(DAV_TRACE_DETAIL,
  878. ("%ld: Entering UMRxFinalizeVNetRoot!!!!\n",
  879. PsGetCurrentThreadId()));
  880. DavDbgTrace(DAV_TRACE_DETAIL,
  881. ("%ld: UMRxFinalizeVNetRoot: NetRootName = %wZ\n",
  882. PsGetCurrentThreadId(), pVNetRoot->pNetRoot->pNetRootName));
  883. SrvCall = pVNetRoot->pNetRoot->pSrvCall;
  884. RxDeviceObject = SrvCall->RxDeviceObject;
  885. DavVNetRoot = MRxDAVGetVNetRootExtension(pVNetRoot);
  886. ASSERT(DavVNetRoot != NULL);
  887. //
  888. // If we created the SecurityClientContext, we need to delete it now. We
  889. // don't need this when we go up to the usermode to finalize the VNetRoot
  890. // since we don't impersonate the client when doing this.
  891. //
  892. if (DavVNetRoot->SCAlreadyInitialized) {
  893. SeDeleteClientSecurity(&(DavVNetRoot->SecurityClientContext));
  894. }
  895. DavDbgTrace(DAV_TRACE_DAVNETROOT,
  896. ("MRxDAVFinalizeVNetRoot deref DavNetRoot %x %x %x\n",pVNetRoot->Context2,pVNetRoot->pNetRoot,pVNetRoot));
  897. MRxDAVDereferenceNetRootContext((PWEBDAV_NET_ROOT)pVNetRoot->Context2);
  898. pVNetRoot->Context2 = NULL;
  899. //
  900. // We need to make sure that the creation of this VNetRoot was successful.
  901. // If it was not, then we don't go to the usermode to finalize the
  902. // PerUserEntry. Also, if the MiniRedir never got called during the
  903. // creation of VNetRoot (possible in some failure case) then we should not
  904. // go to the user mode. If the MiniRedir never gets called LogonIDSet will
  905. // be FALSE. If the MiniRedir gets called this will be TRUE for sure.
  906. //
  907. if (DavVNetRoot->createVNetRootUnSuccessful || !DavVNetRoot->LogonIDSet) {
  908. DavDbgTrace(DAV_TRACE_DETAIL,
  909. ("%ld: UMRxFinalizeVNetRoot. createVNetRootUnSuccessful\n",
  910. PsGetCurrentThreadId()));
  911. goto EXIT_THE_FUNCTION;
  912. }
  913. //
  914. // Unfortunately, we do not have an RxContext here and hence have to create
  915. // one. An RxContext is required for a request to be reflected up.
  916. //
  917. RxContext = RxCreateRxContext(NULL, RxDeviceObject, 0);
  918. if (RxContext == NULL) {
  919. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  920. DavDbgTrace(DAV_TRACE_ERROR,
  921. ("%ld: MRxDAVFinalizeVNetRoot/RxCreateRxContext: "
  922. "NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  923. goto EXIT_THE_FUNCTION;
  924. }
  925. //
  926. // We need to send the VNetRoot to the format routine and use the
  927. // MRxContext[1] pointer of the RxContext structure to store it.
  928. //
  929. RxContext->MRxContext[1] = (PVOID)pVNetRoot;
  930. NtStatus = UMRxAsyncEngOuterWrapper(RxContext,
  931. SIZEOF_DAV_SPECIFIC_CONTEXT,
  932. MRxDAVFormatTheDAVContext,
  933. DAV_MINIRDR_ENTRY_FROM_FINALIZEVNETROOT,
  934. MRxDAVFinalizeVNetRootContinuation,
  935. "MRxDAVFinalizeVNetRoot");
  936. if (NtStatus != ERROR_SUCCESS) {
  937. DavDbgTrace(DAV_TRACE_ERROR,
  938. ("%ld: MRxDAVFinalizeVNetRoot/UMRxAsyncEngOuterWrapper: "
  939. "NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  940. }
  941. EXIT_THE_FUNCTION:
  942. if (RxContext) {
  943. RxDereferenceAndDeleteRxContext(RxContext);
  944. }
  945. DavDbgTrace(DAV_TRACE_DETAIL,
  946. ("%ld: Leaving MRxDAVFinalizeVNetRoot with NtStatus = %08lx.\n",
  947. PsGetCurrentThreadId(), NtStatus));
  948. return NtStatus;
  949. }
  950. NTSTATUS
  951. MRxDAVFinalizeVNetRootContinuation(
  952. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
  953. )
  954. /*++
  955. ORoutine Description:
  956. This is the continuation routine which finalizes a VNetRoot.
  957. Arguments:
  958. AsyncEngineContext - The Reflectors context.
  959. RxContext - The RDBSS context.
  960. Return Value:
  961. RXSTATUS - The return status for the operation
  962. --*/
  963. {
  964. NTSTATUS NtStatus = STATUS_SUCCESS;
  965. PAGED_CODE();
  966. DavDbgTrace(DAV_TRACE_DETAIL,
  967. ("%ld: Entering MRxDAVFinalizeVNetRootContinuation!!!!\n",
  968. PsGetCurrentThreadId()));
  969. DavDbgTrace(DAV_TRACE_CONTEXT,
  970. ("%ld: MRxDAVFinalizeVNetRootContinuation: "
  971. "AsyncEngineContext: %08lx, RxContext: %08lx\n",
  972. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  973. //
  974. // Try usermode.
  975. //
  976. NtStatus = UMRxSubmitAsyncEngUserModeRequest(
  977. UMRX_ASYNCENGINE_ARGUMENTS,
  978. MRxDAVFormatUserModeVNetRootFinalizeRequest,
  979. MRxDAVPrecompleteUserModeVNetRootFinalizeRequest
  980. );
  981. DavDbgTrace(DAV_TRACE_DETAIL,
  982. ("%ld: Leaving MRxDAVFinalizeVNetRootContinuation with NtStatus"
  983. " = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  984. return NtStatus;
  985. }
  986. NTSTATUS
  987. MRxDAVFormatUserModeVNetRootFinalizeRequest(
  988. IN UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  989. IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  990. IN ULONG WorkItemLength,
  991. OUT PULONG_PTR ReturnedLength
  992. )
  993. /*++
  994. Routine Description:
  995. This routine formats the VNetRoot finalize request being sent to the user
  996. mode for processing.
  997. Arguments:
  998. RxContext - The RDBSS context.
  999. AsyncEngineContext - The reflctor's context.
  1000. WorkItem - The work item buffer.
  1001. WorkItemLength - The length of the work item buffer.
  1002. ReturnedLength -
  1003. Return Value:
  1004. STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES.
  1005. --*/
  1006. {
  1007. NTSTATUS NtStatus = STATUS_SUCCESS;
  1008. PDAV_USERMODE_WORKITEM DavWorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  1009. PMRX_SRV_CALL SrvCall = NULL;
  1010. PWEBDAV_SRV_CALL DavSrvCall = NULL;
  1011. PMRX_V_NET_ROOT VNetRoot = NULL;
  1012. PWEBDAV_V_NET_ROOT DavVNetRoot = NULL;
  1013. PWCHAR ServerName = NULL;
  1014. ULONG ServerNameLengthInBytes = 0;
  1015. PBYTE SecondaryBuff = NULL;
  1016. PDAV_USERMODE_FINALIZE_V_NET_ROOT_REQUEST DavFinalizeVNetRootRequest = NULL;
  1017. PAGED_CODE();
  1018. DavDbgTrace(DAV_TRACE_DETAIL,
  1019. ("%ld: Entering MRxDAVFormatUserModeVNetRootFinalizeRequest\n",
  1020. PsGetCurrentThreadId()));
  1021. DavDbgTrace(DAV_TRACE_CONTEXT,
  1022. ("%ld: MRxDAVFormatUserModeVNetRootFinalizeRequest: "
  1023. "AsyncEngineContext: %08lx, RxContext: %08lx.\n",
  1024. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  1025. VNetRoot = (PMRX_V_NET_ROOT)RxContext->MRxContext[1];
  1026. ASSERT(VNetRoot != NULL);
  1027. DavVNetRoot = MRxDAVGetVNetRootExtension(VNetRoot);
  1028. ASSERT(DavVNetRoot != NULL);
  1029. SrvCall = VNetRoot->pNetRoot->pSrvCall;
  1030. ASSERT(SrvCall != NULL);
  1031. DavSrvCall = MRxDAVGetSrvCallExtension(SrvCall);
  1032. ASSERT(DavSrvCall != NULL);
  1033. DavWorkItem->WorkItemType = UserModeFinalizeVNetRoot;
  1034. DavFinalizeVNetRootRequest = &(DavWorkItem->FinalizeVNetRootRequest);
  1035. //
  1036. // Set the ServerID.
  1037. //
  1038. DavFinalizeVNetRootRequest->ServerID = DavSrvCall->ServerID;
  1039. //
  1040. // Set the LogonID.
  1041. //
  1042. DavFinalizeVNetRootRequest->LogonID.LowPart = DavVNetRoot->LogonID.LowPart;
  1043. DavFinalizeVNetRootRequest->LogonID.HighPart = DavVNetRoot->LogonID.HighPart;
  1044. DavDbgTrace(DAV_TRACE_DETAIL,
  1045. ("%ld: MRxDAVFormatUserModeVNetRootFinalizeRequest: "
  1046. "LogonID.LowPart = %d, LogonID.HighPart = %d\n",
  1047. PsGetCurrentThreadId(),
  1048. DavVNetRoot->LogonID.LowPart, DavVNetRoot->LogonID.HighPart));
  1049. //
  1050. // Set the Server name.
  1051. //
  1052. ServerName = &(SrvCall->pSrvCallName->Buffer[1]);
  1053. ServerNameLengthInBytes = (1 + wcslen(ServerName)) * sizeof(WCHAR);
  1054. SecondaryBuff = UMRxAllocateSecondaryBuffer(AsyncEngineContext,
  1055. ServerNameLengthInBytes);
  1056. if (SecondaryBuff == NULL) {
  1057. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  1058. DavDbgTrace(DAV_TRACE_ERROR,
  1059. ("ld: MRxDAVFormatUserModeVNetRootFinalizeRequest/"
  1060. "UMRxAllocateSecondaryBuffer: ERROR: NtStatus = %08lx.\n",
  1061. PsGetCurrentThreadId(), NtStatus));
  1062. goto EXIT_THE_FUNCTION;
  1063. }
  1064. DavFinalizeVNetRootRequest->ServerName = (PWCHAR)SecondaryBuff;
  1065. wcscpy(DavFinalizeVNetRootRequest->ServerName, ServerName);
  1066. EXIT_THE_FUNCTION:
  1067. DavDbgTrace(DAV_TRACE_DETAIL,
  1068. ("%ld: Leaving MRxDAVFormatUserModeVNetRootFinalizeRequest "
  1069. "with NtStatus = %08lx.\n", PsGetCurrentThreadId(), NtStatus));
  1070. return NtStatus;
  1071. }
  1072. BOOL
  1073. MRxDAVPrecompleteUserModeVNetRootFinalizeRequest(
  1074. UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
  1075. PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader,
  1076. ULONG WorkItemLength,
  1077. BOOL OperationCancelled
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. The precompletion routine for the finalize VNetRoot request.
  1082. Arguments:
  1083. RxContext - The RDBSS context.
  1084. AsyncEngineContext - The reflctor's context.
  1085. WorkItem - The work item buffer.
  1086. WorkItemLength - The length of the work item buffer.
  1087. OperationCancelled - TRUE if this operation was cancelled by the user.
  1088. Return Value:
  1089. TRUE - UMRxAsyncEngineCalldownIrpCompletion is called by the function
  1090. UMRxCompleteUserModeRequest after we return.
  1091. --*/
  1092. {
  1093. NTSTATUS NtStatus = STATUS_SUCCESS;
  1094. PDAV_USERMODE_WORKITEM WorkItem = (PDAV_USERMODE_WORKITEM)WorkItemHeader;
  1095. PDAV_USERMODE_FINALIZE_V_NET_ROOT_REQUEST DavFinalizeVNetRootRequest = NULL;
  1096. PAGED_CODE();
  1097. DavDbgTrace(DAV_TRACE_DETAIL,
  1098. ("%ld: Entering MRxDAVPrecompleteUserModeVNetRootFinalizeRequest\n",
  1099. PsGetCurrentThreadId()));
  1100. DavDbgTrace(DAV_TRACE_CONTEXT,
  1101. ("%ld: MRxDAVPrecompleteUserModeVNetRootFinalizeRequest: "
  1102. "AsyncEngineContext: %08lx, RxContext: %08lx.\n",
  1103. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  1104. //
  1105. // A FinalizeVNetRoot request can never by Async.
  1106. //
  1107. ASSERT(AsyncEngineContext->AsyncOperation == FALSE);
  1108. //
  1109. // If this operation was cancelled, then we don't need to do anything
  1110. // special in the FinalizeVNetRoot case.
  1111. //
  1112. if (OperationCancelled) {
  1113. DavDbgTrace(DAV_TRACE_ERROR,
  1114. ("%ld: MRxDAVPrecompleteUserModeVNetRootFinalizeRequest: Operation Cancelled. "
  1115. "AsyncEngineContext = %08lx, RxContext = %08lx.\n",
  1116. PsGetCurrentThreadId(), AsyncEngineContext, RxContext));
  1117. }
  1118. DavFinalizeVNetRootRequest = &(WorkItem->FinalizeVNetRootRequest);
  1119. //
  1120. // We need to free up the heap we allocated in the format routine.
  1121. //
  1122. if (DavFinalizeVNetRootRequest->ServerName != NULL) {
  1123. NtStatus = UMRxFreeSecondaryBuffer(AsyncEngineContext,
  1124. (PBYTE)DavFinalizeVNetRootRequest->ServerName);
  1125. if (NtStatus != STATUS_SUCCESS) {
  1126. DavDbgTrace(DAV_TRACE_ERROR,
  1127. ("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootFinalizeRequestt/"
  1128. "UMRxFreeSecondaryBuffer: NtStatus = %08lx.\n",
  1129. PsGetCurrentThreadId(), NtStatus));
  1130. }
  1131. }
  1132. if (AsyncEngineContext->Status != STATUS_SUCCESS) {
  1133. DavDbgTrace(DAV_TRACE_ERROR,
  1134. ("%ld: ERROR: MRxDAVPrecompleteUserModeVNetRootFinalizeRequest. "
  1135. "Finalize VNetRoot Failed!!!\n",
  1136. PsGetCurrentThreadId()));
  1137. }
  1138. DavDbgTrace(DAV_TRACE_DETAIL,
  1139. ("%ld: Leaving MRxDAVPrecompleteUserModeVNetRootFinalizeRequest\n",
  1140. PsGetCurrentThreadId()));
  1141. return TRUE;
  1142. }