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.

813 lines
22 KiB

  1. /*************************************************************************
  2. *
  3. * tdspx.c
  4. *
  5. * Copyright 1998, Microsoft
  6. *
  7. *************************************************************************/
  8. #include <ntddk.h>
  9. #include <tdi.h>
  10. #include <isnkrnl.h>
  11. #include <ndis.h>
  12. #include <wsnwlink.h>
  13. #include <winstaw.h>
  14. #define _DEFCHARINFO_
  15. #include <icadd.h>
  16. #include <ctxdd.h>
  17. #include <sdapi.h>
  18. #include <td.h>
  19. #include "tdtdi.h"
  20. #include "tdspx.h"
  21. #ifdef _HYDRA_
  22. // This becomes the device name
  23. PWCHAR ModuleName = L"tdspx";
  24. #endif
  25. #define REG_IPX_Linkage \
  26. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\NwlnkIpx\\Linkage"
  27. #if DBG
  28. ULONG
  29. DbgPrint(
  30. PCH Format,
  31. ...
  32. );
  33. #define DBGPRINT(x) DbgPrint x
  34. #if DBGTRACE
  35. #define TRACE0(x) DbgPrint x
  36. #define TRACE1(x) DbgPrint x
  37. #else
  38. #define TRACE0(x)
  39. #define TRACE1(x)
  40. #endif
  41. #else
  42. #define DBGPRINT(x)
  43. #define TRACE0(x)
  44. #define TRACE1(x)
  45. #endif
  46. /*=============================================================================
  47. == External Functions Defined
  48. =============================================================================*/
  49. NTSTATUS TdiDeviceOpen( PTD, PSD_OPEN );
  50. NTSTATUS TdiDeviceClose( PTD, PSD_CLOSE );
  51. NTSTATUS TdiDeviceOpenEndpoint( PTD, PVOID, ULONG );
  52. NTSTATUS TdiDeviceBuildTransportNameAndAddress( PTD, PICA_STACK_ADDRESS,
  53. PUNICODE_STRING,
  54. PTRANSPORT_ADDRESS *, PULONG );
  55. NTSTATUS TdiDeviceBuildWildcardAddress( PTD, PTRANSPORT_ADDRESS *, PULONG );
  56. NTSTATUS TdiDeviceWaitForDatagramConnection( PTD, PFILE_OBJECT, PDEVICE_OBJECT,
  57. PTRANSPORT_ADDRESS *, PULONG );
  58. NTSTATUS TdiDeviceCompleteDatagramConnection( PTD, PFILE_OBJECT, PDEVICE_OBJECT, PTRANSPORT_ADDRESS, ULONG );
  59. NTSTATUS TdiDeviceConnectionSend( PTD );
  60. NTSTATUS TdiDeviceReadComplete( PTD, PUCHAR, PULONG );
  61. NTSTATUS _OpenRegKey(PHANDLE, PWCHAR);
  62. NTSTATUS _GetRegMultiSZValue(HANDLE ,PWCHAR,PUNICODE_STRING );
  63. VOID GetGUID(OUT PUNICODE_STRING, IN int);
  64. /*=============================================================================
  65. == External Functions Referenced
  66. =============================================================================*/
  67. NTSTATUS MemoryAllocate( ULONG, PVOID * );
  68. VOID MemoryFree( PVOID );
  69. /*=============================================================================
  70. == Internal Functions Defined
  71. =============================================================================*/
  72. NTSTATUS _IpxGetTransportAddress( PTD, int, PULONG, PUCHAR );
  73. NTSTATUS _IPXGetAdapterNumber( int Lana, int * AdpNum );
  74. #if DBG
  75. VOID
  76. DumpIpxAddress(
  77. PTRANSPORT_ADDRESS p,
  78. ULONG Len
  79. );
  80. #endif
  81. /*=============================================================================
  82. == Global variables
  83. =============================================================================*/
  84. /*
  85. * Define variables used by afdcommon code
  86. */
  87. USHORT TdiDeviceEndpointType = TdiConnectionStream;
  88. USHORT TdiDeviceAddressType = TDI_ADDRESS_TYPE_IPX;
  89. USHORT TdiDeviceInBufHeader = 0;
  90. // ULONG TdiDeviceMaxTransportAddressLength = sizeof(TA_IPX_ADDRESS);
  91. /*******************************************************************************
  92. *
  93. * TdiDeviceOpen
  94. *
  95. * Allocate and initialize private data structures
  96. *
  97. * ENTRY:
  98. * pTd (input)
  99. * Pointer to TD data structure
  100. * pSdOpen (input/output)
  101. * Points to the parameter structure SD_OPEN.
  102. *
  103. * EXIT:
  104. * STATUS_SUCCESS - no error
  105. *
  106. ******************************************************************************/
  107. NTSTATUS
  108. TdiDeviceOpen( PTD pTd, PSD_OPEN pSdOpen )
  109. {
  110. return( STATUS_SUCCESS );
  111. }
  112. /*******************************************************************************
  113. *
  114. * TdiDeviceClose
  115. *
  116. * Close transport driver
  117. *
  118. * NOTE: this must not close the current connection endpoint
  119. *
  120. * ENTRY:
  121. * pTd (input)
  122. * Pointer to TD data structure
  123. * pSdClose (input/output)
  124. * Points to the parameter structure SD_CLOSE.
  125. *
  126. * EXIT:
  127. * STATUS_SUCCESS - no error
  128. *
  129. ******************************************************************************/
  130. NTSTATUS
  131. TdiDeviceClose( PTD pTd, PSD_CLOSE pSdClose )
  132. {
  133. return( STATUS_SUCCESS );
  134. }
  135. /*******************************************************************************
  136. *
  137. * TdiDeviceOpenEndpoint
  138. *
  139. * Open an existing endpoint
  140. *
  141. * ENTRY:
  142. * pTd (input)
  143. * Pointer to TD data structure
  144. * pIcaEndpoint (input)
  145. * Pointer to ICA endpoint structure
  146. * IcaEndpointLength (input)
  147. * length of endpoint data
  148. *
  149. * EXIT:
  150. * STATUS_SUCCESS - no error
  151. *
  152. ******************************************************************************/
  153. NTSTATUS
  154. TdiDeviceOpenEndpoint(
  155. PTD pTd,
  156. PVOID pIcaEndpoint,
  157. ULONG IcaEndpointLength
  158. )
  159. {
  160. return( STATUS_SUCCESS );
  161. }
  162. /*****************************************************************************
  163. *
  164. * TdiDeviceBuildTransportNameAndAddress
  165. *
  166. * Build the Transport Name and Address given an optional ICA_STACK_ADDRESS,
  167. * or the Lana value from the pTd->Params structure.
  168. *
  169. * ENTRY:
  170. *
  171. * pTd (input)
  172. * pointer to TD data structure
  173. * pLocalAddress (input)
  174. * pointer to local address to use (OPTIONAL)
  175. * pTransportName (output)
  176. * pointer to UNICODE_STRING to return transport name
  177. * NOTE: the buffer pointed to be pTransportName.Buffer must
  178. * be free'd by the caller
  179. * ppTransportAddress (output)
  180. * pointer to location to return TRANSPORT_ADDRESS structure
  181. * NOTE: the transport address buffer must be free'd by the caller
  182. * pTransportAddressLength (output)
  183. * pointer to location to return TransportAddress length
  184. *
  185. * EXIT:
  186. * STATUS_SUCCESS - Success
  187. *
  188. ****************************************************************************/
  189. NTSTATUS
  190. TdiDeviceBuildTransportNameAndAddress(
  191. PTD pTd,
  192. PICA_STACK_ADDRESS pLocalAddress,
  193. PUNICODE_STRING pTransportName,
  194. PTRANSPORT_ADDRESS *ppTransportAddress,
  195. PULONG pTransportAddressLength
  196. )
  197. {
  198. PTDI_ADDRESS_IPX pIpxAddress;
  199. int Lana;
  200. NTSTATUS Status;
  201. /*
  202. * For SPX, the transport device name is fixed,
  203. * so just allocate and initialize the transport name string here.
  204. */
  205. Status = MemoryAllocate( sizeof(DD_SPX_DEVICE_NAME), &pTransportName->Buffer );
  206. if ( !NT_SUCCESS( Status ) ) {
  207. DBGPRINT(("TdiDeviceBuildTransportNameAndAddress: SPX Could not allocate memory\n"));
  208. goto badmalloc1;
  209. }
  210. wcscpy( pTransportName->Buffer, DD_SPX_DEVICE_NAME );
  211. pTransportName->Length = sizeof(DD_SPX_DEVICE_NAME) - sizeof(UNICODE_NULL);
  212. pTransportName->MaximumLength = pTransportName->Length + sizeof(UNICODE_NULL);
  213. /*
  214. * Allocate a transport address structure
  215. */
  216. *pTransportAddressLength = sizeof(TRANSPORT_ADDRESS) +
  217. sizeof(TDI_ADDRESS_IPX);
  218. Status = MemoryAllocate( *pTransportAddressLength, ppTransportAddress );
  219. if ( !NT_SUCCESS( Status ) ) {
  220. DBGPRINT(("TdiDeviceBuildTransportNameAndAddress: SPX Could not allocate memory\n"));
  221. goto badmalloc2;
  222. }
  223. /*
  224. * Initialize the static part of the transport address
  225. */
  226. (*ppTransportAddress)->TAAddressCount = 1;
  227. (*ppTransportAddress)->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX);
  228. (*ppTransportAddress)->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
  229. pIpxAddress = (PTDI_ADDRESS_IPX)(*ppTransportAddress)->Address[0].Address;
  230. pIpxAddress->Socket = htons( CITRIX_SPX_SOCKET );
  231. /*
  232. * If a local address is specified, then use it.
  233. */
  234. if ( pLocalAddress ) {
  235. /*
  236. * Skip over the address family(type) data (bytes 0&1) of the
  237. * local address struct, and copy the remainder of the address
  238. * directly to the Address field of the TransportAddress struct.
  239. */
  240. ASSERT( *(PUSHORT)pLocalAddress == TDI_ADDRESS_TYPE_IPX );
  241. RtlCopyMemory( pIpxAddress, &((PCHAR)pLocalAddress)[2], sizeof(TDI_ADDRESS_IPX) );
  242. TRACE1(("TDSPX: TdiDeviceBuildTransportAddress: Local address:\n"));
  243. /*
  244. * There was no local address specified.
  245. * In this case, we use the LanAdapter value from the PDPARAMS
  246. * structure to lookup the corresponding IPX address.
  247. */
  248. } else if ( (Lana = pTd->Params.Network.LanAdapter) ) {
  249. /*
  250. * Get Local Address Information
  251. */
  252. Status = _IpxGetTransportAddress( pTd, Lana,
  253. &pIpxAddress->NetworkAddress,
  254. pIpxAddress->NodeAddress );
  255. if ( !NT_SUCCESS( Status ) ) {
  256. DBGPRINT(("TDSPX: TdiDeviceBuildTransportAddress: Bad Lana 0x%x\n",Lana));
  257. goto badadapterdata;
  258. }
  259. TRACE1(("TDSPX: TdiDeviceBuildTransportAddress: Found address for Lana 0x%x\n",Lana));
  260. /*
  261. * No LanAdapter value was specified, so use the wildcard address (zero)
  262. */
  263. } else {
  264. DBGPRINT(("TDSPX: TdiDeviceBuildTransportAddress: Wildcard address"));
  265. pIpxAddress->NetworkAddress = 0;
  266. RtlZeroMemory( pIpxAddress->NodeAddress,
  267. sizeof(pIpxAddress->NodeAddress) );
  268. }
  269. #if DBGTRACE
  270. DumpIpxAddress( *ppTransportAddress, *pTransportAddressLength );
  271. #endif
  272. return( STATUS_SUCCESS );
  273. /*=============================================================================
  274. == Error returns
  275. =============================================================================*/
  276. badadapterdata:
  277. MemoryFree( *ppTransportAddress );
  278. badmalloc2:
  279. MemoryFree( pTransportName->Buffer );
  280. badmalloc1:
  281. return( Status );
  282. }
  283. /*****************************************************************************
  284. *
  285. * TdiDeviceBuildWildcardAddress
  286. *
  287. * Build a wildcard Address for this protocol.
  288. *
  289. * ENTRY:
  290. *
  291. * pTd (input)
  292. * pointer to TD data structure
  293. * ppWildcardAddress (output)
  294. * pointer to location to return TRANSPORT_ADDRESS structure
  295. * NOTE: the transport address buffer must be free'd by the caller
  296. * pWildcardAddressLength (output)
  297. * pointer to location to return TransportAddress length
  298. *
  299. * EXIT:
  300. * STATUS_SUCCESS - Success
  301. *
  302. ****************************************************************************/
  303. NTSTATUS
  304. TdiDeviceBuildWildcardAddress(
  305. PTD pTd,
  306. PTRANSPORT_ADDRESS *ppWildcardAddress,
  307. PULONG pWildcardAddressLength
  308. )
  309. {
  310. PTDI_ADDRESS_IPX pIpxAddress;
  311. NTSTATUS Status;
  312. /*
  313. * Allocate a transport address structure
  314. */
  315. *pWildcardAddressLength = sizeof(TRANSPORT_ADDRESS) +
  316. sizeof(TDI_ADDRESS_IPX);
  317. Status = MemoryAllocate( *pWildcardAddressLength, ppWildcardAddress );
  318. if ( !NT_SUCCESS( Status ) )
  319. return( Status );
  320. /*
  321. * Initialize the static part of the transport address
  322. */
  323. (*ppWildcardAddress)->TAAddressCount = 1;
  324. (*ppWildcardAddress)->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX);
  325. (*ppWildcardAddress)->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
  326. pIpxAddress = (PTDI_ADDRESS_IPX)(*ppWildcardAddress)->Address[0].Address;
  327. pIpxAddress->NetworkAddress = 0;
  328. RtlZeroMemory( pIpxAddress->NodeAddress,
  329. sizeof(pIpxAddress->NodeAddress) );
  330. pIpxAddress->Socket = 0;
  331. return( STATUS_SUCCESS );
  332. }
  333. /*****************************************************************************
  334. *
  335. * TdiDeviceWaitForDatagramConnection
  336. *
  337. * Wait for a datagram connection request, validate it,
  338. * and return the remote transport address of the connection.
  339. *
  340. * ENTRY:
  341. *
  342. * pTd (input)
  343. * pointer to TD data structure
  344. * pFileObject (input)
  345. * pointer to file object to wait for a connection on
  346. * ppRemoteAddress (output)
  347. * pointer to location to return TRANSPORT_ADDRESS structure
  348. * NOTE: the transport address buffer must be free'd by the caller
  349. * pRemoteAddressLength (output)
  350. * pointer to location to return RemoteAddress length
  351. *
  352. * EXIT:
  353. * STATUS_SUCCESS - Success
  354. *
  355. ****************************************************************************/
  356. NTSTATUS
  357. TdiDeviceWaitForDatagramConnection(
  358. PTD pTd,
  359. PFILE_OBJECT pFileObject,
  360. PDEVICE_OBJECT pDeviceObject,
  361. PTRANSPORT_ADDRESS *ppRemoteAddress,
  362. PULONG pRemoteAddressLength
  363. )
  364. {
  365. return( STATUS_NOT_SUPPORTED );
  366. }
  367. /*****************************************************************************
  368. *
  369. * TdiDeviceCompleteDatagramConnection
  370. *
  371. * Do any final work to complete a datagram connection.
  372. *
  373. * ENTRY:
  374. *
  375. * pTd (input)
  376. * pointer to TD data structure
  377. * pFileObject (input)
  378. * pointer to file object for this connection
  379. *
  380. * EXIT:
  381. * STATUS_SUCCESS - Success
  382. *
  383. ****************************************************************************/
  384. NTSTATUS
  385. TdiDeviceCompleteDatagramConnection(
  386. PTD pTd,
  387. PFILE_OBJECT pFileObject,
  388. PDEVICE_OBJECT pDeviceObject,
  389. PTRANSPORT_ADDRESS pTransportAddress,
  390. ULONG TransportAddressLength
  391. )
  392. {
  393. return( STATUS_NOT_SUPPORTED );
  394. }
  395. /*******************************************************************************
  396. *
  397. * TdiDeviceConnectionSend
  398. *
  399. * Initialize host module data structure
  400. * -- this structure gets sent to the client
  401. *
  402. *
  403. * ENTRY:
  404. * pTd (input)
  405. * Pointer to td data structure
  406. *
  407. * EXIT:
  408. * STATUS_SUCCESS - no error
  409. *
  410. ******************************************************************************/
  411. NTSTATUS
  412. TdiDeviceConnectionSend( PTD pTd )
  413. {
  414. PCLIENTMODULES pClient;
  415. /*
  416. * Get pointer to client structure
  417. */
  418. pClient = pTd->pClient;
  419. /*
  420. * Initialize Td host module structure
  421. */
  422. pClient->TdVersionL = VERSION_HOSTL_TDSPX;
  423. pClient->TdVersionH = VERSION_HOSTH_TDSPX;
  424. pClient->TdVersion = VERSION_HOSTH_TDSPX;
  425. return( STATUS_SUCCESS );
  426. }
  427. /*******************************************************************************
  428. *
  429. * TdiDeviceReadComplete
  430. *
  431. * Do any read complete processing
  432. *
  433. *
  434. * ENTRY:
  435. * pTd (input)
  436. * Pointer to td data structure
  437. * pBuffer (input)
  438. * Pointer to input buffer
  439. * pByteCount (input/output)
  440. * Pointer to location containing byte count read
  441. *
  442. * EXIT:
  443. * STATUS_SUCCESS - no error
  444. *
  445. ******************************************************************************/
  446. NTSTATUS
  447. TdiDeviceReadComplete( PTD pTd, PUCHAR pBuffer, PULONG pByteCount )
  448. {
  449. return( STATUS_SUCCESS );
  450. }
  451. /*******************************************************************************
  452. *
  453. * _IpxGetTransportAddress
  454. *
  455. * Get IPX transport address for a given LanAdapter number
  456. *
  457. *
  458. * ENTRY:
  459. * pTd (input)
  460. * pointer to TD data structure
  461. * Lana (input)
  462. * Lan Adapter number
  463. * pNetworkAddress (output)
  464. * pointer to location to return NetworkAddress
  465. * pNodeAddress (output)
  466. * pointer to location to return NodeAddress
  467. *
  468. *
  469. * EXIT:
  470. * STATUS_SUCCESS - no error
  471. *
  472. ******************************************************************************/
  473. NTSTATUS
  474. _IpxGetTransportAddress(
  475. PTD pTd,
  476. int Lana,
  477. PULONG pNetworkAddress,
  478. PUCHAR pNodeAddress
  479. )
  480. {
  481. OBJECT_ATTRIBUTES objectAttributes;
  482. IO_STATUS_BLOCK ioStatusBlock;
  483. UNICODE_STRING nameString;
  484. HANDLE IPXHandle;
  485. ULONG tdiBufferLength;
  486. PSTREAMS_TDI_ACTION tdiBuffer;
  487. ULONG cmd;
  488. PIPX_ADDRESS_DATA pIpxAddressData;
  489. PFILE_OBJECT pFileObject;
  490. NTSTATUS Status;
  491. int IpxAdapterNum = 0;
  492. /*
  493. * Open a Handle to the IPX driver.
  494. */
  495. RtlInitUnicodeString( &nameString, DD_IPX_DEVICE_NAME );
  496. InitializeObjectAttributes(
  497. &objectAttributes,
  498. &nameString,
  499. OBJ_CASE_INSENSITIVE,
  500. (HANDLE) NULL,
  501. (PSECURITY_DESCRIPTOR) NULL
  502. );
  503. Status = ZwCreateFile( &IPXHandle,
  504. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  505. &objectAttributes,
  506. &ioStatusBlock,
  507. NULL,
  508. FILE_ATTRIBUTE_NORMAL,
  509. FILE_SHARE_READ | FILE_SHARE_WRITE,
  510. FILE_OPEN_IF,
  511. 0,
  512. NULL,
  513. 0
  514. );
  515. if ( !NT_SUCCESS( Status ) )
  516. return( Status );
  517. /*
  518. * Allocate a TDI buffer to do the IOCTL.
  519. */
  520. tdiBufferLength = sizeof(STREAMS_TDI_ACTION) + sizeof(ULONG) +
  521. sizeof(IPX_ADDRESS_DATA);
  522. Status = MemoryAllocate( tdiBufferLength, &tdiBuffer );
  523. if ( !NT_SUCCESS( Status ) ) {
  524. ZwClose( IPXHandle );
  525. return( Status );
  526. }
  527. // Get IPX Adapter Num from winstation Lana ID
  528. Status = _IPXGetAdapterNumber( Lana, &IpxAdapterNum);
  529. if ( !NT_SUCCESS( Status ) ) {
  530. ZwClose( IPXHandle );
  531. return( Status );
  532. }
  533. /*
  534. * Fill in the tdiBuffer header
  535. */
  536. RtlMoveMemory( &tdiBuffer->Header.TransportId, "MISN", 4 );
  537. // use the following since we opened a control channel above
  538. tdiBuffer->DatagramOption = NWLINK_OPTION_CONTROL;
  539. /**
  540. Fill out the buffer, the buffer looks like this:
  541. ULONG cmd
  542. data passed.
  543. **/
  544. cmd = MIPX_GETCARDINFO;
  545. memcpy( tdiBuffer->Buffer, &cmd, sizeof(ULONG));
  546. tdiBuffer->BufferLength = sizeof(ULONG) + sizeof(IPX_ADDRESS_DATA);
  547. pIpxAddressData = (PIPX_ADDRESS_DATA)(tdiBuffer->Buffer + sizeof(ULONG));
  548. pIpxAddressData->adapternum = IpxAdapterNum;
  549. Status = ObReferenceObjectByHandle( IPXHandle,
  550. 0,
  551. NULL,
  552. KernelMode,
  553. (PVOID *)&pFileObject,
  554. NULL
  555. );
  556. ASSERT( Status == STATUS_SUCCESS );
  557. Status = CtxDeviceIoControlFile( pFileObject,
  558. IOCTL_TDI_ACTION,
  559. NULL,
  560. 0,
  561. tdiBuffer,
  562. tdiBufferLength,
  563. FALSE,
  564. NULL,
  565. &ioStatusBlock,
  566. NULL
  567. );
  568. ObDereferenceObject( pFileObject );
  569. ZwClose( IPXHandle );
  570. if ( Status == STATUS_SUCCESS ) {
  571. RtlCopyMemory( pNetworkAddress, pIpxAddressData->netnum,
  572. sizeof(pIpxAddressData->netnum) );
  573. RtlCopyMemory( pNodeAddress, pIpxAddressData->nodenum,
  574. sizeof(pIpxAddressData->nodenum) );
  575. }
  576. return( Status );
  577. }
  578. #if DBG
  579. VOID
  580. DumpIpxAddress(
  581. PTRANSPORT_ADDRESS p,
  582. ULONG Len
  583. )
  584. {
  585. ULONG j;
  586. LONG i;
  587. PTDI_ADDRESS_IPX Ipx;
  588. DbgPrint("TAAddressCount %d, TotalLen %d\n",p->TAAddressCount,Len);
  589. for( i=0; i < p->TAAddressCount; i++ ) {
  590. DbgPrint("AddressLength %d, AddressType %d\n",p->Address[i].AddressLength,p->Address[i].AddressType);
  591. Ipx = (PTDI_ADDRESS_IPX)&p->Address[i].Address[0];
  592. DbgPrint("Network 0x%x Socket 0x%x\n",Ipx->NetworkAddress,Ipx->Socket);
  593. for( j=0; j < 6; j++ ) {
  594. DbgPrint("%x:",Ipx->NodeAddress[j]);
  595. }
  596. DbgPrint("\n\n");
  597. }
  598. }
  599. #endif
  600. NTSTATUS
  601. _IPXGetAdapterNumber(
  602. int Lana,
  603. int * AdpNum
  604. )
  605. /*++
  606. Routine Description:
  607. Get the IPX Lan Adapter number using the instation Lana ID index
  608. Arguments:
  609. Lana - IN the winstation Lana ID index
  610. AdpNum - OUT the IPX Lana Adapter num
  611. Return Value:
  612. return nt status
  613. --*/
  614. {
  615. NTSTATUS Status;
  616. int AdapterNum;
  617. UNICODE_STRING RouteString;
  618. UNICODE_STRING NameString;
  619. HANDLE KeyHandle = NULL;
  620. PWSTR RouteStr, Str;
  621. unsigned RouteLen, Len;
  622. /*
  623. * Convert winstation Lana_ID to Network Adapter number
  624. */
  625. RtlInitUnicodeString( &RouteString , NULL );
  626. GetGUID( &RouteString , Lana );
  627. RouteLen = RouteString.Length;
  628. RouteStr = RouteString.Buffer;
  629. AdapterNum =0;
  630. #if DBG
  631. KdPrint( ( "TDIPX: _TcpGetTransportAddress Length = %d GUID = %ws\n" , RouteLen, RouteStr ) );
  632. #endif
  633. if (RouteLen < (2 * sizeof(UNICODE_NULL))) {
  634. return( STATUS_DEVICE_DOES_NOT_EXIST );
  635. }
  636. RtlInitUnicodeString( &NameString, NULL );
  637. Status = _OpenRegKey( &KeyHandle, REG_IPX_Linkage );
  638. if ( !NT_SUCCESS( Status ) )
  639. return Status;
  640. NameString.Length = 0;
  641. NameString.MaximumLength = 0;
  642. NameString.Buffer = NULL;
  643. Status = _GetRegMultiSZValue( KeyHandle, L"Route", &NameString );
  644. ZwClose( KeyHandle );
  645. if ( !NT_SUCCESS( Status ) )
  646. return Status;
  647. if (NameString.Length < (2 * sizeof(WCHAR))) {
  648. return(STATUS_DEVICE_DOES_NOT_EXIST);
  649. }
  650. Len = NameString.Length;
  651. Str = NameString.Buffer;
  652. Status = STATUS_DEVICE_DOES_NOT_EXIST;
  653. AdapterNum = 0;
  654. for (;;) {
  655. // Check current string to see if it's a GUID (it must start with an
  656. // open brace after initial double-quote).
  657. if (Str[1] == L'{') {
  658. if ( wcsncmp( (PWSTR) &Str[1],RouteStr, wcslen(RouteStr)-1) == 0) {
  659. #if DBG
  660. KdPrint( ( "TDIPX: _TcpGetTransportAddress: Get Lan Adapter Number = %i\n",AdapterNum ) );
  661. #endif
  662. Status = STATUS_SUCCESS;
  663. break;
  664. }
  665. else {
  666. // KdPrint( ( "TDIPX: _TcpGetTransportAddress, No this lana Adapter = %i\n",AdapterNum ) );
  667. AdapterNum ++;
  668. }
  669. }
  670. // Skip through current string past NULL.
  671. while (Len >= sizeof(WCHAR)) {
  672. Len -= sizeof(WCHAR);
  673. if (*Str++ == UNICODE_NULL)
  674. break;
  675. }
  676. // Check for index out of range.
  677. if (Len < (2 * sizeof(UNICODE_NULL))) {
  678. break;
  679. }
  680. }
  681. if ( !NT_SUCCESS( Status ) )
  682. return Status;
  683. *AdpNum = AdapterNum;
  684. return STATUS_SUCCESS;
  685. }