[WSD] Add perfmon counter object implementation. WSD installation now
[mirror/winof/.git] / tools / wsdinstall / user / installsp.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  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 /*\r
33  *      Module Name: installsp.c\r
34  *      Description: This module installs/removes a winsock service provider for infiniband. \r
35  *      execute:\r
36  *      To install the service provider\r
37  *              installsp -i        \r
38  *      To remove the service provider\r
39  *              installsp -r\r
40  */\r
41 \r
42 #include <winsock2.h>\r
43 #include <ws2spi.h>\r
44 #include <stdio.h>\r
45 \r
46 /* Initialize the LSP's provider path for Infiband Service Provider dll */\r
47 static const WCHAR provider_path[] = L"%SYSTEMROOT%\\system32\\ibwsd.dll";\r
48 static const WCHAR provider_name[] = L"OpenIB Winsock Direct for InfiniBand";\r
49 static const char winsock_key_path[] =\r
50         "System\\CurrentControlSet\\Services\\Winsock\\Parameters\\TCP on SAN";\r
51 static const char openib_key_name[] = "OpenIB Alliance";\r
52 \r
53 /* Unique provider GUID generated with "uuidgen -s" */\r
54 static GUID provider_guid = {\r
55         /* c943654d-2c84-4db7-af3e-fdf1c5322458 */\r
56         0xc943654d, 0x2c84, 0x4db7,\r
57         { 0xaf, 0x3e, 0xfd, 0xf1, 0xc5, 0x32, 0x24,     0x58 }\r
58 };\r
59 \r
60 #ifdef _WIN64\r
61 #define WSCInstallProvider      WSCInstallProvider64_32\r
62 #endif  /* _WIN64 */\r
63 \r
64 #ifdef PERFMON_ENABLED\r
65 #include <Loadperf.h>\r
66 #include "wsd/ibsp_regpath.h"\r
67 \r
68 \r
69 typedef struct _pm_symbol_def\r
70 {\r
71         DWORD   name_def;\r
72         CHAR    name_str[40];\r
73         CHAR    name_desc[40];\r
74         CHAR    help_desc[256];\r
75 \r
76 } pm_symbol_def_t;\r
77 \r
78 static pm_symbol_def_t  _pm_symbols[]=\r
79 {\r
80         { IBSP_PM_OBJ,\r
81         "IBSP_PM_OBJ",\r
82         "IB Winsock Direct",\r
83         "InfiniBand Windows Sockets Direct Provider."\r
84         },\r
85         { IBSP_PM_COUNTER(BYTES_SEND),\r
86         "IBSP_PM_BYTES_TX_SEC",\r
87         "Send bytes/sec",\r
88         "Send bytes/second, excluding RDMA Write."\r
89         },\r
90         { IBSP_PM_COUNTER(BYTES_RECV),\r
91         "IBSP_PM_BYTES_RX_SEC",\r
92         "Recv bytes/sec",\r
93         "Receive bytes/second, excluding RDMA Read."\r
94         },\r
95         { IBSP_PM_COUNTER(BYTES_WRITE),\r
96         "IBSP_PM_RDMA_WR_SEC",\r
97         "RDMA Write bytes/sec",\r
98         "RDMA Write bytes/second."\r
99         },\r
100         { IBSP_PM_COUNTER(BYTES_READ),\r
101         "IBSP_PM_RDMA_RD_SEC",\r
102         "RDMA Read bytes/sec",\r
103         "RDMA Read bytes/second."\r
104         },\r
105         { IBSP_PM_COUNTER(BYTES_TOTAL),\r
106         "IBSP_PM_BYTES_SEC",\r
107         "Total bytes/sec",\r
108         "Total bytes transmitted per second, including send, "\r
109         "receive, RDMA Write, and RDMA Read."\r
110         },\r
111         { IBSP_PM_COUNTER(COMP_SEND),\r
112         "IBSP_PM_SEND_COMPLETIONS_SEC",\r
113         "Send Completions/sec",\r
114         "Send and RDMA Write Completions/sec."\r
115         },\r
116         { IBSP_PM_COUNTER(COMP_RECV),\r
117         "IBSP_PM_RECV_COMPLETIONS_SEC",\r
118         "Recv Completions/sec",\r
119         "Recv and RDMA Read Completions/sec."\r
120         },\r
121         { IBSP_PM_COUNTER(COMP_TOTAL),\r
122         "IBSP_PM_COMPLETIONS_SEC",\r
123         "Total Completions/sec",\r
124         "Total Completions processed per second."\r
125         },\r
126         { IBSP_PM_COUNTER(INTR_TOTAL),\r
127         "IBSP_PM_COMPLETIONS_INTR",\r
128         "Total Interrupts/sec",\r
129         "Completion Queue events per second."\r
130         }\r
131 };\r
132 \r
133 #define IBSP_PM_NUM_SYMBOLS  (sizeof(_pm_symbols)/sizeof(pm_symbol_def_t))\r
134 #define IBSP_PM_LANGUAGE "009" /* good for English */\r
135 \r
136 \r
137 static DWORD\r
138 _IBSPPerfmonIniFilesGenerate( void )\r
139 {\r
140         FILE    *f_handle;\r
141         DWORD   num;\r
142 \r
143         /* create ".h" file first */\r
144         f_handle = fopen( IBSP_PM_SYM_H_FILE, "w+" );\r
145 \r
146         if( !f_handle )\r
147         {\r
148                 fprintf(\r
149                         stderr, "Create Header file %s  failed\n", IBSP_PM_SYM_H_FILE );\r
150                 return ERROR_FILE_INVALID;\r
151         }\r
152 \r
153         fprintf(\r
154                 f_handle, "/* %s Generated by program */ \r\n", IBSP_PM_SYM_H_FILE );\r
155                 \r
156         \r
157         for( num = 0; num < IBSP_PM_NUM_SYMBOLS; num++ )\r
158         {\r
159                 fprintf( f_handle, "#define\t%s\t%d\r\n",\r
160                         _pm_symbols[num].name_str, _pm_symbols[num].name_def );\r
161         }\r
162 \r
163         fflush( f_handle );\r
164         fclose( f_handle );\r
165 \r
166         /* create 'ini' file next */\r
167         f_handle = fopen( IBSP_PM_INI_FILE, "w+" );\r
168 \r
169         if( !f_handle )\r
170         {\r
171                 fprintf( stderr, "Create INI file %s  failed\n", IBSP_PM_INI_FILE );\r
172                 return ERROR_FILE_INVALID;\r
173         }\r
174         \r
175         fprintf( f_handle, "[info]\r\ndrivername=" IBSP_PM_SUBKEY_NAME\r
176                 "\r\nsymbolfile=" IBSP_PM_SYM_H_FILE "\r\n\r\n" );\r
177         fprintf( f_handle,"[languages]\r\n" IBSP_PM_LANGUAGE\r
178                 "=language" IBSP_PM_LANGUAGE "\r\n\r\n" );\r
179 \r
180         fprintf( f_handle, \r
181                 "[objects]\r\n%s_" IBSP_PM_LANGUAGE "_NAME=%s\r\n\r\n[text]\r\n",\r
182                 _pm_symbols[0].name_str, _pm_symbols[0].name_desc );\r
183         \r
184         for( num = 0; num < IBSP_PM_NUM_SYMBOLS; num++ )\r
185         {\r
186                 fprintf( f_handle,"%s_" IBSP_PM_LANGUAGE "_NAME=%s\r\n",\r
187                         _pm_symbols[num].name_str, _pm_symbols[num].name_desc );\r
188                 fprintf( f_handle,"%s_" IBSP_PM_LANGUAGE "_HELP=%s\r\n",\r
189                         _pm_symbols[num].name_str, _pm_symbols[num].help_desc );\r
190         }\r
191 \r
192         fflush( f_handle );\r
193         fclose( f_handle );\r
194 \r
195         return ERROR_SUCCESS;\r
196 }\r
197 \r
198 \r
199 static void\r
200 _IBSPPerfmonIniFilesRemove( void )\r
201 {\r
202         if( !DeleteFile( IBSP_PM_INI_FILE ) )\r
203         {\r
204                 fprintf( stderr, "Delete file %s failed status %d\n",\r
205                         IBSP_PM_INI_FILE, GetLastError() );\r
206         }\r
207         if( !DeleteFile( IBSP_PM_SYM_H_FILE ) )\r
208         {\r
209                 fprintf( stderr,"Delete file %s failed status %d\n",\r
210                         IBSP_PM_SYM_H_FILE, GetLastError() );\r
211         }\r
212 }\r
213 \r
214 \r
215 /* Try to create IB WSD Performance Register Keys */\r
216 static LONG\r
217 _IBSPPerfmonRegisterKeys( void )\r
218 {\r
219         LONG    reg_status;\r
220         HKEY    pm_hkey;\r
221         DWORD   typesSupp = 7;\r
222 \r
223         reg_status = RegCreateKeyEx( HKEY_LOCAL_MACHINE,\r
224                 IBSP_PM_REGISTRY_PATH IBSP_PM_SUBKEY_PERF, 0, NULL,\r
225                 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &pm_hkey, NULL );\r
226 \r
227         if( reg_status != ERROR_SUCCESS )\r
228         {\r
229                 fprintf( stderr,\r
230                         "_IBSPPerfmonRegisterKeys Create Key %s failed with %d\n",\r
231                         IBSP_PM_REGISTRY_PATH IBSP_PM_SUBKEY_PERF, reg_status );\r
232                 return reg_status;\r
233         }\r
234 \r
235         /* create/assign values to the key */\r
236         RegSetValueExW( pm_hkey, L"Library", 0, REG_EXPAND_SZ,\r
237                 (LPBYTE)provider_path, sizeof(provider_path) );\r
238 \r
239         RegSetValueEx( pm_hkey, TEXT("Open"), 0, REG_SZ,\r
240                 (LPBYTE)TEXT("IBSPPmOpen"), sizeof(TEXT("IBSPPmOpen")) );\r
241 \r
242         RegSetValueEx( pm_hkey, TEXT("Collect"), 0, REG_SZ,\r
243                 (LPBYTE)TEXT("IBSPPmCollectData"), sizeof(TEXT("IBSPPmCollectData")) );\r
244 \r
245         RegSetValueEx( pm_hkey, TEXT("Close"), 0, REG_SZ,\r
246                 (LPBYTE)TEXT("IBSPPmClose"), sizeof(TEXT("IBSPPmClose")) );\r
247 \r
248         RegFlushKey( pm_hkey );\r
249         RegCloseKey( pm_hkey );\r
250 \r
251         reg_status = RegCreateKeyEx( HKEY_LOCAL_MACHINE,\r
252                 IBSP_PM_EVENTLOG_PATH, 0, NULL,\r
253                 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &pm_hkey, NULL );\r
254 \r
255         if( reg_status != ERROR_SUCCESS )\r
256         {\r
257                 fprintf(stderr, "Create EventLog Key failed with %d\n", reg_status );\r
258                 return reg_status;\r
259         }\r
260 \r
261         /* create/assign values to the key */\r
262         RegSetValueExW( pm_hkey, L"EventMessageFile", 0, REG_EXPAND_SZ,\\r
263                 (LPBYTE)provider_path, sizeof(provider_path) );\r
264 \r
265         RegSetValueEx( pm_hkey, TEXT("TypesSupported"), 0, REG_DWORD,\r
266                 (LPBYTE)&typesSupp, sizeof(typesSupp) );\r
267 \r
268         RegFlushKey( pm_hkey );\r
269         RegCloseKey( pm_hkey );\r
270 \r
271         return reg_status;\r
272 }\r
273 \r
274 \r
275 /* Try to destroy IB WSD Performance Register Keys */\r
276 static LONG\r
277 _IBSPPerfmonDeregisterKeys( void )\r
278 {\r
279         LONG    reg_status;\r
280 \r
281         reg_status = RegDeleteKeyEx( HKEY_LOCAL_MACHINE,\r
282                 IBSP_PM_REGISTRY_PATH IBSP_PM_SUBKEY_PERF,\r
283                 (KEY_WOW64_32KEY | KEY_WOW64_64KEY), 0 );\r
284 \r
285         if( reg_status != ERROR_SUCCESS )\r
286         {\r
287                 fprintf( stderr,\r
288                         "_IBSPPerfmonRegisterKeys Remove SubKey failed with %d\n",\r
289                         GetLastError() );\r
290         }\r
291 \r
292         reg_status = RegDeleteKeyEx( HKEY_LOCAL_MACHINE,\r
293                 IBSP_PM_REGISTRY_PATH, (KEY_WOW64_32KEY | KEY_WOW64_64KEY), 0 );\r
294 \r
295         if( reg_status != ERROR_SUCCESS )\r
296         {\r
297                 fprintf( stderr,\r
298                         "_IBSPPerfmonRegisterKeys Remove SubKey failed with %d\n",\r
299                         GetLastError() );\r
300         }\r
301 \r
302         reg_status = RegDeleteKeyEx( HKEY_LOCAL_MACHINE,\r
303                 IBSP_PM_EVENTLOG_PATH, (KEY_WOW64_32KEY | KEY_WOW64_64KEY), 0 );\r
304 \r
305         if( reg_status != ERROR_SUCCESS )\r
306         {\r
307                 fprintf( stderr,\r
308                         "_IBSPPerfmonRegisterKeys Remove SubKey failed with %d\n",\r
309                         GetLastError() );\r
310         }\r
311 \r
312         return reg_status;\r
313 }\r
314 \r
315 \r
316 /*\r
317  * functions will try to register performance counters\r
318  * definitions with PerfMon application.\r
319  * API externally called by lodctr.exe/unlodctr.exe utilities.\r
320  */\r
321 static DWORD\r
322 _IBSPPerfmonRegisterCounters( void )\r
323 {\r
324         DWORD status;\r
325         /*\r
326          * format commandline string, as per SDK :\r
327          *      Pointer to a null-terminated string that consists of one or more \r
328          *      arbitrary letters, a space, and then the name of the initialization\r
329          *      file.\r
330          */\r
331         status = LoadPerfCounterTextStrings(\r
332                 TEXT("unused ") TEXT(IBSP_PM_INI_FILE), TRUE );\r
333         if( status != ERROR_SUCCESS )\r
334         {\r
335                 status = GetLastError();\r
336                 fprintf( stderr,\r
337                         "IBSPPerfmonRegisterCounters install failed status %d\n", status );\r
338         }\r
339 \r
340         return status;\r
341 }\r
342 \r
343 \r
344 /*\r
345  * functions will try to unregister performance counters\r
346  * definitions with PerfMon application.\r
347  * API externally called by lodctr.exe/unlodctr.exe utilities.\r
348  */\r
349 static DWORD\r
350 _IBSPPerfmonDeregisterCounters( void )\r
351 {\r
352         DWORD status;\r
353 \r
354         /*\r
355          * format commandline string, as per SDK :\r
356          *      Pointer to a null-terminated string that consists of one or more \r
357          *      arbitrary letters, a space, and then the name of the initialization\r
358          *      file.\r
359          */\r
360         status = UnloadPerfCounterTextStrings(\r
361                 TEXT("unused ") TEXT(IBSP_PM_SUBKEY_NAME), TRUE );\r
362         if( status != ERROR_SUCCESS )\r
363         {\r
364                 fprintf( stderr,\r
365                         "IBSPPerfmonDeregisterCounters remove failed status %d\n",\r
366                         status );\r
367         }\r
368         return status;\r
369 }\r
370 \r
371 #endif /* PERFMON_ENABLED */\r
372 \r
373 \r
374 /*\r
375  * Function: usage\r
376  *   Description: Prints usage information.\r
377  */\r
378 static void\r
379 usage (char *progname)\r
380 {\r
381         printf ("usage: %s [-i/-r [-p]]\n", progname);\r
382         printf ("    -i   Install the service provider\n"\r
383                         "    -r   Remove the OpenIB service provider\n"\r
384                         "    -r <name>   Remove the specified service provider\n"\r
385                         "    -l   List service providers\n");\r
386 }\r
387 \r
388 \r
389 /* Function: print_providers\r
390  *   Description: \r
391  *     This function prints out each entry in the Winsock catalog.\r
392 */\r
393 static void print_providers(void)\r
394 {\r
395         WSAPROTOCOL_INFOW *protocol_info;\r
396         unsigned int protocol_count;\r
397         unsigned int i;\r
398         DWORD protocol_size;\r
399         INT errno;\r
400         int rc;\r
401 \r
402         /* Find the size of the buffer */\r
403         protocol_size = 0;\r
404         rc = WSCEnumProtocols (NULL, NULL, &protocol_size, &errno);\r
405         if (rc == SOCKET_ERROR && errno != WSAENOBUFS) {\r
406                 printf("WSCEnumProtocols() returned error (%d)\n", errno);\r
407                 return;\r
408         }\r
409 \r
410         /* Allocate the buffer */\r
411         protocol_info = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, protocol_size);\r
412         if (protocol_info == NULL) {\r
413                 printf("HeapAlloc() failed\n");\r
414                 return;\r
415         }\r
416 \r
417         /* Enumerate the catalog for real */\r
418         rc = WSCEnumProtocols (NULL, protocol_info, &protocol_size, &errno);\r
419         if (rc == SOCKET_ERROR) {\r
420                 printf("WSCEnumProtocols returned error for real enumeration (%d)\n",\r
421                          errno);\r
422                 HeapFree (GetProcessHeap (), 0, protocol_info);\r
423                 return;\r
424         }\r
425 \r
426         protocol_count = rc;\r
427 \r
428         for (i = 0; i < protocol_count; i++) {\r
429                 printf ("%010d - %S\n", protocol_info[i].dwCatalogEntryId,\r
430                                 protocol_info[i].szProtocol);\r
431         }\r
432 \r
433         HeapFree (GetProcessHeap (), 0, protocol_info);\r
434 \r
435         return;\r
436 }\r
437 \r
438 /*\r
439  * Function: install_provider\r
440  *   Description: installs the service provider\r
441  *\r
442  * Note: most of the information setup here comes from "MSDN Home >\r
443  * MSDN Library > Windows Development > Network Devices and\r
444  * Protocols > Design Guide > System Area Networks > Windows Sockets\r
445  * Direct > Windows Sockets Direct Component Operation > Installing\r
446  * Windows Sockets Direct Components".\r
447  * The direct link is http://msdn.microsoft.com/library/default.asp?url=/library/en-us/network/hh/network/wsdp_2xrb.asp\r
448  */\r
449 static void install_provider(void)\r
450 {\r
451         int rc;\r
452         INT errno;\r
453         LONG reg_error;\r
454         WSAPROTOCOL_INFOW provider;\r
455         HKEY hkey;\r
456 \r
457         /* Now setup the key. */\r
458         reg_error = RegCreateKeyExA( HKEY_LOCAL_MACHINE, winsock_key_path,\r
459                 0, NULL, REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL,\r
460                 &hkey, NULL );\r
461         if( reg_error == ERROR_SUCCESS )\r
462         {\r
463                 reg_error = RegSetValueExA( hkey, openib_key_name, 0, REG_BINARY,\r
464                         (PBYTE)&provider_guid, sizeof(GUID) );\r
465                 if( reg_error == ERROR_SUCCESS )\r
466                 {\r
467                         /* Force the system to write the new key now. */\r
468                         RegFlushKey(hkey);\r
469                 }\r
470                 else\r
471                 {\r
472                         fprintf(stderr, "RegSetValueEx failed with %d\n", GetLastError());\r
473                 }\r
474 \r
475                 RegCloseKey(hkey);\r
476         }\r
477         else\r
478         {\r
479                 fprintf(stderr, "Could not get a handle on Winsock registry (%d)\n", GetLastError());\r
480         }\r
481 \r
482         /* Setup the values in PROTOCOL_INFO */\r
483         provider.dwServiceFlags1 = \r
484                 XP1_GUARANTEED_DELIVERY | \r
485                 XP1_GUARANTEED_ORDER | \r
486                 XP1_MESSAGE_ORIENTED |\r
487                 XP1_GRACEFUL_CLOSE;\r
488         provider.dwServiceFlags2 = 0;   /* Reserved */\r
489         provider.dwServiceFlags3 = 0;   /* Reserved */\r
490         provider.dwServiceFlags4 = 0;   /* Reserved */\r
491         provider.dwProviderFlags = PFL_HIDDEN;\r
492         provider.ProviderId = provider_guid;    /* Service Provider ID provided by vendor. Need to be changed later */\r
493         provider.dwCatalogEntryId = 0;\r
494         provider.ProtocolChain.ChainLen = 1;    /* Base Protocol Service Provider */\r
495         provider.iVersion = 2;  /* don't know what it is */\r
496         provider.iAddressFamily = AF_INET;\r
497         provider.iMaxSockAddr = 16;\r
498         provider.iMinSockAddr = 16;\r
499         provider.iSocketType = SOCK_STREAM;\r
500         provider.iProtocol = IPPROTO_TCP;\r
501         provider.iProtocolMaxOffset = 0;\r
502         provider.iNetworkByteOrder = BIGENDIAN;\r
503         provider.iSecurityScheme = SECURITY_PROTOCOL_NONE;\r
504         provider.dwMessageSize = 0xFFFFFFFF; /* IB supports 32-bit lengths for data transfers on RC */\r
505         provider.dwProviderReserved = 0;\r
506         wcscpy( provider.szProtocol, provider_name );\r
507 \r
508         rc = WSCInstallProvider(\r
509                 &provider_guid, provider_path, &provider, 1, &errno );\r
510         if( rc == SOCKET_ERROR )\r
511         {\r
512                 if( errno == WSANO_RECOVERY )\r
513                         printf("The provider is already installed\n");\r
514                 else\r
515                         printf("install_provider: WSCInstallProvider failed: %d\n", errno);\r
516         }\r
517 }\r
518 \r
519 /*\r
520  * Function: remove_provider\r
521  *   Description: removes our provider.\r
522  */\r
523 static void remove_provider( const char* const provider_name )\r
524 {\r
525         int rc;\r
526         int errno;\r
527         LONG reg_error;\r
528         HKEY hkey;\r
529 \r
530         /* Remove our key */\r
531         reg_error = RegOpenKeyExA(HKEY_LOCAL_MACHINE,\r
532                                                          winsock_key_path,\r
533                                                          0,\r
534                                                          (KEY_WRITE | KEY_READ),\r
535                                                          &hkey);\r
536         if (reg_error == ERROR_SUCCESS) {\r
537 \r
538                 reg_error = RegDeleteValueA(hkey, provider_name);\r
539                 if (reg_error == ERROR_SUCCESS) {\r
540                         /* Force the system to remove the key now. */\r
541                         RegFlushKey(hkey);\r
542                 } else {\r
543                         fprintf(stderr, "RegDeleteValue failed with %d\n", GetLastError());\r
544                 }\r
545 \r
546                 RegCloseKey(hkey);\r
547         }\r
548 \r
549         /* Remove from the catalog */\r
550         rc = WSCDeinstallProvider(&provider_guid, &errno);\r
551         if (rc == SOCKET_ERROR) {\r
552                 printf ("WSCDeinstallProvider failed: %d\n", errno);\r
553         }\r
554 \r
555 #ifdef _WIN64\r
556         /* Remove from the 32-bit catalog too! */\r
557         rc = WSCDeinstallProvider32(&provider_guid, &errno);\r
558         if (rc == SOCKET_ERROR) {\r
559                 printf ("WSCDeinstallProvider32 failed: %d\n", errno);\r
560         }\r
561 #endif  /* _WIN64 */\r
562 }\r
563 \r
564 /* Function: main\r
565  *\r
566  *  Description:\r
567  *    Parse the command line arguments and call either the install or remove\r
568  *    routine.\r
569  */\r
570 int __cdecl main (int argc, char *argv[])\r
571 {\r
572         WSADATA wsd;\r
573 \r
574         /* Load Winsock */\r
575         if (WSAStartup (MAKEWORD (2, 2), &wsd) != 0) {\r
576                 printf ("InstallSP: Unable to load Winsock: %d\n", GetLastError ());\r
577                 return -1;\r
578         }\r
579 \r
580         /* Confirm that the WinSock DLL supports 2.2. Note that if the\r
581          * DLL supports versions greater than 2.2 in addition to 2.2, it\r
582          * will still return 2.2 in wVersion since that is the version we\r
583          * requested. */\r
584         if (LOBYTE (wsd.wVersion) != 2 || HIBYTE (wsd.wVersion) != 2) {\r
585 \r
586                 /* Tell the user that we could not find a usable WinSock DLL. */\r
587                 WSACleanup ();\r
588                 printf\r
589                         ("InstallSP: Unable to find a usable version of Winsock DLL\n");\r
590                 return -1;\r
591         }\r
592         if (argc < 2) {\r
593                 usage (argv[0]);\r
594                 return -1;\r
595         }\r
596         if ((strlen (argv[1]) != 2) && (argv[1][0] != '-')\r
597                 && (argv[1][0] != '/')) {\r
598                 usage (argv[0]);\r
599                 return -1;\r
600         }\r
601         switch (tolower (argv[1][1])) {\r
602 \r
603         case 'i':\r
604                 /* Install the Infiniband Service Provider */\r
605                 install_provider ();\r
606 #ifdef PERFMON_ENABLED\r
607                 _IBSPPerfmonIniFilesGenerate();\r
608                 if ( _IBSPPerfmonRegisterKeys() == ERROR_SUCCESS )\r
609                                 _IBSPPerfmonRegisterCounters();\r
610 #endif\r
611                 break;\r
612 \r
613         case 'r':\r
614                 /* Remove the service provider */\r
615                 if( argc == 2 )\r
616                         remove_provider( openib_key_name );\r
617                 else\r
618                         remove_provider( argv[2] );\r
619 #ifdef PERFMON_ENABLED\r
620                 _IBSPPerfmonIniFilesRemove();\r
621                 if ( _IBSPPerfmonDeregisterCounters() == ERROR_SUCCESS )\r
622                         _IBSPPerfmonDeregisterKeys();\r
623 #endif\r
624                 break;\r
625 \r
626         case 'l':\r
627                 /* List existing providers */\r
628                 print_providers();\r
629                 break;\r
630         \r
631         default:\r
632                 usage (argv[0]);\r
633                 break;\r
634         }\r
635 \r
636         WSACleanup ();\r
637 \r
638         return 0;\r
639 }\r