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.

372 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name :
  4. rnr.cxx (ripped out of tsvcinfo.cxx)
  5. Abstract:
  6. Defines the functions for TCP services Info class.
  7. This module is intended to capture the common scheduler
  8. code for the tcp services ( especially internet services)
  9. which involves the Service Controller dispatch functions.
  10. Also this class provides an interface for common dll of servers.
  11. Author:
  12. Murali R. Krishnan ( MuraliK ) 15-Nov-1994
  13. Project:
  14. Internet Servers Common DLL
  15. --*/
  16. #include "tcpdllp.hxx"
  17. #include <tsunami.hxx>
  18. #include <iistypes.hxx>
  19. #define MAX_SOCKETS ( 20)
  20. #if 0
  21. inline
  22. BOOL
  23. IsConnectionOriented(
  24. IN PPROTOCOL_INFO pProtocolInfo
  25. )
  26. {
  27. return ( ( pProtocolInfo->dwServiceFlags & XP_CONNECTIONLESS) == 0);
  28. } // IsConnectionOriented()
  29. inline
  30. BOOL
  31. IsReliable(
  32. IN PPROTOCOL_INFO pProtocolInfo
  33. )
  34. /*++
  35. This should be a protocol which delivers all packets and in order in which
  36. they are sent.
  37. --*/
  38. {
  39. return ( ( pProtocolInfo->dwServiceFlags & XP_GUARANTEED_DELIVERY) &&
  40. ( pProtocolInfo->dwServiceFlags & XP_GUARANTEED_ORDER) &&
  41. IsConnectionOriented( pProtocolInfo));
  42. } // IsReliable()
  43. INT
  44. GetValidListenAddresses( IN LPCTSTR pszServiceName,
  45. IN LPGUID lpServiceGuid,
  46. IN PCSADDR_INFO pcsAddrInfo,
  47. IN OUT LPDWORD lpcbAddrInfo )
  48. /*++
  49. This function obtains the list of valid listen addresses for the service
  50. specified. It uses the RNR API set to enumerate the list of protocols
  51. installed in a machine and queries using GetAddressByName() to obtain
  52. the list of valid addresses that can be used for establishing a listen
  53. socket.
  54. Arguments:
  55. pszServiceName pointer to null-terminated string containing service name.
  56. lpServiceGuid pointer to GUID for the service.
  57. pcsAddrInfo pointer to an array of CSADDR_INFO structures which
  58. on successful return contains the address information.
  59. lpcbAddInfo pointer to a DWORD containing the count of bytes
  60. available under pcsAddrInfo. When this function is
  61. called, it contains the number of bytes pointed to by
  62. pcsAddrInfo. On return contains the number of
  63. bytes required.
  64. Returns:
  65. count of valid CSADDR_INFO structures found for the given service to
  66. establish a listen socket.
  67. On error returns a value <= 0.
  68. --*/
  69. {
  70. int nAddresses = 0; // assume a safe value == failure.
  71. DWORD cbBuffer;
  72. int cProtocols;
  73. PPROTOCOL_INFO pProtocolInfo;
  74. int rgProtocols[ MAX_SOCKETS + 1];
  75. int * pProtocol;
  76. int i;
  77. BUFFER buff;
  78. #define ENUM_PROTO_BUFF_SIZE 49152
  79. //
  80. // First Look up the protocols installed on this machine. The
  81. // EnumProtocols() API returns about all the windows sockets protocols
  82. // loaded on this machine. We will use this information to identify the
  83. // protocols which provide the necessary semantics.
  84. //
  85. if ( !buff.Resize( ENUM_PROTO_BUFF_SIZE )) {
  86. return 0;
  87. }
  88. cbBuffer = buff.QuerySize();
  89. cProtocols = EnumProtocols( NULL, buff.QueryPtr(), &cbBuffer);
  90. if ( cProtocols < 0) {
  91. return 0;
  92. }
  93. //
  94. // Walk through the available protocols and pick out the ones that
  95. // support the desired characteristics.
  96. //
  97. for( pProtocolInfo = (PPROTOCOL_INFO ) buff.QueryPtr(),
  98. pProtocol = rgProtocols,
  99. i = 0;
  100. ( i < cProtocols &&
  101. ( pProtocol < rgProtocols + MAX_SOCKETS));
  102. pProtocolInfo++, i++ ) {
  103. if ( IsReliable( pProtocolInfo)) {
  104. //
  105. // This protocol matches our requirement of being reliable.
  106. // Make a note of the protocol.
  107. //
  108. IF_DEBUG( DLL_SERVICE_INFO) {
  109. DBGPRINTF( ( DBG_CONTEXT,
  110. " Protocol %d ( %s) matches condition\n",
  111. pProtocolInfo->iProtocol,
  112. pProtocolInfo->lpProtocol));
  113. }
  114. *pProtocol++ = pProtocolInfo->iProtocol;
  115. }
  116. } // for() : Protocol filter ()
  117. IF_DEBUG( DLL_SERVICE_INFO) {
  118. DBGPRINTF( ( DBG_CONTEXT, " Filtering yields %d of %d protocols. \n",
  119. ( pProtocol - rgProtocols), cProtocols));
  120. }
  121. // terminate the protocols array.
  122. *pProtocol = 0;
  123. cProtocols = ( pProtocol - rgProtocols);
  124. //
  125. // Make sure we found at least one acceptable protocol.
  126. // If there is no protocol on this machine, which suit our condition,
  127. // this function fails.
  128. //
  129. if ( cProtocols > 0) {
  130. //
  131. // Use GetAddressByName() to get addresses for chosen protocols.
  132. // We restrict the scope of the search to those protocols of interest
  133. // by passing the protocols array we generated. The function
  134. // returns socket addresses only for the protocols we can support.
  135. //
  136. nAddresses = GetAddressByName(
  137. NS_DEFAULT, // lpszNameSpace
  138. lpServiceGuid,
  139. (char *) pszServiceName,
  140. rgProtocols,
  141. RES_SERVICE | RES_FIND_MULTIPLE,
  142. NULL, // lpServiceAsyncInfo
  143. (PVOID )pcsAddrInfo,
  144. lpcbAddrInfo,
  145. NULL, // lpAliasBuffer
  146. NULL // lpdwAliasBufferLen
  147. );
  148. IF_DEBUG( DLL_SERVICE_INFO) {
  149. // take a copy of error code and set it back, to avoid lost errors
  150. DWORD dwError = GetLastError();
  151. DBGPRINTF( ( DBG_CONTEXT,
  152. " GetAddressByName() returned %d."
  153. " Bytes Written=%d. Error = %ld\n",
  154. nAddresses, *lpcbAddrInfo,
  155. ( nAddresses <= 0) ? dwError: NO_ERROR));
  156. if ( nAddresses <= 0) { SetLastError( dwError); }
  157. }
  158. }
  159. return ( nAddresses);
  160. } // GetValidListenAddress()
  161. #endif
  162. BOOL
  163. RegisterServiceForAdvertising(
  164. IN LPCTSTR pszServiceName,
  165. IN LPGUID lpServiceGuid,
  166. IN SOCKET s,
  167. IN BOOL fRegister
  168. )
  169. /*++
  170. This function registers a service for the purpose of advertising.
  171. By registering using RnR apis, we advertise the fact that this particular
  172. service is running on the protocols designated. Hence RnR compliant
  173. clients can get access to the same.
  174. Arguments:
  175. pszService name of the service
  176. lpServiceGuid pointer to GUID for the service.
  177. s socket whose address needs to be advertised.
  178. fRegister whether to register to deregister
  179. Returns:
  180. TRUE on success and FALSE if there is any failure.
  181. Use GetLastError() for further details on failure.
  182. --*/
  183. {
  184. BOOL fReturn = TRUE;
  185. #if 0
  186. BYTE * pbAddressBuffer;
  187. DWORD cbAddressBuffer;
  188. INT err;
  189. SERVICE_INFO serviceInfo;
  190. SERVICE_ADDRESSES * pServiceAddress;
  191. DBG_ASSERT( pszServiceName && lpServiceGuid );
  192. DBG_ASSERT( s != INVALID_SOCKET );
  193. /*++
  194. Advertising service involves following steps:
  195. 1. Set up a service info structure.
  196. 2. Allocate memory for service addresses for as many sockets need to
  197. be advertised.
  198. 3. Fill in the information containing the socket addresses
  199. 4. Execute call for advertising the service (use SetService( REGISTER)).
  200. --*/
  201. //
  202. // Alloc space for SERVICE_ADDRESSES and n-1 SERVICE_ADDRESS structures.
  203. //
  204. pServiceAddress = ( ( SERVICE_ADDRESSES *)
  205. TCP_ALLOC( sizeof( SERVICE_ADDRESSES) )
  206. );
  207. // Alloc space for SOCKADDR addresses returned.
  208. cbAddressBuffer = sizeof(SOCKADDR);
  209. pbAddressBuffer = (BYTE *) TCP_ALLOC(cbAddressBuffer);
  210. if ( pServiceAddress == NULL || pbAddressBuffer == NULL) {
  211. if ( pServiceAddress != NULL) { TCP_FREE( pServiceAddress); }
  212. if ( pbAddressBuffer != NULL) { TCP_FREE( pbAddressBuffer); }
  213. SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  214. return (FALSE);
  215. }
  216. //
  217. // set up service info structure.
  218. // Here the interesting fields are lpServiceType, lpServiceName,
  219. // and lpServiceAddress fields.
  220. //
  221. serviceInfo.lpServiceType = lpServiceGuid ;
  222. // surprisingly enough! RNR structures dont like constants
  223. serviceInfo.lpServiceName = (LPTSTR ) pszServiceName ;
  224. // do we need better comment ? NYI
  225. serviceInfo.lpComment = "Microsoft Internet Services";
  226. serviceInfo.lpLocale = NULL;
  227. serviceInfo.lpMachineName = NULL ;
  228. serviceInfo.dwVersion = 1;
  229. serviceInfo.dwDisplayHint = 0;
  230. serviceInfo.dwTime = 0;
  231. serviceInfo.lpServiceAddress = pServiceAddress;
  232. serviceInfo.ServiceSpecificInfo.cbSize = 0 ;
  233. serviceInfo.ServiceSpecificInfo.pBlobData = NULL ;
  234. //
  235. // For each socket, get its local association and store the same.
  236. //
  237. PSOCKADDR pSockAddr = (PSOCKADDR ) pbAddressBuffer;
  238. int size = (int) cbAddressBuffer;
  239. //
  240. // Call getsockname() to get the local association for the socket.
  241. //
  242. if ( getsockname( s, pSockAddr, &size) == 0 ) {
  243. //
  244. // Now setup the Addressing information for this socket.
  245. // Only the dwAddressType, dwAddressLength and lpAddress
  246. // is of any interest in this example.
  247. //
  248. pServiceAddress->Addresses[0].dwAddressType = pSockAddr->sa_family;
  249. pServiceAddress->Addresses[0].dwAddressFlags = 0;
  250. pServiceAddress->Addresses[0].dwAddressLength = size ;
  251. pServiceAddress->Addresses[0].dwPrincipalLength= 0 ;
  252. pServiceAddress->Addresses[0].lpAddress = (LPBYTE) pSockAddr;
  253. pServiceAddress->Addresses[0].lpPrincipal = NULL ;
  254. //
  255. // Advance pointer and adjust buffer size. Assumes that
  256. // the structures are aligned. Unaligned accesses !! NYI
  257. //
  258. cbAddressBuffer -= size;
  259. pSockAddr = (PSOCKADDR) ((BYTE*)pSockAddr + size);
  260. pServiceAddress->dwAddressCount = 1;
  261. //
  262. // If we got at least one address, go ahead and advertise it.
  263. //
  264. DWORD dwStatusFlags;
  265. err = SetService(
  266. NS_DEFAULT, // for all default name spaces
  267. fRegister ? SERVICE_REGISTER : SERVICE_DEREGISTER,
  268. 0, // no flags specified
  269. &serviceInfo, // SERVICE_INFO structure
  270. NULL, // no async support yet
  271. &dwStatusFlags) ; // returns status flags
  272. IF_DEBUG( DLL_CONNECTION ) {
  273. DBGPRINTF(( DBG_CONTEXT, " SetService(%s, NS_DEFAULT, Register=%d)"
  274. " returns Status = %08x,"
  275. " err = %d\n",
  276. pszServiceName, fRegister,
  277. dwStatusFlags, err));
  278. }
  279. } else {
  280. SetLastError( ERROR_INVALID_PARAMETER);
  281. fReturn = FALSE;
  282. }
  283. TCP_FREE( pbAddressBuffer);
  284. TCP_FREE( pServiceAddress);
  285. #endif
  286. return ( fReturn);
  287. } // RegisterServiceForAdvertising()