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.

909 lines
25 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. Xport.c
  5. Abstract:
  6. This module contains support for the ServerTransport catagory of
  7. APIs for the NT server service.
  8. Author:
  9. David Treadwell (davidtr) 10-Mar-1991
  10. Revision History:
  11. --*/
  12. #include "srvsvcp.h"
  13. #include "ssreg.h"
  14. #include <tstr.h>
  15. //
  16. // Forward declarations.
  17. //
  18. LPSERVER_TRANSPORT_INFO_3
  19. CaptureSvti3 (
  20. IN DWORD Level,
  21. IN LPTRANSPORT_INFO Svti,
  22. OUT PULONG CapturedSvtiLength
  23. );
  24. NET_API_STATUS NET_API_FUNCTION
  25. I_NetrServerTransportAddEx (
  26. IN DWORD Level,
  27. IN LPTRANSPORT_INFO Buffer
  28. )
  29. {
  30. NET_API_STATUS error;
  31. LPSERVER_TRANSPORT_INFO_3 capturedSvti3;
  32. LPSTR TransportAddress; // Pointer to transport address within capturedSvti1
  33. ULONG capturedSvtiLength;
  34. PSERVER_REQUEST_PACKET srp;
  35. PNAME_LIST_ENTRY service;
  36. PTRANSPORT_LIST_ENTRY transport;
  37. BOOLEAN serviceAllocated = FALSE;
  38. LPTSTR DomainName = NULL;
  39. ULONG Flags = 0;
  40. DWORD len;
  41. if( Level >= 1 && Buffer->Transport1.svti1_domain != NULL ) {
  42. DomainName = Buffer->Transport1.svti1_domain;
  43. if( STRLEN( DomainName ) > DNLEN ) {
  44. return ERROR_INVALID_PARAMETER;
  45. }
  46. }
  47. if( Level >= 2 && Buffer->Transport2.svti2_flags != 0 ) {
  48. Flags = Buffer->Transport2.svti2_flags;
  49. //
  50. // Make sure valid flags are passed in
  51. //
  52. if( Flags & (~SVTI2_REMAP_PIPE_NAMES) ) {
  53. return ERROR_INVALID_PARAMETER;
  54. }
  55. }
  56. //
  57. // Capture the transport request buffer and form the full transport
  58. // address.
  59. //
  60. capturedSvti3 = CaptureSvti3( Level, Buffer, &capturedSvtiLength );
  61. if ( capturedSvti3 == NULL ) {
  62. return ERROR_NOT_ENOUGH_MEMORY;
  63. }
  64. TransportAddress = capturedSvti3->svti3_transportaddress;
  65. OFFSET_TO_POINTER( TransportAddress, capturedSvti3 );
  66. //
  67. // Make sure this name isn't already bound for the transport
  68. //
  69. (VOID)RtlAcquireResourceExclusive( &SsData.SsServerInfoResource, TRUE );
  70. if( DomainName == NULL ) {
  71. DomainName = SsData.DomainNameBuffer;
  72. }
  73. for( service = SsData.SsServerNameList; service != NULL; service = service->Next ) {
  74. if( service->TransportAddressLength != capturedSvti3->svti3_transportaddresslength ) {
  75. continue;
  76. }
  77. if( !RtlEqualMemory( service->TransportAddress,
  78. TransportAddress,
  79. capturedSvti3->svti3_transportaddresslength
  80. ) ) {
  81. continue;
  82. }
  83. for( transport=service->Transports; transport != NULL; transport=transport->Next ) {
  84. if( !STRCMPI( transport->TransportName, Buffer->Transport0.svti0_transportname ) ) {
  85. //
  86. // Error... this transport is already bound to the address
  87. //
  88. RtlReleaseResource( &SsData.SsServerInfoResource );
  89. MIDL_user_free( capturedSvti3 );
  90. return ERROR_DUP_NAME;
  91. }
  92. }
  93. break;
  94. }
  95. //
  96. // Counting on success, ensure we can allocate space for the new entry
  97. //
  98. if( service == NULL ) {
  99. len = sizeof( *service ) + sizeof( SsData.DomainNameBuffer );
  100. service = MIDL_user_allocate( len );
  101. if( service == NULL ) {
  102. RtlReleaseResource( &SsData.SsServerInfoResource );
  103. MIDL_user_free( capturedSvti3 );
  104. return ERROR_NOT_ENOUGH_MEMORY;
  105. }
  106. RtlZeroMemory( service, len );
  107. service->DomainName = (LPTSTR)( service + 1 );
  108. serviceAllocated = TRUE;
  109. }
  110. len = sizeof( *transport ) +
  111. (STRLEN( Buffer->Transport0.svti0_transportname ) + sizeof(CHAR)) * sizeof( TCHAR );
  112. transport = MIDL_user_allocate( len );
  113. if( transport == NULL ) {
  114. RtlReleaseResource( &SsData.SsServerInfoResource );
  115. if( serviceAllocated ) {
  116. MIDL_user_free( service );
  117. }
  118. MIDL_user_free( capturedSvti3 );
  119. return ERROR_NOT_ENOUGH_MEMORY;
  120. }
  121. RtlZeroMemory( transport, len );
  122. //
  123. // Get a SRP in which to send the request.
  124. //
  125. srp = SsAllocateSrp( );
  126. if ( srp == NULL ) {
  127. RtlReleaseResource( &SsData.SsServerInfoResource );
  128. if( serviceAllocated ) {
  129. MIDL_user_free( service );
  130. }
  131. MIDL_user_free( transport );
  132. MIDL_user_free( capturedSvti3 );
  133. return ERROR_NOT_ENOUGH_MEMORY;
  134. }
  135. //
  136. // Add any user-supplied flags
  137. //
  138. if (Flags & SVTI2_REMAP_PIPE_NAMES) {
  139. srp->Flags |= SRP_XADD_REMAP_PIPE_NAMES;
  140. }
  141. //
  142. // Check if this is the primary machine name
  143. //
  144. if((capturedSvti3->svti3_transportaddresslength ==
  145. SsData.SsServerTransportAddressLength)
  146. &&
  147. RtlEqualMemory(SsData.SsServerTransportAddress,
  148. TransportAddress,
  149. SsData.SsServerTransportAddressLength) )
  150. {
  151. srp->Flags |= SRP_XADD_PRIMARY_MACHINE;
  152. }
  153. //
  154. // Send the request on to the server.
  155. //
  156. error = SsServerFsControl(
  157. FSCTL_SRV_NET_SERVER_XPORT_ADD,
  158. srp,
  159. capturedSvti3,
  160. capturedSvtiLength
  161. );
  162. //
  163. // Free the SRP
  164. //
  165. SsFreeSrp( srp );
  166. if( error != NO_ERROR ) {
  167. RtlReleaseResource( &SsData.SsServerInfoResource );
  168. if( serviceAllocated ) {
  169. MIDL_user_free( service );
  170. }
  171. MIDL_user_free( transport );
  172. MIDL_user_free( capturedSvti3 );
  173. return error;
  174. }
  175. //
  176. // Everything worked. Add it to the NAME_LIST
  177. //
  178. transport->TransportName = (LPTSTR)(transport + 1 );
  179. STRCPY( transport->TransportName, Buffer->Transport0.svti0_transportname );
  180. transport->Next = service->Transports;
  181. service->Transports = transport;
  182. if( serviceAllocated ) {
  183. RtlCopyMemory( service->TransportAddress,
  184. TransportAddress,
  185. capturedSvti3->svti3_transportaddresslength );
  186. service->TransportAddress[ capturedSvti3->svti3_transportaddresslength ] = '\0';
  187. service->TransportAddressLength = capturedSvti3->svti3_transportaddresslength;
  188. STRCPY( service->DomainName, DomainName );
  189. service->Next = SsData.SsServerNameList;
  190. //
  191. // If this is the first transport and name added to the server, it must be the primary
  192. // name
  193. //
  194. if( SsData.SsServerNameList == NULL ) {
  195. service->PrimaryName = 1;
  196. }
  197. SsData.SsServerNameList = service;
  198. }
  199. RtlReleaseResource( &SsData.SsServerInfoResource );
  200. MIDL_user_free( capturedSvti3 );
  201. SsSetExportedServerType( service, FALSE, FALSE );
  202. return NO_ERROR;
  203. }
  204. NET_API_STATUS NET_API_FUNCTION
  205. NetrServerTransportAddEx (
  206. IN LPTSTR ServerName,
  207. IN DWORD Level,
  208. IN LPTRANSPORT_INFO Buffer
  209. )
  210. {
  211. NET_API_STATUS error;
  212. PNAME_LIST_ENTRY service;
  213. ULONG Flags;
  214. ServerName;
  215. //
  216. // Make sure that the level is valid.
  217. //
  218. if ( Level != 0 && Level != 1 && Level != 2 && Level != 3 ) {
  219. return ERROR_INVALID_LEVEL;
  220. }
  221. if( Buffer->Transport0.svti0_transportname == NULL ||
  222. Buffer->Transport0.svti0_transportaddress == NULL ||
  223. Buffer->Transport0.svti0_transportaddresslength == 0 ||
  224. Buffer->Transport0.svti0_transportaddresslength >= sizeof(service->TransportAddress) ) {
  225. return ERROR_INVALID_PARAMETER;
  226. }
  227. if( Level >= 2 && Buffer->Transport2.svti2_flags != 0 ) {
  228. Flags = Buffer->Transport2.svti2_flags;
  229. if (Flags & ~(SVTI2_REMAP_PIPE_NAMES)) {
  230. return ERROR_INVALID_PARAMETER;
  231. }
  232. }
  233. //
  234. // Make sure that the caller is allowed to set information in the
  235. // server.
  236. //
  237. if( SsData.SsInitialized ) {
  238. error = SsCheckAccess(
  239. &SsConfigInfoSecurityObject,
  240. SRVSVC_CONFIG_INFO_SET
  241. );
  242. if ( error != NO_ERROR ) {
  243. return ERROR_ACCESS_DENIED;
  244. }
  245. }
  246. return I_NetrServerTransportAddEx ( Level, Buffer );
  247. } // NetrServerTransportAddEx
  248. NET_API_STATUS NET_API_FUNCTION
  249. NetrServerTransportAdd (
  250. IN LPTSTR ServerName,
  251. IN DWORD Level,
  252. IN LPSERVER_TRANSPORT_INFO_0 Buffer
  253. )
  254. {
  255. if( Level != 0 ) {
  256. return ERROR_INVALID_LEVEL;
  257. }
  258. return NetrServerTransportAddEx( ServerName, 0, (LPTRANSPORT_INFO)Buffer );
  259. }
  260. //
  261. // This routine is called from xsproc when the server delivers us a PNP unbind
  262. // notification. This routine unbinds all server names from the named transport
  263. //
  264. VOID
  265. I_NetServerTransportDel(
  266. IN PUNICODE_STRING TransportName
  267. )
  268. {
  269. PSERVER_TRANSPORT_INFO_3 capturedSvti3;
  270. ULONG capturedSvtiLength;
  271. PSERVER_REQUEST_PACKET srp;
  272. PNAME_LIST_ENTRY service;
  273. PNAME_LIST_ENTRY sbackp = NULL;
  274. PTRANSPORT_LIST_ENTRY transport;
  275. PTRANSPORT_LIST_ENTRY tbackp = NULL;
  276. NET_API_STATUS error;
  277. //
  278. // Allocate the SERVER_TRANSPORT_INFO_3 structure and initialize it with
  279. // the name of the transport we wish to delete
  280. //
  281. capturedSvtiLength = sizeof( SERVER_TRANSPORT_INFO_3 ) +
  282. TransportName->Length + sizeof(WCHAR);
  283. capturedSvti3 = MIDL_user_allocate( capturedSvtiLength );
  284. if( capturedSvti3 == NULL ) {
  285. return;
  286. }
  287. RtlZeroMemory( capturedSvti3, capturedSvtiLength );
  288. capturedSvti3->svti3_transportname = (LPTSTR)(capturedSvti3+1);
  289. RtlCopyMemory( capturedSvti3->svti3_transportname,
  290. TransportName->Buffer,
  291. TransportName->Length
  292. );
  293. POINTER_TO_OFFSET( capturedSvti3->svti3_transportname, capturedSvti3 );
  294. //
  295. // Get a SRP in which to send the request.
  296. //
  297. srp = SsAllocateSrp( );
  298. if ( srp == NULL ) {
  299. MIDL_user_free( capturedSvti3 );
  300. return;
  301. }
  302. //
  303. // Send the request on to the server.
  304. //
  305. error = SsServerFsControl(
  306. FSCTL_SRV_NET_SERVER_XPORT_DEL,
  307. srp,
  308. capturedSvti3,
  309. capturedSvtiLength
  310. );
  311. //
  312. // Free the SRP and svti
  313. //
  314. SsFreeSrp( srp );
  315. if( error != NO_ERROR ) {
  316. MIDL_user_free( capturedSvti3 );
  317. return;
  318. }
  319. OFFSET_TO_POINTER( capturedSvti3->svti3_transportname, capturedSvti3 );
  320. //
  321. // Now that we've deleted the transport from the server, delete it from
  322. // our own internal structures
  323. //
  324. (VOID)RtlAcquireResourceExclusive( &SsData.SsServerInfoResource, TRUE );
  325. //
  326. // Remove the entry from the SsData.SsServerNameList. If it's the last transport for
  327. // the NAME_LIST_ENTRY, delete the NAME_LIST_ENTRY as well. These lists are
  328. // expected to be quite short, and this operation is infrequent,
  329. // so the inefficiency of rescans should be of no consequence.
  330. //
  331. outer_scan:
  332. for( service = SsData.SsServerNameList, sbackp = NULL;
  333. service != NULL;
  334. sbackp = service, service = service->Next ) {
  335. inner_scan:
  336. for( transport=service->Transports, tbackp = NULL;
  337. transport != NULL;
  338. tbackp=transport, transport=transport->Next ) {
  339. if( STRCMPI( transport->TransportName, capturedSvti3->svti3_transportname ) ) {
  340. continue;
  341. }
  342. //
  343. // This is the one...remove it from the list
  344. //
  345. if( tbackp == NULL ) {
  346. service->Transports = transport->Next;
  347. } else {
  348. tbackp->Next = transport->Next;
  349. }
  350. MIDL_user_free( transport );
  351. goto inner_scan;
  352. }
  353. //
  354. // If this NAME_LIST_ENTRY no longer has any transports, delete it
  355. //
  356. if( service->Transports == NULL ) {
  357. if( sbackp == NULL ) {
  358. SsData.SsServerNameList = service->Next;
  359. } else {
  360. sbackp->Next = service->Next;
  361. }
  362. //
  363. // If this was the last NAME_LIST_ENTRY, save the ServiceBits
  364. // in case another transport comes back later
  365. //
  366. if( SsData.SsServerNameList == NULL && SsData.ServiceBits == 0 ) {
  367. SsData.ServiceBits = service->ServiceBits;
  368. }
  369. MIDL_user_free( service );
  370. goto outer_scan;
  371. }
  372. }
  373. RtlReleaseResource( &SsData.SsServerInfoResource );
  374. MIDL_user_free( capturedSvti3 );
  375. }
  376. NET_API_STATUS NET_API_FUNCTION
  377. NetrServerTransportDelEx (
  378. IN LPTSTR ServerName,
  379. IN DWORD Level,
  380. IN LPTRANSPORT_INFO Buffer
  381. )
  382. {
  383. NET_API_STATUS error;
  384. LPSERVER_TRANSPORT_INFO_3 capturedSvti3;
  385. LPSTR TransportAddress; // Pointer to transport address within capturedSvti1
  386. ULONG capturedSvtiLength;
  387. PSERVER_REQUEST_PACKET srp;
  388. PNAME_LIST_ENTRY service;
  389. PNAME_LIST_ENTRY sbackp = NULL;
  390. PTRANSPORT_LIST_ENTRY transport;
  391. PTRANSPORT_LIST_ENTRY tbackp = NULL;
  392. ServerName;
  393. //
  394. // Make sure that the level is valid.
  395. //
  396. if ( Level != 0 && Level != 1 ) {
  397. return ERROR_INVALID_LEVEL;
  398. }
  399. if( Buffer->Transport0.svti0_transportname == NULL ||
  400. Buffer->Transport0.svti0_transportaddress == NULL ||
  401. Buffer->Transport0.svti0_transportaddresslength == 0 ||
  402. Buffer->Transport0.svti0_transportaddresslength >= sizeof(service->TransportAddress) ) {
  403. return ERROR_INVALID_PARAMETER;
  404. }
  405. //
  406. // Make sure that the caller is allowed to set information in the
  407. // server.
  408. //
  409. if( SsData.SsInitialized ) {
  410. error = SsCheckAccess(
  411. &SsConfigInfoSecurityObject,
  412. SRVSVC_CONFIG_INFO_SET
  413. );
  414. if ( error != NO_ERROR ) {
  415. return ERROR_ACCESS_DENIED;
  416. }
  417. }
  418. //
  419. // Capture the transport request buffer and form the full transport
  420. // address.
  421. //
  422. capturedSvti3 = CaptureSvti3( Level, Buffer, &capturedSvtiLength );
  423. if ( capturedSvti3 == NULL ) {
  424. return ERROR_NOT_ENOUGH_MEMORY;
  425. }
  426. TransportAddress = capturedSvti3->svti3_transportaddress;
  427. OFFSET_TO_POINTER( TransportAddress, capturedSvti3 );
  428. //
  429. // Get an SRP in which to send the request.
  430. //
  431. srp = SsAllocateSrp( );
  432. if ( srp == NULL ) {
  433. MIDL_user_free( capturedSvti3 );
  434. return ERROR_NOT_ENOUGH_MEMORY;
  435. }
  436. //
  437. // Send the request on to the server.
  438. //
  439. error = SsServerFsControl(
  440. FSCTL_SRV_NET_SERVER_XPORT_DEL,
  441. srp,
  442. capturedSvti3,
  443. capturedSvtiLength
  444. );
  445. //
  446. // Free the SRP and svti
  447. //
  448. SsFreeSrp( srp );
  449. if( error != NO_ERROR ) {
  450. MIDL_user_free( capturedSvti3 );
  451. return error;
  452. }
  453. (VOID)RtlAcquireResourceExclusive( &SsData.SsServerInfoResource, TRUE );
  454. //
  455. // Remove the entry from the SsData.SsServerNameList. If it's the last transport for
  456. // the NAME_LIST_ENTRY, delete the NAME_LIST_ENTRY as well.
  457. //
  458. for( service = SsData.SsServerNameList; service != NULL; sbackp = service, service = service->Next ) {
  459. //
  460. // Walk the list until we find the NAME_LIST_ENTRY having the transportaddress
  461. // of interest
  462. //
  463. if( service->TransportAddressLength != capturedSvti3->svti3_transportaddresslength ) {
  464. continue;
  465. }
  466. if( !RtlEqualMemory( service->TransportAddress,
  467. TransportAddress,
  468. capturedSvti3->svti3_transportaddresslength ) ) {
  469. continue;
  470. }
  471. //
  472. // This is the correct NAME_LIST_ENTRY, now find the TRANSPORT_LIST_ENTRY of interest
  473. //
  474. for( transport=service->Transports; transport != NULL; tbackp=transport, transport=transport->Next ) {
  475. if( STRCMPI( transport->TransportName, Buffer->Transport0.svti0_transportname ) ) {
  476. continue;
  477. }
  478. //
  479. // This is the one...remove it from the list
  480. //
  481. if( tbackp == NULL ) {
  482. service->Transports = transport->Next;
  483. } else {
  484. tbackp->Next = transport->Next;
  485. }
  486. MIDL_user_free( transport );
  487. break;
  488. }
  489. //
  490. // If this NAME_LIST_ENTRY no longer has any transports, delete it
  491. //
  492. if( service->Transports == NULL ) {
  493. if( sbackp == NULL ) {
  494. SsData.SsServerNameList = service->Next;
  495. } else {
  496. sbackp->Next = service->Next;
  497. }
  498. //
  499. // If this was the last NAME_LIST_ENTRY, save the ServiceBits
  500. // in case another transport comes back later
  501. //
  502. if( SsData.SsServerNameList == NULL && SsData.ServiceBits == 0 ) {
  503. SsData.ServiceBits = service->ServiceBits;
  504. }
  505. MIDL_user_free( service );
  506. }
  507. break;
  508. }
  509. RtlReleaseResource( &SsData.SsServerInfoResource );
  510. MIDL_user_free( capturedSvti3 );
  511. return NO_ERROR;
  512. } // NetrServerTransportDelEx
  513. NET_API_STATUS NET_API_FUNCTION
  514. NetrServerTransportDel (
  515. IN LPTSTR ServerName,
  516. IN DWORD Level,
  517. IN LPSERVER_TRANSPORT_INFO_0 Buffer
  518. )
  519. {
  520. // To protect us from penetration bugs, all calls that come in over
  521. // this interface are marshalled and treated as InfoLevel 0. To truly
  522. // use Info Level 1, you need to use the new RPC interface, which is done
  523. // automatically for Whistler+ (NT 5.1)
  524. return NetrServerTransportDelEx( ServerName, 0, (LPTRANSPORT_INFO)Buffer );
  525. }
  526. NET_API_STATUS NET_API_FUNCTION
  527. NetrServerTransportEnum (
  528. IN LPTSTR ServerName,
  529. IN LPSERVER_XPORT_ENUM_STRUCT InfoStruct,
  530. IN DWORD PreferredMaximumLength,
  531. OUT LPDWORD TotalEntries,
  532. IN OUT LPDWORD ResumeHandle OPTIONAL
  533. )
  534. {
  535. NET_API_STATUS error;
  536. PSERVER_REQUEST_PACKET srp;
  537. ServerName;
  538. if (InfoStruct == NULL) {
  539. return ERROR_INVALID_PARAMETER;
  540. }
  541. //
  542. // Make sure that the level is valid.
  543. //
  544. if ( InfoStruct->Level != 0 && InfoStruct->Level != 1 ) {
  545. return ERROR_INVALID_LEVEL;
  546. }
  547. if (InfoStruct->XportInfo.Level0 == NULL) {
  548. return ERROR_INVALID_PARAMETER;
  549. }
  550. //
  551. // Make sure that the caller is allowed to get information from the
  552. // server.
  553. //
  554. if( SsData.SsInitialized ) {
  555. error = SsCheckAccess(
  556. &SsTransportEnumSecurityObject,
  557. SRVSVC_CONFIG_USER_INFO_GET
  558. );
  559. if ( error != NO_ERROR ) {
  560. return ERROR_ACCESS_DENIED;
  561. }
  562. }
  563. //
  564. // Set up the input parameters in the request buffer.
  565. //
  566. srp = SsAllocateSrp( );
  567. if ( srp == NULL ) {
  568. return ERROR_NOT_ENOUGH_MEMORY;
  569. }
  570. srp->Level = InfoStruct->Level;
  571. if ( ARGUMENT_PRESENT( ResumeHandle ) ) {
  572. srp->Parameters.Get.ResumeHandle = *ResumeHandle;
  573. } else {
  574. srp->Parameters.Get.ResumeHandle = 0;
  575. }
  576. if (InfoStruct->XportInfo.Level0->Buffer != NULL) {
  577. // The InfoStruct is defined as a parameter. However the Buffer
  578. // parameter is only used as out. In these cases we need to free
  579. // the buffer allocated by RPC if the client had specified a non
  580. // NULL value for it.
  581. MIDL_user_free(InfoStruct->XportInfo.Level0->Buffer);
  582. InfoStruct->XportInfo.Level0->Buffer = NULL;
  583. }
  584. //
  585. // Get the data from the server. This routine will allocate the
  586. // return buffer and handle the case where PreferredMaximumLength ==
  587. // -1.
  588. //
  589. error = SsServerFsControlGetInfo(
  590. FSCTL_SRV_NET_SERVER_XPORT_ENUM,
  591. srp,
  592. (PVOID *)&InfoStruct->XportInfo.Level0->Buffer,
  593. PreferredMaximumLength
  594. );
  595. //
  596. // Set up return information.
  597. //
  598. InfoStruct->XportInfo.Level0->EntriesRead = srp->Parameters.Get.EntriesRead;
  599. *TotalEntries = srp->Parameters.Get.TotalEntries;
  600. if ( srp->Parameters.Get.EntriesRead > 0 && ARGUMENT_PRESENT( ResumeHandle ) ) {
  601. *ResumeHandle = srp->Parameters.Get.ResumeHandle;
  602. }
  603. SsFreeSrp( srp );
  604. return error;
  605. } // NetrServerTransportEnum
  606. LPSERVER_TRANSPORT_INFO_3
  607. CaptureSvti3 (
  608. IN DWORD Level,
  609. IN LPTRANSPORT_INFO Svti,
  610. OUT PULONG CapturedSvtiLength
  611. )
  612. {
  613. LPSERVER_TRANSPORT_INFO_3 capturedSvti;
  614. PCHAR variableData;
  615. ULONG transportNameLength;
  616. CHAR TransportAddressBuffer[MAX_PATH];
  617. LPBYTE TransportAddress;
  618. DWORD TransportAddressLength;
  619. LPTSTR DomainName;
  620. DWORD domainLength;
  621. //
  622. // If a server transport name is specified, use it, otherwise
  623. // use the default server name on the transport.
  624. //
  625. // Either way, the return transport address is normalized into a netbios address
  626. //
  627. if ( Svti->Transport0.svti0_transportaddress == NULL ) {
  628. TransportAddress = SsData.SsServerTransportAddress;
  629. TransportAddressLength = SsData.SsServerTransportAddressLength;
  630. Svti->Transport0.svti0_transportaddresslength = TransportAddressLength;
  631. } else {
  632. //
  633. // Normalize the transport address.
  634. //
  635. TransportAddress = TransportAddressBuffer;
  636. TransportAddressLength = min( Svti->Transport0.svti0_transportaddresslength,
  637. sizeof( TransportAddressBuffer ));
  638. RtlCopyMemory( TransportAddress,
  639. Svti->Transport0.svti0_transportaddress,
  640. TransportAddressLength );
  641. if ( TransportAddressLength < NETBIOS_NAME_LEN ) {
  642. RtlCopyMemory( TransportAddress + TransportAddressLength,
  643. " ",
  644. NETBIOS_NAME_LEN - TransportAddressLength );
  645. TransportAddressLength = NETBIOS_NAME_LEN;
  646. } else {
  647. TransportAddressLength = NETBIOS_NAME_LEN;
  648. }
  649. }
  650. transportNameLength = SIZE_WSTR( Svti->Transport0.svti0_transportname );
  651. if( Level == 0 || Svti->Transport1.svti1_domain == NULL ) {
  652. DomainName = SsData.DomainNameBuffer;
  653. } else {
  654. DomainName = Svti->Transport1.svti1_domain;
  655. }
  656. domainLength = SIZE_WSTR( DomainName );
  657. //
  658. // Allocate enough space to hold the captured buffer, including the
  659. // full transport name/address and domain name
  660. //
  661. *CapturedSvtiLength = sizeof(*capturedSvti) +
  662. transportNameLength + TransportAddressLength + domainLength;
  663. capturedSvti = MIDL_user_allocate( *CapturedSvtiLength );
  664. if ( capturedSvti == NULL ) {
  665. return NULL;
  666. }
  667. RtlZeroMemory( capturedSvti, *CapturedSvtiLength );
  668. //
  669. // Copy in the domain name
  670. //
  671. variableData = (PCHAR)( capturedSvti + 1 );
  672. capturedSvti->svti3_domain = (PWCH)variableData;
  673. RtlCopyMemory( variableData,
  674. DomainName,
  675. domainLength
  676. );
  677. variableData += domainLength;
  678. POINTER_TO_OFFSET( capturedSvti->svti3_domain, capturedSvti );
  679. //
  680. // Copy the transport name
  681. //
  682. capturedSvti->svti3_transportname = (PWCH)variableData;
  683. RtlCopyMemory(
  684. variableData,
  685. Svti->Transport3.svti3_transportname,
  686. transportNameLength
  687. );
  688. variableData += transportNameLength;
  689. POINTER_TO_OFFSET( capturedSvti->svti3_transportname, capturedSvti );
  690. //
  691. // Copy the transport address
  692. //
  693. capturedSvti->svti3_transportaddress = variableData;
  694. capturedSvti->svti3_transportaddresslength = TransportAddressLength;
  695. RtlCopyMemory(
  696. variableData,
  697. TransportAddress,
  698. TransportAddressLength
  699. );
  700. variableData += TransportAddressLength;
  701. POINTER_TO_OFFSET( capturedSvti->svti3_transportaddress, capturedSvti );
  702. if( Level >= 3 ) {
  703. capturedSvti->svti3_passwordlength = Svti->Transport3.svti3_passwordlength;
  704. RtlCopyMemory( capturedSvti->svti3_password,
  705. Svti->Transport3.svti3_password,
  706. sizeof( capturedSvti->svti3_password )
  707. );
  708. }
  709. return capturedSvti;
  710. } // CaptureSvti3