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 *****************************************************************/
30 #include <ddk/ntddk.h>
31 #include <ntdll/rtl.h>
35 #include "filequeue.h"
38 /* INCLUDES *****************************************************************/
41 typedef struct _QUEUEENTRY
43 struct _QUEUEENTRY *Prev;
44 struct _QUEUEENTRY *Next;
46 PWSTR SourceCabinet; /* May be NULL if file is not in a cabinet */
50 PWSTR TargetDirectory;
53 } QUEUEENTRY, *PQUEUEENTRY;
56 typedef struct _FILEQUEUEHEADER
61 } FILEQUEUEHEADER, *PFILEQUEUEHEADER;
64 /* FUNCTIONS ****************************************************************/
67 SetupOpenFileQueue(VOID)
69 PFILEQUEUEHEADER QueueHeader;
71 /* Allocate queue header */
72 QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap,
74 sizeof(FILEQUEUEHEADER));
75 if (QueueHeader == NULL)
78 /* Initialize queue header */
79 RtlZeroMemory(QueueHeader,
80 sizeof(FILEQUEUEHEADER));
83 return((HSPFILEQ)QueueHeader);
88 SetupCloseFileQueue(HSPFILEQ QueueHandle)
90 PFILEQUEUEHEADER QueueHeader;
93 if (QueueHandle == NULL)
96 QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
98 /* Delete copy queue */
99 Entry = QueueHeader->CopyHead;
100 while (Entry != NULL)
102 /* Delete all strings */
103 if (Entry->SourceCabinet != NULL)
104 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
105 if (Entry->SourceRootPath != NULL)
106 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
107 if (Entry->SourcePath != NULL)
108 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
109 if (Entry->SourceFilename != NULL)
110 RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
111 if (Entry->TargetDirectory != NULL)
112 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,
145 SetupQueueCopy(HSPFILEQ QueueHandle,
146 PCWSTR SourceCabinet,
147 PCWSTR SourceRootPath,
149 PCWSTR SourceFilename,
150 PCWSTR TargetDirectory,
151 PCWSTR TargetFilename)
153 PFILEQUEUEHEADER QueueHeader;
157 /* SourceCabinet may be NULL */
158 if (QueueHandle == NULL ||
159 SourceRootPath == NULL ||
160 SourceFilename == NULL ||
161 TargetDirectory == NULL)
164 QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
166 /* Allocate new queue entry */
167 Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap,
176 /* Copy source cabinet if available */
177 if (SourceCabinet != NULL)
179 Length = wcslen(SourceCabinet);
180 Entry->SourceCabinet = RtlAllocateHeap(ProcessHeap,
182 (Length + 1) * sizeof(WCHAR));
183 if (Entry->SourceCabinet == NULL)
185 RtlFreeHeap(ProcessHeap, 0, Entry);
188 wcsncpy(Entry->SourceCabinet, SourceCabinet, Length);
189 Entry->SourceCabinet[Length] = (WCHAR)0;
193 Entry->SourceCabinet = NULL;
196 /* Copy source root path */
197 Length = wcslen(SourceRootPath);
198 Entry->SourceRootPath = RtlAllocateHeap(ProcessHeap,
200 (Length + 1) * sizeof(WCHAR));
201 if (Entry->SourceRootPath == NULL)
203 if (Entry->SourceCabinet != NULL)
205 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
207 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 Entry->SourcePath = RtlAllocateHeap(ProcessHeap,
219 (Length + 1) * sizeof(WCHAR));
220 if (Entry->SourcePath == NULL)
222 if (Entry->SourceCabinet != NULL)
224 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
226 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
227 RtlFreeHeap(ProcessHeap, 0, Entry);
230 wcsncpy(Entry->SourcePath, SourcePath, Length);
231 Entry->SourcePath[Length] = (WCHAR)0;
234 /* Copy source file name */
235 Length = wcslen(SourceFilename);
236 Entry->SourceFilename = RtlAllocateHeap(ProcessHeap,
238 (Length + 1) * sizeof(WCHAR));
239 if (Entry->SourceFilename == NULL)
241 if (Entry->SourceCabinet != NULL)
243 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
245 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
246 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
247 RtlFreeHeap(ProcessHeap, 0, Entry);
250 wcsncpy(Entry->SourceFilename, SourceFilename, Length);
251 Entry->SourceFilename[Length] = (WCHAR)0;
253 /* Copy target directory */
254 Length = wcslen(TargetDirectory);
255 if (TargetDirectory[Length] == '\\')
257 Entry->TargetDirectory = RtlAllocateHeap(ProcessHeap,
259 (Length + 1) * sizeof(WCHAR));
260 if (Entry->TargetDirectory == NULL)
262 if (Entry->SourceCabinet != NULL)
264 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
266 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
267 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
268 RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
269 RtlFreeHeap(ProcessHeap, 0, Entry);
272 wcsncpy(Entry->TargetDirectory, TargetDirectory, Length);
273 Entry->TargetDirectory[Length] = (WCHAR)0;
275 /* Copy optional target filename */
276 if (TargetFilename != NULL)
278 Length = wcslen(TargetFilename);
279 Entry->TargetFilename = RtlAllocateHeap(ProcessHeap,
281 (Length + 1) * sizeof(WCHAR));
282 if (Entry->TargetFilename == NULL)
284 if (Entry->SourceCabinet != NULL)
286 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
288 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
289 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
290 RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
291 RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory);
292 RtlFreeHeap(ProcessHeap, 0, Entry);
295 wcsncpy(Entry->TargetFilename, TargetFilename, Length);
296 Entry->TargetFilename[Length] = (WCHAR)0;
299 /* Append queue entry */
300 if (QueueHeader->CopyHead == NULL) // && QueueHeader->CopyTail == NULL)
304 QueueHeader->CopyHead = Entry;
305 QueueHeader->CopyTail = Entry;
309 Entry->Prev = QueueHeader->CopyTail;
311 QueueHeader->CopyTail->Next = Entry;
312 QueueHeader->CopyTail = Entry;
314 QueueHeader->CopyCount++;
321 SetupCommitFileQueue(HSPFILEQ QueueHandle,
322 PCWSTR TargetRootPath,
324 PSP_FILE_CALLBACK MsgHandler,
327 WCHAR CabinetName[MAX_PATH];
328 PFILEQUEUEHEADER QueueHeader;
332 WCHAR FileSrcPath[MAX_PATH];
333 WCHAR FileDstPath[MAX_PATH];
335 if (QueueHandle == NULL)
338 QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
341 SPFILENOTIFY_STARTQUEUE,
346 SPFILENOTIFY_STARTSUBQUEUE,
348 (PVOID)QueueHeader->CopyCount);
350 /* Commit copy queue */
351 Entry = QueueHeader->CopyHead;
352 while (Entry != NULL)
354 wcscpy(FileSrcPath, Entry->SourceRootPath);
355 if (Entry->SourcePath != NULL)
356 wcscat(FileSrcPath, Entry->SourcePath);
357 wcscat(FileSrcPath, L"\\");
358 wcscat(FileSrcPath, Entry->SourceFilename);
360 /* Build the full target path */
361 wcscpy(FileDstPath, TargetRootPath);
362 if (Entry->TargetDirectory[0] == L'\\')
364 wcscat(FileDstPath, Entry->TargetDirectory);
368 if (TargetPath != NULL)
370 if (TargetPath[0] != L'\\')
371 wcscat(FileDstPath, L"\\");
372 wcscat(FileDstPath, TargetPath);
374 wcscat(FileDstPath, L"\\");
375 wcscat(FileDstPath, Entry->TargetDirectory);
378 /* Use only the destination path if the file is in a cabinet */
379 if (Entry->SourceCabinet == NULL)
381 wcscat(FileDstPath, L"\\");
382 if (Entry->TargetFilename != NULL)
383 wcscat(FileDstPath, Entry->TargetFilename);
385 wcscat(FileDstPath, Entry->SourceFilename);
389 DPRINT("'%S' ==> '%S'\n",
394 SPFILENOTIFY_STARTCOPY,
395 (PVOID)Entry->SourceFilename,
398 if (Entry->SourceCabinet != NULL)
400 /* Extract the file */
401 wcscpy(CabinetName, Entry->SourceRootPath);
402 if (Entry->SourcePath != NULL)
403 wcscat(CabinetName, Entry->SourcePath);
404 wcscat(CabinetName, L"\\");
405 wcscat(CabinetName, Entry->SourceCabinet);
406 Status = SetupExtractFile(CabinetName, Entry->SourceFilename, FileDstPath);
411 Status = SetupCopyFile(FileSrcPath, FileDstPath);
413 if (!NT_SUCCESS(Status))
416 SPFILENOTIFY_COPYERROR,
417 (PVOID)Entry->SourceFilename,
424 SPFILENOTIFY_ENDCOPY,
425 (PVOID)Entry->SourceFilename,
433 SPFILENOTIFY_ENDSUBQUEUE,
438 SPFILENOTIFY_ENDQUEUE,