Source code of Windows XP (NT5)
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.

1369 lines
42 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. netroot.c
  5. Abstract:
  6. This module implements the routines for creating the SMB net root.
  7. Author:
  8. Balan Sethu Raman [SethuR] 7-March-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "exsessup.h"
  14. #include "dfsfsctl.h"
  15. //
  16. // The Bug check file id for this module
  17. //
  18. #define BugCheckFileId (RDBSS_BUG_CHECK_SMB_NETROOT)
  19. //
  20. // The local debug trace level
  21. //
  22. #define Dbg (DEBUG_TRACE_DISPATCH)
  23. #ifdef ALLOC_PRAGMA
  24. #pragma alloc_text(PAGE, MRxSmbUpdateNetRootState)
  25. #pragma alloc_text(PAGE, MRxSmbGetDialectFlagsFromSrvCall)
  26. #pragma alloc_text(PAGE, MRxSmbCreateVNetRoot)
  27. #pragma alloc_text(PAGE, MRxSmbFinalizeNetRoot)
  28. #pragma alloc_text(PAGE, SmbCeReconnect)
  29. #pragma alloc_text(PAGE, SmbCeEstablishConnection)
  30. #pragma alloc_text(PAGE, SmbConstructNetRootExchangeStart)
  31. #pragma alloc_text(PAGE, MRxSmbExtractNetRootName)
  32. #endif
  33. //
  34. // Forward declarations ...
  35. //
  36. extern NTSTATUS
  37. SmbCeParseConstructNetRootResponse(
  38. PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange,
  39. PSMB_HEADER pSmbHeader,
  40. ULONG BytesAvailable,
  41. ULONG BytesIndicated,
  42. ULONG *pBytesTaken);
  43. extern NTSTATUS
  44. SmbConstructNetRootExchangeFinalize(
  45. PSMB_EXCHANGE pExchange,
  46. BOOLEAN *pPostFinalize);
  47. typedef struct _SMBCE_NETROOT_CONSTRUCTION_CONTEXT {
  48. NTSTATUS Status;
  49. PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext;
  50. PMRX_V_NET_ROOT pVNetRoot;
  51. RX_WORK_QUEUE_ITEM WorkQueueItem;
  52. } SMBCE_NETROOT_CONSTRUCTION_CONTEXT,
  53. *PSMBCE_NETROOT_CONSTRUCTION_CONTEXT;
  54. NTSTATUS
  55. MRxSmbCreateVNetRootOffLine(
  56. IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext);
  57. NTSTATUS
  58. MRxSmbUpdateNetRootState(
  59. IN OUT PMRX_NET_ROOT pNetRoot)
  60. /*++
  61. Routine Description:
  62. This routine update the mini redirector state associated with a net root.
  63. Arguments:
  64. pNetRoot - the net root instance.
  65. Return Value:
  66. RXSTATUS - The return status for the operation
  67. Notes:
  68. By diffrentiating the mini redirewctor state from the net rot condition it is possible
  69. to permit a variety of reconnect strategies. It is conceivable that the RDBSS considers
  70. a net root to be good while the underlying mini redirector might mark it as invalid
  71. and reconnect on the fly.
  72. --*/
  73. {
  74. if (pNetRoot->MRxNetRootState == MRX_NET_ROOT_STATE_GOOD) {
  75. if (pNetRoot->Context == NULL) {
  76. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
  77. } else {
  78. PSMBCEDB_SERVER_ENTRY pServerEntry;
  79. pServerEntry = SmbCeReferenceAssociatedServerEntry(pNetRoot->pSrvCall);
  80. if (pServerEntry != NULL) {
  81. if (pServerEntry->Server.CscState == ServerCscDisconnected) {
  82. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
  83. } else {
  84. switch (pServerEntry->Header.State) {
  85. case SMBCEDB_ACTIVE:
  86. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
  87. break;
  88. case SMBCEDB_INVALID:
  89. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_DISCONNECTED;
  90. break;
  91. case SMBCEDB_CONSTRUCTION_IN_PROGRESS:
  92. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_RECONN;
  93. break;
  94. default:
  95. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
  96. break;
  97. }
  98. }
  99. SmbCeDereferenceServerEntry(pServerEntry);
  100. } else {
  101. pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;
  102. }
  103. }
  104. }
  105. return STATUS_SUCCESS;
  106. }
  107. ULONG
  108. MRxSmbGetDialectFlagsFromSrvCall(
  109. PMRX_SRV_CALL SrvCall
  110. )
  111. {
  112. ULONG DialectFlags;
  113. PSMBCEDB_SERVER_ENTRY pServerEntry;
  114. PAGED_CODE();
  115. pServerEntry = SmbCeReferenceAssociatedServerEntry(SrvCall);
  116. ASSERT(pServerEntry != NULL);
  117. DialectFlags = pServerEntry->Server.DialectFlags;
  118. SmbCeDereferenceServerEntry(pServerEntry);
  119. return(DialectFlags);
  120. }
  121. BOOLEAN
  122. MRxSmbIsThisACscAgentOpen(
  123. IN PRX_CONTEXT RxContext
  124. )
  125. /*++
  126. Routine Description:
  127. This routine determines if the open was made by the user mode CSC agent.
  128. Arguments:
  129. RxContext - the RDBSS context
  130. Return Value:
  131. TRUE - if it is an agent open, FALSE otherwise
  132. Notes:
  133. The agent opens are always satisfied by going to the server. They are never
  134. satisfied from the cached copies. This enables reintegration using snapshots
  135. even when the files are being currently used.
  136. --*/
  137. {
  138. BOOLEAN AgentOpen = FALSE;
  139. ULONG EaInformationLength;
  140. PDFS_NAME_CONTEXT pDfsNameContext;
  141. if (RxContext->Create.EaLength > 0) {
  142. PFILE_FULL_EA_INFORMATION pEaEntry;
  143. pEaEntry = (PFILE_FULL_EA_INFORMATION)RxContext->Create.EaBuffer;
  144. ASSERT(pEaEntry != NULL);
  145. for(;;) {
  146. if (strcmp(pEaEntry->EaName, EA_NAME_CSCAGENT) == 0) {
  147. AgentOpen = TRUE;
  148. break;
  149. }
  150. if (pEaEntry->NextEntryOffset == 0) {
  151. break;
  152. } else {
  153. pEaEntry = (PFILE_FULL_EA_INFORMATION)
  154. ((PCHAR) pEaEntry + pEaEntry->NextEntryOffset);
  155. }
  156. }
  157. }
  158. pDfsNameContext = RxContext->Create.NtCreateParameters.DfsNameContext;
  159. if ((pDfsNameContext != NULL) &&
  160. (pDfsNameContext->NameContextType == DFS_CSCAGENT_NAME_CONTEXT)) {
  161. AgentOpen = TRUE;
  162. }
  163. return AgentOpen;
  164. }
  165. NTSTATUS
  166. MRxSmbCreateVNetRoot(
  167. IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext
  168. )
  169. /*++
  170. Routine Description:
  171. This routine patches the RDBSS created net root instance with the information required
  172. by the mini redirector.
  173. In case the connection cannot be established, the mini redirector tries to transition
  174. the VNetRoot into disconnected mode and establishes the connection off-line. If the
  175. connection failes to establish in the synchronouse way, this routine will do the transition;
  176. Otherwise, SmbConstructNetRootExchangeFinalize routine will try the transition. In both
  177. cases, MRxSmbCreateVNetRoot will be called again to establish the connection in disconnected
  178. mode.
  179. Arguments:
  180. pVNetRoot - the virtual net root instance.
  181. pCreateNetRootContext - the net root context for calling back
  182. Return Value:
  183. RXSTATUS - The return status for the operation
  184. Notes:
  185. CODE.IMPROVEMENT -- The net root create context must supply the open mode in order
  186. to enable the mini redirector to implement a wide variety of reconnect strategies.
  187. --*/
  188. {
  189. NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
  190. PRX_CONTEXT pRxContext = pCreateNetRootContext->RxContext;
  191. PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;
  192. PMRX_SRV_CALL pSrvCall;
  193. PMRX_NET_ROOT pNetRoot;
  194. PSMBCEDB_SERVER_ENTRY pServerEntry;
  195. PUNICODE_STRING pNetRootName,pSrvCallName;
  196. BOOLEAN fInitializeNetRoot;
  197. BOOLEAN fDeferNetworkInitialization = FALSE;
  198. BOOLEAN fCscAgentOpen = FALSE;
  199. BOOLEAN fDisconnectedOperation;
  200. BOOLEAN CallBack = FALSE;
  201. extern DWORD hShareReint;
  202. PAGED_CODE();
  203. pNetRoot = pVNetRoot->pNetRoot;
  204. pSrvCall = pNetRoot->pSrvCall;
  205. pServerEntry = SmbCeGetAssociatedServerEntry(pSrvCall);
  206. if ((pRxContext != NULL) &&
  207. (pRxContext->MajorFunction == IRP_MJ_CREATE)) {
  208. fCscAgentOpen = MRxSmbIsThisACscAgentOpen(pRxContext);
  209. if (pRxContext->Create.ThisIsATreeConnectOpen){
  210. // Determine if this tree connect was initiated by a CSC agent
  211. InterlockedIncrement(&MRxSmbStatistics.UseCount);
  212. }
  213. fDeferNetworkInitialization = pRxContext->Create.TreeConnectOpenDeferred;
  214. }
  215. SmbCeLog(("SmbCreateVNetRoot CscAgent %x %wZ \n",fCscAgentOpen,pNetRoot->pNetRootName));
  216. SmbLog(LOG,
  217. MRxSmbCreateVNetRoot,
  218. LOGUCHAR(fCscAgentOpen)
  219. LOGUSTR(*pNetRoot->pNetRootName));
  220. fInitializeNetRoot = (pNetRoot->Context == NULL);
  221. fDisconnectedOperation = (SmbCeIsServerInDisconnectedMode(pServerEntry) &&
  222. !fCscAgentOpen);
  223. if (fCscAgentOpen &&
  224. SmbCeIsServerInDisconnectedMode(pServerEntry)) {
  225. // this is an EA open. we want this one to succeed but want others to still
  226. // stay offline till an ioctl comes down to say we want to transition
  227. CscPrepareServerEntryForOnlineOperationPartial(pServerEntry);
  228. }
  229. ASSERT((NodeType(pNetRoot) == RDBSS_NTC_NETROOT) &&
  230. (NodeType(pNetRoot->pSrvCall) == RDBSS_NTC_SRVCALL));
  231. if (pNetRoot->Type == NET_ROOT_MAILSLOT) {
  232. pVNetRoot->Context = NULL;
  233. Status = STATUS_SUCCESS;
  234. RxDbgTrace( 0, Dbg, ("Mailslot open\n"));
  235. } else if ((pNetRoot->Type == NET_ROOT_PIPE) &&
  236. (pServerEntry->Header.State == SMBCEDB_ACTIVE)) {
  237. if (fDisconnectedOperation) {
  238. pVNetRoot->Context = NULL;
  239. Status = STATUS_BAD_NETWORK_NAME;
  240. } else if (SmbCeGetServerType(pServerEntry) == SMBCEDB_FILE_SERVER &&
  241. !FlagOn(MRxSmbGetDialectFlagsFromSrvCall(pSrvCall),DF_LANMAN10)) {
  242. pVNetRoot->Context = NULL;
  243. Status = STATUS_NOT_SUPPORTED;
  244. RxDbgTrace( 0, Dbg, ("pipe open to core server\n"));
  245. }
  246. }
  247. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  248. Status = SmbCeFindOrConstructVNetRootContext(
  249. pVNetRoot,
  250. fDeferNetworkInitialization,
  251. fCscAgentOpen);
  252. }
  253. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  254. // Update the flags on the VNetRootContext to indicate if this is a
  255. // agent open
  256. Status = SmbCeEstablishConnection(
  257. pVNetRoot,
  258. pCreateNetRootContext,
  259. fInitializeNetRoot);
  260. }
  261. if (Status != STATUS_PENDING) {
  262. if (fCscAgentOpen && Status == STATUS_RETRY) {
  263. Status = STATUS_CONNECTION_DISCONNECTED;
  264. }
  265. if (!NT_SUCCESS(Status)) {
  266. if (!fCscAgentOpen &&
  267. !SmbCeIsServerInDisconnectedMode(pServerEntry)) {
  268. // if it cannot establish the connect and didn't get chance to transition
  269. // into disconnected state, we should try the transition and if succeed,
  270. // establish the connect again in the disconnected state.
  271. Status = CscTransitionVNetRootForDisconnectedOperation(
  272. pCreateNetRootContext->RxContext,
  273. pVNetRoot,
  274. Status);
  275. }
  276. if (fInitializeNetRoot &&
  277. (pNetRoot->Context != NULL)) {
  278. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  279. SmbCeAcquireResource();
  280. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(pNetRoot);
  281. if (pNetRootEntry != NULL) {
  282. pNetRootEntry->pRdbssNetRoot = NULL;
  283. SmbCeDereferenceNetRootEntry(pNetRootEntry);
  284. }
  285. pNetRoot->Context = NULL;
  286. SmbCeReleaseResource();
  287. }
  288. SmbCeDestroyAssociatedVNetRootContext(pVNetRoot);
  289. if ((pRxContext != NULL) &&
  290. (pRxContext->MajorFunction == IRP_MJ_CREATE) &&
  291. (pRxContext->Create.ThisIsATreeConnectOpen)) {
  292. InterlockedIncrement(&MRxSmbStatistics.FailedUseCount);
  293. }
  294. }
  295. pCreateNetRootContext->VirtualNetRootStatus = Status;
  296. if (fInitializeNetRoot) {
  297. pCreateNetRootContext->NetRootStatus = Status;
  298. } else {
  299. pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
  300. }
  301. if (Status == STATUS_RETRY) {
  302. // STATUS_RETRY is returned from CscTransitionVNetRootForDisconnectedOperation if the
  303. // server entry is transitioned into disconnected mode.
  304. Status = MRxSmbCreateVNetRootOffLine(pCreateNetRootContext);
  305. if (Status != STATUS_SUCCESS) {
  306. // Callback the RDBSS for resumption if create VNetRootOffLine fails
  307. CallBack = TRUE;
  308. }
  309. } else {
  310. CallBack = TRUE;
  311. }
  312. // Map the error code to STATUS_PENDING since this triggers the synchronization
  313. // mechanism in the RDBSS.
  314. Status = STATUS_PENDING;
  315. }
  316. if (CallBack) {
  317. IF_NOT_MRXSMB_CSC_ENABLED{
  318. NOTHING;
  319. } else {
  320. if (pCreateNetRootContext->NetRootStatus == STATUS_SUCCESS){
  321. if ((pRxContext != NULL) &&
  322. (pRxContext->MajorFunction == IRP_MJ_CREATE) &&
  323. (pNetRoot->Type == NET_ROOT_DISK)) {
  324. MRxSmbCscPartOfCreateVNetRoot(pRxContext,pNetRoot);
  325. }
  326. }
  327. }
  328. if (pServerEntry->Server.IsRemoteBootServer &&
  329. pCreateNetRootContext->NetRootStatus != STATUS_SUCCESS) {
  330. pCreateNetRootContext->NetRootStatus = STATUS_RETRY;
  331. pCreateNetRootContext->VirtualNetRootStatus = STATUS_RETRY;
  332. }
  333. // Callback the RDBSS for resumption.
  334. pCreateNetRootContext->Callback(pCreateNetRootContext);
  335. }
  336. return Status;
  337. }
  338. NTSTATUS
  339. MRxSmbFinalizeVNetRoot(
  340. IN PMRX_V_NET_ROOT pVNetRoot,
  341. IN PBOOLEAN ForceDisconnect)
  342. /*++
  343. Routine Description:
  344. Arguments:
  345. pVNetRoot - the virtual net root
  346. ForceDisconnect - disconnect is forced
  347. Return Value:
  348. RXSTATUS - The return status for the operation
  349. --*/
  350. {
  351. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  352. PSMBCEDB_SESSION_ENTRY pDefaultSessionEntry;
  353. // This cannot be paged code since we meed to protect the default session list with the lock
  354. RxDbgTrace( 0, Dbg, ("MRxSmbFinalizeVNetRoot %lx\n",pVNetRoot));
  355. if (pVNetRoot->Context != NULL) {
  356. SmbCeDestroyAssociatedVNetRootContext(pVNetRoot);
  357. }
  358. return STATUS_SUCCESS;
  359. }
  360. NTSTATUS
  361. MRxSmbFinalizeNetRoot(
  362. IN PMRX_NET_ROOT pNetRoot,
  363. IN PBOOLEAN ForceDisconnect)
  364. /*++
  365. Routine Description:
  366. Arguments:
  367. pVirtualNetRoot - the virtual net root
  368. ForceDisconnect - disconnect is forced
  369. Return Value:
  370. RXSTATUS - The return status for the operation
  371. --*/
  372. {
  373. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  374. PAGED_CODE();
  375. RxDbgTrace( 0, Dbg, ("MRxSmbFinalizeNetRoot %lx\n",pNetRoot));
  376. if (pNetRoot->Context != NULL) {
  377. SmbCeAcquireResource();
  378. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(pNetRoot);
  379. InterlockedCompareExchangePointer(
  380. &pNetRootEntry->pRdbssNetRoot,
  381. NULL,
  382. pNetRoot);
  383. SmbCeDereferenceNetRootEntry(pNetRootEntry);
  384. ASSERT(!FlagOn(pNetRoot->Flags,NETROOT_FLAG_FINALIZE_INVOKED));
  385. SetFlag(pNetRoot->Flags,NETROOT_FLAG_FINALIZE_INVOKED);
  386. SmbCeReleaseResource();
  387. }
  388. return STATUS_SUCCESS;
  389. }
  390. VOID
  391. SmbCeReconnectCallback(
  392. PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
  393. /*++
  394. Routine Description:
  395. This routine signals the completion of a reconnect attempt
  396. Arguments:
  397. pCreateNetRootContext - the net root context
  398. Return Value:
  399. RXSTATUS - The return status for the operation
  400. --*/
  401. {
  402. KeSetEvent(&pCreateNetRootContext->FinishEvent, IO_NETWORK_INCREMENT, FALSE );
  403. }
  404. NTSTATUS
  405. SmbCeReconnect(
  406. IN PMRX_V_NET_ROOT pVNetRoot)
  407. /*++
  408. Routine Description:
  409. This routine reconnects, i.e, establishes a new session and tree connect to a previously
  410. connected serverb share
  411. Arguments:
  412. pVNetRoot - the virtual net root instance.
  413. Return Value:
  414. RXSTATUS - The return status for the operation
  415. --*/
  416. {
  417. NTSTATUS Status;
  418. PSMBCEDB_SERVER_ENTRY pServerEntry;
  419. PSMBCEDB_SESSION_ENTRY pSessionEntry;
  420. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  421. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)pVNetRoot->Context;
  422. PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext;
  423. PAGED_CODE();
  424. if ((pVNetRootContext != NULL) &&
  425. (pVNetRootContext->Header.State == SMBCEDB_ACTIVE)) {
  426. pServerEntry = pVNetRootContext->pServerEntry;
  427. pSessionEntry = pVNetRootContext->pSessionEntry;
  428. pNetRootEntry = pVNetRootContext->pNetRootEntry;
  429. if ((pServerEntry->Header.State == SMBCEDB_ACTIVE) &&
  430. (pSessionEntry->Header.State == SMBCEDB_ACTIVE) &&
  431. (pNetRootEntry->Header.State == SMBCEDB_ACTIVE)) {
  432. return STATUS_SUCCESS;
  433. }
  434. }
  435. pCreateNetRootContext = (PMRX_CREATENETROOT_CONTEXT)
  436. RxAllocatePoolWithTag(
  437. NonPagedPool,
  438. sizeof(MRX_CREATENETROOT_CONTEXT),
  439. MRXSMB_NETROOT_POOLTAG);
  440. if (pCreateNetRootContext != NULL) {
  441. for (;;) {
  442. pCreateNetRootContext->pVNetRoot = (PV_NET_ROOT)pVNetRoot;
  443. pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;
  444. pCreateNetRootContext->VirtualNetRootStatus = STATUS_SUCCESS;
  445. pCreateNetRootContext->Callback = SmbCeReconnectCallback;
  446. pCreateNetRootContext->RxContext = NULL;
  447. KeInitializeEvent(
  448. &pCreateNetRootContext->FinishEvent,
  449. SynchronizationEvent,
  450. FALSE );
  451. // Since this is a reconnect instance the net root initialization is not required
  452. Status = SmbCeEstablishConnection(
  453. pVNetRoot,
  454. pCreateNetRootContext,
  455. FALSE);
  456. if (Status == STATUS_PENDING) {
  457. // Wait for the construction to be completed.
  458. KeWaitForSingleObject(
  459. &pCreateNetRootContext->FinishEvent,
  460. Executive,
  461. KernelMode,
  462. FALSE,
  463. NULL);
  464. Status = pCreateNetRootContext->VirtualNetRootStatus;
  465. }
  466. if (Status != STATUS_LINK_FAILED) {
  467. break;
  468. }
  469. }
  470. RxFreePool(pCreateNetRootContext);
  471. } else {
  472. Status = STATUS_INSUFFICIENT_RESOURCES;
  473. }
  474. return Status;
  475. }
  476. NTSTATUS
  477. SmbCeEstablishConnection(
  478. IN OUT PMRX_V_NET_ROOT pVNetRoot,
  479. IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext,
  480. IN BOOLEAN fInitializeNetRoot
  481. )
  482. /*++
  483. Routine Description:
  484. This routine triggers off the connection attempt for initial establishment of a
  485. connection as well as subsequent reconnect attempts.
  486. Arguments:
  487. pVNetRoot - the virtual net root instance.
  488. pCreateNetRootContext - the net root context for calling back
  489. Return Value:
  490. RXSTATUS - The return status for the operation
  491. Notes:
  492. CODE.IMPROVEMENT -- The net root create context must supply the open mode in order
  493. to enable the mini redirector to implement a wide variety of reconnect strategies.
  494. --*/
  495. {
  496. NTSTATUS Status;
  497. PSMBCEDB_SERVER_ENTRY pServerEntry;
  498. PSMBCEDB_SESSION_ENTRY pSessionEntry;
  499. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  500. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  501. PAGED_CODE();
  502. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(pVNetRoot);
  503. if (pVNetRootContext == NULL) {
  504. Status = STATUS_BAD_NETWORK_PATH;
  505. } else {
  506. pServerEntry = pVNetRootContext->pServerEntry;
  507. pSessionEntry = pVNetRootContext->pSessionEntry;
  508. pNetRootEntry = pVNetRootContext->pNetRootEntry;
  509. Status = STATUS_SUCCESS;
  510. }
  511. if (Status == STATUS_SUCCESS) {
  512. //
  513. // The following code initializes the NetRootEntry, VNetRootContext and
  514. // the session entry under certain cases.
  515. //
  516. // The session entry to a doenlevel server needs to be initialized. This
  517. // is not handled by the previous code since the session entry and the
  518. // net root entry initialization can be combined into one exchange.
  519. //
  520. // The net root entry has not been initialized, i.e., this corresponds to
  521. // the construction of the first SMBCE_V_NET_ROOT_CONTEXT instance for a
  522. // given NetRootEntry.
  523. //
  524. // Subsequent SMBCE_V_NET_ROOT context constructions. In these cases the
  525. // construction of each context must obtain a new TID
  526. //
  527. BOOLEAN fNetRootExchangeRequired;
  528. fNetRootExchangeRequired = ((pSessionEntry->Header.State != SMBCEDB_ACTIVE) ||
  529. !BooleanFlagOn(pVNetRootContext->Flags,SMBCE_V_NET_ROOT_CONTEXT_FLAG_VALID_TID));
  530. if (fNetRootExchangeRequired) {
  531. // This is a tree connect open which needs to be triggered immediately.
  532. PSMB_EXCHANGE pSmbExchange;
  533. PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
  534. pSmbExchange = SmbMmAllocateExchange(CONSTRUCT_NETROOT_EXCHANGE,NULL);
  535. if (pSmbExchange != NULL) {
  536. Status = SmbCeInitializeExchange(
  537. &pSmbExchange,
  538. NULL,
  539. pVNetRoot,
  540. CONSTRUCT_NETROOT_EXCHANGE,
  541. &ConstructNetRootExchangeDispatch);
  542. if (Status == RX_MAP_STATUS(SUCCESS)) {
  543. pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pSmbExchange;
  544. // Attempt to reconnect( In this case it amounts to establishing the
  545. // connection/session)
  546. pNetRootExchange->SmbCeFlags |= (SMBCE_EXCHANGE_ATTEMPT_RECONNECTS |
  547. SMBCE_EXCHANGE_TIMED_RECEIVE_OPERATION);
  548. // Initialize the continuation for resumption upon completion of the
  549. // tree connetcion.
  550. pNetRootExchange->NetRootCallback = pCreateNetRootContext->Callback;
  551. pNetRootExchange->pCreateNetRootContext = pCreateNetRootContext;
  552. pNetRootExchange->RxContext = pCreateNetRootContext->RxContext;
  553. pNetRootExchange->fInitializeNetRoot = fInitializeNetRoot;
  554. IF_NOT_MRXSMB_BUILD_FOR_DISCONNECTED_CSC {
  555. // Initiate the exchange.
  556. Status = SmbCeInitiateExchange(pSmbExchange);
  557. if (Status != STATUS_PENDING) {
  558. SmbCeDiscardExchangeWorkerThreadRoutine(pSmbExchange);
  559. }
  560. } else {
  561. if (!SmbCeIsServerInDisconnectedMode(pServerEntry) ||
  562. FlagOn(
  563. pVNetRootContext->Flags,
  564. SMBCE_V_NET_ROOT_CONTEXT_CSCAGENT_INSTANCE)) {
  565. // Initiate the exchange.
  566. Status = SmbCeInitiateExchange(pSmbExchange);
  567. if (Status != STATUS_PENDING) {
  568. SmbCeDiscardExchangeWorkerThreadRoutine(pSmbExchange);
  569. }
  570. } else {
  571. //dont really initiate...just set up to call the completion
  572. //routine which BTW discards the exchange
  573. Status = MRxSmbCscDisconnectedConnect(pNetRootExchange);
  574. }
  575. }
  576. }
  577. } else {
  578. Status = STATUS_INSUFFICIENT_RESOURCES;
  579. }
  580. }
  581. }
  582. return Status;
  583. }
  584. //
  585. // The net roots are normally constructed as part of some other exchange, i.e., the SMB for
  586. // Tree connect is compounded with other operations. However, there is one situation in which
  587. // the tree connect SMB needs to be sent by itself. This case refers to the prefix claim
  588. // situation ( net use command ). This is handled by the construct net root exchange.
  589. //
  590. #define CONSTRUCT_NETROOT_BUFFER_SIZE (4096)
  591. NTSTATUS
  592. SmbConstructNetRootExchangeStart(
  593. PSMB_EXCHANGE pExchange)
  594. /*++
  595. Routine Description:
  596. This is the start routine for net root construction exchanges. This initiates the
  597. construction of the appropriate SMB's if required.
  598. Arguments:
  599. pExchange - the exchange instance
  600. Return Value:
  601. RXSTATUS - The return status for the operation
  602. --*/
  603. {
  604. NTSTATUS Status;
  605. NTSTATUS RequestLockStatus = STATUS_UNSUCCESSFUL;
  606. NTSTATUS ResponseLockStatus = STATUS_UNSUCCESSFUL;
  607. PVOID pSmbActualBuffer;
  608. PVOID pSmbBuffer;
  609. UCHAR SmbCommand,LastCommandInHeader;
  610. ULONG SmbLength;
  611. PUCHAR pCommand;
  612. PMDL pSmbRequestMdl,pSmbResponseMdl;
  613. ULONG SmbMdlSize;
  614. PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
  615. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
  616. PMRX_NET_ROOT pNetRoot = pExchange->SmbCeContext.pVNetRoot->pNetRoot;
  617. PAGED_CODE();
  618. pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pExchange;
  619. ASSERT(pNetRootExchange->Type == CONSTRUCT_NETROOT_EXCHANGE);
  620. if ((pNetRoot->Type == NET_ROOT_PIPE) &&
  621. !FlagOn(pServerEntry->Server.DialectFlags,DF_LANMAN10)) {
  622. RxDbgTrace( 0, Dbg, ("pipe open to core server\n"));
  623. return STATUS_NOT_SUPPORTED;
  624. }
  625. pSmbRequestMdl = pSmbResponseMdl = NULL;
  626. pSmbActualBuffer = RxAllocatePoolWithTag(
  627. PagedPool | POOL_COLD_ALLOCATION,
  628. (CONSTRUCT_NETROOT_BUFFER_SIZE + TRANSPORT_HEADER_SIZE),
  629. MRXSMB_NETROOT_POOLTAG);
  630. if (pSmbActualBuffer != NULL) {
  631. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(pExchange);
  632. (PCHAR) pSmbBuffer = (PCHAR) pSmbActualBuffer + TRANSPORT_HEADER_SIZE;
  633. Status = SmbCeBuildSmbHeader(
  634. pExchange,
  635. pSmbBuffer,
  636. CONSTRUCT_NETROOT_BUFFER_SIZE,
  637. &SmbLength,
  638. &LastCommandInHeader,
  639. &pCommand);
  640. // Ensure that the NET_ROOT/SESSION still needs to be constructed before
  641. // sending it. It is likely that they were costructed by an earlier exchange
  642. if (NT_SUCCESS(Status) &&
  643. (SmbLength > sizeof(SMB_HEADER))) {
  644. if (LastCommandInHeader != SMB_COM_TREE_CONNECT){
  645. *pCommand = SMB_COM_NO_ANDX_COMMAND;
  646. }
  647. RxAllocateHeaderMdl(
  648. pSmbBuffer,
  649. SmbLength,
  650. pSmbRequestMdl
  651. );
  652. pSmbResponseMdl = RxAllocateMdl(pSmbBuffer,CONSTRUCT_NETROOT_BUFFER_SIZE);
  653. if ((pSmbRequestMdl != NULL) &&
  654. (pSmbResponseMdl != NULL)) {
  655. RxProbeAndLockHeaderPages(
  656. pSmbRequestMdl,
  657. KernelMode,
  658. IoModifyAccess,
  659. RequestLockStatus);
  660. RxProbeAndLockPages(
  661. pSmbResponseMdl,
  662. KernelMode,
  663. IoModifyAccess,
  664. ResponseLockStatus);
  665. if ((Status == STATUS_SUCCESS) &&
  666. ((Status = RequestLockStatus) == STATUS_SUCCESS) &&
  667. ((Status = ResponseLockStatus) == STATUS_SUCCESS)) {
  668. pNetRootExchange->pSmbResponseMdl = pSmbResponseMdl;
  669. pNetRootExchange->pSmbRequestMdl = pSmbRequestMdl;
  670. pNetRootExchange->pSmbActualBuffer = pSmbActualBuffer;
  671. pNetRootExchange->pSmbBuffer = pSmbBuffer;
  672. Status = SmbCeTranceive(
  673. pExchange,
  674. (RXCE_SEND_PARTIAL | RXCE_SEND_SYNCHRONOUS),
  675. pNetRootExchange->pSmbRequestMdl,
  676. SmbLength);
  677. RxDbgTrace( 0, Dbg, ("Net Root SmbCeTranceive returned %lx\n",Status));
  678. }
  679. } else {
  680. Status = STATUS_INSUFFICIENT_RESOURCES;
  681. }
  682. if ((Status != STATUS_PENDING) &&
  683. (Status != STATUS_SUCCESS)) {
  684. pNetRootExchange->pSmbResponseMdl = NULL;
  685. pNetRootExchange->pSmbRequestMdl = NULL;
  686. pNetRootExchange->pSmbActualBuffer = NULL;
  687. pNetRootExchange->pSmbBuffer = NULL;
  688. if (pSmbResponseMdl != NULL) {
  689. if (ResponseLockStatus == STATUS_SUCCESS) {
  690. MmUnlockPages(pSmbResponseMdl);
  691. }
  692. IoFreeMdl(pSmbResponseMdl);
  693. }
  694. if (pSmbRequestMdl != NULL) {
  695. if (RequestLockStatus == STATUS_SUCCESS) {
  696. RxUnlockHeaderPages(pSmbRequestMdl);
  697. }
  698. IoFreeMdl(pSmbRequestMdl);
  699. }
  700. RxFreePool(pSmbActualBuffer);
  701. }
  702. } else {
  703. RxFreePool(pSmbActualBuffer);
  704. }
  705. } else {
  706. Status = STATUS_INSUFFICIENT_RESOURCES;
  707. }
  708. return Status;
  709. }
  710. NTSTATUS
  711. SmbConstructNetRootExchangeReceive(
  712. IN struct _SMB_EXCHANGE *pExchange,
  713. IN ULONG BytesIndicated,
  714. IN ULONG BytesAvailable,
  715. OUT ULONG *pBytesTaken,
  716. IN PSMB_HEADER pSmbHeader,
  717. OUT PMDL *pDataBufferPointer,
  718. OUT PULONG pDataSize,
  719. IN ULONG ReceiveFlags)
  720. /*++
  721. Routine Description:
  722. This is the recieve indication handling routine for net root construction exchanges
  723. Arguments:
  724. pExchange - the exchange instance
  725. BytesIndicated - the number of bytes indicated
  726. Bytes Available - the number of bytes available
  727. pBytesTaken - the number of bytes consumed
  728. pSmbHeader - the byte buffer
  729. pDataBufferPointer - the buffer into which the remaining data is to be copied.
  730. pDataSize - the buffer size.
  731. Return Value:
  732. NTSTATUS - The return status for the operation
  733. Notes:
  734. This routine is called at DPC level.
  735. --*/
  736. {
  737. NTSTATUS Status;
  738. PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
  739. pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pExchange;
  740. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader BytesIndicated/Available %ld %ld\n",BytesIndicated,BytesAvailable));
  741. if (BytesAvailable > BytesIndicated ||
  742. !FlagOn(ReceiveFlags,TDI_RECEIVE_ENTIRE_MESSAGE)) {
  743. // The SMB response was not completely returned. Post a copy data request to
  744. // get the remainder of the response. If the response is greater than the original
  745. // buffer size, abort this connection request and consume the bytes available.
  746. if (BytesAvailable > CONSTRUCT_NETROOT_BUFFER_SIZE) {
  747. ASSERT(!"not enough bytes in parsesmbheader.....sigh.............."); // To be removed soon ...
  748. pExchange->Status = STATUS_NOT_IMPLEMENTED;
  749. *pBytesTaken = BytesAvailable;
  750. Status = RX_MAP_STATUS(SUCCESS);
  751. } else {
  752. *pBytesTaken = 0;
  753. *pDataBufferPointer = pNetRootExchange->pSmbResponseMdl;
  754. *pDataSize = CONSTRUCT_NETROOT_BUFFER_SIZE;
  755. Status = STATUS_MORE_PROCESSING_REQUIRED;
  756. }
  757. } else {
  758. // The SMB exchange completed without an error.
  759. pExchange->Status = SmbCeParseConstructNetRootResponse(
  760. pNetRootExchange,
  761. pSmbHeader,
  762. BytesAvailable,
  763. BytesIndicated,
  764. pBytesTaken);
  765. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader BytesTaken %ld\n",*pBytesTaken));
  766. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader Return Status %lx\n",pExchange->Status));
  767. Status = STATUS_SUCCESS;
  768. }
  769. return Status;
  770. }
  771. NTSTATUS
  772. SmbConstructNetRootExchangeCopyDataHandler(
  773. IN PSMB_EXCHANGE pExchange,
  774. IN PMDL pCopyDataBuffer,
  775. IN ULONG DataSize)
  776. /*++
  777. Routine Description:
  778. This is the copy data handling routine for net root construction exchanges
  779. Arguments:
  780. pExchange - the exchange instance
  781. Return Value:
  782. NTSTATUS - The return status for the operation
  783. --*/
  784. {
  785. PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
  786. PSMB_HEADER pSmbHeader;
  787. ULONG ResponseSize = DataSize;
  788. ULONG ResponseBytesConsumed = 0;
  789. NTSTATUS Status = STATUS_SUCCESS;
  790. pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pExchange;
  791. ASSERT(pCopyDataBuffer == pNetRootExchange->pSmbResponseMdl);
  792. pSmbHeader = (PSMB_HEADER)MmGetSystemAddressForMdlSafe(pNetRootExchange->pSmbResponseMdl,LowPagePriority);
  793. if (pSmbHeader != NULL) {
  794. pExchange->Status = SmbCeParseConstructNetRootResponse(
  795. pNetRootExchange,
  796. pSmbHeader,
  797. ResponseSize,
  798. ResponseSize,
  799. &ResponseBytesConsumed);
  800. } else {
  801. Status = STATUS_INSUFFICIENT_RESOURCES;
  802. }
  803. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader BytesTaken %ld\n",ResponseBytesConsumed));
  804. return Status;
  805. }
  806. NTSTATUS
  807. SmbCeParseConstructNetRootResponse(
  808. PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange,
  809. PSMB_HEADER pSmbHeader,
  810. ULONG BytesAvailable,
  811. ULONG BytesIndicated,
  812. ULONG *pBytesTaken)
  813. {
  814. NTSTATUS Status,SmbResponseStatus;
  815. GENERIC_ANDX CommandToProcess;
  816. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseSmbHeader BytesIndicated %ld\n",BytesIndicated));
  817. Status = SmbCeParseSmbHeader(
  818. (PSMB_EXCHANGE)pNetRootExchange,
  819. pSmbHeader,
  820. &CommandToProcess,
  821. &SmbResponseStatus,
  822. BytesAvailable,
  823. BytesIndicated,
  824. pBytesTaken);
  825. if (Status == STATUS_SUCCESS) {
  826. *pBytesTaken = BytesIndicated;
  827. }
  828. return Status;
  829. }
  830. NTSTATUS
  831. SmbConstructNetRootExchangeFinalize(
  832. PSMB_EXCHANGE pExchange,
  833. BOOLEAN *pPostFinalize)
  834. /*++
  835. Routine Description:
  836. This routine finalizes the construct net root exchange. It resumes the RDBSS by invoking
  837. the call back and discards the exchange
  838. Arguments:
  839. pExchange - the exchange instance
  840. CurrentIrql - the current interrupt request level
  841. pPostFinalize - a pointer to a BOOLEAN if the request should be posted
  842. Return Value:
  843. RXSTATUS - The return status for the operation
  844. --*/
  845. {
  846. PSMB_CONSTRUCT_NETROOT_EXCHANGE pNetRootExchange;
  847. PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext;
  848. PMRX_NETROOT_CALLBACK pNetRootCallback;
  849. PMRX_V_NET_ROOT pVNetRoot;
  850. PMRX_NET_ROOT pNetRoot;
  851. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
  852. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  853. NTSTATUS Status = pExchange->Status;
  854. if (RxShouldPostCompletion()) {
  855. *pPostFinalize = TRUE;
  856. return STATUS_SUCCESS;
  857. } else {
  858. *pPostFinalize = FALSE;
  859. }
  860. pVNetRoot = SmbCeGetExchangeVNetRoot(pExchange);
  861. pNetRoot = pVNetRoot->pNetRoot;
  862. pVNetRootContext = SmbCeGetAssociatedVNetRootContext(pVNetRoot);
  863. ASSERT((pVNetRoot == NULL) || (pVNetRoot->pNetRoot == pNetRoot));
  864. pNetRootExchange = (PSMB_CONSTRUCT_NETROOT_EXCHANGE)pExchange;
  865. pNetRootCallback = pNetRootExchange->NetRootCallback;
  866. ASSERT(pNetRootExchange->Type == CONSTRUCT_NETROOT_EXCHANGE);
  867. pCreateNetRootContext = pNetRootExchange->pCreateNetRootContext;
  868. pCreateNetRootContext->VirtualNetRootStatus = RX_MAP_STATUS(SUCCESS);
  869. pCreateNetRootContext->NetRootStatus = RX_MAP_STATUS(SUCCESS);
  870. RxDbgTrace(0,Dbg,("SmbConstructNetRootExchangeFinalize: Net Root Exchange Status %lx\n", pExchange->Status));
  871. if (!NT_SUCCESS(pExchange->Status)) {
  872. if (pCreateNetRootContext->RxContext &&
  873. pCreateNetRootContext->RxContext->Create.ThisIsATreeConnectOpen){
  874. InterlockedIncrement(&MRxSmbStatistics.FailedUseCount);
  875. }
  876. if (!SmbCeIsServerInDisconnectedMode(pServerEntry) &&
  877. !FlagOn(pVNetRootContext->Flags,SMBCE_V_NET_ROOT_CONTEXT_CSCAGENT_INSTANCE)) {
  878. // if it cannot establish the connect and didn't get chance to transition
  879. // into disconnected state, we should try the transition and if succeed,
  880. // establish the connect again in the disconnected state.
  881. Status = CscTransitionVNetRootForDisconnectedOperation(
  882. pCreateNetRootContext->RxContext,
  883. pVNetRoot,
  884. pExchange->Status);
  885. }
  886. pCreateNetRootContext->VirtualNetRootStatus = Status;
  887. if (pCreateNetRootContext->VirtualNetRootStatus == STATUS_INVALID_HANDLE) {
  888. pCreateNetRootContext->VirtualNetRootStatus = STATUS_UNEXPECTED_NETWORK_ERROR;
  889. }
  890. if (pNetRootExchange->fInitializeNetRoot) {
  891. pCreateNetRootContext->NetRootStatus = Status;
  892. if (pCreateNetRootContext->NetRootStatus == STATUS_INVALID_HANDLE) {
  893. pCreateNetRootContext->NetRootStatus = STATUS_UNEXPECTED_NETWORK_ERROR;
  894. }
  895. }
  896. SmbCeUpdateVNetRootContextState(
  897. pVNetRootContext,
  898. SMBCEDB_MARKED_FOR_DELETION);
  899. } else {
  900. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  901. pNetRootEntry = SmbCeGetExchangeNetRootEntry(pExchange);
  902. if(pCreateNetRootContext->RxContext)
  903. {
  904. MRxSmbCscPartOfCreateVNetRoot(pCreateNetRootContext->RxContext, pNetRoot);
  905. }
  906. // Update the associated wrapper data structures.
  907. SmbCeUpdateNetRoot(pNetRootEntry,pNetRoot);
  908. }
  909. SmbCeReferenceVNetRootContext(pVNetRootContext);
  910. SmbCeCompleteVNetRootContextInitialization(pVNetRootContext);
  911. pExchange->SmbCeFlags &= ~SMBCE_EXCHANGE_NETROOT_CONSTRUCTOR;
  912. ASSERT((pCreateNetRootContext->VirtualNetRootStatus != STATUS_SUCCESS) || (pVNetRoot->Context != NULL));
  913. if ((pCreateNetRootContext->NetRootStatus == STATUS_CONNECTION_RESET)||(pCreateNetRootContext->NetRootStatus == STATUS_IO_TIMEOUT))
  914. {
  915. SmbCeLog(("!!Remote Reset Status=%x\n", pCreateNetRootContext->NetRootStatus));
  916. SmbLogError(pCreateNetRootContext->NetRootStatus,
  917. LOG,
  918. SmbConstructNetRootExchangeFinalize,
  919. LOGULONG(pCreateNetRootContext->NetRootStatus)
  920. LOGPTR(pNetRoot)
  921. LOGUSTR(*pNetRoot->pNetRootName));
  922. }
  923. if (pNetRootExchange->pSmbResponseMdl != NULL) {
  924. MmUnlockPages(pNetRootExchange->pSmbResponseMdl);
  925. IoFreeMdl(pNetRootExchange->pSmbResponseMdl);
  926. }
  927. if (pNetRootExchange->pSmbRequestMdl != NULL) {
  928. RxUnlockHeaderPages(pNetRootExchange->pSmbRequestMdl);
  929. IoFreeMdl(pNetRootExchange->pSmbRequestMdl);
  930. }
  931. if (pNetRootExchange->pSmbActualBuffer != NULL) {
  932. RxFreePool(pNetRootExchange->pSmbActualBuffer);
  933. }
  934. // Tear down the exchange instance ...
  935. SmbCeDiscardExchangeWorkerThreadRoutine(pExchange);
  936. if (Status == STATUS_RETRY) {
  937. // create VNetRoot offline if server entry is transitioned into disconnected state
  938. Status = MRxSmbCreateVNetRootOffLine(pCreateNetRootContext);
  939. if (Status != STATUS_SUCCESS) {
  940. // Callback the RDBSS for resumption if create VNetRoot offline fails
  941. pNetRootCallback(pCreateNetRootContext);
  942. }
  943. } else {
  944. if (pServerEntry->Server.IsRemoteBootServer &&
  945. pCreateNetRootContext->NetRootStatus != STATUS_SUCCESS) {
  946. pCreateNetRootContext->NetRootStatus = STATUS_RETRY;
  947. pCreateNetRootContext->VirtualNetRootStatus = STATUS_RETRY;
  948. }
  949. // Callback the RDBSS for resumption
  950. pNetRootCallback(pCreateNetRootContext);
  951. }
  952. return STATUS_SUCCESS;
  953. }
  954. NTSTATUS
  955. MRxSmbCreateVNetRootOffLine(
  956. PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
  957. {
  958. NTSTATUS Status;
  959. Status = RxPostToWorkerThread(
  960. MRxSmbDeviceObject,
  961. CriticalWorkQueue,
  962. &pCreateNetRootContext->WorkQueueItem,
  963. MRxSmbCreateVNetRoot,
  964. pCreateNetRootContext);
  965. return Status;
  966. }
  967. SMB_EXCHANGE_DISPATCH_VECTOR
  968. ConstructNetRootExchangeDispatch = {
  969. SmbConstructNetRootExchangeStart,
  970. SmbConstructNetRootExchangeReceive,
  971. SmbConstructNetRootExchangeCopyDataHandler,
  972. NULL, // No SendCompletionHandler
  973. SmbConstructNetRootExchangeFinalize,
  974. NULL
  975. };
  976. VOID
  977. MRxSmbExtractNetRootName(
  978. IN PUNICODE_STRING FilePathName,
  979. IN PMRX_SRV_CALL SrvCall,
  980. OUT PUNICODE_STRING NetRootName,
  981. OUT PUNICODE_STRING RestOfName OPTIONAL
  982. )
  983. /*++
  984. Routine Description:
  985. This routine parses the input name into srv, netroot, and the
  986. rest.
  987. Arguments:
  988. --*/
  989. {
  990. UNICODE_STRING xRestOfName;
  991. ULONG length = FilePathName->Length;
  992. PWCH w = FilePathName->Buffer;
  993. PWCH wlimit = (PWCH)(((PCHAR)w)+length);
  994. PWCH wlow;
  995. PAGED_CODE();
  996. w += (SrvCall->pSrvCallName->Length/sizeof(WCHAR));
  997. NetRootName->Buffer = wlow = w;
  998. for (;;) {
  999. if (w>=wlimit) break;
  1000. if ( (*w == OBJ_NAME_PATH_SEPARATOR) && (w!=wlow) ){
  1001. #if ZZZ_MODE
  1002. if (*(w-1) == L'z') {
  1003. w++;
  1004. continue;
  1005. }
  1006. #endif //if ZZZ_MODE
  1007. break;
  1008. }
  1009. w++;
  1010. }
  1011. NetRootName->Length = NetRootName->MaximumLength
  1012. = (USHORT)((PCHAR)w - (PCHAR)wlow);
  1013. if (!RestOfName) RestOfName = &xRestOfName;
  1014. RestOfName->Buffer = w;
  1015. RestOfName->Length = RestOfName->MaximumLength
  1016. = (USHORT)((PCHAR)wlimit - (PCHAR)w);
  1017. RxDbgTrace( 0,Dbg,(" MRxSmbExtractNetRootName FilePath=%wZ\n",FilePathName));
  1018. RxDbgTrace(0,Dbg,(" Srv=%wZ,Root=%wZ,Rest=%wZ\n",
  1019. SrvCall->pSrvCallName,NetRootName,RestOfName));
  1020. return;
  1021. }