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