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.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: base/setup/usetup/filequeue.c
22 * PURPOSE: File queue functions
23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 /* INCLUDES *****************************************************************/
33 /* INCLUDES *****************************************************************/
35 typedef struct _QUEUEENTRY
37 struct _QUEUEENTRY
*Prev
;
38 struct _QUEUEENTRY
*Next
;
40 PWSTR SourceCabinet
; /* May be NULL if the file is not in a cabinet */
44 PWSTR TargetDirectory
;
46 } QUEUEENTRY
, *PQUEUEENTRY
;
49 typedef struct _FILEQUEUEHEADER
54 } FILEQUEUEHEADER
, *PFILEQUEUEHEADER
;
57 /* FUNCTIONS ****************************************************************/
61 SetupOpenFileQueue(VOID
)
63 PFILEQUEUEHEADER QueueHeader
;
65 /* Allocate queue header */
66 QueueHeader
= (PFILEQUEUEHEADER
)RtlAllocateHeap(ProcessHeap
,
68 sizeof(FILEQUEUEHEADER
));
69 if (QueueHeader
== NULL
)
72 /* Initialize queue header */
73 RtlZeroMemory(QueueHeader
,
74 sizeof(FILEQUEUEHEADER
));
76 return (HSPFILEQ
)QueueHeader
;
85 PFILEQUEUEHEADER QueueHeader
;
88 if (QueueHandle
== NULL
)
91 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
93 /* Delete copy queue */
94 Entry
= QueueHeader
->CopyHead
;
97 /* Delete all strings */
98 if (Entry
->SourceCabinet
!= NULL
)
99 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
101 if (Entry
->SourceRootPath
!= NULL
)
102 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
104 if (Entry
->SourcePath
!= NULL
)
105 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
107 if (Entry
->SourceFilename
!= NULL
)
108 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
110 if (Entry
->TargetDirectory
!= NULL
)
111 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
113 if (Entry
->TargetFilename
!= NULL
)
114 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetFilename
);
116 /* Unlink current queue entry */
117 if (Entry
->Next
!= NULL
)
119 QueueHeader
->CopyHead
= Entry
->Next
;
120 QueueHeader
->CopyHead
->Prev
= NULL
;
124 QueueHeader
->CopyHead
= NULL
;
125 QueueHeader
->CopyTail
= NULL
;
128 /* Delete queue entry */
129 RtlFreeHeap(ProcessHeap
, 0, Entry
);
131 /* Get next queue entry */
132 Entry
= QueueHeader
->CopyHead
;
135 /* Delete queue header */
136 RtlFreeHeap(ProcessHeap
, 0, QueueHeader
);
142 HSPFILEQ QueueHandle
,
143 PCWSTR SourceCabinet
,
144 PCWSTR SourceRootPath
,
146 PCWSTR SourceFilename
,
147 PCWSTR TargetDirectory
,
148 PCWSTR TargetFilename
)
150 PFILEQUEUEHEADER QueueHeader
;
154 /* SourceCabinet may be NULL */
155 if (QueueHandle
== NULL
||
156 SourceRootPath
== NULL
||
157 SourceFilename
== NULL
||
158 TargetDirectory
== NULL
)
163 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
165 /* Allocate new queue entry */
166 Entry
= (PQUEUEENTRY
)RtlAllocateHeap(ProcessHeap
,
175 /* Copy source cabinet if available */
176 if (SourceCabinet
!= NULL
)
178 Length
= wcslen(SourceCabinet
);
179 Entry
->SourceCabinet
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
181 (Length
+ 1) * sizeof(WCHAR
));
182 if (Entry
->SourceCabinet
== NULL
)
184 RtlFreeHeap(ProcessHeap
, 0, Entry
);
188 wcsncpy(Entry
->SourceCabinet
, SourceCabinet
, Length
);
189 Entry
->SourceCabinet
[Length
] = UNICODE_NULL
;
193 Entry
->SourceCabinet
= NULL
;
196 /* Copy source root path */
197 Length
= wcslen(SourceRootPath
);
198 Entry
->SourceRootPath
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
200 (Length
+ 1) * sizeof(WCHAR
));
201 if (Entry
->SourceRootPath
== NULL
)
203 if (Entry
->SourceCabinet
!= NULL
)
205 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
208 RtlFreeHeap(ProcessHeap
, 0, Entry
);
212 wcsncpy(Entry
->SourceRootPath
, SourceRootPath
, Length
);
213 Entry
->SourceRootPath
[Length
] = UNICODE_NULL
;
215 /* Copy source path */
216 if (SourcePath
!= NULL
)
218 Length
= wcslen(SourcePath
);
219 if ((Length
> 0) && (SourcePath
[Length
- 1] == L
'\\'))
221 Entry
->SourcePath
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
223 (Length
+ 1) * sizeof(WCHAR
));
224 if (Entry
->SourcePath
== NULL
)
226 if (Entry
->SourceCabinet
!= NULL
)
228 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
231 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
232 RtlFreeHeap(ProcessHeap
, 0, Entry
);
236 wcsncpy(Entry
->SourcePath
, SourcePath
, Length
);
237 Entry
->SourcePath
[Length
] = UNICODE_NULL
;
240 /* Copy source file name */
241 Length
= wcslen(SourceFilename
);
242 Entry
->SourceFilename
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
244 (Length
+ 1) * sizeof(WCHAR
));
245 if (Entry
->SourceFilename
== NULL
)
247 if (Entry
->SourceCabinet
!= NULL
)
249 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
252 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
253 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
254 RtlFreeHeap(ProcessHeap
, 0, Entry
);
258 wcsncpy(Entry
->SourceFilename
, SourceFilename
, Length
);
259 Entry
->SourceFilename
[Length
] = UNICODE_NULL
;
261 /* Copy target directory */
262 Length
= wcslen(TargetDirectory
);
263 if ((Length
> 0) && (TargetDirectory
[Length
- 1] == L
'\\'))
265 Entry
->TargetDirectory
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
267 (Length
+ 1) * sizeof(WCHAR
));
268 if (Entry
->TargetDirectory
== NULL
)
270 if (Entry
->SourceCabinet
!= NULL
)
272 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
275 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
276 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
277 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
278 RtlFreeHeap(ProcessHeap
, 0, Entry
);
282 wcsncpy(Entry
->TargetDirectory
, TargetDirectory
, Length
);
283 Entry
->TargetDirectory
[Length
] = UNICODE_NULL
;
285 /* Copy optional target filename */
286 if (TargetFilename
!= NULL
)
288 Length
= wcslen(TargetFilename
);
289 Entry
->TargetFilename
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
291 (Length
+ 1) * sizeof(WCHAR
));
292 if (Entry
->TargetFilename
== NULL
)
294 if (Entry
->SourceCabinet
!= NULL
)
296 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
299 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
300 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
301 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
302 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
303 RtlFreeHeap(ProcessHeap
, 0, Entry
);
307 wcsncpy(Entry
->TargetFilename
, TargetFilename
, Length
);
308 Entry
->TargetFilename
[Length
] = UNICODE_NULL
;
311 /* Append queue entry */
312 if (QueueHeader
->CopyHead
== NULL
) // && QueueHeader->CopyTail == NULL)
316 QueueHeader
->CopyHead
= Entry
;
317 QueueHeader
->CopyTail
= Entry
;
321 Entry
->Prev
= QueueHeader
->CopyTail
;
323 QueueHeader
->CopyTail
->Next
= Entry
;
324 QueueHeader
->CopyTail
= Entry
;
327 QueueHeader
->CopyCount
++;
335 SetupCommitFileQueueW(
337 HSPFILEQ QueueHandle
,
338 PSP_FILE_CALLBACK_W MsgHandler
,
341 WCHAR CabinetName
[MAX_PATH
];
342 PFILEQUEUEHEADER QueueHeader
;
345 PCWSTR TargetRootPath
, TargetPath
;
347 WCHAR FileSrcPath
[MAX_PATH
];
348 WCHAR FileDstPath
[MAX_PATH
];
350 TargetRootPath
= ((PCOPYCONTEXT
)Context
)->DestinationRootPath
;
351 TargetPath
= ((PCOPYCONTEXT
)Context
)->InstallPath
;
353 if (QueueHandle
== NULL
)
356 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
359 SPFILENOTIFY_STARTQUEUE
,
364 SPFILENOTIFY_STARTSUBQUEUE
,
366 QueueHeader
->CopyCount
);
368 /* Commit copy queue */
369 Entry
= QueueHeader
->CopyHead
;
370 while (Entry
!= NULL
)
372 /* Build the full source path */
373 CombinePaths(FileSrcPath
, ARRAYSIZE(FileSrcPath
), 3,
374 Entry
->SourceRootPath
, Entry
->SourcePath
,
375 Entry
->SourceFilename
);
377 /* Build the full target path */
378 wcscpy(FileDstPath
, TargetRootPath
);
379 if (Entry
->TargetDirectory
[0] == UNICODE_NULL
)
381 /* Installation path */
383 /* Add the installation path */
384 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, TargetPath
);
386 else if (Entry
->TargetDirectory
[0] == L
'\\')
389 if (Entry
->TargetDirectory
[1] != UNICODE_NULL
)
390 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, Entry
->TargetDirectory
);
392 else // if (Entry->TargetDirectory[0] != L'\\')
394 /* Path relative to the installation path */
396 /* Add the installation path */
397 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 2,
398 TargetPath
, Entry
->TargetDirectory
);
402 * If the file is in a cabinet, use only the destination path.
403 * Otherwise possibly use a different target name.
405 if (Entry
->SourceCabinet
== NULL
)
407 if (Entry
->TargetFilename
!= NULL
)
408 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, Entry
->TargetFilename
);
410 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, Entry
->SourceFilename
);
414 DPRINT("Copy: '%S' ==> '%S'\n", FileSrcPath
, FileDstPath
);
417 SPFILENOTIFY_STARTCOPY
,
418 (UINT_PTR
)Entry
->SourceFilename
,
421 if (Entry
->SourceCabinet
!= NULL
)
423 /* Extract the file */
424 CombinePaths(CabinetName
, ARRAYSIZE(CabinetName
), 3,
425 Entry
->SourceRootPath
, Entry
->SourcePath
,
426 Entry
->SourceCabinet
);
427 Status
= SetupExtractFile(CabinetName
, Entry
->SourceFilename
, FileDstPath
);
432 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
, FALSE
);
435 if (!NT_SUCCESS(Status
))
438 SPFILENOTIFY_COPYERROR
,
439 (UINT_PTR
)Entry
->SourceFilename
,
445 SPFILENOTIFY_ENDCOPY
,
446 (UINT_PTR
)Entry
->SourceFilename
,
454 SPFILENOTIFY_ENDSUBQUEUE
,
459 SPFILENOTIFY_ENDQUEUE
,