1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: System setup
5 * FILE: dll/win32/syssetup/netinstall.c
6 * PROGRAMER: Eric Kohl
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "precomp.h"
12
13 #include <rpc.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 typedef struct _COMPONENT_INFO
19 {
20 PWSTR pszInfPath;
21 PWSTR pszInfSection;
22 PWSTR pszComponentId;
23 PWSTR pszDescription;
24 PWSTR pszClassGuid;
25 DWORD dwCharacteristics;
26 } COMPONENT_INFO, *PCOMPONENT_INFO;
27
28
29 /* GLOBALS ******************************************************************/
30
31
32 /* FUNCTIONS ****************************************************************/
33
34 static
35 BOOL
InstallInfSections(_In_ HWND hWnd,_In_ HKEY hKey,_In_ LPCWSTR InfFile,_In_ LPCWSTR InfSection)36 InstallInfSections(
37 _In_ HWND hWnd,
38 _In_ HKEY hKey,
39 _In_ LPCWSTR InfFile,
40 _In_ LPCWSTR InfSection)
41 {
42 WCHAR Buffer[MAX_PATH];
43 HINF hInf = INVALID_HANDLE_VALUE;
44 UINT BufferSize;
45 PVOID Context = NULL;
46 BOOL ret = FALSE;
47
48 DPRINT("InstallInfSections()\n");
49
50 if (InfSection == NULL)
51 return FALSE;
52
53 /* Get Windows directory */
54 BufferSize = ARRAYSIZE(Buffer) - 5 - wcslen(InfFile);
55 if (GetWindowsDirectoryW(Buffer, BufferSize) > BufferSize)
56 {
57 /* Function failed */
58 SetLastError(ERROR_GEN_FAILURE);
59 goto cleanup;
60 }
61
62 /* We have enough space to add some information in the buffer */
63 if (Buffer[wcslen(Buffer) - 1] != '\\')
64 wcscat(Buffer, L"\\");
65 wcscat(Buffer, L"Inf\\");
66 wcscat(Buffer, InfFile);
67
68 /* Install specified section */
69 hInf = SetupOpenInfFileW(Buffer, NULL, INF_STYLE_WIN4, NULL);
70 if (hInf == INVALID_HANDLE_VALUE)
71 goto cleanup;
72
73 Context = SetupInitDefaultQueueCallback(hWnd);
74 if (Context == NULL)
75 goto cleanup;
76
77 ret = SetupInstallFromInfSectionW(
78 hWnd, hInf,
79 InfSection, SPINST_ALL,
80 hKey, NULL, SP_COPY_NEWER,
81 SetupDefaultQueueCallbackW, Context,
82 NULL, NULL);
83 if (ret == FALSE)
84 {
85 DPRINT1("SetupInstallFromInfSectionW(%S) failed (Error %lx)\n", InfSection, GetLastError());
86 goto cleanup;
87 }
88
89 wcscpy(Buffer, InfSection);
90 wcscat(Buffer, L".Services");
91
92 ret = SetupInstallServicesFromInfSectionW(hInf, Buffer, 0);
93 if (ret == FALSE)
94 {
95 DPRINT1("SetupInstallServicesFromInfSectionW(%S) failed (Error %lx)\n", Buffer, GetLastError());
96 goto cleanup;
97 }
98
99 cleanup:
100 if (Context)
101 SetupTermDefaultQueueCallback(Context);
102
103 if (hInf != INVALID_HANDLE_VALUE)
104 SetupCloseInfFile(hInf);
105
106 DPRINT("InstallInfSections() done %u\n", ret);
107
108 return ret;
109 }
110
111
112 static
113 BOOL
CreateInstanceKey(_In_ PCOMPONENT_INFO pComponentInfo,_Out_ PHKEY pInstanceKey)114 CreateInstanceKey(
115 _In_ PCOMPONENT_INFO pComponentInfo,
116 _Out_ PHKEY pInstanceKey)
117 {
118 WCHAR szKeyBuffer[128];
119 LPWSTR UuidString = NULL;
120 UUID Uuid;
121 RPC_STATUS RpcStatus;
122 HKEY hInstanceKey;
123 DWORD rc;
124 BOOL ret = FALSE;
125
126 DPRINT("CreateInstanceKey()\n");
127
128 *pInstanceKey = NULL;
129
130 wcscpy(szKeyBuffer, L"SYSTEM\\CurrentControlSet\\Control\\Network\\");
131 wcscat(szKeyBuffer, pComponentInfo->pszClassGuid);
132 wcscat(szKeyBuffer, L"\\{");
133
134 /* Create a new UUID */
135 RpcStatus = UuidCreate(&Uuid);
136 if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
137 {
138 DPRINT1("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
139 goto done;
140 }
141
142 RpcStatus = UuidToStringW(&Uuid, &UuidString);
143 if (RpcStatus != RPC_S_OK)
144 {
145 DPRINT1("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
146 goto done;
147 }
148
149 wcscat(szKeyBuffer, UuidString);
150 wcscat(szKeyBuffer, L"}");
151
152 RpcStringFreeW(&UuidString);
153
154 DPRINT("szKeyBuffer %S\n", szKeyBuffer);
155
156 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
157 szKeyBuffer,
158 0,
159 NULL,
160 REG_OPTION_NON_VOLATILE,
161 KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
162 NULL,
163 &hInstanceKey,
164 NULL);
165 if (rc != ERROR_SUCCESS)
166 {
167 DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
168 goto done;
169 }
170
171 rc = RegSetValueExW(hInstanceKey,
172 L"Characteristics",
173 0,
174 REG_DWORD,
175 (LPBYTE)&pComponentInfo->dwCharacteristics,
176 sizeof(DWORD));
177 if (rc != ERROR_SUCCESS)
178 {
179 DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
180 goto done;
181 }
182
183 rc = RegSetValueExW(hInstanceKey,
184 L"ComponentId",
185 0,
186 REG_SZ,
187 (LPBYTE)pComponentInfo->pszComponentId,
188 (wcslen(pComponentInfo->pszComponentId) + 1) * sizeof(WCHAR));
189 if (rc != ERROR_SUCCESS)
190 {
191 DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
192 goto done;
193 }
194
195 rc = RegSetValueExW(hInstanceKey,
196 L"Description",
197 0,
198 REG_SZ,
199 (LPBYTE)pComponentInfo->pszDescription,
200 (wcslen(pComponentInfo->pszDescription) + 1) * sizeof(WCHAR));
201 if (rc != ERROR_SUCCESS)
202 {
203 DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
204 goto done;
205 }
206
207 rc = RegSetValueExW(hInstanceKey,
208 L"InfPath",
209 0,
210 REG_SZ,
211 (LPBYTE)pComponentInfo->pszInfPath,
212 (wcslen(pComponentInfo->pszInfPath) + 1) * sizeof(WCHAR));
213 if (rc != ERROR_SUCCESS)
214 {
215 DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
216 goto done;
217 }
218
219 rc = RegSetValueExW(hInstanceKey,
220 L"InfSection",
221 0,
222 REG_SZ,
223 (LPBYTE)pComponentInfo->pszInfSection,
224 (wcslen(pComponentInfo->pszInfSection) + 1) * sizeof(WCHAR));
225 if (rc != ERROR_SUCCESS)
226 {
227 DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
228 goto done;
229 }
230
231 *pInstanceKey = hInstanceKey;
232 ret = TRUE;
233
234 done:
235 if (ret == FALSE)
236 RegCloseKey(hInstanceKey);
237
238 DPRINT("CreateInstanceKey() done %u\n", ret);
239
240 return ret;
241 }
242
243
244 static
245 BOOL
CheckInfFile(_In_ PWSTR pszFullInfName,_In_ PWSTR pszComponentId,_In_ PCOMPONENT_INFO pComponentInfo)246 CheckInfFile(
247 _In_ PWSTR pszFullInfName,
248 _In_ PWSTR pszComponentId,
249 _In_ PCOMPONENT_INFO pComponentInfo)
250 {
251 WCHAR szLineBuffer[MAX_PATH];
252 HINF hInf = INVALID_HANDLE_VALUE;
253 INFCONTEXT MfgContext, DevContext, MiscContext;
254 DWORD dwLength;
255
256 hInf = SetupOpenInfFileW(pszFullInfName,
257 NULL,
258 INF_STYLE_WIN4,
259 NULL);
260 if (hInf == INVALID_HANDLE_VALUE)
261 {
262 DPRINT1("\n");
263 return FALSE;
264 }
265
266 if (!SetupFindFirstLineW(hInf,
267 L"Manufacturer",
268 NULL,
269 &MfgContext))
270 {
271 DPRINT("No Manufacurer section found!\n");
272 goto done;
273 }
274
275 for (;;)
276 {
277 if (!SetupGetStringFieldW(&MfgContext,
278 1,
279 szLineBuffer,
280 MAX_PATH,
281 NULL))
282 break;
283
284 DPRINT("Manufacturer: %S\n", szLineBuffer);
285 if (!SetupFindFirstLineW(hInf,
286 szLineBuffer,
287 NULL,
288 &DevContext))
289 break;
290
291 for (;;)
292 {
293 if (!SetupGetStringFieldW(&DevContext,
294 2,
295 szLineBuffer,
296 MAX_PATH,
297 NULL))
298 break;
299
300 DPRINT("Device: %S\n", szLineBuffer);
301 if (_wcsicmp(szLineBuffer, pszComponentId) == 0)
302 {
303 DPRINT("Found it!\n");
304
305 /* Get the section name*/
306 SetupGetStringFieldW(&DevContext,
307 1,
308 NULL,
309 0,
310 &dwLength);
311
312 pComponentInfo->pszInfSection = HeapAlloc(GetProcessHeap(),
313 0,
314 dwLength * sizeof(WCHAR));
315 if (pComponentInfo->pszInfSection)
316 {
317 SetupGetStringFieldW(&DevContext,
318 1,
319 pComponentInfo->pszInfSection,
320 dwLength,
321 &dwLength);
322 }
323
324 /* Get the description*/
325 SetupGetStringFieldW(&DevContext,
326 0,
327 NULL,
328 0,
329 &dwLength);
330
331 pComponentInfo->pszDescription = HeapAlloc(GetProcessHeap(),
332 0,
333 dwLength * sizeof(WCHAR));
334 if (pComponentInfo->pszDescription)
335 {
336 SetupGetStringFieldW(&DevContext,
337 0,
338 pComponentInfo->pszDescription,
339 dwLength,
340 &dwLength);
341 }
342
343 /* Get the class GUID */
344 if (SetupFindFirstLineW(hInf,
345 L"Version",
346 L"ClassGuid",
347 &MiscContext))
348 {
349 SetupGetStringFieldW(&MiscContext,
350 1,
351 NULL,
352 0,
353 &dwLength);
354
355 pComponentInfo->pszClassGuid = HeapAlloc(GetProcessHeap(),
356 0,
357 dwLength * sizeof(WCHAR));
358 if (pComponentInfo->pszInfSection)
359 {
360 SetupGetStringFieldW(&MiscContext,
361 1,
362 pComponentInfo->pszClassGuid,
363 dwLength,
364 &dwLength);
365 }
366 }
367
368 /* Get the Characteristics value */
369 if (SetupFindFirstLineW(hInf,
370 pComponentInfo->pszInfSection,
371 L"Characteristics",
372 &MiscContext))
373 {
374 SetupGetIntField(&MiscContext,
375 1,
376 (PINT)&pComponentInfo->dwCharacteristics);
377 }
378
379 SetupCloseInfFile(hInf);
380 return TRUE;
381 }
382
383 if (!SetupFindNextLine(&DevContext, &DevContext))
384 break;
385 }
386
387 if (!SetupFindNextLine(&MfgContext, &MfgContext))
388 break;
389 }
390
391 done:
392 if (hInf != INVALID_HANDLE_VALUE)
393 SetupCloseInfFile(hInf);
394
395 return FALSE;
396 }
397
398
399 static
400 BOOL
ScanForInfFile(_In_ PWSTR pszComponentId,_In_ PCOMPONENT_INFO pComponentInfo)401 ScanForInfFile(
402 _In_ PWSTR pszComponentId,
403 _In_ PCOMPONENT_INFO pComponentInfo)
404 {
405 WCHAR szInfPath[MAX_PATH];
406 WCHAR szFullInfName[MAX_PATH];
407 WCHAR szPathBuffer[MAX_PATH];
408 WIN32_FIND_DATAW fdw;
409 HANDLE hFindFile = INVALID_HANDLE_VALUE;
410 BOOL bFound = FALSE;
411
412 GetWindowsDirectoryW(szInfPath, MAX_PATH);
413 wcscat(szInfPath, L"\\inf");
414
415 wcscpy(szPathBuffer, szInfPath);
416 wcscat(szPathBuffer, L"\\*.inf");
417
418 hFindFile = FindFirstFileW(szPathBuffer, &fdw);
419 if (hFindFile == INVALID_HANDLE_VALUE)
420 return FALSE;
421
422 for (;;)
423 {
424 if (wcscmp(fdw.cFileName, L".") == 0 ||
425 wcscmp(fdw.cFileName, L"..") == 0)
426 continue;
427
428 DPRINT("FileName: %S\n", fdw.cFileName);
429
430 wcscpy(szFullInfName, szInfPath);
431 wcscat(szFullInfName, L"\\");
432 wcscat(szFullInfName, fdw.cFileName);
433
434 DPRINT("Full Inf Name: %S\n", szFullInfName);
435 if (CheckInfFile(szFullInfName,
436 pszComponentId,
437 pComponentInfo))
438 {
439 pComponentInfo->pszInfPath = HeapAlloc(GetProcessHeap(),
440 0,
441 (wcslen(fdw.cFileName) + 1) * sizeof(WCHAR));
442 if (pComponentInfo->pszInfPath)
443 wcscpy(pComponentInfo->pszInfPath, fdw.cFileName);
444
445 pComponentInfo->pszComponentId = HeapAlloc(GetProcessHeap(),
446 0,
447 (wcslen(pszComponentId) + 1) * sizeof(WCHAR));
448 if (pComponentInfo->pszComponentId)
449 wcscpy(pComponentInfo->pszComponentId, pszComponentId);
450
451 bFound = TRUE;
452 break;
453 }
454
455 if (!FindNextFileW(hFindFile, &fdw))
456 break;
457 }
458
459 if (hFindFile != INVALID_HANDLE_VALUE)
460 FindClose(hFindFile);
461
462 return bFound;
463 }
464
465
466 BOOL
InstallNetworkComponent(_In_ PWSTR pszComponentId)467 InstallNetworkComponent(
468 _In_ PWSTR pszComponentId)
469 {
470 COMPONENT_INFO ComponentInfo;
471 HKEY hInstanceKey = NULL;
472 BOOL bResult = FALSE;
473
474 DPRINT("InstallNetworkComponent(%S)\n", pszComponentId);
475
476 ZeroMemory(&ComponentInfo, sizeof(COMPONENT_INFO));
477
478 if (!ScanForInfFile(pszComponentId, &ComponentInfo))
479 goto done;
480
481 DPRINT("Characteristics: 0x%lx\n", ComponentInfo.dwCharacteristics);
482 DPRINT("ComponentId: %S\n", ComponentInfo.pszComponentId);
483 DPRINT("Description: %S\n", ComponentInfo.pszDescription);
484 DPRINT("InfPath: %S\n", ComponentInfo.pszInfPath);
485 DPRINT("InfSection: %S\n", ComponentInfo.pszInfSection);
486 DPRINT("ClassGuid: %S\n", ComponentInfo.pszClassGuid);
487
488 if (!CreateInstanceKey(&ComponentInfo,
489 &hInstanceKey))
490 {
491 DPRINT1("CreateInstanceKey() failed (Error %lx)\n", GetLastError());
492 goto done;
493 }
494
495 if (!InstallInfSections(NULL,
496 hInstanceKey,
497 ComponentInfo.pszInfPath,
498 ComponentInfo.pszInfSection))
499 {
500 DPRINT1("InstallInfSections() failed (Error %lx)\n", GetLastError());
501 goto done;
502 }
503
504 bResult = TRUE;
505
506 done:
507 if (hInstanceKey != NULL)
508 RegCloseKey(hInstanceKey);
509
510 if (ComponentInfo.pszInfPath)
511 HeapFree(GetProcessHeap(), 0, ComponentInfo.pszInfPath);
512
513 if (ComponentInfo.pszInfSection)
514 HeapFree(GetProcessHeap(), 0, ComponentInfo.pszInfSection);
515
516 if (ComponentInfo.pszComponentId)
517 HeapFree(GetProcessHeap(), 0, ComponentInfo.pszComponentId);
518
519 if (ComponentInfo.pszDescription)
520 HeapFree(GetProcessHeap(), 0, ComponentInfo.pszDescription);
521
522 if (ComponentInfo.pszClassGuid)
523 HeapFree(GetProcessHeap(), 0, ComponentInfo.pszClassGuid);
524
525 return bResult;
526 }
527
528 /* EOF */
529