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
)
161 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
163 /* Allocate new queue entry */
164 Entry
= (PQUEUEENTRY
)RtlAllocateHeap(ProcessHeap
,
173 /* Copy source cabinet if available */
174 if (SourceCabinet
!= NULL
)
176 Length
= wcslen(SourceCabinet
);
177 Entry
->SourceCabinet
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
179 (Length
+ 1) * sizeof(WCHAR
));
180 if (Entry
->SourceCabinet
== NULL
)
182 RtlFreeHeap(ProcessHeap
, 0, Entry
);
186 wcsncpy(Entry
->SourceCabinet
, SourceCabinet
, Length
);
187 Entry
->SourceCabinet
[Length
] = (WCHAR
)0;
191 Entry
->SourceCabinet
= NULL
;
194 /* Copy source root path */
195 Length
= wcslen(SourceRootPath
);
196 Entry
->SourceRootPath
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
198 (Length
+ 1) * sizeof(WCHAR
));
199 if (Entry
->SourceRootPath
== NULL
)
201 if (Entry
->SourceCabinet
!= NULL
)
203 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
206 RtlFreeHeap(ProcessHeap
, 0, Entry
);
210 wcsncpy(Entry
->SourceRootPath
, SourceRootPath
, Length
);
211 Entry
->SourceRootPath
[Length
] = (WCHAR
)0;
213 /* Copy source path */
214 if (SourcePath
!= NULL
)
216 Length
= wcslen(SourcePath
);
217 if ((Length
> 0) && (SourcePath
[Length
- 1] == L
'\\'))
219 Entry
->SourcePath
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
221 (Length
+ 1) * sizeof(WCHAR
));
222 if (Entry
->SourcePath
== NULL
)
224 if (Entry
->SourceCabinet
!= NULL
)
226 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
229 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
230 RtlFreeHeap(ProcessHeap
, 0, Entry
);
234 wcsncpy(Entry
->SourcePath
, SourcePath
, Length
);
235 Entry
->SourcePath
[Length
] = (WCHAR
)0;
238 /* Copy source file name */
239 Length
= wcslen(SourceFilename
);
240 Entry
->SourceFilename
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
242 (Length
+ 1) * sizeof(WCHAR
));
243 if (Entry
->SourceFilename
== NULL
)
245 if (Entry
->SourceCabinet
!= NULL
)
247 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
250 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
251 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
252 RtlFreeHeap(ProcessHeap
, 0, Entry
);
256 wcsncpy(Entry
->SourceFilename
, SourceFilename
, Length
);
257 Entry
->SourceFilename
[Length
] = (WCHAR
)0;
259 /* Copy target directory */
260 Length
= wcslen(TargetDirectory
);
261 if ((Length
> 0) && (TargetDirectory
[Length
- 1] == L
'\\'))
263 Entry
->TargetDirectory
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
265 (Length
+ 1) * sizeof(WCHAR
));
266 if (Entry
->TargetDirectory
== NULL
)
268 if (Entry
->SourceCabinet
!= NULL
)
270 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
273 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
274 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
275 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
276 RtlFreeHeap(ProcessHeap
, 0, Entry
);
280 wcsncpy(Entry
->TargetDirectory
, TargetDirectory
, Length
);
281 Entry
->TargetDirectory
[Length
] = (WCHAR
)0;
283 /* Copy optional target filename */
284 if (TargetFilename
!= NULL
)
286 Length
= wcslen(TargetFilename
);
287 Entry
->TargetFilename
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
289 (Length
+ 1) * sizeof(WCHAR
));
290 if (Entry
->TargetFilename
== NULL
)
292 if (Entry
->SourceCabinet
!= NULL
)
294 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
297 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
298 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
299 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
300 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
301 RtlFreeHeap(ProcessHeap
, 0, Entry
);
305 wcsncpy(Entry
->TargetFilename
, TargetFilename
, Length
);
306 Entry
->TargetFilename
[Length
] = (WCHAR
)0;
309 /* Append queue entry */
310 if (QueueHeader
->CopyHead
== NULL
) // && QueueHeader->CopyTail == NULL)
314 QueueHeader
->CopyHead
= Entry
;
315 QueueHeader
->CopyTail
= Entry
;
319 Entry
->Prev
= QueueHeader
->CopyTail
;
321 QueueHeader
->CopyTail
->Next
= Entry
;
322 QueueHeader
->CopyTail
= Entry
;
325 QueueHeader
->CopyCount
++;
333 SetupCommitFileQueueW(
335 HSPFILEQ QueueHandle
,
336 PSP_FILE_CALLBACK_W MsgHandler
,
339 WCHAR CabinetName
[MAX_PATH
];
340 PFILEQUEUEHEADER QueueHeader
;
343 PCWSTR TargetRootPath
, TargetPath
;
345 WCHAR FileSrcPath
[MAX_PATH
];
346 WCHAR FileDstPath
[MAX_PATH
];
348 TargetRootPath
= ((PCOPYCONTEXT
)Context
)->DestinationRootPath
;
349 TargetPath
= ((PCOPYCONTEXT
)Context
)->InstallPath
;
351 if (QueueHandle
== NULL
)
354 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
357 SPFILENOTIFY_STARTQUEUE
,
362 SPFILENOTIFY_STARTSUBQUEUE
,
364 QueueHeader
->CopyCount
);
366 /* Commit copy queue */
367 Entry
= QueueHeader
->CopyHead
;
368 while (Entry
!= NULL
)
370 /* Build the full source path */
371 wcscpy(FileSrcPath
, Entry
->SourceRootPath
);
372 if (Entry
->SourcePath
!= NULL
)
373 wcscat(FileSrcPath
, Entry
->SourcePath
);
374 wcscat(FileSrcPath
, L
"\\");
375 wcscat(FileSrcPath
, Entry
->SourceFilename
);
377 /* Build the full target path */
378 wcscpy(FileDstPath
, TargetRootPath
);
379 if (Entry
->TargetDirectory
[0] == 0)
381 /* Installation path */
383 /* Add the installation path */
384 if (TargetPath
!= NULL
)
386 if (TargetPath
[0] != L
'\\')
387 wcscat(FileDstPath
, L
"\\");
388 wcscat(FileDstPath
, TargetPath
);
391 else if (Entry
->TargetDirectory
[0] == L
'\\')
394 if (Entry
->TargetDirectory
[1] != 0)
395 wcscat(FileDstPath
, Entry
->TargetDirectory
);
397 else // if (Entry->TargetDirectory[0] != L'\\')
399 /* Path relative to the installation path */
401 /* Add the installation path */
402 if (TargetPath
!= NULL
)
404 if (TargetPath
[0] != L
'\\')
405 wcscat(FileDstPath
, L
"\\");
406 wcscat(FileDstPath
, TargetPath
);
409 wcscat(FileDstPath
, L
"\\");
410 wcscat(FileDstPath
, Entry
->TargetDirectory
);
414 * If the file is in a cabinet, use only the destination path.
415 * Otherwise possibly use a different target name.
417 if (Entry
->SourceCabinet
== NULL
)
419 wcscat(FileDstPath
, L
"\\");
420 if (Entry
->TargetFilename
!= NULL
)
421 wcscat(FileDstPath
, Entry
->TargetFilename
);
423 wcscat(FileDstPath
, Entry
->SourceFilename
);
427 DPRINT("Copy: '%S' ==> '%S'\n", FileSrcPath
, FileDstPath
);
430 SPFILENOTIFY_STARTCOPY
,
431 (UINT_PTR
)Entry
->SourceFilename
,
434 if (Entry
->SourceCabinet
!= NULL
)
436 /* Extract the file */
437 wcscpy(CabinetName
, Entry
->SourceRootPath
);
438 if (Entry
->SourcePath
!= NULL
)
439 wcscat(CabinetName
, Entry
->SourcePath
);
440 wcscat(CabinetName
, L
"\\");
441 wcscat(CabinetName
, Entry
->SourceCabinet
);
442 Status
= SetupExtractFile(CabinetName
, Entry
->SourceFilename
, FileDstPath
);
447 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
);
450 if (!NT_SUCCESS(Status
))
453 SPFILENOTIFY_COPYERROR
,
454 (UINT_PTR
)Entry
->SourceFilename
,
460 SPFILENOTIFY_ENDCOPY
,
461 (UINT_PTR
)Entry
->SourceFilename
,
469 SPFILENOTIFY_ENDSUBQUEUE
,
474 SPFILENOTIFY_ENDQUEUE
,