[IBAL/MTHCA/IPOIB/TOOLS] fix inf to search driver in the same directory (not to use...
[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("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("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("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("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 \r
139         // Get a list of drivers.\r
140         bSuccess =\r
141                 SetupDiBuildDriverInfoList( hDevList, pDevInfo, SPDIT_CLASSDRIVER );\r
142         if( !bSuccess )\r
143         {\r
144                 swprintf( debug_buf,L"[IbInstaller] SetupDiBuildDriverInfoList failed Error %d\n",GetLastError());\r
145                 OutputDebugString( debug_buf );\r
146                 return GetLastError();\r
147         }\r
148 \r
149         // Set the size of the structure properly.\r
150         pDrvInfo->cbSize = sizeof(SP_DRVINFO_DATA);\r
151 \r
152         // Enumerate all drivers, looking for the correct description.\r
153         i = 0;\r
154         do\r
155         {\r
156 \r
157                 bSuccess = SetupDiEnumDriverInfo( hDevList, pDevInfo,\r
158                         SPDIT_CLASSDRIVER, i++, pDrvInfo );\r
159                 if( !bSuccess )\r
160                 {\r
161                         swprintf( debug_buf,L"[IbInstaller] SetupDiEnumDriverInfo failed Error %d\n",GetLastError());\r
162                         OutputDebugString( debug_buf );\r
163                         break;\r
164                 }\r
165 \r
166                 // make the string\r
167                 swprintf( debug_buf,TEXT("[IbInstaller]  pDrvInfo->Description %s\n"),pDrvInfo->Description);\r
168                 OutputDebugString( debug_buf );\r
169                 \r
170                 if( _tcscmp( pDrvInfo->Description, DEVICE_DESC ) )\r
171                         continue;\r
172 \r
173                 // Found it!\r
174                 OutputDebugString( TEXT("Found our driver!\n") );\r
175                 return ERROR_SUCCESS;\r
176 \r
177         } while( bSuccess );\r
178 \r
179         return ERROR_NOT_FOUND;\r
180 }\r
181 \r
182 \r
183 DWORD\r
184 CreateIbBusRoot(\r
185         IN                              PCTSTR                                          driverPath )\r
186 {\r
187         HDEVINFO                                hDevList;\r
188         BOOL                                    bSuccess;\r
189         SP_DEVINFO_DATA                 devInfo;\r
190         SP_DRVINFO_DATA                 drvInfo;\r
191         LONG                                    status;\r
192         SP_DEVINSTALL_PARAMS    installParams;\r
193 \r
194 \r
195         memset( &devInfo, 0, sizeof(SP_DEVINFO_DATA) );\r
196         devInfo.cbSize = sizeof(SP_DEVINFO_DATA);\r
197 \r
198         OutputDebugString( TEXT("Creating IB Fabric Root device.\n") );\r
199 \r
200         // Create a list for devices of the system class.\r
201         hDevList = SetupDiCreateDeviceInfoList( &GUID_CLASS_SYSTEM, NULL );\r
202         if( hDevList == INVALID_HANDLE_VALUE )\r
203         {\r
204                 OutputDebugString( TEXT("Failed to create dev info list.\n") );\r
205                 return GetLastError();\r
206         }\r
207 \r
208         // Create the device.\r
209         bSuccess = SetupDiCreateDeviceInfo( hDevList, TEXT("SYSTEM"), \r
210                 &GUID_CLASS_SYSTEM, DEVICE_DESC,\r
211                 NULL, DICD_GENERATE_ID, &devInfo );\r
212         if( !bSuccess )\r
213         {\r
214                 OutputDebugString( TEXT("SetupDiCreateDeviceInfo failed.\n") );\r
215                 SetupDiDestroyDeviceInfoList( hDevList );\r
216                 return GetLastError();\r
217         }\r
218 \r
219         // Setup the HW ID for the device.\r
220         bSuccess = SetupDiSetDeviceRegistryProperty( hDevList, &devInfo,\r
221                 SPDRP_HARDWAREID, (BYTE*)GUID_IB_BUS_HW_ID, sizeof(GUID_IB_BUS_HW_ID) );\r
222         if( !bSuccess )\r
223         {\r
224                 OutputDebugString(\r
225                         TEXT("SetupDiSetDeviceRegistryProperty failed.\n") );\r
226                 SetupDiDestroyDeviceInfoList( hDevList );\r
227                 return GetLastError();\r
228         }\r
229 \r
230         // Setup the install path.\r
231         ZeroMemory( &installParams, sizeof(installParams) );\r
232         installParams.cbSize = sizeof(installParams);\r
233         _tcsncpy( installParams.DriverPath, driverPath, MAX_PATH );\r
234 \r
235         bSuccess =\r
236                 SetupDiSetDeviceInstallParams( hDevList, &devInfo, &installParams );\r
237         if( !bSuccess )\r
238         {\r
239                 OutputDebugString( TEXT("SetupDiSetDeviceInstallParams failed.\n") );\r
240                 SetupDiDestroyDeviceInfoList( hDevList );\r
241                 return GetLastError();\r
242         }\r
243 \r
244         status = SelectDriver( hDevList, &devInfo, &drvInfo );\r
245         if( status != ERROR_SUCCESS )\r
246         {\r
247                 OutputDebugString( TEXT("Could not find driver.\n") );\r
248                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
249                 SetupDiDestroyDeviceInfoList( hDevList );\r
250                 return status;\r
251         }\r
252 \r
253         // Select the device.\r
254         bSuccess = SetupDiSetSelectedDevice( hDevList, &devInfo );\r
255         if( !bSuccess )\r
256         {\r
257                 OutputDebugString( TEXT("SetupDiSetSelectedDevice failed.\n") );\r
258                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
259                 SetupDiDestroyDeviceInfoList( hDevList );\r
260                 return GetLastError();\r
261         }\r
262 \r
263         // Select the driver.\r
264         bSuccess = SetupDiSetSelectedDriver( hDevList, &devInfo, &drvInfo );\r
265         if( !bSuccess )\r
266         {\r
267                 OutputDebugString( TEXT("SetupDiSetSelectedDriver failed.\n") );\r
268                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
269                 SetupDiDestroyDeviceInfoList( hDevList );\r
270                 return GetLastError();\r
271         }\r
272 \r
273         // Register the device (since it is non-PnP).\r
274         bSuccess = SetupDiRegisterDeviceInfo( hDevList, &devInfo, SPRDI_FIND_DUPS,\r
275                 NULL, NULL, NULL );\r
276         if( !bSuccess )\r
277         {\r
278                 OutputDebugString( TEXT("SetupDiRegisterDeviceInfo failed.\n") );\r
279                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
280                 SetupDiDestroyDeviceInfoList( hDevList );\r
281                 return GetLastError();\r
282         }\r
283 \r
284         // Install the device (copies the files and starts it).\r
285         bSuccess = SetupDiInstallDevice( hDevList, &devInfo );\r
286         if( !bSuccess )\r
287         {\r
288                 OutputDebugString( TEXT("SetupDiInstallDevice failed.\n") );\r
289                 SetupDiDestroyDriverInfoList( hDevList, &devInfo, SPDIT_CLASSDRIVER );\r
290                 SetupDiDestroyDeviceInfoList( hDevList );\r
291                 return GetLastError();\r
292         }\r
293 \r
294         return ERROR_SUCCESS;\r
295 }\r
296 \r
297 \r
298 UINT CALLBACK\r
299 IbFileCallback(\r
300         IN      PVOID           Context,\r
301         IN      UINT            Notification,\r
302         IN      UINT_PTR        Param1,\r
303         IN      UINT_PTR        Param2 )\r
304 {\r
305         TCHAR           *pPath;\r
306         FILEPATHS       *pFileInfo;\r
307 \r
308         UNREFERENCED_PARAMETER( Param2 );\r
309 \r
310         if( Notification != SPFILENOTIFY_QUEUESCAN_EX )\r
311                 return 0;\r
312 \r
313         pPath = (TCHAR*)Context;\r
314         pFileInfo = (FILEPATHS*)Param1;\r
315 \r
316         // Copy the source path of the file to the path.\r
317         if( pFileInfo->Source )\r
318                 _tcsncpy( pPath, pFileInfo->Source, MAX_PATH );\r
319 \r
320         return 0;\r
321 }\r
322 \r
323 extern "C"\r
324 {\r
325 \r
326 \r
327 HRESULT\r
328 IbCoInstaller(\r
329         IN DI_FUNCTION                                          InstallFunction,\r
330         IN HDEVINFO                                                     DeviceInfoSet,\r
331         IN PSP_DEVINFO_DATA                                     DeviceInfoData  OPTIONAL,\r
332         IN OUT PCOINSTALLER_CONTEXT_DATA        Context )\r
333 {\r
334         SP_DEVINSTALL_PARAMS    InstallParams;\r
335         DWORD                                   result;\r
336         BOOL                                    b;\r
337         TCHAR                                   path[MAX_PATH];\r
338         size_t                                  nEnd;\r
339 \r
340         UNREFERENCED_PARAMETER( Context );\r
341 \r
342         // The file queue is valid on the DIF_INSTALLDEVICE, so trap that\r
343         // code and extract the install path.\r
344         if( InstallFunction != DIF_INSTALLDEVICE )\r
345                 return NO_ERROR;\r
346 \r
347         // First find out if we need to install the transport.\r
348         result = NeedInstall();\r
349         if( result != ERROR_SUCCESS )\r
350         {\r
351                 if( result == ERROR_ALREADY_EXISTS )\r
352                         return NO_ERROR;\r
353                 else\r
354                         return result;\r
355         }\r
356 \r
357         // Extract the file path from the file queue.\r
358         // First get the file queue (it's in the install parameters).\r
359         memset( &InstallParams, 0, sizeof(InstallParams) );\r
360         InstallParams.cbSize = sizeof(InstallParams);\r
361 \r
362         // Get the installation parameters.\r
363         b = SetupDiGetDeviceInstallParams( DeviceInfoSet, DeviceInfoData,\r
364                 &InstallParams );\r
365         if( !b )\r
366                 return GetLastError();\r
367 \r
368         // If there isn't a file queue, abort the installation.\r
369         if( !InstallParams.FileQueue )\r
370                 return ERROR_DI_DONT_INSTALL;\r
371 \r
372         // Scan the file queue.  The callback will copy the file name to our path.\r
373         SetupScanFileQueue( InstallParams.FileQueue, SPQ_SCAN_USE_CALLBACKEX, NULL,\r
374                 IbFileCallback, &path, &result );\r
375         if( result )\r
376                 return result;\r
377 \r
378         // Strip the file name from the path.\r
379         nEnd = _tcslen( path );\r
380         while( path[nEnd] != '\\' )\r
381                 nEnd--;\r
382 /*\r
383         NOTE: no need to strip the platform directoty it was removed for WHQL\r
384         // Skip the slash.\r
385         nEnd--;\r
386         // Strip the platform subdir name from the path.\r
387         while( path[nEnd] != '\\' )\r
388                 nEnd--;\r
389 */\r
390         path[nEnd] = _T('\0');\r
391 \r
392         swprintf( debug_buf ,L"[IbInstaller] path %s\n",path);\r
393         OutputDebugString( debug_buf );\r
394 \r
395 \r
396         // Create the bus root.\r
397         result = CreateIbBusRoot( path );\r
398         if( result != ERROR_SUCCESS )\r
399                 return result;\r
400 \r
401         return NO_ERROR;\r
402 }\r
403 \r
404 }       // extern "C"\r
405 \r