merge with WinIB stack to make the stacks as identical as possible
[mirror/winof/.git] / tools / coinstaller / user / IbInstaller.cpp
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 // IBInstaller.cpp : Defines the entry point for the DLL application.\r
34 //\r
35 \r
36 #include "stdafx.h"\r
37 \r
38 wchar_t  debug_buf[256];\r
39 \r
40 // IB Fabric device HW ID\r
41 #define GUID_IB_BUS_HW_ID       TEXT("{94f41ced-78eb-407c-b5df-958040af0fd8}")\r
42 #ifdef WINIB \r
43 #define DEVICE_DESC                     TEXT("Mellanox InfiniBand Fabric")\r
44 #else\r
45 #define DEVICE_DESC                     TEXT("InfiniBand Fabric")\r
46 #endif\r
47 \r
48 // System Class GUID (from wdmguid.h)\r
49 //{4D36E97D-E325-11CE-BFC1-08002BE10318}\r
50 static const GUID GUID_CLASS_SYSTEM = \r
51 { 0x4D36E97D, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } };\r
52 \r
53 \r
54 BOOL APIENTRY DllMain(\r
55         HANDLE hModule, \r
56         DWORD  ul_reason_for_call, \r
57         LPVOID lpReserved )\r
58 {\r
59         UNREFERENCED_PARAMETER( hModule );\r
60         UNREFERENCED_PARAMETER( ul_reason_for_call );\r
61         UNREFERENCED_PARAMETER( lpReserved );\r
62         return TRUE;\r
63 }\r
64 \r
65 \r
66 //\r
67 // Checks the installed devices, looking for an instance of the bus root.\r
68 //\r
69 DWORD NeedInstall()\r
70 {\r
71         HDEVINFO                hDevList;\r
72         BOOL                    bSuccess;\r
73         SP_DEVINFO_DATA devInfo;\r
74         DWORD                   i;\r
75         TCHAR                   buf[128];\r
76 \r
77         memset( &devInfo, 0, sizeof(SP_DEVINFO_DATA) );\r
78         devInfo.cbSize = sizeof(SP_DEVINFO_DATA);\r
79 \r
80         OutputDebugString(\r
81                 TEXT("[IbInstaller]Checking for existance of IB Fabric Root device.\n") );\r
82 \r
83         // Get all devices of the system class.\r
84         hDevList = SetupDiGetClassDevs( &GUID_CLASS_SYSTEM, 0, NULL, 0 );\r
85         if( hDevList == INVALID_HANDLE_VALUE )\r
86         {\r
87                 swprintf( debug_buf,L"[IbInstaller] Failed to get system class dev info list Error %d\n",GetLastError());\r
88                 OutputDebugString( debug_buf );\r
89                 return GetLastError();\r
90         }\r
91 \r
92         // Enumerate until we find our device.  If the device exists, we\r
93         // exit.\r
94         i = 0;\r
95         do\r
96         {\r
97                 // Get the next device.\r
98                 bSuccess = SetupDiEnumDeviceInfo( hDevList, i++, &devInfo );\r
99                 if( !bSuccess )\r
100                 {\r
101                         OutputDebugString( TEXT("[IbInstaller]SetupDiEnumDeviceInfo failed.\n") );\r
102                         break;\r
103                 }\r
104 \r
105                 // Get the device's description.\r
106                 bSuccess = SetupDiGetDeviceRegistryProperty( hDevList, &devInfo,\r
107                         SPDRP_HARDWAREID, NULL, (BYTE*)buf, sizeof(buf), NULL );\r
108                 if( !bSuccess )\r
109                 {\r
110                         // Device has no HW ID.\r
111                         OutputDebugString(\r
112                                 TEXT("[IbInstaller]SetupDiGetDeviceRegistryProperty failed.\n") );\r
113                         // Skip to the next.\r
114                         bSuccess = TRUE;\r
115                         continue;\r
116                 }\r
117 \r
118                 // Compare to our device description.\r
119                 if( _tcscmp( buf, GUID_IB_BUS_HW_ID ) )\r
120                         continue;\r
121 \r
122                 // The device is already installed.\r
123                 SetupDiDestroyDeviceInfoList( hDevList );\r
124                 OutputDebugString( TEXT("[IbInstaller]IB Fabric Root device already exists.\n") );\r
125                 return ERROR_ALREADY_EXISTS;\r
126 \r
127         } while( bSuccess );\r
128 \r
129         return ERROR_SUCCESS;\r
130 }\r
131 \r
132 \r
133 DWORD SelectDriver(\r
134         IN                              HDEVINFO                                        hDevList,\r
135         IN                              SP_DEVINFO_DATA                         *pDevInfo,\r
136         OUT                             SP_DRVINFO_DATA                         *pDrvInfo )\r
137 {\r
138         DWORD   i;\r
139         BOOL    bSuccess;\r
140         \r
141         OutputDebugString( L"SelectDriver" );\r
142 \r
143         // Get a list of drivers.\r
144         bSuccess =\r
145                 SetupDiBuildDriverInfoList( hDevList, pDevInfo, SPDIT_CLASSDRIVER );\r
146         if( !bSuccess )\r
147         {\r
148                 swprintf( debug_buf,L"[IbInstaller] SetupDiBuildDriverInfoList failed Error %d\n",GetLastError());\r
149                 OutputDebugString( debug_buf );\r
150                 return GetLastError();\r
151         }\r
152 \r
153         // Set the size of the structure properly.\r
154         pDrvInfo->cbSize = sizeof(SP_DRVINFO_DATA);\r
155 \r
156         // Enumerate all drivers, looking for the correct description.\r
157         i = 0;\r
158         do\r
159         {\r
160 \r
161                 bSuccess = SetupDiEnumDriverInfo( hDevList, pDevInfo,\r
162                         SPDIT_CLASSDRIVER, i++, pDrvInfo );\r
163                 if( !bSuccess )\r
164                 {\r
165                         swprintf( debug_buf,L"[IbInstaller] SetupDiEnumDriverInfo failed Error %d\n",GetLastError());\r
166                         OutputDebugString( debug_buf );\r
167                         break;\r
168                 }\r
169                 // make the string\r
170 \r
171                 swprintf( debug_buf,TEXT("[IbInstaller]  pDrvInfo->Description %s\n"),pDrvInfo->Description);\r
172                 OutputDebugString( debug_buf );\r
173                 \r
174                 if( _tcscmp( pDrvInfo->Description, DEVICE_DESC ) )\r
175                         continue;\r
176 \r
177                 // Found it!\r
178                 OutputDebugString( TEXT("[IbInstaller]Found our driver!\n") );\r
179                 return ERROR_SUCCESS;\r
180 \r
181         } while( bSuccess );\r
182 \r
183         return ERROR_NOT_FOUND;\r
184 }\r
185 \r
186 \r
187 DWORD\r
188 CreateIbBusRoot(\r
189         IN                              PTSTR                                           driverPath )\r
190 {\r
191         HDEVINFO                                hDevList;\r
192         BOOL                                    bSuccess;\r
193         SP_DEVINFO_DATA                 devInfo;\r
194         SP_DRVINFO_DATA                 drvInfo;\r
195         LONG                                    status;\r
196         SP_DEVINSTALL_PARAMS    installParams;\r
197         size_t                                  nEnd;\r
198         DWORD gle = 0;\r
199 \r
200         memset( &devInfo, 0, sizeof(SP_DEVINFO_DATA) );\r
201         devInfo.cbSize = sizeof(SP_DEVINFO_DATA);\r
202 \r
203         OutputDebugString( TEXT("[IbInstaller]Creating IB Fabric Root device.\n") );\r
204 \r
205         // Create a list for devices of the system class.\r
206         hDevList = SetupDiCreateDeviceInfoList( &GUID_CLASS_SYSTEM, NULL );\r
207         if( hDevList == INVALID_HANDLE_VALUE )\r
208         {\r
209                 gle = GetLastError();\r
210                 OutputDebugString( TEXT("[IbInstaller]Failed to create dev info list.\n") );\r
211                 return gle;\r
212         }\r
213 \r
214         // Create the device.\r
215         bSuccess = SetupDiCreateDeviceInfo( hDevList, TEXT("SYSTEM"), \r
216                 &GUID_CLASS_SYSTEM, DEVICE_DESC,\r
217                 NULL, DICD_GENERATE_ID, &devInfo );\r
218         if( !bSuccess )\r
219         {\r
220                 gle = GetLastError();\r
221                 OutputDebugString( TEXT("[IbInstaller]SetupDiCreateDeviceInfo failed.\n") );\r
222                 SetupDiDestroyDeviceInfoList( hDevList );\r
223                 return gle;\r
224         }\r
225 \r
226         // Setup the HW ID for the device.\r
227         bSuccess = SetupDiSetDeviceRegistryProperty( hDevList, &devInfo,\r
228                 SPDRP_HARDWAREID, (BYTE*)GUID_IB_BUS_HW_ID, sizeof(GUID_IB_BUS_HW_ID) );\r
229         if( !bSuccess )\r
230         {\r
231                 gle = GetLastError();\r
232                 OutputDebugString(\r
233                         TEXT("[IbInstaller]SetupDiSetDeviceRegistryProperty failed.\n") );\r
234                 SetupDiDestroyDeviceInfoList( hDevList );\r
235                 return gle;\r
236         }\r
237 \r
238         // Setup the install path.\r
239         ZeroMemory( &installParams, sizeof(installParams) );\r
240         installParams.cbSize = sizeof(installParams);\r
241 \r
242 \r
243         OSVERSIONINFO osvi;\r
244         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
245         bSuccess = GetVersionEx (&osvi);\r
246         if( !bSuccess )\r
247         {\r
248                 gle = GetLastError();\r
249                 OutputDebugString(\r
250                         TEXT("[IbInstaller]GetVersionEx failed.\n") );\r
251                 SetupDiDestroyDeviceInfoList( hDevList );\r
252                 return gle;\r
253         }\r
254 \r
255         // for LH we want to find the correct path\r
256         if (osvi.dwMajorVersion > 5) \r
257         {\r
258                 WIN32_FIND_DATA FindFileData;\r
259                 HANDLE hFind;\r
260 \r
261                 // Strip the file name from the path.\r
262                 nEnd = _tcslen( driverPath );\r
263                 while( driverPath[nEnd] != '\\' ) {\r
264                         nEnd--;\r
265                 }\r
266                 driverPath[nEnd] = _T('\0');\r
267                 _tcsncat(driverPath,TEXT("\\ib_bus.inf_*"), MAX_PATH);\r
268 \r
269                 hFind = FindFirstFile(driverPath, &FindFileData);\r
270                 if (hFind == INVALID_HANDLE_VALUE) \r
271                 {\r
272                         printf ("Invalid File Handle. GetLastError reports %d\n", GetLastError ());\r
273                         return ERROR_FILE_NOT_FOUND;\r
274                 } \r
275                 else \r
276                 {\r
277                         printf ("The first file found is %s\n", FindFileData.cFileName);\r
278 \r
279                         // Strip the file name from the path.\r
280                         nEnd = _tcslen( driverPath );\r
281                         while( driverPath[nEnd] != '\\' ) {\r
282                                 nEnd--;\r
283                         }\r
284                         driverPath[nEnd+1] = _T('\0');            \r
285 \r
286                         _tcsncpy( installParams.DriverPath, driverPath, MAX_PATH );\r
287                         _tcsncat(installParams.DriverPath, FindFileData.cFileName, MAX_PATH);\r
288                         FindClose(hFind);\r
289                 }\r
290 \r
291         } else {\r
292                         _tcsncpy( installParams.DriverPath, driverPath, MAX_PATH );\r
293         }\r
294 \r
295 \r
296         bSuccess =\r
297                 SetupDiSetDeviceInstallParams( hDevList, &devInfo, &installParams );\r
298         if( !bSuccess )\r
299         {\r
300                 gle = GetLastError();\r
301                 OutputDebugString( TEXT("[IbInstaller]SetupDiSetDeviceInstallParams failed.\n") );\r
302                 SetupDiDestroyDeviceInfoList( hDevList );\r
303                 return gle;\r
304         }\r
305 \r
306         status = SelectDriver( hDevList, &devInfo, &drvInfo );\r
307         if( status != ERROR_SUCCESS )\r
308         {\r
309                 OutputDebugString( TEXT("[IbInstaller]Could not find driver.\n") );\r
310                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
311                 SetupDiDestroyDeviceInfoList( hDevList );\r
312                 return status;\r
313         }\r
314 \r
315         // Select the device.\r
316         bSuccess = SetupDiSetSelectedDevice( hDevList, &devInfo );\r
317         if( !bSuccess )\r
318         {\r
319                 gle = GetLastError();\r
320                 OutputDebugString( TEXT("[IbInstaller]SetupDiSetSelectedDevice failed.\n") );\r
321                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
322                 SetupDiDestroyDeviceInfoList( hDevList );\r
323                 return gle;\r
324         }\r
325 \r
326         // Select the driver.\r
327         bSuccess = SetupDiSetSelectedDriver( hDevList, &devInfo, &drvInfo );\r
328         if( !bSuccess )\r
329         {\r
330                 gle = GetLastError();\r
331                 OutputDebugString( TEXT("[IbInstaller]SetupDiSetSelectedDriver failed.\n") );\r
332                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
333                 SetupDiDestroyDeviceInfoList( hDevList );\r
334                 return gle;\r
335         }\r
336 \r
337         // Register the device (since it is non-PnP).\r
338         bSuccess = SetupDiRegisterDeviceInfo( hDevList, &devInfo, SPRDI_FIND_DUPS,\r
339                 NULL, NULL, NULL );\r
340         if( !bSuccess )\r
341         {\r
342                 gle = GetLastError();\r
343                 OutputDebugString( TEXT("[IbInstaller]SetupDiRegisterDeviceInfo failed.\n") );\r
344                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
345                 SetupDiDestroyDeviceInfoList( hDevList );\r
346                 return gle;\r
347         }\r
348 \r
349         // Install the device (copies the files and starts it).\r
350         bSuccess = SetupDiInstallDevice( hDevList, &devInfo );\r
351         if( !bSuccess )\r
352         {\r
353                 gle = GetLastError();\r
354                 OutputDebugString( TEXT("[IbInstaller]SetupDiInstallDevice failed.\n") );\r
355                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
356                 SetupDiDestroyDeviceInfoList( hDevList );\r
357                 return gle;\r
358         }\r
359 \r
360         return ERROR_SUCCESS;\r
361 }\r
362 \r
363 \r
364 UINT CALLBACK\r
365 IbFileCallback(\r
366         IN      PVOID           Context,\r
367         IN      UINT            Notification,\r
368         IN      UINT_PTR        Param1,\r
369         IN      UINT_PTR        Param2 )\r
370 {\r
371         TCHAR           *pPath;\r
372         FILEPATHS       *pFileInfo;\r
373 \r
374         OutputDebugString( L"IbFileCallback" );\r
375 \r
376         UNREFERENCED_PARAMETER( Param2 );\r
377 \r
378         if( Notification != SPFILENOTIFY_QUEUESCAN_EX )\r
379                 return 0;\r
380 \r
381         pPath = (TCHAR*)Context;\r
382         pFileInfo = (FILEPATHS*)Param1;\r
383 \r
384         // Copy the source path of the file to the path.\r
385         if( pFileInfo->Source )\r
386                 _tcsncpy( pPath, pFileInfo->Source, MAX_PATH );\r
387 \r
388         return 0;\r
389 }\r
390 \r
391 extern "C"\r
392 {\r
393 \r
394 \r
395 HRESULT\r
396 IbCoInstaller(\r
397         IN DI_FUNCTION                                          InstallFunction,\r
398         IN HDEVINFO                                                     DeviceInfoSet,\r
399         IN PSP_DEVINFO_DATA                                     DeviceInfoData  OPTIONAL,\r
400         IN OUT PCOINSTALLER_CONTEXT_DATA        Context )\r
401 {\r
402         SP_DEVINSTALL_PARAMS    InstallParams;\r
403         DWORD                                   result;\r
404         BOOL                                    b;\r
405         TCHAR                                   path[MAX_PATH];\r
406         size_t                                  nEnd;\r
407 \r
408         UNREFERENCED_PARAMETER( Context );\r
409 \r
410         swprintf( debug_buf ,L"IbCoInstaller called DI_FUNCTION =%d\n", InstallFunction);\r
411         OutputDebugString( debug_buf );\r
412 \r
413         // The file queue is valid on the DIF_INSTALLDEVICE, so trap that\r
414         // code and extract the install path.\r
415         if( InstallFunction != DIF_INSTALLDEVICE )\r
416                 return NO_ERROR;\r
417 \r
418         // First find out if we need to install the transport.\r
419         result = NeedInstall();\r
420         if( result != ERROR_SUCCESS )\r
421         {\r
422                 if( result == ERROR_ALREADY_EXISTS )\r
423                         return NO_ERROR;\r
424                 else\r
425                         return result;\r
426         }\r
427 \r
428         // Extract the file path from the file queue.\r
429         // First get the file queue (it's in the install parameters).\r
430         memset( &InstallParams, 0, sizeof(InstallParams) );\r
431         InstallParams.cbSize = sizeof(InstallParams);\r
432 \r
433         // Get the installation parameters.\r
434         b = SetupDiGetDeviceInstallParams( DeviceInfoSet, DeviceInfoData,\r
435                 &InstallParams );\r
436         if( !b )\r
437                 return GetLastError();\r
438 \r
439         // If there isn't a file queue, abort the installation.\r
440         if( !InstallParams.FileQueue )\r
441                 return ERROR_DI_DONT_INSTALL;\r
442 \r
443         // Scan the file queue.  The callback will copy the file name to our path.\r
444         SetupScanFileQueue( InstallParams.FileQueue, SPQ_SCAN_USE_CALLBACKEX, NULL,\r
445                 IbFileCallback, &path, &result );\r
446         if( result )\r
447                 return result;\r
448 \r
449         // Strip the file name from the path.\r
450         nEnd = _tcslen( path );\r
451         while( path[nEnd] != '\\' )\r
452                 nEnd--;\r
453 /*\r
454         NOTE: no need to strip the platform directoty it was removed for WHQL\r
455         // Skip the slash.\r
456         nEnd--;\r
457         // Strip the platform subdir name from the path.\r
458         while( path[nEnd] != '\\' )\r
459                 nEnd--;\r
460 */\r
461         path[nEnd] = _T('\0');\r
462 \r
463         swprintf( debug_buf ,L"[IbInstaller] path %s\n",path);\r
464         OutputDebugString( debug_buf );\r
465 \r
466 \r
467         // Create the bus root.\r
468         result = CreateIbBusRoot( path );\r
469         if( result != ERROR_SUCCESS )\r
470                 return result;\r
471 \r
472         return NO_ERROR;\r
473 }\r
474 \r
475 }       // extern "C"\r
476 \r