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 CombinePaths(FileSrcPath
, ARRAYSIZE(FileSrcPath
), 3,
372 Entry
->SourceRootPath
, Entry
->SourcePath
,
373 Entry
->SourceFilename
);
375 /* Build the full target path */
376 wcscpy(FileDstPath
, TargetRootPath
);
377 if (Entry
->TargetDirectory
[0] == UNICODE_NULL
)
379 /* Installation path */
381 /* Add the installation path */
382 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, TargetPath
);
384 else if (Entry
->TargetDirectory
[0] == L
'\\')
387 if (Entry
->TargetDirectory
[1] != UNICODE_NULL
)
388 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, Entry
->TargetDirectory
);
390 else // if (Entry->TargetDirectory[0] != L'\\')
392 /* Path relative to the installation path */
394 /* Add the installation path */
395 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 2,
396 TargetPath
, Entry
->TargetDirectory
);
400 * If the file is in a cabinet, use only the destination path.
401 * Otherwise possibly use a different target name.
403 if (Entry
->SourceCabinet
== NULL
)
405 if (Entry
->TargetFilename
!= NULL
)
406 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, Entry
->TargetFilename
);
408 ConcatPaths(FileDstPath
, ARRAYSIZE(FileDstPath
), 1, Entry
->SourceFilename
);
412 DPRINT("Copy: '%S' ==> '%S'\n", FileSrcPath
, FileDstPath
);
415 SPFILENOTIFY_STARTCOPY
,
416 (UINT_PTR
)Entry
->SourceFilename
,
419 if (Entry
->SourceCabinet
!= NULL
)
421 /* Extract the file */
422 CombinePaths(CabinetName
, ARRAYSIZE(CabinetName
), 3,
423 Entry
->SourceRootPath
, Entry
->SourcePath
,
424 Entry
->SourceCabinet
);
425 Status
= SetupExtractFile(CabinetName
, Entry
->SourceFilename
, FileDstPath
);
430 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
);
433 if (!NT_SUCCESS(Status
))
436 SPFILENOTIFY_COPYERROR
,
437 (UINT_PTR
)Entry
->SourceFilename
,
443 SPFILENOTIFY_ENDCOPY
,
444 (UINT_PTR
)Entry
->SourceFilename
,
452 SPFILENOTIFY_ENDSUBQUEUE
,
457 SPFILENOTIFY_ENDQUEUE
,