Changeset 96390 in vbox
- Timestamp:
- Aug 21, 2022 2:04:19 AM (2 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT/Installer
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Installer/Makefile.kmk
r96387 r96390 47 47 48 48 PROGRAMS += VBoxGuestDrvInst 49 VBoxGuestDrvInst_TEMPLATE= VBoxGuestR3Exe 50 VBoxGuestDrvInst_DEFS = _WIN32_WINNT=0x0400 UNICODE 51 VBoxGuestDrvInst_SOURCES = \ 49 VBoxGuestDrvInst_TEMPLATE := VBoxGuestR3Exe 50 VBoxGuestDrvInst_DEFS := _WIN32_WINNT=0x0400 51 VBoxGuestDrvInst_BLD_TRG_ARCH := x86 52 VBoxGuestDrvInst_SOURCES := \ 52 53 VBoxGuestDrvInst.cpp \ 53 54 VBoxGuestDrvInst.rc -
trunk/src/VBox/Additions/WINNT/Installer/VBoxGuestDrvInst.cpp
r93115 r96390 16 16 */ 17 17 18 /** 19 * @todo 20 * The spacing in this file is horrible! Here are some simple rules: 21 * - tabs are forbidden 22 * - indentation is 4 spaces 23 */ 24 25 18 19 /********************************************************************************************************************************* 20 * Header Files * 21 *********************************************************************************************************************************/ 26 22 #include <iprt/win/windows.h> 27 23 #include <iprt/win/setupapi.h> 28 24 #include <regstr.h> 29 25 #include <DEVGUID.h> 30 #include <stdio.h> 31 32 #include "tchar.h" 33 #include "string.h" 26 27 #include <iprt/path.h> 28 #include <iprt/string.h> 29 #include <iprt/utf16.h> 30 34 31 35 32 … … 37 34 * Defined Constants And Macros * 38 35 *********************************************************************************************************************************/ 39 40 36 /** The video service name. */ 41 #define VBOXGUEST_VIDEO_NAME"VBoxVideo"37 #define VBOXGUEST_VIDEO_NAME "VBoxVideo" 42 38 43 39 /** The video inf file name */ 44 #define VBOXGUEST_VIDEO_INF_NAME "VBoxVideo.inf" 45 46 ///////////////////////////////////////////////////////////////////////////// 40 #define VBOXGUEST_VIDEO_INF_NAME "VBoxVideo.inf" 41 42 43 /* 44 * A few error messaging functions that avoids dragging in printf-like stuff. 45 */ 46 47 static RTEXITCODE ErrorMsg(const char *pszMsg) 48 { 49 HANDLE const hStdOut = GetStdHandle(STD_ERROR_HANDLE); 50 DWORD cbIgn; 51 WriteFile(hStdOut, RT_STR_TUPLE("error: "), &cbIgn, NULL); 52 WriteFile(hStdOut, pszMsg, (DWORD)strlen(pszMsg), &cbIgn, NULL); 53 WriteFile(hStdOut, RT_STR_TUPLE("\r\n"), &cbIgn, NULL); 54 return RTEXITCODE_FAILURE; 55 } 56 57 58 static RTEXITCODE ErrorMsgErr(const char *pszMsg, DWORD dwErr, const char *pszErrIntro, size_t cchErrIntro, bool fSigned) 59 { 60 HANDLE const hStdOut = GetStdHandle(STD_ERROR_HANDLE); 61 DWORD cbIgn; 62 WriteFile(hStdOut, RT_STR_TUPLE("error: "), &cbIgn, NULL); 63 WriteFile(hStdOut, pszMsg, (DWORD)strlen(pszMsg), &cbIgn, NULL); 64 WriteFile(hStdOut, pszErrIntro, (DWORD)cchErrIntro, &cbIgn, NULL); 65 char szVal[128]; 66 ssize_t cchVal = RTStrFormatU32(szVal, sizeof(szVal), dwErr, 10, 0, 0, fSigned ? RTSTR_F_VALSIGNED : 0); 67 WriteFile(hStdOut, szVal, (DWORD)cchVal, &cbIgn, NULL); 68 WriteFile(hStdOut, RT_STR_TUPLE("/\r\n"), &cbIgn, NULL); 69 cchVal = RTStrFormatU32(szVal, sizeof(szVal), dwErr, 16, 0, 0, RTSTR_F_SPECIAL); 70 WriteFile(hStdOut, szVal, (DWORD)cchVal, &cbIgn, NULL); 71 WriteFile(hStdOut, RT_STR_TUPLE(")\r\n"), &cbIgn, NULL); 72 return RTEXITCODE_FAILURE; 73 } 74 75 76 static RTEXITCODE ErrorMsgLastErr(const char *pszMsg) 77 { 78 return ErrorMsgErr(pszMsg, GetLastError(), RT_STR_TUPLE(" (last error "), false); 79 } 80 81 82 static RTEXITCODE ErrorMsgLStatus(const char *pszMsg, LSTATUS lrc) 83 { 84 return ErrorMsgErr(pszMsg, (DWORD)lrc, RT_STR_TUPLE(" ("), true); 85 } 47 86 48 87 49 88 50 89 /** 51 * Do some cleanup of data we used. Called by installVideoDriver() 90 * Inner video driver installation function. 91 * 92 * This can normally return immediately on errors as the parent will do the 93 * cleaning up. 52 94 */ 53 void closeAndDestroy(HDEVINFO hDevInfo, HINF hInf) 54 { 55 SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER); 56 SetupDiDestroyDeviceInfoList(hDevInfo); 57 SetupCloseInfFile(hInf); 58 } 95 static RTEXITCODE InstallVideoDriverInner(WCHAR const * const pwszDriverDir, HDEVINFO hDevInfo, HINF *phInf) 96 { 97 /* 98 * Get the first found driver. 99 * Our Inf file only contains one so this is fine. 100 */ 101 SP_DRVINFO_DATA_W drvInfoData = { sizeof(SP_DRVINFO_DATA) }; 102 if (!SetupDiEnumDriverInfoW(hDevInfo, NULL, SPDIT_CLASSDRIVER, 0, &drvInfoData)) 103 return ErrorMsgLastErr("SetupDiEnumDriverInfoW"); 104 105 /* 106 * Get necessary driver details 107 */ 108 union 109 { 110 SP_DRVINFO_DETAIL_DATA_W s; 111 uint64_t au64Padding[(sizeof(SP_DRVINFO_DETAIL_DATA_W) + 256) / sizeof(uint64_t)]; 112 } DriverInfoDetailData = { { sizeof(SP_DRVINFO_DETAIL_DATA) } }; 113 DWORD cbReqSize = NULL; 114 if ( !SetupDiGetDriverInfoDetailW(hDevInfo, NULL, &drvInfoData, 115 &DriverInfoDetailData.s, sizeof(DriverInfoDetailData), &cbReqSize) 116 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 117 return ErrorMsgLastErr("SetupDiGetDriverInfoDetailW"); 118 119 HINF hInf = *phInf = SetupOpenInfFileW(DriverInfoDetailData.s.InfFileName, NULL, INF_STYLE_WIN4, NULL); 120 if (hInf == INVALID_HANDLE_VALUE) 121 return ErrorMsgLastErr("SetupOpenInfFileW"); 122 123 /* 124 * First install the service. 125 */ 126 WCHAR wszServiceSection[LINE_LEN]; 127 int rc = RTUtf16Copy(wszServiceSection, RT_ELEMENTS(wszServiceSection), DriverInfoDetailData.s.SectionName); 128 if (RT_SUCCESS(rc)) 129 rc = RTUtf16CatAscii(wszServiceSection, RT_ELEMENTS(wszServiceSection), ".Services"); 130 if (RT_FAILURE(rc)) 131 return ErrorMsg("wszServiceSection too small"); 132 133 INFCONTEXT SvcCtx; 134 if (!SetupFindFirstLineW(hInf, wszServiceSection, NULL, &SvcCtx)) 135 return ErrorMsgLastErr("SetupFindFirstLine"); /* impossible... */ 136 137 /* 138 * Get the name 139 */ 140 WCHAR wszServiceData[LINE_LEN] = {0}; 141 if (!SetupGetStringFieldW(&SvcCtx, 1, wszServiceData, RT_ELEMENTS(wszServiceData), NULL)) 142 return ErrorMsgLastErr("SetupGetStringFieldW"); 143 144 WCHAR wszDevInstanceId[LINE_LEN]; 145 rc = RTUtf16CopyAscii(wszDevInstanceId, RT_ELEMENTS(wszDevInstanceId), "Root\\LEGACY_"); 146 if (RT_SUCCESS(rc)) 147 rc = RTUtf16Cat(wszDevInstanceId, RT_ELEMENTS(wszDevInstanceId), wszServiceData); 148 if (RT_SUCCESS(rc)) 149 rc = RTUtf16CatAscii(wszDevInstanceId, RT_ELEMENTS(wszDevInstanceId), "\\0000"); 150 if (RT_FAILURE(rc)) 151 return ErrorMsg("wszDevInstanceId too small"); 152 153 /* 154 * ... 155 */ 156 SP_DEVINFO_DATA deviceInfoData = { sizeof(SP_DEVINFO_DATA) }; 157 /* Check for existing first. */ 158 BOOL fDevInfoOkay = SetupDiOpenDeviceInfoW(hDevInfo, wszDevInstanceId, NULL, 0, &deviceInfoData); 159 if (!fDevInfoOkay) 160 { 161 /* Okay, try create a new device info element. */ 162 if (SetupDiCreateDeviceInfoW(hDevInfo, wszDevInstanceId, (LPGUID)&GUID_DEVCLASS_DISPLAY, 163 NULL, // Do we need a description here? 164 NULL, // No user interface 165 0, &deviceInfoData)) 166 { 167 if (SetupDiRegisterDeviceInfo(hDevInfo, &deviceInfoData, 0, NULL, NULL, NULL)) 168 fDevInfoOkay = TRUE; 169 else 170 return ErrorMsgLastErr("SetupDiRegisterDeviceInfo"); /** @todo Original code didn't return here. */ 171 } 172 else 173 return ErrorMsgLastErr("SetupDiCreateDeviceInfoW"); /** @todo Original code didn't return here. */ 174 } 175 if (fDevInfoOkay) /** @todo if not needed if it's okay to fail on failure above */ 176 { 177 /* We created a new key in the registry */ /* bogus... */ 178 179 /* 180 * Redo the install parameter thing with deviceInfoData. 181 */ 182 SP_DEVINSTALL_PARAMS_W DeviceInstallParams = { sizeof(SP_DEVINSTALL_PARAMS) }; 183 if (!SetupDiGetDeviceInstallParamsW(hDevInfo, &deviceInfoData, &DeviceInstallParams)) 184 return ErrorMsgLastErr("SetupDiGetDeviceInstallParamsW(#2)"); /** @todo Original code didn't return here. */ 185 186 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 187 DeviceInstallParams.Flags |= DI_NOFILECOPY /* We did our own file copying */ 188 | DI_DONOTCALLCONFIGMG 189 | DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */ 190 rc = RTUtf16Copy(DeviceInstallParams.DriverPath, RT_ELEMENTS(DeviceInstallParams.DriverPath), pwszDriverDir); 191 if (RT_SUCCESS(rc)) 192 rc = RTUtf16CatAscii(DeviceInstallParams.DriverPath, RT_ELEMENTS(DeviceInstallParams.DriverPath), 193 VBOXGUEST_VIDEO_INF_NAME); 194 if (RT_FAILURE(rc)) 195 return ErrorMsg("Install dir too deep (long)"); 196 197 if (!SetupDiSetDeviceInstallParamsW(hDevInfo, &deviceInfoData, &DeviceInstallParams)) 198 return ErrorMsgLastErr("SetupDiSetDeviceInstallParamsW(#2)"); /** @todo Original code didn't return here. */ 199 200 if (!SetupDiBuildDriverInfoList(hDevInfo, &deviceInfoData, SPDIT_CLASSDRIVER)) 201 return ErrorMsgLastErr("SetupDiBuildDriverInfoList(#2)"); 202 203 /* 204 * Repeate the query at the start of the function. 205 */ 206 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); 207 if (!SetupDiEnumDriverInfoW(hDevInfo, &deviceInfoData, SPDIT_CLASSDRIVER, 0, &drvInfoData)) 208 return ErrorMsgLastErr("SetupDiEnumDriverInfoW(#2)"); 209 210 /* 211 * ... 212 */ 213 if (!SetupDiSetSelectedDriverW(hDevInfo, &deviceInfoData, &drvInfoData)) 214 return ErrorMsgLastErr("SetupDiSetSelectedDriverW(#2)"); 215 216 if (!SetupDiInstallDevice(hDevInfo, &deviceInfoData)) 217 return ErrorMsgLastErr("SetupDiInstallDevice(#2)"); 218 } 219 220 /* 221 * Make sure the device is enabled. 222 */ 223 DWORD fConfig = 0; 224 if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData, SPDRP_CONFIGFLAGS, 225 NULL, (LPBYTE)&fConfig, sizeof(DWORD), NULL)) 226 { 227 if (fConfig & CONFIGFLAG_DISABLED) 228 { 229 fConfig &= ~CONFIGFLAG_DISABLED; 230 if (!SetupDiSetDeviceRegistryPropertyW(hDevInfo, &deviceInfoData, SPDRP_CONFIGFLAGS, 231 (LPBYTE)&fConfig, sizeof(fConfig))) 232 ErrorMsg("SetupDiSetDeviceRegistryPropertyW"); 233 } 234 } 235 else 236 ErrorMsg("SetupDiGetDeviceRegistryPropertyW"); 237 238 /* 239 * Open the service key. 240 */ 241 WCHAR wszSvcRegKey[LINE_LEN + 64]; 242 rc = RTUtf16CopyAscii(wszSvcRegKey, RT_ELEMENTS(wszSvcRegKey), "System\\CurrentControlSet\\Services\\"); 243 if (RT_SUCCESS(rc)) 244 rc = RTUtf16Cat(wszSvcRegKey, RT_ELEMENTS(wszSvcRegKey), wszServiceData); 245 if (RT_SUCCESS(rc)) 246 rc = RTUtf16CatAscii(wszSvcRegKey, RT_ELEMENTS(wszSvcRegKey), "\\Device0"); /* We only have one device. */ 247 if (RT_FAILURE(rc)) 248 return ErrorMsg("Service key name too long"); 249 250 DWORD dwIgn; 251 HKEY hKey = NULL; 252 LSTATUS lrc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, wszSvcRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, 253 KEY_READ | KEY_WRITE, NULL, &hKey, &dwIgn); 254 if (lrc == ERROR_SUCCESS) 255 { 256 /* 257 * Insert service description. 258 */ 259 lrc = RegSetValueExW(hKey, L"Device Description", 0, REG_SZ, (LPBYTE)DriverInfoDetailData.s.DrvDescription, 260 (DWORD)((RTUtf16Len(DriverInfoDetailData.s.DrvDescription) + 1) * sizeof(WCHAR))); 261 if (lrc != ERROR_SUCCESS) 262 ErrorMsgLStatus("RegSetValueExW", lrc); 263 264 /* 265 * Execute the SoftwareSettings section of the INF-file or something like that. 266 */ 267 BOOL fOkay = FALSE; 268 WCHAR wszSoftwareSection[LINE_LEN + 32]; 269 rc = RTUtf16Copy(wszSoftwareSection, RT_ELEMENTS(wszSoftwareSection), wszServiceData); 270 if (RT_SUCCESS(rc)) 271 rc = RTUtf16CatAscii(wszSoftwareSection, RT_ELEMENTS(wszSoftwareSection), ".SoftwareSettings"); 272 if (RT_SUCCESS(rc)) 273 { 274 if (SetupInstallFromInfSectionW(NULL, hInf, wszSoftwareSection, SPINST_REGISTRY, hKey, 275 NULL, 0, NULL, NULL, NULL, NULL)) 276 fOkay = TRUE; 277 else 278 ErrorMsgLastErr("SetupInstallFromInfSectionW"); 279 } 280 else 281 ErrorMsg("Software settings section name too long"); 282 RegCloseKey(hKey); 283 if (!fOkay) 284 return RTEXITCODE_FAILURE; 285 } 286 else 287 ErrorMsgLStatus("RegCreateKeyExW/Service", lrc); 288 289 /* 290 * Install OpenGL stuff. 291 */ 292 lrc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers", 0, NULL, 293 REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwIgn); 294 if (lrc == ERROR_SUCCESS) 295 { 296 /* Do installation here if ever necessary. Currently there is no OpenGL stuff */ 297 RegCloseKey(hKey); 298 } 299 else 300 ErrorMsgLStatus("RegCreateKeyExW/OpenGLDrivers", lrc); 301 302 #if 0 303 /* If this key is inserted into the registry, windows will show the desktop 304 applet on next boot. We decide in the installer if we want that so the code 305 is disabled here. */ 306 lrc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay", 307 0, NULL, REG_OPTION_NON_VOLATILE, 308 KEY_READ | KEY_WRITE, NULL, &hHey, &dwIgn) 309 if (lrc == ERROR_SUCCESS) 310 RegCloseKey(hHey); 311 else 312 ErrorMsgLStatus("RegCreateKeyExW/NewDisplay", lrc); 313 #endif 314 315 /* 316 * We must reboot at some point 317 */ 318 lrc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary", 0, NULL, 319 REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwIgn); 320 if (lrc == ERROR_SUCCESS) 321 RegCloseKey(hKey); 322 else 323 ErrorMsgLStatus("RegCreateKeyExW/RebootNecessary", lrc); 324 325 return RTEXITCODE_SUCCESS; 326 } 327 59 328 60 329 … … 62 331 * Install the VBox video driver. 63 332 * 64 * @returns TRUE on success. 65 * @returns FALSE on failure. 66 * @param szDriverDir The base directory where we find the INF. 333 * @param pwszDriverDir The base directory where we find the INF. 67 334 */ 68 BOOL installVideoDriver(TCHAR* szDriverDir) 69 { 70 HDEVINFO hDevInfo; 71 SP_DEVINSTALL_PARAMS DeviceInstallParams={0}; 72 SP_DRVINFO_DATA drvInfoData={0}; 73 SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0}; 74 75 DWORD cbReqSize; 76 77 /* Vars used for reading the INF */ 78 HINF hInf; 79 TCHAR szServiceSection[LINE_LEN]; 80 INFCONTEXT serviceContext; 81 TCHAR szServiceData[LINE_LEN]; 82 TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody... 83 84 SP_DEVINFO_DATA deviceInfoData; 85 DWORD configFlags; 86 87 HKEY hkey; 88 DWORD disp; 89 TCHAR regKeyName[LINE_LEN]; 90 91 BOOL rc; 92 93 /* Create an empty list */ 94 hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY, 95 NULL); 96 97 if (hDevInfo == INVALID_HANDLE_VALUE) 98 return FALSE; 99 100 memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS)); 101 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 102 103 rc=SetupDiGetDeviceInstallParams(hDevInfo, 104 NULL, 105 &DeviceInstallParams); 106 107 if(!rc) 108 return FALSE; 109 110 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 111 DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */ 112 DI_DONOTCALLCONFIGMG | 113 DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */ 114 115 116 /* Path to inf file */ 117 wsprintf(DeviceInstallParams.DriverPath, 118 TEXT("%ws\\%ws"), 119 szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME)); 120 121 rc=SetupDiSetDeviceInstallParams(hDevInfo, 122 NULL, 123 &DeviceInstallParams); 124 if(!rc) 125 return FALSE; 126 127 /* Read the drivers from the inf file */ 128 if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER)) 129 { 130 SetupDiDestroyDeviceInfoList(hDevInfo); 131 return FALSE; 132 } 133 134 /* Get the first found driver. 135 Our Inf file only contains one so this is fine */ 136 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); 137 if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER, 138 0, &drvInfoData)){ 335 static RTEXITCODE InstallVideoDriver(WCHAR const * const pwszDriverDir) 336 { 337 /* 338 * Create an empty list 339 */ 340 HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_DISPLAY, NULL); 341 if (hDevInfo == INVALID_HANDLE_VALUE) 342 return ErrorMsgLastErr("SetupDiCreateDeviceInfoList"); 343 344 /* 345 * Get the default install parameters. 346 */ 347 RTEXITCODE rcExit = RTEXITCODE_FAILURE; 348 SP_DEVINSTALL_PARAMS_W DeviceInstallParams = { sizeof(SP_DEVINSTALL_PARAMS) }; 349 if (SetupDiGetDeviceInstallParamsW(hDevInfo, NULL, &DeviceInstallParams)) 350 { 351 /* 352 * Insert our install parameters and update hDevInfo with them. 353 */ 354 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 355 DeviceInstallParams.Flags |= DI_NOFILECOPY /* We did our own file copying */ 356 | DI_DONOTCALLCONFIGMG 357 | DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */ 358 int rc = RTUtf16Copy(DeviceInstallParams.DriverPath, RT_ELEMENTS(DeviceInstallParams.DriverPath), pwszDriverDir); 359 if (RT_SUCCESS(rc)) 360 rc = RTUtf16CatAscii(DeviceInstallParams.DriverPath, RT_ELEMENTS(DeviceInstallParams.DriverPath), 361 VBOXGUEST_VIDEO_INF_NAME); 362 if (RT_SUCCESS(rc)) 363 { 364 if (SetupDiSetDeviceInstallParamsW(hDevInfo, NULL, &DeviceInstallParams)) 365 { 366 /* 367 * Read the drivers from the INF-file. 368 */ 369 if (SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER)) 370 { 371 HINF hInf = NULL; 372 rcExit = InstallVideoDriverInner(pwszDriverDir, hDevInfo, &hInf); 373 374 if (hInf) 375 SetupCloseInfFile(hInf); 376 SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER); 377 } 378 else 379 ErrorMsgLastErr("SetupDiBuildDriverInfoList"); 380 } 381 else 382 ErrorMsgLastErr("SetupDiSetDeviceInstallParamsW"); 383 384 } 385 else 386 ErrorMsg("Install dir too deep (long)"); 387 SetupDiDestroyDeviceInfoList(hDevInfo); 388 } 389 else 390 ErrorMsgLastErr("SetupDiGetDeviceInstallParams"); /** @todo Original code didn't return here. */ 139 391 SetupDiDestroyDeviceInfoList(hDevInfo); 140 return FALSE; 141 } 142 143 /* Get necessary driver details */ 144 DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); 145 if (!(!SetupDiGetDriverInfoDetail(hDevInfo, 146 NULL, 147 &drvInfoData, 148 &DriverInfoDetailData, 149 DriverInfoDetailData.cbSize, 150 &cbReqSize) 151 &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) ) 152 { 153 SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER); 154 SetupDiDestroyDeviceInfoList(hDevInfo); 155 return FALSE; 156 } 157 158 hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName, 159 NULL, INF_STYLE_WIN4, NULL); 160 161 if (hInf == INVALID_HANDLE_VALUE) 162 { 163 SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER); 164 SetupDiDestroyDeviceInfoList(hDevInfo); 165 return FALSE; 166 } 167 168 /* First install the service */ 169 wsprintf(szServiceSection, TEXT("%ws.Services"), 170 DriverInfoDetailData.SectionName); 171 172 if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext)) 173 { 174 /* No service line?? Can't be... */ 175 closeAndDestroy(hDevInfo, hInf); 176 return FALSE; 177 } 178 179 /* Get the name */ 180 SetupGetStringField(&serviceContext, 181 1, 182 szServiceData, 183 sizeof(szServiceData), 184 NULL); 185 186 wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData); 187 188 memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA)); 189 deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 190 191 if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing 192 ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr, //Create new 193 (LPGUID) &GUID_DEVCLASS_DISPLAY, 194 NULL, //Do we need a description here? 195 NULL, //No user interface 196 0, 197 &deviceInfoData) && 198 SetupDiRegisterDeviceInfo(hDevInfo, 199 &deviceInfoData, 200 0, 201 NULL, 202 NULL, 203 NULL)) ) 204 { 205 /* We created a new key in the registry */ 206 207 memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS)); 208 DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 209 210 SetupDiGetDeviceInstallParams(hDevInfo, 211 &deviceInfoData, 212 &DeviceInstallParams); 213 214 DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files 215 DI_DONOTCALLCONFIGMG | 216 DI_ENUMSINGLEINF; //Use our INF file only 217 218 /* Path to inf file */ 219 wsprintf(DeviceInstallParams.DriverPath, 220 TEXT("%ws\\%ws"), 221 szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME)); 222 223 SetupDiSetDeviceInstallParams(hDevInfo, 224 &deviceInfoData, 225 &DeviceInstallParams); 226 227 228 if(!SetupDiBuildDriverInfoList(hDevInfo, 229 &deviceInfoData, 230 SPDIT_CLASSDRIVER)) 392 return rcExit; 393 } 394 395 396 /** 397 * Video driver uninstallation will be added later if necessary. 398 */ 399 static RTEXITCODE UninstallDrivers(void) 400 { 401 return ErrorMsg("Uninstall not implemented"); 402 } 403 404 405 static RTEXITCODE displayHelpAndExit(char *pszProgName) 406 { 407 HANDLE const hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 408 DWORD cbIgn; 409 WriteFile(hStdOut, RT_STR_TUPLE("Installs VirtualBox Guest Additions Graphics Drivers for Windows NT 4.0\r\n" 410 "\r\n" 411 "Syntax: "), &cbIgn, NULL); 412 WriteFile(hStdOut, pszProgName, (DWORD)strlen(pszProgName), &cbIgn, NULL); 413 WriteFile(hStdOut, RT_STR_TUPLE("</i|/u>\r\n" 414 "\r\n" 415 "Options:\r\n" 416 " /i - Install draphics drivers\r\n" 417 " /u - Uninstall draphics drivers (not implemented)\r\n" 418 ), &cbIgn, NULL); 419 return RTEXITCODE_SYNTAX; 420 } 421 422 423 static bool IsNt4(void) 424 { 425 OSVERSIONINFOW VerInfo = { sizeof(VerInfo), 0 }; 426 GetVersionExW(&VerInfo); 427 return VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT 428 && VerInfo.dwMajorVersion == 4; 429 } 430 431 432 int main(int argc, char **argv) 433 { 434 /* 435 * "Parse" arguments 436 */ 437 if (argc != 2) 438 { 439 if (argc > 2) 440 ErrorMsg("Too many parameter. Expected only one."); 441 return displayHelpAndExit(argv[0]); 442 } 443 444 bool fInstall = true; 445 const char *pszArg = argv[1]; 446 if (RTStrICmpAscii(pszArg, "/i") == 0) 447 fInstall = true; 448 else if (RTStrICmpAscii(pszArg, "/u") == 0) 449 fInstall = false; 450 else 451 { 452 ErrorMsg("Unknown parameter (only known parameters are '/i' and '/u')"); 453 ErrorMsg(pszArg); 454 return displayHelpAndExit(argv[0]); 455 } 456 457 /* 458 * This program is only for installing drivers on NT4. 459 */ 460 RTEXITCODE rcExit = RTEXITCODE_FAILURE; 461 if (IsNt4()) 462 { 463 /* 464 * Derive the installation directory from the executable location. 465 * Just strip the filename and use the path. 466 */ 467 WCHAR wszInstallDir[MAX_PATH]; 468 DWORD cwcInstallDir = GetModuleFileNameW(GetModuleHandle(NULL), &wszInstallDir[0], RT_ELEMENTS(wszInstallDir)); 469 if (cwcInstallDir > 0) 231 470 { 232 closeAndDestroy(hDevInfo, hInf); 233 return FALSE; 471 while (cwcInstallDir > 0 && RTPATH_IS_SEP(wszInstallDir[cwcInstallDir - 1])) 472 cwcInstallDir--; 473 if (!cwcInstallDir) /* paranoia^3 */ 474 { 475 wszInstallDir[cwcInstallDir++] = '.'; 476 wszInstallDir[cwcInstallDir++] = '\\'; 477 } 478 wszInstallDir[cwcInstallDir] = '\0'; 479 480 /* 481 * Do the install/uninstall. 482 */ 483 if (fInstall) 484 rcExit = InstallVideoDriver(wszInstallDir); 485 else 486 rcExit = UninstallDrivers(); 487 488 /* 489 * Summary message. 490 */ 491 if (rcExit != RTEXITCODE_SUCCESS) 492 ErrorMsg("Some failure occurred during driver installation"); 234 493 } 235 236 drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); 237 if (!SetupDiEnumDriverInfo(hDevInfo, 238 &deviceInfoData, 239 SPDIT_CLASSDRIVER, 240 0, 241 &drvInfoData)) 242 { 243 closeAndDestroy(hDevInfo, hInf); 244 return FALSE; 245 } 246 247 if(!SetupDiSetSelectedDriver(hDevInfo, 248 &deviceInfoData, 249 &drvInfoData)) 250 { 251 closeAndDestroy(hDevInfo, hInf); 252 return FALSE; 253 } 254 255 if(!SetupDiInstallDevice(hDevInfo, 256 &deviceInfoData)) 257 { 258 closeAndDestroy(hDevInfo, hInf); 259 return FALSE; 260 } 261 } 262 263 /* Make sure the device is enabled */ 264 if (SetupDiGetDeviceRegistryProperty(hDevInfo, 265 &deviceInfoData, SPDRP_CONFIGFLAGS, 266 NULL, (LPBYTE) &configFlags, 267 sizeof(DWORD), 268 NULL) 269 && (configFlags & CONFIGFLAG_DISABLED)) 270 { 271 configFlags &= ~CONFIGFLAG_DISABLED; 272 273 SetupDiSetDeviceRegistryProperty(hDevInfo, 274 &deviceInfoData, 275 SPDRP_CONFIGFLAGS, 276 (LPBYTE) &configFlags, 277 sizeof(DWORD)); 278 } 279 280 wsprintf(regKeyName, 281 TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"), 282 szServiceData, 0); //We only have one device 283 284 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, 285 regKeyName, 286 0, 287 NULL, 288 REG_OPTION_NON_VOLATILE, 289 KEY_READ | KEY_WRITE, 290 NULL, 291 &hkey, 292 &disp) == ERROR_SUCCESS) 293 { 294 /* Insert description */ 295 RegSetValueEx(hkey, 296 TEXT("Device Description"), 297 0, 298 REG_SZ, 299 (LPBYTE) DriverInfoDetailData.DrvDescription, 300 (lstrlen(DriverInfoDetailData.DrvDescription) + 1) * 301 sizeof(TCHAR) ); 302 303 TCHAR szSoftwareSection[LINE_LEN]; 304 305 wsprintf(szSoftwareSection, 306 TEXT("%ws.SoftwareSettings"), 307 szServiceData); 308 309 if (!SetupInstallFromInfSection(NULL, 310 hInf, 311 szSoftwareSection, 312 SPINST_REGISTRY, 313 hkey, 314 NULL, 315 0, 316 NULL, 317 NULL, 318 NULL, 319 NULL)) 320 { 321 RegCloseKey(hkey); 322 closeAndDestroy(hDevInfo, hInf); 323 return FALSE; 324 } 325 326 RegCloseKey(hkey); 327 } 328 329 /* Install OpenGL stuff */ 330 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, 331 TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"), 332 0, 333 NULL, 334 REG_OPTION_NON_VOLATILE, 335 KEY_READ | KEY_WRITE, 336 NULL, 337 &hkey, 338 &disp) == ERROR_SUCCESS) 339 { 340 /* Do installation here if ever necessary. Currently there is no OpenGL stuff */ 341 342 RegCloseKey(hkey); 343 } 344 345 346 /* Cleanup */ 347 closeAndDestroy(hDevInfo, hInf); 348 349 #if 0 350 /* If this key is inserted into the registry, windows will show the desktop 351 applet on next boot. We decide in the installer if we want that so the code 352 is disabled here. */ 353 /* Set registry keys so windows picks up the changes */ 354 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, 355 TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"), 356 0, 357 NULL, 358 REG_OPTION_NON_VOLATILE, 359 KEY_READ | KEY_WRITE, 360 NULL, 361 &hkey, 362 &disp) == ERROR_SUCCESS) 363 { 364 RegCloseKey(hkey); 365 } 366 #endif 367 368 /* We must reboot at some point */ 369 if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, 370 TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"), 371 0, 372 NULL, 373 REG_OPTION_NON_VOLATILE, 374 KEY_READ | KEY_WRITE, 375 NULL, 376 &hkey, 377 &disp) == ERROR_SUCCESS) 378 { 379 RegCloseKey(hkey); 380 } 381 382 return TRUE; 383 } 384 385 386 void displayHelpAndExit(char *programName) 387 { 388 printf("Installs VirtualBox Guest Additions for Windows NT 4.0\n\n"); 389 printf("Syntax: %s [/i|/u]\n", programName); 390 printf("\n\t/i - perform Guest Additions installation\n"); 391 printf("\t/u: - perform Guest Additions uninstallation\n"); 392 exit(1); 393 } 394 395 /** 396 * Check if we are running on NT4. 397 * 398 * @returns TRUE if NT 4. 399 * @returns FALSE otherwise. 400 */ 401 BOOL isNT4(void) 402 { 403 OSVERSIONINFO osVersion; 404 405 osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 406 GetVersionEx(&osVersion); 407 408 switch (osVersion.dwPlatformId) 409 { 410 case VER_PLATFORM_WIN32s: 411 case VER_PLATFORM_WIN32_WINDOWS: 412 return FALSE; 413 case VER_PLATFORM_WIN32_NT: 414 if (osVersion.dwMajorVersion == 4) 415 return TRUE; 416 else 417 return FALSE; 418 default: 419 break; 420 } 421 return FALSE; 422 } 423 424 /** 425 * Video driver uninstallation will be added later if necessary. 426 */ 427 int uninstallDrivers(void) 428 { 429 return 0; 430 } 431 432 433 int main(int argc, char **argv) 434 { 435 BOOL rc=FALSE; 436 TCHAR szInstallDir[MAX_PATH]; 437 HMODULE hExe = GetModuleHandle(NULL); 438 439 /** @todo r=bird: 440 * And by the way, we're only missing the coding style dmik uses now 441 * and this file would contain the complete set. */ 442 if(2!=argc || (stricmp(argv[1], "/i") && stricmp(argv[1], "/u"))) 443 displayHelpAndExit(argv[0]); 444 445 /* This program is only for installing drivers on NT4 */ 446 if(!isNT4()){ 447 printf("This program only runs on NT4\n"); 448 return -1; 449 } 450 451 if (!GetModuleFileName(hExe, &szInstallDir[0], sizeof(szInstallDir))) 452 { 453 printf("GetModuleFileName failed! rc=%lu\n", GetLastError()); 454 return -1; 455 } 456 457 TCHAR *lastBackslash = wcsrchr(szInstallDir, L'\\'); 458 459 if (!lastBackslash) 460 { 461 printf("Invalid path name!\n"); 462 return -1; 463 } 464 465 *lastBackslash=L'\0'; 466 467 /* Install video driver. Mouse driver installation is done by overwriting 468 the image path in the setup script. */ 469 if(!stricmp(argv[1], "/i")){ 470 rc=installVideoDriver(szInstallDir); 471 } 472 else{ 473 /* No video driver uninstallation yet. Do we need it? */ 474 } 475 476 if(FALSE==rc) 477 printf("Some failure occurred during driver installation.\n"); 478 return !rc; /* Return != 0 on failure. */ 479 } 494 else 495 ErrorMsgLastErr("GetModuleFileNameW failed!"); 496 } 497 else 498 ErrorMsg("This program only runs on NT4"); 499 return rcExit; 500 } 501
Note:
See TracChangeset
for help on using the changeset viewer.