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