xref: /reactos/dll/win32/syssetup/netinstall.c (revision 9393fc32)
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
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
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
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
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
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