ReactOS 0.4.15-dev-7089-gea8a49d
install.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Setup Library
4 * FILE: base/setup/lib/install.c
5 * PURPOSE: Installation functions
6 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10/* INCLUDES *****************************************************************/
11
12#include "precomp.h"
13#include "filesup.h"
14#include "infsupp.h"
15
16#include "setuplib.h" // HAXX for USETUP_DATA!!
17
18#include "install.h"
19
20#define NDEBUG
21#include <debug.h>
22
23
24/* FUNCTIONS ****************************************************************/
25
26static BOOL
28 IN HINF InfHandle,
29 IN OUT PINFCONTEXT InfContext,
30 IN PCWSTR DirId,
31 OUT PCWSTR* pDirectory)
32{
34
35 // ReactOS-specific
36 Success = SpInfFindFirstLine(InfHandle, L"Directories", DirId, InfContext);
37 if (!Success)
38 {
39 // Windows-compatible
40 Success = SpInfFindFirstLine(InfHandle, L"WinntDirectories", DirId, InfContext);
41 if (!Success)
42 DPRINT1("SpInfFindFirstLine() failed\n");
43 }
44 if (Success)
45 {
46 Success = INF_GetData(InfContext, NULL, pDirectory);
47 if (!Success)
48 DPRINT1("INF_GetData() failed\n");
49 }
50
51 if (!Success)
52 DPRINT1("LookupDirectoryById(%S) - directory not found!\n", DirId);
53
54 return Success;
55}
56
57/*
58 * Note: Modeled after SetupGetSourceFileLocation(), SetupGetSourceInfo()
59 * and SetupGetTargetPath() APIs.
60 * Technically the target path is the same for a given file section,
61 * but here we try to remove this constraint.
62 *
63 * TXTSETUP.SIF entries syntax explained at:
64 * http://www.msfn.org/board/topic/125480-txtsetupsif-syntax/
65 */
66static NTSTATUS
68 IN HINF InfHandle,
69 IN PINFCONTEXT InfContext OPTIONAL,
70 IN PCWSTR SourceFileName OPTIONAL,
71 OUT PCWSTR* pSourceRootPath,
72 OUT PCWSTR* pSourcePath,
73 OUT PCWSTR* pTargetDirectory,
74 OUT PCWSTR* pTargetFileName)
75{
79 PCWSTR SourceRootDirId;
80 PCWSTR SourceRootDir;
81 PCWSTR SourceRelativePath;
82 PCWSTR TargetDirId;
83 PCWSTR TargetDir;
84 PCWSTR TargetFileName;
85
86 /* Either InfContext or SourceFileName must be specified */
87 if (!InfContext && !SourceFileName)
89
90 /* InfContext to a file was not given, retrieve one corresponding to SourceFileName */
91 if (!InfContext)
92 {
93 /* Search for the SourceDisksFiles section */
94
95 /* Search in the optional platform-specific first (currently hardcoded; make it runtime-dependent?) */
96 Success = SpInfFindFirstLine(InfHandle, L"SourceDisksFiles." INF_ARCH, SourceFileName, &FileContext);
97 if (!Success)
98 {
99 /* Search in the global section */
100 Success = SpInfFindFirstLine(InfHandle, L"SourceDisksFiles", SourceFileName, &FileContext);
101 }
102 if (!Success)
103 {
104 // pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
105 // if (pSetupData->ErrorRoutine)
106 // pSetupData->ErrorRoutine(pSetupData, SectionName);
107 return STATUS_NOT_FOUND;
108 }
109 InfContext = &FileContext;
110 }
111 // else, InfContext != NULL and ignore SourceFileName (that may or may not be == NULL).
112
113 /*
114 * Getting Source File Location -- SetupGetSourceFileLocation()
115 */
116
117 /* Get source root directory id */
118 if (!INF_GetDataField(InfContext, 1, &SourceRootDirId))
119 {
120 /* FIXME: Handle error! */
121 DPRINT1("INF_GetData() failed\n");
122 return STATUS_NOT_FOUND;
123 }
124
125 /* Lookup source root directory -- SetupGetSourceInfo() */
126 /* Search in the optional platform-specific first (currently hardcoded; make it runtime-dependent?) */
127 Success = SpInfFindFirstLine(InfHandle, L"SourceDisksNames." INF_ARCH, SourceRootDirId, &DirContext);
128 if (!Success)
129 {
130 /* Search in the global section */
131 Success = SpInfFindFirstLine(InfHandle, L"SourceDisksNames", SourceRootDirId, &DirContext);
132 if (!Success)
133 DPRINT1("SpInfFindFirstLine(\"SourceDisksNames\", \"%S\") failed\n", SourceRootDirId);
134 }
135 INF_FreeData(SourceRootDirId);
136 if (!Success)
137 {
138 /* FIXME: Handle error! */
139 // pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
140 // if (pSetupData->ErrorRoutine)
141 // pSetupData->ErrorRoutine(pSetupData, SectionName);
142 return STATUS_NOT_FOUND;
143 }
144 if (!INF_GetDataField(&DirContext, 4, &SourceRootDir))
145 {
146 /* FIXME: Handle error! */
147 DPRINT1("INF_GetData() failed\n");
148 return STATUS_NOT_FOUND;
149 }
150
151 /* Get optional source relative directory */
152 if (!INF_GetDataField(InfContext, 2, &SourceRelativePath))
153 {
154 SourceRelativePath = NULL;
155 }
156 else if (!*SourceRelativePath)
157 {
158 INF_FreeData(SourceRelativePath);
159 SourceRelativePath = NULL;
160 }
161 if (!SourceRelativePath)
162 {
163 /* Use WinPE directory instead */
164 if (INF_GetDataField(InfContext, 13, &TargetDirId))
165 {
166 /* Lookup directory */
167 Success = LookupDirectoryById(InfHandle, &DirContext, TargetDirId, &SourceRelativePath);
168 INF_FreeData(TargetDirId);
169 if (!Success)
170 {
171 SourceRelativePath = NULL;
172 }
173 else if (!*SourceRelativePath)
174 {
175 INF_FreeData(SourceRelativePath);
176 SourceRelativePath = NULL;
177 }
178 }
179 }
180
181 /*
182 * Getting Target File Location -- SetupGetTargetPath()
183 */
184
185 /* Get target directory id */
186 if (!INF_GetDataField(InfContext, 8, &TargetDirId))
187 {
188 /* FIXME: Handle error! */
189 DPRINT1("INF_GetData() failed\n");
190 INF_FreeData(SourceRelativePath);
191 INF_FreeData(SourceRootDir);
192 return STATUS_NOT_FOUND;
193 }
194
195 /* Lookup target directory */
196 Success = LookupDirectoryById(InfHandle, &DirContext, TargetDirId, &TargetDir);
197 INF_FreeData(TargetDirId);
198 if (!Success)
199 {
200 /* FIXME: Handle error! */
201 INF_FreeData(SourceRelativePath);
202 INF_FreeData(SourceRootDir);
203 return STATUS_NOT_FOUND;
204 }
205
206 /* Get optional target file name */
207 if (!INF_GetDataField(InfContext, 11, &TargetFileName))
208 TargetFileName = NULL;
209 else if (!*TargetFileName)
210 TargetFileName = NULL;
211
212 DPRINT("GetSourceFileAndTargetLocation(%S) = "
213 "SrcRootDir: '%S', SrcRelPath: '%S' --> TargetDir: '%S', TargetFileName: '%S'\n",
214 SourceFileName, SourceRootDir, SourceRelativePath, TargetDir, TargetFileName);
215
216#if 0
217 INF_FreeData(TargetDir);
218 INF_FreeData(TargetFileName);
219 INF_FreeData(SourceRelativePath);
220 INF_FreeData(SourceRootDir);
221#endif
222
223 *pSourceRootPath = SourceRootDir;
224 *pSourcePath = SourceRelativePath;
225 *pTargetDirectory = TargetDir;
226 *pTargetFileName = TargetFileName;
227
228 return STATUS_SUCCESS;
229}
230
231static NTSTATUS
233 IN PCWSTR RootPath,
234 IN PCWSTR BasePath,
235 IN PCWSTR RelativePath,
236 OUT PWSTR FullPath,
237 IN SIZE_T cchFullPathSize)
238{
240
241 if ((RelativePath[0] == UNICODE_NULL) || (RelativePath[0] == L'\\' && RelativePath[1] == UNICODE_NULL))
242 {
243 /* Installation path */
244 DPRINT("InstallationPath: '%S'\n", RelativePath);
245
246 Status = CombinePaths(FullPath, cchFullPathSize, 2,
247 RootPath, BasePath);
248
249 DPRINT("InstallationPath(2): '%S'\n", FullPath);
250 }
251 else if (RelativePath[0] == L'\\')
252 {
253 /* Absolute path */
254 DPRINT("AbsolutePath: '%S'\n", RelativePath);
255
256 Status = CombinePaths(FullPath, cchFullPathSize, 2,
257 RootPath, RelativePath);
258
259 DPRINT("AbsolutePath(2): '%S'\n", FullPath);
260 }
261 else // if (RelativePath[0] != L'\\')
262 {
263 /* Path relative to the installation path */
264 DPRINT("RelativePath: '%S'\n", RelativePath);
265
266 Status = CombinePaths(FullPath, cchFullPathSize, 3,
267 RootPath, BasePath, RelativePath);
268
269 DPRINT("RelativePath(2): '%S'\n", FullPath);
270 }
271
272 return Status;
273}
274
275
276/*
277 * This code enumerates the list of files in reactos.dff / reactos.inf
278 * that need to be extracted from reactos.cab and be installed in their
279 * respective directories.
280 */
281/*
282 * IMPORTANT NOTE: The INF file specification used for the .CAB in ReactOS
283 * is not compliant with respect to TXTSETUP.SIF syntax or the standard syntax.
284 */
285static BOOLEAN
287 IN PUSETUP_DATA pSetupData,
288 IN HINF InfFile,
289 IN PCWSTR SectionName,
290 IN PCWSTR SourceCabinet,
291 IN PCUNICODE_STRING DestinationPath)
292{
295 INFCONTEXT FilesContext;
297 PCWSTR SourceFileName;
298 PCWSTR TargetDirId;
299 PCWSTR TargetDir;
300 PCWSTR TargetFileName;
301 WCHAR FileDstPath[MAX_PATH];
302
303 /* Search for the SectionName section */
304 if (!SpInfFindFirstLine(InfFile, SectionName, NULL, &FilesContext))
305 {
306 DPRINT1("AddSectionToCopyQueueCab(): Unable to find section '%S' in cabinet file\n", SectionName);
307 return FALSE;
308 }
309
310 /*
311 * Enumerate the files in the section and add them to the file queue.
312 */
313 do
314 {
315 /* Get source file name and target directory id */
316 if (!INF_GetData(&FilesContext, &SourceFileName, &TargetDirId))
317 {
318 /* FIXME: Handle error! */
319 DPRINT1("INF_GetData() failed\n");
320 break;
321 }
322
323 /* Get optional target file name */
324 if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
325 {
326 TargetFileName = NULL;
327 }
328 else if (!*TargetFileName)
329 {
330 INF_FreeData(TargetFileName);
331 TargetFileName = NULL;
332 }
333
334 /* Lookup target directory */
335 Success = LookupDirectoryById(InfFile, &DirContext, TargetDirId, &TargetDir);
336 INF_FreeData(TargetDirId);
337 if (!Success)
338 {
339 /* FIXME: Handle error! */
340 INF_FreeData(TargetFileName);
341 INF_FreeData(SourceFileName);
342 break;
343 }
344
345 DPRINT("GetSourceTargetFromCab(%S) = "
346 "SrcRootDir: '%S', SrcRelPath: '%S' --> TargetDir: '%S', TargetFileName: '%S'\n",
347 SourceFileName,
348 pSetupData->SourcePath.Buffer,
349 pSetupData->SourceRootDir.Buffer,
350 TargetDir, TargetFileName);
351
352 Status = CombinePaths(FileDstPath, ARRAYSIZE(FileDstPath), 2,
353 pSetupData->DestinationPath.Buffer,
354 TargetDir);
356 DPRINT(" --> FileDstPath = '%S'\n", FileDstPath);
357
358 INF_FreeData(TargetDir);
359
360 if (!SpFileQueueCopy((HSPFILEQ)pSetupData->SetupFileQueue,
361 pSetupData->SourcePath.Buffer, // SourcePath == SourceRootPath ++ SourceRootDir
362 NULL,
363 SourceFileName,
364 NULL,
365 SourceCabinet,
366 NULL,
367 FileDstPath,
368 TargetFileName,
369 0 /* FIXME */))
370 {
371 /* FIXME: Handle error! */
372 DPRINT1("SpFileQueueCopy() failed\n");
373 }
374
375 INF_FreeData(TargetFileName);
376 INF_FreeData(SourceFileName);
377
378 } while (SpInfFindNextLine(&FilesContext, &FilesContext));
379
380 return TRUE;
381}
382
383// Note: Modeled after the SetupQueueCopySection() API
384/*
385BOOL SetupQueueCopySection(
386 _In_ HSPFILEQ QueueHandle,
387 _In_ PCTSTR SourceRootPath,
388 _In_ HINF InfHandle,
389 _In_ HINF ListInfHandle,
390 _In_ PCTSTR Section,
391 _In_ DWORD CopyStyle
392);
393*/
394static BOOLEAN
396 IN PUSETUP_DATA pSetupData,
397 IN HINF InfFile,
398 IN PCWSTR SectionName,
399 IN PCUNICODE_STRING DestinationPath)
400{
402 INFCONTEXT FilesContext;
403 PCWSTR SourceFileName;
404 PCWSTR SourceRootPath;
405 PCWSTR SourcePath;
406 PCWSTR TargetDirectory;
407 PCWSTR TargetFileName;
408 WCHAR FileSrcRootPath[MAX_PATH];
409 WCHAR FileDstPath[MAX_PATH];
410
411 /*
412 * This code enumerates the list of files in txtsetup.sif
413 * that need to be installed in their respective directories.
414 */
415
416 /* Search for the SectionName section */
417 if (!SpInfFindFirstLine(InfFile, SectionName, NULL, &FilesContext))
418 {
419 DPRINT1("AddSectionToCopyQueue(): Unable to find section '%S' in TXTSETUP.SIF\n", SectionName);
420 return FALSE;
421 }
422
423 /*
424 * Enumerate the files in the section and add them to the file queue.
425 */
426 do
427 {
428 /* Get source file name */
429 if (!INF_GetDataField(&FilesContext, 0, &SourceFileName))
430 {
431 /* FIXME: Handle error! */
432 DPRINT1("INF_GetData() failed\n");
433 break;
434 }
435
437 &FilesContext,
438 SourceFileName,
439 &SourceRootPath, // SourceRootDir
440 &SourcePath,
441 &TargetDirectory,
442 &TargetFileName);
443 if (!NT_SUCCESS(Status))
444 {
445 DPRINT1("Could not find source and target location for file '%S'\n", SourceFileName);
446 INF_FreeData(SourceFileName);
447
448 // FIXME: Another error?
449 pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
450 if (pSetupData->ErrorRoutine)
451 pSetupData->ErrorRoutine(pSetupData, SectionName);
452 return FALSE;
453 // break;
454 }
455 /*
456 * SourcePath: '\Device\CdRom0\I386'
457 * SourceRootPath: '\Device\CdRom0'
458 * SourceRootDir: '\I386'
459 */
460
461 Status = CombinePaths(FileSrcRootPath, ARRAYSIZE(FileSrcRootPath), 2,
462 pSetupData->SourceRootPath.Buffer,
463 SourceRootPath);
465 // DPRINT1("Could not build the full path for '%S', skipping...\n", SourceRootPath);
466 DPRINT(" --> FileSrcRootPath = '%S'\n", FileSrcRootPath);
467
468 INF_FreeData(SourceRootPath);
469
470 Status = CombinePaths(FileDstPath, ARRAYSIZE(FileDstPath), 2,
471 pSetupData->DestinationPath.Buffer,
472 TargetDirectory);
474 // DPRINT1("Could not build the full path for '%S', skipping...\n", TargetDirectory);
475 DPRINT(" --> FileDstPath = '%S'\n", FileDstPath);
476
477 INF_FreeData(TargetDirectory);
478
479 if (!SpFileQueueCopy((HSPFILEQ)pSetupData->SetupFileQueue,
480 FileSrcRootPath,
481 SourcePath,
482 SourceFileName,
483 NULL,
484 NULL, // No SourceCabinet
485 NULL,
486 FileDstPath,
487 TargetFileName,
488 0 /* FIXME */))
489 {
490 /* FIXME: Handle error! */
491 DPRINT1("SpFileQueueCopy() failed\n");
492 }
493
494 INF_FreeData(TargetFileName);
495 INF_FreeData(SourcePath);
496 INF_FreeData(SourceFileName);
497
498 } while (SpInfFindNextLine(&FilesContext, &FilesContext));
499
500 return TRUE;
501}
502
503BOOLEAN // ERROR_NUMBER
505 IN OUT PUSETUP_DATA pSetupData,
506 IN HINF InfFile,
507 IN PCWSTR SourceCabinet OPTIONAL)
508{
512 PWCHAR AdditionalSectionName = NULL;
513 PCWSTR DirKeyValue;
514 WCHAR PathBuffer[MAX_PATH];
515
516 if (SourceCabinet == NULL)
517 {
518 /* Add common files -- Search for the SourceDisksFiles section */
519 /* Search in the optional platform-specific first (currently hardcoded; make it runtime-dependent?) */
520 Success = AddSectionToCopyQueue(pSetupData, InfFile,
521 L"SourceDisksFiles." INF_ARCH,
522 &pSetupData->DestinationPath);
523 if (!Success)
524 {
525 DPRINT1("AddSectionToCopyQueue(%S) failed!\n", L"SourceDisksFiles." INF_ARCH);
526 }
527 /* Search in the global section */
528 Success = AddSectionToCopyQueue(pSetupData, InfFile,
529 L"SourceDisksFiles",
530 &pSetupData->DestinationPath);
531 if (!Success)
532 {
533 DPRINT1("AddSectionToCopyQueue(%S) failed!\n", L"SourceDisksFiles");
534 pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
535 if (pSetupData->ErrorRoutine)
536 pSetupData->ErrorRoutine(pSetupData, L"SourceDisksFiles");
537 return FALSE;
538 }
539
540 /* Add specific files depending of computer type */
541 if (!ProcessComputerFiles(InfFile, pSetupData->ComputerList, &AdditionalSectionName))
542 return FALSE;
543
544 if (AdditionalSectionName &&
545 !AddSectionToCopyQueue(pSetupData, InfFile,
546 AdditionalSectionName,
547 &pSetupData->DestinationPath))
548 {
549 pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
550 if (pSetupData->ErrorRoutine)
551 pSetupData->ErrorRoutine(pSetupData, AdditionalSectionName);
552 return FALSE;
553 }
554 }
555 else
556 {
557 /* Process a cabinet INF */
558 Success = AddSectionToCopyQueueCab(pSetupData, InfFile,
559 L"SourceFiles",
560 SourceCabinet,
561 &pSetupData->DestinationPath);
562 if (!Success)
563 {
564 DPRINT1("AddSectionToCopyQueueCab(%S) failed!\n", SourceCabinet);
565 pSetupData->LastErrorNumber = ERROR_CABINET_SECTION;
566 if (pSetupData->ErrorRoutine)
567 pSetupData->ErrorRoutine(pSetupData, L"SourceFiles");
568 return FALSE;
569 }
570 }
571
572 /* Create directories */
573
574 /*
575 * NOTE: This is technically optional since SpFileQueueCommit()
576 * does that. This is however needed if one wants to create
577 * empty directories.
578 */
579
580 /*
581 * FIXME:
582 * Copying files to pSetupData->DestinationRootPath should be done from within
583 * the SystemPartitionFiles section.
584 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
585 * For installing to pSetupData->DestinationPath specify just '\' .
586 */
587
588 /* Get destination path */
589 RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
590 pSetupData->DestinationPath.Buffer);
591
592 DPRINT("FullPath(1): '%S'\n", PathBuffer);
593
594 /* Create the install directory */
595 Status = SetupCreateDirectory(PathBuffer);
597 {
598 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer, Status);
599 pSetupData->LastErrorNumber = ERROR_CREATE_INSTALL_DIR;
600 if (pSetupData->ErrorRoutine)
601 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
602 return FALSE;
603 }
604
605 /* Search for the 'Directories' section */
606 // ReactOS-specific
607 if (!SpInfFindFirstLine(InfFile, L"Directories", NULL, &DirContext))
608 {
609 // Windows-compatible
610 if (!SpInfFindFirstLine(InfFile, L"WinntDirectories", NULL, &DirContext))
611 {
612 if (SourceCabinet)
613 pSetupData->LastErrorNumber = ERROR_CABINET_SECTION;
614 else
615 pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
616
617 if (pSetupData->ErrorRoutine)
618 pSetupData->ErrorRoutine(pSetupData, L"Directories");
619 return FALSE;
620 }
621 }
622
623 /* Enumerate the directory values and create the subdirectories */
624 do
625 {
626 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
627 {
628 DPRINT1("break\n");
629 break;
630 }
631
632 Status = BuildFullDirectoryPath(pSetupData->DestinationRootPath.Buffer,
633 pSetupData->InstallPath.Buffer,
634 DirKeyValue,
635 PathBuffer,
636 ARRAYSIZE(PathBuffer));
637 if (!NT_SUCCESS(Status))
638 {
639 DPRINT1("Could not build the full path for '%S', skipping...\n", DirKeyValue);
640 INF_FreeData(DirKeyValue);
641 continue;
642 }
643
644 if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
645 {
646 /*
647 * Installation path -- No need to create it
648 * because it has been already created above.
649 */
650 }
651 else
652 {
653 /* Arbitrary path -- Create it */
654 Status = SetupCreateDirectory(PathBuffer);
656 {
657 INF_FreeData(DirKeyValue);
658 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer, Status);
659 pSetupData->LastErrorNumber = ERROR_CREATE_DIR;
660 if (pSetupData->ErrorRoutine)
661 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
662 return FALSE;
663 }
664 }
665
666 INF_FreeData(DirKeyValue);
668
669 return TRUE;
670}
671
672
673// #define USE_CABINET_INF
674
675BOOLEAN // ERROR_NUMBER
677 IN OUT PUSETUP_DATA pSetupData,
679{
680 HINF InfHandle;
681 INFCONTEXT CabinetsContext;
682 PCWSTR CabinetName;
683 UINT ErrorLine;
684#if defined(__REACTOS__) && defined(USE_CABINET_INF)
685 ULONG InfFileSize;
686 PVOID InfFileData;
687 CABINET_CONTEXT CabinetContext;
688#endif
689 WCHAR PathBuffer[MAX_PATH];
690
691 /* Create the file queue */
692 pSetupData->SetupFileQueue = (PVOID)SpFileQueueOpen();
693 if (pSetupData->SetupFileQueue == NULL)
694 {
695 pSetupData->LastErrorNumber = ERROR_COPY_QUEUE;
696 if (pSetupData->ErrorRoutine)
697 pSetupData->ErrorRoutine(pSetupData);
698 return FALSE;
699 }
700
701 /* Prepare the copy of the common files that are not in installation cabinets */
702 if (!PrepareCopyInfFile(pSetupData, pSetupData->SetupInf, NULL))
703 {
704 /* FIXME: show an error dialog */
705 return FALSE;
706 }
707
708 /* Search for the 'Cabinets' section */
709 if (!SpInfFindFirstLine(pSetupData->SetupInf, L"Cabinets", NULL, &CabinetsContext))
710 {
711 /* Skip this step and return success if no cabinet file is listed */
712 return TRUE;
713 }
714
715 /*
716 * Enumerate the installation cabinets listed in the
717 * 'Cabinets' section and parse their inf files.
718 */
719 do
720 {
721 if (!INF_GetData(&CabinetsContext, NULL, &CabinetName))
722 break;
723
724 CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
725 pSetupData->SourcePath.Buffer, CabinetName);
726
727#if defined(__REACTOS__) && defined(USE_CABINET_INF)
728 INF_FreeData(CabinetName);
729
730 CabinetInitialize(&CabinetContext);
731 CabinetSetEventHandlers(&CabinetContext, NULL, NULL, NULL);
732 CabinetSetCabinetName(&CabinetContext, PathBuffer);
733
734 if (CabinetOpen(&CabinetContext) == CAB_STATUS_SUCCESS)
735 {
736 DPRINT("Cabinet %S\n", PathBuffer);
737
738 InfFileData = CabinetGetCabinetReservedArea(&CabinetContext, &InfFileSize);
739 if (InfFileData == NULL)
740 {
741 CabinetCleanup(&CabinetContext);
742
743 pSetupData->LastErrorNumber = ERROR_CABINET_SCRIPT;
744 if (pSetupData->ErrorRoutine)
745 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
746 return FALSE;
747 }
748 }
749 else
750 {
751 DPRINT("Cannot open cabinet: %S.\n", PathBuffer);
752 CabinetCleanup(&CabinetContext);
753
754 pSetupData->LastErrorNumber = ERROR_CABINET_MISSING;
755 if (pSetupData->ErrorRoutine)
756 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
757 return FALSE;
758 }
759
760 InfHandle = INF_OpenBufferedFileA((PSTR)InfFileData,
761 InfFileSize,
762 NULL,
764 pSetupData->LanguageId,
765 &ErrorLine);
766
767 CabinetCleanup(&CabinetContext);
768#else
769 {
770 PWCHAR ptr;
771
772 /* First find the filename */
773 ptr = wcsrchr(PathBuffer, L'\\');
774 if (!ptr) ptr = PathBuffer;
775
776 /* Then find its extension */
777 ptr = wcsrchr(ptr, L'.');
778 if (!ptr)
779 ptr = PathBuffer + wcslen(PathBuffer);
780
781 /* Replace it by '.inf' */
782 wcscpy(ptr, L".inf");
783
784 InfHandle = SpInfOpenInfFile(PathBuffer,
785 NULL,
787 pSetupData->LanguageId,
788 &ErrorLine);
789 }
790#endif
791
792 if (InfHandle == INVALID_HANDLE_VALUE)
793 {
794 pSetupData->LastErrorNumber = ERROR_INVALID_CABINET_INF;
795 if (pSetupData->ErrorRoutine)
796 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
797 return FALSE;
798 }
799
800 if (!PrepareCopyInfFile(pSetupData, InfHandle, CabinetName))
801 {
802#if !(defined(__REACTOS__) && defined(USE_CABINET_INF))
803 SpInfCloseInfFile(InfHandle);
804#endif
805 /* FIXME: show an error dialog */
806 return FALSE;
807 }
808
809#if !(defined(__REACTOS__) && defined(USE_CABINET_INF))
810 SpInfCloseInfFile(InfHandle);
811#endif
812 } while (SpInfFindNextLine(&CabinetsContext, &CabinetsContext));
813
814 return TRUE;
815}
816
819 IN OUT PUSETUP_DATA pSetupData,
820 IN PSP_FILE_CALLBACK_W MsgHandler,
822{
824
826 (HSPFILEQ)pSetupData->SetupFileQueue,
827 MsgHandler,
828 Context);
829
830 SpFileQueueClose((HSPFILEQ)pSetupData->SetupFileQueue);
831 pSetupData->SetupFileQueue = NULL;
832
833 return Success;
834}
835
836/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
static BOOL LookupDirectoryById(IN HINF InfHandle, IN OUT PINFCONTEXT InfContext, IN PCWSTR DirId, OUT PCWSTR *pDirectory)
Definition: install.c:27
BOOLEAN DoFileCopy(IN OUT PUSETUP_DATA pSetupData, IN PSP_FILE_CALLBACK_W MsgHandler, IN PVOID Context OPTIONAL)
Definition: install.c:818
static NTSTATUS BuildFullDirectoryPath(IN PCWSTR RootPath, IN PCWSTR BasePath, IN PCWSTR RelativePath, OUT PWSTR FullPath, IN SIZE_T cchFullPathSize)
Definition: install.c:232
BOOLEAN PrepareCopyInfFile(IN OUT PUSETUP_DATA pSetupData, IN HINF InfFile, IN PCWSTR SourceCabinet OPTIONAL)
Definition: install.c:504
BOOLEAN PrepareFileCopy(IN OUT PUSETUP_DATA pSetupData, IN PFILE_COPY_STATUS_ROUTINE StatusRoutine OPTIONAL)
Definition: install.c:676
static BOOLEAN AddSectionToCopyQueueCab(IN PUSETUP_DATA pSetupData, IN HINF InfFile, IN PCWSTR SectionName, IN PCWSTR SourceCabinet, IN PCUNICODE_STRING DestinationPath)
Definition: install.c:286
static BOOLEAN AddSectionToCopyQueue(IN PUSETUP_DATA pSetupData, IN HINF InfFile, IN PCWSTR SectionName, IN PCUNICODE_STRING DestinationPath)
Definition: install.c:395
static NTSTATUS GetSourceFileAndTargetLocation(IN HINF InfHandle, IN PINFCONTEXT InfContext OPTIONAL, IN PCWSTR SourceFileName OPTIONAL, OUT PCWSTR *pSourceRootPath, OUT PCWSTR *pSourcePath, OUT PCWSTR *pTargetDirectory, OUT PCWSTR *pTargetFileName)
Definition: install.c:67
VOID(__cdecl * PFILE_COPY_STATUS_ROUTINE)(IN FILE_COPY_STATUS,...)
Definition: install.h:19
BOOLEAN ProcessComputerFiles(IN HINF InfFile, IN PGENERIC_LIST List, OUT PWSTR *AdditionalSectionName)
Definition: settings.c:787
#define CAB_STATUS_SUCCESS
Definition: cabinet.h:23
HINF WINAPI INF_OpenBufferedFileA(IN PSTR FileBuffer, IN ULONG FileSize, IN PCSTR InfClass, IN DWORD InfStyle, IN LCID LocaleId, OUT PUINT ErrorLine)
Definition: infsupp.c:244
ULONG CabinetOpen(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:621
PVOID CabinetGetCabinetReservedArea(IN PCABINET_CONTEXT CabinetContext, OUT PULONG Size)
Definition: cabinet.c:1357
VOID CabinetSetEventHandlers(IN PCABINET_CONTEXT CabinetContext, IN PCABINET_OVERWRITE Overwrite, IN PCABINET_EXTRACT Extract, IN PCABINET_DISK_CHANGE DiskChange, IN PCABINET_CREATE_FILE CreateFile)
Definition: cabinet.c:1340
VOID CabinetInitialize(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:501
VOID CabinetCleanup(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:529
VOID CabinetSetCabinetName(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName)
Definition: cabinet.c:580
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PFILE_ENUM_CONTEXT FileContext
Definition: cdprocs.h:442
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:425
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define wcsrchr
Definition: compat.h:16
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
@ ERROR_CABINET_MISSING
Definition: errorcode.h:44
@ ERROR_TXTSETUP_SECTION
Definition: errorcode.h:48
@ ERROR_CABINET_SCRIPT
Definition: errorcode.h:45
@ ERROR_CREATE_DIR
Definition: errorcode.h:47
@ ERROR_CABINET_SECTION
Definition: errorcode.h:49
@ ERROR_COPY_QUEUE
Definition: errorcode.h:46
@ ERROR_CREATE_INSTALL_DIR
Definition: errorcode.h:50
@ ERROR_INVALID_CABINET_INF
Definition: errorcode.h:43
@ Success
Definition: eventcreate.c:712
pSpFileQueueClose SpFileQueueClose
Definition: fileqsup.c:154
UINT(CALLBACK * PSP_FILE_CALLBACK_W)(IN PVOID Context, IN UINT Notification, IN UINT_PTR Param1, IN UINT_PTR Param2)
Definition: fileqsup.h:66
pSpFileQueueCopy SpFileQueueCopy
Definition: fileqsup.c:155
pSpFileQueueOpen SpFileQueueOpen
Definition: fileqsup.c:153
pSpFileQueueCommit SpFileQueueCommit
Definition: fileqsup.c:158
NTSTATUS CombinePaths(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:681
NTSTATUS SetupCreateDirectory(IN PCWSTR PathName)
Definition: filesup.c:84
unsigned int BOOL
Definition: ntddk_ex.h:94
Status
Definition: gdiplustypes.h:25
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define INF_STYLE_WIN4
Definition: infsupp.h:41
pSpInfFindNextLine SpInfFindNextLine
Definition: infsupp.c:88
pSpInfFindFirstLine SpInfFindFirstLine
Definition: infsupp.c:87
FORCEINLINE VOID INF_FreeData(IN PCWSTR InfData)
Definition: infsupp.h:157
pSpInfOpenInfFile SpInfOpenInfFile
Definition: infsupp.c:95
pSpInfCloseInfFile SpInfCloseInfFile
Definition: infsupp.c:86
BOOLEAN INF_GetDataField(IN PINFCONTEXT Context, IN ULONG FieldIndex, OUT PCWSTR *Data)
Definition: infsupp.c:42
BOOLEAN INF_GetData(IN PINFCONTEXT Context, OUT PCWSTR *Key, OUT PCWSTR *Data)
Definition: infsupp.c:90
static PVOID ptr
Definition: dispmode.c:27
static const char const char const char PIMAGEHLP_STATUS_ROUTINE StatusRoutine
Definition: image.c:35
unsigned int UINT
Definition: ndis.h:50
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
NTSTRSAFEAPI RtlStringCchCopyW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:127
#define L(x)
Definition: ntvdm.h:50
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define DPRINT
Definition: sndvol32.h:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
uint16_t * PWSTR
Definition: typedefs.h:56
char * PSTR
Definition: typedefs.h:51
const uint16_t * PCWSTR
Definition: typedefs.h:57
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
__wchar_t WCHAR
Definition: xmlstorage.h:180