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.

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