netdirect: add winverbs ND provider
[mirror/winof/.git] / ulp / netdirect / user / nd_provider.cpp
1 /*\r
2  * Copyright (c) 2009 Intel Corporation. All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  */\r
29 \r
30 #include "nd_provider.h"\r
31 #include "nd_adapter.h"\r
32 #include <ws2tcpip.h>\r
33 \r
34 STDMETHODIMP CNDProvider::\r
35 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
36 {\r
37         if (riid != IID_IUnknown && riid != IID_INDProvider) {\r
38                 *ppvObj = NULL;\r
39                 return E_NOINTERFACE;\r
40         }\r
41 \r
42         *ppvObj = this;\r
43         AddRef();\r
44         return ND_SUCCESS;\r
45 }\r
46 \r
47 STDMETHODIMP_(ULONG) CNDProvider::\r
48 AddRef(void)\r
49 {\r
50         return CNDBase::AddRef();\r
51 }\r
52 \r
53 STDMETHODIMP_(ULONG) CNDProvider::\r
54 Release(void)\r
55 {\r
56         return CNDBase::Release();\r
57 }\r
58 \r
59 STDMETHODIMP CNDProvider::\r
60 QueryAddressList(SOCKET_ADDRESS_LIST* pAddressList, SIZE_T* pBufferSize)\r
61 {\r
62         WV_DEVICE_ADDRESS devaddr;\r
63         IWVProvider *prov;\r
64         struct addrinfo *res, *ai;\r
65         HRESULT hr;\r
66         int cnt = 0;\r
67         size_t addrlen = 0, size;\r
68         UINT8 *offset;\r
69 \r
70         hr = WvGetObject(IID_IWVProvider, (LPVOID *) &prov);\r
71         if (FAILED(hr)) {\r
72                 return hr;\r
73         }\r
74 \r
75         hr = getaddrinfo("..localmachine", NULL, NULL, &res);\r
76         if (hr) {\r
77                 goto release;\r
78         }\r
79 \r
80         for (ai = res; ai; ai = ai->ai_next) {\r
81                 ai->ai_flags = prov->TranslateAddress(ai->ai_addr, &devaddr);\r
82                 if (SUCCEEDED(ai->ai_flags)) {\r
83                         cnt++;\r
84                         addrlen += ai->ai_addrlen;\r
85                 }\r
86         }\r
87 \r
88         if (cnt == 0) {\r
89                 *pBufferSize = 0;\r
90                 goto free;\r
91         }\r
92 \r
93         size = sizeof(SOCKET_ADDRESS_LIST) + sizeof(SOCKET_ADDRESS) * (cnt - 1);\r
94         if (size + addrlen > *pBufferSize) {\r
95                 *pBufferSize = size + addrlen;\r
96                 hr = ND_BUFFER_OVERFLOW;\r
97                 goto free;\r
98         }\r
99 \r
100         pAddressList->iAddressCount = cnt;\r
101         offset = (UINT8 *) pAddressList + size;\r
102         for (cnt = 0, ai = res; ai; ai = ai->ai_next) {\r
103                 if (SUCCEEDED(ai->ai_flags)) {\r
104                         pAddressList->Address[cnt].iSockaddrLength = ai->ai_addrlen;\r
105                         pAddressList->Address[cnt].lpSockaddr = (LPSOCKADDR) offset;\r
106                         RtlCopyMemory(offset, ai->ai_addr, ai->ai_addrlen);\r
107                         offset += ai->ai_addrlen;\r
108                 }\r
109         }\r
110 \r
111 free:\r
112         freeaddrinfo(res);\r
113 release:\r
114         prov->Release();\r
115         return hr;\r
116 }\r
117 \r
118 STDMETHODIMP CNDProvider::\r
119 OpenAdapter(const struct sockaddr* pAddress, SIZE_T AddressLength,\r
120                         INDAdapter** ppAdapter)\r
121 {\r
122         return CNDAdapter::CreateInstance(this, pAddress, AddressLength, ppAdapter);\r
123 }\r
124 \r
125 \r
126 //-------------------------\r
127 // CNDClassFactory routines\r
128 //-------------------------\r
129 \r
130 STDMETHODIMP CNDClassFactory::\r
131 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
132 {\r
133         if (riid != IID_IUnknown && riid != IID_IClassFactory) {\r
134                 *ppvObj = NULL;\r
135                 return E_NOINTERFACE;\r
136         }\r
137 \r
138         *ppvObj = this;\r
139         AddRef();\r
140         return ND_SUCCESS;\r
141 }\r
142 \r
143 STDMETHODIMP_(ULONG) CNDClassFactory::\r
144 AddRef(void)\r
145 {\r
146         return CNDBase::AddRef();\r
147 }\r
148 \r
149 STDMETHODIMP_(ULONG) CNDClassFactory::\r
150 Release(void)\r
151 {\r
152         return CNDBase::Release();\r
153 }\r
154 \r
155 STDMETHODIMP CNDClassFactory::\r
156 CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppObject)\r
157 {\r
158         if (pUnkOuter != NULL) {\r
159                 return CLASS_E_NOAGGREGATION;\r
160         }\r
161 \r
162         if (riid != IID_INDProvider) {\r
163                 *ppObject = NULL;\r
164                 return E_NOINTERFACE;\r
165         }\r
166 \r
167         *ppObject = new CNDProvider();\r
168         if (*ppObject == NULL) {\r
169                 return E_OUTOFMEMORY;\r
170         }\r
171 \r
172         return S_OK;\r
173 }\r
174 \r
175 STDMETHODIMP CNDClassFactory::\r
176 LockServer(BOOL fLock)\r
177 {\r
178         UNREFERENCED_PARAMETER(fLock);\r
179         return S_OK;\r
180 }\r