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: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
27 /* INCLUDES *****************************************************************/
34 /* INCLUDES *****************************************************************/
36 typedef struct _QUEUEENTRY
38 struct _QUEUEENTRY
*Prev
;
39 struct _QUEUEENTRY
*Next
;
41 PWSTR SourceCabinet
; /* May be NULL if the file is not in a cabinet */
45 PWSTR TargetDirectory
;
47 } QUEUEENTRY
, *PQUEUEENTRY
;
50 typedef struct _FILEQUEUEHEADER
55 } FILEQUEUEHEADER
, *PFILEQUEUEHEADER
;
58 /* FUNCTIONS ****************************************************************/
62 SetupOpenFileQueue(VOID
)
64 PFILEQUEUEHEADER QueueHeader
;
66 /* Allocate queue header */
67 QueueHeader
= (PFILEQUEUEHEADER
)RtlAllocateHeap(ProcessHeap
,
69 sizeof(FILEQUEUEHEADER
));
70 if (QueueHeader
== NULL
)
73 /* Initialize queue header */
74 RtlZeroMemory(QueueHeader
,
75 sizeof(FILEQUEUEHEADER
));
77 return (HSPFILEQ
)QueueHeader
;
86 PFILEQUEUEHEADER QueueHeader
;
89 if (QueueHandle
== NULL
)
92 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
94 /* Delete copy queue */
95 Entry
= QueueHeader
->CopyHead
;
98 /* Delete all strings */
99 if (Entry
->SourceCabinet
!= NULL
)
100 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
102 if (Entry
->SourceRootPath
!= NULL
)
103 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
105 if (Entry
->SourcePath
!= NULL
)
106 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
108 if (Entry
->SourceFilename
!= NULL
)
109 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
111 if (Entry
->TargetDirectory
!= NULL
)
112 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
114 if (Entry
->TargetFilename
!= NULL
)
115 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetFilename
);
117 /* Unlink current queue entry */
118 if (Entry
->Next
!= NULL
)
120 QueueHeader
->CopyHead
= Entry
->Next
;
121 QueueHeader
->CopyHead
->Prev
= NULL
;
125 QueueHeader
->CopyHead
= NULL
;
126 QueueHeader
->CopyTail
= NULL
;
129 /* Delete queue entry */
130 RtlFreeHeap(ProcessHeap
, 0, Entry
);
132 /* Get next queue entry */
133 Entry
= QueueHeader
->CopyHead
;
136 /* Delete queue header */
137 RtlFreeHeap(ProcessHeap
, 0, QueueHeader
);
143 HSPFILEQ QueueHandle
,
144 PCWSTR SourceCabinet
,
145 PCWSTR SourceRootPath
,
147 PCWSTR SourceFilename
,
148 PCWSTR TargetDirectory
,
149 PCWSTR TargetFilename
)
151 PFILEQUEUEHEADER QueueHeader
;
155 /* SourceCabinet may be NULL */
156 if (QueueHandle
== NULL
||
157 SourceRootPath
== NULL
||
158 SourceFilename
== NULL
||
159 TargetDirectory
== NULL
)
162 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
164 /* Allocate new queue entry */
165 Entry
= (PQUEUEENTRY
)RtlAllocateHeap(ProcessHeap
,
174 /* Copy source cabinet if available */
175 if (SourceCabinet
!= NULL
)
177 Length
= wcslen(SourceCabinet
);
178 Entry
->SourceCabinet
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
180 (Length
+ 1) * sizeof(WCHAR
));
181 if (Entry
->SourceCabinet
== NULL
)
183 RtlFreeHeap(ProcessHeap
, 0, Entry
);
187 wcsncpy(Entry
->SourceCabinet
, SourceCabinet
, Length
);
188 Entry
->SourceCabinet
[Length
] = (WCHAR
)0;
192 Entry
->SourceCabinet
= NULL
;
195 /* Copy source root path */
196 Length
= wcslen(SourceRootPath
);
197 Entry
->SourceRootPath
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
199 (Length
+ 1) * sizeof(WCHAR
));
200 if (Entry
->SourceRootPath
== NULL
)
202 if (Entry
->SourceCabinet
!= NULL
)
204 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
207 RtlFreeHeap(ProcessHeap
, 0, Entry
);
211 wcsncpy(Entry
->SourceRootPath
, SourceRootPath
, Length
);
212 Entry
->SourceRootPath
[Length
] = (WCHAR
)0;
214 /* Copy source path */
215 if (SourcePath
!= NULL
)
217 Length
= wcslen(SourcePath
);
218 if ((Length
> 0) && (SourcePath
[Length
- 1] == L
'\\'))
220 Entry
->SourcePath
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
222 (Length
+ 1) * sizeof(WCHAR
));
223 if (Entry
->SourcePath
== NULL
)
225 if (Entry
->SourceCabinet
!= NULL
)
227 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
230 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
231 RtlFreeHeap(ProcessHeap
, 0, Entry
);
235 wcsncpy(Entry
->SourcePath
, SourcePath
, Length
);
236 Entry
->SourcePath
[Length
] = (WCHAR
)0;
239 /* Copy source file name */
240 Length
= wcslen(SourceFilename
);
241 Entry
->SourceFilename
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
243 (Length
+ 1) * sizeof(WCHAR
));
244 if (Entry
->SourceFilename
== NULL
)
246 if (Entry
->SourceCabinet
!= NULL
)
248 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
251 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
252 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
253 RtlFreeHeap(ProcessHeap
, 0, Entry
);
257 wcsncpy(Entry
->SourceFilename
, SourceFilename
, Length
);
258 Entry
->SourceFilename
[Length
] = (WCHAR
)0;
260 /* Copy target directory */
261 Length
= wcslen(TargetDirectory
);
262 if ((Length
> 0) && (TargetDirectory
[Length
- 1] == L
'\\'))
264 Entry
->TargetDirectory
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
266 (Length
+ 1) * sizeof(WCHAR
));
267 if (Entry
->TargetDirectory
== NULL
)
269 if (Entry
->SourceCabinet
!= NULL
)
271 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
274 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
275 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
276 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
277 RtlFreeHeap(ProcessHeap
, 0, Entry
);
281 wcsncpy(Entry
->TargetDirectory
, TargetDirectory
, Length
);
282 Entry
->TargetDirectory
[Length
] = (WCHAR
)0;
284 /* Copy optional target filename */
285 if (TargetFilename
!= NULL
)
287 Length
= wcslen(TargetFilename
);
288 Entry
->TargetFilename
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
290 (Length
+ 1) * sizeof(WCHAR
));
291 if (Entry
->TargetFilename
== NULL
)
293 if (Entry
->SourceCabinet
!= NULL
)
295 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
298 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
299 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
300 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
301 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
302 RtlFreeHeap(ProcessHeap
, 0, Entry
);
306 wcsncpy(Entry
->TargetFilename
, TargetFilename
, Length
);
307 Entry
->TargetFilename
[Length
] = (WCHAR
)0;
310 /* Append queue entry */
311 if (QueueHeader
->CopyHead
== NULL
) // && QueueHeader->CopyTail == NULL)
315 QueueHeader
->CopyHead
= Entry
;
316 QueueHeader
->CopyTail
= Entry
;
320 Entry
->Prev
= QueueHeader
->CopyTail
;
322 QueueHeader
->CopyTail
->Next
= Entry
;
323 QueueHeader
->CopyTail
= Entry
;
326 QueueHeader
->CopyCount
++;
334 SetupCommitFileQueueW(
336 HSPFILEQ QueueHandle
,
337 PSP_FILE_CALLBACK_W MsgHandler
,
340 WCHAR CabinetName
[MAX_PATH
];
341 PFILEQUEUEHEADER QueueHeader
;
344 PCWSTR TargetRootPath
, TargetPath
;
346 WCHAR FileSrcPath
[MAX_PATH
];
347 WCHAR FileDstPath
[MAX_PATH
];
349 TargetRootPath
= ((PCOPYCONTEXT
)Context
)->DestinationRootPath
;
350 TargetPath
= ((PCOPYCONTEXT
)Context
)->InstallPath
;
352 if (QueueHandle
== NULL
)
355 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
358 SPFILENOTIFY_STARTQUEUE
,
363 SPFILENOTIFY_STARTSUBQUEUE
,
365 QueueHeader
->CopyCount
);
367 /* Commit copy queue */
368 Entry
= QueueHeader
->CopyHead
;
369 while (Entry
!= NULL
)
371 /* Build the full source path */
372 wcscpy(FileSrcPath
, Entry
->SourceRootPath
);
373 if (Entry
->SourcePath
!= NULL
)
374 wcscat(FileSrcPath
, Entry
->SourcePath
);
375 wcscat(FileSrcPath
, L
"\\");
376 wcscat(FileSrcPath
, Entry
->SourceFilename
);
378 /* Build the full target path */
379 wcscpy(FileDstPath
, TargetRootPath
);
380 if (Entry
->TargetDirectory
[0] == 0)
382 /* Installation path */
384 /* Add the installation path */
385 if (TargetPath
!= NULL
)
387 if (TargetPath
[0] != L
'\\')
388 wcscat(FileDstPath
, L
"\\");
389 wcscat(FileDstPath
, TargetPath
);
392 else if (Entry
->TargetDirectory
[0] == L
'\\')
395 if (Entry
->TargetDirectory
[1] != 0)
396 wcscat(FileDstPath
, Entry
->TargetDirectory
);
398 else // if (Entry->TargetDirectory[0] != L'\\')
400 /* Path relative to the installation path */
402 /* Add the installation path */
403 if (TargetPath
!= NULL
)
405 if (TargetPath
[0] != L
'\\')
406 wcscat(FileDstPath
, L
"\\");
407 wcscat(FileDstPath
, TargetPath
);
410 wcscat(FileDstPath
, L
"\\");
411 wcscat(FileDstPath
, Entry
->TargetDirectory
);
415 * If the file is in a cabinet, use only the destination path.
416 * Otherwise possibly use a different target name.
418 if (Entry
->SourceCabinet
== NULL
)
420 wcscat(FileDstPath
, L
"\\");
421 if (Entry
->TargetFilename
!= NULL
)
422 wcscat(FileDstPath
, Entry
->TargetFilename
);
424 wcscat(FileDstPath
, Entry
->SourceFilename
);
428 DPRINT("Copy: '%S' ==> '%S'\n", FileSrcPath
, FileDstPath
);
431 SPFILENOTIFY_STARTCOPY
,
432 (UINT_PTR
)Entry
->SourceFilename
,
435 if (Entry
->SourceCabinet
!= NULL
)
437 /* Extract the file */
438 wcscpy(CabinetName
, Entry
->SourceRootPath
);
439 if (Entry
->SourcePath
!= NULL
)
440 wcscat(CabinetName
, Entry
->SourcePath
);
441 wcscat(CabinetName
, L
"\\");
442 wcscat(CabinetName
, Entry
->SourceCabinet
);
443 Status
= SetupExtractFile(CabinetName
, Entry
->SourceFilename
, FileDstPath
);
448 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
);
451 if (!NT_SUCCESS(Status
))
454 SPFILENOTIFY_COPYERROR
,
455 (UINT_PTR
)Entry
->SourceFilename
,
461 SPFILENOTIFY_ENDCOPY
,
462 (UINT_PTR
)Entry
->SourceFilename
,
470 SPFILENOTIFY_ENDSUBQUEUE
,
475 SPFILENOTIFY_ENDQUEUE
,