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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/filequeue.c
23 * PURPOSE: File queue functions
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
28 /* INCLUDES *****************************************************************/
35 /* INCLUDES *****************************************************************/
38 typedef struct _QUEUEENTRY
40 struct _QUEUEENTRY
*Prev
;
41 struct _QUEUEENTRY
*Next
;
43 PWSTR SourceCabinet
; /* May be NULL if file is not in a cabinet */
47 PWSTR TargetDirectory
;
50 } QUEUEENTRY
, *PQUEUEENTRY
;
53 typedef struct _FILEQUEUEHEADER
58 } FILEQUEUEHEADER
, *PFILEQUEUEHEADER
;
61 /* FUNCTIONS ****************************************************************/
64 SetupOpenFileQueue(VOID
)
66 PFILEQUEUEHEADER QueueHeader
;
68 /* Allocate queue header */
69 QueueHeader
= (PFILEQUEUEHEADER
)RtlAllocateHeap(ProcessHeap
,
71 sizeof(FILEQUEUEHEADER
));
72 if (QueueHeader
== NULL
)
75 /* Initialize queue header */
76 RtlZeroMemory(QueueHeader
,
77 sizeof(FILEQUEUEHEADER
));
80 return((HSPFILEQ
)QueueHeader
);
85 SetupCloseFileQueue(HSPFILEQ QueueHandle
)
87 PFILEQUEUEHEADER QueueHeader
;
90 if (QueueHandle
== NULL
)
93 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
95 /* Delete copy queue */
96 Entry
= QueueHeader
->CopyHead
;
99 /* Delete all strings */
100 if (Entry
->SourceCabinet
!= NULL
)
101 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
102 if (Entry
->SourceRootPath
!= NULL
)
103 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
104 if (Entry
->SourcePath
!= NULL
)
105 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
106 if (Entry
->SourceFilename
!= NULL
)
107 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
108 if (Entry
->TargetDirectory
!= NULL
)
109 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
110 if (Entry
->TargetFilename
!= NULL
)
111 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetFilename
);
113 /* Unlink current queue entry */
114 if (Entry
->Next
!= NULL
)
116 QueueHeader
->CopyHead
= Entry
->Next
;
117 QueueHeader
->CopyHead
->Prev
= NULL
;
121 QueueHeader
->CopyHead
= NULL
;
122 QueueHeader
->CopyTail
= NULL
;
125 /* Delete queue entry */
126 RtlFreeHeap(ProcessHeap
, 0, Entry
);
128 /* Get next queue entry */
129 Entry
= QueueHeader
->CopyHead
;
132 /* Delete queue header */
133 RtlFreeHeap(ProcessHeap
,
142 SetupQueueCopy(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
= RtlAllocateHeap(ProcessHeap
,
179 (Length
+ 1) * sizeof(WCHAR
));
180 if (Entry
->SourceCabinet
== NULL
)
182 RtlFreeHeap(ProcessHeap
, 0, Entry
);
185 wcsncpy(Entry
->SourceCabinet
, SourceCabinet
, Length
);
186 Entry
->SourceCabinet
[Length
] = (WCHAR
)0;
190 Entry
->SourceCabinet
= NULL
;
193 /* Copy source root path */
194 Length
= wcslen(SourceRootPath
);
195 Entry
->SourceRootPath
= RtlAllocateHeap(ProcessHeap
,
197 (Length
+ 1) * sizeof(WCHAR
));
198 if (Entry
->SourceRootPath
== NULL
)
200 if (Entry
->SourceCabinet
!= NULL
)
202 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
204 RtlFreeHeap(ProcessHeap
, 0, Entry
);
207 wcsncpy(Entry
->SourceRootPath
, SourceRootPath
, Length
);
208 Entry
->SourceRootPath
[Length
] = (WCHAR
)0;
210 /* Copy source path */
211 if (SourcePath
!= NULL
)
213 Length
= wcslen(SourcePath
);
214 Entry
->SourcePath
= RtlAllocateHeap(ProcessHeap
,
216 (Length
+ 1) * sizeof(WCHAR
));
217 if (Entry
->SourcePath
== NULL
)
219 if (Entry
->SourceCabinet
!= NULL
)
221 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
223 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
224 RtlFreeHeap(ProcessHeap
, 0, Entry
);
227 wcsncpy(Entry
->SourcePath
, SourcePath
, Length
);
228 Entry
->SourcePath
[Length
] = (WCHAR
)0;
231 /* Copy source file name */
232 Length
= wcslen(SourceFilename
);
233 Entry
->SourceFilename
= RtlAllocateHeap(ProcessHeap
,
235 (Length
+ 1) * sizeof(WCHAR
));
236 if (Entry
->SourceFilename
== NULL
)
238 if (Entry
->SourceCabinet
!= NULL
)
240 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
242 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
243 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
244 RtlFreeHeap(ProcessHeap
, 0, Entry
);
247 wcsncpy(Entry
->SourceFilename
, SourceFilename
, Length
);
248 Entry
->SourceFilename
[Length
] = (WCHAR
)0;
250 /* Copy target directory */
251 Length
= wcslen(TargetDirectory
);
252 if (TargetDirectory
[Length
] == '\\')
254 Entry
->TargetDirectory
= RtlAllocateHeap(ProcessHeap
,
256 (Length
+ 1) * sizeof(WCHAR
));
257 if (Entry
->TargetDirectory
== NULL
)
259 if (Entry
->SourceCabinet
!= NULL
)
261 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
263 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
264 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
265 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
266 RtlFreeHeap(ProcessHeap
, 0, Entry
);
269 wcsncpy(Entry
->TargetDirectory
, TargetDirectory
, Length
);
270 Entry
->TargetDirectory
[Length
] = (WCHAR
)0;
272 /* Copy optional target filename */
273 if (TargetFilename
!= NULL
)
275 Length
= wcslen(TargetFilename
);
276 Entry
->TargetFilename
= RtlAllocateHeap(ProcessHeap
,
278 (Length
+ 1) * sizeof(WCHAR
));
279 if (Entry
->TargetFilename
== NULL
)
281 if (Entry
->SourceCabinet
!= NULL
)
283 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
285 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
286 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
287 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
288 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
289 RtlFreeHeap(ProcessHeap
, 0, Entry
);
292 wcsncpy(Entry
->TargetFilename
, TargetFilename
, Length
);
293 Entry
->TargetFilename
[Length
] = (WCHAR
)0;
296 /* Append queue entry */
297 if (QueueHeader
->CopyHead
== NULL
) // && QueueHeader->CopyTail == NULL)
301 QueueHeader
->CopyHead
= Entry
;
302 QueueHeader
->CopyTail
= Entry
;
306 Entry
->Prev
= QueueHeader
->CopyTail
;
308 QueueHeader
->CopyTail
->Next
= Entry
;
309 QueueHeader
->CopyTail
= Entry
;
311 QueueHeader
->CopyCount
++;
318 SetupCommitFileQueue(HSPFILEQ QueueHandle
,
319 PCWSTR TargetRootPath
,
321 PSP_FILE_CALLBACK MsgHandler
,
324 WCHAR CabinetName
[MAX_PATH
];
325 PFILEQUEUEHEADER QueueHeader
;
329 WCHAR FileSrcPath
[MAX_PATH
];
330 WCHAR FileDstPath
[MAX_PATH
];
332 if (QueueHandle
== NULL
)
335 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
338 SPFILENOTIFY_STARTQUEUE
,
343 SPFILENOTIFY_STARTSUBQUEUE
,
345 (PVOID
)QueueHeader
->CopyCount
);
347 /* Commit copy queue */
348 Entry
= QueueHeader
->CopyHead
;
349 while (Entry
!= NULL
)
351 wcscpy(FileSrcPath
, Entry
->SourceRootPath
);
352 if (Entry
->SourcePath
!= NULL
)
353 wcscat(FileSrcPath
, Entry
->SourcePath
);
354 wcscat(FileSrcPath
, L
"\\");
355 wcscat(FileSrcPath
, Entry
->SourceFilename
);
357 /* Build the full target path */
358 wcscpy(FileDstPath
, TargetRootPath
);
359 if (Entry
->TargetDirectory
[0] == L
'\\')
361 wcscat(FileDstPath
, Entry
->TargetDirectory
);
365 if (TargetPath
!= NULL
)
367 if (TargetPath
[0] != L
'\\')
368 wcscat(FileDstPath
, L
"\\");
369 wcscat(FileDstPath
, TargetPath
);
371 wcscat(FileDstPath
, L
"\\");
372 wcscat(FileDstPath
, Entry
->TargetDirectory
);
375 /* Use only the destination path if the file is in a cabinet */
376 if (Entry
->SourceCabinet
== NULL
)
378 wcscat(FileDstPath
, L
"\\");
379 if (Entry
->TargetFilename
!= NULL
)
380 wcscat(FileDstPath
, Entry
->TargetFilename
);
382 wcscat(FileDstPath
, Entry
->SourceFilename
);
386 DPRINT("'%S' ==> '%S'\n",
391 SPFILENOTIFY_STARTCOPY
,
392 (PVOID
)Entry
->SourceFilename
,
395 if (Entry
->SourceCabinet
!= NULL
)
397 /* Extract the file */
398 wcscpy(CabinetName
, Entry
->SourceRootPath
);
399 if (Entry
->SourcePath
!= NULL
)
400 wcscat(CabinetName
, Entry
->SourcePath
);
401 wcscat(CabinetName
, L
"\\");
402 wcscat(CabinetName
, Entry
->SourceCabinet
);
403 Status
= SetupExtractFile(CabinetName
, Entry
->SourceFilename
, FileDstPath
);
408 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
);
410 if (!NT_SUCCESS(Status
))
413 SPFILENOTIFY_COPYERROR
,
414 (PVOID
)Entry
->SourceFilename
,
421 SPFILENOTIFY_ENDCOPY
,
422 (PVOID
)Entry
->SourceFilename
,
430 SPFILENOTIFY_ENDSUBQUEUE
,
435 SPFILENOTIFY_ENDQUEUE
,