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 | --*/
|
---|
15 |
|
---|
16 | #ifndef UNICODE
|
---|
17 | #define UNICODE
|
---|
18 | #endif
|
---|
19 |
|
---|
20 | #include <VBox/version.h>
|
---|
21 |
|
---|
22 | #include <windows.h>
|
---|
23 | #include <setupapi.h>
|
---|
24 | #include <newdev.h>
|
---|
25 | #include <regstr.h>
|
---|
26 | #include <cfgmgr32.h>
|
---|
27 | #include <devguid.h>
|
---|
28 | #include <stdio.h>
|
---|
29 | #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 | */
|
---|
57 |
|
---|
58 | /* Exit codes */
|
---|
59 | #define EXIT_OK (0)
|
---|
60 | #define EXIT_REBOOT (1)
|
---|
61 | #define EXIT_FAIL (2)
|
---|
62 | #define EXIT_USAGE (3)
|
---|
63 | #ifdef VBOX_WITH_WDDM
|
---|
64 | #define EXIT_FALSE (4)
|
---|
65 | #endif
|
---|
66 |
|
---|
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);
|
---|
269 | return false;
|
---|
270 | }
|
---|
271 | else
|
---|
272 | {
|
---|
273 | _TCHAR* p = _tcschr(a_pszMsg, _T('\r'));
|
---|
274 |
|
---|
275 | if (p != NULL)
|
---|
276 | *p = _T('\0');
|
---|
277 | }
|
---|
278 |
|
---|
279 | return true;
|
---|
280 | }
|
---|
281 |
|
---|
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 | }
|
---|
384 | 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());
|
---|
391 | }
|
---|
392 | else
|
---|
393 | {
|
---|
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 |
|
---|
409 | _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))
|
---|
432 | {
|
---|
433 | dwErr = GetLastError();
|
---|
434 | GetErrorMsg(dwErr, szErrMsg, sizeof(szErrMsg));
|
---|
435 | _tprintf(_T("ERROR (%08x): %ws\n"), dwErr, szErrMsg);
|
---|
436 |
|
---|
437 | rc = EXIT_FAIL;
|
---|
438 | }
|
---|
439 | else
|
---|
440 | _tprintf(_T("OK. Installed to: %ws\n"), szDestInf);
|
---|
441 | }
|
---|
442 | else
|
---|
443 | {
|
---|
444 | switch (dwErr)
|
---|
445 | {
|
---|
446 |
|
---|
447 | case ERROR_INVALID_FLAGS:
|
---|
448 |
|
---|
449 | _tprintf(_T("ERROR: The value specified for InstallFlags is invalid!\n"));
|
---|
450 | break;
|
---|
451 |
|
---|
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"));
|
---|
457 | break;
|
---|
458 |
|
---|
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]))
|
---|
1000 | {
|
---|
1001 | match = TRUE;
|
---|
1002 | }
|
---|
1003 | }
|
---|
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 |
|
---|
1172 | #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);
|
---|
1566 |
|
---|
1567 | /* Executed by the installer that already has proper privileges. */
|
---|
1568 | _TCHAR szCommandLine[_MAX_PATH + 1] = { 0 };
|
---|
1569 | swprintf(szCommandLine, sizeof(szCommandLine), TEXT( "%ws %d %ws" ), a_pszSection, a_iMode, a_pszInf);
|
---|
1570 |
|
---|
1571 | #ifdef _DEBUG
|
---|
1572 | _tprintf (_T( "Commandline: %ws\n"), szCommandLine);
|
---|
1573 | #endif
|
---|
1574 |
|
---|
1575 | InstallHinfSection(NULL, NULL, szCommandLine, SW_SHOW);
|
---|
1576 |
|
---|
1577 | return EXIT_OK;
|
---|
1578 | }
|
---|
1579 |
|
---|
1580 | int AddNetworkProvider (TCHAR* a_pszProvider, int a_iOrder)
|
---|
1581 | {
|
---|
1582 | TCHAR szKeyValue[512] = { 0 };
|
---|
1583 | TCHAR szNewKeyValue[512] = { 0 };
|
---|
1584 | HKEY hKey = NULL;
|
---|
1585 | 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 | {
|
---|
1676 | TCHAR szKeyValue[512] = { 0 };
|
---|
1677 | 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 | DWORD cbKeyValue = sizeof(szKeyValue);
|
---|
1691 |
|
---|
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 |
|
---|
1758 | return rc;
|
---|
1759 | }
|
---|
1760 |
|
---|
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 |
|
---|
1843 | return rc;
|
---|
1844 | }
|
---|
1845 |
|
---|
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)
|
---|
1855 | {
|
---|
1856 | int rc = ERROR_SUCCESS;
|
---|
1857 |
|
---|
1858 | _tprintf(_T("Installing service %ws (%ws) ...\n"), a_pszDisplayName, a_pszStartStopName);
|
---|
1859 |
|
---|
1860 | SC_HANDLE hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
---|
1861 | if (hSCManager == NULL)
|
---|
1862 | {
|
---|
1863 | _tprintf(_T("Could not get handle to SCM! Error: %ld\n"), GetLastError());
|
---|
1864 | return EXIT_FAIL;
|
---|
1865 | }
|
---|
1866 |
|
---|
1867 | /* Fixup end of multistring */
|
---|
1868 | TCHAR szDepend[ _MAX_PATH ] = { 0 }; /* @todo Use dynamically allocated string here! */
|
---|
1869 | if (a_pszDependencies != NULL)
|
---|
1870 | {
|
---|
1871 | _tcsnccpy (szDepend, a_pszDependencies, wcslen(a_pszDependencies));
|
---|
1872 | DWORD len = (DWORD)wcslen (szDepend);
|
---|
1873 | szDepend [len + 1] = 0;
|
---|
1874 |
|
---|
1875 | /* Replace comma separator on null separator */
|
---|
1876 | for (DWORD i = 0; i < len; i++)
|
---|
1877 | {
|
---|
1878 | if (',' == szDepend [i])
|
---|
1879 | szDepend [i] = 0;
|
---|
1880 | }
|
---|
1881 | }
|
---|
1882 |
|
---|
1883 | DWORD dwTag = 0xDEADBEAF;
|
---|
1884 | SC_HANDLE hService = CreateService (hSCManager, // SCManager database
|
---|
1885 | a_pszStartStopName, // name of service
|
---|
1886 | a_pszDisplayName, // name to display
|
---|
1887 | SERVICE_ALL_ACCESS, // desired access
|
---|
1888 | a_iServiceType, // service type
|
---|
1889 | a_iStartType, // start type
|
---|
1890 | SERVICE_ERROR_NORMAL, // error control type
|
---|
1891 | a_pszBinPath, // service's binary
|
---|
1892 | a_pszLoadOrderGroup, // ordering group
|
---|
1893 | (a_pszLoadOrderGroup != NULL) ? &dwTag : NULL, // tag identifier
|
---|
1894 | (a_pszDependencies != NULL) ? szDepend : NULL, // dependencies
|
---|
1895 | (a_pszLogonUser != NULL) ? a_pszLogonUser: NULL, // account
|
---|
1896 | (a_pszLogonPw != NULL) ? a_pszLogonPw : NULL); // password
|
---|
1897 | if (NULL == hService)
|
---|
1898 | {
|
---|
1899 | DWORD dwErr = GetLastError();
|
---|
1900 | switch (dwErr)
|
---|
1901 | {
|
---|
1902 |
|
---|
1903 | case ERROR_SERVICE_EXISTS:
|
---|
1904 | {
|
---|
1905 | _tprintf(_T("Service already exists. No installation required. Updating the service config.\n"));
|
---|
1906 |
|
---|
1907 | hService = OpenService (hSCManager, // SCManager database
|
---|
1908 | a_pszStartStopName, // name of service
|
---|
1909 | SERVICE_ALL_ACCESS); // desired access
|
---|
1910 | if (NULL == hService)
|
---|
1911 | {
|
---|
1912 | dwErr = GetLastError();
|
---|
1913 | _tprintf(_T("Could not open service! Error: %ld\n"), dwErr);
|
---|
1914 | }
|
---|
1915 | else
|
---|
1916 | {
|
---|
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 | {
|
---|
1930 | _tprintf(_T("The service config has been successfully updated.\n"));
|
---|
1931 | }
|
---|
1932 | else
|
---|
1933 | {
|
---|
1934 | dwErr = GetLastError();
|
---|
1935 | _tprintf(_T("Could not change service config! Error: %ld\n"), dwErr);
|
---|
1936 | }
|
---|
1937 |
|
---|
1938 | CloseServiceHandle (hService);
|
---|
1939 | }
|
---|
1940 |
|
---|
1941 | /* This entire branch do not return an error to avoid installations failures,
|
---|
1942 | * if updating service parameters. Better to have a running system with old
|
---|
1943 | * parameters and the failure information in the installation log.
|
---|
1944 | */
|
---|
1945 | break;
|
---|
1946 | }
|
---|
1947 |
|
---|
1948 | case ERROR_INVALID_PARAMETER:
|
---|
1949 |
|
---|
1950 | _tprintf(_T("Invalid parameter specified!\n"));
|
---|
1951 | rc = EXIT_FAIL;
|
---|
1952 | break;
|
---|
1953 |
|
---|
1954 | default:
|
---|
1955 |
|
---|
1956 | _tprintf(_T("Could not create service! Error: %ld\n"), dwErr);
|
---|
1957 | rc = EXIT_FAIL;
|
---|
1958 | break;
|
---|
1959 | }
|
---|
1960 |
|
---|
1961 | if (rc == EXIT_FAIL)
|
---|
1962 | goto cleanup;
|
---|
1963 | }
|
---|
1964 | else
|
---|
1965 | {
|
---|
1966 | CloseServiceHandle (hService);
|
---|
1967 | _tprintf(_T("Installation of service successful!\n"));
|
---|
1968 | }
|
---|
1969 |
|
---|
1970 | cleanup:
|
---|
1971 |
|
---|
1972 | if (hSCManager != NULL)
|
---|
1973 | CloseServiceHandle (hSCManager);
|
---|
1974 |
|
---|
1975 | return rc;
|
---|
1976 | }
|
---|
1977 |
|
---|
1978 | int DelService (TCHAR* a_pszStartStopName)
|
---|
1979 | {
|
---|
1980 | int rc = ERROR_SUCCESS;
|
---|
1981 |
|
---|
1982 | _tprintf(_T("Deleting service '%ws' ...\n"), a_pszStartStopName);
|
---|
1983 |
|
---|
1984 | SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
---|
1985 | SC_HANDLE hService = NULL;
|
---|
1986 | if (hSCManager == NULL)
|
---|
1987 | {
|
---|
1988 | _tprintf(_T("Could not get handle to SCM! Error: %ld\n"), GetLastError());
|
---|
1989 | rc = EXIT_FAIL;
|
---|
1990 | }
|
---|
1991 | else
|
---|
1992 | {
|
---|
1993 | hService = OpenService(hSCManager, a_pszStartStopName, SERVICE_ALL_ACCESS);
|
---|
1994 | if (NULL == hService)
|
---|
1995 | {
|
---|
1996 | _tprintf(_T("Could not open service '%ws'! Error: %ld\n"), a_pszStartStopName, GetLastError());
|
---|
1997 | rc = EXIT_FAIL;
|
---|
1998 | }
|
---|
1999 | }
|
---|
2000 |
|
---|
2001 | if (hService != NULL)
|
---|
2002 | {
|
---|
2003 | if (LockServiceDatabase(hSCManager))
|
---|
2004 | {
|
---|
2005 | if (FALSE == DeleteService(hService))
|
---|
2006 | {
|
---|
2007 | DWORD dwErr = GetLastError();
|
---|
2008 | switch (dwErr)
|
---|
2009 | {
|
---|
2010 |
|
---|
2011 | case ERROR_SERVICE_MARKED_FOR_DELETE:
|
---|
2012 |
|
---|
2013 | _tprintf(_T("Service '%ws' already marked for deletion.\n"), a_pszStartStopName);
|
---|
2014 | break;
|
---|
2015 |
|
---|
2016 | default:
|
---|
2017 |
|
---|
2018 | _tprintf(_T("Could not delete service '%ws'! Error: %ld\n"), a_pszStartStopName, GetLastError());
|
---|
2019 | rc = EXIT_FAIL;
|
---|
2020 | break;
|
---|
2021 | }
|
---|
2022 | }
|
---|
2023 | else
|
---|
2024 | {
|
---|
2025 | _tprintf(_T("Service '%ws' successfully removed!\n"), a_pszStartStopName);
|
---|
2026 | }
|
---|
2027 | UnlockServiceDatabase(hSCManager);
|
---|
2028 | }
|
---|
2029 | else
|
---|
2030 | {
|
---|
2031 | _tprintf(_T("Unable to lock service database! Error: %ld\n"), GetLastError());
|
---|
2032 | rc = EXIT_FAIL;
|
---|
2033 | }
|
---|
2034 | CloseServiceHandle(hService);
|
---|
2035 | }
|
---|
2036 |
|
---|
2037 | if (hSCManager != NULL)
|
---|
2038 | CloseServiceHandle(hSCManager);
|
---|
2039 |
|
---|
2040 | return rc;
|
---|
2041 | }
|
---|
2042 |
|
---|
2043 | DWORD RegistryWrite(HKEY hRootKey,
|
---|
2044 | const _TCHAR *pszSubKey,
|
---|
2045 | const _TCHAR *pszValueName,
|
---|
2046 | DWORD dwType,
|
---|
2047 | const BYTE *pbData,
|
---|
2048 | DWORD cbData)
|
---|
2049 | {
|
---|
2050 | DWORD lRet;
|
---|
2051 | HKEY hKey;
|
---|
2052 | lRet = RegCreateKeyEx (hRootKey,
|
---|
2053 | pszSubKey,
|
---|
2054 | 0, /* Reserved */
|
---|
2055 | NULL, /* lpClass [in, optional] */
|
---|
2056 | 0, /* dwOptions [in] */
|
---|
2057 | KEY_WRITE,
|
---|
2058 | NULL, /* lpSecurityAttributes [in, optional] */
|
---|
2059 | &hKey,
|
---|
2060 | NULL); /* lpdwDisposition [out, optional] */
|
---|
2061 | if (lRet != ERROR_SUCCESS)
|
---|
2062 | {
|
---|
2063 | _tprintf(_T("Could not open registry key! Error: %ld\n"), GetLastError());
|
---|
2064 | }
|
---|
2065 | else
|
---|
2066 | {
|
---|
2067 | lRet = RegSetValueEx(hKey, pszValueName, 0, dwType, (BYTE*)pbData, cbData);
|
---|
2068 | if (lRet != ERROR_SUCCESS)
|
---|
2069 | _tprintf(_T("Could not write to registry! Error: %ld\n"), GetLastError());
|
---|
2070 | RegCloseKey(hKey);
|
---|
2071 |
|
---|
2072 | }
|
---|
2073 | return lRet;
|
---|
2074 | }
|
---|
2075 |
|
---|
2076 | void PrintHelp (void)
|
---|
2077 | {
|
---|
2078 | _tprintf(_T("Installs / Uninstalls VirtualBox drivers for Windows XP/2K/Vista\n"));
|
---|
2079 | _tprintf(_T("Version: %d.%d.%d.%d\n\n"), VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
|
---|
2080 | _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;
|
---|
2094 | 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
|
---|
2115 | {
|
---|
2116 | if (OSinfo.dwMajorVersion < 5)
|
---|
2117 | {
|
---|
2118 | _tprintf(_T("ERROR: Platform not supported yet!\n"));
|
---|
2119 | rc = ERROR_NOT_SUPPORTED;
|
---|
2120 | }
|
---|
2121 |
|
---|
2122 | if (rc == ERROR_SUCCESS)
|
---|
2123 | {
|
---|
2124 | _stprintf(szHwID, _T("%ws"), argv[2]);
|
---|
2125 | _stprintf(szINF, _T("%ws"), argv[3]);
|
---|
2126 | _stprintf(szDevClass, _T("%ws"), argv[4]);
|
---|
2127 |
|
---|
2128 | rc = InstallDriver(szINF, szHwID, szDevClass);
|
---|
2129 | }
|
---|
2130 | }
|
---|
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)
|
---|
2141 | {
|
---|
2142 | _tprintf(_T("ERROR: Platform not supported yet!\n"));
|
---|
2143 | rc = ERROR_NOT_SUPPORTED;
|
---|
2144 | }
|
---|
2145 |
|
---|
2146 | if (rc == ERROR_SUCCESS)
|
---|
2147 | {
|
---|
2148 | _stprintf(szHwID, _T("%ws"), argv[2]);
|
---|
2149 | rc = UninstallDriver(szHwID);
|
---|
2150 | }
|
---|
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 | }
|
---|
2314 | #endif
|
---|
2315 | }
|
---|
2316 |
|
---|
2317 | if (rc == EXIT_USAGE)
|
---|
2318 | PrintHelp();
|
---|
2319 |
|
---|
2320 | FreeAPICalls();
|
---|
2321 | return rc;
|
---|
2322 | }
|
---|