Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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