5db0413837521a9a3dee9725a601174faaaa2728
[mirror/winof/.git] / core / winverbs / user / wv_ep.cpp
1 /*\r
2  * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
3  * Portions Copyright (c) 2009 Microsoft Corporation.  All rights reserved.\r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  */\r
30 \r
31 #include "wv_memory.h"\r
32 #include "wv_ep.h"\r
33 #include "wv_ioctl.h"\r
34 #include "wv_qp.h"\r
35 \r
36 static void WvIoConvertConnParam(WV_IO_CONNECT_PARAM *pIoParam,\r
37                                                                  WV_CONNECT_PARAM *pParam)\r
38 {\r
39         pIoParam->DataLength = (UINT8) pParam->DataLength;\r
40         pIoParam->ResponderResources = pParam->ResponderResources;\r
41         pIoParam->InitiatorDepth = pParam->InitiatorDepth;\r
42         pIoParam->RetryCount = pParam->RetryCount;\r
43         pIoParam->RnrRetryCount = pParam->RnrRetryCount;\r
44         RtlZeroMemory(pIoParam->Reserved, sizeof pIoParam->Reserved);\r
45         RtlCopyMemory(pIoParam->Data, pParam->Data, pParam->DataLength);\r
46 }\r
47 \r
48 CWVConnectEndpoint::CWVConnectEndpoint(CWVProvider *pProvider)\r
49 {\r
50         pProvider->AddRef();\r
51         m_pProvider = pProvider;\r
52         m_hFile = pProvider->m_hFile;\r
53         m_Socket = INVALID_SOCKET;\r
54 }\r
55 \r
56 STDMETHODIMP CWVConnectEndpoint::\r
57 Allocate(void)\r
58 {\r
59         UINT64                  EpType;\r
60         DWORD                   bytes;\r
61         HRESULT                 hr;\r
62 \r
63         EpType = WV_IO_EP_TYPE_CONNECT;\r
64         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CREATE, &EpType, sizeof EpType,\r
65                                                   &m_Id, sizeof m_Id, &bytes, NULL)) {\r
66                 hr = WV_SUCCESS;\r
67         } else {\r
68                 hr = HRESULT_FROM_WIN32(GetLastError());\r
69         }\r
70 \r
71         return hr;\r
72 }\r
73 \r
74 CWVConnectEndpoint::~CWVConnectEndpoint()\r
75 {\r
76         DWORD   bytes;\r
77 \r
78         if (m_pQp != NULL) {\r
79                 m_pQp->Release();\r
80         }\r
81 \r
82         if (m_Id != 0) {\r
83                 WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DESTROY, &m_Id, sizeof m_Id,\r
84                                                   NULL, 0, &bytes, NULL);\r
85         }\r
86 \r
87         if (m_Socket != INVALID_SOCKET) {\r
88                 closesocket(m_Socket);\r
89         }\r
90         m_pProvider->Release();\r
91 }\r
92 \r
93 STDMETHODIMP CWVConnectEndpoint::\r
94 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
95 {\r
96         if (riid != IID_IUnknown && riid != IID_IWVEndpoint &&\r
97                 riid != IID_IWVConnectEndpoint) {\r
98                 *ppvObj = NULL;\r
99                 return E_NOINTERFACE;\r
100         }\r
101 \r
102         *ppvObj = this;\r
103         AddRef();\r
104         return WV_SUCCESS;\r
105 }\r
106 \r
107 STDMETHODIMP_(ULONG) CWVConnectEndpoint::\r
108 AddRef(void)\r
109 {\r
110         return CWVBase::AddRef();\r
111 }\r
112 \r
113 STDMETHODIMP_(ULONG) CWVConnectEndpoint::\r
114 Release(void)\r
115 {\r
116         return CWVBase::Release();\r
117 }\r
118 \r
119 STDMETHODIMP CWVConnectEndpoint::\r
120 CancelOverlappedRequests(void)\r
121 {\r
122         DWORD   bytes;\r
123 \r
124         return WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CANCEL, &m_Id, sizeof m_Id,\r
125                                                          NULL, 0, &bytes, NULL) ?\r
126                                                          WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
127 }\r
128 \r
129 STDMETHODIMP CWVConnectEndpoint::\r
130 GetOverlappedResult(OVERLAPPED *pOverlapped,\r
131                                         DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
132 {\r
133         ::GetOverlappedResult(m_hFile, pOverlapped, pNumberOfBytesTransferred, bWait);\r
134         return (HRESULT) pOverlapped->Internal;\r
135 }\r
136 \r
137 STDMETHODIMP CWVConnectEndpoint::\r
138 Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength)\r
139 {\r
140         WV_IO_ID                        *pId;\r
141         DWORD                           bytes;\r
142         HRESULT                         hr;\r
143         CWVBuffer                       buf;\r
144 \r
145         bytes = sizeof WV_IO_ID + OptionLength;\r
146         pId = (WV_IO_ID *) buf.Get(bytes);\r
147         if (pId == NULL) {\r
148                 return WV_NO_MEMORY;\r
149         }\r
150 \r
151         pId->Id = m_Id;\r
152         pId->Data = Option;\r
153         RtlCopyMemory(pId + 1, pOptionData, OptionLength);\r
154 \r
155         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_MODIFY, pId, bytes,\r
156                                                   NULL, 0, &bytes, NULL)) {\r
157                 hr = WV_SUCCESS;\r
158         } else {\r
159                 hr = HRESULT_FROM_WIN32(GetLastError());\r
160         }\r
161 \r
162         buf.Put();\r
163         return hr;\r
164 }\r
165 \r
166 STDMETHODIMP CWVConnectEndpoint::\r
167 BindAddress(SOCKADDR* pAddress)\r
168 {\r
169         WV_IO_EP_BIND           attr;\r
170         BOOLEAN                         any;\r
171         DWORD                           bytes;\r
172         int                                     len;\r
173         HRESULT                         hr;\r
174 \r
175         if (pAddress->sa_family == AF_INET) {\r
176                 any = (((SOCKADDR_IN *) pAddress)->sin_addr.S_un.S_addr == INADDR_ANY);\r
177                 bytes = sizeof(SOCKADDR_IN);\r
178         } else {\r
179                 any = IN6ADDR_ISANY((SOCKADDR_IN6 *) pAddress);\r
180                 bytes = sizeof(SOCKADDR_IN6);\r
181         }\r
182 \r
183         if (any) {\r
184                 RtlZeroMemory(&attr.Device, sizeof attr.Device);\r
185         } else {\r
186                 hr = m_pProvider->TranslateAddress(pAddress, (WV_DEVICE_ADDRESS *) &attr.Device);\r
187                 if (FAILED(hr)) {\r
188                         return hr;\r
189                 }\r
190         }\r
191 \r
192         m_Socket = socket(pAddress->sa_family, SOCK_STREAM, IPPROTO_TCP);\r
193         if (m_Socket == INVALID_SOCKET) {\r
194                 return WSAGetLastError();\r
195         }\r
196 \r
197         hr = bind(m_Socket, pAddress, bytes);\r
198         if (FAILED(hr)) {\r
199                 goto get_err;\r
200         }\r
201 \r
202         attr.Id = m_Id;\r
203         len = sizeof attr.Address;\r
204         hr = getsockname(m_Socket, (sockaddr *) &attr.Address, &len);\r
205         if (FAILED(hr)) {\r
206                 goto get_err;\r
207         }\r
208 \r
209         if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_BIND, &attr, sizeof attr,\r
210                                                    &attr, sizeof attr, &bytes, NULL)) {\r
211                 hr = HRESULT_FROM_WIN32(GetLastError());\r
212                 goto err;\r
213         }\r
214 \r
215         return WV_SUCCESS;\r
216 \r
217 get_err:\r
218         hr = WSAGetLastError();\r
219 err:\r
220         closesocket(m_Socket);\r
221         m_Socket = INVALID_SOCKET;\r
222         return hr;\r
223 }\r
224 \r
225 STDMETHODIMP CWVConnectEndpoint::\r
226 Listen(SIZE_T Backlog)\r
227 {\r
228         WV_IO_EP_LISTEN         attr;\r
229         DWORD                           bytes;\r
230         HRESULT                         hr;\r
231 \r
232         attr.Id = m_Id;\r
233         attr.Backlog = Backlog;\r
234 \r
235         if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_LISTEN, &attr, sizeof attr,\r
236                                                    &attr, sizeof attr, &bytes, NULL)) {\r
237                 hr = HRESULT_FROM_WIN32(GetLastError());\r
238         } else {\r
239                 hr = WV_SUCCESS;\r
240         }\r
241 \r
242         return hr;\r
243 }\r
244 \r
245 STDMETHODIMP CWVConnectEndpoint::\r
246 Reject(const VOID* pUserData, SIZE_T UserDataLength)\r
247 {\r
248         WV_IO_ID                        *pId;\r
249         DWORD                           bytes;\r
250         HRESULT                         hr;\r
251         CWVBuffer                       buf;\r
252 \r
253         bytes = sizeof WV_IO_ID + UserDataLength;\r
254         pId = (WV_IO_ID *) buf.Get(bytes);\r
255         if (pId == NULL) {\r
256                 return WV_NO_MEMORY;\r
257         }\r
258 \r
259         pId->Id = m_Id;\r
260         RtlCopyMemory(pId + 1, pUserData, UserDataLength);\r
261 \r
262         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_REJECT, pId, bytes,\r
263                                                   NULL, 0, &bytes, NULL)) {\r
264                 hr = WV_SUCCESS;\r
265         } else {\r
266                 hr = HRESULT_FROM_WIN32(GetLastError());\r
267         }\r
268 \r
269         buf.Put();\r
270         return hr;\r
271 }\r
272 \r
273 STDMETHODIMP CWVConnectEndpoint::\r
274 GetRequest(IWVConnectEndpoint* pEndpoint, OVERLAPPED* pOverlapped)\r
275 {\r
276         WV_IO_EP_GET_REQUEST    req;\r
277         DWORD                                   bytes;\r
278         HRESULT                                 hr;\r
279 \r
280         req.Id = m_Id;\r
281         req.EpId = ((CWVConnectEndpoint *) pEndpoint)->m_Id;\r
282         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_GET_REQUEST,\r
283                                                   &req, sizeof req, NULL, 0, &bytes, pOverlapped)) {\r
284                 hr = WV_SUCCESS;\r
285         } else {\r
286                 hr = HRESULT_FROM_WIN32(GetLastError());\r
287         }\r
288 \r
289         return hr;\r
290 }\r
291 \r
292 STDMETHODIMP CWVConnectEndpoint::\r
293 Connect(IWVConnectQueuePair* pQp, const SOCKADDR* pAddress,\r
294                 WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)\r
295 {\r
296         WV_IO_EP_CONNECT        attr;\r
297         DWORD                           bytes;\r
298         HRESULT                         hr;\r
299 \r
300         m_pQp = (CWVConnectQueuePair *) pQp;\r
301         m_pQp->AddRef();\r
302         attr.Id = m_Id;\r
303         attr.QpId = m_pQp->m_Id;\r
304 \r
305         if (pAddress->sa_family == AF_INET) {\r
306                 RtlCopyMemory(&attr.PeerAddress, pAddress, sizeof(SOCKADDR_IN));\r
307         } else {\r
308                 RtlCopyMemory(&attr.PeerAddress, pAddress, sizeof(SOCKADDR_IN6));\r
309         }\r
310         WvIoConvertConnParam(&attr.Param, pParam);\r
311 \r
312         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CONNECT, &attr, sizeof attr,\r
313                                                   NULL, 0, &bytes, pOverlapped)) {\r
314                 hr = WV_SUCCESS;\r
315         } else {\r
316                 hr = HRESULT_FROM_WIN32(GetLastError());\r
317         }\r
318 \r
319         return hr;\r
320 }\r
321 \r
322 STDMETHODIMP CWVConnectEndpoint::\r
323 Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)\r
324 {\r
325         WV_IO_EP_ACCEPT         attr;\r
326         DWORD                           bytes;\r
327         HRESULT                         hr;\r
328         void                            *pout;\r
329         DWORD                           size;\r
330 \r
331         if (m_pQp == NULL) {\r
332                 m_pQp = (CWVConnectQueuePair *) pQp;\r
333                 m_pQp->AddRef();\r
334         }\r
335 \r
336         attr.Id = m_Id;\r
337         attr.QpId = m_pQp->m_Id;\r
338         m_pQp->m_pVerbs->nd_modify_qp(m_pQp->m_hVerbsQp, &pout, &size);\r
339         WvIoConvertConnParam(&attr.Param, pParam);\r
340 \r
341         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_ACCEPT, &attr, sizeof attr,\r
342                                                   pout, size, &bytes, pOverlapped)) {\r
343                 hr = WV_SUCCESS;\r
344         } else {\r
345                 hr = HRESULT_FROM_WIN32(GetLastError());\r
346         }\r
347 \r
348         return hr;\r
349 }\r
350 \r
351 STDMETHODIMP CWVConnectEndpoint::\r
352 Disconnect(OVERLAPPED* pOverlapped)\r
353 {\r
354         WV_IO_EP_DISCONNECT     attr;\r
355         DWORD                           bytes;\r
356         HRESULT                         hr;\r
357         void                            *pout;\r
358         DWORD                           size;\r
359 \r
360         attr.Id = m_Id;\r
361         attr.QpId = m_pQp->m_Id;\r
362         m_pQp->m_pVerbs->nd_modify_qp(m_pQp->m_hVerbsQp, &pout, &size);\r
363 \r
364         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DISCONNECT,\r
365                                                   &attr, sizeof attr, pout, size, &bytes, pOverlapped)) {\r
366                 hr = WV_SUCCESS;\r
367         } else {\r
368                 hr = HRESULT_FROM_WIN32(GetLastError());\r
369         }\r
370 \r
371         return hr;\r
372 }\r
373 \r
374 STDMETHODIMP CWVConnectEndpoint::\r
375 NotifyDisconnect(OVERLAPPED* pOverlapped)\r
376 {\r
377         DWORD           bytes;\r
378         HRESULT         hr;\r
379 \r
380         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DISCONNECT_NOTIFY,\r
381                                                   &m_Id, sizeof m_Id, NULL, 0, &bytes, pOverlapped)) {\r
382                 hr = WV_SUCCESS;\r
383         } else {\r
384                 hr = HRESULT_FROM_WIN32(GetLastError());\r
385         }\r
386 \r
387         return hr;\r
388 }\r
389 \r
390 STDMETHODIMP CWVConnectEndpoint::\r
391 Query(WV_CONNECT_ATTRIBUTES* pAttributes)\r
392 {\r
393         WV_IO_EP_ATTRIBUTES     attr;\r
394         DWORD                           bytes;\r
395         HRESULT                         hr;\r
396 \r
397         if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_QUERY, &m_Id, sizeof m_Id,\r
398                                                    &attr, sizeof attr, &bytes, NULL)) {\r
399                 return HRESULT_FROM_WIN32(GetLastError());\r
400         }\r
401 \r
402         RtlCopyMemory(&pAttributes->LocalAddress, &attr.LocalAddress,\r
403                                   sizeof pAttributes->LocalAddress);\r
404         RtlCopyMemory(&pAttributes->PeerAddress, &attr.PeerAddress,\r
405                                   sizeof pAttributes->PeerAddress);\r
406         RtlCopyMemory(&pAttributes->Device, &attr.Device, sizeof pAttributes->Device);\r
407         pAttributes->Param.DataLength = attr.Param.Connect.DataLength;\r
408         pAttributes->Param.ResponderResources = (SIZE_T) attr.Param.Connect.ResponderResources;\r
409         pAttributes->Param.InitiatorDepth = (SIZE_T) attr.Param.Connect.InitiatorDepth;\r
410         pAttributes->Param.RetryCount = attr.Param.Connect.RetryCount;\r
411         pAttributes->Param.RnrRetryCount = attr.Param.Connect.RnrRetryCount;\r
412         RtlCopyMemory(pAttributes->Param.Data, attr.Param.Connect.Data, attr.Param.Connect.DataLength);\r
413 \r
414         return WV_SUCCESS;\r
415 }\r
416 \r
417 \r
418 CWVDatagramEndpoint::CWVDatagramEndpoint(CWVProvider *pProvider)\r
419 {\r
420         pProvider->AddRef();\r
421         m_pProvider = pProvider;\r
422         m_hFile = pProvider->m_hFile;\r
423 }\r
424         \r
425 STDMETHODIMP CWVDatagramEndpoint::\r
426 Allocate(void)\r
427 {\r
428         UINT64                  EpType;\r
429         DWORD                   bytes;\r
430         HRESULT                 hr;\r
431 \r
432         EpType = WV_IO_EP_TYPE_DATAGRAM;\r
433         if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CREATE, &EpType, sizeof EpType,\r
434                                                   &m_Id, sizeof m_Id, &bytes, NULL)) {\r
435                 hr = WV_SUCCESS;\r
436         } else {\r
437                 hr = HRESULT_FROM_WIN32(GetLastError());\r
438         }\r
439 \r
440         return hr;\r
441 }\r
442 \r
443 CWVDatagramEndpoint::~CWVDatagramEndpoint()\r
444 {\r
445         DWORD   bytes;\r
446 \r
447         if (m_Id != 0) {\r
448                 WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DESTROY, &m_Id, sizeof m_Id,\r
449                                                   NULL, 0, &bytes, NULL);\r
450         }\r
451         m_pProvider->Release();\r
452 }\r
453 \r
454 STDMETHODIMP CWVDatagramEndpoint::\r
455 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
456 {\r
457         if (riid != IID_IUnknown && riid != IID_IWVEndpoint &&\r
458                 riid != IID_IWVDatagramEndpoint) {\r
459                 *ppvObj = NULL;\r
460                 return E_NOINTERFACE;\r
461         }\r
462 \r
463         *ppvObj = this;\r
464         AddRef();\r
465         return WV_SUCCESS;\r
466 }\r
467 \r
468 STDMETHODIMP_(ULONG) CWVDatagramEndpoint::\r
469 AddRef(void)\r
470 {\r
471         return CWVBase::AddRef();\r
472 }\r
473 \r
474 STDMETHODIMP_(ULONG) CWVDatagramEndpoint::\r
475 Release(void)\r
476 {\r
477         return CWVBase::Release();\r
478 }\r
479 \r
480 STDMETHODIMP CWVDatagramEndpoint::\r
481 CancelOverlappedRequests(void)\r
482 {\r
483         DWORD   bytes;\r
484 \r
485         return WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CANCEL, &m_Id, sizeof m_Id,\r
486                                                          NULL, 0, &bytes, NULL) ?\r
487                                                          WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
488 }\r
489 \r
490 STDMETHODIMP CWVDatagramEndpoint::\r
491 GetOverlappedResult(OVERLAPPED *pOverlapped,\r
492                                         DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
493 {\r
494         ::GetOverlappedResult(m_hFile, pOverlapped, pNumberOfBytesTransferred, bWait);\r
495         return (HRESULT) pOverlapped->Internal;\r
496 }\r
497 \r
498 STDMETHODIMP CWVDatagramEndpoint::\r
499 Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength)\r
500 {\r
501         UNREFERENCED_PARAMETER(Option);\r
502         UNREFERENCED_PARAMETER(pOptionData);\r
503         UNREFERENCED_PARAMETER(OptionLength);\r
504 \r
505         return E_NOTIMPL;\r
506 }\r
507 \r
508 STDMETHODIMP CWVDatagramEndpoint::\r
509 BindAddress(SOCKADDR* pAddress)\r
510 {\r
511         UNREFERENCED_PARAMETER(pAddress);\r
512 \r
513         return E_NOTIMPL;\r
514 }\r
515 \r
516 STDMETHODIMP CWVDatagramEndpoint::\r
517 Listen(SIZE_T Backlog)\r
518 {\r
519         UNREFERENCED_PARAMETER(Backlog);\r
520 \r
521         return E_NOTIMPL;\r
522 }\r
523 \r
524 STDMETHODIMP CWVDatagramEndpoint::\r
525 Reject(const VOID* pUserData, SIZE_T UserDataLength)\r
526 {\r
527         UNREFERENCED_PARAMETER(pUserData);\r
528         UNREFERENCED_PARAMETER(UserDataLength);\r
529 \r
530         return E_NOTIMPL;\r
531 }\r
532 \r
533 STDMETHODIMP CWVDatagramEndpoint::\r
534 GetRequest(IWVDatagramEndpoint* pEndpoint, OVERLAPPED* pOverlapped)\r
535 {\r
536         UNREFERENCED_PARAMETER(pEndpoint);\r
537         UNREFERENCED_PARAMETER(pOverlapped);\r
538 \r
539         return E_NOTIMPL;\r
540 }\r
541 \r
542 STDMETHODIMP CWVDatagramEndpoint::\r
543 Lookup(const SOCKADDR* pAddress, const VOID* pUserData,\r
544            SIZE_T UserDataLength, OVERLAPPED* pOverlapped)\r
545 {\r
546         UNREFERENCED_PARAMETER(pAddress);\r
547         UNREFERENCED_PARAMETER(pUserData);\r
548         UNREFERENCED_PARAMETER(UserDataLength);\r
549         UNREFERENCED_PARAMETER(pOverlapped);\r
550 \r
551         return E_NOTIMPL;\r
552 }\r
553 \r
554 STDMETHODIMP CWVDatagramEndpoint::\r
555 Accept(WV_DATAGRAM_PARAM* pParam, OVERLAPPED* pOverlapped)\r
556 {\r
557         UNREFERENCED_PARAMETER(pParam);\r
558         UNREFERENCED_PARAMETER(pOverlapped);\r
559 \r
560         return E_NOTIMPL;\r
561 }\r
562 \r
563 STDMETHODIMP CWVDatagramEndpoint::\r
564 JoinMulticast(const SOCKADDR* pAddress, OVERLAPPED* pOverlapped)\r
565 {\r
566         UNREFERENCED_PARAMETER(pAddress);\r
567         UNREFERENCED_PARAMETER(pOverlapped);\r
568 \r
569         return E_NOTIMPL;\r
570 }\r
571 \r
572 STDMETHODIMP CWVDatagramEndpoint::\r
573 LeaveMulticast(const SOCKADDR* pAddress, OVERLAPPED* pOverlapped)\r
574 {\r
575         UNREFERENCED_PARAMETER(pAddress);\r
576         UNREFERENCED_PARAMETER(pOverlapped);\r
577 \r
578         return E_NOTIMPL;\r
579 }\r
580 \r
581 STDMETHODIMP CWVDatagramEndpoint::\r
582 Query(WV_DATAGRAM_ATTRIBUTES* pAttributes)\r
583 {\r
584         UNREFERENCED_PARAMETER(pAttributes);\r
585 \r
586         return E_NOTIMPL;\r
587 }\r