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