xref: /reactos/dll/cpl/desk/classinst.c (revision 5696e4ba)
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
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
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