8111f08dacff7b3778c9c7d305522387ceca94a7
[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 = "System\\CurrentControlSet\\Services\\Winsock\\Parameters\\TCP on SAN";\r
50 static const char *openib_key_name = "OpenIB Alliance";\r
51 \r
52 /* Unique provider GUID generated with "uuidgen -s" */\r
53 static GUID provider_guid = {\r
54         /* c943654d-2c84-4db7-af3e-fdf1c5322458 */\r
55         0xc943654d, 0x2c84, 0x4db7,\r
56         { 0xaf, 0x3e, 0xfd, 0xf1, 0xc5, 0x32, 0x24,     0x58 }\r
57 };\r
58 \r
59 #ifdef _WIN64\r
60 #define WSCInstallProvider      WSCInstallProvider64_32\r
61 #endif  /* _WIN64 */\r
62 \r
63 /*\r
64  * Function: usage\r
65  *   Description: Prints usage information.\r
66  */\r
67 static void\r
68 usage (char *progname)\r
69 {\r
70         printf ("usage: %s [-i/-r]\n", progname);\r
71         printf ("    -i   Install the service provider\n"\r
72                         "    -r   Remove the OpenIB service provider\n"\r
73                         "    -r <name>   Remove the specified service provider\n"\r
74                         "    -l   List service providers\n");\r
75 }\r
76 \r
77 \r
78 /* Function: print_providers\r
79  *   Description: \r
80  *     This function prints out each entry in the Winsock catalog.\r
81 */\r
82 static void print_providers(void)\r
83 {\r
84         WSAPROTOCOL_INFOW *protocol_info;\r
85         unsigned int protocol_count;\r
86         unsigned int i;\r
87         DWORD protocol_size;\r
88         INT errno;\r
89         int rc;\r
90 \r
91         /* Find the size of the buffer */\r
92         protocol_size = 0;\r
93         rc = WSCEnumProtocols (NULL, NULL, &protocol_size, &errno);\r
94         if (rc == SOCKET_ERROR && errno != WSAENOBUFS) {\r
95                 printf("WSCEnumProtocols() returned error (%d)\n", errno);\r
96                 return;\r
97         }\r
98 \r
99         /* Allocate the buffer */\r
100         protocol_info = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, protocol_size);\r
101         if (protocol_info == NULL) {\r
102                 printf("HeapAlloc() failed\n");\r
103                 return;\r
104         }\r
105 \r
106         /* Enumerate the catalog for real */\r
107         rc = WSCEnumProtocols (NULL, protocol_info, &protocol_size, &errno);\r
108         if (rc == SOCKET_ERROR) {\r
109                 printf("WSCEnumProtocols returned error for real enumeration (%d)\n",\r
110                          errno);\r
111                 HeapFree (GetProcessHeap (), 0, protocol_info);\r
112                 return;\r
113         }\r
114 \r
115         protocol_count = rc;\r
116 \r
117         for (i = 0; i < protocol_count; i++) {\r
118                 printf ("%010d - %S\n", protocol_info[i].dwCatalogEntryId,\r
119                                 protocol_info[i].szProtocol);\r
120         }\r
121 \r
122         HeapFree (GetProcessHeap (), 0, protocol_info);\r
123 \r
124         return;\r
125 }\r
126 \r
127 /*\r
128  * Function: install_provider\r
129  *   Description: installs the service provider\r
130  *\r
131  * Note: most of the information setup here comes from "MSDN Home >\r
132  * MSDN Library > Windows Development > Network Devices and\r
133  * Protocols > Design Guide > System Area Networks > Windows Sockets\r
134  * Direct > Windows Sockets Direct Component Operation > Installing\r
135  * Windows Sockets Direct Components".\r
136  * The direct link is http://msdn.microsoft.com/library/default.asp?url=/library/en-us/network/hh/network/wsdp_2xrb.asp\r
137  */\r
138 static void install_provider(void)\r
139 {\r
140         int rc;\r
141         INT errno;\r
142         LONG reg_error;\r
143         WSAPROTOCOL_INFOW provider;\r
144         HKEY hkey;\r
145 \r
146         /* Now setup the key. */\r
147         reg_error = RegCreateKeyEx( HKEY_LOCAL_MACHINE, winsock_key_path, 0, NULL,\r
148                 REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL, &hkey, NULL );\r
149         if( reg_error == ERROR_SUCCESS )\r
150         {\r
151                 reg_error = RegSetValueEx( hkey, openib_key_name, 0, REG_BINARY,\r
152                         (PBYTE)&provider_guid, sizeof(GUID) );\r
153                 if( reg_error == ERROR_SUCCESS )\r
154                 {\r
155                         /* Force the system to write the new key now. */\r
156                         RegFlushKey(hkey);\r
157                 }\r
158                 else\r
159                 {\r
160                         fprintf(stderr, "RegSetValueEx failed with %d\n", GetLastError());\r
161                 }\r
162 \r
163                 RegCloseKey(hkey);\r
164         }\r
165         else\r
166         {\r
167                 fprintf(stderr, "Could not get a handle on Winsock registry (%d)\n", GetLastError());\r
168         }\r
169 \r
170         /* Setup the values in PROTOCOL_INFO */\r
171         provider.dwServiceFlags1 = \r
172                 XP1_GUARANTEED_DELIVERY | \r
173                 XP1_GUARANTEED_ORDER | \r
174                 XP1_MESSAGE_ORIENTED |\r
175                 XP1_GRACEFUL_CLOSE;\r
176         provider.dwServiceFlags2 = 0;   /* Reserved */\r
177         provider.dwServiceFlags3 = 0;   /* Reserved */\r
178         provider.dwServiceFlags4 = 0;   /* Reserved */\r
179         provider.dwProviderFlags = PFL_HIDDEN;\r
180         provider.ProviderId = provider_guid;    /* Service Provider ID provided by vendor. Need to be changed later */\r
181         provider.dwCatalogEntryId = 0;\r
182         provider.ProtocolChain.ChainLen = 1;    /* Base Protocol Service Provider */\r
183         provider.iVersion = 2;  /* don't know what it is */\r
184         provider.iAddressFamily = AF_INET;\r
185         provider.iMaxSockAddr = 16;\r
186         provider.iMinSockAddr = 16;\r
187         provider.iSocketType = SOCK_STREAM;\r
188         provider.iProtocol = IPPROTO_TCP;\r
189         provider.iProtocolMaxOffset = 0;\r
190         provider.iNetworkByteOrder = BIGENDIAN;\r
191         provider.iSecurityScheme = SECURITY_PROTOCOL_NONE;\r
192         provider.dwMessageSize = 0xFFFFFFFF; /* IB supports 32-bit lengths for data transfers on RC */\r
193         provider.dwProviderReserved = 0;\r
194         wcscpy( provider.szProtocol, provider_name );\r
195 \r
196         rc = WSCInstallProvider(\r
197                 &provider_guid, provider_path, &provider, 1, &errno );\r
198         if( rc == SOCKET_ERROR )\r
199         {\r
200                 if( errno == WSANO_RECOVERY )\r
201                         printf("The provider is already installed\n");\r
202                 else\r
203                         printf("install_provider: WSCInstallProvider failed: %d\n", errno);\r
204         }\r
205 }\r
206 \r
207 /*\r
208  * Function: remove_provider\r
209  *   Description: removes our provider.\r
210  */\r
211 static void remove_provider( const char* const provider_name )\r
212 {\r
213         int rc;\r
214         int errno;\r
215         LONG reg_error;\r
216         HKEY hkey;\r
217 \r
218         /* Remove our key */\r
219         reg_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,\r
220                                                          winsock_key_path,\r
221                                                          0,\r
222                                                          (KEY_WRITE | KEY_READ),\r
223                                                          &hkey);\r
224         if (reg_error == ERROR_SUCCESS) {\r
225 \r
226                 reg_error = RegDeleteValue(hkey, provider_name);\r
227                 if (reg_error == ERROR_SUCCESS) {\r
228                         /* Force the system to remove the key now. */\r
229                         RegFlushKey(hkey);\r
230                 } else {\r
231                         fprintf(stderr, "RegDeleteValue failed with %d\n", GetLastError());\r
232                 }\r
233 \r
234                 RegCloseKey(hkey);\r
235         }\r
236 \r
237         /* Remove from the catalog */\r
238         rc = WSCDeinstallProvider(&provider_guid, &errno);\r
239         if (rc == SOCKET_ERROR) {\r
240                 printf ("WSCDeinstallProvider failed: %d\n", errno);\r
241         }\r
242 \r
243 #ifdef _WIN64\r
244         /* Remove from the 32-bit catalog too! */\r
245         rc = WSCDeinstallProvider32(&provider_guid, &errno);\r
246         if (rc == SOCKET_ERROR) {\r
247                 printf ("WSCDeinstallProvider32 failed: %d\n", errno);\r
248         }\r
249 #endif  /* _WIN64 */\r
250 }\r
251 \r
252 /* Function: main\r
253  *\r
254  *  Description:\r
255  *    Parse the command line arguments and call either the install or remove\r
256  *    routine.\r
257  */\r
258 int __cdecl main (int argc, char *argv[])\r
259 {\r
260         WSADATA wsd;\r
261 \r
262         /* Load Winsock */\r
263         if (WSAStartup (MAKEWORD (2, 2), &wsd) != 0) {\r
264                 printf ("InstallSP: Unable to load Winsock: %d\n", GetLastError ());\r
265                 return -1;\r
266         }\r
267 \r
268         /* Confirm that the WinSock DLL supports 2.2. Note that if the\r
269          * DLL supports versions greater than 2.2 in addition to 2.2, it\r
270          * will still return 2.2 in wVersion since that is the version we\r
271          * requested. */\r
272         if (LOBYTE (wsd.wVersion) != 2 || HIBYTE (wsd.wVersion) != 2) {\r
273 \r
274                 /* Tell the user that we could not find a usable WinSock DLL. */\r
275                 WSACleanup ();\r
276                 printf\r
277                         ("InstallSP: Unable to find a usable version of Winsock DLL\n");\r
278                 return -1;\r
279         }\r
280         if (argc < 2) {\r
281                 usage (argv[0]);\r
282                 return -1;\r
283         }\r
284         if ((strlen (argv[1]) != 2) && (argv[1][0] != '-')\r
285                 && (argv[1][0] != '/')) {\r
286                 usage (argv[0]);\r
287                 return -1;\r
288         }\r
289         switch (tolower (argv[1][1])) {\r
290 \r
291         case 'i':\r
292                 /* Install the Infiniband Service Provider */\r
293                 install_provider ();\r
294                 break;\r
295 \r
296         case 'r':\r
297                 /* Remove the service provider */\r
298                 if( argc == 2 )\r
299                         remove_provider( openib_key_name );\r
300                 else\r
301                         remove_provider( argv[2] );\r
302                 break;\r
303 \r
304         case 'l':\r
305                 /* List existing providers */\r
306                 print_providers();\r
307                 break;\r
308 \r
309         default:\r
310                 usage (argv[0]);\r
311                 break;\r
312         }\r
313 \r
314         WSACleanup ();\r
315 \r
316         return 0;\r
317 }\r