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