VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.cpp@ 67273

Last change on this file since 67273 was 62686, checked in by vboxsync, 8 years ago

Use the iprt/win/setupapi.h wrapper for setupapi.h to deal with preprocessor warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.4 KB
Line 
1/** @file
2 *
3 * instdrvmain - Install guest drivers on NT4
4 *
5 * Copyright (C) 2006-2016 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15
16/**
17 * @todo
18 * The spacing in this file is horrible! Here are some simple rules:
19 * - tabs are forbidden
20 * - indentation is 4 spaces
21 */
22
23
24#include <iprt/win/windows.h>
25#include <iprt/win/setupapi.h>
26#include <regstr.h>
27#include <DEVGUID.h>
28#include <stdio.h>
29
30#include "tchar.h"
31#include "string.h"
32
33
34/*********************************************************************************************************************************
35* Defined Constants And Macros *
36*********************************************************************************************************************************/
37
38/** The video service name. */
39#define VBOXGUEST_VIDEO_NAME "VBoxVideo"
40
41/** The video inf file name */
42#define VBOXGUEST_VIDEO_INF_NAME "VBoxVideo.inf"
43
44/////////////////////////////////////////////////////////////////////////////
45
46
47
48/**
49 * Do some cleanup of data we used. Called by installVideoDriver()
50 */
51void closeAndDestroy(HDEVINFO hDevInfo, HINF hInf)
52{
53 SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
54 SetupDiDestroyDeviceInfoList(hDevInfo);
55 SetupCloseInfFile(hInf);
56}
57
58
59/**
60 * Install the VBox video driver.
61 *
62 * @returns TRUE on success.
63 * @returns FALSE on failure.
64 * @param szDriverDir The base directory where we find the INF.
65 */
66BOOL installVideoDriver(TCHAR* szDriverDir)
67{
68 HDEVINFO hDevInfo;
69 SP_DEVINSTALL_PARAMS DeviceInstallParams={0};
70 SP_DRVINFO_DATA drvInfoData={0};
71 SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0};
72
73 DWORD cbReqSize;
74
75 /* Vars used for reading the INF */
76 HINF hInf;
77 TCHAR szServiceSection[LINE_LEN];
78 INFCONTEXT serviceContext;
79 TCHAR szServiceData[LINE_LEN];
80 TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody...
81
82 SP_DEVINFO_DATA deviceInfoData;
83 DWORD configFlags;
84
85 HKEY hkey;
86 DWORD disp;
87 TCHAR regKeyName[LINE_LEN];
88
89 BOOL rc;
90
91 /* Create an empty list */
92 hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY,
93 NULL);
94
95 if (hDevInfo == INVALID_HANDLE_VALUE)
96 return FALSE;
97
98 memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS));
99 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
100
101 rc=SetupDiGetDeviceInstallParams(hDevInfo,
102 NULL,
103 &DeviceInstallParams);
104
105 if(!rc)
106 return FALSE;
107
108 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
109 DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */
110 DI_DONOTCALLCONFIGMG |
111 DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */
112
113
114 /* Path to inf file */
115 wsprintf(DeviceInstallParams.DriverPath,
116 TEXT("%ws\\%ws"),
117 szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));
118
119 rc=SetupDiSetDeviceInstallParams(hDevInfo,
120 NULL,
121 &DeviceInstallParams);
122 if(!rc)
123 return FALSE;
124
125 /* Read the drivers from the inf file */
126 if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
127 {
128 SetupDiDestroyDeviceInfoList(hDevInfo);
129 return FALSE;
130 }
131
132 /* Get the first found driver.
133 Our Inf file only contains one so this is fine */
134 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
135 if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
136 0, &drvInfoData)){
137 SetupDiDestroyDeviceInfoList(hDevInfo);
138 return FALSE;
139 }
140
141 /* Get necessary driver details */
142 DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
143 if (!(!SetupDiGetDriverInfoDetail(hDevInfo,
144 NULL,
145 &drvInfoData,
146 &DriverInfoDetailData,
147 DriverInfoDetailData.cbSize,
148 &cbReqSize)
149 &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) )
150 {
151 SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
152 SetupDiDestroyDeviceInfoList(hDevInfo);
153 return FALSE;
154 }
155
156 hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
157 NULL, INF_STYLE_WIN4, NULL);
158
159 if (hInf == INVALID_HANDLE_VALUE)
160 {
161 SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
162 SetupDiDestroyDeviceInfoList(hDevInfo);
163 return FALSE;
164 }
165
166 /* First install the service */
167 wsprintf(szServiceSection, TEXT("%ws.Services"),
168 DriverInfoDetailData.SectionName);
169
170 if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext))
171 {
172 /* No service line?? Can't be... */
173 closeAndDestroy(hDevInfo, hInf);
174 return FALSE;
175 }
176
177 /* Get the name */
178 SetupGetStringField(&serviceContext,
179 1,
180 szServiceData,
181 sizeof(szServiceData),
182 NULL);
183
184 wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData);
185
186 memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
187 deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
188
189 if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing
190 ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr, //Create new
191 (LPGUID) &GUID_DEVCLASS_DISPLAY,
192 NULL, //Do we need a description here?
193 NULL, //No user interface
194 0,
195 &deviceInfoData) &&
196 SetupDiRegisterDeviceInfo(hDevInfo,
197 &deviceInfoData,
198 0,
199 NULL,
200 NULL,
201 NULL)) )
202 {
203 /* We created a new key in the registry */
204
205 memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS));
206 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
207
208 SetupDiGetDeviceInstallParams(hDevInfo,
209 &deviceInfoData,
210 &DeviceInstallParams);
211
212 DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files
213 DI_DONOTCALLCONFIGMG |
214 DI_ENUMSINGLEINF; //Use our INF file only
215
216 /* Path to inf file */
217 wsprintf(DeviceInstallParams.DriverPath,
218 TEXT("%ws\\%ws"),
219 szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));
220
221 SetupDiSetDeviceInstallParams(hDevInfo,
222 &deviceInfoData,
223 &DeviceInstallParams);
224
225
226 if(!SetupDiBuildDriverInfoList(hDevInfo,
227 &deviceInfoData,
228 SPDIT_CLASSDRIVER))
229 {
230 closeAndDestroy(hDevInfo, hInf);
231 return FALSE;
232 }
233
234 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
235 if (!SetupDiEnumDriverInfo(hDevInfo,
236 &deviceInfoData,
237 SPDIT_CLASSDRIVER,
238 0,
239 &drvInfoData))
240 {
241 closeAndDestroy(hDevInfo, hInf);
242 return FALSE;
243 }
244
245 if(!SetupDiSetSelectedDriver(hDevInfo,
246 &deviceInfoData,
247 &drvInfoData))
248 {
249 closeAndDestroy(hDevInfo, hInf);
250 return FALSE;
251 }
252
253 if(!SetupDiInstallDevice(hDevInfo,
254 &deviceInfoData))
255 {
256 closeAndDestroy(hDevInfo, hInf);
257 return FALSE;
258 }
259 }
260
261 /* Make sure the device is enabled */
262 if (SetupDiGetDeviceRegistryProperty(hDevInfo,
263 &deviceInfoData, SPDRP_CONFIGFLAGS,
264 NULL, (LPBYTE) &configFlags,
265 sizeof(DWORD),
266 NULL)
267 && (configFlags & CONFIGFLAG_DISABLED))
268 {
269 configFlags &= ~CONFIGFLAG_DISABLED;
270
271 SetupDiSetDeviceRegistryProperty(hDevInfo,
272 &deviceInfoData,
273 SPDRP_CONFIGFLAGS,
274 (LPBYTE) &configFlags,
275 sizeof(DWORD));
276 }
277
278 wsprintf(regKeyName,
279 TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"),
280 szServiceData, 0); //We only have one device
281
282 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
283 regKeyName,
284 0,
285 NULL,
286 REG_OPTION_NON_VOLATILE,
287 KEY_READ | KEY_WRITE,
288 NULL,
289 &hkey,
290 &disp) == ERROR_SUCCESS)
291 {
292 /* Insert description */
293 RegSetValueEx(hkey,
294 TEXT("Device Description"),
295 0,
296 REG_SZ,
297 (LPBYTE) DriverInfoDetailData.DrvDescription,
298 (lstrlen(DriverInfoDetailData.DrvDescription) + 1) *
299 sizeof(TCHAR) );
300
301 TCHAR szSoftwareSection[LINE_LEN];
302
303 wsprintf(szSoftwareSection,
304 TEXT("%ws.SoftwareSettings"),
305 szServiceData);
306
307 if (!SetupInstallFromInfSection(NULL,
308 hInf,
309 szSoftwareSection,
310 SPINST_REGISTRY,
311 hkey,
312 NULL,
313 0,
314 NULL,
315 NULL,
316 NULL,
317 NULL))
318 {
319 RegCloseKey(hkey);
320 closeAndDestroy(hDevInfo, hInf);
321 return FALSE;
322 }
323
324 RegCloseKey(hkey);
325 }
326
327 /* Install OpenGL stuff */
328 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
329 TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"),
330 0,
331 NULL,
332 REG_OPTION_NON_VOLATILE,
333 KEY_READ | KEY_WRITE,
334 NULL,
335 &hkey,
336 &disp) == ERROR_SUCCESS)
337 {
338 /* Do installation here if ever necessary. Currently there is no OpenGL stuff */
339
340 RegCloseKey(hkey);
341 }
342
343
344 /* Cleanup */
345 closeAndDestroy(hDevInfo, hInf);
346
347#if 0
348 /* If this key is inserted into the registry, windows will show the desktop
349 applet on next boot. We decide in the installer if we want that so the code
350 is disabled here. */
351 /* Set registry keys so windows picks up the changes */
352 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
353 TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"),
354 0,
355 NULL,
356 REG_OPTION_NON_VOLATILE,
357 KEY_READ | KEY_WRITE,
358 NULL,
359 &hkey,
360 &disp) == ERROR_SUCCESS)
361 {
362 RegCloseKey(hkey);
363 }
364#endif
365
366 /* We must reboot at some point */
367 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
368 TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"),
369 0,
370 NULL,
371 REG_OPTION_NON_VOLATILE,
372 KEY_READ | KEY_WRITE,
373 NULL,
374 &hkey,
375 &disp) == ERROR_SUCCESS)
376 {
377 RegCloseKey(hkey);
378 }
379
380 return TRUE;
381}
382
383
384void displayHelpAndExit(char *programName)
385{
386 printf("Installs VirtualBox Guest Additions for Windows NT 4.0\n\n");
387 printf("Syntax: %s [/i|/u]\n", programName);
388 printf("\n\t/i - perform Guest Additions installation\n");
389 printf("\t/u: - perform Guest Additions uninstallation\n");
390 exit(1);
391}
392
393/**
394 * Check if we are running on NT4.
395 *
396 * @returns TRUE if NT 4.
397 * @returns FALSE otherwise.
398 */
399BOOL isNT4(void)
400{
401 OSVERSIONINFO osVersion;
402
403 osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
404 GetVersionEx(&osVersion);
405
406 switch (osVersion.dwPlatformId)
407 {
408 case VER_PLATFORM_WIN32s:
409 case VER_PLATFORM_WIN32_WINDOWS:
410 return FALSE;
411 case VER_PLATFORM_WIN32_NT:
412 if (osVersion.dwMajorVersion == 4)
413 return TRUE;
414 else
415 return FALSE;
416 default:
417 break;
418 }
419 return FALSE;
420}
421
422/**
423 * Video driver uninstallation will be added later if necessary.
424 */
425int uninstallDrivers(void)
426{
427 return 0;
428}
429
430
431int main(int argc, char **argv)
432{
433 BOOL rc=FALSE;
434 TCHAR szInstallDir[MAX_PATH];
435 HMODULE hExe = GetModuleHandle(NULL);
436
437 /** @todo r=bird:
438 * And by the way, we're only missing the coding style dmik uses now
439 * and this file would contain the complete set. */
440 if(2!=argc || (stricmp(argv[1], "/i") && stricmp(argv[1], "/u")))
441 displayHelpAndExit(argv[0]);
442
443 /* This program is only for installing drivers on NT4 */
444 if(!isNT4()){
445 printf("This program only runs on NT4\n");
446 return -1;
447 }
448
449 if (!GetModuleFileName(hExe, &szInstallDir[0], sizeof(szInstallDir)))
450 {
451 printf("GetModuleFileName failed! rc = %d\n", GetLastError());
452 return -1;
453 }
454
455 TCHAR *lastBackslash = wcsrchr(szInstallDir, L'\\');
456
457 if (!lastBackslash)
458 {
459 printf("Invalid path name!\n");
460 return -1;
461 }
462
463 *lastBackslash=L'\0';
464
465 /* Install video driver. Mouse driver installation is done by overwriting
466 the image path in the setup script. */
467 if(!stricmp(argv[1], "/i")){
468 rc=installVideoDriver(szInstallDir);
469 }
470 else{
471 /* No video driver uninstallation yet. Do we need it? */
472 }
473
474 if(FALSE==rc)
475 printf("Some failure occurred during driver installation.\n");
476 return !rc; /* Return != 0 on failure. */
477}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette