1 /*
2 * Copyright (c) 2015-2016 Intel Corporation, Inc. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33 #ifdef _WIN32
34
35 #include <initguid.h>
36 #include <guiddef.h>
37
38 #include <ws2spi.h>
39 #include <cassert>
40 #include "ndspi.h"
41
42 #include "netdir.h"
43 #include "netdir_log.h"
44
45 #ifndef ofi_sizeofaddr
46 #define ofi_sizeofaddr(address) \
47 (address)->sa_family == AF_INET ? \
48 sizeof(struct sockaddr_in) : \
49 sizeof(struct sockaddr_in6)
50 #endif
51
52 #define FI_ND_PROTO_FLAG (XP1_GUARANTEED_DELIVERY | XP1_GUARANTEED_ORDER | \
53 XP1_MESSAGE_ORIENTED | XP1_CONNECT_DATA)
54
55 static int ofi_nd_startup_done = 0;
56
57 typedef HRESULT(*can_unload_now_t)(void);
58 typedef HRESULT(*get_class_object_t)(REFCLSID rclsid, REFIID rrid, LPVOID* ppv);
59
60 struct module_t {
61 const wchar_t *path;
62 HMODULE module;
63 can_unload_now_t can_unload_now;
64 get_class_object_t get_class_object;
65 };
66
67 struct factory_t {
68 WSAPROTOCOL_INFOW protocol;
69 IClassFactory *class_factory;
70 IND2Provider *provider;
71 struct module_t *module;
72 SOCKET_ADDRESS_LIST *addr_list;
73 };
74
75 struct adapter_t {
76 union {
77 struct sockaddr addr;
78 struct sockaddr_in addr4;
79 struct sockaddr_in6 addr6;
80 } address;
81 ND2_ADAPTER_INFO info;
82 IND2Adapter *adapter;
83 struct factory_t *factory;
84 const char *name;
85 };
86
87 static struct ofi_nd_infra_t {
88 struct modules_t {
89 struct module_t *modules;
90 size_t count;
91 } providers;
92
93 struct class_factory_t {
94 struct factory_t *factory;
95 size_t count;
96 } class_factories;
97
98 struct adapters_t {
99 struct adapter_t *adapter;
100 size_t count;
101 } adapters;
102 } ofi_nd_infra = {0};
103
104 /* release all objects, do not free strings or arrays */
ofi_nd_release_infra()105 static inline void ofi_nd_release_infra()
106 {
107 size_t i;
108
109 if (ofi_nd_infra.adapters.count) {
110 assert(ofi_nd_infra.adapters.adapter);
111 for (i = 0; i < ofi_nd_infra.adapters.count; i++) {
112 struct adapter_t *adapter = &ofi_nd_infra.adapters.adapter[i];
113 if (adapter->adapter) {
114 adapter->adapter->lpVtbl->Release(adapter->adapter);
115 adapter->adapter = 0;
116 }
117 }
118 }
119
120 if (ofi_nd_infra.class_factories.count) {
121 assert(ofi_nd_infra.class_factories.factory);
122 for (i = 0; i < ofi_nd_infra.class_factories.count; i++) {
123 struct factory_t *factory = &ofi_nd_infra.class_factories.factory[i];
124 if (factory->provider) {
125 factory->provider->lpVtbl->Release(factory->provider);
126 factory->provider = 0;
127 }
128 if (factory->class_factory) {
129 factory->class_factory->lpVtbl->Release(factory->class_factory);
130 factory->class_factory = 0;
131 }
132 }
133 }
134 }
135
ofi_nd_free_infra()136 static inline void ofi_nd_free_infra()
137 {
138 size_t i;
139
140 ofi_nd_release_infra();
141
142 if (ofi_nd_infra.adapters.count) {
143 assert(ofi_nd_infra.adapters.adapter);
144 for (i = 0; i < ofi_nd_infra.adapters.count; i++) {
145 struct adapter_t *adapter = &ofi_nd_infra.adapters.adapter[i];
146 if (adapter->name) {
147 free((void*)adapter->name);
148 adapter->name = 0;
149 }
150 }
151 free(ofi_nd_infra.adapters.adapter);
152 ofi_nd_infra.adapters.adapter = 0;
153 ofi_nd_infra.adapters.count = 0;
154 }
155
156 if (ofi_nd_infra.class_factories.count) {
157 assert(ofi_nd_infra.class_factories.factory);
158 for (i = 0; i < ofi_nd_infra.class_factories.count; i++) {
159 struct factory_t *factory = &ofi_nd_infra.class_factories.factory[i];
160 assert(factory->module);
161 if (factory->addr_list) {
162 free(factory->addr_list);
163 factory->addr_list = 0;
164 }
165 }
166 free(ofi_nd_infra.class_factories.factory);
167 ofi_nd_infra.class_factories.factory = 0;
168 ofi_nd_infra.class_factories.count = 0;
169 }
170
171 if (ofi_nd_infra.providers.count) {
172 assert(ofi_nd_infra.providers.modules);
173 for (i = 0; i < ofi_nd_infra.providers.count; i++) {
174 struct module_t *module = &ofi_nd_infra.providers.modules[i];
175 assert(module->path);
176 free((void*)module->path);
177 }
178 free(ofi_nd_infra.providers.modules);
179 ofi_nd_infra.providers.modules = 0;
180 ofi_nd_infra.providers.count = 0;
181 }
182 }
183
ofi_nd_alloc_infra(size_t cnt)184 static inline HRESULT ofi_nd_alloc_infra(size_t cnt)
185 {
186 memset(&ofi_nd_infra, 0, sizeof(*(&ofi_nd_infra)));
187
188 ofi_nd_infra.providers.modules = (struct module_t*)malloc(cnt * sizeof(*ofi_nd_infra.providers.modules));
189 if (!ofi_nd_infra.providers.modules)
190 return ND_NO_MEMORY;
191
192 ofi_nd_infra.class_factories.factory = (struct factory_t*)malloc(cnt * sizeof(*ofi_nd_infra.class_factories.factory));
193 if (!ofi_nd_infra.class_factories.factory) {
194 ofi_nd_free_infra();
195 return ND_NO_MEMORY;
196 }
197
198 return S_OK;
199 }
200
ofi_nd_get_provider_path(const WSAPROTOCOL_INFOW * proto)201 static inline wchar_t *ofi_nd_get_provider_path(const WSAPROTOCOL_INFOW *proto)
202 {
203 assert(proto);
204
205 int len, lenex, err, res;
206 wchar_t *prov, *provex;
207
208 res = WSCGetProviderPath((GUID*)&proto->ProviderId, NULL, &len, &err);
209 if (err != WSAEFAULT || !len)
210 return NULL;
211
212 prov = (wchar_t*)malloc(len * sizeof(*prov));
213 if (!prov)
214 return NULL;
215
216 res = WSCGetProviderPath((GUID*)&proto->ProviderId, prov, &len, &err);
217 if (res)
218 goto fn1;
219
220 lenex = ExpandEnvironmentStringsW(prov, NULL, 0);
221 if (!lenex)
222 goto fn1;
223
224 provex = (wchar_t*)malloc(lenex * sizeof(*provex));
225 if (!provex)
226 goto fn1;
227
228 lenex = ExpandEnvironmentStringsW(prov, provex, lenex);
229 if (!lenex)
230 goto fn2;
231
232 free(prov);
233 return provex;
234
235 fn2:
236 free(provex);
237 fn1:
238 free(prov);
239 return NULL;
240 }
241
ofi_nd_is_valid_proto(const WSAPROTOCOL_INFOW * proto)242 static inline int ofi_nd_is_valid_proto(const WSAPROTOCOL_INFOW *proto)
243 {
244 assert(proto);
245
246 if ((proto->dwServiceFlags1 & FI_ND_PROTO_FLAG) != FI_ND_PROTO_FLAG)
247 return 0;
248
249 if (!(proto->iAddressFamily == AF_INET ||
250 proto->iAddressFamily == AF_INET6))
251 return 0;
252
253 if (proto->iSocketType != -1)
254 return 0;
255
256 if (proto->iProtocol || proto->iProtocolMaxOffset)
257 return 0;
258 return 1;
259 }
260
ofi_nd_search_module(const wchar_t * path)261 static inline struct module_t *ofi_nd_search_module(const wchar_t* path)
262 {
263 size_t i;
264 size_t j;
265
266 for (i = 0; i < ofi_nd_infra.providers.count; i++) {
267 if (path && ofi_nd_file_exists(path) &&
268 !ofi_nd_is_directory(path)) {
269 for (j = 0; j < ofi_nd_infra.providers.count; j++) {
270 if (ofi_nd_is_same_file(path, ofi_nd_infra.providers.modules[j].path)) {
271 return &ofi_nd_infra.providers.modules[j];
272 }
273 }
274 }
275 }
276 return NULL;
277 }
278
ofi_nd_create_module(const wchar_t * path)279 static inline struct module_t *ofi_nd_create_module(const wchar_t* path)
280 {
281 struct module_t *module;
282 HMODULE hmodule;
283 can_unload_now_t unload;
284 get_class_object_t getclass;
285
286 assert(ofi_nd_infra.providers.modules);
287
288 module = ofi_nd_search_module(path);
289 if (module)
290 return module;
291
292 /* ok, this is not duplicate. try to
293 load it and get class factory*/
294 hmodule = LoadLibraryW(path);
295 if (!hmodule) {
296 ND_LOG_WARN(FI_LOG_CORE,
297 "ofi_nd_create_module: provider : %S, failed to load: %s\n",
298 path, ofi_nd_strerror(GetLastError(), 0));
299 return NULL;
300 }
301
302 unload = (can_unload_now_t)GetProcAddress(hmodule, "DllCanUnloadNow");
303 getclass = (get_class_object_t)GetProcAddress(hmodule, "DllGetClassObject");
304 if (!unload || !getclass) {
305 ND_LOG_WARN(FI_LOG_CORE,
306 "ofi_nd_create_module: provider: %S, failed to import interface\n",
307 path);
308 goto fn_noiface;
309 }
310
311 module = &ofi_nd_infra.providers.modules[ofi_nd_infra.providers.count];
312 ofi_nd_infra.providers.count++;
313
314 module->path = _wcsdup(path);
315 module->module = hmodule;
316 module->can_unload_now = unload;
317 module->get_class_object = getclass;
318
319 return module;
320
321 fn_noiface:
322 FreeLibrary(hmodule);
323 return NULL;
324 }
325
ofi_nd_create_factory(const WSAPROTOCOL_INFOW * proto)326 static inline HRESULT ofi_nd_create_factory(const WSAPROTOCOL_INFOW* proto)
327 {
328 wchar_t *path;
329 struct module_t *module;
330 IClassFactory* factory;
331 HRESULT hr;
332 struct factory_t *ftr;
333
334 assert(proto);
335 assert(ofi_nd_is_valid_proto(proto));
336 assert(ofi_nd_infra.class_factories.factory);
337
338 path = ofi_nd_get_provider_path(proto);
339 if (path)
340 ND_LOG_INFO(FI_LOG_CORE,
341 "ofi_nd_create_factory: provider " FI_ND_GUID_FORMAT " path: %S \n",
342 FI_ND_GUID_ARG(proto->ProviderId), path);
343 else /* can't get provider path. just return */
344 return S_OK;
345
346 module = ofi_nd_create_module(path);
347 free(path);
348 if (!module)
349 return S_OK;
350
351 assert(module->get_class_object);
352 hr = module->get_class_object(&proto->ProviderId, &IID_IClassFactory,
353 (void**)&factory);
354 if (FAILED(hr))
355 return hr;
356
357 ftr = &ofi_nd_infra.class_factories.factory[ofi_nd_infra.class_factories.count];
358 ofi_nd_infra.class_factories.count++;
359 ftr->class_factory = factory;
360 ftr->module = module;
361 ftr->protocol = *proto;
362
363 return S_OK;
364 }
365
ofi_nd_adapter_cmp(const void * adapter1,const void * adapter2)366 static int ofi_nd_adapter_cmp(const void *adapter1, const void *adapter2)
367 {
368 return ofi_nd_addr_cmp(&((struct adapter_t*)adapter1)->address,
369 &((struct adapter_t*)adapter2)->address);
370 }
371
ofi_nd_create_adapter(void)372 static HRESULT ofi_nd_create_adapter(void)
373 {
374 size_t addr_count = 0;
375 HRESULT hr;
376
377 for (size_t i = 0; i < ofi_nd_infra.class_factories.count; i++) {
378 struct factory_t *factory = &ofi_nd_infra.class_factories.factory[i];
379 ULONG listsize = 0;
380
381 assert(factory->class_factory);
382
383 hr = factory->class_factory->lpVtbl->CreateInstance(factory->class_factory,
384 NULL, &IID_IND2Provider, (void**)&factory->provider);
385 if (FAILED(hr))
386 return hr;
387 hr = factory->provider->lpVtbl->QueryAddressList(factory->provider, NULL, &listsize);
388 if (hr != ND_BUFFER_OVERFLOW)
389 return hr;
390 if (!listsize) {
391 continue;
392 }
393
394 factory->addr_list = (SOCKET_ADDRESS_LIST*)malloc(listsize);
395 if (!factory->addr_list)
396 return ND_NO_MEMORY;
397
398 hr = factory->provider->lpVtbl->QueryAddressList(factory->provider,
399 factory->addr_list, &listsize);
400 if (FAILED(hr))
401 return hr;
402
403 for (INT j = 0; j < factory->addr_list->iAddressCount; j++) {
404 if (ofi_nd_is_valid_addr(factory->addr_list->Address[j].lpSockaddr))
405 addr_count++;
406 }
407 }
408
409 if (!addr_count)
410 return E_NOINTERFACE;
411
412 ofi_nd_infra.adapters.adapter = (struct adapter_t*)malloc(addr_count * sizeof(*ofi_nd_infra.adapters.adapter));
413 if (!ofi_nd_infra.adapters.adapter)
414 return ND_NO_MEMORY;
415
416 /* put all available valid addresses into common array */
417 for (size_t i = 0; i < ofi_nd_infra.class_factories.count; i++) {
418 struct factory_t *factory = &ofi_nd_infra.class_factories.factory[i];
419 for (INT j = 0; j < factory->addr_list->iAddressCount; j++) {
420 if (ofi_nd_is_valid_addr(factory->addr_list->Address[j].lpSockaddr)) {
421 struct adapter_t *adapter = &ofi_nd_infra.adapters.adapter[ofi_nd_infra.adapters.count];
422 assert((int)sizeof(adapter->address) >= factory->addr_list->Address[j].iSockaddrLength);
423 memcpy(&adapter->address,
424 factory->addr_list->Address[j].lpSockaddr,
425 factory->addr_list->Address[j].iSockaddrLength);
426 adapter->factory = factory;
427 ofi_nd_infra.adapters.count++;
428 }
429 }
430 }
431
432 if (!ofi_nd_infra.adapters.count)
433 return E_NOINTERFACE;
434
435 /* sort adapters by addresses to set IP4 addresses first. then remove
436 duplicates */
437 qsort(ofi_nd_infra.adapters.adapter, ofi_nd_infra.adapters.count,
438 sizeof(struct adapter_t), ofi_nd_adapter_cmp);
439 ofi_nd_infra.adapters.count = unique(ofi_nd_infra.adapters.adapter,
440 ofi_nd_infra.adapters.count,
441 sizeof(struct adapter_t), ofi_nd_adapter_cmp);
442
443 for (size_t i = 0; i < ofi_nd_infra.adapters.count; i++) {
444 struct adapter_t *adapter = &ofi_nd_infra.adapters.adapter[i];
445 struct factory_t *factory = adapter->factory;
446 wchar_t *saddr;
447 DWORD addrlen = 0;
448 UINT64 id;
449 int res;
450
451 assert(factory);
452 assert(factory->provider);
453
454 assert(adapter->address.addr.sa_family == AF_INET ||
455 adapter->address.addr.sa_family == AF_INET6);
456
457 hr = factory->provider->lpVtbl->ResolveAddress(factory->provider,
458 &adapter->address.addr,
459 ofi_sizeofaddr(&adapter->address.addr), &id);
460
461 if (FAILED(hr))
462 return hr;
463
464 hr = factory->provider->lpVtbl->OpenAdapter(factory->provider,
465 &IID_IND2Adapter, id, (void**)&adapter->adapter);
466 if (FAILED(hr))
467 return hr;
468
469 ULONG linfo = sizeof(adapter->info);
470 adapter->info.InfoVersion = ND_VERSION_2;
471 hr = adapter->adapter->lpVtbl->Query(adapter->adapter, &adapter->info, &linfo);
472 if (FAILED(hr) && hr == ND_BUFFER_OVERFLOW) {
473 ND2_ADAPTER_INFO *info = (ND2_ADAPTER_INFO*)malloc(linfo);
474 if (!info)
475 return ND_NO_MEMORY;
476 info->InfoVersion = ND_VERSION_2;
477 hr = adapter->adapter->lpVtbl->Query(adapter->adapter, info, &linfo);
478 if (FAILED(hr))
479 return hr;
480 adapter->info = *info;
481 free(info);
482 } else if (FAILED(hr)) {
483 return hr;
484 }
485
486 /* generate adapter's name */
487 res = WSAAddressToStringW(&adapter->address.addr,
488 ofi_sizeofaddr(&adapter->address.addr),
489 NULL, NULL, &addrlen);
490 if (res == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT && addrlen) {
491 saddr = (wchar_t*)malloc((addrlen + 1) * sizeof(*saddr));
492 WSAAddressToStringW(&adapter->address.addr,
493 ofi_sizeofaddr(&adapter->address.addr),
494 NULL, saddr, &addrlen);
495 }
496 else {
497 saddr = _wcsdup(L"unknown");
498 }
499
500 asprintf((char**)&adapter->name, "netdir-%S-%S-%p",
501 ofi_nd_filename(adapter->factory->module->path),
502 saddr, adapter);
503 free(saddr);
504 }
505
506 return S_OK;
507 }
508
ofi_nd_init(ofi_nd_adapter_cb_t cb)509 static HRESULT ofi_nd_init(ofi_nd_adapter_cb_t cb)
510 {
511 DWORD proto_len = 0;
512 HRESULT hr = ND_INTERNAL_ERROR;
513 int i, protonum, err;
514 size_t j, prov_count = 0;
515 WSAPROTOCOL_INFOW *proto = 0;
516
517 memset(&ofi_nd_infra, 0, sizeof(ofi_nd_infra));
518
519 int ret = WSCEnumProtocols(NULL, NULL, &proto_len, &err);
520 if (ret != SOCKET_ERROR || err != WSAENOBUFS) {
521 hr = ND_NO_MEMORY;
522 goto fn_exit;
523 }
524
525 proto = (WSAPROTOCOL_INFOW*)(malloc(proto_len));
526 if (!proto) {
527 hr = ND_NO_MEMORY;
528 goto fn_exit;
529 }
530
531 protonum = WSCEnumProtocols(NULL, proto, &proto_len, &err);
532 if (protonum == SOCKET_ERROR) {
533 hr = ND_INTERNAL_ERROR;
534 goto fn_protofail;
535 }
536
537 /* calculating number of valid protocols. this number is used
538 as maximum of existing providers and class factories */
539 for (i = 0; i < protonum; i++) {
540 if (ofi_nd_is_valid_proto(&proto[i]))
541 prov_count++;
542 }
543
544 if (!prov_count) {
545 hr = E_NOINTERFACE;
546 goto fn_protofail;
547 }
548
549 hr = ofi_nd_alloc_infra(prov_count);
550 if (hr != S_OK)
551 goto fn_protofail;
552
553 for (i = 0; i < protonum; i++) {
554 if (ofi_nd_is_valid_proto(&proto[i]))
555 ofi_nd_create_factory(&proto[i]);
556 }
557
558 free(proto);
559
560 /* ok, factories are created, now list all available addresses, try to
561 create adapters & collect adapter's info */
562 hr = ofi_nd_create_adapter();
563 if (FAILED(hr))
564 return hr;
565
566 /* free all interfaces. we don't need it right now */
567 ofi_nd_release_infra();
568
569 /* now call cb function to create info's */
570 for (j = 0; j < ofi_nd_infra.adapters.count; j++)
571 cb(&ofi_nd_infra.adapters.adapter[j].info,
572 ofi_nd_infra.adapters.adapter[j].name);
573
574 return hr;
575 fn_protofail:
576 free(proto);
577 fn_exit:
578 return hr;
579 }
580
581 /* we don't need here exclusive execution because this function
582 * is called from OFI init routine which is single thread */
ofi_nd_startup(ofi_nd_adapter_cb_t cb)583 HRESULT ofi_nd_startup(ofi_nd_adapter_cb_t cb)
584 {
585 WSADATA data;
586 HRESULT hr;
587 int ret;
588
589 assert(cb);
590
591 if (ofi_nd_startup_done)
592 return S_OK;
593
594 ND_LOG_INFO(FI_LOG_CORE, "ofi_nd_startup: starting initialization\n");
595
596 ret = WSAStartup(MAKEWORD(2, 2), &data);
597 if (ret)
598 return HRESULT_FROM_WIN32(ret);
599
600 ND_LOG_DEBUG(FI_LOG_CORE, "ofi_nd_startup: WSAStartup complete\n");
601
602 hr = ofi_nd_init(cb);
603
604 ofi_nd_startup_done = 1;
605
606 return hr;
607 }
608
ofi_nd_shutdown(void)609 HRESULT ofi_nd_shutdown(void)
610 {
611 if (!ofi_nd_startup_done)
612 return S_OK;
613
614 ND_LOG_INFO(FI_LOG_CORE, "ofi_nd_shutdown: shutdown WSA\n");
615
616 ofi_nd_free_infra();
617 ofi_nd_startup_done = 0;
618
619 return HRESULT_FROM_WIN32(WSACleanup());
620 }
621
ofi_nd_lookup_adapter(const char * name,IND2Adapter ** adapter,struct sockaddr ** addr)622 int ofi_nd_lookup_adapter(const char *name, IND2Adapter **adapter, struct sockaddr** addr)
623 {
624 size_t i;
625
626 assert(name);
627 assert(adapter);
628
629 if (!ofi_nd_startup_done)
630 return -FI_EOPBADSTATE;
631
632 for (i = 0; i < ofi_nd_infra.adapters.count; i++) {
633 struct adapter_t *ada = &ofi_nd_infra.adapters.adapter[i];
634 if (ada->name && !strcmp(ada->name, name)) {
635 HRESULT hr;
636 UINT64 adapter_id;
637 IClassFactory* factory = NULL;
638 IND2Provider *provider = NULL;
639
640 /* ok, we found good adapter. try to initialize it */
641 if (ada->adapter) {
642 *adapter = ada->adapter;
643 *addr = &ada->address.addr;
644 ada->adapter->lpVtbl->AddRef(ada->adapter);
645 return FI_SUCCESS;
646 }
647
648 assert(ada->factory);
649 assert(ada->factory->module);
650 assert(ada->factory->module->get_class_object);
651
652 hr = ada->factory->module->get_class_object(
653 &ada->factory->protocol.ProviderId,
654 &IID_IClassFactory,
655 (void**)&factory);
656 if (FAILED(hr))
657 return H2F(hr);
658 assert(factory);
659
660 hr = factory->lpVtbl->CreateInstance(factory, NULL,
661 &IID_IND2Provider,
662 (void**)&provider);
663 factory->lpVtbl->Release(factory);
664 if (FAILED(hr))
665 return H2F(hr);
666 assert(provider);
667
668 hr = provider->lpVtbl->ResolveAddress(provider, &ada->address.addr,
669 ofi_sizeofaddr(&ada->address.addr),
670 &adapter_id);
671 if (FAILED(hr)) {
672 provider->lpVtbl->Release(provider);
673 return H2F(hr);
674 }
675
676 hr = provider->lpVtbl->OpenAdapter(provider, &IID_IND2Adapter, adapter_id,
677 (void**)&ada->adapter);
678 provider->lpVtbl->Release(provider);
679 if (FAILED(hr))
680 return H2F(hr);
681
682 *adapter = ada->adapter;
683 *addr = &ada->address.addr;
684 ada->adapter->lpVtbl->AddRef(ada->adapter);
685
686 return FI_SUCCESS;
687 }
688 }
689
690 return -FI_EINVAL;
691 }
692
693 #endif /* _WIN32 */
694
695