1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: dll/cpl/desk/classinst.c
5 * PURPOSE: Class installers
6 *
7 * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.org)
8 */
9
10 #include "desk.h"
11
12 //#define NDEBUG
13 #include <debug.h>
14
15 DWORD WINAPI
DisplayClassInstaller(IN DI_FUNCTION InstallFunction,IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)16 DisplayClassInstaller(
17 IN DI_FUNCTION InstallFunction,
18 IN HDEVINFO DeviceInfoSet,
19 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
20 {
21 SP_DEVINSTALL_PARAMS InstallParams;
22 SP_DRVINFO_DATA DriverInfoData;
23 HINF hInf = INVALID_HANDLE_VALUE;
24 TCHAR SectionName[MAX_PATH];
25 TCHAR ServiceName[MAX_SERVICE_NAME_LEN];
26 TCHAR DeviceName[12];
27 SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
28 DISPLAY_DEVICE DisplayDevice;
29 HKEY hDriverKey = INVALID_HANDLE_VALUE; /* SetupDiOpenDevRegKey returns INVALID_HANDLE_VALUE in case of error! */
30 HKEY hSettingsKey = NULL;
31 HKEY hServicesKey = NULL;
32 HKEY hServiceKey = NULL;
33 HKEY hDeviceSubKey = NULL;
34 DWORD disposition, cchMax, cbData;
35 WORD wIndex;
36 BOOL result;
37 LONG rc;
38 HRESULT hr;
39
40 if (InstallFunction != DIF_INSTALLDEVICE)
41 return ERROR_DI_DO_DEFAULT;
42
43 /* Set DI_DONOTCALLCONFIGMG flag */
44 InstallParams.cbSize = sizeof(InstallParams);
45 result = SetupDiGetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &InstallParams);
46 if (!result)
47 {
48 rc = GetLastError();
49 DPRINT("SetupDiGetDeviceInstallParams() failed with error 0x%lx\n", rc);
50 goto cleanup;
51 }
52
53 InstallParams.Flags |= DI_DONOTCALLCONFIGMG;
54
55 result = SetupDiSetDeviceInstallParams(DeviceInfoSet, DeviceInfoData, &InstallParams);
56 if (!result)
57 {
58 rc = GetLastError();
59 DPRINT("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", rc);
60 goto cleanup;
61 }
62
63 /* Do normal install */
64 result = SetupDiInstallDevice(DeviceInfoSet, DeviceInfoData);
65 if (!result)
66 {
67 rc = GetLastError();
68 DPRINT("SetupDiInstallDevice() failed with error 0x%lx\n", rc);
69 goto cleanup;
70 }
71
72 /* Get .inf file name and section name */
73 DriverInfoData.cbSize = sizeof(DriverInfoData);
74 result = SetupDiGetSelectedDriver(DeviceInfoSet, DeviceInfoData, &DriverInfoData);
75 if (!result)
76 {
77 rc = GetLastError();
78 DPRINT("SetupDiGetSelectedDriver() failed with error 0x%lx\n", rc);
79 goto cleanup;
80 }
81
82 DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
83 result = SetupDiGetDriverInfoDetail(DeviceInfoSet, DeviceInfoData,
84 &DriverInfoData, &DriverInfoDetailData,
85 sizeof(DriverInfoDetailData), NULL);
86 if (!result && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
87 {
88 rc = GetLastError();
89 DPRINT("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", rc);
90 goto cleanup;
91 }
92
93 hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName, NULL, INF_STYLE_WIN4, NULL);
94 if (hInf == INVALID_HANDLE_VALUE)
95 {
96 rc = GetLastError();
97 DPRINT("SetupOpenInfFile() failed with error 0x%lx\n", rc);
98 goto cleanup;
99 }
100
101 cchMax = MAX_PATH - (sizeof(_T(".SoftwareSettings")) / sizeof(TCHAR));
102 result = SetupDiGetActualSectionToInstall(hInf,
103 DriverInfoDetailData.SectionName,
104 SectionName,
105 cchMax,
106 NULL,
107 NULL);
108 if (!result)
109 {
110 rc = GetLastError();
111 DPRINT("SetupDiGetActualSectionToInstall() failed with error 0x%lx\n", rc);
112 goto cleanup;
113 }
114 hr = StringCbCat(SectionName, sizeof(SectionName), _T(".SoftwareSettings"));
115 if (FAILED(hr))
116 {
117 rc = ERROR_INSUFFICIENT_BUFFER;
118 goto cleanup;
119 }
120
121 /* Open driver registry key and create Settings subkey */
122 hDriverKey = SetupDiOpenDevRegKey(
123 DeviceInfoSet, DeviceInfoData,
124 DICS_FLAG_GLOBAL, 0, DIREG_DRV,
125 KEY_CREATE_SUB_KEY);
126 if (hDriverKey == INVALID_HANDLE_VALUE)
127 {
128 rc = GetLastError();
129 DPRINT("SetupDiOpenDevRegKey() failed with error 0x%lx\n", rc);
130 goto cleanup;
131 }
132 rc = RegCreateKeyEx(
133 hDriverKey, L"Settings",
134 0, NULL, REG_OPTION_NON_VOLATILE,
135 #if _WIN32_WINNT >= 0x502
136 KEY_READ | KEY_WRITE,
137 #else
138 KEY_ALL_ACCESS,
139 #endif
140 NULL, &hSettingsKey, &disposition);
141 if (rc != ERROR_SUCCESS)
142 {
143 DPRINT("RegCreateKeyEx() failed with error 0x%lx\n", rc);
144 goto cleanup;
145 }
146
147 /* Install .SoftwareSettings to Settings subkey */
148 result = SetupInstallFromInfSection(
149 InstallParams.hwndParent, hInf, SectionName,
150 SPINST_REGISTRY, hSettingsKey,
151 NULL, 0, NULL, NULL,
152 NULL, NULL);
153 if (!result)
154 {
155 rc = GetLastError();
156 DPRINT("SetupInstallFromInfSection() failed with error 0x%lx\n", rc);
157 goto cleanup;
158 }
159
160 /* Get service name and open service registry key */
161 result = SetupDiGetDeviceRegistryProperty(
162 DeviceInfoSet, DeviceInfoData,
163 SPDRP_SERVICE, NULL,
164 (PBYTE)ServiceName, MAX_SERVICE_NAME_LEN * sizeof(TCHAR), NULL);
165 if (!result)
166 {
167 rc = GetLastError();
168 DPRINT("SetupDiGetDeviceRegistryProperty() failed with error 0x%lx\n", rc);
169 goto cleanup;
170 }
171
172 rc = RegOpenKeyEx(
173 HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services"),
174 0, KEY_ENUMERATE_SUB_KEYS, &hServicesKey);
175 if (rc != ERROR_SUCCESS)
176 {
177 DPRINT("RegOpenKeyEx() failed with error 0x%lx\n", rc);
178 goto cleanup;
179 }
180 rc = RegOpenKeyEx(
181 hServicesKey, ServiceName,
182 0, KEY_CREATE_SUB_KEY, &hServiceKey);
183 if (rc != ERROR_SUCCESS)
184 {
185 DPRINT("RegOpenKeyEx() failed with error 0x%lx\n", rc);
186 goto cleanup;
187 }
188
189 /* Create a new DeviceX subkey */
190 for (wIndex = 0; wIndex < 9999; wIndex++)
191 {
192 _stprintf(DeviceName, _T("Device%hu"), wIndex);
193
194 rc = RegCreateKeyEx(
195 hServiceKey, DeviceName, 0, NULL,
196 REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,
197 &hDeviceSubKey, &disposition);
198 if (rc != ERROR_SUCCESS)
199 {
200 DPRINT("RegCreateKeyEx() failed with error 0x%lx\n", rc);
201 goto cleanup;
202 }
203
204 if (disposition == REG_CREATED_NEW_KEY)
205 break;
206
207 if (wIndex == 9999)
208 {
209 rc = ERROR_GEN_FAILURE;
210 DPRINT("RegCreateKeyEx() failed\n");
211 goto cleanup;
212 }
213
214 RegCloseKey(hDeviceSubKey);
215 hDeviceSubKey = NULL;
216 }
217
218 /* Install SoftwareSettings section */
219 /* Yes, we're installing this section for the second time.
220 * We don't want to create a link to Settings subkey */
221 result = SetupInstallFromInfSection(
222 InstallParams.hwndParent, hInf, SectionName,
223 SPINST_REGISTRY, hDeviceSubKey,
224 NULL, 0, NULL, NULL,
225 NULL, NULL);
226 if (!result)
227 {
228 rc = GetLastError();
229 DPRINT("SetupInstallFromInfSection() failed with error 0x%lx\n", rc);
230 goto cleanup;
231 }
232
233 /* Add Device Description string */
234 cbData = (DWORD)(_tcslen(DriverInfoData.Description) + 1) * sizeof(TCHAR);
235 rc = RegSetValueEx(hDeviceSubKey,
236 _T("Device Description"),
237 0,
238 REG_SZ,
239 (const BYTE*)DriverInfoData.Description,
240 cbData);
241 if (rc != ERROR_SUCCESS)
242 {
243 DPRINT("RegSetValueEx() failed with error 0x%lx\n", rc);
244 goto cleanup;
245 }
246
247 /* FIXME: install OpenGLSoftwareSettings section */
248
249 /* Reenumerate display devices ; this will rescan for potential new devices */
250 DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
251 EnumDisplayDevices(NULL, 0, &DisplayDevice, 0);
252
253 rc = ERROR_SUCCESS;
254
255 cleanup:
256 if (hInf != INVALID_HANDLE_VALUE)
257 SetupCloseInfFile(hInf);
258 if (hDriverKey != INVALID_HANDLE_VALUE)
259 {
260 /* SetupDiOpenDevRegKey returns INVALID_HANDLE_VALUE in case of error! */
261 RegCloseKey(hDriverKey);
262 }
263 if (hSettingsKey != NULL)
264 RegCloseKey(hSettingsKey);
265 if (hServicesKey != NULL)
266 RegCloseKey(hServicesKey);
267 if (hServiceKey != NULL)
268 RegCloseKey(hServiceKey);
269 if (hDeviceSubKey != NULL)
270 RegCloseKey(hDeviceSubKey);
271
272 return rc;
273 }
274
275 DWORD WINAPI
MonitorClassInstaller(IN DI_FUNCTION InstallFunction,IN HDEVINFO DeviceInfoSet,IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)276 MonitorClassInstaller(
277 IN DI_FUNCTION InstallFunction,
278 IN HDEVINFO DeviceInfoSet,
279 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
280 {
281 return ERROR_DI_DO_DEFAULT;
282 }
283