Changeset 35649 in vbox
- Timestamp:
- Jan 20, 2011 1:45:52 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Installer/VBoxDrvInst.cpp
r34544 r35649 1 /*++ 2 3 Copyright (c) Microsoft Corporation. All rights reserved. 4 5 Module Name: 6 7 VBoxDrvInst.cpp 8 9 Abstract: 10 11 Command-line interface for installing / uninstalling device drivers 12 with a given Hardware-ID (and .INF-file). 13 14 --*/ 1 /* $Id$ */ 2 /** @file 3 * VBoxDrvInst - Driver and service installation helper for Windows guests. 4 */ 5 6 /* 7 * Copyright (C) 2011 Oracle Corporation 8 * 9 * This file is part of VirtualBox Open Source Edition (OSE), as 10 * available from http://www.virtualbox.org. This file is free software; 11 * you can redistribute it and/or modify it under the terms of the GNU 12 * General Public License (GPL) as published by the Free Software 13 * Foundation, in version 2 as it comes in the "COPYING" file of the 14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 */ 17 18 19 /******************************************************************************* 20 * Header Files * 21 *******************************************************************************/ 15 22 16 23 #ifndef UNICODE … … 22 29 #include <windows.h> 23 30 #include <setupapi.h> 24 #include <newdev.h>25 #include <regstr.h>26 #include <cfgmgr32.h>27 #include <devguid.h>28 31 #include <stdio.h> 29 32 #include <tchar.h> 30 #include <string.h> 31 32 /*#define _DEBUG*/ 33 34 typedef int (*fnCallback) (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context); 35 36 struct IdEntry 37 { 38 LPCTSTR szString; /* string looking for */ 39 LPCTSTR szWild; /* first wild character if any */ 40 BOOL bInstanceId; 41 }; 42 43 #define INSTANCEID_PREFIX_CHAR TEXT('@') /* character used to prefix instance ID's */ 44 #define CLASS_PREFIX_CHAR TEXT('=') /* character used to prefix class name */ 45 #define WILD_CHAR TEXT('*') /* wild character */ 46 #define QUOTE_PREFIX_CHAR TEXT('\'') /* prefix character to ignore wild characters */ 47 #define SPLIT_COMMAND_SEP TEXT(":=") /* whole word, indicates end of id's */ 48 49 /* @todo Split this program into several modules: 50 51 - Main 52 - Utility functions 53 - Dynamic API loading 54 - Installation / uninstallation routines 55 - ... 56 */ 33 34 /******************************************************************************* 35 * Defines * 36 *******************************************************************************/ 57 37 58 38 /* Exit codes */ … … 61 41 #define EXIT_FAIL (2) 62 42 #define EXIT_USAGE (3) 63 #ifdef VBOX_WITH_WDDM 64 #define EXIT_FALSE (4) 43 44 /* Prototypes */ 45 typedef struct { 46 PWSTR pApplicationId; 47 PWSTR pDisplayName; 48 PWSTR pProductName; 49 PWSTR pMfgName; 50 } INSTALLERINFO, *PINSTALLERINFO; 51 typedef const PINSTALLERINFO PCINSTALLERINFO; 52 53 typedef enum { 54 DIFXAPI_SUCCESS, 55 DIFXAPI_INFO, 56 DIFXAPI_WARNING, 57 DIFXAPI_ERROR 58 } DIFXAPI_LOG; 59 60 typedef void (WINAPI * DIFXLOGCALLBACK_W)( DIFXAPI_LOG Event, DWORD Error, PCWSTR EventDescription, PVOID CallbackContext); 61 typedef void ( __cdecl* DIFXAPILOGCALLBACK_W)( DIFXAPI_LOG Event, DWORD Error, PCWSTR EventDescription, PVOID CallbackContext); 62 63 typedef DWORD (WINAPI *fnDriverPackageInstall) (PCTSTR DriverPackageInfPath, DWORD Flags, PCINSTALLERINFO pInstallerInfo, BOOL *pNeedReboot); 64 fnDriverPackageInstall g_pfnDriverPackageInstall = NULL; 65 66 typedef DWORD (WINAPI *fnDriverPackageUninstall) (PCTSTR DriverPackageInfPath, DWORD Flags, PCINSTALLERINFO pInstallerInfo, BOOL *pNeedReboot); 67 fnDriverPackageUninstall g_pfnDriverPackageUninstall = NULL; 68 69 typedef VOID (WINAPI *fnDIFXAPISetLogCallback) (DIFXAPILOGCALLBACK_W LogCallback, PVOID CallbackContext); 70 fnDIFXAPISetLogCallback g_pfnDIFXAPISetLogCallback = NULL; 71 72 /* Defines */ 73 #define DRIVER_PACKAGE_REPAIR 0x00000001 74 #define DRIVER_PACKAGE_SILENT 0x00000002 75 #define DRIVER_PACKAGE_FORCE 0x00000004 76 #define DRIVER_PACKAGE_ONLY_IF_DEVICE_PRESENT 0x00000008 77 #define DRIVER_PACKAGE_LEGACY_MODE 0x00000010 78 #define DRIVER_PACKAGE_DELETE_FILES 0x00000020 79 80 /* DIFx error codes */ 81 #define ERROR_DEPENDENT_APPLICATIONS_EXIST \ 82 (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x300) 83 #define ERROR_DRIVER_STORE_ADD_FAILED \ 84 (APPLICATION_ERROR_MASK | ERROR_SEVERITY_ERROR | 0x0247L) 85 #define ERROR_DRIVER_PACKAGE_NOT_IN_STORE \ 86 (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x302) 87 88 /* Registry string list flags */ 89 #define VBOX_REG_STRINGLIST_NONE 0x00000000 /* No flags set. */ 90 #define VBOX_REG_STRINGLIST_ALLOW_DUPLICATES 0x00000001 /* Allows duplicates in list when adding a value. */ 91 92 #ifdef DEBUG 93 #define VBOX_DRVINST_LOGFILE "C:\\Temp\\VBoxDrvInstDIFx.log" 65 94 #endif 66 95 67 /* Dynamic loaded libs */ 68 HMODULE g_hSetupAPI = NULL; 69 HMODULE g_hNewDev = NULL; 70 HMODULE g_hCfgMgr = NULL; 71 72 /* Function pointers for dynamic loading of some API calls NT4 hasn't ... */ 73 typedef BOOL (WINAPI *fnSetupDiCreateDeviceInfo) (HDEVINFO DeviceInfoSet, PCTSTR DeviceName, LPGUID ClassGuid, PCTSTR DeviceDescription, HWND hwndParent, DWORD CreationFlags, 74 PSP_DEVINFO_DATA DeviceInfoData); 75 fnSetupDiCreateDeviceInfo g_pfnSetupDiCreateDeviceInfo = NULL; 76 77 typedef BOOL (WINAPI *fnSetupDiOpenDeviceInfo) (HDEVINFO DeviceInfoSet, PCTSTR DeviceInstanceId, HWND hwndParent, DWORD OpenFlags, PSP_DEVINFO_DATA DeviceInfoData); 78 fnSetupDiOpenDeviceInfo g_pfnSetupDiOpenDeviceInfo = NULL; 79 80 typedef BOOL (WINAPI *fnSetupDiEnumDeviceInfo) (HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData); 81 fnSetupDiEnumDeviceInfo g_pfnSetupDiEnumDeviceInfo = NULL; 82 83 /***/ 84 85 typedef HDEVINFO (WINAPI *fnSetupDiCreateDeviceInfoList) (LPGUID ClassGuid, HWND hwndParent); 86 fnSetupDiCreateDeviceInfoList g_pfnSetupDiCreateDeviceInfoList = NULL; 87 88 typedef HDEVINFO (WINAPI *fnSetupDiCreateDeviceInfoListEx) (LPGUID ClassGuid, HWND hwndParent, PCTSTR MachineName, PVOID Reserved); 89 fnSetupDiCreateDeviceInfoListEx g_pfnSetupDiCreateDeviceInfoListEx = NULL; 90 91 typedef BOOL (WINAPI *fnSetupDiDestroyDriverInfoList) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD DriverType); 92 fnSetupDiDestroyDriverInfoList g_pfnSetupDiDestroyDriverInfoList = NULL; 93 94 typedef BOOL (WINAPI *fnSetupDiDestroyDeviceInfoList) (HDEVINFO DeviceInfoSet); 95 fnSetupDiDestroyDeviceInfoList g_pfnSetupDiDestroyDeviceInfoList = NULL; 96 97 typedef BOOL (WINAPI *fnSetupDiGetDeviceInfoListDetail) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_LIST_DETAIL_DATA DeviceInfoSetDetailData); 98 fnSetupDiGetDeviceInfoListDetail g_pfnSetupDiGetDeviceInfoListDetail = NULL; 99 100 /***/ 101 102 typedef BOOL (WINAPI *fnSetupDiSetDeviceRegistryProperty) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, CONST BYTE *PropertyBuffer, DWORD PropertyBufferSize); 103 fnSetupDiSetDeviceRegistryProperty g_pfnSetupDiSetDeviceRegistryProperty = NULL; 104 105 typedef BOOL (WINAPI *fnSetupDiGetDeviceRegistryProperty) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, 106 DWORD PropertyBufferSize, PDWORD RequiredSize); 107 fnSetupDiGetDeviceRegistryProperty g_pfnSetupDiGetDeviceRegistryProperty = NULL; 108 109 /***/ 110 111 typedef BOOL (WINAPI *fnSetupDiCallClassInstaller) (DI_FUNCTION InstallFunction, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData); 112 fnSetupDiCallClassInstaller g_pfnSetupDiCallClassInstaller = NULL; 113 114 typedef BOOL (WINAPI *fnSetupDiClassGuidsFromNameEx) (PCTSTR ClassName, LPGUID ClassGuidList, DWORD ClassGuidListSize, PDWORD RequiredSize, PCTSTR MachineName, PVOID Reserved); 115 fnSetupDiClassGuidsFromNameEx g_pfnSetupDiClassGuidsFromNameEx = NULL; 116 117 typedef HDEVINFO (WINAPI *fnSetupDiGetClassDevsEx) (LPGUID ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags, HDEVINFO DeviceInfoSet, PCTSTR MachineName, PVOID Reserved); 118 fnSetupDiGetClassDevsEx g_pfnSetupDiGetClassDevsEx = NULL; 119 120 typedef BOOL (WINAPI *fnSetupDiSetClassInstallParams) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_CLASSINSTALL_HEADER ClassInstallParams, DWORD ClassInstallParamsSize); 121 fnSetupDiSetClassInstallParams g_pfnSetupDiSetClassInstallParams = NULL; 122 123 typedef BOOL (WINAPI *fnSetupDiGetDeviceInstallParams) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DEVINSTALL_PARAMS DeviceInstallParams); 124 fnSetupDiGetDeviceInstallParams g_pfnSetupDiGetDeviceInstallParams = NULL; 125 126 typedef HKEY (WINAPI *fnSetupDiOpenDevRegKey) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Scope, DWORD HwProfile, DWORD KeyType, REGSAM samDesired); 127 fnSetupDiOpenDevRegKey g_pfnSetupDiOpenDevRegKey = NULL; 128 129 typedef BOOL (WINAPI *fnSetupDiBuildDriverInfoList) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD DriverType); 130 fnSetupDiBuildDriverInfoList g_pfnSetupDiBuildDriverInfoList = NULL; 131 132 typedef BOOL (WINAPI *fnSetupDiEnumDriverInfo) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD DriverType, DWORD MemberIndex, PSP_DRVINFO_DATA DriverInfoData); 133 fnSetupDiEnumDriverInfo g_pfnSetupDiEnumDriverInfo = NULL; 134 135 typedef BOOL (WINAPI *fnSetupDiGetDriverInfoDetail) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA DriverInfoData, PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData, 136 DWORD DriverInfoDetailDataSize, PDWORD RequiredSize); 137 fnSetupDiGetDriverInfoDetail g_pfnSetupDiGetDriverInfoDetail = NULL; 138 139 typedef BOOL (WINAPI *fnSetupDiSetSelectedDriver) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DRVINFO_DATA DriverInfoData); 140 fnSetupDiSetSelectedDriver g_pfnSetupDiSetSelectedDriver = NULL; 141 142 typedef BOOL (WINAPI *fnSetupDiSetDeviceInstallParams) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PSP_DEVINSTALL_PARAMS DeviceInstallParams); 143 fnSetupDiSetDeviceInstallParams g_pfnSetupDiSetDeviceInstallParams = NULL; 144 145 typedef CONFIGRET (WINAPI *fnCM_Get_Device_ID_Ex) (DEVINST dnDevInst, PTCHAR Buffer, ULONG BufferLen, ULONG ulFlags, HMACHINE hMachine); 146 fnCM_Get_Device_ID_Ex g_pfnCM_Get_Device_ID_Ex = NULL; 147 148 typedef BOOL (WINAPI* fnSetupCopyOEMInf) (PCTSTR SourceInfFileName, PCTSTR OEMSourceMediaLocation, DWORD OEMSourceMediaType, DWORD CopyStyle, PTSTR DestinationInfFileName, 149 DWORD DestinationInfFileNameSize, PDWORD RequiredSize, PTSTR DestinationInfFileNameComponent); 150 fnSetupCopyOEMInf g_pfnSetupCopyOEMInf = NULL; 151 152 typedef BOOL (WINAPI* fnUpdateDriverForPlugAndPlayDevices) (HWND hwndParent, LPCTSTR HardwareId, LPCTSTR FullInfPath, DWORD InstallFlags, PBOOL bRebootRequired); 153 fnUpdateDriverForPlugAndPlayDevices g_pfnUpdateDriverForPlugAndPlayDevices = NULL; 154 155 #define VBOX_LOAD_API( a_hModule, a_Func ) \ 156 { \ 157 g_pfn##a_Func = (fn##a_Func)GetProcAddress(a_hModule, "##a_Func"); \ 158 _tprintf (_T("API call ##a_Func loaded: %p\n"), g_pfn##a_Func); \ 159 } 160 161 int LoadAPICalls () 162 { 163 int rc = ERROR_SUCCESS; 164 OSVERSIONINFO OSinfo; 165 OSinfo.dwOSVersionInfoSize = sizeof(OSinfo); 166 GetVersionEx(&OSinfo); 167 168 #ifdef _DEBUG 169 _tprintf (_T("Loading API calls ...\n")); 170 #endif 171 172 /* Use unicode calls where available. */ 173 if (OSinfo.dwMajorVersion >= 5) /* APIs available only on W2K and up! */ 174 { 175 g_hSetupAPI = LoadLibrary(_T("SetupAPI")); 176 if (NULL == g_hSetupAPI) 177 { 178 _tprintf(_T("ERROR: SetupAPI.dll not found! Return code: %d\n"), GetLastError()); 179 rc = ERROR_NOT_INSTALLED; 180 } 181 else 182 { 183 g_pfnSetupDiCreateDeviceInfoList = (fnSetupDiCreateDeviceInfoList)GetProcAddress(g_hSetupAPI, "SetupDiCreateDeviceInfoList"); 184 g_pfnSetupDiCreateDeviceInfo = (fnSetupDiCreateDeviceInfo)GetProcAddress(g_hSetupAPI, "SetupDiCreateDeviceInfoW"); 185 g_pfnSetupDiSetDeviceRegistryProperty = (fnSetupDiSetDeviceRegistryProperty)GetProcAddress(g_hSetupAPI, "SetupDiSetDeviceRegistryPropertyW"); 186 g_pfnSetupDiCallClassInstaller = (fnSetupDiCallClassInstaller)GetProcAddress(g_hSetupAPI, "SetupDiCallClassInstaller"); 187 g_pfnSetupDiDestroyDeviceInfoList = (fnSetupDiDestroyDeviceInfoList)GetProcAddress(g_hSetupAPI, "SetupDiDestroyDeviceInfoList"); 188 g_pfnSetupDiClassGuidsFromNameEx = (fnSetupDiClassGuidsFromNameEx)GetProcAddress(g_hSetupAPI, "SetupDiClassGuidsFromNameExW"); 189 g_pfnSetupDiGetDeviceRegistryProperty = (fnSetupDiGetDeviceRegistryProperty)GetProcAddress(g_hSetupAPI, "SetupDiGetDeviceRegistryPropertyW"); 190 g_pfnSetupDiGetClassDevsEx = (fnSetupDiGetClassDevsEx)GetProcAddress(g_hSetupAPI, "SetupDiGetClassDevsExW"); 191 g_pfnSetupDiCreateDeviceInfoListEx = (fnSetupDiCreateDeviceInfoListEx)GetProcAddress(g_hSetupAPI, "SetupDiCreateDeviceInfoListExW"); 192 g_pfnSetupDiOpenDeviceInfo = (fnSetupDiOpenDeviceInfo)GetProcAddress(g_hSetupAPI, "SetupDiOpenDeviceInfoW"); 193 g_pfnSetupDiGetDeviceInfoListDetail = (fnSetupDiGetDeviceInfoListDetail)GetProcAddress(g_hSetupAPI, "SetupDiGetDeviceInfoListDetailW"); 194 g_pfnSetupDiEnumDeviceInfo = (fnSetupDiEnumDeviceInfo)GetProcAddress(g_hSetupAPI, "SetupDiEnumDeviceInfo"); 195 g_pfnSetupDiSetClassInstallParams = (fnSetupDiSetClassInstallParams)GetProcAddress(g_hSetupAPI, "SetupDiSetClassInstallParamsW"); 196 g_pfnSetupDiGetDeviceInstallParams = (fnSetupDiGetDeviceInstallParams)GetProcAddress(g_hSetupAPI, "SetupDiGetDeviceInstallParamsW"); 197 g_pfnSetupDiOpenDevRegKey = (fnSetupDiOpenDevRegKey)GetProcAddress(g_hSetupAPI, "SetupDiOpenDevRegKey"); 198 g_pfnSetupDiBuildDriverInfoList = (fnSetupDiBuildDriverInfoList)GetProcAddress(g_hSetupAPI, "SetupDiBuildDriverInfoList"); 199 g_pfnSetupDiEnumDriverInfo = (fnSetupDiEnumDriverInfo)GetProcAddress(g_hSetupAPI, "SetupDiEnumDriverInfoW"); 200 g_pfnSetupDiGetDriverInfoDetail = (fnSetupDiGetDriverInfoDetail)GetProcAddress(g_hSetupAPI, "SetupDiGetDriverInfoDetailW"); 201 g_pfnSetupDiDestroyDriverInfoList = (fnSetupDiDestroyDriverInfoList)GetProcAddress(g_hSetupAPI, "SetupDiDestroyDriverInfoList"); 202 g_pfnSetupDiSetSelectedDriver = (fnSetupDiSetSelectedDriver)GetProcAddress(g_hSetupAPI, "SetupDiSetSelectedDriverW"); 203 g_pfnSetupDiSetDeviceInstallParams = (fnSetupDiSetDeviceInstallParams)GetProcAddress(g_hSetupAPI, "SetupDiSetDeviceInstallParamsW"); 204 g_pfnSetupCopyOEMInf = (fnSetupCopyOEMInf)GetProcAddress(g_hSetupAPI, "SetupCopyOEMInfW"); 205 } 206 207 if (rc == ERROR_SUCCESS) 208 { 209 g_hNewDev = LoadLibrary(_T("NewDev")); 210 if (NULL != g_hNewDev) 211 { 212 g_pfnUpdateDriverForPlugAndPlayDevices = (fnUpdateDriverForPlugAndPlayDevices)GetProcAddress(g_hNewDev, "UpdateDriverForPlugAndPlayDevicesW"); 213 } 214 else 215 { 216 _tprintf(_T("ERROR: NewDev.dll not found! Return code: %d\n"), GetLastError()); 217 rc = ERROR_FILE_NOT_FOUND; 218 } 219 } 220 221 if (rc == ERROR_SUCCESS) 222 { 223 g_hCfgMgr = LoadLibrary(_T("CfgMgr32")); 224 if (NULL != g_hCfgMgr) 225 { 226 g_pfnCM_Get_Device_ID_Ex = (fnCM_Get_Device_ID_Ex)GetProcAddress(g_hCfgMgr, "CM_Get_Device_ID_ExW"); 227 } 228 else 229 { 230 _tprintf(_T("ERROR: NewDev.dll not found! Return code: %d\n"), GetLastError()); 231 rc = ERROR_FILE_NOT_FOUND; 232 } 233 } 234 } 235 else if (OSinfo.dwMajorVersion <= 4) /* Windows NT 4.0. */ 236 { 237 /* Nothing to do here yet. */ 238 } 239 else /* Other platforms */ 240 { 241 _tprintf(_T("ERROR: Platform not supported yet!\n")); 242 rc = ERROR_NOT_SUPPORTED; 243 } 244 245 return rc; 246 } 247 248 void FreeAPICalls () 249 { 250 #ifdef _DEBUG 251 _tprintf (_T("Freeing API calls ...\n")); 252 #endif 253 254 if (NULL != g_hSetupAPI) 255 FreeLibrary(g_hSetupAPI); 256 257 if (NULL != g_hNewDev) 258 FreeLibrary(g_hNewDev); 259 260 if (NULL != g_hCfgMgr) 261 FreeLibrary(g_hCfgMgr); 262 } 263 264 bool GetErrorMsg (DWORD a_dwLastError, _TCHAR* a_pszMsg, DWORD a_dwBufSize) 265 { 266 if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, a_dwLastError, 0, a_pszMsg, a_dwBufSize / sizeof(TCHAR), NULL) == 0) 267 { 268 _stprintf(a_pszMsg, _T("Unknown error!\n"), a_dwLastError); 96 bool GetErrorMsg(DWORD dwLastError, _TCHAR *pszMsg, DWORD dwBufSize) 97 { 98 if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, pszMsg, dwBufSize / sizeof(TCHAR), NULL) == 0) 99 { 100 _stprintf(pszMsg, _T("Unknown error!\n"), dwLastError); 269 101 return false; 270 102 } 271 103 else 272 104 { 273 _TCHAR * p = _tcschr(a_pszMsg, _T('\r'));105 _TCHAR *p = _tcschr(pszMsg, _T('\r')); 274 106 275 107 if (p != NULL) … … 280 112 } 281 113 282 /* @todo Add exception handling instead of crappy goto's! */ 283 284 int CreateDevice (_TCHAR* a_pszHwID, GUID a_devClass) 285 { 286 int iRet = EXIT_OK; 287 HDEVINFO devInfoSet; 288 SP_DEVINFO_DATA devInfoData; 289 DWORD dwErr = 0; 290 _TCHAR szErrMsg[_MAX_PATH + 1] = { 0 }; 291 292 _tprintf(_T("Creating device ...\n")); 293 294 devInfoSet = g_pfnSetupDiCreateDeviceInfoList(&a_devClass, NULL); 295 if (devInfoSet == INVALID_HANDLE_VALUE) 296 { 297 _tprintf(_T("Could not build device info list!\n")); 298 return EXIT_FAIL; 299 } 300 301 devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 302 if (FALSE == g_pfnSetupDiCreateDeviceInfo(devInfoSet, a_pszHwID, &a_devClass, NULL, NULL, DICD_GENERATE_ID, &devInfoData)) 303 { 304 dwErr = GetLastError(); 305 306 switch (dwErr) 307 { 308 309 case ERROR_DEVINST_ALREADY_EXISTS: 310 311 _tprintf(_T("Device already exists.\n")); 312 break; 313 314 case ERROR_CLASS_MISMATCH: 315 316 _tprintf(_T("ERROR: Device does not match to class ID!\n")); 317 break; 318 319 case ERROR_INVALID_USER_BUFFER: 320 321 _tprintf(_T("ERROR: Invalid user buffer!\n")); 322 break; 323 324 case ERROR_INVALID_DEVINST_NAME: 325 326 _tprintf(_T("ERROR: Invalid device instance name!\n")); 327 break; 328 329 default: 330 331 GetErrorMsg(dwErr, szErrMsg, sizeof(szErrMsg)); 332 _tprintf(_T("ERROR (%08x): %ws\n"), dwErr, szErrMsg); 333 break; 334 } 335 336 iRet = EXIT_FAIL; 337 goto InstallCleanup; 338 } 339 340 if (FALSE == g_pfnSetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID, (LPBYTE)a_pszHwID, (DWORD)((_tcsclen(a_pszHwID) + 2) * sizeof(_TCHAR)))) 341 { 342 dwErr = GetLastError(); 343 _tprintf(_T("Could not set device registry info!\n")); 344 iRet = EXIT_FAIL; 345 goto InstallCleanup; 346 } 347 348 if (FALSE == g_pfnSetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData)) 349 { 350 dwErr = GetLastError(); 351 _tprintf(_T("Could not register device!\n")); 352 iRet = EXIT_FAIL; 353 goto InstallCleanup; 354 } 355 356 InstallCleanup: g_pfnSetupDiDestroyDeviceInfoList(devInfoSet); 357 358 return iRet; 359 } 360 361 int InstallDriver (_TCHAR* a_pszInfFile, _TCHAR* a_pszHwID, _TCHAR* a_pszDevClass) 362 { 363 int rc = EXIT_OK; /** @todo Use IPRT values! */ 364 365 DWORD dwErr = 0; 366 BOOL bReboot = FALSE; 367 368 _TCHAR szInf[_MAX_PATH] = { 0 }; /* Full path + .INF file */ 369 _TCHAR szInfPath[_MAX_PATH] = { 0 }; /* Full path to .INF file */ 370 GUID devClassArr[32]; /* The device class GUID array */ 371 DWORD dwReqSize = 0; /* Number of GUIDs in array after lookup */ 372 373 _tprintf(_T("Installing driver ...\n")); 374 _tprintf(_T("HardwareID: %ws\n"), a_pszHwID); 375 _tprintf(_T("Device class name: %ws\n"), a_pszDevClass); 376 377 /* Retrieve GUID of device class */ 378 /* Not used here: g_pfnSetupDiClassNameFromGuidEx( ... ) */ 379 if (FALSE == g_pfnSetupDiClassGuidsFromNameEx(a_pszDevClass, devClassArr, 32, &dwReqSize, NULL, NULL)) 380 { 381 _tprintf(_T("Could not retrieve device class GUID! Error: %ld\n"), GetLastError()); 382 rc = EXIT_FAIL; 383 } 114 /** 115 * Log callback for DIFxAPI calls. 116 * 117 * @param Event The event's structure to log. 118 * @param dwError The event's error level. 119 * @param pEventDescription The event's text description. 120 * @param pCallbackContext User-supplied callback context. 121 */ 122 void LogCallback(DIFXAPI_LOG Event, DWORD dwError, PCWSTR pEventDescription, PVOID pCallbackContext) 123 { 124 #ifdef DEBUG 125 if (dwError == 0) 126 _tprintf(_T("(%u) %ws\n"), Event, pEventDescription); 384 127 else 385 { 386 /* Do not fail if dwReqSize is 0. For whatever reason Windows Server 2008 Core does not have the "Media" 387 device class installed. Maybe they stripped down too much? :-/ */ 388 if (dwReqSize <= 0) 389 { 390 _tprintf(_T("WARNING: No device class with this name found! ReqSize: %ld, Error: %ld\n"), dwReqSize, GetLastError()); 128 _tprintf(_T("(%u) ERROR: %u - %ws\n"), Event, dwError, pEventDescription); 129 #else 130 if (dwError > 0) 131 _tprintf(_T("ERROR: (%u) %u - %ws\n"), Event, dwError, pEventDescription); 132 #endif 133 134 if (pCallbackContext) 135 fwprintf((FILE*)pCallbackContext, _T("(%u) %u - %s\n"), Event, dwError, pEventDescription); 136 } 137 138 /** 139 * (Un)Installs a driver from/to the system. 140 * 141 * @return Exit code (EXIT_OK, EXIT_FAIL) 142 * @param fInstall Flag indicating whether to install (TRUE) or uninstall (FALSE) a driver. 143 * @param pszDriverPath Full qualified path to the driver's .INF file (+ driver files). 144 * @param fSilent Flag indicating a silent installation (TRUE) or not (FALSE). 145 */ 146 int VBoxInstallDriver(const BOOL fInstall, const _TCHAR *pszDriverPath, BOOL fSilent) 147 { 148 HRESULT hr = ERROR_SUCCESS; 149 HMODULE hDIFxAPI = LoadLibrary(_T("DIFxAPI.dll")); 150 if (NULL == hDIFxAPI) 151 { 152 _tprintf(_T("ERROR: Unable to locate DIFxAPI.dll!\n")); 153 hr = ERROR_FILE_NOT_FOUND; 154 } 155 else 156 { 157 if (fInstall) 158 { 159 g_pfnDriverPackageInstall = (fnDriverPackageInstall)GetProcAddress(hDIFxAPI, "DriverPackageInstallW"); 160 if (g_pfnDriverPackageInstall == NULL) 161 { 162 _tprintf(_T("ERROR: Unable to retrieve entry point for DriverPackageInstallW!\n")); 163 hr = ERROR_PROC_NOT_FOUND; 164 } 391 165 } 392 166 else 393 167 { 394 _tprintf(_T("Number of GUIDs found: %ld\n"), dwReqSize); 395 } 396 397 /* Not needed for now! 398 if (EXIT_FAIL == CreateDevice (a_pszHwID, devClassArr[0])) 399 return EXIT_FAIL;*/ 400 } 401 402 if (rc == EXIT_OK) 403 { 404 _TCHAR* pcFile = NULL; 405 if (0 == GetFullPathName(a_pszInfFile, _MAX_PATH, szInf, &pcFile)) 406 { 407 dwErr = GetLastError(); 408 168 g_pfnDriverPackageUninstall = (fnDriverPackageUninstall)GetProcAddress(hDIFxAPI, "DriverPackageUninstallW"); 169 if (g_pfnDriverPackageUninstall == NULL) 170 { 171 _tprintf(_T("ERROR: Unable to retrieve entry point for DriverPackageUninstallW!\n")); 172 hr = ERROR_PROC_NOT_FOUND; 173 } 174 } 175 176 if (SUCCEEDED(hr)) 177 { 178 g_pfnDIFXAPISetLogCallback = (fnDIFXAPISetLogCallback)GetProcAddress(hDIFxAPI, "DIFXAPISetLogCallbackW"); 179 if (g_pfnDIFXAPISetLogCallback == NULL) 180 { 181 _tprintf(_T("ERROR: Unable to retrieve entry point for DIFXAPISetLogCallbackW!\n")); 182 hr = ERROR_PROC_NOT_FOUND; 183 } 184 } 185 } 186 187 if (SUCCEEDED(hr)) 188 { 189 FILE *fh = NULL; 190 #ifdef DEBUG 191 char szLogFile[MAX_PATH + 1]; 192 sprintf(szLogFile, VBOX_DRVINST_LOGFILE); 193 fh = fopen(szLogFile, "a"); 194 if (!fh) 195 _tprintf(_T("ERROR: Unable to create log file!\n")); 196 else 197 _tprintf(_T("Logging enabled ...\n")); 198 #endif 199 g_pfnDIFXAPISetLogCallback(LogCallback, fh); 200 201 INSTALLERINFO instInfo = 202 { 203 TEXT("{7d2c708d-c202-40ab-b3e8-de21da1dc629}"), /* Our GUID for representing this installation tool. */ 204 TEXT("VirtualBox Guest Additions Install Helper"), 205 TEXT("VirtualBox Guest Additions"), /** @todo Add version! */ 206 TEXT("Oracle Corporation") 207 }; 208 209 _TCHAR szDriverInf[MAX_PATH + 1]; 210 if (0 == GetFullPathNameW(pszDriverPath, MAX_PATH, szDriverInf, NULL)) 211 { 409 212 _tprintf(_T("ERROR: INF-Path too long / could not be retrieved!\n")); 410 rc = EXIT_FAIL;411 } 412 413 /* Extract path from path+INF */414 if (pcFile != NULL)415 _tcsnccpy(szInfPath, szInf, pcFile - szInf);416 417 _tprintf(_T("INF-File: %ws\n"), szInf);418 _tprintf(_T("INF-Path: %ws\n"), szInfPath);419 420 _tprintf(_T("Updating driver for plug'n play devices ...\n"));421 if (!g_pfnUpdateDriverForPlugAndPlayDevices(NULL, a_pszHwID, szInf, INSTALLFLAG_FORCE, &bReboot))422 {423 DWORD dwErr = GetLastError(); 424 _TCHAR szErrMsg[_MAX_PATH + 1] = { 0 };425 426 if (dwErr == ERROR_NO_SUCH_DEVINST)427 {428 _TCHAR szDestInf[_MAX_PATH] = { 0 };429 _tprintf(_T("The device is not plugged in (yet), pre-installing drivers ...\n"));430 431 if ( FALSE == g_pfnSetupCopyOEMInf(szInf, szInfPath, SPOST_PATH, 0, szDestInf, sizeof(szDestInf), NULL, NULL))213 hr = ERROR_INVALID_PARAMETER; 214 } 215 else 216 { 217 if (fInstall) 218 _tprintf(_T("Installing driver ...\n")); 219 else 220 _tprintf(_T("Uninstalling driver ...\n")); 221 _tprintf(_T("INF-File: %ws\n"), szDriverInf); 222 223 DWORD dwFlags = DRIVER_PACKAGE_FORCE; 224 if (!fInstall) 225 dwFlags |= DRIVER_PACKAGE_DELETE_FILES; 226 227 OSVERSIONINFO osi; 228 memset(&osi, 0, sizeof(OSVERSIONINFO)); 229 osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 230 if ( (GetVersionEx(&osi) != 0) 231 && (osi.dwPlatformId == VER_PLATFORM_WIN32_NT) 232 && (osi.dwMajorVersion < 6)) 233 { 234 if (fInstall) 432 235 { 433 dwErr = GetLastError(); 434 GetErrorMsg(dwErr, szErrMsg, sizeof(szErrMsg)); 435 _tprintf(_T("ERROR (%08x): %ws\n"), dwErr, szErrMsg); 436 437 rc = EXIT_FAIL; 236 _tprintf(_T("Using legacy mode for install ...\n")); 237 dwFlags |= DRIVER_PACKAGE_LEGACY_MODE; 438 238 } 439 else 440 _tprintf(_T("OK. Installed to: %ws\n"), szDestInf); 441 } 442 else 443 { 444 switch (dwErr) 239 } 240 241 if (fSilent) 242 { 243 _tprintf(_T("Installation is silent ...\n")); 244 dwFlags |= DRIVER_PACKAGE_SILENT; 245 } 246 247 BOOL fReboot; 248 DWORD dwRet = fInstall ? 249 g_pfnDriverPackageInstall(szDriverInf, dwFlags, &instInfo, &fReboot) 250 : g_pfnDriverPackageUninstall(szDriverInf, dwFlags, &instInfo, &fReboot); 251 if (dwRet != ERROR_SUCCESS) 252 { 253 switch (dwRet) 445 254 { 446 447 case ERROR_INVALID_FLAGS: 448 449 _tprintf(_T("ERROR: The value specified for InstallFlags is invalid!\n")); 255 case CRYPT_E_FILE_ERROR: 256 _tprintf(_T("ERROR: The catalog file for the specified driver package was not found!\n")); 257 break; 258 259 case ERROR_ACCESS_DENIED: 260 _tprintf(_T("ERROR: Caller is not in Administrators group to (un)install this driver package!\n")); 261 break; 262 263 case ERROR_BAD_ENVIRONMENT: 264 _tprintf(_T("ERROR: The current Microsoft Windows version does not support this operation!\n")); 265 break; 266 267 case ERROR_CANT_ACCESS_FILE: 268 _tprintf(_T("ERROR: The driver package files could not be accessed!\n")); 269 break; 270 271 case ERROR_DEPENDENT_APPLICATIONS_EXIST: 272 _tprintf(_T("ERROR: DriverPackageUninstall removed an association between the driver package and the specified application but the function did not uninstall the driver package because other applications are associated with the driver package!\n")); 273 break; 274 275 case ERROR_DRIVER_PACKAGE_NOT_IN_STORE: 276 _tprintf(_T("ERROR: There is no INF file in the DIFx driver store that corresponds to the INF file %ws!\n"), szDriverInf); 277 break; 278 279 case ERROR_FILE_NOT_FOUND: 280 _tprintf(_T("ERROR: File not found! File = %ws\n"), szDriverInf); 281 break; 282 283 case ERROR_IN_WOW64: 284 _tprintf(_T("ERROR: The calling application is a 32-bit application attempting to execute in a 64-bit environment, which is not allowed!\n")); 285 break; 286 287 case ERROR_INVALID_FLAGS: 288 _tprintf(_T("ERROR: The flags specified are invalid!\n")); 289 break; 290 291 case ERROR_INSTALL_FAILURE: 292 _tprintf(_T("ERROR: The (un)install operation failed! Consult the Setup API logs for more information.\n")); 293 break; 294 295 case ERROR_NO_MORE_ITEMS: 296 _tprintf( 297 _T( 298 "ERROR: The function found a match for the HardwareId value, but the specified driver was not a better match than the current driver and the caller did not specify the INSTALLFLAG_FORCE flag!\n")); 299 break; 300 301 case ERROR_NO_DRIVER_SELECTED: 302 _tprintf(_T("ERROR: No driver in .INF-file selected!\n")); 303 break; 304 305 case ERROR_SECTION_NOT_FOUND: 306 _tprintf(_T("ERROR: Section in .INF-file was not found!\n")); 307 break; 308 309 case ERROR_SHARING_VIOLATION: 310 _tprintf(_T("ERROR: A component of the driver package in the DIFx driver store is locked by a thread or process\n")); 450 311 break; 451 312 452 case ERROR_NO_MORE_ITEMS: 453 454 _tprintf( 455 _T( 456 "ERROR: The function found a match for the HardwareId value, but the specified driver was not a better match than the current driver and the caller did not specify the INSTALLFLAG_FORCE flag!\n")); 313 /* 314 * ! sig: Verifying file against specific Authenticode(tm) catalog failed! (0x800b0109) 315 * ! sig: Error 0x800b0109: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider. 316 * !!! sto: No error message will be displayed as client is running in non-interactive mode. 317 * !!! ndv: Driver package failed signature validation. Error = 0xE0000247 318 */ 319 case ERROR_DRIVER_STORE_ADD_FAILED: 320 _tprintf(_T("ERROR: Adding driver to the driver store failed!!\n")); 321 break; 322 323 case ERROR_UNSUPPORTED_TYPE: 324 _tprintf(_T("ERROR: The driver package type is not supported of INF %ws!\n"), szDriverInf); 457 325 break; 458 326 459 case ERROR_FILE_NOT_FOUND: 460 461 _tprintf(_T("ERROR: File not found! File = %ws\n"), szInf); 462 break; 463 464 case ERROR_IN_WOW64: 465 466 _tprintf(_T("ERROR: The calling application is a 32-bit application attempting to execute in a 64-bit environment, which is not allowed!")); 467 break; 468 469 case ERROR_NO_DRIVER_SELECTED: 470 471 _tprintf(_T("ERROR: No driver in .INF-file selected!\n")); 472 break; 473 474 case ERROR_SECTION_NOT_FOUND: 475 476 _tprintf(_T("ERROR: Section in .INF-file was not found!\n")); 477 break; 478 479 default: 480 481 /* Try error lookup with GetErrorMsg() */ 482 GetErrorMsg(dwErr, szErrMsg, sizeof(szErrMsg)); 483 _tprintf(_T("ERROR (%08x): %ws\n"), dwErr, szErrMsg); 484 break; 485 } 486 487 rc = EXIT_FAIL; 488 } 489 } 490 } 491 492 if (rc == EXIT_OK) 493 _tprintf(_T("Installation successful.\n")); 494 return rc; 495 } 496 497 /*++ 498 499 Routine Description: 500 501 Determine if this is instance id or hardware id and if there's any wildcards 502 instance ID is prefixed by '@' 503 wildcards are '*' 504 505 506 Arguments: 507 508 Id - ptr to string to check 509 510 Return Value: 511 512 IdEntry 513 514 --*/ 515 IdEntry GetIdType (LPCTSTR Id) 516 { 517 IdEntry Entry; 518 519 Entry.bInstanceId = FALSE; 520 Entry.szWild = NULL; 521 Entry.szString = Id; 522 523 if (Entry.szString[0] == INSTANCEID_PREFIX_CHAR) 524 { 525 Entry.bInstanceId = TRUE; 526 Entry.szString = CharNext(Entry.szString); 527 } 528 if (Entry.szString[0] == QUOTE_PREFIX_CHAR) 529 { 530 /* prefix to treat rest of string literally */ 531 Entry.szString = CharNext(Entry.szString); 532 } 533 else 534 { 535 /* see if any wild characters exist */ 536 Entry.szWild = _tcschr(Entry.szString, WILD_CHAR); 537 } 538 return Entry; 539 } 540 541 /*++ 542 543 Routine Description: 544 545 Get an index array pointing to the MultiSz passed in 546 547 Arguments: 548 549 MultiSz - well formed multi-sz string 550 551 Return Value: 552 553 array of strings. last entry+1 of array contains NULL 554 returns NULL on failure 555 556 --*/ 557 LPTSTR * GetMultiSzIndexArray (LPTSTR MultiSz) 558 { 559 LPTSTR scan; 560 LPTSTR * array; 561 int elements; 562 563 for (scan = MultiSz, elements = 0; scan[0]; elements++) 564 { 565 scan += lstrlen(scan) + 1; 566 } 567 array = new LPTSTR[elements + 2]; 568 if (!array) 569 { 570 return NULL; 571 } 572 array[0] = MultiSz; 573 array++; 574 if (elements) 575 { 576 for (scan = MultiSz, elements = 0; scan[0]; elements++) 577 { 578 array[elements] = scan; 579 scan += lstrlen(scan) + 1; 580 } 581 } 582 array[elements] = NULL; 583 return array; 584 } 585 586 /*++ 587 588 Routine Description: 589 590 Deletes the string array allocated by GetDevMultiSz/GetRegMultiSz/GetMultiSzIndexArray 591 592 Arguments: 593 594 Array - pointer returned by GetMultiSzIndexArray 595 596 Return Value: 597 598 None 599 600 --*/ 601 void DelMultiSz (LPTSTR * Array) 602 { 603 if (Array) 604 { 605 Array--; 606 if (Array[0]) 607 { 608 delete[] Array[0]; 609 } 610 delete[] Array; 611 } 612 } 613 614 /*++ 615 616 Routine Description: 617 618 Get a multi-sz device property 619 and return as an array of strings 620 621 Arguments: 622 623 Devs - HDEVINFO containing DevInfo 624 DevInfo - Specific device 625 Prop - SPDRP_HARDWAREID or SPDRP_COMPATIBLEIDS 626 627 Return Value: 628 629 array of strings. last entry+1 of array contains NULL 630 returns NULL on failure 631 632 --*/ 633 LPTSTR * GetDevMultiSz (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Prop) 634 { 635 LPTSTR buffer; 636 DWORD size; 637 DWORD reqSize; 638 DWORD dataType; 639 LPTSTR * array; 640 DWORD szChars; 641 642 size = 8192; /* initial guess, nothing magic about this */ 643 buffer = new TCHAR[(size / sizeof(TCHAR)) + 2]; 644 if (!buffer) 645 { 646 return NULL; 647 } 648 while (!g_pfnSetupDiGetDeviceRegistryProperty(Devs, DevInfo, Prop, &dataType, (LPBYTE)buffer, size, &reqSize)) 649 { 650 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 651 { 652 goto failed; 653 } 654 if (dataType != REG_MULTI_SZ) 655 { 656 goto failed; 657 } 658 size = reqSize; 659 delete[] buffer; 660 buffer = new TCHAR[(size / sizeof(TCHAR)) + 2]; 661 if (!buffer) 662 { 663 goto failed; 664 } 665 } 666 szChars = reqSize / sizeof(TCHAR); 667 buffer[szChars] = TEXT('\0'); 668 buffer[szChars + 1] = TEXT('\0'); 669 array = GetMultiSzIndexArray(buffer); 670 if (array) 671 { 672 return array; 673 } 674 675 failed: if (buffer) 676 { 677 delete[] buffer; 678 } 679 return NULL; 680 } 681 682 /*++ 683 684 Routine Description: 685 686 Compare a single item against wildcard 687 I'm sure there's better ways of implementing this 688 Other than a command-line management tools 689 it's a bad idea to use wildcards as it implies 690 assumptions about the hardware/instance ID 691 eg, it might be tempting to enumerate root\* to 692 find all root devices, however there is a CfgMgr 693 API to query status and determine if a device is 694 root enumerated, which doesn't rely on implementation 695 details. 696 697 Arguments: 698 699 Item - item to find match for eg a\abcd\c 700 MatchEntry - eg *\*bc*\* 701 702 Return Value: 703 704 TRUE if any match, otherwise FALSE 705 706 --*/ 707 BOOL WildCardMatch (LPCTSTR Item, const IdEntry & MatchEntry) 708 { 709 LPCTSTR scanItem; 710 LPCTSTR wildMark; 711 LPCTSTR nextWild; 712 size_t matchlen; 713 714 /* Before attempting anything else, 715 try and compare everything up to first wild */ 716 // 717 if (!MatchEntry.szWild) 718 { 719 return _tcsicmp(Item, MatchEntry.szString) ? FALSE : TRUE; 720 } 721 if (_tcsnicmp(Item, MatchEntry.szString, MatchEntry.szWild - MatchEntry.szString) != 0) 722 { 723 return FALSE; 724 } 725 wildMark = MatchEntry.szWild; 726 scanItem = Item + (MatchEntry.szWild - MatchEntry.szString); 727 728 for (; wildMark[0];) 729 { 730 /* If we get here, we're either at or past a wildcard */ 731 if (wildMark[0] == WILD_CHAR) 732 { 733 /* So skip wild chars */ 734 wildMark = CharNext(wildMark); 735 continue; 736 } 737 738 /* Find next wild-card */ 739 nextWild = _tcschr(wildMark, WILD_CHAR); 740 741 if (nextWild) 742 { 743 /* Substring */ 744 matchlen = nextWild - wildMark; 745 } 746 else 747 { 748 /* Last portion of match */ 749 size_t scanlen = lstrlen(scanItem); 750 matchlen = lstrlen(wildMark); 751 752 if (scanlen < matchlen) 753 { 754 return FALSE; 755 } 756 757 return _tcsicmp(scanItem + scanlen - matchlen, wildMark) ? FALSE : TRUE; 758 } 759 760 if (_istalpha(wildMark[0])) 761 { 762 /* Scan for either lower or uppercase version of first character */ 763 TCHAR u = _totupper(wildMark[0]); 764 TCHAR l = _totlower(wildMark[0]); 765 while (scanItem[0] && scanItem[0] != u && scanItem[0] != l) 766 { 767 scanItem = CharNext(scanItem); 768 } 769 770 if (!scanItem[0]) 771 { 772 /* Ran out of string */ 773 return FALSE; 774 } 775 } 776 else 777 { 778 /* Scan for first character (no case) */ 779 scanItem = _tcschr(scanItem, wildMark[0]); 780 if (!scanItem) 781 { 782 /* Ran out of string */ 783 return FALSE; 784 } 785 } 786 787 /* Try and match the sub-string at wildMark against scanItem */ 788 if (_tcsnicmp(scanItem, wildMark, matchlen) != 0) 789 { 790 /* Nope, try again */ 791 scanItem = CharNext(scanItem); 792 continue; 793 } 794 795 /* Substring matched */ 796 scanItem += matchlen; 797 wildMark += matchlen; 798 } 799 return (wildMark[0] ? FALSE : TRUE); 800 } 801 802 /*++ 803 804 Routine Description: 805 806 Compares all strings in Array against Id 807 Use WildCardMatch to do real compare 808 809 Arguments: 810 811 Array - pointer returned by GetDevMultiSz 812 MatchEntry - string to compare against 813 814 Return Value: 815 816 TRUE if any match, otherwise FALSE 817 818 --*/ 819 BOOL WildCompareHwIds (LPTSTR * Array, const IdEntry & MatchEntry) 820 { 821 if (Array) 822 { 823 while (Array[0]) 824 { 825 if (WildCardMatch(Array[0], MatchEntry)) 826 { 827 return TRUE; 828 } 829 Array++; 830 } 831 } 832 return FALSE; 833 } 834 835 /*++ 836 837 Routine Description: 838 839 Generic enumerator for devices that will be passed the following arguments: 840 <id> [<id>...] 841 =<class> [<id>...] 842 where <id> can either be @instance-id, or hardware-id and may contain wildcards 843 <class> is a class name 844 845 Arguments: 846 847 BaseName - name of executable 848 Machine - name of machine to enumerate 849 Flags - extra enumeration flags (eg DIGCF_PRESENT) 850 argc/argv - remaining arguments on command line 851 Callback - function to call for each hit 852 Context - data to pass function for each hit 853 854 Return Value: 855 856 EXIT_xxxx 857 858 --*/ 859 int EnumerateDevices (LPCTSTR BaseName, LPCTSTR Machine, DWORD Flags, int argc, LPTSTR argv[], fnCallback Callback, LPVOID Context) 860 { 861 HDEVINFO devs = INVALID_HANDLE_VALUE; 862 IdEntry * templ = NULL; 863 int failcode = EXIT_FAIL; 864 int retcode; 865 int argIndex; 866 DWORD devIndex; 867 SP_DEVINFO_DATA devInfo; 868 SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; 869 BOOL doSearch = FALSE; 870 BOOL match; 871 BOOL all = FALSE; 872 GUID cls; 873 DWORD numClass = 0; 874 int skip = 0; 875 876 if (!argc) 877 { 878 return EXIT_USAGE; 879 } 880 881 templ = new IdEntry[argc]; 882 if (!templ) 883 { 884 goto final; 885 } 886 887 /* Determine if a class is specified */ 888 if (argc > skip && argv[skip][0] == CLASS_PREFIX_CHAR && argv[skip][1]) 889 { 890 if (!g_pfnSetupDiClassGuidsFromNameEx(argv[skip] + 1, &cls, 1, &numClass, Machine, NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 891 { 892 goto final; 893 } 894 if (!numClass) 895 { 896 failcode = EXIT_OK; 897 goto final; 898 } 899 skip++; 900 } 901 902 if (argc > skip && argv[skip][0] == WILD_CHAR && !argv[skip][1]) 903 { 904 /* Catch convenient case of specifying a single argument '*' */ 905 all = TRUE; 906 skip++; 907 } 908 else if (argc <= skip) 909 { 910 /* At least one parameter, but no <id>'s */ 911 all = TRUE; 912 } 913 914 /* Determine if any instance id's were specified */ 915 916 /* Note, if =<class> was specified with no id's 917 we'll mark it as not doSearch 918 but will go ahead and add them all */ 919 for (argIndex = skip; argIndex < argc; argIndex++) 920 { 921 templ[argIndex] = GetIdType(argv[argIndex]); 922 if (templ[argIndex].szWild || !templ[argIndex].bInstanceId) 923 { 924 /* Anything other than simple bInstanceId's require a search */ 925 doSearch = TRUE; 926 } 927 } 928 if (doSearch || all) 929 { 930 /* Add all id's to list 931 If there's a class, filter on specified class */ 932 devs = g_pfnSetupDiGetClassDevsEx(numClass ? &cls : NULL, NULL, NULL, (numClass ? 0 : DIGCF_ALLCLASSES) | Flags, NULL, Machine, NULL); 933 934 } 935 else 936 { 937 /* Blank list, we'll add instance id's by hand */ 938 devs = g_pfnSetupDiCreateDeviceInfoListEx(numClass ? &cls : NULL, NULL, Machine, NULL); 939 } 940 if (devs == INVALID_HANDLE_VALUE) 941 { 942 goto final; 943 } 944 for (argIndex = skip; argIndex < argc; argIndex++) 945 { 946 /* Add explicit instances to list (even if enumerated all, 947 this gets around DIGCF_PRESENT) 948 do this even if wildcards appear to be detected since they 949 might actually be part of the instance ID of a non-present device */ 950 if (templ[argIndex].bInstanceId) 951 { 952 g_pfnSetupDiOpenDeviceInfo(devs, templ[argIndex].szString, NULL, 0, NULL); 953 } 954 } 955 956 devInfoListDetail.cbSize = sizeof(devInfoListDetail); 957 if (!g_pfnSetupDiGetDeviceInfoListDetail(devs, &devInfoListDetail)) 958 { 959 goto final; 960 } 961 962 /* Now enumerate them */ 963 if (all) 964 { 965 doSearch = FALSE; 966 } 967 968 devInfo.cbSize = sizeof(devInfo); 969 for (devIndex = 0; g_pfnSetupDiEnumDeviceInfo(devs, devIndex, &devInfo); devIndex++) 970 { 971 972 if (doSearch) 973 { 974 for (argIndex = skip, match = FALSE; (argIndex < argc) && !match; argIndex++) 975 { 976 TCHAR devID[MAX_DEVICE_ID_LEN]; 977 LPTSTR *hwIds = NULL; 978 LPTSTR *compatIds = NULL; 979 980 /* Determine instance ID */ 981 if (g_pfnCM_Get_Device_ID_Ex(devInfo.DevInst, devID, MAX_DEVICE_ID_LEN, 0, devInfoListDetail.RemoteMachineHandle) != CR_SUCCESS) 982 { 983 devID[0] = TEXT('\0'); 984 } 985 986 if (templ[argIndex].bInstanceId) 987 { 988 /* Match on the instance ID */ 989 if (WildCardMatch(devID, templ[argIndex])) 990 match = TRUE; 991 992 } 993 else 994 { 995 /* Determine hardware ID's and search for matches */ 996 hwIds = GetDevMultiSz(devs, &devInfo, SPDRP_HARDWAREID); 997 compatIds = GetDevMultiSz(devs, &devInfo, SPDRP_COMPATIBLEIDS); 998 999 if (WildCompareHwIds(hwIds, templ[argIndex]) || WildCompareHwIds(compatIds, templ[argIndex])) 327 default: 1000 328 { 1001 match = TRUE; 329 /* Try error lookup with GetErrorMsg(). */ 330 TCHAR szErrMsg[1024]; 331 GetErrorMsg(dwRet, szErrMsg, sizeof(szErrMsg)); 332 _tprintf(_T("ERROR (%08x): %ws\n"), dwRet, szErrMsg); 333 break; 1002 334 } 1003 335 } 1004 DelMultiSz(hwIds); 1005 DelMultiSz(compatIds); 1006 } 1007 } 1008 else 1009 { 1010 match = TRUE; 1011 } 1012 if (match) 1013 { 1014 retcode = Callback(devs, &devInfo, devIndex, Context); 1015 if (retcode) 1016 { 1017 failcode = retcode; 1018 goto final; 1019 } 1020 } 1021 } 1022 1023 failcode = EXIT_OK; 1024 1025 final: if (templ) 1026 { 1027 delete[] templ; 1028 } 1029 if (devs != INVALID_HANDLE_VALUE) 1030 { 1031 g_pfnSetupDiDestroyDeviceInfoList(devs); 1032 } 1033 return failcode; 1034 1035 } 1036 1037 /*++ 1038 1039 Routine Description: 1040 1041 Callback for use by Remove 1042 Invokes DIF_REMOVE 1043 uses g_pfnSetupDiCallClassInstaller so cannot be done for remote devices 1044 Don't use CM_xxx API's, they bypass class/co-installers and this is bad. 1045 1046 Arguments: 1047 1048 Devs )_ uniquely identify the device 1049 DevInfo ) 1050 Index - index of device 1051 Context - GenericContext 1052 1053 Return Value: 1054 1055 EXIT_xxxx 1056 1057 --*/ 1058 int UninstallCallback (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context) 1059 { 1060 SP_REMOVEDEVICE_PARAMS rmdParams; 1061 SP_DEVINSTALL_PARAMS devParams; 1062 LPCTSTR action = NULL; 1063 1064 /* Need hardware ID before trying to remove, as we wont have it after */ 1065 TCHAR devID[MAX_DEVICE_ID_LEN]; 1066 SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; 1067 1068 devInfoListDetail.cbSize = sizeof(devInfoListDetail); 1069 1070 if ((!g_pfnSetupDiGetDeviceInfoListDetail(Devs, &devInfoListDetail)) || (g_pfnCM_Get_Device_ID_Ex(DevInfo->DevInst, devID, MAX_DEVICE_ID_LEN, 0, devInfoListDetail.RemoteMachineHandle) 1071 != CR_SUCCESS)) 1072 { 1073 /* Skip this */ 1074 return EXIT_OK; 1075 } 1076 1077 rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); 1078 rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE; 1079 rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL; 1080 rmdParams.HwProfile = 0; 1081 1082 if (!g_pfnSetupDiSetClassInstallParams(Devs, DevInfo, &rmdParams.ClassInstallHeader, sizeof(rmdParams)) || !g_pfnSetupDiCallClassInstaller(DIF_REMOVE, Devs, DevInfo)) 1083 { 1084 /* Failed to invoke DIF_REMOVE, TODO! */ 1085 _tprintf(_T("Failed to invoke interface!\n")); 1086 return EXIT_FAIL; 1087 } 1088 1089 /* See if device needs reboot */ 1090 devParams.cbSize = sizeof(devParams); 1091 if (g_pfnSetupDiGetDeviceInstallParams(Devs, DevInfo, &devParams) && (devParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))) 1092 { 1093 /* Reboot required */ 1094 _tprintf(_T("To fully uninstall, a reboot is required!\n")); 1095 } 1096 else 1097 { 1098 /* Appears to have succeeded */ 1099 _tprintf(_T("Uninstall succeeded!\n")); 1100 } 1101 1102 return EXIT_OK; 1103 } 1104 1105 /*++ 1106 1107 Routine Description: 1108 1109 Find the driver that is associated with the current device 1110 We can do this either the quick way (available in WinXP) 1111 or the long way that works in Win2k. 1112 1113 Arguments: 1114 1115 Devs )_ uniquely identify device 1116 DevInfo ) 1117 1118 Return Value: 1119 1120 TRUE if we managed to determine and select current driver 1121 1122 --*/ 1123 BOOL FindCurrentDriver (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, PSP_DRVINFO_DATA DriverInfoData) 1124 { 1125 SP_DEVINSTALL_PARAMS deviceInstallParams; 1126 WCHAR SectionName[LINE_LEN]; 1127 WCHAR DrvDescription[LINE_LEN]; 1128 WCHAR MfgName[LINE_LEN]; 1129 WCHAR ProviderName[LINE_LEN]; 1130 HKEY hKey = NULL; 1131 DWORD RegDataLength; 1132 DWORD RegDataType; 1133 DWORD c; 1134 BOOL match = FALSE; 1135 long regerr; 1136 1137 ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); 1138 deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 1139 1140 if (!g_pfnSetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) 1141 { 1142 printf("Could not retrieve install params!"); 1143 return FALSE; 1144 } 1145 1146 #ifdef DI_FLAGSEX_INSTALLEDDRIVER 1147 1148 /* Set the flags that tell g_pfnSetupDiBuildDriverInfoList to just put the 1149 currently installed driver node in the list, and that it should allow 1150 excluded drivers. This flag introduced in WinXP. */ 1151 deviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS); 1152 1153 if (g_pfnSetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) 1154 { 1155 /* We were able to specify this flag, so proceed the easy way 1156 We should get a list of no more than 1 driver */ 1157 if (!g_pfnSetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) 1158 { 1159 return FALSE; 1160 } 1161 if (!g_pfnSetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_CLASSDRIVER, 0, DriverInfoData)) 1162 { 1163 return FALSE; 1164 } 1165 1166 /* We've selected the current driver */ 1167 return TRUE; 1168 } 1169 1170 deviceInstallParams.FlagsEx &= ~(DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS); 1171 336 hr = ERROR_INSTALL_FAILURE; 337 } 338 g_pfnDIFXAPISetLogCallback(NULL, NULL); 339 #ifdef DEBUG 340 if (fh) 341 fclose(fh); 1172 342 #endif 1173 1174 /* The following method works in Win2k, but it's slow and painful. 1175 First, get driver key - if it doesn't exist, no driver */ 1176 hKey = g_pfnSetupDiOpenDevRegKey(Devs, DevInfo, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ 1177 ); 1178 1179 if (hKey == INVALID_HANDLE_VALUE) 1180 { 1181 1182 _tprintf(_T("No associated driver found in registry!")); 1183 1184 /* No such value exists, so there can't be an associated driver */ 1185 RegCloseKey(hKey); 1186 return FALSE; 1187 } 1188 1189 /* Obtain path of INF - we'll do a search on this specific INF */ 1190 RegDataLength = sizeof(deviceInstallParams.DriverPath); /* Bytes!!! */ 1191 regerr = RegQueryValueEx(hKey, REGSTR_VAL_INFPATH, NULL, &RegDataType, (PBYTE)deviceInstallParams.DriverPath, &RegDataLength); 1192 1193 if ((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) 1194 { 1195 1196 _tprintf(_T("No associated .inf path found in registry!")); 1197 1198 /* No such value exists, so no associated driver */ 1199 RegCloseKey(hKey); 1200 return FALSE; 1201 } 1202 1203 /* Obtain name of Provider to fill into DriverInfoData */ 1204 RegDataLength = sizeof(ProviderName); /* Bytes!!! */ 1205 regerr = RegQueryValueEx(hKey, REGSTR_VAL_PROVIDER_NAME, NULL, &RegDataType, (PBYTE)ProviderName, &RegDataLength); 1206 1207 if ((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) 1208 { 1209 /* No such value exists, so we don't have a valid associated driver */ 1210 RegCloseKey(hKey); 1211 return FALSE; 1212 } 1213 1214 /* Obtain name of section - for final verification */ 1215 RegDataLength = sizeof(SectionName); /* Bytes!!! */ 1216 regerr = RegQueryValueEx(hKey, REGSTR_VAL_INFSECTION, NULL, &RegDataType, (PBYTE)SectionName, &RegDataLength); 1217 1218 if ((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) 1219 { 1220 /* No such value exists, so we don't have a valid associated driver */ 1221 RegCloseKey(hKey); 1222 return FALSE; 1223 } 1224 1225 /* Driver description (need not be same as device description) - for final verification */ 1226 RegDataLength = sizeof(DrvDescription); /* Bytes!!! */ 1227 regerr = RegQueryValueEx(hKey, REGSTR_VAL_DRVDESC, NULL, &RegDataType, (PBYTE)DrvDescription, &RegDataLength); 1228 1229 RegCloseKey(hKey); 1230 1231 if ((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) 1232 { 1233 /* No such value exists, so we don't have a valid associated driver */ 1234 return FALSE; 1235 } 1236 1237 /* Manufacturer (via SPDRP_MFG, don't access registry directly!) */ 1238 if (!g_pfnSetupDiGetDeviceRegistryProperty(Devs, DevInfo, SPDRP_MFG, NULL, /* Datatype is guaranteed to always be REG_SZ */ 1239 (PBYTE)MfgName, sizeof(MfgName), /* Bytes!!! */ 1240 NULL)) 1241 { 1242 /* No such value exists, so we don't have a valid associated driver */ 1243 return FALSE; 1244 } 1245 1246 /* Now search for drivers listed in the INF */ 1247 deviceInstallParams.Flags |= DI_ENUMSINGLEINF; 1248 deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS; 1249 1250 if (!g_pfnSetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) 1251 { 1252 return FALSE; 1253 } 1254 if (!g_pfnSetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) 1255 { 1256 return FALSE; 1257 } 1258 1259 /* Find the entry in the INF that was used to install the driver for this device */ 1260 for (c = 0; g_pfnSetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_CLASSDRIVER, c, DriverInfoData); c++) 1261 { 1262 if ((_tcscmp(DriverInfoData->MfgName, MfgName) == 0) && (_tcscmp(DriverInfoData->ProviderName, ProviderName) == 0)) 1263 { 1264 /* These two fields match, try more detailed info to ensure we have the exact driver entry used */ 1265 SP_DRVINFO_DETAIL_DATA detail; 1266 detail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); 1267 if (!g_pfnSetupDiGetDriverInfoDetail(Devs, DevInfo, DriverInfoData, &detail, sizeof(detail), NULL) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) 1268 { 1269 continue; 1270 } 1271 if ((_tcscmp(detail.SectionName, SectionName) == 0) && (_tcscmp(detail.DrvDescription, DrvDescription) == 0)) 1272 { 1273 match = TRUE; 1274 break; 1275 } 1276 } 1277 } 1278 if (!match) 1279 { 1280 g_pfnSetupDiDestroyDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER); 1281 } 1282 return match; 1283 } 1284 1285 /*++ 1286 1287 Routine Description: 1288 1289 if Context provided, Simply count 1290 otherwise dump files indented 2 1291 1292 Arguments: 1293 1294 Context - DWORD Count 1295 Notification - SPFILENOTIFY_QUEUESCAN 1296 Param1 - scan 1297 1298 Return Value: 1299 1300 none 1301 1302 --*/ 1303 UINT DumpDeviceDriversCallback (IN PVOID Context, IN UINT Notification, IN UINT_PTR Param1, IN UINT_PTR Param2) 1304 { 1305 LPDWORD count = (LPDWORD)Context; 1306 LPTSTR file = (LPTSTR)Param1; 1307 if (count) 1308 { 1309 count[0]++; 1310 } 1311 else 1312 { 1313 _tprintf(TEXT("%s\n"), file); 1314 } 1315 1316 return NO_ERROR; 1317 } 1318 1319 /*++ 1320 1321 Routine Description: 1322 1323 Dump information about what files were installed for driver package 1324 <tab>Installed using OEM123.INF section [abc.NT] 1325 <tab><tab>file... 1326 1327 Arguments: 1328 1329 Devs )_ uniquely identify device 1330 DevInfo ) 1331 1332 Return Value: 1333 1334 none 1335 1336 --*/ 1337 int DeleteOEMInfCallback (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context) 1338 { 1339 /* Do this by 'searching' for the current driver 1340 mimicking a copy-only install to our own file queue 1341 and then parsing that file queue */ 1342 SP_DEVINSTALL_PARAMS deviceInstallParams; 1343 SP_DRVINFO_DATA driverInfoData; 1344 SP_DRVINFO_DETAIL_DATA driverInfoDetail; 1345 HSPFILEQ queueHandle = INVALID_HANDLE_VALUE; 1346 DWORD count; 1347 DWORD scanResult; 1348 int success = EXIT_FAIL; 1349 1350 ZeroMemory(&driverInfoData,sizeof(driverInfoData)); 1351 driverInfoData.cbSize = sizeof(driverInfoData); 1352 1353 if (!FindCurrentDriver(Devs, DevInfo, &driverInfoData)) 1354 return EXIT_FAIL; 1355 1356 _tprintf(_T("Driver files found!\n")); 1357 1358 /* Get useful driver information */ 1359 driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); 1360 if (!g_pfnSetupDiGetDriverInfoDetail(Devs, DevInfo, &driverInfoData, &driverInfoDetail, sizeof(SP_DRVINFO_DETAIL_DATA), NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 1361 { 1362 /* No information about driver or section */ 1363 _tprintf(_T("No information about driver or section!\n")); 1364 goto final; 1365 } 1366 1367 if (!driverInfoDetail.InfFileName[0] || !driverInfoDetail.SectionName[0]) 1368 { 1369 _tprintf(_T("Driver or section name is empty!\n")); 1370 goto final; 1371 } 1372 1373 _tprintf(_T("Desc: %s\n"), driverInfoDetail.DrvDescription); 1374 _tprintf(_T("SecName: %s\n"), driverInfoDetail.SectionName); 1375 _tprintf(_T("INF-File: %s\n"), driverInfoDetail.InfFileName); 1376 1377 /* Pretend to do the file-copy part of a driver install 1378 to determine what files are used 1379 the specified driver must be selected as the active driver */ 1380 if (!g_pfnSetupDiSetSelectedDriver(Devs, DevInfo, &driverInfoData)) 1381 goto final; 1382 1383 /* Create a file queue so we can look at this queue later */ 1384 queueHandle = SetupOpenFileQueue(); 1385 1386 if (queueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE) 1387 { 1388 goto final; 1389 } 1390 1391 /* Modify flags to indicate we're providing our own queue */ 1392 ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); 1393 deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); 1394 if (!g_pfnSetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) 1395 goto final; 1396 1397 /* We want to add the files to the file queue, not install them! */ 1398 deviceInstallParams.FileQueue = queueHandle; 1399 deviceInstallParams.Flags |= DI_NOVCP; 1400 1401 if (!g_pfnSetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) 1402 goto final; 1403 1404 /* Now fill queue with files that are to be installed this involves all class/co-installers */ 1405 if (!g_pfnSetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, Devs, DevInfo)) 1406 goto final; 1407 1408 /* We now have a list of delete/rename/copy files 1409 iterate the copy queue twice - 1st time to get # of files 1410 2nd time to get files (WinXP has API to get # of files, but we want this to work 1411 on Win2k too */ 1412 count = 0; 1413 scanResult = 0; 1414 1415 /* Call once to count (NOT YET IMPLEMENTED!) */ 1416 //SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,&count,&scanResult); 1417 //FormatToStream(stdout, count ? MSG_DUMP_DRIVER_FILES : MSG_DUMP_NO_DRIVER_FILES, count, driverInfoDetail.InfFileName, driverInfoDetail.SectionName); 1418 1419 /* Call again to dump the files (NOT YET IMPLEMENTED!) */ 1420 //SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,NULL,&scanResult); 1421 1422 if (!DeleteFile(driverInfoDetail.InfFileName)) 1423 scanResult = GetLastError(); 1424 else 1425 { 1426 DWORD index = 0; 1427 1428 index = lstrlen(driverInfoDetail.InfFileName); 1429 if (index > 3) 1430 { 1431 lstrcpy(driverInfoDetail.InfFileName + index - 3, TEXT( "pnf" ) ); 1432 1433 if (!DeleteFile(driverInfoDetail.InfFileName)) 1434 scanResult = GetLastError(); 1435 } 1436 } 1437 1438 success = EXIT_OK; 1439 1440 final: 1441 1442 g_pfnSetupDiDestroyDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER); 1443 1444 if (queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE) 1445 { 1446 SetupCloseFileQueue(queueHandle); 1447 } 1448 1449 if (EXIT_OK != success) 1450 { 1451 _tprintf(_T("Something went wrong while delete the OEM INF-files!\n\n")); 1452 } 1453 1454 return success; 1455 1456 } 1457 1458 int UninstallDriver (_TCHAR* a_pszHwID) 1459 { 1460 _tprintf(_T("Uninstalling device: %ws\n"), a_pszHwID); 1461 1462 _tprintf(_T("Removing driver files ...\n\n")); 1463 int iRet = EnumerateDevices(NULL, NULL, DIGCF_PRESENT, 1, &a_pszHwID, DeleteOEMInfCallback, NULL); 1464 1465 if (EXIT_OK != iRet) 1466 return iRet; 1467 1468 _tprintf(_T("Uninstalling driver ...\n\n")); 1469 iRet = EnumerateDevices(NULL, NULL, DIGCF_PRESENT, 1, &a_pszHwID, UninstallCallback, NULL); 1470 1471 return iRet; 1472 } 1473 1474 #ifdef VBOX_WITH_WDDM 1475 /*++ 1476 1477 Routine Description: 1478 1479 Dump information about what files were installed for driver package 1480 <tab>Installed using OEM123.INF section [abc.NT] 1481 <tab><tab>file... 1482 1483 Arguments: 1484 1485 Devs )_ uniquely identify device 1486 DevInfo ) 1487 1488 Return Value: 1489 1490 none 1491 1492 --*/ 1493 int MatchDriverCallback (HDEVINFO Devs, PSP_DEVINFO_DATA DevInfo, DWORD Index, LPVOID Context) 1494 { 1495 /* Do this by 'searching' for the current driver 1496 mimicking a copy-only install to our own file queue 1497 and then parsing that file queue */ 1498 SP_DRVINFO_DATA driverInfoData; 1499 SP_DRVINFO_DETAIL_DATA driverInfoDetail; 1500 LPCTSTR pStr = (LPCTSTR)Context; 1501 int success = EXIT_FAIL; 1502 1503 ZeroMemory(&driverInfoData,sizeof(driverInfoData)); 1504 driverInfoData.cbSize = sizeof(driverInfoData); 1505 1506 if (!FindCurrentDriver(Devs, DevInfo, &driverInfoData)) 1507 return EXIT_FAIL; 1508 1509 _tprintf(_T("Driver files found!\n")); 1510 1511 /* Get useful driver information */ 1512 driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); 1513 if (!g_pfnSetupDiGetDriverInfoDetail(Devs, DevInfo, &driverInfoData, &driverInfoDetail, sizeof(SP_DRVINFO_DETAIL_DATA), NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 1514 { 1515 /* No information about driver or section */ 1516 _tprintf(_T("No information about driver or section!\n")); 1517 goto final; 1518 } 1519 1520 if (!driverInfoDetail.InfFileName[0] || !driverInfoDetail.SectionName[0]) 1521 { 1522 _tprintf(_T("Driver or section name is empty!\n")); 1523 goto final; 1524 } 1525 1526 _tprintf(_T("Desc: %s\n"), driverInfoDetail.DrvDescription); 1527 _tprintf(_T("SecName: %s\n"), driverInfoDetail.SectionName); 1528 _tprintf(_T("INF-File: %s\n"), driverInfoDetail.InfFileName); 1529 1530 if (_tcsstr(driverInfoDetail.DrvDescription, pStr)) 1531 { 1532 _tprintf(_T("Driver name matched\n")); 1533 success = EXIT_OK; 1534 } 1535 else 1536 { 1537 _tprintf(_T("Driver name NOT matched\n")); 1538 success = EXIT_FALSE; 1539 } 1540 1541 final: 1542 1543 g_pfnSetupDiDestroyDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER); 1544 1545 if (EXIT_OK != success && EXIT_FALSE != success) 1546 { 1547 _tprintf(_T("Something went wrong while delete the OEM INF-files!\n\n")); 1548 } 1549 1550 return success; 1551 } 1552 1553 int MatchDriver (_TCHAR* a_pszHwID, _TCHAR* a_pszDrvName) 1554 { 1555 _tprintf(_T("Checking Device: %ws ; for driver desc string %ws\n"), a_pszHwID, a_pszDrvName); 1556 1557 int iRet = EnumerateDevices(NULL, NULL, DIGCF_PRESENT, 1, &a_pszHwID, MatchDriverCallback, a_pszDrvName); 1558 1559 return iRet; 1560 } 1561 #endif 1562 1563 int ExecuteInfFile (_TCHAR* a_pszSection, int a_iMode, _TCHAR* a_pszInf) 1564 { 1565 _tprintf(_T("Executing INF-File: %ws (%ws) ...\n"), a_pszInf, a_pszSection); 343 if (SUCCEEDED(hr)) 344 { 345 if (fReboot) 346 _tprintf(_T("A reboot is needed to complete the driver (un)installation!\n")); 347 } 348 } 349 } 350 351 if (NULL != hDIFxAPI) 352 FreeLibrary(hDIFxAPI); 353 354 return SUCCEEDED(hr) ? EXIT_OK : EXIT_FAIL; 355 } 356 357 /** 358 * Executes a sepcified .INF section to install/uninstall drivers and/or services. 359 * 360 * @return Exit code (EXIT_OK, EXIT_FAIL) 361 * @param pszSection Section to execute; usually it's "DefaultInstall". 362 * @param iMode Execution mode to use (see MSDN). 363 * @param pszInf Full qualified path of the .INF file to use. 364 */ 365 int ExecuteInfFile(const _TCHAR *pszSection, int iMode, const _TCHAR *pszInf) 366 { 367 _tprintf(_T("Executing INF-File: %ws (Section: %ws) ...\n"), pszInf, pszSection); 1566 368 1567 369 /* Executed by the installer that already has proper privileges. */ 1568 370 _TCHAR szCommandLine[_MAX_PATH + 1] = { 0 }; 1569 swprintf(szCommandLine, sizeof(szCommandLine), TEXT( "%ws %d %ws" ), a_pszSection, a_iMode, a_pszInf);1570 1571 #ifdef _DEBUG371 swprintf(szCommandLine, sizeof(szCommandLine), TEXT( "%ws %d %ws" ), pszSection, iMode, pszInf); 372 373 #ifdef DEBUG 1572 374 _tprintf (_T( "Commandline: %ws\n"), szCommandLine); 1573 375 #endif 1574 376 1575 377 InstallHinfSection(NULL, NULL, szCommandLine, SW_SHOW); 378 /* No return value given! */ 1576 379 1577 380 return EXIT_OK; 1578 381 } 1579 382 1580 int AddNetworkProvider (TCHAR* a_pszProvider, int a_iOrder) 1581 { 383 /** 384 * Adds a string entry to a MULTI_SZ registry list. 385 * 386 * @return Exit code (EXIT_OK, EXIT_FAIL) 387 * @param pszSubKey Sub key containing the list. 388 * @param pszKeyValue The actual key name of the list. 389 * @param pszValueToRemove The value to add to the list. 390 * @param uiOrder Position (zero-based) of where to add the value to the list. 391 */ 392 int RegistryAddStringToMultiSZ(const TCHAR *pszSubKey, const TCHAR *pszKeyValue, const TCHAR *pszValueToAdd, unsigned int uiOrder) 393 { 394 #ifdef DEBUG 395 _tprintf(_T("AddStringToMultiSZ: Adding MULTI_SZ string %ws to %ws\\%ws (Order = %d)\n"), pszValueToAdd, pszSubKey, pszKeyValue, uiOrder); 396 #endif 397 398 HKEY hKey = NULL; 399 DWORD disp, dwType; 400 LONG lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &disp); 401 if (lRet != ERROR_SUCCESS) 402 _tprintf(_T("AddStringToMultiSZ: RegCreateKeyEx %ts failed with error %ld!\n"), pszSubKey, lRet); 403 404 if (lRet == ERROR_SUCCESS) 405 { 406 TCHAR szKeyValue[512] = { 0 }; 407 TCHAR szNewKeyValue[512] = { 0 }; 408 DWORD cbKeyValue = sizeof(szKeyValue); 409 410 lRet = RegQueryValueEx(hKey, pszKeyValue, NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue); 411 if ( lRet != ERROR_SUCCESS 412 || dwType != REG_MULTI_SZ) 413 { 414 _tprintf(_T("AddStringToMultiSZ: RegQueryValueEx failed with error %ld, key type = 0x%x!\n"), lRet, dwType); 415 } 416 else 417 { 418 419 /* Look if the network provider is already in the list. */ 420 int iPos = 0; 421 size_t cb = 0; 422 423 /* Replace delimiting "\0"'s with "," to make tokenizing work. */ 424 for (int i = 0; i < cbKeyValue / sizeof(TCHAR); i++) 425 if (szKeyValue[i] == '\0') szKeyValue[i] = ','; 426 427 TCHAR *pszToken = wcstok(szKeyValue, _T(",")); 428 TCHAR *pszNewToken = NULL; 429 TCHAR *pNewKeyValuePos = szNewKeyValue; 430 while (pszToken != NULL) 431 { 432 pszNewToken = wcstok(NULL, _T(",")); 433 434 /* Append new value (at beginning if iOrder=0). */ 435 if (iPos == uiOrder) 436 { 437 memcpy(pNewKeyValuePos, pszValueToAdd, wcslen(pszValueToAdd)*sizeof(TCHAR)); 438 439 cb += (wcslen(pszValueToAdd) + 1) * sizeof(TCHAR); /* Add trailing zero as well. */ 440 pNewKeyValuePos += wcslen(pszValueToAdd) + 1; 441 iPos++; 442 } 443 444 if (0 != wcsicmp(pszToken, pszValueToAdd)) 445 { 446 memcpy(pNewKeyValuePos, pszToken, wcslen(pszToken)*sizeof(TCHAR)); 447 cb += (wcslen(pszToken) + 1) * sizeof(TCHAR); /* Add trailing zero as well. */ 448 pNewKeyValuePos += wcslen(pszToken) + 1; 449 iPos++; 450 } 451 452 pszToken = pszNewToken; 453 } 454 455 /* Append as last item if needed. */ 456 if (uiOrder >= iPos) 457 { 458 memcpy(pNewKeyValuePos, pszValueToAdd, wcslen(pszValueToAdd)*sizeof(TCHAR)); 459 cb += wcslen(pszValueToAdd) * sizeof(TCHAR); /* Add trailing zero as well. */ 460 } 461 462 lRet = RegSetValueExW(hKey, pszKeyValue, 0, REG_MULTI_SZ, (LPBYTE)szNewKeyValue, (DWORD)cb); 463 if (lRet != ERROR_SUCCESS) 464 _tprintf(_T("AddStringToMultiSZ: RegSetValueEx failed with error %ld!\n"), lRet); 465 } 466 467 RegCloseKey(hKey); 468 #ifdef DEBUG 469 if (lRet == ERROR_SUCCESS) 470 _tprintf(_T("AddStringToMultiSZ: Value %ws successfully written!\n"), pszValueToAdd); 471 #endif 472 } 473 474 return (lRet == ERROR_SUCCESS) ? EXIT_OK : EXIT_FAIL; 475 } 476 477 /** 478 * Removes a string entry from a MULTI_SZ registry list. 479 * 480 * @return Exit code (EXIT_OK, EXIT_FAIL) 481 * @param pszSubKey Sub key containing the list. 482 * @param pszKeyValue The actual key name of the list. 483 * @param pszValueToRemove The value to remove from the list. 484 */ 485 int RegistryRemoveStringFromMultiSZ(const TCHAR *pszSubKey, const TCHAR *pszKeyValue, const TCHAR *pszValueToRemove) 486 { 487 // @todo Make string sizes dynamically allocated! 488 489 const TCHAR *pszKey = pszSubKey; 490 #ifdef DEBUG 491 _tprintf(_T("RemoveStringFromMultiSZ: Removing MULTI_SZ string: %ws from %ws\\%ws ...\n"), pszValueToRemove, pszSubKey, pszKeyValue); 492 #endif 493 494 HKEY hkey; 495 DWORD disp, dwType; 496 LONG lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp); 497 if (lRet != ERROR_SUCCESS) 498 _tprintf(_T("RemoveStringFromMultiSZ: RegCreateKeyEx %ts failed with error %ld!\n"), pszKey, lRet); 499 500 if (lRet == ERROR_SUCCESS) 501 { 502 TCHAR szKeyValue[1024]; 503 DWORD cbKeyValue = sizeof(szKeyValue); 504 505 lRet = RegQueryValueEx(hkey, pszKeyValue, NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue); 506 if ( lRet != ERROR_SUCCESS 507 || dwType != REG_MULTI_SZ) 508 { 509 _tprintf(_T("RemoveStringFromMultiSZ: RegQueryValueEx failed with %d, key type = 0x%x!\n"), lRet, dwType); 510 } 511 else 512 { 513 #ifdef DEBUG 514 _tprintf(_T("RemoveStringFromMultiSZ: Current key len: %ld\n"), cbKeyValue); 515 #endif 516 517 TCHAR szCurString[1024] = { 0 }; 518 TCHAR szFinalString[1024] = { 0 }; 519 int iIndex = 0; 520 int iNewIndex = 0; 521 for (int i = 0; i < cbKeyValue / sizeof(TCHAR); i++) 522 { 523 if (szKeyValue[i] != _T('\0')) 524 szCurString[iIndex++] = szKeyValue[i]; 525 526 if ( (!szKeyValue[i] == _T('\0')) 527 && (szKeyValue[i + 1] == _T('\0'))) 528 { 529 if (NULL == wcsstr(szCurString, pszValueToRemove)) 530 { 531 wcscat(&szFinalString[iNewIndex], szCurString); 532 533 if (iNewIndex == 0) 534 iNewIndex = iIndex; 535 else iNewIndex += iIndex; 536 537 szFinalString[++iNewIndex] = _T('\0'); 538 } 539 540 iIndex = 0; 541 ZeroMemory(szCurString, sizeof(szCurString)); 542 } 543 } 544 szFinalString[++iNewIndex] = _T('\0'); 545 #ifdef DEBUG 546 _tprintf(_T("RemoveStringFromMultiSZ: New key value: %ws (%u bytes)\n"), 547 szFinalString, iNewIndex * sizeof(TCHAR)); 548 #endif 549 550 lRet = RegSetValueExW(hkey, pszKeyValue, 0, REG_MULTI_SZ, (LPBYTE)szFinalString, iNewIndex * sizeof(TCHAR)); 551 if (lRet != ERROR_SUCCESS) 552 _tprintf(_T("RemoveStringFromMultiSZ: RegSetValueEx failed with %d!\n"), lRet); 553 } 554 555 RegCloseKey(hkey); 556 #ifdef DEBUG 557 if (lRet == ERROR_SUCCESS) 558 _tprintf(_T("RemoveStringFromMultiSZ: Value %ws successfully removed!\n"), pszValueToRemove); 559 #endif 560 } 561 562 return (lRet == ERROR_SUCCESS) ? EXIT_OK : EXIT_FAIL; 563 } 564 565 /** 566 * Adds a string to a registry string list (STRING_SZ). 567 * Only operates in HKLM for now, needs to be extended later for 568 * using other hives. Only processes lists with a "," separator 569 * at the moment. 570 * 571 * @return Exit code (EXIT_OK, EXIT_FAIL) 572 * @param pszSubKey Sub key containing the list. 573 * @param pszKeyValue The actual key name of the list. 574 * @param pszValueToAdd The value to add to the list. 575 * @param uiOrder Position (zero-based) of where to add the value to the list. 576 * @param dwFlags Flags. 577 */ 578 int RegistryAddStringToList(const TCHAR *pszSubKey, const TCHAR *pszKeyValue, const TCHAR *pszValueToAdd, 579 unsigned int uiOrder, DWORD dwFlags) 580 { 581 HKEY hKey = NULL; 582 DWORD disp, dwType; 583 LONG lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &disp); 584 if (lRet != ERROR_SUCCESS) 585 _tprintf(_T("RegistryAddStringToList: RegCreateKeyEx %ts failed with error %ld!\n"), pszSubKey, lRet); 586 1582 587 TCHAR szKeyValue[512] = { 0 }; 1583 588 TCHAR szNewKeyValue[512] = { 0 }; 589 DWORD cbKeyValue = sizeof(szKeyValue); 590 591 lRet = RegQueryValueEx(hKey, pszKeyValue, NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue); 592 if ( lRet != ERROR_SUCCESS 593 || dwType != REG_SZ) 594 { 595 _tprintf(_T("RegistryAddStringToList: RegQueryValueEx failed with %d, key type = 0x%x!\n"), lRet, dwType); 596 } 597 598 if (lRet == ERROR_SUCCESS) 599 { 600 #ifdef DEBUG 601 _tprintf(_T("RegistryAddStringToList: Key value: %ws\n"), szKeyValue); 602 #endif 603 604 /* Create entire new list. */ 605 unsigned int iPos = 0; 606 TCHAR *pszToken = wcstok(szKeyValue, _T(",")); 607 TCHAR *pszNewToken = NULL; 608 while (pszToken != NULL) 609 { 610 pszNewToken = wcstok(NULL, _T(",")); 611 612 /* Append new provider name (at beginning if iOrder=0). */ 613 if (iPos == uiOrder) 614 { 615 wcscat(szNewKeyValue, pszValueToAdd); 616 wcscat(szNewKeyValue, _T(",")); 617 iPos++; 618 } 619 620 BOOL fAddToList = FALSE; 621 if ( !wcsicmp(pszToken, pszValueToAdd) 622 && (dwFlags & VBOX_REG_STRINGLIST_ALLOW_DUPLICATES)) 623 fAddToList = TRUE; 624 else if (wcsicmp(pszToken, pszValueToAdd)) 625 fAddToList = TRUE; 626 627 if (fAddToList) 628 { 629 wcscat(szNewKeyValue, pszToken); 630 wcscat(szNewKeyValue, _T(",")); 631 iPos++; 632 } 633 634 #ifdef DEBUG 635 _tprintf (_T("RegistryAddStringToList: Temp new key value: %ws\n"), szNewKeyValue); 636 #endif 637 pszToken = pszNewToken; 638 } 639 640 /* Append as last item if needed. */ 641 if (uiOrder >= iPos) 642 wcscat(szNewKeyValue, pszValueToAdd); 643 644 /* Last char a delimiter? Cut off ... */ 645 if (szNewKeyValue[wcslen(szNewKeyValue) - 1] == ',') 646 szNewKeyValue[wcslen(szNewKeyValue) - 1] = '\0'; 647 648 size_t iNewLen = (wcslen(szNewKeyValue) * sizeof(WCHAR)) + sizeof(WCHAR); 649 650 #ifdef DEBUG 651 _tprintf(_T("RegistryAddStringToList: New provider list: %ws (%u bytes)\n"), szNewKeyValue, iNewLen); 652 #endif 653 654 lRet = RegSetValueExW(hKey, pszKeyValue, 0, REG_SZ, (LPBYTE)szNewKeyValue, (DWORD)iNewLen); 655 if (lRet != ERROR_SUCCESS) 656 _tprintf(_T("RegistryAddStringToList: RegSetValueEx failed with %ld!\n"), lRet); 657 } 658 659 RegCloseKey(hKey); 660 return (lRet == ERROR_SUCCESS) ? EXIT_OK : EXIT_FAIL; 661 } 662 663 /** 664 * Removes a string from a registry string list (STRING_SZ). 665 * Only operates in HKLM for now, needs to be extended later for 666 * using other hives. Only processes lists with a "," separator 667 * at the moment. 668 * 669 * @return Exit code (EXIT_OK, EXIT_FAIL) 670 * @param pszSubKey Sub key containing the list. 671 * @param pszKeyValue The actual key name of the list. 672 * @param pszValueToRemove The value to remove from the list. 673 */ 674 int RegistryRemoveStringFromList(const TCHAR *pszSubKey, const TCHAR *pszKeyValue, const TCHAR *pszValueToRemove) 675 { 1584 676 HKEY hKey = NULL; 1585 677 DWORD disp, dwType; 1586 int rc; 1587 1588 _tprintf(_T("Adding network provider: %ws (Order = %d)\n"), a_pszProvider, a_iOrder); 1589 1590 /* Note: HWOrder is not accessible in Windows 2000; it is updated automatically anyway. */ 1591 TCHAR *pszKey = _T("System\\CurrentControlSet\\Control\\NetworkProvider\\Order"); 1592 1593 rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &disp); 1594 if (rc != ERROR_SUCCESS) 1595 { 1596 _tprintf(_T("RegCreateKeyEx %ts failed with %d!\n"), pszKey, rc); 1597 return EXIT_FAIL; 1598 } 1599 DWORD cbKeyValue = sizeof(szKeyValue); 1600 1601 rc = RegQueryValueEx(hKey, _T("ProviderOrder"), NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue); 1602 if (rc != ERROR_SUCCESS || dwType != REG_SZ) 1603 { 1604 _tprintf(_T("RegQueryValueEx failed with %d dwType = 0x%x!\n"), rc, dwType); 1605 return EXIT_FAIL; 1606 } 1607 1608 #ifdef _DEBUG 1609 _tprintf(_T("Key value: %ws\n"), szKeyValue); 1610 #endif 1611 1612 /* Create entire new list. */ 1613 int iPos = 0; 1614 1615 TCHAR* pszToken = wcstok(szKeyValue, _T(",")); 1616 TCHAR* pszNewToken = NULL; 1617 while (pszToken != NULL) 1618 { 1619 pszNewToken = wcstok(NULL, _T(",")); 1620 1621 /* Append new provider name (at beginning if a_iOrder=0). */ 1622 if (iPos == a_iOrder) 1623 { 1624 wcscat(szNewKeyValue, a_pszProvider); 1625 wcscat(szNewKeyValue, _T(",")); 1626 iPos++; 1627 } 1628 1629 if (0 != wcsicmp(pszToken, a_pszProvider)) 1630 { 1631 wcscat(szNewKeyValue, pszToken); 1632 wcscat(szNewKeyValue, _T(",")); 1633 iPos++; 1634 } 1635 1636 #ifdef _DEBUG 1637 _tprintf (_T("Temp new key value: %ws\n"), szNewKeyValue); 1638 #endif 1639 1640 pszToken = pszNewToken; 1641 } 1642 1643 /* Append as last item if needed. */ 1644 if (a_iOrder >= iPos) 1645 wcscat(szNewKeyValue, a_pszProvider); 1646 1647 /* Last char a delimiter? Cut off ... */ 1648 if (szNewKeyValue[wcslen(szNewKeyValue) - 1] == ',') 1649 szNewKeyValue[wcslen(szNewKeyValue) - 1] = '\0'; 1650 1651 size_t iNewLen = (wcslen(szNewKeyValue) * sizeof(WCHAR)) + sizeof(WCHAR); 1652 1653 _tprintf(_T("New provider list (%u bytes): %ws\n"), iNewLen, szNewKeyValue); 1654 1655 rc = RegSetValueExW(hKey, _T("ProviderOrder"), 0, REG_SZ, (LPBYTE)szNewKeyValue, (DWORD)iNewLen); 1656 1657 if (rc != ERROR_SUCCESS) 1658 { 1659 _tprintf(_T("RegSetValueEx failed with %d!\n"), rc); 1660 return EXIT_FAIL; 1661 } 1662 1663 rc = RegCloseKey(hKey); 1664 1665 if (rc == ERROR_SUCCESS) 1666 { 1667 _tprintf(_T("Network provider successfully installed!\n"), rc); 1668 rc = EXIT_OK; 1669 } 1670 1671 return rc; 1672 } 1673 1674 int AddStringToMultiSZ (TCHAR* a_pszSubKey, TCHAR* a_pszKeyValue, TCHAR* a_pszValueToAdd, int a_iOrder) 1675 { 678 LONG lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &disp); 679 if (lRet != ERROR_SUCCESS) 680 _tprintf(_T("RegistryRemoveStringFromList: RegCreateKeyEx %ts failed with error %ld!\n"), pszSubKey, lRet); 681 1676 682 TCHAR szKeyValue[512] = { 0 }; 1677 683 TCHAR szNewKeyValue[512] = { 0 }; 1678 HKEY hKey = NULL;1679 DWORD disp, dwType;1680 int rc = 0;1681 1682 _tprintf(_T("Adding MULTI_SZ string: %ws to %ws\\%ws (Order = %d)\n"), a_pszValueToAdd, a_pszSubKey, a_pszKeyValue, a_iOrder);1683 1684 rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, a_pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &disp);1685 if (rc != ERROR_SUCCESS)1686 {1687 _tprintf(_T("RegCreateKeyEx %ts failed with %d!\n"), a_pszSubKey, rc);1688 return EXIT_FAIL;1689 }1690 684 DWORD cbKeyValue = sizeof(szKeyValue); 1691 685 1692 rc = RegQueryValueEx(hKey, a_pszKeyValue, NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue); 1693 if (rc != ERROR_SUCCESS || dwType != REG_MULTI_SZ) 1694 { 1695 _tprintf(_T("RegQueryValueEx failed with %d, dwType = 0x%x!\n"), rc, dwType); 1696 return EXIT_FAIL; 1697 } 1698 1699 /* Look if the network provider is already in the list. */ 1700 int iPos = 0; 1701 size_t cb = 0; 1702 1703 /* Replace delimiting "\0"'s with "," to make tokenizing work. */ 1704 for (int i=0; i<cbKeyValue/sizeof(TCHAR);i++) 1705 if (szKeyValue[i] == '\0') szKeyValue[i] = ','; 1706 1707 TCHAR* pszToken = wcstok(szKeyValue, _T(",")); 1708 TCHAR* pszNewToken = NULL; 1709 TCHAR* pNewKeyValuePos = szNewKeyValue; 1710 while (pszToken != NULL) 1711 { 1712 pszNewToken = wcstok(NULL, _T(",")); 1713 1714 /* Append new value (at beginning if a_iOrder=0). */ 1715 if (iPos == a_iOrder) 1716 { 1717 memcpy(pNewKeyValuePos, a_pszValueToAdd, wcslen(a_pszValueToAdd)*sizeof(TCHAR)); 1718 1719 cb += (wcslen(a_pszValueToAdd) + 1) * sizeof(TCHAR); /* Add trailing zero as well. */ 1720 pNewKeyValuePos += wcslen(a_pszValueToAdd) + 1; 1721 iPos++; 1722 } 1723 1724 if (0 != wcsicmp(pszToken, a_pszValueToAdd)) 1725 { 1726 memcpy(pNewKeyValuePos, pszToken, wcslen(pszToken)*sizeof(TCHAR)); 1727 cb += (wcslen(pszToken) + 1) * sizeof(TCHAR); /* Add trailing zero as well. */ 1728 pNewKeyValuePos += wcslen(pszToken) + 1; 1729 iPos++; 1730 } 1731 1732 pszToken = pszNewToken; 1733 } 1734 1735 /* Append as last item if needed. */ 1736 if (a_iOrder >= iPos) 1737 { 1738 memcpy(pNewKeyValuePos, a_pszValueToAdd, wcslen(a_pszValueToAdd)*sizeof(TCHAR)); 1739 cb += wcslen(a_pszValueToAdd) * sizeof(TCHAR); /* Add trailing zero as well. */ 1740 } 1741 1742 rc = RegSetValueExW(hKey, a_pszKeyValue, 0, REG_MULTI_SZ, (LPBYTE)szNewKeyValue, (DWORD)cb); 1743 1744 if (rc != ERROR_SUCCESS) 1745 { 1746 _tprintf(_T("RegSetValueEx failed with %d!\n"), rc); 1747 return EXIT_FAIL; 1748 } 1749 1750 rc = RegCloseKey(hKey); 1751 1752 if (rc == ERROR_SUCCESS) 1753 { 1754 _tprintf(_T("Value successfully written (%u bytes)!\n"), cb); 1755 rc = EXIT_OK; 1756 } 1757 686 lRet = RegQueryValueEx(hKey, pszKeyValue, NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue); 687 if ( lRet != ERROR_SUCCESS 688 || dwType != REG_SZ) 689 { 690 _tprintf(_T("RegistryRemoveStringFromList: RegQueryValueEx failed with %d, key type = 0x%x!\n"), lRet, dwType); 691 } 692 693 if (lRet == ERROR_SUCCESS) 694 { 695 #ifdef DEBUG 696 _tprintf(_T("RegistryRemoveStringFromList: Key value: %ws\n"), szKeyValue); 697 #endif 698 699 /* Create entire new list. */ 700 int iPos = 0; 701 702 TCHAR *pszToken = wcstok(szKeyValue, _T(",")); 703 TCHAR *pszNewToken = NULL; 704 while (pszToken != NULL) 705 { 706 pszNewToken = wcstok(NULL, _T(",")); 707 708 /* Append all list values as long as it's not the 709 * value we want to remove. */ 710 if (wcsicmp(pszToken, pszValueToRemove)) 711 { 712 wcscat(szNewKeyValue, pszToken); 713 wcscat(szNewKeyValue, _T(",")); 714 iPos++; 715 } 716 717 #ifdef DEBUG 718 _tprintf (_T("RegistryRemoveStringFromList: Temp new key value: %ws\n"), szNewKeyValue); 719 #endif 720 pszToken = pszNewToken; 721 } 722 723 /* Last char a delimiter? Cut off ... */ 724 if (szNewKeyValue[wcslen(szNewKeyValue) - 1] == ',') 725 szNewKeyValue[wcslen(szNewKeyValue) - 1] = '\0'; 726 727 size_t iNewLen = (wcslen(szNewKeyValue) * sizeof(WCHAR)) + sizeof(WCHAR); 728 729 #ifdef DEBUG 730 _tprintf(_T("RegistryRemoveStringFromList: New provider list: %ws (%u bytes)\n"), szNewKeyValue, iNewLen); 731 #endif 732 733 lRet = RegSetValueExW(hKey, pszKeyValue, 0, REG_SZ, (LPBYTE)szNewKeyValue, (DWORD)iNewLen); 734 if (lRet != ERROR_SUCCESS) 735 _tprintf(_T("RegistryRemoveStringFromList: RegSetValueEx failed with %ld!\n"), lRet); 736 } 737 738 RegCloseKey(hKey); 739 return (lRet == ERROR_SUCCESS) ? EXIT_OK : EXIT_FAIL; 740 } 741 742 /** 743 * Adds a network provider with a specified order to the system. 744 * 745 * @return Exit code (EXIT_OK, EXIT_FAIL) 746 * @param pszProvider Name of network provider to add. 747 * @param uiOrder Position in list (zero-based) of where to add. 748 */ 749 int AddNetworkProvider(const TCHAR *pszProvider, unsigned int uiOrder) 750 { 751 _tprintf(_T("Adding network provider \"%ws\" (Order = %u) ...\n"), pszProvider, uiOrder); 752 int rc = RegistryAddStringToList(_T("System\\CurrentControlSet\\Control\\NetworkProvider\\Order"), 753 _T("ProviderOrder"), 754 pszProvider, uiOrder, VBOX_REG_STRINGLIST_NONE /* No flags set */); 755 if (rc == EXIT_OK) 756 _tprintf(_T("Network provider successfully added!\n")); 1758 757 return rc; 1759 758 } 1760 759 1761 int RemoveStringFromMultiSZ (TCHAR* a_pszSubKey, TCHAR* a_pszKeyValue, TCHAR* a_pszValueToRemove) 1762 { 1763 // @todo Make string sizes dynamically allocated! 1764 1765 TCHAR szKeyValue[1024]; 1766 HKEY hkey; 1767 DWORD disp, dwType; 1768 int rc; 1769 1770 TCHAR *pszKey = a_pszSubKey; 1771 1772 _tprintf(_T("Removing MULTI_SZ string: %ws from %ws\\%ws ...\n"), a_pszValueToRemove, a_pszSubKey, a_pszKeyValue); 1773 1774 rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkey, &disp); 1775 if (rc != ERROR_SUCCESS) 1776 { 1777 _tprintf(_T("RegCreateKeyEx %ts failed with %d!\n"), pszKey, rc); 1778 return EXIT_FAIL; 1779 } 1780 DWORD cbKeyValue = sizeof(szKeyValue); 1781 1782 rc = RegQueryValueEx(hkey, a_pszKeyValue, NULL, &dwType, (LPBYTE)szKeyValue, &cbKeyValue); 1783 if (rc != ERROR_SUCCESS || dwType != REG_MULTI_SZ) 1784 { 1785 _tprintf(_T("RegQueryValueEx failed with %d dwType = 0x%x!\n"), rc, dwType); 1786 return EXIT_FAIL; 1787 } 1788 1789 #ifdef _DEBUG 1790 _tprintf(_T("Current key len: %d\n"), cbKeyValue); 1791 #endif 1792 1793 TCHAR szCurString[1024] = { 0 }; 1794 TCHAR szFinalString[1024] = { 0 }; 1795 int iIndex = 0; 1796 int iNewIndex = 0; 1797 for (int i = 0; i < cbKeyValue / sizeof(TCHAR); i++) 1798 { 1799 if (szKeyValue[i] != _T('\0')) 1800 szCurString[iIndex++] = szKeyValue[i]; 1801 1802 if ((!szKeyValue[i] == _T('\0')) && szKeyValue[i + 1] == _T('\0')) 1803 { 1804 if (NULL == wcsstr(szCurString, a_pszValueToRemove)) 1805 { 1806 wcscat(&szFinalString[iNewIndex], szCurString); 1807 1808 if (iNewIndex == 0) 1809 iNewIndex = iIndex; 1810 else iNewIndex += iIndex; 1811 1812 szFinalString[++iNewIndex] = _T('\0'); 1813 } 1814 1815 iIndex = 0; 1816 ZeroMemory( szCurString, sizeof(szCurString)); 1817 } 1818 } 1819 1820 szFinalString[++iNewIndex] = _T('\0'); 1821 1822 #ifdef _DEBUG 1823 _tprintf(_T("New key len: %d\n"), iNewIndex * sizeof(TCHAR)); 1824 _tprintf(_T("New key value: %ws\n"), szFinalString); 1825 #endif 1826 1827 rc = RegSetValueExW(hkey, a_pszKeyValue, 0, REG_MULTI_SZ, (LPBYTE)szFinalString, iNewIndex * sizeof(TCHAR)); 1828 1829 if (rc != ERROR_SUCCESS) 1830 { 1831 _tprintf(_T("RegSetValueEx failed with %d!\n"), rc); 1832 return EXIT_FAIL; 1833 } 1834 1835 rc = RegCloseKey(hkey); 1836 1837 if (rc == ERROR_SUCCESS) 1838 { 1839 _tprintf(_T("Value successfully removed!\n"), rc); 1840 rc = EXIT_OK; 1841 } 1842 760 /** 761 * Removes a network provider from the system. 762 * 763 * @return Exit code (EXIT_OK, EXIT_FAIL) 764 * @param pszProvider Name of network provider to remove. 765 */ 766 int RemoveNetworkProvider(const TCHAR *pszProvider) 767 { 768 _tprintf(_T("Removing network provider \"%ws\" ...\n"), pszProvider); 769 int rc = RegistryRemoveStringFromList(_T("System\\CurrentControlSet\\Control\\NetworkProvider\\Order"), 770 _T("ProviderOrder"), 771 pszProvider); 772 if (rc == EXIT_OK) 773 _tprintf(_T("Network provider successfully removed!\n")); 1843 774 return rc; 1844 775 } 1845 776 1846 int CreateService (TCHAR* a_pszStartStopName,1847 TCHAR* a_pszDisplayName,1848 int a_iServiceType,1849 int a_iStartType,1850 TCHAR* a_pszBinPath,1851 TCHAR* a_pszLoadOrderGroup,1852 TCHAR* a_pszDependencies,1853 TCHAR* a_pszLogonUser,1854 TCHAR* a_pszLogonPw)777 int CreateService(const TCHAR *pszStartStopName, 778 const TCHAR *pszDisplayName, 779 int iServiceType, 780 int iStartType, 781 const TCHAR *pszBinPath, 782 const TCHAR *pszLoadOrderGroup, 783 const TCHAR *pszDependencies, 784 const TCHAR *pszLogonUser, 785 const TCHAR *pszLogonPassword) 1855 786 { 1856 787 int rc = ERROR_SUCCESS; 1857 788 1858 _tprintf(_T("Installing service %ws (%ws) ...\n"), a_pszDisplayName, a_pszStartStopName);789 _tprintf(_T("Installing service %ws (%ws) ...\n"), pszDisplayName, pszStartStopName); 1859 790 1860 791 SC_HANDLE hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); … … 1865 796 } 1866 797 1867 /* Fixup end of multistring */1868 TCHAR szDepend[ _MAX_PATH ] = { 0 }; 1869 if ( a_pszDependencies != NULL)1870 { 1871 _tcsnccpy (szDepend, a_pszDependencies, wcslen(a_pszDependencies));798 /* Fixup end of multistring. */ 799 TCHAR szDepend[ _MAX_PATH ] = { 0 }; /* @todo Use dynamically allocated string here! */ 800 if (pszDependencies != NULL) 801 { 802 _tcsnccpy (szDepend, pszDependencies, wcslen(pszDependencies)); 1872 803 DWORD len = (DWORD)wcslen (szDepend); 1873 804 szDepend [len + 1] = 0; 1874 805 1875 /* Replace comma separator on null separator */806 /* Replace comma separator on null separator. */ 1876 807 for (DWORD i = 0; i < len; i++) 1877 808 { … … 1882 813 1883 814 DWORD dwTag = 0xDEADBEAF; 1884 SC_HANDLE hService = CreateService (hSCManager, // SCManager database1885 a_pszStartStopName, // name of service1886 a_pszDisplayName, // name to display1887 SERVICE_ALL_ACCESS, // desired access1888 a_iServiceType, // service type1889 a_iStartType, // start type1890 SERVICE_ERROR_NORMAL, // error control type1891 a_pszBinPath, // service's binary1892 a_pszLoadOrderGroup, // ordering group1893 ( a_pszLoadOrderGroup != NULL) ? &dwTag : NULL, // tag identifier1894 ( a_pszDependencies != NULL) ? szDepend : NULL, // dependencies1895 ( a_pszLogonUser != NULL) ? a_pszLogonUser: NULL, // account1896 ( a_pszLogonPw != NULL) ? a_pszLogonPw : NULL); // password815 SC_HANDLE hService = CreateService (hSCManager, /* SCManager database handle. */ 816 pszStartStopName, /* Name of service. */ 817 pszDisplayName, /* Name to display. */ 818 SERVICE_ALL_ACCESS, /* Desired access. */ 819 iServiceType, /* Service type. */ 820 iStartType, /* Start type. */ 821 SERVICE_ERROR_NORMAL, /* Error control type. */ 822 pszBinPath, /* Service's binary. */ 823 pszLoadOrderGroup, /* Ordering group. */ 824 (pszLoadOrderGroup != NULL) ? &dwTag : NULL, /* Tag identifier. */ 825 (pszDependencies != NULL) ? szDepend : NULL, /* Dependencies. */ 826 (pszLogonUser != NULL) ? pszLogonUser: NULL, /* Account. */ 827 (pszLogonPassword != NULL) ? pszLogonPassword : NULL); /* Password. */ 1897 828 if (NULL == hService) 1898 829 { … … 1905 836 _tprintf(_T("Service already exists. No installation required. Updating the service config.\n")); 1906 837 1907 hService = OpenService (hSCManager, // SCManager database1908 a_pszStartStopName, // name of service1909 SERVICE_ALL_ACCESS); // desired access838 hService = OpenService (hSCManager, /* SCManager database handle. */ 839 pszStartStopName, /* Name of service. */ 840 SERVICE_ALL_ACCESS); /* Desired access. */ 1910 841 if (NULL == hService) 1911 842 { … … 1915 846 else 1916 847 { 1917 BOOL Result = ChangeServiceConfig (hService, // service handle 1918 a_iServiceType, // service type 1919 a_iStartType, // start type 1920 SERVICE_ERROR_NORMAL, // error control type 1921 a_pszBinPath, // service's binary 1922 a_pszLoadOrderGroup, // ordering group 1923 (a_pszLoadOrderGroup != NULL) ? &dwTag : NULL, // tag identifier 1924 (a_pszDependencies != NULL) ? szDepend : NULL, // dependencies 1925 (a_pszLogonUser != NULL) ? a_pszLogonUser: NULL, // account 1926 (a_pszLogonPw != NULL) ? a_pszLogonPw : NULL, // password 1927 a_pszDisplayName); // name to display 1928 if (Result) 1929 { 848 BOOL fResult = ChangeServiceConfig (hService, /* Service handle. */ 849 iServiceType, /* Service type. */ 850 iStartType, /* Start type. */ 851 SERVICE_ERROR_NORMAL, /* Error control type. */ 852 pszBinPath, /* Service's binary. */ 853 pszLoadOrderGroup, /* Ordering group. */ 854 (pszLoadOrderGroup != NULL) ? &dwTag : NULL, /* Tag identifier. */ 855 (pszDependencies != NULL) ? szDepend : NULL, /* Dependencies. */ 856 (pszLogonUser != NULL) ? pszLogonUser: NULL, /* Account. */ 857 (pszLogonPassword != NULL) ? pszLogonPassword : NULL, /* Password. */ 858 pszDisplayName); /* Name to display. */ 859 if (fResult) 1930 860 _tprintf(_T("The service config has been successfully updated.\n")); 1931 }1932 861 else 1933 862 { … … 1935 864 _tprintf(_T("Could not change service config! Error: %ld\n"), dwErr); 1936 865 } 1937 1938 CloseServiceHandle (hService);1939 } 1940 1941 /* This entire branch do not return an error to avoid installations failures,866 CloseServiceHandle(hService); 867 } 868 869 /* 870 * This entire branch do not return an error to avoid installations failures, 1942 871 * if updating service parameters. Better to have a running system with old 1943 872 * parameters and the failure information in the installation log. … … 1976 905 } 1977 906 1978 int DelService (TCHAR* a_pszStartStopName)907 int DelService(const TCHAR *pszStartStopName) 1979 908 { 1980 909 int rc = ERROR_SUCCESS; 1981 910 1982 _tprintf(_T("Deleting service '%ws' ...\n"), a_pszStartStopName);911 _tprintf(_T("Deleting service '%ws' ...\n"), pszStartStopName); 1983 912 1984 913 SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); … … 1991 920 else 1992 921 { 1993 hService = OpenService(hSCManager, a_pszStartStopName, SERVICE_ALL_ACCESS);922 hService = OpenService(hSCManager, pszStartStopName, SERVICE_ALL_ACCESS); 1994 923 if (NULL == hService) 1995 924 { 1996 _tprintf(_T("Could not open service '%ws'! Error: %ld\n"), a_pszStartStopName, GetLastError());925 _tprintf(_T("Could not open service '%ws'! Error: %ld\n"), pszStartStopName, GetLastError()); 1997 926 rc = EXIT_FAIL; 1998 927 } … … 2011 940 case ERROR_SERVICE_MARKED_FOR_DELETE: 2012 941 2013 _tprintf(_T("Service '%ws' already marked for deletion.\n"), a_pszStartStopName);942 _tprintf(_T("Service '%ws' already marked for deletion.\n"), pszStartStopName); 2014 943 break; 2015 944 2016 945 default: 2017 946 2018 _tprintf(_T("Could not delete service '%ws'! Error: %ld\n"), a_pszStartStopName, GetLastError());947 _tprintf(_T("Could not delete service '%ws'! Error: %ld\n"), pszStartStopName, GetLastError()); 2019 948 rc = EXIT_FAIL; 2020 949 break; … … 2023 952 else 2024 953 { 2025 _tprintf(_T("Service '%ws' successfully removed!\n"), a_pszStartStopName);954 _tprintf(_T("Service '%ws' successfully removed!\n"), pszStartStopName); 2026 955 } 2027 956 UnlockServiceDatabase(hSCManager); … … 2074 1003 } 2075 1004 2076 void PrintHelp 2077 { 2078 _tprintf(_T(" Installs / Uninstalls VirtualBox drivers for Windows XP/2K/Vista\n"));1005 void PrintHelp(void) 1006 { 1007 _tprintf(_T("VirtualBox Guest Additions Installation Helper for Windows\n")); 2079 1008 _tprintf(_T("Version: %d.%d.%d.%d\n\n"), VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); 2080 1009 _tprintf(_T("Syntax:\n")); 2081 _tprintf(_T("\tTo install: VBoxDrvInst /i <HardwareID> <INF-File> <Device Class>\n")); 2082 _tprintf(_T("\tTo uninstall: VBoxDrvInst /u <HardwareID>\n")); 2083 _tprintf(_T("\tTo execute an INF-File: VBoxDrvInst /inf <INF-File>\n")); 2084 _tprintf(_T("\tTo add a network provider: VBoxDrvInst /addnetprovider <Name> [Order]\n\n")); 2085 _tprintf(_T("\tTo write registry values: VBoxDrvInst /registry write <root> <sub key> <key name> <key type> <value> [type] [size]\n\n")); 2086 _tprintf(_T("Examples:\n")); 2087 _tprintf(_T("\tVBoxDrvInst /i \"PCI\\VEN_80EE&DEV_BEEF&SUBSYS_00000000&REV_00\" VBoxVideo.inf Display\n")); 2088 _tprintf(_T("\tVBoxDrvInst /addnetprovider VboxSF 1\n\n")); 2089 } 2090 2091 int __cdecl _tmain (int argc, _TCHAR* argv[]) 2092 { 2093 int rc; 1010 _tprintf(_T("\n")); 1011 _tprintf(_T("Drivers:\n")); 1012 _tprintf(_T("\tVBoxDrvInst driver install <inf-file>\n")); 1013 _tprintf(_T("\tVBoxDrvInst driver uninstall <inf-file>\n")); 1014 _tprintf(_T("\tVBoxDrvInst driver executeinf <inf-file>\n")); 1015 _tprintf(_T("\n")); 1016 _tprintf(_T("Network Provider:\n")); 1017 _tprintf(_T("\tVBoxDrvInst netprovider add <name> [order]\n")); 1018 _tprintf(_T("\tVBoxDrvInst netprovider remove <name>\n")); 1019 _tprintf(_T("\n")); 1020 _tprintf(_T("Registry:\n")); 1021 _tprintf(_T("\tVBoxDrvInst registry write <root> <sub key>\n") 1022 _T("\t <key name> <key type> <value>\n") 1023 _T("\t [type] [size]\n")); 1024 _tprintf(_T("\tVBoxDrvInst registry addmultisz <root> <sub key>\n") 1025 _T("\t <value> [order]\n")); 1026 _tprintf(_T("\tVBoxDrvInst registry delmultisz <root> <sub key>\n") 1027 _T("\t <key name> <value to remove>\n")); 1028 /** @todo Add "service" category! */ 1029 _tprintf(_T("\n")); 1030 } 1031 1032 int __cdecl _tmain(int argc, _TCHAR *argv[]) 1033 { 1034 int rc = EXIT_USAGE; 1035 2094 1036 OSVERSIONINFO OSinfo; 2095 2096 _TCHAR szHwID[_MAX_PATH] = { 0 }; /* Hardware ID. */ 2097 _TCHAR szINF[_MAX_PATH] = { 0 }; /* Complete path to INF file.*/ 2098 _TCHAR szDevClass[_MAX_PATH] = { 0 }; /* Device class. */ 2099 _TCHAR szProvider[_MAX_PATH] = { 0 }; /* The network provider name for the registry. */ 2100 2101 rc = LoadAPICalls(); 2102 if ( rc == ERROR_SUCCESS 2103 && argc >= 2) 2104 { 2105 OSinfo.dwOSVersionInfoSize = sizeof(OSinfo); 2106 GetVersionEx(&OSinfo); 2107 2108 if (0 == _tcsicmp(argv[1], _T("/i"))) 2109 { 2110 if (argc < 5) 2111 { 2112 rc = EXIT_USAGE; 2113 } 2114 else 1037 OSinfo.dwOSVersionInfoSize = sizeof(OSinfo); 1038 GetVersionEx(&OSinfo); 1039 1040 if (argc >= 2) 1041 { 1042 if ( !_tcsicmp(argv[1], _T("driver")) 1043 && argc >= 3) 1044 { 1045 _TCHAR szINF[_MAX_PATH] = { 0 }; /* Complete path to INF file.*/ 1046 if ( ( !_tcsicmp(argv[2], _T("install")) 1047 || !_tcsicmp(argv[2], _T("uninstall"))) 1048 && argc == 4) 2115 1049 { 2116 1050 if (OSinfo.dwMajorVersion < 5) 2117 1051 { 2118 _tprintf(_T("ERROR: Platform not supported yet!\n"));2119 rc = E RROR_NOT_SUPPORTED;1052 _tprintf(_T("ERROR: Platform not supported for driver (un)installation!\n")); 1053 rc = EXIT_FAIL; 2120 1054 } 2121 2122 if (rc == ERROR_SUCCESS) 1055 else 2123 1056 { 2124 _stprintf(szHwID, _T("%ws"), argv[2]);2125 1057 _stprintf(szINF, _T("%ws"), argv[3]); 2126 _stprintf(szDevClass, _T("%ws"), argv[4]); 2127 2128 rc = InstallDriver(szINF, szHwID, szDevClass); 1058 rc = VBoxInstallDriver(!_tcsicmp(argv[2], _T("install")) ? TRUE : FALSE, szINF, FALSE); 2129 1059 } 2130 1060 } 2131 } 2132 else if (0 == _tcsicmp(argv[1], _T("/u"))) 2133 { 2134 if (argc < 3) 2135 { 2136 rc = EXIT_USAGE; 2137 } 2138 else 2139 { 2140 if (OSinfo.dwMajorVersion < 5) 1061 else if ( !_tcsicmp(argv[2], _T("executeinf")) 1062 && argc == 4) 1063 { 1064 _stprintf(szINF, _T("%ws"), argv[3]); 1065 rc = ExecuteInfFile(_T("DefaultInstall"), 132, szINF); 1066 } 1067 } 1068 else if ( !_tcsicmp(argv[1], _T("netprovider")) 1069 && argc >= 3) 1070 { 1071 _TCHAR szProvider[_MAX_PATH] = { 0 }; /* The network provider name for the registry. */ 1072 if ( !_tcsicmp(argv[2], _T("add")) 1073 && argc >= 4) 1074 { 1075 int iOrder = 0; 1076 if (argc > 4) 1077 iOrder = _ttoi(argv[4]); 1078 _stprintf(szProvider, _T("%ws"), argv[3]); 1079 rc = AddNetworkProvider(szProvider, iOrder); 1080 } 1081 else if ( !_tcsicmp(argv[2], _T("remove")) 1082 && argc >= 4) 1083 { 1084 _stprintf(szProvider, _T("%ws"), argv[3]); 1085 rc = RemoveNetworkProvider(szProvider); 1086 } 1087 } 1088 else if ( !_tcsicmp(argv[1], _T("service")) 1089 && argc >= 3) 1090 { 1091 if ( !_tcsicmp(argv[2], _T("create")) 1092 && argc >= 8) 1093 { 1094 rc = CreateService(argv[3], 1095 argv[4], 1096 _ttoi(argv[5]), 1097 _ttoi(argv[6]), 1098 argv[7], 1099 (argc > 8) ? argv[8] : NULL, 1100 (argc > 9) ? argv[9] : NULL, 1101 (argc > 10) ? argv[10] : NULL, 1102 (argc > 11) ? argv[11] : NULL); 1103 } 1104 else if ( !_tcsicmp(argv[2], _T("delete")) 1105 && argc == 4) 1106 { 1107 rc = DelService(argv[3]); 1108 } 1109 } 1110 else if ( !_tcsicmp(argv[1], _T("registry")) 1111 && argc >= 3) 1112 { 1113 /** @todo add a handleRegistry(argc, argv) method to keep things cleaner */ 1114 if ( !_tcsicmp(argv[2], _T("addmultisz")) 1115 && argc == 7) 1116 { 1117 rc = RegistryAddStringToMultiSZ(argv[3], argv[4], argv[5], _ttoi(argv[6])); 1118 } 1119 else if ( !_tcsicmp(argv[2], _T("delmultisz")) 1120 && argc == 6) 1121 { 1122 rc = RegistryRemoveStringFromMultiSZ(argv[3], argv[4], argv[5]); 1123 } 1124 else if ( !_tcsicmp(argv[2], _T("write")) 1125 && argc >= 8) 1126 { 1127 HKEY hRootKey = HKEY_LOCAL_MACHINE; /** @todo needs to be expanded (argv[3]) */ 1128 DWORD dwValSize; 1129 BYTE *pbVal = NULL; 1130 DWORD dwVal; 1131 1132 if (argc > 8) 2141 1133 { 2142 _tprintf(_T("ERROR: Platform not supported yet!\n")); 2143 rc = ERROR_NOT_SUPPORTED; 1134 if (!_tcsicmp(argv[8], _T("dword"))) 1135 { 1136 dwVal = _ttol(argv[7]); 1137 pbVal = (BYTE*)&dwVal; 1138 dwValSize = sizeof(DWORD); 1139 } 2144 1140 } 2145 2146 if (rc == ERROR_SUCCESS) 1141 if (pbVal == NULL) /* By default interpret value as string */ 2147 1142 { 2148 _stprintf(szHwID, _T("%ws"), argv[2]);2149 rc = UninstallDriver(szHwID);1143 pbVal = (BYTE*)argv[7]; 1144 dwValSize = _tcslen(argv[7]); 2150 1145 } 2151 } 2152 } 2153 else if (0 == _tcsicmp(argv[1], _T("/inf"))) 2154 { 2155 if (argc < 3) 2156 { 2157 rc = EXIT_USAGE; 2158 } 2159 else 2160 { 2161 if (OSinfo.dwMajorVersion < 5) 2162 { 2163 _tprintf(_T("ERROR: Platform not supported yet!\n")); 2164 rc = ERROR_NOT_SUPPORTED; 2165 } 2166 2167 if (rc == ERROR_SUCCESS) 2168 { 2169 _stprintf(szINF, _T("%ws"), argv[2]); 2170 rc = ExecuteInfFile(_T("DefaultInstall"), 132, szINF); 2171 } 2172 } 2173 } 2174 else if (0 == _tcsicmp(argv[1], _T("/addnetprovider"))) 2175 { 2176 if (argc < 3) 2177 { 2178 rc = EXIT_USAGE; 2179 } 2180 else 2181 { 2182 2183 int iOrder = 0; 2184 if (argc > 3) 2185 iOrder = _ttoi(argv[3]); 2186 _stprintf(szProvider, _T("%ws"), argv[2]); 2187 rc = AddNetworkProvider(szProvider, iOrder); 2188 } 2189 } 2190 else if (0 == _tcsicmp(argv[1], _T("/reg_addmultisz"))) 2191 { 2192 if (argc < 6) 2193 { 2194 rc = EXIT_USAGE; 2195 } 2196 else 2197 { 2198 rc = AddStringToMultiSZ(argv[2], argv[3], argv[4], _ttoi(argv[5])); 2199 } 2200 } 2201 else if (0 == _tcsicmp(argv[1], _T("/reg_delmultisz"))) 2202 { 2203 if (argc < 5) 2204 { 2205 rc = EXIT_USAGE; 2206 } 2207 else 2208 { 2209 rc = RemoveStringFromMultiSZ(argv[2], argv[3], argv[4]); 2210 } 2211 } 2212 else if (0 == _tcsicmp(argv[1], _T("/createsvc"))) 2213 { 2214 if (argc < 7) 2215 { 2216 rc = EXIT_USAGE; 2217 } 2218 else 2219 { 2220 rc = CreateService( 2221 argv[2], 2222 argv[3], 2223 _ttoi(argv[4]), 2224 _ttoi(argv[5]), 2225 argv[6], 2226 (argc > 7) ? argv[7] : NULL, 2227 (argc > 8) ? argv[8] : NULL, 2228 (argc > 9) ? argv[9] : NULL, 2229 (argc > 10) ? argv[10] : NULL); 2230 } 2231 } 2232 else if (0 == _tcsicmp(argv[1], _T("/delsvc"))) 2233 { 2234 if (argc < 3) 2235 { 2236 rc = EXIT_USAGE; 2237 } 2238 else 2239 { 2240 rc = DelService(argv[2]); 2241 } 2242 } 2243 else if (0 == _tcsicmp(argv[1], _T("/registry"))) 2244 { 2245 if (argc < 8) 2246 { 2247 rc = EXIT_USAGE; 2248 } 2249 else 2250 { 2251 /** @todo add a handleRegistry(argc, argv) method to keep things cleaner */ 2252 if (0 == _tcsicmp(argv[2], _T("write"))) 2253 { 2254 HKEY hRootKey = HKEY_LOCAL_MACHINE; /** @todo needs to be expanded (argv[3]) */ 2255 DWORD dwValSize; 2256 BYTE *pbVal = NULL; 2257 DWORD dwVal; 2258 2259 if (argc > 8) 2260 { 2261 if (0 == _tcsicmp(argv[8], _T("dword"))) 2262 { 2263 dwVal = _ttol(argv[7]); 2264 pbVal = (BYTE*)&dwVal; 2265 dwValSize = sizeof(DWORD); 2266 } 2267 } 2268 if (pbVal == NULL) /* By default interpret value as string */ 2269 { 2270 pbVal = (BYTE*)argv[7]; 2271 dwValSize = _tcslen(argv[7]); 2272 } 2273 if (argc > 9) 2274 dwValSize = _ttol(argv[9]); /* Get the size in bytes of the value we want to write */ 2275 rc = RegistryWrite(hRootKey, 2276 argv[4], /* Sub key */ 2277 argv[5], /* Value name */ 2278 REG_BINARY, /** @todo needs to be expanded (argv[6]) */ 2279 pbVal, /* The value itself */ 2280 dwValSize); /* Size of the value */ 2281 } 2282 /*else if (0 == _tcsicmp(argv[2], _T("read"))) 2283 { 2284 } 2285 else if (0 == _tcsicmp(argv[2], _T("del"))) 2286 { 2287 }*/ 2288 else 2289 rc = EXIT_USAGE; 2290 } 2291 } 2292 #ifdef VBOX_WITH_WDDM 2293 else if (0 == _tcsicmp(argv[1], _T("/matchdrv"))) 2294 { 2295 if (argc < 4) 2296 { 2297 rc = EXIT_USAGE; 2298 } 2299 else 2300 { 2301 if (OSinfo.dwMajorVersion < 5) 2302 { 2303 _tprintf(_T("ERROR: Platform not supported yet!\n")); 2304 rc = ERROR_NOT_SUPPORTED; 2305 } 2306 2307 if (rc == ERROR_SUCCESS) 2308 { 2309 _stprintf(szHwID, _T("%ws"), argv[2]); 2310 rc = MatchDriver(szHwID, argv[3]); 2311 } 2312 } 2313 } 1146 if (argc > 9) 1147 dwValSize = _ttol(argv[9]); /* Get the size in bytes of the value we want to write */ 1148 rc = RegistryWrite(hRootKey, 1149 argv[4], /* Sub key */ 1150 argv[5], /* Value name */ 1151 REG_BINARY, /** @todo needs to be expanded (argv[6]) */ 1152 pbVal, /* The value itself */ 1153 dwValSize); /* Size of the value */ 1154 } 1155 #if 0 1156 else if (!_tcsicmp(argv[2], _T("read"))) 1157 { 1158 } 1159 else if (!_tcsicmp(argv[2], _T("del"))) 1160 { 1161 } 2314 1162 #endif 1163 } 1164 else if (!_tcsicmp(argv[1], _T("--version"))) 1165 { 1166 _tprintf(_T("%d.%d.%d.%d\n"), VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); 1167 rc = EXIT_OK; 1168 } 1169 else if ( !_tcsicmp(argv[1], _T("--help")) 1170 || !_tcsicmp(argv[1], _T("/help")) 1171 || !_tcsicmp(argv[1], _T("/h")) 1172 || !_tcsicmp(argv[1], _T("/?"))) 1173 { 1174 PrintHelp(); 1175 rc = EXIT_OK; 1176 } 2315 1177 } 2316 1178 2317 1179 if (rc == EXIT_USAGE) 2318 PrintHelp(); 2319 2320 FreeAPICalls(); 1180 _tprintf(_T("No or wrong parameters given! Please consult the help (\"--help\" or \"/?\") for more information.\n")); 1181 2321 1182 return rc; 2322 1183 } 1184
Note:
See TracChangeset
for help on using the changeset viewer.