ReactOS  0.4.13-dev-249-gcba1a2f
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 
26 static BOOL
28  IN HINF InfHandle,
29  IN OUT PINFCONTEXT InfContext,
30  IN PCWSTR DirId,
31  OUT PCWSTR* pDirectory)
32 {
33  BOOL Success;
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  */
66 static 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 {
76  BOOL Success;
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 
231 static 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  */
285 static 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 /*
385 BOOL 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 */
394 static 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 
503 BOOLEAN // 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  DPRINT("Creating directory '%S' failed: Status = 0x%08lx", 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 
675 BOOLEAN // 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 
817 BOOLEAN
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 */
VOID CabinetInitialize(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:501
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
const uint16_t * PCWSTR
Definition: typedefs.h:55
static const char const char const char PIMAGEHLP_STATUS_ROUTINE StatusRoutine
Definition: image.c:34
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
#define INF_STYLE_WIN4
Definition: infsupp.h:41
pSpFileQueueClose SpFileQueueClose
Definition: fileqsup.c:154
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint16_t * PWSTR
Definition: typedefs.h:54
LONG NTSTATUS
Definition: precomp.h:26
static NTSTATUS BuildFullDirectoryPath(IN PCWSTR RootPath, IN PCWSTR BasePath, IN PCWSTR RelativePath, OUT PWSTR FullPath, IN SIZE_T cchFullPathSize)
Definition: install.c:232
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
pSpInfFindFirstLine SpInfFindFirstLine
Definition: infsupp.c:87
pSpFileQueueOpen SpFileQueueOpen
Definition: fileqsup.c:153
uint16_t * PWCHAR
Definition: typedefs.h:54
pSpFileQueueCommit SpFileQueueCommit
Definition: fileqsup.c:158
VOID CabinetSetCabinetName(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName)
Definition: cabinet.c:580
BOOLEAN DoFileCopy(IN OUT PUSETUP_DATA pSetupData, IN PSP_FILE_CALLBACK_W MsgHandler, IN PVOID Context OPTIONAL)
Definition: install.c:818
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
#define UNICODE_NULL
pSpFileQueueCopy SpFileQueueCopy
Definition: fileqsup.c:155
unsigned int BOOL
Definition: ntddk_ex.h:94
NTSTATUS SetupCreateDirectory(IN PCWSTR PathName)
Definition: filesup.c:84
static PVOID ptr
Definition: dispmode.c:27
unsigned char BOOLEAN
BOOLEAN INF_GetDataField(IN PINFCONTEXT Context, IN ULONG FieldIndex, OUT PCWSTR *Data)
Definition: infsupp.c:42
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
void * PVOID
Definition: retypes.h:9
pSpInfCloseInfFile SpInfCloseInfFile
Definition: infsupp.c:86
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PFILE_ENUM_CONTEXT FileContext
Definition: cdprocs.h:444
static BOOLEAN AddSectionToCopyQueue(IN PUSETUP_DATA pSetupData, IN HINF InfFile, IN PCWSTR SectionName, IN PCUNICODE_STRING DestinationPath)
Definition: install.c:395
#define STATUS_NOT_FOUND
Definition: shellext.h:67
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN ProcessComputerFiles(IN HINF InfFile, IN PGENERIC_LIST List, OUT PWSTR *AdditionalSectionName)
Definition: settings.c:752
UINT(CALLBACK * PSP_FILE_CALLBACK_W)(IN PVOID Context, IN UINT Notification, IN UINT_PTR Param1, IN UINT_PTR Param2)
Definition: fileqsup.h:66
BOOLEAN PrepareCopyInfFile(IN OUT PUSETUP_DATA pSetupData, IN HINF InfFile, IN PCWSTR SourceCabinet OPTIONAL)
Definition: install.c:504
#define MAX_PATH
Definition: compat.h:26
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: cdprocs.h:429
static BOOL LookupDirectoryById(IN HINF InfHandle, IN OUT PINFCONTEXT InfContext, IN PCWSTR DirId, OUT PCWSTR *pDirectory)
Definition: install.c:27
FORCEINLINE VOID INF_FreeData(IN PCWSTR InfData)
Definition: infsupp.h:157
#define CAB_STATUS_SUCCESS
Definition: cabinet.h:23
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1250
pSpInfOpenInfFile SpInfOpenInfFile
Definition: infsupp.c:95
ULONG CabinetOpen(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:621
BOOLEAN INF_GetData(IN PINFCONTEXT Context, OUT PCWSTR *Key, OUT PCWSTR *Data)
Definition: infsupp.c:90
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
static BOOLEAN AddSectionToCopyQueueCab(IN PUSETUP_DATA pSetupData, IN HINF InfFile, IN PCWSTR SectionName, IN PCWSTR SourceCabinet, IN PCUNICODE_STRING DestinationPath)
Definition: install.c:286
NTSTRSAFEAPI RtlStringCchCopyW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:135
VOID(__cdecl * PFILE_COPY_STATUS_ROUTINE)(IN FILE_COPY_STATUS,...)
Definition: install.h:19
pSpInfFindNextLine SpInfFindNextLine
Definition: infsupp.c:88
signed char * PSTR
Definition: retypes.h:7
unsigned int UINT
Definition: ndis.h:50
#define DPRINT1
Definition: precomp.h:8
PVOID CabinetGetCabinetReservedArea(IN PCABINET_CONTEXT CabinetContext, OUT PULONG Size)
Definition: cabinet.c:1330
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
VOID CabinetSetEventHandlers(IN PCABINET_CONTEXT CabinetContext, IN PCABINET_OVERWRITE Overwrite, IN PCABINET_EXTRACT Extract, IN PCABINET_DISK_CHANGE DiskChange)
Definition: cabinet.c:1315
typedef struct _USETUP_DATA * PUSETUP_DATA
BOOLEAN PrepareFileCopy(IN OUT PUSETUP_DATA pSetupData, IN PFILE_COPY_STATUS_ROUTINE StatusRoutine OPTIONAL)
Definition: install.c:676
return STATUS_SUCCESS
Definition: btrfs.c:2745
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 CabinetCleanup(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:529
NTSTATUS CombinePaths(OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:681
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68