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.

562 lines
14 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. svcconn.c
  5. Abstract:
  6. This module contains routines for supporting the connection APIs in
  7. the server service, SrvNetConnectionEnum.
  8. Author:
  9. David Treadwell (davidtr) 23-Feb-1991
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include "svcconn.tmh"
  14. #pragma hdrstop
  15. #define BugCheckFileId SRV_FILE_SVCCONN
  16. //
  17. // Forward declarations.
  18. //
  19. VOID
  20. FillConnectionInfoBuffer (
  21. IN PSERVER_REQUEST_PACKET Srp,
  22. IN PVOID Block,
  23. IN OUT PVOID *FixedStructurePointer,
  24. IN OUT LPWSTR *EndOfVariableData
  25. );
  26. BOOLEAN
  27. FilterConnections (
  28. IN PSERVER_REQUEST_PACKET Srp,
  29. IN PVOID Block
  30. );
  31. ULONG
  32. SizeConnections (
  33. IN PSERVER_REQUEST_PACKET Srp,
  34. IN PVOID Block
  35. );
  36. #ifdef ALLOC_PRAGMA
  37. #pragma alloc_text( PAGE, SrvNetConnectionEnum )
  38. #pragma alloc_text( PAGE, FillConnectionInfoBuffer )
  39. #pragma alloc_text( PAGE, FilterConnections )
  40. #pragma alloc_text( PAGE, SizeConnections )
  41. #endif
  42. //
  43. // Macros to determine the size a share would take up at one of the
  44. // levels of share information.
  45. //
  46. #define TOTAL_SIZE_OF_CONNECTION(treeConnect,level,user,netname) \
  47. ( (level) == 0 ? sizeof(CONNECTION_INFO_0) : \
  48. sizeof(CONNECTION_INFO_1) + \
  49. SrvLengthOfStringInApiBuffer((user)) + \
  50. SrvLengthOfStringInApiBuffer((netname)) )
  51. #define FIXED_SIZE_OF_CONNECTION(level) \
  52. ( (level) == 0 ? sizeof(CONNECTION_INFO_0) : \
  53. sizeof(CONNECTION_INFO_1) )
  54. NTSTATUS
  55. SrvNetConnectionEnum (
  56. IN PSERVER_REQUEST_PACKET Srp,
  57. IN PVOID Buffer,
  58. IN ULONG BufferLength
  59. )
  60. /*++
  61. Routine Description:
  62. This routine processes the NetConnectionEnum API in the server FSD.
  63. Arguments:
  64. Srp - a pointer to the server request packet that contains all
  65. the information necessary to satisfy the request. This includes:
  66. INPUT:
  67. Name1 - qualifier for determining the basis for the search. It
  68. is either a computer name, in which case information about
  69. tree connects from the specified client is returned, or
  70. a share name, in which case information about tree connects
  71. to the specified share is returned.
  72. Level - level of information to return, 0 or 1.
  73. OUTPUT:
  74. Parameters.Get.EntriesRead - the number of entries that fit in
  75. the output buffer.
  76. Parameters.Get.TotalEntries - the total number of entries that
  77. would be returned with a large enough buffer.
  78. Parameters.Get.TotalBytesNeeded - the buffer size that would be
  79. required to hold all the entries.
  80. Buffer - a pointer to the buffer for results.
  81. BufferLength - the length of this buffer.
  82. Return Value:
  83. NTSTATUS - result of operation to return to the server service.
  84. --*/
  85. {
  86. PAGED_CODE( );
  87. return SrvEnumApiHandler(
  88. Srp,
  89. Buffer,
  90. BufferLength,
  91. &SrvTreeConnectList,
  92. FilterConnections,
  93. SizeConnections,
  94. FillConnectionInfoBuffer
  95. );
  96. } // SrvNetConnectionEnum
  97. STATIC
  98. VOID
  99. FillConnectionInfoBuffer (
  100. IN PSERVER_REQUEST_PACKET Srp,
  101. IN PVOID Block,
  102. IN OUT PVOID *FixedStructure,
  103. IN LPWSTR *EndOfVariableData
  104. )
  105. /*++
  106. Routine Description:
  107. This routine puts a single fixed session structure and, if it fits,
  108. associated variable data, into a buffer. Fixed data goes at the
  109. beginning of the buffer, variable data at the end.
  110. *** This routine must be called with Connection->Lock held!
  111. Arguments:
  112. Level - the level of information to copy from the connection.
  113. Connection - the tree connect from which to get information.
  114. FixedStructure - where the ine buffer to place the fixed structure.
  115. This pointer is updated to point to the next available
  116. position for a fixed structure.
  117. EndOfVariableData - the last position on the buffer that variable
  118. data for this structure can occupy. The actual variable data
  119. is written before this position as long as it won't overwrite
  120. fixed structures. It is would overwrite fixed structures, it
  121. is not written.
  122. Return Value:
  123. None.
  124. --*/
  125. {
  126. PTREE_CONNECT treeConnect = Block;
  127. PSESSION session;
  128. PCONNECTION_INFO_1 coni1;
  129. LARGE_INTEGER currentTime;
  130. ULONG currentSecondsSince1980;
  131. ULONG startTimeInSecondsSince1980;
  132. ULONG secondsAlive;
  133. PAGED_CODE();
  134. //
  135. // Get the current time and use this to determine how long the
  136. // tree connection has been alive.
  137. //
  138. KeQuerySystemTime( &currentTime );
  139. RtlTimeToSecondsSince1980(
  140. &currentTime,
  141. &currentSecondsSince1980
  142. );
  143. RtlTimeToSecondsSince1980(
  144. &treeConnect->StartTime,
  145. &startTimeInSecondsSince1980
  146. );
  147. secondsAlive = currentSecondsSince1980 - startTimeInSecondsSince1980;
  148. //
  149. // Set up the fixed structure pointer and find out where the fixed
  150. // structure ends.
  151. //
  152. coni1 = *FixedStructure;
  153. *FixedStructure = (PCHAR)*FixedStructure +
  154. FIXED_SIZE_OF_CONNECTION( Srp->Level );
  155. ASSERT( (ULONG_PTR)*EndOfVariableData >= (ULONG_PTR)*FixedStructure );
  156. //
  157. // Case on the level to fill in the fixed structure appropriately.
  158. // We fill in actual pointers in the output structure. This is
  159. // possible because we are in the server FSD, hence the server
  160. // service's process and address space.
  161. //
  162. // *** This routine assumes that the fixed structure will fit in the
  163. // buffer!
  164. //
  165. // *** Using the switch statement in this fashion relies on the fact
  166. // that the first fields on the different session structures are
  167. // identical.
  168. //
  169. switch( Srp->Level ) {
  170. case 1:
  171. //
  172. // Convert the server's internal representation of share types
  173. // to the expected format.
  174. //
  175. switch ( treeConnect->Share->ShareType ) {
  176. case ShareTypeDisk:
  177. coni1->coni1_type = STYPE_DISKTREE;
  178. break;
  179. case ShareTypePrint:
  180. coni1->coni1_type = STYPE_PRINTQ;
  181. break;
  182. #if SRV_COMM_DEVICES
  183. case ShareTypeComm:
  184. coni1->coni1_type = STYPE_DEVICE;
  185. break;
  186. #endif
  187. case ShareTypePipe:
  188. coni1->coni1_type = STYPE_IPC;
  189. break;
  190. default:
  191. //
  192. // This should never happen. It means that somebody
  193. // stomped on the share block.
  194. //
  195. INTERNAL_ERROR(
  196. ERROR_LEVEL_UNEXPECTED,
  197. "FillConnectionInfoBuffer: invalid share type in share: %ld",
  198. treeConnect->Share->ShareType,
  199. NULL
  200. );
  201. SrvLogInvalidSmb( NULL );
  202. return;
  203. }
  204. //
  205. // Set up the count of opens done on this tree connect. Do not include
  206. // cached opens, as they are transparent to users and administrators
  207. //
  208. coni1->coni1_num_opens = treeConnect->CurrentFileOpenCount;
  209. if( coni1->coni1_num_opens > 0 ) {
  210. ULONG count = SrvCountCachedRfcbsForTid(
  211. treeConnect->Connection,
  212. treeConnect->Tid );
  213. if( coni1->coni1_num_opens > count ) {
  214. coni1->coni1_num_opens -= count;
  215. } else {
  216. coni1->coni1_num_opens = 0;
  217. }
  218. }
  219. //
  220. // There is always exactly one user on a tree connect.
  221. //
  222. // !!! Is this correct???
  223. coni1->coni1_num_users = 1;
  224. //
  225. // Set up the alive time.
  226. //
  227. coni1->coni1_time = secondsAlive;
  228. //
  229. // Attempt to find a reasonable user name. Since the SMB
  230. // protocol does not link tree connects with users, only with
  231. // sessions, it may not be possible to return a user name.
  232. //
  233. ACQUIRE_LOCK( &treeConnect->Connection->Lock );
  234. session = treeConnect->Session;
  235. if ( session != NULL ) {
  236. UNICODE_STRING userName;
  237. SrvGetUserAndDomainName( session, &userName, NULL );
  238. SrvCopyUnicodeStringToBuffer(
  239. &userName,
  240. *FixedStructure,
  241. EndOfVariableData,
  242. &coni1->coni1_username
  243. );
  244. if( userName.Buffer ) {
  245. SrvReleaseUserAndDomainName( session, &userName, NULL );
  246. }
  247. } else {
  248. coni1->coni1_username = NULL;
  249. }
  250. RELEASE_LOCK( &treeConnect->Connection->Lock );
  251. //
  252. // Set up the net name. If the qualifier passed in the
  253. // SRP is a computer name, then the net name is the share
  254. // name. If the qualifier is a share name, the net name
  255. // is a computer name.
  256. //
  257. if ( Srp->Name1.Length > 2 && *Srp->Name1.Buffer == '\\' &&
  258. *(Srp->Name1.Buffer+1) == '\\' ) {
  259. SrvCopyUnicodeStringToBuffer(
  260. &treeConnect->Share->ShareName,
  261. *FixedStructure,
  262. EndOfVariableData,
  263. &coni1->coni1_netname
  264. );
  265. } else {
  266. UNICODE_STRING clientName;
  267. PUNICODE_STRING clientMachineName;
  268. clientMachineName =
  269. &treeConnect->Connection->PagedConnection->ClientMachineNameString;
  270. //
  271. // Make a string that does not contain the leading
  272. // backslashes.
  273. //
  274. clientName.Buffer = clientMachineName->Buffer + 2;
  275. clientName.Length =
  276. (USHORT) (clientMachineName->Length - 2 * sizeof(WCHAR));
  277. clientName.MaximumLength = clientName.Length;
  278. SrvCopyUnicodeStringToBuffer(
  279. &clientName,
  280. *FixedStructure,
  281. EndOfVariableData,
  282. &coni1->coni1_netname
  283. );
  284. }
  285. // *** Lack of break is intentional!
  286. case 0:
  287. //
  288. // Set up the tree connect ID.
  289. //
  290. coni1->coni1_id = SrvGetResumeHandle( &SrvTreeConnectList, treeConnect );
  291. break;
  292. default:
  293. //
  294. // This should never happen. The server service should have
  295. // checked for an invalid level.
  296. //
  297. INTERNAL_ERROR(
  298. ERROR_LEVEL_UNEXPECTED,
  299. "FillConnectionInfoBuffer: invalid level number: %ld",
  300. Srp->Level,
  301. NULL
  302. );
  303. SrvLogInvalidSmb( NULL );
  304. }
  305. return;
  306. } // FillConnectionInfoBuffer
  307. BOOLEAN
  308. FilterConnections (
  309. IN PSERVER_REQUEST_PACKET Srp,
  310. IN PVOID Block
  311. )
  312. /*++
  313. Routine Description:
  314. This routine is intended to be called by SrvEnumApiHandler to check
  315. whether a particular tree connect should be returned.
  316. Arguments:
  317. Srp - a pointer to the SRP for the operation. Name1 ("qualifier"
  318. on NetConnectionEnum) is used to do the filtering.
  319. Block - a pointer to the tree connect to check.
  320. Return Value:
  321. TRUE if the block should be placed in the output buffer, FALSE
  322. if it should be passed over.
  323. --*/
  324. {
  325. PTREE_CONNECT treeConnect = Block;
  326. PUNICODE_STRING compareName;
  327. PAGED_CODE( );
  328. //
  329. // We're going to compare the Name1 field against the share name
  330. // if a computer name is the qualifier or against the computer
  331. // name if the share name was the qualifier.
  332. //
  333. if ( Srp->Name1.Length > 2*sizeof(WCHAR) && *Srp->Name1.Buffer == '\\' &&
  334. *(Srp->Name1.Buffer+1) == '\\' ) {
  335. compareName =
  336. &treeConnect->Connection->PagedConnection->ClientMachineNameString;
  337. } else {
  338. compareName = &treeConnect->Share->ShareName;
  339. }
  340. return RtlEqualUnicodeString(
  341. &Srp->Name1,
  342. compareName,
  343. TRUE
  344. );
  345. } // FilterConnections
  346. ULONG
  347. SizeConnections (
  348. IN PSERVER_REQUEST_PACKET Srp,
  349. IN PVOID Block
  350. )
  351. /*++
  352. Routine Description:
  353. This routine returns the size the passed-in tree connect would take
  354. up in an API output buffer.
  355. Arguments:
  356. Srp - a pointer to the SRP for the operation. The level and Name1
  357. ("qualifier" on NetConnectionEnum) are used.
  358. Block - a pointer to the tree connect to size.
  359. Return Value:
  360. ULONG - The number of bytes the tree connect would take up in the
  361. output buffer.
  362. --*/
  363. {
  364. PTREE_CONNECT treeConnect = Block;
  365. PUNICODE_STRING netName;
  366. UNICODE_STRING userName;
  367. PSESSION session;
  368. ULONG size;
  369. PAGED_CODE( );
  370. if ( Srp->Name1.Length > 2 && *Srp->Name1.Buffer == '\\' &&
  371. *(Srp->Name1.Buffer+1) == '\\' ) {
  372. netName = &treeConnect->Share->ShareName;
  373. } else {
  374. netName =
  375. &treeConnect->Connection->PagedConnection->ClientMachineNameString;
  376. }
  377. //
  378. // Attempt to find a reasonable user name. Since the SMB protocol
  379. // does not link tree connects with users, only with sessions, it
  380. // may not be possible to return a user name.
  381. //
  382. ACQUIRE_LOCK( &treeConnect->Connection->Lock );
  383. session = treeConnect->Session;
  384. if ( (session != NULL) && (GET_BLOCK_STATE(session) == BlockStateActive) ) {
  385. SrvGetUserAndDomainName( session, &userName, NULL );
  386. } else {
  387. userName.Buffer = NULL;
  388. }
  389. size = TOTAL_SIZE_OF_CONNECTION( treeConnect,
  390. Srp->Level,
  391. userName.Buffer ? &userName : NULL,
  392. netName
  393. );
  394. if( userName.Buffer ) {
  395. SrvReleaseUserAndDomainName( session, &userName, NULL );
  396. }
  397. RELEASE_LOCK( &treeConnect->Connection->Lock );
  398. return size;
  399. } // SizeConnections