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.

3528 lines
102 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. D:\nt\private\net\sockets\wshatm\wshatm.c
  5. Abstract:
  6. This module contains necessary routines for the ATM Windows Sockets
  7. Helper DLL. This DLL provides the transport-specific support necessary
  8. for the Windows Sockets DLL to use ATM as a transport.
  9. Revision History:
  10. arvindm 20-May-1997 Created based on TCP/IP's helper DLL, wshtcpip
  11. --*/
  12. #define UNICODE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include <wchar.h>
  20. #include <tdi.h>
  21. #include <winsock2.h>
  22. #include <mswsock.h>
  23. #include <ws2atm.h>
  24. #include <wsahelp.h>
  25. #include <tdistat.h>
  26. #include <tdiinfo.h>
  27. #include <rwanuser.h>
  28. typedef unsigned long ulong;
  29. typedef unsigned short ushort;
  30. typedef unsigned int uint;
  31. typedef unsigned char uchar;
  32. #define TL_INSTANCE 0
  33. #include <ws2atmsp.h>
  34. #define NT // temporarily needed by tdiinfo.h...
  35. #include <tdiinfo.h>
  36. #include <basetyps.h>
  37. #include <nspapi.h>
  38. #define ATM_NAME L"ATM"
  39. #define RWAN_NAME L"RawWan"
  40. #define ATM_ADDR_SIZE 20
  41. #define ATM_ADDR_BLANK_CHAR L' '
  42. #define ATM_ADDR_PUNCTUATION_CHAR L'.'
  43. #define ATM_ADDR_E164_START_CHAR '+'
  44. #define ATM_AAL5_SOCK_TYPE SOCK_RAW
  45. #define ATM_WSA_MULTIPOINT_FLAGS (WSA_FLAG_MULTIPOINT_C_ROOT | \
  46. WSA_FLAG_MULTIPOINT_C_LEAF | \
  47. WSA_FLAG_MULTIPOINT_D_ROOT | \
  48. WSA_FLAG_MULTIPOINT_D_LEAF)
  49. //
  50. // Define valid flags for WSHOpenSocket2().
  51. //
  52. #define VALID_ATM_FLAGS (WSA_FLAG_OVERLAPPED | \
  53. ATM_WSA_MULTIPOINT_FLAGS)
  54. //
  55. // Maximum expected size of ATM Connection Options: this includes the
  56. // base QOS structure, plus all possible IEs.
  57. //
  58. #if 0
  59. #define MAX_ATM_OPTIONS_LENGTH \
  60. sizeof(QOS) + \
  61. sizeof(Q2931_IE) + sizeof(AAL_PARAMETERS_IE) + \
  62. sizeof(Q2931_IE) + sizeof(ATM_TRAFFIC_DESCRIPTOR_IE) + \
  63. sizeof(Q2931_IE) + sizeof(ATM_BROADBAND_BEARER_CAPABILITY_IE) + \
  64. (3 * (sizeof(Q2931_IE) + sizeof(ATM_BLLI_IE))) + \
  65. sizeof(Q2931_IE) + sizeof(ATM_CALLED_PARTY_NUMBER_IE) + \
  66. sizeof(Q2931_IE) + sizeof(ATM_CALLED_PARTY_SUBADDRESS_IE) + \
  67. sizeof(Q2931_IE) + sizeof(ATM_CALLING_PARTY_SUBADDRESS_IE) + \
  68. sizeof(Q2931_IE) + sizeof(ATM_CAUSE_IE) + \
  69. sizeof(Q2931_IE) + sizeof(ATM_QOS_CLASS_IE) + \
  70. sizeof(Q2931_IE) + sizeof(ATM_TRANSIT_NETWORK_SELECTION_IE)
  71. #else
  72. //
  73. // Need much more with ATMUNI 4.0...
  74. //
  75. #define MAX_ATM_OPTIONS_LENGTH 1024
  76. #endif
  77. #if DBG1
  78. #define DBGPRINT(stmt) { DbgPrint ("WSHATM: "); DbgPrint stmt; }
  79. #else
  80. #define DBGPRINT(stmt)
  81. #endif // DBG1
  82. #if DBG
  83. extern
  84. PVOID
  85. MyRtlAllocateHeap(
  86. IN PVOID HeapHandle,
  87. IN ULONG Flags,
  88. IN ULONG Size,
  89. IN ULONG LineNumber
  90. );
  91. extern
  92. VOID
  93. MyRtlFreeHeap(
  94. IN PVOID HeapHandle,
  95. IN ULONG Flags,
  96. IN PVOID MemPtr,
  97. IN ULONG LineNumber
  98. );
  99. #define RTL_ALLOCATE_HEAP(_Handle, _Flags, _Size) MyRtlAllocateHeap(_Handle, _Flags, _Size, __LINE__)
  100. #define RTL_FREE_HEAP(_Handle, _Flags, _Memptr) MyRtlFreeHeap(_Handle, _Flags, _Memptr, __LINE__)
  101. #else
  102. #define RTL_ALLOCATE_HEAP(_Handle, _Flags, _Size) RtlAllocateHeap(_Handle, _Flags, _Size)
  103. #define RTL_FREE_HEAP(_Handle, _Flags, _Memptr) RtlFreeHeap(_Handle, _Flags, _Memptr)
  104. #endif
  105. #define ATM_AAL5_PACKET_SIZE 65535
  106. //
  107. // Structure and variables to define the triples supported by ATM. The
  108. // first entry of each array is considered the canonical triple for
  109. // that socket type; the other entries are synonyms for the first.
  110. //
  111. typedef struct _MAPPING_TRIPLE {
  112. INT AddressFamily;
  113. INT SocketType;
  114. INT Protocol;
  115. } MAPPING_TRIPLE, *PMAPPING_TRIPLE;
  116. MAPPING_TRIPLE AtmMappingTriples[] = {
  117. AF_ATM, ATM_AAL5_SOCK_TYPE, ATMPROTO_AAL5,
  118. AF_ATM, ATM_AAL5_SOCK_TYPE, 0,
  119. AF_ATM, SOCK_RAW, ATMPROTO_AAL5,
  120. AF_ATM, SOCK_RAW, 0,
  121. AF_ATM, 0, ATMPROTO_AAL5,
  122. AF_UNSPEC, 0, ATMPROTO_AAL5,
  123. AF_UNSPEC, ATM_AAL5_SOCK_TYPE, ATMPROTO_AAL5,
  124. AF_UNSPEC, SOCK_RAW, ATMPROTO_AAL5
  125. };
  126. //
  127. // Winsock 2 WSAPROTOCOL_INFO structures for all supported protocols.
  128. //
  129. #define ATM_UNI_VERSION 0x00030001 // For UNI 3.1
  130. WSAPROTOCOL_INFOW Winsock2Protocols[] =
  131. {
  132. //
  133. // ATM AAL5
  134. //
  135. {
  136. XP1_GUARANTEED_ORDER // dwServiceFlags1
  137. | XP1_MESSAGE_ORIENTED
  138. // | XP1_PARTIAL_MESSAGE
  139. | XP1_IFS_HANDLES
  140. | XP1_SUPPORT_MULTIPOINT
  141. | XP1_MULTIPOINT_DATA_PLANE
  142. | XP1_MULTIPOINT_CONTROL_PLANE
  143. | XP1_QOS_SUPPORTED,
  144. 0, // dwServiceFlags2
  145. 0, // dwServiceFlags3
  146. 0, // dwServiceFlags4
  147. PFL_MATCHES_PROTOCOL_ZERO, // dwProviderFlags
  148. { // gProviderId
  149. 0, 0, 0,
  150. { 0, 0, 0, 0, 0, 0, 0, 0 }
  151. },
  152. 0, // dwCatalogEntryId
  153. { // ProtocolChain
  154. BASE_PROTOCOL, // ChainLen
  155. { 0, 0, 0, 0, 0, 0, 0 } // ChainEntries
  156. },
  157. ATM_UNI_VERSION, // iVersion
  158. AF_ATM, // iAddressFamily
  159. sizeof(sockaddr_atm), // iMaxSockAddr
  160. sizeof(sockaddr_atm), // iMinSockAddr
  161. ATM_AAL5_SOCK_TYPE, // iSocketType
  162. ATMPROTO_AAL5, // iProtocol
  163. 0, // iProtocolMaxOffset
  164. BIGENDIAN, // iNetworkByteOrder
  165. SECURITY_PROTOCOL_NONE, // iSecurityScheme
  166. ATM_AAL5_PACKET_SIZE, // dwMessageSize
  167. 0, // dwProviderReserved
  168. L"MSAFD ATM AAL5" // szProtocol
  169. }
  170. };
  171. #define NUM_WINSOCK2_PROTOCOLS \
  172. ( sizeof(Winsock2Protocols) / sizeof(Winsock2Protocols[0]) )
  173. //
  174. // The GUID identifying this provider.
  175. //
  176. GUID AtmProviderGuid = { /* {C3656046-3AAF-11d1-A8C3-00C04FC99C9C} */
  177. 0xC3656046,
  178. 0x3AAF,
  179. 0x11D1,
  180. {0xA8, 0xC3, 0x00, 0xC0, 0x4F, 0xC9, 0x9C, 0x9C}
  181. };
  182. //
  183. // Given a digit (0-9) represented in ANSI, return its WCHAR representation
  184. //
  185. #define ANSI_TO_WCHAR(_AnsiDigit) \
  186. (L'0' + (WCHAR)((_AnsiDigit) - '0'))
  187. //
  188. // Given a hex digit value (0-15), return its WCHAR representation
  189. // (i.e. 0 -> L'0', 12 -> L'C')
  190. //
  191. #define DIGIT_TO_WCHAR(_Value) \
  192. (((_Value) > 9)? (L'A' + (WCHAR)((_Value) - 10)) : \
  193. (L'0' + (WCHAR)((_Value) - 0 )))
  194. //
  195. // The socket context structure for this DLL. Each open ATM socket
  196. // will have one of these context structures, which is used to maintain
  197. // information about the socket.
  198. //
  199. typedef struct _WSHATM_SOCKET_CONTEXT {
  200. INT AddressFamily;
  201. INT SocketType;
  202. INT Protocol;
  203. INT ReceiveBufferSize;
  204. SOCKET SocketHandle;
  205. DWORD Flags;
  206. DWORD LocalFlags;
  207. ATM_CONNECTION_ID ConnectionId;
  208. } WSHATM_SOCKET_CONTEXT, *PWSHATM_SOCKET_CONTEXT;
  209. #define DEFAULT_RECEIVE_BUFFER_SIZE ATM_AAL5_PACKET_SIZE
  210. //
  211. // LocalFlags in WSHATM_SOCKET_CONTEXT:
  212. //
  213. #define WSHATM_SOCK_IS_BOUND 0x00000001
  214. #define WSHATM_SOCK_IS_PVC 0x00000004
  215. #define WSHATM_SOCK_ASSOCIATE_PVC_PENDING 0x00000008
  216. //
  217. // Forward declarations of internal routines.
  218. //
  219. BOOLEAN
  220. IsTripleInList (
  221. IN PMAPPING_TRIPLE List,
  222. IN ULONG ListLength,
  223. IN INT AddressFamily,
  224. IN INT SocketType,
  225. IN INT Protocol
  226. );
  227. INT
  228. WSHAtmSetQoS(
  229. IN PVOID HelperDllSocketContext,
  230. IN SOCKET SocketHandle,
  231. IN LPVOID InputBuffer,
  232. IN DWORD InputBufferLength
  233. );
  234. INT
  235. WSHAtmGetQoS(
  236. IN PVOID HelperDllSocketContext,
  237. IN SOCKET SocketHandle,
  238. IN LPVOID OutputBuffer,
  239. IN DWORD OutputBufferLength,
  240. OUT LPDWORD NumberOfBytesReturned
  241. );
  242. INT
  243. AtmQueryAtmGlobalInformation(
  244. IN ATM_OBJECT_ID ObjectId,
  245. IN LPVOID pContext,
  246. IN DWORD ContextLength,
  247. IN LPVOID OutputBuffer,
  248. IN DWORD OutputBufferLength,
  249. OUT LPDWORD NumberOfBytesReturned
  250. );
  251. INT
  252. AtmSetGenericObjectInformation (
  253. IN HANDLE TdiObjectHandle,
  254. IN ULONG IoControlCode,
  255. IN RWAN_OBJECT_ID ObjectId,
  256. IN PVOID InputBuffer,
  257. IN ULONG InputBufferLength
  258. );
  259. INT
  260. AtmGetGenericObjectInformation (
  261. IN HANDLE TdiObjectHandle,
  262. IN ULONG IoControlCode,
  263. IN RWAN_OBJECT_ID ObjectId,
  264. IN PVOID InputBuffer,
  265. IN ULONG InputBufferLength,
  266. OUT PVOID OutputBuffer,
  267. IN ULONG OutputBufferLength,
  268. OUT LPDWORD NumberOfBytesReturned
  269. );
  270. INT
  271. AtmSetAtmObjectInformation (
  272. IN HANDLE TdiObjectHandle,
  273. IN ULONG IoControlCode,
  274. IN ATM_OBJECT_ID ObjectId,
  275. IN PVOID InputBuffer,
  276. IN ULONG InputBufferLength
  277. );
  278. INT
  279. AtmGetAtmObjectInformation (
  280. IN HANDLE TdiObjectHandle,
  281. IN ULONG IoControlCode,
  282. IN ATM_OBJECT_ID ObjectId,
  283. IN PVOID InputBuffer,
  284. IN ULONG InputBufferLength,
  285. OUT PVOID OutputBuffer,
  286. IN ULONG OutputBufferLength,
  287. OUT LPDWORD NumberOfBytesReturned
  288. );
  289. INT
  290. AtmAssociatePVC(
  291. IN SOCKET SocketHandle,
  292. IN PVOID HelperDllSocketContext,
  293. IN HANDLE TdiAddressObjectHandle,
  294. IN HANDLE TdiConnectionObjectHandle,
  295. IN LPVOID InputBuffer,
  296. IN DWORD InputBufferLength
  297. );
  298. INT
  299. AtmDoAssociatePVC(
  300. IN PWSHATM_SOCKET_CONTEXT Context,
  301. IN HANDLE TdiAddressObjectHandle
  302. );
  303. BOOLEAN
  304. DllInitialize (
  305. IN PVOID DllHandle,
  306. IN ULONG Reason,
  307. IN PVOID Context OPTIONAL
  308. )
  309. {
  310. DBGPRINT(("DllInitialize, Reason %d\n", Reason));
  311. switch ( Reason ) {
  312. case DLL_PROCESS_ATTACH:
  313. //
  314. // We don't need to receive thread attach and detach
  315. // notifications, so disable them to help application
  316. // performance.
  317. //
  318. DisableThreadLibraryCalls( DllHandle );
  319. return TRUE;
  320. case DLL_THREAD_ATTACH:
  321. break;
  322. case DLL_PROCESS_DETACH:
  323. break;
  324. case DLL_THREAD_DETACH:
  325. break;
  326. }
  327. return TRUE;
  328. } // SockInitialize
  329. INT
  330. WSHGetSockaddrType (
  331. IN PSOCKADDR Sockaddr,
  332. IN DWORD SockaddrLength,
  333. OUT PSOCKADDR_INFO SockaddrInfo
  334. )
  335. /*++
  336. Routine Description:
  337. This routine parses a sockaddr to determine the type of the
  338. machine address and endpoint address portions of the sockaddr.
  339. This is called by the winsock DLL whenever it needs to interpret
  340. a sockaddr.
  341. Arguments:
  342. Sockaddr - a pointer to the sockaddr structure to evaluate.
  343. SockaddrLength - the number of bytes in the sockaddr structure.
  344. SockaddrInfo - a pointer to a structure that will receive information
  345. about the specified sockaddr.
  346. Return Value:
  347. INT - a winsock error code indicating the status of the operation, or
  348. NO_ERROR if the operation succeeded.
  349. --*/
  350. {
  351. UNALIGNED SOCKADDR_ATM *sockaddr = (PSOCKADDR_ATM)Sockaddr;
  352. ULONG i;
  353. DBGPRINT(("GetSockaddrType: SockaddrLength %d, satm_family %d, AddrType x%x\n",
  354. SockaddrLength, sockaddr->satm_family, sockaddr->satm_number.AddressType));
  355. //
  356. // Make sure that the address family is correct.
  357. //
  358. if ( sockaddr->satm_family != AF_ATM ) {
  359. return WSAEAFNOSUPPORT;
  360. }
  361. //
  362. // Make sure that the length is correct.
  363. //
  364. if ( SockaddrLength < sizeof(SOCKADDR_ATM) ) {
  365. return WSAEFAULT;
  366. }
  367. #if 0
  368. //
  369. // The ATM address part cannot be "absent".
  370. //
  371. if ( sockaddr->satm_number.AddressType == SAP_FIELD_ABSENT ) {
  372. return WSAEINVAL;
  373. }
  374. #endif
  375. if ( sockaddr->satm_number.NumofDigits > ATM_ADDR_SIZE ) {
  376. return WSAEINVAL;
  377. }
  378. //
  379. // The address passed the tests, looks like a good address.
  380. // Determine the type of the address and endpoint portions
  381. // of the sockaddr.
  382. //
  383. if ( sockaddr->satm_number.AddressType == SAP_FIELD_ANY &&
  384. sockaddr->satm_blli.Layer2Protocol == SAP_FIELD_ANY &&
  385. sockaddr->satm_blli.Layer3Protocol == SAP_FIELD_ANY &&
  386. sockaddr->satm_bhli.HighLayerInfoType == SAP_FIELD_ANY ) {
  387. SockaddrInfo->AddressInfo = SockaddrAddressInfoWildcard;
  388. SockaddrInfo->EndpointInfo = SockaddrEndpointInfoWildcard;
  389. } else if ( sockaddr->satm_number.AddressType == SAP_FIELD_ABSENT ) {
  390. SockaddrInfo->AddressInfo = SockaddrAddressInfoWildcard;
  391. SockaddrInfo->EndpointInfo = SockaddrEndpointInfoWildcard;
  392. } else {
  393. SockaddrInfo->AddressInfo = SockaddrAddressInfoNormal;
  394. SockaddrInfo->EndpointInfo = SockaddrEndpointInfoNormal;
  395. }
  396. return NO_ERROR;
  397. } // WSHGetSockaddrType
  398. INT
  399. WSHGetSocketInformation (
  400. IN PVOID HelperDllSocketContext,
  401. IN SOCKET SocketHandle,
  402. IN HANDLE TdiAddressObjectHandle,
  403. IN HANDLE TdiConnectionObjectHandle,
  404. IN INT Level,
  405. IN INT OptionName,
  406. OUT PCHAR OptionValue,
  407. OUT PINT OptionLength
  408. )
  409. /*++
  410. Routine Description:
  411. This routine retrieves information about a socket for those socket
  412. options supported in this helper DLL. Currently there are none
  413. supported.
  414. This is called by the winsock DLL when a level/option name
  415. combination is passed to getsockopt() that the winsock DLL does
  416. not understand.
  417. Arguments:
  418. HelperDllSocketContext - the context pointer returned from
  419. WSHOpenSocket().
  420. SocketHandle - the handle of the socket for which we're getting
  421. information.
  422. TdiAddressObjectHandle - the TDI address object of the socket, if
  423. any. If the socket is not yet bound to an address, then
  424. it does not have a TDI address object and this parameter
  425. will be NULL.
  426. TdiConnectionObjectHandle - the TDI connection object of the socket,
  427. if any. If the socket is not yet connected, then it does not
  428. have a TDI connection object and this parameter will be NULL.
  429. Level - the level parameter passed to getsockopt().
  430. OptionName - the optname parameter passed to getsockopt().
  431. OptionValue - the optval parameter passed to getsockopt().
  432. OptionLength - the optlen parameter passed to getsockopt().
  433. Return Value:
  434. INT - a winsock error code indicating the status of the operation, or
  435. NO_ERROR if the operation succeeded.
  436. --*/
  437. {
  438. PWSHATM_SOCKET_CONTEXT context = HelperDllSocketContext;
  439. INT err;
  440. DBGPRINT(("GetSocketInformation: Level %d, OptionName %d, OptionLength %d\n",
  441. Level, OptionName, *OptionLength));
  442. UNREFERENCED_PARAMETER( SocketHandle );
  443. UNREFERENCED_PARAMETER( TdiAddressObjectHandle );
  444. UNREFERENCED_PARAMETER( TdiConnectionObjectHandle );
  445. //
  446. // Check if this is an internal request for context information.
  447. //
  448. if ( Level == SOL_INTERNAL && OptionName == SO_CONTEXT ) {
  449. //
  450. // The Windows Sockets DLL is requesting context information
  451. // from us. If an output buffer was not supplied, the Windows
  452. // Sockets DLL is just requesting the size of our context
  453. // information.
  454. //
  455. if ( OptionValue != NULL ) {
  456. //
  457. // Make sure that the buffer is sufficient to hold all the
  458. // context information.
  459. //
  460. if ( *OptionLength < sizeof(*context) ) {
  461. return WSAEFAULT;
  462. }
  463. //
  464. // Copy in the context information.
  465. //
  466. RtlCopyMemory( OptionValue, context, sizeof(*context) );
  467. }
  468. *OptionLength = sizeof(*context);
  469. err = NO_ERROR;
  470. } else {
  471. switch ( OptionName ) {
  472. case SO_MAX_MSG_SIZE:
  473. if ( TdiConnectionObjectHandle == NULL ) {
  474. DbgPrint("wshatm: SO_MAX_MSG_SIZE: immed return\n");
  475. if ( *OptionLength >= sizeof(DWORD) ) {
  476. *(LPDWORD)OptionValue = DEFAULT_RECEIVE_BUFFER_SIZE;
  477. *OptionLength = sizeof(DWORD);
  478. err = NO_ERROR;
  479. } else {
  480. err = WSAEFAULT;
  481. }
  482. } else {
  483. DbgPrint("wshatm: SO_MAX_MSG_SIZE: querying driver\n");
  484. err = AtmGetGenericObjectInformation(
  485. TdiConnectionObjectHandle,
  486. IOCTL_RWAN_GENERIC_CONN_HANDLE_QUERY,
  487. RWAN_OID_CONN_OBJECT_MAX_MSG_SIZE,
  488. NULL, // No Input buffer
  489. 0, // Input Buffer length
  490. OptionValue, // Output buffer
  491. *OptionLength, // Output buffer length
  492. OptionLength // NumberOfBytesReturned
  493. );
  494. }
  495. break;
  496. default:
  497. err = WSAENOPROTOOPT;
  498. break;
  499. }
  500. }
  501. return err;
  502. } // WSHGetSocketInformation
  503. INT
  504. WSHGetWildcardSockaddr (
  505. IN PVOID HelperDllSocketContext,
  506. OUT PSOCKADDR Sockaddr,
  507. OUT PINT SockaddrLength
  508. )
  509. /*++
  510. Routine Description:
  511. This routine returns a wildcard socket address. A wildcard address
  512. is one which will bind the socket to an endpoint of the transport's
  513. choosing. For ATM, a wildcard address has AddressType and BHLI and
  514. BLLI Type fields set to SAP_FIELD_ANY.
  515. Arguments:
  516. HelperDllSocketContext - the context pointer returned from
  517. WSHOpenSocket() for the socket for which we need a wildcard
  518. address.
  519. Sockaddr - points to a buffer which will receive the wildcard socket
  520. address.
  521. SockaddrLength - receives the length of the wioldcard sockaddr.
  522. Return Value:
  523. INT - a winsock error code indicating the status of the operation, or
  524. NO_ERROR if the operation succeeded.
  525. --*/
  526. {
  527. PSOCKADDR_ATM sockaddr;
  528. DBGPRINT(("GetWildcardAddress\n"));
  529. sockaddr = (PSOCKADDR_ATM)Sockaddr;
  530. if ( *SockaddrLength < sizeof(SOCKADDR_ATM) ) {
  531. return WSAEFAULT;
  532. }
  533. *SockaddrLength = sizeof(SOCKADDR_ATM);
  534. //
  535. // Prepare the ATM wild card address.
  536. //
  537. RtlZeroMemory( sockaddr, sizeof(SOCKADDR_ATM) );
  538. sockaddr->satm_family = AF_ATM;
  539. sockaddr->satm_number.AddressType = SAP_FIELD_ABSENT;
  540. sockaddr->satm_blli.Layer2Protocol = SAP_FIELD_ANY;
  541. sockaddr->satm_blli.Layer3Protocol = SAP_FIELD_ANY;
  542. sockaddr->satm_bhli.HighLayerInfoType = SAP_FIELD_ANY;
  543. return NO_ERROR;
  544. } // WSAGetWildcardSockaddr
  545. DWORD
  546. WSHGetWinsockMapping (
  547. OUT PWINSOCK_MAPPING Mapping,
  548. IN DWORD MappingLength
  549. )
  550. /*++
  551. Routine Description:
  552. Returns the list of address family/socket type/protocol triples
  553. supported by this helper DLL.
  554. Arguments:
  555. Mapping - receives a pointer to a WINSOCK_MAPPING structure that
  556. describes the triples supported here.
  557. MappingLength - the length, in bytes, of the passed-in Mapping buffer.
  558. Return Value:
  559. DWORD - the length, in bytes, of a WINSOCK_MAPPING structure for this
  560. helper DLL. If the passed-in buffer is too small, the return
  561. value will indicate the size of a buffer needed to contain
  562. the WINSOCK_MAPPING structure.
  563. --*/
  564. {
  565. DWORD mappingLength;
  566. DBGPRINT(("GetWinsockMapping\n"));
  567. mappingLength = sizeof(WINSOCK_MAPPING) - sizeof(MAPPING_TRIPLE) +
  568. sizeof(AtmMappingTriples);
  569. //
  570. // If the passed-in buffer is too small, return the length needed
  571. // now without writing to the buffer. The caller should allocate
  572. // enough memory and call this routine again.
  573. //
  574. if ( mappingLength > MappingLength ) {
  575. return mappingLength;
  576. }
  577. //
  578. // Fill in the output mapping buffer with the list of triples
  579. // supported in this helper DLL.
  580. //
  581. Mapping->Rows = sizeof(AtmMappingTriples) / sizeof(AtmMappingTriples[0]);
  582. Mapping->Columns = sizeof(MAPPING_TRIPLE) / sizeof(DWORD);
  583. RtlMoveMemory(
  584. Mapping->Mapping,
  585. AtmMappingTriples,
  586. sizeof(AtmMappingTriples)
  587. );
  588. //
  589. // Return the number of bytes we wrote.
  590. //
  591. return mappingLength;
  592. } // WSHGetWinsockMapping
  593. INT
  594. WSHOpenSocket (
  595. IN OUT PINT AddressFamily,
  596. IN OUT PINT SocketType,
  597. IN OUT PINT Protocol,
  598. OUT PUNICODE_STRING TransportDeviceName,
  599. OUT PVOID *HelperDllSocketContext,
  600. OUT PDWORD NotificationEvents
  601. )
  602. {
  603. return WSHOpenSocket2(
  604. AddressFamily,
  605. SocketType,
  606. Protocol,
  607. 0, // Group
  608. 0, // Flags
  609. TransportDeviceName,
  610. HelperDllSocketContext,
  611. NotificationEvents
  612. );
  613. } // WSHOpenSocket
  614. INT
  615. WSHOpenSocket2 (
  616. IN OUT PINT AddressFamily,
  617. IN OUT PINT SocketType,
  618. IN OUT PINT Protocol,
  619. IN GROUP Group,
  620. IN DWORD Flags,
  621. OUT PUNICODE_STRING TransportDeviceName,
  622. OUT PVOID *HelperDllSocketContext,
  623. OUT PDWORD NotificationEvents
  624. )
  625. /*++
  626. Routine Description:
  627. Does the necessary work for this helper DLL to open a socket and is
  628. called by the winsock DLL in the socket() routine. This routine
  629. verifies that the specified triple is valid, determines the NT
  630. device name of the TDI provider that will support that triple,
  631. allocates space to hold the socket's context block, and
  632. canonicalizes the triple.
  633. Arguments:
  634. AddressFamily - on input, the address family specified in the
  635. socket() call. On output, the canonicalized value for the
  636. address family.
  637. SocketType - on input, the socket type specified in the socket()
  638. call. On output, the canonicalized value for the socket type.
  639. Protocol - on input, the protocol specified in the socket() call.
  640. On output, the canonicalized value for the protocol.
  641. Group - Identifies the group for the new socket.
  642. Flags - Zero or more WSA_FLAG_* flags as passed into WSASocket().
  643. TransportDeviceName - receives the name of the TDI provider that
  644. will support the specified triple.
  645. HelperDllSocketContext - receives a context pointer that the winsock
  646. DLL will return to this helper DLL on future calls involving
  647. this socket.
  648. NotificationEvents - receives a bitmask of those state transitions
  649. this helper DLL should be notified on.
  650. Return Value:
  651. INT - a winsock error code indicating the status of the operation, or
  652. NO_ERROR if the operation succeeded.
  653. --*/
  654. {
  655. PWSHATM_SOCKET_CONTEXT context;
  656. DWORD multipointFlags;
  657. UNICODE_STRING atmDeviceName;
  658. //
  659. // Determine whether this is an ATM socket.
  660. //
  661. DBGPRINT(("WSHOpenSocket2: AF %d, Type %d, Proto %d\n",
  662. *AddressFamily, *SocketType, *Protocol));
  663. if ( IsTripleInList(
  664. AtmMappingTriples,
  665. sizeof(AtmMappingTriples) / sizeof(AtmMappingTriples[0]),
  666. *AddressFamily,
  667. *SocketType,
  668. *Protocol ) ) {
  669. //
  670. // It's an ATM socket. Check the flags.
  671. //
  672. if ( ( Flags & ~VALID_ATM_FLAGS ) != 0 ) {
  673. DBGPRINT(("WSHOpenSocket2: Bad flags x%x\n", Flags));
  674. return WSAEINVAL;
  675. }
  676. if ( ( Flags & ATM_WSA_MULTIPOINT_FLAGS ) != 0 ) {
  677. //
  678. // The only multipoint combinations allowed are:
  679. //
  680. // 1. C_ROOT|D_ROOT
  681. // 2. C_LEAF|D_LEAF
  682. //
  683. multipointFlags = ( Flags & ATM_WSA_MULTIPOINT_FLAGS );
  684. if ( ( multipointFlags != (WSA_FLAG_MULTIPOINT_C_ROOT | WSA_FLAG_MULTIPOINT_D_ROOT) ) &&
  685. ( multipointFlags != (WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF) ) ) {
  686. DBGPRINT(("WSHOpenSocket2: Bad multipoint flags x%x\n",
  687. Flags));
  688. return WSAEINVAL;
  689. } else {
  690. DBGPRINT(("WSHOpenSocket2: Good multipoint flags x%x\n", Flags));
  691. }
  692. }
  693. //
  694. // Return the canonical form of a ATM socket triple.
  695. //
  696. *AddressFamily = AtmMappingTriples[0].AddressFamily;
  697. *SocketType = AtmMappingTriples[0].SocketType;
  698. *Protocol = AtmMappingTriples[0].Protocol;
  699. //
  700. // Prepare the name of the TDI device.
  701. //
  702. RtlInitUnicodeString( &atmDeviceName, DD_ATM_DEVICE_NAME );
  703. TransportDeviceName->Buffer = RTL_ALLOCATE_HEAP( RtlProcessHeap( ), 0, atmDeviceName.MaximumLength );
  704. if ( TransportDeviceName->Buffer == NULL ) {
  705. return WSAEFAULT;
  706. }
  707. TransportDeviceName->MaximumLength = atmDeviceName.MaximumLength;
  708. TransportDeviceName->Length = 0;
  709. RtlCopyUnicodeString(TransportDeviceName, &atmDeviceName);
  710. } else {
  711. //
  712. // This should never happen if the registry information about this
  713. // helper DLL is correct. If somehow this did happen, just return
  714. // an error.
  715. //
  716. DBGPRINT(("WSHOpenSocket2: Triple not found!\n"));
  717. if ( *Protocol != ATMPROTO_AAL5 ) {
  718. return WSAEPROTONOSUPPORT;
  719. }
  720. return WSAEINVAL;
  721. }
  722. //
  723. // Allocate context for this socket. The Windows Sockets DLL will
  724. // return this value to us when it asks us to get/set socket options.
  725. //
  726. context = RTL_ALLOCATE_HEAP( RtlProcessHeap( ), 0, sizeof(*context) );
  727. if ( context == NULL ) {
  728. return WSAENOBUFS;
  729. }
  730. //
  731. // Initialize the context for the socket.
  732. //
  733. context->AddressFamily = *AddressFamily;
  734. context->SocketType = *SocketType;
  735. context->Protocol = *Protocol;
  736. context->ReceiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE;
  737. context->Flags = Flags;
  738. context->LocalFlags = 0;
  739. //
  740. // Tell the Windows Sockets DLL which state transitions we're
  741. // interested in being notified of.
  742. //
  743. *NotificationEvents =
  744. WSH_NOTIFY_BIND | WSH_NOTIFY_LISTEN | WSH_NOTIFY_CLOSE;
  745. //
  746. // Everything worked, return success.
  747. //
  748. *HelperDllSocketContext = context;
  749. DBGPRINT(("WSHOpenSocket2 success: AF %d, Type %d, Proto %d\n",
  750. *AddressFamily, *SocketType, *Protocol));
  751. return NO_ERROR;
  752. } // WSHOpenSocket
  753. INT
  754. WSHNotify (
  755. IN PVOID HelperDllSocketContext,
  756. IN SOCKET SocketHandle,
  757. IN HANDLE TdiAddressObjectHandle,
  758. IN HANDLE TdiConnectionObjectHandle,
  759. IN DWORD NotifyEvent
  760. )
  761. /*++
  762. Routine Description:
  763. This routine is called by the winsock DLL after a state transition
  764. of the socket. Only state transitions returned in the
  765. NotificationEvents parameter of WSHOpenSocket() are notified here.
  766. This routine allows a winsock helper DLL to track the state of
  767. socket and perform necessary actions corresponding to state
  768. transitions.
  769. If we see a LISTEN event, we call setsockopt() to force AFD to
  770. allocate data buffers (for options) for incoming connection requests
  771. on this socket.
  772. If we see a BIND event for a socket to be used for multipoint
  773. activity, we tell RAWWAN that the associated address object is
  774. of multipoint type.
  775. Arguments:
  776. HelperDllSocketContext - the context pointer given to the winsock
  777. DLL by WSHOpenSocket().
  778. SocketHandle - the handle for the socket.
  779. TdiAddressObjectHandle - the TDI address object of the socket, if
  780. any. If the socket is not yet bound to an address, then
  781. it does not have a TDI address object and this parameter
  782. will be NULL.
  783. TdiConnectionObjectHandle - the TDI connection object of the socket,
  784. if any. If the socket is not yet connected, then it does not
  785. have a TDI connection object and this parameter will be NULL.
  786. NotifyEvent - indicates the state transition for which we're being
  787. called.
  788. Return Value:
  789. INT - a winsock error code indicating the status of the operation, or
  790. NO_ERROR if the operation succeeded.
  791. --*/
  792. {
  793. PWSHATM_SOCKET_CONTEXT context = HelperDllSocketContext;
  794. INT err;
  795. INT Option;
  796. INT OptionLength = sizeof(Option);
  797. PCHAR pOption = (PCHAR)&Option;
  798. DBGPRINT(("Notify: Event = %d\n", NotifyEvent));
  799. err = NO_ERROR;
  800. switch (NotifyEvent)
  801. {
  802. case WSH_NOTIFY_BIND:
  803. DBGPRINT(("NotifyBind: context %x, Flags %x, LocalFlags %x\n",
  804. context, context->Flags, context->LocalFlags));
  805. //
  806. // Request the Winsock DLL to set the options.
  807. //
  808. Option = MAX_ATM_OPTIONS_LENGTH;
  809. err = setsockopt(
  810. SocketHandle,
  811. SOL_SOCKET,
  812. SO_CONNOPTLEN,
  813. pOption,
  814. OptionLength
  815. );
  816. if ( err != NO_ERROR ) {
  817. DBGPRINT(("WSHATM: NotifyBind: setsockopt SO_CONNOPTLEN err %x\n", err));
  818. break;
  819. }
  820. context->LocalFlags |= WSHATM_SOCK_IS_BOUND;
  821. if ( ( context->Flags & ATM_WSA_MULTIPOINT_FLAGS ) != 0 ) {
  822. //
  823. // Prepare flags for RAWWAN.
  824. //
  825. Option = 0;
  826. if ( context->Flags & WSA_FLAG_MULTIPOINT_C_ROOT ) {
  827. Option |= RWAN_AOFLAG_C_ROOT;
  828. }
  829. if ( context->Flags & WSA_FLAG_MULTIPOINT_C_LEAF ) {
  830. Option |= RWAN_AOFLAG_C_LEAF;
  831. }
  832. if ( context->Flags & WSA_FLAG_MULTIPOINT_D_ROOT ) {
  833. Option |= RWAN_AOFLAG_D_ROOT;
  834. }
  835. if ( context->Flags & WSA_FLAG_MULTIPOINT_D_LEAF ) {
  836. Option |= RWAN_AOFLAG_D_LEAF;
  837. }
  838. //
  839. // Inform RAWWAN about the Multipoint nature of this
  840. // Address Object.
  841. //
  842. err = AtmSetGenericObjectInformation(
  843. TdiAddressObjectHandle,
  844. IOCTL_RWAN_GENERIC_ADDR_HANDLE_SET,
  845. RWAN_OID_ADDRESS_OBJECT_FLAGS,
  846. &Option,
  847. sizeof(Option)
  848. );
  849. DBGPRINT(("Notify: Bind Notify on PMP endpoint, Option x%x, ret = %d\n",
  850. Option, err));
  851. }
  852. else if ( ( context->LocalFlags & WSHATM_SOCK_ASSOCIATE_PVC_PENDING ) ) {
  853. DBGPRINT(("Notify: Bind Notify will Associate PVC\n"));
  854. err = AtmDoAssociatePVC(
  855. context,
  856. TdiAddressObjectHandle
  857. );
  858. }
  859. break;
  860. case WSH_NOTIFY_CLOSE:
  861. RTL_FREE_HEAP( RtlProcessHeap( ), 0, context );
  862. break;
  863. case WSH_NOTIFY_LISTEN:
  864. //
  865. // Request the Winsock DLL to set the options.
  866. //
  867. Option = MAX_ATM_OPTIONS_LENGTH;
  868. err = setsockopt(
  869. SocketHandle,
  870. SOL_SOCKET,
  871. SO_CONNOPTLEN,
  872. pOption,
  873. OptionLength
  874. );
  875. break;
  876. default:
  877. err = WSAEINVAL;
  878. break;
  879. }
  880. return err;
  881. } // WSHNotify
  882. INT
  883. WSHSetSocketInformation (
  884. IN PVOID HelperDllSocketContext,
  885. IN SOCKET SocketHandle,
  886. IN HANDLE TdiAddressObjectHandle,
  887. IN HANDLE TdiConnectionObjectHandle,
  888. IN INT Level,
  889. IN INT OptionName,
  890. IN PCHAR OptionValue,
  891. IN INT OptionLength
  892. )
  893. /*++
  894. Routine Description:
  895. This routine sets information about a socket for those socket
  896. options supported in this helper DLL. We don't support any
  897. options at present.
  898. This routine is called by the winsock DLL when a level/option
  899. name combination is passed to setsockopt() that the winsock DLL
  900. does not understand.
  901. Arguments:
  902. HelperDllSocketContext - the context pointer returned from
  903. WSHOpenSocket().
  904. SocketHandle - the handle of the socket for which we're getting
  905. information.
  906. TdiAddressObjectHandle - the TDI address object of the socket, if
  907. any. If the socket is not yet bound to an address, then
  908. it does not have a TDI address object and this parameter
  909. will be NULL.
  910. TdiConnectionObjectHandle - the TDI connection object of the socket,
  911. if any. If the socket is not yet connected, then it does not
  912. have a TDI connection object and this parameter will be NULL.
  913. Level - the level parameter passed to setsockopt().
  914. OptionName - the optname parameter passed to setsockopt().
  915. OptionValue - the optval parameter passed to setsockopt().
  916. OptionLength - the optlen parameter passed to setsockopt().
  917. Return Value:
  918. INT - a winsock error code indicating the status of the operation, or
  919. NO_ERROR if the operation succeeded.
  920. --*/
  921. {
  922. PWSHATM_SOCKET_CONTEXT context = HelperDllSocketContext;
  923. INT error;
  924. INT optionValue;
  925. UNREFERENCED_PARAMETER( SocketHandle );
  926. UNREFERENCED_PARAMETER( TdiAddressObjectHandle );
  927. UNREFERENCED_PARAMETER( TdiConnectionObjectHandle );
  928. DBGPRINT(("SetSocketInformation: Level %d, Option x%x\n", Level, OptionName));
  929. //
  930. // Check if this is an internal request for context information.
  931. //
  932. if ( Level == SOL_INTERNAL && OptionName == SO_CONTEXT ) {
  933. //
  934. // The Windows Sockets DLL is requesting that we set context
  935. // information for a new socket. If the new socket was
  936. // accept()'ed, then we have already been notified of the socket
  937. // and HelperDllSocketContext will be valid. If the new socket
  938. // was inherited or duped into this process, then this is our
  939. // first notification of the socket and HelperDllSocketContext
  940. // will be equal to NULL.
  941. //
  942. // Insure that the context information being passed to us is
  943. // sufficiently large.
  944. //
  945. if ( OptionLength < sizeof(*context) ) {
  946. return WSAEINVAL;
  947. }
  948. if ( HelperDllSocketContext == NULL ) {
  949. //
  950. // This is our notification that a socket handle was
  951. // inherited or duped into this process. Allocate a context
  952. // structure for the new socket.
  953. //
  954. context = RTL_ALLOCATE_HEAP( RtlProcessHeap( ), 0, sizeof(*context) );
  955. if ( context == NULL ) {
  956. return WSAENOBUFS;
  957. }
  958. //
  959. // Copy over information into the context block.
  960. //
  961. RtlCopyMemory( context, OptionValue, sizeof(*context) );
  962. context->SocketHandle = SocketHandle;
  963. //
  964. // Tell the Windows Sockets DLL where our context information is
  965. // stored so that it can return the context pointer in future
  966. // calls.
  967. //
  968. *(PWSHATM_SOCKET_CONTEXT *)OptionValue = context;
  969. return NO_ERROR;
  970. } else {
  971. PWSHATM_SOCKET_CONTEXT parentContext;
  972. INT one = 1;
  973. INT zero = 0;
  974. //
  975. // The socket was accept()'ed and it needs to have the same
  976. // properties as it's parent. The OptionValue buffer
  977. // contains the context information of this socket's parent.
  978. //
  979. parentContext = (PWSHATM_SOCKET_CONTEXT)OptionValue;
  980. ASSERT( context->AddressFamily == parentContext->AddressFamily );
  981. ASSERT( context->SocketType == parentContext->SocketType );
  982. ASSERT( context->Protocol == parentContext->Protocol );
  983. return NO_ERROR;
  984. }
  985. }
  986. return WSAENOPROTOOPT;
  987. #if 0
  988. //
  989. // Handle socket-level options.
  990. //
  991. optionValue = *OptionValue;
  992. switch ( OptionName ) {
  993. case SO_RCVBUF:
  994. context->ReceiveBufferSize = optionValue;
  995. break;
  996. default:
  997. return WSAENOPROTOOPT;
  998. }
  999. return NO_ERROR;
  1000. #endif
  1001. } // WSHSetSocketInformation
  1002. INT
  1003. WSHEnumProtocols (
  1004. IN LPINT lpiProtocols,
  1005. IN LPWSTR lpTransportKeyName,
  1006. IN OUT LPVOID lpProtocolBuffer,
  1007. IN OUT LPDWORD lpdwBufferLength
  1008. )
  1009. /*++
  1010. Routine Description:
  1011. Enumerates the protocols supported by this helper.
  1012. Arguments:
  1013. lpiProtocols - Pointer to a NULL-terminated array of protocol
  1014. identifiers. Only protocols specified in this array will
  1015. be returned by this function. If this pointer is NULL,
  1016. all protocols are returned.
  1017. lpTransportKeyName -
  1018. lpProtocolBuffer - Pointer to a buffer to fill with PROTOCOL_INFO
  1019. structures.
  1020. lpdwBufferLength - Pointer to a variable that, on input, contains
  1021. the size of lpProtocolBuffer. On output, this value will be
  1022. updated with the size of the data actually written to the buffer.
  1023. Return Value:
  1024. INT - The number of protocols returned if successful, -1 if not.
  1025. --*/
  1026. {
  1027. DWORD bytesRequired;
  1028. PPROTOCOL_INFO atmProtocolInfo;
  1029. PPROTOCOL_INFO udpProtocolInfo;
  1030. BOOL useAtm = FALSE;
  1031. DWORD i;
  1032. lpTransportKeyName; // Avoid compiler warnings.
  1033. DBGPRINT(("EnumProtocols\n"));
  1034. //
  1035. // Make sure that the caller cares about ATM.
  1036. //
  1037. if ( ARGUMENT_PRESENT( lpiProtocols ) ) {
  1038. for ( i = 0; lpiProtocols[i] != 0; i++ ) {
  1039. if ( lpiProtocols[i] == ATMPROTO_AAL5 ) {
  1040. useAtm = TRUE;
  1041. }
  1042. }
  1043. } else {
  1044. useAtm = TRUE;
  1045. }
  1046. if ( !useAtm ) {
  1047. *lpdwBufferLength = 0;
  1048. return 0;
  1049. }
  1050. //
  1051. // Make sure that the caller has specified a sufficiently large
  1052. // buffer.
  1053. //
  1054. bytesRequired = (DWORD)((sizeof(PROTOCOL_INFO) * 1) +
  1055. ( (wcslen( ATM_NAME ) + 1) * sizeof(WCHAR)));
  1056. if ( bytesRequired > *lpdwBufferLength ) {
  1057. *lpdwBufferLength = bytesRequired;
  1058. return -1;
  1059. }
  1060. //
  1061. // Fill in ATM info, if requested.
  1062. //
  1063. if ( useAtm ) {
  1064. atmProtocolInfo = lpProtocolBuffer;
  1065. atmProtocolInfo->dwServiceFlags = XP_GUARANTEED_ORDER |
  1066. XP_MESSAGE_ORIENTED |
  1067. XP_SUPPORTS_MULTICAST |
  1068. XP_BANDWIDTH_ALLOCATION ;
  1069. atmProtocolInfo->iAddressFamily = AF_ATM;
  1070. atmProtocolInfo->iMaxSockAddr = sizeof(SOCKADDR_ATM);
  1071. atmProtocolInfo->iMinSockAddr = sizeof(SOCKADDR_ATM);
  1072. atmProtocolInfo->iSocketType = ATM_AAL5_SOCK_TYPE;
  1073. atmProtocolInfo->iProtocol = ATMPROTO_AAL5;
  1074. atmProtocolInfo->dwMessageSize = 1;
  1075. atmProtocolInfo->lpProtocol = (LPWSTR)
  1076. ( (PBYTE)lpProtocolBuffer + *lpdwBufferLength -
  1077. ( (wcslen( ATM_NAME ) + 1) * sizeof(WCHAR) ) );
  1078. wcscpy( atmProtocolInfo->lpProtocol, ATM_NAME );
  1079. DBGPRINT(("EnumProtocols: lpProtocolBuffer %x, lpProtocol %x, BufLen %d\n",
  1080. lpProtocolBuffer,
  1081. atmProtocolInfo->lpProtocol,
  1082. *lpdwBufferLength));
  1083. }
  1084. *lpdwBufferLength = bytesRequired;
  1085. return (1);
  1086. } // WSHEnumProtocols
  1087. BOOLEAN
  1088. IsTripleInList (
  1089. IN PMAPPING_TRIPLE List,
  1090. IN ULONG ListLength,
  1091. IN INT AddressFamily,
  1092. IN INT SocketType,
  1093. IN INT Protocol
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. Determines whether the specified triple has an exact match in the
  1098. list of triples.
  1099. Arguments:
  1100. List - a list of triples (address family/socket type/protocol) to
  1101. search.
  1102. ListLength - the number of triples in the list.
  1103. AddressFamily - the address family to look for in the list.
  1104. SocketType - the socket type to look for in the list.
  1105. Protocol - the protocol to look for in the list.
  1106. Return Value:
  1107. BOOLEAN - TRUE if the triple was found in the list, false if not.
  1108. --*/
  1109. {
  1110. ULONG i;
  1111. //
  1112. // Walk through the list searching for an exact match.
  1113. //
  1114. for ( i = 0; i < ListLength; i++ ) {
  1115. //
  1116. // If all three elements of the triple match, return indicating
  1117. // that the triple did exist in the list.
  1118. //
  1119. if ( AddressFamily == List[i].AddressFamily &&
  1120. SocketType == List[i].SocketType &&
  1121. Protocol == List[i].Protocol
  1122. ) {
  1123. return TRUE;
  1124. }
  1125. }
  1126. //
  1127. // The triple was not found in the list.
  1128. //
  1129. return FALSE;
  1130. } // IsTripleInList
  1131. INT
  1132. WINAPI
  1133. WSHJoinLeaf (
  1134. IN PVOID HelperDllSocketContext,
  1135. IN SOCKET SocketHandle,
  1136. IN HANDLE TdiAddressObjectHandle,
  1137. IN HANDLE TdiConnectionObjectHandle,
  1138. IN PVOID LeafHelperDllSocketContext,
  1139. IN SOCKET LeafSocketHandle,
  1140. IN PSOCKADDR Sockaddr,
  1141. IN DWORD SockaddrLength,
  1142. IN LPWSABUF CallerData,
  1143. IN LPWSABUF CalleeData,
  1144. IN LPQOS SocketQOS,
  1145. IN LPQOS GroupQOS,
  1146. IN DWORD Flags
  1147. )
  1148. /*++
  1149. Routine Description:
  1150. Performs the protocol-dependent portion of creating a multicast
  1151. socket.
  1152. TBD: Needs a Lot Of Work!
  1153. Arguments:
  1154. The following four parameters correspond to the socket passed into
  1155. the WSAJoinLeaf() API:
  1156. HelperDllSocketContext - The context pointer returned from
  1157. WSHOpenSocket().
  1158. SocketHandle - The handle of the socket used to establish the
  1159. multicast "session".
  1160. TdiAddressObjectHandle - The TDI address object of the socket, if
  1161. any. If the socket is not yet bound to an address, then
  1162. it does not have a TDI address object and this parameter
  1163. will be NULL.
  1164. TdiConnectionObjectHandle - The TDI connection object of the socket,
  1165. if any. If the socket is not yet connected, then it does not
  1166. have a TDI connection object and this parameter will be NULL.
  1167. The next two parameters correspond to the newly created socket that
  1168. identifies the multicast "session":
  1169. LeafHelperDllSocketContext - The context pointer returned from
  1170. WSHOpenSocket().
  1171. LeafSocketHandle - The handle of the socket that identifies the
  1172. multicast "session".
  1173. Sockaddr - The name of the peer to which the socket is to be joined.
  1174. SockaddrLength - The length of Sockaddr.
  1175. CallerData - Pointer to user data to be transferred to the peer
  1176. during multipoint session establishment.
  1177. CalleeData - Pointer to user data to be transferred back from
  1178. the peer during multipoint session establishment.
  1179. SocketQOS - Pointer to the flowspecs for SocketHandle, one in each
  1180. direction.
  1181. GroupQOS - Pointer to the flowspecs for the socket group, if any.
  1182. Flags - Flags to indicate if the socket is acting as sender,
  1183. receiver, or both.
  1184. Return Value:
  1185. INT - 0 if successful, a WinSock error code if not.
  1186. --*/
  1187. {
  1188. INT err;
  1189. if( Flags != JL_SENDER_ONLY ) {
  1190. return WSAEINVAL;
  1191. }
  1192. if (SocketQOS)
  1193. {
  1194. err = WSHAtmSetQoS(
  1195. LeafHelperDllSocketContext,
  1196. LeafSocketHandle,
  1197. SocketQOS,
  1198. sizeof(*SocketQOS)
  1199. );
  1200. }
  1201. return NO_ERROR;
  1202. } // WSHJoinLeaf
  1203. INT
  1204. WINAPI
  1205. WSHGetBroadcastSockaddr (
  1206. IN PVOID HelperDllSocketContext,
  1207. OUT PSOCKADDR Sockaddr,
  1208. OUT PINT SockaddrLength
  1209. )
  1210. /*++
  1211. Routine Description:
  1212. This routine returns a broadcast socket address. A broadcast address
  1213. may be used as a destination for the sendto() API to send a datagram
  1214. to all interested clients.
  1215. Arguments:
  1216. HelperDllSocketContext - the context pointer returned from
  1217. WSHOpenSocket() for the socket for which we need a broadcast
  1218. address.
  1219. Sockaddr - points to a buffer which will receive the broadcast socket
  1220. address.
  1221. SockaddrLength - receives the length of the broadcast sockaddr.
  1222. Return Value:
  1223. INT - a winsock error code indicating the status of the operation, or
  1224. NO_ERROR if the operation succeeded.
  1225. --*/
  1226. {
  1227. #if 1
  1228. return WSAEINVAL;
  1229. #else
  1230. LPSOCKADDR_ATM addr;
  1231. if( *SockaddrLength < sizeof(SOCKADDR_ATM) ) {
  1232. return WSAEFAULT;
  1233. }
  1234. *SockaddrLength = sizeof(SOCKADDR_ATM);
  1235. //
  1236. // Build the broadcast address.
  1237. //
  1238. addr = (LPSOCKADDR_ATM)Sockaddr;
  1239. RtlZeroMemory(
  1240. addr,
  1241. sizeof(*addr)
  1242. );
  1243. addr->satm_family = AF_ATM;
  1244. addr->satm_number.s_addr = htonl( INADDR_BROADCAST );
  1245. return NO_ERROR;
  1246. #endif // 1
  1247. } // WSAGetBroadcastSockaddr
  1248. INT
  1249. WINAPI
  1250. WSHGetWSAProtocolInfo (
  1251. IN LPWSTR ProviderName,
  1252. OUT LPWSAPROTOCOL_INFOW * ProtocolInfo,
  1253. OUT LPDWORD ProtocolInfoEntries
  1254. )
  1255. /*++
  1256. Routine Description:
  1257. Retrieves a pointer to the WSAPROTOCOL_INFOW structure(s) describing
  1258. the protocol(s) supported by this helper.
  1259. Arguments:
  1260. ProviderName - Contains the name of the provider, such as "RawWan".
  1261. ProtocolInfo - Receives a pointer to the WSAPROTOCOL_INFOW array.
  1262. ProtocolInfoEntries - Receives the number of entries in the array.
  1263. Return Value:
  1264. INT - 0 if successful, WinSock error code if not.
  1265. --*/
  1266. {
  1267. if( ProviderName == NULL ||
  1268. ProtocolInfo == NULL ||
  1269. ProtocolInfoEntries == NULL ) {
  1270. return WSAEFAULT;
  1271. }
  1272. DBGPRINT(("WSHGetWSAProtocolInfo: Provider Name: %ws\n", ProviderName));
  1273. if( _wcsicmp( ProviderName, L"RawWan" ) == 0 ) {
  1274. *ProtocolInfo = Winsock2Protocols;
  1275. *ProtocolInfoEntries = NUM_WINSOCK2_PROTOCOLS;
  1276. return NO_ERROR;
  1277. }
  1278. return WSAEINVAL;
  1279. } // WSHGetWSAProtocolInfo
  1280. INT
  1281. WINAPI
  1282. WSHAddressToString (
  1283. IN LPSOCKADDR Address,
  1284. IN INT AddressLength,
  1285. IN LPWSAPROTOCOL_INFOW ProtocolInfo,
  1286. OUT LPWSTR AddressString,
  1287. IN OUT LPDWORD AddressStringLength
  1288. )
  1289. /*++
  1290. Routine Description:
  1291. Converts a SOCKADDR to a human-readable form.
  1292. Arguments:
  1293. Address - The SOCKADDR to convert.
  1294. AddressLength - The length of Address.
  1295. ProtocolInfo - The WSAPROTOCOL_INFOW for a particular provider.
  1296. AddressString - Receives the formatted address string.
  1297. AddressStringLength - On input, contains the length of AddressString.
  1298. On output, contains the number of characters actually written
  1299. to AddressString.
  1300. Return Value:
  1301. INT - 0 if successful, WinSock error code if not.
  1302. --*/
  1303. {
  1304. WCHAR string[64];
  1305. PWCHAR pstring;
  1306. INT length; // Number of WCHARs filled into string
  1307. UINT i;
  1308. LPSOCKADDR_ATM addr;
  1309. UCHAR Val;
  1310. //
  1311. // Quick sanity checks.
  1312. //
  1313. if( Address == NULL ||
  1314. AddressLength < sizeof(SOCKADDR_ATM) ||
  1315. AddressString == NULL ||
  1316. AddressStringLength == NULL ) {
  1317. return WSAEFAULT;
  1318. }
  1319. addr = (LPSOCKADDR_ATM)Address;
  1320. if( addr->satm_family != AF_ATM ) {
  1321. return WSAEINVAL;
  1322. }
  1323. if ( addr->satm_number.NumofDigits > ATM_ADDR_SIZE ) {
  1324. return WSAEINVAL;
  1325. }
  1326. //
  1327. // Do the conversion.
  1328. //
  1329. length = 0;
  1330. pstring = string;
  1331. //
  1332. // If this is an E.164 address, prepend a '+'.
  1333. // Each entry in the array in satm_number consists of one
  1334. // digit coded in IA5 (ANSI).
  1335. //
  1336. if ( addr->satm_number.AddressType == ATM_E164 ) {
  1337. *pstring++ = L'+';
  1338. length++;
  1339. for ( i = 0; i < addr->satm_number.NumofDigits; i++ ) {
  1340. if ( !iswdigit(addr->satm_number.Addr[i]) ) {
  1341. return WSAEINVAL;
  1342. }
  1343. *pstring++ = ANSI_TO_WCHAR(addr->satm_number.Addr[i]);
  1344. }
  1345. length += addr->satm_number.NumofDigits;
  1346. } else {
  1347. //
  1348. // This must be NSAP format. Each entry in the array
  1349. // is a full hex byte (two BCD digits). We'll unpack
  1350. // each array entry into two characters.
  1351. //
  1352. for ( i = 0; i < addr->satm_number.NumofDigits; i++ ) {
  1353. Val = (addr->satm_number.Addr[i] >> 4);
  1354. *pstring++ = DIGIT_TO_WCHAR(Val);
  1355. Val = (addr->satm_number.Addr[i] & 0xf);
  1356. *pstring++ = DIGIT_TO_WCHAR(Val);
  1357. }
  1358. length += (2 * addr->satm_number.NumofDigits);
  1359. }
  1360. //
  1361. // Terminate the string.
  1362. //
  1363. *pstring = L'\0';
  1364. length++; // account for terminator
  1365. if( *AddressStringLength < (DWORD)length ) {
  1366. return WSAEFAULT;
  1367. }
  1368. *AddressStringLength = (DWORD)length;
  1369. RtlCopyMemory(
  1370. AddressString,
  1371. string,
  1372. length * sizeof(WCHAR)
  1373. );
  1374. return NO_ERROR;
  1375. } // WSHAddressToString
  1376. INT
  1377. WINAPI
  1378. WSHStringToAddress (
  1379. IN LPWSTR AddressString,
  1380. IN DWORD AddressFamily,
  1381. IN LPWSAPROTOCOL_INFOW ProtocolInfo,
  1382. OUT LPSOCKADDR Address,
  1383. IN OUT LPINT AddressLength
  1384. )
  1385. /*++
  1386. Routine Description:
  1387. Fills in a SOCKADDR structure by parsing a human-readable string.
  1388. Arguments:
  1389. AddressString - Points to the zero-terminated human-readable string.
  1390. AddressFamily - The address family to which the string belongs.
  1391. ProtocolInfo - The WSAPROTOCOL_INFOW for a particular provider.
  1392. Address - Receives the SOCKADDR structure.
  1393. AddressLength - On input, contains the length of Address. On output,
  1394. contains the number of bytes actually written to Address.
  1395. Return Value:
  1396. INT - 0 if successful, WinSock error code if not.
  1397. --*/
  1398. {
  1399. WCHAR string[2*ATM_ADDR_SIZE+1];
  1400. UNICODE_STRING unistring;
  1401. CHAR ansistring[2*ATM_ADDR_SIZE+1];
  1402. ANSI_STRING ansstring;
  1403. PCHAR src;
  1404. PCHAR dst;
  1405. LPWSTR terminator;
  1406. LPSOCKADDR_ATM addr;
  1407. PWCHAR s, d;
  1408. INT numDigits, i;
  1409. NTSTATUS status;
  1410. //
  1411. // Quick sanity checks.
  1412. //
  1413. if( AddressString == NULL ||
  1414. Address == NULL ||
  1415. AddressLength == NULL ||
  1416. *AddressLength < sizeof(SOCKADDR_ATM) ) {
  1417. return WSAEFAULT;
  1418. }
  1419. if( AddressFamily != AF_ATM ) {
  1420. DBGPRINT(("StrToAddr: invalid addrfam %d\n", AddressFamily));
  1421. return WSAEINVAL;
  1422. }
  1423. addr = (LPSOCKADDR_ATM)Address;
  1424. RtlZeroMemory(
  1425. Address,
  1426. sizeof(SOCKADDR_ATM)
  1427. );
  1428. //
  1429. // Strip off all punctuation characters (spaces and periods).
  1430. //
  1431. for ( numDigits = 0, s = AddressString, d = string;
  1432. (numDigits <= sizeof(WCHAR)*ATM_ADDR_SIZE) && (*s != L'\0');
  1433. s++ ) {
  1434. if ( *s == ATM_ADDR_BLANK_CHAR ||
  1435. *s == ATM_ADDR_PUNCTUATION_CHAR ) {
  1436. continue;
  1437. }
  1438. *d++ = *s;
  1439. numDigits ++;
  1440. }
  1441. if ( numDigits == 0 ) {
  1442. DBGPRINT(("StrToAddr[%ws]: numdigits after stripping is 0!\n",
  1443. AddressString));
  1444. return WSAEINVAL;
  1445. }
  1446. //
  1447. // Terminate it and convert into Unicode string.
  1448. //
  1449. *d = L'\0';
  1450. RtlInitUnicodeString(&unistring, string);
  1451. //
  1452. // Convert it into an ANSI string.
  1453. //
  1454. ansstring.Buffer = ansistring;
  1455. ansstring.MaximumLength = 2*ATM_ADDR_SIZE + 1;
  1456. ansstring.Length = 0;
  1457. status = RtlUnicodeStringToAnsiString(&ansstring, &unistring, FALSE);
  1458. if ( status != STATUS_SUCCESS ) {
  1459. DBGPRINT(("StrToAddr[%ws]: RtlUnicodeToAnsi failed (%x)\n",
  1460. string, status));
  1461. return WSAEINVAL;
  1462. }
  1463. addr->satm_family = AF_ATM;
  1464. src = ansistring;
  1465. if ( *src == ATM_ADDR_E164_START_CHAR ) {
  1466. src ++;
  1467. numDigits --;
  1468. if ( numDigits == 0 ) {
  1469. DBGPRINT(("StrToAddr[%ws]: AnsiString:[%s], numDigits is 0!\n",
  1470. string, ansistring));
  1471. return WSAEINVAL;
  1472. }
  1473. addr->satm_number.AddressType = ATM_E164;
  1474. addr->satm_number.NumofDigits = numDigits;
  1475. RtlCopyMemory(addr->satm_number.Addr, src, numDigits);
  1476. } else {
  1477. UCHAR hexString[3];
  1478. ULONG Val;
  1479. hexString[2] = 0;
  1480. if ( numDigits != 2 * ATM_ADDR_SIZE ) {
  1481. return WSAEINVAL;
  1482. }
  1483. addr->satm_number.AddressType = ATM_NSAP;
  1484. addr->satm_number.NumofDigits = numDigits/2;
  1485. for ( i = 0; i < ATM_ADDR_SIZE; i++ ) {
  1486. hexString[0] = *src++;
  1487. hexString[1] = *src++;
  1488. status = RtlCharToInteger(hexString, 16, &Val);
  1489. if ( status != STATUS_SUCCESS ) {
  1490. DBGPRINT(("StrToAtm[%ws]: index %d, hexString: %s, CharToInt %x\n",
  1491. string, hexString, status));
  1492. return WSAEINVAL;
  1493. }
  1494. addr->satm_number.Addr[i] = (UCHAR)Val;
  1495. }
  1496. }
  1497. addr->satm_blli.Layer2Protocol = SAP_FIELD_ABSENT;
  1498. addr->satm_blli.Layer3Protocol = SAP_FIELD_ABSENT;
  1499. addr->satm_bhli.HighLayerInfoType = SAP_FIELD_ABSENT;
  1500. *AddressLength = sizeof(SOCKADDR_ATM);
  1501. return NO_ERROR;
  1502. } // WSHStringToAddress
  1503. INT
  1504. WINAPI
  1505. WSHGetProviderGuid (
  1506. IN LPWSTR ProviderName,
  1507. OUT LPGUID ProviderGuid
  1508. )
  1509. /*++
  1510. Routine Description:
  1511. Returns the GUID identifying the protocols supported by this helper.
  1512. Arguments:
  1513. ProviderName - Contains the name of the provider, such as "RawWan".
  1514. ProviderGuid - Points to a buffer that receives the provider's GUID.
  1515. Return Value:
  1516. INT - 0 if successful, WinSock error code if not.
  1517. --*/
  1518. {
  1519. if( ProviderName == NULL ||
  1520. ProviderGuid == NULL ) {
  1521. return WSAEFAULT;
  1522. }
  1523. if( _wcsicmp( ProviderName, RWAN_NAME ) == 0 ) {
  1524. RtlCopyMemory(
  1525. ProviderGuid,
  1526. &AtmProviderGuid,
  1527. sizeof(GUID)
  1528. );
  1529. return NO_ERROR;
  1530. }
  1531. return WSAEINVAL;
  1532. } // WSHGetProviderGuid
  1533. INT
  1534. WINAPI
  1535. WSHIoctl (
  1536. IN PVOID HelperDllSocketContext,
  1537. IN SOCKET SocketHandle,
  1538. IN HANDLE TdiAddressObjectHandle,
  1539. IN HANDLE TdiConnectionObjectHandle,
  1540. IN DWORD IoControlCode,
  1541. IN LPVOID InputBuffer,
  1542. IN DWORD InputBufferLength,
  1543. IN LPVOID OutputBuffer,
  1544. IN DWORD OutputBufferLength,
  1545. OUT LPDWORD NumberOfBytesReturned,
  1546. IN LPWSAOVERLAPPED Overlapped,
  1547. IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine,
  1548. OUT LPBOOL NeedsCompletion
  1549. )
  1550. /*++
  1551. Routine Description:
  1552. Performs queries & controls on the socket. This is basically an
  1553. "escape hatch" for IOCTLs not supported by MSAFD.DLL. Any unknown
  1554. IOCTLs are routed to the socket's helper DLL for protocol-specific
  1555. processing.
  1556. Arguments:
  1557. HelperDllSocketContext - the context pointer returned from
  1558. WSHOpenSocket().
  1559. SocketHandle - the handle of the socket for which we're controlling.
  1560. TdiAddressObjectHandle - the TDI address object of the socket, if
  1561. any. If the socket is not yet bound to an address, then
  1562. it does not have a TDI address object and this parameter
  1563. will be NULL.
  1564. TdiConnectionObjectHandle - the TDI connection object of the socket,
  1565. if any. If the socket is not yet connected, then it does not
  1566. have a TDI connection object and this parameter will be NULL.
  1567. IoControlCode - Control code of the operation to perform.
  1568. InputBuffer - Address of the input buffer.
  1569. InputBufferLength - The length of InputBuffer.
  1570. OutputBuffer - Address of the output buffer.
  1571. OutputBufferLength - The length of OutputBuffer.
  1572. NumberOfBytesReturned - Receives the number of bytes actually written
  1573. to the output buffer.
  1574. Overlapped - Pointer to a WSAOVERLAPPED structure for overlapped
  1575. operations.
  1576. CompletionRoutine - Pointer to a completion routine to call when
  1577. the operation is completed.
  1578. NeedsCompletion - WSAIoctl() can be overlapped, with all the gory
  1579. details that involves, such as setting events, queuing completion
  1580. routines, and posting to IO completion ports. Since the majority
  1581. of the IOCTL codes can be completed quickly "in-line", MSAFD.DLL
  1582. can optionally perform the overlapped completion of the operation.
  1583. Setting *NeedsCompletion to TRUE (the default) causes MSAFD.DLL
  1584. to handle all of the IO completion details iff this is an
  1585. overlapped operation on an overlapped socket.
  1586. Setting *NeedsCompletion to FALSE tells MSAFD.DLL to take no
  1587. further action because the helper DLL will perform any necessary
  1588. IO completion.
  1589. Note that if a helper performs its own IO completion, the helper
  1590. is responsible for maintaining the "overlapped" mode of the socket
  1591. at socket creation time and NOT performing overlapped IO completion
  1592. on non-overlapped sockets.
  1593. Return Value:
  1594. INT - 0 if successful, WinSock error code if not.
  1595. --*/
  1596. {
  1597. INT err;
  1598. PWSHATM_SOCKET_CONTEXT context;
  1599. //
  1600. // Quick sanity checks.
  1601. //
  1602. if( HelperDllSocketContext == NULL ||
  1603. SocketHandle == INVALID_SOCKET ||
  1604. NumberOfBytesReturned == NULL ||
  1605. NeedsCompletion == NULL ) {
  1606. return WSAEINVAL;
  1607. }
  1608. context = (PWSHATM_SOCKET_CONTEXT)HelperDllSocketContext;
  1609. *NeedsCompletion = TRUE;
  1610. DBGPRINT(("WSHIoctl: IoControlCode x%x, InBuf: x%x/%d, OutBuf: x%x/%d\n",
  1611. IoControlCode,
  1612. InputBuffer,
  1613. InputBufferLength,
  1614. OutputBuffer,
  1615. OutputBufferLength));
  1616. switch (IoControlCode) {
  1617. case SIO_ASSOCIATE_PVC:
  1618. context->SocketHandle = SocketHandle;
  1619. err = AtmAssociatePVC(
  1620. SocketHandle,
  1621. HelperDllSocketContext,
  1622. TdiAddressObjectHandle,
  1623. TdiConnectionObjectHandle,
  1624. InputBuffer,
  1625. InputBufferLength
  1626. );
  1627. DBGPRINT(("WSHIoctl: ASSOCIATE_PVC: context %x, LocalFlags %x, err %d\n",
  1628. context, context->LocalFlags, err));
  1629. if ( (err == NO_ERROR) &&
  1630. (( context->LocalFlags & WSHATM_SOCK_IS_BOUND ) == 0 )) {
  1631. SOCKADDR_ATM addr;
  1632. INT len = sizeof(addr);
  1633. (VOID) WSHGetWildcardSockaddr (
  1634. HelperDllSocketContext,
  1635. (struct sockaddr *)&addr,
  1636. &len);
  1637. DBGPRINT(("WSHIoctl: ASSOCIATE_PVC: will bind\n"));
  1638. err = bind(SocketHandle, (struct sockaddr *)&addr, len);
  1639. #if DBG
  1640. if ( err != NO_ERROR ) {
  1641. DbgPrint("WSHATM: bind err %d, context %x, LocalFlags %x\n",
  1642. err, context, context->LocalFlags);
  1643. }
  1644. #endif
  1645. }
  1646. if ( err == NO_ERROR ) {
  1647. SOCKADDR_ATM addr;
  1648. INT len = sizeof(addr);
  1649. (VOID) WSHGetWildcardSockaddr (
  1650. HelperDllSocketContext,
  1651. (struct sockaddr *)&addr,
  1652. &len);
  1653. addr.satm_family = AF_ATM;
  1654. addr.satm_number.AddressType = ATM_NSAP;
  1655. addr.satm_number.NumofDigits = ATM_ADDR_SIZE;
  1656. err = WSAConnect(
  1657. SocketHandle,
  1658. (struct sockaddr *)&addr,
  1659. len,
  1660. NULL,
  1661. NULL,
  1662. NULL,
  1663. NULL);
  1664. if ( err != NO_ERROR ) {
  1665. DBGPRINT(("WSHIoctl: connect (%d) returned %d\n",
  1666. SocketHandle, err));
  1667. if ( err == SOCKET_ERROR ) {
  1668. err = WSAGetLastError();
  1669. }
  1670. }
  1671. }
  1672. break;
  1673. case SIO_SET_QOS:
  1674. err = WSHAtmSetQoS(
  1675. HelperDllSocketContext,
  1676. SocketHandle,
  1677. InputBuffer,
  1678. InputBufferLength
  1679. );
  1680. break;
  1681. case SIO_GET_QOS:
  1682. err = WSHAtmGetQoS(
  1683. HelperDllSocketContext,
  1684. SocketHandle,
  1685. OutputBuffer,
  1686. OutputBufferLength,
  1687. NumberOfBytesReturned
  1688. );
  1689. break;
  1690. case SIO_GET_GROUP_QOS:
  1691. *NumberOfBytesReturned = 0;
  1692. err = NO_ERROR;
  1693. break;
  1694. case SIO_SET_GROUP_QOS:
  1695. *NumberOfBytesReturned = 0;
  1696. err = WSAEOPNOTSUPP;
  1697. break;
  1698. case SIO_GET_NUMBER_OF_ATM_DEVICES:
  1699. err = AtmQueryAtmGlobalInformation(
  1700. ATMSP_OID_NUMBER_OF_DEVICES,
  1701. NULL,
  1702. 0,
  1703. OutputBuffer,
  1704. OutputBufferLength,
  1705. NumberOfBytesReturned
  1706. );
  1707. break;
  1708. case SIO_GET_ATM_ADDRESS:
  1709. err = AtmQueryAtmGlobalInformation(
  1710. ATMSP_OID_ATM_ADDRESS,
  1711. InputBuffer,
  1712. InputBufferLength,
  1713. OutputBuffer,
  1714. OutputBufferLength,
  1715. NumberOfBytesReturned
  1716. );
  1717. break;
  1718. case SIO_GET_ATM_CONNECTION_ID:
  1719. if ( TdiConnectionObjectHandle == NULL ) {
  1720. //
  1721. // Check if this is a PVC. If so, the Connection ID is
  1722. // available locally.
  1723. //
  1724. if ( context && ( context->LocalFlags & WSHATM_SOCK_IS_PVC )) {
  1725. if ( ( OutputBuffer != NULL ) &&
  1726. ( OutputBufferLength >= sizeof(ATM_CONNECTION_ID) ) ) {
  1727. ATM_CONNECTION_ID * pConnId = OutputBuffer;
  1728. *pConnId = context->ConnectionId;
  1729. err = NO_ERROR;
  1730. } else {
  1731. err = WSAEFAULT;
  1732. }
  1733. } else {
  1734. err = WSAENOTCONN;
  1735. }
  1736. } else {
  1737. err = AtmGetAtmObjectInformation(
  1738. TdiConnectionObjectHandle,
  1739. IOCTL_RWAN_MEDIA_SPECIFIC_CONN_HANDLE_QUERY,
  1740. ATMSP_OID_CONNECTION_ID,
  1741. InputBuffer,
  1742. InputBufferLength,
  1743. OutputBuffer,
  1744. OutputBufferLength,
  1745. NumberOfBytesReturned
  1746. );
  1747. }
  1748. break;
  1749. case SIO_ENABLE_CIRCULAR_QUEUEING:
  1750. err = NO_ERROR;
  1751. break;
  1752. default:
  1753. err = WSAEINVAL;
  1754. break;
  1755. }
  1756. DBGPRINT(("WSHIoctl: IoControlCode x%x, returning %d\n",
  1757. IoControlCode, err));
  1758. return err;
  1759. } // WSHIoctl
  1760. INT
  1761. WSHAtmSetQoS(
  1762. IN PVOID HelperDllSocketContext,
  1763. IN SOCKET SocketHandle,
  1764. IN LPVOID InputBuffer,
  1765. IN DWORD InputBufferLength
  1766. )
  1767. /*++
  1768. Routine Description:
  1769. This routine is called to process a SIO_SET_QOS Ioctl. The QoS is represented
  1770. by a basic QOS structure, and an optional provider-specific part. We first
  1771. copy this two-part structure into a single flat buffer, and then call
  1772. setsockopt(SO_CONNOPT) to get MSAFD to copy this down to AFD. Later, if/when
  1773. a WSAConnect() is made, AFD will pass these "connection options" in the TDI
  1774. connect to the transport.
  1775. Arguments:
  1776. HelperDllSocketContext - the context pointer returned from
  1777. WSHOpenSocket().
  1778. SocketHandle - the handle of the socket for which we're controlling.
  1779. InputBuffer - Address of the input buffer.
  1780. InputBufferLength - The length of InputBuffer.
  1781. Return Value:
  1782. INT - The completion status.
  1783. --*/
  1784. {
  1785. INT err;
  1786. LPQOS lpQOS;
  1787. PUCHAR pQoSBuffer; // Flat buffer for use in SO_CONNOPT
  1788. INT QoSBufferLength;
  1789. LPQOS lpOutputQOS;
  1790. err = NO_ERROR;
  1791. lpQOS = (LPQOS)InputBuffer;
  1792. DBGPRINT(("SetQoS: Context x%x, Handle x%x, InBuf x%x, InBufLen %d\n",
  1793. HelperDllSocketContext,
  1794. SocketHandle,
  1795. InputBuffer,
  1796. InputBufferLength));
  1797. do
  1798. {
  1799. if (lpQOS == NULL)
  1800. {
  1801. err = WSAEINVAL;
  1802. break;
  1803. }
  1804. //
  1805. // Expect atleast the base QOS structure to be present.
  1806. //
  1807. if (InputBufferLength < sizeof(*lpQOS))
  1808. {
  1809. err = WSAENOBUFS;
  1810. break;
  1811. }
  1812. //
  1813. // Sanity check the provider-specific part.
  1814. //
  1815. if (((lpQOS->ProviderSpecific.buf != NULL) &&
  1816. (lpQOS->ProviderSpecific.len == 0))
  1817. ||
  1818. ((lpQOS->ProviderSpecific.buf == NULL) &&
  1819. (lpQOS->ProviderSpecific.len != 0)))
  1820. {
  1821. DBGPRINT(("lpQOS %x, buf %x, len %x, not consistent\n",
  1822. lpQOS, lpQOS->ProviderSpecific.buf,
  1823. lpQOS->ProviderSpecific.len));
  1824. err = WSAEINVAL;
  1825. break;
  1826. }
  1827. //
  1828. // Compute the total length we need.
  1829. //
  1830. QoSBufferLength = sizeof(QOS) + lpQOS->ProviderSpecific.len;
  1831. pQoSBuffer = RTL_ALLOCATE_HEAP(RtlProcessHeap(), 0, QoSBufferLength);
  1832. if (pQoSBuffer == NULL)
  1833. {
  1834. err = WSAENOBUFS;
  1835. break;
  1836. }
  1837. lpOutputQOS = (LPQOS)pQoSBuffer;
  1838. //
  1839. // Copy in the generic QOS part.
  1840. //
  1841. RtlCopyMemory(
  1842. lpOutputQOS,
  1843. lpQOS,
  1844. sizeof(QOS)
  1845. );
  1846. //
  1847. // Copy in the provider-specific QOS just after the generic part.
  1848. //
  1849. if (lpQOS->ProviderSpecific.len != 0)
  1850. {
  1851. RtlCopyMemory(
  1852. (PCHAR)pQoSBuffer+sizeof(QOS),
  1853. lpQOS->ProviderSpecific.buf,
  1854. lpQOS->ProviderSpecific.len
  1855. );
  1856. //
  1857. // Set up the offset to provider-specific part. Note that we
  1858. // use the "buf" to mean the offset from the beginning of the
  1859. // flat QOS buffer and not a pointer.
  1860. //
  1861. lpOutputQOS->ProviderSpecific.buf = (char FAR *)sizeof(QOS);
  1862. }
  1863. else
  1864. {
  1865. lpOutputQOS->ProviderSpecific.buf = NULL;
  1866. }
  1867. //
  1868. // Request the Winsock DLL to set the options.
  1869. //
  1870. err = setsockopt(
  1871. SocketHandle,
  1872. SOL_SOCKET,
  1873. SO_CONNOPT,
  1874. pQoSBuffer,
  1875. QoSBufferLength
  1876. );
  1877. RTL_FREE_HEAP(
  1878. RtlProcessHeap(),
  1879. 0,
  1880. pQoSBuffer
  1881. );
  1882. break;
  1883. }
  1884. while (FALSE);
  1885. DBGPRINT(("SetQoS: returning err %d\n", err));
  1886. return (err);
  1887. }
  1888. INT
  1889. WSHAtmGetQoS(
  1890. IN PVOID HelperDllSocketContext,
  1891. IN SOCKET SocketHandle,
  1892. IN LPVOID OutputBuffer,
  1893. IN DWORD OutputBufferLength,
  1894. OUT LPDWORD NumberOfBytesReturned
  1895. )
  1896. /*++
  1897. Routine Description:
  1898. This routine is called to process a SIO_GET_QOS Ioctl. We translate
  1899. this to a "Get Connect Options" and ask MSAFD to get them for us.
  1900. The connect options for ATM will contain the base QoS structure and
  1901. optionally a provider-specific part that contains additional information
  1902. elements.
  1903. One of the places this might be called is when processing a WSAAccept
  1904. with a condition function specified. MSAFD calls us to get the QoS,
  1905. and we in turn request MSAFD to get SO_CONNOPT.
  1906. Arguments:
  1907. HelperDllSocketContext - the context pointer returned from
  1908. WSHOpenSocket().
  1909. SocketHandle - the handle of the socket for which we're controlling.
  1910. OutputBuffer - Address of the Output buffer.
  1911. OutputBufferLength - The length of OutputBuffer.
  1912. NumberOfBytesReturned - where we return the number of bytes we filled into
  1913. OutputBuffer.
  1914. Return Value:
  1915. INT - The completion status.
  1916. --*/
  1917. {
  1918. INT err;
  1919. DWORD BytesReturned;
  1920. LPQOS lpQOS;
  1921. err = NO_ERROR;
  1922. DBGPRINT(("GetQoS: Context x%x, Handle x%x, OutBuf x%x, OutBufLen %d\n",
  1923. HelperDllSocketContext,
  1924. SocketHandle,
  1925. OutputBuffer,
  1926. OutputBufferLength));
  1927. do
  1928. {
  1929. //
  1930. // Expect atleast enough space to fit in the base QoS structure.
  1931. //
  1932. if (OutputBufferLength < sizeof(QOS))
  1933. {
  1934. *NumberOfBytesReturned = MAX_ATM_OPTIONS_LENGTH;
  1935. err = WSAEFAULT;
  1936. break;
  1937. }
  1938. //
  1939. // Request the Winsock DLL to get the options.
  1940. //
  1941. BytesReturned = OutputBufferLength;
  1942. err = getsockopt(
  1943. SocketHandle,
  1944. SOL_SOCKET,
  1945. SO_CONNOPT,
  1946. OutputBuffer,
  1947. &BytesReturned
  1948. );
  1949. if ((err == NO_ERROR) && (BytesReturned != 0))
  1950. {
  1951. *NumberOfBytesReturned = BytesReturned;
  1952. lpQOS = (LPQOS)OutputBuffer;
  1953. //
  1954. // Fix up the provider-specific part, if any.
  1955. //
  1956. if (BytesReturned > sizeof(QOS))
  1957. {
  1958. lpQOS->ProviderSpecific.buf = (PCHAR)((PCHAR)lpQOS + sizeof(QOS));
  1959. }
  1960. else
  1961. {
  1962. lpQOS->ProviderSpecific.buf = NULL;
  1963. lpQOS->ProviderSpecific.len = 0;
  1964. }
  1965. DBGPRINT(("GetQoS: lpQOS %x, ProvSpec buf %x, len %d\n",
  1966. lpQOS, lpQOS->ProviderSpecific.buf, lpQOS->ProviderSpecific.len));
  1967. }
  1968. else
  1969. {
  1970. if (BytesReturned == 0)
  1971. {
  1972. //
  1973. // Probably because we aren't connected yet? Let's return
  1974. // all "NOT_SPECIFIED" values:
  1975. //
  1976. *NumberOfBytesReturned = sizeof(QOS);
  1977. lpQOS = (LPQOS)OutputBuffer;
  1978. lpQOS->ProviderSpecific.buf = NULL;
  1979. lpQOS->ProviderSpecific.len = 0;
  1980. lpQOS->SendingFlowspec.TokenRate =
  1981. lpQOS->SendingFlowspec.TokenBucketSize =
  1982. lpQOS->SendingFlowspec.PeakBandwidth =
  1983. lpQOS->SendingFlowspec.Latency =
  1984. lpQOS->SendingFlowspec.DelayVariation =
  1985. lpQOS->SendingFlowspec.ServiceType =
  1986. lpQOS->SendingFlowspec.MaxSduSize =
  1987. lpQOS->SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
  1988. lpQOS->ReceivingFlowspec = lpQOS->SendingFlowspec;
  1989. } else {
  1990. err = WSAGetLastError();
  1991. }
  1992. }
  1993. break;
  1994. }
  1995. while (FALSE);
  1996. return (err);
  1997. }
  1998. INT
  1999. AtmAssociatePVC(
  2000. IN SOCKET SocketHandle,
  2001. IN PVOID HelperDllSocketContext,
  2002. IN HANDLE TdiAddressObjectHandle,
  2003. IN HANDLE TdiConnectionObjectHandle,
  2004. IN LPVOID InputBuffer,
  2005. IN DWORD InputBufferLength
  2006. )
  2007. {
  2008. INT err;
  2009. PWSHATM_SOCKET_CONTEXT context;
  2010. ATM_PVC_PARAMS * pInPvcParams;
  2011. context = (PWSHATM_SOCKET_CONTEXT)HelperDllSocketContext;
  2012. DBGPRINT(("AssociatePVC: InputBuffer %x, Length %d, sizeof(ATM_PVC_PARAMS) %d\n",
  2013. InputBuffer, InputBufferLength, sizeof(ATM_PVC_PARAMS)));
  2014. do {
  2015. if ( InputBuffer == NULL ||
  2016. InputBufferLength < sizeof(ATM_PVC_PARAMS) ) {
  2017. err = WSAEFAULT;
  2018. break;
  2019. }
  2020. if ( context == NULL ) {
  2021. err = WSAEINVAL;
  2022. break;
  2023. }
  2024. //
  2025. // We want to allow the user to change the PVC info any number of times
  2026. // before connecting, but not after the fact.
  2027. //
  2028. if ( TdiConnectionObjectHandle != NULL ) {
  2029. err = WSAEISCONN;
  2030. break;
  2031. }
  2032. if ( context->LocalFlags & WSHATM_SOCK_IS_PVC ) {
  2033. //
  2034. // Already associated. Fail this.
  2035. //
  2036. err = WSAEISCONN;
  2037. break;
  2038. }
  2039. //
  2040. // Use the standard QoS mechanism to associate the QOS info
  2041. // with this socket.
  2042. //
  2043. pInPvcParams = InputBuffer;
  2044. err = setsockopt(
  2045. SocketHandle,
  2046. SOL_SOCKET,
  2047. SO_CONNOPT,
  2048. (PCHAR)&pInPvcParams->PvcQos,
  2049. InputBufferLength - (DWORD)((PUCHAR)&pInPvcParams->PvcQos - (PUCHAR)pInPvcParams)
  2050. );
  2051. DBGPRINT(("AssociatePVC: setsockopt, ptr %x, length %d, ret %d\n",
  2052. &pInPvcParams->PvcQos,
  2053. InputBufferLength - (DWORD)((PUCHAR)&pInPvcParams->PvcQos - (PUCHAR)pInPvcParams),
  2054. err));
  2055. if ( err != NO_ERROR ) {
  2056. break;
  2057. }
  2058. //
  2059. // Store the Connection Id.
  2060. //
  2061. context->ConnectionId = pInPvcParams->PvcConnectionId;
  2062. context->LocalFlags |= WSHATM_SOCK_IS_PVC;
  2063. if ( TdiAddressObjectHandle == NULL ) {
  2064. //
  2065. // We've got an ASSOCIATE_PVC before this socket has been
  2066. // bound. Just remember this, so that we do the rest when
  2067. // the bind actually happens.
  2068. //
  2069. context->LocalFlags |= WSHATM_SOCK_ASSOCIATE_PVC_PENDING;
  2070. err = NO_ERROR;
  2071. break;
  2072. }
  2073. //
  2074. // The socket is bound, so send info about the PVC Connection
  2075. // ID to the transport.
  2076. //
  2077. err = AtmDoAssociatePVC(
  2078. context,
  2079. TdiAddressObjectHandle
  2080. );
  2081. DBGPRINT(("AssociatePVC: DoAssociatePVC ret %d\n", err));
  2082. break;
  2083. }
  2084. while (FALSE);
  2085. DBGPRINT(("AssociatePVC: context Flags %x, LocalFlags %x, returning %d\n",
  2086. context? context->Flags: 0,
  2087. context? context->LocalFlags: 0,
  2088. err));
  2089. return err;
  2090. }
  2091. INT
  2092. AtmDoAssociatePVC(
  2093. IN PWSHATM_SOCKET_CONTEXT Context,
  2094. IN HANDLE TdiAddressObjectHandle
  2095. )
  2096. {
  2097. INT err;
  2098. DBGPRINT(("DoAssociatePVC: Context %x, LocalFlags %x\n",
  2099. Context, LocalFlags));
  2100. Context->LocalFlags &= ~WSHATM_SOCK_ASSOCIATE_PVC_PENDING;
  2101. err = AtmSetAtmObjectInformation(
  2102. TdiAddressObjectHandle,
  2103. IOCTL_RWAN_MEDIA_SPECIFIC_ADDR_HANDLE_SET,
  2104. ATMSP_OID_PVC_ID,
  2105. &Context->ConnectionId,
  2106. sizeof(ATM_CONNECTION_ID)
  2107. );
  2108. return err;
  2109. }
  2110. INT
  2111. AtmQueryAtmGlobalInformation(
  2112. IN ATM_OBJECT_ID ObjectId,
  2113. IN LPVOID pContext,
  2114. IN DWORD ContextLength,
  2115. IN LPVOID OutputBuffer,
  2116. IN DWORD OutputBufferLength,
  2117. OUT LPDWORD NumberOfBytesReturned
  2118. )
  2119. {
  2120. INT err;
  2121. NTSTATUS status;
  2122. OBJECT_ATTRIBUTES objectAttributes;
  2123. UNICODE_STRING deviceName;
  2124. HANDLE deviceHandle = NULL;
  2125. PIO_STATUS_BLOCK ioStatusBlock;
  2126. PATM_QUERY_INFORMATION_EX pQueryInfo;
  2127. do
  2128. {
  2129. ioStatusBlock = RTL_ALLOCATE_HEAP(
  2130. RtlProcessHeap( ),
  2131. 0,
  2132. sizeof(*ioStatusBlock) + sizeof(ATM_QUERY_INFORMATION_EX) + ContextLength
  2133. );
  2134. if ( ioStatusBlock == NULL ) {
  2135. err = WSAENOBUFS;
  2136. break;
  2137. }
  2138. //
  2139. // Open a handle to the ATM device.
  2140. //
  2141. RtlInitUnicodeString(
  2142. &deviceName,
  2143. DD_ATM_DEVICE_NAME
  2144. );
  2145. InitializeObjectAttributes(
  2146. &objectAttributes,
  2147. &deviceName,
  2148. OBJ_CASE_INSENSITIVE,
  2149. NULL,
  2150. NULL
  2151. );
  2152. status = NtCreateFile(
  2153. &deviceHandle,
  2154. SYNCHRONIZE | GENERIC_EXECUTE,
  2155. &objectAttributes,
  2156. ioStatusBlock,
  2157. NULL,
  2158. FILE_ATTRIBUTE_NORMAL,
  2159. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2160. FILE_OPEN_IF,
  2161. FILE_SYNCHRONOUS_IO_NONALERT,
  2162. NULL,
  2163. 0
  2164. );
  2165. if( !NT_SUCCESS(status) ) {
  2166. if (status == STATUS_INSUFFICIENT_RESOURCES) {
  2167. err = WSAEFAULT;
  2168. } else {
  2169. err = WSAEINVAL;
  2170. }
  2171. break;
  2172. }
  2173. pQueryInfo = (PATM_QUERY_INFORMATION_EX)(ioStatusBlock + 1);
  2174. pQueryInfo->ObjectId = ObjectId;
  2175. pQueryInfo->ContextLength = ContextLength;
  2176. if ( pQueryInfo->ContextLength > 0 ) {
  2177. RtlCopyMemory(
  2178. pQueryInfo->Context,
  2179. pContext,
  2180. pQueryInfo->ContextLength
  2181. );
  2182. }
  2183. status = NtDeviceIoControlFile(
  2184. deviceHandle,
  2185. NULL, // No Event
  2186. NULL, // No completion APC
  2187. NULL, // No completion APC Context
  2188. ioStatusBlock,
  2189. IOCTL_RWAN_MEDIA_SPECIFIC_GLOBAL_QUERY,
  2190. pQueryInfo,
  2191. sizeof(ATM_QUERY_INFORMATION_EX) + ContextLength,
  2192. OutputBuffer,
  2193. OutputBufferLength
  2194. );
  2195. DBGPRINT(("DevIoControl (Oid %x) returned x%x, Info %d\n",
  2196. pQueryInfo->ObjectId, status, ioStatusBlock->Information));
  2197. if ( NT_SUCCESS(status) ) {
  2198. err = NO_ERROR;
  2199. *NumberOfBytesReturned = (ULONG)ioStatusBlock->Information;
  2200. }
  2201. else {
  2202. if (status == STATUS_INSUFFICIENT_RESOURCES) {
  2203. err = WSAEFAULT;
  2204. } else {
  2205. err = WSAEINVAL;
  2206. }
  2207. }
  2208. }
  2209. while (FALSE);
  2210. if( deviceHandle != NULL ) {
  2211. NtClose( deviceHandle );
  2212. }
  2213. if ( ioStatusBlock != NULL ) {
  2214. RTL_FREE_HEAP( RtlProcessHeap( ), 0, ioStatusBlock );
  2215. }
  2216. return err;
  2217. }
  2218. INT
  2219. AtmSetGenericObjectInformation (
  2220. IN HANDLE TdiObjectHandle,
  2221. IN ULONG IoControlCode,
  2222. IN RWAN_OBJECT_ID ObjectId,
  2223. IN PVOID InputBuffer,
  2224. IN ULONG InputBufferLength
  2225. )
  2226. /*++
  2227. Routine Description:
  2228. Performs a RWAN Set Information action to the Raw Wan driver. This operation
  2229. is directed to either an Address Object or to a Connection object, according
  2230. to TdiObjectHandle.
  2231. Arguments:
  2232. TdiObjectHandle - a TDI handle to either an Address or a Connection object
  2233. on which to perform the Set Info operation.
  2234. IoControlCode - IOCTL_RWAN_GENERIC_XXXSET
  2235. ObjectId - value to put in the ObjectId field of the Set Info structure.
  2236. InputBuffer - Points to buffer containing value for the Object.
  2237. InputBufferLength - Length of the above.
  2238. Return Value:
  2239. INT - NO_ERROR, or a Windows Sockets error code.
  2240. --*/
  2241. {
  2242. NTSTATUS status;
  2243. INT err;
  2244. PRWAN_SET_INFORMATION_EX pSetInfo;
  2245. PIO_STATUS_BLOCK ioStatusBlock;
  2246. do
  2247. {
  2248. ioStatusBlock = RTL_ALLOCATE_HEAP(
  2249. RtlProcessHeap( ),
  2250. 0,
  2251. sizeof(*ioStatusBlock) + sizeof(RWAN_SET_INFORMATION_EX) + InputBufferLength
  2252. );
  2253. if ( ioStatusBlock == NULL ) {
  2254. err = WSAENOBUFS;
  2255. break;
  2256. }
  2257. pSetInfo = (PRWAN_SET_INFORMATION_EX)(ioStatusBlock + 1);
  2258. pSetInfo->ObjectId = ObjectId;
  2259. pSetInfo->BufferSize = InputBufferLength;
  2260. if ( pSetInfo->BufferSize > 0 ) {
  2261. RtlCopyMemory(
  2262. pSetInfo->Buffer,
  2263. InputBuffer,
  2264. pSetInfo->BufferSize
  2265. );
  2266. }
  2267. status = NtDeviceIoControlFile(
  2268. TdiObjectHandle,
  2269. NULL, // No Event
  2270. NULL, // No completion APC
  2271. NULL, // No completion APC Context
  2272. ioStatusBlock,
  2273. IoControlCode,
  2274. pSetInfo,
  2275. sizeof(RWAN_SET_INFORMATION_EX) + InputBufferLength,
  2276. NULL, // No output buffer
  2277. 0 // output buffer length
  2278. );
  2279. DBGPRINT(("AtmSetInfo: IOCTL (Oid %x) returned x%x\n", pSetInfo->ObjectId, status));
  2280. if ( NT_SUCCESS(status) ) {
  2281. err = NO_ERROR;
  2282. }
  2283. else {
  2284. if (status == STATUS_INSUFFICIENT_RESOURCES) {
  2285. err = WSAEFAULT;
  2286. } else {
  2287. err = WSAEINVAL;
  2288. }
  2289. }
  2290. }
  2291. while (FALSE);
  2292. if ( ioStatusBlock != NULL ) {
  2293. RTL_FREE_HEAP( RtlProcessHeap( ), 0, ioStatusBlock );
  2294. }
  2295. return err;
  2296. }
  2297. INT
  2298. AtmGetGenericObjectInformation (
  2299. IN HANDLE TdiObjectHandle,
  2300. IN ULONG IoControlCode,
  2301. IN RWAN_OBJECT_ID ObjectId,
  2302. IN PVOID InputBuffer,
  2303. IN ULONG InputBufferLength,
  2304. OUT PVOID OutputBuffer,
  2305. IN ULONG OutputBufferLength,
  2306. OUT LPDWORD NumberOfBytesReturned
  2307. )
  2308. /*++
  2309. Routine Description:
  2310. Performs a RWAN Get Information action to the Raw Wan driver. This operation
  2311. is directed to either an Address Object or to a Connection object, according
  2312. to TdiObjectHandle.
  2313. Arguments:
  2314. TdiObjectHandle - a TDI handle to either an Address or a Connection object
  2315. on which to perform the Set Info operation.
  2316. IoControlCode - IOCTL_RWAN_GENERIC_XXXGET
  2317. ObjectId - value to put in the ObjectId field of the Set Info structure.
  2318. InputBuffer - Points to buffer containing context for the Object.
  2319. InputBufferLength - Length of the above.
  2320. OutputBuffer - place to return value
  2321. OutputBufferLength - bytes available in OutputBuffer
  2322. NumberOfBytesReturned - place to return bytes written
  2323. Return Value:
  2324. INT - NO_ERROR, or a Windows Sockets error code.
  2325. --*/
  2326. {
  2327. NTSTATUS status;
  2328. INT err;
  2329. PRWAN_QUERY_INFORMATION_EX pQueryInfo;
  2330. PIO_STATUS_BLOCK ioStatusBlock;
  2331. do
  2332. {
  2333. ioStatusBlock = RTL_ALLOCATE_HEAP(
  2334. RtlProcessHeap( ),
  2335. 0,
  2336. sizeof(*ioStatusBlock) + sizeof(RWAN_QUERY_INFORMATION_EX) + InputBufferLength
  2337. );
  2338. if ( ioStatusBlock == NULL ) {
  2339. err = WSAENOBUFS;
  2340. break;
  2341. }
  2342. pQueryInfo = (PRWAN_QUERY_INFORMATION_EX)(ioStatusBlock + 1);
  2343. pQueryInfo->ObjectId = ObjectId;
  2344. pQueryInfo->ContextLength = InputBufferLength;
  2345. if ( pQueryInfo->ContextLength > 0 ) {
  2346. RtlCopyMemory(
  2347. pQueryInfo->Context,
  2348. InputBuffer,
  2349. pQueryInfo->ContextLength
  2350. );
  2351. }
  2352. status = NtDeviceIoControlFile(
  2353. TdiObjectHandle,
  2354. NULL, // No Event
  2355. NULL, // No completion APC
  2356. NULL, // No completion APC Context
  2357. ioStatusBlock,
  2358. IoControlCode,
  2359. pQueryInfo,
  2360. sizeof(RWAN_QUERY_INFORMATION_EX) + InputBufferLength,
  2361. OutputBuffer,
  2362. OutputBufferLength // output buffer length
  2363. );
  2364. DBGPRINT(("AtmGetGenericInfo: IOCTL (Oid %x) returned x%x\n", pQueryInfo->ObjectId, status));
  2365. if ( NT_SUCCESS(status) ) {
  2366. err = NO_ERROR;
  2367. *NumberOfBytesReturned = (ULONG)ioStatusBlock->Information;
  2368. }
  2369. else {
  2370. if (status == STATUS_INSUFFICIENT_RESOURCES) {
  2371. err = WSAEFAULT;
  2372. } else {
  2373. err = WSAEINVAL;
  2374. }
  2375. }
  2376. }
  2377. while (FALSE);
  2378. if ( ioStatusBlock != NULL ) {
  2379. RTL_FREE_HEAP( RtlProcessHeap( ), 0, ioStatusBlock );
  2380. }
  2381. return err;
  2382. }
  2383. INT
  2384. AtmSetAtmObjectInformation (
  2385. IN HANDLE TdiObjectHandle,
  2386. IN ULONG IoControlCode,
  2387. IN ATM_OBJECT_ID ObjectId,
  2388. IN PVOID InputBuffer,
  2389. IN ULONG InputBufferLength
  2390. )
  2391. /*++
  2392. Routine Description:
  2393. Performs a Media-specific Set Information action to the Raw Wan driver.
  2394. This operation is directed to either an Address Object or to a Connection
  2395. object, according to TdiObjectHandle.
  2396. Arguments:
  2397. TdiObjectHandle - a TDI handle to either an Address or a Connection object
  2398. on which to perform the Set Info operation.
  2399. IoControlCode - IOCTL_RWAN_MEDIA_SPECIFIC_XXX
  2400. ObjectId - value to put in the ObjectId field of the Set Info structure.
  2401. InputBuffer - Points to buffer containing value for the Object.
  2402. InputBufferLength - Length of the above.
  2403. Return Value:
  2404. INT - NO_ERROR, or a Windows Sockets error code.
  2405. --*/
  2406. {
  2407. NTSTATUS status;
  2408. INT err;
  2409. PATM_SET_INFORMATION_EX pSetInfo;
  2410. PIO_STATUS_BLOCK ioStatusBlock;
  2411. do
  2412. {
  2413. ioStatusBlock = RTL_ALLOCATE_HEAP(
  2414. RtlProcessHeap( ),
  2415. 0,
  2416. sizeof(*ioStatusBlock) + sizeof(ATM_SET_INFORMATION_EX) + InputBufferLength
  2417. );
  2418. if ( ioStatusBlock == NULL ) {
  2419. err = WSAENOBUFS;
  2420. break;
  2421. }
  2422. pSetInfo = (PATM_SET_INFORMATION_EX)(ioStatusBlock + 1);
  2423. pSetInfo->ObjectId = ObjectId;
  2424. pSetInfo->BufferSize = InputBufferLength;
  2425. if ( pSetInfo->BufferSize > 0 ) {
  2426. RtlCopyMemory(
  2427. pSetInfo->Buffer,
  2428. InputBuffer,
  2429. pSetInfo->BufferSize
  2430. );
  2431. }
  2432. status = NtDeviceIoControlFile(
  2433. TdiObjectHandle,
  2434. NULL, // No Event
  2435. NULL, // No completion APC
  2436. NULL, // No completion APC Context
  2437. ioStatusBlock,
  2438. IoControlCode,
  2439. pSetInfo,
  2440. sizeof(ATM_SET_INFORMATION_EX) + InputBufferLength,
  2441. NULL, // No output buffer
  2442. 0 // output buffer length
  2443. );
  2444. DBGPRINT(("AtmSetInfo: IOCTL (Oid %x) returned x%x\n", pSetInfo->ObjectId, status));
  2445. if ( NT_SUCCESS(status) ) {
  2446. err = NO_ERROR;
  2447. }
  2448. else {
  2449. if (status == STATUS_INSUFFICIENT_RESOURCES) {
  2450. err = WSAEFAULT;
  2451. } else {
  2452. err = WSAEINVAL;
  2453. }
  2454. }
  2455. }
  2456. while (FALSE);
  2457. if ( ioStatusBlock != NULL ) {
  2458. RTL_FREE_HEAP( RtlProcessHeap( ), 0, ioStatusBlock );
  2459. }
  2460. return err;
  2461. }
  2462. INT
  2463. AtmGetAtmObjectInformation (
  2464. IN HANDLE TdiObjectHandle,
  2465. IN ULONG IoControlCode,
  2466. IN ATM_OBJECT_ID ObjectId,
  2467. IN PVOID InputBuffer,
  2468. IN ULONG InputBufferLength,
  2469. OUT PVOID OutputBuffer,
  2470. IN ULONG OutputBufferLength,
  2471. OUT LPDWORD NumberOfBytesReturned
  2472. )
  2473. /*++
  2474. Routine Description:
  2475. Performs a Media-specific Get Information action to the Raw Wan driver.
  2476. This operation is directed to either an Address Object or to a Connection
  2477. object, according to TdiObjectHandle.
  2478. Arguments:
  2479. TdiObjectHandle - a TDI handle to either an Address or a Connection object
  2480. on which to perform the Set Info operation.
  2481. IoControlCode - IOCTL_RWAN_MEDIA_SPECIFIC_XXX
  2482. ObjectId - value to put in the ObjectId field of the Set Info structure.
  2483. InputBuffer - Points to buffer containing context for the Object.
  2484. InputBufferLength - Length of the above.
  2485. OutputBuffer - place to return value
  2486. OutputBufferLength - bytes available in OutputBuffer
  2487. NumberOfBytesReturned - place to return bytes written
  2488. Return Value:
  2489. INT - NO_ERROR, or a Windows Sockets error code.
  2490. --*/
  2491. {
  2492. NTSTATUS status;
  2493. INT err;
  2494. PATM_QUERY_INFORMATION_EX pQueryInfo;
  2495. PIO_STATUS_BLOCK ioStatusBlock;
  2496. do
  2497. {
  2498. *NumberOfBytesReturned = 0;
  2499. ioStatusBlock = RTL_ALLOCATE_HEAP(
  2500. RtlProcessHeap( ),
  2501. 0,
  2502. sizeof(*ioStatusBlock) + sizeof(ATM_QUERY_INFORMATION_EX) + InputBufferLength
  2503. );
  2504. if ( ioStatusBlock == NULL ) {
  2505. err = WSAENOBUFS;
  2506. break;
  2507. }
  2508. pQueryInfo = (PATM_QUERY_INFORMATION_EX)(ioStatusBlock + 1);
  2509. pQueryInfo->ObjectId = ObjectId;
  2510. pQueryInfo->ContextLength = InputBufferLength;
  2511. if ( pQueryInfo->ContextLength > 0 ) {
  2512. RtlCopyMemory(
  2513. pQueryInfo->Context,
  2514. InputBuffer,
  2515. pQueryInfo->ContextLength
  2516. );
  2517. }
  2518. status = NtDeviceIoControlFile(
  2519. TdiObjectHandle,
  2520. NULL, // No Event
  2521. NULL, // No completion APC
  2522. NULL, // No completion APC Context
  2523. ioStatusBlock,
  2524. IoControlCode,
  2525. pQueryInfo,
  2526. sizeof(ATM_QUERY_INFORMATION_EX) + InputBufferLength,
  2527. OutputBuffer,
  2528. OutputBufferLength
  2529. );
  2530. DBGPRINT(("AtmGetAtmObjInfo: IOCTL (Oid %x) returned x%x\n",
  2531. pQueryInfo->ObjectId, status));
  2532. if ( NT_SUCCESS(status) ) {
  2533. err = NO_ERROR;
  2534. *NumberOfBytesReturned = (ULONG)ioStatusBlock->Information;
  2535. }
  2536. else {
  2537. if (status == STATUS_INSUFFICIENT_RESOURCES) {
  2538. err = WSAEFAULT;
  2539. } else {
  2540. err = WSAEINVAL;
  2541. }
  2542. }
  2543. }
  2544. while (FALSE);
  2545. if ( ioStatusBlock != NULL ) {
  2546. RTL_FREE_HEAP( RtlProcessHeap( ), 0, ioStatusBlock );
  2547. }
  2548. return err;
  2549. }
  2550. #if DBG
  2551. PVOID
  2552. MyRtlAllocateHeap(
  2553. IN PVOID HeapHandle,
  2554. IN ULONG Flags,
  2555. IN ULONG Size,
  2556. IN ULONG LineNumber
  2557. )
  2558. {
  2559. PVOID pRetValue;
  2560. pRetValue = RtlAllocateHeap(HeapHandle, Flags, Size);
  2561. #if DBG2
  2562. DbgPrint("WSHATM: AllocHeap size %d at line %d, ret x%x\n",
  2563. Size, LineNumber, pRetValue);
  2564. #endif
  2565. return (pRetValue);
  2566. }
  2567. VOID
  2568. MyRtlFreeHeap(
  2569. IN PVOID HeapHandle,
  2570. IN ULONG Flags,
  2571. IN PVOID MemPtr,
  2572. IN ULONG LineNumber
  2573. )
  2574. {
  2575. #if DBG2
  2576. DbgPrint("WSHATM: FreeHeap x%x, line %d\n", MemPtr, LineNumber);
  2577. #endif
  2578. RtlFreeHeap(HeapHandle, Flags, MemPtr);
  2579. }
  2580. #endif // DBG