ReactOS 0.4.16-dev-197-g92996da
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 {
543 Entry = GetCurrentListEntry(pSetupData->ComputerList);
544 ASSERT(Entry);
545 pSetupData->ComputerType = ((PGENENTRY)GetListEntryData(Entry))->Id;
546 ASSERT(pSetupData->ComputerType);
547
548 if (!ProcessComputerFiles(InfFile, pSetupData->ComputerType, &AdditionalSectionName))
549 return FALSE;
550 }
551
552 if (AdditionalSectionName &&
553 !AddSectionToCopyQueue(pSetupData, InfFile,
554 AdditionalSectionName,
555 &pSetupData->DestinationPath))
556 {
557 pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
558 if (pSetupData->ErrorRoutine)
559 pSetupData->ErrorRoutine(pSetupData, AdditionalSectionName);
560 return FALSE;
561 }
562 }
563 else
564 {
565 /* Process a cabinet INF */
566 Success = AddSectionToCopyQueueCab(pSetupData, InfFile,
567 L"SourceFiles",
568 SourceCabinet,
569 &pSetupData->DestinationPath);
570 if (!Success)
571 {
572 DPRINT1("AddSectionToCopyQueueCab(%S) failed!\n", SourceCabinet);
573 pSetupData->LastErrorNumber = ERROR_CABINET_SECTION;
574 if (pSetupData->ErrorRoutine)
575 pSetupData->ErrorRoutine(pSetupData, L"SourceFiles");
576 return FALSE;
577 }
578 }
579
580 /* Create directories */
581
582 /*
583 * NOTE: This is technically optional since SpFileQueueCommit()
584 * does that. This is however needed if one wants to create
585 * empty directories.
586 */
587
588 /*
589 * FIXME:
590 * Copying files to pSetupData->DestinationRootPath should be done from within
591 * the SystemPartitionFiles section.
592 * At the moment we check whether we specify paths like '\foo' or '\\' for that.
593 * For installing to pSetupData->DestinationPath specify just '\' .
594 */
595
596 /* Get destination path */
597 RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
598 pSetupData->DestinationPath.Buffer);
599
600 DPRINT("FullPath(1): '%S'\n", PathBuffer);
601
602 /* Create the install directory */
603 Status = SetupCreateDirectory(PathBuffer);
605 {
606 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer, Status);
607 pSetupData->LastErrorNumber = ERROR_CREATE_INSTALL_DIR;
608 if (pSetupData->ErrorRoutine)
609 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
610 return FALSE;
611 }
612
613 /* Search for the 'Directories' section */
614 // ReactOS-specific
615 if (!SpInfFindFirstLine(InfFile, L"Directories", NULL, &DirContext))
616 {
617 // Windows-compatible
618 if (!SpInfFindFirstLine(InfFile, L"WinntDirectories", NULL, &DirContext))
619 {
620 if (SourceCabinet)
621 pSetupData->LastErrorNumber = ERROR_CABINET_SECTION;
622 else
623 pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
624
625 if (pSetupData->ErrorRoutine)
626 pSetupData->ErrorRoutine(pSetupData, L"Directories");
627 return FALSE;
628 }
629 }
630
631 /* Enumerate the directory values and create the subdirectories */
632 do
633 {
634 if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
635 {
636 DPRINT1("break\n");
637 break;
638 }
639
640 Status = BuildFullDirectoryPath(pSetupData->DestinationRootPath.Buffer,
641 pSetupData->InstallPath.Buffer,
642 DirKeyValue,
643 PathBuffer,
644 ARRAYSIZE(PathBuffer));
645 if (!NT_SUCCESS(Status))
646 {
647 DPRINT1("Could not build the full path for '%S', skipping...\n", DirKeyValue);
648 INF_FreeData(DirKeyValue);
649 continue;
650 }
651
652 if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
653 {
654 /*
655 * Installation path -- No need to create it
656 * because it has been already created above.
657 */
658 }
659 else
660 {
661 /* Arbitrary path -- Create it */
662 Status = SetupCreateDirectory(PathBuffer);
664 {
665 INF_FreeData(DirKeyValue);
666 DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer, Status);
667 pSetupData->LastErrorNumber = ERROR_CREATE_DIR;
668 if (pSetupData->ErrorRoutine)
669 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
670 return FALSE;
671 }
672 }
673
674 INF_FreeData(DirKeyValue);
676
677 return TRUE;
678}
679
680
681// #define USE_CABINET_INF
682
683BOOLEAN // ERROR_NUMBER
685 IN OUT PUSETUP_DATA pSetupData,
687{
688 HINF InfHandle;
689 INFCONTEXT CabinetsContext;
690 PCWSTR CabinetName;
691 UINT ErrorLine;
692#if defined(__REACTOS__) && defined(USE_CABINET_INF)
693 ULONG InfFileSize;
694 PVOID InfFileData;
695 CABINET_CONTEXT CabinetContext;
696#endif
697 WCHAR PathBuffer[MAX_PATH];
698
699 /* Create the file queue */
700 pSetupData->SetupFileQueue = (PVOID)SpFileQueueOpen();
701 if (pSetupData->SetupFileQueue == NULL)
702 {
703 pSetupData->LastErrorNumber = ERROR_COPY_QUEUE;
704 if (pSetupData->ErrorRoutine)
705 pSetupData->ErrorRoutine(pSetupData);
706 return FALSE;
707 }
708
709 /* Prepare the copy of the common files that are not in installation cabinets */
710 if (!PrepareCopyInfFile(pSetupData, pSetupData->SetupInf, NULL))
711 {
712 /* FIXME: show an error dialog */
713 return FALSE;
714 }
715
716 /* Search for the 'Cabinets' section */
717 if (!SpInfFindFirstLine(pSetupData->SetupInf, L"Cabinets", NULL, &CabinetsContext))
718 {
719 /* Skip this step and return success if no cabinet file is listed */
720 return TRUE;
721 }
722
723 /*
724 * Enumerate the installation cabinets listed in the
725 * 'Cabinets' section and parse their inf files.
726 */
727 do
728 {
729 if (!INF_GetData(&CabinetsContext, NULL, &CabinetName))
730 break;
731
732 CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
733 pSetupData->SourcePath.Buffer, CabinetName);
734
735#if defined(__REACTOS__) && defined(USE_CABINET_INF)
736 INF_FreeData(CabinetName);
737
738 CabinetInitialize(&CabinetContext);
739 CabinetSetEventHandlers(&CabinetContext, NULL, NULL, NULL);
740 CabinetSetCabinetName(&CabinetContext, PathBuffer);
741
742 if (CabinetOpen(&CabinetContext) == CAB_STATUS_SUCCESS)
743 {
744 DPRINT("Cabinet %S\n", PathBuffer);
745
746 InfFileData = CabinetGetCabinetReservedArea(&CabinetContext, &InfFileSize);
747 if (InfFileData == NULL)
748 {
749 CabinetCleanup(&CabinetContext);
750
751 pSetupData->LastErrorNumber = ERROR_CABINET_SCRIPT;
752 if (pSetupData->ErrorRoutine)
753 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
754 return FALSE;
755 }
756 }
757 else
758 {
759 DPRINT("Cannot open cabinet: %S.\n", PathBuffer);
760 CabinetCleanup(&CabinetContext);
761
762 pSetupData->LastErrorNumber = ERROR_CABINET_MISSING;
763 if (pSetupData->ErrorRoutine)
764 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
765 return FALSE;
766 }
767
768 InfHandle = INF_OpenBufferedFileA((PSTR)InfFileData,
769 InfFileSize,
770 NULL,
772 pSetupData->LanguageId,
773 &ErrorLine);
774
775 CabinetCleanup(&CabinetContext);
776#else
777 {
778 PWCHAR ptr;
779
780 /* First find the filename */
781 ptr = wcsrchr(PathBuffer, L'\\');
782 if (!ptr) ptr = PathBuffer;
783
784 /* Then find its extension */
785 ptr = wcsrchr(ptr, L'.');
786 if (!ptr)
787 ptr = PathBuffer + wcslen(PathBuffer);
788
789 /* Replace it by '.inf' */
790 wcscpy(ptr, L".inf");
791
792 InfHandle = SpInfOpenInfFile(PathBuffer,
793 NULL,
795 pSetupData->LanguageId,
796 &ErrorLine);
797 }
798#endif
799
800 if (InfHandle == INVALID_HANDLE_VALUE)
801 {
802 pSetupData->LastErrorNumber = ERROR_INVALID_CABINET_INF;
803 if (pSetupData->ErrorRoutine)
804 pSetupData->ErrorRoutine(pSetupData, PathBuffer);
805 return FALSE;
806 }
807
808 if (!PrepareCopyInfFile(pSetupData, InfHandle, CabinetName))
809 {
810#if !(defined(__REACTOS__) && defined(USE_CABINET_INF))
811 SpInfCloseInfFile(InfHandle);
812#endif
813 /* FIXME: show an error dialog */
814 return FALSE;
815 }
816
817#if !(defined(__REACTOS__) && defined(USE_CABINET_INF))
818 SpInfCloseInfFile(InfHandle);
819#endif
820 } while (SpInfFindNextLine(&CabinetsContext, &CabinetsContext));
821
822 return TRUE;
823}
824
827 IN OUT PUSETUP_DATA pSetupData,
828 IN PSP_FILE_CALLBACK_W MsgHandler,
830{
832
834 (HSPFILEQ)pSetupData->SetupFileQueue,
835 MsgHandler,
836 Context);
837
838 SpFileQueueClose((HSPFILEQ)pSetupData->SetupFileQueue);
839 pSetupData->SetupFileQueue = NULL;
840
841 return Success;
842}
843
844/* EOF */
DWORD Id
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:826
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:684
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_ PCWSTR ComputerType, _Out_ PWSTR *AdditionalSectionName)
Definition: settings.c:787
struct _GENENTRY * PGENENTRY
#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:246
ULONG CabinetOpen(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:627
PVOID CabinetGetCabinetReservedArea(IN PCABINET_CONTEXT CabinetContext, OUT PULONG Size)
Definition: cabinet.c:1372
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:1355
VOID CabinetInitialize(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:507
VOID CabinetCleanup(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:535
VOID CabinetSetCabinetName(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName)
Definition: cabinet.c:586
_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:33
#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:1001
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:1002
pSpFileQueueOpen SpFileQueueOpen
Definition: fileqsup.c:1000
pSpFileQueueCommit SpFileQueueCommit
Definition: fileqsup.c:1005
NTSTATUS CombinePaths(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:671
NTSTATUS SetupCreateDirectory(_In_ PCWSTR PathName)
Create a new directory, specified by the given path. Any intermediate non-existing directory is creat...
Definition: filesup.c:79
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
PGENERIC_LIST_ENTRY GetCurrentListEntry(IN PGENERIC_LIST List)
Definition: genlist.c:97
PVOID GetListEntryData(IN PGENERIC_LIST_ENTRY Entry)
Definition: genlist.c:126
#define ASSERT(a)
Definition: mode.c:44
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:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
Definition: genlist.h:11
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