3 * Copyright (C) 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/lib/fileqsup.c
23 * PURPOSE: Interfacing with Setup* API File Queue support functions
24 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
28 /* INCLUDES *****************************************************************/
35 /* DEFINITIONS **************************************************************/
37 typedef struct _QUEUEENTRY
40 PWSTR SourceCabinet
; /* May be NULL if the file is not in a cabinet */
44 PWSTR TargetDirectory
;
46 } QUEUEENTRY
, *PQUEUEENTRY
;
48 typedef struct _FILEQUEUEHEADER
50 LIST_ENTRY DeleteQueue
; // PQUEUEENTRY entries
53 LIST_ENTRY RenameQueue
; // PQUEUEENTRY entries
56 LIST_ENTRY CopyQueue
; // PQUEUEENTRY entries
59 BOOLEAN HasCurrentCabinet
;
60 CABINET_CONTEXT CabinetContext
;
62 WCHAR CurrentCabinetName
[MAX_PATH
];
63 } FILEQUEUEHEADER
, *PFILEQUEUEHEADER
;
66 /* SETUP* API COMPATIBILITY FUNCTIONS ****************************************/
70 IN OUT PFILEQUEUEHEADER QueueHeader
,
71 IN PCWSTR CabinetFileName
,
72 IN PCWSTR SourceFileName
,
73 IN PCWSTR DestinationPathName
)
77 DPRINT("SetupExtractFile(CabinetFileName: '%S', SourceFileName: '%S', DestinationPathName: '%S')\n",
78 CabinetFileName
, SourceFileName
, DestinationPathName
);
80 if (QueueHeader
->HasCurrentCabinet
)
82 DPRINT("CurrentCabinetName: '%S'\n", QueueHeader
->CurrentCabinetName
);
85 if (QueueHeader
->HasCurrentCabinet
&&
86 (wcscmp(CabinetFileName
, QueueHeader
->CurrentCabinetName
) == 0))
88 DPRINT("Using same cabinet as last time\n");
90 /* Use our last location because the files should be sequential */
91 CabStatus
= CabinetFindNextFileSequential(&QueueHeader
->CabinetContext
,
93 &QueueHeader
->Search
);
94 if (CabStatus
!= CAB_STATUS_SUCCESS
)
96 DPRINT("Sequential miss on file: %S\n", SourceFileName
);
98 /* Looks like we got unlucky */
99 CabStatus
= CabinetFindFirst(&QueueHeader
->CabinetContext
,
101 &QueueHeader
->Search
);
106 DPRINT("Using new cabinet\n");
108 if (QueueHeader
->HasCurrentCabinet
)
110 QueueHeader
->HasCurrentCabinet
= FALSE
;
111 CabinetCleanup(&QueueHeader
->CabinetContext
);
114 RtlStringCchCopyW(QueueHeader
->CurrentCabinetName
,
115 ARRAYSIZE(QueueHeader
->CurrentCabinetName
),
118 CabinetInitialize(&QueueHeader
->CabinetContext
);
119 CabinetSetEventHandlers(&QueueHeader
->CabinetContext
,
121 CabinetSetCabinetName(&QueueHeader
->CabinetContext
, CabinetFileName
);
123 CabStatus
= CabinetOpen(&QueueHeader
->CabinetContext
);
124 if (CabStatus
== CAB_STATUS_SUCCESS
)
126 DPRINT("Opened cabinet %S\n", CabinetFileName
/*CabinetGetCabinetName(&QueueHeader->CabinetContext)*/);
127 QueueHeader
->HasCurrentCabinet
= TRUE
;
131 DPRINT("Cannot open cabinet (%d)\n", CabStatus
);
132 return STATUS_UNSUCCESSFUL
;
135 /* We have to start at the beginning here */
136 CabStatus
= CabinetFindFirst(&QueueHeader
->CabinetContext
,
138 &QueueHeader
->Search
);
141 if (CabStatus
!= CAB_STATUS_SUCCESS
)
143 DPRINT1("Unable to find '%S' in cabinet '%S'\n",
144 SourceFileName
, CabinetGetCabinetName(&QueueHeader
->CabinetContext
));
145 return STATUS_UNSUCCESSFUL
;
148 CabinetSetDestinationPath(&QueueHeader
->CabinetContext
, DestinationPathName
);
149 CabStatus
= CabinetExtractFile(&QueueHeader
->CabinetContext
, &QueueHeader
->Search
);
150 if (CabStatus
!= CAB_STATUS_SUCCESS
)
152 DPRINT("Cannot extract file %S (%d)\n", SourceFileName
, CabStatus
);
153 return STATUS_UNSUCCESSFUL
;
156 return STATUS_SUCCESS
;
161 SetupOpenFileQueue(VOID
)
163 PFILEQUEUEHEADER QueueHeader
;
165 /* Allocate the queue header */
166 QueueHeader
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(FILEQUEUEHEADER
));
167 if (QueueHeader
== NULL
)
170 RtlZeroMemory(QueueHeader
, sizeof(FILEQUEUEHEADER
));
172 /* Initialize the file queues */
173 InitializeListHead(&QueueHeader
->DeleteQueue
);
174 QueueHeader
->DeleteCount
= 0;
175 InitializeListHead(&QueueHeader
->RenameQueue
);
176 QueueHeader
->RenameCount
= 0;
177 InitializeListHead(&QueueHeader
->CopyQueue
);
178 QueueHeader
->CopyCount
= 0;
180 QueueHeader
->HasCurrentCabinet
= FALSE
;
182 return (HSPFILEQ
)QueueHeader
;
186 SetupDeleteQueueEntry(
187 IN PQUEUEENTRY Entry
)
192 /* Delete all strings */
193 if (Entry
->SourceCabinet
!= NULL
)
194 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
196 if (Entry
->SourceRootPath
!= NULL
)
197 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
199 if (Entry
->SourcePath
!= NULL
)
200 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
202 if (Entry
->SourceFileName
!= NULL
)
203 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFileName
);
205 if (Entry
->TargetDirectory
!= NULL
)
206 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
208 if (Entry
->TargetFileName
!= NULL
)
209 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetFileName
);
211 /* Delete queue entry */
212 RtlFreeHeap(ProcessHeap
, 0, Entry
);
218 IN HSPFILEQ QueueHandle
)
220 PFILEQUEUEHEADER QueueHeader
;
221 PLIST_ENTRY ListEntry
;
224 if (QueueHandle
== NULL
)
227 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
229 /* Delete the delete queue */
230 while (!IsListEmpty(&QueueHeader
->DeleteQueue
))
232 ListEntry
= RemoveHeadList(&QueueHeader
->DeleteQueue
);
233 Entry
= CONTAINING_RECORD(ListEntry
, QUEUEENTRY
, ListEntry
);
234 SetupDeleteQueueEntry(Entry
);
237 /* Delete the rename queue */
238 while (!IsListEmpty(&QueueHeader
->RenameQueue
))
240 ListEntry
= RemoveHeadList(&QueueHeader
->RenameQueue
);
241 Entry
= CONTAINING_RECORD(ListEntry
, QUEUEENTRY
, ListEntry
);
242 SetupDeleteQueueEntry(Entry
);
245 /* Delete the copy queue */
246 while (!IsListEmpty(&QueueHeader
->CopyQueue
))
248 ListEntry
= RemoveHeadList(&QueueHeader
->CopyQueue
);
249 Entry
= CONTAINING_RECORD(ListEntry
, QUEUEENTRY
, ListEntry
);
250 SetupDeleteQueueEntry(Entry
);
253 /* Delete queue header */
254 RtlFreeHeap(ProcessHeap
, 0, QueueHeader
);
259 /* A simplified version of SetupQueueCopyW that wraps Cabinet support around */
262 SetupQueueCopyWithCab(
263 IN HSPFILEQ QueueHandle
,
264 IN PCWSTR SourceRootPath
,
265 IN PCWSTR SourcePath OPTIONAL
,
266 IN PCWSTR SourceFileName
,
267 IN PCWSTR SourceDescription OPTIONAL
,
268 IN PCWSTR SourceCabinet OPTIONAL
,
269 IN PCWSTR SourceTagFile OPTIONAL
,
270 IN PCWSTR TargetDirectory
,
271 IN PCWSTR TargetFileName OPTIONAL
,
274 PFILEQUEUEHEADER QueueHeader
;
278 if (QueueHandle
== NULL
||
279 SourceRootPath
== NULL
||
280 SourceFileName
== NULL
||
281 TargetDirectory
== NULL
)
286 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
288 DPRINT("SetupQueueCopy(Cab '%S', SrcRootPath '%S', SrcPath '%S', SrcFN '%S' --> DstPath '%S', DstFN '%S')\n",
289 SourceCabinet
? SourceCabinet
: L
"n/a",
290 SourceRootPath
, SourcePath
, SourceFileName
,
291 TargetDirectory
, TargetFileName
);
293 /* Allocate new queue entry */
294 Entry
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(QUEUEENTRY
));
298 RtlZeroMemory(Entry
, sizeof(QUEUEENTRY
));
300 /* Copy source cabinet if available */
301 Entry
->SourceCabinet
= NULL
;
302 if (SourceCabinet
!= NULL
)
304 Length
= wcslen(SourceCabinet
);
305 Entry
->SourceCabinet
= RtlAllocateHeap(ProcessHeap
,
307 (Length
+ 1) * sizeof(WCHAR
));
308 if (Entry
->SourceCabinet
== NULL
)
310 RtlFreeHeap(ProcessHeap
, 0, Entry
);
313 RtlStringCchCopyW(Entry
->SourceCabinet
, Length
+ 1, SourceCabinet
);
316 /* Copy source root path */
317 Length
= wcslen(SourceRootPath
);
318 Entry
->SourceRootPath
= RtlAllocateHeap(ProcessHeap
,
320 (Length
+ 1) * sizeof(WCHAR
));
321 if (Entry
->SourceRootPath
== NULL
)
323 if (Entry
->SourceCabinet
!= NULL
)
324 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
326 RtlFreeHeap(ProcessHeap
, 0, Entry
);
329 RtlStringCchCopyW(Entry
->SourceRootPath
, Length
+ 1, SourceRootPath
);
331 /* Copy source path */
332 Entry
->SourcePath
= NULL
;
333 if (SourcePath
!= NULL
)
335 Length
= wcslen(SourcePath
);
336 if ((Length
> 0) && (SourcePath
[Length
- 1] == L
'\\'))
338 Entry
->SourcePath
= RtlAllocateHeap(ProcessHeap
,
340 (Length
+ 1) * sizeof(WCHAR
));
341 if (Entry
->SourcePath
== NULL
)
343 if (Entry
->SourceCabinet
!= NULL
)
344 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
346 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
347 RtlFreeHeap(ProcessHeap
, 0, Entry
);
350 RtlStringCchCopyW(Entry
->SourcePath
, Length
+ 1, SourcePath
);
353 /* Copy source file name */
354 Length
= wcslen(SourceFileName
);
355 Entry
->SourceFileName
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
357 (Length
+ 1) * sizeof(WCHAR
));
358 if (Entry
->SourceFileName
== NULL
)
360 if (Entry
->SourcePath
!= NULL
)
361 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
363 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
365 if (Entry
->SourceCabinet
!= NULL
)
366 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
368 RtlFreeHeap(ProcessHeap
, 0, Entry
);
371 RtlStringCchCopyW(Entry
->SourceFileName
, Length
+ 1, SourceFileName
);
373 /* Copy target directory */
374 Length
= wcslen(TargetDirectory
);
375 if ((Length
> 0) && (TargetDirectory
[Length
- 1] == L
'\\'))
377 Entry
->TargetDirectory
= RtlAllocateHeap(ProcessHeap
,
379 (Length
+ 1) * sizeof(WCHAR
));
380 if (Entry
->TargetDirectory
== NULL
)
382 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFileName
);
384 if (Entry
->SourcePath
!= NULL
)
385 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
387 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
389 if (Entry
->SourceCabinet
!= NULL
)
390 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
392 RtlFreeHeap(ProcessHeap
, 0, Entry
);
395 RtlStringCchCopyW(Entry
->TargetDirectory
, Length
+ 1, TargetDirectory
);
397 /* Copy optional target filename */
398 Entry
->TargetFileName
= NULL
;
399 if (TargetFileName
!= NULL
)
401 Length
= wcslen(TargetFileName
);
402 Entry
->TargetFileName
= RtlAllocateHeap(ProcessHeap
,
404 (Length
+ 1) * sizeof(WCHAR
));
405 if (Entry
->TargetFileName
== NULL
)
407 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
408 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFileName
);
410 if (Entry
->SourcePath
!= NULL
)
411 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
413 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
415 if (Entry
->SourceCabinet
!= NULL
)
416 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
418 RtlFreeHeap(ProcessHeap
, 0, Entry
);
421 RtlStringCchCopyW(Entry
->TargetFileName
, Length
+ 1, TargetFileName
);
424 /* Append queue entry */
425 InsertTailList(&QueueHeader
->CopyQueue
, &Entry
->ListEntry
);
426 ++QueueHeader
->CopyCount
;
434 IN HSPFILEQ QueueHandle
,
436 IN PCWSTR PathPart2 OPTIONAL
)
438 PFILEQUEUEHEADER QueueHeader
;
442 if (QueueHandle
== NULL
|| PathPart1
== NULL
)
447 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
449 DPRINT1("SetupQueueDeleteW(PathPart1 '%S', PathPart2 '%S')\n",
450 PathPart1
, PathPart2
);
452 /* Allocate new queue entry */
453 Entry
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(QUEUEENTRY
));
457 RtlZeroMemory(Entry
, sizeof(QUEUEENTRY
));
459 Entry
->SourceCabinet
= NULL
;
460 Entry
->SourceRootPath
= NULL
;
461 Entry
->SourcePath
= NULL
;
462 Entry
->SourceFileName
= NULL
;
464 /* Copy first part of path */
465 Length
= wcslen(PathPart1
);
466 // if ((Length > 0) && (SourcePath[Length - 1] == L'\\'))
468 Entry
->TargetDirectory
= RtlAllocateHeap(ProcessHeap
,
470 (Length
+ 1) * sizeof(WCHAR
));
471 if (Entry
->TargetDirectory
== NULL
)
473 RtlFreeHeap(ProcessHeap
, 0, Entry
);
476 RtlStringCchCopyW(Entry
->TargetDirectory
, Length
+ 1, PathPart1
);
478 /* Copy optional second part of path */
479 if (PathPart2
!= NULL
)
481 Length
= wcslen(PathPart2
);
482 Entry
->TargetFileName
= RtlAllocateHeap(ProcessHeap
,
484 (Length
+ 1) * sizeof(WCHAR
));
485 if (Entry
->TargetFileName
== NULL
)
487 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
488 RtlFreeHeap(ProcessHeap
, 0, Entry
);
491 RtlStringCchCopyW(Entry
->TargetFileName
, Length
+ 1, PathPart2
);
494 /* Append the queue entry */
495 InsertTailList(&QueueHeader
->DeleteQueue
, &Entry
->ListEntry
);
496 ++QueueHeader
->DeleteCount
;
504 IN HSPFILEQ QueueHandle
,
505 IN PCWSTR SourcePath
,
506 IN PCWSTR SourceFileName OPTIONAL
,
507 IN PCWSTR TargetPath OPTIONAL
,
508 IN PCWSTR TargetFileName
)
510 PFILEQUEUEHEADER QueueHeader
;
514 if (QueueHandle
== NULL
||
515 SourcePath
== NULL
||
516 TargetFileName
== NULL
)
521 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
523 DPRINT1("SetupQueueRenameW(SrcPath '%S', SrcFN '%S' --> DstPath '%S', DstFN '%S')\n",
524 SourcePath
, SourceFileName
, TargetPath
, TargetFileName
);
526 /* Allocate a new queue entry */
527 Entry
= RtlAllocateHeap(ProcessHeap
, 0, sizeof(QUEUEENTRY
));
531 RtlZeroMemory(Entry
, sizeof(QUEUEENTRY
));
533 Entry
->SourceCabinet
= NULL
;
534 Entry
->SourceRootPath
= NULL
;
536 /* Copy source path */
537 Length
= wcslen(SourcePath
);
538 if ((Length
> 0) && (SourcePath
[Length
- 1] == L
'\\'))
540 Entry
->SourcePath
= RtlAllocateHeap(ProcessHeap
,
542 (Length
+ 1) * sizeof(WCHAR
));
543 if (Entry
->SourcePath
== NULL
)
545 RtlFreeHeap(ProcessHeap
, 0, Entry
);
548 RtlStringCchCopyW(Entry
->SourcePath
, Length
+ 1, SourcePath
);
550 /* Copy optional source file name */
551 Entry
->SourceFileName
= NULL
;
552 if (SourceFileName
!= NULL
)
554 Length
= wcslen(SourceFileName
);
555 Entry
->SourceFileName
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
557 (Length
+ 1) * sizeof(WCHAR
));
558 if (Entry
->SourceFileName
== NULL
)
560 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
561 RtlFreeHeap(ProcessHeap
, 0, Entry
);
564 RtlStringCchCopyW(Entry
->SourceFileName
, Length
+ 1, SourceFileName
);
567 /* Copy optional target directory */
568 Entry
->TargetDirectory
= NULL
;
569 if (TargetPath
!= NULL
)
571 Length
= wcslen(TargetPath
);
572 if ((Length
> 0) && (TargetPath
[Length
- 1] == L
'\\'))
574 Entry
->TargetDirectory
= RtlAllocateHeap(ProcessHeap
,
576 (Length
+ 1) * sizeof(WCHAR
));
577 if (Entry
->TargetDirectory
== NULL
)
579 if (Entry
->SourceFileName
!= NULL
)
580 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFileName
);
582 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
583 RtlFreeHeap(ProcessHeap
, 0, Entry
);
586 RtlStringCchCopyW(Entry
->TargetDirectory
, Length
+ 1, TargetPath
);
589 /* Copy target filename */
590 Length
= wcslen(TargetFileName
);
591 Entry
->TargetFileName
= RtlAllocateHeap(ProcessHeap
,
593 (Length
+ 1) * sizeof(WCHAR
));
594 if (Entry
->TargetFileName
== NULL
)
596 if (Entry
->TargetDirectory
!= NULL
)
597 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
599 if (Entry
->SourceFileName
!= NULL
)
600 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFileName
);
602 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
603 RtlFreeHeap(ProcessHeap
, 0, Entry
);
606 RtlStringCchCopyW(Entry
->TargetFileName
, Length
+ 1, TargetFileName
);
608 /* Append the queue entry */
609 InsertTailList(&QueueHeader
->RenameQueue
, &Entry
->ListEntry
);
610 ++QueueHeader
->RenameCount
;
617 SetupCommitFileQueueW(
619 IN HSPFILEQ QueueHandle
,
620 IN PSP_FILE_CALLBACK_W MsgHandler
,
621 IN PVOID Context OPTIONAL
)
623 BOOL Success
= TRUE
; // Suppose success
625 PFILEQUEUEHEADER QueueHeader
;
626 PLIST_ENTRY ListEntry
;
628 FILEPATHS_W FilePathInfo
;
629 WCHAR CabinetName
[MAX_PATH
];
630 WCHAR FileSrcPath
[MAX_PATH
];
631 WCHAR FileDstPath
[MAX_PATH
];
633 if (QueueHandle
== NULL
)
636 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
639 SPFILENOTIFY_STARTQUEUE
,
645 * Commit the delete queue
649 SPFILENOTIFY_STARTSUBQUEUE
,
651 QueueHeader
->DeleteCount
);
653 ListEntry
= QueueHeader
->DeleteQueue
.Flink
;
654 while (ListEntry
!= &QueueHeader
->DeleteQueue
)
656 Entry
= CONTAINING_RECORD(ListEntry
, QUEUEENTRY
, ListEntry
);
657 ListEntry
= ListEntry
->Flink
;
659 /* Build the full target path */
660 CombinePaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 2,
661 Entry
->TargetDirectory
, Entry
->TargetFileName
);
662 // RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath), Entry->TargetDirectory);
663 // ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->TargetFileName);
665 DPRINT1(" -----> " "Delete: '%S'\n", FileDstPath
);
667 FilePathInfo
.Target
= FileDstPath
;
668 FilePathInfo
.Source
= NULL
;
669 FilePathInfo
.Win32Error
= STATUS_SUCCESS
;
670 FilePathInfo
.Flags
= 0; // FIXME: Unused yet...
673 SPFILENOTIFY_STARTDELETE
,
674 (UINT_PTR
)&FilePathInfo
,
677 /* Force-delete the file */
678 Status
= SetupDeleteFile(FileDstPath
, TRUE
);
679 if (!NT_SUCCESS(Status
))
681 /* An error happened */
682 FilePathInfo
.Win32Error
= (UINT
)Status
;
684 SPFILENOTIFY_DELETEERROR
,
685 (UINT_PTR
)&FilePathInfo
,
690 /* This notification is always sent, even in case of error */
691 FilePathInfo
.Win32Error
= (UINT
)Status
;
693 SPFILENOTIFY_ENDDELETE
,
694 (UINT_PTR
)&FilePathInfo
,
699 SPFILENOTIFY_ENDSUBQUEUE
,
705 * Commit the rename queue
709 SPFILENOTIFY_STARTSUBQUEUE
,
711 QueueHeader
->RenameCount
);
713 ListEntry
= QueueHeader
->RenameQueue
.Flink
;
714 while (ListEntry
!= &QueueHeader
->RenameQueue
)
716 Entry
= CONTAINING_RECORD(ListEntry
, QUEUEENTRY
, ListEntry
);
717 ListEntry
= ListEntry
->Flink
;
719 /* Build the full source path */
720 CombinePaths(FileSrcPath
, ARRAYSIZE(FileSrcPath
), 2,
721 Entry
->SourcePath
, Entry
->SourceFileName
);
723 /* Build the full target path */
724 CombinePaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 2,
725 Entry
->TargetDirectory
, Entry
->TargetFileName
);
726 // RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath), Entry->TargetDirectory);
727 // ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, Entry->TargetFileName);
729 DPRINT1(" -----> " "Rename: '%S' ==> '%S'\n", FileSrcPath
, FileDstPath
);
731 FilePathInfo
.Target
= FileDstPath
;
732 FilePathInfo
.Source
= FileSrcPath
;
733 FilePathInfo
.Win32Error
= STATUS_SUCCESS
;
734 FilePathInfo
.Flags
= 0; // FIXME: Unused yet...
737 SPFILENOTIFY_STARTRENAME
,
738 (UINT_PTR
)&FilePathInfo
,
741 /* Move or rename the file */
742 Status
= SetupMoveFile(FileSrcPath
, FileDstPath
,
743 MOVEFILE_REPLACE_EXISTING
744 | MOVEFILE_COPY_ALLOWED
745 | MOVEFILE_WRITE_THROUGH
);
746 if (!NT_SUCCESS(Status
))
748 /* An error happened */
749 FilePathInfo
.Win32Error
= (UINT
)Status
;
751 SPFILENOTIFY_RENAMEERROR
,
752 (UINT_PTR
)&FilePathInfo
,
757 /* This notification is always sent, even in case of error */
758 FilePathInfo
.Win32Error
= (UINT
)Status
;
760 SPFILENOTIFY_ENDRENAME
,
761 (UINT_PTR
)&FilePathInfo
,
766 SPFILENOTIFY_ENDSUBQUEUE
,
772 * Commit the copy queue
776 SPFILENOTIFY_STARTSUBQUEUE
,
778 QueueHeader
->CopyCount
);
780 ListEntry
= QueueHeader
->CopyQueue
.Flink
;
781 while (ListEntry
!= &QueueHeader
->CopyQueue
)
783 Entry
= CONTAINING_RECORD(ListEntry
, QUEUEENTRY
, ListEntry
);
784 ListEntry
= ListEntry
->Flink
;
786 /* Build the full source path */
787 CombinePaths(FileSrcPath
, ARRAYSIZE(FileSrcPath
), 3,
788 Entry
->SourceRootPath
, Entry
->SourcePath
,
789 Entry
->SourceFileName
);
791 /* Build the full target path */
792 RtlStringCchCopyW(FileDstPath
, ARRAYSIZE(FileDstPath
), Entry
->TargetDirectory
);
795 * If the file is in a cabinet, use only the destination path.
796 * Otherwise possibly use a different target name.
798 if (Entry
->SourceCabinet
== NULL
)
800 if (Entry
->TargetFileName
!= NULL
)
801 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, Entry
->TargetFileName
);
803 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, Entry
->SourceFileName
);
806 DPRINT(" -----> " "Copy: '%S' ==> '%S'\n", FileSrcPath
, FileDstPath
);
809 // Technically, here we should create the target directory,
810 // if it does not already exist... before calling the handler!
813 FilePathInfo
.Target
= FileDstPath
;
814 FilePathInfo
.Source
= FileSrcPath
; // when SourceCabinet not NULL, use CabinetName ...
815 FilePathInfo
.Win32Error
= STATUS_SUCCESS
;
816 FilePathInfo
.Flags
= 0; // FIXME: Unused yet...
819 SPFILENOTIFY_STARTCOPY
,
820 (UINT_PTR
)&FilePathInfo
,
823 if (Entry
->SourceCabinet
!= NULL
)
826 * Extract the file from the cabinet.
827 * The cabinet must be in Entry->SourceRootPath only!
828 * (ignore Entry->SourcePath).
830 CombinePaths(CabinetName
, ARRAYSIZE(CabinetName
), 3,
831 Entry
->SourceRootPath
, Entry
->SourcePath
,
832 Entry
->SourceCabinet
);
833 Status
= SetupExtractFile(QueueHeader
,
835 Entry
->SourceFileName
,
841 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
, FALSE
);
844 if (!NT_SUCCESS(Status
))
846 /* An error happened */
847 FilePathInfo
.Win32Error
= (UINT
)Status
;
849 SPFILENOTIFY_COPYERROR
,
850 (UINT_PTR
)&FilePathInfo
,
851 (UINT_PTR
)NULL
); // FIXME: Unused yet...
855 /* This notification is always sent, even in case of error */
856 FilePathInfo
.Win32Error
= (UINT
)Status
;
858 SPFILENOTIFY_ENDCOPY
,
859 (UINT_PTR
)&FilePathInfo
,
864 SPFILENOTIFY_ENDSUBQUEUE
,
869 /* All the queues have been committed */
871 SPFILENOTIFY_ENDQUEUE
,
879 /* GLOBALS *******************************************************************/
881 pSpFileQueueOpen SpFileQueueOpen
= SetupOpenFileQueue
;
882 pSpFileQueueClose SpFileQueueClose
= SetupCloseFileQueue
;
883 pSpFileQueueCopy SpFileQueueCopy
= SetupQueueCopyWithCab
;
884 pSpFileQueueDelete SpFileQueueDelete
= SetupQueueDeleteW
;
885 pSpFileQueueRename SpFileQueueRename
= SetupQueueRenameW
;
886 pSpFileQueueCommit SpFileQueueCommit
= SetupCommitFileQueueW
;