Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

605 lines
18 KiB

  1. /*----------------------------------------------------------------------------
  2. * File: RTPINIT.C
  3. * Product: RTP/RTCP implementation
  4. * Description: Provides initialization functions.
  5. *
  6. * INTEL Corporation Proprietary Information
  7. * This listing is supplied under the terms of a license agreement with
  8. * Intel Corporation and may not be copied nor disclosed except in
  9. * accordance with the terms of that agreement.
  10. * Copyright (c) 1995 Intel Corporation.
  11. *--------------------------------------------------------------------------*/
  12. #include "rrcm.h"
  13. /*---------------------------------------------------------------------------
  14. / External Variables
  15. /--------------------------------------------------------------------------*/
  16. extern SOCKET PASCAL WS2EmulSocket(
  17. int af, int type,int protocol, LPWSAPROTOCOL_INFO ,GROUP,DWORD);
  18. extern int PASCAL WS2EmulCloseSocket(SOCKET s);
  19. extern int PASCAL WS2EmulSetSockOpt(SOCKET s, int level,int optname,const char FAR * optval,int optlen);
  20. extern int PASCAL WS2EmulBind( SOCKET s, const struct sockaddr FAR * name, int namelen);
  21. extern int PASCAL WS2EmulRecvFrom(
  22. SOCKET s,LPWSABUF , DWORD, LPDWORD, LPDWORD,struct sockaddr FAR *, LPINT,
  23. LPWSAOVERLAPPED,LPWSAOVERLAPPED_COMPLETION_ROUTINE );
  24. extern int PASCAL WS2EmulSendTo(
  25. SOCKET s,LPWSABUF, DWORD ,LPDWORD , DWORD , const struct sockaddr FAR *, int,
  26. LPWSAOVERLAPPED , LPWSAOVERLAPPED_COMPLETION_ROUTINE );
  27. extern int PASCAL WS2EmulGetSockName( SOCKET s, struct sockaddr * name, int * namelen );
  28. extern int PASCAL WS2EmulHtonl( SOCKET s,u_long hostlong,u_long FAR * lpnetlong);
  29. extern int PASCAL WS2EmulNtohl( SOCKET s,u_long ,u_long FAR * );
  30. extern int PASCAL WS2EmulHtons( SOCKET s,u_short ,u_short FAR *);
  31. extern int PASCAL WS2EmulNtohs( SOCKET s,u_short ,u_short FAR *);
  32. extern int PASCAL WS2EmulGetHostName(char *name, int namelen);
  33. extern struct hostent FAR * PASCAL WS2EmulGetHostByName(const char * name);
  34. extern SOCKET PASCAL WS2EmulJoinLeaf(SOCKET s, const struct sockaddr FAR * name,int , LPWSABUF , LPWSABUF , LPQOS, LPQOS, DWORD dwFlags);
  35. extern int PASCAL WS2EmulIoctl(SOCKET s, DWORD, LPVOID,DWORD cbInBuffer, LPVOID ,
  36. DWORD, LPDWORD lpcbBytesReturned,LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
  37. extern void WS2EmulInit();
  38. extern void WS2EmulTerminate();
  39. /*---------------------------------------------------------------------------
  40. / Global Variables
  41. /--------------------------------------------------------------------------*/
  42. PRTP_CONTEXT pRTPContext = NULL;
  43. RRCM_WS RRCMws =
  44. {
  45. NULL, // hWSdll
  46. WS2EmulSendTo,
  47. WS2EmulRecvFrom,
  48. WS2EmulNtohl,
  49. WS2EmulNtohs,
  50. WS2EmulHtonl,
  51. WS2EmulHtons,
  52. WS2EmulGetSockName,
  53. WS2EmulGetHostName,
  54. WS2EmulGetHostByName,
  55. WS2EmulCloseSocket,
  56. WS2EmulSocket,
  57. WS2EmulBind,
  58. NULL, //WSAEnumProtocols
  59. WS2EmulJoinLeaf, //WSAJoinLeaf
  60. WS2EmulIoctl, //WSAIoctl
  61. WS2EmulSetSockOpt
  62. };
  63. DWORD g_fDisableWinsock2 = 0;
  64. #ifdef ENABLE_ISDM2
  65. KEY_HANDLE hRRCMRootKey;
  66. ISDM2 Isdm2;
  67. #endif
  68. #ifdef _DEBUG
  69. char debug_string[DBG_STRING_LEN];
  70. #endif
  71. #ifdef UNICODE
  72. static const char szWSASocket[] = "WSASocketW";
  73. static const char szWSAEnumProtocols[] = "WSAEnumProtocolsW";
  74. #else
  75. static const char szWSASocket[] = "WSASocketA";
  76. static const char szWSAEnumProtocols[] = "WSAEnumProtocolsA";
  77. #endif
  78. /*----------------------------------------------------------------------------
  79. * Function : initRTP
  80. * Description: Initializes the RTP task.
  81. *
  82. * Input : hInst: Handle to the DLL instance
  83. *
  84. * Return: RRCM_NoError = OK.
  85. * Otherwise(!=0) = Initialization Error (see RRCM.H).
  86. ---------------------------------------------------------------------------*/
  87. DWORD initRTP (HINSTANCE hInst)
  88. {
  89. DWORD dwStatus;
  90. DWORD hashTableEntries = NUM_RTP_HASH_SESS;
  91. IN_OUT_STR ("RTP : Enter initRTP()\n");
  92. // If RTP has already been initialized, stop, report the error and return
  93. if (pRTPContext != NULL)
  94. {
  95. RRCM_DBG_MSG ("RTP : ERROR - Multiple RTP Instances", 0,
  96. __FILE__, __LINE__, DBG_CRITICAL);
  97. IN_OUT_STR ("RTP : Exit initRTP()\n");
  98. return (MAKE_RRCM_ERROR(RRCMError_RTPReInit));
  99. }
  100. // Obtain our context
  101. pRTPContext = (PRTP_CONTEXT)GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT,
  102. sizeof(RTP_CONTEXT));
  103. // if no resources, exit with appropriate error
  104. if (pRTPContext == NULL)
  105. {
  106. RRCM_DBG_MSG ("RTP : ERROR - Resource allocation failed", 0,
  107. __FILE__, __LINE__, DBG_CRITICAL);
  108. IN_OUT_STR ("RTP : Exit initRTP()\n");
  109. return (MAKE_RRCM_ERROR(RRCMError_RTPResources));
  110. }
  111. // Get information from the registry if any present
  112. RRCMreadRegistry (pRTPContext);
  113. // Perform dynamic linking of what we need
  114. if ((dwStatus = RRCMgetDynamicLink ()) != RRCM_NoError)
  115. {
  116. GlobalFree(pRTPContext);
  117. pRTPContext = NULL;
  118. RRCM_DBG_MSG ("RTP : ERROR - Winsock library not found", 0,
  119. __FILE__, __LINE__, DBG_CRITICAL);
  120. IN_OUT_STR ("RTP : Exit initRTP()\n");
  121. return MAKE_RRCM_ERROR(dwStatus);
  122. }
  123. // Initialize RTP context critical section
  124. InitializeCriticalSection(&pRTPContext->critSect);
  125. //Initialize WS2Emulation critical section
  126. WS2EmulInit();
  127. // Create RTCP and look at return value. If error, don't proceed
  128. // any further. Pass this error to the calling function
  129. if ((dwStatus = initRTCP()) == RRCM_NoError)
  130. {
  131. // RTCP is up. We need to initialize our context
  132. pRTPContext->hInst = hInst;
  133. pRTPContext->pRTPSession.next = NULL;
  134. pRTPContext->pRTPSession.prev = NULL;
  135. }
  136. // if any part of initialation did not succeed, declare it all a failure
  137. // and return all resourses allocated
  138. if (dwStatus != RRCM_NoError)
  139. {
  140. if (pRTPContext)
  141. {
  142. GlobalFree(pRTPContext);
  143. pRTPContext = NULL;
  144. }
  145. }
  146. IN_OUT_STR ("RTP : Exit initRTP()\n");
  147. if (dwStatus != RRCM_NoError)
  148. dwStatus = MAKE_RRCM_ERROR(dwStatus);
  149. return (dwStatus);
  150. }
  151. /*----------------------------------------------------------------------------
  152. * Function : deleteRTP
  153. * Description: Deletes RTP. Closes all RTP and RTCP sessions and releases all
  154. * resources.
  155. *
  156. * Input : hInst: Handle to the DLL instance.
  157. *
  158. * Return: RRCM_NoError = OK.
  159. * Otherwise(!=0) = Initialization Error (see RRCM.H).
  160. ---------------------------------------------------------------------------*/
  161. DWORD deleteRTP (HINSTANCE hInst)
  162. {
  163. DWORD dwStatus;
  164. PRTP_SESSION pDeleteSession;
  165. #ifdef ENABLE_ISDM2
  166. HRESULT hError;
  167. #endif
  168. IN_OUT_STR ("RTP : Enter deleteRTP()\n");
  169. // If RTP context doesn't exist, report error and return.
  170. if (pRTPContext == NULL)
  171. {
  172. RRCM_DBG_MSG ("RTP : ERROR - No RTP instance", 0,
  173. __FILE__, __LINE__, DBG_ERROR);
  174. IN_OUT_STR ("RTP : Exit deleteRTP()\n");
  175. return (MAKE_RRCM_ERROR(RRCMError_RTPInvalidDelete));
  176. }
  177. if (pRTPContext->hInst != hInst)
  178. {
  179. RRCM_DBG_MSG ("RTP : ERROR - Invalid DLL instance handle", 0,
  180. __FILE__, __LINE__, DBG_ERROR);
  181. IN_OUT_STR ("RTP : Exit deleteRTP()\n");
  182. return (MAKE_RRCM_ERROR(RRCMError_RTPNoContext));
  183. }
  184. // If we still have sessions open, clean them up
  185. while ((pDeleteSession =
  186. (PRTP_SESSION)pRTPContext->pRTPSession.prev) != NULL)
  187. {
  188. RRCM_DBG_MSG ("RTP : ERROR - Session x still open at DLL exit", 0,
  189. __FILE__, __LINE__, DBG_ERROR);
  190. ASSERT(0);
  191. //Close all open sessions
  192. CloseRTPSession (pDeleteSession, NULL, FALSE);
  193. }
  194. // Call RTCP to terminate and cleanup
  195. dwStatus = deleteRTCP();
  196. #ifdef ENABLE_ISDM2
  197. // Query ISDM key
  198. if (Isdm2.hISDMdll)
  199. {
  200. DWORD dwKeys = 0;
  201. DWORD dwValues = 0;
  202. if (SUCCEEDED (Isdm2.ISDMEntry.ISD_QueryInfoKey (hRRCMRootKey,
  203. NULL, NULL,
  204. &dwKeys, &dwValues)))
  205. {
  206. if (!dwKeys && !dwValues)
  207. {
  208. hError = Isdm2.ISDMEntry.ISD_DeleteKey(hRRCMRootKey);
  209. if(FAILED(hError))
  210. RRCM_DBG_MSG ("RTP: ISD_DeleteKey failed", 0,
  211. NULL, 0, DBG_NOTIFY);
  212. }
  213. }
  214. DeleteCriticalSection (&Isdm2.critSect);
  215. if (FreeLibrary (Isdm2.hISDMdll) == FALSE)
  216. {
  217. RRCM_DBG_MSG ("RTP : ERROR - Freeing WS Lib", GetLastError(),
  218. __FILE__, __LINE__, DBG_ERROR);
  219. }
  220. }
  221. #endif
  222. // unload the WS library
  223. if (RRCMws.hWSdll)
  224. {
  225. if (FreeLibrary (RRCMws.hWSdll) == FALSE)
  226. {
  227. RRCM_DBG_MSG ("RTP : ERROR - Freeing WS Lib", GetLastError(),
  228. __FILE__, __LINE__, DBG_ERROR);
  229. }
  230. }
  231. // delete RTP context critical section
  232. DeleteCriticalSection(&pRTPContext->critSect);
  233. // delete WS2 Emulation
  234. WS2EmulTerminate();
  235. // delete RTP context
  236. GlobalFree(pRTPContext);
  237. pRTPContext = NULL;
  238. IN_OUT_STR ("RTP : Exit deleteRTP()\n");
  239. if (dwStatus != RRCM_NoError)
  240. dwStatus = MAKE_RRCM_ERROR(dwStatus);
  241. return (dwStatus);
  242. }
  243. /*----------------------------------------------------------------------------
  244. * Function : RRCMreadRegistry
  245. * Description: Access the registry
  246. *
  247. * Input : pCtxt: -> to the RTP context
  248. *
  249. * Return: None
  250. ---------------------------------------------------------------------------*/
  251. void RRCMreadRegistry (PRTP_CONTEXT pCtxt)
  252. {
  253. HKEY hKey;
  254. long lRes;
  255. char keyBfr[50];
  256. // open the key
  257. strcpy (keyBfr, szRegRRCMKey);
  258. // INTEL key vs MICROSOFT KEY
  259. #ifndef INTEL
  260. strcat (keyBfr, szRegRRCMSubKey);
  261. #else
  262. strcat (keyBfr, szRegRRCMSubKeyIntel);
  263. #endif
  264. lRes = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  265. keyBfr,
  266. 0,
  267. KEY_READ,
  268. &hKey);
  269. if (lRes || !hKey)
  270. {
  271. // key not found, setup default values
  272. pCtxt->registry.NumSessions = NUM_RRCM_SESS;
  273. pCtxt->registry.NumFreeSSRC = NUM_FREE_SSRC;
  274. pCtxt->registry.NumRTCPPostedBfr = NUM_RCV_BFR_POSTED;
  275. pCtxt->registry.RTCPrcvBfrSize = RRCM_RCV_BFR_SIZE;
  276. return;
  277. }
  278. // get the number of RRCM sessions
  279. RRCMgetRegistryValue (hKey, szRegRRCMNumSessions,
  280. &pCtxt->registry.NumSessions,
  281. REG_DWORD, sizeof(DWORD));
  282. // check range
  283. if (pCtxt->registry.NumSessions < MIN_NUM_RRCM_SESS)
  284. pCtxt->registry.NumSessions = MIN_NUM_RRCM_SESS;
  285. else if (pCtxt->registry.NumSessions > MAX_NUM_RRCM_SESS)
  286. pCtxt->registry.NumSessions = MAX_NUM_RRCM_SESS;
  287. // get the number of initial free SSRC
  288. RRCMgetRegistryValue (hKey, szRegRRCMNumFreeSSRC,
  289. &pCtxt->registry.NumFreeSSRC,
  290. REG_DWORD, sizeof(DWORD));
  291. // check range
  292. if (pCtxt->registry.NumFreeSSRC < MIN_NUM_FREE_SSRC)
  293. pCtxt->registry.NumFreeSSRC = MIN_NUM_FREE_SSRC;
  294. else if (pCtxt->registry.NumFreeSSRC > MAX_NUM_FREE_SSRC)
  295. pCtxt->registry.NumFreeSSRC = MAX_NUM_FREE_SSRC;
  296. // get the number of RTCP rcv buffers to be posted
  297. RRCMgetRegistryValue (hKey, szRegRRCMNumRTCPPostedBfr,
  298. &pCtxt->registry.NumRTCPPostedBfr,
  299. REG_DWORD, sizeof(DWORD));
  300. // check range
  301. if (pCtxt->registry.NumRTCPPostedBfr < MIN_NUM_RCV_BFR_POSTED)
  302. pCtxt->registry.NumRTCPPostedBfr = MIN_NUM_RCV_BFR_POSTED;
  303. else if (pCtxt->registry.NumRTCPPostedBfr > MAX_NUM_RCV_BFR_POSTED)
  304. pCtxt->registry.NumRTCPPostedBfr = MAX_NUM_RCV_BFR_POSTED;
  305. // get the RTCP rcv buffer size
  306. RRCMgetRegistryValue (hKey, szRegRRCMRTCPrcvBfrSize,
  307. &pCtxt->registry.RTCPrcvBfrSize,
  308. REG_DWORD, sizeof(DWORD));
  309. // check range
  310. if (pCtxt->registry.RTCPrcvBfrSize < MIN_RRCM_RCV_BFR_SIZE)
  311. pCtxt->registry.RTCPrcvBfrSize = MIN_RRCM_RCV_BFR_SIZE;
  312. else if (pCtxt->registry.RTCPrcvBfrSize > MAX_RRCM_RCV_BFR_SIZE)
  313. pCtxt->registry.RTCPrcvBfrSize = MAX_RRCM_RCV_BFR_SIZE;
  314. RRCMgetRegistryValue(hKey, "DisableWinsock2",
  315. &g_fDisableWinsock2,
  316. REG_DWORD, sizeof(DWORD));
  317. // close the key
  318. RegCloseKey (hKey);
  319. }
  320. /*----------------------------------------------------------------------------
  321. * Function : RRCMgetRegistryValue
  322. * Description: Read a value from the registry
  323. *
  324. * Input : hKey : Key handle
  325. * pValStr : -> to string value
  326. * pKeyVal : -> to value
  327. * type : Type to read
  328. * len : Receiving buffer length
  329. *
  330. * Return: None
  331. ---------------------------------------------------------------------------*/
  332. void RRCMgetRegistryValue (HKEY hKey, LPTSTR pValStr,
  333. PDWORD pKeyVal, DWORD type, DWORD len)
  334. {
  335. DWORD dwType = type;
  336. DWORD retSize = len;
  337. // query the value
  338. RegQueryValueEx (hKey,
  339. pValStr,
  340. NULL,
  341. &dwType,
  342. (BYTE *)pKeyVal,
  343. &retSize);
  344. }
  345. /*----------------------------------------------------------------------------
  346. * Function : RRCMgetDynamicLink
  347. * Description: Get all dynamic linked DLL entries
  348. *
  349. * Input : None
  350. *
  351. * Return: None
  352. ---------------------------------------------------------------------------*/
  353. DWORD RRCMgetDynamicLink (void)
  354. {
  355. HINSTANCE hWSdll;
  356. #ifdef ENABLE_ISDM2
  357. HRESULT hError;
  358. Isdm2.hISDMdll = LoadLibrary(szISDMdll);
  359. // make sure the LoadLibrary call did not fail
  360. if (Isdm2.hISDMdll)
  361. {
  362. RRCM_DBG_MSG ("RTP: ISDM2 LoadLibrary worked", 0, NULL, 0, DBG_NOTIFY);
  363. // get the ISDM entry points used by RRCM
  364. Isdm2.ISDMEntry.ISD_CreateKey =
  365. (ISD_CREATEKEY) GetProcAddress (Isdm2.hISDMdll,
  366. "ISD_CreateKey");
  367. Isdm2.ISDMEntry.ISD_CreateValue =
  368. (ISD_CREATEVALUE) GetProcAddress (Isdm2.hISDMdll, "ISD_CreateValue");
  369. Isdm2.ISDMEntry.ISD_SetValue =
  370. (ISD_SETVALUE) GetProcAddress (Isdm2.hISDMdll, "ISD_SetValue");
  371. Isdm2.ISDMEntry.ISD_DeleteValue =
  372. (ISD_DELETEVALUE) GetProcAddress (Isdm2.hISDMdll, "ISD_DeleteValue");
  373. Isdm2.ISDMEntry.ISD_DeleteKey =
  374. (ISD_DELETEKEY) GetProcAddress (Isdm2.hISDMdll, "ISD_DeleteKey");
  375. Isdm2.ISDMEntry.ISD_QueryInfoKey =
  376. (ISD_QUERYINFOKEY) GetProcAddress (Isdm2.hISDMdll, "ISD_QueryInfoKey");
  377. // initialize critical section
  378. InitializeCriticalSection (&Isdm2.critSect);
  379. // make sure we have all of them
  380. if (Isdm2.ISDMEntry.ISD_CreateKey == NULL ||
  381. Isdm2.ISDMEntry.ISD_CreateValue == NULL ||
  382. Isdm2.ISDMEntry.ISD_SetValue == NULL ||
  383. Isdm2.ISDMEntry.ISD_DeleteValue == NULL ||
  384. Isdm2.ISDMEntry.ISD_DeleteKey == NULL ||
  385. Isdm2.ISDMEntry.ISD_QueryInfoKey == NULL )
  386. {
  387. Isdm2.hISDMdll = 0;
  388. RRCM_DBG_MSG ("RTP: Failed to load all ISDM2 functions",
  389. 0, NULL, 0, DBG_NOTIFY);
  390. // delete critical section
  391. DeleteCriticalSection (&Isdm2.critSect);
  392. }
  393. else
  394. {
  395. hError = Isdm2.ISDMEntry.ISD_CreateKey(MAIN_ROOT_KEY, szRRCMISDM, &hRRCMRootKey);
  396. if(FAILED(hError))
  397. {
  398. RRCM_DBG_MSG ("RTP: ISD_CreateKey Failed",0, NULL, 0, DBG_NOTIFY);
  399. hRRCMRootKey = 0;
  400. }
  401. }
  402. }
  403. #endif
  404. if (!g_fDisableWinsock2)
  405. {
  406. // load Winsock2 if present
  407. hWSdll = LoadLibrary(szRRCMdefaultLib);
  408. if (hWSdll)
  409. {
  410. RRCMws.hWSdll = hWSdll;
  411. RRCMws.sendTo = (LPFN_WSASENDTO)GetProcAddress (hWSdll,
  412. "WSASendTo");
  413. RRCMws.recvFrom = (LPFN_WSARECVFROM)GetProcAddress (hWSdll,
  414. "WSARecvFrom");
  415. RRCMws.getsockname = (LPFN_GETSOCKNAME)GetProcAddress (hWSdll,
  416. "getsockname");
  417. RRCMws.gethostname = (LPFN_GETHOSTNAME)GetProcAddress (hWSdll,
  418. "gethostname");
  419. RRCMws.gethostbyname = (LPFN_GETHOSTBYNAME)GetProcAddress (hWSdll,
  420. "gethostbyname");
  421. RRCMws.WSASocket = (LPFN_WSASOCKET)GetProcAddress (hWSdll,
  422. szWSASocket);
  423. RRCMws.closesocket = (LPFN_CLOSESOCKET)GetProcAddress (hWSdll,
  424. "closesocket");
  425. RRCMws.bind = (LPFN_BIND)GetProcAddress (hWSdll,
  426. "bind");
  427. RRCMws.WSAEnumProtocols = (LPFN_WSAENUMPROTOCOLS) ::GetProcAddress(hWSdll, szWSAEnumProtocols);
  428. RRCMws.WSAIoctl = (LPFN_WSAIOCTL) ::GetProcAddress(hWSdll, "WSAIoctl");
  429. RRCMws.WSAJoinLeaf = (LPFN_WSAJOINLEAF) ::GetProcAddress(hWSdll, "WSAJoinLeaf");
  430. RRCMws.setsockopt = (LPFN_SETSOCKOPT) ::GetProcAddress(hWSdll, "setsockopt");
  431. RRCMws.ntohl = (LPFN_WSANTOHL)GetProcAddress (hWSdll, "WSANtohl");
  432. RRCMws.ntohs = (LPFN_WSANTOHS)GetProcAddress (hWSdll, "WSANtohs");
  433. RRCMws.htonl = (LPFN_WSAHTONL)GetProcAddress (hWSdll, "WSAHtonl");
  434. RRCMws.htons = (LPFN_WSAHTONS)GetProcAddress (hWSdll, "WSAHtons");
  435. if (RRCMws.WSAEnumProtocols)
  436. {
  437. int nProt = 0, i;
  438. int iProt[2]; // array of protocols we're interested in
  439. DWORD dwBufLength = sizeof(WSAPROTOCOL_INFO);
  440. LPWSAPROTOCOL_INFO pProtInfo = (LPWSAPROTOCOL_INFO) LocalAlloc(0,dwBufLength);
  441. iProt[0] = IPPROTO_UDP;
  442. iProt[1] = 0;
  443. // figure out the buffer size needed for WSAPROTOCOLINFO structs
  444. nProt = RRCMws.WSAEnumProtocols(iProt,pProtInfo,&dwBufLength);
  445. if (nProt < 0 && GetLastError() == WSAENOBUFS) {
  446. LocalFree(pProtInfo);
  447. pProtInfo = (LPWSAPROTOCOL_INFO) LocalAlloc(0,dwBufLength);
  448. if (pProtInfo)
  449. nProt = RRCMws.WSAEnumProtocols(iProt,pProtInfo,&dwBufLength);
  450. }
  451. if (nProt > 0) {
  452. for (i=0;i < nProt; i++) {
  453. if (pProtInfo[i].iProtocol == IPPROTO_UDP
  454. && pProtInfo[i].iSocketType == SOCK_DGRAM
  455. && ((pProtInfo[i].dwServiceFlags1 & XP1_QOS_SUPPORTED) || RRCMws.RTPProtInfo.iProtocol == 0)
  456. )
  457. { // make a copy of the matching WSAPROTOCOL_INFO
  458. RRCMws.RTPProtInfo = pProtInfo[i];
  459. if (pProtInfo[i].dwServiceFlags1 & XP1_QOS_SUPPORTED)
  460. {
  461. RRCM_DBG_MSG ("QOS UDP provider found.\n", 0,
  462. __FILE__, __LINE__, DBG_WARNING);
  463. break;
  464. }
  465. // else keep looking for a provider that supports QOS
  466. }
  467. }
  468. }
  469. if (pProtInfo)
  470. LocalFree(pProtInfo);
  471. if (RRCMws.RTPProtInfo.iProtocol == IPPROTO_UDP)
  472. {
  473. // we found the protocol(s) we wanted
  474. //RETAILMSG(("NAC: Using Winsock 2"));
  475. }
  476. else
  477. {
  478. FreeLibrary(RRCMws.hWSdll);
  479. RRCMws.hWSdll = NULL;
  480. }
  481. }
  482. }
  483. }
  484. // make sure we have the Xmt/Recv functionality
  485. if (RRCMws.sendTo == NULL ||
  486. RRCMws.recvFrom == NULL ||
  487. RRCMws.getsockname == NULL ||
  488. RRCMws.ntohl == NULL ||
  489. RRCMws.ntohs == NULL ||
  490. RRCMws.htonl == NULL ||
  491. RRCMws.htons == NULL ||
  492. RRCMws.gethostname == NULL ||
  493. RRCMws.gethostbyname == NULL ||
  494. RRCMws.WSASocket == NULL ||
  495. RRCMws.closesocket == NULL ||
  496. RRCMws.WSAIoctl == NULL ||
  497. RRCMws.WSAJoinLeaf == NULL
  498. )
  499. {
  500. RRCM_DBG_MSG ("RTP : ERROR - Invalid Winsock DLL", 0,
  501. __FILE__, __LINE__, DBG_CRITICAL);
  502. return RRCMError_WinsockLibNotFound;
  503. }
  504. else
  505. return RRCM_NoError;
  506. }
  507. // [EOF]