Remove stale HPC Pack 2008 Beta 1 objects
[mirror/winof/.git] / ulp / nd / user / NdProv.cpp
1 /*\r
2  * Copyright (c) 2008 Microsoft 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  * $Id:$\r
30  */\r
31 \r
32 #include <tchar.h>\r
33 #include <ndspi.h>\r
34 #include <iba/ib_at_ioctl.h>\r
35 #include <complib/cl_types.h>\r
36 #include <complib/cl_ioctl.h>\r
37 #pragma warning( push, 3 )\r
38 #include <unknwn.h>\r
39 #include <assert.h>\r
40 #include <ws2tcpip.h>\r
41 #include <winioctl.h>\r
42 #include <limits.h>\r
43 #include <ws2spi.h>\r
44 #pragma warning( pop )\r
45 #include "ndprov.h"\r
46 #include "ndadapter.h"\r
47 \r
48 #if defined(EVENT_TRACING)\r
49 #ifdef offsetof\r
50 #undef offsetof\r
51 #endif\r
52 #include "NdProv.tmh"\r
53 #endif\r
54 \r
55 #include "nddebug.h"\r
56 \r
57 uint32_t g_nd_dbg_level = TRACE_LEVEL_ERROR;\r
58 /* WPP doesn't want here literals! */\r
59 uint32_t g_nd_dbg_flags = 0x80000001; /* ND_DBG_ERROR | ND_DBG_NDI; */\r
60 \r
61 HANDLE ghHeap;\r
62 \r
63 \r
64 namespace NetworkDirect\r
65 {\r
66 \r
67     static LONG gnRef = 0;\r
68 \r
69     CProvider::CProvider() :\r
70         m_nRef( 1 )\r
71     {\r
72         InterlockedIncrement( &gnRef );\r
73     }\r
74 \r
75     CProvider::~CProvider()\r
76     {\r
77         InterlockedDecrement( &gnRef );\r
78     }\r
79 \r
80     HRESULT CProvider::QueryInterface(\r
81         const IID &riid,\r
82         void **ppObject )\r
83     {\r
84         if( IsEqualIID( riid, IID_IUnknown ) )\r
85         {\r
86             *ppObject = this;\r
87             return S_OK;\r
88         }\r
89 \r
90         if( IsEqualIID( riid, IID_INDProvider ) )\r
91         {\r
92             *ppObject = this;\r
93             return S_OK;\r
94         }\r
95 \r
96         return E_NOINTERFACE;\r
97     }\r
98 \r
99     ULONG CProvider::AddRef()\r
100     {\r
101         return InterlockedIncrement( &m_nRef );\r
102     }\r
103 \r
104     ULONG CProvider::Release()\r
105     {\r
106         ULONG ref = InterlockedDecrement( &m_nRef );\r
107         if( ref == 0 )\r
108             delete this;\r
109 \r
110         return ref;\r
111     }\r
112 \r
113     HRESULT CProvider::QueryAddressList(\r
114             __out_bcount_part_opt(*pBufferSize, *pBufferSize) SOCKET_ADDRESS_LIST* pAddressList,\r
115             __inout SIZE_T* pBufferSize )\r
116     {\r
117         ND_ENTER( ND_DBG_NDI );\r
118 \r
119         HANDLE hIbatDev = CreateFileW( IBAT_WIN32_NAME,\r
120             MAXIMUM_ALLOWED, 0, NULL,\r
121             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
122         if( hIbatDev == INVALID_HANDLE_VALUE )\r
123             return ND_NO_MEMORY;\r
124 \r
125         IOCTL_IBAT_IP_ADDRESSES_IN addrIn;\r
126 \r
127         addrIn.Version = IBAT_IOCTL_VERSION;\r
128         addrIn.PortGuid = 0;\r
129 \r
130         DWORD size = sizeof(IOCTL_IBAT_IP_ADDRESSES_OUT);\r
131         IOCTL_IBAT_IP_ADDRESSES_OUT *pAddrOut;\r
132         do\r
133         {\r
134             pAddrOut = (IOCTL_IBAT_IP_ADDRESSES_OUT*)HeapAlloc(\r
135                 GetProcessHeap(),\r
136                 0,\r
137                 size );\r
138             if( !pAddrOut )\r
139             {\r
140                 //AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
141                 //    ("Failed to allocate output buffer.\n") );\r
142                 return ND_NO_MEMORY;\r
143             }\r
144 \r
145             if( !DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_ADDRESSES,\r
146                 &addrIn, sizeof(addrIn), pAddrOut, size, &size, NULL ) )\r
147             {\r
148                 HeapFree( GetProcessHeap(), 0, pAddrOut );\r
149                 //AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
150                 //    ("IOCTL_IBAT_IP_ADDRESSES failed (%x).\n", GetLastError()) );\r
151                 return ND_UNSUCCESSFUL;\r
152             }\r
153 \r
154             if( pAddrOut->Size > size )\r
155             {\r
156                 size = pAddrOut->Size;\r
157                 HeapFree( GetProcessHeap(), 0, pAddrOut );\r
158                 pAddrOut = NULL;\r
159             }\r
160 \r
161         } while( !pAddrOut );\r
162 \r
163         CloseHandle( hIbatDev );\r
164 \r
165         //\r
166         // Note: the required size computed is a few bytes larger than necessary, \r
167         // but that keeps the code clean.\r
168         //\r
169         SIZE_T size_req = sizeof(SOCKET_ADDRESS_LIST);\r
170 \r
171         switch( pAddrOut->AddressCount )\r
172         {\r
173         case 0:\r
174             break;\r
175 \r
176         default:\r
177             size_req += (pAddrOut->AddressCount - 1) *\r
178                 (sizeof(SOCKET_ADDRESS) + sizeof(SOCKADDR));\r
179             /* Fall through. */\r
180             __fallthrough;\r
181 \r
182         case 1:\r
183             /* Add the space for the first address. */\r
184             size_req += sizeof(SOCKADDR);\r
185             break;\r
186         }\r
187 \r
188         if( size_req > *pBufferSize )\r
189         {\r
190             HeapFree( GetProcessHeap(), 0, pAddrOut );\r
191             *pBufferSize = size_req;\r
192             return ND_BUFFER_OVERFLOW;\r
193         }\r
194 \r
195         ZeroMemory( pAddressList, *pBufferSize );\r
196 \r
197         /* We store the array of addresses after the last address pointer:\r
198         *      iAddressCount\r
199         *      Address[0]; <-- points to sockaddr[0]\r
200         *      Address[1]; <-- points to sockaddr[1]\r
201         *      ...\r
202         *      Address[n-1]; <-- points to sockaddr[n-1]\r
203         *      sockaddr[0];\r
204         *      sockaddr[1];\r
205         *      ...\r
206         *      sockaddr[n-1]\r
207         */\r
208         BYTE* pBuf = (BYTE*)(&(pAddressList->Address[pAddrOut->AddressCount]));\r
209         *pBufferSize = size_req;\r
210 \r
211         pAddressList->iAddressCount = 0;\r
212         for( LONG i = 0; i < pAddrOut->AddressCount; i++ )\r
213         {\r
214             pAddressList->Address[pAddressList->iAddressCount].lpSockaddr =\r
215                 (LPSOCKADDR)pBuf;\r
216 \r
217             switch( pAddrOut->Address[i].IpVersion )\r
218             {\r
219             case 4:\r
220                 {\r
221                     struct sockaddr_in* pAddr4 = ((struct sockaddr_in*)pBuf);\r
222                     pAddr4->sin_family = AF_INET;\r
223                     pAddr4->sin_addr.s_addr =\r
224                         *((u_long*)&pAddrOut->Address[i].Address[12]);\r
225                     pAddressList->Address[pAddressList->iAddressCount].iSockaddrLength =\r
226                         sizeof(struct sockaddr_in);\r
227                 }\r
228                 break;\r
229 \r
230             case 6:\r
231                 {\r
232                     struct sockaddr_in6* pAddr6 = ((struct sockaddr_in6*)pBuf);\r
233                     pAddr6->sin6_family = AF_INET6;\r
234                     CopyMemory(\r
235                         &pAddr6->sin6_addr,\r
236                         pAddrOut->Address[i].Address,\r
237                         sizeof(pAddr6->sin6_addr) );\r
238                     pAddressList->Address[pAddressList->iAddressCount].iSockaddrLength =\r
239                         sizeof(struct sockaddr_in6);\r
240                 }\r
241                 break;\r
242 \r
243             default:\r
244                 continue;\r
245             }\r
246 \r
247             pBuf += pAddressList->Address[pAddressList->iAddressCount++].iSockaddrLength;\r
248         }\r
249 \r
250         HeapFree( GetProcessHeap(), 0, pAddrOut );\r
251 \r
252         return S_OK;\r
253     }\r
254 \r
255     HRESULT CProvider::OpenAdapter(\r
256             __in_bcount(AddressLength) const struct sockaddr* pAddress,\r
257             __in SIZE_T AddressLength,\r
258             __deref_out INDAdapter** ppAdapter )\r
259     {\r
260         ND_ENTER( ND_DBG_NDI );\r
261 \r
262         if( AddressLength < sizeof(struct sockaddr) )\r
263             return ND_INVALID_ADDRESS;\r
264 \r
265         IOCTL_IBAT_IP_TO_PORT_IN in;\r
266         in.Version = IBAT_IOCTL_VERSION;\r
267 \r
268         switch( pAddress->sa_family )\r
269         {\r
270         case AF_INET:\r
271             if( AddressLength < sizeof(struct sockaddr_in) )\r
272                 return ND_INVALID_ADDRESS;\r
273             in.Address.IpVersion = 4;\r
274             RtlCopyMemory(\r
275                 &in.Address.Address[12],\r
276                 &((struct sockaddr_in*)pAddress)->sin_addr,\r
277                 sizeof( ((struct sockaddr_in*)pAddress)->sin_addr ) );\r
278             break;\r
279 \r
280         case AF_INET6:\r
281             if( AddressLength < sizeof(struct sockaddr_in6) )\r
282                 return ND_INVALID_ADDRESS;\r
283             in.Address.IpVersion = 6;\r
284             RtlCopyMemory(\r
285                 in.Address.Address,\r
286                 &((struct sockaddr_in6*)pAddress)->sin6_addr,\r
287                 sizeof(in.Address.Address) );\r
288             break;\r
289 \r
290         default:\r
291             return ND_INVALID_ADDRESS;\r
292         }\r
293 \r
294         HANDLE hIbatDev = CreateFileW( IBAT_WIN32_NAME,\r
295             MAXIMUM_ALLOWED, 0, NULL,\r
296             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
297         if( hIbatDev == INVALID_HANDLE_VALUE )\r
298             return ND_NO_MEMORY;\r
299 \r
300         IBAT_PORT_RECORD out;\r
301         DWORD size;\r
302         BOOL fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_TO_PORT,\r
303             &in, sizeof(in), &out, sizeof(out), &size, NULL );\r
304         \r
305         CloseHandle( hIbatDev );\r
306         if( !fSuccess || size == 0 )\r
307             return ND_INVALID_ADDRESS;\r
308 \r
309         return CAdapter::Create( this, pAddress, &out, ppAdapter );\r
310     }\r
311 \r
312     CClassFactory::CClassFactory(void) :\r
313         m_nRef( 1 )\r
314     {\r
315         InterlockedIncrement( &gnRef );\r
316     }\r
317 \r
318     CClassFactory::~CClassFactory(void)\r
319     {\r
320         InterlockedDecrement( &gnRef );\r
321     }\r
322 \r
323     HRESULT CClassFactory::QueryInterface(\r
324         REFIID riid,\r
325         void** ppObject )\r
326     {\r
327         if( IsEqualIID( riid, IID_IUnknown ) )\r
328         {\r
329             *ppObject = this;\r
330             return S_OK;\r
331         }\r
332         if( IsEqualIID( riid, IID_IClassFactory ) )\r
333         {\r
334             *ppObject = this;\r
335             return S_OK;\r
336         }\r
337 \r
338         return E_NOINTERFACE;\r
339     }\r
340 \r
341     ULONG CClassFactory::AddRef()\r
342     {\r
343         return InterlockedIncrement( &m_nRef );\r
344     }\r
345 \r
346     ULONG CClassFactory::Release()\r
347     {\r
348         ULONG ref = InterlockedDecrement( &m_nRef );\r
349         if( ref == 0 )\r
350             delete this;\r
351 \r
352         return ref;\r
353     }\r
354 \r
355     HRESULT CClassFactory::CreateInstance(\r
356         IUnknown* pUnkOuter,\r
357         REFIID riid,\r
358         void** ppObject )\r
359     {\r
360         if( pUnkOuter != NULL )\r
361             return CLASS_E_NOAGGREGATION;\r
362 \r
363         if( IsEqualIID( riid, IID_INDProvider ) )\r
364         {\r
365             *ppObject = new CProvider();\r
366             if( !*ppObject )\r
367                 return E_OUTOFMEMORY;\r
368 \r
369             return S_OK;\r
370         }\r
371 \r
372         return E_NOINTERFACE;\r
373     }\r
374 \r
375     HRESULT CClassFactory::LockServer( BOOL fLock )\r
376     { \r
377         UNREFERENCED_PARAMETER( fLock );\r
378         return S_OK;\r
379     }\r
380 \r
381 } // namespace\r
382 \r
383 void* __cdecl operator new(\r
384     size_t count\r
385     )\r
386 {\r
387     return HeapAlloc( ghHeap, 0, count );\r
388 }\r
389 \r
390 \r
391 void __cdecl operator delete(\r
392     void* object\r
393     )\r
394 {\r
395     HeapFree( ghHeap, 0, object );\r
396 }\r
397 \r
398 extern "C" {\r
399 STDAPI DllGetClassObject(\r
400     REFCLSID rclsid,\r
401     REFIID riid,\r
402     LPVOID * ppv\r
403     )\r
404 {\r
405     ND_ENTER( ND_DBG_NDI );\r
406 \r
407     UNREFERENCED_PARAMETER( rclsid );\r
408 \r
409     if( IsEqualIID( riid, IID_IClassFactory ) )\r
410     {\r
411         NetworkDirect::CClassFactory* pFactory = new NetworkDirect::CClassFactory();\r
412         if( pFactory == NULL )\r
413             return E_OUTOFMEMORY;\r
414 \r
415         *ppv = pFactory;\r
416         return S_OK;\r
417     }\r
418 \r
419     return E_NOINTERFACE;\r
420 }\r
421 \r
422 STDAPI DllCanUnloadNow(void)\r
423 {\r
424     ND_ENTER( ND_DBG_NDI );\r
425 \r
426     if( InterlockedCompareExchange( &NetworkDirect::gnRef, 0, 0 ) != 0 )\r
427         return S_FALSE;\r
428 \r
429     return S_OK;\r
430 }\r
431 \r
432 int\r
433 WSPAPI\r
434 WSPStartup(\r
435     IN WORD wVersionRequested,\r
436     OUT LPWSPDATA lpWSPData,\r
437     IN LPWSAPROTOCOL_INFOW lpProtocolInfo,\r
438     IN WSPUPCALLTABLE UpcallTable,\r
439     OUT LPWSPPROC_TABLE lpProcTable\r
440     )\r
441 {\r
442     UNREFERENCED_PARAMETER( wVersionRequested );\r
443     UNREFERENCED_PARAMETER( lpWSPData );\r
444     UNREFERENCED_PARAMETER( lpProtocolInfo );\r
445     UNREFERENCED_PARAMETER( UpcallTable );\r
446     UNREFERENCED_PARAMETER( lpProcTable );\r
447     return WSASYSNOTREADY;\r
448 }\r
449 \r
450 static BOOL\r
451 _DllMain(\r
452     IN                HINSTANCE                    hinstDll,\r
453     IN                DWORD                        dwReason,\r
454     IN                LPVOID                        lpvReserved )\r
455 {\r
456 \r
457     ND_ENTER( ND_DBG_NDI );\r
458 \r
459     UNUSED_PARAM( hinstDll );\r
460     UNUSED_PARAM( lpvReserved );\r
461 \r
462     switch( dwReason )\r
463     {\r
464     case DLL_PROCESS_ATTACH:\r
465 \r
466 \r
467 #if defined(EVENT_TRACING)\r
468 #if DBG\r
469         WPP_INIT_TRACING(L"ibndprov.dll");\r
470 #else\r
471         WPP_INIT_TRACING(L"ibndprov.dll");\r
472 #endif\r
473 #elif DBG \r
474         TCHAR    env_var[16];\r
475         DWORD    i;\r
476 \r
477         i = GetEnvironmentVariable( "IBNDPROV_DBG_LEVEL", env_var, sizeof(env_var) );\r
478         if( i && i <= 16 )\r
479         {\r
480             g_nd_dbg_level = _tcstoul( env_var, NULL, 16 );\r
481         }\r
482 \r
483         i = GetEnvironmentVariable( "IBNDPROV_DBG_FLAGS", env_var, sizeof(env_var) );\r
484         if( i && i <= 16 )\r
485         {\r
486             g_nd_dbg_flags = _tcstoul( env_var, NULL, 16 );\r
487         }\r
488 \r
489         if( g_nd_dbg_flags & ND_DBG_ERR )\r
490             g_nd_dbg_flags |= CL_DBG_ERROR;\r
491 \r
492         ND_PRINT( TRACE_LEVEL_ERROR, ND_DBG_ERR ,\r
493             ("(pcs %#x) IbNdProv: Debug print: level:%d, flags 0x%x\n",\r
494             GetCurrentProcessId(), g_nd_dbg_level ,g_nd_dbg_flags) );\r
495 #endif\r
496 \r
497         ghHeap = HeapCreate( 0, 0, 0 );\r
498         if( ghHeap == NULL )\r
499         {\r
500             ND_PRINT_EXIT(\r
501                 TRACE_LEVEL_ERROR, ND_DBG_NDI, ("Failed to allocate private heap.\n") );\r
502 #if defined(EVENT_TRACING)\r
503             WPP_CLEANUP();\r
504 #endif\r
505             return FALSE;\r
506         }\r
507 \r
508         ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_PROCESS_ATTACH\n") );\r
509         break;\r
510 \r
511     case DLL_PROCESS_DETACH:\r
512         HeapDestroy( ghHeap );\r
513         ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
514             ("DllMain: DLL_PROCESS_DETACH, ref count %d\n", NetworkDirect::gnRef) );\r
515 \r
516 #if defined(EVENT_TRACING)\r
517         WPP_CLEANUP();\r
518 #endif\r
519         break;\r
520     }\r
521 \r
522     ND_EXIT( ND_DBG_NDI );\r
523 \r
524     return TRUE;\r
525 }\r
526 \r
527 \r
528 extern BOOL APIENTRY\r
529 _DllMainCRTStartupForGS(\r
530     IN                HINSTANCE                    h_module,\r
531     IN                DWORD                        ul_reason_for_call, \r
532     IN                LPVOID                        lp_reserved );\r
533 \r
534 \r
535 BOOL APIENTRY\r
536 DllMain(\r
537     IN                HINSTANCE                    h_module,\r
538     IN                DWORD                        ul_reason_for_call, \r
539     IN                LPVOID                        lp_reserved )\r
540 {\r
541     switch( ul_reason_for_call )\r
542     {\r
543     case DLL_PROCESS_ATTACH:\r
544         if( !_DllMainCRTStartupForGS(\r
545             h_module, ul_reason_for_call, lp_reserved ) )\r
546         {\r
547             return FALSE;\r
548         }\r
549 \r
550         return _DllMain( h_module, ul_reason_for_call, lp_reserved );\r
551 \r
552     case DLL_THREAD_ATTACH:\r
553         ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_THREAD_ATTACH\n") );\r
554         break;\r
555 \r
556     case DLL_THREAD_DETACH:\r
557         ND_PRINT(TRACE_LEVEL_INFORMATION, ND_DBG_NDI, ("DllMain: DLL_THREAD_DETACH\n") );\r
558         break;\r
559 \r
560     case DLL_PROCESS_DETACH:\r
561         _DllMain( h_module, ul_reason_for_call, lp_reserved );\r
562 \r
563         return _DllMainCRTStartupForGS(\r
564             h_module, ul_reason_for_call, lp_reserved );\r
565     }\r
566     return TRUE;\r
567 }\r
568 \r
569 }   // extern "C"\r
570 \r