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: subsys/system/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 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 Entry
->SourcePath
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
220 (Length
+ 1) * sizeof(WCHAR
));
221 if (Entry
->SourcePath
== NULL
)
223 if (Entry
->SourceCabinet
!= NULL
)
225 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
228 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
229 RtlFreeHeap(ProcessHeap
, 0, Entry
);
233 wcsncpy(Entry
->SourcePath
, SourcePath
, Length
);
234 Entry
->SourcePath
[Length
] = (WCHAR
)0;
237 /* Copy source file name */
238 Length
= wcslen(SourceFilename
);
239 Entry
->SourceFilename
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
241 (Length
+ 1) * sizeof(WCHAR
));
242 if (Entry
->SourceFilename
== NULL
)
244 if (Entry
->SourceCabinet
!= NULL
)
246 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
249 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
250 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
251 RtlFreeHeap(ProcessHeap
, 0, Entry
);
255 wcsncpy(Entry
->SourceFilename
, SourceFilename
, Length
);
256 Entry
->SourceFilename
[Length
] = (WCHAR
)0;
258 /* Copy target directory */
259 Length
= wcslen(TargetDirectory
);
260 if (TargetDirectory
[Length
] == '\\')
262 Entry
->TargetDirectory
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
264 (Length
+ 1) * sizeof(WCHAR
));
265 if (Entry
->TargetDirectory
== NULL
)
267 if (Entry
->SourceCabinet
!= NULL
)
269 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
272 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
273 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
274 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
275 RtlFreeHeap(ProcessHeap
, 0, Entry
);
279 wcsncpy(Entry
->TargetDirectory
, TargetDirectory
, Length
);
280 Entry
->TargetDirectory
[Length
] = (WCHAR
)0;
282 /* Copy optional target filename */
283 if (TargetFilename
!= NULL
)
285 Length
= wcslen(TargetFilename
);
286 Entry
->TargetFilename
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
,
288 (Length
+ 1) * sizeof(WCHAR
));
289 if (Entry
->TargetFilename
== NULL
)
291 if (Entry
->SourceCabinet
!= NULL
)
293 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
296 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
297 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
298 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
299 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
300 RtlFreeHeap(ProcessHeap
, 0, Entry
);
304 wcsncpy(Entry
->TargetFilename
, TargetFilename
, Length
);
305 Entry
->TargetFilename
[Length
] = (WCHAR
)0;
308 /* Append queue entry */
309 if (QueueHeader
->CopyHead
== NULL
) // && QueueHeader->CopyTail == NULL)
313 QueueHeader
->CopyHead
= Entry
;
314 QueueHeader
->CopyTail
= Entry
;
318 Entry
->Prev
= QueueHeader
->CopyTail
;
320 QueueHeader
->CopyTail
->Next
= Entry
;
321 QueueHeader
->CopyTail
= Entry
;
324 QueueHeader
->CopyCount
++;
332 SetupCommitFileQueueW(
334 HSPFILEQ QueueHandle
,
335 PSP_FILE_CALLBACK_W MsgHandler
,
338 WCHAR CabinetName
[MAX_PATH
];
339 PFILEQUEUEHEADER QueueHeader
;
342 PCWSTR TargetRootPath
, TargetPath
;
344 WCHAR FileSrcPath
[MAX_PATH
];
345 WCHAR FileDstPath
[MAX_PATH
];
347 TargetRootPath
= ((PCOPYCONTEXT
)Context
)->DestinationRootPath
;
348 TargetPath
= ((PCOPYCONTEXT
)Context
)->InstallPath
;
350 if (QueueHandle
== NULL
)
353 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
356 SPFILENOTIFY_STARTQUEUE
,
361 SPFILENOTIFY_STARTSUBQUEUE
,
363 QueueHeader
->CopyCount
);
365 /* Commit copy queue */
366 Entry
= QueueHeader
->CopyHead
;
367 while (Entry
!= NULL
)
369 wcscpy(FileSrcPath
, Entry
->SourceRootPath
);
370 if (Entry
->SourcePath
!= NULL
)
371 wcscat(FileSrcPath
, Entry
->SourcePath
);
372 wcscat(FileSrcPath
, L
"\\");
373 wcscat(FileSrcPath
, Entry
->SourceFilename
);
375 /* Build the full target path */
376 wcscpy(FileDstPath
, TargetRootPath
);
377 if (Entry
->TargetDirectory
[0] == L
'\\')
379 wcscat(FileDstPath
, Entry
->TargetDirectory
);
383 if (TargetPath
!= NULL
)
385 if (TargetPath
[0] != L
'\\')
386 wcscat(FileDstPath
, L
"\\");
387 wcscat(FileDstPath
, TargetPath
);
390 wcscat(FileDstPath
, L
"\\");
391 wcscat(FileDstPath
, Entry
->TargetDirectory
);
394 /* Use only the destination path if the file is in a cabinet */
395 if (Entry
->SourceCabinet
== NULL
)
397 wcscat(FileDstPath
, L
"\\");
398 if (Entry
->TargetFilename
!= NULL
)
399 wcscat(FileDstPath
, Entry
->TargetFilename
);
401 wcscat(FileDstPath
, Entry
->SourceFilename
);
405 DPRINT("'%S' ==> '%S'\n", FileSrcPath
, FileDstPath
);
408 SPFILENOTIFY_STARTCOPY
,
409 (UINT_PTR
)Entry
->SourceFilename
,
412 if (Entry
->SourceCabinet
!= NULL
)
414 /* Extract the file */
415 wcscpy(CabinetName
, Entry
->SourceRootPath
);
416 if (Entry
->SourcePath
!= NULL
)
417 wcscat(CabinetName
, Entry
->SourcePath
);
418 wcscat(CabinetName
, L
"\\");
419 wcscat(CabinetName
, Entry
->SourceCabinet
);
420 Status
= SetupExtractFile(CabinetName
, Entry
->SourceFilename
, FileDstPath
);
425 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
);
428 if (!NT_SUCCESS(Status
))
431 SPFILENOTIFY_COPYERROR
,
432 (UINT_PTR
)Entry
->SourceFilename
,
438 SPFILENOTIFY_ENDCOPY
,
439 (UINT_PTR
)Entry
->SourceFilename
,
447 SPFILENOTIFY_ENDSUBQUEUE
,
452 SPFILENOTIFY_ENDQUEUE
,