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.

2054 lines
72 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. NtConnct.c
  5. Abstract:
  6. This module implements the nt version of the high level routines dealing with
  7. connections including both the routines for establishing connections and the
  8. winnet connection apis.
  9. Author:
  10. Joe Linn [JoeLinn] 1-mar-95
  11. Revision History:
  12. Balan Sethu Raman [SethuR] --
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include <ntddnfs2.h>
  17. #include <ntddmup.h>
  18. #include "fsctlbuf.h"
  19. #include "prefix.h"
  20. #include <lmuse.h> //need the lm constants here......because of wkssvc
  21. #include "usrcnnct.h" //just to get the stovepipe definition
  22. #include "secext.h"
  23. #include "nb30.h" // to get ADAPTER_STATUS definition
  24. #include "vcsndrcv.h"
  25. //
  26. // The Bug check file id for this module
  27. //
  28. #define BugCheckFileId (RDBSS_BUG_CHECK_NTCONNCT)
  29. //
  30. // The local trace mask for this part of the module
  31. //
  32. #define Dbg (DEBUG_TRACE_CONNECT)
  33. VOID
  34. MRxSmbGetConnectInfoLevel3Fields(
  35. IN OUT PLMR_CONNECTION_INFO_3 ConnectionInfo,
  36. IN PSMBCEDB_SERVER_ENTRY pServerEntry,
  37. IN BOOL fAgentCall
  38. );
  39. extern NTSTATUS
  40. MRxEnumerateTransportBindings(
  41. IN PLMR_REQUEST_PACKET pLmrRequestPacket,
  42. IN ULONG LmrRequestPacketLength,
  43. OUT PVOID pBindingBuffer,
  44. IN OUT ULONG BindingBufferLength);
  45. BOOLEAN
  46. MRxSmbShowConnection(
  47. IN LUID LogonId,
  48. IN PV_NET_ROOT VNetRoot
  49. );
  50. #ifdef _WIN64
  51. typedef struct _UNICODE_STRING_32 {
  52. USHORT Length;
  53. USHORT MaximumLength;
  54. WCHAR * POINTER_32 Buffer;
  55. } UNICODE_STRING_32, *PUNICODE_STRING_32;
  56. typedef struct _LMR_CONNECTION_INFO_0_32 {
  57. UNICODE_STRING_32 UNCName; // Name of UNC connection
  58. ULONG ResumeKey; // Resume key for this entry.
  59. } LMR_CONNECTION_INFO_0_32, *PLMR_CONNECTION_INFO_0_32;
  60. typedef struct _LMR_CONNECTION_INFO_1_32 {
  61. UNICODE_STRING_32 UNCName; // Name of UNC connection
  62. ULONG ResumeKey; // Resume key for this entry.
  63. DEVICE_TYPE SharedResourceType; // Type of shared resource
  64. ULONG ConnectionStatus; // Status of the connection
  65. ULONG NumberFilesOpen; // Number of opened files
  66. } LMR_CONNECTION_INFO_1_32, *PLMR_CONNECTION_INFO_1_32;
  67. typedef struct _LMR_CONNECTION_INFO_2_32 {
  68. UNICODE_STRING_32 UNCName; // Name of UNC connection
  69. ULONG ResumeKey; // Resume key for this entry.
  70. DEVICE_TYPE SharedResourceType; // Type of shared resource
  71. ULONG ConnectionStatus; // Status of the connection
  72. ULONG NumberFilesOpen; // Number of opened files
  73. UNICODE_STRING_32 UserName; // User who created connection.
  74. UNICODE_STRING_32 DomainName; // Domain of user who created connection.
  75. ULONG Capabilities; // Bit mask of remote abilities.
  76. UCHAR UserSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH]; // User session key
  77. UCHAR LanmanSessionKey[MSV1_0_LANMAN_SESSION_KEY_LENGTH]; // Lanman session key
  78. } LMR_CONNECTION_INFO_2_32, *PLMR_CONNECTION_INFO_2_32;
  79. typedef struct _LMR_CONNECTION_INFO_3_32 {
  80. UNICODE_STRING_32 UNCName; // Name of UNC connection
  81. ULONG ResumeKey; // Resume key for this entry.
  82. DEVICE_TYPE SharedResourceType; // Type of shared resource
  83. ULONG ConnectionStatus; // Status of the connection
  84. ULONG NumberFilesOpen; // Number of opened files
  85. UNICODE_STRING_32 UserName; // User who created connection.
  86. UNICODE_STRING_32 DomainName; // Domain of user who created connection.
  87. ULONG Capabilities; // Bit mask of remote abilities.
  88. UCHAR UserSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH]; // User session key
  89. UCHAR LanmanSessionKey[MSV1_0_LANMAN_SESSION_KEY_LENGTH]; // Lanman session key
  90. UNICODE_STRING_32 TransportName; // Transport connection is active on
  91. ULONG Throughput; // Throughput of connection.
  92. ULONG Delay; // Small packet overhead.
  93. LARGE_INTEGER TimeZoneBias; // Time zone delta in 100ns units.
  94. BOOL IsSpecialIpcConnection; // True IFF there is a special IPC connection active.
  95. BOOL Reliable; // True iff the connection is reliable
  96. BOOL ReadAhead; // True iff readahead is active on connection.
  97. BOOL Core;
  98. BOOL MsNet103;
  99. BOOL Lanman10;
  100. BOOL WindowsForWorkgroups;
  101. BOOL Lanman20;
  102. BOOL Lanman21;
  103. BOOL WindowsNt;
  104. BOOL MixedCasePasswords;
  105. BOOL MixedCaseFiles;
  106. BOOL LongNames;
  107. BOOL ExtendedNegotiateResponse;
  108. BOOL LockAndRead;
  109. BOOL NtSecurity;
  110. BOOL SupportsEa;
  111. BOOL NtNegotiateResponse;
  112. BOOL CancelSupport;
  113. BOOL UnicodeStrings;
  114. BOOL LargeFiles;
  115. BOOL NtSmbs;
  116. BOOL RpcRemoteAdmin;
  117. BOOL NtStatusCodes;
  118. BOOL LevelIIOplock;
  119. BOOL UtcTime;
  120. BOOL UserSecurity;
  121. BOOL EncryptsPasswords;
  122. } LMR_CONNECTION_INFO_3_32, *PLMR_CONNECTION_INFO_3_32;
  123. VOID
  124. MRxSmbGetConnectInfoLevel3FieldsThunked(
  125. IN OUT PLMR_CONNECTION_INFO_3_32 ConnectionInfo,
  126. IN PSMBCEDB_SERVER_ENTRY pServerEntry,
  127. BOOL fAgentCall
  128. );
  129. BOOLEAN
  130. MRxSmbPackStringIntoConnectInfoThunked(
  131. IN PUNICODE_STRING_32 String,
  132. IN PUNICODE_STRING Source,
  133. IN OUT PCHAR * BufferStart,
  134. IN OUT PCHAR * BufferEnd,
  135. IN ULONG BufferDisplacement,
  136. IN OUT PULONG TotalBytes
  137. );
  138. BOOLEAN
  139. MRxSmbPackConnectEntryThunked (
  140. IN OUT PRX_CONTEXT RxContext,
  141. IN ULONG Level,
  142. IN OUT PCHAR *BufferStart,
  143. IN OUT PCHAR *BufferEnd,
  144. IN PV_NET_ROOT VNetRoot,
  145. IN OUT ULONG BufferDisplacement,
  146. OUT PULONG TotalBytesNeeded
  147. );
  148. #endif
  149. #ifdef ALLOC_PRAGMA
  150. #pragma alloc_text(PAGE, MRxSmbPackStringIntoConnectInfo)
  151. #pragma alloc_text(PAGE, MRxSmbPackConnectEntry)
  152. #pragma alloc_text(PAGE, MRxSmbGetConnectInfoLevel3Fields)
  153. #pragma alloc_text(PAGE, MRxSmbEnumerateConnections)
  154. #pragma alloc_text(PAGE, MRxSmbGetConnectionInfo)
  155. #pragma alloc_text(PAGE, MRxSmbDeleteConnection)
  156. #pragma alloc_text(PAGE, MRxEnumerateTransports)
  157. #pragma alloc_text(PAGE, MRxEnumerateTransportBindings)
  158. #ifdef _WIN64
  159. #pragma alloc_text(PAGE, MRxSmbGetConnectInfoLevel3FieldsThunked)
  160. #pragma alloc_text(PAGE, MRxSmbPackStringIntoConnectInfoThunked)
  161. #pragma alloc_text(PAGE, MRxSmbPackConnectEntryThunked)
  162. #endif
  163. #endif
  164. BOOLEAN
  165. MRxSmbPackStringIntoConnectInfo(
  166. IN PUNICODE_STRING String,
  167. IN PUNICODE_STRING Source,
  168. IN OUT PCHAR * BufferStart,
  169. IN OUT PCHAR * BufferEnd,
  170. IN ULONG BufferDisplacement,
  171. IN OUT PULONG TotalBytes
  172. )
  173. /*
  174. Routine Description:
  175. This code copies a string to the end of the buffer IF THERE'S ROOM. the buffer
  176. displacement is used to map the buffer back into the user's space in case we
  177. have posted.
  178. Arguments:
  179. Return Value:
  180. */
  181. {
  182. LONG size;
  183. PAGED_CODE();
  184. ASSERT (*BufferStart <= *BufferEnd);
  185. //
  186. // is there room for the string?
  187. //
  188. size = Source->Length;
  189. if ((*BufferEnd - *BufferStart) < size) {
  190. String->Length = 0;
  191. return(FALSE);
  192. } else {
  193. String->Length = Source->Length;
  194. String->MaximumLength = Source->Length;
  195. *BufferEnd -= size;
  196. if (TotalBytes!=NULL) { *TotalBytes += size; }
  197. RtlCopyMemory(*BufferEnd, Source->Buffer, size);
  198. (PCHAR )(String->Buffer) = *BufferEnd;
  199. (PCHAR )(String->Buffer) -= BufferDisplacement;
  200. return(TRUE);
  201. }
  202. }
  203. #ifdef _WIN64
  204. BOOLEAN
  205. MRxSmbPackStringIntoConnectInfoThunked(
  206. IN PUNICODE_STRING_32 String,
  207. IN PUNICODE_STRING Source,
  208. IN OUT PCHAR * BufferStart,
  209. IN OUT PCHAR * BufferEnd,
  210. IN ULONG BufferDisplacement,
  211. IN OUT PULONG TotalBytes
  212. )
  213. /*
  214. Routine Description:
  215. This code copies a string to the end of the buffer IF THERE'S ROOM. the buffer
  216. displacement is used to map the buffer back into the user's space in case we
  217. have posted.
  218. Arguments:
  219. Return Value:
  220. */
  221. {
  222. LONG size;
  223. PAGED_CODE();
  224. ASSERT (*BufferStart <= *BufferEnd);
  225. //
  226. // is there room for the string?
  227. //
  228. size = Source->Length;
  229. if ((*BufferEnd - *BufferStart) < size) {
  230. String->Length = 0;
  231. return(FALSE);
  232. } else {
  233. String->Length = Source->Length;
  234. String->MaximumLength = Source->Length;
  235. *BufferEnd -= size;
  236. if (TotalBytes!=NULL) { *TotalBytes += size; }
  237. RtlCopyMemory(*BufferEnd, Source->Buffer, size);
  238. (WCHAR * POINTER_32)(String->Buffer) = (WCHAR * POINTER_32)(*BufferEnd);
  239. (WCHAR * POINTER_32)(String->Buffer) -= BufferDisplacement;
  240. return(TRUE);
  241. }
  242. }
  243. #endif
  244. UNICODE_STRING MRxSmbPackConnectNull = {0,0,NULL};
  245. BOOLEAN
  246. MRxSmbPackConnectEntry (
  247. IN OUT PRX_CONTEXT RxContext,
  248. IN ULONG Level,
  249. IN OUT PCHAR *BufferStart,
  250. IN OUT PCHAR *BufferEnd,
  251. IN PV_NET_ROOT VNetRoot,
  252. IN OUT ULONG BufferDisplacement,
  253. OUT PULONG TotalBytesNeeded
  254. )
  255. /*++
  256. Routine Description:
  257. This routine packs a connectlistentry into the buffer provided updating
  258. all relevant pointers. The way that this works is that constant length stuff is
  259. copied to the front of the buffer and variable length stuff to the end. The
  260. "start and end" pointers are updated. You have to calculate the totalbytes correctly
  261. no matter what but a last can be setup incompletely as long as you return false.
  262. the way that this works is that it calls down into the minirdr on the devfcb
  263. interface. it calls down twice and passes a structure back and forth thru the
  264. context to maintain state.
  265. Arguments:
  266. IN ULONG Level - Level of information requested.
  267. IN OUT PCHAR *BufferStart - Supplies the output buffer.
  268. Updated to point to the next buffer
  269. IN OUT PCHAR *BufferEnd - Supplies the end of the buffer. Updated to
  270. point before the start of the
  271. strings being packed.
  272. IN PNET_ROOT NetRoot - Supplies the NetRoot to enumerate.
  273. IN OUT PULONG TotalBytesNeeded - Updated to account for the length of this
  274. entry
  275. Return Value:
  276. BOOLEAN - True if the entry was successfully packed into the buffer.
  277. --*/
  278. {
  279. NTSTATUS Status;
  280. BOOLEAN ReturnValue = TRUE;
  281. //PWCHAR ConnectName; // Buffer to hold the packed name
  282. UNICODE_STRING ConnectName; // Buffer to hold the packed name
  283. //ULONG NameLength;
  284. ULONG BufferSize;
  285. PLMR_CONNECTION_INFO_3 ConnectionInfo = (PLMR_CONNECTION_INFO_3)*BufferStart;
  286. PNET_ROOT NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
  287. PSMBCEDB_SERVER_ENTRY pServerEntry;
  288. PSMBCEDB_SESSION_ENTRY pSessionEntry;
  289. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = SmbCeGetAssociatedVNetRootContext((PMRX_V_NET_ROOT)VNetRoot);
  290. PAGED_CODE();
  291. RxDbgTrace(+1, Dbg, ("PackC\n"));
  292. switch (Level) {
  293. case 0:
  294. BufferSize = sizeof(LMR_CONNECTION_INFO_0);
  295. break;
  296. case 1:
  297. BufferSize = sizeof(LMR_CONNECTION_INFO_1);
  298. break;
  299. case 2:
  300. BufferSize = sizeof(LMR_CONNECTION_INFO_2);
  301. break;
  302. case 3:
  303. BufferSize = sizeof(LMR_CONNECTION_INFO_3);
  304. break;
  305. default:
  306. return FALSE;
  307. }
  308. if (pVNetRootContext == NULL) {
  309. return TRUE;
  310. }
  311. ConnectName.Buffer = RxAllocatePoolWithTag(NonPagedPool,
  312. NetRoot->PrefixEntry.Prefix.Length + sizeof(WCHAR),
  313. 'mNxR');
  314. if( ConnectName.Buffer == NULL ) {
  315. return FALSE;
  316. }
  317. try {
  318. pServerEntry = pVNetRootContext->pServerEntry;
  319. pSessionEntry = pVNetRootContext->pSessionEntry;
  320. ASSERT((pServerEntry != NULL) && (pSessionEntry != NULL));
  321. *BufferStart = ((PUCHAR)*BufferStart) + BufferSize;
  322. *TotalBytesNeeded += BufferSize;
  323. //
  324. // Initialize the name to "\" then add in the rest
  325. //
  326. ConnectName.Buffer[0] = L'\\';
  327. RtlCopyMemory(&ConnectName.Buffer[1], NetRoot->PrefixEntry.Prefix.Buffer, NetRoot->PrefixEntry.Prefix.Length);
  328. ConnectName.Length = (sizeof(WCHAR)) + NetRoot->PrefixEntry.Prefix.Length;
  329. ConnectName.MaximumLength = ConnectName.Length;
  330. //
  331. // Update the total number of bytes needed for this structure.
  332. //
  333. *TotalBytesNeeded += ConnectName.Length;
  334. if (*BufferStart > *BufferEnd) {
  335. try_return( ReturnValue = FALSE);
  336. }
  337. ConnectionInfo->ResumeKey = NetRoot->SerialNumberForEnum;
  338. if (Level > 0) {
  339. ULONG ConnectionStatus = 0;
  340. ConnectionInfo->SharedResourceType = NetRoot->DeviceType;
  341. RxDbgTrace(0, Dbg, ("PackC data---> netroot netrootcondifiton %08lx %08lx\n",
  342. NetRoot,NetRoot->Condition));
  343. MRxSmbUpdateNetRootState((PMRX_NET_ROOT)NetRoot);
  344. ConnectionInfo->ConnectionStatus = NetRoot->MRxNetRootState;
  345. ConnectionInfo->NumberFilesOpen = NetRoot->NumberOfSrvOpens;
  346. RxDbgTrace(0, Dbg, ("PackC data---> length restype resumek connstatus numfiles %08lx %08lx %08lx %08lx %08lx\n",
  347. ConnectionInfo->UNCName.Length,
  348. ConnectionInfo->SharedResourceType,
  349. ConnectionInfo->ResumeKey,
  350. ConnectionInfo->ConnectionStatus,
  351. ConnectionInfo->NumberFilesOpen));
  352. }
  353. if (Level > 1) {
  354. ULONG DialectFlags = pServerEntry->Server.DialectFlags;
  355. if (!BooleanFlagOn(
  356. pSessionEntry->Session.Flags,
  357. SMBCE_SESSION_FLAGS_LANMAN_SESSION_KEY_USED)) {
  358. RtlCopyMemory(
  359. ConnectionInfo->UserSessionKey,
  360. pSessionEntry->Session.UserSessionKey,
  361. MSV1_0_USER_SESSION_KEY_LENGTH);
  362. } else {
  363. ASSERT(MSV1_0_USER_SESSION_KEY_LENGTH >= MSV1_0_LANMAN_SESSION_KEY_LENGTH);
  364. RtlZeroMemory(
  365. ConnectionInfo->UserSessionKey,
  366. MSV1_0_USER_SESSION_KEY_LENGTH);
  367. RtlCopyMemory(
  368. ConnectionInfo->UserSessionKey,
  369. pSessionEntry->Session.LanmanSessionKey,
  370. MSV1_0_LANMAN_SESSION_KEY_LENGTH);
  371. }
  372. RtlCopyMemory(
  373. ConnectionInfo->LanmanSessionKey,
  374. pSessionEntry->Session.LanmanSessionKey,
  375. MSV1_0_LANMAN_SESSION_KEY_LENGTH);
  376. ConnectionInfo->Capabilities = 0;
  377. if (DialectFlags & DF_UNICODE) {
  378. ConnectionInfo->Capabilities |= CAPABILITY_UNICODE;
  379. }
  380. if (DialectFlags & DF_RPC_REMOTE) {
  381. ConnectionInfo->Capabilities |= CAPABILITY_RPC;
  382. }
  383. if ((DialectFlags & DF_NT_SMBS) && (DialectFlags & DF_RPC_REMOTE)) {
  384. ConnectionInfo->Capabilities |= CAPABILITY_SAM_PROTOCOL;
  385. }
  386. if (DialectFlags & DF_MIXEDCASE) {
  387. ConnectionInfo->Capabilities |= CAPABILITY_CASE_SENSITIVE_PASSWDS;
  388. }
  389. if (DialectFlags & DF_LANMAN10) {
  390. ConnectionInfo->Capabilities |= CAPABILITY_REMOTE_ADMIN_PROTOCOL;
  391. }
  392. ASSERT (!RxContext->PostRequest);
  393. RxDbgTrace(0, Dbg, ("PackC data---> capabilities %08lx \n", ConnectionInfo->Capabilities));
  394. }
  395. if (!MRxSmbPackStringIntoConnectInfo(
  396. &ConnectionInfo->UNCName,
  397. &ConnectName,
  398. BufferStart,
  399. BufferEnd,
  400. BufferDisplacement,
  401. NULL)) {
  402. if (Level > 1) {
  403. ConnectionInfo->UserName.Length = 0;
  404. ConnectionInfo->UserName.Buffer = NULL;
  405. }
  406. try_return( ReturnValue = FALSE);
  407. }
  408. if (Level > 1) {
  409. WCHAR UserNameBuffer[UNLEN + 1];
  410. WCHAR UserDomainNameBuffer[UNLEN + 1];
  411. UNICODE_STRING UserName,UserDomainName;
  412. UserName.Length = UserName.MaximumLength = UNLEN * sizeof(WCHAR);
  413. UserName.Buffer = UserNameBuffer;
  414. UserDomainName.Length = UserDomainName.MaximumLength = UNLEN * sizeof(WCHAR);
  415. UserDomainName.Buffer = UserDomainNameBuffer;
  416. Status = SmbCeGetUserNameAndDomainName(
  417. pSessionEntry,
  418. &UserName,
  419. &UserDomainName);
  420. if (NT_SUCCESS(Status)) {
  421. if (!MRxSmbPackStringIntoConnectInfo(
  422. &ConnectionInfo->UserName,
  423. &UserName,
  424. BufferStart,
  425. BufferEnd,
  426. BufferDisplacement,
  427. TotalBytesNeeded)) {
  428. try_return( ReturnValue = FALSE);
  429. }
  430. if (!MRxSmbPackStringIntoConnectInfo(
  431. &ConnectionInfo->DomainName,
  432. &UserDomainName,
  433. BufferStart,
  434. BufferEnd,
  435. BufferDisplacement,
  436. TotalBytesNeeded)) {
  437. try_return( ReturnValue = FALSE);
  438. }
  439. } else {
  440. try_return( ReturnValue = FALSE);
  441. }
  442. }
  443. if (Level > 2) {
  444. MRxSmbGetConnectInfoLevel3Fields(ConnectionInfo,pServerEntry, FALSE);
  445. if ((pServerEntry->pTransport != NULL) &&
  446. !SmbCeIsServerInDisconnectedMode(pServerEntry)) {
  447. NTSTATUS RefTransportStatus;
  448. RefTransportStatus = SmbCeReferenceServerTransport(&pServerEntry->pTransport);
  449. if (RefTransportStatus == STATUS_SUCCESS) {
  450. PUNICODE_STRING RxCeTransportName = &pServerEntry->pTransport->pTransport->RxCeTransport.Name;
  451. if (!MRxSmbPackStringIntoConnectInfo(
  452. &ConnectionInfo->TransportName,
  453. RxCeTransportName,
  454. BufferStart,
  455. BufferEnd,
  456. BufferDisplacement,
  457. TotalBytesNeeded)) {
  458. ReturnValue = FALSE;
  459. }
  460. SmbCeDereferenceServerTransport(&pServerEntry->pTransport);
  461. }
  462. }
  463. }
  464. try_exit:
  465. NOTHING;
  466. } finally {
  467. RxFreePool(ConnectName.Buffer);
  468. }
  469. RxDbgTrace(-1, Dbg, ("PackC...%08lx\n",ReturnValue));
  470. return ReturnValue;
  471. }
  472. #ifdef _WIN64
  473. BOOLEAN
  474. MRxSmbPackConnectEntryThunked (
  475. IN OUT PRX_CONTEXT RxContext,
  476. IN ULONG Level,
  477. IN OUT PCHAR *BufferStart,
  478. IN OUT PCHAR *BufferEnd,
  479. IN PV_NET_ROOT VNetRoot,
  480. IN OUT ULONG BufferDisplacement,
  481. OUT PULONG TotalBytesNeeded
  482. )
  483. /*++
  484. Routine Description:
  485. This routine packs a connectlistentry into the buffer provided updating
  486. all relevant pointers. The way that this works is that constant length stuff is
  487. copied to the front of the buffer and variable length stuff to the end. The
  488. "start and end" pointers are updated. You have to calculate the totalbytes correctly
  489. no matter what but a last can be setup incompletely as long as you return false.
  490. the way that this works is that it calls down into the minirdr on the devfcb
  491. interface. it calls down twice and passes a structure back and forth thru the
  492. context to maintain state.
  493. Arguments:
  494. IN ULONG Level - Level of information requested.
  495. IN OUT PCHAR *BufferStart - Supplies the output buffer.
  496. Updated to point to the next buffer
  497. IN OUT PCHAR *BufferEnd - Supplies the end of the buffer. Updated to
  498. point before the start of the
  499. strings being packed.
  500. IN PNET_ROOT NetRoot - Supplies the NetRoot to enumerate.
  501. IN OUT PULONG TotalBytesNeeded - Updated to account for the length of this
  502. entry
  503. Return Value:
  504. BOOLEAN - True if the entry was successfully packed into the buffer.
  505. --*/
  506. {
  507. NTSTATUS Status;
  508. BOOLEAN ReturnValue = TRUE;
  509. //PWCHAR ConnectName; // Buffer to hold the packed name
  510. UNICODE_STRING ConnectName; // Buffer to hold the packed name
  511. //ULONG NameLength;
  512. ULONG BufferSize;
  513. PLMR_CONNECTION_INFO_3_32 ConnectionInfo = (PLMR_CONNECTION_INFO_3_32)*BufferStart;
  514. PNET_ROOT NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
  515. PSMBCEDB_SERVER_ENTRY pServerEntry;
  516. PSMBCEDB_SESSION_ENTRY pSessionEntry;
  517. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = SmbCeGetAssociatedVNetRootContext((PMRX_V_NET_ROOT)VNetRoot);
  518. PAGED_CODE();
  519. RxDbgTrace(+1, Dbg, ("PackC\n"));
  520. switch (Level) {
  521. case 0:
  522. BufferSize = sizeof(LMR_CONNECTION_INFO_0_32);
  523. break;
  524. case 1:
  525. BufferSize = sizeof(LMR_CONNECTION_INFO_1_32);
  526. break;
  527. case 2:
  528. BufferSize = sizeof(LMR_CONNECTION_INFO_2_32);
  529. break;
  530. case 3:
  531. BufferSize = sizeof(LMR_CONNECTION_INFO_3_32);
  532. break;
  533. default:
  534. return FALSE;
  535. }
  536. if (pVNetRootContext == NULL) {
  537. return TRUE;
  538. }
  539. ConnectName.Buffer = RxAllocatePoolWithTag(NonPagedPool,
  540. NetRoot->PrefixEntry.Prefix.Length + sizeof(WCHAR),
  541. 'mNxR');
  542. if( ConnectName.Buffer == NULL ) {
  543. return FALSE;
  544. }
  545. try {
  546. pServerEntry = pVNetRootContext->pServerEntry;
  547. pSessionEntry = pVNetRootContext->pSessionEntry;
  548. ASSERT((pServerEntry != NULL) && (pSessionEntry != NULL));
  549. *BufferStart = ((PUCHAR)*BufferStart) + BufferSize;
  550. *TotalBytesNeeded += BufferSize;
  551. //
  552. // Initialize the name to "\" then add in the rest
  553. //
  554. ConnectName.Buffer[0] = L'\\';
  555. RtlCopyMemory(&ConnectName.Buffer[1], NetRoot->PrefixEntry.Prefix.Buffer, NetRoot->PrefixEntry.Prefix.Length);
  556. ConnectName.Length = (sizeof(WCHAR)) + NetRoot->PrefixEntry.Prefix.Length;
  557. ConnectName.MaximumLength = ConnectName.Length;
  558. //
  559. // Update the total number of bytes needed for this structure.
  560. //
  561. *TotalBytesNeeded += ConnectName.Length;
  562. if (*BufferStart > *BufferEnd) {
  563. try_return( ReturnValue = FALSE);
  564. }
  565. ConnectionInfo->ResumeKey = NetRoot->SerialNumberForEnum;
  566. if (Level > 0) {
  567. ULONG ConnectionStatus = 0;
  568. ConnectionInfo->SharedResourceType = NetRoot->DeviceType;
  569. RxDbgTrace(0, Dbg, ("PackC data---> netroot netrootcondifiton %08lx %08lx\n",
  570. NetRoot,NetRoot->Condition));
  571. MRxSmbUpdateNetRootState((PMRX_NET_ROOT)NetRoot);
  572. ConnectionInfo->ConnectionStatus = NetRoot->MRxNetRootState;
  573. ConnectionInfo->NumberFilesOpen = NetRoot->NumberOfSrvOpens;
  574. RxDbgTrace(0, Dbg, ("PackC data---> length restype resumek connstatus numfiles %08lx %08lx %08lx %08lx %08lx\n",
  575. ConnectionInfo->UNCName.Length,
  576. ConnectionInfo->SharedResourceType,
  577. ConnectionInfo->ResumeKey,
  578. ConnectionInfo->ConnectionStatus,
  579. ConnectionInfo->NumberFilesOpen));
  580. }
  581. if (Level > 1) {
  582. ULONG DialectFlags = pServerEntry->Server.DialectFlags;
  583. if (!BooleanFlagOn(
  584. pSessionEntry->Session.Flags,
  585. SMBCE_SESSION_FLAGS_LANMAN_SESSION_KEY_USED)) {
  586. RtlCopyMemory(
  587. ConnectionInfo->UserSessionKey,
  588. pSessionEntry->Session.UserSessionKey,
  589. MSV1_0_USER_SESSION_KEY_LENGTH);
  590. } else {
  591. ASSERT(MSV1_0_USER_SESSION_KEY_LENGTH >= MSV1_0_LANMAN_SESSION_KEY_LENGTH);
  592. RtlZeroMemory(
  593. ConnectionInfo->UserSessionKey,
  594. MSV1_0_USER_SESSION_KEY_LENGTH);
  595. RtlCopyMemory(
  596. ConnectionInfo->UserSessionKey,
  597. pSessionEntry->Session.LanmanSessionKey,
  598. MSV1_0_LANMAN_SESSION_KEY_LENGTH);
  599. }
  600. RtlCopyMemory(
  601. ConnectionInfo->LanmanSessionKey,
  602. pSessionEntry->Session.LanmanSessionKey,
  603. MSV1_0_LANMAN_SESSION_KEY_LENGTH);
  604. ConnectionInfo->Capabilities = 0;
  605. if (DialectFlags & DF_UNICODE) {
  606. ConnectionInfo->Capabilities |= CAPABILITY_UNICODE;
  607. }
  608. if (DialectFlags & DF_RPC_REMOTE) {
  609. ConnectionInfo->Capabilities |= CAPABILITY_RPC;
  610. }
  611. if ((DialectFlags & DF_NT_SMBS) && (DialectFlags & DF_RPC_REMOTE)) {
  612. ConnectionInfo->Capabilities |= CAPABILITY_SAM_PROTOCOL;
  613. }
  614. if (DialectFlags & DF_MIXEDCASE) {
  615. ConnectionInfo->Capabilities |= CAPABILITY_CASE_SENSITIVE_PASSWDS;
  616. }
  617. if (DialectFlags & DF_LANMAN10) {
  618. ConnectionInfo->Capabilities |= CAPABILITY_REMOTE_ADMIN_PROTOCOL;
  619. }
  620. ASSERT (!RxContext->PostRequest);
  621. RxDbgTrace(0, Dbg, ("PackC data---> capabilities %08lx \n", ConnectionInfo->Capabilities));
  622. }
  623. if (!MRxSmbPackStringIntoConnectInfoThunked(
  624. &ConnectionInfo->UNCName,
  625. &ConnectName,
  626. BufferStart,
  627. BufferEnd,
  628. BufferDisplacement,
  629. NULL)) {
  630. if (Level > 1) {
  631. ConnectionInfo->UserName.Length = 0;
  632. ConnectionInfo->UserName.Buffer = NULL;
  633. }
  634. try_return( ReturnValue = FALSE);
  635. }
  636. if (Level > 1) {
  637. WCHAR UserNameBuffer[UNLEN + 1];
  638. WCHAR UserDomainNameBuffer[UNLEN + 1];
  639. UNICODE_STRING UserName,UserDomainName;
  640. UserName.Length = UserName.MaximumLength = UNLEN * sizeof(WCHAR);
  641. UserName.Buffer = UserNameBuffer;
  642. UserDomainName.Length = UserDomainName.MaximumLength = UNLEN * sizeof(WCHAR);
  643. UserDomainName.Buffer = UserDomainNameBuffer;
  644. Status = SmbCeGetUserNameAndDomainName(
  645. pSessionEntry,
  646. &UserName,
  647. &UserDomainName);
  648. if (NT_SUCCESS(Status)) {
  649. if (!MRxSmbPackStringIntoConnectInfoThunked(
  650. &ConnectionInfo->UserName,
  651. &UserName,
  652. BufferStart,
  653. BufferEnd,
  654. BufferDisplacement,
  655. TotalBytesNeeded)) {
  656. try_return( ReturnValue = FALSE);
  657. }
  658. if (!MRxSmbPackStringIntoConnectInfoThunked(
  659. &ConnectionInfo->DomainName,
  660. &UserDomainName,
  661. BufferStart,
  662. BufferEnd,
  663. BufferDisplacement,
  664. TotalBytesNeeded)) {
  665. try_return( ReturnValue = FALSE);
  666. }
  667. } else {
  668. try_return( ReturnValue = FALSE);
  669. }
  670. }
  671. if (Level > 2) {
  672. MRxSmbGetConnectInfoLevel3FieldsThunked(ConnectionInfo,pServerEntry, FALSE);
  673. if ((pServerEntry->pTransport != NULL) &&
  674. !SmbCeIsServerInDisconnectedMode(pServerEntry)) {
  675. NTSTATUS RefTransportStatus;
  676. RefTransportStatus = SmbCeReferenceServerTransport(&pServerEntry->pTransport);
  677. if (RefTransportStatus == STATUS_SUCCESS) {
  678. PUNICODE_STRING RxCeTransportName = &pServerEntry->pTransport->pTransport->RxCeTransport.Name;
  679. if (!MRxSmbPackStringIntoConnectInfoThunked(
  680. &ConnectionInfo->TransportName,
  681. RxCeTransportName,
  682. BufferStart,
  683. BufferEnd,
  684. BufferDisplacement,
  685. TotalBytesNeeded)) {
  686. ReturnValue = FALSE;
  687. }
  688. SmbCeDereferenceServerTransport(&pServerEntry->pTransport);
  689. }
  690. }
  691. }
  692. try_exit:
  693. NOTHING;
  694. } finally {
  695. RxFreePool(ConnectName.Buffer);
  696. }
  697. RxDbgTrace(-1, Dbg, ("PackC...%08lx\n",ReturnValue));
  698. return ReturnValue;
  699. }
  700. #endif
  701. VOID
  702. MRxSmbGetConnectInfoLevel3Fields(
  703. IN OUT PLMR_CONNECTION_INFO_3 ConnectionInfo,
  704. IN PSMBCEDB_SERVER_ENTRY pServerEntry,
  705. BOOL fAgentCall
  706. )
  707. {
  708. ULONG DialectFlags = pServerEntry->Server.DialectFlags;
  709. NTSTATUS Status;
  710. RXCE_CONNECTION_INFO QueryConnectionInfo;
  711. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pServerEntry->pTransport;
  712. PSMBCE_VC pVc;
  713. PAGED_CODE();
  714. ConnectionInfo->Throughput = 0;
  715. ConnectionInfo->Delay = 0;
  716. ConnectionInfo->Reliable = FALSE;
  717. ConnectionInfo->ReadAhead = TRUE;
  718. ConnectionInfo->IsSpecialIpcConnection = FALSE;
  719. if ((pServerEntry->Header.State == SMBCEDB_ACTIVE) &&
  720. (pVcTransport != NULL) &&
  721. (!SmbCeIsServerInDisconnectedMode(pServerEntry)||fAgentCall)) {
  722. pVc = &pVcTransport->Vcs[0];
  723. Status = RxCeQueryInformation(
  724. &pVc->RxCeVc,
  725. RxCeConnectionEndpointInformation,
  726. &QueryConnectionInfo,
  727. sizeof(QueryConnectionInfo));
  728. if (NT_SUCCESS(Status)) {
  729. ConnectionInfo->Reliable = !QueryConnectionInfo.Unreliable;
  730. if (QueryConnectionInfo.Delay.QuadPart != 0) {
  731. if (QueryConnectionInfo.Delay.QuadPart == -1) {
  732. ConnectionInfo->Delay = 0;
  733. } else if (QueryConnectionInfo.Delay.HighPart != 0xffffffff) {
  734. ConnectionInfo->Delay = 0xffffffff;
  735. } else {
  736. ConnectionInfo->Delay = -1 * QueryConnectionInfo.Delay.LowPart;
  737. }
  738. } else {
  739. ConnectionInfo->Delay = 0;
  740. }
  741. if (QueryConnectionInfo.Throughput.QuadPart == -1) {
  742. ConnectionInfo->Throughput = 0;
  743. } else if (QueryConnectionInfo.Throughput.HighPart != 0) {
  744. ConnectionInfo->Throughput = 0xffffffff;
  745. } else {
  746. ConnectionInfo->Throughput = QueryConnectionInfo.Throughput.LowPart;
  747. }
  748. }
  749. }
  750. ConnectionInfo->TimeZoneBias = pServerEntry->Server.TimeZoneBias;
  751. ConnectionInfo->Core = (DialectFlags & DF_CORE) != 0;
  752. ConnectionInfo->MsNet103 = (DialectFlags & DF_OLDRAWIO) != 0;
  753. ConnectionInfo->Lanman10 = (DialectFlags & DF_LANMAN10) != 0;
  754. ConnectionInfo->WindowsForWorkgroups = (DialectFlags & DF_WFW) != 0;
  755. ConnectionInfo->Lanman20 = (DialectFlags & DF_LANMAN20) != 0;
  756. ConnectionInfo->Lanman21 = (DialectFlags & DF_LANMAN21) != 0;
  757. ConnectionInfo->WindowsNt = (DialectFlags & DF_NTPROTOCOL) != 0;
  758. ConnectionInfo->MixedCasePasswords = (DialectFlags & DF_MIXEDCASEPW) != 0;
  759. ConnectionInfo->MixedCaseFiles = (DialectFlags & DF_MIXEDCASE) != 0;
  760. ConnectionInfo->LongNames = (DialectFlags & DF_LONGNAME) != 0;
  761. ConnectionInfo->ExtendedNegotiateResponse = (DialectFlags & DF_EXTENDNEGOT) != 0;
  762. ConnectionInfo->LockAndRead = (DialectFlags & DF_LOCKREAD) != 0;
  763. ConnectionInfo->NtSecurity = (DialectFlags & DF_SECURITY) != 0;
  764. ConnectionInfo->SupportsEa = (DialectFlags & DF_SUPPORTEA) != 0;
  765. ConnectionInfo->NtNegotiateResponse = (DialectFlags & DF_NTNEGOTIATE) != 0;
  766. ConnectionInfo->CancelSupport = (DialectFlags & DF_CANCEL) != 0;
  767. ConnectionInfo->UnicodeStrings = (DialectFlags & DF_UNICODE) != 0;
  768. ConnectionInfo->LargeFiles = (DialectFlags & DF_LARGE_FILES) != 0;
  769. ConnectionInfo->NtSmbs = (DialectFlags & DF_NT_SMBS) != 0;
  770. ConnectionInfo->RpcRemoteAdmin = (DialectFlags & DF_RPC_REMOTE) != 0;
  771. ConnectionInfo->NtStatusCodes = (DialectFlags & DF_NT_STATUS) != 0;
  772. ConnectionInfo->LevelIIOplock = (DialectFlags & DF_OPLOCK_LVL2) != 0;
  773. ConnectionInfo->UtcTime = (DialectFlags & DF_TIME_IS_UTC) != 0;
  774. ConnectionInfo->UserSecurity = (pServerEntry->Server.SecurityMode==SECURITY_MODE_USER_LEVEL);
  775. ConnectionInfo->EncryptsPasswords = pServerEntry->Server.EncryptPasswords;
  776. return;
  777. }
  778. #ifdef _WIN64
  779. VOID
  780. MRxSmbGetConnectInfoLevel3FieldsThunked(
  781. IN OUT PLMR_CONNECTION_INFO_3_32 ConnectionInfo,
  782. IN PSMBCEDB_SERVER_ENTRY pServerEntry,
  783. BOOL fAgentCall
  784. )
  785. {
  786. ULONG DialectFlags = pServerEntry->Server.DialectFlags;
  787. NTSTATUS Status;
  788. RXCE_CONNECTION_INFO QueryConnectionInfo;
  789. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pServerEntry->pTransport;
  790. PSMBCE_VC pVc;
  791. PAGED_CODE();
  792. ConnectionInfo->Throughput = 0;
  793. ConnectionInfo->Delay = 0;
  794. ConnectionInfo->Reliable = FALSE;
  795. ConnectionInfo->ReadAhead = TRUE;
  796. ConnectionInfo->IsSpecialIpcConnection = FALSE;
  797. if ((pServerEntry->Header.State == SMBCEDB_ACTIVE) &&
  798. (pVcTransport != NULL) &&
  799. (!SmbCeIsServerInDisconnectedMode(pServerEntry)||fAgentCall)) {
  800. pVc = &pVcTransport->Vcs[0];
  801. Status = RxCeQueryInformation(
  802. &pVc->RxCeVc,
  803. RxCeConnectionEndpointInformation,
  804. &QueryConnectionInfo,
  805. sizeof(QueryConnectionInfo));
  806. if (NT_SUCCESS(Status)) {
  807. ConnectionInfo->Reliable = !QueryConnectionInfo.Unreliable;
  808. if (QueryConnectionInfo.Delay.QuadPart != 0) {
  809. if (QueryConnectionInfo.Delay.QuadPart == -1) {
  810. ConnectionInfo->Delay = 0;
  811. } else if (QueryConnectionInfo.Delay.HighPart != 0xffffffff) {
  812. ConnectionInfo->Delay = 0xffffffff;
  813. } else {
  814. ConnectionInfo->Delay = -1 * QueryConnectionInfo.Delay.LowPart;
  815. }
  816. } else {
  817. ConnectionInfo->Delay = 0;
  818. }
  819. if (QueryConnectionInfo.Throughput.QuadPart == -1) {
  820. ConnectionInfo->Throughput = 0;
  821. } else if (QueryConnectionInfo.Throughput.HighPart != 0) {
  822. ConnectionInfo->Throughput = 0xffffffff;
  823. } else {
  824. ConnectionInfo->Throughput = QueryConnectionInfo.Throughput.LowPart;
  825. }
  826. }
  827. }
  828. ConnectionInfo->TimeZoneBias = pServerEntry->Server.TimeZoneBias;
  829. ConnectionInfo->Core = (DialectFlags & DF_CORE) != 0;
  830. ConnectionInfo->MsNet103 = (DialectFlags & DF_OLDRAWIO) != 0;
  831. ConnectionInfo->Lanman10 = (DialectFlags & DF_LANMAN10) != 0;
  832. ConnectionInfo->WindowsForWorkgroups = (DialectFlags & DF_WFW) != 0;
  833. ConnectionInfo->Lanman20 = (DialectFlags & DF_LANMAN20) != 0;
  834. ConnectionInfo->Lanman21 = (DialectFlags & DF_LANMAN21) != 0;
  835. ConnectionInfo->WindowsNt = (DialectFlags & DF_NTPROTOCOL) != 0;
  836. ConnectionInfo->MixedCasePasswords = (DialectFlags & DF_MIXEDCASEPW) != 0;
  837. ConnectionInfo->MixedCaseFiles = (DialectFlags & DF_MIXEDCASE) != 0;
  838. ConnectionInfo->LongNames = (DialectFlags & DF_LONGNAME) != 0;
  839. ConnectionInfo->ExtendedNegotiateResponse = (DialectFlags & DF_EXTENDNEGOT) != 0;
  840. ConnectionInfo->LockAndRead = (DialectFlags & DF_LOCKREAD) != 0;
  841. ConnectionInfo->NtSecurity = (DialectFlags & DF_SECURITY) != 0;
  842. ConnectionInfo->SupportsEa = (DialectFlags & DF_SUPPORTEA) != 0;
  843. ConnectionInfo->NtNegotiateResponse = (DialectFlags & DF_NTNEGOTIATE) != 0;
  844. ConnectionInfo->CancelSupport = (DialectFlags & DF_CANCEL) != 0;
  845. ConnectionInfo->UnicodeStrings = (DialectFlags & DF_UNICODE) != 0;
  846. ConnectionInfo->LargeFiles = (DialectFlags & DF_LARGE_FILES) != 0;
  847. ConnectionInfo->NtSmbs = (DialectFlags & DF_NT_SMBS) != 0;
  848. ConnectionInfo->RpcRemoteAdmin = (DialectFlags & DF_RPC_REMOTE) != 0;
  849. ConnectionInfo->NtStatusCodes = (DialectFlags & DF_NT_STATUS) != 0;
  850. ConnectionInfo->LevelIIOplock = (DialectFlags & DF_OPLOCK_LVL2) != 0;
  851. ConnectionInfo->UtcTime = (DialectFlags & DF_TIME_IS_UTC) != 0;
  852. ConnectionInfo->UserSecurity = (pServerEntry->Server.SecurityMode==SECURITY_MODE_USER_LEVEL);
  853. ConnectionInfo->EncryptsPasswords = pServerEntry->Server.EncryptPasswords;
  854. return;
  855. }
  856. #endif
  857. NTSTATUS
  858. MRxSmbEnumerateConnections (
  859. IN PRX_CONTEXT RxContext,
  860. OUT PBOOLEAN PostToFsp
  861. )
  862. /*++
  863. Routine Description:
  864. This routine enumerates the connections on all minirdrs. we may have to do
  865. it by minirdr.
  866. Arguments:
  867. IN PRX_CONTEXT RxContext - Describes the Fsctl and Context
  868. Return Value:
  869. NTSTATUS
  870. --*/
  871. {
  872. NTSTATUS Status;
  873. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  874. BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  875. BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
  876. PLMR_REQUEST_PACKET InputBuffer = LowIoContext->ParamsFor.FsCtl.pInputBuffer;
  877. PUCHAR OriginalOutputBuffer = LowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  878. ULONG OutputBufferLength = LowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  879. ULONG InputBufferLength = LowIoContext->ParamsFor.FsCtl.InputBufferLength;
  880. PUCHAR OutputBuffer;
  881. ULONG BufferDisplacement;
  882. ULONG Level, ResumeHandle;
  883. PCHAR BufferStart;
  884. PCHAR BufferEnd;
  885. PCHAR PreviousBufferStart;
  886. PLIST_ENTRY ListEntry;
  887. LUID LogonId;
  888. BOOLEAN TableLockHeld = FALSE;
  889. ULONG TotalBytesNeeded = 0;
  890. PAGED_CODE();
  891. RxDbgTrace(+1, Dbg, ("MRxSmbEnumerateConnections [Start] -> %08lx\n", 0));
  892. OutputBuffer = RxMapUserBuffer( RxContext, RxContext->CurrentIrp );
  893. BufferDisplacement = (ULONG)(OutputBuffer - OriginalOutputBuffer);
  894. BufferStart = OutputBuffer;
  895. BufferEnd = OutputBuffer+OutputBufferLength;
  896. if (InFSD && RxContext->CurrentIrp->RequestorMode != KernelMode) {
  897. ASSERT(BufferDisplacement==0);
  898. try {
  899. ProbeForWrite(InputBuffer,InputBufferLength,sizeof(UCHAR));
  900. ProbeForWrite(OutputBuffer,OutputBufferLength,sizeof(UCHAR));
  901. } except(EXCEPTION_EXECUTE_HANDLER) {
  902. return STATUS_INVALID_PARAMETER;
  903. }
  904. }
  905. try {
  906. try {
  907. if (InputBufferLength < sizeof(LMR_REQUEST_PACKET)) {
  908. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  909. }
  910. if (InputBuffer->Version != REQUEST_PACKET_VERSION) {
  911. try_return(Status = STATUS_INVALID_PARAMETER);
  912. }
  913. Level = InputBuffer->Level;
  914. ResumeHandle = InputBuffer->Parameters.Get.ResumeHandle;
  915. LogonId = InputBuffer->LogonId;
  916. RxDbgTrace(0, Dbg, ("MRxSmbEnumerateConnections Level -> %08lx\n", Level));
  917. #ifdef _WIN64
  918. if (IoIs32bitProcess(RxContext->CurrentIrp)) {
  919. switch (Level) {
  920. case 0:
  921. if ( OutputBufferLength < sizeof(LMR_CONNECTION_INFO_0_32)) {
  922. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  923. }
  924. break;
  925. case 1:
  926. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_1_32)) {
  927. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  928. }
  929. break;
  930. case 2:
  931. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_2_32)) {
  932. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  933. }
  934. break;
  935. case 3:
  936. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_3_32)) {
  937. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  938. }
  939. break;
  940. default:
  941. try_return(Status = STATUS_INVALID_INFO_CLASS);
  942. }
  943. } else {
  944. switch (Level) {
  945. case 0:
  946. if ( OutputBufferLength < sizeof(LMR_CONNECTION_INFO_0)) {
  947. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  948. }
  949. break;
  950. case 1:
  951. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_1)) {
  952. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  953. }
  954. break;
  955. case 2:
  956. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_2)) {
  957. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  958. }
  959. break;
  960. case 3:
  961. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_3)) {
  962. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  963. }
  964. break;
  965. default:
  966. try_return(Status = STATUS_INVALID_INFO_CLASS);
  967. }
  968. }
  969. #else
  970. switch (Level) {
  971. case 0:
  972. if ( OutputBufferLength < sizeof(LMR_CONNECTION_INFO_0)) {
  973. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  974. }
  975. break;
  976. case 1:
  977. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_1)) {
  978. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  979. }
  980. break;
  981. case 2:
  982. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_2)) {
  983. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  984. }
  985. break;
  986. case 3:
  987. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_3)) {
  988. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  989. }
  990. break;
  991. default:
  992. try_return(Status = STATUS_INVALID_INFO_CLASS);
  993. }
  994. #endif
  995. InputBuffer->Parameters.Get.EntriesRead = 0;
  996. InputBuffer->Parameters.Get.TotalEntries = 0;
  997. RxAcquirePrefixTableLockExclusive( &RxNetNameTable, TRUE);
  998. TableLockHeld = TRUE;
  999. if (IsListEmpty( &RxNetNameTable.MemberQueue )) {
  1000. try_return(Status = RX_MAP_STATUS(SUCCESS));
  1001. }
  1002. //must do the list forwards!!!!!
  1003. ListEntry = RxNetNameTable.MemberQueue.Flink;
  1004. for (;ListEntry != &RxNetNameTable.MemberQueue;) {
  1005. PVOID Container;
  1006. PRX_PREFIX_ENTRY PrefixEntry;
  1007. PNET_ROOT NetRoot;
  1008. PV_NET_ROOT VNetRoot;
  1009. PUNICODE_STRING VNetRootName;
  1010. PrefixEntry = CONTAINING_RECORD( ListEntry, RX_PREFIX_ENTRY, MemberQLinks );
  1011. ListEntry = ListEntry->Flink;
  1012. ASSERT (NodeType(PrefixEntry) == RDBSS_NTC_PREFIX_ENTRY);
  1013. Container = PrefixEntry->ContainingRecord;
  1014. RxDbgTrace(0, Dbg, ("---> ListE PfxE Container Name %08lx %08lx %08lx %wZ\n",
  1015. ListEntry, PrefixEntry, Container, &PrefixEntry->Prefix));
  1016. switch (NodeType(Container)) {
  1017. case RDBSS_NTC_NETROOT :
  1018. continue;
  1019. case RDBSS_NTC_SRVCALL :
  1020. continue;
  1021. case RDBSS_NTC_V_NETROOT :
  1022. VNetRoot = (PV_NET_ROOT)Container;
  1023. NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
  1024. VNetRootName = &VNetRoot->PrefixEntry.Prefix;
  1025. if ((VNetRoot->SerialNumberForEnum >= ResumeHandle) &&
  1026. (VNetRootName->Buffer[1] != L';') &&
  1027. (VNetRoot->Condition == Condition_Good) &&
  1028. MRxSmbShowConnection(LogonId,VNetRoot) &&
  1029. VNetRoot->IsExplicitConnection) {
  1030. break;
  1031. } else {
  1032. continue;
  1033. }
  1034. default:
  1035. continue;
  1036. }
  1037. RxDbgTrace(0, Dbg, (" ImplicitConnectionFound!!!\n"));
  1038. InputBuffer->Parameters.Get.TotalEntries ++ ;
  1039. PreviousBufferStart = BufferStart;
  1040. #ifdef _WIN64
  1041. if (IoIs32bitProcess(RxContext->CurrentIrp)) {
  1042. if (MRxSmbPackConnectEntryThunked(RxContext,Level,
  1043. &BufferStart,
  1044. &BufferEnd,
  1045. VNetRoot,
  1046. BufferDisplacement,
  1047. &TotalBytesNeeded)) {
  1048. InputBuffer->Parameters.Get.EntriesRead ++ ;
  1049. RxDbgTrace(0, Dbg, (" Processed %wZ\n",
  1050. &((PLMR_CONNECTION_INFO_0)PreviousBufferStart)->UNCName
  1051. ));
  1052. } else {
  1053. break;
  1054. }
  1055. } else {
  1056. if (MRxSmbPackConnectEntry(RxContext,Level,
  1057. &BufferStart,
  1058. &BufferEnd,
  1059. VNetRoot,
  1060. BufferDisplacement,
  1061. &TotalBytesNeeded)) {
  1062. InputBuffer->Parameters.Get.EntriesRead ++ ;
  1063. RxDbgTrace(0, Dbg, (" Processed %wZ\n",
  1064. &((PLMR_CONNECTION_INFO_0)PreviousBufferStart)->UNCName
  1065. ));
  1066. } else {
  1067. break;
  1068. }
  1069. }
  1070. #else
  1071. if (MRxSmbPackConnectEntry(RxContext,Level,
  1072. &BufferStart,
  1073. &BufferEnd,
  1074. VNetRoot,
  1075. BufferDisplacement,
  1076. &TotalBytesNeeded)) {
  1077. InputBuffer->Parameters.Get.EntriesRead ++ ;
  1078. RxDbgTrace(0, Dbg, (" Processed %wZ\n",
  1079. &((PLMR_CONNECTION_INFO_0)PreviousBufferStart)->UNCName
  1080. ));
  1081. } else {
  1082. break;
  1083. }
  1084. #endif
  1085. }
  1086. InputBuffer->Parameters.Get.TotalBytesNeeded = TotalBytesNeeded;
  1087. RxContext->InformationToReturn = sizeof(LMR_REQUEST_PACKET);
  1088. try_return(Status = RX_MAP_STATUS(SUCCESS));
  1089. } except(EXCEPTION_EXECUTE_HANDLER) {
  1090. return STATUS_INVALID_PARAMETER;
  1091. }
  1092. try_exit:NOTHING;
  1093. } finally {
  1094. if (TableLockHeld) {
  1095. RxReleasePrefixTableLock( &RxNetNameTable );
  1096. }
  1097. RxDbgTraceUnIndent(-1,Dbg);
  1098. }
  1099. return Status;
  1100. }
  1101. NTSTATUS
  1102. MRxSmbGetConnectionInfo (
  1103. IN PRX_CONTEXT RxContext,
  1104. OUT PBOOLEAN PostToFsp
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. This routine gets the connection info for a single vnetroot.
  1109. There is some happiness here about the output buffer. What happens is that we
  1110. pick up the output buffer in the usual way. However, there are all sorts of
  1111. pointers in the return structure and these pointers must obviously be in terms
  1112. of the original process. so, if we post then we have to apply a fixup!
  1113. Arguments:
  1114. IN PRX_CONTEXT RxContext - Describes the Fsctl and Context
  1115. Return Value:
  1116. STATUS_SUCCESS if successful
  1117. --*/
  1118. {
  1119. NTSTATUS Status;
  1120. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  1121. RxCaptureFobx;
  1122. BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  1123. BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
  1124. PLMR_REQUEST_PACKET InputBuffer = LowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1125. PUCHAR OriginalOutputBuffer = LowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  1126. ULONG OutputBufferLength = LowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  1127. ULONG InputBufferLength = LowIoContext->ParamsFor.FsCtl.InputBufferLength;
  1128. PUCHAR OutputBuffer;
  1129. ULONG BufferDisplacement;
  1130. ULONG Level;
  1131. PCHAR BufferStart;
  1132. PCHAR OriginalBufferStart;
  1133. PCHAR BufferEnd;
  1134. BOOLEAN TableLockHeld = FALSE;
  1135. PNET_ROOT NetRoot;
  1136. PV_NET_ROOT VNetRoot;
  1137. ULONG TotalBytesNeeded = 0;
  1138. PAGED_CODE();
  1139. RxDbgTrace(+1, Dbg, ("MRxSmbGetConnectionInfo [Start] -> %08lx\n", 0));
  1140. OutputBuffer = RxMapUserBuffer( RxContext, RxContext->CurrentIrp );
  1141. BufferDisplacement = (ULONG)(OutputBuffer - OriginalOutputBuffer);
  1142. BufferStart = OutputBuffer;
  1143. OriginalBufferStart = BufferStart;
  1144. BufferEnd = OutputBuffer+OutputBufferLength;
  1145. if (InFSD && RxContext->CurrentIrp->RequestorMode != KernelMode) {
  1146. ASSERT(BufferDisplacement==0);
  1147. try {
  1148. ProbeForWrite(InputBuffer,InputBufferLength,sizeof(UCHAR));
  1149. ProbeForWrite(OutputBuffer,OutputBufferLength,sizeof(UCHAR));
  1150. } except(EXCEPTION_EXECUTE_HANDLER) {
  1151. return STATUS_INVALID_PARAMETER;
  1152. }
  1153. }
  1154. try {
  1155. try {
  1156. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext;
  1157. ASSERT (NodeType(capFobx)==RDBSS_NTC_V_NETROOT);
  1158. VNetRoot = (PV_NET_ROOT)capFobx;
  1159. NetRoot = (PNET_ROOT)(VNetRoot->NetRoot);
  1160. if (NetRoot == NULL) {
  1161. try_return(Status = STATUS_ALREADY_DISCONNECTED);
  1162. }
  1163. if (InputBufferLength < sizeof(LMR_REQUEST_PACKET)) {
  1164. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1165. }
  1166. if (InputBuffer->Version != REQUEST_PACKET_VERSION) {
  1167. try_return(Status = STATUS_INVALID_PARAMETER);
  1168. }
  1169. // if the level is asking for the session key, determine whether we are able
  1170. // to give it out yet.
  1171. pVNetRootContext = SmbCeGetAssociatedVNetRootContext((PMRX_V_NET_ROOT)VNetRoot);
  1172. if( InputBuffer->Level > 2 &&
  1173. pVNetRootContext->pSessionEntry->Session.SessionKeyState != SmbSessionKeyAvailible )
  1174. {
  1175. try_return(Status = STATUS_ACCESS_DENIED);
  1176. }
  1177. Level = InputBuffer->Level;
  1178. RxDbgTrace(0, Dbg, ("MRxSmbGetConnectionInfo Level -> %08lx\n", Level));
  1179. #ifdef _WIN64
  1180. if (IoIs32bitProcess(RxContext->CurrentIrp)) {
  1181. switch (Level) {
  1182. case 0:
  1183. if ( OutputBufferLength < sizeof(LMR_CONNECTION_INFO_0_32)) {
  1184. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1185. }
  1186. break;
  1187. case 1:
  1188. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_1_32)) {
  1189. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1190. }
  1191. break;
  1192. case 2:
  1193. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_2_32)) {
  1194. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1195. }
  1196. break;
  1197. case 3:
  1198. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_3_32)) {
  1199. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1200. }
  1201. break;
  1202. default:
  1203. try_return(Status = STATUS_INVALID_INFO_CLASS);
  1204. }
  1205. } else {
  1206. switch (Level) {
  1207. case 0:
  1208. if ( OutputBufferLength < sizeof(LMR_CONNECTION_INFO_0)) {
  1209. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1210. }
  1211. break;
  1212. case 1:
  1213. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_1)) {
  1214. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1215. }
  1216. break;
  1217. case 2:
  1218. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_2)) {
  1219. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1220. }
  1221. break;
  1222. case 3:
  1223. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_3)) {
  1224. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1225. }
  1226. break;
  1227. default:
  1228. try_return(Status = STATUS_INVALID_INFO_CLASS);
  1229. }
  1230. }
  1231. #else
  1232. switch (Level) {
  1233. case 0:
  1234. if ( OutputBufferLength < sizeof(LMR_CONNECTION_INFO_0)) {
  1235. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1236. }
  1237. break;
  1238. case 1:
  1239. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_1)) {
  1240. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1241. }
  1242. break;
  1243. case 2:
  1244. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_2)) {
  1245. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1246. }
  1247. break;
  1248. case 3:
  1249. if (OutputBufferLength < sizeof(LMR_CONNECTION_INFO_3)) {
  1250. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1251. }
  1252. break;
  1253. default:
  1254. try_return(Status = STATUS_INVALID_INFO_CLASS);
  1255. }
  1256. #endif
  1257. InputBuffer->Parameters.Get.TotalEntries = 1;
  1258. RxAcquirePrefixTableLockExclusive( &RxNetNameTable, TRUE);
  1259. TableLockHeld = TRUE;
  1260. #ifdef _WIN64
  1261. if (IoIs32bitProcess(RxContext->CurrentIrp)) {
  1262. if (MRxSmbPackConnectEntryThunked(RxContext,Level,
  1263. &BufferStart,
  1264. &BufferEnd,
  1265. VNetRoot,
  1266. BufferDisplacement,
  1267. &TotalBytesNeeded)) {
  1268. InputBuffer->Parameters.Get.EntriesRead = 1;
  1269. RxDbgTrace(0, Dbg, (" Processed %wZ\n",
  1270. &((PLMR_CONNECTION_INFO_0)OriginalBufferStart)->UNCName
  1271. ));
  1272. }
  1273. } else {
  1274. if (MRxSmbPackConnectEntry(RxContext,Level,
  1275. &BufferStart,
  1276. &BufferEnd,
  1277. VNetRoot,
  1278. BufferDisplacement,
  1279. &TotalBytesNeeded)) {
  1280. InputBuffer->Parameters.Get.EntriesRead = 1;
  1281. RxDbgTrace(0, Dbg, (" Processed %wZ\n",
  1282. &((PLMR_CONNECTION_INFO_0)OriginalBufferStart)->UNCName
  1283. ));
  1284. }
  1285. }
  1286. #else
  1287. if (MRxSmbPackConnectEntry(RxContext,Level,
  1288. &BufferStart,
  1289. &BufferEnd,
  1290. VNetRoot,
  1291. BufferDisplacement,
  1292. &TotalBytesNeeded)) {
  1293. InputBuffer->Parameters.Get.EntriesRead = 1;
  1294. RxDbgTrace(0, Dbg, (" Processed %wZ\n",
  1295. &((PLMR_CONNECTION_INFO_0)OriginalBufferStart)->UNCName
  1296. ));
  1297. }
  1298. #endif
  1299. InputBuffer->Parameters.Get.TotalBytesNeeded = TotalBytesNeeded;
  1300. RxContext->InformationToReturn = InputBuffer->Parameters.Get.TotalBytesNeeded;
  1301. try_return(Status = RX_MAP_STATUS(SUCCESS));
  1302. } except(EXCEPTION_EXECUTE_HANDLER) {
  1303. return STATUS_INVALID_PARAMETER;
  1304. }
  1305. try_exit:NOTHING;
  1306. } finally {
  1307. if (TableLockHeld) {
  1308. RxReleasePrefixTableLock( &RxNetNameTable );
  1309. }
  1310. RxDbgTraceUnIndent(-1,Dbg);
  1311. }
  1312. return Status;
  1313. }
  1314. NTSTATUS
  1315. MRxSmbDeleteConnection (
  1316. IN PRX_CONTEXT RxContext,
  1317. OUT PBOOLEAN PostToFsp
  1318. )
  1319. /*++
  1320. Routine Description:
  1321. This routine deletes a single vnetroot. joejoe
  1322. Arguments:
  1323. IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
  1324. Return Value:
  1325. RXSTATUS
  1326. --*/
  1327. {
  1328. NTSTATUS Status;
  1329. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  1330. RxCaptureFobx;
  1331. BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  1332. BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
  1333. PLMR_REQUEST_PACKET InputBuffer = LowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1334. ULONG InputBufferLength = LowIoContext->ParamsFor.FsCtl.InputBufferLength;
  1335. ULONG Level;
  1336. //PLIST_ENTRY ListEntry;
  1337. BOOLEAN TableLockHeld = FALSE;
  1338. PMRX_NET_ROOT NetRoot = NULL;
  1339. PMRX_V_NET_ROOT VNetRoot = NULL;
  1340. PSMBCE_V_NET_ROOT_CONTEXT VNetRootContext = NULL;
  1341. PAGED_CODE();
  1342. RxDbgTrace(+1, Dbg, ("MRxSmbDeleteConnection Fobx %08lx\n", capFobx));
  1343. ASSERT( (FSCTL_LMR_DELETE_CONNECTION&3)==METHOD_BUFFERED );
  1344. //no probing for buffered!
  1345. if (!Wait) {
  1346. //just post right now!
  1347. *PostToFsp = TRUE;
  1348. return(RX_MAP_STATUS(PENDING));
  1349. }
  1350. try {
  1351. if (NodeType(capFobx)==RDBSS_NTC_V_NETROOT) {
  1352. VNetRoot = (PMRX_V_NET_ROOT)capFobx;
  1353. VNetRootContext = (PSMBCE_V_NET_ROOT_CONTEXT)VNetRoot->Context;
  1354. NetRoot = (PMRX_NET_ROOT)VNetRoot->pNetRoot;
  1355. } else {
  1356. ASSERT(FALSE);
  1357. try_return(Status = STATUS_INVALID_DEVICE_REQUEST);
  1358. NetRoot = (PMRX_NET_ROOT)capFobx;
  1359. VNetRoot = NULL;
  1360. }
  1361. if (InputBufferLength < sizeof(LMR_REQUEST_PACKET)) {
  1362. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1363. }
  1364. if (InputBuffer->Version != REQUEST_PACKET_VERSION) {
  1365. try_return(Status = STATUS_INVALID_PARAMETER);
  1366. }
  1367. Level = InputBuffer->Level;
  1368. RxDbgTrace(0, Dbg, ("MRxSmbDeleteConnection Level(ofForce) -> %08lx\n", Level));
  1369. if (Level <= USE_LOTS_OF_FORCE) {
  1370. if (Level == USE_LOTS_OF_FORCE) {
  1371. //SmbCeFinalizeAllExchangesForNetRoot(VNetRoot->pNetRoot);
  1372. }
  1373. if (VNetRootContext != NULL && Level == USE_LOTS_OF_FORCE) {
  1374. // Prevent any new connection from reusing the session if this is the last connection on
  1375. // this session right now
  1376. SmbCeDecrementNumberOfActiveVNetRootOnSession(VNetRootContext);
  1377. // Recover the count which will be taken away when VNetRoot is finalized
  1378. InterlockedIncrement(&VNetRootContext->pSessionEntry->Session.NumberOfActiveVNetRoot);
  1379. }
  1380. // The boolean ForceFilesClosed is now a tristate. If the state is 0xff then
  1381. // we take off the extra reference on vnetroot made during xxx_CONNECT
  1382. Status = RxFinalizeConnection(
  1383. (PNET_ROOT)NetRoot,
  1384. (PV_NET_ROOT)VNetRoot,
  1385. (Level==USE_LOTS_OF_FORCE)?TRUE:
  1386. ((Level==USE_NOFORCE)?FALSE:0xff));
  1387. } else {
  1388. Status = STATUS_INVALID_PARAMETER;
  1389. }
  1390. try_return(Status);
  1391. try_exit:NOTHING;
  1392. } finally {
  1393. if (TableLockHeld) {
  1394. RxReleasePrefixTableLock( &RxNetNameTable );
  1395. }
  1396. RxDbgTraceUnIndent(-1,Dbg);
  1397. }
  1398. return Status;
  1399. }
  1400. NTSTATUS
  1401. MRxEnumerateTransports(
  1402. IN PRX_CONTEXT RxContext,
  1403. OUT PBOOLEAN pPostToFsp)
  1404. /*++
  1405. Routine Description:
  1406. This routine invokes the underlying connection engine method to bind to a transport
  1407. or unbind from it in the context of FSP.
  1408. Arguments:
  1409. RxContext - the context
  1410. pPostToFsp - set to TRUE if the routine cannot be completed in the context of the FSD.
  1411. Return Value:
  1412. returns RxStatus(PENDING) if invoked in FSD.
  1413. returns the status value from the connection engine if invoked in FSP.
  1414. --*/
  1415. {
  1416. NTSTATUS Status;
  1417. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  1418. RxCaptureFobx;
  1419. BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  1420. BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
  1421. PLMR_REQUEST_PACKET pLmrRequestBuffer = LowIoContext->ParamsFor.FsCtl.pInputBuffer;
  1422. PUCHAR pTransportEnumerationBuffer = LowIoContext->ParamsFor.FsCtl.pOutputBuffer;
  1423. ULONG EnumerationBufferLength = LowIoContext->ParamsFor.FsCtl.OutputBufferLength;
  1424. ULONG LmrRequestBufferLength = LowIoContext->ParamsFor.FsCtl.InputBufferLength;
  1425. PAGED_CODE();
  1426. RxDbgTrace(+1, Dbg, ("RxEnumerateTransports [Start] ->\n"));
  1427. //
  1428. // This routine is invoked as part of ioinit on a remote boot client.
  1429. // In that case, previous mode is kernel and the buffers are in kernel
  1430. // space, so we can't probe the buffers.
  1431. //
  1432. if (RxContext->CurrentIrp->RequestorMode != KernelMode) {
  1433. try {
  1434. ProbeForWrite(pLmrRequestBuffer,LmrRequestBufferLength,sizeof(UCHAR));
  1435. ProbeForWrite(pTransportEnumerationBuffer,EnumerationBufferLength,sizeof(UCHAR));
  1436. } except(EXCEPTION_EXECUTE_HANDLER) {
  1437. return STATUS_ACCESS_VIOLATION;
  1438. }
  1439. }
  1440. try {
  1441. try {
  1442. if (LmrRequestBufferLength < sizeof(LMR_REQUEST_PACKET)) {
  1443. try_return(Status = STATUS_BUFFER_TOO_SMALL);
  1444. }
  1445. if (pLmrRequestBuffer->Version != REQUEST_PACKET_VERSION) {
  1446. try_return(Status = STATUS_INVALID_PARAMETER);
  1447. }
  1448. Status = MRxEnumerateTransportBindings(
  1449. pLmrRequestBuffer,
  1450. LmrRequestBufferLength,
  1451. pTransportEnumerationBuffer,
  1452. EnumerationBufferLength);
  1453. RxContext->InformationToReturn = sizeof(LMR_REQUEST_PACKET);
  1454. } except(EXCEPTION_EXECUTE_HANDLER) {
  1455. return STATUS_ACCESS_VIOLATION;
  1456. }
  1457. try_exit:NOTHING;
  1458. } finally {
  1459. RxDbgTraceUnIndent(-1,Dbg);
  1460. }
  1461. return Status;
  1462. }
  1463. #define ADAPTER_STATUS_LENGTH_IN_BYTES (26)
  1464. UNICODE_STRING NullAdapterStatus = {
  1465. ADAPTER_STATUS_LENGTH_IN_BYTES,
  1466. ADAPTER_STATUS_LENGTH_IN_BYTES,
  1467. L"000000000000\0"};
  1468. #define HexDigit(a) ((CHAR)( (a) > 9 ? ((a) + 'A' - 0xA) : ((a) + '0') ))
  1469. NTSTATUS
  1470. MRxEnumerateTransportBindings(
  1471. IN PLMR_REQUEST_PACKET pLmrRequestPacket,
  1472. IN ULONG LmrRequestPacketLength,
  1473. OUT PVOID pBindingBuffer,
  1474. IN OUT ULONG BindingBufferLength)
  1475. /*++
  1476. Routine Description:
  1477. This routine enables the specified transport.
  1478. Arguments:
  1479. pLmrRequestPacket - the LM Request Packet for enumerating bindings to transports.
  1480. LmrRequestPacketLength - length of the LM request.
  1481. pBindingBuffer - the buffer for returning transport bindings
  1482. BindingBufferLength -- length of the buffer in which bindings are returned.
  1483. Return Value:
  1484. STATUS_SUCCESS - if the call was successfull.
  1485. Notes:
  1486. The workstation service and other clients of LMR_FSCTL's expect the variable length
  1487. data to be packed in a specific way, i.e., the variable length data is copied from
  1488. the end while the fixed length data is copied from the left. Any changes to the format
  1489. in which the data is packed should be accompanied by the corresponding changes for
  1490. unpacking in these services.
  1491. --*/
  1492. {
  1493. NTSTATUS ReturnStatus = STATUS_SUCCESS;
  1494. NTSTATUS Status;
  1495. PSMBCE_TRANSPORT pTransport;
  1496. ULONG TransportsPreviouslyReturned;
  1497. PVOID pVariableLengthInfo;
  1498. ULONG VariableLengthInfoOffset;
  1499. PSMBCE_TRANSPORT_ARRAY pTransportArray;
  1500. PAGED_CODE();
  1501. try {
  1502. // Ensure that the buffer can hold atleast one entry
  1503. if (BindingBufferLength < sizeof(WKSTA_TRANSPORT_INFO_0)) {
  1504. try_return(ReturnStatus = STATUS_BUFFER_TOO_SMALL);
  1505. }
  1506. VariableLengthInfoOffset = BindingBufferLength;
  1507. TransportsPreviouslyReturned = pLmrRequestPacket->Parameters.Get.ResumeHandle;
  1508. pLmrRequestPacket->Parameters.Get.EntriesRead = 0;
  1509. // Skip the transports that were previously returned
  1510. pTransportArray = SmbCeReferenceTransportArray();
  1511. if (pTransportArray == NULL || pTransportArray->Count == 0) {
  1512. if (pTransportArray != NULL) {
  1513. SmbCeDereferenceTransportArray(pTransportArray);
  1514. }
  1515. RxDbgTrace(0, Dbg, ("MRxEnumerateTransportBindings : Transport not available.\n"));
  1516. try_return(ReturnStatus = STATUS_NETWORK_UNREACHABLE);
  1517. }
  1518. if (TransportsPreviouslyReturned < pTransportArray->Count) {
  1519. // The subsequent entries have not been returned. Obtain the information
  1520. // for them.
  1521. WKSTA_TRANSPORT_INFO_0 UNALIGNED *pTransportInfo = (WKSTA_TRANSPORT_INFO_0 UNALIGNED *)pBindingBuffer;
  1522. LONG RemainingLength = (LONG)BindingBufferLength;
  1523. PCHAR pBufferEnd = (PCHAR)pBindingBuffer + BindingBufferLength;
  1524. PCHAR pBufferStart = (PCHAR)pBindingBuffer;
  1525. ULONG Length;
  1526. ULONG TransportsPacked = 0;
  1527. ULONG CurrentTransport;
  1528. ULONG LengthRequired = 0;
  1529. CurrentTransport = TransportsPreviouslyReturned;
  1530. while(CurrentTransport < pTransportArray->Count) {
  1531. RXCE_TRANSPORT_INFORMATION TransportInformation;
  1532. pTransport = pTransportArray->SmbCeTransports[CurrentTransport++];
  1533. Status = RxCeQueryTransportInformation(
  1534. &pTransport->RxCeTransport,
  1535. &TransportInformation);
  1536. if (Status == STATUS_SUCCESS) {
  1537. ULONG BufferSize;
  1538. if (pTransport->RxCeTransport.Name.Length > UNLEN * sizeof(WCHAR)) {
  1539. Status = STATUS_BUFFER_OVERFLOW;
  1540. }
  1541. BufferSize = sizeof(WKSTA_TRANSPORT_INFO_0) +
  1542. ADAPTER_STATUS_LENGTH_IN_BYTES +
  1543. (pTransport->RxCeTransport.Name.Length + sizeof(WCHAR));
  1544. RemainingLength -= BufferSize;
  1545. LengthRequired += BufferSize;
  1546. if (Status == STATUS_SUCCESS && RemainingLength >= 0) {
  1547. PCHAR pName;
  1548. PWCHAR pAdapter;
  1549. ADAPTER_STATUS AdapterStatus;
  1550. // Copy the values for the current binding into the output buffer.
  1551. pTransportInfo->wkti0_quality_of_service =
  1552. TransportInformation.QualityOfService;
  1553. pTransportInfo->wkti0_wan_ish =
  1554. TransportInformation.ServiceFlags & TDI_SERVICE_ROUTE_DIRECTED;
  1555. pTransportInfo->wkti0_number_of_vcs = TransportInformation.ConnectionCount;
  1556. VariableLengthInfoOffset -= (pTransport->RxCeTransport.Name.Length + sizeof(WCHAR));
  1557. pName = ((PCHAR)pBindingBuffer + VariableLengthInfoOffset);
  1558. pTransportInfo->wkti0_transport_name = (LPWSTR)pName;
  1559. // Copy the variable length data, i.e. the transport name and in the case of
  1560. // NETBIOS provides the adapter address
  1561. RtlCopyMemory(
  1562. pName,
  1563. pTransport->RxCeTransport.Name.Buffer,
  1564. pTransport->RxCeTransport.Name.Length);
  1565. pName += pTransport->RxCeTransport.Name.Length;
  1566. *((PWCHAR)pName) = L'\0';
  1567. VariableLengthInfoOffset -= ADAPTER_STATUS_LENGTH_IN_BYTES;
  1568. pAdapter = (PWCHAR)((PCHAR)pBindingBuffer + VariableLengthInfoOffset);
  1569. pTransportInfo->wkti0_transport_address = pAdapter;
  1570. Status = RxCeQueryAdapterStatus(
  1571. &pTransport->RxCeTransport,
  1572. &AdapterStatus);
  1573. if (NT_SUCCESS(Status) ||
  1574. (Status == STATUS_BUFFER_OVERFLOW)) {
  1575. ULONG i;
  1576. for (i = 0; i < 6; i++) {
  1577. *pAdapter++ = HexDigit((AdapterStatus.adapter_address[i] >> 4) & 0x0F);
  1578. *pAdapter++ = HexDigit(AdapterStatus.adapter_address[i] & 0x0F);
  1579. }
  1580. *pAdapter = L'\0';
  1581. } else {
  1582. RtlCopyMemory(
  1583. pAdapter,
  1584. NullAdapterStatus.Buffer,
  1585. ADAPTER_STATUS_LENGTH_IN_BYTES);
  1586. }
  1587. // Increment the number of transports that have been returned.
  1588. pLmrRequestPacket->Parameters.Get.ResumeHandle++;
  1589. pLmrRequestPacket->Parameters.Get.EntriesRead++;
  1590. pTransportInfo++;
  1591. } else {
  1592. pTransportInfo->wkti0_transport_name = NULL;
  1593. pTransportInfo->wkti0_transport_address = NULL;
  1594. }
  1595. }
  1596. }
  1597. if (RemainingLength < 0) {
  1598. ReturnStatus = STATUS_MORE_ENTRIES;
  1599. pLmrRequestPacket->Parameters.Get.TotalBytesNeeded = LengthRequired;
  1600. }
  1601. } else {
  1602. ReturnStatus = STATUS_NO_MORE_FILES;
  1603. }
  1604. SmbCeDereferenceTransportArray(pTransportArray);
  1605. try_exit:NOTHING;
  1606. } finally {
  1607. RxDbgTraceUnIndent(-1,Dbg);
  1608. }
  1609. return ReturnStatus;
  1610. }
  1611. BOOLEAN
  1612. MRxSmbShowConnection(
  1613. IN LUID LogonId,
  1614. IN PV_NET_ROOT VNetRoot
  1615. )
  1616. /*++
  1617. Routine Description:
  1618. Returns whether the given V_NET_ROOT should be returned
  1619. from an LMR_ENUMERATE_CONNECTIONS call.
  1620. Arguments:
  1621. IN LUID LogonId - LogonId of caller asking for enumeration of connections
  1622. IN PVNET_ROOT VNetRoot - Supplies the NetRoot to enumerate.
  1623. Return Value:
  1624. BOOLEAN - True if the entry should be returned to the caller
  1625. --*/
  1626. {
  1627. PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = SmbCeGetAssociatedVNetRootContext((PMRX_V_NET_ROOT)VNetRoot);
  1628. // If no Context, not session specific
  1629. if( pVNetRootContext == NULL ) {
  1630. return TRUE;
  1631. }
  1632. if( RtlEqualLuid( &LogonId, &pVNetRootContext->pSessionEntry->Session.LogonId ) ) {
  1633. return TRUE;
  1634. }
  1635. else {
  1636. return FALSE;
  1637. }
  1638. }