From: Hermès Bélusca-Maïto Date: Fri, 5 Jan 2018 01:08:59 +0000 (+0100) Subject: [USETUP] Improvements for the File-queues code. X-Git-Tag: 0.4.12-dev~312 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=44c101c9dcec40e8c87b96391501de59a53c4565 [USETUP] Improvements for the File-queues code. - Add support for delete and move/rename operations, which are needed for implementing ReactOS upgrading support. - Use cabinet contexts. - Use standard LIST_ENTRY structures for implementing the lists. - Move the path-building hack code in SetupCommitFileQueueW() that had been introduced in r66604 (97bb83f) out of the file-queues code. - Make the function prototypes compatible with win32's setupapi functions. - Fix the format of the data passed to the custom notification handler. - Adjust the file-copy callback to correctly use its arguments (setupapi-compatible). --- diff --git a/base/setup/usetup/filequeue.c b/base/setup/usetup/filequeue.c index bb1f71218c1..c50203c3613 100644 --- a/base/setup/usetup/filequeue.c +++ b/base/setup/usetup/filequeue.c @@ -34,98 +34,95 @@ typedef struct _QUEUEENTRY { - struct _QUEUEENTRY *Prev; - struct _QUEUEENTRY *Next; - + LIST_ENTRY ListEntry; PWSTR SourceCabinet; /* May be NULL if the file is not in a cabinet */ PWSTR SourceRootPath; PWSTR SourcePath; - PWSTR SourceFilename; + PWSTR SourceFileName; PWSTR TargetDirectory; - PWSTR TargetFilename; + PWSTR TargetFileName; } QUEUEENTRY, *PQUEUEENTRY; - typedef struct _FILEQUEUEHEADER { - PQUEUEENTRY CopyHead; - PQUEUEENTRY CopyTail; + LIST_ENTRY DeleteQueue; // PQUEUEENTRY entries + ULONG DeleteCount; + + LIST_ENTRY RenameQueue; // PQUEUEENTRY entries + ULONG RenameCount; + + LIST_ENTRY CopyQueue; // PQUEUEENTRY entries ULONG CopyCount; + + BOOLEAN HasCurrentCabinet; + CABINET_CONTEXT CabinetContext; + CAB_SEARCH Search; + WCHAR CurrentCabinetName[MAX_PATH]; } FILEQUEUEHEADER, *PFILEQUEUEHEADER; -/* FUNCTIONS ****************************************************************/ - -static BOOLEAN HasCurrentCabinet = FALSE; -static WCHAR CurrentCabinetName[MAX_PATH]; -static CAB_SEARCH Search; - -// HACK: Temporary compatibility code. -#if 1 - static CABINET_CONTEXT CabinetContext; - #define CabinetInitialize() (CabinetInitialize(&CabinetContext)) - #define CabinetSetEventHandlers(a,b,c) (CabinetSetEventHandlers(&CabinetContext,(a),(b),(c))) - #define CabinetSetCabinetName(a) (CabinetSetCabinetName(&CabinetContext,(a))) - #define CabinetOpen() (CabinetOpen(&CabinetContext)) - #define CabinetGetCabinetName() (CabinetGetCabinetName(&CabinetContext)) - #define CabinetGetCabinetReservedArea(a) (CabinetGetCabinetReservedArea(&CabinetContext,(a))) - #define CabinetFindNextFileSequential(a,b) (CabinetFindNextFileSequential(&CabinetContext,(a),(b))) - #define CabinetFindFirst(a,b) (CabinetFindFirst(&CabinetContext,(a),(b))) - #define CabinetSetDestinationPath(a) (CabinetSetDestinationPath(&CabinetContext,(a))) - #define CabinetExtractFile(a) (CabinetExtractFile(&CabinetContext,(a))) - #define CabinetCleanup() (CabinetCleanup(&CabinetContext)) -#endif - -NTSTATUS +/* SETUP* API COMPATIBILITY FUNCTIONS ****************************************/ + +static NTSTATUS SetupExtractFile( - PWCHAR CabinetFileName, - PWCHAR SourceFileName, - PWCHAR DestinationPathName) + IN OUT PFILEQUEUEHEADER QueueHeader, + IN PCWSTR CabinetFileName, + IN PCWSTR SourceFileName, + IN PCWSTR DestinationPathName) { ULONG CabStatus; - DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n", + DPRINT("SetupExtractFile(CabinetFileName: '%S', SourceFileName: '%S', DestinationPathName: '%S')\n", CabinetFileName, SourceFileName, DestinationPathName); - if (HasCurrentCabinet) + if (QueueHeader->HasCurrentCabinet) { - DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName); + DPRINT("CurrentCabinetName: '%S'\n", QueueHeader->CurrentCabinetName); } - if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0)) + if (QueueHeader->HasCurrentCabinet && + (wcscmp(CabinetFileName, QueueHeader->CurrentCabinetName) == 0)) { DPRINT("Using same cabinet as last time\n"); /* Use our last location because the files should be sequential */ - CabStatus = CabinetFindNextFileSequential(SourceFileName, &Search); + CabStatus = CabinetFindNextFileSequential(&QueueHeader->CabinetContext, + SourceFileName, + &QueueHeader->Search); if (CabStatus != CAB_STATUS_SUCCESS) { DPRINT("Sequential miss on file: %S\n", SourceFileName); /* Looks like we got unlucky */ - CabStatus = CabinetFindFirst(SourceFileName, &Search); + CabStatus = CabinetFindFirst(&QueueHeader->CabinetContext, + SourceFileName, + &QueueHeader->Search); } } else { DPRINT("Using new cabinet\n"); - if (HasCurrentCabinet) + if (QueueHeader->HasCurrentCabinet) { - CabinetCleanup(); + QueueHeader->HasCurrentCabinet = FALSE; + CabinetCleanup(&QueueHeader->CabinetContext); } - wcscpy(CurrentCabinetName, CabinetFileName); + RtlStringCchCopyW(QueueHeader->CurrentCabinetName, + ARRAYSIZE(QueueHeader->CurrentCabinetName), + CabinetFileName); - CabinetInitialize(); - CabinetSetEventHandlers(NULL, NULL, NULL); - CabinetSetCabinetName(CabinetFileName); + CabinetInitialize(&QueueHeader->CabinetContext); + CabinetSetEventHandlers(&QueueHeader->CabinetContext, + NULL, NULL, NULL); + CabinetSetCabinetName(&QueueHeader->CabinetContext, CabinetFileName); - CabStatus = CabinetOpen(); + CabStatus = CabinetOpen(&QueueHeader->CabinetContext); if (CabStatus == CAB_STATUS_SUCCESS) { - DPRINT("Opened cabinet %S\n", CabinetGetCabinetName()); - HasCurrentCabinet = TRUE; + DPRINT("Opened cabinet %S\n", CabinetFileName /*CabinetGetCabinetName(&QueueHeader->CabinetContext)*/); + QueueHeader->HasCurrentCabinet = TRUE; } else { @@ -134,17 +131,20 @@ SetupExtractFile( } /* We have to start at the beginning here */ - CabStatus = CabinetFindFirst(SourceFileName, &Search); + CabStatus = CabinetFindFirst(&QueueHeader->CabinetContext, + SourceFileName, + &QueueHeader->Search); } if (CabStatus != CAB_STATUS_SUCCESS) { - DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName()); + DPRINT1("Unable to find '%S' in cabinet '%S'\n", + SourceFileName, CabinetGetCabinetName(&QueueHeader->CabinetContext)); return STATUS_UNSUCCESSFUL; } - CabinetSetDestinationPath(DestinationPathName); - CabStatus = CabinetExtractFile(&Search); + CabinetSetDestinationPath(&QueueHeader->CabinetContext, DestinationPathName); + CabStatus = CabinetExtractFile(&QueueHeader->CabinetContext, &QueueHeader->Search); if (CabStatus != CAB_STATUS_SUCCESS) { DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus); @@ -160,27 +160,63 @@ SetupOpenFileQueue(VOID) { PFILEQUEUEHEADER QueueHeader; - /* Allocate queue header */ - QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(FILEQUEUEHEADER)); + /* Allocate the queue header */ + QueueHeader = RtlAllocateHeap(ProcessHeap, 0, sizeof(FILEQUEUEHEADER)); if (QueueHeader == NULL) return NULL; - /* Initialize queue header */ - RtlZeroMemory(QueueHeader, - sizeof(FILEQUEUEHEADER)); + RtlZeroMemory(QueueHeader, sizeof(FILEQUEUEHEADER)); + + /* Initialize the file queues */ + InitializeListHead(&QueueHeader->DeleteQueue); + QueueHeader->DeleteCount = 0; + InitializeListHead(&QueueHeader->RenameQueue); + QueueHeader->RenameCount = 0; + InitializeListHead(&QueueHeader->CopyQueue); + QueueHeader->CopyCount = 0; + + QueueHeader->HasCurrentCabinet = FALSE; return (HSPFILEQ)QueueHeader; } +static VOID +SetupDeleteQueueEntry( + IN PQUEUEENTRY Entry) +{ + if (Entry == NULL) + return; + + /* 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) + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + + if (Entry->SourceFileName != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourceFileName); + + if (Entry->TargetDirectory != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); + + if (Entry->TargetFileName != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->TargetFileName); + + /* Delete queue entry */ + RtlFreeHeap(ProcessHeap, 0, Entry); +} VOID WINAPI SetupCloseFileQueue( - HSPFILEQ QueueHandle) + IN HSPFILEQ QueueHandle) { PFILEQUEUEHEADER QueueHeader; + PLIST_ENTRY ListEntry; PQUEUEENTRY Entry; if (QueueHandle == NULL) @@ -188,71 +224,53 @@ SetupCloseFileQueue( QueueHeader = (PFILEQUEUEHEADER)QueueHandle; - /* Delete copy queue */ - Entry = QueueHeader->CopyHead; - while (Entry != NULL) + /* Delete the delete queue */ + while (!IsListEmpty(&QueueHeader->DeleteQueue)) { - /* 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) - RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); - - if (Entry->SourceFilename != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); - - if (Entry->TargetDirectory != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); - - if (Entry->TargetFilename != NULL) - RtlFreeHeap(ProcessHeap, 0, Entry->TargetFilename); - - /* Unlink current queue entry */ - if (Entry->Next != NULL) - { - QueueHeader->CopyHead = Entry->Next; - QueueHeader->CopyHead->Prev = NULL; - } - else - { - QueueHeader->CopyHead = NULL; - QueueHeader->CopyTail = NULL; - } + ListEntry = RemoveHeadList(&QueueHeader->DeleteQueue); + Entry = CONTAINING_RECORD(ListEntry, QUEUEENTRY, ListEntry); + SetupDeleteQueueEntry(Entry); + } - /* Delete queue entry */ - RtlFreeHeap(ProcessHeap, 0, Entry); + /* Delete the rename queue */ + while (!IsListEmpty(&QueueHeader->RenameQueue)) + { + ListEntry = RemoveHeadList(&QueueHeader->RenameQueue); + Entry = CONTAINING_RECORD(ListEntry, QUEUEENTRY, ListEntry); + SetupDeleteQueueEntry(Entry); + } - /* Get next queue entry */ - Entry = QueueHeader->CopyHead; + /* Delete the copy queue */ + while (!IsListEmpty(&QueueHeader->CopyQueue)) + { + ListEntry = RemoveHeadList(&QueueHeader->CopyQueue); + Entry = CONTAINING_RECORD(ListEntry, QUEUEENTRY, ListEntry); + SetupDeleteQueueEntry(Entry); } /* Delete queue header */ RtlFreeHeap(ProcessHeap, 0, QueueHeader); } - +/* A simplified version of SetupQueueCopyW that wraps Cabinet support around */ BOOL -SetupQueueCopy( - HSPFILEQ QueueHandle, - PCWSTR SourceCabinet, - PCWSTR SourceRootPath, - PCWSTR SourcePath, - PCWSTR SourceFilename, - PCWSTR TargetDirectory, - PCWSTR TargetFilename) +WINAPI +SetupQueueCopyWithCab( // SetupQueueCopyW + IN HSPFILEQ QueueHandle, + IN PCWSTR SourceCabinet OPTIONAL, + IN PCWSTR SourceRootPath, + IN PCWSTR SourcePath OPTIONAL, + IN PCWSTR SourceFileName, + IN PCWSTR TargetDirectory, + IN PCWSTR TargetFileName OPTIONAL) { PFILEQUEUEHEADER QueueHeader; PQUEUEENTRY Entry; ULONG Length; - /* SourceCabinet may be NULL */ if (QueueHandle == NULL || SourceRootPath == NULL || - SourceFilename == NULL || + SourceFileName == NULL || TargetDirectory == NULL) { return FALSE; @@ -260,194 +278,351 @@ SetupQueueCopy( QueueHeader = (PFILEQUEUEHEADER)QueueHandle; + DPRINT("SetupQueueCopy(Cab '%S', SrcRootPath '%S', SrcPath '%S', SrcFN '%S' --> DstPath '%S', DstFN '%S')\n", + SourceCabinet ? SourceCabinet : L"n/a", + SourceRootPath, SourcePath, SourceFileName, + TargetDirectory, TargetFileName); + /* Allocate new queue entry */ - Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap, - 0, - sizeof(QUEUEENTRY)); + Entry = RtlAllocateHeap(ProcessHeap, 0, sizeof(QUEUEENTRY)); if (Entry == NULL) return FALSE; - RtlZeroMemory(Entry, - sizeof(QUEUEENTRY)); + RtlZeroMemory(Entry, sizeof(QUEUEENTRY)); /* Copy source cabinet if available */ + Entry->SourceCabinet = NULL; if (SourceCabinet != NULL) { Length = wcslen(SourceCabinet); - Entry->SourceCabinet = (WCHAR*)RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); + 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] = UNICODE_NULL; - } - else - { - Entry->SourceCabinet = NULL; + RtlStringCchCopyW(Entry->SourceCabinet, Length + 1, SourceCabinet); } /* Copy source root path */ Length = wcslen(SourceRootPath); - Entry->SourceRootPath = (WCHAR*)RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); + Entry->SourceRootPath = RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); if (Entry->SourceRootPath == NULL) { if (Entry->SourceCabinet != NULL) - { RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - } RtlFreeHeap(ProcessHeap, 0, Entry); return FALSE; } - - wcsncpy(Entry->SourceRootPath, SourceRootPath, Length); - Entry->SourceRootPath[Length] = UNICODE_NULL; + RtlStringCchCopyW(Entry->SourceRootPath, Length + 1, SourceRootPath); /* Copy source path */ + Entry->SourcePath = NULL; if (SourcePath != NULL) { Length = wcslen(SourcePath); if ((Length > 0) && (SourcePath[Length - 1] == L'\\')) Length--; - Entry->SourcePath = (WCHAR*)RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); + Entry->SourcePath = RtlAllocateHeap(ProcessHeap, + 0, + (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; } - - wcsncpy(Entry->SourcePath, SourcePath, Length); - Entry->SourcePath[Length] = UNICODE_NULL; + RtlStringCchCopyW(Entry->SourcePath, Length + 1, SourcePath); } /* Copy source file name */ - Length = wcslen(SourceFilename); - Entry->SourceFilename = (WCHAR*)RtlAllocateHeap(ProcessHeap, + Length = wcslen(SourceFileName); + Entry->SourceFileName = (WCHAR*)RtlAllocateHeap(ProcessHeap, 0, (Length + 1) * sizeof(WCHAR)); - if (Entry->SourceFilename == NULL) + if (Entry->SourceFileName == NULL) { + if (Entry->SourcePath != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + + RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); + if (Entry->SourceCabinet != NULL) - { RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - } - RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); RtlFreeHeap(ProcessHeap, 0, Entry); return FALSE; } - - wcsncpy(Entry->SourceFilename, SourceFilename, Length); - Entry->SourceFilename[Length] = UNICODE_NULL; + RtlStringCchCopyW(Entry->SourceFileName, Length + 1, SourceFileName); /* Copy target directory */ Length = wcslen(TargetDirectory); if ((Length > 0) && (TargetDirectory[Length - 1] == L'\\')) Length--; - Entry->TargetDirectory = (WCHAR*)RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); + Entry->TargetDirectory = RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); if (Entry->TargetDirectory == NULL) { + RtlFreeHeap(ProcessHeap, 0, Entry->SourceFileName); + + if (Entry->SourcePath != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + + RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); + if (Entry->SourceCabinet != NULL) - { RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - } - RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); RtlFreeHeap(ProcessHeap, 0, Entry); return FALSE; } - - wcsncpy(Entry->TargetDirectory, TargetDirectory, Length); - Entry->TargetDirectory[Length] = UNICODE_NULL; + RtlStringCchCopyW(Entry->TargetDirectory, Length + 1, TargetDirectory); /* Copy optional target filename */ - if (TargetFilename != NULL) + Entry->TargetFileName = NULL; + if (TargetFileName != NULL) { - Length = wcslen(TargetFilename); - Entry->TargetFilename = (WCHAR*)RtlAllocateHeap(ProcessHeap, - 0, - (Length + 1) * sizeof(WCHAR)); - if (Entry->TargetFilename == NULL) + Length = wcslen(TargetFileName); + Entry->TargetFileName = RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->TargetFileName == NULL) { + RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); + RtlFreeHeap(ProcessHeap, 0, Entry->SourceFileName); + + if (Entry->SourcePath != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + + RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); + if (Entry->SourceCabinet != NULL) - { RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet); - } - RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); - RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename); - RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); RtlFreeHeap(ProcessHeap, 0, Entry); return FALSE; } - - wcsncpy(Entry->TargetFilename, TargetFilename, Length); - Entry->TargetFilename[Length] = UNICODE_NULL; + RtlStringCchCopyW(Entry->TargetFileName, Length + 1, TargetFileName); } /* Append queue entry */ - if (QueueHeader->CopyHead == NULL) // && QueueHeader->CopyTail == NULL) + InsertTailList(&QueueHeader->CopyQueue, &Entry->ListEntry); + ++QueueHeader->CopyCount; + + return TRUE; +} + +BOOL +WINAPI +SetupQueueDeleteW( + IN HSPFILEQ QueueHandle, + IN PCWSTR PathPart1, + IN PCWSTR PathPart2 OPTIONAL) +{ + PFILEQUEUEHEADER QueueHeader; + PQUEUEENTRY Entry; + ULONG Length; + + if (QueueHandle == NULL || PathPart1 == NULL) { - Entry->Prev = NULL; - Entry->Next = NULL; - QueueHeader->CopyHead = Entry; - QueueHeader->CopyTail = Entry; + return FALSE; } - else + + QueueHeader = (PFILEQUEUEHEADER)QueueHandle; + + DPRINT1("SetupQueueDeleteW(PathPart1 '%S', PathPart2 '%S')\n", + PathPart1, PathPart2); + + /* Allocate new queue entry */ + Entry = RtlAllocateHeap(ProcessHeap, 0, sizeof(QUEUEENTRY)); + if (Entry == NULL) + return FALSE; + + RtlZeroMemory(Entry, sizeof(QUEUEENTRY)); + + Entry->SourceCabinet = NULL; + Entry->SourceRootPath = NULL; + Entry->SourcePath = NULL; + Entry->SourceFileName = NULL; + + /* Copy first part of path */ + Length = wcslen(PathPart1); + // if ((Length > 0) && (SourcePath[Length - 1] == L'\\')) + // Length--; + Entry->TargetDirectory = RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->TargetDirectory == NULL) { - Entry->Prev = QueueHeader->CopyTail; - Entry->Next = NULL; - QueueHeader->CopyTail->Next = Entry; - QueueHeader->CopyTail = Entry; + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + RtlStringCchCopyW(Entry->TargetDirectory, Length + 1, PathPart1); + + /* Copy optional second part of path */ + if (PathPart2 != NULL) + { + Length = wcslen(PathPart2); + Entry->TargetFileName = RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->TargetFileName == NULL) + { + RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + RtlStringCchCopyW(Entry->TargetFileName, Length + 1, PathPart2); } - QueueHeader->CopyCount++; + /* Append the queue entry */ + InsertTailList(&QueueHeader->DeleteQueue, &Entry->ListEntry); + ++QueueHeader->DeleteCount; return TRUE; } +BOOL +WINAPI +SetupQueueRenameW( + IN HSPFILEQ QueueHandle, + IN PCWSTR SourcePath, + IN PCWSTR SourceFileName OPTIONAL, + IN PCWSTR TargetPath OPTIONAL, + IN PCWSTR TargetFileName) +{ + PFILEQUEUEHEADER QueueHeader; + PQUEUEENTRY Entry; + ULONG Length; + + if (QueueHandle == NULL || + SourcePath == NULL || + TargetFileName == NULL) + { + return FALSE; + } + + QueueHeader = (PFILEQUEUEHEADER)QueueHandle; + + DPRINT1("SetupQueueRenameW(SrcPath '%S', SrcFN '%S' --> DstPath '%S', DstFN '%S')\n", + SourcePath, SourceFileName, TargetPath, TargetFileName); + + /* Allocate a new queue entry */ + Entry = RtlAllocateHeap(ProcessHeap, 0, sizeof(QUEUEENTRY)); + if (Entry == NULL) + return FALSE; + + RtlZeroMemory(Entry, sizeof(QUEUEENTRY)); + + Entry->SourceCabinet = NULL; + Entry->SourceRootPath = NULL; + + /* Copy source path */ + Length = wcslen(SourcePath); + if ((Length > 0) && (SourcePath[Length - 1] == L'\\')) + Length--; + Entry->SourcePath = RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->SourcePath == NULL) + { + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + RtlStringCchCopyW(Entry->SourcePath, Length + 1, SourcePath); + + /* Copy optional source file name */ + Entry->SourceFileName = NULL; + if (SourceFileName != NULL) + { + Length = wcslen(SourceFileName); + Entry->SourceFileName = (WCHAR*)RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->SourceFileName == NULL) + { + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + RtlStringCchCopyW(Entry->SourceFileName, Length + 1, SourceFileName); + } + + /* Copy optional target directory */ + Entry->TargetDirectory = NULL; + if (TargetPath != NULL) + { + Length = wcslen(TargetPath); + if ((Length > 0) && (TargetPath[Length - 1] == L'\\')) + Length--; + Entry->TargetDirectory = RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->TargetDirectory == NULL) + { + if (Entry->SourceFileName != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourceFileName); + + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + RtlStringCchCopyW(Entry->TargetDirectory, Length + 1, TargetPath); + } + + /* Copy target filename */ + Length = wcslen(TargetFileName); + Entry->TargetFileName = RtlAllocateHeap(ProcessHeap, + 0, + (Length + 1) * sizeof(WCHAR)); + if (Entry->TargetFileName == NULL) + { + if (Entry->TargetDirectory != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory); + + if (Entry->SourceFileName != NULL) + RtlFreeHeap(ProcessHeap, 0, Entry->SourceFileName); + + RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath); + RtlFreeHeap(ProcessHeap, 0, Entry); + return FALSE; + } + RtlStringCchCopyW(Entry->TargetFileName, Length + 1, TargetFileName); + + /* Append the queue entry */ + InsertTailList(&QueueHeader->RenameQueue, &Entry->ListEntry); + ++QueueHeader->RenameCount; + + return TRUE; +} BOOL WINAPI SetupCommitFileQueueW( - HWND Owner, - HSPFILEQ QueueHandle, - PSP_FILE_CALLBACK_W MsgHandler, - PVOID Context) + IN HWND Owner, + IN HSPFILEQ QueueHandle, + IN PSP_FILE_CALLBACK_W MsgHandler, + IN PVOID Context OPTIONAL) { - WCHAR CabinetName[MAX_PATH]; + BOOL Success = TRUE; // Suppose success + NTSTATUS Status; PFILEQUEUEHEADER QueueHeader; + PLIST_ENTRY ListEntry; PQUEUEENTRY Entry; - NTSTATUS Status; - PCWSTR TargetRootPath, TargetPath; - + FILEPATHS_W FilePathInfo; + WCHAR CabinetName[MAX_PATH]; WCHAR FileSrcPath[MAX_PATH]; WCHAR FileDstPath[MAX_PATH]; - TargetRootPath = ((PCOPYCONTEXT)Context)->DestinationRootPath; - TargetPath = ((PCOPYCONTEXT)Context)->InstallPath; - if (QueueHandle == NULL) return FALSE; @@ -455,74 +630,203 @@ SetupCommitFileQueueW( MsgHandler(Context, SPFILENOTIFY_STARTQUEUE, - 0, + (UINT_PTR)Owner, 0); + + /* + * Commit the delete queue + */ + MsgHandler(Context, SPFILENOTIFY_STARTSUBQUEUE, - FILEOP_COPY, - QueueHeader->CopyCount); + FILEOP_DELETE, + QueueHeader->DeleteCount); - /* Commit copy queue */ - Entry = QueueHeader->CopyHead; - while (Entry != NULL) + ListEntry = QueueHeader->DeleteQueue.Flink; + while (ListEntry != &QueueHeader->DeleteQueue) { - /* Build the full source path */ - CombinePaths(FileSrcPath, ARRAYSIZE(FileSrcPath), 3, - Entry->SourceRootPath, Entry->SourcePath, - Entry->SourceFilename); + Entry = CONTAINING_RECORD(ListEntry, QUEUEENTRY, ListEntry); + ListEntry = ListEntry->Flink; /* Build the full target path */ - wcscpy(FileDstPath, TargetRootPath); - if (Entry->TargetDirectory[0] == UNICODE_NULL) - { - /* Installation path */ + CombinePaths(FileDstPath, ARRAYSIZE(FileDstPath), 2, + Entry->TargetDirectory, Entry->TargetFileName); + // RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath), Entry->TargetDirectory); + // ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->TargetFileName); - /* Add the installation path */ - ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, TargetPath); - } - else if (Entry->TargetDirectory[0] == L'\\') + DPRINT1(" -----> " "Delete: '%S'\n", FileDstPath); + + FilePathInfo.Target = FileDstPath; + FilePathInfo.Source = NULL; + FilePathInfo.Win32Error = STATUS_SUCCESS; + FilePathInfo.Flags = 0; // FIXME: Unused yet... + + MsgHandler(Context, + SPFILENOTIFY_STARTDELETE, + (UINT_PTR)&FilePathInfo, + FILEOP_DELETE); + + /* Force-delete the file */ + Status = SetupDeleteFile(FileDstPath, TRUE); + if (!NT_SUCCESS(Status)) { - /* Absolute path */ - if (Entry->TargetDirectory[1] != UNICODE_NULL) - ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->TargetDirectory); + /* An error happened */ + FilePathInfo.Win32Error = (UINT)Status; + MsgHandler(Context, + SPFILENOTIFY_DELETEERROR, + (UINT_PTR)&FilePathInfo, + 0); + Success = FALSE; } - else // if (Entry->TargetDirectory[0] != L'\\') - { - /* Path relative to the installation path */ - /* Add the installation path */ - ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2, - TargetPath, Entry->TargetDirectory); + /* This notification is always sent, even in case of error */ + FilePathInfo.Win32Error = (UINT)Status; + MsgHandler(Context, + SPFILENOTIFY_ENDDELETE, + (UINT_PTR)&FilePathInfo, + 0); + } + + MsgHandler(Context, + SPFILENOTIFY_ENDSUBQUEUE, + FILEOP_DELETE, + 0); + + + /* + * Commit the rename queue + */ + + MsgHandler(Context, + SPFILENOTIFY_STARTSUBQUEUE, + FILEOP_RENAME, + QueueHeader->RenameCount); + + ListEntry = QueueHeader->RenameQueue.Flink; + while (ListEntry != &QueueHeader->RenameQueue) + { + Entry = CONTAINING_RECORD(ListEntry, QUEUEENTRY, ListEntry); + ListEntry = ListEntry->Flink; + + /* Build the full source path */ + CombinePaths(FileSrcPath, ARRAYSIZE(FileSrcPath), 2, + Entry->SourcePath, Entry->SourceFileName); + + /* Build the full target path */ + CombinePaths(FileDstPath, ARRAYSIZE(FileDstPath), 2, + Entry->TargetDirectory, Entry->TargetFileName); + // RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath), Entry->TargetDirectory); + // ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->TargetFileName); + + DPRINT1(" -----> " "Rename: '%S' ==> '%S'\n", FileSrcPath, FileDstPath); + + FilePathInfo.Target = FileDstPath; + FilePathInfo.Source = FileSrcPath; + FilePathInfo.Win32Error = STATUS_SUCCESS; + FilePathInfo.Flags = 0; // FIXME: Unused yet... + + MsgHandler(Context, + SPFILENOTIFY_STARTRENAME, + (UINT_PTR)&FilePathInfo, + FILEOP_RENAME); + + /* Move or rename the file */ + Status = SetupMoveFile(FileSrcPath, FileDstPath, + MOVEFILE_REPLACE_EXISTING + | MOVEFILE_COPY_ALLOWED + | MOVEFILE_WRITE_THROUGH); + if (!NT_SUCCESS(Status)) + { + /* An error happened */ + FilePathInfo.Win32Error = (UINT)Status; + MsgHandler(Context, + SPFILENOTIFY_RENAMEERROR, + (UINT_PTR)&FilePathInfo, + 0); + Success = FALSE; } + /* This notification is always sent, even in case of error */ + FilePathInfo.Win32Error = (UINT)Status; + MsgHandler(Context, + SPFILENOTIFY_ENDRENAME, + (UINT_PTR)&FilePathInfo, + 0); + } + + MsgHandler(Context, + SPFILENOTIFY_ENDSUBQUEUE, + FILEOP_RENAME, + 0); + + + /* + * Commit the copy queue + */ + + MsgHandler(Context, + SPFILENOTIFY_STARTSUBQUEUE, + FILEOP_COPY, + QueueHeader->CopyCount); + + ListEntry = QueueHeader->CopyQueue.Flink; + while (ListEntry != &QueueHeader->CopyQueue) + { + Entry = CONTAINING_RECORD(ListEntry, QUEUEENTRY, ListEntry); + ListEntry = ListEntry->Flink; + + /* Build the full source path */ + CombinePaths(FileSrcPath, ARRAYSIZE(FileSrcPath), 3, + Entry->SourceRootPath, Entry->SourcePath, + Entry->SourceFileName); + + /* Build the full target path */ + RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath), Entry->TargetDirectory); + /* * If the file is in a cabinet, use only the destination path. * Otherwise possibly use a different target name. */ if (Entry->SourceCabinet == NULL) { - if (Entry->TargetFilename != NULL) - ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->TargetFilename); + if (Entry->TargetFileName != NULL) + ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->TargetFileName); else - ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->SourceFilename); + ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->SourceFileName); } - /* FIXME: Do it! */ - DPRINT("Copy: '%S' ==> '%S'\n", FileSrcPath, FileDstPath); + DPRINT(" -----> " "Copy: '%S' ==> '%S'\n", FileSrcPath, FileDstPath); + + // + // Technically, here we should create the target directory, + // if it does not already exist... before calling the handler! + // + + FilePathInfo.Target = FileDstPath; + FilePathInfo.Source = FileSrcPath; // when SourceCabinet not NULL, use CabinetName ... + FilePathInfo.Win32Error = STATUS_SUCCESS; + FilePathInfo.Flags = 0; // FIXME: Unused yet... MsgHandler(Context, SPFILENOTIFY_STARTCOPY, - (UINT_PTR)Entry->SourceFilename, + (UINT_PTR)&FilePathInfo, FILEOP_COPY); if (Entry->SourceCabinet != NULL) { - /* Extract the file */ + /* + * Extract the file from the cabinet. + * The cabinet must be in Entry->SourceRootPath only! + * (ignore Entry->SourcePath). + */ CombinePaths(CabinetName, ARRAYSIZE(CabinetName), 3, Entry->SourceRootPath, Entry->SourcePath, Entry->SourceCabinet); - Status = SetupExtractFile(CabinetName, Entry->SourceFilename, FileDstPath); + Status = SetupExtractFile(QueueHeader, + CabinetName, + Entry->SourceFileName, + FileDstPath); } else { @@ -532,20 +836,21 @@ SetupCommitFileQueueW( if (!NT_SUCCESS(Status)) { + /* An error happened */ + FilePathInfo.Win32Error = (UINT)Status; MsgHandler(Context, SPFILENOTIFY_COPYERROR, - (UINT_PTR)Entry->SourceFilename, - FILEOP_COPY); - } - else - { - MsgHandler(Context, - SPFILENOTIFY_ENDCOPY, - (UINT_PTR)Entry->SourceFilename, - FILEOP_COPY); + (UINT_PTR)&FilePathInfo, + (UINT_PTR)NULL); // FIXME: Unused yet... + Success = FALSE; } - Entry = Entry->Next; + /* This notification is always sent, even in case of error */ + FilePathInfo.Win32Error = (UINT)Status; + MsgHandler(Context, + SPFILENOTIFY_ENDCOPY, + (UINT_PTR)&FilePathInfo, + 0); } MsgHandler(Context, @@ -553,12 +858,14 @@ SetupCommitFileQueueW( FILEOP_COPY, 0); + + /* All the queues have been committed */ MsgHandler(Context, SPFILENOTIFY_ENDQUEUE, - 0, + (UINT_PTR)Success, 0); - return TRUE; + return Success; } /* EOF */ diff --git a/base/setup/usetup/filequeue.h b/base/setup/usetup/filequeue.h index 16234400359..cf608377e1a 100644 --- a/base/setup/usetup/filequeue.h +++ b/base/setup/usetup/filequeue.h @@ -26,55 +26,59 @@ #pragma once -#define SPFILENOTIFY_STARTQUEUE 0x1 -#define SPFILENOTIFY_ENDQUEUE 0x2 -#define SPFILENOTIFY_STARTSUBQUEUE 0x3 -#define SPFILENOTIFY_ENDSUBQUEUE 0x4 +#define SPFILENOTIFY_STARTQUEUE 0x00000001 +#define SPFILENOTIFY_ENDQUEUE 0x00000002 +#define SPFILENOTIFY_STARTSUBQUEUE 0x00000003 +#define SPFILENOTIFY_ENDSUBQUEUE 0x00000004 -#define SPFILENOTIFY_STARTCOPY 0xb -#define SPFILENOTIFY_ENDCOPY 0xc -#define SPFILENOTIFY_COPYERROR 0xd +#define SPFILENOTIFY_STARTDELETE 0x00000005 +#define SPFILENOTIFY_ENDDELETE 0x00000006 +#define SPFILENOTIFY_DELETEERROR 0x00000007 -#define FILEOP_COPY 0x0 -#define FILEOP_RENAME 0x1 -#define FILEOP_DELETE 0x2 -#define FILEOP_BACKUP 0x3 +#define SPFILENOTIFY_STARTRENAME 0x00000008 +#define SPFILENOTIFY_ENDRENAME 0x00000009 +#define SPFILENOTIFY_RENAMEERROR 0x0000000a -#define FILEOP_ABORT 0x0 -#define FILEOP_DOIT 0x1 -#define FILEOP_SKIP 0x2 -#define FILEOP_RETRY FILEOP_DOIT -#define FILEOP_NEWPATH 0x4 +#define SPFILENOTIFY_STARTCOPY 0x0000000b +#define SPFILENOTIFY_ENDCOPY 0x0000000c +#define SPFILENOTIFY_COPYERROR 0x0000000d + +#define SPFILENOTIFY_NEEDMEDIA 0x0000000e +#define SPFILENOTIFY_QUEUESCAN 0x0000000f + +#define FILEOP_COPY 0 +#define FILEOP_RENAME 1 +#define FILEOP_DELETE 2 +#define FILEOP_BACKUP 3 + +#define FILEOP_ABORT 0 +#define FILEOP_DOIT 1 +#define FILEOP_SKIP 2 +#define FILEOP_RETRY FILEOP_DOIT +#define FILEOP_NEWPATH 4 /* TYPES ********************************************************************/ typedef PVOID HSPFILEQ; +typedef struct _FILEPATHS_W +{ + PCWSTR Target; + PCWSTR Source; + UINT Win32Error; + ULONG Flags; +} FILEPATHS_W, *PFILEPATHS_W; + typedef UINT (CALLBACK* PSP_FILE_CALLBACK_W)( - PVOID Context, - UINT Notification, - UINT_PTR Param1, - UINT_PTR Param2); + IN PVOID Context, + IN UINT Notification, + IN UINT_PTR Param1, + IN UINT_PTR Param2); -typedef struct _COPYCONTEXT -{ - LPCWSTR DestinationRootPath; /* Not owned by this structure */ - LPCWSTR InstallPath; /* Not owned by this structure */ - ULONG TotalOperations; - ULONG CompletedOperations; - PPROGRESSBAR ProgressBar; - PPROGRESSBAR MemoryBars[4]; -} COPYCONTEXT, *PCOPYCONTEXT; /* FUNCTIONS ****************************************************************/ -NTSTATUS -SetupExtractFile( - PWCHAR CabinetFileName, - PWCHAR SourceFileName, - PWCHAR DestinationFileName); - HSPFILEQ WINAPI SetupOpenFileQueue(VOID); @@ -99,22 +103,40 @@ SetupQueueCopyWNew( IN DWORD CopyStyle); #endif +/* A simplified version of SetupQueueCopyW that wraps Cabinet support around */ +BOOL +WINAPI +SetupQueueCopyWithCab( // SetupQueueCopyW + IN HSPFILEQ QueueHandle, + IN PCWSTR SourceCabinet OPTIONAL, + IN PCWSTR SourceRootPath, + IN PCWSTR SourcePath OPTIONAL, + IN PCWSTR SourceFileName, + IN PCWSTR TargetDirectory, + IN PCWSTR TargetFileName OPTIONAL); + BOOL -SetupQueueCopy( - HSPFILEQ QueueHandle, - PCWSTR SourceCabinet, - PCWSTR SourceRootPath, - PCWSTR SourcePath, - PCWSTR SourceFilename, - PCWSTR TargetDirectory, - PCWSTR TargetFilename); +WINAPI +SetupQueueDeleteW( + IN HSPFILEQ QueueHandle, + IN PCWSTR PathPart1, + IN PCWSTR PathPart2 OPTIONAL); + +BOOL +WINAPI +SetupQueueRenameW( + IN HSPFILEQ QueueHandle, + IN PCWSTR SourcePath, + IN PCWSTR SourceFileName OPTIONAL, + IN PCWSTR TargetPath OPTIONAL, + IN PCWSTR TargetFileName); BOOL WINAPI SetupCommitFileQueueW( - HWND Owner, - HSPFILEQ QueueHandle, - PSP_FILE_CALLBACK_W MsgHandler, - PVOID Context); + IN HWND Owner, + IN HSPFILEQ QueueHandle, + IN PSP_FILE_CALLBACK_W MsgHandler, + IN PVOID Context OPTIONAL); /* EOF */ diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c index edd98fd6547..929a4dca9ab 100644 --- a/base/setup/usetup/usetup.c +++ b/base/setup/usetup/usetup.c @@ -71,6 +71,8 @@ static PGENERIC_LIST NtOsInstallsList = NULL; // HACK: Temporary compatibility code. #if 1 + #define SetupQueueCopy SetupQueueCopyWithCab + static CABINET_CONTEXT CabinetContext; #define CabinetInitialize() (CabinetInitialize(&CabinetContext)) #define CabinetSetEventHandlers(a,b,c) (CabinetSetEventHandlers(&CabinetContext,(a),(b),(c))) @@ -3494,6 +3496,7 @@ AddSectionToCopyQueueCab(HINF InfFile, PWCHAR FileKeyValue; PWCHAR DirKeyValue; PWCHAR TargetFileName; + WCHAR FileDstPath[MAX_PATH]; /* * This code enumerates the list of files in reactos.dff / reactos.inf @@ -3549,12 +3552,46 @@ AddSectionToCopyQueueCab(HINF InfFile, break; } +#if 1 // HACK moved! (r66604) + { + ULONG Length = wcslen(DirKeyValue); + if ((Length > 0) && (DirKeyValue[Length - 1] == L'\\')) + Length--; + DirKeyValue[Length] = UNICODE_NULL; + } + + /* Build the full target path */ + RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath), + USetupData.DestinationRootPath.Buffer); + if (DirKeyValue[0] == UNICODE_NULL) + { + /* Installation path */ + + /* Add the installation path */ + ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, USetupData.InstallPath.Buffer); + } + else if (DirKeyValue[0] == L'\\') + { + /* Absolute path */ + // if (DirKeyValue[1] != UNICODE_NULL) + ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, DirKeyValue); + } + else // if (DirKeyValue[0] != L'\\') + { + /* Path relative to the installation path */ + + /* Add the installation path */ + ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2, + USetupData.InstallPath.Buffer, DirKeyValue); + } +#endif + if (!SetupQueueCopy(USetupData.SetupFileQueue, SourceCabinet, USetupData.SourceRootPath.Buffer, USetupData.SourceRootDir.Buffer, FileKeyName, - DirKeyValue, + FileDstPath, TargetFileName)) { /* FIXME: Handle error! */ @@ -3584,6 +3621,7 @@ AddSectionToCopyQueue(HINF InfFile, PWCHAR DirKeyValue; PWCHAR TargetFileName; WCHAR CompleteOrigDirName[512]; // FIXME: MAX_PATH is not enough? + WCHAR FileDstPath[MAX_PATH]; if (SourceCabinet) return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir); @@ -3683,12 +3721,46 @@ AddSectionToCopyQueue(HINF InfFile, DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName); } +#if 1 // HACK moved! (r66604) + { + ULONG Length = wcslen(DirKeyValue); + if ((Length > 0) && (DirKeyValue[Length - 1] == L'\\')) + Length--; + DirKeyValue[Length] = UNICODE_NULL; + } + + /* Build the full target path */ + RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath), + USetupData.DestinationRootPath.Buffer); + if (DirKeyValue[0] == UNICODE_NULL) + { + /* Installation path */ + + /* Add the installation path */ + ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, USetupData.InstallPath.Buffer); + } + else if (DirKeyValue[0] == L'\\') + { + /* Absolute path */ + // if (DirKeyValue[1] != UNICODE_NULL) + ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, DirKeyValue); + } + else // if (DirKeyValue[0] != L'\\') + { + /* Path relative to the installation path */ + + /* Add the installation path */ + ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2, + USetupData.InstallPath.Buffer, DirKeyValue); + } +#endif + if (!SetupQueueCopy(USetupData.SetupFileQueue, SourceCabinet, USetupData.SourceRootPath.Buffer, CompleteOrigDirName, FileKeyName, - DirKeyValue, + FileDstPath, TargetFileName)) { /* FIXME: Handle error! */ @@ -3938,9 +4010,15 @@ PrepareCopyPage(PINPUT_RECORD Ir) return FILE_COPY_PAGE; } +typedef struct _COPYCONTEXT +{ + ULONG TotalOperations; + ULONG CompletedOperations; + PPROGRESSBAR ProgressBar; + PPROGRESSBAR MemoryBars[4]; +} COPYCONTEXT, *PCOPYCONTEXT; -VOID -NTAPI +static VOID SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext, IN BOOLEAN First) { @@ -3967,7 +4045,6 @@ SetupUpdateMemoryInfo(IN PCOPYCONTEXT CopyContext, ProgressSetStep(CopyContext->MemoryBars[2], PerfInfo.AvailablePages); } - static UINT CALLBACK FileCopyCallback(PVOID Context, @@ -3975,26 +4052,78 @@ FileCopyCallback(PVOID Context, UINT_PTR Param1, UINT_PTR Param2) { - PCOPYCONTEXT CopyContext; - - CopyContext = (PCOPYCONTEXT)Context; + PCOPYCONTEXT CopyContext = (PCOPYCONTEXT)Context; + PFILEPATHS_W FilePathInfo; + PCWSTR SrcFileName, DstFileName; switch (Notification) { case SPFILENOTIFY_STARTSUBQUEUE: + { CopyContext->TotalOperations = (ULONG)Param2; + CopyContext->CompletedOperations = 0; ProgressSetStepCount(CopyContext->ProgressBar, CopyContext->TotalOperations); SetupUpdateMemoryInfo(CopyContext, TRUE); break; + } + case SPFILENOTIFY_STARTDELETE: + case SPFILENOTIFY_STARTRENAME: case SPFILENOTIFY_STARTCOPY: - /* Display copy message */ - CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), (PWSTR)Param1); + { + FilePathInfo = (PFILEPATHS_W)Param1; + + if (Notification == SPFILENOTIFY_STARTDELETE) + { + /* Display delete message */ + ASSERT(Param2 == FILEOP_DELETE); + + DstFileName = wcsrchr(FilePathInfo->Target, L'\\'); + if (DstFileName) ++DstFileName; + else DstFileName = FilePathInfo->Target; + + CONSOLE_SetStatusText(MUIGetString(STRING_DELETING), + DstFileName); + } + else if (Notification == SPFILENOTIFY_STARTRENAME) + { + /* Display move/rename message */ + ASSERT(Param2 == FILEOP_RENAME); + + SrcFileName = wcsrchr(FilePathInfo->Source, L'\\'); + if (SrcFileName) ++SrcFileName; + else SrcFileName = FilePathInfo->Source; + + DstFileName = wcsrchr(FilePathInfo->Target, L'\\'); + if (DstFileName) ++DstFileName; + else DstFileName = FilePathInfo->Target; + + // TODO: Determine whether using STRING_RENAMING or STRING_MOVING + CONSOLE_SetStatusText(MUIGetString(STRING_MOVING), + SrcFileName, DstFileName); + } + else if (Notification == SPFILENOTIFY_STARTCOPY) + { + /* Display copy message */ + ASSERT(Param2 == FILEOP_COPY); + + SrcFileName = wcsrchr(FilePathInfo->Source, L'\\'); + if (SrcFileName) ++SrcFileName; + else SrcFileName = FilePathInfo->Source; + + CONSOLE_SetStatusText(MUIGetString(STRING_COPYING), + SrcFileName); + } + SetupUpdateMemoryInfo(CopyContext, FALSE); break; + } + case SPFILENOTIFY_ENDDELETE: + case SPFILENOTIFY_ENDRENAME: case SPFILENOTIFY_ENDCOPY: + { CopyContext->CompletedOperations++; /* SYSREG checkpoint */ @@ -4004,9 +4133,10 @@ FileCopyCallback(PVOID Context, ProgressNextStep(CopyContext->ProgressBar); SetupUpdateMemoryInfo(CopyContext, FALSE); break; + } } - return 0; + return FILEOP_DOIT; } @@ -4027,13 +4157,11 @@ static PAGE_NUMBER FileCopyPage(PINPUT_RECORD Ir) { COPYCONTEXT CopyContext; - unsigned int mem_bar_width; + UINT MemBarWidth; MUIDisplayPage(FILE_COPY_PAGE); /* Create context for the copy process */ - CopyContext.DestinationRootPath = USetupData.DestinationRootPath.Buffer; - CopyContext.InstallPath = USetupData.InstallPath.Buffer; CopyContext.TotalOperations = 0; CopyContext.CompletedOperations = 0; @@ -4048,13 +4176,13 @@ FileCopyPage(PINPUT_RECORD Ir) MUIGetString(STRING_SETUPCOPYINGFILES)); // fit memory bars to screen width, distribute them uniform - mem_bar_width = (xScreen - 26) / 5; - mem_bar_width -= mem_bar_width % 2; // make even + MemBarWidth = (xScreen - 26) / 5; + MemBarWidth -= MemBarWidth % 2; // make even /* ATTENTION: The following progress bars are debug stuff, which should not be translated!! */ /* Create the paged pool progress bar */ CopyContext.MemoryBars[0] = CreateProgressBar(13, 40, - 13 + mem_bar_width, + 13 + MemBarWidth, 43, 13, 44, @@ -4062,21 +4190,21 @@ FileCopyPage(PINPUT_RECORD Ir) "Kernel Pool"); /* Create the non paged pool progress bar */ - CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (mem_bar_width / 2), + CopyContext.MemoryBars[1] = CreateProgressBar((xScreen / 2)- (MemBarWidth / 2), 40, - (xScreen / 2) + (mem_bar_width / 2), + (xScreen / 2) + (MemBarWidth / 2), 43, - (xScreen / 2)- (mem_bar_width / 2), + (xScreen / 2)- (MemBarWidth / 2), 44, FALSE, "Kernel Cache"); /* Create the global memory progress bar */ - CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - mem_bar_width, + CopyContext.MemoryBars[2] = CreateProgressBar(xScreen - 13 - MemBarWidth, 40, xScreen - 13, 43, - xScreen - 13 - mem_bar_width, + xScreen - 13 - MemBarWidth, 44, FALSE, "Free Memory");