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 *****************************************************************/
31 #include <ntdll/rtl.h>
35 #include "filequeue.h"
40 /* INCLUDES *****************************************************************/
43 typedef struct _QUEUEENTRY
45 struct _QUEUEENTRY
*Prev
;
46 struct _QUEUEENTRY
*Next
;
48 PWSTR SourceCabinet
; /* May be NULL if file is not in a cabinet */
52 PWSTR TargetDirectory
;
55 } QUEUEENTRY
, *PQUEUEENTRY
;
58 typedef struct _FILEQUEUEHEADER
63 } FILEQUEUEHEADER
, *PFILEQUEUEHEADER
;
66 /* FUNCTIONS ****************************************************************/
69 SetupOpenFileQueue(VOID
)
71 PFILEQUEUEHEADER QueueHeader
;
73 /* Allocate queue header */
74 QueueHeader
= (PFILEQUEUEHEADER
)RtlAllocateHeap(ProcessHeap
,
76 sizeof(FILEQUEUEHEADER
));
77 if (QueueHeader
== NULL
)
80 /* Initialize queue header */
81 RtlZeroMemory(QueueHeader
,
82 sizeof(FILEQUEUEHEADER
));
85 return((HSPFILEQ
)QueueHeader
);
90 SetupCloseFileQueue(HSPFILEQ QueueHandle
)
92 PFILEQUEUEHEADER QueueHeader
;
95 if (QueueHandle
== NULL
)
98 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
100 /* Delete copy queue */
101 Entry
= QueueHeader
->CopyHead
;
102 while (Entry
!= NULL
)
104 /* Delete all strings */
105 if (Entry
->SourceCabinet
!= NULL
)
106 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
107 if (Entry
->SourceRootPath
!= NULL
)
108 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
109 if (Entry
->SourcePath
!= NULL
)
110 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
111 if (Entry
->SourceFilename
!= NULL
)
112 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
113 if (Entry
->TargetDirectory
!= NULL
)
114 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
115 if (Entry
->TargetFilename
!= NULL
)
116 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetFilename
);
118 /* Unlink current queue entry */
119 if (Entry
->Next
!= NULL
)
121 QueueHeader
->CopyHead
= Entry
->Next
;
122 QueueHeader
->CopyHead
->Prev
= NULL
;
126 QueueHeader
->CopyHead
= NULL
;
127 QueueHeader
->CopyTail
= NULL
;
130 /* Delete queue entry */
131 RtlFreeHeap(ProcessHeap
, 0, Entry
);
133 /* Get next queue entry */
134 Entry
= QueueHeader
->CopyHead
;
137 /* Delete queue header */
138 RtlFreeHeap(ProcessHeap
,
147 SetupQueueCopy(HSPFILEQ QueueHandle
,
148 PCWSTR SourceCabinet
,
149 PCWSTR SourceRootPath
,
151 PCWSTR SourceFilename
,
152 PCWSTR TargetDirectory
,
153 PCWSTR TargetFilename
)
155 PFILEQUEUEHEADER QueueHeader
;
159 /* SourceCabinet may be NULL */
160 if (QueueHandle
== NULL
||
161 SourceRootPath
== NULL
||
162 SourceFilename
== NULL
||
163 TargetDirectory
== NULL
)
166 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
168 /* Allocate new queue entry */
169 Entry
= (PQUEUEENTRY
)RtlAllocateHeap(ProcessHeap
,
178 /* Copy source cabinet if available */
179 if (SourceCabinet
!= NULL
)
181 Length
= wcslen(SourceCabinet
);
182 Entry
->SourceCabinet
= RtlAllocateHeap(ProcessHeap
,
184 (Length
+ 1) * sizeof(WCHAR
));
185 if (Entry
->SourceCabinet
== NULL
)
187 RtlFreeHeap(ProcessHeap
, 0, Entry
);
190 wcsncpy(Entry
->SourceCabinet
, SourceCabinet
, Length
);
191 Entry
->SourceCabinet
[Length
] = (WCHAR
)0;
195 Entry
->SourceCabinet
= NULL
;
198 /* Copy source root path */
199 Length
= wcslen(SourceRootPath
);
200 Entry
->SourceRootPath
= RtlAllocateHeap(ProcessHeap
,
202 (Length
+ 1) * sizeof(WCHAR
));
203 if (Entry
->SourceRootPath
== NULL
)
205 if (Entry
->SourceCabinet
!= NULL
)
207 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
209 RtlFreeHeap(ProcessHeap
, 0, Entry
);
212 wcsncpy(Entry
->SourceRootPath
, SourceRootPath
, Length
);
213 Entry
->SourceRootPath
[Length
] = (WCHAR
)0;
215 /* Copy source path */
216 if (SourcePath
!= NULL
)
218 Length
= wcslen(SourcePath
);
219 Entry
->SourcePath
= RtlAllocateHeap(ProcessHeap
,
221 (Length
+ 1) * sizeof(WCHAR
));
222 if (Entry
->SourcePath
== NULL
)
224 if (Entry
->SourceCabinet
!= NULL
)
226 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
228 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
229 RtlFreeHeap(ProcessHeap
, 0, Entry
);
232 wcsncpy(Entry
->SourcePath
, SourcePath
, Length
);
233 Entry
->SourcePath
[Length
] = (WCHAR
)0;
236 /* Copy source file name */
237 Length
= wcslen(SourceFilename
);
238 Entry
->SourceFilename
= RtlAllocateHeap(ProcessHeap
,
240 (Length
+ 1) * sizeof(WCHAR
));
241 if (Entry
->SourceFilename
== NULL
)
243 if (Entry
->SourceCabinet
!= NULL
)
245 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
247 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
248 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
249 RtlFreeHeap(ProcessHeap
, 0, Entry
);
252 wcsncpy(Entry
->SourceFilename
, SourceFilename
, Length
);
253 Entry
->SourceFilename
[Length
] = (WCHAR
)0;
255 /* Copy target directory */
256 Length
= wcslen(TargetDirectory
);
257 if (TargetDirectory
[Length
] == '\\')
259 Entry
->TargetDirectory
= RtlAllocateHeap(ProcessHeap
,
261 (Length
+ 1) * sizeof(WCHAR
));
262 if (Entry
->TargetDirectory
== NULL
)
264 if (Entry
->SourceCabinet
!= NULL
)
266 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
268 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
269 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
270 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
271 RtlFreeHeap(ProcessHeap
, 0, Entry
);
274 wcsncpy(Entry
->TargetDirectory
, TargetDirectory
, Length
);
275 Entry
->TargetDirectory
[Length
] = (WCHAR
)0;
277 /* Copy optional target filename */
278 if (TargetFilename
!= NULL
)
280 Length
= wcslen(TargetFilename
);
281 Entry
->TargetFilename
= RtlAllocateHeap(ProcessHeap
,
283 (Length
+ 1) * sizeof(WCHAR
));
284 if (Entry
->TargetFilename
== NULL
)
286 if (Entry
->SourceCabinet
!= NULL
)
288 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
290 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
291 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
292 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
293 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
294 RtlFreeHeap(ProcessHeap
, 0, Entry
);
297 wcsncpy(Entry
->TargetFilename
, TargetFilename
, Length
);
298 Entry
->TargetFilename
[Length
] = (WCHAR
)0;
301 /* Append queue entry */
302 if (QueueHeader
->CopyHead
== NULL
) // && QueueHeader->CopyTail == NULL)
306 QueueHeader
->CopyHead
= Entry
;
307 QueueHeader
->CopyTail
= Entry
;
311 Entry
->Prev
= QueueHeader
->CopyTail
;
313 QueueHeader
->CopyTail
->Next
= Entry
;
314 QueueHeader
->CopyTail
= Entry
;
316 QueueHeader
->CopyCount
++;
323 SetupCommitFileQueue(HSPFILEQ QueueHandle
,
324 PCWSTR TargetRootPath
,
326 PSP_FILE_CALLBACK MsgHandler
,
329 WCHAR CabinetName
[MAX_PATH
];
330 PFILEQUEUEHEADER QueueHeader
;
334 WCHAR FileSrcPath
[MAX_PATH
];
335 WCHAR FileDstPath
[MAX_PATH
];
337 if (QueueHandle
== NULL
)
340 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
343 SPFILENOTIFY_STARTQUEUE
,
348 SPFILENOTIFY_STARTSUBQUEUE
,
350 (PVOID
)QueueHeader
->CopyCount
);
352 /* Commit copy queue */
353 Entry
= QueueHeader
->CopyHead
;
354 while (Entry
!= NULL
)
356 wcscpy(FileSrcPath
, Entry
->SourceRootPath
);
357 if (Entry
->SourcePath
!= NULL
)
358 wcscat(FileSrcPath
, Entry
->SourcePath
);
359 wcscat(FileSrcPath
, L
"\\");
360 wcscat(FileSrcPath
, Entry
->SourceFilename
);
362 /* Build the full target path */
363 wcscpy(FileDstPath
, TargetRootPath
);
364 if (Entry
->TargetDirectory
[0] == L
'\\')
366 wcscat(FileDstPath
, Entry
->TargetDirectory
);
370 if (TargetPath
!= NULL
)
372 if (TargetPath
[0] != L
'\\')
373 wcscat(FileDstPath
, L
"\\");
374 wcscat(FileDstPath
, TargetPath
);
376 wcscat(FileDstPath
, L
"\\");
377 wcscat(FileDstPath
, Entry
->TargetDirectory
);
380 /* Use only the destination path if the file is in a cabinet */
381 if (Entry
->SourceCabinet
== NULL
)
383 wcscat(FileDstPath
, L
"\\");
384 if (Entry
->TargetFilename
!= NULL
)
385 wcscat(FileDstPath
, Entry
->TargetFilename
);
387 wcscat(FileDstPath
, Entry
->SourceFilename
);
391 DPRINT("'%S' ==> '%S'\n",
396 SPFILENOTIFY_STARTCOPY
,
397 (PVOID
)Entry
->SourceFilename
,
400 if (Entry
->SourceCabinet
!= NULL
)
402 /* Extract the file */
403 wcscpy(CabinetName
, Entry
->SourceRootPath
);
404 if (Entry
->SourcePath
!= NULL
)
405 wcscat(CabinetName
, Entry
->SourcePath
);
406 wcscat(CabinetName
, L
"\\");
407 wcscat(CabinetName
, Entry
->SourceCabinet
);
408 Status
= SetupExtractFile(CabinetName
, Entry
->SourceFilename
, FileDstPath
);
413 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
);
415 if (!NT_SUCCESS(Status
))
418 SPFILENOTIFY_COPYERROR
,
419 (PVOID
)Entry
->SourceFilename
,
426 SPFILENOTIFY_ENDCOPY
,
427 (PVOID
)Entry
->SourceFilename
,
435 SPFILENOTIFY_ENDSUBQUEUE
,
440 SPFILENOTIFY_ENDQUEUE
,