branch update for HEAD-2003091401
[reactos.git] / subsys / system / usetup / filequeue.c
index 5b2ae96..6caa86c 100644 (file)
@@ -22,6 +22,7 @@
  * FILE:            subsys/system/usetup/filequeue.c
  * PURPOSE:         File queue functions
  * PROGRAMMER:      Eric Kohl
+ *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
  */
 
 /* INCLUDES *****************************************************************/
@@ -42,6 +43,7 @@ typedef struct _QUEUEENTRY
   struct _QUEUEENTRY *Prev;
   struct _QUEUEENTRY *Next;
 
+  PWSTR SourceCabinet;          /* May be NULL if file is not in a cabinet */
   PWSTR SourceRootPath;
   PWSTR SourcePath;
   PWSTR SourceFilename;
@@ -98,6 +100,8 @@ SetupCloseFileQueue(HSPFILEQ QueueHandle)
   while (Entry != NULL)
     {
       /* Delete all strings */
+      if (Entry->SourceCabinet != NULL)
+       RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
       if (Entry->SourceRootPath != NULL)
        RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
       if (Entry->SourcePath != NULL)
@@ -139,6 +143,7 @@ SetupCloseFileQueue(HSPFILEQ QueueHandle)
 
 BOOL
 SetupQueueCopy(HSPFILEQ QueueHandle,
+         PCWSTR SourceCabinet,
               PCWSTR SourceRootPath,
               PCWSTR SourcePath,
               PCWSTR SourceFilename,
@@ -149,6 +154,7 @@ SetupQueueCopy(HSPFILEQ QueueHandle,
   PQUEUEENTRY Entry;
   ULONG Length;
 
+  /* SourceCabinet may be NULL */
   if (QueueHandle == NULL ||
       SourceRootPath == NULL ||
       SourceFilename == NULL ||
@@ -167,6 +173,26 @@ SetupQueueCopy(HSPFILEQ QueueHandle,
   RtlZeroMemory(Entry,
                sizeof(QUEUEENTRY));
 
+  /* Copy source cabinet if available */
+  if (SourceCabinet != NULL)
+    {
+      Length = wcslen(SourceCabinet);
+      Entry->SourceCabinet = RtlAllocateHeap(ProcessHeap,
+                                         0,
+                                         (Length + 1) * sizeof(WCHAR));
+      if (Entry->SourceCabinet == NULL)
+      {
+        RtlFreeHeap(ProcessHeap, 0, Entry);
+        return(FALSE);
+      }
+      wcsncpy(Entry->SourceCabinet, SourceCabinet, Length);
+      Entry->SourceCabinet[Length] = (WCHAR)0;
+    }
+  else
+    {
+      Entry->SourceCabinet = NULL;
+    }
+
   /* Copy source root path */
   Length = wcslen(SourceRootPath);
   Entry->SourceRootPath = RtlAllocateHeap(ProcessHeap,
@@ -174,6 +200,10 @@ SetupQueueCopy(HSPFILEQ QueueHandle,
                                          (Length + 1) * sizeof(WCHAR));
   if (Entry->SourceRootPath == NULL)
   {
+    if (Entry->SourceCabinet != NULL)
+      {
+        RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+      }
     RtlFreeHeap(ProcessHeap, 0, Entry);
     return(FALSE);
   }
@@ -189,6 +219,10 @@ SetupQueueCopy(HSPFILEQ QueueHandle,
                                        (Length + 1) * sizeof(WCHAR));
     if (Entry->SourcePath == NULL)
     {
+      if (Entry->SourceCabinet != NULL)
+        {
+          RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+        }
       RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
       RtlFreeHeap(ProcessHeap, 0, Entry);
       return(FALSE);
@@ -204,6 +238,10 @@ SetupQueueCopy(HSPFILEQ QueueHandle,
                                          (Length + 1) * sizeof(WCHAR));
   if (Entry->SourceFilename == NULL)
   {
+    if (Entry->SourceCabinet != NULL)
+      {
+        RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+      }
     RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
     RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
     RtlFreeHeap(ProcessHeap, 0, Entry);
@@ -221,6 +259,10 @@ SetupQueueCopy(HSPFILEQ QueueHandle,
                                           (Length + 1) * sizeof(WCHAR));
   if (Entry->TargetDirectory == NULL)
   {
+    if (Entry->SourceCabinet != NULL)
+      {
+        RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+      }
     RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
     RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
     RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
@@ -239,6 +281,10 @@ SetupQueueCopy(HSPFILEQ QueueHandle,
                                            (Length + 1) * sizeof(WCHAR));
     if (Entry->TargetFilename == NULL)
     {
+      if (Entry->SourceCabinet != NULL)
+        {
+          RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
+        }
       RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
       RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
       RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
@@ -278,6 +324,7 @@ SetupCommitFileQueue(HSPFILEQ QueueHandle,
                     PSP_FILE_CALLBACK MsgHandler,
                     PVOID Context)
 {
+  WCHAR CabinetName[MAX_PATH];
   PFILEQUEUEHEADER QueueHeader;
   PQUEUEENTRY Entry;
   NTSTATUS Status;
@@ -304,7 +351,6 @@ SetupCommitFileQueue(HSPFILEQ QueueHandle,
   Entry = QueueHeader->CopyHead;
   while (Entry != NULL)
   {
-    /* Build the full source path */
     wcscpy(FileSrcPath, Entry->SourceRootPath);
     if (Entry->SourcePath != NULL)
       wcscat(FileSrcPath, Entry->SourcePath);
@@ -328,11 +374,16 @@ SetupCommitFileQueue(HSPFILEQ QueueHandle,
       wcscat(FileDstPath, L"\\");
       wcscat(FileDstPath, Entry->TargetDirectory);
     }
-    wcscat(FileDstPath, L"\\");
-    if (Entry->TargetFilename != NULL)
-      wcscat(FileDstPath, Entry->TargetFilename);
-    else
-      wcscat(FileDstPath, Entry->SourceFilename);
+
+    /* Use only the destination path if the file is in a cabinet */
+    if (Entry->SourceCabinet == NULL)
+      {
+        wcscat(FileDstPath, L"\\");
+        if (Entry->TargetFilename != NULL)
+          wcscat(FileDstPath, Entry->TargetFilename);
+        else
+          wcscat(FileDstPath, Entry->SourceFilename);
+      }
 
     /* FIXME: Do it! */
     DPRINT("'%S' ==> '%S'\n",
@@ -344,8 +395,21 @@ SetupCommitFileQueue(HSPFILEQ QueueHandle,
               (PVOID)Entry->SourceFilename,
               (PVOID)FILEOP_COPY);
 
-    /* Copy the file */
-    Status = SetupCopyFile(FileSrcPath, FileDstPath);
+    if (Entry->SourceCabinet != NULL)
+      {
+        /* Extract the file */
+        wcscpy(CabinetName, Entry->SourceRootPath);
+        if (Entry->SourcePath != NULL)
+          wcscat(CabinetName, Entry->SourcePath);
+        wcscat(CabinetName, L"\\");
+        wcscat(CabinetName, Entry->SourceCabinet);
+        Status = SetupExtractFile(CabinetName, Entry->SourceFilename, FileDstPath);
+      }
+    else
+      {
+        /* Copy the file */
+        Status = SetupCopyFile(FileSrcPath, FileDstPath);
+      }
     if (!NT_SUCCESS(Status))
     {
       MsgHandler(Context,