Sync to trunk revision 63922.
[reactos.git] / dll / cpl / desk / classinst.c
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;
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(SP_DEVINSTALL_PARAMS);
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(SP_DRVINFO_DATA);
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(SP_DRVINFO_DETAIL_DATA);
80 result = SetupDiGetDriverInfoDetail(
81 DeviceInfoSet, DeviceInfoData,
82 &DriverInfoData, &DriverInfoDetailData,
83 sizeof(SP_DRVINFO_DETAIL_DATA), NULL);
84 if (!result && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
85 {
86 rc = GetLastError();
87 DPRINT("SetupDiGetDriverInfoDetail() failed with error 0x%lx\n", rc);
88 goto cleanup;
89 }
90
91 hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName, NULL, INF_STYLE_WIN4, NULL);
92 if (hInf == INVALID_HANDLE_VALUE)
93 {
94 rc = GetLastError();
95 DPRINT("SetupOpenInfFile() failed with error 0x%lx\n", rc);
96 goto cleanup;
97 }
98
99 result = SetupDiGetActualSectionToInstall(
100 hInf, DriverInfoDetailData.SectionName,
101 SectionName, MAX_PATH - _tcslen(_T(".SoftwareSettings")), NULL, NULL);
102 if (!result)
103 {
104 rc = GetLastError();
105 DPRINT("SetupDiGetActualSectionToInstall() failed with error 0x%lx\n", rc);
106 goto cleanup;
107 }
108 hr = StringCbCat(SectionName, sizeof(SectionName), _T(".SoftwareSettings"));
109 if (FAILED(hr))
110 {
111 rc = ERROR_INSUFFICIENT_BUFFER;
112 goto cleanup;
113 }
114
115 /* Open driver registry key and create Settings subkey */
116 hDriverKey = SetupDiOpenDevRegKey(
117 DeviceInfoSet, DeviceInfoData,
118 DICS_FLAG_GLOBAL, 0, DIREG_DRV,
119 KEY_CREATE_SUB_KEY);
120 if (hDriverKey == INVALID_HANDLE_VALUE)
121 {
122 rc = GetLastError();
123 DPRINT("SetupDiOpenDevRegKey() failed with error 0x%lx\n", rc);
124 goto cleanup;
125 }
126 rc = RegCreateKeyEx(
127 hDriverKey, L"Settings",
128 0, NULL, REG_OPTION_NON_VOLATILE,
129 #if _WIN32_WINNT >= 0x502
130 KEY_READ | KEY_WRITE,
131 #else
132 KEY_ALL_ACCESS,
133 #endif
134 NULL, &hSettingsKey, &disposition);
135 if (rc != ERROR_SUCCESS)
136 {
137 DPRINT("RegCreateKeyEx() failed with error 0x%lx\n", rc);
138 goto cleanup;
139 }
140
141 /* Install .SoftwareSettings to Settings subkey */
142 result = SetupInstallFromInfSection(
143 InstallParams.hwndParent, hInf, SectionName,
144 SPINST_REGISTRY, hSettingsKey,
145 NULL, 0, NULL, NULL,
146 NULL, NULL);
147 if (!result)
148 {
149 rc = GetLastError();
150 DPRINT("SetupInstallFromInfSection() failed with error 0x%lx\n", rc);
151 goto cleanup;
152 }
153
154 /* Get service name and open service registry key */
155 result = SetupDiGetDeviceRegistryProperty(
156 DeviceInfoSet, DeviceInfoData,
157 SPDRP_SERVICE, NULL,
158 (PBYTE)ServiceName, MAX_SERVICE_NAME_LEN * sizeof(TCHAR), NULL);
159 if (!result)
160 {
161 rc = GetLastError();
162 DPRINT("SetupDiGetDeviceRegistryProperty() failed with error 0x%lx\n", rc);
163 goto cleanup;
164 }
165
166 rc = RegOpenKeyEx(
167 HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services"),
168 0, KEY_ENUMERATE_SUB_KEYS, &hServicesKey);
169 if (rc != ERROR_SUCCESS)
170 {
171 DPRINT("RegOpenKeyEx() failed with error 0x%lx\n", rc);
172 goto cleanup;
173 }
174 rc = RegOpenKeyEx(
175 hServicesKey, ServiceName,
176 0, KEY_CREATE_SUB_KEY, &hServiceKey);
177 if (rc != ERROR_SUCCESS)
178 {
179 DPRINT("RegOpenKeyEx() failed with error 0x%lx\n", rc);
180 goto cleanup;
181 }
182
183 /* Create a Device0 subkey (FIXME: do a loop to find a free number?) */
184 rc = RegCreateKeyEx(
185 hServiceKey, _T("Device0"), 0, NULL,
186 REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,
187 &hDeviceSubKey, &disposition);
188 if (rc != ERROR_SUCCESS)
189 {
190 DPRINT("RegCreateKeyEx() failed with error 0x%lx\n", rc);
191 goto cleanup;
192 }
193 if (disposition != REG_CREATED_NEW_KEY)
194 {
195 rc = ERROR_GEN_FAILURE;
196 DPRINT("RegCreateKeyEx() failed\n");
197 goto cleanup;
198 }
199
200 /* Install SoftwareSettings section */
201 /* Yes, we're installing this section for the second time.
202 * We don't want to create a link to Settings subkey */
203 result = SetupInstallFromInfSection(
204 InstallParams.hwndParent, hInf, SectionName,
205 SPINST_REGISTRY, hDeviceSubKey,
206 NULL, 0, NULL, NULL,
207 NULL, NULL);
208 if (!result)
209 {
210 rc = GetLastError();
211 DPRINT("SetupInstallFromInfSection() failed with error 0x%lx\n", rc);
212 goto cleanup;
213 }
214 /* Add Device Description string */
215 rc = RegSetValueEx(hDeviceSubKey, _T("Device Description"), 0,
216 REG_SZ, (const BYTE*)DriverInfoData.Description,
217 (_tcslen(DriverInfoData.Description) + 1) * sizeof(TCHAR));
218 if (rc != ERROR_SUCCESS)
219 {
220 DPRINT("RegSetValueEx() failed with error 0x%lx\n", rc);
221 goto cleanup;
222 }
223
224 /* FIXME: install OpenGLSoftwareSettings section */
225
226 rc = ERROR_SUCCESS;
227
228 cleanup:
229 if (hInf != INVALID_HANDLE_VALUE)
230 SetupCloseInfFile(hInf);
231 if (hDriverKey != INVALID_HANDLE_VALUE)
232 {
233 /* SetupDiOpenDevRegKey returns INVALID_HANDLE_VALUE in case of error! */
234 RegCloseKey(hDriverKey);
235 }
236 if (hSettingsKey != NULL)
237 RegCloseKey(hSettingsKey);
238 if (hServicesKey != NULL)
239 RegCloseKey(hServicesKey);
240 if (hServiceKey != NULL)
241 RegCloseKey(hServiceKey);
242 if (hDeviceSubKey != NULL)
243 RegCloseKey(hDeviceSubKey);
244
245 return rc;
246 }